summaryrefslogtreecommitdiff
path: root/misc/userscripts
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2020-12-22 14:16:47 +0100
committerFlorian Bruhin <me@the-compiler.org>2020-12-22 14:16:47 +0100
commit52af93eb53c212167a586dcf81af5d72b05007b2 (patch)
treeba27d70399baf52c664ac9e6d1e51930daf06990 /misc/userscripts
parent20c4fda9b77094fe5c91006b615e810c8909b784 (diff)
parent6f9d5bf43315ec83e10cae6342e0546eb318f017 (diff)
downloadqutebrowser-52af93eb53c212167a586dcf81af5d72b05007b2.tar.gz
qutebrowser-52af93eb53c212167a586dcf81af5d72b05007b2.zip
Merge remote-tracking branch 'origin/pr/5939'
Diffstat (limited to 'misc/userscripts')
-rw-r--r--misc/userscripts/README.md2
-rwxr-xr-xmisc/userscripts/add-nextcloud-bookmarks171
-rwxr-xr-xmisc/userscripts/add-nextcloud-cookbook131
3 files changed, 304 insertions, 0 deletions
diff --git a/misc/userscripts/README.md b/misc/userscripts/README.md
index 669bfa664..7e809a20a 100644
--- a/misc/userscripts/README.md
+++ b/misc/userscripts/README.md
@@ -35,6 +35,8 @@ The following userscripts are included in the current directory.
- [qr](./qr): Show a QR code for the current webpage via
[qrencode](https://fukuchi.org/works/qrencode/).
- [kodi](./kodi): Play videos in Kodi.
+- [add-nextcloud-bookmarks](./add-nextcloud-bookmarks): create bookmarks in Nextcloud's Bookmarks app
+- [add-nextcloud-cookbook](./add-nextcloud-cookbook): add recipes to Nextcloud's Cookbook app
[castnow]: https://github.com/xat/castnow
[youtube-dl]: https://rg3.github.io/youtube-dl/
diff --git a/misc/userscripts/add-nextcloud-bookmarks b/misc/userscripts/add-nextcloud-bookmarks
new file mode 100755
index 000000000..4e66620dc
--- /dev/null
+++ b/misc/userscripts/add-nextcloud-bookmarks
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+
+"""
+Behavior:
+ A qutebrowser userscript that creates bookmarks in Nextcloud's Bookmarks app.
+
+Requirements:
+ requests
+
+userscript setup:
+ Optionally create ~/.config/qutebrowser/add-nextcloud-bookmarks.ini like:
+
+[nextcloud]
+HOST=https://nextcloud.example.com
+USER=username
+;PASSWORD=lamepassword
+DESCRIPTION=None
+;TAGS=just-one
+TAGS=read-me-later,added-by-qutebrowser, Another-One
+
+ If settings aren't in the configuration file, the user will be prompted during
+ bookmark creation. If DESCRIPTION and TAGS are set to None, they will be left
+ blank. If the user does not want to be prompted for a password, it is recommended
+ to set up an 'app password'. See the following for instructions:
+ https://docs.nextcloud.com/server/latest/user_manual/en/session_management.html#managing-devices # noqa: E501
+
+qutebrowser setup:
+ add bookmark via hints
+ config.bind('X', 'hint links userscript add-nextcloud-bookmarks')
+
+ add bookmark of current URL
+ config.bind('X', 'spawn --userscript add-nextcloud-bookmarks')
+
+troubleshooting:
+ Errors detected within this userscript will have an exit of 231. All other
+ exit codes will come from requests.
+"""
+
+import configparser
+from json import dumps
+from os import environ, path
+from sys import argv, exit
+
+from PyQt5.QtWidgets import QApplication, QInputDialog, QLineEdit
+from requests import get, post
+from requests.auth import HTTPBasicAuth
+
+
+def get_text(name, info):
+ """Get input from the user."""
+ _app = QApplication(argv) # noqa: F841
+ if name == "password":
+ text, ok = QInputDialog.getText(
+ None,
+ "add-nextcloud-bookmarks userscript",
+ "Please enter {}".format(info),
+ QLineEdit.Password,
+ )
+ else:
+ text, ok = QInputDialog.getText(
+ None, "add-nextcloud-bookmarks userscript", "Please enter {}".format(info)
+ )
+ if not ok:
+ message("info", "Dialog box canceled.")
+ exit(0)
+ return text
+
+
+def message(level, text):
+ """display message"""
+ with open(environ["QUTE_FIFO"], "w") as fifo:
+ fifo.write(
+ 'message-{} "add-nextcloud-bookmarks userscript: {}"\n'.format(level, text)
+ )
+ fifo.flush()
+
+
+if "QUTE_FIFO" not in environ:
+ print(
+ "This script is designed to run as a qutebrowser userscript, "
+ "not as a standalone script."
+ )
+ exit(231)
+
+if "QUTE_CONFIG_DIR" not in environ:
+ if "XDG_CONFIG_HOME" in environ:
+ QUTE_CONFIG_DIR = environ["XDG_CONFIG_HOME"] + "/qutebrowser"
+ else:
+ QUTE_CONFIG_DIR = environ["HOME"] + "/.config/qutebrowser"
+else:
+ QUTE_CONFIG_DIR = environ["QUTE_CONFIG_DIR"]
+
+config_file = QUTE_CONFIG_DIR + "/add-nextcloud-bookmarks.ini"
+if path.isfile(config_file):
+ config = configparser.ConfigParser()
+ config.read(config_file)
+ settings = dict(config.items("nextcloud"))
+else:
+ settings = {}
+
+settings_info = [
+ ("host", "host information.", "required"),
+ ("user", "username.", "required"),
+ ("password", "password.", "required"),
+ ("description", "description or leave blank", "optional"),
+ ("tags", "tags (comma separated) or leave blank", "optional"),
+]
+
+# check for settings that need user interaction and clear optional setting if need be
+for setting in settings_info:
+ if setting[0] not in settings:
+ userInput = get_text(setting[0], setting[1])
+ settings[setting[0]] = userInput
+ if setting[2] == "optional":
+ if settings[setting[0]] == "None":
+ settings[setting[0]] = ""
+
+tags = settings["tags"].split(",")
+
+QUTE_URL = environ["QUTE_URL"]
+api_url = settings["host"] + "/index.php/apps/bookmarks/public/rest/v2/bookmark"
+
+headers = {"Content-Type": "application/json"}
+auth = HTTPBasicAuth(settings["user"], settings["password"])
+
+# check if there is already a bookmark for the URL
+r = get(
+ "{}?url={}".format(api_url, QUTE_URL),
+ auth=auth,
+ headers=headers,
+ timeout=(3.05, 27),
+)
+if r.status_code != 200:
+ message(
+ "error",
+ "Could not connect to {} with status code {}".format(
+ settings["host"], r.status_code
+ ),
+ )
+ exit(r.status_code)
+
+try:
+ r.json()["data"][0]["id"]
+except IndexError:
+ pass
+else:
+ message("info", "bookmark already exists for {}".format(QUTE_URL))
+ exit(0)
+
+if environ["QUTE_MODE"] == "hints":
+ QUTE_TITLE = QUTE_URL
+else:
+ QUTE_TITLE = environ["QUTE_TITLE"]
+
+# JSON format
+# https://nextcloud-bookmarks.readthedocs.io/en/latest/bookmark.html#create-a-bookmark
+dict = {
+ "url": QUTE_URL,
+ "title": QUTE_TITLE,
+ "description": settings["description"],
+ "tags": tags,
+}
+data = dumps(dict)
+
+r = post(api_url, data=data, headers=headers, auth=auth, timeout=(3.05, 27))
+
+if r.status_code == 200:
+ message("info", "bookmark {} added".format(QUTE_URL))
+else:
+ message("error", "something went wrong {} bookmark not added".format(QUTE_URL))
+ exit(r.status_code)
diff --git a/misc/userscripts/add-nextcloud-cookbook b/misc/userscripts/add-nextcloud-cookbook
new file mode 100755
index 000000000..a348417e0
--- /dev/null
+++ b/misc/userscripts/add-nextcloud-cookbook
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+
+"""
+Behavior:
+ A qutebrowser userscript that adds recipes to Nextcloud's Cookbook app.
+
+Requirements:
+ requests
+
+userscript setup:
+ Optionally create ~/.config/qutebrowser/add-nextcloud-cookbook.ini like:
+
+[nextcloud]
+HOST=https://nextcloud.example.com
+USER=username
+;PASSWORD=lamepassword
+
+ If settings aren't in the configuration file, the user will be prompted.
+ If the user does not want to be prompted for a password, it is recommended
+ to set up an 'app password' with 'Allow filesystem access' enabled.
+ See the following for instructions:
+ https://docs.nextcloud.com/server/latest/user_manual/en/session_management.html#managing-devices # noqa: E501
+
+qutebrowser setup:
+ add recipe via hints
+ config.bind('X', 'hint links userscript add-nextcloud-cookbook')
+
+ add recipe of current URL
+ config.bind('X', 'spawn --userscript add-nextcloud-cookbook')
+
+troubleshooting:
+ Errors detected within this userscript will have an exit of 231. All other
+ exit codes will come from requests.
+"""
+
+import configparser
+from os import environ, path
+from sys import argv, exit
+
+from PyQt5.QtWidgets import QApplication, QInputDialog, QLineEdit
+from requests import post
+from requests.auth import HTTPBasicAuth
+
+
+def get_text(name, info):
+ """Get input from the user."""
+ _app = QApplication(argv) # noqa: F841
+ if name == "password":
+ text, ok = QInputDialog.getText(
+ None,
+ "add-nextcloud-cookbook userscript",
+ "Please enter {}".format(info),
+ QLineEdit.Password,
+ )
+ else:
+ text, ok = QInputDialog.getText(
+ None, "add-nextcloud-cookbook userscript", "Please enter {}".format(info)
+ )
+ if not ok:
+ message("info", "Dialog box canceled.")
+ exit(0)
+ return text
+
+
+def message(level, text):
+ """display message"""
+ with open(environ["QUTE_FIFO"], "w") as fifo:
+ fifo.write(
+ "message-{} 'add-nextcloud-cookbook userscript: {}'\n".format(level, text)
+ )
+ fifo.flush()
+
+
+if "QUTE_FIFO" not in environ:
+ print(
+ "This script is designed to run as a qutebrowser userscript, "
+ "not as a standalone script."
+ )
+ exit(231)
+
+if "QUTE_CONFIG_DIR" not in environ:
+ if "XDG_CONFIG_HOME" in environ:
+ QUTE_CONFIG_DIR = environ["XDG_CONFIG_HOME"] + "/qutebrowser"
+ else:
+ QUTE_CONFIG_DIR = environ["HOME"] + "/.config/qutebrowser"
+else:
+ QUTE_CONFIG_DIR = environ["QUTE_CONFIG_DIR"]
+
+config_file = QUTE_CONFIG_DIR + "/add-nextcloud-cookbook.ini"
+if path.isfile(config_file):
+ config = configparser.ConfigParser()
+ config.read(config_file)
+ settings = dict(config.items("nextcloud"))
+else:
+ settings = {}
+
+settings_info = [
+ ("host", "host information.", "required"),
+ ("user", "username.", "required"),
+ ("password", "password.", "required"),
+]
+
+# check for settings that need user interaction
+for setting in settings_info:
+ if setting[0] not in settings:
+ userInput = get_text(setting[0], setting[1])
+ settings[setting[0]] = userInput
+
+api_url = settings["host"] + "/index.php/apps/cookbook/import"
+headers = {"Content-Type": "application/x-www-form-urlencoded"}
+auth = HTTPBasicAuth(settings["user"], settings["password"])
+data = "url=" + environ["QUTE_URL"]
+
+message("info", "starting to process {}".format(environ["QUTE_URL"]))
+
+r = post(api_url, data=data, headers=headers, auth=auth, timeout=(3.05, 27))
+
+if r.status_code == 200:
+ message("info", "recipe from {} added.".format(environ["QUTE_URL"]))
+ exit(0)
+elif r.status_code == 500:
+ message("warning", "Cookbook app reports {}".format(r.text))
+ exit(0)
+else:
+ message(
+ "error",
+ "Could not connect to {} with status code {}".format(
+ settings["host"], r.status_code
+ ),
+ )
+ exit(r.status_code)