mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-27 13:34:28 +00:00
vabbè per oggi basta
This commit is contained in:
parent
48c746ea7d
commit
a7d5d8c72a
11 changed files with 238 additions and 964 deletions
755
poetry.lock
generated
755
poetry.lock
generated
|
@ -1,755 +0,0 @@
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Async http client/server framework (asyncio)"
|
|
||||||
name = "aiohttp"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=3.5.3"
|
|
||||||
version = "3.5.4"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
async-timeout = ">=3.0,<4.0"
|
|
||||||
attrs = ">=17.3.0"
|
|
||||||
chardet = ">=2.0,<4.0"
|
|
||||||
multidict = ">=4.0,<5.0"
|
|
||||||
yarl = ">=1.0,<2.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
speedups = ["aiodns", "brotlipy", "cchardet"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Timeout context manager for asyncio programs"
|
|
||||||
name = "async-timeout"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=3.5.3"
|
|
||||||
version = "3.0.1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Classes Without Boilerplate"
|
|
||||||
name = "attrs"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
version = "19.3.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
|
|
||||||
dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"]
|
|
||||||
docs = ["sphinx", "zope.interface"]
|
|
||||||
tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Python package for providing Mozilla's CA Bundle."
|
|
||||||
name = "certifi"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "2019.9.11"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Foreign Function Interface for Python calling C code."
|
|
||||||
name = "cffi"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "1.13.2"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
pycparser = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Universal encoding detector for Python 2 and 3"
|
|
||||||
name = "chardet"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "3.0.4"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Composable command line interface toolkit"
|
|
||||||
name = "click"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
version = "7.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
|
||||||
name = "cryptography"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
|
||||||
version = "2.8"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
cffi = ">=1.8,<1.11.3 || >1.11.3"
|
|
||||||
six = ">=1.4.1"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"]
|
|
||||||
docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"]
|
|
||||||
idna = ["idna (>=2.1)"]
|
|
||||||
pep8test = ["flake8", "flake8-import-order", "pep8-naming"]
|
|
||||||
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]]
|
|
||||||
category = "main"
|
|
||||||
description = "Date parsing library designed to parse dates from HTML pages"
|
|
||||||
name = "dateparser"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
|
||||||
version = "0.7.2"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
python-dateutil = "*"
|
|
||||||
pytz = "*"
|
|
||||||
regex = "*"
|
|
||||||
tzlocal = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "A python wrapper for the Discord API"
|
|
||||||
name = "discord.py"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=3.5.3"
|
|
||||||
version = "1.3.0a2122+g09a08f9"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
aiohttp = ">=3.3.0,<3.6.0"
|
|
||||||
websockets = ">=8.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["sphinx (1.8.5)", "sphinxcontrib_trio (1.1.0)", "sphinxcontrib-websupport"]
|
|
||||||
voice = ["PyNaCl (1.3.0)"]
|
|
||||||
|
|
||||||
[package.source]
|
|
||||||
reference = "09a08f9a9f126aa1f55c2444eb70508d1d52f8d9"
|
|
||||||
type = "git"
|
|
||||||
url = "https://github.com/Steffo99/discord.py"
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Python bindings for FFmpeg - with complex filtering support"
|
|
||||||
name = "ffmpeg-python"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "0.2.0"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
future = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["future (0.17.1)", "numpy (1.16.4)", "pytest-mock (1.10.4)", "pytest (4.6.1)", "Sphinx (2.1.0)", "tox (3.12.1)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Clean single-source support for Python 3 and 2"
|
|
||||||
name = "future"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
|
||||||
version = "0.18.2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
|
||||||
name = "h11"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "0.8.1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "A collection of framework independent HTTP protocol utils."
|
|
||||||
marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"pypy\""
|
|
||||||
name = "httptools"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "0.0.13"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
|
||||||
name = "idna"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
version = "2.8"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "multidict implementation"
|
|
||||||
name = "multidict"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=3.4.1"
|
|
||||||
version = "4.5.2"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
|
||||||
name = "psycopg2"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
|
||||||
version = "2.8.4"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
|
||||||
name = "psycopg2-binary"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
|
||||||
version = "2.8.4"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "C parser in Python"
|
|
||||||
name = "pycparser"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
version = "2.19"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Python binding to the Networking and Cryptography (NaCl) library"
|
|
||||||
name = "pynacl"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "1.3.0"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
cffi = ">=1.4.1"
|
|
||||||
six = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
|
|
||||||
tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)", "hypothesis (>=3.27.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Extensions to the standard Python datetime module"
|
|
||||||
name = "python-dateutil"
|
|
||||||
optional = false
|
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
|
||||||
version = "2.8.1"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
six = ">=1.5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "We have made you a wrapper you can't refuse"
|
|
||||||
name = "python-telegram-bot"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "12.2.0"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
certifi = "*"
|
|
||||||
cryptography = "*"
|
|
||||||
future = ">=0.16.0"
|
|
||||||
tornado = ">=5.1"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
json = ["ujson"]
|
|
||||||
socks = ["pysocks"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "World timezone definitions, modern and historical"
|
|
||||||
name = "pytz"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
version = "2019.3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Alternative regular expression module, to replace re."
|
|
||||||
name = "regex"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
version = "2019.11.1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Python client for Sentry (https://getsentry.com)"
|
|
||||||
name = "sentry-sdk"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "0.13.2"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
certifi = "*"
|
|
||||||
urllib3 = ">=1.10.0"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
bottle = ["bottle (>=0.12.13)"]
|
|
||||||
falcon = ["falcon (>=1.4)"]
|
|
||||||
flask = ["flask (>=0.8)", "blinker (>=1.1)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Python 2 and 3 compatibility utilities"
|
|
||||||
name = "six"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
|
|
||||||
version = "1.13.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Database Abstraction Library"
|
|
||||||
name = "sqlalchemy"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
version = "1.3.11"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
mssql = ["pyodbc"]
|
|
||||||
mssql_pymssql = ["pymssql"]
|
|
||||||
mssql_pyodbc = ["pyodbc"]
|
|
||||||
mysql = ["mysqlclient"]
|
|
||||||
oracle = ["cx-oracle"]
|
|
||||||
postgresql = ["psycopg2"]
|
|
||||||
postgresql_pg8000 = ["pg8000"]
|
|
||||||
postgresql_psycopg2binary = ["psycopg2-binary"]
|
|
||||||
postgresql_psycopg2cffi = ["psycopg2cffi"]
|
|
||||||
pymysql = ["pymysql"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "The little ASGI library that shines."
|
|
||||||
name = "starlette"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
version = "0.12.13"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "ujson"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
|
|
||||||
name = "tornado"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">= 3.5"
|
|
||||||
version = "6.0.3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "tzinfo object for the local timezone"
|
|
||||||
name = "tzlocal"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
version = "2.0.0"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
pytz = "*"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
|
||||||
name = "urllib3"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4"
|
|
||||||
version = "1.25.7"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
brotli = ["brotlipy (>=0.6.0)"]
|
|
||||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
|
||||||
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "The lightning-fast ASGI server."
|
|
||||||
name = "uvicorn"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "0.10.8"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
click = ">=7.0.0,<8.0.0"
|
|
||||||
h11 = ">=0.8.0,<0.9.0"
|
|
||||||
httptools = "0.0.13"
|
|
||||||
uvloop = ">=0.14.0"
|
|
||||||
websockets = ">=8.0.0,<9.0.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Fast implementation of asyncio event loop on top of libuv"
|
|
||||||
marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"pypy\""
|
|
||||||
name = "uvloop"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "0.14.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
|
|
||||||
name = "websockets"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=3.6.1"
|
|
||||||
version = "8.1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "Yet another URL library"
|
|
||||||
name = "yarl"
|
|
||||||
optional = true
|
|
||||||
python-versions = ">=3.5.3"
|
|
||||||
version = "1.3.0"
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
idna = ">=2.0"
|
|
||||||
multidict = ">=4.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
category = "main"
|
|
||||||
description = "YouTube video downloader"
|
|
||||||
name = "youtube-dl"
|
|
||||||
optional = true
|
|
||||||
python-versions = "*"
|
|
||||||
version = "2019.11.5"
|
|
||||||
|
|
||||||
[extras]
|
|
||||||
alchemy_easy = ["sqlalchemy", "psycopg2_binary"]
|
|
||||||
alchemy_hard = ["sqlalchemy", "psycopg2"]
|
|
||||||
bard = ["ffmpeg_python", "youtube_dl"]
|
|
||||||
constellation = ["starlette", "uvicorn"]
|
|
||||||
discord = ["discord.py", "pynacl"]
|
|
||||||
sentry = ["sentry_sdk"]
|
|
||||||
telegram = ["python_telegram_bot"]
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
content-hash = "d101c51ae28aea2b4692767328e42026950bd3f920fdf6f6afca76bac40e41df"
|
|
||||||
python-versions = "^3.8"
|
|
||||||
|
|
||||||
[metadata.files]
|
|
||||||
aiohttp = [
|
|
||||||
{file = "aiohttp-3.5.4-cp35-cp35m-macosx_10_10_x86_64.whl", hash = "sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5"},
|
|
||||||
{file = "aiohttp-3.5.4-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed"},
|
|
||||||
{file = "aiohttp-3.5.4-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303"},
|
|
||||||
{file = "aiohttp-3.5.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10"},
|
|
||||||
{file = "aiohttp-3.5.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa"},
|
|
||||||
{file = "aiohttp-3.5.4-cp35-cp35m-win32.whl", hash = "sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4"},
|
|
||||||
{file = "aiohttp-3.5.4-cp35-cp35m-win_amd64.whl", hash = "sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72"},
|
|
||||||
{file = "aiohttp-3.5.4-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5"},
|
|
||||||
{file = "aiohttp-3.5.4-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12"},
|
|
||||||
{file = "aiohttp-3.5.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6"},
|
|
||||||
{file = "aiohttp-3.5.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6"},
|
|
||||||
{file = "aiohttp-3.5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d"},
|
|
||||||
{file = "aiohttp-3.5.4-cp36-cp36m-win32.whl", hash = "sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1"},
|
|
||||||
{file = "aiohttp-3.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d"},
|
|
||||||
{file = "aiohttp-3.5.4-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300"},
|
|
||||||
{file = "aiohttp-3.5.4-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390"},
|
|
||||||
{file = "aiohttp-3.5.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366"},
|
|
||||||
{file = "aiohttp-3.5.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889"},
|
|
||||||
{file = "aiohttp-3.5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55"},
|
|
||||||
{file = "aiohttp-3.5.4-cp37-cp37m-win32.whl", hash = "sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc"},
|
|
||||||
{file = "aiohttp-3.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939"},
|
|
||||||
{file = "aiohttp-3.5.4.tar.gz", hash = "sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf"},
|
|
||||||
]
|
|
||||||
async-timeout = [
|
|
||||||
{file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"},
|
|
||||||
{file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"},
|
|
||||||
]
|
|
||||||
attrs = [
|
|
||||||
{file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
|
|
||||||
{file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
|
|
||||||
]
|
|
||||||
certifi = [
|
|
||||||
{file = "certifi-2019.9.11-py2.py3-none-any.whl", hash = "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"},
|
|
||||||
{file = "certifi-2019.9.11.tar.gz", hash = "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50"},
|
|
||||||
]
|
|
||||||
cffi = [
|
|
||||||
{file = "cffi-1.13.2-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43"},
|
|
||||||
{file = "cffi-1.13.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396"},
|
|
||||||
{file = "cffi-1.13.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54"},
|
|
||||||
{file = "cffi-1.13.2-cp27-cp27m-win32.whl", hash = "sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159"},
|
|
||||||
{file = "cffi-1.13.2-cp27-cp27m-win_amd64.whl", hash = "sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97"},
|
|
||||||
{file = "cffi-1.13.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579"},
|
|
||||||
{file = "cffi-1.13.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc"},
|
|
||||||
{file = "cffi-1.13.2-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f"},
|
|
||||||
{file = "cffi-1.13.2-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858"},
|
|
||||||
{file = "cffi-1.13.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42"},
|
|
||||||
{file = "cffi-1.13.2-cp34-cp34m-win32.whl", hash = "sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b"},
|
|
||||||
{file = "cffi-1.13.2-cp34-cp34m-win_amd64.whl", hash = "sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20"},
|
|
||||||
{file = "cffi-1.13.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3"},
|
|
||||||
{file = "cffi-1.13.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25"},
|
|
||||||
{file = "cffi-1.13.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5"},
|
|
||||||
{file = "cffi-1.13.2-cp35-cp35m-win32.whl", hash = "sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c"},
|
|
||||||
{file = "cffi-1.13.2-cp35-cp35m-win_amd64.whl", hash = "sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b"},
|
|
||||||
{file = "cffi-1.13.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04"},
|
|
||||||
{file = "cffi-1.13.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652"},
|
|
||||||
{file = "cffi-1.13.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57"},
|
|
||||||
{file = "cffi-1.13.2-cp36-cp36m-win32.whl", hash = "sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e"},
|
|
||||||
{file = "cffi-1.13.2-cp36-cp36m-win_amd64.whl", hash = "sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d"},
|
|
||||||
{file = "cffi-1.13.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410"},
|
|
||||||
{file = "cffi-1.13.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a"},
|
|
||||||
{file = "cffi-1.13.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12"},
|
|
||||||
{file = "cffi-1.13.2-cp37-cp37m-win32.whl", hash = "sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e"},
|
|
||||||
{file = "cffi-1.13.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a"},
|
|
||||||
{file = "cffi-1.13.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d"},
|
|
||||||
{file = "cffi-1.13.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3"},
|
|
||||||
{file = "cffi-1.13.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db"},
|
|
||||||
{file = "cffi-1.13.2-cp38-cp38-win32.whl", hash = "sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506"},
|
|
||||||
{file = "cffi-1.13.2-cp38-cp38-win_amd64.whl", hash = "sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba"},
|
|
||||||
{file = "cffi-1.13.2.tar.gz", hash = "sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346"},
|
|
||||||
]
|
|
||||||
chardet = [
|
|
||||||
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
|
|
||||||
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
|
|
||||||
]
|
|
||||||
click = [
|
|
||||||
{file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"},
|
|
||||||
{file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"},
|
|
||||||
]
|
|
||||||
cryptography = [
|
|
||||||
{file = "cryptography-2.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8"},
|
|
||||||
{file = "cryptography-2.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2"},
|
|
||||||
{file = "cryptography-2.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad"},
|
|
||||||
{file = "cryptography-2.8-cp27-cp27m-win32.whl", hash = "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2"},
|
|
||||||
{file = "cryptography-2.8-cp27-cp27m-win_amd64.whl", hash = "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912"},
|
|
||||||
{file = "cryptography-2.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d"},
|
|
||||||
{file = "cryptography-2.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42"},
|
|
||||||
{file = "cryptography-2.8-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879"},
|
|
||||||
{file = "cryptography-2.8-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d"},
|
|
||||||
{file = "cryptography-2.8-cp34-abi3-manylinux2010_x86_64.whl", hash = "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9"},
|
|
||||||
{file = "cryptography-2.8-cp34-cp34m-win32.whl", hash = "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c"},
|
|
||||||
{file = "cryptography-2.8-cp34-cp34m-win_amd64.whl", hash = "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0"},
|
|
||||||
{file = "cryptography-2.8-cp35-cp35m-win32.whl", hash = "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf"},
|
|
||||||
{file = "cryptography-2.8-cp35-cp35m-win_amd64.whl", hash = "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793"},
|
|
||||||
{file = "cryptography-2.8-cp36-cp36m-win32.whl", hash = "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595"},
|
|
||||||
{file = "cryptography-2.8-cp36-cp36m-win_amd64.whl", hash = "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7"},
|
|
||||||
{file = "cryptography-2.8-cp37-cp37m-win32.whl", hash = "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff"},
|
|
||||||
{file = "cryptography-2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f"},
|
|
||||||
{file = "cryptography-2.8-cp38-cp38-win32.whl", hash = "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e"},
|
|
||||||
{file = "cryptography-2.8-cp38-cp38-win_amd64.whl", hash = "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13"},
|
|
||||||
{file = "cryptography-2.8.tar.gz", hash = "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651"},
|
|
||||||
]
|
|
||||||
dateparser = [
|
|
||||||
{file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"},
|
|
||||||
{file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"},
|
|
||||||
]
|
|
||||||
"discord.py" = []
|
|
||||||
ffmpeg-python = [
|
|
||||||
{file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"},
|
|
||||||
{file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"},
|
|
||||||
]
|
|
||||||
future = [
|
|
||||||
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
|
|
||||||
]
|
|
||||||
h11 = [
|
|
||||||
{file = "h11-0.8.1-py2.py3-none-any.whl", hash = "sha256:f2b1ca39bfed357d1f19ac732913d5f9faa54a5062eca7d2ec3a916cfb7ae4c7"},
|
|
||||||
{file = "h11-0.8.1.tar.gz", hash = "sha256:acca6a44cb52a32ab442b1779adf0875c443c689e9e028f8d831a3769f9c5208"},
|
|
||||||
]
|
|
||||||
httptools = [
|
|
||||||
{file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"},
|
|
||||||
]
|
|
||||||
idna = [
|
|
||||||
{file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"},
|
|
||||||
{file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"},
|
|
||||||
]
|
|
||||||
multidict = [
|
|
||||||
{file = "multidict-4.5.2-cp34-cp34m-macosx_10_12_intel.macosx_10_12_x86_64.macosx_10_13_intel.macosx_10_13_x86_64.whl", hash = "sha256:068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73"},
|
|
||||||
{file = "multidict-4.5.2-cp34-cp34m-macosx_10_6_intel.macosx_10_6_x86_64.macosx_10_7_intel.macosx_10_7_x86_64.macosx_10_8_intel.macosx_10_8_x86_64.whl", hash = "sha256:7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5"},
|
|
||||||
{file = "multidict-4.5.2-cp34-cp34m-macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.macosx_10_11_intel.macosx_10_11_x86_64.whl", hash = "sha256:8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d"},
|
|
||||||
{file = "multidict-4.5.2-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0"},
|
|
||||||
{file = "multidict-4.5.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351"},
|
|
||||||
{file = "multidict-4.5.2-cp34-cp34m-win32.whl", hash = "sha256:8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a"},
|
|
||||||
{file = "multidict-4.5.2-cp34-cp34m-win_amd64.whl", hash = "sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9"},
|
|
||||||
{file = "multidict-4.5.2-cp35-cp35m-macosx_10_12_intel.macosx_10_12_x86_64.macosx_10_13_intel.macosx_10_13_x86_64.whl", hash = "sha256:1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3"},
|
|
||||||
{file = "multidict-4.5.2-cp35-cp35m-macosx_10_6_intel.macosx_10_6_x86_64.macosx_10_7_intel.macosx_10_7_x86_64.macosx_10_8_intel.macosx_10_8_x86_64.whl", hash = "sha256:3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d"},
|
|
||||||
{file = "multidict-4.5.2-cp35-cp35m-macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.macosx_10_11_intel.macosx_10_11_x86_64.whl", hash = "sha256:7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036"},
|
|
||||||
{file = "multidict-4.5.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3"},
|
|
||||||
{file = "multidict-4.5.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1"},
|
|
||||||
{file = "multidict-4.5.2-cp35-cp35m-win32.whl", hash = "sha256:34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941"},
|
|
||||||
{file = "multidict-4.5.2-cp35-cp35m-win_amd64.whl", hash = "sha256:5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3"},
|
|
||||||
{file = "multidict-4.5.2-cp36-cp36m-macosx_10_12_intel.macosx_10_12_x86_64.macosx_10_13_intel.macosx_10_13_x86_64.whl", hash = "sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b"},
|
|
||||||
{file = "multidict-4.5.2-cp36-cp36m-macosx_10_6_intel.macosx_10_6_x86_64.macosx_10_7_intel.macosx_10_7_x86_64.macosx_10_8_intel.macosx_10_8_x86_64.whl", hash = "sha256:ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a"},
|
|
||||||
{file = "multidict-4.5.2-cp36-cp36m-macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.macosx_10_11_intel.macosx_10_11_x86_64.whl", hash = "sha256:4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a"},
|
|
||||||
{file = "multidict-4.5.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b"},
|
|
||||||
{file = "multidict-4.5.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc"},
|
|
||||||
{file = "multidict-4.5.2-cp36-cp36m-win32.whl", hash = "sha256:4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b"},
|
|
||||||
{file = "multidict-4.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7"},
|
|
||||||
{file = "multidict-4.5.2-cp37-cp37m-macosx_10_12_intel.macosx_10_12_x86_64.macosx_10_13_intel.macosx_10_13_x86_64.whl", hash = "sha256:1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd"},
|
|
||||||
{file = "multidict-4.5.2-cp37-cp37m-macosx_10_6_intel.macosx_10_6_x86_64.macosx_10_7_intel.macosx_10_7_x86_64.macosx_10_8_intel.macosx_10_8_x86_64.whl", hash = "sha256:61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7"},
|
|
||||||
{file = "multidict-4.5.2-cp37-cp37m-macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.macosx_10_11_intel.macosx_10_11_x86_64.whl", hash = "sha256:76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0"},
|
|
||||||
{file = "multidict-4.5.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014"},
|
|
||||||
{file = "multidict-4.5.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce"},
|
|
||||||
{file = "multidict-4.5.2-cp37-cp37m-win32.whl", hash = "sha256:045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef"},
|
|
||||||
{file = "multidict-4.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1"},
|
|
||||||
{file = "multidict-4.5.2.tar.gz", hash = "sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f"},
|
|
||||||
]
|
|
||||||
psycopg2 = [
|
|
||||||
{file = "psycopg2-2.8.4-cp27-cp27m-win32.whl", hash = "sha256:72772181d9bad1fa349792a1e7384dde56742c14af2b9986013eb94a240f005b"},
|
|
||||||
{file = "psycopg2-2.8.4-cp27-cp27m-win_amd64.whl", hash = "sha256:893c11064b347b24ecdd277a094413e1954f8a4e8cdaf7ffbe7ca3db87c103f0"},
|
|
||||||
{file = "psycopg2-2.8.4-cp34-cp34m-win32.whl", hash = "sha256:9ab75e0b2820880ae24b7136c4d230383e07db014456a476d096591172569c38"},
|
|
||||||
{file = "psycopg2-2.8.4-cp34-cp34m-win_amd64.whl", hash = "sha256:b0845e3bdd4aa18dc2f9b6fb78fbd3d9d371ad167fd6d1b7ad01c0a6cdad4fc6"},
|
|
||||||
{file = "psycopg2-2.8.4-cp35-cp35m-win32.whl", hash = "sha256:ef6df7e14698e79c59c7ee7cf94cd62e5b869db369ed4b1b8f7b729ea825712a"},
|
|
||||||
{file = "psycopg2-2.8.4-cp35-cp35m-win_amd64.whl", hash = "sha256:965c4c93e33e6984d8031f74e51227bd755376a9df6993774fd5b6fb3288b1f4"},
|
|
||||||
{file = "psycopg2-2.8.4-cp36-cp36m-win32.whl", hash = "sha256:ed686e5926929887e2c7ae0a700e32c6129abb798b4ad2b846e933de21508151"},
|
|
||||||
{file = "psycopg2-2.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:dca2d7203f0dfce8ea4b3efd668f8ea65cd2b35112638e488a4c12594015f67b"},
|
|
||||||
{file = "psycopg2-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:8396be6e5ff844282d4d49b81631772f80dabae5658d432202faf101f5283b7c"},
|
|
||||||
{file = "psycopg2-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:47fc642bf6f427805daf52d6e52619fe0637648fe27017062d898f3bf891419d"},
|
|
||||||
{file = "psycopg2-2.8.4-cp38-cp38-win32.whl", hash = "sha256:4212ca404c4445dc5746c0d68db27d2cbfb87b523fe233dc84ecd24062e35677"},
|
|
||||||
{file = "psycopg2-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:92a07dfd4d7c325dd177548c4134052d4842222833576c8391aab6f74038fc3f"},
|
|
||||||
{file = "psycopg2-2.8.4.tar.gz", hash = "sha256:f898e5cc0a662a9e12bde6f931263a1bbd350cfb18e1d5336a12927851825bb6"},
|
|
||||||
]
|
|
||||||
psycopg2-binary = [
|
|
||||||
{file = "psycopg2-binary-2.8.4.tar.gz", hash = "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp27-cp27m-win32.whl", hash = "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp27-cp27m-win_amd64.whl", hash = "sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp34-cp34m-win32.whl", hash = "sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp34-cp34m-win_amd64.whl", hash = "sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp35-cp35m-win32.whl", hash = "sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp35-cp35m-win_amd64.whl", hash = "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp36-cp36m-win32.whl", hash = "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp38-cp38-win32.whl", hash = "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1"},
|
|
||||||
{file = "psycopg2_binary-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f"},
|
|
||||||
]
|
|
||||||
pycparser = [
|
|
||||||
{file = "pycparser-2.19.tar.gz", hash = "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"},
|
|
||||||
]
|
|
||||||
pynacl = [
|
|
||||||
{file = "PyNaCl-1.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp27-cp27m-win32.whl", hash = "sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp34-abi3-manylinux1_i686.whl", hash = "sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp34-cp34m-win32.whl", hash = "sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp34-cp34m-win_amd64.whl", hash = "sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp35-cp35m-win32.whl", hash = "sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp36-cp36m-win32.whl", hash = "sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp37-cp37m-win32.whl", hash = "sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp38-cp38-win32.whl", hash = "sha256:53126cd91356342dcae7e209f840212a58dcf1177ad52c1d938d428eebc9fee5"},
|
|
||||||
{file = "PyNaCl-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:bf459128feb543cfca16a95f8da31e2e65e4c5257d2f3dfa8c0c1031139c9c92"},
|
|
||||||
{file = "PyNaCl-1.3.0.tar.gz", hash = "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c"},
|
|
||||||
]
|
|
||||||
python-dateutil = [
|
|
||||||
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
|
|
||||||
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
|
|
||||||
]
|
|
||||||
python-telegram-bot = [
|
|
||||||
{file = "python-telegram-bot-12.2.0.tar.gz", hash = "sha256:346d42771c2b23384c59f5f41e05bd7e801a0ce118d8dcb95209bb73d5f694c5"},
|
|
||||||
{file = "python_telegram_bot-12.2.0-py2.py3-none-any.whl", hash = "sha256:3beee89cba3bc3217566c96199f04776dd25f541ac8992da27fd247b2d208a14"},
|
|
||||||
]
|
|
||||||
pytz = [
|
|
||||||
{file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"},
|
|
||||||
{file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"},
|
|
||||||
]
|
|
||||||
regex = [
|
|
||||||
{file = "regex-2019.11.1-cp27-none-win32.whl", hash = "sha256:604dc563a02a74d70ae1f55208ddc9bfb6d9f470f6d1a5054c4bd5ae58744ab1"},
|
|
||||||
{file = "regex-2019.11.1-cp27-none-win_amd64.whl", hash = "sha256:5e00f65cc507d13ab4dfa92c1232d004fa202c1d43a32a13940ab8a5afe2fb96"},
|
|
||||||
{file = "regex-2019.11.1-cp35-none-win32.whl", hash = "sha256:15454b37c5a278f46f7aa2d9339bda450c300617ca2fca6558d05d870245edc7"},
|
|
||||||
{file = "regex-2019.11.1-cp35-none-win_amd64.whl", hash = "sha256:d2b302f8cdd82c8f48e9de749d1d17f85ce9a0f082880b9a4859f66b07037dc6"},
|
|
||||||
{file = "regex-2019.11.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b4e0406d822aa4993ac45072a584d57aa4931cf8288b5455bbf30c1d59dbad59"},
|
|
||||||
{file = "regex-2019.11.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7faf534c1841c09d8fefa60ccde7b9903c9b528853ecf41628689793290ca143"},
|
|
||||||
{file = "regex-2019.11.1-cp36-none-win32.whl", hash = "sha256:7caf47e4a9ac6ef08cabd3442cc4ca3386db141fb3c8b2a7e202d0470028e910"},
|
|
||||||
{file = "regex-2019.11.1-cp36-none-win_amd64.whl", hash = "sha256:e3d8dd0ec0ea280cf89026b0898971f5750a7bd92cb62c51af5a52abd020054a"},
|
|
||||||
{file = "regex-2019.11.1-cp37-none-win32.whl", hash = "sha256:c31eaf28c6fe75ea329add0022efeed249e37861c19681960f99bbc7db981fb2"},
|
|
||||||
{file = "regex-2019.11.1-cp37-none-win_amd64.whl", hash = "sha256:1ad40708c255943a227e778b022c6497c129ad614bb7a2a2f916e12e8a359ee7"},
|
|
||||||
{file = "regex-2019.11.1-cp38-none-win32.whl", hash = "sha256:ec032cbfed59bd5a4b8eab943c310acfaaa81394e14f44454ad5c9eba4f24a74"},
|
|
||||||
{file = "regex-2019.11.1-cp38-none-win_amd64.whl", hash = "sha256:c7393597191fc2043c744db021643549061e12abe0b3ff5c429d806de7b93b66"},
|
|
||||||
{file = "regex-2019.11.1.tar.gz", hash = "sha256:720e34a539a76a1fedcebe4397290604cc2bdf6f81eca44adb9fb2ea071c0c69"},
|
|
||||||
]
|
|
||||||
sentry-sdk = [
|
|
||||||
{file = "sentry-sdk-0.13.2.tar.gz", hash = "sha256:ff1fa7fb85703ae9414c8b427ee73f8363232767c9cd19158f08f6e4f0b58fc7"},
|
|
||||||
{file = "sentry_sdk-0.13.2-py2.py3-none-any.whl", hash = "sha256:09e1e8f00f22ea580348f83bbbd880adf40b29f1dec494a8e4b33e22f77184fb"},
|
|
||||||
]
|
|
||||||
six = [
|
|
||||||
{file = "six-1.13.0-py2.py3-none-any.whl", hash = "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd"},
|
|
||||||
{file = "six-1.13.0.tar.gz", hash = "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"},
|
|
||||||
]
|
|
||||||
sqlalchemy = [
|
|
||||||
{file = "SQLAlchemy-1.3.11.tar.gz", hash = "sha256:afa5541e9dea8ad0014251bc9d56171ca3d8b130c9627c6cb3681cff30be3f8a"},
|
|
||||||
]
|
|
||||||
starlette = [
|
|
||||||
{file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"},
|
|
||||||
]
|
|
||||||
tornado = [
|
|
||||||
{file = "tornado-6.0.3-cp35-cp35m-win32.whl", hash = "sha256:c9399267c926a4e7c418baa5cbe91c7d1cf362d505a1ef898fde44a07c9dd8a5"},
|
|
||||||
{file = "tornado-6.0.3-cp35-cp35m-win_amd64.whl", hash = "sha256:398e0d35e086ba38a0427c3b37f4337327231942e731edaa6e9fd1865bbd6f60"},
|
|
||||||
{file = "tornado-6.0.3-cp36-cp36m-win32.whl", hash = "sha256:4e73ef678b1a859f0cb29e1d895526a20ea64b5ffd510a2307b5998c7df24281"},
|
|
||||||
{file = "tornado-6.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:349884248c36801afa19e342a77cc4458caca694b0eda633f5878e458a44cb2c"},
|
|
||||||
{file = "tornado-6.0.3-cp37-cp37m-win32.whl", hash = "sha256:559bce3d31484b665259f50cd94c5c28b961b09315ccd838f284687245f416e5"},
|
|
||||||
{file = "tornado-6.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:abbe53a39734ef4aba061fca54e30c6b4639d3e1f59653f0da37a0003de148c7"},
|
|
||||||
{file = "tornado-6.0.3.tar.gz", hash = "sha256:c845db36ba616912074c5b1ee897f8e0124df269468f25e4fe21fe72f6edd7a9"},
|
|
||||||
]
|
|
||||||
tzlocal = [
|
|
||||||
{file = "tzlocal-2.0.0-py2.py3-none-any.whl", hash = "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048"},
|
|
||||||
{file = "tzlocal-2.0.0.tar.gz", hash = "sha256:949b9dd5ba4be17190a80c0268167d7e6c92c62b30026cf9764caf3e308e5590"},
|
|
||||||
]
|
|
||||||
urllib3 = [
|
|
||||||
{file = "urllib3-1.25.7-py2.py3-none-any.whl", hash = "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293"},
|
|
||||||
{file = "urllib3-1.25.7.tar.gz", hash = "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"},
|
|
||||||
]
|
|
||||||
uvicorn = [
|
|
||||||
{file = "uvicorn-0.10.8.tar.gz", hash = "sha256:f4c34642618449f55e2bab8c6b22ff7615b520d2e7e23275be2ca894254327a3"},
|
|
||||||
]
|
|
||||||
uvloop = [
|
|
||||||
{file = "uvloop-0.14.0-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd"},
|
|
||||||
{file = "uvloop-0.14.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:4544dcf77d74f3a84f03dd6278174575c44c67d7165d4c42c71db3fdc3860726"},
|
|
||||||
{file = "uvloop-0.14.0-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:b4f591aa4b3fa7f32fb51e2ee9fea1b495eb75b0b3c8d0ca52514ad675ae63f7"},
|
|
||||||
{file = "uvloop-0.14.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f07909cd9fc08c52d294b1570bba92186181ca01fe3dc9ffba68955273dd7362"},
|
|
||||||
{file = "uvloop-0.14.0-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:afd5513c0ae414ec71d24f6f123614a80f3d27ca655a4fcf6cabe50994cc1891"},
|
|
||||||
{file = "uvloop-0.14.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e7514d7a48c063226b7d06617cbb12a14278d4323a065a8d46a7962686ce2e95"},
|
|
||||||
{file = "uvloop-0.14.0-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:bcac356d62edd330080aed082e78d4b580ff260a677508718f88016333e2c9c5"},
|
|
||||||
{file = "uvloop-0.14.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09"},
|
|
||||||
{file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"},
|
|
||||||
]
|
|
||||||
websockets = [
|
|
||||||
{file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"},
|
|
||||||
{file = "websockets-8.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170"},
|
|
||||||
{file = "websockets-8.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8"},
|
|
||||||
{file = "websockets-8.1-cp36-cp36m-win32.whl", hash = "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a"},
|
|
||||||
{file = "websockets-8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5"},
|
|
||||||
{file = "websockets-8.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989"},
|
|
||||||
{file = "websockets-8.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d"},
|
|
||||||
{file = "websockets-8.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779"},
|
|
||||||
{file = "websockets-8.1-cp37-cp37m-win32.whl", hash = "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc"},
|
|
||||||
{file = "websockets-8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308"},
|
|
||||||
{file = "websockets-8.1.tar.gz", hash = "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f"},
|
|
||||||
]
|
|
||||||
yarl = [
|
|
||||||
{file = "yarl-1.3.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:3e2724eb9af5dc41648e5bb304fcf4891adc33258c6e14e2a7414ea32541e320"},
|
|
||||||
{file = "yarl-1.3.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3890ab952d508523ef4881457c4099056546593fa05e93da84c7250516e632eb"},
|
|
||||||
{file = "yarl-1.3.0-cp35-cp35m-win32.whl", hash = "sha256:7ab825726f2940c16d92aaec7d204cfc34ac26c0040da727cf8ba87255a33829"},
|
|
||||||
{file = "yarl-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:b25de84a8c20540531526dfbb0e2d2b648c13fd5dd126728c496d7c3fea33310"},
|
|
||||||
{file = "yarl-1.3.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:2f3010703295fbe1aec51023740871e64bb9664c789cba5a6bdf404e93f7568f"},
|
|
||||||
{file = "yarl-1.3.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5badb97dd0abf26623a9982cd448ff12cb39b8e4c94032ccdedf22ce01a64842"},
|
|
||||||
{file = "yarl-1.3.0-cp36-cp36m-win32.whl", hash = "sha256:c9bb7c249c4432cd47e75af3864bc02d26c9594f49c82e2a28624417f0ae63b8"},
|
|
||||||
{file = "yarl-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:c6e341f5a6562af74ba55205dbd56d248daf1b5748ec48a0200ba227bb9e33f4"},
|
|
||||||
{file = "yarl-1.3.0-cp37-cp37m-win32.whl", hash = "sha256:e060906c0c585565c718d1c3841747b61c5439af2211e185f6739a9412dfbde1"},
|
|
||||||
{file = "yarl-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:73f447d11b530d860ca1e6b582f947688286ad16ca42256413083d13f260b7a0"},
|
|
||||||
{file = "yarl-1.3.0.tar.gz", hash = "sha256:024ecdc12bc02b321bc66b41327f930d1c2c543fa9a561b39861da9388ba7aa9"},
|
|
||||||
]
|
|
||||||
youtube-dl = [
|
|
||||||
{file = "youtube_dl-2019.11.5-py2.py3-none-any.whl", hash = "sha256:1314de17f0d41c0f1062c4942406b8e0558d14d44b32f9fce00272760a06455b"},
|
|
||||||
{file = "youtube_dl-2019.11.5.tar.gz", hash = "sha256:25324aab78df9a09b2ee34f642f116933134bc66ea629a778c1fffe05b66f733"},
|
|
||||||
]
|
|
|
@ -20,10 +20,11 @@
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.8"
|
python = "^3.8"
|
||||||
dateparser = "^0.7.2"
|
dateparser = "^0.7.2"
|
||||||
|
keyring = "^19.2.0" # TODO: Maybe remove this when possible?
|
||||||
# telegram
|
# telegram
|
||||||
python_telegram_bot = {version="^12.2.0", optional=true}
|
python_telegram_bot = {version="^12.2.0", optional=true}
|
||||||
# discord
|
# discord
|
||||||
"discord.py" = {git = "https://github.com/Steffo99/discord.py", optional=true} # discord.py 1.2.4 is missing Go Live related methods
|
"discord.py" = {git="https://github.com/Steffo99/discord.py.git", optional=true} # discord.py 1.2.4 is missing Go Live related methods
|
||||||
pynacl = {version="^1.3.0", optional=true} # This requires libffi-dev and python3.*-dev to be installed on Linux systems
|
pynacl = {version="^1.3.0", optional=true} # This requires libffi-dev and python3.*-dev to be installed on Linux systems
|
||||||
# bard
|
# bard
|
||||||
ffmpeg_python = {version="~0.2.0", optional=true}
|
ffmpeg_python = {version="~0.2.0", optional=true}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
__version__ = "5.1a1"
|
|
@ -28,17 +28,17 @@ class Alchemy:
|
||||||
self._engine: Engine = create_engine(database_uri)
|
self._engine: Engine = create_engine(database_uri)
|
||||||
self._Base: DeclarativeMeta = declarative_base(bind=self._engine)
|
self._Base: DeclarativeMeta = declarative_base(bind=self._engine)
|
||||||
self._Session: sessionmaker = sessionmaker(bind=self._engine)
|
self._Session: sessionmaker = sessionmaker(bind=self._engine)
|
||||||
self._tables: Dict[str, Type[Table]] = {}
|
self._tables: Dict[str, Table] = {}
|
||||||
for table in tables:
|
for table in tables:
|
||||||
name = table.__name__
|
name = table.__name__
|
||||||
assert self._tables.get(name) is None
|
assert self._tables.get(name) is None
|
||||||
assert isinstance(name, str)
|
assert isinstance(name, str)
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
bound_table: Type[Table] = type(name, (self._Base, table), {})
|
bound_table: Table = type(name, (self._Base, table), {})
|
||||||
self._tables[name] = bound_table
|
self._tables[name] = bound_table
|
||||||
self._Base.metadata.create_all()
|
self._Base.metadata.create_all()
|
||||||
|
|
||||||
def get(self, table: Union[str, type]) -> Type[Table]:
|
def get(self, table: Union[str, type]) -> Table:
|
||||||
"""Get the table with a specified name or class.
|
"""Get the table with a specified name or class.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
|
@ -3,7 +3,7 @@ from sqlalchemy.inspection import inspect
|
||||||
from sqlalchemy.schema import Table
|
from sqlalchemy.schema import Table
|
||||||
|
|
||||||
|
|
||||||
def table_dfs(starting_table: Type[Table], ending_table: Type[Table]) -> tuple:
|
def table_dfs(starting_table: Table, ending_table: Table) -> tuple:
|
||||||
"""Depth-first-search for the path from the starting table to the ending table.
|
"""Depth-first-search for the path from the starting table to the ending table.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
|
@ -9,6 +9,8 @@ import royalnet
|
||||||
import keyring
|
import keyring
|
||||||
from starlette.applications import Starlette
|
from starlette.applications import Starlette
|
||||||
from .star import PageStar, ExceptionStar
|
from .star import PageStar, ExceptionStar
|
||||||
|
from royalnet.alchemy import Alchemy
|
||||||
|
from royalnet import __version__ as version
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -23,7 +25,6 @@ class Constellation:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
secrets_name: str,
|
secrets_name: str,
|
||||||
database_uri: str,
|
database_uri: str,
|
||||||
tables: set,
|
|
||||||
page_stars: typing.List[typing.Type[PageStar]] = None,
|
page_stars: typing.List[typing.Type[PageStar]] = None,
|
||||||
exc_stars: typing.List[typing.Type[ExceptionStar]] = None,
|
exc_stars: typing.List[typing.Type[ExceptionStar]] = None,
|
||||||
*,
|
*,
|
||||||
|
@ -53,12 +54,12 @@ class Constellation:
|
||||||
log.debug(f"Found Tables: {' '.join([table.__name__ for table in tables])}")
|
log.debug(f"Found Tables: {' '.join([table.__name__ for table in tables])}")
|
||||||
|
|
||||||
log.info(f"Creating Alchemy...")
|
log.info(f"Creating Alchemy...")
|
||||||
self.alchemy: royalnet.database.Alchemy = royalnet.database.Alchemy(database_uri=database_uri, tables=tables)
|
self.alchemy: Alchemy = Alchemy(database_uri=database_uri, tables=tables)
|
||||||
"""The :class:`Alchemy: of this Constellation."""
|
"""The :class:`Alchemy: of this Constellation."""
|
||||||
|
|
||||||
log.info("Registering PageStars...")
|
log.info("Registering PageStars...")
|
||||||
for SelectedPageStar in page_stars:
|
for SelectedPageStar in page_stars:
|
||||||
log.info(f"Registering: {page_star_instance.path} -> {page_star_instance.__class__.__name__}")
|
log.info(f"Registering: {SelectedPageStar.path} -> {SelectedPageStar.__class__.__name__}")
|
||||||
try:
|
try:
|
||||||
page_star_instance = SelectedPageStar(constellation=self)
|
page_star_instance = SelectedPageStar(constellation=self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -68,7 +69,7 @@ class Constellation:
|
||||||
|
|
||||||
log.info("Registering ExceptionStars...")
|
log.info("Registering ExceptionStars...")
|
||||||
for SelectedExcStar in exc_stars:
|
for SelectedExcStar in exc_stars:
|
||||||
log.info(f"Registering: {exc_star_instance.error} -> {exc_star_instance.__class__.__name__}")
|
log.info(f"Registering: {SelectedExcStar.error} -> {SelectedExcStar.__class__.__name__}")
|
||||||
try:
|
try:
|
||||||
exc_star_instance = SelectedExcStar(constellation=self)
|
exc_star_instance = SelectedExcStar(constellation=self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -98,7 +99,7 @@ class Constellation:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
release = f"Dev"
|
release = f"Dev"
|
||||||
else:
|
else:
|
||||||
release = f"{royalnet.version.semantic}"
|
release = f"{version}"
|
||||||
log.debug("Initializing Sentry...")
|
log.debug("Initializing Sentry...")
|
||||||
sentry_sdk.init(sentry_dsn,
|
sentry_sdk.init(sentry_dsn,
|
||||||
integrations=[AioHttpIntegration(),
|
integrations=[AioHttpIntegration(),
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
from . import default
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"common",
|
|
||||||
]
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Various bot interfaces, and a common class to create new ones."""
|
from .serf import Serf
|
||||||
|
from .alchemyconfig import AlchemyConfig
|
||||||
|
|
||||||
from .serf import GenericBot
|
__all__ = [
|
||||||
from .telegram import TelegramBot
|
"Serf",
|
||||||
from .discord import DiscordBot
|
"AlchemyConfig"
|
||||||
|
]
|
||||||
__all__ = ["TelegramBot", "DiscordBot", "GenericBot"]
|
|
||||||
|
|
|
@ -5,8 +5,14 @@ from sqlalchemy.schema import Table
|
||||||
class AlchemyConfig:
|
class AlchemyConfig:
|
||||||
"""A helper class to configure :class:`Alchemy` in a :class:`Serf`."""
|
"""A helper class to configure :class:`Alchemy` in a :class:`Serf`."""
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
|
database_url: str,
|
||||||
master_table: Type[Table],
|
master_table: Type[Table],
|
||||||
identity_table: Type[Table],
|
identity_table: Type[Table],
|
||||||
):
|
identity_column: str):
|
||||||
|
self.database_url: str = database_url
|
||||||
self.master_table: Type[Table] = master_table
|
self.master_table: Type[Table] = master_table
|
||||||
self.identity_table: Type[Table] = identity_table
|
self.identity_table: Type[Table] = identity_table
|
||||||
|
self.identity_column: str = identity_column
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<{self.__class__.__qualname__} for {self.server_url}>"
|
|
@ -1,18 +1,19 @@
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union
|
from asyncio import Task, AbstractEventLoop
|
||||||
|
from typing import Type, Optional, Awaitable, Dict, List, Any, Callable, Union, Set
|
||||||
|
from keyring import get_password
|
||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
import keyring
|
|
||||||
from royalnet.herald import Response, ResponseSuccess, Broadcast, ResponseFailure, Request, Link
|
|
||||||
from royalnet.herald import Config as HeraldConfig
|
|
||||||
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
||||||
from sentry_sdk.integrations.aiohttp import AioHttpIntegration
|
from sentry_sdk.integrations.aiohttp import AioHttpIntegration
|
||||||
from sentry_sdk.integrations.logging import LoggingIntegration
|
from sentry_sdk.integrations.logging import LoggingIntegration
|
||||||
|
from sqlalchemy.schema import Table
|
||||||
|
from royalnet import __version__ as version
|
||||||
from royalnet.commands import Command, CommandInterface, CommandData, CommandError, UnsupportedError
|
from royalnet.commands import Command, CommandInterface, CommandData, CommandError, UnsupportedError
|
||||||
from royalnet.alchemy import Alchemy
|
from royalnet.alchemy import Alchemy, table_dfs
|
||||||
|
from royalnet.herald import Response, ResponseSuccess, Broadcast, ResponseFailure, Request, Link
|
||||||
|
from royalnet.herald import Config as HeraldConfig
|
||||||
from .alchemyconfig import AlchemyConfig
|
from .alchemyconfig import AlchemyConfig
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,13 +26,25 @@ class Serf:
|
||||||
alchemy_config: Optional[AlchemyConfig] = None,
|
alchemy_config: Optional[AlchemyConfig] = None,
|
||||||
commands: List[Type[Command]] = None,
|
commands: List[Type[Command]] = None,
|
||||||
network_config: Optional[HeraldConfig] = None,
|
network_config: Optional[HeraldConfig] = None,
|
||||||
sentry_dsn: Optional[str] = None,
|
|
||||||
loop: asyncio.AbstractEventLoop = None,
|
|
||||||
secrets_name: str = "__default__"):
|
secrets_name: str = "__default__"):
|
||||||
self.secrets_name = secrets_name
|
self.secrets_name = secrets_name
|
||||||
|
|
||||||
|
self.alchemy: Optional[Alchemy] = None
|
||||||
|
"""The :class:`Alchemy` object connecting this Serf to the database."""
|
||||||
|
|
||||||
|
self._master_table: Optional[Table] = None
|
||||||
|
"""The central table listing all users. It usually is :class:`User`."""
|
||||||
|
|
||||||
|
self._identity_table: Optional[Table] = None
|
||||||
|
"""The identity table containing the interface data (such as the Telegram user data) and that is in a
|
||||||
|
many-to-one relationship with the master table."""
|
||||||
|
|
||||||
|
# TODO: I'm not sure what this is either
|
||||||
|
self._identity_column: Optional[str] = None
|
||||||
|
|
||||||
if alchemy_config is not None:
|
if alchemy_config is not None:
|
||||||
self.init_alchemy(alchemy_config)
|
tables = self.find_tables(alchemy_config, commands)
|
||||||
|
self.init_alchemy(alchemy_config, tables)
|
||||||
|
|
||||||
self.Interface: Type[CommandInterface] = self.interface_factory()
|
self.Interface: Type[CommandInterface] = self.interface_factory()
|
||||||
"""The :class:`CommandInterface` class of this Serf."""
|
"""The :class:`CommandInterface` class of this Serf."""
|
||||||
|
@ -53,19 +66,55 @@ class Serf:
|
||||||
self.herald: Optional[Link] = None
|
self.herald: Optional[Link] = None
|
||||||
"""The :class:`Link` object connecting the Serf to the rest of the herald network."""
|
"""The :class:`Link` object connecting the Serf to the rest of the herald network."""
|
||||||
|
|
||||||
self.herald_task: Optional[asyncio.Task] = None
|
self.herald_task: Optional[Task] = None
|
||||||
"""A reference to the :class:`asyncio.Task` that runs the :class:`Link`."""
|
"""A reference to the :class:`asyncio.Task` that runs the :class:`Link`."""
|
||||||
|
|
||||||
if network_config is not None:
|
if network_config is not None:
|
||||||
self.init_network(network_config)
|
self.init_network(network_config)
|
||||||
|
|
||||||
|
self.loop: Optional[AbstractEventLoop] = None
|
||||||
|
"""The event loop this Serf is running on."""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def find_tables(alchemy_config: AlchemyConfig, commands: List[Type[Command]]) -> Set[type]:
|
||||||
|
"""Find the :class:`Table`s required by the Serf.
|
||||||
|
|
||||||
|
Warning:
|
||||||
|
This function will return a wrong result if there are tables between the master table and the identity table
|
||||||
|
that aren't included by a command.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A :class:`list` of :class:`Table`s."""
|
||||||
|
# FIXME: breaks if there are nonincluded tables between master and identity.
|
||||||
|
tables = {alchemy_config.master_table, alchemy_config.identity_table}
|
||||||
|
for command in commands:
|
||||||
|
tables = tables.union(command.tables)
|
||||||
|
return tables
|
||||||
|
|
||||||
|
def init_alchemy(self, alchemy_config: AlchemyConfig, tables: Set[type]) -> None:
|
||||||
|
"""Create and initialize the :class:`Alchemy` with the required tables, and find the link between the master
|
||||||
|
table and the identity table."""
|
||||||
|
self.alchemy = Alchemy(alchemy_config.database_url, tables)
|
||||||
|
self._master_table = self.alchemy.get(alchemy_config.master_table)
|
||||||
|
self._identity_table = self.alchemy.get(alchemy_config.identity_table)
|
||||||
|
# FIXME: this MAY break
|
||||||
|
self._identity_column = self._identity_table.__getattribute__(alchemy_config.identity_column)
|
||||||
|
# self._identity_column = self._identity_table.__getattribute__(self._identity_table,
|
||||||
|
# alchemy_config.identity_column)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _identity_chain(self) -> tuple:
|
||||||
|
"""Find a relationship path starting from the master table and ending at the identity table, and return it."""
|
||||||
|
return table_dfs(self._master_table, self._identity_table)
|
||||||
|
|
||||||
def interface_factory(self) -> Type[CommandInterface]:
|
def interface_factory(self) -> Type[CommandInterface]:
|
||||||
"""Create the :class:`CommandInterface` class for the Serf."""
|
"""Create the :class:`CommandInterface` class for the Serf."""
|
||||||
|
|
||||||
# noinspection PyMethodParameters
|
# noinspection PyMethodParameters
|
||||||
class GenericInterface(CommandInterface):
|
class GenericInterface(CommandInterface):
|
||||||
alchemy: Alchemy = self.alchemy
|
alchemy: Alchemy = self.alchemy
|
||||||
bot: "Serf" = self
|
bot: "Serf" = self
|
||||||
loop: asyncio.AbstractEventLoop = self.loop
|
loop: AbstractEventLoop = self.loop
|
||||||
|
|
||||||
def register_herald_action(ci,
|
def register_herald_action(ci,
|
||||||
event_name: str,
|
event_name: str,
|
||||||
|
@ -171,86 +220,44 @@ class Serf:
|
||||||
return ResponseFailure("exception_in_handler",
|
return ResponseFailure("exception_in_handler",
|
||||||
f"An exception was raised in {network_handler} for {message.handler}.",
|
f"An exception was raised in {network_handler} for {message.handler}.",
|
||||||
extra_info={
|
extra_info={
|
||||||
"type": e.__class__.__name__,
|
"type": e.__class__.__name__,
|
||||||
"message": str(e)
|
"message": str(e)
|
||||||
})
|
})
|
||||||
elif isinstance(message, Broadcast):
|
elif isinstance(message, Broadcast):
|
||||||
await network_handler(self, **message.data)
|
await network_handler(self, **message.data)
|
||||||
|
|
||||||
def _init_database(self):
|
def init_sentry(self):
|
||||||
"""Create an :py:class:`royalnet.database.Alchemy` with the tables required by the packs. Then,
|
sentry_dsn = self.get_secret("sentry")
|
||||||
find the chain that links the ``master_table`` to the ``identity_table``. """
|
if sentry_dsn:
|
||||||
if self.uninitialized_database_config:
|
|
||||||
log.info(f"Alchemy: enabled")
|
|
||||||
required_tables = {self.uninitialized_database_config.master_table, self.uninitialized_database_config.identity_table}
|
|
||||||
for command in self.uninitialized_commands:
|
|
||||||
required_tables = required_tables.union(command.tables)
|
|
||||||
log.debug(f"Required tables: {', '.join([item.__qualname__ for item in required_tables])}")
|
|
||||||
self.alchemy = Alchemy(self.uninitialized_database_config.database_uri, required_tables)
|
|
||||||
self.master_table = self.alchemy.__getattribute__(self.uninitialized_database_config.master_table.__name__)
|
|
||||||
log.debug(f"Master table: {self.master_table.__qualname__}")
|
|
||||||
self.identity_table = self.alchemy.__getattribute__(self.uninitialized_database_config.identity_table.__name__)
|
|
||||||
log.debug(f"Identity table: {self.identity_table.__qualname__}")
|
|
||||||
self.identity_column = self.identity_table.__getattribute__(self.identity_table,
|
|
||||||
self.uninitialized_database_config.identity_column_name)
|
|
||||||
log.debug(f"Identity column: {self.identity_column.__class__.__qualname__}")
|
|
||||||
self.identity_chain = table_dfs(self.master_table, self.identity_table)
|
|
||||||
log.debug(f"Identity chain: {' -> '.join([str(item) for item in self.identity_chain])}")
|
|
||||||
else:
|
|
||||||
log.info(f"Alchemy: disabled")
|
|
||||||
self.alchemy = None
|
|
||||||
self.master_table = None
|
|
||||||
self.identity_table = None
|
|
||||||
self.identity_column = None
|
|
||||||
|
|
||||||
def _init_sentry(self):
|
|
||||||
if self.uninitialized_sentry_dsn:
|
|
||||||
# noinspection PyUnreachableCode
|
# noinspection PyUnreachableCode
|
||||||
if __debug__:
|
if __debug__:
|
||||||
release = "DEV"
|
release = f"Dev"
|
||||||
else:
|
else:
|
||||||
release = royalnet.version.semantic
|
release = f"{version}"
|
||||||
|
log.debug("Initializing Sentry...")
|
||||||
|
sentry_sdk.init(sentry_dsn,
|
||||||
|
integrations=[AioHttpIntegration(),
|
||||||
|
SqlalchemyIntegration(),
|
||||||
|
LoggingIntegration(event_level=None)],
|
||||||
|
release=release)
|
||||||
log.info(f"Sentry: enabled (Royalnet {release})")
|
log.info(f"Sentry: enabled (Royalnet {release})")
|
||||||
self.sentry = sentry_sdk.init(self.uninitialized_sentry_dsn,
|
|
||||||
integrations=[AioHttpIntegration(),
|
|
||||||
SqlalchemyIntegration(),
|
|
||||||
LoggingIntegration(event_level=None)],
|
|
||||||
release=release)
|
|
||||||
else:
|
else:
|
||||||
log.info("Sentry: disabled")
|
log.info("Sentry: disabled")
|
||||||
|
|
||||||
def _init_loop(self):
|
|
||||||
if self.uninitialized_loop is None:
|
|
||||||
self.loop = asyncio.get_event_loop()
|
|
||||||
else:
|
|
||||||
self.loop = self.uninitialized_loop
|
|
||||||
|
|
||||||
def get_secret(self, username: str):
|
def get_secret(self, username: str):
|
||||||
return keyring.get_password(f"Royalnet/{self.secrets_name}", username)
|
"""Get a Royalnet secret from the keyring.
|
||||||
|
|
||||||
def set_secret(self, username: str, password: str):
|
Args:
|
||||||
return keyring.set_password(f"Royalnet/{self.secrets_name}", username, password)
|
username: the name of the secret that should be retrieved."""
|
||||||
|
return get_password(f"Royalnet/{self.secrets_name}", username)
|
||||||
|
|
||||||
def _initialize(self):
|
async def run(self):
|
||||||
if not self.initialized:
|
"""A coroutine that starts the event loop and handles command calls."""
|
||||||
self._init_sentry()
|
|
||||||
self._init_loop()
|
|
||||||
self._init_database()
|
|
||||||
self._init_commands()
|
|
||||||
self.init_network()
|
|
||||||
self.initialized = True
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
"""A blocking coroutine that should make the bot start listening to packs and requests."""
|
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def run_blocking(self, verbose=False):
|
def run_blocking(self):
|
||||||
if verbose:
|
"""Blockingly run the Serf.
|
||||||
core_logger = logging.root
|
|
||||||
core_logger.setLevel(logging.DEBUG)
|
This should be used as the target of a :class:`multiprocessing.Process`."""
|
||||||
stream_handler = logging.StreamHandler()
|
self.init_sentry()
|
||||||
stream_handler.formatter = logging.Formatter("{asctime}\t{name}\t{levelname}\t{message}", style="{")
|
|
||||||
core_logger.addHandler(stream_handler)
|
|
||||||
core_logger.debug("Logging setup complete.")
|
|
||||||
self._initialize()
|
|
||||||
self.loop.run_until_complete(self.run())
|
self.loop.run_until_complete(self.run())
|
||||||
|
|
|
@ -1,110 +1,48 @@
|
||||||
import telegram
|
import logging
|
||||||
import telegram.utils.request
|
|
||||||
import uuid
|
|
||||||
import urllib3
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import sentry_sdk
|
|
||||||
import logging as _logging
|
|
||||||
import warnings
|
import warnings
|
||||||
from .interface import GenericBot
|
import uuid
|
||||||
from ..utils import *
|
from typing import Type, Optional, Dict, List, Tuple, Callable
|
||||||
from ..error import *
|
import telegram
|
||||||
from ..commands import *
|
import urllib3
|
||||||
|
import sentry_sdk
|
||||||
|
from telegram.utils.request import Request as TRequest
|
||||||
|
from royalnet.commands import Command, CommandInterface, CommandData, CommandArgs, CommandError, InvalidInputError, \
|
||||||
|
UnsupportedError, KeyboardExpiredError
|
||||||
|
from royalnet.herald import Config as HeraldConfig
|
||||||
|
from royalnet.utils import asyncify
|
||||||
|
from .escape import escape
|
||||||
|
from ..alchemyconfig import AlchemyConfig
|
||||||
|
from ..serf import Serf
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
log = _logging.getLogger(__name__)
|
class TelegramSerf(Serf):
|
||||||
|
"""A Serf that connects to `Telegram <https://telegram.org/>`_."""
|
||||||
|
|
||||||
class TelegramBot(GenericBot):
|
|
||||||
"""A bot that connects to `Telegram <https://telegram.org/>`_."""
|
|
||||||
interface_name = "telegram"
|
interface_name = "telegram"
|
||||||
|
|
||||||
def _init_client(self):
|
def __init__(self, *,
|
||||||
"""Create the :py:class:`telegram.Bot`, and set the starting offset."""
|
alchemy_config: Optional[AlchemyConfig] = None,
|
||||||
# https://github.com/python-telegram-bot/python-telegram-bot/issues/341
|
commands: List[Type[Command]] = None,
|
||||||
request = telegram.utils.request.Request(5, read_timeout=30)
|
network_config: Optional[HeraldConfig] = None,
|
||||||
token = self.get_secret("telegram")
|
secrets_name: str = "__default__"):
|
||||||
self.client = telegram.Bot(token, request=request)
|
super().__init__(alchemy_config=alchemy_config,
|
||||||
self._offset: int = -100
|
commands=commands,
|
||||||
|
network_config=network_config,
|
||||||
|
secrets_name=secrets_name)
|
||||||
|
|
||||||
def _interface_factory(self) -> typing.Type[CommandInterface]:
|
self.client = telegram.Bot(self.get_secret("telegram"), request=TRequest(5, read_timeout=30))
|
||||||
# noinspection PyPep8Naming
|
"""The :class:`telegram.Bot` instance that will be used from the Serf."""
|
||||||
GenericInterface = super().interface_factory()
|
|
||||||
|
|
||||||
# noinspection PyMethodParameters,PyAbstractClass
|
self.update_offset: int = -100
|
||||||
class TelegramInterface(GenericInterface):
|
"""The current `update offset <https://core.telegram.org/bots/api#getupdates>`_."""
|
||||||
name = self.interface_name
|
|
||||||
prefix = "/"
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.keys_callbacks: typing.Dict[typing.Tuple[int, str], typing.Callable] = {}
|
|
||||||
|
|
||||||
def register_keyboard_key(interface, key_name: str, callback: typing.Callable):
|
|
||||||
interface.keys_callbacks[key_name] = callback
|
|
||||||
|
|
||||||
def unregister_keyboard_key(interface, key_name: str):
|
|
||||||
try:
|
|
||||||
del interface.keys_callbacks[key_name]
|
|
||||||
except KeyError:
|
|
||||||
raise KeyError(f"Key '{key_name}' is not registered")
|
|
||||||
|
|
||||||
return TelegramInterface
|
|
||||||
|
|
||||||
def _data_factory(self) -> typing.Type[CommandData]:
|
|
||||||
# noinspection PyMethodParameters,PyAbstractClass
|
|
||||||
class TelegramData(CommandData):
|
|
||||||
def __init__(data, interface: CommandInterface, update: telegram.Update):
|
|
||||||
super().__init__(interface)
|
|
||||||
data.update = update
|
|
||||||
|
|
||||||
async def reply(data, text: str):
|
|
||||||
await TelegramBot.safe_api_call(data.update.effective_chat.send_message,
|
|
||||||
telegram_escape(text),
|
|
||||||
parse_mode="HTML",
|
|
||||||
disable_web_page_preview=True)
|
|
||||||
|
|
||||||
async def get_author(data, error_if_none=False):
|
|
||||||
if data.update.message is not None:
|
|
||||||
user: telegram.User = data.update.message.from_user
|
|
||||||
elif data.update.callback_query is not None:
|
|
||||||
user: telegram.user = data.update.callback_query.from_user
|
|
||||||
else:
|
|
||||||
raise CommandError("Command caller can not be determined")
|
|
||||||
if user is None:
|
|
||||||
if error_if_none:
|
|
||||||
raise CommandError("No command caller for this message")
|
|
||||||
return None
|
|
||||||
query = data.session.query(self.master_table)
|
|
||||||
for link in self.identity_chain:
|
|
||||||
query = query.join(link.mapper.class_)
|
|
||||||
query = query.filter(self.identity_column == user.id)
|
|
||||||
result = await asyncify(query.one_or_none)
|
|
||||||
if result is None and error_if_none:
|
|
||||||
raise CommandError("Command caller is not registered")
|
|
||||||
return result
|
|
||||||
|
|
||||||
async def keyboard(data, text: str, keyboard: typing.Dict[str, typing.Callable]) -> None:
|
|
||||||
warnings.warn("keyboard is deprecated, please avoid using it", category=DeprecationWarning)
|
|
||||||
tg_keyboard = []
|
|
||||||
for key in keyboard:
|
|
||||||
press_id = uuid.uuid4()
|
|
||||||
tg_keyboard.append([telegram.InlineKeyboardButton(key, callback_data=str(press_id))])
|
|
||||||
data._interface.register_keyboard_key(key_name=str(press_id), callback=keyboard[key])
|
|
||||||
await TelegramBot.safe_api_call(data.update.effective_chat.send_message,
|
|
||||||
telegram_escape(text),
|
|
||||||
reply_markup=telegram.InlineKeyboardMarkup(tg_keyboard),
|
|
||||||
parse_mode="HTML",
|
|
||||||
disable_web_page_preview=True)
|
|
||||||
|
|
||||||
async def delete_invoking(data, error_if_unavailable=False) -> None:
|
|
||||||
message: telegram.Message = data.update.message
|
|
||||||
await TelegramBot.safe_api_call(message.delete)
|
|
||||||
|
|
||||||
return TelegramData
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def safe_api_call(f: typing.Callable, *args, **kwargs) -> typing.Optional:
|
async def api_call(f: Callable, *args, **kwargs) -> Optional:
|
||||||
|
"""Call a :class:`telegram.Bot` method safely, without getting a mess of errors raised.
|
||||||
|
|
||||||
|
The method may return None if it was decided that the call should be skipped."""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
return await asyncify(f, *args, **kwargs)
|
return await asyncify(f, *args, **kwargs)
|
||||||
|
@ -131,7 +69,86 @@ class TelegramBot(GenericBot):
|
||||||
break
|
break
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def interface_factory(self) -> Type[CommandInterface]:
|
||||||
|
# noinspection PyPep8Naming
|
||||||
|
GenericInterface = super().interface_factory()
|
||||||
|
|
||||||
|
# noinspection PyMethodParameters
|
||||||
|
class TelegramInterface(GenericInterface):
|
||||||
|
name = self.interface_name
|
||||||
|
prefix = "/"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.keys_callbacks: Dict[..., Callable] = {}
|
||||||
|
|
||||||
|
def register_keyboard_key(interface, key_name: ..., callback: Callable):
|
||||||
|
warnings.warn("register_keyboard_key is deprecated", category=DeprecationWarning)
|
||||||
|
interface.keys_callbacks[key_name] = callback
|
||||||
|
|
||||||
|
def unregister_keyboard_key(interface, key_name: ...):
|
||||||
|
warnings.warn("unregister_keyboard_key is deprecated", category=DeprecationWarning)
|
||||||
|
try:
|
||||||
|
del interface.keys_callbacks[key_name]
|
||||||
|
except KeyError:
|
||||||
|
raise KeyError(f"Key '{key_name}' is not registered")
|
||||||
|
|
||||||
|
return TelegramInterface
|
||||||
|
|
||||||
|
def data_factory(self) -> Type[CommandData]:
|
||||||
|
# noinspection PyMethodParameters
|
||||||
|
class TelegramData(CommandData):
|
||||||
|
def __init__(data, interface: CommandInterface, update: telegram.Update):
|
||||||
|
super().__init__(interface)
|
||||||
|
data.update = update
|
||||||
|
|
||||||
|
async def reply(data, text: str):
|
||||||
|
await self.api_call(data.update.effective_chat.send_message,
|
||||||
|
escape(text),
|
||||||
|
parse_mode="HTML",
|
||||||
|
disable_web_page_preview=True)
|
||||||
|
|
||||||
|
async def get_author(data, error_if_none=False):
|
||||||
|
if data.update.message is not None:
|
||||||
|
user: telegram.User = data.update.message.from_user
|
||||||
|
elif data.update.callback_query is not None:
|
||||||
|
user: telegram.User = data.update.callback_query.from_user
|
||||||
|
else:
|
||||||
|
raise CommandError("Command caller can not be determined")
|
||||||
|
if user is None:
|
||||||
|
if error_if_none:
|
||||||
|
raise CommandError("No command caller for this message")
|
||||||
|
return None
|
||||||
|
query = data.session.query(self._master_table)
|
||||||
|
for link in self._identity_chain:
|
||||||
|
query = query.join(link.mapper.class_)
|
||||||
|
query = query.filter(self._identity_column == user.id)
|
||||||
|
result = await asyncify(query.one_or_none)
|
||||||
|
if result is None and error_if_none:
|
||||||
|
raise CommandError("Command caller is not registered")
|
||||||
|
return result
|
||||||
|
|
||||||
|
async def keyboard(data, text: str, keyboard: Dict[str, Callable]) -> None:
|
||||||
|
warnings.warn("keyboard is deprecated, please avoid using it", category=DeprecationWarning)
|
||||||
|
tg_keyboard = []
|
||||||
|
for key in keyboard:
|
||||||
|
press_id = uuid.uuid4()
|
||||||
|
tg_keyboard.append([telegram.InlineKeyboardButton(key, callback_data=str(press_id))])
|
||||||
|
data._interface.register_keyboard_key(key_name=str(press_id), callback=keyboard[key])
|
||||||
|
await self.api_call(data.update.effective_chat.send_message,
|
||||||
|
escape(text),
|
||||||
|
reply_markup=telegram.InlineKeyboardMarkup(tg_keyboard),
|
||||||
|
parse_mode="HTML",
|
||||||
|
disable_web_page_preview=True)
|
||||||
|
|
||||||
|
async def delete_invoking(data, error_if_unavailable=False) -> None:
|
||||||
|
message: telegram.Message = data.update.message
|
||||||
|
await self.api_call(message.delete)
|
||||||
|
|
||||||
|
return TelegramData
|
||||||
|
|
||||||
async def _handle_update(self, update: telegram.Update):
|
async def _handle_update(self, update: telegram.Update):
|
||||||
|
"""What should be done when a :class:`telegram.Update` is received?"""
|
||||||
# Skip non-message updates
|
# Skip non-message updates
|
||||||
if update.message is not None:
|
if update.message is not None:
|
||||||
await self._handle_message(update)
|
await self._handle_message(update)
|
||||||
|
@ -139,6 +156,7 @@ class TelegramBot(GenericBot):
|
||||||
await self._handle_callback_query(update)
|
await self._handle_callback_query(update)
|
||||||
|
|
||||||
async def _handle_message(self, update: telegram.Update):
|
async def _handle_message(self, update: telegram.Update):
|
||||||
|
"""What should be done when a :class:`telegram.Message` is received?"""
|
||||||
message: telegram.Message = update.message
|
message: telegram.Message = update.message
|
||||||
text: str = message.text
|
text: str = message.text
|
||||||
# Try getting the caption instead
|
# Try getting the caption instead
|
||||||
|
@ -154,7 +172,7 @@ class TelegramBot(GenericBot):
|
||||||
command_text, *parameters = text.split(" ")
|
command_text, *parameters = text.split(" ")
|
||||||
command_name = command_text.replace(f"@{self.client.username}", "").lower()
|
command_name = command_text.replace(f"@{self.client.username}", "").lower()
|
||||||
# Send a typing notification
|
# Send a typing notification
|
||||||
await self.safe_api_call(update.message.chat.send_action, telegram.ChatAction.TYPING)
|
await self.api_call(update.message.chat.send_action, telegram.ChatAction.TYPING)
|
||||||
# Find the command
|
# Find the command
|
||||||
try:
|
try:
|
||||||
command = self.commands[command_name]
|
command = self.commands[command_name]
|
||||||
|
@ -162,7 +180,7 @@ class TelegramBot(GenericBot):
|
||||||
# Skip the message
|
# Skip the message
|
||||||
return
|
return
|
||||||
# Prepare data
|
# Prepare data
|
||||||
data = self._Data(interface=command.interface, update=update)
|
data = self.Data(interface=command.interface, update=update)
|
||||||
try:
|
try:
|
||||||
# Run the command
|
# Run the command
|
||||||
await command.run(CommandArgs(parameters), data)
|
await command.run(CommandArgs(parameters), data)
|
||||||
|
@ -185,18 +203,18 @@ class TelegramBot(GenericBot):
|
||||||
async def _handle_callback_query(self, update: telegram.Update):
|
async def _handle_callback_query(self, update: telegram.Update):
|
||||||
query: telegram.CallbackQuery = update.callback_query
|
query: telegram.CallbackQuery = update.callback_query
|
||||||
source: telegram.Message = query.message
|
source: telegram.Message = query.message
|
||||||
callback: typing.Optional[typing.Callable] = None
|
callback: Optional[Callable] = None
|
||||||
command: typing.Optional[Command] = None
|
command: Optional[Command] = None
|
||||||
for command in self.commands.values():
|
for command in self.commands.values():
|
||||||
if query.data in command.interface.keys_callbacks:
|
if query.data in command.interface.keys_callbacks:
|
||||||
callback = command.interface.keys_callbacks[query.data]
|
callback = command.interface.keys_callbacks[query.data]
|
||||||
break
|
break
|
||||||
if callback is None:
|
if callback is None:
|
||||||
await self.safe_api_call(source.edit_reply_markup, reply_markup=None)
|
await self.api_call(source.edit_reply_markup, reply_markup=None)
|
||||||
await self.safe_api_call(query.answer, text="⛔️ This keyboard has expired.")
|
await self.api_call(query.answer, text="⛔️ This keyboard has expired.")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
response = await callback(data=self._Data(interface=command.interface, update=update))
|
response = await callback(data=self.Data(interface=command.interface, update=update))
|
||||||
except KeyboardExpiredError as e:
|
except KeyboardExpiredError as e:
|
||||||
# FIXME: May cause a memory leak, as keys are not deleted after use
|
# FIXME: May cause a memory leak, as keys are not deleted after use
|
||||||
await self.safe_api_call(source.edit_reply_markup, reply_markup=None)
|
await self.safe_api_call(source.edit_reply_markup, reply_markup=None)
|
||||||
|
@ -221,10 +239,10 @@ class TelegramBot(GenericBot):
|
||||||
self._initialize()
|
self._initialize()
|
||||||
while True:
|
while True:
|
||||||
# Get the latest 100 updates
|
# Get the latest 100 updates
|
||||||
last_updates: typing.List[telegram.Update] = await self.safe_api_call(self.client.get_updates,
|
last_updates: List[telegram.Update] = await self.safe_api_call(self.client.get_updates,
|
||||||
offset=self._offset,
|
offset=self._offset,
|
||||||
timeout=30,
|
timeout=30,
|
||||||
read_latency=5.0)
|
read_latency=5.0)
|
||||||
# Handle updates
|
# Handle updates
|
||||||
for update in last_updates:
|
for update in last_updates:
|
||||||
# noinspection PyAsyncCall
|
# noinspection PyAsyncCall
|
Loading…
Reference in a new issue