summaryrefslogtreecommitdiff
path: root/misc/userscripts/add-nextcloud-bookmarks
blob: 86f4f5bc7be0efab62254da81a032970acbbbac8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/env python3

"""
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"

auth = HTTPBasicAuth(settings["user"], settings["password"])
headers = {"Content-Type": "application/json"}
params = {"url": QUTE_URL}

# check if there is already a bookmark for the URL
r = get(
    api_url,
    auth=auth,
    headers=headers,
    params=params,
    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)