132 lines
3.8 KiB
Python
Executable File
132 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
"""
|
|
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 PyQt6.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.EchoMode.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)
|