quasarr 2.3.3__tar.gz → 2.4.1__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.

Files changed (88) hide show
  1. {quasarr-2.3.3 → quasarr-2.4.1}/PKG-INFO +1 -1
  2. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/api/captcha/__init__.py +57 -48
  3. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/api/sponsors_helper/__init__.py +2 -0
  4. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/notifications.py +5 -2
  5. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/version.py +1 -1
  6. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr.egg-info/PKG-INFO +1 -1
  7. {quasarr-2.3.3 → quasarr-2.4.1}/LICENSE +0 -0
  8. {quasarr-2.3.3 → quasarr-2.4.1}/README.md +0 -0
  9. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/__init__.py +0 -0
  10. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/api/__init__.py +0 -0
  11. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/api/arr/__init__.py +0 -0
  12. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/api/config/__init__.py +0 -0
  13. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/api/packages/__init__.py +0 -0
  14. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/api/statistics/__init__.py +0 -0
  15. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/__init__.py +0 -0
  16. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/linkcrypters/__init__.py +0 -0
  17. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/linkcrypters/al.py +0 -0
  18. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
  19. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/linkcrypters/hide.py +0 -0
  20. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/packages/__init__.py +0 -0
  21. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/__init__.py +0 -0
  22. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/al.py +0 -0
  23. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/by.py +0 -0
  24. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/dd.py +0 -0
  25. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/dj.py +0 -0
  26. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/dl.py +0 -0
  27. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/dt.py +0 -0
  28. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/dw.py +0 -0
  29. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/he.py +0 -0
  30. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/mb.py +0 -0
  31. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/nk.py +0 -0
  32. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/nx.py +0 -0
  33. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/sf.py +0 -0
  34. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/sj.py +0 -0
  35. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/sl.py +0 -0
  36. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/wd.py +0 -0
  37. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/downloads/sources/wx.py +0 -0
  38. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/__init__.py +0 -0
  39. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/auth.py +0 -0
  40. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/cloudflare.py +0 -0
  41. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/hostname_issues.py +0 -0
  42. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/html_images.py +0 -0
  43. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/html_templates.py +0 -0
  44. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/imdb_metadata.py +0 -0
  45. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/jd_cache.py +0 -0
  46. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/log.py +0 -0
  47. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/myjd_api.py +0 -0
  48. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/obfuscated.py +0 -0
  49. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/sessions/__init__.py +0 -0
  50. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/sessions/al.py +0 -0
  51. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/sessions/dd.py +0 -0
  52. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/sessions/dl.py +0 -0
  53. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/sessions/nx.py +0 -0
  54. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/shared_state.py +0 -0
  55. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/statistics.py +0 -0
  56. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/utils.py +0 -0
  57. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/providers/web_server.py +0 -0
  58. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/__init__.py +0 -0
  59. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/__init__.py +0 -0
  60. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/al.py +0 -0
  61. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/by.py +0 -0
  62. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/dd.py +0 -0
  63. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/dj.py +0 -0
  64. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/dl.py +0 -0
  65. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/dt.py +0 -0
  66. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/dw.py +0 -0
  67. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/fx.py +0 -0
  68. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/he.py +0 -0
  69. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/mb.py +0 -0
  70. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/nk.py +0 -0
  71. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/nx.py +0 -0
  72. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/sf.py +0 -0
  73. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/sj.py +0 -0
  74. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/sl.py +0 -0
  75. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/wd.py +0 -0
  76. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/search/sources/wx.py +0 -0
  77. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/storage/__init__.py +0 -0
  78. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/storage/config.py +0 -0
  79. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/storage/setup.py +0 -0
  80. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr/storage/sqlite_database.py +0 -0
  81. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr.egg-info/SOURCES.txt +0 -0
  82. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr.egg-info/dependency_links.txt +0 -0
  83. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr.egg-info/entry_points.txt +0 -0
  84. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr.egg-info/not-zip-safe +0 -0
  85. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr.egg-info/requires.txt +0 -0
  86. {quasarr-2.3.3 → quasarr-2.4.1}/quasarr.egg-info/top_level.txt +0 -0
  87. {quasarr-2.3.3 → quasarr-2.4.1}/setup.cfg +0 -0
  88. {quasarr-2.3.3 → quasarr-2.4.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 2.3.3
3
+ Version: 2.4.1
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
@@ -86,6 +86,8 @@ def setup_captcha_routes(app):
86
86
  except KeyError:
87
87
  desired_mirror = None
88
88
 
89
+ original_url = data.get("original_url")
90
+
89
91
  # This is required for cutcaptcha
90
92
  rapid = [ln for ln in links if "rapidgator" in ln[1].lower()]
91
93
  others = [ln for ln in links if "rapidgator" not in ln[1].lower()]
@@ -97,6 +99,7 @@ def setup_captcha_routes(app):
97
99
  "password": password,
98
100
  "mirror": desired_mirror,
99
101
  "links": prioritized_links,
102
+ "original_url": original_url,
100
103
  }
