quasarr 2.1.2__py3-none-any.whl → 2.1.4__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 +4 -1
- quasarr/api/packages/__init__.py +108 -26
- quasarr/downloads/packages/__init__.py +19 -10
- quasarr/providers/auth.py +6 -1
- quasarr/providers/version.py +1 -1
- {quasarr-2.1.2.dist-info → quasarr-2.1.4.dist-info}/METADATA +1 -1
- {quasarr-2.1.2.dist-info → quasarr-2.1.4.dist-info}/RECORD +11 -11
- {quasarr-2.1.2.dist-info → quasarr-2.1.4.dist-info}/WHEEL +0 -0
- {quasarr-2.1.2.dist-info → quasarr-2.1.4.dist-info}/entry_points.txt +0 -0
- {quasarr-2.1.2.dist-info → quasarr-2.1.4.dist-info}/licenses/LICENSE +0 -0
- {quasarr-2.1.2.dist-info → quasarr-2.1.4.dist-info}/top_level.txt +0 -0
quasarr/api/__init__.py
CHANGED
|
@@ -25,7 +25,10 @@ def get_api(shared_state_dict, shared_state_lock):
|
|
|
25
25
|
|
|
26
26
|
# Auth: routes must come first, then hook
|
|
27
27
|
add_auth_routes(app)
|
|
28
|
-
add_auth_hook(app,
|
|
28
|
+
add_auth_hook(app,
|
|
29
|
+
whitelist_prefixes=['/api', '/api/', '/sponsors_helper/', '/download/'],
|
|
30
|
+
whitelist_suffixes=['.user.js']
|
|
31
|
+
)
|
|
29
32
|
|
|
30
33
|
setup_arr_routes(app)
|
|
31
34
|
setup_captcha_routes(app)
|
quasarr/api/packages/__init__.py
CHANGED
|
@@ -9,14 +9,24 @@ from quasarr.providers.html_templates import render_button, render_centered_html
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def _get_category_emoji(cat):
|
|
12
|
-
return {'movies': '🎬', 'tv': '📺', 'docs': '📄', 'not_quasarr': '
|
|
12
|
+
return {'movies': '🎬', 'tv': '📺', 'docs': '📄', 'not_quasarr': '❓'}.get(cat, '❓')
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def _format_size(mb=None, bytes_val=None):
|
|
16
16
|
if bytes_val is not None:
|
|
17
|
+
# Handle bytes directly for better precision with small files
|
|
18
|
+
if bytes_val == 0:
|
|
19
|
+
return "? MB"
|
|
20
|
+
if bytes_val < 1024 * 1024: # Less than 1 MB
|
|
21
|
+
kb = bytes_val / 1024
|
|
22
|
+
if kb < 1:
|
|
23
|
+
return f"{bytes_val} B"
|
|
24
|
+
return f"{kb:.0f} KB"
|
|
17
25
|
mb = bytes_val / (1024 * 1024)
|
|
18
26
|
if mb is None or mb == 0:
|
|
19
27
|
return "? MB"
|
|
28
|
+
if mb < 1:
|
|
29
|
+
return f"{mb * 1024:.0f} KB"
|
|
20
30
|
if mb < 1024:
|
|
21
31
|
return f"{mb:.0f} MB"
|
|
22
32
|
return f"{mb / 1024:.1f} GB"
|
|
@@ -30,7 +40,7 @@ def _render_queue_item(item):
|
|
|
30
40
|
filename = item.get('filename', 'Unknown')
|
|
31
41
|
percentage = item.get('percentage', 0)
|
|
32
42
|
timeleft = item.get('timeleft', '??:??:??')
|
|
33
|
-
|
|
43
|
+
bytes_val = item.get('bytes', 0)
|
|
34
44
|
cat = item.get('cat', 'not_quasarr')
|
|
35
45
|
is_archive = item.get('is_archive', False)
|
|
36
46
|
nzo_id = item.get('nzo_id', '')
|
|
@@ -51,9 +61,9 @@ def _render_queue_item(item):
|
|
|
51
61
|
for prefix in ['[Downloading] ', '[Extracting] ', '[Paused] ', '[Linkgrabber] ', '[CAPTCHA not solved!] ']:
|
|
52
62
|
display_name = display_name.replace(prefix, '')
|
|
53
63
|
|
|
54
|
-
archive_badge = '<span class="badge archive"
|
|
64
|
+
archive_badge = '<span class="badge archive">📁</span>' if is_archive else ''
|
|
55
65
|
cat_emoji = _get_category_emoji(cat)
|
|
56
|
-
size_str = _format_size(
|
|
66
|
+
size_str = _format_size(bytes_val=bytes_val)
|
|
57
67
|
|
|
58
68
|
# Progress bar - show "waiting..." for 0%
|
|
59
69
|
if percentage == 0:
|
|
@@ -84,7 +94,6 @@ def _render_queue_item(item):
|
|
|
84
94
|
<div class="package-header">
|
|
85
95
|
<span class="status-emoji">{status_emoji}</span>
|
|
86
96
|
<span class="package-name">{display_name}</span>
|
|
87
|
-
{archive_badge}
|
|
88
97
|
</div>
|
|
89
98
|
<div class="package-progress">
|
|
90
99
|
{progress_html}
|
|
@@ -93,7 +102,8 @@ def _render_queue_item(item):
|
|
|
93
102
|
<div class="package-details">
|
|
94
103
|
<span>⏱️ {timeleft}</span>
|
|
95
104
|
<span>💾 {size_str}</span>
|
|
96
|
-
<span>{cat_emoji}
|
|
105
|
+
<span>{cat_emoji}</span>
|
|
106
|
+
{archive_badge}
|
|
97
107
|
</div>
|
|
98
108
|
{actions}
|
|
99
109
|
</div>
|
|
@@ -119,11 +129,11 @@ def _render_history_item(item):
|
|
|
119
129
|
archive_badge = ''
|
|
120
130
|
if is_archive:
|
|
121
131
|
if extraction_status == 'SUCCESSFUL':
|
|
122
|
-
archive_badge = '<span class="badge extracted"
|
|
132
|
+
archive_badge = '<span class="badge extracted">✅</span>'
|
|
123
133
|
elif extraction_status == 'RUNNING':
|
|
124
|
-
archive_badge = '<span class="badge pending"
|
|
134
|
+
archive_badge = '<span class="badge pending">⏳</span>'
|
|
125
135
|
else:
|
|
126
|
-
archive_badge = '<span class="badge archive"
|
|
136
|
+
archive_badge = '<span class="badge archive">📁</span>'
|
|
127
137
|
|
|
128
138
|
status_emoji = '❌' if is_error else '✅'
|
|
129
139
|
error_html = f'<div class="package-error">⚠️ {fail_message}</div>' if fail_message else ''
|
|
@@ -143,11 +153,11 @@ def _render_history_item(item):
|
|
|
143
153
|
<div class="package-header">
|
|
144
154
|
<span class="status-emoji">{status_emoji}</span>
|
|
145
155
|
<span class="package-name">{name}</span>
|
|
146
|
-
{archive_badge}
|
|
147
156
|
</div>
|
|
148
157
|
<div class="package-details">
|
|
149
158
|
<span>💾 {size_str}</span>
|
|
150
|
-
<span>{cat_emoji}
|
|
159
|
+
<span>{cat_emoji}</span>
|
|
160
|
+
{archive_badge}
|
|
151
161
|
</div>
|
|
152
162
|
{error_html}
|
|
153
163
|
{actions}
|
|
@@ -167,7 +177,12 @@ def _render_packages_content():
|
|
|
167
177
|
quasarr_history = [p for p in history if p.get('category') != 'not_quasarr']
|
|
168
178
|
other_history = [p for p in history if p.get('category') == 'not_quasarr']
|
|
169
179
|
|
|
170
|
-
#
|
|
180
|
+
# Check if there's anything at all
|
|
181
|
+
has_quasarr_content = quasarr_queue or quasarr_history
|
|
182
|
+
has_other_content = other_queue or other_history
|
|
183
|
+
has_any_content = has_quasarr_content or has_other_content
|
|
184
|
+
|
|
185
|
+
# Build queue section (only if has items)
|
|
171
186
|
queue_html = ''
|
|
172
187
|
if quasarr_queue:
|
|
173
188
|
queue_items = ''.join(_render_queue_item(item) for item in quasarr_queue)
|
|
@@ -177,10 +192,8 @@ def _render_packages_content():
|
|
|
177
192
|
<div class="packages-list">{queue_items}</div>
|
|
178
193
|
</div>
|
|
179
194
|
'''
|
|
180
|
-
else:
|
|
181
|
-
queue_html = '<div class="section"><p class="empty-message">No active downloads</p></div>'
|
|
182
195
|
|
|
183
|
-
# Build history section
|
|
196
|
+
# Build history section (only if has items)
|
|
184
197
|
history_html = ''
|
|
185
198
|
if quasarr_history:
|
|
186
199
|
history_items = ''.join(_render_history_item(item) for item in quasarr_history[:10])
|
|
@@ -204,20 +217,28 @@ def _render_packages_content():
|
|
|
204
217
|
other_items += ''.join(_render_history_item(item) for item in other_history[:5])
|
|
205
218
|
|
|
206
219
|
plural = 's' if other_count != 1 else ''
|
|
220
|
+
# Only add separator class if there's Quasarr content above
|
|
221
|
+
section_class = 'other-packages-section' if has_quasarr_content else 'other-packages-section no-separator'
|
|
207
222
|
other_html = f'''
|
|
208
|
-
<div class="
|
|
223
|
+
<div class="{section_class}">
|
|
209
224
|
<details id="otherPackagesDetails">
|
|
210
|
-
<summary id="otherPackagesSummary">Show {other_count}
|
|
225
|
+
<summary id="otherPackagesSummary">Show {other_count} other package{plural}</summary>
|
|
211
226
|
<div class="other-packages-content">{other_items}</div>
|
|
212
227
|
</details>
|
|
213
228
|
</div>
|
|
214
229
|
'''
|
|
215
230
|
|
|
231
|
+
# Only show "no downloads" if there's literally nothing
|
|
232
|
+
empty_html = ''
|
|
233
|
+
if not has_any_content:
|
|
234
|
+
empty_html = '<p class="empty-message">No packages</p>'
|
|
235
|
+
|
|
216
236
|
return f'''
|
|
217
237
|
<div class="packages-container">
|
|
218
238
|
{queue_html}
|
|
219
239
|
{history_html}
|
|
220
240
|
{other_html}
|
|
241
|
+
{empty_html}
|
|
221
242
|
</div>
|
|
222
243
|
'''
|
|
223
244
|
|
|
@@ -283,6 +304,8 @@ def setup_packages_routes(app):
|
|
|
283
304
|
|
|
284
305
|
{status_message}
|
|
285
306
|
|
|
307
|
+
<div id="slow-warning" class="slow-warning" style="display:none;">⚠️ Slow connection detected</div>
|
|
308
|
+
|
|
286
309
|
<div id="packages-content">
|
|
287
310
|
{packages_content}
|
|
288
311
|
</div>
|
|
@@ -349,7 +372,26 @@ def setup_packages_routes(app):
|
|
|
349
372
|
|
|
350
373
|
.empty-message {{ color: var(--text-muted, #888); font-style: italic; text-align: center; padding: 20px; }}
|
|
351
374
|
|
|
375
|
+
.slow-warning {{
|
|
376
|
+
text-align: center;
|
|
377
|
+
font-size: 0.85em;
|
|
378
|
+
color: #856404;
|
|
379
|
+
background: #fff3cd;
|
|
380
|
+
border: 1px solid #ffc107;
|
|
381
|
+
padding: 8px 12px;
|
|
382
|
+
border-radius: 6px;
|
|
383
|
+
margin-bottom: 15px;
|
|
384
|
+
}}
|
|
385
|
+
@media (prefers-color-scheme: dark) {{
|
|
386
|
+
.slow-warning {{
|
|
387
|
+
color: #ffc107;
|
|
388
|
+
background: #3d3510;
|
|
389
|
+
border-color: #665c00;
|
|
390
|
+
}}
|
|
391
|
+
}}
|
|
392
|
+
|
|
352
393
|
.other-packages-section {{ margin-top: 30px; padding-top: 20px; border-top: 1px solid var(--border-color, #ddd); }}
|
|
394
|
+
.other-packages-section.no-separator {{ margin-top: 0; padding-top: 0; border-top: none; }}
|
|
353
395
|
.other-packages-section summary {{ cursor: pointer; padding: 8px 0; color: var(--text-muted, #666); }}
|
|
354
396
|
.other-packages-section summary:hover {{ color: var(--link-color, #0066cc); }}
|
|
355
397
|
.other-packages-content {{ margin-top: 15px; }}
|
|
@@ -405,24 +447,51 @@ def setup_packages_routes(app):
|
|
|
405
447
|
<script>
|
|
406
448
|
// Background refresh - fetches content via AJAX, waits 5s between refresh cycles
|
|
407
449
|
let refreshPaused = false;
|
|
450
|
+
let slowConnection = false;
|
|
408
451
|
|
|
409
452
|
async function refreshContent() {{
|
|
410
453
|
if (refreshPaused) return;
|
|
454
|
+
|
|
455
|
+
const startTime = Date.now();
|
|
456
|
+
const warningEl = document.getElementById('slow-warning');
|
|
457
|
+
|
|
458
|
+
// Save scroll position before refresh
|
|
459
|
+
const scrollY = window.scrollY;
|
|
460
|
+
|
|
461
|
+
// Show warning after 5s if still loading
|
|
462
|
+
const slowTimer = setTimeout(() => {{
|
|
463
|
+
slowConnection = true;
|
|
464
|
+
if (warningEl) warningEl.style.display = 'block';
|
|
465
|
+
}}, 5000);
|
|
466
|
+
|
|
411
467
|
try {{
|
|
412
468
|
const response = await fetch('/api/packages/content');
|
|
469
|
+
const elapsed = Date.now() - startTime;
|
|
470
|
+
|
|
471
|
+
clearTimeout(slowTimer);
|
|
472
|
+
|
|
473
|
+
// Update slow connection state
|
|
474
|
+
if (elapsed < 5000) {{
|
|
475
|
+
slowConnection = false;
|
|
476
|
+
if (warningEl) warningEl.style.display = 'none';
|
|
477
|
+
}} else {{
|
|
478
|
+
slowConnection = true;
|
|
479
|
+
if (warningEl) warningEl.style.display = 'block';
|
|
480
|
+
}}
|
|
481
|
+
|
|
413
482
|
if (response.ok) {{
|
|
414
483
|
const html = await response.text();
|
|
415
484
|
const container = document.getElementById('packages-content');
|
|
416
485
|
if (container && html) {{
|
|
417
486
|
container.innerHTML = html;
|
|
418
|
-
// Re-apply collapse state after content update
|
|
419
487
|
restoreCollapseState();
|
|
488
|
+
// Restore scroll position after content update
|
|
489
|
+
window.scrollTo(0, scrollY);
|
|
420
490
|
}}
|
|
421
491
|
}}
|
|
422
492
|
}} catch (e) {{
|
|
423
|
-
|
|
493
|
+
clearTimeout(slowTimer);
|
|
424
494
|
}}
|
|
425
|
-
// Schedule next refresh 5 seconds after this one completes
|
|
426
495
|
setTimeout(refreshContent, 5000);
|
|
427
496
|
}}
|
|
428
497
|
|
|
@@ -434,7 +503,7 @@ def setup_packages_routes(app):
|
|
|
434
503
|
const plural = count !== '1' ? 's' : '';
|
|
435
504
|
if (localStorage.getItem('otherPackagesOpen') === 'true') {{
|
|
436
505
|
otherDetails.open = true;
|
|
437
|
-
otherSummary.textContent = 'Hide ' + count + '
|
|
506
|
+
otherSummary.textContent = 'Hide ' + count + ' other package' + plural;
|
|
438
507
|
}}
|
|
439
508
|
// Re-attach event listener
|
|
440
509
|
otherDetails.onclick = null;
|
|
@@ -442,23 +511,36 @@ def setup_packages_routes(app):
|
|
|
442
511
|
localStorage.setItem('otherPackagesOpen', this.open);
|
|
443
512
|
const summaryEl = document.getElementById('otherPackagesSummary');
|
|
444
513
|
if (summaryEl) {{
|
|
445
|
-
summaryEl.textContent = (this.open ? 'Hide ' : 'Show ') + count + '
|
|
514
|
+
summaryEl.textContent = (this.open ? 'Hide ' : 'Show ') + count + ' other package' + plural;
|
|
446
515
|
}}
|
|
447
516
|
}});
|
|
448
517
|
}}
|
|
449
518
|
}}
|
|
450
519
|
|
|
451
|
-
// Start refresh cycle after initial 5s delay
|
|
452
|
-
setTimeout(refreshContent, 5000);
|
|
453
|
-
|
|
454
520
|
// Initial collapse state setup
|
|
455
521
|
restoreCollapseState();
|
|
456
522
|
|
|
457
|
-
// Clear status message from URL after display
|
|
523
|
+
// Clear status message from URL after display and auto-hide after 5s
|
|
458
524
|
if (window.location.search.includes('deleted=')) {{
|
|
459
525
|
const url = new URL(window.location);
|
|
460
526
|
url.searchParams.delete('deleted');
|
|
461
527
|
window.history.replaceState({{}}, '', url);
|
|
528
|
+
|
|
529
|
+
// Hide the status message after 5 seconds
|
|
530
|
+
const statusMsg = document.querySelector('.status-message');
|
|
531
|
+
if (statusMsg) {{
|
|
532
|
+
setTimeout(() => {{
|
|
533
|
+
statusMsg.style.transition = 'opacity 0.3s';
|
|
534
|
+
statusMsg.style.opacity = '0';
|
|
535
|
+
setTimeout(() => statusMsg.remove(), 300);
|
|
536
|
+
}}, 5000);
|
|
537
|
+
}}
|
|
538
|
+
|
|
539
|
+
// Reset refresh - start fresh 5s countdown after delete
|
|
540
|
+
setTimeout(refreshContent, 5000);
|
|
541
|
+
}} else {{
|
|
542
|
+
// Normal start - 5s delay
|
|
543
|
+
setTimeout(refreshContent, 5000);
|
|
462
544
|
}}
|
|
463
545
|
|
|
464
546
|
// Delete modal
|
|
@@ -510,22 +510,27 @@ def get_packages(shared_state, _cache=None):
|
|
|
510
510
|
package_type = "protected"
|
|
511
511
|
package_uuid = None
|
|
512
512
|
|
|
513
|
-
if
|
|
513
|
+
# Use package_id if available, otherwise use uuid as fallback for non-Quasarr packages
|
|
514
|
+
effective_id = package_id or package_uuid
|
|
515
|
+
|
|
516
|
+
if effective_id:
|
|
514
517
|
try:
|
|
515
|
-
mb_left = int(mb_left) if mb_left else 0
|
|
516
|
-
mb = int(mb) if mb else 0
|
|
517
518
|
percentage = int(100 * (mb - mb_left) / mb) if mb > 0 else 0
|
|
518
519
|
except (ZeroDivisionError, ValueError, TypeError):
|
|
519
520
|
percentage = 0
|
|
520
521
|
|
|
522
|
+
# Keep mb/mbleft as integers for API compatibility, add bytes for UI display
|
|
523
|
+
bytes_total = int(mb * 1024 * 1024) if mb else 0
|
|
524
|
+
|
|
521
525
|
downloads["queue"].append({
|
|
522
526
|
"index": queue_index,
|
|
523
|
-
"nzo_id":
|
|
527
|
+
"nzo_id": effective_id,
|
|
524
528
|
"priority": "Normal",
|
|
525
529
|
"filename": name,
|
|
526
530
|
"cat": category,
|
|
527
|
-
"mbleft": mb_left,
|
|
528
|
-
"mb": mb,
|
|
531
|
+
"mbleft": int(mb_left) if mb_left else 0,
|
|
532
|
+
"mb": int(mb) if mb else 0,
|
|
533
|
+
"bytes": bytes_total,
|
|
529
534
|
"status": "Downloading",
|
|
530
535
|
"percentage": percentage,
|
|
531
536
|
"timeleft": time_left,
|
|
@@ -535,18 +540,21 @@ def get_packages(shared_state, _cache=None):
|
|
|
535
540
|
})
|
|
536
541
|
queue_index += 1
|
|
537
542
|
else:
|
|
538
|
-
debug(f"get_packages: Skipping queue package without package_id: {name}")
|
|
543
|
+
debug(f"get_packages: Skipping queue package without package_id or uuid: {name}")
|
|
539
544
|
|
|
540
545
|
elif package["location"] == "history":
|
|
541
546
|
details = package["details"]
|
|
542
547
|
name = details.get("name", "unknown")
|
|
543
548
|
try:
|
|
544
|
-
|
|
549
|
+
# Use bytesLoaded first, fall back to bytesTotal for failed/incomplete downloads
|
|
550
|
+
size = int(details.get("bytesLoaded", 0)) or int(details.get("bytesTotal", 0))
|
|
545
551
|
except (KeyError, TypeError, ValueError):
|
|
546
552
|
size = 0
|
|
547
553
|
storage = details.get("saveTo", "/")
|
|
548
554
|
|
|
549
555
|
package_id = package.get("comment")
|
|
556
|
+
# Use package_id if available, otherwise use uuid as fallback for non-Quasarr packages
|
|
557
|
+
effective_id = package_id or package.get("uuid")
|
|
550
558
|
category = get_category_from_package_id(package_id)
|
|
551
559
|
|
|
552
560
|
error = package.get("error")
|
|
@@ -562,7 +570,7 @@ def get_packages(shared_state, _cache=None):
|
|
|
562
570
|
"category": category,
|
|
563
571
|
"storage": storage,
|
|
564
572
|
"status": status,
|
|
565
|
-
"nzo_id":
|
|
573
|
+
"nzo_id": effective_id,
|
|
566
574
|
"name": name,
|
|
567
575
|
"bytes": int(size),
|
|
568
576
|
"percentage": 100,
|
|
@@ -671,7 +679,8 @@ def delete_package(shared_state, package_id):
|
|
|
671
679
|
found = False
|
|
672
680
|
for package_location in packages:
|
|
673
681
|
for package in packages[package_location]:
|
|
674
|
-
|
|
682
|
+
# Compare as strings to handle int UUIDs from JDownloader
|
|
683
|
+
if str(package.get("nzo_id", "")) == str(package_id):
|
|
675
684
|
found = True
|
|
676
685
|
package_type = package.get("type")
|
|
677
686
|
package_uuid = package.get("uuid")
|
quasarr/providers/auth.py
CHANGED
|
@@ -273,7 +273,7 @@ def add_auth_routes(app):
|
|
|
273
273
|
return _handle_logout()
|
|
274
274
|
|
|
275
275
|
|
|
276
|
-
def add_auth_hook(app, whitelist_prefixes=None):
|
|
276
|
+
def add_auth_hook(app, whitelist_prefixes=None, whitelist_suffixes=None):
|
|
277
277
|
"""Add authentication hook to a Bottle app.
|
|
278
278
|
|
|
279
279
|
Args:
|
|
@@ -299,6 +299,11 @@ def add_auth_hook(app, whitelist_prefixes=None):
|
|
|
299
299
|
if path.startswith(prefix):
|
|
300
300
|
return
|
|
301
301
|
|
|
302
|
+
# Check whitelist suffixes:
|
|
303
|
+
for suffix in whitelist_suffixes:
|
|
304
|
+
if path.endswith(suffix):
|
|
305
|
+
return
|
|
306
|
+
|
|
302
307
|
# Check authentication
|
|
303
308
|
if is_form_auth():
|
|
304
309
|
if not check_form_auth():
|
quasarr/providers/version.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
quasarr/__init__.py,sha256=cEtxN2AuwKvrxpIvAR7UL997VtYQ4iN3Eo3ZnP-WjZQ,14682
|
|
2
|
-
quasarr/api/__init__.py,sha256=
|
|
2
|
+
quasarr/api/__init__.py,sha256=yrDJM0qxmsOruOyqUwhSmmaT6E3DLK-yPy7Lutk1WYM,16384
|
|
3
3
|
quasarr/api/arr/__init__.py,sha256=eEop8A5t936uT5azn4qz0bq1DMX84_Ja16wyleGFhyM,18495
|
|
4
4
|
quasarr/api/captcha/__init__.py,sha256=2pca9jnJMWZECHeAvKP9Lwsa3_GkVsvQEn7rof8Ep1s,73504
|
|
5
5
|
quasarr/api/config/__init__.py,sha256=HDoqRv6El-e5iejVpwEz6ttySjDeiTQGom5D__nachU,13682
|
|
6
|
-
quasarr/api/packages/__init__.py,sha256=
|
|
6
|
+
quasarr/api/packages/__init__.py,sha256=0X7U47xfU9zvNT-yxFGhQG3upqX7q-7PEC6dETRD-I8,26407
|
|
7
7
|
quasarr/api/sponsors_helper/__init__.py,sha256=vZIFGkc5HTRozjvi47tqxz6XpwDe8sDXVyeydc9k0Y0,6708
|
|
8
8
|
quasarr/api/statistics/__init__.py,sha256=NrBAjjHkIUE95HhPUGIfNqh2IqBqJ_zm00S90Y-Qnus,7038
|
|
9
9
|
quasarr/downloads/__init__.py,sha256=BUZpqWN3VnYSM8ZX4lC3MXVfShwx95I6FKz8Xl95T1s,16004
|
|
@@ -11,7 +11,7 @@ quasarr/downloads/linkcrypters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
|
|
|
11
11
|
quasarr/downloads/linkcrypters/al.py,sha256=mfUG5VclC_-FcGoZL9zHYD7dz7X_YpaNmoKkgiyl9-0,8812
|
|
12
12
|
quasarr/downloads/linkcrypters/filecrypt.py,sha256=nUZCTmvKylaNk1KAXcYUV1FgQCVAKNE3roXCNaqHLYA,17057
|
|
13
13
|
quasarr/downloads/linkcrypters/hide.py,sha256=H4hJWhENkszV1u_ULC3aOW2fu9infC-Nv-7wx2DYqrA,6266
|
|
14
|
-
quasarr/downloads/packages/__init__.py,sha256=
|
|
14
|
+
quasarr/downloads/packages/__init__.py,sha256=nBG4-O5-J3DRVp8tzMUN5HsUA946KwVyxhK0I69kAUw,32740
|
|
15
15
|
quasarr/downloads/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
quasarr/downloads/sources/al.py,sha256=g587VESZRZHZ03uxHKpufEr5qAtzbyGLmoijksU35jk,27297
|
|
17
17
|
quasarr/downloads/sources/by.py,sha256=kmUTn3izayRCV7W-t0E4kYE8qTbt3L3reCLozfvRGcU,3807
|
|
@@ -30,7 +30,7 @@ quasarr/downloads/sources/sl.py,sha256=jWprFt1Hew1T67fB1O_pc9YWgc3NVh30KXSwSyS50
|
|
|
30
30
|
quasarr/downloads/sources/wd.py,sha256=kr1I1uJa7ZkEPH2LA6alXTJEn0LBPgLCwIh3wLXwCv8,4447
|
|
31
31
|
quasarr/downloads/sources/wx.py,sha256=NzNNeqVL6sKkFKyreW-oerrreb5QP2tUGHTWHM5pMCU,7013
|
|
32
32
|
quasarr/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
-
quasarr/providers/auth.py,sha256=
|
|
33
|
+
quasarr/providers/auth.py,sha256=h0GuqLSvzzH0lduMXxVVs6OMYFBM8YBnamtZsRF7Ny8,10537
|
|
34
34
|
quasarr/providers/cloudflare.py,sha256=9iet8runc2VHVcA0_2z1qkrL6D5JKqz1ndktqCgsJFs,7873
|
|
35
35
|
quasarr/providers/html_images.py,sha256=2n82gTJg7E7q2ytPFN4FWouYTIlmPYu_iHFtG7uktIA,28482
|
|
36
36
|
quasarr/providers/html_templates.py,sha256=22g3WhAmwDQgMqaXirVaFF1LtlSxHS-Fjm2gpRcbMNg,12463
|
|
@@ -43,7 +43,7 @@ quasarr/providers/obfuscated.py,sha256=d0dxu3oPqDqN8I7qmGPPIBqjLzTQbZTQsLAZ5auw1
|
|
|
43
43
|
quasarr/providers/shared_state.py,sha256=5a_ZbGqTvt4-OqBt2a1WtR9I5J_Ky7IlkEY8EGtKVu8,30646
|
|
44
44
|
quasarr/providers/statistics.py,sha256=cEQixYnDMDqtm5wWe40E_2ucyo4mD0n3SrfelhQi1L8,6452
|
|
45
45
|
quasarr/providers/utils.py,sha256=mcUPbcXMsLmrYv0CTZO5a9aOt2-JLyL3SZxu6N8OyjU,12075
|
|
46
|
-
quasarr/providers/version.py,sha256=
|
|
46
|
+
quasarr/providers/version.py,sha256=viG1avqtR1pw7V6UDPJRnVo5bxMllFUzhKf7fVFXt_Q,4003
|
|
47
47
|
quasarr/providers/web_server.py,sha256=AYd0KRxdDWMBr87BP8wlSMuL4zZo0I_rY-vHBai6Pfg,1688
|
|
48
48
|
quasarr/providers/sessions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
49
|
quasarr/providers/sessions/al.py,sha256=WXue9LaT4y0BzsbKtHbN6bb_72c4AZZWR9NP-vg9-cg,12462
|
|
@@ -73,9 +73,9 @@ quasarr/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
73
73
|
quasarr/storage/config.py,sha256=SSTgIce2FVYoVTK_6OCU3msknhxuLA3EC4Kcrrf_dxQ,6378
|
|
74
74
|
quasarr/storage/setup.py,sha256=eXtgUqMacbaUDy-dszPtT15O9lJKSO1eI3v0jGjMiUA,42361
|
|
75
75
|
quasarr/storage/sqlite_database.py,sha256=yMqFQfKf0k7YS-6Z3_7pj4z1GwWSXJ8uvF4IydXsuTE,3554
|
|
76
|
-
quasarr-2.1.
|
|
77
|
-
quasarr-2.1.
|
|
78
|
-
quasarr-2.1.
|
|
79
|
-
quasarr-2.1.
|
|
80
|
-
quasarr-2.1.
|
|
81
|
-
quasarr-2.1.
|
|
76
|
+
quasarr-2.1.4.dist-info/licenses/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
|
|
77
|
+
quasarr-2.1.4.dist-info/METADATA,sha256=TMPUtWRbDzFwakaRor7JLnx2TwKZFUqB9-SZVoJbTH4,14914
|
|
78
|
+
quasarr-2.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
79
|
+
quasarr-2.1.4.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
|
|
80
|
+
quasarr-2.1.4.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
|
|
81
|
+
quasarr-2.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|