quasarr 1.30.0__tar.gz → 1.32.0__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-1.30.0 → quasarr-1.32.0}/PKG-INFO +1 -1
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/api/captcha/__init__.py +29 -22
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/__init__.py +7 -0
- quasarr-1.32.0/quasarr/downloads/packages/__init__.py +753 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/dl.py +24 -122
- quasarr-1.32.0/quasarr/downloads/sources/wx.py +168 -0
- quasarr-1.32.0/quasarr/providers/jd_cache.py +289 -0
- quasarr-1.32.0/quasarr/providers/utils.py +366 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/version.py +1 -1
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/wx.py +40 -24
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/storage/setup.py +3 -1
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr.egg-info/PKG-INFO +1 -1
- quasarr-1.30.0/quasarr/downloads/packages/__init__.py +0 -490
- quasarr-1.30.0/quasarr/downloads/sources/wx.py +0 -126
- quasarr-1.30.0/quasarr/providers/jd_cache.py +0 -131
- quasarr-1.30.0/quasarr/providers/utils.py +0 -189
- {quasarr-1.30.0 → quasarr-1.32.0}/LICENSE +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/README.md +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/api/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/api/arr/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/api/config/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/api/sponsors_helper/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/api/statistics/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/linkcrypters/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/linkcrypters/al.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/linkcrypters/hide.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/al.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/by.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/dd.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/dj.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/dt.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/dw.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/he.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/mb.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/nk.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/nx.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/sf.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/sj.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/sl.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/downloads/sources/wd.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/cloudflare.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/html_images.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/html_templates.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/imdb_metadata.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/log.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/myjd_api.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/notifications.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/obfuscated.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/sessions/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/sessions/al.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/sessions/dd.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/sessions/dl.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/sessions/nx.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/shared_state.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/statistics.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/providers/web_server.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/al.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/by.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/dd.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/dj.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/dl.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/dt.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/dw.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/fx.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/he.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/mb.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/nk.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/nx.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/sf.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/sj.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/sl.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/search/sources/wd.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/storage/__init__.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/storage/config.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr/storage/sqlite_database.py +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr.egg-info/SOURCES.txt +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr.egg-info/dependency_links.txt +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr.egg-info/entry_points.txt +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr.egg-info/not-zip-safe +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr.egg-info/requires.txt +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/quasarr.egg-info/top_level.txt +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/setup.cfg +0 -0
- {quasarr-1.30.0 → quasarr-1.32.0}/setup.py +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import json
|
|
6
6
|
import re
|
|
7
7
|
from base64 import urlsafe_b64encode, urlsafe_b64decode
|
|
8
|
-
from urllib.parse import quote, unquote
|
|
8
|
+
from urllib.parse import quote, unquote
|
|
9
9
|
|
|
10
10
|
import requests
|
|
11
11
|
from bottle import request, response, redirect, HTTPResponse
|
|
@@ -308,7 +308,7 @@ def setup_captcha_routes(app):
|
|
|
308
308
|
|
|
309
309
|
check_package_exists(package_id)
|
|
310
310
|
|
|
311
|
-
package_selector = render_package_selector(package_id)
|
|
311
|
+
package_selector = render_package_selector(package_id, title)
|
|
312
312
|
failed_warning = render_failed_attempts_warning(package_id)
|
|
313
313
|
|
|
314
314
|
return render_centered_html(f"""
|
|
@@ -318,7 +318,6 @@ def setup_captcha_routes(app):
|
|
|
318
318
|
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
319
319
|
{package_selector}
|
|
320
320
|
{failed_warning}
|
|
321
|
-
<p><b>Package:</b> {title}</p>
|
|
322
321
|
{render_userscript_section(url, package_id, title, password, "hide")}
|
|
323
322
|
<p>
|
|
324
323
|
{render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
|
|
@@ -349,7 +348,7 @@ def setup_captcha_routes(app):
|
|
|
349
348
|
|
|
350
349
|
check_package_exists(package_id)
|
|
351
350
|
|
|
352
|
-
package_selector = render_package_selector(package_id)
|
|
351
|
+
package_selector = render_package_selector(package_id, title)
|
|
353
352
|
failed_warning = render_failed_attempts_warning(package_id)
|
|
354
353
|
|
|
355
354
|
return render_centered_html(f"""
|
|
@@ -359,7 +358,6 @@ def setup_captcha_routes(app):
|
|
|
359
358
|
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
360
359
|
{package_selector}
|
|
361
360
|
{failed_warning}
|
|
362
|
-
<p><b>Package:</b> {title}</p>
|
|
363
361
|
{render_userscript_section(url, package_id, title, password, "junkies")}
|
|
364
362
|
<p>
|
|
365
363
|
{render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
|
|
@@ -391,7 +389,7 @@ def setup_captcha_routes(app):
|
|
|
391
389
|
|
|
392
390
|
url = urls[0][0] if isinstance(urls[0], (list, tuple)) else urls[0]
|
|
393
391
|
|
|
394
|
-
package_selector = render_package_selector(package_id)
|
|
392
|
+
package_selector = render_package_selector(package_id, title)
|
|
395
393
|
failed_warning = render_failed_attempts_warning(package_id)
|
|
396
394
|
|
|
397
395
|
return render_centered_html(f"""
|
|
@@ -401,7 +399,6 @@ def setup_captcha_routes(app):
|
|
|
401
399
|
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
402
400
|
{package_selector}
|
|
403
401
|
{failed_warning}
|
|
404
|
-
<p><b>Package:</b> {title}</p>
|
|
405
402
|
{render_userscript_section(url, package_id, title, password, "keeplinks")}
|
|
406
403
|
<p>
|
|
407
404
|
{render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
|
|
@@ -433,7 +430,7 @@ def setup_captcha_routes(app):
|
|
|
433
430
|
|
|
434
431
|
url = urls[0][0] if isinstance(urls[0], (list, tuple)) else urls[0]
|
|
435
432
|
|
|
436
|
-
package_selector = render_package_selector(package_id)
|
|
433
|
+
package_selector = render_package_selector(package_id, title)
|
|
437
434
|
failed_warning = render_failed_attempts_warning(package_id)
|
|
438
435
|
|
|
439
436
|
return render_centered_html(f"""
|
|
@@ -443,7 +440,6 @@ def setup_captcha_routes(app):
|
|
|
443
440
|
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
444
441
|
{package_selector}
|
|
445
442
|
{failed_warning}
|
|
446
|
-
<p><b>Package:</b> {title}</p>
|
|
447
443
|
{render_userscript_section(url, package_id, title, password, "tolink")}
|
|
448
444
|
<p>
|
|
449
445
|
{render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
|
|
@@ -619,12 +615,22 @@ def setup_captcha_routes(app):
|
|
|
619
615
|
</script>
|
|
620
616
|
'''
|
|
621
617
|
|
|
622
|
-
def render_package_selector(current_package_id):
|
|
623
|
-
"""Render
|
|
618
|
+
def render_package_selector(current_package_id, current_title=None):
|
|
619
|
+
"""Render package title, with dropdown selector if multiple packages available"""
|
|
624
620
|
protected = shared_state.get_db("protected").retrieve_all_titles()
|
|
625
621
|
|
|
626
|
-
if not protected
|
|
627
|
-
return ""
|
|
622
|
+
if not protected:
|
|
623
|
+
return ""
|
|
624
|
+
|
|
625
|
+
# Single package - just show the title without dropdown
|
|
626
|
+
if len(protected) <= 1:
|
|
627
|
+
if current_title:
|
|
628
|
+
return f'''
|
|
629
|
+
<div class="package-selector" style="margin-bottom: 20px; padding: 12px; background: rgba(128, 128, 128, 0.1); border: 1px solid rgba(128, 128, 128, 0.3); border-radius: 8px;">
|
|
630
|
+
<p style="margin: 0; word-break: break-all;"><b>📦 Package:</b> {current_title}</p>
|
|
631
|
+
</div>
|
|
632
|
+
'''
|
|
633
|
+
return ""
|
|
628
634
|
|
|
629
635
|
sj = shared_state.values["config"]("Hostnames").get("sj")
|
|
630
636
|
dj = shared_state.values["config"]("Hostnames").get("dj")
|
|
@@ -815,7 +821,7 @@ def setup_captcha_routes(app):
|
|
|
815
821
|
f"pkg_pass={quote(password)}"
|
|
816
822
|
)
|
|
817
823
|
|
|
818
|
-
package_selector = render_package_selector(package_id)
|
|
824
|
+
package_selector = render_package_selector(package_id, title)
|
|
819
825
|
failed_warning = render_failed_attempts_warning(package_id)
|
|
820
826
|
|
|
821
827
|
return render_centered_html(f"""
|
|
@@ -825,7 +831,6 @@ def setup_captcha_routes(app):
|
|
|
825
831
|
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
826
832
|
{package_selector}
|
|
827
833
|
{failed_warning}
|
|
828
|
-
<p style="max-width: 370px; word-wrap: break-word; overflow-wrap: break-word;"><b>Package:</b> {title}</p>
|
|
829
834
|
|
|
830
835
|
<div>
|
|
831
836
|
<!-- Info section explaining the process -->
|
|
@@ -1171,7 +1176,7 @@ def setup_captcha_routes(app):
|
|
|
1171
1176
|
bypass_section = render_filecrypt_bypass_section(url, package_id, title, password)
|
|
1172
1177
|
|
|
1173
1178
|
# Add package selector and failed attempts warning
|
|
1174
|
-
package_selector = render_package_selector(package_id)
|
|
1179
|
+
package_selector = render_package_selector(package_id, title)
|
|
1175
1180
|
|
|
1176
1181
|
# Create fallback URL for the manual FileCrypt page
|
|
1177
1182
|
fallback_payload = {
|
|
@@ -1187,6 +1192,9 @@ def setup_captcha_routes(app):
|
|
|
1187
1192
|
failed_warning = render_failed_attempts_warning(package_id, include_delete_button=False,
|
|
1188
1193
|
fallback_url=filecrypt_fallback_url) # Delete button is already below
|
|
1189
1194
|
|
|
1195
|
+
# Escape title for safe use in JavaScript string
|
|
1196
|
+
escaped_title_js = title.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r')
|
|
1197
|
+
|
|
1190
1198
|
content = render_centered_html(r'''
|
|
1191
1199
|
<style>
|
|
1192
1200
|
@media (max-width: 600px) {
|
|
@@ -1203,6 +1211,9 @@ def setup_captcha_routes(app):
|
|
|
1203
1211
|
}
|
|
1204
1212
|
</style>
|
|
1205
1213
|
<script type="text/javascript">
|
|
1214
|
+
// Package title for result display
|
|
1215
|
+
var packageTitleText = "''' + escaped_title_js + r'''";
|
|
1216
|
+
|
|
1206
1217
|
// Check if we should redirect to fallback due to failed attempts
|
|
1207
1218
|
(function() {
|
|
1208
1219
|
const storageKey = 'captcha_attempts_''' + package_id + r'''';
|
|
@@ -1231,11 +1242,8 @@ def setup_captcha_routes(app):
|
|
|
1231
1242
|
var warnBox = document.getElementById("failed-attempts-warning");
|
|
1232
1243
|
if (warnBox) warnBox.style.display = "none";
|
|
1233
1244
|
|
|
1234
|
-
//
|
|
1235
|
-
|
|
1236
|
-
packageTitle.style.maxWidth = "none";
|
|
1237
|
-
|
|
1238
|
-
document.getElementById("captcha-key").innerText = 'Using result "' + token + '" to decrypt links...';
|
|
1245
|
+
// Add package title to result area
|
|
1246
|
+
document.getElementById("captcha-key").innerHTML = '<p style="word-break: break-all;"><b>Package:</b> ' + packageTitleText + '</p><p style="word-break: break-all;">Using result "' + token + '" to decrypt links...</p>';
|
|
1239
1247
|
var link = document.getElementById("link-hidden").value;
|
|
1240
1248
|
const fullPath = '/captcha/decrypt-filecrypt';
|
|
1241
1249
|
|
|
@@ -1288,7 +1296,6 @@ def setup_captcha_routes(app):
|
|
|
1288
1296
|
{package_selector}
|
|
1289
1297
|
</div>
|
|
1290
1298
|
{failed_warning}
|
|
1291
|
-
<p id="package-title" style="max-width: 370px; word-wrap: break-word; overflow-wrap: break-word;"><b>Package:</b> {title}</p>
|
|
1292
1299
|
<div id="captcha-key"></div>
|
|
1293
1300
|
{link_select}<br><br>
|
|
1294
1301
|
<input type="hidden" id="link-hidden" value="{prioritized_links[0][0]}" />
|
|
@@ -25,6 +25,7 @@ from quasarr.downloads.sources.wx import get_wx_download_links
|
|
|
25
25
|
from quasarr.providers.log import info
|
|
26
26
|
from quasarr.providers.notifications import send_discord_message
|
|
27
27
|
from quasarr.providers.statistics import StatsHelper
|
|
28
|
+
from quasarr.providers.utils import filter_offline_links
|
|
28
29
|
|
|
29
30
|
# =============================================================================
|
|
30
31
|
# CRYPTER CONFIGURATION
|
|
@@ -184,6 +185,12 @@ def process_links(shared_state, source_result, title, password, package_id, imdb
|
|
|
184
185
|
reason=f'All links are offline or IP is banned for "{title}" on {label} - "{source_url}"')
|
|
185
186
|
links = valid_links
|
|
186
187
|
|
|
188
|
+
# Filter out verifiably offline links
|
|
189
|
+
links = filter_offline_links(links, shared_state=shared_state, log_func=info)
|
|
190
|
+
if not links:
|
|
191
|
+
return fail(title, package_id, shared_state,
|
|
192
|
+
reason=f'All verifiable links are offline for "{title}" on {label} - "{source_url}"')
|
|
193
|
+
|
|
187
194
|
classified = classify_links(links, shared_state)
|
|
188
195
|
|
|
189
196
|
# PRIORITY 1: Direct hoster links
|