quasarr 1.19.0__py3-none-any.whl → 1.20.1__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/captcha/__init__.py +162 -17
- quasarr/downloads/__init__.py +6 -0
- quasarr/downloads/sources/dj.py +7 -0
- quasarr/downloads/sources/sj.py +7 -0
- quasarr/providers/html_images.py +2 -0
- quasarr/providers/html_templates.py +1 -1
- quasarr/providers/obfuscated.py +18 -1
- quasarr/providers/version.py +1 -1
- quasarr/search/__init__.py +8 -0
- quasarr/search/sources/dj.py +213 -0
- quasarr/search/sources/sj.py +213 -0
- quasarr/storage/config.py +2 -0
- {quasarr-1.19.0.dist-info → quasarr-1.20.1.dist-info}/METADATA +1 -1
- {quasarr-1.19.0.dist-info → quasarr-1.20.1.dist-info}/RECORD +18 -14
- {quasarr-1.19.0.dist-info → quasarr-1.20.1.dist-info}/WHEEL +0 -0
- {quasarr-1.19.0.dist-info → quasarr-1.20.1.dist-info}/entry_points.txt +0 -0
- {quasarr-1.19.0.dist-info → quasarr-1.20.1.dist-info}/licenses/LICENSE +0 -0
- {quasarr-1.19.0.dist-info → quasarr-1.20.1.dist-info}/top_level.txt +0 -0
quasarr/api/captcha/__init__.py
CHANGED
|
@@ -16,7 +16,7 @@ from quasarr.downloads.packages import delete_package
|
|
|
16
16
|
from quasarr.providers import shared_state
|
|
17
17
|
from quasarr.providers.html_templates import render_button, render_centered_html
|
|
18
18
|
from quasarr.providers.log import info, debug
|
|
19
|
-
from quasarr.providers.obfuscated import captcha_js, captcha_values,
|
|
19
|
+
from quasarr.providers.obfuscated import captcha_js, captcha_values, filecrypt_user_js, junkies_user_js
|
|
20
20
|
from quasarr.providers.statistics import StatsHelper
|
|
21
21
|
|
|
22
22
|
|
|
@@ -58,7 +58,7 @@ def setup_captcha_routes(app):
|
|
|
58
58
|
desired_mirror = None
|
|
59
59
|
|
|
60
60
|
# This is set for circle CAPTCHAs
|
|
61
|
-
|
|
61
|
+
filecrypt_session = data.get("session", None)
|
|
62
62
|
|
|
63
63
|
# This is required for cutcaptcha
|
|
64
64
|
rapid = [ln for ln in links if "rapidgator" in ln[1].lower()]
|
|
@@ -73,15 +73,25 @@ def setup_captcha_routes(app):
|
|
|
73
73
|
"title": title,
|
|
74
74
|
"password": password,
|
|
75
75
|
"mirror": desired_mirror,
|
|
76
|
-
"session":
|
|
76
|
+
"session": filecrypt_session,
|
|
77
77
|
"links": prioritized_links,
|
|
78
78
|
"original_url": original_url
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
encoded_payload = urlsafe_b64encode(json.dumps(payload).encode()).decode()
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
sj = shared_state.values["config"]("Hostnames").get("sj")
|
|
84
|
+
dj = shared_state.values["config"]("Hostnames").get("dj")
|
|
85
|
+
has_junkies_links = any(
|
|
86
|
+
(sj and sj in link) or (dj and dj in link)
|
|
87
|
+
for link in prioritized_links
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if has_junkies_links:
|
|
91
|
+
debug("Redirecting to Junkies CAPTCHA")
|
|
92
|
+
redirect(f"/captcha/junkies?data={quote(encoded_payload)}")
|
|
93
|
+
elif filecrypt_session:
|
|
94
|
+
debug(f'Redirecting to circle CAPTCHA')
|
|
85
95
|
redirect(f"/captcha/circle?data={quote(encoded_payload)}")
|
|
86
96
|
else:
|
|
87
97
|
debug(f"Redirecting to cutcaptcha")
|
|
@@ -101,13 +111,140 @@ def setup_captcha_routes(app):
|
|
|
101
111
|
except Exception as e:
|
|
102
112
|
return {"error": f"Failed to decode payload: {str(e)}"}
|
|
103
113
|
|
|
104
|
-
@app.get(
|
|
105
|
-
def
|
|
106
|
-
|
|
114
|
+
@app.get("/captcha/junkies")
|
|
115
|
+
def serve_junkies_captcha():
|
|
116
|
+
payload = decode_payload()
|
|
117
|
+
|
|
118
|
+
if "error" in payload:
|
|
119
|
+
return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
120
|
+
<p>{payload["error"]}</p>
|
|
121
|
+
<p>
|
|
122
|
+
{render_button("Back", "secondary", {"onclick": "location.href='/'"})}
|
|
123
|
+
</p>''')
|
|
124
|
+
|
|
125
|
+
package_id = payload.get("package_id")
|
|
126
|
+
title = payload.get("title")
|
|
127
|
+
password = payload.get("password")
|
|
128
|
+
urls = payload.get("links")
|
|
129
|
+
url = urls[0]
|
|
130
|
+
|
|
131
|
+
return render_centered_html(f"""
|
|
132
|
+
<!DOCTYPE html>
|
|
133
|
+
<html>
|
|
134
|
+
<body>
|
|
135
|
+
<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
136
|
+
<p><b>Package:</b> {title}</p>
|
|
137
|
+
{render_junkies_section(url, package_id, title, password)}
|
|
138
|
+
<p>
|
|
139
|
+
{render_button("Delete Package", "secondary", {"onclick": f"location.href='/captcha/delete/{package_id}'"})}
|
|
140
|
+
</p>
|
|
141
|
+
<p>
|
|
142
|
+
{render_button("Back", "secondary", {"onclick": "location.href='/'"})}
|
|
143
|
+
</p>
|
|
144
|
+
|
|
145
|
+
</body>
|
|
146
|
+
</html>""")
|
|
147
|
+
|
|
148
|
+
def render_junkies_section(url, package_id, title, password):
|
|
149
|
+
"""Render the UI section for SJ and DJ pages"""
|
|
150
|
+
|
|
151
|
+
# Generate userscript URL with transfer params
|
|
152
|
+
# Get base URL of current request
|
|
153
|
+
base_url = request.urlparts.scheme + '://' + request.urlparts.netloc
|
|
154
|
+
transfer_url = f"{base_url}/captcha/quick-transfer"
|
|
155
|
+
|
|
156
|
+
url_with_quick_transfer_params = (
|
|
157
|
+
f"{url}?"
|
|
158
|
+
f"transfer_url={quote(transfer_url)}&"
|
|
159
|
+
f"pkg_id={quote(package_id)}&"
|
|
160
|
+
f"pkg_title={quote(title)}&"
|
|
161
|
+
f"pkg_pass={quote(password)}"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return f'''
|
|
165
|
+
<div>
|
|
166
|
+
<!-- One-time setup section - visually separated -->
|
|
167
|
+
<div id="setup-instructions" style="background: #2a2a2a; border: 2px solid #444; border-radius: 8px; padding: 16px; margin-bottom: 24px;">
|
|
168
|
+
<h3 style="margin-top: 0; color: #58a6ff;">First Time Setup:</h3>
|
|
169
|
+
<p style="margin-bottom: 8px;">
|
|
170
|
+
<a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. Install Tampermonkey</a>
|
|
171
|
+
</p>
|
|
172
|
+
<p style="margin-top: 0; margin-bottom: 12px;">
|
|
173
|
+
<a href="/captcha/junkies.user.js" target="_blank">2. Install this userscript</a>
|
|
174
|
+
</p>
|
|
175
|
+
<p style="margin-top: 0;">
|
|
176
|
+
<button id="hide-setup-btn" type="button" style="background: #444; color: #fff; border: 1px solid #666; padding: 6px 12px; border-radius: 4px; cursor: pointer;">
|
|
177
|
+
✅ Don't show this again
|
|
178
|
+
</button>
|
|
179
|
+
</p>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<!-- Hidden "show instructions" link -->
|
|
183
|
+
<div id="show-instructions-link" style="display: none; margin-bottom: 16px;">
|
|
184
|
+
<a href="#" id="show-setup-btn" style="color: #58a6ff;">ℹ️ Show instructions again</a>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<strong><a href="{url_with_quick_transfer_params}" target="_blank">🔗 Obtain the download links here!</a></strong><br><br>
|
|
188
|
+
|
|
189
|
+
<form id="bypass-form" action="/captcha/bypass-submit" method="post" enctype="multipart/form-data">
|
|
190
|
+
<input type="hidden" name="package_id" value="{package_id}" />
|
|
191
|
+
<input type="hidden" name="title" value="{title}" />
|
|
192
|
+
<input type="hidden" name="password" value="{password}" />
|
|
193
|
+
|
|
194
|
+
<div>
|
|
195
|
+
<strong>Paste the download links (one per line):</strong>
|
|
196
|
+
<textarea id="links-input" name="links" rows="5" style="width: 100%; padding: 8px; font-family: monospace; resize: vertical;"></textarea>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
<div>
|
|
200
|
+
{render_button("Submit", "primary", {"type": "submit"})}
|
|
201
|
+
</div>
|
|
202
|
+
</form>
|
|
203
|
+
</div>
|
|
204
|
+
<script>
|
|
205
|
+
// Handle setup instructions hide/show
|
|
206
|
+
const hideSetup = localStorage.getItem('hideJunkiesSetupInstructions');
|
|
207
|
+
const setupBox = document.getElementById('setup-instructions');
|
|
208
|
+
const showLink = document.getElementById('show-instructions-link');
|
|
209
|
+
|
|
210
|
+
if (hideSetup === 'true') {{
|
|
211
|
+
setupBox.style.display = 'none';
|
|
212
|
+
showLink.style.display = 'block';
|
|
213
|
+
}}
|
|
214
|
+
|
|
215
|
+
// Hide setup instructions
|
|
216
|
+
document.getElementById('hide-setup-btn').addEventListener('click', function() {{
|
|
217
|
+
localStorage.setItem('hideJunkiesSetupInstructions', 'true');
|
|
218
|
+
setupBox.style.display = 'none';
|
|
219
|
+
showLink.style.display = 'block';
|
|
220
|
+
}});
|
|
221
|
+
|
|
222
|
+
// Show setup instructions again
|
|
223
|
+
document.getElementById('show-setup-btn').addEventListener('click', function(e) {{
|
|
224
|
+
e.preventDefault();
|
|
225
|
+
localStorage.setItem('hideJunkiesSetupInstructions', 'false');
|
|
226
|
+
setupBox.style.display = 'block';
|
|
227
|
+
showLink.style.display = 'none';
|
|
228
|
+
}});
|
|
229
|
+
</script>
|
|
230
|
+
'''
|
|
231
|
+
|
|
232
|
+
@app.get('/captcha/junkies.user.js')
|
|
233
|
+
def serve_junkies_user_js():
|
|
234
|
+
sj = shared_state.values["config"]("Hostnames").get("sj")
|
|
235
|
+
dj = shared_state.values["config"]("Hostnames").get("dj")
|
|
236
|
+
|
|
237
|
+
content = junkies_user_js(sj, dj)
|
|
238
|
+
response.content_type = 'application/javascript'
|
|
239
|
+
return content
|
|
240
|
+
|
|
241
|
+
@app.get('/captcha/filecrypt.user.js')
|
|
242
|
+
def serve_filecrypt_user_js():
|
|
243
|
+
content = filecrypt_user_js()
|
|
107
244
|
response.content_type = 'application/javascript'
|
|
108
245
|
return content
|
|
109
246
|
|
|
110
|
-
def
|
|
247
|
+
def render_filecrypt_bypass_section(url, package_id, title, password):
|
|
111
248
|
"""Render the bypass UI section for both cutcaptcha and circle captcha pages"""
|
|
112
249
|
|
|
113
250
|
# Generate userscript URL with transfer params
|
|
@@ -135,7 +272,7 @@ def setup_captcha_routes(app):
|
|
|
135
272
|
<a href="https://www.tampermonkey.net/" target="_blank" rel="noopener noreferrer">1. Install Tampermonkey</a>
|
|
136
273
|
</p>
|
|
137
274
|
<p style="margin-top: 0; margin-bottom: 12px;">
|
|
138
|
-
<a href="/captcha/
|
|
275
|
+
<a href="/captcha/filecrypt.user.js" target="_blank">2. Install this userscript</a>
|
|
139
276
|
</p>
|
|
140
277
|
<p style="margin-top: 0;">
|
|
141
278
|
<button id="hide-setup-btn" type="button" style="background: #444; color: #fff; border: 1px solid #666; padding: 6px 12px; border-radius: 4px; cursor: pointer;">
|
|
@@ -146,7 +283,7 @@ def setup_captcha_routes(app):
|
|
|
146
283
|
|
|
147
284
|
<!-- Hidden "show instructions" link -->
|
|
148
285
|
<div id="show-instructions-link" style="display: none; margin-bottom: 16px;">
|
|
149
|
-
<a href="#" id="show-setup-btn" style="color: #58a6ff;
|
|
286
|
+
<a href="#" id="show-setup-btn" style="color: #58a6ff;">ℹ️ Show instructions again</a>
|
|
150
287
|
</div>
|
|
151
288
|
|
|
152
289
|
<strong><a href="{url_with_quick_transfer_params}" target="_blank">🔗 Obtain the download links here!</a></strong><br><br>
|
|
@@ -188,7 +325,7 @@ def setup_captcha_routes(app):
|
|
|
188
325
|
}}
|
|
189
326
|
|
|
190
327
|
// Handle setup instructions hide/show
|
|
191
|
-
const hideSetup = localStorage.getItem('
|
|
328
|
+
const hideSetup = localStorage.getItem('hideFileCryptSetupInstructions');
|
|
192
329
|
const setupBox = document.getElementById('setup-instructions');
|
|
193
330
|
const showLink = document.getElementById('show-instructions-link');
|
|
194
331
|
|
|
@@ -199,7 +336,7 @@ def setup_captcha_routes(app):
|
|
|
199
336
|
|
|
200
337
|
// Hide setup instructions
|
|
201
338
|
document.getElementById('hide-setup-btn').addEventListener('click', function() {{
|
|
202
|
-
localStorage.setItem('
|
|
339
|
+
localStorage.setItem('hideFileCryptSetupInstructions', 'true');
|
|
203
340
|
setupBox.style.display = 'none';
|
|
204
341
|
showLink.style.display = 'block';
|
|
205
342
|
}});
|
|
@@ -207,7 +344,7 @@ def setup_captcha_routes(app):
|
|
|
207
344
|
// Show setup instructions again
|
|
208
345
|
document.getElementById('show-setup-btn').addEventListener('click', function(e) {{
|
|
209
346
|
e.preventDefault();
|
|
210
|
-
localStorage.setItem('
|
|
347
|
+
localStorage.setItem('hideFileCryptSetupInstructions', 'false');
|
|
211
348
|
setupBox.style.display = 'block';
|
|
212
349
|
showLink.style.display = 'none';
|
|
213
350
|
}});
|
|
@@ -426,7 +563,7 @@ def setup_captcha_routes(app):
|
|
|
426
563
|
url = prioritized_links[0][0]
|
|
427
564
|
|
|
428
565
|
# Add bypass section
|
|
429
|
-
bypass_section =
|
|
566
|
+
bypass_section = render_filecrypt_bypass_section(url, package_id, title, password)
|
|
430
567
|
|
|
431
568
|
content = render_centered_html(r'''
|
|
432
569
|
<script type="text/javascript">
|
|
@@ -468,7 +605,7 @@ def setup_captcha_routes(app):
|
|
|
468
605
|
.then(data => {
|
|
469
606
|
if (data.success) {
|
|
470
607
|
document.getElementById("captcha-key").insertAdjacentHTML('afterend',
|
|
471
|
-
'<p
|
|
608
|
+
'<p>✅ Successful!</p>');
|
|
472
609
|
} else {
|
|
473
610
|
document.getElementById("captcha-key").insertAdjacentHTML('afterend',
|
|
474
611
|
'<p>Failed. Check console for details!</p>');
|
|
@@ -607,6 +744,14 @@ def setup_captcha_routes(app):
|
|
|
607
744
|
{render_button("Back", "secondary", {"onclick": "location.href='/captcha'"})}
|
|
608
745
|
</p>''')
|
|
609
746
|
|
|
747
|
+
package_exists = shared_state.get_db("protected").retrieve(package_id)
|
|
748
|
+
if not package_exists:
|
|
749
|
+
return render_centered_html(f'''<h1><img src="{images.logo}" type="image/png" alt="Quasarr logo" class="logo"/>Quasarr</h1>
|
|
750
|
+
<p><b>Error:</b> Package not found or already solved.</p>
|
|
751
|
+
<p>
|
|
752
|
+
{render_button("Back", "secondary", {"onclick": "location.href='/captcha'"})}
|
|
753
|
+
</p>''')
|
|
754
|
+
|
|
610
755
|
# Process links input
|
|
611
756
|
if links_input:
|
|
612
757
|
info(f"Processing direct links bypass for {title}")
|
|
@@ -787,7 +932,7 @@ def setup_captcha_routes(app):
|
|
|
787
932
|
return "Missing required parameters"
|
|
788
933
|
|
|
789
934
|
# Add bypass section
|
|
790
|
-
bypass_section =
|
|
935
|
+
bypass_section = render_filecrypt_bypass_section(original_url, package_id, title, password)
|
|
791
936
|
|
|
792
937
|
return render_centered_html(f"""
|
|
793
938
|
<!DOCTYPE html>
|
quasarr/downloads/__init__.py
CHANGED
|
@@ -11,6 +11,7 @@ from quasarr.downloads.linkcrypters.hide import decrypt_links_if_hide
|
|
|
11
11
|
from quasarr.downloads.sources.al import get_al_download_links
|
|
12
12
|
from quasarr.downloads.sources.by import get_by_download_links
|
|
13
13
|
from quasarr.downloads.sources.dd import get_dd_download_links
|
|
14
|
+
from quasarr.downloads.sources.dj import get_dj_download_links
|
|
14
15
|
from quasarr.downloads.sources.dt import get_dt_download_links
|
|
15
16
|
from quasarr.downloads.sources.dw import get_dw_download_links
|
|
16
17
|
from quasarr.downloads.sources.he import get_he_download_links
|
|
@@ -18,6 +19,7 @@ from quasarr.downloads.sources.mb import get_mb_download_links
|
|
|
18
19
|
from quasarr.downloads.sources.nk import get_nk_download_links
|
|
19
20
|
from quasarr.downloads.sources.nx import get_nx_download_links
|
|
20
21
|
from quasarr.downloads.sources.sf import get_sf_download_links, resolve_sf_redirect
|
|
22
|
+
from quasarr.downloads.sources.sj import get_sj_download_links
|
|
21
23
|
from quasarr.downloads.sources.sl import get_sl_download_links
|
|
22
24
|
from quasarr.downloads.sources.wd import get_wd_download_links
|
|
23
25
|
from quasarr.providers.log import info
|
|
@@ -201,6 +203,7 @@ def download(shared_state, request_from, title, url, mirror, size_mb, password,
|
|
|
201
203
|
'AL': config.get("al"),
|
|
202
204
|
'BY': config.get("by"),
|
|
203
205
|
'DD': config.get("dd"),
|
|
206
|
+
'DJ': config.get("dj"),
|
|
204
207
|
'DT': config.get("dt"),
|
|
205
208
|
'DW': config.get("dw"),
|
|
206
209
|
'HE': config.get("he"),
|
|
@@ -208,6 +211,7 @@ def download(shared_state, request_from, title, url, mirror, size_mb, password,
|
|
|
208
211
|
'NK': config.get("nk"),
|
|
209
212
|
'NX': config.get("nx"),
|
|
210
213
|
'SF': config.get("sf"),
|
|
214
|
+
'SJ': config.get("sj"),
|
|
211
215
|
'SL': config.get("sl"),
|
|
212
216
|
'WD': config.get("wd")
|
|
213
217
|
}
|
|
@@ -216,6 +220,7 @@ def download(shared_state, request_from, title, url, mirror, size_mb, password,
|
|
|
216
220
|
(flags['AL'], handle_al),
|
|
217
221
|
(flags['BY'], handle_by),
|
|
218
222
|
(flags['DD'], lambda *a: handle_unprotected(*a, func=get_dd_download_links, label='DD')),
|
|
223
|
+
(flags['DJ'], lambda *a: handle_protected(*a, func=get_dj_download_links, label='DJ')),
|
|
219
224
|
(flags['DT'], lambda *a: handle_unprotected(*a, func=get_dt_download_links, label='DT')),
|
|
220
225
|
(flags['DW'], lambda *a: handle_protected(*a, func=get_dw_download_links, label='DW')),
|
|
221
226
|
(flags['HE'], lambda *a: handle_unprotected(*a, func=get_he_download_links, label='HE')),
|
|
@@ -223,6 +228,7 @@ def download(shared_state, request_from, title, url, mirror, size_mb, password,
|
|
|
223
228
|
(flags['NK'], lambda *a: handle_protected(*a, func=get_nk_download_links, label='NK')),
|
|
224
229
|
(flags['NX'], lambda *a: handle_unprotected(*a, func=get_nx_download_links, label='NX')),
|
|
225
230
|
(flags['SF'], handle_sf),
|
|
231
|
+
(flags['SJ'], lambda *a: handle_protected(*a, func=get_sj_download_links, label='SJ')),
|
|
226
232
|
(flags['SL'], handle_sl),
|
|
227
233
|
(flags['WD'], handle_wd),
|
|
228
234
|
]
|
quasarr/providers/html_images.py
CHANGED
|
@@ -6,6 +6,7 @@ logo = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAX
|
|
|
6
6
|
al = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA9UlEQVR4nBXBv0rDQADA4d8ld8EQ2yJiGxAchOqgQSFEEEGfQV18DgcHwYcQ36GDg07+wUlwcBApCnUrbYcKIrRIa0qTy534fSI+vbMCi7GSUe7zr6QmOEJjEUhhDcZReHLEQXiLNoKn4S66CHBMjjTKJ0+nHPZPOJrtEPguc+17GuE5fjCD9H57rHYuCT/H3HxUmaYp5aDPRnZBd2kfp9d6I15fYe/qmdryJiVvge3GI1tRnW7rHbF2fG0rXy9E5QFJnoFSNF1Jc1jhp5YgkrMHm2kYtF9R+TdYS6aqzNdjPBek0RolYDHaoSgsWHClQE/GGA1/SzpdtJMWu3cAAAAASUVORK5CYII='
|
|
7
7
|
by = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAMAAADz0U65AAAATlBMVEX///8crf/29fQDo//J7f/u7u7w+v/2/P/8/PyytLWenp6IhoWTwNfPz8+mpaVYxP94eHhryf+75fyB0f+oxNPl5eW4yNGrr68xsfmUlJQWKuGqAAAAQklEQVQI1yWLSRKAIBADMzOAsgiC+/8/aiwvSR+6AUB15mJyZ42ev8ldclI4MWvXuvwQCaGblPxQCmNP9fgyqGf+AkFFAeZ3L10cAAAAAElFTkSuQmCC'
|
|
8
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='
|
|
9
10
|
dt = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA4ElEQVR4nD2PsWrCUBSGv3ubBoq+QevQUhAXV6dMRcyTZBV8CCfxCTq4ZOmSJwg+giB4t16p1NCpSFECyY2n5EL7LeeD8/PDr5qmEa01+XrNz35PaAxFUXCrNQ/DIVophbWW19WKt+WSp16PYLvlvtNBHY8ESZLg6ppPaxmMRgymUz4WC577fR5nM3SapryMx0RRxPf5jDjHXRi21bQEWZZhjCGeTIiDgOvpxM3hQLXb+QAiImVZSlVV0tS1XEXkPY7laz5vX0K74h/n/KnyXNxm41351B+tKoVcLt5Vt8svgsSBPKnRQSAAAAAASUVORK5CYII='
|
|
10
11
|
dw = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA70lEQVR4nAXBTUrDQBiA4febmfjbpqZUsFkJxS6UIq4EvYS46CUExRPkBL2HFM/gIdxIFq4Ff2JNia3JzBefR+bzuZ1Op+E+y/q6Fd/GSe8qijZH1lpfN00uADdZNt5NDh7GJ8dng2HKxvYOBtB6jctms/5S3ePpxeWklw69tZE1IqKqrIxT81U1d4PReCJJ338HXBVURCCokhelMZW467YTt9pi1rUntPCHYJ0ljiyubMJh0yJFuZSk26ENjufPFV0CCeAUfLEo8V7pRBHWOMJvBc5Q+xpnIf8pl+fvi1Lztw9zlO6T7sWw9jy9vPIPUL1kPErau3YAAAAASUVORK5CYII='
|
|
11
12
|
fx = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAABB0lEQVR4nB2LP0sCcQBA3/2Uzugu8E4IoT9cSYhUENFWYSA1FFTQ4hK5SENNDW19hoYcImhvaGgLguYgcIk0haLOE7wrNGzo5A4v9K3vPWknmwt0LYrrunieTygkAAm300EIQTg5nWB3e5O39w9s54t4fISEYfBZq/H4VETIsoxp1ftyJpWkR7lSZXFhnsFIhLBtOxR9n1KliqZFeX4po+saZ4VLTMtC9M61TJrTk2OarR9WV5bIpJfZ2ljH8zxEw3EovVaZm01xd//AsKpwfXNLLKaTmDSQ9vJHwWE+x3ezRbv9i6oqTBkTmLU65xdXSNn9g0CWB2jYDuNjo/y5Lqoy1A+63S7/GeVj+5KBt3UAAAAASUVORK5CYII='
|
|
@@ -14,5 +15,6 @@ he = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAAXNS
|
|
|
14
15
|
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='
|
|
15
16
|
nx = 'data:image/png;base64,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'
|
|
16
17
|
sf = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA8ElEQVR4nBXBv0rDQADA4d/lz1lqmlREECUIFTq4FBeHDA6uPkRfwwfxBRx19gmk4GZBBAcjCAUrWEkaTUzucjnx+0R6kzQboZDCb7AWdNmiMo3KLHUmlCcDR/Z2DujvJXRth6kNqqgoXufo6kk6lpzwcEr7fUrx7POTugh9xPZkilE5jh9MsJ2mreaUi0eKdIa7CUIogjjB8wcnyOiM0rmkH+8ih8dY1gTxOeHoA69eLRCOxBvsE21JOmVo8gy3N6T+fMNbPdwiwzG6XFJ/vWC1xY9GvN9dsZxdI+4vxo3rtxLH8q/TFvPbYhqL0Z76AydWbEnTqqOqAAAAAElFTkSuQmCC'
|
|
18
|
+
sj = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAMAAADz0U65AAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAC9UExURY2NjYWGhoeIiYiIiIiIiYWFhoODg4mKillZWYSEhFBMS3x7e0xIR3Bsa0E+PldWVi4wMT4/Px0eHiQkJA8PDwoMDAsMDAsMDAsLCw0NDWxqaHZtZnBrZ2dnZ25qZ21oZJ94XtWNWr6DXG9mYpp2X6p5V6JwVNJ9TsN4UXBgWZhtVaxuTZBbR6xiRMpoQKlgQ6JfRZ5cQHFGN6dOMqFOM5lMM6tPMmZBNCYlJS8mIywlJCglJC8mJCMhIf////64+awAAAAadFJOU1SosLCwokSyl7ugup+6n7ugr5RLlJmYmZA8Hg7dEgAAAAFiS0dEPklkAOMAAAAHdElNRQfpDBESHCL8f1a2AAAAUElEQVQI12NgYGRiYmZhZWNgl5KWkZWT52DgVFBUUlZR5WLgVlPX0NTS5mHg1dHV0zcw5GPgNzI2MTUzF2AQtLC0sraxFWIQFhEVExOXkAQA4WIHfGNBCckAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjUtMTItMTdUMTg6Mjg6MjgrMDA6MDDR5B2HAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI1LTEyLTE3VDE4OjI4OjI4KzAwOjAwoLmlOwAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNS0xMi0xN1QxODoyODozNCswMDowMPym7g4AAAAASUVORK5CYII='
|
|
17
19
|
sl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA/ElEQVR4nE3PrUpDYRzH8d/z5tnRozugImIYgjAwGY5egGUG64JRkxgWvIFV0zCIwVsQLLYhWgSDLizJiowVFUHZdJ7zvP7Ftu8NfPgybOwvImcFet0C6FhMtrYTSQg1Ru/id3W7sfTxmc3rQpeE4gk8BZJiigF1kWYLe9rSGZEvR4o/AvRAxBLB8SObzXVqXb/tBjFdJjOCtliJI/U6fDo/CQSwf4ozIM2OGrm2xyGEClQCReO76tZmTabZYcsHmnHOfSvJ+8axCiNtlJDtztdNkLmxbViyEIx7669YxPPlZG44uD99wXs9ltqNbvF8aSbvBgBH9WAWMZX+AJIYacQLryqFAAAAAElFTkSuQmCC'
|
|
18
20
|
wd = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAA90lEQVR4nC3OsS5DUQAG4P8/Pb2kiS4mliaEkMYgTBiQiMVk6C6RsHmAxuoFbHTzCmIR9QSWLko6kIiQCnqHq+fec84vEt8TfMS/5s3jniFf36uD9sTH6Fg9rQ8aDQY2r7trhJmFUY1kW9I4gF0I9wGuZUOM04x+B4o9EvMSZ0D1EVWYkklsnn51TFIOhJ2DwgaN6QiqgsbRh00rseu9J1WsUngGOBmhSvaZnZwdbA1MkWfrwQ2PvXMvwbk7n7taLPKppFpe+cvb8DN8gi09RGmkbEv9GHQLqQZi+bB19WZDdN+WlYskRe/0aNsBaO+fXy4ZxEWKC7/R+XkmFbstdAAAAABJRU5ErkJggg=='
|