quasarr 0.1.6__py3-none-any.whl → 1.23.0__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/__init__.py +316 -42
- quasarr/api/__init__.py +187 -0
- quasarr/api/arr/__init__.py +387 -0
- quasarr/api/captcha/__init__.py +1189 -0
- quasarr/api/config/__init__.py +23 -0
- quasarr/api/sponsors_helper/__init__.py +166 -0
- quasarr/api/statistics/__init__.py +196 -0
- quasarr/downloads/__init__.py +319 -256
- quasarr/downloads/linkcrypters/__init__.py +0 -0
- quasarr/downloads/linkcrypters/al.py +237 -0
- quasarr/downloads/linkcrypters/filecrypt.py +444 -0
- quasarr/downloads/linkcrypters/hide.py +123 -0
- quasarr/downloads/packages/__init__.py +476 -0
- quasarr/downloads/sources/al.py +697 -0
- quasarr/downloads/sources/by.py +106 -0
- quasarr/downloads/sources/dd.py +76 -0
- quasarr/downloads/sources/dj.py +7 -0
- quasarr/downloads/sources/dl.py +199 -0
- quasarr/downloads/sources/dt.py +66 -0
- quasarr/downloads/sources/dw.py +14 -7
- quasarr/downloads/sources/he.py +112 -0
- quasarr/downloads/sources/mb.py +47 -0
- quasarr/downloads/sources/nk.py +54 -0
- quasarr/downloads/sources/nx.py +42 -83
- quasarr/downloads/sources/sf.py +159 -0
- quasarr/downloads/sources/sj.py +7 -0
- quasarr/downloads/sources/sl.py +90 -0
- quasarr/downloads/sources/wd.py +110 -0
- quasarr/downloads/sources/wx.py +127 -0
- quasarr/providers/cloudflare.py +204 -0
- quasarr/providers/html_images.py +22 -0
- quasarr/providers/html_templates.py +211 -104
- quasarr/providers/imdb_metadata.py +108 -3
- quasarr/providers/log.py +19 -0
- quasarr/providers/myjd_api.py +201 -40
- quasarr/providers/notifications.py +99 -11
- quasarr/providers/obfuscated.py +65 -0
- quasarr/providers/sessions/__init__.py +0 -0
- quasarr/providers/sessions/al.py +286 -0
- quasarr/providers/sessions/dd.py +78 -0
- quasarr/providers/sessions/dl.py +175 -0
- quasarr/providers/sessions/nx.py +76 -0
- quasarr/providers/shared_state.py +656 -79
- quasarr/providers/statistics.py +154 -0
- quasarr/providers/version.py +60 -1
- quasarr/providers/web_server.py +1 -1
- quasarr/search/__init__.py +144 -15
- quasarr/search/sources/al.py +448 -0
- quasarr/search/sources/by.py +204 -0
- quasarr/search/sources/dd.py +135 -0
- quasarr/search/sources/dj.py +213 -0
- quasarr/search/sources/dl.py +354 -0
- quasarr/search/sources/dt.py +265 -0
- quasarr/search/sources/dw.py +94 -67
- quasarr/search/sources/fx.py +89 -33
- quasarr/search/sources/he.py +196 -0
- quasarr/search/sources/mb.py +195 -0
- quasarr/search/sources/nk.py +188 -0
- quasarr/search/sources/nx.py +75 -21
- quasarr/search/sources/sf.py +374 -0
- quasarr/search/sources/sj.py +213 -0
- quasarr/search/sources/sl.py +246 -0
- quasarr/search/sources/wd.py +208 -0
- quasarr/search/sources/wx.py +337 -0
- quasarr/storage/config.py +39 -10
- quasarr/storage/setup.py +269 -97
- quasarr/storage/sqlite_database.py +6 -1
- quasarr-1.23.0.dist-info/METADATA +306 -0
- quasarr-1.23.0.dist-info/RECORD +77 -0
- {quasarr-0.1.6.dist-info → quasarr-1.23.0.dist-info}/WHEEL +1 -1
- quasarr/arr/__init__.py +0 -423
- quasarr/captcha_solver/__init__.py +0 -284
- quasarr-0.1.6.dist-info/METADATA +0 -81
- quasarr-0.1.6.dist-info/RECORD +0 -31
- {quasarr-0.1.6.dist-info → quasarr-1.23.0.dist-info}/entry_points.txt +0 -0
- {quasarr-0.1.6.dist-info → quasarr-1.23.0.dist-info/licenses}/LICENSE +0 -0
- {quasarr-0.1.6.dist-info → quasarr-1.23.0.dist-info}/top_level.txt +0 -0
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
# Quasarr
|
|
3
|
-
# Project by https://github.com/rix1337
|
|
4
|
-
|
|
5
|
-
import base64
|
|
6
|
-
import json
|
|
7
|
-
import random
|
|
8
|
-
import re
|
|
9
|
-
import xml.dom.minidom
|
|
10
|
-
from urllib.parse import urlparse
|
|
11
|
-
|
|
12
|
-
import dukpy
|
|
13
|
-
import requests
|
|
14
|
-
from Cryptodome.Cipher import AES
|
|
15
|
-
from bs4 import BeautifulSoup
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class CNL:
|
|
19
|
-
def __init__(self, crypted_data):
|
|
20
|
-
self.crypted_data = crypted_data
|
|
21
|
-
|
|
22
|
-
def jk_eval(self, f_def):
|
|
23
|
-
js_code = f"""
|
|
24
|
-
{f_def}
|
|
25
|
-
f();
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
result = dukpy.evaljs(js_code).strip()
|
|
29
|
-
|
|
30
|
-
return result
|
|
31
|
-
|
|
32
|
-
def aes_decrypt(self, data, key):
|
|
33
|
-
try:
|
|
34
|
-
encrypted_data = base64.b64decode(data)
|
|
35
|
-
except Exception as e:
|
|
36
|
-
raise ValueError("Failed to decode base64 data") from e
|
|
37
|
-
|
|
38
|
-
try:
|
|
39
|
-
key_bytes = bytes.fromhex(key)
|
|
40
|
-
except Exception as e:
|
|
41
|
-
raise ValueError("Failed to convert key to bytes") from e
|
|
42
|
-
|
|
43
|
-
iv = key_bytes
|
|
44
|
-
cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
|
|
45
|
-
|
|
46
|
-
try:
|
|
47
|
-
decrypted_data = cipher.decrypt(encrypted_data)
|
|
48
|
-
except ValueError as e:
|
|
49
|
-
raise ValueError("Decryption failed") from e
|
|
50
|
-
|
|
51
|
-
try:
|
|
52
|
-
return decrypted_data.decode('utf-8').replace('\x00', '').replace('\x08', '')
|
|
53
|
-
except UnicodeDecodeError as e:
|
|
54
|
-
raise ValueError("Failed to decode decrypted data") from e
|
|
55
|
-
|
|
56
|
-
def decrypt(self):
|
|
57
|
-
crypted = self.crypted_data[2]
|
|
58
|
-
jk = "function f(){ return \'" + self.crypted_data[1] + "';}"
|
|
59
|
-
key = self.jk_eval(jk)
|
|
60
|
-
uncrypted = self.aes_decrypt(crypted, key)
|
|
61
|
-
urls = [result for result in uncrypted.split("\r\n") if len(result) > 0]
|
|
62
|
-
|
|
63
|
-
return urls
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class DLC:
|
|
67
|
-
def __init__(self, dlc_file):
|
|
68
|
-
global user_agent
|
|
69
|
-
self.data = dlc_file
|
|
70
|
-
self.KEY = b"cb99b5cbc24db398"
|
|
71
|
-
self.IV = b"9bc24cb995cb8db3"
|
|
72
|
-
self.API_URL = "http://service.jdownloader.org/dlcrypt/service.php?srcType=dlc&destType=pylo&data="
|
|
73
|
-
|
|
74
|
-
def parse_packages(self, start_node):
|
|
75
|
-
return [
|
|
76
|
-
(
|
|
77
|
-
base64.b64decode(node.getAttribute("name")).decode("utf-8"),
|
|
78
|
-
self.parse_links(node)
|
|
79
|
-
)
|
|
80
|
-
for node in start_node.getElementsByTagName("package")
|
|
81
|
-
]
|
|
82
|
-
|
|
83
|
-
def parse_links(self, start_node):
|
|
84
|
-
return [
|
|
85
|
-
base64.b64decode(node.getElementsByTagName("url")[0].firstChild.data).decode("utf-8")
|
|
86
|
-
for node in start_node.getElementsByTagName("file")
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
def decrypt(self):
|
|
90
|
-
if not isinstance(self.data, bytes):
|
|
91
|
-
raise TypeError("data must be bytes.")
|
|
92
|
-
|
|
93
|
-
all_urls = []
|
|
94
|
-
|
|
95
|
-
try:
|
|
96
|
-
data = self.data.strip()
|
|
97
|
-
|
|
98
|
-
data += b"=" * (-len(data) % 4)
|
|
99
|
-
|
|
100
|
-
dlc_key = data[-88:].decode("utf-8")
|
|
101
|
-
dlc_data = base64.b64decode(data[:-88])
|
|
102
|
-
dlc_content = requests.get(self.API_URL + dlc_key).content.decode("utf-8")
|
|
103
|
-
|
|
104
|
-
rc = base64.b64decode(re.search(r"<rc>(.+)</rc>", dlc_content, re.S).group(1))[:16]
|
|
105
|
-
|
|
106
|
-
cipher = AES.new(self.KEY, AES.MODE_CBC, self.IV)
|
|
107
|
-
key = iv = cipher.decrypt(rc)
|
|
108
|
-
|
|
109
|
-
cipher = AES.new(key, AES.MODE_CBC, iv)
|
|
110
|
-
xml_data = base64.b64decode(cipher.decrypt(dlc_data)).decode("utf-8")
|
|
111
|
-
|
|
112
|
-
root = xml.dom.minidom.parseString(xml_data).documentElement
|
|
113
|
-
content_node = root.getElementsByTagName("content")[0]
|
|
114
|
-
|
|
115
|
-
packages = self.parse_packages(content_node)
|
|
116
|
-
|
|
117
|
-
for package in packages:
|
|
118
|
-
urls = package[1]
|
|
119
|
-
all_urls.extend(urls)
|
|
120
|
-
|
|
121
|
-
except Exception as e:
|
|
122
|
-
print("DLC Error: " + str(e))
|
|
123
|
-
return None
|
|
124
|
-
|
|
125
|
-
return all_urls
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
def get_filecrypt_links(shared_state, token, title, url, password=None):
|
|
129
|
-
print("Attempting to decrypt Filecrypt link: " + url)
|
|
130
|
-
session = requests.Session()
|
|
131
|
-
|
|
132
|
-
password_field = None
|
|
133
|
-
if password:
|
|
134
|
-
try:
|
|
135
|
-
output = requests.get(url, headers={'User-Agent': shared_state.values["user_agent"]})
|
|
136
|
-
soup = BeautifulSoup(output.text, 'html.parser')
|
|
137
|
-
input_element = soup.find('input', placeholder=lambda value: value and 'password' in value.lower())
|
|
138
|
-
password_field = input_element['name']
|
|
139
|
-
print("Password field name identified: " + password_field)
|
|
140
|
-
url = output.url
|
|
141
|
-
except:
|
|
142
|
-
print("No password field found. Skipping password entry!")
|
|
143
|
-
|
|
144
|
-
if password and password_field:
|
|
145
|
-
print("Using Password: " + password)
|
|
146
|
-
output = session.post(url, data=password_field + "=" + password,
|
|
147
|
-
headers={'User-Agent': shared_state.values["user_agent"],
|
|
148
|
-
'Content-Type': 'application/x-www-form-urlencoded'})
|
|
149
|
-
else:
|
|
150
|
-
output = session.get(url, headers={'User-Agent': shared_state.values["user_agent"]})
|
|
151
|
-
|
|
152
|
-
url = output.url
|
|
153
|
-
soup = BeautifulSoup(output.text, 'html.parser')
|
|
154
|
-
if bool(soup.findAll("input", {"id": "p4assw0rt"})):
|
|
155
|
-
print(f"Password was wrong or missing. Could not get links for {title}")
|
|
156
|
-
return False
|
|
157
|
-
|
|
158
|
-
no_captcha_present = bool(soup.find("form", {"class": "cnlform"}))
|
|
159
|
-
if no_captcha_present:
|
|
160
|
-
print("No CAPTCHA present. Skipping token!")
|
|
161
|
-
else:
|
|
162
|
-
circle_captcha = bool(soup.findAll("div", {"class": "circle_captcha"}))
|
|
163
|
-
i = 0
|
|
164
|
-
while circle_captcha and i < 3:
|
|
165
|
-
print("Sending Fake solution to skip Circle-CAPTCHA...")
|
|
166
|
-
random_x = str(random.randint(100, 200))
|
|
167
|
-
random_y = str(random.randint(100, 200))
|
|
168
|
-
output = session.post(url, data="buttonx.x=" + random_x + "&buttonx.y=" + random_y,
|
|
169
|
-
headers={'User-Agent': shared_state.values["user_agent"],
|
|
170
|
-
'Content-Type': 'application/x-www-form-urlencoded'})
|
|
171
|
-
url = output.url
|
|
172
|
-
soup = BeautifulSoup(output.text, 'html.parser')
|
|
173
|
-
circle_captcha = bool(soup.findAll("div", {"class": "circle_captcha"}))
|
|
174
|
-
|
|
175
|
-
output = session.post(url, data="cap_token=" + token, headers={'User-Agent': shared_state.values["user_agent"],
|
|
176
|
-
'Content-Type': 'application/x-www-form-urlencoded'})
|
|
177
|
-
url = output.url
|
|
178
|
-
soup = BeautifulSoup(output.text, 'html.parser')
|
|
179
|
-
|
|
180
|
-
solved = bool(soup.findAll("div", {"class": "container"}))
|
|
181
|
-
if not solved:
|
|
182
|
-
print(f"Filecrypt did did not accept the token! Could not get links for {title}")
|
|
183
|
-
return False
|
|
184
|
-
else:
|
|
185
|
-
season_number = ""
|
|
186
|
-
episode_number = ""
|
|
187
|
-
episode_in_title = re.findall(r'.*\.s(\d{1,3})e(\d{1,3})\..*', title, re.IGNORECASE)
|
|
188
|
-
season_in_title = re.findall(r'.*\.s(\d{1,3})\..*', title, re.IGNORECASE)
|
|
189
|
-
if episode_in_title:
|
|
190
|
-
try:
|
|
191
|
-
season_number = str(int(episode_in_title[0][0]))
|
|
192
|
-
episode_number = str(int(episode_in_title[0][1]))
|
|
193
|
-
except:
|
|
194
|
-
pass
|
|
195
|
-
elif season_in_title:
|
|
196
|
-
try:
|
|
197
|
-
season_number = str(int(season_in_title[0]))
|
|
198
|
-
except:
|
|
199
|
-
pass
|
|
200
|
-
|
|
201
|
-
season = ""
|
|
202
|
-
episode = ""
|
|
203
|
-
tv_show_selector = soup.find("div", {"class": "dlpart"})
|
|
204
|
-
if tv_show_selector:
|
|
205
|
-
|
|
206
|
-
season = "season="
|
|
207
|
-
episode = "episode="
|
|
208
|
-
|
|
209
|
-
season_selection = soup.find("div", {"id": "selbox_season"})
|
|
210
|
-
try:
|
|
211
|
-
if season_selection:
|
|
212
|
-
season += str(season_number)
|
|
213
|
-
except:
|
|
214
|
-
pass
|
|
215
|
-
|
|
216
|
-
episode_selection = soup.find("div", {"id": "selbox_episode"})
|
|
217
|
-
try:
|
|
218
|
-
if episode_selection:
|
|
219
|
-
episode += str(episode_number)
|
|
220
|
-
except:
|
|
221
|
-
pass
|
|
222
|
-
|
|
223
|
-
links = []
|
|
224
|
-
|
|
225
|
-
mirrors = []
|
|
226
|
-
mirrors_available = soup.select("a[href*=mirror]")
|
|
227
|
-
if mirrors_available:
|
|
228
|
-
for mirror in mirrors_available:
|
|
229
|
-
try:
|
|
230
|
-
mirror_query = mirror.get("href").split("?")[1]
|
|
231
|
-
base_url = url.split("?")[0] if "mirror" in url else url
|
|
232
|
-
mirrors.append(f"{base_url}?{mirror_query}")
|
|
233
|
-
except IndexError:
|
|
234
|
-
continue
|
|
235
|
-
else:
|
|
236
|
-
mirrors = [url]
|
|
237
|
-
|
|
238
|
-
for mirror in mirrors:
|
|
239
|
-
if not len(mirrors) == 1:
|
|
240
|
-
output = session.get(mirror, headers={'User-Agent': shared_state.values["user_agent"]})
|
|
241
|
-
url = output.url
|
|
242
|
-
soup = BeautifulSoup(output.text, 'html.parser')
|
|
243
|
-
|
|
244
|
-
try:
|
|
245
|
-
crypted_payload = soup.find("form", {"class": "cnlform"}).get('onsubmit')
|
|
246
|
-
crypted_data = re.findall(r"'(.*?)'", crypted_payload)
|
|
247
|
-
if not title:
|
|
248
|
-
title = crypted_data[3]
|
|
249
|
-
crypted_data = [
|
|
250
|
-
crypted_data[0],
|
|
251
|
-
crypted_data[1],
|
|
252
|
-
crypted_data[2],
|
|
253
|
-
title
|
|
254
|
-
]
|
|
255
|
-
if episode and season:
|
|
256
|
-
domain = urlparse(url).netloc
|
|
257
|
-
filtered_cnl_secret = soup.find("input", {"name": "hidden_cnl_id"}).attrs["value"]
|
|
258
|
-
filtered_cnl_link = f"https://{domain}/_CNL/{filtered_cnl_secret}.html?{season}&{episode}"
|
|
259
|
-
filtered_cnl_result = session.post(filtered_cnl_link,
|
|
260
|
-
headers={'User-Agent': shared_state.values["user_agent"]})
|
|
261
|
-
if filtered_cnl_result.status_code == 200:
|
|
262
|
-
filtered_cnl_data = json.loads(filtered_cnl_result.text)
|
|
263
|
-
if filtered_cnl_data["success"]:
|
|
264
|
-
crypted_data = [
|
|
265
|
-
crypted_data[0],
|
|
266
|
-
filtered_cnl_data["data"][0],
|
|
267
|
-
filtered_cnl_data["data"][1],
|
|
268
|
-
title
|
|
269
|
-
]
|
|
270
|
-
links.extend(CNL(crypted_data).decrypt())
|
|
271
|
-
except:
|
|
272
|
-
print("Click'n'Load not found! Falling back to DLC...")
|
|
273
|
-
crypted_payload = soup.find("button", {"class": "dlcdownload"}).get("onclick")
|
|
274
|
-
crypted_data = re.findall(r"'(.*?)'", crypted_payload)
|
|
275
|
-
dlc_secret = crypted_data[0]
|
|
276
|
-
domain = urlparse(url).netloc
|
|
277
|
-
if episode and season:
|
|
278
|
-
dlc_link = f"https://{domain}/DLC/{dlc_secret}.dlc?{episode}&{season}"
|
|
279
|
-
else:
|
|
280
|
-
dlc_link = f"https://{domain}/DLC/{dlc_secret}.dlc"
|
|
281
|
-
dlc_file = session.get(dlc_link, headers={'User-Agent': shared_state.values["user_agent"]}).content
|
|
282
|
-
links.extend(DLC(dlc_file).decrypt())
|
|
283
|
-
|
|
284
|
-
return links
|
quasarr-0.1.6.dist-info/METADATA
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: quasarr
|
|
3
|
-
Version: 0.1.6
|
|
4
|
-
Summary: Full template for python web projects with Docker, GitHub Actions, PyPI, and more.
|
|
5
|
-
Home-page: https://github.com/rix1337/Quasarr
|
|
6
|
-
Author: rix1337
|
|
7
|
-
Author-email:
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Requires-Dist: beautifulsoup4==4.12.3
|
|
14
|
-
Requires-Dist: bottle==0.12.25
|
|
15
|
-
Requires-Dist: dukpy==0.4.0
|
|
16
|
-
Requires-Dist: pycryptodomex==3.20.0
|
|
17
|
-
Requires-Dist: requests==2.32.3
|
|
18
|
-
|
|
19
|
-
# Quasarr
|
|
20
|
-
|
|
21
|
-
<img src="https://raw.githubusercontent.com/rix1337/Quasarr/main/Quasarr.png" data-canonical-src="https://raw.githubusercontent.com/rix1337/Quasarr/main/Quasarr.png" width="64" height="64" />
|
|
22
|
-
|
|
23
|
-
Quasarr is a Bridge to use JDownloader in Radarr and (later also) Sonarr.
|
|
24
|
-
|
|
25
|
-
[](https://badge.fury.io/py/quasarr)
|
|
26
|
-
[](https://github.com/users/rix1337/sponsorship)
|
|
27
|
-
|
|
28
|
-
Quasarr poses as a Newznab Indexer and a SABnzbd client.
|
|
29
|
-
It will thus never work in parallel with a real NZB indexer and download client set up.
|
|
30
|
-
Torrents are unaffected.
|
|
31
|
-
|
|
32
|
-
Quasarr includes a solution to quickly and easily decrypt protected links.
|
|
33
|
-
Just follow the link from the console output (or discord notification) and solve the CAPTCHA.
|
|
34
|
-
Quasarr will confidently handle the rest.
|
|
35
|
-
|
|
36
|
-
**Warning: this project is still in the proof-of-concept stage.
|
|
37
|
-
It is only tested with Radarr and the three currently supported hostnames.**
|
|
38
|
-
|
|
39
|
-
# Instructions
|
|
40
|
-
|
|
41
|
-
* Follow instructions to set up at least one hostname for Quasarr
|
|
42
|
-
* Provide your [MyJDownloader credentials](https://my.jdownloader.org)
|
|
43
|
-
* Set up Quasarr's URL as 'Newznab Indexer' and 'SABnzbd Download Client' in Sonarr/Radarr.
|
|
44
|
-
* Leave settings at default
|
|
45
|
-
* Use this API key: `quasarr`
|
|
46
|
-
* As with other download clients, you must ensure the download path used by JDownloader is accessible to *arr.
|
|
47
|
-
|
|
48
|
-
# Setup
|
|
49
|
-
|
|
50
|
-
`pip install quasarr`
|
|
51
|
-
|
|
52
|
-
* Requires Python 3.12 or later
|
|
53
|
-
|
|
54
|
-
# Run
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
quasarr
|
|
58
|
-
--port=8080
|
|
59
|
-
--discord=https://discord.com/api/webhooks/1234567890/ABCDEFGHIJKLMN
|
|
60
|
-
--external_address=http://foo.bar/
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
* `--discord` must be a valid Discord Webhook URL and is optional.
|
|
64
|
-
* `--external_address` is used in Discord notifications and is optional.
|
|
65
|
-
|
|
66
|
-
# Docker
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
docker run -d \
|
|
70
|
-
--name="Quasarr" \
|
|
71
|
-
-p port:8080 \
|
|
72
|
-
-v /path/to/config/:/config:rw \
|
|
73
|
-
-e 'INTERNAL_ADDRESS'='http://192.168.0.1:8080' \
|
|
74
|
-
-e 'EXTERNAL_ADDRESS'='http://foo.bar/' \
|
|
75
|
-
-e 'DISCORD'='https://discord.com/api/webhooks/1234567890/ABCDEFGHIJKLMN' \
|
|
76
|
-
rix1337/docker-quasarr:latest
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
* `INTERNAL_ADDRESS` is required so Radarr/Sonarr can reach Quasarr. **Must** include port!
|
|
80
|
-
* `EXTERNAL_ADDRESS` is optional and used in Discord notifications.
|
|
81
|
-
* `DISCORD` is optional and must be a valid Discord Webhook URL.
|
quasarr-0.1.6.dist-info/RECORD
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
quasarr/__init__.py,sha256=dA9ChjAr-rCMGruOOMw2SSMkhE45H0bTbxaNBf3lqy8,7153
|
|
2
|
-
quasarr/arr/__init__.py,sha256=0JdXIXT6rm623feYE9CwKyPo-vbPlXeOkYpupSsHBzY,17708
|
|
3
|
-
quasarr/captcha_solver/__init__.py,sha256=P0DTvDXPueQs_eAhQb9cSZnaZLfP_-wjopikln9-etM,10783
|
|
4
|
-
quasarr/downloads/__init__.py,sha256=42aOQmGXam38ulUPIlxZLA2nVQ1h6PPTJ2z5Ykf-CXk,10336
|
|
5
|
-
quasarr/downloads/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
quasarr/downloads/sources/dw.py,sha256=GE1x9lDME_Uaxrjef9mFj-DKJd3uS2ws1ttNbtvLqzc,2057
|
|
7
|
-
quasarr/downloads/sources/nx.py,sha256=Tcb9fi-r36Bdh7Ky1cMujRLJAOQ9VGzNMjRhvupuCB4,4834
|
|
8
|
-
quasarr/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
quasarr/providers/html_templates.py,sha256=wnce3vGoZq0lZpxE5AEtjTL8t6A007OZCQL7D46XO6Q,4587
|
|
10
|
-
quasarr/providers/imdb_metadata.py,sha256=AKn9ob22LpbAQAVVO7Uoxk9bwrqAgmEwEug8yOGxBi8,970
|
|
11
|
-
quasarr/providers/myjd_api.py,sha256=yDnaL3MTrstTPBwQOrki9in7BsFuATu8VnJ-XiSOrbw,28552
|
|
12
|
-
quasarr/providers/notifications.py,sha256=zC87QuIewHVClRH9d3pVn8XJfqFO6eSM4iwGliiDVlU,1049
|
|
13
|
-
quasarr/providers/obfuscated.py,sha256=XfiEblJizqixUoA4MIsillr5Nh1dwFqCgLvBQWM7Lwo,193865
|
|
14
|
-
quasarr/providers/shared_state.py,sha256=rNCvLFF9qP0UAYSCImGPI6tcCUanKJFuQYECLJQdxlY,7924
|
|
15
|
-
quasarr/providers/version.py,sha256=wfbOt1e-0KxktMEluyI9POzZqqfpjU6J2RNS7Zh0DEI,2186
|
|
16
|
-
quasarr/providers/web_server.py,sha256=wc2enK8pWUocSgoA_5RXx8pCekBwMMf6z3fjyG71Osc,1389
|
|
17
|
-
quasarr/search/__init__.py,sha256=ce9YKpOQMotRdCegNF-w_3W-cQdhnFIbyWXWAwMzBtI,1110
|
|
18
|
-
quasarr/search/sources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
-
quasarr/search/sources/dw.py,sha256=4Uyp8ngU-41EnQqKRGcNy--6hWvdIeQqpayLsopVwHE,6372
|
|
20
|
-
quasarr/search/sources/fx.py,sha256=AbfgJHAhoFvxqK45jckDbAoBjexlL8eqsRRxgQwo4JU,6129
|
|
21
|
-
quasarr/search/sources/nx.py,sha256=da3_cPD_yKn5fa0lGiFeWTiVAbsj92qhEeE4jbRqul8,4329
|
|
22
|
-
quasarr/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
quasarr/storage/config.py,sha256=JneX7stV8dgdEuMAGHo9Es4CRhheuTbOWFlx69scgAA,5493
|
|
24
|
-
quasarr/storage/setup.py,sha256=qr_DKqvqv_WoAv6DGQllAxFGeqVGzWFXaoLg2JF14Ss,11108
|
|
25
|
-
quasarr/storage/sqlite_database.py,sha256=u-tU2dJV_vQQfGUlxKpl_HSSVFvHDYF48Yq9aAkNCKo,3436
|
|
26
|
-
quasarr-0.1.6.dist-info/LICENSE,sha256=QQFCAfDgt7lSA8oSWDHIZ9aTjFbZaBJdjnGOHkuhK7k,1060
|
|
27
|
-
quasarr-0.1.6.dist-info/METADATA,sha256=Tt-QWjWDh47454pYeAQEC6x0xWWqYxYzd857mAe4oLw,2927
|
|
28
|
-
quasarr-0.1.6.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
|
29
|
-
quasarr-0.1.6.dist-info/entry_points.txt,sha256=gXi8mUKsIqKVvn-bOc8E5f04sK_KoMCC-ty6b2Hf-jc,40
|
|
30
|
-
quasarr-0.1.6.dist-info/top_level.txt,sha256=dipJdaRda5ruTZkoGfZU60bY4l9dtPlmOWwxK_oGSF0,8
|
|
31
|
-
quasarr-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|