101
104
 
102
105
  encoded_payload = urlsafe_b64encode(json.dumps(payload).encode()).decode()
@@ -194,29 +197,18 @@ def setup_captcha_routes(app):
194
197
 
195
198
  return f'''
196
199
  <div>
197
- <!-- Info section explaining the process -->
198
- <div class="info-box">
199
- <h3>ℹ️ How This Works:</h3>
200
- <p style="margin-bottom: 8px;">
201
- 1. Click the link below to open {provider_name}
202
- </p>
203
- <p style="margin-top: 0; margin-bottom: 8px;">
204
- 2. Solve any CAPTCHAs on their site to reveal the download links
205
- </p>
206
- <p style="margin-top: 0; margin-bottom: 0;">
207
- 3. <b>With the userscript installed</b>, links are automatically sent back to Quasarr!
208
- </p>
209
- </div>
210
-
211
200
  <!-- One-time setup section - visually separated -->
212
201
  <div id="setup-instructions" class="setup-box">
213
202
  <h3>📦 First Time Setup:</h3>
214
203
  <p style="margin-bottom: 8px;">
215
- <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. Install Tampermonkey</a>
204
+ <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. On mobile Safari/Firefox or any Desktop Browser install Tampermonkey</a>
216
205
  </p>
217
- <p style="margin-top: 0; margin-bottom: 12px;">
206
+ <p style="margin-top: 0; margin-bottom: 8px;">
218
207
  <a href="{userscript_url}" target="_blank">2. Install the {provider_name} userscript</a>
219
208
  </p>
209
+ <p style="margin-top: 0; margin-bottom: 12px;">
210
+ 3. Open link, solve CAPTCHAs, and links are automatically sent back to Quasarr!
211
+ </p>
220
212
  <p style="margin-top: 0;">
221
213
  <button id="hide-setup-btn" type="button" class="btn-subtle">
222
214
  ✅ Don't show this again
@@ -318,6 +310,7 @@ def setup_captcha_routes(app):
318
310
  title = payload.get("title")
319
311
  password = payload.get("password")
320
312
  urls = payload.get("links")
313
+ original_url = payload.get("original_url")
321
314
  url = urls[0][0] if isinstance(urls[0], (list, tuple)) else urls[0]
322
315
 
323
316
  check_package_exists(package_id)
@@ -325,6 +318,10 @@ def setup_captcha_routes(app):
325
318
  package_selector = render_package_selector(package_id, title)
326
319
  failed_warning = render_failed_attempts_warning(package_id)
327
320
 
321
+ source_button = ""
322
+ if original_url:
323
+ source_button = f'<p>{render_button("Source", "secondary", {"onclick": f"window.open(\'{js_single_quoted_string_safe(original_url)}\', \'_blank\')" })}</p>'
324
+
328
325
  return render_centered_html(f"""
329
326
  <!DOCTYPE html>
330
327
  <html>
@@ -333,6 +330,7 @@ def setup_captcha_routes(app):
333
330
  {package_selector}
334
331
  {failed_warning}
335
332
  {render_userscript_section(url, package_id, title, password, "hide")}
333
+ {source_button}
336
334
  <p>
337
335
  {render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
338
336
  </p>
@@ -358,6 +356,7 @@ def setup_captcha_routes(app):
358
356
  title = payload.get("title")
359
357
  password = payload.get("password")
360
358
  urls = payload.get("links")
359
+ original_url = payload.get("original_url")
361
360
  url = urls[0][0] if isinstance(urls[0], (list, tuple)) else urls[0]
362
361
 
363
362
  check_package_exists(package_id)
@@ -365,6 +364,10 @@ def setup_captcha_routes(app):
365
364
  package_selector = render_package_selector(package_id, title)
366
365
  failed_warning = render_failed_attempts_warning(package_id)
367
366
 
367
+ source_button = ""
368
+ if original_url:
369
+ source_button = f'<p>{render_button("Source", "secondary", {"onclick": f"window.open(\'{js_single_quoted_string_safe(original_url)}\', \'_blank\')" })}</p>'
370
+
368
371
  return render_centered_html(f"""
369
372
  <!DOCTYPE html>
370
373
  <html>
@@ -373,6 +376,7 @@ def setup_captcha_routes(app):
373
376
  {package_selector}
374
377
  {failed_warning}
375
378
  {render_userscript_section(url, package_id, title, password, "junkies")}
379
+ {source_button}
376
380
  <p>
377
381
  {render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
378
382
  </p>
@@ -398,6 +402,7 @@ def setup_captcha_routes(app):
398
402
  title = payload.get("title")
399
403
  password = payload.get("password")
400
404
  urls = payload.get("links")
405
+ original_url = payload.get("original_url")
401
406
 
402
407
  check_package_exists(package_id)
403
408
 
@@ -406,6 +411,10 @@ def setup_captcha_routes(app):
406
411
  package_selector = render_package_selector(package_id, title)
407
412
  failed_warning = render_failed_attempts_warning(package_id)
408
413
 
414
+ source_button = ""
415
+ if original_url:
416
+ source_button = f'<p>{render_button("Source", "secondary", {"onclick": f"window.open(\'{js_single_quoted_string_safe(original_url)}\', \'_blank\')" })}</p>'
417
+
409
418
  return render_centered_html(f"""
410
419
  <!DOCTYPE html>
411
420
  <html>
@@ -414,6 +423,7 @@ def setup_captcha_routes(app):
414
423
  {package_selector}
415
424
  {failed_warning}
416
425
  {render_userscript_section(url, package_id, title, password, "keeplinks")}
426
+ {source_button}
417
427
  <p>
418
428
  {render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
419
429
  </p>
@@ -439,6 +449,7 @@ def setup_captcha_routes(app):
439
449
  title = payload.get("title")
440
450
  password = payload.get("password")
441
451
  urls = payload.get("links")
452
+ original_url = payload.get("original_url")
442
453
 
443
454
  check_package_exists(package_id)
444
455
 
@@ -447,6 +458,10 @@ def setup_captcha_routes(app):
447
458
  package_selector = render_package_selector(package_id, title)
448
459
  failed_warning = render_failed_attempts_warning(package_id)
449
460
 
461
+ source_button = ""
462
+ if original_url:
463
+ source_button = f'<p>{render_button("Source", "secondary", {"onclick": f"window.open(\'{js_single_quoted_string_safe(original_url)}\', \'_blank\')" })}</p>'
464
+
450
465
  return render_centered_html(f"""
451
466
  <!DOCTYPE html>
452
467
  <html>
@@ -455,6 +470,7 @@ def setup_captcha_routes(app):
455
470
  {package_selector}
456
471
  {failed_warning}
457
472
  {render_userscript_section(url, package_id, title, password, "tolink")}
473
+ {source_button}
458
474
  <p>
459
475
  {render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
460
476
  </p>
@@ -519,29 +535,18 @@ def setup_captcha_routes(app):
519
535
  <details id="bypassDetails">
520
536
  <summary id="bypassSummary">Show CAPTCHA Bypass</summary><br>
521
537
 
522
- <!-- Info section explaining the process -->
523
- <div class="info-box">
524
- <h3>ℹ️ How This Works:</h3>
525
- <p style="margin-bottom: 8px;">
526
- 1. Click the button below to open FileCrypt directly
527
- </p>
528
- <p style="margin-top: 0; margin-bottom: 8px;">
529
- 2. Solve any CAPTCHAs on their site to reveal the download links
530
- </p>
531
- <p style="margin-top: 0; margin-bottom: 0;">
532
- 3. <b>With the userscript installed</b>, links are automatically sent back to Quasarr!
533
- </p>
534
- </div>
535
-
536
538
  <!-- One-time setup section - visually separated -->
537
539
  <div id="setup-instructions" class="setup-box">
538
540
  <h3>📦 First Time Setup:</h3>
539
541
  <p style="margin-bottom: 8px;">
540
- <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. Install Tampermonkey</a>
542
+ <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. On mobile Safari/Firefox or any Desktop Browser install Tampermonkey</a>
541
543
  </p>
542
- <p style="margin-top: 0; margin-bottom: 12px;">
544
+ <p style="margin-top: 0; margin-bottom: 8px;">
543
545
  <a href="/captcha/filecrypt.user.js" target="_blank">2. Install the FileCrypt userscript</a>
544
546
  </p>
547
+ <p style="margin-top: 0; margin-bottom: 12px;">
548
+ 3. Open link, solve CAPTCHAs, and links are automatically sent back to Quasarr!
549
+ </p>
545
550
  <p style="margin-top: 0;">
546
551
  <button id="hide-setup-btn" type="button" class="btn-subtle">
547
552
  ✅ Don't show this again
@@ -682,6 +687,7 @@ def setup_captcha_routes(app):
682
687
  links = data.get("links", [])
683
688
  password = data.get("password", "")
684
689
  mirror = data.get("mirror")
690
+ original_url = data.get("original_url")
685
691
 
686
692
  # Prioritize rapidgator links for cutcaptcha
687
693
  rapid = [ln for ln in links if "rapidgator" in ln[1].lower()]
@@ -694,6 +700,7 @@ def setup_captcha_routes(app):
694
700
  "password": password,
695
701
  "mirror": mirror,
696
702
  "links": prioritized,
703
+ "original_url": original_url,
697
704
  }
698
705
  encoded = urlsafe_b64encode(json.dumps(payload).encode()).decode()
699
706
  captcha_type = get_captcha_type_for_links(prioritized)
@@ -818,6 +825,7 @@ def setup_captcha_routes(app):
818
825
  title = payload.get("title")
819
826
  password = payload.get("password")
820
827
  urls = payload.get("links")
828
+ original_url = payload.get("original_url")
821
829
 
822
830
  check_package_exists(package_id)
823
831
 
@@ -838,6 +846,10 @@ def setup_captcha_routes(app):
838
846
  package_selector = render_package_selector(package_id, title)
839
847
  failed_warning = render_failed_attempts_warning(package_id)
840
848
 
849
+ source_button = ""
850
+ if original_url:
851
+ source_button = f'<p>{render_button("Source", "secondary", {"onclick": f"window.open(\'{js_single_quoted_string_safe(original_url)}\', \'_blank\')" })}</p>'
852
+
841
853
  return render_centered_html(f"""
842
854
  <!DOCTYPE html>
843
855
  <html>
@@ -847,29 +859,18 @@ def setup_captcha_routes(app):
847
859
  {failed_warning}
848
860
 
849
861
  <div>
850
- <!-- Info section explaining the process -->
851
- <div class="info-box">
852
- <h3>ℹ️ How This Works:</h3>
853
- <p style="margin-bottom: 8px;">
854
- 1. Click the button below to open FileCrypt directly
855
- </p>
856
- <p style="margin-top: 0; margin-bottom: 8px;">
857
- 2. Solve any CAPTCHAs on their site to reveal the download links
858
- </p>
859
- <p style="margin-top: 0; margin-bottom: 0;">
860
- 3. <b>With the userscript installed</b>, links are automatically sent back to Quasarr!
861
- </p>
862
- </div>
863
-
864
862
  <!-- One-time setup section - visually separated -->
865
863
  <div id="setup-instructions" class="setup-box">
866
864
  <h3>📦 First Time Setup:</h3>
867
865
  <p style="margin-bottom: 8px;">
868
- <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. Install Tampermonkey</a>
866
+ <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. On mobile Safari/Firefox or any Desktop Browser install Tampermonkey</a>
869
867
  </p>
870
- <p style="margin-top: 0; margin-bottom: 12px;">
868
+ <p style="margin-top: 0; margin-bottom: 8px;">
871
869
  <a href="/captcha/filecrypt.user.js" target="_blank">2. Install the FileCrypt userscript</a>
872
870
  </p>
871
+ <p style="margin-top: 0; margin-bottom: 12px;">
872
+ 3. Open link, solve CAPTCHAs, and links are automatically sent back to Quasarr!
873
+ </p>
873
874
  <p style="margin-top: 0;">
874
875
  <button id="hide-setup-btn" type="button" class="btn-subtle">
875
876
  ✅ Don't show this again
@@ -921,6 +922,7 @@ def setup_captcha_routes(app):
921
922
  </div>
922
923
  </div>
923
924
 
925
+ {source_button}
924
926
  <p>
925
927
  {render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
926
928
  </p>
@@ -1142,6 +1144,7 @@ def setup_captcha_routes(app):
1142
1144
  password = payload.get("password")
1143
1145
  desired_mirror = payload.get("mirror")
1144
1146
  prioritized_links = payload.get("links")
1147
+ original_url = payload.get("original_url")
1145
1148
 
1146
1149
  check_package_exists(package_id)
1147
1150
 
@@ -1199,6 +1202,7 @@ def setup_captcha_routes(app):
1199
1202
  "password": password,
1200
1203
  "mirror": desired_mirror,
1201
1204
  "links": prioritized_links,
1205
+ "original_url": original_url,
1202
1206
  }
1203
1207
  fallback_encoded = urlsafe_b64encode(json.dumps(fallback_payload).encode()).decode()
1204
1208
  filecrypt_fallback_url = f"/captcha/filecrypt?data={quote(fallback_encoded)}"
@@ -1209,6 +1213,10 @@ def setup_captcha_routes(app):
1209
1213
  # Escape title for safe use in JavaScript string
1210
1214
  escaped_title_js = title.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r')
1211
1215
 
1216
+ source_button_html = ""
1217
+ if original_url:
1218
+ source_button_html = f'<p>{render_button("Source", "secondary", {"onclick": f"window.open(\'{js_single_quoted_string_safe(original_url)}\', \'_blank\')" })}</p>'
1219
+
1212
1220
  content = render_centered_html(r'''
