diff --git a/poetry.lock b/poetry.lock index 1d194772..5b687bff 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,13 @@ [[package]] -category = "main" -description = "Async http client/server framework (asyncio)" name = "aiohttp" +version = "3.6.2" +description = "Async http client/server framework (asyncio)" +category = "main" optional = false python-versions = ">=3.5.3" -version = "3.6.2" + +[package.extras] +speedups = ["aiodns", "brotlipy", "cchardet"] [package.dependencies] async-timeout = ">=3.0,<4.0" @@ -13,24 +16,21 @@ chardet = ">=2.0,<4.0" multidict = ">=4.5,<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" +version = "3.0.1" +description = "Timeout context manager for asyncio programs" +category = "main" optional = false python-versions = ">=3.5.3" -version = "3.0.1" [[package]] -category = "main" -description = "Classes Without Boilerplate" name = "attrs" +version = "19.3.0" +description = "Classes Without Boilerplate" +category = "main" optional = false 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"] @@ -39,98 +39,95 @@ docs = ["sphinx", "zope.interface"] tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] [[package]] -category = "main" -description = "Modern password hashing for your software and your servers" name = "bcrypt" +version = "3.2.0" +description = "Modern password hashing for your software and your servers" +category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.1.7" +python-versions = ">=3.6" + +[package.extras] +tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)"] +typecheck = ["mypy"] [package.dependencies] cffi = ">=1.1" six = ">=1.4.1" -[package.extras] -tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)"] - [[package]] -category = "main" -description = "Extensible memoizing collections and decorators" name = "cachetools" +version = "4.1.1" +description = "Extensible memoizing collections and decorators" +category = "main" optional = false python-versions = "~=3.5" -version = "4.1.1" [[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." name = "certifi" +version = "2020.6.20" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = "*" -version = "2020.6.20" [[package]] -category = "main" -description = "Foreign Function Interface for Python calling C code." name = "cffi" +version = "1.14.2" +description = "Foreign Function Interface for Python calling C code." +category = "main" optional = false python-versions = "*" -version = "1.14.0" [package.dependencies] pycparser = "*" [[package]] -category = "main" -description = "Universal encoding detector for Python 2 and 3" name = "chardet" -optional = false -python-versions = "*" version = "3.0.4" - -[[package]] +description = "Universal encoding detector for Python 2 and 3" category = "main" -description = "Composable command line interface toolkit" -name = "click" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "7.1.2" - -[[package]] -category = "main" -description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\"" -name = "colorama" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.4.3" - -[[package]] -category = "main" -description = "Colored terminal output for Python's logging module" -name = "coloredlogs" optional = false python-versions = "*" + +[[package]] +name = "click" +version = "7.1.2" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[[package]] +name = "colorama" +version = "0.4.3" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +marker = "sys_platform == \"win32\"" + +[[package]] +name = "coloredlogs" version = "10.0" +description = "Colored terminal output for Python's logging module" +category = "main" +optional = false +python-versions = "*" + +[package.extras] +cron = ["capturer (>=2.4)"] [package.dependencies] colorama = "*" humanfriendly = ">=4.7" -[package.extras] -cron = ["capturer (>=2.4)"] - [[package]] -category = "main" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." name = "cryptography" +version = "3.0" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "3.0" - -[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,<3.1.0 || >3.1.0,<3.1.1 || >3.1.1)", "sphinx-rtd-theme"] @@ -140,13 +137,17 @@ 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)"] +[package.dependencies] +cffi = ">=1.8,<1.11.3 || >1.11.3" +six = ">=1.4.1" + [[package]] -category = "main" -description = "Date parsing library designed to parse dates from HTML pages" name = "dateparser" +version = "0.7.6" +description = "Date parsing library designed to parse dates from HTML pages" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.7.6" [package.dependencies] python-dateutil = "*" @@ -155,237 +156,162 @@ regex = "!=2019.02.19" tzlocal = "*" [[package]] -category = "main" -description = "Decorators for Humans" name = "decorator" +version = "4.4.2" +description = "Decorators for Humans" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.4.2" [[package]] -category = "main" -description = "A library to handle automated deprecations" -name = "deprecation" -optional = false -python-versions = "*" -version = "2.1.0" - -[package.dependencies] -packaging = "*" - -[[package]] -category = "main" -description = "A Python wrapper for the Discord API" name = "discord.py" +version = "1.4.1" +description = "A Python wrapper for the Discord API" +category = "main" optional = false python-versions = ">=3.5.3" -version = "1.3.4" - -[package.dependencies] -aiohttp = ">=3.6.0,<3.7.0" -websockets = ">=6.0,<7.0 || >7.0,<8.0 || >8.0,<8.0.1 || >8.0.1,<9.0" [package.extras] docs = ["sphinx (1.8.5)", "sphinxcontrib-trio (1.1.1)", "sphinxcontrib-websupport"] voice = ["PyNaCl (1.3.0)"] -[[package]] -category = "main" -description = "Python audio data toolkit (ID3 and MP3)" -name = "eyed3" -optional = false -python-versions = "*" -version = "0.9.5" - [package.dependencies] -deprecation = "*" -filetype = "*" - -[package.extras] -art-plugin = ["pylast", "requests", "pillow"] -display-plugin = ["grako"] -yaml-plugin = ["ruamel.yaml"] +aiohttp = ">=3.6.0,<3.7.0" [[package]] -category = "main" -description = "Python bindings for FFmpeg - with complex filtering support" -name = "ffmpeg-python" -optional = false -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 = "Infer file type and MIME type of any file/buffer. No external dependencies." -name = "filetype" -optional = false -python-versions = "*" -version = "1.0.7" - -[[package]] -category = "main" -description = "Clean single-source support for Python 3 and 2" -name = "future" -optional = false -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 = false -python-versions = "*" version = "0.9.0" - -[[package]] +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 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 = false python-versions = "*" -version = "0.0.13" [[package]] +name = "httptools" +version = "0.0.13" +description = "A collection of framework independent HTTP protocol utils." category = "main" -description = "Human friendly output for text interfaces using Python" +optional = false +python-versions = "*" +marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"pypy\"" + +[[package]] name = "humanfriendly" +version = "8.2" +description = "Human friendly output for text interfaces using Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "8.2" [package.dependencies] pyreadline = "*" [[package]] -category = "main" -description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.10" - -[[package]] +description = "Internationalized Domain Names in Applications (IDNA)" category = "main" -description = "Various helpers to pass data to untrusted environments and back." -name = "itsdangerous" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.1.0" [[package]] +name = "itsdangerous" +version = "1.1.0" +description = "Various helpers to pass data to untrusted environments and back." category = "main" -description = "multidict implementation" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] name = "multidict" +version = "4.7.6" +description = "multidict implementation" +category = "main" optional = false python-versions = ">=3.5" -version = "4.7.6" [[package]] -category = "main" -description = "Core utilities for Python packages" -name = "packaging" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.4" - -[package.dependencies] -pyparsing = ">=2.0.2" -six = "*" - -[[package]] -category = "main" -description = "psycopg2 - Python-PostgreSQL Database Adapter" name = "psycopg2-binary" +version = "2.8.5" +description = "psycopg2 - Python-PostgreSQL Database Adapter" +category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "2.8.5" [[package]] -category = "main" -description = "C parser in Python" name = "pycparser" +version = "2.20" +description = "C parser in Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.20" [[package]] -category = "main" -description = "Cryptographic library for Python" name = "pycryptodomex" +version = "3.9.8" +description = "Cryptographic library for Python" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.8" [[package]] -category = "main" -description = "Python binding to the Networking and Cryptography (NaCl) library" name = "pynacl" +version = "1.4.0" +description = "Python binding to the Networking and Cryptography (NaCl) library" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.4.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 = "Python parsing module" -name = "pyparsing" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.7" +[package.dependencies] +cffi = ">=1.4.1" +six = "*" [[package]] -category = "main" -description = "A python implmementation of GNU readline." -marker = "sys_platform == \"win32\"" name = "pyreadline" +version = "2.1" +description = "A python implmementation of GNU readline." +category = "main" optional = false python-versions = "*" -version = "2.1" +marker = "sys_platform == \"win32\"" [[package]] -category = "main" -description = "Extensions to the standard Python datetime module" name = "python-dateutil" +version = "2.8.1" +description = "Extensions to the standard Python datetime module" +category = "main" 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 = "A streaming multipart parser for Python" name = "python-multipart" +version = "0.0.5" +description = "A streaming multipart parser for Python" +category = "main" optional = false python-versions = "*" -version = "0.0.5" [package.dependencies] six = ">=1.4.0" [[package]] -category = "main" -description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" +version = "12.8" +description = "We have made you a wrapper you can't refuse" +category = "main" optional = false python-versions = "*" -version = "12.8" + +[package.extras] +json = ["ujson"] +socks = ["pysocks"] [package.dependencies] certifi = "*" @@ -393,33 +319,33 @@ cryptography = "*" decorator = ">=4.4.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 = "2020.1" - -[[package]] +description = "World timezone definitions, modern and historical" category = "main" -description = "Alternative regular expression module, to replace re." -name = "regex" optional = false python-versions = "*" -version = "2020.7.14" [[package]] +name = "regex" +version = "2020.7.14" +description = "Alternative regular expression module, to replace re." category = "main" -description = "Python HTTP for Humans." +optional = false +python-versions = "*" + +[[package]] name = "requests" +version = "2.24.0" +description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.24.0" + +[package.extras] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [package.dependencies] certifi = ">=2017.4.17" @@ -427,127 +353,105 @@ chardet = ">=3.0.2,<4" idna = ">=2.5,<3" urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" -[package.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] - [[package]] -category = "main" -description = "RiotWatcher is a thin wrapper on top of the Riot Games API for League of Legends." name = "riotwatcher" +version = "3.0.0" +description = "RiotWatcher is a thin wrapper on top of the Riot Games API for League of Legends." +category = "main" optional = false python-versions = "*" -version = "3.0.0" - -[package.dependencies] -requests = "*" [package.extras] dev = ["coverage", "pre-commit", "pytest", "pytest-cov", "tox"] +[package.dependencies] +requests = "*" + [[package]] -category = "main" -description = "A multipurpose bot and web framework" name = "royalnet" +version = "5.11.0" +description = "A multipurpose bot and web framework" +category = "main" optional = false python-versions = ">=3.8,<4.0" -version = "5.10.4" + +[package.extras] +telegram = ["python_telegram_bot (>=12.2.0,<13.0.0)"] +discord = ["discord.py (>=1.3.1,<2.0.0)", "pynacl (>=1.3.0,<2.0.0)"] +alchemy_easy = ["sqlalchemy (>=1.3.18,<2.0.0)", "psycopg2_binary (>=2.8.4,<3.0.0)", "bcrypt (>=3.1.7,<4.0.0)"] +alchemy_hard = ["sqlalchemy (>=1.3.18,<2.0.0)", "psycopg2 (>=2.8.4,<3.0.0)", "bcrypt (>=3.1.7,<4.0.0)"] +constellation = ["starlette (>=0.12.13,<0.13.0)", "uvicorn (>=0.10.7,<0.11.0)", "python-multipart (>=0.0.5,<0.0.6)"] +sentry = ["sentry_sdk (>=0.13.2,<0.14.0)"] +herald = ["websockets (>=8.1,<9.0)"] +coloredlogs = ["coloredlogs (>=10.0,<11.0)"] [package.dependencies] dateparser = ">=0.7.2,<0.8.0" toml = ">=0.10.0,<0.11.0" [package.dependencies.bcrypt] -optional = true version = ">=3.1.7,<4.0.0" +optional = true [package.dependencies.coloredlogs] -optional = true version = ">=10.0,<11.0" +optional = true [package.dependencies."discord.py"] -optional = true version = ">=1.3.1,<2.0.0" - -[package.dependencies.eyed3] optional = true -version = ">=0.9,<0.10" - -[package.dependencies.ffmpeg_python] -optional = true -version = ">=0.2.0,<0.3.0" [package.dependencies.psycopg2_binary] -optional = true version = ">=2.8.4,<3.0.0" +optional = true [package.dependencies.pynacl] -optional = true version = ">=1.3.0,<2.0.0" +optional = true [package.dependencies.python-multipart] -optional = true version = ">=0.0.5,<0.0.6" +optional = true [package.dependencies.python_telegram_bot] -optional = true version = ">=12.2.0,<13.0.0" +optional = true [package.dependencies.sentry_sdk] -optional = true version = ">=0.13.2,<0.14.0" +optional = true [package.dependencies.sqlalchemy] -optional = true version = ">=1.3.18,<2.0.0" +optional = true [package.dependencies.starlette] -optional = true version = ">=0.12.13,<0.13.0" +optional = true [package.dependencies.uvicorn] -optional = true version = ">=0.10.7,<0.11.0" +optional = true [package.dependencies.websockets] -optional = true version = ">=8.1,<9.0" - -[package.dependencies.youtube_dl] optional = true -version = "*" - -[package.extras] -alchemy_easy = ["sqlalchemy (>=1.3.18,<2.0.0)", "psycopg2_binary (>=2.8.4,<3.0.0)", "bcrypt (>=3.1.7,<4.0.0)"] -alchemy_hard = ["sqlalchemy (>=1.3.18,<2.0.0)", "psycopg2 (>=2.8.4,<3.0.0)", "bcrypt (>=3.1.7,<4.0.0)"] -bard = ["ffmpeg_python (>=0.2.0,<0.3.0)", "youtube-dl", "eyed3 (>=0.9,<0.10)"] -coloredlogs = ["coloredlogs (>=10.0,<11.0)"] -constellation = ["starlette (>=0.12.13,<0.13.0)", "uvicorn (>=0.10.7,<0.11.0)", "python-multipart (>=0.0.5,<0.0.6)"] -discord = ["discord.py (>=1.3.1,<2.0.0)", "pynacl (>=1.3.0,<2.0.0)"] -herald = ["websockets (>=8.1,<9.0)"] -matrix = ["matrix-nio (>=0.6,<0.7)"] -sentry = ["sentry_sdk (>=0.13.2,<0.14.0)"] -telegram = ["python_telegram_bot (>=12.2.0,<13.0.0)"] [[package]] -category = "main" -description = "A package to procedurally generate useless spells!" name = "royalspells" +version = "3.2" +description = "A package to procedurally generate useless spells!" +category = "main" optional = false python-versions = "~=3.6" -version = "3.2" [[package]] -category = "main" -description = "Python client for Sentry (https://getsentry.com)" name = "sentry-sdk" +version = "0.13.5" +description = "Python client for Sentry (https://getsentry.com)" +category = "main" optional = false python-versions = "*" -version = "0.13.5" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.10.0" [package.extras] aiohttp = ["aiohttp (>=3.5)"] @@ -563,21 +467,25 @@ sanic = ["sanic (>=0.8)"] sqlalchemy = ["sqlalchemy (>=1.2)"] tornado = ["tornado (>=5)"] -[[package]] -category = "main" -description = "Python 2 and 3 compatibility utilities" -name = "six" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.15.0" +[package.dependencies] +certifi = "*" +urllib3 = ">=1.10.0" [[package]] +name = "six" +version = "1.15.0" +description = "Python 2 and 3 compatibility utilities" category = "main" -description = "Database Abstraction Library" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] name = "sqlalchemy" +version = "1.3.19" +description = "Database Abstraction Library" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.18" [package.extras] mssql = ["pyodbc"] @@ -592,23 +500,26 @@ postgresql_psycopg2cffi = ["psycopg2cffi"] pymysql = ["pymysql"] [[package]] -category = "main" -description = "The little ASGI library that shines." name = "starlette" +version = "0.12.13" +description = "The little ASGI library that shines." +category = "main" optional = false python-versions = ">=3.6" -version = "0.12.13" [package.extras] full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests", "ujson"] [[package]] -category = "main" -description = "Module for interacting with various Steam features" name = "steam" +version = "1.0.2" +description = "Module for interacting with various Steam features" +category = "main" optional = false python-versions = "*" -version = "1.0.2" + +[package.extras] +client = ["gevent (>=1.3.0)", "protobuf (>=3.0.0)", "gevent-eventemitter (>=2.1)"] [package.dependencies] cachetools = ">=3.0.0" @@ -617,43 +528,40 @@ requests = ">=2.9.1" six = ">=1.10" vdf = ">=3.3" -[package.extras] -client = ["gevent (>=1.3.0)", "protobuf (>=3.0.0)", "gevent-eventemitter (>=2.1)"] - [[package]] -category = "main" -description = "Python Library for Tom's Obvious, Minimal Language" name = "toml" +version = "0.10.1" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = "*" -version = "0.10.1" [[package]] -category = "main" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." name = "tornado" +version = "6.0.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "main" optional = false python-versions = ">= 3.5" -version = "6.0.4" [[package]] -category = "main" -description = "tzinfo object for the local timezone" name = "tzlocal" +version = "2.1" +description = "tzinfo object for the local timezone" +category = "main" optional = false python-versions = "*" -version = "2.1" [package.dependencies] pytz = "*" [[package]] -category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" +version = "1.25.10" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.9" [package.extras] brotli = ["brotlipy (>=0.6.0)"] @@ -661,12 +569,12 @@ secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0 socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] -category = "main" -description = "The lightning-fast ASGI server." name = "uvicorn" +version = "0.10.9" +description = "The lightning-fast ASGI server." +category = "main" optional = false python-versions = "*" -version = "0.10.9" [package.dependencies] click = ">=7.0.0,<8.0.0" @@ -676,54 +584,46 @@ 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 = false -python-versions = "*" version = "0.14.0" - -[[package]] +description = "Fast implementation of asyncio event loop on top of libuv" category = "main" -description = "Library for working with Valve's VDF text format" -name = "vdf" optional = false python-versions = "*" -version = "3.3" +marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"pypy\"" [[package]] +name = "vdf" +version = "3.3" +description = "Library for working with Valve's VDF text format" category = "main" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = "*" + +[[package]] name = "websockets" +version = "8.1" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +category = "main" optional = false python-versions = ">=3.6.1" -version = "8.1" [[package]] -category = "main" -description = "Yet another URL library" name = "yarl" +version = "1.5.1" +description = "Yet another URL library" +category = "main" optional = false python-versions = ">=3.5" -version = "1.4.2" [package.dependencies] idna = ">=2.0" multidict = ">=4.0" -[[package]] -category = "main" -description = "YouTube video downloader" -name = "youtube-dl" -optional = false -python-versions = "*" -version = "2020.6.16.1" - [metadata] -content-hash = "bd3b2b2a3ab95481b04d72980ab5365028e6aee69b12e395b0c4cbdfde95c452" lock-version = "1.0" python-versions = "^3.8" +content-hash = "b45296e9be3f2ad43dd04bc9359fd9bfce913970a0dc06dd6027726bfa8c9858" [metadata.files] aiohttp = [ @@ -749,24 +649,13 @@ attrs = [ {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, ] bcrypt = [ - {file = "bcrypt-3.1.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:d7bdc26475679dd073ba0ed2766445bb5b20ca4793ca0db32b399dccc6bc84b7"}, - {file = "bcrypt-3.1.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:69361315039878c0680be456640f8705d76cb4a3a3fe1e057e0f261b74be4b31"}, - {file = "bcrypt-3.1.7-cp27-cp27m-win32.whl", hash = "sha256:5432dd7b34107ae8ed6c10a71b4397f1c853bd39a4d6ffa7e35f40584cffd161"}, - {file = "bcrypt-3.1.7-cp27-cp27m-win_amd64.whl", hash = "sha256:9fe92406c857409b70a38729dbdf6578caf9228de0aef5bc44f859ffe971a39e"}, - {file = "bcrypt-3.1.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:763669a367869786bb4c8fcf731f4175775a5b43f070f50f46f0b59da45375d0"}, - {file = "bcrypt-3.1.7-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:a190f2a5dbbdbff4b74e3103cef44344bc30e61255beb27310e2aec407766052"}, - {file = "bcrypt-3.1.7-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:c9457fa5c121e94a58d6505cadca8bed1c64444b83b3204928a866ca2e599105"}, - {file = "bcrypt-3.1.7-cp34-cp34m-win32.whl", hash = "sha256:8b10acde4e1919d6015e1df86d4c217d3b5b01bb7744c36113ea43d529e1c3de"}, - {file = "bcrypt-3.1.7-cp34-cp34m-win_amd64.whl", hash = "sha256:cb93f6b2ab0f6853550b74e051d297c27a638719753eb9ff66d1e4072be67133"}, - {file = "bcrypt-3.1.7-cp35-cp35m-win32.whl", hash = "sha256:6fe49a60b25b584e2f4ef175b29d3a83ba63b3a4df1b4c0605b826668d1b6be5"}, - {file = "bcrypt-3.1.7-cp35-cp35m-win_amd64.whl", hash = "sha256:a595c12c618119255c90deb4b046e1ca3bcfad64667c43d1166f2b04bc72db09"}, - {file = "bcrypt-3.1.7-cp36-cp36m-win32.whl", hash = "sha256:74a015102e877d0ccd02cdeaa18b32aa7273746914a6c5d0456dd442cb65b99c"}, - {file = "bcrypt-3.1.7-cp36-cp36m-win_amd64.whl", hash = "sha256:0258f143f3de96b7c14f762c770f5fc56ccd72f8a1857a451c1cd9a655d9ac89"}, - {file = "bcrypt-3.1.7-cp37-cp37m-win32.whl", hash = "sha256:19a4b72a6ae5bb467fea018b825f0a7d917789bcfe893e53f15c92805d187294"}, - {file = "bcrypt-3.1.7-cp37-cp37m-win_amd64.whl", hash = "sha256:ff032765bb8716d9387fd5376d987a937254b0619eff0972779515b5c98820bc"}, - {file = "bcrypt-3.1.7-cp38-cp38-win32.whl", hash = "sha256:ce4e4f0deb51d38b1611a27f330426154f2980e66582dc5f438aad38b5f24fc1"}, - {file = "bcrypt-3.1.7-cp38-cp38-win_amd64.whl", hash = "sha256:6305557019906466fc42dbc53b46da004e72fd7a551c044a827e572c82191752"}, - {file = "bcrypt-3.1.7.tar.gz", hash = "sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42"}, + {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"}, + {file = "bcrypt-3.2.0-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7"}, + {file = "bcrypt-3.2.0-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1"}, + {file = "bcrypt-3.2.0-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"}, + {file = "bcrypt-3.2.0-cp36-abi3-win32.whl", hash = "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55"}, + {file = "bcrypt-3.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34"}, + {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"}, ] cachetools = [ {file = "cachetools-4.1.1-py3-none-any.whl", hash = "sha256:513d4ff98dd27f85743a8dc0e92f55ddb1b49e060c2d5961512855cda2c01a98"}, @@ -777,34 +666,34 @@ certifi = [ {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, ] cffi = [ - {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, - {file = "cffi-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30"}, - {file = "cffi-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"}, - {file = "cffi-1.14.0-cp27-cp27m-win32.whl", hash = "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78"}, - {file = "cffi-1.14.0-cp27-cp27m-win_amd64.whl", hash = "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793"}, - {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e"}, - {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a"}, - {file = "cffi-1.14.0-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff"}, - {file = "cffi-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f"}, - {file = "cffi-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa"}, - {file = "cffi-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5"}, - {file = "cffi-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4"}, - {file = "cffi-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d"}, - {file = "cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc"}, - {file = "cffi-1.14.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac"}, - {file = "cffi-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f"}, - {file = "cffi-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b"}, - {file = "cffi-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3"}, - {file = "cffi-1.14.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66"}, - {file = "cffi-1.14.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0"}, - {file = "cffi-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f"}, - {file = "cffi-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26"}, - {file = "cffi-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd"}, - {file = "cffi-1.14.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55"}, - {file = "cffi-1.14.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2"}, - {file = "cffi-1.14.0-cp38-cp38-win32.whl", hash = "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8"}, - {file = "cffi-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b"}, - {file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"}, + {file = "cffi-1.14.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:da9d3c506f43e220336433dffe643fbfa40096d408cb9b7f2477892f369d5f82"}, + {file = "cffi-1.14.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23e44937d7695c27c66a54d793dd4b45889a81b35c0751ba91040fe825ec59c4"}, + {file = "cffi-1.14.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0da50dcbccd7cb7e6c741ab7912b2eff48e85af217d72b57f80ebc616257125e"}, + {file = "cffi-1.14.2-cp27-cp27m-win32.whl", hash = "sha256:76ada88d62eb24de7051c5157a1a78fd853cca9b91c0713c2e973e4196271d0c"}, + {file = "cffi-1.14.2-cp27-cp27m-win_amd64.whl", hash = "sha256:15a5f59a4808f82d8ec7364cbace851df591c2d43bc76bcbe5c4543a7ddd1bf1"}, + {file = "cffi-1.14.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e4082d832e36e7f9b2278bc774886ca8207346b99f278e54c9de4834f17232f7"}, + {file = "cffi-1.14.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:57214fa5430399dffd54f4be37b56fe22cedb2b98862550d43cc085fb698dc2c"}, + {file = "cffi-1.14.2-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:6843db0343e12e3f52cc58430ad559d850a53684f5b352540ca3f1bc56df0731"}, + {file = "cffi-1.14.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:577791f948d34d569acb2d1add5831731c59d5a0c50a6d9f629ae1cefd9ca4a0"}, + {file = "cffi-1.14.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8662aabfeab00cea149a3d1c2999b0731e70c6b5bac596d95d13f643e76d3d4e"}, + {file = "cffi-1.14.2-cp35-cp35m-win32.whl", hash = "sha256:837398c2ec00228679513802e3744d1e8e3cb1204aa6ad408b6aff081e99a487"}, + {file = "cffi-1.14.2-cp35-cp35m-win_amd64.whl", hash = "sha256:bf44a9a0141a082e89c90e8d785b212a872db793a0080c20f6ae6e2a0ebf82ad"}, + {file = "cffi-1.14.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:29c4688ace466a365b85a51dcc5e3c853c1d283f293dfcc12f7a77e498f160d2"}, + {file = "cffi-1.14.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:99cc66b33c418cd579c0f03b77b94263c305c389cb0c6972dac420f24b3bf123"}, + {file = "cffi-1.14.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:65867d63f0fd1b500fa343d7798fa64e9e681b594e0a07dc934c13e76ee28fb1"}, + {file = "cffi-1.14.2-cp36-cp36m-win32.whl", hash = "sha256:f5033952def24172e60493b68717792e3aebb387a8d186c43c020d9363ee7281"}, + {file = "cffi-1.14.2-cp36-cp36m-win_amd64.whl", hash = "sha256:7057613efefd36cacabbdbcef010e0a9c20a88fc07eb3e616019ea1692fa5df4"}, + {file = "cffi-1.14.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6539314d84c4d36f28d73adc1b45e9f4ee2a89cdc7e5d2b0a6dbacba31906798"}, + {file = "cffi-1.14.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:672b539db20fef6b03d6f7a14b5825d57c98e4026401fce838849f8de73fe4d4"}, + {file = "cffi-1.14.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:95e9094162fa712f18b4f60896e34b621df99147c2cee216cfa8f022294e8e9f"}, + {file = "cffi-1.14.2-cp37-cp37m-win32.whl", hash = "sha256:b9aa9d8818c2e917fa2c105ad538e222a5bce59777133840b93134022a7ce650"}, + {file = "cffi-1.14.2-cp37-cp37m-win_amd64.whl", hash = "sha256:e4b9b7af398c32e408c00eb4e0d33ced2f9121fd9fb978e6c1b57edd014a7d15"}, + {file = "cffi-1.14.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e613514a82539fc48291d01933951a13ae93b6b444a88782480be32245ed4afa"}, + {file = "cffi-1.14.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9b219511d8b64d3fa14261963933be34028ea0e57455baf6781fe399c2c3206c"}, + {file = "cffi-1.14.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c0b48b98d79cf795b0916c57bebbc6d16bb43b9fc9b8c9f57f4cf05881904c75"}, + {file = "cffi-1.14.2-cp38-cp38-win32.whl", hash = "sha256:15419020b0e812b40d96ec9d369b2bc8109cc3295eac6e013d3261343580cc7e"}, + {file = "cffi-1.14.2-cp38-cp38-win_amd64.whl", hash = "sha256:12a453e03124069b6896107ee133ae3ab04c624bb10683e1ed1c1663df17c13c"}, + {file = "cffi-1.14.2.tar.gz", hash = "sha256:ae8f34d50af2c2154035984b8b5fc5d9ed63f32fe615646ab435b05b132ca91b"}, ] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, @@ -851,29 +740,9 @@ decorator = [ {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, ] -deprecation = [ - {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, - {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, -] "discord.py" = [ - {file = "discord.py-1.3.4-py3-none-any.whl", hash = "sha256:8ef58d6fc1e66903bc00ae79c4c09a38aa71043e88a83da4d2e8b9b1c9f9b9e2"}, - {file = "discord.py-1.3.4.tar.gz", hash = "sha256:1b546a32c0cd83d949392a71e5b06e30e19d1067246e3826d32ae9b8b3d06c1e"}, -] -eyed3 = [ - {file = "eyeD3-0.9.5-py2.py3-none-any.whl", hash = "sha256:94d475c0b55d9227a7f885f0be0f8433da9de6e5037e5164a524b042e78a2b62"}, - {file = "eyeD3-0.9.5-py3.8.egg", hash = "sha256:5e517b8c0eb36d5225e9bc3e85ab340e211a0887dfb83507a1dd8f586bf55df9"}, - {file = "eyeD3-0.9.5.tar.gz", hash = "sha256:faf5806197f2093e82c2830d41f2378f07b3a9da07a16fafb14fc6fbdebac50a"}, -] -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"}, -] -filetype = [ - {file = "filetype-1.0.7-py2.py3-none-any.whl", hash = "sha256:353369948bb1c09b8b3ea3d78390b5586e9399bff9aab894a1dff954e31a66f6"}, - {file = "filetype-1.0.7.tar.gz", hash = "sha256:da393ece8d98b47edf2dd5a85a2c8733e44b769e32c71af4cd96ed8d38d96aa7"}, -] -future = [ - {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, + {file = "discord.py-1.4.1-py3-none-any.whl", hash = "sha256:98ea3096a3585c9c379209926f530808f5fcf4930928d8cfb579d2562d119570"}, + {file = "discord.py-1.4.1.tar.gz", hash = "sha256:f9decb3bfa94613d922376288617e6a6f969260923643e2897f4540c34793442"}, ] h11 = [ {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, @@ -913,10 +782,6 @@ multidict = [ {file = "multidict-4.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19"}, {file = "multidict-4.7.6.tar.gz", hash = "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430"}, ] -packaging = [ - {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, - {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, -] psycopg2-binary = [ {file = "psycopg2-binary-2.8.5.tar.gz", hash = "sha256:ccdc6a87f32b491129ada4b87a43b1895cf2c20fdb7f98ad979647506ffc41b6"}, {file = "psycopg2_binary-2.8.5-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:96d3038f5bd061401996614f65d27a4ecb62d843eb4f48e212e6d129171a721f"}, @@ -1003,10 +868,6 @@ pynacl = [ {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"}, {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"}, ] -pyparsing = [ - {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, - {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, -] pyreadline = [ {file = "pyreadline-2.1.win-amd64.exe", hash = "sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"}, {file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"}, @@ -1059,8 +920,8 @@ riotwatcher = [ {file = "riotwatcher-3.0.0.tar.gz", hash = "sha256:bf8b8eb7e13c794730c18cd7846513cf22295a068204433117ce4d83a25b0fd2"}, ] royalnet = [ - {file = "royalnet-5.10.4-py3-none-any.whl", hash = "sha256:664b81400d58078d6759d23f0c9a6e231f6499ddeeb93e19a7f1043d6892fb17"}, - {file = "royalnet-5.10.4.tar.gz", hash = "sha256:4b28bc90bcae0257dd48386fd637d83c953a5bb8ef785c0a39c126ac6e560c28"}, + {file = "royalnet-5.11.0-py3-none-any.whl", hash = "sha256:cb2ed753044ae563b73389acce4c9c0b0b4a4cb2cb5bc2bc0197a91478a12575"}, + {file = "royalnet-5.11.0.tar.gz", hash = "sha256:aab356a1a845a893c2f1c4e96ec01faf799c9efb5041451a25aa3264f8926859"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1074,34 +935,34 @@ six = [ {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.18-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:f11c2437fb5f812d020932119ba02d9e2bc29a6eca01a055233a8b449e3e1e7d"}, - {file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0ec575db1b54909750332c2e335c2bb11257883914a03bc5a3306a4488ecc772"}, - {file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f57be5673e12763dd400fea568608700a63ce1c6bd5bdbc3cc3a2c5fdb045274"}, - {file = "SQLAlchemy-1.3.18-cp27-cp27m-win32.whl", hash = "sha256:8cac7bb373a5f1423e28de3fd5fc8063b9c8ffe8957dc1b1a59cb90453db6da1"}, - {file = "SQLAlchemy-1.3.18-cp27-cp27m-win_amd64.whl", hash = "sha256:adad60eea2c4c2a1875eb6305a0b6e61a83163f8e233586a4d6a55221ef984fe"}, - {file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:57aa843b783179ab72e863512e14bdcba186641daf69e4e3a5761d705dcc35b1"}, - {file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:621f58cd921cd71ba6215c42954ffaa8a918eecd8c535d97befa1a8acad986dd"}, - {file = "SQLAlchemy-1.3.18-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fc728ece3d5c772c196fd338a99798e7efac7a04f9cb6416299a3638ee9a94cd"}, - {file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:736d41cfebedecc6f159fc4ac0769dc89528a989471dc1d378ba07d29a60ba1c"}, - {file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:427273b08efc16a85aa2b39892817e78e3ed074fcb89b2a51c4979bae7e7ba98"}, - {file = "SQLAlchemy-1.3.18-cp35-cp35m-win32.whl", hash = "sha256:cbe1324ef52ff26ccde2cb84b8593c8bf930069dfc06c1e616f1bfd4e47f48a3"}, - {file = "SQLAlchemy-1.3.18-cp35-cp35m-win_amd64.whl", hash = "sha256:8fd452dc3d49b3cc54483e033de6c006c304432e6f84b74d7b2c68afa2569ae5"}, - {file = "SQLAlchemy-1.3.18-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e89e0d9e106f8a9180a4ca92a6adde60c58b1b0299e1b43bd5e0312f535fbf33"}, - {file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6ac2558631a81b85e7fb7a44e5035347938b0a73f5fdc27a8566777d0792a6a4"}, - {file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:87fad64529cde4f1914a5b9c383628e1a8f9e3930304c09cf22c2ae118a1280e"}, - {file = "SQLAlchemy-1.3.18-cp36-cp36m-win32.whl", hash = "sha256:e4624d7edb2576cd72bb83636cd71c8ce544d8e272f308bd80885056972ca299"}, - {file = "SQLAlchemy-1.3.18-cp36-cp36m-win_amd64.whl", hash = "sha256:89494df7f93b1836cae210c42864b292f9b31eeabca4810193761990dc689cce"}, - {file = "SQLAlchemy-1.3.18-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:716754d0b5490bdcf68e1e4925edc02ac07209883314ad01a137642ddb2056f1"}, - {file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:50c4ee32f0e1581828843267d8de35c3298e86ceecd5e9017dc45788be70a864"}, - {file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d98bc827a1293ae767c8f2f18be3bb5151fd37ddcd7da2a5f9581baeeb7a3fa1"}, - {file = "SQLAlchemy-1.3.18-cp37-cp37m-win32.whl", hash = "sha256:0942a3a0df3f6131580eddd26d99071b48cfe5aaf3eab2783076fbc5a1c1882e"}, - {file = "SQLAlchemy-1.3.18-cp37-cp37m-win_amd64.whl", hash = "sha256:16593fd748944726540cd20f7e83afec816c2ac96b082e26ae226e8f7e9688cf"}, - {file = "SQLAlchemy-1.3.18-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c26f95e7609b821b5f08a72dab929baa0d685406b953efd7c89423a511d5c413"}, - {file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:512a85c3c8c3995cc91af3e90f38f460da5d3cade8dc3a229c8e0879037547c9"}, - {file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d05c4adae06bd0c7f696ae3ec8d993ed8ffcc4e11a76b1b35a5af8a099bd2284"}, - {file = "SQLAlchemy-1.3.18-cp38-cp38-win32.whl", hash = "sha256:109581ccc8915001e8037b73c29590e78ce74be49ca0a3630a23831f9e3ed6c7"}, - {file = "SQLAlchemy-1.3.18-cp38-cp38-win_amd64.whl", hash = "sha256:8619b86cb68b185a778635be5b3e6018623c0761dde4df2f112896424aa27bd8"}, - {file = "SQLAlchemy-1.3.18.tar.gz", hash = "sha256:da2fb75f64792c1fc64c82313a00c728a7c301efe6a60b7a9fe35b16b4368ce7"}, + {file = "SQLAlchemy-1.3.19-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:f2e8a9c0c8813a468aa659a01af6592f71cd30237ec27c4cc0683f089f90dcfc"}, + {file = "SQLAlchemy-1.3.19-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:33d29ae8f1dc7c75b191bb6833f55a19c932514b9b5ce8c3ab9bc3047da5db36"}, + {file = "SQLAlchemy-1.3.19-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3292a28344922415f939ee7f4fc0c186f3d5a0bf02192ceabd4f1129d71b08de"}, + {file = "SQLAlchemy-1.3.19-cp27-cp27m-win32.whl", hash = "sha256:883c9fb62cebd1e7126dd683222b3b919657590c3e2db33bdc50ebbad53e0338"}, + {file = "SQLAlchemy-1.3.19-cp27-cp27m-win_amd64.whl", hash = "sha256:860d0fe234922fd5552b7f807fbb039e3e7ca58c18c8d38aa0d0a95ddf4f6c23"}, + {file = "SQLAlchemy-1.3.19-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:73a40d4fcd35fdedce07b5885905753d5d4edf413fbe53544dd871f27d48bd4f"}, + {file = "SQLAlchemy-1.3.19-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5a49e8473b1ab1228302ed27365ea0fadd4bf44bc0f9e73fe38e10fdd3d6b4fc"}, + {file = "SQLAlchemy-1.3.19-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:6547b27698b5b3bbfc5210233bd9523de849b2bb8a0329cd754c9308fc8a05ce"}, + {file = "SQLAlchemy-1.3.19-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:107d4af989831d7b091e382d192955679ec07a9209996bf8090f1f539ffc5804"}, + {file = "SQLAlchemy-1.3.19-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:eb1d71643e4154398b02e88a42fc8b29db8c44ce4134cf0f4474bfc5cb5d4dac"}, + {file = "SQLAlchemy-1.3.19-cp35-cp35m-win32.whl", hash = "sha256:96f51489ac187f4bab588cf51f9ff2d40b6d170ac9a4270ffaed535c8404256b"}, + {file = "SQLAlchemy-1.3.19-cp35-cp35m-win_amd64.whl", hash = "sha256:618db68745682f64cedc96ca93707805d1f3a031747b5a0d8e150cfd5055ae4d"}, + {file = "SQLAlchemy-1.3.19-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:6557af9e0d23f46b8cd56f8af08eaac72d2e3c632ac8d5cf4e20215a8dca7cea"}, + {file = "SQLAlchemy-1.3.19-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8280f9dae4adb5889ce0bb3ec6a541bf05434db5f9ab7673078c00713d148365"}, + {file = "SQLAlchemy-1.3.19-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:b595e71c51657f9ee3235db8b53d0b57c09eee74dfb5b77edff0e46d2218dc02"}, + {file = "SQLAlchemy-1.3.19-cp36-cp36m-win32.whl", hash = "sha256:8afcb6f4064d234a43fea108859942d9795c4060ed0fbd9082b0f280181a15c1"}, + {file = "SQLAlchemy-1.3.19-cp36-cp36m-win_amd64.whl", hash = "sha256:e49947d583fe4d29af528677e4f0aa21f5e535ca2ae69c48270ebebd0d8843c0"}, + {file = "SQLAlchemy-1.3.19-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:9e865835e36dfbb1873b65e722ea627c096c11b05f796831e3a9b542926e979e"}, + {file = "SQLAlchemy-1.3.19-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:276936d41111a501cf4a1a0543e25449108d87e9f8c94714f7660eaea89ae5fe"}, + {file = "SQLAlchemy-1.3.19-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:c7adb1f69a80573698c2def5ead584138ca00fff4ad9785a4b0b2bf927ba308d"}, + {file = "SQLAlchemy-1.3.19-cp37-cp37m-win32.whl", hash = "sha256:aa0554495fe06172b550098909be8db79b5accdf6ffb59611900bea345df5eba"}, + {file = "SQLAlchemy-1.3.19-cp37-cp37m-win_amd64.whl", hash = "sha256:15c0bcd3c14f4086701c33a9e87e2c7ceb3bcb4a246cd88ec54a49cf2a5bd1a6"}, + {file = "SQLAlchemy-1.3.19-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:fe7fe11019fc3e6600819775a7d55abc5446dda07e9795f5954fdbf8a49e1c37"}, + {file = "SQLAlchemy-1.3.19-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c898b3ebcc9eae7b36bd0b4bbbafce2d8076680f6868bcbacee2d39a7a9726a7"}, + {file = "SQLAlchemy-1.3.19-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:072766c3bd09294d716b2d114d46ffc5ccf8ea0b714a4e1c48253014b771c6bb"}, + {file = "SQLAlchemy-1.3.19-cp38-cp38-win32.whl", hash = "sha256:b70bad2f1a5bd3460746c3fb3ab69e4e0eb5f59d977a23f9b66e5bdc74d97b86"}, + {file = "SQLAlchemy-1.3.19-cp38-cp38-win_amd64.whl", hash = "sha256:83469ad15262402b0e0974e612546bc0b05f379b5aa9072ebf66d0f8fef16bea"}, + {file = "SQLAlchemy-1.3.19.tar.gz", hash = "sha256:3bba2e9fbedb0511769780fe1d63007081008c5c2d7d715e91858c94dbaa260e"}, ] starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, @@ -1129,8 +990,8 @@ tzlocal = [ {file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"}, ] urllib3 = [ - {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, - {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, + {file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"}, + {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"}, ] uvicorn = [ {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, @@ -1176,25 +1037,21 @@ websockets = [ {file = "websockets-8.1.tar.gz", hash = "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f"}, ] yarl = [ - {file = "yarl-1.4.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b"}, - {file = "yarl-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1"}, - {file = "yarl-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080"}, - {file = "yarl-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a"}, - {file = "yarl-1.4.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f"}, - {file = "yarl-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea"}, - {file = "yarl-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb"}, - {file = "yarl-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70"}, - {file = "yarl-1.4.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d"}, - {file = "yarl-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce"}, - {file = "yarl-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2"}, - {file = "yarl-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce"}, - {file = "yarl-1.4.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b"}, - {file = "yarl-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae"}, - {file = "yarl-1.4.2-cp38-cp38-win32.whl", hash = "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462"}, - {file = "yarl-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6"}, - {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, -] -youtube-dl = [ - {file = "youtube_dl-2020.6.16.1-py2.py3-none-any.whl", hash = "sha256:e54b307048bb18164729fb278013af6d5477c69c3d995147205a16f22a61296b"}, - {file = "youtube_dl-2020.6.16.1.tar.gz", hash = "sha256:9fc0389a1bbbeb609a5bb4ad5630dea107a9d1a24c73721c611a78c234309a75"}, + {file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"}, + {file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"}, + {file = "yarl-1.5.1-cp35-cp35m-win32.whl", hash = "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409"}, + {file = "yarl-1.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317"}, + {file = "yarl-1.5.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511"}, + {file = "yarl-1.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e"}, + {file = "yarl-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f"}, + {file = "yarl-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2"}, + {file = "yarl-1.5.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a"}, + {file = "yarl-1.5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8"}, + {file = "yarl-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8"}, + {file = "yarl-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d"}, + {file = "yarl-1.5.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02"}, + {file = "yarl-1.5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a"}, + {file = "yarl-1.5.1-cp38-cp38-win32.whl", hash = "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"}, + {file = "yarl-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692"}, + {file = "yarl-1.5.1.tar.gz", hash = "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6"}, ] diff --git a/pyproject.toml b/pyproject.toml index 7995350f..ecba6195 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.13.9" + version = "5.14.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -28,13 +28,12 @@ itsdangerous = "^1.1.0" [tool.poetry.dependencies.royalnet] - version = "~5.10.4" + version = "~5.11.0" # Maybe... there is a way to make these selectable? extras = [ "telegram", "discord", "alchemy_easy", - "bard", "constellation", "sentry", "herald", diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index eb4d5a1b..73d1ad3c 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -23,7 +23,6 @@ from .leagueoflegends import LeagueoflegendsCommand from .magickfiorygi import MagickfiorygiCommand from .magicktreasure import MagicktreasureCommand from .matchmaking import MatchmakingCommand -from .peertubeupdates import PeertubeUpdatesCommand from .ping import PingCommand from .pmots import PmotsCommand from .dog import DogCommand @@ -37,7 +36,6 @@ from .steammatch import SteammatchCommand from .steampowered import SteampoweredCommand from .treasure import TreasureCommand from .trivia import TriviaCommand -from .userinfo import UserinfoCommand from .osu import OsuCommand # Enter the commands of your Pack here! @@ -66,7 +64,6 @@ available_commands = [ MagickfiorygiCommand, MagicktreasureCommand, MatchmakingCommand, - PeertubeUpdatesCommand, PingCommand, PmotsCommand, DogCommand, @@ -80,7 +77,6 @@ available_commands = [ SteampoweredCommand, TreasureCommand, TriviaCommand, - UserinfoCommand, OsuCommand, ] diff --git a/royalpack/commands/abstract/linker.py b/royalpack/commands/abstract/linker.py index 198df1f8..5ac2b760 100644 --- a/royalpack/commands/abstract/linker.py +++ b/royalpack/commands/abstract/linker.py @@ -14,37 +14,37 @@ log = logging.getLogger(__name__) class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) - + def __init__(self, serf, config): + super().__init__(serf, config) self.updater_task = None if self.enabled(): self.updater_task = self.loop.create_task(self.run_updater()) async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: author = await data.get_author(error_if_none=True) - if len(args) == 0: - message = [] - for obj in await self.get_updatables_of_user(session=data.session, user=author): - async def change(attribute: str, value: Any): - """A shortcut for self.__change.""" - await self._change(session=data.session, - obj=obj, - attribute=attribute, - new=value) + async with data.session_acm() as session: + if len(args) == 0: + message = [] + for obj in await self.get_updatables_of_user(session=session, user=author): + async def change(attribute: str, value: Any): + """A shortcut for self.__change.""" + await self._change(session=session, + obj=obj, + attribute=attribute, + new=value) - await self.update(session=data.session, obj=obj, change=change) - message.append(self.describe(obj)) - if len(message) == 0: - raise rc.UserError("Nessun account connesso.") - await data.session_commit() - await data.reply("\n".join(message)) - else: - created = await self.create(session=data.session, user=author, args=args, data=data) - await data.session_commit() - if created is not None: - message = ["🔗 Account collegato!", "", self.describe(created)] + await self.update(session=session, obj=obj, change=change) + message.append(self.describe(obj)) + if len(message) == 0: + raise rc.UserError("Nessun account connesso.") + await ru.asyncify(session.commit) await data.reply("\n".join(message)) + else: + created = await self.create(session=session, user=author, args=args, data=data) + await ru.asyncify(session.commit) + if created is not None: + message = ["🔗 Account collegato!", "", self.describe(created)] + await data.reply("\n".join(message)) def describe(self, obj: Updatable) -> str: """The text that should be appended to the report message for a given Updatable.""" @@ -143,7 +143,7 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): def enabled(self) -> bool: """Whether the updater is enabled or not.""" - return self.config[self.name]["updater"]["enabled"] and self.interface.name == "telegram" + return self.config[self.name]["updater"]["enabled"] and isinstance(self.serf, rst.TelegramSerf) def period(self) -> int: """The time between two updater cycles.""" diff --git a/royalpack/commands/ciaoruozi.py b/royalpack/commands/ciaoruozi.py index be932f5b..fe0228cf 100644 --- a/royalpack/commands/ciaoruozi.py +++ b/royalpack/commands/ciaoruozi.py @@ -1,15 +1,16 @@ from typing import * import telegram -from royalnet.commands import * +import royalnet.commands as rc +import royalnet.serf.telegram as rst -class CiaoruoziCommand(Command): +class CiaoruoziCommand(rc.Command): name: str = "ciaoruozi" description: str = "Saluta Ruozi, un leggendario essere che è tornato in Royal Games." - async def run(self, args: CommandArgs, data: CommandData) -> None: - if self.interface.name == "telegram": + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + if isinstance(self.serf, rst.TelegramSerf): user: telegram.User = data.message.from_user # Se sei Ruozi, salutati da solo! if user.id == 112437036: diff --git a/royalpack/commands/cv.py b/royalpack/commands/cv.py index 3dbb3d4d..527af223 100644 --- a/royalpack/commands/cv.py +++ b/royalpack/commands/cv.py @@ -9,9 +9,6 @@ class CvCommand(Command): syntax: str = "[a][o][n][d][h]" - def __init__(self, interface: CommandInterface): - super().__init__(interface) - def _render_member(self, member, display_nick: bool, @@ -92,7 +89,7 @@ class CvCommand(Command): return f"{status}{voice} {name}{activity}\n" async def run(self, args: CommandArgs, data: CommandData) -> None: - response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_cv") + response: Dict[str, Any] = await self.serf.call_herald_event("discord", "discord_cv") flags = args.optional(0, default="") display_nicks = "n" in flags diff --git a/royalpack/commands/cvstats.py b/royalpack/commands/cvstats.py index eed97d70..2c73cba9 100644 --- a/royalpack/commands/cvstats.py +++ b/royalpack/commands/cvstats.py @@ -4,6 +4,7 @@ import asyncio import datetime import royalnet.commands as rc import royalnet.utils as ru +import royalnet.serf.discord as rsd from ..tables import Cvstats @@ -18,14 +19,14 @@ class CvstatsCommand(rc.Command): syntax: str = "" - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) - if self.interface.name == "discord": + def __init__(self, serf, config): + super().__init__(serf=serf, config=config) + if isinstance(self.serf, rsd.DiscordSerf): self.loop.create_task(self._updater(1800)) def _is_ryg_member(self, member: dict): for role in member["roles"]: - if role["id"] == self.interface.config["Cv"]["displayed_role_id"]: + if role["id"] == self.config["Cv"]["displayed_role_id"]: return True return False @@ -33,7 +34,7 @@ class CvstatsCommand(rc.Command): log.info(f"Gathering Cvstats...") while True: try: - response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_cv") + response: Dict[str, Any] = await self.serf.call_herald_event("discord", "discord_cv") except rc.ConfigurationError: await asyncio.sleep(10) continue @@ -118,7 +119,8 @@ class CvstatsCommand(rc.Command): async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: CvstatsT = self.alchemy.get(Cvstats) - cvstats = data.session.query(CvstatsT).order_by(CvstatsT.timestamp.desc()).first() + async with data.session_acm() as session: + cvstats = session.query(CvstatsT).order_by(CvstatsT.timestamp.desc()).first() message = [ f"ℹ️ [b]Statistiche[/b]", diff --git a/royalpack/commands/diario.py b/royalpack/commands/diario.py index 750244c3..70000667 100644 --- a/royalpack/commands/diario.py +++ b/royalpack/commands/diario.py @@ -6,6 +6,7 @@ import aiohttp import royalnet.commands as rc import royalnet.utils as ru import royalnet.backpack.tables as rbt +import royalnet.serf.telegram as rst from ..tables import * @@ -38,169 +39,166 @@ class DiarioCommand(rc.Command): syntax = "[!] \"{testo}\" --[autore], [contesto]" async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name == "telegram": - message: telegram.Message = data.message - reply: telegram.Message = message.reply_to_message - creator = await data.get_author() - # noinspection PyUnusedLocal - quoted: Optional[str] - # noinspection PyUnusedLocal - text: Optional[str] - # noinspection PyUnusedLocal - context: Optional[str] - # noinspection PyUnusedLocal - timestamp: datetime.datetime - # noinspection PyUnusedLocal - media_url: Optional[str] - # noinspection PyUnusedLocal - spoiler: bool - if creator is None: - await data.reply("⚠️ Devi essere registrato a Royalnet per usare questo comando!") - return - if reply is not None: - # Get the message text - text = reply.text - # Check if there's an image associated with the reply - photosizes: Optional[List[telegram.PhotoSize]] = reply.photo - if photosizes: - # Text is a caption - text = reply.caption - media_url = await to_imgur(self.interface.config["Imgur"]["token"], - photosizes, text if text is not None else "") - else: - media_url = None - # Ensure there is a text or an image - if not (text or media_url): - raise rc.InvalidInputError("Il messaggio a cui hai risposto non contiene testo o immagini.") - # Find the Royalnet account associated with the sender - quoted_tg = await ru.asyncify(data.session.query(self.alchemy.get(rbt.Telegram)) - .filter_by(tg_id=reply.from_user.id) - .one_or_none) - quoted_account = quoted_tg.user if quoted_tg is not None else None - # Find the quoted name to assign - quoted_user: telegram.User = reply.from_user - quoted = quoted_user.full_name - # Get the timestamp - timestamp = reply.date - # Set the other properties - spoiler = False - context = None - else: - # Get the current timestamp - timestamp = datetime.datetime.now() - # Get the message text - raw_text = " ".join(args) - # Check if there's an image associated with the reply - photosizes: Optional[List[telegram.PhotoSize]] = message.photo - if photosizes: - media_url = await to_imgur(self.interface.config["Imgur"]["token"], - photosizes, raw_text if raw_text is not None else "") - else: - media_url = None - # Parse the text, if it exists - if raw_text: - # Pass the sentence through the diario regex - match = re.match( - r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([^,]+))?(?:, *([^ ].*))?', - raw_text) - # Find the corresponding matches - if match is not None: - spoiler = bool(match.group(1)) - text = match.group(2) - quoted = match.group(3) - context = match.group(4) - # Otherwise, consider everything part of the text + async with data.session_acm() as session: + if isinstance(self.serf, rst.TelegramSerf): + message: telegram.Message = data.message + reply: telegram.Message = message.reply_to_message + creator = await data.get_author() + # noinspection PyUnusedLocal + quoted: Optional[str] + # noinspection PyUnusedLocal + text: Optional[str] + # noinspection PyUnusedLocal + context: Optional[str] + # noinspection PyUnusedLocal + timestamp: datetime.datetime + # noinspection PyUnusedLocal + media_url: Optional[str] + # noinspection PyUnusedLocal + spoiler: bool + if creator is None: + await data.reply("⚠️ Devi essere registrato a Royalnet per usare questo comando!") + return + if reply is not None: + # Get the message text + text = reply.text + # Check if there's an image associated with the reply + photosizes: Optional[List[telegram.PhotoSize]] = reply.photo + if photosizes: + # Text is a caption + text = reply.caption + media_url = await to_imgur(self.config["Imgur"]["token"], + photosizes, text if text is not None else "") else: - spoiler = False - text = raw_text - quoted = None - context = None - # Ensure there's a quoted - if not quoted: - quoted = None - if not context: - context = None - # Find if there's a Royalnet account associated with the quoted name - if quoted is not None: - quoted_alias = await ru.asyncify( - data.session.query(self.alchemy.get(rbt.Alias)) - .filter_by(alias=quoted.lower()).one_or_none - ) - else: - quoted_alias = None - quoted_account = quoted_alias.user if quoted_alias is not None else None - else: - text = None - quoted = None - quoted_account = None + media_url = None + # Ensure there is a text or an image + if not (text or media_url): + raise rc.InvalidInputError("Il messaggio a cui hai risposto non contiene testo o immagini.") + # Find the Royalnet account associated with the sender + quoted_tg = await ru.asyncify(session.query(self.alchemy.get(rbt.Telegram)) + .filter_by(tg_id=reply.from_user.id) + .one_or_none) + quoted_account = quoted_tg.user if quoted_tg is not None else None + # Find the quoted name to assign + quoted_user: telegram.User = reply.from_user + quoted = quoted_user.full_name + # Get the timestamp + timestamp = reply.date + # Set the other properties spoiler = False context = None - # Ensure there is a text or an image - if not (text or media_url): + else: + # Get the current timestamp + timestamp = datetime.datetime.now() + # Get the message text + raw_text = " ".join(args) + # Check if there's an image associated with the reply + photosizes: Optional[List[telegram.PhotoSize]] = message.photo + if photosizes: + media_url = await to_imgur(self.config["Imgur"]["token"], + photosizes, raw_text if raw_text is not None else "") + else: + media_url = None + # Parse the text, if it exists + if raw_text: + # Pass the sentence through the diario regex + match = re.match( + r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([^,]+))?(?:, *([^ ].*))?', + raw_text) + # Find the corresponding matches + if match is not None: + spoiler = bool(match.group(1)) + text = match.group(2) + quoted = match.group(3) + context = match.group(4) + # Otherwise, consider everything part of the text + else: + spoiler = False + text = raw_text + quoted = None + context = None + # Ensure there's a quoted + if not quoted: + quoted = None + if not context: + context = None + # Find if there's a Royalnet account associated with the quoted name + if quoted is not None: + quoted_alias = await ru.asyncify( + session.query(self.alchemy.get(rbt.Alias)) + .filter_by(alias=quoted.lower()).one_or_none + ) + else: + quoted_alias = None + quoted_account = quoted_alias.user if quoted_alias is not None else None + else: + text = None + quoted = None + quoted_account = None + spoiler = False + context = None + # Ensure there is a text or an image + if not (text or media_url): + raise rc.InvalidInputError("Manca il testo o l'immagine da inserire nel diario.") + # Create the diario quote + diario = self.alchemy.get(Diario)(creator=creator, + quoted_account=quoted_account, + quoted=quoted, + text=text, + context=context, + timestamp=timestamp, + media_url=media_url, + spoiler=spoiler) + session.add(diario) + await ru.asyncify(session.commit) + await data.reply(f"✅ {str(diario)}") + else: + # Find the creator of the quotes + creator = await data.get_author(error_if_none=True) + # Recreate the full sentence + raw_text = " ".join(args) + # Pass the sentence through the diario regex + match = re.match(r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([^,]+))?(?:, *([^ ].*))?', + raw_text) + # Find the corresponding matches + if match is not None: + spoiler = bool(match.group(1)) + text = match.group(2) + quoted = match.group(3) + context = match.group(4) + # Otherwise, consider everything part of the text + else: + spoiler = False + text = raw_text + quoted = None + context = None + timestamp = datetime.datetime.now() + # Ensure there is some text + if not text: raise rc.InvalidInputError("Manca il testo o l'immagine da inserire nel diario.") - # Create the diario quote - diario = self.alchemy.get(Diario)(creator=creator, - quoted_account=quoted_account, - quoted=quoted, - text=text, - context=context, - timestamp=timestamp, - media_url=media_url, - spoiler=spoiler) - data.session.add(diario) - await ru.asyncify(data.session.commit) - await data.reply(f"✅ {str(diario)}") - else: - # Find the creator of the quotes - creator = await data.get_author(error_if_none=True) - # Recreate the full sentence - raw_text = " ".join(args) - # Pass the sentence through the diario regex - match = re.match(r'(!)? *["«‘“‛‟❛❝〝"`]([^"]+)["»’”❜❞〞"`] *(?:(?:-{1,2}|—) *([^,]+))?(?:, *([^ ].*))?', - raw_text) - # Find the corresponding matches - if match is not None: - spoiler = bool(match.group(1)) - text = match.group(2) - quoted = match.group(3) - context = match.group(4) - # Otherwise, consider everything part of the text - else: - spoiler = False - text = raw_text - quoted = None - context = None - timestamp = datetime.datetime.now() - # Ensure there is some text - if not text: - raise rc.InvalidInputError("Manca il testo o l'immagine da inserire nel diario.") - # Or a quoted - if not quoted: - quoted = None - if not context: - context = None - # Find if there's a Royalnet account associated with the quoted name - if quoted is not None: - quoted_alias = await ru.asyncify( - data.session.query(self.alchemy.get(rbt.Alias)) - .filter_by(alias=quoted.lower()) - .one_or_none - ) - else: - quoted_alias = None - quoted_account = quoted_alias.user if quoted_alias is not None else None - if quoted_alias is not None and quoted_account is None: - raise rc.UserError("Il nome dell'autore è ambiguo, quindi la riga non è stata aggiunta.\n" - "Per piacere, ripeti il comando con un nome più specifico!") - # Create the diario quote - diario = self.alchemy.Diario(creator=creator, - quoted_account=quoted_account, - quoted=quoted, - text=text, - context=context, - timestamp=timestamp, - media_url=None, - spoiler=spoiler) - data.session.add(diario) - await ru.asyncify(data.session.commit) - await data.reply(f"✅ {str(diario)}") + # Or a quoted + if not quoted: + quoted = None + if not context: + context = None + # Find if there's a Royalnet account associated with the quoted name + if quoted is not None: + quoted_account = await rbt.User.find(self.alchemy, session, quoted) + else: + quoted_account = None + if quoted_account is None: + raise rc.UserError("Il nome dell'autore è ambiguo, quindi la riga non è stata aggiunta.\n" + "Per piacere, ripeti il comando con un nome più specifico!") + # Create the diario quote + DiarioT = self.alchemy.get(Diario) + diario = DiarioT(creator=creator, + quoted_account=quoted_account, + quoted=quoted, + text=text, + context=context, + timestamp=timestamp, + media_url=None, + spoiler=spoiler) + session.add(diario) + await ru.asyncify(session.commit) + await data.reply(f"✅ {str(diario)}") diff --git a/royalpack/commands/diarioquote.py b/royalpack/commands/diarioquote.py index 4b35f725..e5039e53 100644 --- a/royalpack/commands/diarioquote.py +++ b/royalpack/commands/diarioquote.py @@ -19,7 +19,8 @@ class DiarioquoteCommand(rc.Command): entry_id = int(args[0].lstrip("#")) except ValueError: raise rc.CommandError("L'id che hai specificato non è valido.") - entry: Diario = await ru.asyncify(data.session.query(self.alchemy.get(Diario)).get, entry_id) + async with data.session_acm() as session: + entry: Diario = await ru.asyncify(session.query(self.alchemy.get(Diario)).get, entry_id) if entry is None: raise rc.CommandError("Nessuna riga con quell'id trovata.") await data.reply(f"ℹ️ {entry}") diff --git a/royalpack/commands/diarioshuffle.py b/royalpack/commands/diarioshuffle.py index 8468a954..01153e61 100644 --- a/royalpack/commands/diarioshuffle.py +++ b/royalpack/commands/diarioshuffle.py @@ -16,14 +16,11 @@ class DiarioshuffleCommand(rc.Command): syntax = "" async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - DiarioT = self.alchemy.get(Diario) - entry: List[Diario] = await ru.asyncify( - data.session - .query(DiarioT) - .order_by(func.random()) - .limit(1) - .one_or_none - ) - if entry is None: - raise rc.CommandError("Nessuna riga del diario trovata.") - await data.reply(f"ℹ️ {entry}") + async with data.session_acm() as session: + DiarioT = self.alchemy.get(Diario) + entry: List[Diario] = await ru.asyncify( + session.query(DiarioT).order_by(func.random()).limit(1).one_or_none + ) + if entry is None: + raise rc.CommandError("Nessuna riga del diario trovata.") + await data.reply(f"ℹ️ {entry}") diff --git a/royalpack/commands/eval.py b/royalpack/commands/eval.py index 21de0da0..06d25619 100644 --- a/royalpack/commands/eval.py +++ b/royalpack/commands/eval.py @@ -15,7 +15,7 @@ class EvalCommand(rc.Command): user: rbt.User = await data.get_author(error_if_none=True) if "admin" not in user.roles: raise rc.CommandError("Non sei autorizzato a eseguire codice arbitrario!\n" - "(Sarebbe un po' pericoloso se te lo lasciassi eseguire, non trovi?)") + "(Sarebbe un po' pericoloso se te lo lasciassi eseguire, non trovi?)") try: result = eval(args.joined(require_at_least=1)) except Exception as e: diff --git a/royalpack/commands/exec.py b/royalpack/commands/exec.py index 65c3b013..ba024137 100644 --- a/royalpack/commands/exec.py +++ b/royalpack/commands/exec.py @@ -15,7 +15,7 @@ class ExecCommand(rc.Command): user: rbt.User = await data.get_author(error_if_none=True) if "admin" not in user.roles: raise rc.CommandError("Non sei autorizzato a eseguire codice arbitrario!\n" - "(Sarebbe un po' pericoloso se te lo lasciassi eseguire, non trovi?)") + "(Sarebbe un po' pericoloso se te lo lasciassi eseguire, non trovi?)") try: exec(args.joined(require_at_least=1)) except Exception as e: diff --git a/royalpack/commands/givefiorygi.py b/royalpack/commands/givefiorygi.py index b9f536fc..c1e29230 100644 --- a/royalpack/commands/givefiorygi.py +++ b/royalpack/commands/givefiorygi.py @@ -20,7 +20,8 @@ class GivefiorygiCommand(rc.Command): if user_arg is None: raise rc.InvalidInputError("Non hai specificato un destinatario!") - user = await rbt.User.find(self.alchemy, data.session, user_arg) + async with data.session_acm() as session: + user = await rbt.User.find(self.alchemy, session, user_arg) if user is None: raise rc.InvalidInputError("L'utente specificato non esiste!") if user.uid == author.uid: diff --git a/royalpack/commands/givetreasure.py b/royalpack/commands/givetreasure.py index 554902b5..92d0ad23 100644 --- a/royalpack/commands/givetreasure.py +++ b/royalpack/commands/givetreasure.py @@ -13,14 +13,14 @@ class GivetreasureCommand(MagicktreasureCommand): syntax: str = "{codice} {valore}" - async def _permission_check(self, author, code, value, data): + async def _permission_check(self, author, code, value, data, session): if author.fiorygi.fiorygi < value: raise rc.UserError("Non hai abbastanza fiorygi per creare questo Treasure.") - async def _create_treasure(self, author, code, value, data): + async def _create_treasure(self, author, code, value, data, session): TreasureT = self.alchemy.get(Treasure) - treasure = await ru.asyncify(data.session.query(TreasureT).get, code) + treasure = await ru.asyncify(session.query(TreasureT).get, code) if treasure is not None: raise rc.UserError("Esiste già un Treasure con quel codice.") diff --git a/royalpack/commands/help.py b/royalpack/commands/help.py index ca129d18..a4109841 100644 --- a/royalpack/commands/help.py +++ b/royalpack/commands/help.py @@ -17,19 +17,19 @@ class HelpCommand(rc.Command): ] for command in sorted(list(set(self.serf.commands.values())), key=lambda c: c.name): - message.append(f"- [c]{self.interface.prefix}{command.name}[/c]") + message.append(f"- [c]{self.serf.prefix}{command.name}[/c]") await data.reply("\n".join(message)) else: - name: str = args[0].lstrip(self.interface.prefix) + name: str = args[0].lstrip(self.serf.prefix) try: - command: rc.Command = self.serf.commands[f"{self.interface.prefix}{name}"] + command: rc.Command = self.serf.commands[f"{self.serf.prefix}{name}"] except KeyError: raise rc.InvalidInputError("Il comando richiesto non esiste.") message = [ - f"ℹ️ [c]{self.interface.prefix}{command.name} {command.syntax}[/c]", + f"ℹ️ [c]{self.serf.prefix}{command.name} {command.syntax}[/c]", "", f"{command.description}" ] diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 0925a9fb..049128c0 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -29,8 +29,8 @@ class LeagueoflegendsCommand(LinkerCommand): "rank_flexq": "Flex", } - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) + def __init__(self, serf, config): + super().__init__(serf, config) self._lolwatcher: Optional[riotwatcher.RiotWatcher] = None self._tftwatcher: Optional[riotwatcher.RiotWatcher] = None if self.enabled(): diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py index 3f98f64e..cd86a010 100644 --- a/royalpack/commands/magickfiorygi.py +++ b/royalpack/commands/magickfiorygi.py @@ -23,7 +23,8 @@ class MagickfiorygiCommand(rc.Command): if user_arg is None: raise rc.InvalidInputError("Non hai specificato un destinatario!") - user = await rbt.User.find(self.alchemy, data.session, user_arg) + async with data.session_acm() as session: + user = await rbt.User.find(self.alchemy, session, user_arg) if user is None: raise rc.InvalidInputError("L'utente specificato non esiste!") diff --git a/royalpack/commands/magicktreasure.py b/royalpack/commands/magicktreasure.py index 8752d08a..e0872641 100644 --- a/royalpack/commands/magicktreasure.py +++ b/royalpack/commands/magicktreasure.py @@ -12,15 +12,15 @@ class MagicktreasureCommand(rc.Command): syntax: str = "{codice} {valore}" - async def _permission_check(self, author, code, value, data): + async def _permission_check(self, author, code, value, data, session): if "banker" not in author.roles: raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") return author - async def _create_treasure(self, author, code, value, data): + async def _create_treasure(self, author, code, value, data, session): TreasureT = self.alchemy.get(Treasure) - treasure = await ru.asyncify(data.session.query(TreasureT).get, code) + treasure = await ru.asyncify(session.query(TreasureT).get, code) if treasure is not None: raise rc.UserError("Esiste già un Treasure con quel codice.") @@ -44,10 +44,10 @@ class MagicktreasureCommand(rc.Command): if value < 0: raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.") - await self._permission_check(author, code, value, data) - treasure = await self._create_treasure(author, code, value, data) - - data.session.add(treasure) - await data.session_commit() + async with data.session_acm() as session: + await self._permission_check(author, code, value, data, session) + treasure = await self._create_treasure(author, code, value, data, session) + session.add(treasure) + await ru.asyncify(session.commit) await data.reply("✅ Treasure creato!") diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index fa601be5..53f9fcb6 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -3,7 +3,9 @@ import datetime import re import dateparser import typing +import royalnet.utils as ru import royalnet.commands as rc +import royalnet.serf.telegram as rst from ..tables import MMEvent from ..utils import MMTask @@ -18,20 +20,20 @@ class MatchmakingCommand(rc.Command): aliases = ["mm", "lfg"] - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) + def __init__(self, serf, config): + super().__init__(serf, config) # Find all active MMEvents and run the tasks for them session = self.alchemy.Session() # Create a new MMEvent and run it - if self.interface.name == "telegram": + if isinstance(self.serf, rst.TelegramSerf): MMEventT = self.alchemy.get(MMEvent) active_mmevents = ( session .query(MMEventT) .filter( - MMEventT.interface == self.interface.name, + MMEventT.interface == self.serf.interface_name, MMEventT.interrupted == False ) .all() @@ -74,13 +76,14 @@ class MatchmakingCommand(rc.Command): dt, title, description = self._parse_args(args) # Add the MMEvent to the database - mmevent: MMEvent = self.alchemy.get(MMEvent)(creator=author, - datetime=dt, - title=title, - description=description, - interface=self.interface.name) - data.session.add(mmevent) - await data.session_commit() + async with data.session_acm() as session: + mmevent: MMEvent = self.alchemy.get(MMEvent)(creator=author, + datetime=dt, + title=title, + description=description, + interface=self.serf.interface_name) + session.add(mmevent) + await ru.asyncify(session.commit) # Create and run a task for the newly created MMEvent task = MMTask(mmevent.mmid, command=self) diff --git a/royalpack/commands/osu.py b/royalpack/commands/osu.py index ce0dedfb..1a7f1c7c 100644 --- a/royalpack/commands/osu.py +++ b/royalpack/commands/osu.py @@ -7,7 +7,6 @@ import royalnet.commands as rc import royalnet.utils as ru from .abstract.linker import LinkerCommand -from ..types import Updatable from ..tables import Osu from ..stars.api_auth_login_osu import ApiAuthLoginOsuStar diff --git a/royalpack/commands/peertubeupdates.py b/royalpack/commands/peertubeupdates.py deleted file mode 100644 index 6c19a196..00000000 --- a/royalpack/commands/peertubeupdates.py +++ /dev/null @@ -1,81 +0,0 @@ -from typing import * -import aiohttp -import asyncio -import datetime -import logging -import dateparser -import royalnet.commands as rc -import royalnet.serf.telegram as rst - - -log = logging.getLogger(__name__) - - -class PeertubeUpdatesCommand(rc.Command): - name: str = "peertubeupdates" - - description: str = "Guarda quando è uscito l'ultimo video su PeerTube." - - aliases = ["ptu"] - - _ready = asyncio.Event() - - _latest_date: datetime.datetime = None - - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) - if self.interface.name == "telegram": - self.loop.create_task(self._ready_up()) - self.loop.create_task(self._update()) - - async def _get_json(self): - log.debug("Getting jsonfeed") - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Peertube"]["instance_url"] + - "/feeds/videos.json?sort=-publishedAt&filter=local") as response: - log.debug("Parsing jsonfeed") - if response.status != 200: - raise rc.ExternalError("Peertube is unavailable") - j = await response.json() - log.debug("Jsonfeed parsed successfully") - return j - - async def _send(self, message): - client = self.interface.bot.client - await self.interface.bot.safe_api_call(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=rst.escape(message), - parse_mode="HTML", - disable_webpage_preview=True) - - async def _ready_up(self): - j = await self._get_json() - if j["version"] != "https://jsonfeed.org/version/1": - raise rc.ConfigurationError("url is not a jsonfeed") - videos = j["items"] - for video in reversed(videos): - date_modified = dateparser.parse(video["date_modified"]) - if self._latest_date is None or date_modified > self._latest_date: - log.debug(f"Found newer video: {date_modified}") - self._latest_date = date_modified - self._ready.set() - - async def _update(self): - await self._ready.wait() - while True: - j = await self._get_json() - videos = j["items"] - for video in reversed(videos): - date_modified = dateparser.parse(video["date_modified"]) - if date_modified > self._latest_date: - log.debug(f"Found newer video: {date_modified}") - self._latest_date = date_modified - await self._send(f"🆕 Nuovo video su RoyalTube!\n" - f"[b]{video['title']}[/b]\n" - f"{video['url']}") - await asyncio.sleep(self.config["Peertube"]["feed_update_timeout"]) - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name != "telegram": - raise rc.UnsupportedError() - await data.reply(f"ℹ️ Ultimo video caricato il: [b]{self._latest_date.isoformat()}[/b]") diff --git a/royalpack/commands/ping.py b/royalpack/commands/ping.py index 576f6e63..8230b62a 100644 --- a/royalpack/commands/ping.py +++ b/royalpack/commands/ping.py @@ -12,7 +12,7 @@ class PingCommand(rc.Command): syntax: str = "" - _targets = ["telegram", "discord", "matrix", "constellation"] + _targets = ["telegram", "discord", "constellation"] async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: await data.reply("📶 Ping...") @@ -21,7 +21,7 @@ class PingCommand(rc.Command): start = datetime.datetime.now() for target in self._targets: - tasks[target] = self.loop.create_task(self.interface.call_herald_event(target, "pong")) + tasks[target] = self.loop.create_task(self.serf.call_herald_event(target, "pong")) await asyncio.sleep(10) diff --git a/royalpack/commands/reminder.py b/royalpack/commands/reminder.py index 48d7075a..cfa89d27 100644 --- a/royalpack/commands/reminder.py +++ b/royalpack/commands/reminder.py @@ -7,8 +7,8 @@ import discord from sqlalchemy import and_ import royalnet.commands as rc import royalnet.utils as ru -from royalnet.serf.telegram import escape as telegram_escape -from royalnet.serf.discord import escape as discord_escape +import royalnet.serf.telegram as rst +import royalnet.serf.discord as rsd from ..tables import Reminder @@ -22,34 +22,35 @@ class ReminderCommand(rc.Command): syntax: str = "[ {data} ] {messaggio}" - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) - session = interface.alchemy.Session() + def __init__(self, serf, config): + super().__init__(serf, config) + + session = self.alchemy.Session() reminders = ( - session.query(interface.alchemy.get(Reminder)) + session.query(self.alchemy.get(Reminder)) .filter(and_( - interface.alchemy.get(Reminder).datetime >= datetime.datetime.now(), - interface.alchemy.get(Reminder).interface_name == interface.name)) + self.alchemy.get(Reminder).datetime >= datetime.datetime.now(), + self.alchemy.get(Reminder).interface_name == self.serf.interface_name)) .all() ) for reminder in reminders: - interface.loop.create_task(self._remind(reminder)) + self.loop.create_task(self._remind(reminder)) async def _remind(self, reminder): await ru.sleep_until(reminder.datetime) - if self.interface.name == "telegram": + if isinstance(self.serf, rst.TelegramSerf): chat_id: int = pickle.loads(reminder.interface_data) client: telegram.Bot = self.serf.client await self.serf.api_call(client.send_message, chat_id=chat_id, - text=telegram_escape(f"❗️ {reminder.message}"), + text=rst.escape(f"❗️ {reminder.message}"), parse_mode="HTML", disable_web_page_preview=True) - elif self.interface.name == "discord": + elif isinstance(self.serf, rsd.DiscordSerf): channel_id: int = pickle.loads(reminder.interface_data) client: discord.Client = self.serf.client channel = client.get_channel(channel_id) - await channel.send(discord_escape(f"❗️ {reminder.message}")) + await channel.send(rsd.escape(f"❗️ {reminder.message}")) async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: try: @@ -70,18 +71,19 @@ class ReminderCommand(rc.Command): await data.reply("⚠️ La data che hai specificato è nel passato.") return await data.reply(f"✅ Promemoria impostato per [b]{date.strftime('%Y-%m-%d %H:%M:%S')}[/b]") - if self.interface.name == "telegram": + if isinstance(self.serf, rst.TelegramSerf): interface_data = pickle.dumps(data.message.chat.id) - elif self.interface.name == "discord": + elif isinstance(self.serf, rsd.DiscordSerf): interface_data = pickle.dumps(data.message.channel.id) else: raise rc.UnsupportedError("This command does not support the current interface.") creator = await data.get_author() - reminder = self.interface.alchemy.get(Reminder)(creator=creator, - interface_name=self.interface.name, - interface_data=interface_data, - datetime=date, - message=reminder_text) - self.interface.loop.create_task(self._remind(reminder)) - data.session.add(reminder) - await ru.asyncify(data.session.commit) + async with data.session_acm() as session: + reminder = self.alchemy.get(Reminder)(creator=creator, + interface_name=self.serf.interface_name, + interface_data=interface_data, + datetime=date, + message=reminder_text) + self.loop.create_task(self._remind(reminder)) + session.add(reminder) + await ru.asyncify(session.commit) diff --git a/royalpack/commands/royalpackversion.py b/royalpack/commands/royalpackversion.py index b397987c..a9ef4f27 100644 --- a/royalpack/commands/royalpackversion.py +++ b/royalpack/commands/royalpackversion.py @@ -16,10 +16,7 @@ class RoyalpackCommand(rc.Command): return pkg_resources.get_distribution("royalpack").version async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if __debug__: - message = f"ℹ️ Royalpack [url=https://github.com/Steffo99/royalpack/]Unreleased[/url]\n" - else: - message = f"ℹ️ Royalpack [url=https://github.com/Steffo99/royalpack/releases/tag/{self.royalpack_version}]{self.royalpack_version}[/url]\n" + message = f"ℹ️ Royalpack [url=https://github.com/Steffo99/royalpack/releases/tag/{self.royalpack_version}]{self.royalpack_version}[/url]\n" if "69" in self.royalpack_version: message += "(Nice.)" await data.reply(message) diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index 90cb2171..1c859217 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -53,8 +53,8 @@ class SteammatchCommand(rc.Command): syntax: str = "{royalnet_username}+" - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) + def __init__(self, serf, config): + super().__init__(serf, config) self._api = steam.webapi.WebAPI(self.config["steampowered"]["token"]) async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: @@ -64,7 +64,8 @@ class SteammatchCommand(rc.Command): users.append(author) for arg in args: - user = await rbt.User.find(self.alchemy, data.session, arg) + async with data.session_acm() as session: + user = await rbt.User.find(self.alchemy, session, arg) users.append(user) if len(users) < 2: diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 662c61c7..395f1d41 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -22,8 +22,8 @@ class SteampoweredCommand(LinkerCommand): syntax: str = "{url_profilo}" - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) + def __init__(self, serf, config): + super().__init__(serf, config) self._api = steam.webapi.WebAPI(self.token()) def token(self): diff --git a/royalpack/commands/treasure.py b/royalpack/commands/treasure.py index bc7337d2..6b5ad7f3 100644 --- a/royalpack/commands/treasure.py +++ b/royalpack/commands/treasure.py @@ -16,16 +16,17 @@ class TreasureCommand(rc.Command): author = await data.get_author(error_if_none=True) code = args[0].lower() - TreasureT = self.alchemy.get(Treasure) + async with data.session_acm() as session: + TreasureT = self.alchemy.get(Treasure) - treasure = await ru.asyncify(data.session.query(TreasureT).get, code) - if treasure is None: - raise rc.UserError("Non esiste nessun Treasure con quel codice.") - if treasure.redeemed_by is not None: - raise rc.UserError(f"Quel tesoro è già stato riscattato da {treasure.redeemed_by}.") + treasure = await ru.asyncify(session.query(TreasureT).get, code) + if treasure is None: + raise rc.UserError("Non esiste nessun Treasure con quel codice.") + if treasure.redeemed_by is not None: + raise rc.UserError(f"Quel tesoro è già stato riscattato da {treasure.redeemed_by}.") - treasure.redeemed_by = author - await data.session_commit() + treasure.redeemed_by = author + await ru.asyncify(session.commit) await FiorygiTransaction.spawn_fiorygi(data, author, treasure.value, diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index d5226028..502818dd 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -31,117 +31,116 @@ class TriviaCommand(rc.Command): # _question_lock: bool = False - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) + def __init__(self, serf, config): + super().__init__(serf, config) self._answerers: Dict[uuid.UUID, Dict[str, bool]] = {} async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: arg = args.optional(0) - if arg == "credits": - await data.reply(f"ℹ️ [c]{self.interface.prefix}{self.name}[/c] di [i]Steffo[/i]\n" - f"\n" - f"Tutte le domande vengono dall'[b]Open Trivia Database[/b] di [i]Pixeltail Games[/i]," - f" creatori di Tower Unite, e sono rilasciate sotto la licenza [b]CC BY-SA 4.0[/b].") - return - elif arg == "scores": - trivia_scores = await ru.asyncify(data.session.query(self.alchemy.get(TriviaScore)).all) - strings = ["🏆 [b]Trivia Leaderboards[/b]\n"] - for index, ts in enumerate(sorted(trivia_scores, key=lambda ts: -ts.score)): - if index > 3: - index = 3 - strings.append(f"{self._medal_emojis[index]} {ts.user.username}: [b]{ts.score:.0f}p[/b]" - f" ({ts.correct_answers}/{ts.total_answers})") - await data.reply("\n".join(strings)) - return - # if self._question_lock: - # raise rc.CommandError("C'è già un'altra domanda attiva!") - # self._question_lock = True - # Fetch the question - async with aiohttp.ClientSession() as session: - async with session.get("https://opentdb.com/api.php?amount=1") as response: - j = await response.json() - # Parse the question - if j["response_code"] != 0: - raise rc.CommandError(f"OpenTDB returned an error response_code ({j['response_code']}).") - question = j["results"][0] - text = f'❓ [b]{question["category"]}[/b]\n' \ - f'{html.unescape(question["question"])}' - # Prepare answers - correct_answer: str = question["correct_answer"] - wrong_answers: List[str] = question["incorrect_answers"] - answers: List[str] = [correct_answer, *wrong_answers] - if question["type"] == "multiple": - random.shuffle(answers) - elif question["type"] == "boolean": - answers.sort(key=lambda a: a) - answers.reverse() - else: - raise NotImplementedError("Unknown question type") - # Find the correct index - for index, answer in enumerate(answers): - if answer == correct_answer: - correct_index = index - break - else: - raise ValueError("correct_index not found") - # Add emojis - for index, answer in enumerate(answers): - answers[index] = f"{self._letter_emojis[index]} {html.unescape(answers[index])}" - # Create the question id - question_id = uuid.uuid4() - self._answerers[question_id] = {} - - # Create the correct and wrong functions - async def correct(data: rc.CommandData): - answerer_ = await data.get_author(error_if_none=True) - try: - self._answerers[question_id][answerer_.uid] = True - except KeyError: - raise rc.UserError("Tempo scaduto!") - await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!") - - async def wrong(data: rc.CommandData): - answerer_ = await data.get_author(error_if_none=True) - try: - self._answerers[question_id][answerer_.uid] = False - except KeyError: - raise rc.UserError("Tempo scaduto!") - await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!") - - # Add question - keyboard: List[rc.KeyboardKey] = [] - for index, answer in enumerate(answers): - if index == correct_index: - keyboard.append(rc.KeyboardKey(interface=self.interface, - short=self._letter_emojis[index], - text=answers[index], - callback=correct)) + async with data.session_acm() as session: + if arg == "credits": + await data.reply(f"ℹ️ [c]{self.serf.prefix}{self.name}[/c] di [i]Steffo[/i]\n" + f"\n" + f"Tutte le domande vengono dall'[b]Open Trivia Database[/b] di [i]Pixeltail Games[/i]," + f" creatori di Tower Unite, e sono rilasciate sotto la licenza [b]CC BY-SA 4.0[/b].") + return + elif arg == "scores": + trivia_scores = await ru.asyncify(session.query(self.alchemy.get(TriviaScore)).all) + strings = ["🏆 [b]Trivia Leaderboards[/b]\n"] + for index, ts in enumerate(sorted(trivia_scores, key=lambda ts: -ts.score)): + if index > 3: + index = 3 + strings.append(f"{self._medal_emojis[index]} {ts.user.username}: [b]{ts.score:.0f}p[/b]" + f" ({ts.correct_answers}/{ts.total_answers})") + await data.reply("\n".join(strings)) + return + # if self._question_lock: + # raise rc.CommandError("C'è già un'altra domanda attiva!") + # self._question_lock = True + # Fetch the question + async with aiohttp.ClientSession() as ws: + async with ws.get("https://opentdb.com/api.php?amount=1") as response: + j = await response.json() + # Parse the question + if j["response_code"] != 0: + raise rc.CommandError(f"OpenTDB returned an error response_code ({j['response_code']}).") + question = j["results"][0] + text = f'❓ [b]{question["category"]}[/b]\n' \ + f'{html.unescape(question["question"])}' + # Prepare answers + correct_answer: str = question["correct_answer"] + wrong_answers: List[str] = question["incorrect_answers"] + answers: List[str] = [correct_answer, *wrong_answers] + if question["type"] == "multiple": + random.shuffle(answers) + elif question["type"] == "boolean": + answers.sort(key=lambda a: a) + answers.reverse() else: - keyboard.append(rc.KeyboardKey(interface=self.interface, - short=self._letter_emojis[index], - text=answers[index], - callback=wrong)) - async with data.keyboard(text=text, keys=keyboard): - await asyncio.sleep(self._answer_time) - results = f"❗️ Tempo scaduto!\n" \ - f"La risposta corretta era [b]{answers[correct_index]}[/b]!\n\n" - for answerer_id in self._answerers[question_id]: - answerer = data.session.query(self.alchemy.get(rbt.users.User)).get(answerer_id) - if answerer.trivia_score is None: - ts = self.interface.alchemy.get(TriviaScore)(user=answerer) - data.session.add(ts) - await ru.asyncify(data.session.commit) - previous_score = answerer.trivia_score.score - if self._answerers[question_id][answerer_id]: - results += self._correct_emoji - answerer.trivia_score.correct_answers += 1 + raise NotImplementedError("Unknown question type") + # Find the correct index + for index, answer in enumerate(answers): + if answer == correct_answer: + correct_index = index + break else: - results += self._wrong_emoji - answerer.trivia_score.wrong_answers += 1 - current_score = answerer.trivia_score.score - score_difference = current_score - previous_score - results += f" {answerer}: [b]{current_score:.0f}p[/b] ({score_difference:+.0f}p)\n" - await data.reply(results) - del self._answerers[question_id] - await ru.asyncify(data.session.commit) - # self._question_lock = False + raise ValueError("correct_index not found") + # Add emojis + for index, answer in enumerate(answers): + answers[index] = f"{self._letter_emojis[index]} {html.unescape(answers[index])}" + # Create the question id + question_id = uuid.uuid4() + self._answerers[question_id] = {} + + # Create the correct and wrong functions + async def correct(data: rc.CommandData): + answerer_ = await data.get_author(error_if_none=True) + try: + self._answerers[question_id][answerer_.uid] = True + except KeyError: + raise rc.UserError("Tempo scaduto!") + await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!") + + async def wrong(data: rc.CommandData): + answerer_ = await data.get_author(error_if_none=True) + try: + self._answerers[question_id][answerer_.uid] = False + except KeyError: + raise rc.UserError("Tempo scaduto!") + await data.reply("🆗 Hai risposto alla domanda. Ora aspetta un attimo per i risultati!") + + # Add question + keyboard: List[rc.KeyboardKey] = [] + for index, answer in enumerate(answers): + if index == correct_index: + keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index], + text=answers[index], + callback=correct)) + else: + keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index], + text=answers[index], + callback=wrong)) + async with data.keyboard(text=text, keys=keyboard): + await asyncio.sleep(self._answer_time) + results = f"❗️ Tempo scaduto!\n" \ + f"La risposta corretta era [b]{answers[correct_index]}[/b]!\n\n" + for answerer_id in self._answerers[question_id]: + answerer = session.query(self.alchemy.get(rbt.users.User)).get(answerer_id) + if answerer.trivia_score is None: + ts = self.alchemy.get(TriviaScore)(user=answerer) + session.add(ts) + await ru.asyncify(session.commit) + previous_score = answerer.trivia_score.score + if self._answerers[question_id][answerer_id]: + results += self._correct_emoji + answerer.trivia_score.correct_answers += 1 + else: + results += self._wrong_emoji + answerer.trivia_score.wrong_answers += 1 + current_score = answerer.trivia_score.score + score_difference = current_score - previous_score + results += f" {answerer}: [b]{current_score:.0f}p[/b] ({score_difference:+.0f}p)\n" + await data.reply(results) + del self._answerers[question_id] + await ru.asyncify(session.commit) + # self._question_lock = False diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py deleted file mode 100644 index 2917f569..00000000 --- a/royalpack/commands/userinfo.py +++ /dev/null @@ -1,74 +0,0 @@ -from typing import * -import royalnet.commands as rc -import royalnet.backpack.tables as rbt - - -class UserinfoCommand(rc.Command): - name: str = "userinfo" - - aliases = ["uinfo", "ui", "useri"] - - description: str = "Visualizza informazioni su un utente." - - syntax = "[username]" - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - username = args.optional(0) - if username is None: - user: rbt.User = await data.get_author(error_if_none=True) - else: - found: Optional[rbt.User] = await rbt.User.find(self.alchemy, data.session, username) - if not found: - raise rc.InvalidInputError("Utente non trovato.") - else: - user = found - - r = [ - f"ℹ️ [url=https://ryg.steffo.eu/#/user/{user.uid}]{user.username}[/url]", - f"{', '.join(user.roles)}", - ] - - if user.email: - r.append(f"{user.email}") - - r.append("") - - # Bios are a bit too long - # if user.bio: - # r.append(f"{user.bio}") - - for account in user.telegram: - r.append(f"{account}") - - for account in user.discord: - r.append(f"{account}") - - for account in user.steam: - r.append(f"{account}") - if account.dota is not None: - r.append(f"{account.dota}") - if account.brawlhalla is not None: - r.append(f"{account.brawlhalla}") - - for account in user.leagueoflegends: - r.append(f"{account}") - - r.append("") - - r.append(f"Ha creato [b]{len(user.diario_created)}[/b] righe di " - f"[url=https://ryg.steffo.eu/#/diario]Diario[/url], e vi compare in" - f" [b]{len(user.diario_quoted)}[/b] righe.") - - r.append("") - - if user.trivia_score: - r.append(f"Ha [b]{user.trivia_score.score:.0f}[/b] punti Trivia, avendo risposto correttamente a" - f" [b]{user.trivia_score.correct_answers}[/b] domande su" - f" [b]{user.trivia_score.total_answers}[/b].") - r.append("") - - if user.fiorygi: - r.append(f"Ha [b]{user.fiorygi}[/b].") - r.append("") - - await data.reply("\n".join(r)) diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py index 406381e8..6f6cf224 100644 --- a/royalpack/tables/fiorygitransactions.py +++ b/royalpack/tables/fiorygitransactions.py @@ -4,6 +4,7 @@ import datetime from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declared_attr +import royalnet.utils as ru from .fiorygi import Fiorygi @@ -48,35 +49,38 @@ class FiorygiTransaction: @classmethod async def spawn_fiorygi(cls, data: "CommandData", user, qty: int, reason: str): if user.fiorygi is None: - data.session.add(data._interface.alchemy.get(Fiorygi)( + async with data.session_acm() as session: + session.add(data.alchemy.get(Fiorygi)( + user_id=user.uid, + fiorygi=0 + )) + await ru.asyncify(session.commit) + + async with data.session_acm() as session: + transaction = data.alchemy.get(FiorygiTransaction)( user_id=user.uid, - fiorygi=0 - )) - await data.session_commit() + change=qty, + reason=reason, + timestamp=datetime.datetime.now() + ) + session.add(transaction) - transaction = data._interface.alchemy.get(FiorygiTransaction)( - user_id=user.uid, - change=qty, - reason=reason, - timestamp=datetime.datetime.now() - ) - data.session.add(transaction) + user.fiorygi.fiorygi += qty + await ru.asyncify(session.commit) - user.fiorygi.fiorygi += qty - await data.session_commit() + if len(user.telegram) > 0: + user_str = user.telegram[0].mention() + else: + user_str = user.username - if len(user.telegram) > 0: - user_str = user.telegram[0].mention() - else: - user_str = user.username + if qty > 0: + msg = f"💰 [b]{user_str}[/b] ha ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''} per [i]{reason}[/i]!" + elif qty == 0: + msg = f"❓ [b]{user_str}[/b] ha mantenuto i suoi fiorygi attuali per [i]{reason}[/i].\nWait, cosa?" + else: + msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason}[/i]." - if qty > 0: - msg = f"💰 [b]{user_str}[/b] ha ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''} per [i]{reason}[/i]!" - elif qty == 0: - msg = f"❓ [b]{user_str}[/b] ha mantenuto i suoi fiorygi attuali per [i]{reason}[/i].\nWait, cosa?" - else: - msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason}[/i]." - - await data._interface.call_herald_event("telegram", "telegram_message", - chat_id=data._interface.config["Telegram"]["main_group_id"], - text=msg) + await data.command.serf.call_herald_event( + "telegram", "telegram_message", + chat_id=data.command.config["Telegram"]["main_group_id"], + text=msg)