quasarr 1.31.0__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of quasarr might be problematic. Click here for more details.
- quasarr/api/__init__.py +324 -106
- quasarr/api/captcha/__init__.py +26 -1
- quasarr/api/packages/__init__.py +374 -0
- quasarr/api/sponsors_helper/__init__.py +4 -0
- quasarr/downloads/__init__.py +2 -0
- quasarr/downloads/linkcrypters/hide.py +45 -6
- quasarr/downloads/packages/__init__.py +482 -219
- quasarr/providers/auth.py +250 -0
- quasarr/providers/jd_cache.py +211 -53
- quasarr/providers/obfuscated.py +9 -7
- quasarr/providers/shared_state.py +24 -0
- quasarr/providers/version.py +1 -1
- quasarr/search/sources/dl.py +3 -2
- quasarr/storage/setup.py +15 -1
- {quasarr-1.31.0.dist-info → quasarr-2.0.0.dist-info}/METADATA +12 -2
- {quasarr-1.31.0.dist-info → quasarr-2.0.0.dist-info}/RECORD +20 -18
- {quasarr-1.31.0.dist-info → quasarr-2.0.0.dist-info}/WHEEL +0 -0
- {quasarr-1.31.0.dist-info → quasarr-2.0.0.dist-info}/entry_points.txt +0 -0
- {quasarr-1.31.0.dist-info → quasarr-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {quasarr-1.31.0.dist-info → quasarr-2.0.0.dist-info}/top_level.txt +0 -0
|
@@ -7,6 +7,7 @@ import os
|
|
|
7
7
|
import re
|
|
8
8
|
import time
|
|
9
9
|
import traceback
|
|
10
|
+
import unicodedata
|
|
10
11
|
from datetime import datetime, timedelta, date
|
|
11
12
|
from urllib import parse
|
|
12
13
|
|
|
@@ -826,6 +827,8 @@ def get_recently_searched(shared_state, context, timeout_seconds):
|
|
|
826
827
|
|
|
827
828
|
|
|
828
829
|
def download_package(links, title, password, package_id):
|
|
830
|
+
links = [sanitize_url(link) for link in links]
|
|
831
|
+
|
|
829
832
|
device = get_device()
|
|
830
833
|
downloaded = device.linkgrabber.add_links(params=[
|
|
831
834
|
{
|
|
@@ -841,3 +844,24 @@ def download_package(links, title, password, package_id):
|
|
|
841
844
|
}
|
|
842
845
|
])
|
|
843
846
|
return downloaded
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
def sanitize_url(url: str) -> str:
|
|
850
|
+
# normalize first
|
|
851
|
+
url = unicodedata.normalize("NFKC", url)
|
|
852
|
+
|
|
853
|
+
# 1) real control characters (U+0000–U+001F, U+007F–U+009F)
|
|
854
|
+
_REAL_CTRL_RE = re.compile(r'[\u0000-\u001f\u007f-\u009f]')
|
|
855
|
+
|
|
856
|
+
# 2) *literal* escaped unicode junk: \u0010, \x10, repeated variants
|
|
857
|
+
_ESCAPED_CTRL_RE = re.compile(
|
|
858
|
+
r'(?:\\u00[0-1][0-9a-fA-F]|\\x[0-1][0-9a-fA-F])'
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
# remove literal escaped control sequences like "\u0010"
|
|
862
|
+
url = _ESCAPED_CTRL_RE.sub("", url)
|
|
863
|
+
|
|
864
|
+
# remove actual control characters if already decoded
|
|
865
|
+
url = _REAL_CTRL_RE.sub("", url)
|
|
866
|
+
|
|
867
|
+
return url.strip()
|
quasarr/providers/version.py
CHANGED
quasarr/search/sources/dl.py
CHANGED
|
@@ -97,7 +97,7 @@ def dl_feed(shared_state, start_time, request_from, mirror=None):
|
|
|
97
97
|
if not title_elem:
|
|
98
98
|
continue
|
|
99
99
|
|
|
100
|
-
title = title_elem.
|
|
100
|
+
title = ''.join(title_elem.strings)
|
|
101
101
|
if not title:
|
|
102
102
|
continue
|
|
103
103
|
|
|
@@ -230,7 +230,8 @@ def _search_single_page(shared_state, host, search_string, search_id, page_num,
|
|
|
230
230
|
if not title_elem:
|
|
231
231
|
continue
|
|
232
232
|
|
|
233
|
-
title = title_elem.
|
|
233
|
+
title = ''.join(title_elem.strings)
|
|
234
|
+
|
|
234
235
|
title = re.sub(r'\s+', ' ', title)
|
|
235
236
|
title = unescape(title)
|
|
236
237
|
title_normalized = normalize_title_for_sonarr(title)
|
quasarr/storage/setup.py
CHANGED
|
@@ -15,6 +15,7 @@ import quasarr.providers.sessions.al
|
|
|
15
15
|
import quasarr.providers.sessions.dd
|
|
16
16
|
import quasarr.providers.sessions.dl
|
|
17
17
|
import quasarr.providers.sessions.nx
|
|
18
|
+
from quasarr.providers.auth import add_auth_routes, add_auth_hook
|
|
18
19
|
from quasarr.providers.html_templates import render_button, render_form, render_success, render_fail, \
|
|
19
20
|
render_centered_html
|
|
20
21
|
from quasarr.providers.log import info
|
|
@@ -91,9 +92,16 @@ def add_no_cache_headers(app):
|
|
|
91
92
|
response.set_header('Expires', '0')
|
|
92
93
|
|
|
93
94
|
|
|
95
|
+
def setup_auth(app):
|
|
96
|
+
"""Add authentication to setup app if enabled."""
|
|
97
|
+
add_auth_routes(app)
|
|
98
|
+
add_auth_hook(app)
|
|
99
|
+
|
|
100
|
+
|
|
94
101
|
def path_config(shared_state):
|
|
95
102
|
app = Bottle()
|
|
96
103
|
add_no_cache_headers(app)
|
|
104
|
+
setup_auth(app)
|
|
97
105
|
|
|
98
106
|
current_path = os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
99
107
|
|
|
@@ -239,7 +247,9 @@ def hostname_form_html(shared_state, message, show_restart_button=False, show_sk
|
|
|
239
247
|
.import-status {{
|
|
240
248
|
margin-top: 0.5rem;
|
|
241
249
|
font-size: 0.875rem;
|
|
242
|
-
|
|
250
|
+
}}
|
|
251
|
+
.import-status:empty {{
|
|
252
|
+
display: none;
|
|
243
253
|
}}
|
|
244
254
|
.import-status.success {{ color: #198754; }}
|
|
245
255
|
.import-status.error {{ color: #dc3545; }}
|
|
@@ -558,6 +568,7 @@ def save_hostnames(shared_state, timeout=5, first_run=True):
|
|
|
558
568
|
def hostnames_config(shared_state):
|
|
559
569
|
app = Bottle()
|
|
560
570
|
add_no_cache_headers(app)
|
|
571
|
+
setup_auth(app)
|
|
561
572
|
|
|
562
573
|
@app.get('/')
|
|
563
574
|
def hostname_form():
|
|
@@ -636,6 +647,7 @@ def hostnames_config(shared_state):
|
|
|
636
647
|
def hostname_credentials_config(shared_state, shorthand, domain):
|
|
637
648
|
app = Bottle()
|
|
638
649
|
add_no_cache_headers(app)
|
|
650
|
+
setup_auth(app)
|
|
639
651
|
|
|
640
652
|
shorthand = shorthand.upper()
|
|
641
653
|
|
|
@@ -791,6 +803,7 @@ def hostname_credentials_config(shared_state, shorthand, domain):
|
|
|
791
803
|
def flaresolverr_config(shared_state):
|
|
792
804
|
app = Bottle()
|
|
793
805
|
add_no_cache_headers(app)
|
|
806
|
+
setup_auth(app)
|
|
794
807
|
|
|
795
808
|
@app.get('/')
|
|
796
809
|
def url_form():
|
|
@@ -931,6 +944,7 @@ def flaresolverr_config(shared_state):
|
|
|
931
944
|
def jdownloader_config(shared_state):
|
|
932
945
|
app = Bottle()
|
|
933
946
|
add_no_cache_headers(app)
|
|
947
|
+
setup_auth(app)
|
|
934
948
|
|
|
935
949
|
@app.get('/')
|
|
936
950
|
def jd_form():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quasarr
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Quasarr connects JDownloader with Radarr, Sonarr and LazyLibrarian. It also decrypts links protected by CAPTCHAs.
|
|
5
5
|
Home-page: https://github.com/rix1337/Quasarr
|
|
6
6
|
Author: rix1337
|
|
@@ -75,6 +75,11 @@ http://192.168.1.1:8191/v1
|
|
|
75
75
|
|
|
76
76
|
📋 Alternatively, browse community suggestions via [pastebin search](https://pastebin.com/search?q=hostnames+quasarr) (login required).
|
|
77
77
|
|
|
78
|
+
> Authentication is optional but strongly recommended.
|
|
79
|
+
>
|
|
80
|
+
> - 🔐 Set `USER` and `PASS` to enable form-based login (30-day session)
|
|
81
|
+
> - 🔑 Set `AUTH=basic` to use HTTP Basic Authentication instead
|
|
82
|
+
|
|
78
83
|
---
|
|
79
84
|
|
|
80
85
|
## JDownloader
|
|
@@ -170,7 +175,10 @@ docker run -d \
|
|
|
170
175
|
-e 'INTERNAL_ADDRESS'='http://192.168.0.1:8080' \
|
|
171
176
|
-e 'EXTERNAL_ADDRESS'='https://foo.bar/' \
|
|
172
177
|
-e 'DISCORD'='https://discord.com/api/webhooks/1234567890/ABCDEFGHIJKLMN' \
|
|
173
|
-
-e 'HOSTNAMES'='https://quasarr-host.name/ini?token=123...'
|
|
178
|
+
-e 'HOSTNAMES'='https://quasarr-host.name/ini?token=123...' \
|
|
179
|
+
-e 'USER'='admin' \
|
|
180
|
+
-e 'PASS'='change-me' \
|
|
181
|
+
-e 'AUTH'='form' \
|
|
174
182
|
-e 'SILENT'='True' \
|
|
175
183
|
-e 'DEBUG'='' \
|
|
176
184
|
-e 'TZ'='Europe/Berlin' \
|
|
@@ -184,6 +192,8 @@ docker run -d \
|
|
|
184
192
|
* Must be a publicly available `HTTP` or `HTTPs` link
|
|
185
193
|
* Must be a raw `.ini` / text file (not HTML or JSON)
|
|
186
194
|
* Must contain at least one valid Hostname per line `ab = xyz`
|
|
195
|
+
* `USER` / `PASS` are credentials to protect the web UI
|
|
196
|
+
* `AUTH` is the authentication mode (`form` or `basic`)
|
|
187
197
|
* `SILENT` is optional and silences all discord notifications except for error messages from SponsorsHelper if `True`.
|
|
188
198
|
* `DEBUG` is optional and enables debug logging if `True`.
|
|
189
199
|
* `TZ` is optional, wrong timezone can cause HTTPS/SSL issues
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
quasarr/__init__.py,sha256=cEtxN2AuwKvrxpIvAR7UL997VtYQ4iN3Eo3ZnP-WjZQ,14682
|
|
2
|
-
quasarr/api/__init__.py,sha256=
|
|
2
|
+
quasarr/api/__init__.py,sha256=CejYHdwOf2hkk4HQuBEjfU4Tqg3fKn3kIOZUkaqzERk,16321
|
|
3
3
|
quasarr/api/arr/__init__.py,sha256=BNEugX1hUF5kn8MIgdoyE1HeyabpojjxAa6RlXSem74,17518
|
|
4
|
-
quasarr/api/captcha/__init__.py,sha256=
|
|
4
|
+
quasarr/api/captcha/__init__.py,sha256=2pca9jnJMWZECHeAvKP9Lwsa3_GkVsvQEn7rof8Ep1s,73504
|
|
5
5
|
quasarr/api/config/__init__.py,sha256=m0DrbanI0lK_PaZA6ey3osj5l1_tMjjYjoFKkzrdPu0,13692
|
|
6
|
-
quasarr/api/
|
|
6
|
+
quasarr/api/packages/__init__.py,sha256=22XTb5ovtFFt4EEAle9vhC35u3hl5VhJIZpvUv-OF9w,20642
|
|
7
|
+
quasarr/api/sponsors_helper/__init__.py,sha256=aXkZJmqxM5q04V1pnC__FANL9vm_gLtOWONO6AVvs6s,6465
|
|
7
8
|
quasarr/api/statistics/__init__.py,sha256=NrBAjjHkIUE95HhPUGIfNqh2IqBqJ_zm00S90Y-Qnus,7038
|
|
8
|
-
quasarr/downloads/__init__.py,sha256=
|
|
9
|
+
quasarr/downloads/__init__.py,sha256=YUO1q9FelAYwTPNCNza6GTOwjJcWl5E2iqsHFj1jugQ,12122
|
|
9
10
|
quasarr/downloads/linkcrypters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
11
|
quasarr/downloads/linkcrypters/al.py,sha256=mfUG5VclC_-FcGoZL9zHYD7dz7X_YpaNmoKkgiyl9-0,8812
|
|
11
12
|
quasarr/downloads/linkcrypters/filecrypt.py,sha256=He8b7HjoPA-LmRwVwY0l_5JAVlJ3sYOXs5tcWXooqI4,17055
|
|
12
|
-
quasarr/downloads/linkcrypters/hide.py,sha256=
|
|
13
|
-
quasarr/downloads/packages/__init__.py,sha256=
|
|
13
|
+
quasarr/downloads/linkcrypters/hide.py,sha256=H4hJWhENkszV1u_ULC3aOW2fu9infC-Nv-7wx2DYqrA,6266
|
|
14
|
+
quasarr/downloads/packages/__init__.py,sha256=zDMhLJz-16r4WSv2zzSlcBJEFrIUky2dRDkQaQLVSXY,32055
|
|
14
15
|
quasarr/downloads/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
16
|
quasarr/downloads/sources/al.py,sha256=g587VESZRZHZ03uxHKpufEr5qAtzbyGLmoijksU35jk,27297
|
|
16
17
|
quasarr/downloads/sources/by.py,sha256=kmUTn3izayRCV7W-t0E4kYE8qTbt3L3reCLozfvRGcU,3807
|
|
@@ -29,19 +30,20 @@ quasarr/downloads/sources/sl.py,sha256=jWprFt1Hew1T67fB1O_pc9YWgc3NVh30KXSwSyS50
|
|
|
29
30
|
quasarr/downloads/sources/wd.py,sha256=kr1I1uJa7ZkEPH2LA6alXTJEn0LBPgLCwIh3wLXwCv8,4447
|
|
30
31
|
quasarr/downloads/sources/wx.py,sha256=NzNNeqVL6sKkFKyreW-oerrreb5QP2tUGHTWHM5pMCU,7013
|
|
31
32
|
quasarr/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
quasarr/providers/auth.py,sha256=hqSVaHBljf4yTx8JVqfxmi65T5Q36aewUmqfJbHtCNg,8730
|
|
32
34
|
quasarr/providers/cloudflare.py,sha256=9iet8runc2VHVcA0_2z1qkrL6D5JKqz1ndktqCgsJFs,7873
|
|
33
35
|
quasarr/providers/html_images.py,sha256=2n82gTJg7E7q2ytPFN4FWouYTIlmPYu_iHFtG7uktIA,28482
|
|
34
36
|
quasarr/providers/html_templates.py,sha256=YMwdi7l_tHL0-qsUnwi4aPrE5Q6ZDxbjsPIfr-6uemY,10265
|
|
35
37
|
quasarr/providers/imdb_metadata.py,sha256=10L4kZkt6Fg0HGdNcc6KCtIQHRYEqdarLyaMVN6mT8w,4843
|
|
36
|
-
quasarr/providers/jd_cache.py,sha256=
|
|
38
|
+
quasarr/providers/jd_cache.py,sha256=mSvMrs3UwTn3sd9yGSJKGT-qwYeyYKC_l8whpXTVn7s,13530
|
|
37
39
|
quasarr/providers/log.py,sha256=_g5RwtfuksARXnvryhsngzoJyFcNzj6suqd3ndqZM0Y,313
|
|
38
40
|
quasarr/providers/myjd_api.py,sha256=Z3PEiO3c3UfDSr4Up5rgwTAnjloWHb-H1RkJ6BLKZv8,34140
|
|
39
41
|
quasarr/providers/notifications.py,sha256=bohT-6yudmFnmZMc3BwCGX0n1HdzSVgQG_LDZm_38dI,4630
|
|
40
|
-
quasarr/providers/obfuscated.py,sha256=
|
|
41
|
-
quasarr/providers/shared_state.py,sha256
|
|
42
|
+
quasarr/providers/obfuscated.py,sha256=9z8nwcLFezazsfAgOz4S679VJJMe1AP-6odtlILDkE8,1404048
|
|
43
|
+
quasarr/providers/shared_state.py,sha256=5a_ZbGqTvt4-OqBt2a1WtR9I5J_Ky7IlkEY8EGtKVu8,30646
|
|
42
44
|
quasarr/providers/statistics.py,sha256=cEQixYnDMDqtm5wWe40E_2ucyo4mD0n3SrfelhQi1L8,6452
|
|
43
45
|
quasarr/providers/utils.py,sha256=mcUPbcXMsLmrYv0CTZO5a9aOt2-JLyL3SZxu6N8OyjU,12075
|
|
44
|
-
quasarr/providers/version.py,sha256=
|
|
46
|
+
quasarr/providers/version.py,sha256=KkR4lHopacRigrcdM-fst1j72YqiWFcE2T2Yk-aBhTo,4003
|
|
45
47
|
quasarr/providers/web_server.py,sha256=AYd0KRxdDWMBr87BP8wlSMuL4zZo0I_rY-vHBai6Pfg,1688
|
|
46
48
|
quasarr/providers/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
49
|
quasarr/providers/sessions/al.py,sha256=WXue9LaT4y0BzsbKtHbN6bb_72c4AZZWR9NP-vg9-cg,12462
|
|
@@ -54,7 +56,7 @@ quasarr/search/sources/al.py,sha256=AmTQDc6voMXh8Sh_IrJX_3gQ5UYKMri-aGaE-wbI3ik,
|
|
|
54
56
|
quasarr/search/sources/by.py,sha256=vnE3L43V8suPhPHcn6LVxKO1e3mJaDRqIIMg2BGxr_g,7915
|
|
55
57
|
quasarr/search/sources/dd.py,sha256=pVpdHLZlw2CYklBf_YLkeDWbCNsDLR2iecccR2c2RyI,4889
|
|
56
58
|
quasarr/search/sources/dj.py,sha256=2HIdg5ddXP4DtjHlyXmuQ8QVhOPt3Hh2kL4uxhFJK-8,7074
|
|
57
|
-
quasarr/search/sources/dl.py,sha256=
|
|
59
|
+
quasarr/search/sources/dl.py,sha256=kf8FPUn7BIjolDt5ApNDZpjTSMxkcz9xbHrJ_8c-qhg,12517
|
|
58
60
|
quasarr/search/sources/dt.py,sha256=m1kQ7mC43QlWZyVIkw-OXJGjWiT9IbQuFtHWiR8CjhA,9580
|
|
59
61
|
quasarr/search/sources/dw.py,sha256=-daUTBTA5izeatrE7TITVlnzNCQ5HfovYMMZ8UTM-2o,7636
|
|
60
62
|
quasarr/search/sources/fx.py,sha256=JAyD727yDAFIP14bzfi2SkX9paysXGkQdIybShYtdko,8596
|
|
@@ -69,11 +71,11 @@ quasarr/search/sources/wd.py,sha256=O02j3irSlVw2qES82g_qHuavAk-njjSRH1dHSCnOUas,
|
|
|
69
71
|
quasarr/search/sources/wx.py,sha256=zlRvg7Ls-DFRo4sUBMRAXZRMfE2mnaXCkzP7pu53pIY,13842
|
|
70
72
|
quasarr/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
73
|
quasarr/storage/config.py,sha256=SSTgIce2FVYoVTK_6OCU3msknhxuLA3EC4Kcrrf_dxQ,6378
|
|
72
|
-
quasarr/storage/setup.py,sha256=
|
|
74
|
+
quasarr/storage/setup.py,sha256=eXtgUqMacbaUDy-dszPtT15O9lJKSO1eI3v0jGjMiUA,42361
|
|
73
75
|
quasarr/storage/sqlite_database.py,sha256=yMqFQfKf0k7YS-6Z3_7pj4z1GwWSXJ8uvF4IydXsuTE,3554
|
|
74
|
-
quasarr-
|
|
75
|
-
quasarr-
|
|
76
|
-
quasarr-
|
|
77
|
-
quasarr-
|
|
78
|
-
quasarr-
|
|
79
|
-
quasarr-
|
|
76
|
+
quasarr-2.0.0.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
|
|
77
|
+
quasarr-2.0.0.dist-info/METADATA,sha256=fAV2_D6qwGXSdtXQT5AhiNX55XbA8zIlBhS0DUC_NMY,11391
|
|
78
|
+
quasarr-2.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
79
|
+
quasarr-2.0.0.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
|
|
80
|
+
quasarr-2.0.0.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
|
|
81
|
+
quasarr-2.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|