update readme, fix setup.js setting toggle

This commit is contained in:
Harvey Tindall 2020-08-02 02:33:34 +01:00
parent f2966ef810
commit d5609f3870
6 changed files with 83 additions and 73 deletions

View File

@ -1,5 +1,7 @@
# ![jellyfin-accounts](https://raw.githubusercontent.com/hrfee/jellyfin-accounts/bs5/images/jellyfin-accounts-banner-wide.svg) # ![jellyfin-accounts](https://raw.githubusercontent.com/hrfee/jellyfin-accounts/bs5/images/jellyfin-accounts-banner-wide.svg)
#### 👀 ➡️: Have a look at [jfa-go](https://github.com/hrfee/jfa-go), an attempted rewrite in Go. Identical look and features but might be faster.
A basic account management system for [Jellyfin](https://github.com/jellyfin/jellyfin). A basic account management system for [Jellyfin](https://github.com/jellyfin/jellyfin).
* Provides a web interface for creating/sending invites * Provides a web interface for creating/sending invites
* Sends out emails when a user requests a password reset * Sends out emails when a user requests a password reset

View File

@ -98,7 +98,8 @@ config = Config(config_path, secrets.token_urlsafe(16), data_dir, local_dir, log
web_log = create_log("waitress") web_log = create_log("waitress")
if not first_run: if not first_run:
email_log = create_log("emails") email_log = create_log("email")
pwr_log = create_log("pwr")
auth_log = create_log("auth") auth_log = create_log("auth")
if args.host is not None: if args.host is not None:
@ -185,6 +186,7 @@ def resp(success=True, code=500):
r.status_code = code r.status_code = code
return r return r
app = Flask(__name__, root_path=str(local_dir))
def main(): def main():
if args.install: if args.install:
@ -290,8 +292,6 @@ def main():
success = True success = True
else: else:
global app
app = Flask(__name__, root_path=str(local_dir))
app.config["DEBUG"] = config.getboolean("ui", "debug") app.config["DEBUG"] = config.getboolean("ui", "debug")
app.config["SECRET_KEY"] = secrets.token_urlsafe(16) app.config["SECRET_KEY"] = secrets.token_urlsafe(16)
app.config["JSON_SORT_KEYS"] = False app.config["JSON_SORT_KEYS"] = False
@ -328,7 +328,7 @@ def main():
jellyfin_accounts.pw_reset.start() jellyfin_accounts.pw_reset.start()
pwr = threading.Thread(target=start_pwr, daemon=True) pwr = threading.Thread(target=start_pwr, daemon=True)
log.info("Starting email thread") log.info("Starting password reset thread")
pwr.start() pwr.start()
def signal_handler(sig, frame): def signal_handler(sig, frame):

View File

@ -21,16 +21,19 @@ function checkEmailRadio() {
document.getElementById('emailCommonArea').style.display = ''; document.getElementById('emailCommonArea').style.display = '';
document.getElementById('emailSMTPArea').style.display = ''; document.getElementById('emailSMTPArea').style.display = '';
document.getElementById('emailMailgunArea').style.display = 'none'; document.getElementById('emailMailgunArea').style.display = 'none';
document.getElementById('notificationsEnabled').checked = true;
} else if (document.getElementById('emailMailgunRadio').checked) { } else if (document.getElementById('emailMailgunRadio').checked) {
document.getElementById('emailCommonArea').style.display = ''; document.getElementById('emailCommonArea').style.display = '';
document.getElementById('emailSMTPArea').style.display = 'none'; document.getElementById('emailSMTPArea').style.display = 'none';
document.getElementById('emailMailgunArea').style.display = ''; document.getElementById('emailMailgunArea').style.display = '';
document.getElementById('notificationsEnabled').checked = true;
} else if (document.getElementById('emailDisabledRadio').checked) { } else if (document.getElementById('emailDisabledRadio').checked) {
document.getElementById('emailCommonArea').style.display = 'none'; document.getElementById('emailCommonArea').style.display = 'none';
document.getElementById('emailSMTPArea').style.display = 'none'; document.getElementById('emailSMTPArea').style.display = 'none';
document.getElementById('emailMailgunArea').style.display = 'none'; document.getElementById('emailMailgunArea').style.display = 'none';
document.getElementById('emailNextButton').href = '#page-8'; document.getElementById('emailNextButton').href = '#page-8';
document.getElementById('valBackButton').href = '#page-4'; document.getElementById('valBackButton').href = '#page-4';
document.getElementById('notificationsEnabled').checked = false;
}; };
}; };
var emailRadios = ['emailDisabledRadio', 'emailSMTPRadio', 'emailMailgunRadio']; var emailRadios = ['emailDisabledRadio', 'emailSMTPRadio', 'emailMailgunRadio'];
@ -165,6 +168,7 @@ document.getElementById('submitButton').onclick = function() {
if (document.getElementById('emailDisabledRadio').checked) { if (document.getElementById('emailDisabledRadio').checked) {
config['password_resets']['enabled'] = 'false'; config['password_resets']['enabled'] = 'false';
config['invite_emails']['enabled'] = 'false'; config['invite_emails']['enabled'] = 'false';
config['notificatons']['enabled'] = 'false';
} else { } else {
if (document.getElementById('emailSMTPRadio').checked) { if (document.getElementById('emailSMTPRadio').checked) {
if (document.getElementById('emailSSL_TLS').checked) { if (document.getElementById('emailSSL_TLS').checked) {

View File

@ -61,6 +61,7 @@ class Jellyfin:
self.version = version self.version = version
self.device = device self.device = device
self.deviceId = deviceId self.deviceId = deviceId
self.authenticated = False
self.timeout = cacheMinutes * 60 self.timeout = cacheMinutes * 60
self.userCacheAge = time.time() - self.timeout - 1 self.userCacheAge = time.time() - self.timeout - 1
self.userCachePublicAge = self.userCacheAge self.userCachePublicAge = self.userCacheAge
@ -80,7 +81,7 @@ class Jellyfin:
"X-Emby-Authorization": self.auth, "X-Emby-Authorization": self.auth,
} }
try: try:
self.info = requests.get(self.server + "/System/Info/Public").json() self.info = requests.get(f"{self.server}/System/Info/Public").json()
except: except:
pass pass
@ -107,7 +108,7 @@ class Jellyfin:
""" """
if public is True: if public is True:
if (time.time() - self.userCachePublicAge) >= self.timeout: if (time.time() - self.userCachePublicAge) >= self.timeout:
response = requests.get(self.server + "/emby/Users/Public").json() response = requests.get(f"{self.server}/Users/Public").json()
self.userCachePublic = response self.userCachePublic = response
self.userCachePublicAge = time.time() self.userCachePublicAge = time.time()
else: else:
@ -117,7 +118,7 @@ class Jellyfin:
): ):
if (time.time() - self.userCacheAge) >= self.timeout: if (time.time() - self.userCacheAge) >= self.timeout:
response = requests.get( response = requests.get(
self.server + "/emby/Users", f"{self.server}/Users",
headers=self.header, headers=self.header,
params={"Username": self.username, "Pw": self.password}, params={"Username": self.username, "Pw": self.password},
) )
@ -125,7 +126,7 @@ class Jellyfin:
response = response.json() response = response.json()
self.userCache = response self.userCache = response
self.userCacheAge = time.time() self.userCacheAge = time.time()
else: elif response.status_code == 401:
try: try:
self.authenticate(self.username, self.password) self.authenticate(self.username, self.password)
return self.getUsers(username, userId, public) return self.getUsers(username, userId, public)
@ -161,12 +162,10 @@ class Jellyfin:
:param username: Plaintext username. :param username: Plaintext username.
:param password: Plaintext password. :param password: Plaintext password.
""" """
self.username = username
self.password = password
response = requests.post( response = requests.post(
self.server + "/emby/Users/AuthenticateByName", f"{self.server}/Users/AuthenticateByName",
headers=self.header, headers=self.header,
params={"Username": self.username, "Pw": self.password}, params={"Username": username, "Pw": password},
) )
if response.status_code == 200: if response.status_code == 200:
json = response.json() json = response.json()
@ -180,8 +179,11 @@ class Jellyfin:
self.auth += f", Token={self.accessToken}" self.auth += f", Token={self.accessToken}"
self.header["X-Emby-Authorization"] = self.auth self.header["X-Emby-Authorization"] = self.auth
self.info = requests.get( self.info = requests.get(
self.server + "/System/Info", headers=self.header f"{self.server}/System/Info", headers=self.header
).json() ).json()
self.username = username
self.password = password
self.authenticated = True
return True return True
else: else:
raise self.AuthenticationError raise self.AuthenticationError
@ -194,7 +196,7 @@ class Jellyfin:
:param policy: User policy in dictionary form. :param policy: User policy in dictionary form.
""" """
return requests.post( return requests.post(
self.server + "/Users/" + userId + "/Policy", f"{self.server}/Users/" + userId + "/Policy",
headers=self.header, headers=self.header,
params=policy, params=policy,
) )
@ -204,7 +206,7 @@ class Jellyfin:
if user["Name"] == username: if user["Name"] == username:
raise self.UserExistsError raise self.UserExistsError
response = requests.post( response = requests.post(
self.server + "/emby/Users/New", f"{self.server}/Users/New",
headers=self.header, headers=self.header,
params={"Name": username, "Password": password}, params={"Name": username, "Password": password},
) )
@ -222,7 +224,7 @@ class Jellyfin:
else: else:
param = "" param = ""
views = requests.get( views = requests.get(
self.server + "/Users/" + userId + "/Views" + param, headers=self.header f"{self.server}/Users/" + userId + "/Views" + param, headers=self.header
).json()["Items"] ).json()["Items"]
orderedViews = [] orderedViews = []
for library in views: for library in views:
@ -236,7 +238,7 @@ class Jellyfin:
:param configuration: Configuration to write in dictionary form. :param configuration: Configuration to write in dictionary form.
""" """
resp = requests.post( resp = requests.post(
self.server + "/Users/" + userId + "/Configuration", f"{self.server}/Users/" + userId + "/Configuration",
headers=self.header, headers=self.header,
params=configuration, params=configuration,
) )

View File

@ -6,7 +6,7 @@ from watchdog.events import FileSystemEventHandler
from jellyfin_accounts.email import Mailgun, Smtp from jellyfin_accounts.email import Mailgun, Smtp
from jellyfin_accounts.web_api import jf from jellyfin_accounts.web_api import jf
from jellyfin_accounts import config, data_store from jellyfin_accounts import config, data_store
from jellyfin_accounts import email_log as log from jellyfin_accounts import pwr_log as log
class Watcher: class Watcher:

110
poetry.lock generated
View File

@ -54,7 +54,7 @@ description = "Foreign Function Interface for Python calling C code."
name = "cffi" name = "cffi"
optional = false optional = false
python-versions = "*" python-versions = "*"
version = "1.14.0" version = "1.14.1"
[package.dependencies] [package.dependencies]
pycparser = "*" pycparser = "*"
@ -81,17 +81,18 @@ description = "cryptography is a package which provides cryptographic recipes an
name = "cryptography" name = "cryptography"
optional = false optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*"
version = "2.9.2" version = "3.0"
[package.dependencies] [package.dependencies]
cffi = ">=1.8,<1.11.3 || >1.11.3" cffi = ">=1.8,<1.11.3 || >1.11.3"
six = ">=1.4.1" six = ">=1.4.1"
[package.extras] [package.extras]
docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"] docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0,<3.1.0 || >3.1.0,<3.1.1 || >3.1.1)", "sphinx-rtd-theme"]
docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
idna = ["idna (>=2.1)"] idna = ["idna (>=2.1)"]
pep8test = ["flake8", "flake8-import-order", "pep8-naming"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"]
[[package]] [[package]]
@ -387,7 +388,7 @@ description = "HTTP library with thread-safe connection pooling, file post, and
name = "urllib3" name = "urllib3"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
version = "1.25.9" version = "1.25.10"
[package.extras] [package.extras]
brotli = ["brotlipy (>=0.6.0)"] brotli = ["brotlipy (>=0.6.0)"]
@ -434,6 +435,7 @@ watchdog = ["watchdog"]
[metadata] [metadata]
content-hash = "1c2741c9be187d9d0be662509fb4a87f5978e5f44420e5049a20504824c29a59" content-hash = "1c2741c9be187d9d0be662509fb4a87f5978e5f44420e5049a20504824c29a59"
lock-version = "1.0"
python-versions = "^3.6" python-versions = "^3.6"
[metadata.files] [metadata.files]
@ -454,34 +456,34 @@ certifi = [
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
] ]
cffi = [ cffi = [
{file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, {file = "cffi-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:66dd45eb9530e3dde8f7c009f84568bc7cac489b93d04ac86e3111fb46e470c2"},
{file = "cffi-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30"}, {file = "cffi-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:4f53e4128c81ca3212ff4cf097c797ab44646a40b42ec02a891155cd7a2ba4d8"},
{file = "cffi-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"}, {file = "cffi-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:833401b15de1bb92791d7b6fb353d4af60dc688eaa521bd97203dcd2d124a7c1"},
{file = "cffi-1.14.0-cp27-cp27m-win32.whl", hash = "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78"}, {file = "cffi-1.14.1-cp27-cp27m-win32.whl", hash = "sha256:26f33e8f6a70c255767e3c3f957ccafc7f1f706b966e110b855bfe944511f1f9"},
{file = "cffi-1.14.0-cp27-cp27m-win_amd64.whl", hash = "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793"}, {file = "cffi-1.14.1-cp27-cp27m-win_amd64.whl", hash = "sha256:b87dfa9f10a470eee7f24234a37d1d5f51e5f5fa9eeffda7c282e2b8f5162eb1"},
{file = "cffi-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e"}, {file = "cffi-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:effd2ba52cee4ceff1a77f20d2a9f9bf8d50353c854a282b8760ac15b9833168"},
{file = "cffi-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a"}, {file = "cffi-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bac0d6f7728a9cc3c1e06d4fcbac12aaa70e9379b3025b27ec1226f0e2d404cf"},
{file = "cffi-1.14.0-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff"}, {file = "cffi-1.14.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d6033b4ffa34ef70f0b8086fd4c3df4bf801fee485a8a7d4519399818351aa8e"},
{file = "cffi-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f"}, {file = "cffi-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8416ed88ddc057bab0526d4e4e9f3660f614ac2394b5e019a628cdfff3733849"},
{file = "cffi-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa"}, {file = "cffi-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:892daa86384994fdf4856cb43c93f40cbe80f7f95bb5da94971b39c7f54b3a9c"},
{file = "cffi-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5"}, {file = "cffi-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:c991112622baee0ae4d55c008380c32ecfd0ad417bcd0417ba432e6ba7328caa"},
{file = "cffi-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4"}, {file = "cffi-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fcf32bf76dc25e30ed793145a57426064520890d7c02866eb93d3e4abe516948"},
{file = "cffi-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d"}, {file = "cffi-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f960375e9823ae6a07072ff7f8a85954e5a6434f97869f50d0e41649a1c8144f"},
{file = "cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc"}, {file = "cffi-1.14.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a6d28e7f14ecf3b2ad67c4f106841218c8ab12a0683b1528534a6c87d2307af3"},
{file = "cffi-1.14.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac"}, {file = "cffi-1.14.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:cda422d54ee7905bfc53ee6915ab68fe7b230cacf581110df4272ee10462aadc"},
{file = "cffi-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f"}, {file = "cffi-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:4a03416915b82b81af5502459a8a9dd62a3c299b295dcdf470877cb948d655f2"},
{file = "cffi-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b"}, {file = "cffi-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:4ce1e995aeecf7cc32380bc11598bfdfa017d592259d5da00fc7ded11e61d022"},
{file = "cffi-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3"}, {file = "cffi-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e23cb7f1d8e0f93addf0cae3c5b6f00324cccb4a7949ee558d7b6ca973ab8ae9"},
{file = "cffi-1.14.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66"}, {file = "cffi-1.14.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ddff0b2bd7edcc8c82d1adde6dbbf5e60d57ce985402541cd2985c27f7bec2a0"},
{file = "cffi-1.14.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0"}, {file = "cffi-1.14.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f90c2267101010de42f7273c94a1f026e56cbc043f9330acd8a80e64300aba33"},
{file = "cffi-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f"}, {file = "cffi-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:3cd2c044517f38d1b577f05927fb9729d3396f1d44d0c659a445599e79519792"},
{file = "cffi-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26"}, {file = "cffi-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fa72a52a906425416f41738728268072d5acfd48cbe7796af07a923236bcf96"},
{file = "cffi-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd"}, {file = "cffi-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:267adcf6e68d77ba154334a3e4fc921b8e63cbb38ca00d33d40655d4228502bc"},
{file = "cffi-1.14.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55"}, {file = "cffi-1.14.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d3148b6ba3923c5850ea197a91a42683f946dba7e8eb82dfa211ab7e708de939"},
{file = "cffi-1.14.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2"}, {file = "cffi-1.14.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:98be759efdb5e5fa161e46d404f4e0ce388e72fbf7d9baf010aff16689e22abe"},
{file = "cffi-1.14.0-cp38-cp38-win32.whl", hash = "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8"}, {file = "cffi-1.14.1-cp38-cp38-win32.whl", hash = "sha256:6923d077d9ae9e8bacbdb1c07ae78405a9306c8fd1af13bfa06ca891095eb995"},
{file = "cffi-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b"}, {file = "cffi-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:b1d6ebc891607e71fd9da71688fcf332a6630b7f5b7f5549e6e631821c0e5d90"},
{file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"}, {file = "cffi-1.14.1.tar.gz", hash = "sha256:b2a2b0d276a136146e012154baefaea2758ef1f56ae9f4e01c612b0831e0bd2f"},
] ]
chardet = [ chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
@ -492,25 +494,25 @@ click = [
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
] ]
cryptography = [ cryptography = [
{file = "cryptography-2.9.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e"}, {file = "cryptography-3.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ab49edd5bea8d8b39a44b3db618e4783ef84c19c8b47286bf05dfdb3efb01c83"},
{file = "cryptography-2.9.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b"}, {file = "cryptography-3.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:124af7255ffc8e964d9ff26971b3a6153e1a8a220b9a685dc407976ecb27a06a"},
{file = "cryptography-2.9.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365"}, {file = "cryptography-3.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:51e40123083d2f946794f9fe4adeeee2922b581fa3602128ce85ff813d85b81f"},
{file = "cryptography-2.9.2-cp27-cp27m-win32.whl", hash = "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"}, {file = "cryptography-3.0-cp27-cp27m-win32.whl", hash = "sha256:dea0ba7fe6f9461d244679efa968d215ea1f989b9c1957d7f10c21e5c7c09ad6"},
{file = "cryptography-2.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55"}, {file = "cryptography-3.0-cp27-cp27m-win_amd64.whl", hash = "sha256:8ecf9400d0893836ff41b6f977a33972145a855b6efeb605b49ee273c5e6469f"},
{file = "cryptography-2.9.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270"}, {file = "cryptography-3.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0c608ff4d4adad9e39b5057de43657515c7da1ccb1807c3a27d4cf31fc923b4b"},
{file = "cryptography-2.9.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf"}, {file = "cryptography-3.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:bec7568c6970b865f2bcebbe84d547c52bb2abadf74cefce396ba07571109c67"},
{file = "cryptography-2.9.2-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d"}, {file = "cryptography-3.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:0cbfed8ea74631fe4de00630f4bb592dad564d57f73150d6f6796a24e76c76cd"},
{file = "cryptography-2.9.2-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785"}, {file = "cryptography-3.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:a09fd9c1cca9a46b6ad4bea0a1f86ab1de3c0c932364dbcf9a6c2a5eeb44fa77"},
{file = "cryptography-2.9.2-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b"}, {file = "cryptography-3.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ce82cc06588e5cbc2a7df3c8a9c778f2cb722f56835a23a68b5a7264726bb00c"},
{file = "cryptography-2.9.2-cp35-cp35m-win32.whl", hash = "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae"}, {file = "cryptography-3.0-cp35-cp35m-win32.whl", hash = "sha256:9367d00e14dee8d02134c6c9524bb4bd39d4c162456343d07191e2a0b5ec8b3b"},
{file = "cryptography-2.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b"}, {file = "cryptography-3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:384d7c681b1ab904fff3400a6909261cae1d0939cc483a68bdedab282fb89a07"},
{file = "cryptography-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6"}, {file = "cryptography-3.0-cp36-cp36m-win32.whl", hash = "sha256:4d355f2aee4a29063c10164b032d9fa8a82e2c30768737a2fd56d256146ad559"},
{file = "cryptography-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3"}, {file = "cryptography-3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:45741f5499150593178fc98d2c1a9c6722df88b99c821ad6ae298eff0ba1ae71"},
{file = "cryptography-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b"}, {file = "cryptography-3.0-cp37-cp37m-win32.whl", hash = "sha256:8ecef21ac982aa78309bb6f092d1677812927e8b5ef204a10c326fc29f1367e2"},
{file = "cryptography-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e"}, {file = "cryptography-3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4b9303507254ccb1181d1803a2080a798910ba89b1a3c9f53639885c90f7a756"},
{file = "cryptography-2.9.2-cp38-cp38-win32.whl", hash = "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0"}, {file = "cryptography-3.0-cp38-cp38-win32.whl", hash = "sha256:8713ddb888119b0d2a1462357d5946b8911be01ddbf31451e1d07eaa5077a261"},
{file = "cryptography-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5"}, {file = "cryptography-3.0-cp38-cp38-win_amd64.whl", hash = "sha256:bea0b0468f89cdea625bb3f692cd7a4222d80a6bdafd6fb923963f2b9da0e15f"},
{file = "cryptography-2.9.2.tar.gz", hash = "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229"}, {file = "cryptography-3.0.tar.gz", hash = "sha256:8e924dbc025206e97756e8903039662aa58aa9ba357d8e1d8fc29e3092322053"},
] ]
flask = [ flask = [
{file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"}, {file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"},
@ -738,8 +740,8 @@ typed-ast = [
{file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"},
] ]
urllib3 = [ urllib3 = [
{file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, {file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"},
{file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"},
] ]
waitress = [ waitress = [
{file = "waitress-1.4.4-py2.py3-none-any.whl", hash = "sha256:3d633e78149eb83b60a07dfabb35579c29aac2d24bb803c18b26fb2ab1a584db"}, {file = "waitress-1.4.4-py2.py3-none-any.whl", hash = "sha256:3d633e78149eb83b60a07dfabb35579c29aac2d24bb803c18b26fb2ab1a584db"},