quasarr 2.3.1__tar.gz → 2.3.3__tar.gz
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-2.3.1 → quasarr-2.3.3}/PKG-INFO +1 -1
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/__init__.py +24 -6
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/api/config/__init__.py +2 -2
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/api/sponsors_helper/__init__.py +25 -37
- quasarr-2.3.3/quasarr/providers/imdb_metadata.py +577 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/version.py +1 -1
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr.egg-info/PKG-INFO +1 -1
- quasarr-2.3.1/quasarr/providers/imdb_metadata.py +0 -353
- {quasarr-2.3.1 → quasarr-2.3.3}/LICENSE +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/README.md +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/api/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/api/arr/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/api/captcha/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/api/packages/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/api/statistics/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/linkcrypters/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/linkcrypters/al.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/linkcrypters/hide.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/packages/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/al.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/by.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/dd.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/dj.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/dl.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/dt.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/dw.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/he.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/mb.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/nk.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/nx.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/sf.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/sj.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/sl.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/wd.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/downloads/sources/wx.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/auth.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/cloudflare.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/hostname_issues.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/html_images.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/html_templates.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/jd_cache.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/log.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/myjd_api.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/notifications.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/obfuscated.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/sessions/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/sessions/al.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/sessions/dd.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/sessions/dl.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/sessions/nx.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/shared_state.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/statistics.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/utils.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/providers/web_server.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/al.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/by.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/dd.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/dj.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/dl.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/dt.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/dw.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/fx.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/he.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/mb.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/nk.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/nx.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/sf.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/sj.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/sl.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/wd.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/search/sources/wx.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/storage/__init__.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/storage/config.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/storage/setup.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr/storage/sqlite_database.py +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr.egg-info/SOURCES.txt +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr.egg-info/dependency_links.txt +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr.egg-info/entry_points.txt +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr.egg-info/not-zip-safe +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr.egg-info/requires.txt +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/quasarr.egg-info/top_level.txt +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/setup.cfg +0 -0
- {quasarr-2.3.1 → quasarr-2.3.3}/setup.py +0 -0
|
@@ -169,6 +169,14 @@ def run():
|
|
|
169
169
|
else:
|
|
170
170
|
hostname_credentials_config(shared_state, site.upper(), hostname)
|
|
171
171
|
|
|
172
|
+
# Check FlareSolverr configuration
|
|
173
|
+
skip_flaresolverr_db = DataBase("skip_flaresolverr")
|
|
174
|
+
flaresolverr_skipped = skip_flaresolverr_db.retrieve("skipped")
|
|
175
|
+
flaresolverr_url = Config('FlareSolverr').get('url')
|
|
176
|
+
|
|
177
|
+
if not flaresolverr_url and not flaresolverr_skipped:
|
|
178
|
+
flaresolverr_config(shared_state)
|
|
179
|
+
|
|
172
180
|
config = Config('JDownloader')
|
|
173
181
|
user = config.get('user')
|
|
174
182
|
password = config.get('password')
|
|
@@ -249,23 +257,33 @@ def flaresolverr_checker(shared_state_dict, shared_state_lock):
|
|
|
249
257
|
flaresolverr_skipped = skip_flaresolverr_db.retrieve("skipped")
|
|
250
258
|
|
|
251
259
|
flaresolverr_url = Config('FlareSolverr').get('url')
|
|
260
|
+
|
|
261
|
+
# If FlareSolverr is not configured and not skipped, it means it's the first run
|
|
262
|
+
# and the user needs to be prompted via the WebUI.
|
|
263
|
+
# This background process should NOT block or prompt the user.
|
|
264
|
+
# It should only check and log the status.
|
|
252
265
|
if not flaresolverr_url and not flaresolverr_skipped:
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
flaresolverr_url = Config('FlareSolverr').get('url')
|
|
266
|
+
info('FlareSolverr URL not configured. Please configure it via the WebUI.')
|
|
267
|
+
info('Some sites (AL) will not work without FlareSolverr.')
|
|
268
|
+
return # Exit the checker, it will be re-checked if user configures it later
|
|
257
269
|
|
|
258
270
|
if flaresolverr_skipped:
|
|
259
271
|
info('FlareSolverr setup skipped by user preference')
|
|
260
272
|
info('Some sites (AL) will not work without FlareSolverr. Configure it later in the web UI.')
|
|
261
273
|
elif flaresolverr_url:
|
|
262
|
-
|
|
274
|
+
info(f'Checking FlareSolverr at URL: "{flaresolverr_url}"')
|
|
263
275
|
flaresolverr_check = check_flaresolverr(shared_state, flaresolverr_url)
|
|
264
276
|
if flaresolverr_check:
|
|
265
|
-
|
|
277
|
+
info(f'FlareSolverr connection successful. Using User-Agent: "{shared_state.values["user_agent"]}"')
|
|
278
|
+
else:
|
|
279
|
+
info('FlareSolverr check failed - using fallback user agent')
|
|
280
|
+
# Fallback user agent is already set in main process, but we log it
|
|
281
|
+
info(f'User Agent (fallback): "{FALLBACK_USER_AGENT}"')
|
|
266
282
|
|
|
267
283
|
except KeyboardInterrupt:
|
|
268
284
|
pass
|
|
285
|
+
except Exception as e:
|
|
286
|
+
info(f"An unexpected error occurred in FlareSolverr checker: {e}")
|
|
269
287
|
|
|
270
288
|
|
|
271
289
|
def update_checker(shared_state_dict, shared_state_lock):
|
|
@@ -288,8 +288,8 @@ def setup_config(app, shared_state):
|
|
|
288
288
|
"FlareSolverr URL saved successfully! A restart is recommended.")
|
|
289
289
|
else:
|
|
290
290
|
return render_fail(f"FlareSolverr returned unexpected status: {json_data.get('status')}")
|
|
291
|
-
except requests.RequestException
|
|
292
|
-
return render_fail(f"Could not reach FlareSolverr
|
|
291
|
+
except requests.RequestException:
|
|
292
|
+
return render_fail(f"Could not reach FlareSolverr!")
|
|
293
293
|
|
|
294
294
|
return render_fail("Could not reach FlareSolverr at that URL (expected HTTP 200).")
|
|
295
295
|
|
|
@@ -33,16 +33,16 @@ def setup_sponsors_helper_routes(app):
|
|
|
33
33
|
if not protected:
|
|
34
34
|
return abort(404, "No encrypted packages found")
|
|
35
35
|
|
|
36
|
-
# Find the first package
|
|
36
|
+
# Find the first package that hasn't been disabled
|
|
37
37
|
selected_package = None
|
|
38
38
|
for package in protected:
|
|
39
39
|
data = json.loads(package[1])
|
|
40
|
-
if "
|
|
40
|
+
if "disabled" not in data:
|
|
41
41
|
selected_package = (package[0], data)
|
|
42
42
|
break
|
|
43
43
|
|
|
44
44
|
if not selected_package:
|
|
45
|
-
return abort(404, "No valid packages
|
|
45
|
+
return abort(404, "No valid packages found")
|
|
46
46
|
|
|
47
47
|
package_id, data = selected_package
|
|
48
48
|
title = data["title"]
|
|
@@ -67,9 +67,9 @@ def setup_sponsors_helper_routes(app):
|
|
|
67
67
|
except Exception as e:
|
|
68
68
|
return abort(500, str(e))
|
|
69
69
|
|
|
70
|
-
@app.post("/sponsors_helper/api/
|
|
70
|
+
@app.post("/sponsors_helper/api/download/")
|
|
71
71
|
@require_api_key
|
|
72
|
-
def
|
|
72
|
+
def download_api():
|
|
73
73
|
try:
|
|
74
74
|
data = request.json
|
|
75
75
|
title = data.get('name')
|
|
@@ -97,51 +97,39 @@ def setup_sponsors_helper_routes(app):
|
|
|
97
97
|
StatsHelper(shared_state).increment_failed_decryptions_automatic()
|
|
98
98
|
return abort(500, "Failed")
|
|
99
99
|
|
|
100
|
-
@app.post("/sponsors_helper/api/
|
|
100
|
+
@app.post("/sponsors_helper/api/disable/")
|
|
101
101
|
@require_api_key
|
|
102
|
-
def
|
|
102
|
+
def disable_api():
|
|
103
103
|
try:
|
|
104
104
|
data = request.json
|
|
105
|
-
name = data.get('name')
|
|
106
105
|
package_id = data.get('package_id')
|
|
107
|
-
password = data.get('password')
|
|
108
|
-
replace_url = data.get('replace_url')
|
|
109
|
-
mirror = data.get('mirror')
|
|
110
|
-
session = data.get('session')
|
|
111
|
-
|
|
112
|
-
if not all([name, package_id, replace_url, mirror, session]):
|
|
113
|
-
info("Missing required replacement data")
|
|
114
|
-
return {"error": "Missing required replacement data"}, 400
|
|
115
|
-
|
|
116
|
-
if password is None:
|
|
117
|
-
password = ""
|
|
118
|
-
|
|
119
|
-
blob = json.dumps(
|
|
120
|
-
{
|
|
121
|
-
"title": name,
|
|
122
|
-
"links": [replace_url, mirror],
|
|
123
|
-
"size_mb": 0,
|
|
124
|
-
"password": password,
|
|
125
|
-
"mirror": mirror,
|
|
126
|
-
"session": session
|
|
127
|
-
})
|
|
128
106
|
|
|
129
|
-
|
|
107
|
+
if not package_id:
|
|
108
|
+
return {"error": "Missing package_id"}, 400
|
|
109
|
+
|
|
110
|
+
StatsHelper(shared_state).increment_failed_decryptions_automatic()
|
|
130
111
|
|
|
131
|
-
|
|
112
|
+
blob = shared_state.get_db("protected").retrieve(package_id)
|
|
113
|
+
package_data = json.loads(blob)
|
|
114
|
+
title = package_data.get('title')
|
|
115
|
+
|
|
116
|
+
package_data["disabled"] = True
|
|
117
|
+
|
|
118
|
+
shared_state.get_db("protected").update_store(package_id, json.dumps(package_data))
|
|
119
|
+
|
|
120
|
+
info(f"Disabled package {title}")
|
|
132
121
|
|
|
133
122
|
StatsHelper(shared_state).increment_captcha_decryptions_automatic()
|
|
134
123
|
|
|
135
|
-
return f"
|
|
124
|
+
return f"Package {title} disabled"
|
|
136
125
|
|
|
137
126
|
except Exception as e:
|
|
138
|
-
|
|
139
|
-
info(f"Error handling replacement: {e}")
|
|
127
|
+
info(f"Error handling disable: {e}")
|
|
140
128
|
return {"error": str(e)}, 500
|
|
141
129
|
|
|
142
|
-
@app.delete("/sponsors_helper/api/
|
|
130
|
+
@app.delete("/sponsors_helper/api/fail/")
|
|
143
131
|
@require_api_key
|
|
144
|
-
def
|
|
132
|
+
def fail_api():
|
|
145
133
|
try:
|
|
146
134
|
StatsHelper(shared_state).increment_failed_decryptions_automatic()
|
|
147
135
|
|
|
@@ -165,7 +153,7 @@ def setup_sponsors_helper_routes(app):
|
|
|
165
153
|
|
|
166
154
|
@app.put("/sponsors_helper/api/set_sponsor_status/")
|
|
167
155
|
@require_api_key
|
|
168
|
-
def
|
|
156
|
+
def set_sponsor_status_api():
|
|
169
157
|
try:
|
|
170
158
|
data = request.body.read().decode("utf-8")
|
|
171
159
|
payload = json.loads(data)
|