1213
1221
  <style>
1214
1222
  /* Fix captcha container to shrink-wrap iframe on desktop */
@@ -1321,6 +1329,7 @@ def setup_captcha_routes(app):
1321
1329
  </div>
1322
1330
  <br>
1323
1331
  <div id="delete-package-section">
1332
+ ''' + source_button_html + f'''
1324
1333
  <p>
1325
1334
  {render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
1326
1335
  </p>
@@ -121,6 +121,8 @@ def setup_sponsors_helper_routes(app):
121
121
 
122
122
  StatsHelper(shared_state).increment_captcha_decryptions_automatic()
123
123
 
124
+ send_discord_message(shared_state, title=title, case="disabled")
125
+
124
126
  return f"Package {title} disabled"
125
127
 
126
128
  except Exception as e:
@@ -53,7 +53,10 @@ def send_discord_message(shared_state, title, case, imdb_id=None, details=None,
53
53
  description = 'CAPTCHA solved by SponsorsHelper!'
54
54
  fields = None
55
55
  elif case == "failed":
56
- description = 'SponsorsHelper failed to solve the CAPTCHA! Package marked es failed.'
56
+ description = 'SponsorsHelper failed to solve the CAPTCHA! Package marked as failed for deletion.'
57
+ fields = None
58
+ elif case == "disabled":
59
+ description = 'SponsorsHelper failed to solve the CAPTCHA! Please solve it manually to proceed.'
57
60
  fields = None
58
61
  elif case == "captcha":
59
62
  description = 'Download will proceed, once the CAPTCHA has been solved.'
@@ -112,7 +115,7 @@ def send_discord_message(shared_state, title, case, imdb_id=None, details=None,
112
115
  }
113
116
 
114
117
  # Apply silent mode: suppress notifications for all cases except 'deleted'
115
- if silent and case not in ["failed", "quasarr_update"]:
118
+ if silent and case not in ["failed", "quasarr_update", "disabled"]:
116
119
  data['flags'] = SUPPRESS_NOTIFICATIONS
117
120
 
118
121
  response = requests.post(shared_state.values["discord"], data=json.dumps(data),
@@ -8,7 +8,7 @@ import requests
8
8
 
9
9
 
10
10
  def get_version():
11
- return "2.3.3"
11
+ return "2.4.1"
12
12
 
13
13
 
14
14
  def get_latest_version():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quasarr
3
- Version: 2.3.3
3
+ Version: 2.4.1
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes