diff --git a/script-resources/common_script_utils.py b/script-resources/common_script_utils.py new file mode 100644 index 0000000..9285ba3 --- /dev/null +++ b/script-resources/common_script_utils.py @@ -0,0 +1,80 @@ +import sys +import os +import subprocess + + +def platform_not_supported_error(): + raise Exception("platform '{}' is not supported!".format(sys.platform)) + + +def run_chooser(choices, prompt=None, async_read=False): + if sys.platform == "darwin": + process_args = ["choose", "-i"] + elif os.name == "posix": + process_args = ["rofi", "-dmenu", "-i", "-format", "i"] + if prompt is not None: + process_args += ["-p", prompt] + if async_read: + process_args += ["-async-pre-read", "0"] + else: + platform_not_supported_error() + + chooser_process = subprocess.Popen( + process_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE + ) + + with chooser_process.stdin as pipe: + for choice in choices: + assert "\n" not in choice + pipe.write(choice.encode()) + pipe.write(b"\n") + + exit_code = chooser_process.wait() + if exit_code != 0: + raise Exception("chooser process failed with exit code {}".format(exit_code)) + + chosen_index = int( + # an extra newline is inserted by rofi for whatever reason + chooser_process.stdout.read().rstrip(b"\n") + ) + + return chosen_index + + +def send_notification(title, message, url=None): + if sys.platform == "darwin": + process_args = [ + "terminal-notifier", + "-title", + title, + "-message", + message, + "-open", + ] + if url is not None: + process_args += [url] + elif os.name == "posix": + process_args = [ + "notify-send", + "--icon=utilities-terminal", + "--expire-time=3000", + title, + message, + ] + else: + platform_not_supported_error() + + subprocess.run(process_args, check=True) + + +def set_clipboard(text): + # TODO: somehow merge program selection with the logic in `zsh/functions.zsh` + if sys.platform == "darwin": + process_args = ["pbcopy"] + elif os.name == "posix": + process_args = ["xsel", "--clipboard", "--input"] + # process_args = ["xclip", "-in", "-selection", "clipboard"] + else: + platform_not_supported_error() + + subprocess.run(process_args, input=text.encode(), check=True) diff --git a/scripts/copy-crosscode-emoji-url b/scripts/copy-crosscode-emoji-url index 0dd5897..2937290 100755 --- a/scripts/copy-crosscode-emoji-url +++ b/scripts/copy-crosscode-emoji-url @@ -1,33 +1,50 @@ -#!/usr/bin/env bash +#!/usr/bin/env python3 -set -euo pipefail +import sys +import os +from pathlib import Path +from configparser import ConfigParser +import requests -# shellcheck source=/dev/null -source ~/.config/dotfiles/copy-crosscode-emoji-url.conf.sh - -data_refs=() -data_urls=() -data_titles=() - -read_line() { - IFS= read -r "$@" -} - -# https://stackoverflow.com/a/15692004/12005228 -print_lines() { - eval "printf '%s\n' \"\${$1[@]}\"" -} - -while read_line ref && read_line url && read_line title; do - data_refs+=("$ref") - data_urls+=("$url") - data_titles+=("$title") -done < <( - curl --location --fail --max-time 10 "$CCBOT_EMOTE_REGISTRY_DUMP_URL" | - jq -r '.list[] | select(.safe) | .ref, .url, "\(.ref) [\(.guild_name)]"' +sys.path.insert( + 1, os.path.join(os.path.dirname(os.path.dirname(__file__)), "script-resources") ) -if index="$(print_lines data_titles | rofi -dmenu -i -p cc-emoji -format i)"; then - echo -n "${data_urls[$index]}" | xsel --clipboard --input - notify-send --icon=utilities-terminal --expire-time=3000 "$0" "copied URL of ${data_refs[$index]} to clipboard!" -fi +import common_script_utils # noqa F401 + + +if os.name == "posix": + config_path = Path.home() / ".config" / "dotfiles" / "copy-crosscode-emoji-url.ini" +else: + common_script_utils.platform_not_supported_error() +config = ConfigParser(interpolation=None) +config.read(config_path) + + +data = [] + + +def emote_downloader_and_iterator(): + global data + + response = requests.get( + config["default"]["ccbot_emote_registry_dump_url"], timeout=3 + ) + response.raise_for_status() + + data = response.json() + assert data["version"] == 1 + + for emote in data["list"]: + yield "{emote[ref]} [{emote[guild_name]}]".format(emote=emote) + + +chosen_index = common_script_utils.run_chooser( + emote_downloader_and_iterator(), prompt="emote", async_read=True +) +chosen_emote = data["list"][chosen_index] +common_script_utils.set_clipboard(chosen_emote["url"]) +common_script_utils.send_notification( + os.path.basename(__file__), + "copied URL of {} to clipboard!".format(chosen_emote["ref"]), +) diff --git a/scripts/discord-whois b/scripts/discord-whois index c9aedf4..6304df1 100755 --- a/scripts/discord-whois +++ b/scripts/discord-whois @@ -37,6 +37,7 @@ user_snowflake = int(sys.argv[1]) response = requests.get( "https://discordapp.com/api/users/{}".format(user_snowflake), headers={"Authorization": "Bot {}".format(bot_token)}, + timeout=3, ) try: response.raise_for_status() diff --git a/scripts/query-bookmarks b/scripts/query-bookmarks index b4040f3..cfcf830 100755 --- a/scripts/query-bookmarks +++ b/scripts/query-bookmarks @@ -15,37 +15,20 @@ from configparser import ConfigParser import tempfile import shutil import sqlite3 -import subprocess + +sys.path.insert( + 1, os.path.join(os.path.dirname(os.path.dirname(__file__)), "script-resources") +) + +import common_script_utils # noqa F401 -# TODO: somehow merge `chooser_program` selection with the logic in `zsh/functions.zsh` if sys.platform == "darwin": firefox_home = Path.home() / "Library" / "Application Support" / "Firefox" - chooser_program = ["choose", "-i"] - clipboard_copy_program = ["pbcopy"] - - def notify_program_args(title, message, url): - return ["terminal-notifier", "-title", title, "-message", message, "-open", url] - - elif os.name == "posix": firefox_home = Path.home() / ".mozilla" / "firefox" - chooser_program = ["rofi", "-dmenu", "-i", "-p", "bookmark", "-format", "i"] - clipboard_copy_program = ["xsel", "--clipboard", "--input"] - # clipboard_copy_program = ["xclip", "-in", "-selection", "clipboard"] - - def notify_program_args(title, message, url): - return [ - "notify-send", - "--icon=utilities-terminal", - "--expire-time=3000", - title, - message, - ] - - else: - raise Exception("platform '{}' is not supported!".format(sys.platform)) + common_script_utils.platform_not_supported_error() profiles_config = ConfigParser(interpolation=None) @@ -91,28 +74,15 @@ finally: os.remove(db_copy_path) -chooser_process = subprocess.Popen( - chooser_program, stdin=subprocess.PIPE, stdout=subprocess.PIPE +chosen_index = common_script_utils.run_chooser( + ("{} \u2014\u2014 {}".format(title, url) for title, url in chooser_entries), + prompt="bookmark", ) -with chooser_process.stdin as pipe: - for title, url in chooser_entries: - pipe.write("{} \u2014\u2014 {}\n".format(title, url).encode()) +_title, url = chooser_entries[chosen_index] +print(url) -exit_code = chooser_process.wait() -if exit_code == 0: - chosen_index = int( - # an extra newline is inserted by rofi for whatever reason - chooser_process.stdout.read().rstrip(b"\n") - ) - _title, url = chooser_entries[chosen_index] - print(url) - - subprocess.run(clipboard_copy_program, input=url.encode(), check=True) - subprocess.run( - notify_program_args( - "query-bookmarks.py", "bookmark URL copied to clipboard!", url - ), - input=url.encode(), - check=True, - ) +common_script_utils.set_clipboard(url) +common_script_utils.send_notification( + os.path.basename(__file__), "bookmark URL copied to clipboard!", url +)