quasarr 1.25.0__tar.gz → 1.26.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.
- {quasarr-1.25.0 → quasarr-1.26.1}/PKG-INFO +1 -1
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/api/captcha/__init__.py +73 -22
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/__init__.py +2 -1
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/linkcrypters/hide.py +22 -8
- quasarr-1.26.1/quasarr/providers/html_images.py +22 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/html_templates.py +68 -3
- quasarr-1.26.1/quasarr/providers/obfuscated.py +119 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/version.py +1 -1
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr.egg-info/PKG-INFO +1 -1
- quasarr-1.25.0/quasarr/providers/html_images.py +0 -22
- quasarr-1.25.0/quasarr/providers/obfuscated.py +0 -86
- {quasarr-1.25.0 → quasarr-1.26.1}/LICENSE +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/README.md +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/api/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/api/arr/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/api/config/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/api/sponsors_helper/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/api/statistics/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/linkcrypters/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/linkcrypters/al.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/linkcrypters/filecrypt.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/packages/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/al.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/by.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/dd.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/dj.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/dl.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/dt.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/dw.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/he.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/mb.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/nk.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/nx.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/sf.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/sj.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/sl.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/wd.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/downloads/sources/wx.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/cloudflare.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/imdb_metadata.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/log.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/myjd_api.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/notifications.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/sessions/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/sessions/al.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/sessions/dd.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/sessions/dl.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/sessions/nx.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/shared_state.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/statistics.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/providers/web_server.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/al.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/by.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/dd.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/dj.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/dl.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/dt.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/dw.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/fx.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/he.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/mb.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/nk.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/nx.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/sf.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/sj.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/sl.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/wd.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/search/sources/wx.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/storage/__init__.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/storage/config.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/storage/setup.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr/storage/sqlite_database.py +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr.egg-info/SOURCES.txt +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr.egg-info/dependency_links.txt +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr.egg-info/entry_points.txt +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr.egg-info/not-zip-safe +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr.egg-info/requires.txt +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/quasarr.egg-info/top_level.txt +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/setup.cfg +0 -0
- {quasarr-1.25.0 → quasarr-1.26.1}/setup.py +0 -0
|
@@ -108,6 +108,12 @@ def setup_captcha_routes(app):
|
|
|
108
108
|
|
|
109
109
|
has_junkies_links = any(is_junkies_link(link) for link in prioritized_links)
|
|
110
110
|
|
|
111
|
+
# Hide uses nested arrays like FileCrypt: [["url", "mirror"]]
|
|
112
|
+
has_hide_links = any(
|
|
113
|
+
("hide." in link[0] if isinstance(link, (list, tuple)) else "hide." in link)
|
|
114
|
+
for link in prioritized_links
|
|
115
|
+
)
|
|
116
|
+
|
|
111
117
|
# KeepLinks uses nested arrays like FileCrypt: [["url", "mirror"]]
|
|
112
118
|
has_keeplinks_links = any(
|
|
113
119
|
("keeplinks." in link[0] if isinstance(link, (list, tuple)) else "keeplinks." in link)
|
|
@@ -120,7 +126,10 @@ def setup_captcha_routes(app):
|
|
|
120
126
|
for link in prioritized_links
|
|
121
127
|
)
|
|
122
128
|
|
|
123
|
-
if
|
|
129
|
+
if has_hide_links:
|
|
130
|
+
debug("Redirecting to Hide page")
|
|
131
|
+
redirect(f"/captcha/hide?data={quote(encoded_payload)}")
|
|
132
|
+
elif has_junkies_links:
|
|
124
133
|
debug("Redirecting to Junkies CAPTCHA")
|
|
125
134
|
redirect(f"/captcha/junkies?data={quote(encoded_payload)}")
|
|
126
135
|
elif has_keeplinks_links:
|
|
@@ -151,7 +160,7 @@ def setup_captcha_routes(app):
|
|
|
151
160
|
return {"error": f"Failed to decode payload: {str(e)}"}
|
|
152
161
|
|
|
153
162
|
def render_userscript_section(url, package_id, title, password, provider_type="junkies"):
|
|
154
|
-
"""Render the userscript UI section for Junkies, KeepLinks, or
|
|
163
|
+
"""Render the userscript UI section for Junkies, KeepLinks, ToLink, or Hide pages
|
|
155
164
|
|
|
156
165
|
This is the MAIN solution for these providers (not a bypass/fallback).
|
|
157
166
|
|
|
@@ -160,10 +169,10 @@ def setup_captcha_routes(app):
|
|
|
160
169
|
package_id: Package identifier
|
|
161
170
|
title: Package title
|
|
162
171
|
password: Package password
|
|
163
|
-
provider_type: Either "junkies", "keeplinks", or "tolink"
|
|
172
|
+
provider_type: Either "hide", "junkies", "keeplinks", or "tolink"
|
|
164
173
|
"""
|
|
165
174
|
|
|
166
|
-
provider_names = {"junkies": "Junkies", "keeplinks": "KeepLinks", "tolink": "ToLink"}
|
|
175
|
+
provider_names = {"hide": "Hide", "junkies": "Junkies", "keeplinks": "KeepLinks", "tolink": "ToLink"}
|
|
167
176
|
provider_name = provider_names.get(provider_type, "Provider")
|
|
168
177
|
userscript_url = f"/captcha/{provider_type}.user.js"
|
|
169
178
|
storage_key = f"hide{provider_name}SetupInstructions"
|
|
@@ -183,8 +192,8 @@ def setup_captcha_routes(app):
|
|
|
183
192
|
return f'''
|
|
184
193
|
<div>
|
|
185
194
|
<!-- Info section explaining the process -->
|
|
186
|
-
<div
|
|
187
|
-
<h3
|
|
195
|
+
<div class="info-box">
|
|
196
|
+
<h3>ℹ️ How This Works:</h3>
|
|
188
197
|
<p style="margin-bottom: 8px;">
|
|
189
198
|
1. Click the link below to open {provider_name}
|
|
190
199
|
</p>
|
|
@@ -197,8 +206,8 @@ def setup_captcha_routes(app):
|
|
|
197
206
|
</div>
|
|
198
207
|
|
|
199
208
|
<!-- One-time setup section - visually separated -->
|
|
200
|
-
<div id="setup-instructions"
|
|
201
|
-
<h3
|
|
209
|
+
<div id="setup-instructions" class="setup-box">
|
|
210
|
+
<h3>📦 First Time Setup:</h3>
|
|
202
211
|
<p style="margin-bottom: 8px;">
|
|
203
212
|
<a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. Install Tampermonkey</a>
|
|
204
213
|
</p>
|
|
@@ -206,7 +215,7 @@ def setup_captcha_routes(app):
|
|
|
206
215
|
<a href="{userscript_url}" target="_blank">2. Install the {provider_name} userscript</a>
|
|
207
216
|
</p>
|
|
208
217
|
<p style="margin-top: 0;">
|
|
209
|
-
<button id="hide-setup-btn" type="button"
|
|
218
|
+
<button id="hide-setup-btn" type="button" class="btn-subtle">
|
|
210
219
|
✅ Don't show this again
|
|
211
220
|
</button>
|
|
212
221
|
</p>
|
|
@@ -214,7 +223,7 @@ def setup_captcha_routes(app):
|
|
|
214
223
|
|
|
215
224
|
<!-- Hidden "show instructions" button -->
|
|
216
225
|
<div id="show-instructions-link" style="display: none; margin-bottom: 16px;">
|
|
217
|
-
<button id="show-setup-btn" type="button"
|
|
226
|
+
<button id="show-setup-btn" type="button" class="btn-subtle">
|
|
218
227
|
ℹ️ Show setup instructions
|
|
219
228
|
</button>
|
|
220
229
|
</div>
|
|
@@ -225,11 +234,11 @@ def setup_captcha_routes(app):
|
|
|
225
234
|
</p>
|
|
226
235
|
|
|
227
236
|
<!-- Manual submission - collapsible -->
|
|
228
|
-
<div
|
|
237
|
+
<div class="section-divider">
|
|
229
238
|
<details id="manualSubmitDetails">
|
|
230
|
-
<summary id="manualSubmitSummary" style="cursor: pointer;
|
|
239
|
+
<summary id="manualSubmitSummary" style="cursor: pointer;">Show Manual Submission</summary>
|
|
231
240
|
<div style="margin-top: 16px;">
|
|
232
|
-
<p style="
|
|
241
|
+
<p style="font-size: 0.9em;">
|
|
233
242
|
If the userscript doesn't work, you can manually paste the links below:
|
|
234
243
|
</p>
|
|
235
244
|
<form id="bypass-form" action="/captcha/bypass-submit" method="post" enctype="multipart/form-data">
|
|
@@ -291,6 +300,42 @@ def setup_captcha_routes(app):
|
|
|
291
300
|
</script>
|
|
292
301
|
'''
|
|
293
302
|
|
|
303
|
+
@app.get("/captcha/hide")
|
|
304
|
+
def serve_hide_captcha():
|
|
305
|
+
payload = decode_payload()
|
|
306
|
+
|
|
307
|
+
if "error" in payload:
|
|
308
|
+
return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
309
|
+
<p>{payload["error"]}</p>
|
|
310
|
+
<p>
|
|
311
|
+
{render_button("Back", "secondary", {"onclick": "location.href='/'"})}
|
|
312
|
+
</p>''')
|
|
313
|
+
|
|
314
|
+
package_id = payload.get("package_id")
|
|
315
|
+
title = payload.get("title")
|
|
316
|
+
password = payload.get("password")
|
|
317
|
+
urls = payload.get("links")
|
|
318
|
+
url = urls[0][0] if isinstance(urls[0], (list, tuple)) else urls[0]
|
|
319
|
+
|
|
320
|
+
check_package_exists(package_id)
|
|
321
|
+
|
|
322
|
+
return render_centered_html(f"""
|
|
323
|
+
<!DOCTYPE html>
|
|
324
|
+
<html>
|
|
325
|
+
<body>
|
|
326
|
+
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
327
|
+
<p><b>Package:</b> {title}</p>
|
|
328
|
+
{render_userscript_section(url, package_id, title, password, "hide")}
|
|
329
|
+
<p>
|
|
330
|
+
{render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
|
|
331
|
+
</p>
|
|
332
|
+
<p>
|
|
333
|
+
{render_button("Back", "secondary", {"onclick": "location.href='/'"})}
|
|
334
|
+
</p>
|
|
335
|
+
|
|
336
|
+
</body>
|
|
337
|
+
</html>""")
|
|
338
|
+
|
|
294
339
|
@app.get("/captcha/junkies")
|
|
295
340
|
def serve_junkies_captcha():
|
|
296
341
|
payload = decode_payload()
|
|
@@ -407,6 +452,12 @@ def setup_captcha_routes(app):
|
|
|
407
452
|
response.content_type = 'application/javascript'
|
|
408
453
|
return content
|
|
409
454
|
|
|
455
|
+
@app.get('/captcha/hide.user.js')
|
|
456
|
+
def serve_hide_user_js():
|
|
457
|
+
content = obfuscated.hide_user_js()
|
|
458
|
+
response.content_type = 'application/javascript'
|
|
459
|
+
return content
|
|
460
|
+
|
|
410
461
|
@app.get('/captcha/junkies.user.js')
|
|
411
462
|
def serve_junkies_user_js():
|
|
412
463
|
sj = shared_state.values["config"]("Hostnames").get("sj")
|
|
@@ -445,13 +496,13 @@ def setup_captcha_routes(app):
|
|
|
445
496
|
)
|
|
446
497
|
|
|
447
498
|
return f'''
|
|
448
|
-
<div
|
|
499
|
+
<div class="section-divider" style="max-width: 370px; margin-left: auto; margin-right: auto;">
|
|
449
500
|
<details id="bypassDetails">
|
|
450
501
|
<summary id="bypassSummary">Show CAPTCHA Bypass</summary><br>
|
|
451
502
|
|
|
452
503
|
<!-- Info section explaining the process -->
|
|
453
|
-
<div
|
|
454
|
-
<h3
|
|
504
|
+
<div class="info-box">
|
|
505
|
+
<h3>ℹ️ How This Works:</h3>
|
|
455
506
|
<p style="margin-bottom: 8px;">
|
|
456
507
|
1. Click the button below to open FileCrypt directly
|
|
457
508
|
</p>
|
|
@@ -464,8 +515,8 @@ def setup_captcha_routes(app):
|
|
|
464
515
|
</div>
|
|
465
516
|
|
|
466
517
|
<!-- One-time setup section - visually separated -->
|
|
467
|
-
<div id="setup-instructions"
|
|
468
|
-
<h3
|
|
518
|
+
<div id="setup-instructions" class="setup-box">
|
|
519
|
+
<h3>📦 First Time Setup:</h3>
|
|
469
520
|
<p style="margin-bottom: 8px;">
|
|
470
521
|
<a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. Install Tampermonkey</a>
|
|
471
522
|
</p>
|
|
@@ -473,7 +524,7 @@ def setup_captcha_routes(app):
|
|
|
473
524
|
<a href="/captcha/filecrypt.user.js" target="_blank">2. Install the FileCrypt userscript</a>
|
|
474
525
|
</p>
|
|
475
526
|
<p style="margin-top: 0;">
|
|
476
|
-
<button id="hide-setup-btn" type="button"
|
|
527
|
+
<button id="hide-setup-btn" type="button" class="btn-subtle">
|
|
477
528
|
✅ Don't show this again
|
|
478
529
|
</button>
|
|
479
530
|
</p>
|
|
@@ -481,7 +532,7 @@ def setup_captcha_routes(app):
|
|
|
481
532
|
|
|
482
533
|
<!-- Hidden "show instructions" button -->
|
|
483
534
|
<div id="show-instructions-link" style="display: none; margin-bottom: 16px;">
|
|
484
|
-
<button id="show-setup-btn" type="button"
|
|
535
|
+
<button id="show-setup-btn" type="button" class="btn-subtle">
|
|
485
536
|
ℹ️ Show setup instructions
|
|
486
537
|
</button>
|
|
487
538
|
</div>
|
|
@@ -492,8 +543,8 @@ def setup_captcha_routes(app):
|
|
|
492
543
|
</p>
|
|
493
544
|
|
|
494
545
|
<!-- Manual submission section -->
|
|
495
|
-
<div
|
|
496
|
-
<p style="
|
|
546
|
+
<div class="section-divider">
|
|
547
|
+
<p style="font-size: 0.9em; margin-bottom: 16px;">
|
|
497
548
|
If the userscript doesn't work, you can manually paste the links or upload a DLC file:
|
|
498
549
|
</p>
|
|
499
550
|
<form id="bypass-form" action="/captcha/bypass-submit" method="post" enctype="multipart/form-data">
|
|
@@ -202,7 +202,8 @@ def process_links(shared_state, source_result, title, password, package_id, imdb
|
|
|
202
202
|
if result["success"]:
|
|
203
203
|
send_discord_message(shared_state, title=title, case="unprotected", imdb_id=imdb_id, source=source_url)
|
|
204
204
|
return {"success": True, "title": title}
|
|
205
|
-
info(f"Auto-decrypt failed for {title},
|
|
205
|
+
info(f"Auto-decrypt failed for {title}, falling back to manual CAPTCHA...")
|
|
206
|
+
classified['protected'].extend(classified['auto'])
|
|
206
207
|
|
|
207
208
|
# PRIORITY 3: Protected (filecrypt, tolink, keeplinks, junkies)
|
|
208
209
|
if classified['protected']:
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# Project by https://github.com/rix1337
|
|
4
4
|
|
|
5
5
|
import re
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
6
7
|
from typing import List, Dict, Any
|
|
7
8
|
|
|
8
9
|
import requests
|
|
@@ -29,18 +30,31 @@ def unhide_links(shared_state, url):
|
|
|
29
30
|
response = requests.get(container_url, headers=headers)
|
|
30
31
|
data = response.json()
|
|
31
32
|
|
|
32
|
-
for link in data.get("links", [])
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
link_ids = [link.get("id") for link in data.get("links", []) if link.get("id")]
|
|
34
|
+
|
|
35
|
+
if not link_ids:
|
|
36
|
+
debug(f"No link IDs found in container {container_id}")
|
|
37
|
+
return []
|
|
36
38
|
|
|
39
|
+
def fetch_link(link_id):
|
|
37
40
|
debug(f"Fetching hide.cx link with ID: {link_id}")
|
|
38
41
|
link_url = f"https://api.hide.cx/containers/{container_id}/links/{link_id}"
|
|
39
42
|
link_data = requests.get(link_url, headers=headers).json()
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
return link_data.get("url")
|
|
44
|
+
|
|
45
|
+
# Process links in batches of 10
|
|
46
|
+
batch_size = 10
|
|
47
|
+
for i in range(0, len(link_ids), batch_size):
|
|
48
|
+
batch = link_ids[i:i + batch_size]
|
|
49
|
+
with ThreadPoolExecutor(max_workers=batch_size) as executor:
|
|
50
|
+
futures = [executor.submit(fetch_link, link_id) for link_id in batch]
|
|
51
|
+
for future in as_completed(futures):
|
|
52
|
+
try:
|
|
53
|
+
final_url = future.result()
|
|
54
|
+
if final_url and final_url not in links:
|
|
55
|
+
links.append(final_url)
|
|
56
|
+
except Exception as e:
|
|
57
|
+
info(f"Error fetching link: {e}")
|
|
44
58
|
|
|
45
59
|
success = bool(links)
|
|
46
60
|
if success:
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Quasarr
|
|
3
|
+
# Project by https://github.com/rix1337
|
|
4
|
+
|
|
5
|
+
logo = 'data:image/webp;base64,UklGRiYtAABXRUJQVlA4WAoAAAAQAAAAfwAAfwAAQUxQSDUTAAAB8Ibt/zol27Z9/zPADIgjCnrIoRhg7PvuTrhjtyJgt7jbsUuYO2kXtrvdgdjdYrHbRRkItqI7Y1KCCszA5PfF/H/f/w/Q9xExAfCjdvFUwU/da/GhqAY/M9tpL80PAmU/MbtZn1A9+WcG/rsvbeoIP3O5d3sPIAoqlUol/HBs7O0d6tevZW9vzYVeu2XA4mXLlva1/mEoq3o3GxQcPCU6OnrHjpXR0ZODg4N8m3nZK/g4thi7Zv/DgtLSwgO9fggqN7+B0+cdP5mgVqs1Gg2iRqNRq9UZF08emB3u36G6nQRl80Gzj6fmoejHKbKKJjh5D5294frtz4XIt/DNzZOrQwP+sGapOodsv12A7DeTKlgl7zEL9qd9NGCZmg2vknYPEkQcfMIPPDEgu+TBypZQgWVufebtv5+N5TInzBoAqnaZeUptRqb5Q8rmsY2h4io8xqy+k2tEru8LJb08PFAApe+M06+Rbco6P7+/uxVUWJs/JsSma5CzYddFCRlHo1rbKFtNOZiBbPPLg9P9naDiyrxDdt8zIP+CfFLx1dn+jtbtww48MyBT/3hfWPvKUIHrDt780IDl1JQRM7QmNBwVm65DpvH14fD29kBWKMqXssviG99R8hM1p6yjk1vIHHqvvalDYmH8Eh8lUKv2nB7ZRV6O3AIPZ6F0Y+JDLoak5f52Vu3mxuWjxOwjQQ0IVsMvZKljuwvlxc5vebIBuRp5ZBwJaSzUHhmbYULJxpQVreUM161axILljtwqd+zZkFJzxNFPyNQ+KSVxLL46q71d5Z7R17XINTN2oErMLQYR9SudeMlHH7897xdWk7+v6ZGp2z8p1lQGpuSVQ2oITaaeyUfe+XF/1xJxXvwKzSkhSl7Oa0vwwZ+MjtFpSMyOcJnxjt+ncyGNZbX6r08zI3/z3QhPC2i65PDBKQ2Bt9PCbOOFviI2fTZ/QKr50pIjJg4ay/x767uprNvNuZqPUhMO5xEQny9uLQAAuLi7q4C/79LtY1QWioGH85BuLjEhPSvryvlji6Ojo6Pnj/CG2iNj35pQ8vkZn0n4anNnGTBr+fvW4AM16ysBAKqNOaLFMjS+Stw7e2rfNi2r29vb21cCm/bzb+qQo+6tkYbvtvkIYv+be+ViVE0+4vZB8SXI//utHaEBv1aXAdt1zL73WD5ztncVRDqeRzzuXQbKgOMG5K1/e3TOYE87oDr4rLujR+Lbo6cy+WHuDl/BwnPHty/bmvCzHXK8BMWzCiXoH+6e3L6KAFSZZ+jJHCQW3Aht3zni3DODlKdPTCKYt7qZhbzvqqV+Mm6yASd0KP51xQHay8NBzRRAd+i3Ps2MxAexA2oCOPScfjyTljNvqVYM36xoDpa1awJ3wW9nPjINtxIphRej2iqALniFxX1DYs6pGc1lYFmp88yT2ZSic3tYmDHTzaIsm63ORq7mJ5sHOYFEx4GbnyHRcH9Vr/8B+389Vz4xsBCNSEwOcSybWjOeI9fSG5HeMqDLmk2LL0RiYdzk34Du/velQgLZdClAWRb2IdeQa97RMTVAYvUh214iVb1tSGWQWmPIzndcsOigTxkIPU6Yubze3ksJdHnLmfFFSDTfWTrkj3pWUkDeZVGymQe+X+rKr8nKPOSZtLSVDOg1/9z23IxUY/ablH1bJvrUltEA3KZfNdFMIpgUqORVZcoDFNeSnsxqAHSrVjPii5CjTn164Yhm9jSoFfiviWL8KGY40tVCcPtdKcXnpFks7yrlxUJPoNccuuM18i68vTuyqUCCaoHxJkLyVTHMml0TAFqv3TtUTqu7KBPFk4+Usp4v8gT673OulWAZGp9uHlSPBFUDk0ys9CsM/PdPABj5RLNURZIF3EH2R2R+WuIBZEWvtWlYxt8uzWsmo0C9iXdZWMzKWdMAoMeRm1OVpMbriwjs4q0dgewydv9XLPunmwepKFA38jmLeme0NSh8+tQCqtWIBJRuPN9PTvKKSjRieSw6N64uBbxWZXLQbfQCye6xGg5JISogCj7LXyLPFyc/S0JTYmQ9itBpt0YaJgRZSZGNSELpWcsaA1HWdXsOcn207oE0xOSo+gSwGXWNg2Z9Qyl113+1MOlJR3yBKPPdnoucNcj13nRXAtSekyENL/eXIPS9ipb3Nn0nvIiqSukak4dl/zWFgPdCFQTwPWaW9n6JM0216IvIh4tGVuG+VkD8bcVHpGv4vEmkfJxlR6k08QWhWCOCx/xobQ7pRci3xioIzjMeIF23M5sLGlkl9zf5AbnFPh0j70S8WHqoLcUqJBkla9c0Abb1sCsoNdXEh/3ycFBTGU05OY1hSk0QK13ZkOI4N1/awzFyQtuYUkllq7sQ2VoBKp+h/jYsaLnPIEa94kPxOmyWtrMZsB1mZ2B5Ltg/2hHsWs88/fjwQBlLteCjtBdTbQjDElDyf2EqltAvzsjKLg+fkidUbzkh9pUBi/5pzIKe8dKK1rixrIMzpJ3sAWyXRXnIflUe0BQfduCVCRHxch+BVW+TVhIe9WbV2aSTVLLlV0L3Y8jWXSsXmPJEj6J50x1Z8sA30u6PZv2xHyVnT1eyKoe+ZqlPRz8qLgdGEzLNh9uwoOsZaW+n2DD6J0m73gfYjTcju/jR5o9INWkf3tm149zDzFIJ5JfjbVhNdhRJ0m6oIyYPeiLtdEdC3wQCYjpSP8UtHdHfvX6HQdM23zfx0m2uw1JMK5CE238RUy3WSNKtdGYpw1+T3lESFnV1koGl3a+Tjmk44WlflnVIurRrfcQcl2jFvhQzsiPtWI6LtCQz4W5YXSDa9z/wlVPKIBb4XJF2f6CY1x4U1e/cqRNLHSqwWhxEvndCawPZut+BIj65Cyqz2h2n5OZapI6TiXSKFzOcjjcyAoDd4SKfj9H1QKJ1wEWWMeEJQbtExaq7ppSw56gREbMXVJZAvdCF0IXTZT+QXGNWAUO/dtU3liGmEcthOeXudUTEkqUqbrG/s4RhaVx0q1ykCQOuMjA3F4mXOvERZ3X7V1qMG8s6LIdh1ukIjyfYSINmuw0MejxlcQG3YenlQn92xY5CVmoAcHRYXlpG8r8/V6zPfzsH/8e60IWHKjrnx1ZydMrmb6zEQTwclml+bKh9r0V2agAPp+WlZWQ/K6uC0Z/PrMyh9SEsI4flpeXoSCuWMDKNi269hzTZsLt8druXh37XpSUMYkGni1zwzlCZJMW0Ai7aJdVYtVextHopneKlpQYQOnAq2tZckizghIGQ+pBRtFjFanMUxf9bmV52zyZas/7Ya+aCr5Z6SwHbkGtmhn7HVoNYWqCM5XOFUXTxFTfT2yyxkhXVWFUWafng039aySVA9QlXzWKozkLxxH7AtApMZRAzp1cSaX+G8Tx0l5huSxOWYvIzhva+gYRvY4f/qqSBU/AVvRhx+28su+kFUkqe7usMovU3asVyYs6J4bWuLOh+ifF6RSYNtQlbJwe4kcAp8KhWQtaC6izPvSZawY3VUZ2sxFRLGNTHE6xZLhtLxbAQJZte317VigSKgUe0tBuDgd35JFK/3F028hdbYNpN+0/at/lOLKvAZwy+6jVtSKAYcFhD0e5xJ4zPIOTdXvpnHRlQ+6dIMx9rxoIWB82S9BR8t7abFQVsBhwqJjyZqGTV+qeAkXlufh83qOTVq5sTy+ekNHw4juAQnikpj4Sf9/WxpoB1v32fWDnbfGSMZrvR0vj8QLiPs1Dbf9rB2/8OZdXdwuH97Gos6HDCIKE0nYaF+/taU8Dab1MBA3O3+woiNsEPENH06ui0LlUElwHLrn7S44u/WDWX5knDY34E+2lPJWRckIBFB/qpKCDrs+s9A3N3+MosmsWUYMGTIxEd7OVNxqy8louIeKw1C/7K4JAWasuC5tsNlNI3O8ISSs0kLDo5woECVu3W5TMwL2aIHQB0jCtN3ziuhb2dx9hNd7+hpW6DG6HbOcKzK2K6/W0IyrF3zWIlxcXpcaHDTz0sLCZh8cWhDhSAXuveMbD4xFA7AIfxSyOaymxbTdqRWIziedOUhEYbNaybsWKYFmzHgtrhT8UszQkn9ChZe3GgDUlovUbNQM2poXYA1ipba8+gfc/NyL7WH4g2oa9YxZkMw8E2BGi68TsBv6cjR82R8SoKQOvVmQwsPjPcHsCmadCWRCMSdTubUqBLPIuaMceJIPTdX0jA5zxQdzzIkQStVr1loPbsSHuPv2LTSpD8YU5lUt2lGg54upfAAqvB5w2EAlZ2go6Fpn+DnUjQcsVbBupPBe5K06PExIFAlg+/z+PrGncCqMacLWURMzbkE9B8dUJ1ErSYdZ+BhTe1KFW3rRENmm3Xc8BHUx0IYD8q7ps01CPZdH1iDRK4Tb/H4Pk62EaCYtJrHuYzf9oQwL73FrU0qebrk/5HAtdpKVKM2axjbUFqu4NmDli8y18ggKzVglslZYN4Y3JNEtSPSjbTbi1Si32c7iSpcmQGQc/C/FUtKAD1xu7NKCPzzZm/kaBeRBLt3v4PYpf9QHqHg3rWYwK+/acxCRSdIs5/KBM0P57fhAR1w++Q2FmLa3GwC0tnZK5LMrLw4eyWJACHbnPj3pjKAPHJgt9J4BKewOOMv8AB2u0sEcvdnobU19GtaQBO7afuufvKSDK/O3jTzMKn0e4kcAm9YJL0clo14Gk17r4YvjSTMHN1GwkAjh1D96SaCbnxi3wm39Cx8NmyjiSo8XecQULp/ubAt/HaIjETSny/rrsVycojMDZNh2xj0tY+NcA58KSOheqNnQQKqEaeNdDujFNwkgVcMotIz9o3sgpL5jp+60Mjss3PD45vIsibTYh9ZCbg+y1dBArYjzijp+SvdgfeThNTOGHJubC6Yg79Vt4pQmJR/EwfpeA2fEuKFulZW7oIFKg0/GQBS3+8l8ANmmz+ygnNSVMVAGDdIuzsd6S+2BZQHZwGL0/WouT3230ECth2j81nXA+2Bf6yHof1vNIjlAD1xu1/htTPl6K8ZYpOURdyUFyrfsXCT9t9ZRSQ++/8IpI5zwXK0i7oppnLtwtRv4Jd18V3dEg03F3Sw1HmNf7AfyhenLJ97qIXLMzb4SejgNwv5jMiFsS2A+7WDd0EqDkjjYP5acwgJ8Fzyol3aFn0xuLbgfFuUG3g5qdGFNU/jw3yquS56DELv8T4yyggdF2uRv2e7nJussExm7sJ8MtKtaRvFyNbyKr23/BYh6JGLaL50foeSpl31IUCFNUl7R7XxhoA3Bc+Y+GXnd3kFIDO29+cGmYD3B2WFRf8Ux2g9ZpMCU829q8qaxp5oRCpX86EesqcBm1+YkLRFwf/amMDYPNrj5BtZ16xsCC2u5wk6zS+nx3wt4tIujejCgC0Wp1J+Xom1EOw9dv6Askv1vVzkDeLvPANLc0fDkU0VwBU7Th560W1DskFu4ZWopR5/cGDG4Jlyy0FrLdreleBRhOO5SLVcHWuF1QbvOUJin6PX9TVAYR6fRafeFCKkjVnR9qXH6KsW2y+iPbK7BaCovvK+0akfjoy2hncJvyrQUvTvRVDaoCs8Yj1Vz4Ykac+blTl8qV0rgIg99/5BRGzDg1zhlqj92Yj1Zy83L+STbtlKSa0/Hw4qKEM/j905fUvyNtwbrSqPLlN2TitAYDM758MfL7O1wa8FtwwILXk2oSGUHX47v/QUpuwxNcWXAYsv6ZBiS8paDg/RlWOxt03PQi3BQDvZQfCPUBotuQFknOOjXGC38Pi9GiZeSCwAdj5LLn4GSU/MlPQeGFslfITosavCysDALj8XhUEn60vkfxqWy8luEc/NSMi6hKWtFXK/og88hklF6dGX9FR0HihW/nx3/0xLkCwsGy4KRfJiYtbyYROq56hZf6x8a7g1HPzYz1KLtGmLEspIeH1XuVH3m1yz8rA/m13KUV3J8wNhM6bP6Pli/X9FELj0BPfkG8ikr+enepcfgAEoCqGxT5kfT8zujZAly1ZiIiGa5FeYOO/PAl5v6WU3l3bpwpUWOWg/Vox9c7e9gA1F2cjIn4+OtoZHEccysJyqN4/zl2ACmvd70ARir5a3VoOAG47jIj4ZI1/JagffFmL4o8e8Cu9Hd1JARVX6BhbjKIPF7QES9u/bmHpzdneAI1m3TUj88ELXoUP1o92gfJev8sQ/zqMFhs/o6X5/syGIO4ScWjPmHoArVY+xDLXpmwd5y6H8l53/qX0+JkNRTwXvUBLXXywG7Cd3JsoAFqvUWMZmwuurx/5ixzK/6jbiPhwqgIAXCKfo6XmzPhqILXNGjWWbd6rIwv61ZFDBbRfkI+IpRtqASjHJaCl5tCAKiDVY907LENTydO4dZNaqaBiKsPViFi40hmg40GDxafN/W1A8p8PkHvRh1tHV4/uU08GFXZAHCI+mGIDMCIFEfHjxg5ykN56Y/K7d98lad69u3FqzbSe7atbQUV2nHQ09dB0NwAIfIuIHza0F4Cj0HxwSEh0TEzMhRupqampl+JiYmJilk4M6d3cVQkV3r7D4DbVAAB6Xzfiu/XtgL+Dq2ujtv0GDx482K+Nq6uraw05/GBrhxw8Mr+tUAY/QTsPz//DzxEAVlA4IMoZAACQVgCdASqAAIAAPikQh0KhoQoFgx4MAUJaQDGeyt8B0fta5sLpugtHa9H/9y3hnPQeeBv2lAZfxn8Kf0g+JHcT86/E79tvYf8T+Z/pX4s/1//m/5D4NP47yBdI+JX63fTv7V+wf9t/8n+q+Uf8N+Lv63etPyI/c/xd/ID7Avwj+J/078ev7t/0f9r7au1fzL+4f6b8pPgC9RPnH9s/un7N/3D9svZM/sPRv6sf5T8kPoA/jX8u/vX9z/az+//+j5q/yH/A/qvkw/IP7x/sP8r+Tv2A/x/+hf6L+7/uP/kv//9pP7h/lv7n+2n9s///uv/Jv7D/mf8X/nv+b/f//1/1/0C/if8p/wH9o/y//C/vX/7/5P29es39gvYX/TL7z/3///7gGF9i2ZiDpy39DmgKs8XC3poiPkdDiTNsznrvzYOFsjgLL9wn90iHDnyG/rEzwzF0HJ2Zwrm6m7acs0E9WCUoGnQSmvkNOZWYRdL+nis/7vbPrh5grtMYXn2444AwtbpXC/WOs7NTyS3qWYnvD3bfoM7xCh723sInv7YQpn//rdMZyUzobjs6lBekLJnhgZxIR4XX0/bIbTY0X7qFgQkye610VAoFg/9i6rtbzzfvLrhsgrw7FcFL8ABGMOdF6QD8bBHq1lndWvRf54Bl+vsupAxE1bSVL6Ga1ZxJ7rBh+0PQ5K2QLOAFQzaJxcNsAZzENjyrPvC4VYhV3L8/kr1TQMFqNSGPMbplKv6U5oVBeH+JTYBv8VBKVJEmRpHxVvUuD9zaEpgmn+D2EsqqmdTOf1+LlzLAsIlV6v/Kxkobz+BSpfYO2cX8XatcnKouw3Q2Qby8oyJR7g5aKwoFiqVumetYLGRUX/0MkQfwvKm+18FnyBLwXwz9e4ut93B5+K1hUZhPjJpEy0GK92KNXxMcPe86smWvR03sAAD+/4+8JH9YAAKc1Ijj6kfJ9nHWFKzRmHH5YwuvIlp+5GTIwwtWIhgwtNVOLtU7X5f7A75iuFl6PjGQhu4yTlit/PSUurVc31Wv6gAAhk6Tb0uRCBfGB3jDij+X9soH8jTm0J7v+qIrBff6OXcdrnrL+Y6fp3gZ5T04bbY+/r2qravbU/8+ItvKQFQIjEsGe4ipj4rMczLogp3NbWQz1fc1zzDXJ5RyusOl7v8fcPFcRMV3Q7b+oXSiFdJhQN+kPTjGbanta1kPt7dGUZxyhKWXvgA/U/Q7xcRRSx20S9n6LMTyyzeTkiMDs2UjTY51+N2y9TxNuhN6DL6g2YpPWcwOnvwoukgZ7yl/X+sOJPEcUuNmfe6ynwUhmLZBT0M842N1SgTGo7Mk9NZhAk++hzMs1Dg36JZn5TeAwDrhIXTeQXgf/ht8AAJTcKsK8z4DfqQGwtaPgEVcDYLj5EdD0NTSh5DzhL3ojlRTyw6Ak9lZuszuxWv9gqDnWdK3CKFPxIBsDk4AaNtkjYqHooJJInrTjQ/XWH3iJZ+FKF4si7xzoH0r7EtsW9qhutx6olbkylGutRGSOowpQcJMGLL4eXkYDD+8OFBy7Y38bmcGWqOG1aE4KCrTFxg+5f/yhcGj9C7pMuVv04vRWPGsYH7PuUg9Q9bcMOrbBg14Xpj2z/o57v0h1lcaIL5Un7+/9IxKU+/rPfv4uvZzBhXs3hoFOWUq6rBSB9WB5I80AvPfHSrd9E9ESFQicQ60q/fnEQTX6fTMrHpjOkGxiXRhG5ZFGTQqW/v/w18PW1DiZFuTuMZE3kzOyOQsk9tWLqp7kvCWUgO7QIsvGaRBDcaP4yeE/+PCRMW+s9cfKdxWb6yeL9Tg8Pm8zXeBBJSjReCDBfa2yU3m9Ix66jQRrCYEOXvBVCPQoSLv9G2RYNRkf7nTFbRyDbQYXkTchQpBcg8Bc8hjvy8hxk33oD6W2zrDB/F8+JbHTtZjYH0t6yHoZia5vufdcy3w/6jO2+d9Fvsw2Lu55S2Jj5W5faQjtnu4pjd09Ws2/5IVQIGQb+vl+rt7ZToZ2vs/djTNNh7MYtRtC9EYCZ60y01fBvsoKPI8nhFXdQ/aiXU/Wn4LcZf4rtqoHN8wPTqNhJHktLJ5SKB6FrR2GtGZlSusjWWW8q82wmsWIqSEy8AQQ+Bgz+7/R4Up5HJv/2lHG61jYQokz6L0P2bVbv5HzHjdIv/J4OUrYtnXhs6eDp7tjilXTYrIu+dJUdZbyYcsQnbDQ0Zh9MSywcne/4xodr1nGRCMGsx+Ak2Ego8XG1TGjKkwFjEXNownSwunI0HlBhs3aHa4JGQ7LPA5r4fnaBUwz/iOzuNZcxIX+3TauyFMjLo3ugsAkbgeXtgr2TmD9F8zQesyKAPkBi9MsuNbXBnVG0ELPRSVp61x5ADtS8x4dDKuuWEOcp9XQYYg1318a2rkMK8ANEnUSMKjc7LSyh1qSENevfr8M2liCtSg3VPEnzSMBQVZ9RKBxsoS7fJ0Hmz9rLUMw3+c8aYdiEbMCaSRvQhIF+i+6D75CRQI92XK9w1bH7PyNn/9pEIx6HpJ4odetjRRUWJ52GFU1bZQuapXoDUfvAmSF1VA/SxHnZEBrY79YupFLI+eLBCfqgEjSFz1OpSkKgKrcLF/Tm00YyqsEtJzAHKKwEJO+Sk+AEqQ0UqSJGzyY1+PgNwZ6HwvCZAr3qT9qdUs6UHB5lHJIeVVcWUdElkhtb5C7PL2iU7MSJZomgcTt8WoXXaudwTt7R3FWem4bsZAq1f5uFGgXJrCNhzivOZX5Ze/JVpA+SJWHTbv/gPzsCI0OrPEf+UxEpcySPn/ZGQoSGL8AaYztEKJRRA9cV/In2pLWgCr1TWz0VCAHP/3ys+qalPl23pdAqIgJRWiroT6JF7Kt6kz150tkqaF1V5bfGch9FTQklEqADKwo6lrq3GJQKAxcfCdamkFNeMKdDu/IVh1kPinCrjeS/CYcxXm8WuKy1FW6eR49YIRC8iX3DgqBg+dfQjVus9tznMCaSKzmSh2JuEMNPi0esAKsgAdIgTXtW1Uff+B0A9DUfGpX8fRpgANBQIFW+fy34GcjWAF70veU9YCUrQfIWRhfUowQ2XPbPTThoau+L5y4oxkzZoMWQx8jtiHSxf1A7dGTwVEKmZqFWKiep2VohJHgUbND1CPRyzv9Omu3I/CheMRB46l2cPcTXAa7SrAvHpGshPMhYwVT8z6+fP1hElQzgqhV3jk7UlV7UHfpCEF1SaURPcVMeI7GJkG7vsAJAl3b3W6CETrHCC2EVtNEeXFjrOQo01EGr3n/9YHVntCWioUTnB91e+dXqSpuf08O8MQEktX7WcnAAfUEn290t+6xw+vnPkv6/rHjmjXI6pj9NQyxbgaz6kklwkYPcFll7BJI+fyFUiu0KUuYfPTGw+70JDLh9pC69wa0O3NtBcxCQmChPFqpGQCLjVaESL7A0dcH5Yh5dkGTLc59I6frcMMUA8z4EQlIxR+ooJZ/qVMOLFlVjxWAVE/4XvIktabdqs2nHVwhrPVseNjFaU+PF+upUET+R5d9ny6W/osUisXYV2k6/ii2TZOtppK8WFnIlGWFEAr/MWtJEOGWPhCW2wElXBMR4pch0okadHU0Wd/Ghuz/8TvtkHhpAhG4GCTW/IVA2Z3Yt+7VsJ91J4XKxzmrekrmGdH/xMtnafeUQrmYWdlhD71um5xE0n8lISfaBPsPEgmnivINyzWS3OjhMC2SRwUciPmcq2DQMq5coEpiYMcVkH2ueK4b1RAlAUgzgprU740NgLawZR/TMGi//ix+M6mTgziYNAwJ22VZsMy6dDYVZlqD7JbaRnVvJYXWhtOqDRROSJo1ymZXNNrbFaudEM/CAsQJ0prokLY4gu3ZuMg3S2EALFvt3hkWjpAm2BA4zsUjjegNaoThwtMB9JN9J8YRUM4Vl97cPTcNBWMu6uADFlabqsFUG4UcbygM1nB/z+h+aWMJ8SLpKKhoKANAnYv/dzaXkk+mMAbA7fpnxIKIkjeGCj7NVcrI9PvKOoEuV567+3mjatZ4wis19lgubGS7emHpyvmducWhN7vFkJVrZZbORuv0h9bASzAZqt53g0PDufeeGkY205mp11pHQXf9wkQVMhlJZVJu8LIwZExef0TeQf6B5nPnDL+7A5AtSnSvAhCWqzJSB6zClGAbTylZPU96UfGtxiFjVtztmBAzITB6Orc8D5jvhsHHjRN79ZJ4gaj3hjfJXl3nnMmSGAos818hnzBNgkCjTcVX64fDloggPo1PoDDOi03YgOCkbtu0LBPdG3Fvhq70di0cFREeqDI/NAXPzo+U1Xiip8xjvI8fqRH6qniZLX/1TyhoX02pro4cv1BhT1iYZBsFny0cTinQcUUU1MiZR0CprSqRW9I+ivsTkkekPHV8VNj4bFQY8b8I/OdQN8qqujcP2gZvp7EbfzCX64DGvVeq8jqDEsgbNLeVxOTeyqZxsPvQZp5b8jXqFpZwxdJzyN+E2L/vsigrF8zYvIZu8TQqt/oafVHqeY4kzNVMLvC93QC4pLQnh5khBMT9Jz9MfCRb/nhzlPq/TArBBtG349LfMO2zA8YW7uPr9c7miSF7JhRjfBUSON/kPtNQVVbT4UPSmAZDlfbGMr1owk+csLKhFk3k9vrCePo2CRCrB7GMog9L3vHZ1rUvOsK5SvtlMhNJZAGEXXCkYdsOuAR77qiBAk7FEjn1iExdlcGNak/dV4FKXGkemLQDeA/wLfJLqy/HLbCzbrLAACaOzTWL92iV7mBcojBtAGqOwx2RAZw0ZVli6qy+jUEepf2DDap/7XTj1GLMB1xA3szx0H0mimVapgmjxOp0ntsQXhDqwpsBgJoTVUhQjO/ob+Nv06AIVmcKEsMtQWI9Cz4m3Q0WCG03m/MGqF45peWsI36Df1X/0zXo48wQUO+BIbCuRnoF8MMG62RDm/rsCFko2WQPmURAKxX3LWUEUEnYaDYOsN+5UfL9ZNu/oFFCuGtiU62QuwCZXV+ku3w0uMt4sdNg/RvGDsCKjYUAhxz2unfKYcMPV7tUygdkg1cMuV3eYqFLLvOO8QKDfuydvCL9PEGZuEGEVAL7xyETdhUhL339FLuueiSKai0KvHolS1C26Wd+2x5q/4fpbLAoDic8WhA9FeIlFSpfXHedinUh2Q44dWOYAJcC0KlN6Jd/zkf6fjcbxTOMHgx4HIqwUDHm71QW+giM57ygtmHEaTUXC71fqSc3DoJJSbjVErwldd26s5RcYD+dluzMCbdAKAXXh62TNgFWOTKCtBPQpQCFTicJEuvMUmUuu4ahM1wvOJy03yIqVrhZ1HYd9CUdwNb+cKIrNmZl68kdwWhVjvGEhzAVWZ3U7/h/716LBqzqjOo3EQeeZ5u+08Zc3rl8WIHn0JCo3ff8nIPO5iUgmWoAVvtHY9g4vI+os5TYevQf3SlbXItEwzBZTXbdoLUCdr/SPVLJhWoOtBvR9PIjxPACUQvKwH5ZhAztlhSn6PHYphT8iz5k6Xvr6oZjdjGdrmRYuJ413F2OQ/CE/HiUNia9hdg5og21Rt3NeKK4m7+JcACaG/HDhnglumQfkdVzubiasUaG68UrD66ZZ/+JQhSe7iuNQwjTJ5OcSYncFvKdXEFoUTfXJihoTlVVGCYA5NUfuac7XNoqNEnPWZ58amK6NpWeBiur35eJH+xaPbzrtUfsk15svZ4hadfQecaJwfs2EmrLJCeNW0ex8BSCLZcj9mjPuadysrSlufM3f9vbQLj/YDDhDlLH3hdZA8RnzOLZUcyyg0YF6qhfvJxVThXPVKJb0jz0Zgjh0/vYPw4U7Hg3s//YVDFfCEPyXJXtR6DZIyHWRwAR3Y9PX4SaGhq5aaT4fA6e1/SJEJPp5od/xFLlTUJXAek9bX+QUT5+MaNBXQ8sc6yGxZTjUBzphgieyXUql1slHz6zIeWDP/HFNJtDCLRwmGcZb4TLQkCDPNzu5kjoUmTOhKpHrIHG1woEds4byLj5Kkd6BcfptnRvORweag5AKB5sbdsHOnAorPX1huo11B9NgluZ3UbzsCSIbpSZVpV4vxAQn+SBbrRqyytt46ExnLWPiqaqKHMGOnIz0UWr1ktabsXZXaCEyAztEESIbF+CuUv0zfjLTuq8vDqQbLg9JRnATtpNKFIvzNLUE8ULhR7zjrs/nfBo7wJuqZPzDy/5JXWIuhDxoGJkhKtGchWkLCc5zxN5/UwZ/+sDFBziqID2XcgG+tCNLgPgixZKeL61AMFHueX04bIA6Dc4lVHb7DJrwhquG0tkIxh8FJm0D5YsTt1CKBRf+iBnLP69DwssKpb2CazAJXC8W3eXjHlXeCd7SAFZx1hIiOKpE/1uA9oyMy50jIKH9gTq3rNaQRZSg+RVs+XzpaZQ4yvNjoX6Ga3aMSnsEKH9ppGfw/fi/u8wZC/2R9i63H7rc8EawU5b7qk1rf+LOLHHXKWe37lAScPT1NBKglo472fekM6P+YyUsLmas1mAA0+RdEv/bstTYsiMuMnCFac64WRAzLfK+JpbS/0nK5T/znTi/9VrtBOlTe+vWNaqPBu/aUyqhWzo4W3h/Z+9QHoG0EgzcZSWjhTO5h9BkgYvCKn87pwG/CEYFDGJpGailBrM3z7Q23xjkEhCL+fi6RPciXJNnCmrKDFrecJ0zm9hnYfSvesUHCrDYxcO8mRQ+Bq7U2DyvCse6IXrm7WCSfaQb1cWjtrWfnjosC7Ws3Ftz1xMrVQ7zqNiRYSJNvULsikLV4ELC9e1elurJQj/HhnD5ji2rnvmJ74Bj4IOkmSKIfcfJPEouw3kBS4BOm9dYlF9VzrqeGBYCaXtCUa5ZVA6Rwixy8SmzICg/KuF4HGkVtd1fcjdJ1JIDWB9u9UKQa8/gr8wuOMYE4OH3Mn/8plwdtyJ7XMQaTAJhQ7fKJQ1J7ibxdJqdS+jg28qWXALHsFt0vudMnnzA1S25PNS46+AtlZ9iMSZx7TvenEM71t2i4CBMDXSk5SjfFHJeFd9uVHf/U3Cw0Y8U7daHpXFtaopWcGLx7O/qasgvLnYD8vjDblSUMM6+VxVcXzt8zWGzQ+fa0ydBskhK7fd9qiDnVWtAiRECvmzUJlAfKdg+EkrXeBXO23vvqd79cR2q8p4Bzppvoigikywn/u1DgEh0t8j7PVsb7NbQ77OGAgFcowC3hKU7yiLyzG2ildZEQGPf40OaswAVbKDdRVd1p4HhTHhAr40X1Sb4AhIp7LzRPIMbxcHl/vn3ohsa6piVKtdpB/IQJJ5HMK4gPmcmH/Sd6+hZsid7622iStxusGH9ETAbQdmHIMFZIkRHebCy/IBuipgEsX0Qfz6jRCphMrETz/7gQ/+2woS4vZBGO+vjtdTvKMBAKWzvY2twA+NCerCWHz0Pk3XV5F8fTGa/BxGrVVNcw7wcBUnWmn/Hz7ePhnurskSvZbn0cYqUJOZ7y6tsPsCZsxfoa0iDO2E9GIe+/mmJA8YWO5GuQFcs8mOFHVl6TA2fZVl52pk/BB8flCulQBq57dro9v5j+tXPSei5YaulEhKOsqMfy7jr3UHJahXppM+tMfp4eeOdq8WBZMeQ0HVbc5wcdAcQJ3epWDx0FtQCQHQ9v8JVwDFPcOGi+JY8WN+SJMZbQ+X8cZfuYIPr64Py9leLPQxps4lbFGLTft4AU4/A2YGqJXnKBdo1OVsH/vLNAlrmR/ArnYqH2YCeHFw/NU31aHgh3B9bg9+d9XtZqWfEy/Gh00D90uTeP1XLNwOr8J9jfkubI/or78Juy2FJZ+DCBfAvaLpHS/5LP73IPfcWNMvpBqC/PIUf+AQm5bG9he219FAoORaOvASo8XpTW1NNvqDNFADGcxkOP0ivvXBvctidbqxynbNybvTiTy7WGSOaZVzcZ5OLMXFAZjBFMNlddOGh1PaQ/08df8yuRWzuIN4t/vz5ttbIq94ye5Sb3+BJuD4tG+DQfnp40JXHPLBASkKMwivpGoLq6XUAE+fpx4r5YC2+slFHqMarfrJnhQUAZ1d4JUxL/7vYLtzpJ12HtXobcSWS+aEYiJoD3kjI/agN7AA+AelZtFY58NlNWyV1qZWtXa73Q7nhFN/2z4L/mYrV9cODx6HX9c5gtGHNMqebmn9BtDYrpku6+izI3NDcJHP/5b8Hy/CkUbgs84ey/8U3oHTWP9Zk8EZKORKQ9DEtH1Kecz2IuTnQ8HS1Ei1CyhlyK0XOcsOaa+Bv6ZL065EllL1CL5sw/IdONLSgFaZmu4h73UUoJBUfuEwGjOp3YgeQzFKiAnyKzi1mx1LL0/uqvl/N1xXDAa7IpMddjURugYyDIvl7oJWD2+WCjadNRs0avZ8y5ymx508Ry+aGmBeFR3MZIwYXYAk0NDPuUGdXywZPGxei2uYGjAiNqDN7dgRsMiXgj6mH87CcIO7WnE5nSPY1HuBr1i/Jq8/9UYpbpHiy1feJ5RuzV8q0s9NE/u1krZ8tQnqPEbGF3VdXlpzQRkBGrh91PY0UUoEMr998iAKhIFeb+HQfJY8nWWV3NrfMFjJIua5R81+S11SHrxlUM80jEOEe1SBekTDHMMA+b7QdsEOlMIQox0G0GC+NTATiicnLbftAu0bzP/eYZ6ya84HPSXRqdChC6x9m+H9qIdSwjPGmc9IBQl+7XnlA4syZ/nvY159OpzIwGHUoi9Df4r3rirhdCOhAn9tFxWmBJrCMVdi2I5AKDR+cc4FmJk6dUz3O4wPW77ql+btlvPicc1ZCwXalLFn8luXjv+2WFnQGJrrl4MyIwjRhV7s6MiPNeePqFTK4X+Y/GwBKj0IZgAAAAAAA=='
|
|
6
|
+
al = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA9UlEQVR4nBXBv0rDQADA4d8ld8EQ2yJiGxAchOqgQSFEEEGfQV18DgcHwYcQ36GDg07+wUlwcBApCnUrbYcKIrRIa0qTy534fSI+vbMCi7GSUe7zr6QmOEJjEUhhDcZReHLEQXiLNoKn4S66CHBMjjTKJ0+nHPZPOJrtEPguc+17GuE5fjCD9H57rHYuCT/H3HxUmaYp5aDPRnZBd2kfp9d6I15fYe/qmdryJiVvge3GI1tRnW7rHbF2fG0rXy9E5QFJnoFSNF1Jc1jhp5YgkrMHm2kYtF9R+TdYS6aqzNdjPBek0RolYDHaoSgsWHClQE/GGA1/SzpdtJMWu3cAAAAASUVORK5CYII='
|
|
7
|
+
by = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAMAAADz0U65AAAATlBMVEX///8crf/29fQDo//J7f/u7u7w+v/2/P/8/PyytLWenp6IhoWTwNfPz8+mpaVYxP94eHhryf+75fyB0f+oxNPl5eW4yNGrr68xsfmUlJQWKuGqAAAAQklEQVQI1yWLSRKAIBADMzOAsgiC+/8/aiwvSR+6AUB15mJyZ42ev8ldclI4MWvXuvwQCaGblPxQCmNP9fgyqGf+AkFFAeZ3L10cAAAAAElFTkSuQmCC'
|
|
8
|
+
dd = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAABCElEQVR4nAXBP0sCYRzA8e89d6eQ4SRkdNKQOEVSvQQbegdB4dAgLY1tLS1NvYFoDIIIGtqKXPq3JJGWEQkaDQliGJnaPXf6e/p8rGrt4/CxUl777fZQylYGg4iReHyMxez8kXN1c5c/Pj1D7AhKQqKujQgqCDSrK35evTca/InD+sYmyXSWdqeLFvCHhka9bpyvdgsdCpl0msRkin1/xMLcLKXbIs3mp6UG/R5vL2VKzzV29g4oFAokkh7XxQuGgcbxtTYy6Fr97xaZ6QmeHu55rVYIf9poHeAMR8ZCNLvbW8TGY5x0OrgK7KhLEIY4U6nUeS63tBwGWowR5dgziME4bsTyPO/yH3LufRKlNxKMAAAAAElFTkSuQmCC'
|
|
9
|
+
dj = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAMAAADz0U65AAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAC9UExURY2NjYWGhoeIiYiIiIiIiYWFhoODg4mKillZWYSEhFBMS3x7e0xIR3Bsa0E+PldWVi4wMT4/Px0eHiQkJA8PDwoMDAsMDAsMDAsLCw0NDWxqaHZtZnBrZ2dnZ25qZ21oZJ94XtWNWr6DXG9mYpp2X6p5V6JwVNJ9TsN4UXBgWZhtVaxuTZBbR6xiRMpoQKlgQ6JfRZ5cQHFGN6dOMqFOM5lMM6tPMmZBNCYlJS8mIywlJCglJC8mJCMhIf////64+awAAAAadFJOU1SosLCwokSyl7ugup+6n7ugr5RLlJmYmZA8Hg7dEgAAAAFiS0dEPklkAOMAAAAHdElNRQfpDBESHCL8f1a2AAAAUElEQVQI12NgYGRiYmZhZWNgl5KWkZWT52DgVFBUUlZR5WLgVlPX0NTS5mHg1dHV0zcw5GPgNzI2MTUzF2AQtLC0sraxFWIQFhEVExOXkAQA4WIHfGNBCckAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjUtMTItMTdUMTg6Mjg6MjgrMDA6MDDR5B2HAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI1LTEyLTE3VDE4OjI4OjI4KzAwOjAwoLmlOwAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNS0xMi0xN1QxODoyODozNCswMDowMPym7g4AAAAASUVORK5CYII='
|
|
10
|
+
dl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAACKADAAQAAAABAAAACAAAAACVhHtSAAAAw0lEQVQYGV2PMQrCQBBF/+6OSUy1aYQgSI7gCSR4Bhs78RKCtQfxAnqGVLYewE6ENELSqHFJdt0hCOIvhtl9zPw/Al55voqCNikFoPntgNpQlRbFvhEMwzZ5MfjXm6oh8aQigdZZ+A2QfpxlJcCMiISeqgwRxYgfGuflHLjfMLuMcbzuND3JYGPXiE2IMjAYHU6YIIMNFKzoQEEzqBdqqzu/21nX20hvZgRkp2ritBxSdr33b/UhU8mncFo+7Qu55z9mH8f7S3Ax+Zg1AAAAAElFTkSuQmCC'
|
|
11
|
+
dt = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA4ElEQVR4nD2PsWrCUBSGv3ubBoq+QevQUhAXV6dMRcyTZBV8CCfxCTq4ZOmSJwg+giB4t16p1NCpSFECyY2n5EL7LeeD8/PDr5qmEa01+XrNz35PaAxFUXCrNQ/DIVophbWW19WKt+WSp16PYLvlvtNBHY8ESZLg6ppPaxmMRgymUz4WC577fR5nM3SapryMx0RRxPf5jDjHXRi21bQEWZZhjCGeTIiDgOvpxM3hQLXb+QAiImVZSlVV0tS1XEXkPY7laz5vX0K74h/n/KnyXNxm41351B+tKoVcLt5Vt8svgsSBPKnRQSAAAAAASUVORK5CYII='
|
|
12
|
+
dw = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA70lEQVR4nAXBTUrDQBiA4febmfjbpqZUsFkJxS6UIq4EvYS46CUExRPkBL2HFM/gIdxIFq4Ff2JNia3JzBefR+bzuZ1Op+E+y/q6Fd/GSe8qijZH1lpfN00uADdZNt5NDh7GJ8dng2HKxvYOBtB6jctms/5S3ePpxeWklw69tZE1IqKqrIxT81U1d4PReCJJ338HXBVURCCokhelMZW467YTt9pi1rUntPCHYJ0ljiyubMJh0yJFuZSk26ENjufPFV0CCeAUfLEo8V7pRBHWOMJvBc5Q+xpnIf8pl+fvi1Lztw9zlO6T7sWw9jy9vPIPUL1kPErau3YAAAAASUVORK5CYII='
|
|
13
|
+
fx = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAABB0lEQVR4nB2LP0sCcQBA3/2Uzugu8E4IoT9cSYhUENFWYSA1FFTQ4hK5SENNDW19hoYcImhvaGgLguYgcIk0haLOE7wrNGzo5A4v9K3vPWknmwt0LYrrunieTygkAAm300EIQTg5nWB3e5O39w9s54t4fISEYfBZq/H4VETIsoxp1ftyJpWkR7lSZXFhnsFIhLBtOxR9n1KliqZFeX4po+saZ4VLTMtC9M61TJrTk2OarR9WV5bIpJfZ2ljH8zxEw3EovVaZm01xd//AsKpwfXNLLKaTmDSQ9vJHwWE+x3ezRbv9i6oqTBkTmLU65xdXSNn9g0CWB2jYDuNjo/y5Lqoy1A+63S7/GeVj+5KBt3UAAAAASUVORK5CYII='
|
|
14
|
+
nk = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAHYYAAB2GAV2iE4EAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADrmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4NCjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4NCgk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNCAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4RUJCOThFRkQ5RTcxMUU1QTcyN0EzQzFGN0YzNjcwNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4RUJCOThGMEQ5RTcxMUU1QTcyN0EzQzFGN0YzNjcwNCI+DQoJCQk8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4RUJCOThFREQ5RTcxMUU1QTcyN0EzQzFGN0YzNjcwNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4RUJCOThFRUQ5RTcxMUU1QTcyN0EzQzFGN0YzNjcwNCIvPg0KCQk8L3JkZjpEZXNjcmlwdGlvbj4NCgkJPHJkZjpEZXNjcmlwdGlvbiB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+PHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj48L3JkZjpEZXNjcmlwdGlvbj48L3JkZjpSREY+DQo8L3g6eG1wbWV0YT4NCjw/eHBhY2tldCBlbmQ9J3cnPz7hg4LgAAAA3UlEQVQoU2NgIAAYGRgYGP7//8/4cHak44//jJfY//3T+S0vdpz/zXvZZ8+/yTIzMDAwhP490ir479ecx89/H2X69nH123vvn/1592HVy6+/rjNeyrPR+/jz927mf3+5v7Pz+vH8/DSXm51Z7NW3v8ec5p11Zfr44fOSv5+/MDB+/fqP4dOnoJ9fvjN++/TtE/P376IMDAwMzL5qYt8Y/v5+ws383+ndb8ajLP9+2T36xZ7O/f9HTIyhFCMjzLVLIw28Hv8ROarA8sL64Ve+wyocX+R//mOQQfIQdgAAAghnscY2ZXIAAAAASUVORK5CYII='
|
|
15
|
+
he = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAHYYAAB2GAV2iE4EAAACsSURBVChTY2CAgv///zPC2DA+uhh28IiBxZ5FQTWdS8tUgktOLZlHTq2eR05tAoeschxYwTsGpnpRVq6bDMxscxhYue4xsPM8ZBIULWVg57nAwM6uyPCPg0N+DwPD4zgGhnMyDAz32BgY7jAwMJQxMDCeMmdgCAeb8oeBIeEfA4PjMgaG3FQGhnlODIzHHBgY18UzMARjur6+numfuDj3f0lJLogA1DvoCmEAAJVNNF84URktAAAAAElFTkSuQmCC'
|
|
16
|
+
mb = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAABE0lEQVR4nAEIAff+AQAAAACHttAxAQ0Kjd7o7ToDAQH/GREOxcDT4HK+cErSAYy70DHs/AG6tNjoFNzn6gD5+fwAQjElAIE/JuqWxdZEBBwVD5RSIhsUnsTV/JBRNwT9/v4AjcDU/DsgOxbW6RqUArra5zf39vb/KRwTBKPN3gBMKhwA3unyBJHE2P/i7/U6Auvz+ACkzt4AaTkmAN/u9AARCQYAQysdALXW5ADl8fYAAi4bEMbD5vQBMxoR/CwYEACVxtkAfUMr/PoECAEZDwrFAiAPCmwpEAjq/gcKBAUDAQCQwtcAMSIZBDkbDukIBAJtAmU5KNIP//1F1ePrvScWD/hSLR/4uNXkvAHz9kZ+RS/T0LpzUht5tWAAAAAASUVORK5CYII='
|
|
17
|
+
nx = 'data:image/png;base64,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'
|
|
18
|
+
sf = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA8ElEQVR4nBXBv0rDQADA4d/lz1lqmlREECUIFTq4FBeHDA6uPkRfwwfxBRx19gmk4GZBBAcjCAUrWEkaTUzucjnx+0R6kzQboZDCb7AWdNmiMo3KLHUmlCcDR/Z2DujvJXRth6kNqqgoXufo6kk6lpzwcEr7fUrx7POTugh9xPZkilE5jh9MsJ2mreaUi0eKdIa7CUIogjjB8wcnyOiM0rmkH+8ih8dY1gTxOeHoA69eLRCOxBvsE21JOmVo8gy3N6T+fMNbPdwiwzG6XFJ/vWC1xY9GvN9dsZxdI+4vxo3rtxLH8q/TFvPbYhqL0Z76AydWbEnTqqOqAAAAAElFTkSuQmCC'
|
|
19
|
+
sj = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAMAAADz0U65AAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAC9UExURY2NjYWGhoeIiYiIiIiIiYWFhoODg4mKillZWYSEhFBMS3x7e0xIR3Bsa0E+PldWVi4wMT4/Px0eHiQkJA8PDwoMDAsMDAsMDAsLCw0NDWxqaHZtZnBrZ2dnZ25qZ21oZJ94XtWNWr6DXG9mYpp2X6p5V6JwVNJ9TsN4UXBgWZhtVaxuTZBbR6xiRMpoQKlgQ6JfRZ5cQHFGN6dOMqFOM5lMM6tPMmZBNCYlJS8mIywlJCglJC8mJCMhIf////64+awAAAAadFJOU1SosLCwokSyl7ugup+6n7ugr5RLlJmYmZA8Hg7dEgAAAAFiS0dEPklkAOMAAAAHdElNRQfpDBESHCL8f1a2AAAAUElEQVQI12NgYGRiYmZhZWNgl5KWkZWT52DgVFBUUlZR5WLgVlPX0NTS5mHg1dHV0zcw5GPgNzI2MTUzF2AQtLC0sraxFWIQFhEVExOXkAQA4WIHfGNBCckAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjUtMTItMTdUMTg6Mjg6MjgrMDA6MDDR5B2HAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI1LTEyLTE3VDE4OjI4OjI4KzAwOjAwoLmlOwAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNS0xMi0xN1QxODoyODozNCswMDowMPym7g4AAAAASUVORK5CYII='
|
|
20
|
+
sl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA/ElEQVR4nE3PrUpDYRzH8d/z5tnRozugImIYgjAwGY5egGUG64JRkxgWvIFV0zCIwVsQLLYhWgSDLizJiowVFUHZdJ7zvP7Ftu8NfPgybOwvImcFet0C6FhMtrYTSQg1Ru/id3W7sfTxmc3rQpeE4gk8BZJiigF1kWYLe9rSGZEvR4o/AvRAxBLB8SObzXVqXb/tBjFdJjOCtliJI/U6fDo/CQSwf4ozIM2OGrm2xyGEClQCReO76tZmTabZYcsHmnHOfSvJ+8axCiNtlJDtztdNkLmxbViyEIx7669YxPPlZG44uD99wXs9ltqNbvF8aSbvBgBH9WAWMZX+AJIYacQLryqFAAAAAElFTkSuQmCC'
|
|
21
|
+
wd = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA90lEQVR4nC3OsS5DUQAG4P8/Pb2kiS4mliaEkMYgTBiQiMVk6C6RsHmAxuoFbHTzCmIR9QSWLko6kIiQCnqHq+fec84vEt8TfMS/5s3jniFf36uD9sTH6Fg9rQ8aDQY2r7trhJmFUY1kW9I4gF0I9wGuZUOM04x+B4o9EvMSZ0D1EVWYkklsnn51TFIOhJ2DwgaN6QiqgsbRh00rseu9J1WsUngGOBmhSvaZnZwdbA1MkWfrwQ2PvXMvwbk7n7taLPKppFpe+cvb8DN8gi09RGmkbEv9GHQLqQZi+bB19WZDdN+WlYskRe/0aNsBaO+fXy4ZxEWKC7/R+XkmFbstdAAAAABJRU5ErkJggg=='
|
|
22
|
+
wx = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAACKADAAQAAAABAAAACAAAAACVhHtSAAAAcUlEQVQYGWNgYGD4B8S4wD+mf7y2jEDZ/0CsiKRKEiT2j9cGLMQGJH8DMUwhyEQQGyTGBcRg3T+hNMgkGP4EYsN0AdlgAHMPE0wARMN0XEASBLHB4ixQQUGgg94xMjCCBMEyTJ8PiwKZr0F8kDW4ACMASI8hUcBfWMAAAAAASUVORK5CYII='
|
|
@@ -24,6 +24,11 @@ def render_centered_html(inner_content):
|
|
|
24
24
|
--secondary: #6c757d;
|
|
25
25
|
--code-bg: #f8f9fa;
|
|
26
26
|
--spacing: 1rem;
|
|
27
|
+
--info-border: #2d5a2d;
|
|
28
|
+
--setup-border: var(--primary);
|
|
29
|
+
--divider-color: #dee2e6;
|
|
30
|
+
--btn-subtle-bg: #e9ecef;
|
|
31
|
+
--btn-subtle-border: #ced4da;
|
|
27
32
|
}
|
|
28
33
|
@media (prefers-color-scheme: dark) {
|
|
29
34
|
:root {
|
|
@@ -32,8 +37,57 @@ def render_centered_html(inner_content):
|
|
|
32
37
|
--card-bg: #242526;
|
|
33
38
|
--card-shadow: rgba(0, 0, 0, 0.5);
|
|
34
39
|
--code-bg: #2c2f33;
|
|
40
|
+
--info-border: #4a8c4a;
|
|
41
|
+
--setup-border: var(--primary);
|
|
42
|
+
--divider-color: #444;
|
|
43
|
+
--btn-subtle-bg: #444;
|
|
44
|
+
--btn-subtle-border: #666;
|
|
35
45
|
}
|
|
36
46
|
}
|
|
47
|
+
/* Info box styling */
|
|
48
|
+
.info-box {
|
|
49
|
+
border: 1px solid var(--info-border);
|
|
50
|
+
border-radius: 8px;
|
|
51
|
+
padding: 16px;
|
|
52
|
+
margin-bottom: 24px;
|
|
53
|
+
}
|
|
54
|
+
.info-box h3 {
|
|
55
|
+
margin-top: 0;
|
|
56
|
+
color: var(--info-border);
|
|
57
|
+
}
|
|
58
|
+
/* Setup box styling */
|
|
59
|
+
.setup-box {
|
|
60
|
+
border: 1px solid var(--setup-border);
|
|
61
|
+
border-radius: 8px;
|
|
62
|
+
padding: 16px;
|
|
63
|
+
margin-bottom: 24px;
|
|
64
|
+
}
|
|
65
|
+
.setup-box h3 {
|
|
66
|
+
margin-top: 0;
|
|
67
|
+
color: var(--setup-border);
|
|
68
|
+
}
|
|
69
|
+
/* Subtle button styling (ghost style) */
|
|
70
|
+
.btn-subtle {
|
|
71
|
+
background: transparent;
|
|
72
|
+
color: var(--fg-color);
|
|
73
|
+
border: 1.5px solid var(--btn-subtle-border);
|
|
74
|
+
padding: 8px 16px;
|
|
75
|
+
border-radius: 0.5rem;
|
|
76
|
+
cursor: pointer;
|
|
77
|
+
font-size: 1rem;
|
|
78
|
+
font-weight: 500;
|
|
79
|
+
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
80
|
+
}
|
|
81
|
+
.btn-subtle:hover {
|
|
82
|
+
background: var(--btn-subtle-bg);
|
|
83
|
+
border-color: var(--fg-color);
|
|
84
|
+
}
|
|
85
|
+
/* Divider styling */
|
|
86
|
+
.section-divider {
|
|
87
|
+
margin-top: 20px;
|
|
88
|
+
padding-top: 20px;
|
|
89
|
+
border-top: 1px solid var(--divider-color);
|
|
90
|
+
}
|
|
37
91
|
/* Logo and heading alignment */
|
|
38
92
|
h1 {
|
|
39
93
|
display: inline-flex;
|
|
@@ -142,24 +196,35 @@ def render_centered_html(inner_content):
|
|
|
142
196
|
border-radius: 0.5rem;
|
|
143
197
|
font-weight: 500;
|
|
144
198
|
cursor: pointer;
|
|
145
|
-
transition: background-color 0.2s ease, border-color 0.2s ease;
|
|
146
|
-
border: none;
|
|
199
|
+
transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
|
|
147
200
|
margin-top: 0.5rem;
|
|
148
201
|
}
|
|
149
202
|
.btn-primary {
|
|
150
203
|
background-color: var(--primary);
|
|
151
204
|
color: #fff;
|
|
205
|
+
border: 1.5px solid #0856c7;
|
|
206
|
+
}
|
|
207
|
+
.btn-primary:hover {
|
|
208
|
+
background-color: #0b5ed7;
|
|
209
|
+
border-color: #084298;
|
|
210
|
+
box-shadow: 0 2px 6px rgba(13, 110, 253, 0.4);
|
|
152
211
|
}
|
|
153
212
|
.btn-secondary {
|
|
154
213
|
background-color: var(--secondary);
|
|
155
214
|
color: #fff;
|
|
215
|
+
border: 1.5px solid #565e64;
|
|
216
|
+
}
|
|
217
|
+
.btn-secondary:hover {
|
|
218
|
+
background-color: #5c636a;
|
|
219
|
+
border-color: #41464b;
|
|
220
|
+
box-shadow: 0 2px 6px rgba(108, 117, 125, 0.4);
|
|
156
221
|
}
|
|
157
222
|
a {
|
|
158
223
|
color: var(--primary);
|
|
159
224
|
text-decoration: none;
|
|
160
225
|
}
|
|
161
226
|
a:hover {
|
|
162
|
-
|
|
227
|
+
|
|
163
228
|
}
|
|
164
229
|
/* footer styling */
|
|
165
230
|
footer {
|