From 5ed03118c0677216b1e9e225a5ff7221ee40b635 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 6 Jan 2020 00:44:02 +0100 Subject: [PATCH 001/227] Add funkwhale command --- pyproject.toml | 2 +- royalpack/commands/__init__.py | 1 + royalpack/commands/funkwhale.py | 24 ++++++++++++++++++++++++ royalpack/version.py | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 royalpack/commands/funkwhale.py diff --git a/pyproject.toml b/pyproject.toml index 01b5f50b..226f19bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.1.9" + version = "5.1.10" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 6921a8e5..ad70374a 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -27,6 +27,7 @@ from .ahnonlosoio import AhnonlosoioCommand from .eat import EatCommand from .pmots import PmotsCommand from .peertube import PeertubeCommand +from .funkwhale import FunkwhaleCommand from .eval import EvalCommand from .exec import ExecCommand diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py new file mode 100644 index 00000000..cecf1d7b --- /dev/null +++ b/royalpack/commands/funkwhale.py @@ -0,0 +1,24 @@ +from .play import PlayCommand +from royalnet.commands import * +import aiohttp +import urllib.parse + + +class FunkwhaleCommand(PlayCommand): + name: str = "funkwhale" + + aliases = ["fw", "royalwhale", "rw"] + + description: str = "Cerca un video su RoyalWhale e lo aggiunge alla coda della chat vocale." + + syntax = "{ricerca}" + + async def get_url(self, args): + search = urllib.parse.quote(args.joined(require_at_least=1)) + async with aiohttp.ClientSession() as session: + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/search?query={search}") as response: + j = await response.json() + if len(j["tracks"]) < 1: + raise InvalidInputError("Nessun video trovato.") + return f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}' diff --git a/royalpack/version.py b/royalpack/version.py index a0d642bb..c3eb0c9c 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.1.9" +semantic = "5.1.10" From d895e2e0b7c37c963a7fede9fecfd38614d51ba7 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 6 Jan 2020 00:46:22 +0100 Subject: [PATCH 002/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 226f19bb..d008a437 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.1.10" + version = "5.1.11" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index c3eb0c9c..15dfaae0 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.1.10" +semantic = "5.1.11" From bab11c177b67771cbcd0cee9b37844d9ee23c20c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 6 Jan 2020 00:57:02 +0100 Subject: [PATCH 003/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d008a437..e63b846e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.1.11" + version = "5.2.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 15dfaae0..286c364d 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.1.11" +semantic = "5.2.2" From 7721368b9b0820b34d1f8b3e263748a83f3fac59 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 6 Jan 2020 01:00:51 +0100 Subject: [PATCH 004/227] derp --- pyproject.toml | 2 +- royalpack/commands/__init__.py | 1 + royalpack/version.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e63b846e..cfa26d90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.2" + version = "5.2.3" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index ad70374a..7bee64cc 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -63,6 +63,7 @@ available_commands = [ PeertubeCommand, EvalCommand, ExecCommand, + FunkwhaleCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/version.py b/royalpack/version.py index 286c364d..08723330 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.2" +semantic = "5.2.3" From 334a835d2c3098cab5edef4ede20fb049796a52e Mon Sep 17 00:00:00 2001 From: Cookie <58516648+Cookie-CHR@users.noreply.github.com> Date: Mon, 6 Jan 2020 20:23:59 +0100 Subject: [PATCH 005/227] Update eat.py Aggiunti alcuni nuovi cibi --- royalpack/commands/eat.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index da10a809..07d2e3e7 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -47,6 +47,7 @@ class EatCommand(Command): # sezione con piante e anmali "cactus": "🌵 Hai mangiato un {food}.\n[i]Gli hai tolto le spine prima, vero?[/i]", "tango": "🌳 Hai mangiato un {food}, e un albero insieme ad esso.\n[i]Senti le tue ferite curarsi...[/i]", + "foglia": "🍁 Hai mangiato la {food}.\n[i]A te non la si fa![/i]" "gatto": "🐱 Vieni fermato prima di poter compiere questo gesto orribile.\n" "[i]Il {food} verrà pettato da tutti per farlo riavere dal trauma.[/i]", "3 porcellini": "🐷 Hai mangiato i {food}.\n[i]La casa di mattoni non è bastata a fermarti![/i]", @@ -109,8 +110,20 @@ class EatCommand(Command): "red hat": "🐧 Hai mangiato {food}.\n[i]La tua anima appartiene a IBM, ora.[/i]", "redhat": "🐧 Hai mangiato {food}.\n[i]La tua anima appartiene a IBM, ora.[/i]", "linux from scratch": "🐧 Hai mangiato {food}.\n[i]Sei diventato un puzzle.[/i]", - + + #Citazioni da film (nello specifico dai Blues Brothers) + "pane bianco tostato liscio, quattro polli fritti e una coca": "🕶 Tu e tuo fratello avete ordinato {food}." + " Il cuoco vi ha riconosciuto e vuole tornare a suonare nella vostra band.\n[i]Sua moglie gliene canta" + " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]" + "pane bianco tostato liscio": "🕶 Tu e tuo fratello avete ordinato {food}, quattro polli fritti e una coca." + " Il cuoco vi ha riconosciuto e vuole tornare a suonare nella vostra band.\n[i]Sua moglie gliene canta" + " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]" + "quattro polli fritti e una coca": "🕶 Tu e tuo fratello avete ordinato pane bianco tostato liscio, {food}." + " Il cuoco vi ha riconosciuto e vuole tornare a suonare nella vostra band.\n[i]Sua moglie gliene canta" + " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]" + # Altro + "vendetta": "😈 Ti sei gustato la tua {food}.\n[i]Deliziosa, se servita fredda![/i]", "demone": "👿 Hai mangiato un {food}. Non l'ha presa bene...\n[i]Hai terribili bruciori di stomaco.[/i]", "diavolo": "👿 Hai mangiato un {food}. Non l'ha presa bene...\n[i]Hai terribili bruciori di stomaco.[/i]", "cacca": "💩 Che schifo! Hai mangiato {food}!\n[i]Allontati per favore, PLEH![/i]", @@ -121,12 +134,15 @@ class EatCommand(Command): "bot": "🤖 Come osi provare a mangiarmi?!\n[i]Il {food} è arrabbiato con te.[/i]", "royal bot": "🤖 Come osi provare a mangiarmi?!\n[i]Il {food} è arrabbiato con te.[/i]", "re": "👑 Hai mangiato il {food} avversario! \n[i]Scacco matto![/i]", + "furry": "🐕 Hai mangiato {food}.\n[i]OwO[/i] "polvere": "☁️ Hai mangiato la {food}.\n[i]Ti hanno proprio battuto![/i]", "giaroun": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "giarone": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "sasso": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "bomba": "💣 Hai mangiato una {food}. Speriamo fosse solo calorica!\n[i]3... 2... 1...[/i]", "ass": "🕳 Hai mangiato {food}./n[i]Bleah! Lo sai cosa fa quel coso per sopravvivere?[/i]", + "onion": "🗞 You ate the {food}. Ci sei proprio cascato!\n[i] Hai mai creduto a una notizia di Lercio," + "invece?[/i] "uranio": "☢️ L'{food} che hai mangiato era radioattivo.\n[i]Stai brillando di verde![/i]", "tide pod": "☣️ I {food} che hai mangiato erano buonissimi.\n[i]Stai sbiancando![/i]", "tide pods": "☣️ I {food} che hai mangiato erano buonissimi.\n[i]Stai sbiancando![/i]", From 34c3d2ee51c799c88f4ec734abee1c7a6207fc7c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 7 Jan 2020 02:33:28 +0100 Subject: [PATCH 006/227] Messe le virgole :P --- royalpack/commands/eat.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 07d2e3e7..9618b45b 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -47,7 +47,7 @@ class EatCommand(Command): # sezione con piante e anmali "cactus": "🌵 Hai mangiato un {food}.\n[i]Gli hai tolto le spine prima, vero?[/i]", "tango": "🌳 Hai mangiato un {food}, e un albero insieme ad esso.\n[i]Senti le tue ferite curarsi...[/i]", - "foglia": "🍁 Hai mangiato la {food}.\n[i]A te non la si fa![/i]" + "foglia": "🍁 Hai mangiato la {food}.\n[i]A te non la si fa![/i]", "gatto": "🐱 Vieni fermato prima di poter compiere questo gesto orribile.\n" "[i]Il {food} verrà pettato da tutti per farlo riavere dal trauma.[/i]", "3 porcellini": "🐷 Hai mangiato i {food}.\n[i]La casa di mattoni non è bastata a fermarti![/i]", @@ -111,16 +111,16 @@ class EatCommand(Command): "redhat": "🐧 Hai mangiato {food}.\n[i]La tua anima appartiene a IBM, ora.[/i]", "linux from scratch": "🐧 Hai mangiato {food}.\n[i]Sei diventato un puzzle.[/i]", - #Citazioni da film (nello specifico dai Blues Brothers) + # Citazioni da film (nello specifico dai Blues Brothers) "pane bianco tostato liscio, quattro polli fritti e una coca": "🕶 Tu e tuo fratello avete ordinato {food}." " Il cuoco vi ha riconosciuto e vuole tornare a suonare nella vostra band.\n[i]Sua moglie gliene canta" - " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]" + " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]", "pane bianco tostato liscio": "🕶 Tu e tuo fratello avete ordinato {food}, quattro polli fritti e una coca." " Il cuoco vi ha riconosciuto e vuole tornare a suonare nella vostra band.\n[i]Sua moglie gliene canta" - " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]" + " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]", "quattro polli fritti e una coca": "🕶 Tu e tuo fratello avete ordinato pane bianco tostato liscio, {food}." " Il cuoco vi ha riconosciuto e vuole tornare a suonare nella vostra band.\n[i]Sua moglie gliene canta" - " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]" + " quattro (letteralmente), ma non riesce a fargli cambiare idea. Siete in missione per conto di Dio![/i]", # Altro "vendetta": "😈 Ti sei gustato la tua {food}.\n[i]Deliziosa, se servita fredda![/i]", @@ -134,15 +134,15 @@ class EatCommand(Command): "bot": "🤖 Come osi provare a mangiarmi?!\n[i]Il {food} è arrabbiato con te.[/i]", "royal bot": "🤖 Come osi provare a mangiarmi?!\n[i]Il {food} è arrabbiato con te.[/i]", "re": "👑 Hai mangiato il {food} avversario! \n[i]Scacco matto![/i]", - "furry": "🐕 Hai mangiato {food}.\n[i]OwO[/i] + "furry": "🐕 Hai mangiato {food}.\n[i]OwO[/i]", "polvere": "☁️ Hai mangiato la {food}.\n[i]Ti hanno proprio battuto![/i]", "giaroun": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "giarone": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "sasso": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "bomba": "💣 Hai mangiato una {food}. Speriamo fosse solo calorica!\n[i]3... 2... 1...[/i]", "ass": "🕳 Hai mangiato {food}./n[i]Bleah! Lo sai cosa fa quel coso per sopravvivere?[/i]", - "onion": "🗞 You ate the {food}. Ci sei proprio cascato!\n[i] Hai mai creduto a una notizia di Lercio," - "invece?[/i] + "onion": "🗞 You ate the {food}. Ci sei proprio cascato!\n [i]Hai mai creduto a una notizia di Lercio," + " invece?[/i]", "uranio": "☢️ L'{food} che hai mangiato era radioattivo.\n[i]Stai brillando di verde![/i]", "tide pod": "☣️ I {food} che hai mangiato erano buonissimi.\n[i]Stai sbiancando![/i]", "tide pods": "☣️ I {food} che hai mangiato erano buonissimi.\n[i]Stai sbiancando![/i]", From 0cce2c0a4b50f59fad69ee0b5bf07318af06ffd1 Mon Sep 17 00:00:00 2001 From: Fabio De Simone Date: Tue, 7 Jan 2020 21:10:14 +0100 Subject: [PATCH 007/227] Update funkwhale.py --- royalpack/commands/funkwhale.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index cecf1d7b..20f12600 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -5,9 +5,9 @@ import urllib.parse class FunkwhaleCommand(PlayCommand): - name: str = "funkwhale" + name: str = "fuckwhale" - aliases = ["fw", "royalwhale", "rw"] + aliases = ["funkwhale", "fw", "royalwhale", "rw"] description: str = "Cerca un video su RoyalWhale e lo aggiunge alla coda della chat vocale." From 2a0714b8b84aed6c2820992472afb9b2239d8562 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Jan 2020 03:14:56 +0100 Subject: [PATCH 008/227] Update and add markov --- .gitignore | 3 +- poetry.lock | 320 ++++++++++++++++++++++++++++----- pyproject.toml | 6 +- royalpack/commands/__init__.py | 2 + royalpack/commands/eat.py | 1 + royalpack/commands/markov.py | 35 ++++ royalpack/version.py | 2 +- 7 files changed, 319 insertions(+), 50 deletions(-) create mode 100644 royalpack/commands/markov.py diff --git a/.gitignore b/.gitignore index 01ed3d1f..cad48a6a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # Royalnet ignores config*.toml downloads/ - +markov/ # Python ignores **/__pycache__/ @@ -11,4 +11,3 @@ dist/ # PyCharm ignores .idea/ - diff --git a/poetry.lock b/poetry.lock index 14d8f8eb..fd6e11ea 100644 --- a/poetry.lock +++ b/poetry.lock @@ -158,7 +158,27 @@ description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" name = "h11" optional = false python-versions = "*" -version = "0.8.1" +version = "0.9.0" + +[[package]] +category = "main" +description = "HTTP/2 State-Machine based protocol implementation" +name = "h2" +optional = false +python-versions = "*" +version = "3.1.1" + +[package.dependencies] +hpack = ">=2.3,<4" +hyperframe = ">=5.2.0,<6" + +[[package]] +category = "main" +description = "Pure-Python HPACK header compression" +name = "hpack" +optional = false +python-versions = "*" +version = "3.0.0" [[package]] category = "main" @@ -180,6 +200,14 @@ version = "4.18" [package.dependencies] pyreadline = "*" +[[package]] +category = "main" +description = "HTTP/2 framing layer for Python" +name = "hyperframe" +optional = false +python-versions = "*" +version = "5.2.0" + [[package]] category = "main" description = "Internationalized Domain Names in Applications (IDNA)" @@ -188,13 +216,86 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.8" +[[package]] +category = "main" +description = "An implementation of JSON Schema validation for Python" +name = "jsonschema" +optional = false +python-versions = "*" +version = "3.2.0" + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0" +setuptools = "*" +six = ">=1.11.0" + +[package.extras] +format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] +format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] + +[[package]] +category = "main" +description = "A logging replacement for Python" +name = "logbook" +optional = false +python-versions = "*" +version = "1.5.3" + +[package.extras] +all = ["redis", "brotli", "pytest (>4.0)", "execnet (>=1.0.9)", "cython", "pyzmq", "pytest-cov (>=2.6)", "sqlalchemy", "jinja2"] +compression = ["brotli"] +dev = ["pytest-cov (>=2.6)", "pytest (>4.0)", "cython"] +execnet = ["execnet (>=1.0.9)"] +jinja = ["jinja2"] +redis = ["redis"] +sqlalchemy = ["sqlalchemy"] +test = ["pytest-cov (>=2.6)", "pytest (>4.0)"] +zmq = ["pyzmq"] + +[[package]] +category = "main" +description = "A simple, extensible Markov chain generator. Uses include generating random semi-plausible sentences based on an existing text." +name = "markovify" +optional = false +python-versions = "*" +version = "0.8.0" + +[package.dependencies] +unidecode = "*" + +[[package]] +category = "main" +description = "A Python Matrix client library, designed according to sans I/O principles." +name = "matrix-nio" +optional = false +python-versions = "*" +version = "0.6" + +[package.dependencies] +attrs = "*" +future = "*" +h11 = "*" +h2 = "*" +jsonschema = "*" +logbook = "*" +pycryptodome = "*" +unpaddedbase64 = "*" + +[package.dependencies.aiohttp] +python = ">=3.6" +version = "*" + +[package.extras] +e2e = ["python-olm (>=3.1.0)", "peewee (>=3.9.5)", "cachetools", "atomicwrites"] + [[package]] category = "main" description = "multidict implementation" name = "multidict" optional = false python-versions = ">=3.5" -version = "4.6.1" +version = "4.7.3" [[package]] category = "main" @@ -212,6 +313,14 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.19" +[[package]] +category = "main" +description = "Cryptographic library for Python" +name = "pycryptodome" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.9.4" + [[package]] category = "main" description = "Python binding to the Networking and Cryptography (NaCl) library" @@ -237,6 +346,17 @@ optional = false python-versions = "*" version = "2.1" +[[package]] +category = "main" +description = "Persistent/Functional/Immutable data structures" +name = "pyrsistent" +optional = false +python-versions = "*" +version = "0.15.7" + +[package.dependencies] +six = "*" + [[package]] category = "main" description = "Extensions to the standard Python datetime module" @@ -291,7 +411,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2019.12.9" +version = "2020.1.8" [[package]] category = "main" @@ -331,7 +451,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.1.6" +version = "5.2.1" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -345,6 +465,10 @@ version = ">=10.0,<11.0" optional = true version = ">=0.2.0,<0.3.0" +[package.dependencies.matrix-nio] +optional = true +version = ">=0.6,<0.7" + [package.dependencies.psycopg2_binary] optional = true version = ">=2.8.4,<3.0.0" @@ -397,6 +521,7 @@ 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 = ["temp_discordpy_without_websockets_requirement (0.1)", "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)"] @@ -448,7 +573,7 @@ description = "Database Abstraction Library" name = "sqlalchemy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.11" +version = "1.3.12" [package.extras] mssql = ["pyodbc"] @@ -516,6 +641,22 @@ version = "2.0.0" [package.dependencies] pytz = "*" +[[package]] +category = "main" +description = "ASCII transliterations of Unicode text" +name = "unidecode" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.1.1" + +[[package]] +category = "main" +description = "Unpadded Base64" +name = "unpaddedbase64" +optional = false +python-versions = "*" +version = "1.1.0" + [[package]] category = "main" description = "HTTP library with thread-safe connection pooling, file post, and more." @@ -535,11 +676,11 @@ description = "The lightning-fast ASGI server." name = "uvicorn" optional = false python-versions = "*" -version = "0.10.8" +version = "0.10.9" [package.dependencies] click = ">=7.0.0,<8.0.0" -h11 = ">=0.8.0,<0.9.0" +h11 = ">=0.9.0,<0.10.0" httptools = "0.0.13" uvloop = ">=0.14.0" websockets = ">=8.0.0,<9.0.0" @@ -579,10 +720,10 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2019.11.28" +version = "2020.1.1" [metadata] -content-hash = "131063cd0294061fef5c403e5c71281f0ca7109576fedfcbbc15540b6a3ac1f9" +content-hash = "bcb120a4e881fcde2001d4cda54ecd19c291ee6243afe7b71b4aed0b227d2f6a" python-versions = "^3.8" [metadata.files] @@ -708,8 +849,16 @@ future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] h11 = [ - {file = "h11-0.8.1-py2.py3-none-any.whl", hash = "sha256:f2b1ca39bfed357d1f19ac732913d5f9faa54a5062eca7d2ec3a916cfb7ae4c7"}, - {file = "h11-0.8.1.tar.gz", hash = "sha256:acca6a44cb52a32ab442b1779adf0875c443c689e9e028f8d831a3769f9c5208"}, + {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, + {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, +] +h2 = [ + {file = "h2-3.1.1-py2.py3-none-any.whl", hash = "sha256:ac377fcf586314ef3177bfd90c12c7826ab0840edeb03f0f24f511858326049e"}, + {file = "h2-3.1.1.tar.gz", hash = "sha256:b8a32bd282594424c0ac55845377eea13fa54fe4a8db012f3a198ed923dc3ab4"}, +] +hpack = [ + {file = "hpack-3.0.0-py2.py3-none-any.whl", hash = "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89"}, + {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"}, ] httptools = [ {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, @@ -718,28 +867,53 @@ humanfriendly = [ {file = "humanfriendly-4.18-py2.py3-none-any.whl", hash = "sha256:23057b10ad6f782e7bc3a20e3cb6768ab919f619bbdc0dd75691121bbde5591d"}, {file = "humanfriendly-4.18.tar.gz", hash = "sha256:33ee8ceb63f1db61cce8b5c800c531e1a61023ac5488ccde2ba574a85be00a85"}, ] +hyperframe = [ + {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, + {file = "hyperframe-5.2.0.tar.gz", hash = "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"}, +] idna = [ {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, ] +jsonschema = [ + {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, + {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, +] +logbook = [ + {file = "Logbook-1.5.3-cp27-cp27m-win32.whl", hash = "sha256:56ee54c11df3377314cedcd6507638f015b4b88c0238c2e01b5eb44fd3a6ad1b"}, + {file = "Logbook-1.5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:2dc85f1510533fddb481e97677bb7bca913560862734c0b3b289bfed04f78c92"}, + {file = "Logbook-1.5.3-cp35-cp35m-win32.whl", hash = "sha256:94e2e11ff3c2304b0d09a36c6208e5ae756eb948b210e5cbd63cd8d27f911542"}, + {file = "Logbook-1.5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:97fee1bd9605f76335b169430ed65e15e457a844b2121bd1d90a08cf7e30aba0"}, + {file = "Logbook-1.5.3-cp36-cp36m-win32.whl", hash = "sha256:7c533eb728b3d220b1b5414ba4635292d149d79f74f6973b4aa744c850ca944a"}, + {file = "Logbook-1.5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:e18f7422214b1cf0240c56f884fd9c9b4ff9d0da2eabca9abccba56df7222f66"}, + {file = "Logbook-1.5.3-cp37-cp37m-win32.whl", hash = "sha256:8f76a2e7b1f72595f753228732f81ce342caf03babc3fed6bbdcf366f2f20f18"}, + {file = "Logbook-1.5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0cf2cdbfb65a03b5987d19109dacad13417809dcf697f66e1a7084fb21744ea9"}, + {file = "Logbook-1.5.3.tar.gz", hash = "sha256:66f454ada0f56eae43066f604a222b09893f98c1adc18df169710761b8f32fe8"}, +] +markovify = [ + {file = "markovify-0.8.0.tar.gz", hash = "sha256:c533a2e1aba8148bb98031b7159e8bf1a276c61db53d2e882ecb74fa5603a4f4"}, +] +matrix-nio = [ + {file = "matrix-nio-0.6.tar.gz", hash = "sha256:25a4ac9d5e1435035f5c5b6e9a6b453ac66ade25cb455ba6bbe9cc3ae1e0ef50"}, +] multidict = [ - {file = "multidict-4.6.1-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:318aadf1cfb6741c555c7dd83d94f746dc95989f4f106b25b8a83dfb547f2756"}, - {file = "multidict-4.6.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9c890978e2b37dd0dc1bd952da9a5d9f245d4807bee33e3517e4119c48d66f8c"}, - {file = "multidict-4.6.1-cp35-cp35m-win32.whl", hash = "sha256:efaf1b18ea6c1f577b1371c0159edbe4749558bfe983e13aa24d0a0c01e1ad7b"}, - {file = "multidict-4.6.1-cp35-cp35m-win_amd64.whl", hash = "sha256:07f9a6bf75ad675d53956b2c6a2d4ef2fa63132f33ecc99e9c24cf93beb0d10b"}, - {file = "multidict-4.6.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:42cdd649741a14b0602bf15985cad0dd4696a380081a3319cd1ead46fd0f0fab"}, - {file = "multidict-4.6.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:205a011e636d885af6dd0029e41e3514a46e05bb2a43251a619a6e8348b96fc0"}, - {file = "multidict-4.6.1-cp36-cp36m-win32.whl", hash = "sha256:cfec9d001a83dc73580143f3c77e898cf7ad78b27bb5e64dbe9652668fcafec7"}, - {file = "multidict-4.6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8d919034420378132d074bf89df148d0193e9780c9fe7c0e495e895b8af4d8a2"}, - {file = "multidict-4.6.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a37433ce8cdb35fc9e6e47e1606fa1bfd6d70440879038dca7d8dd023197eaa9"}, - {file = "multidict-4.6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1b605272c558e4c659dbaf0fb32a53bfede44121bcf77b356e6e906867b958b7"}, - {file = "multidict-4.6.1-cp37-cp37m-win32.whl", hash = "sha256:891b7e142885e17a894d9d22b0349b92bb2da4769b4e675665d0331c08719be5"}, - {file = "multidict-4.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:250632316295f2311e1ed43e6b26a63b0216b866b45c11441886ac1543ca96e1"}, - {file = "multidict-4.6.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:2bc9c2579312c68a3552ee816311c8da76412e6f6a9cf33b15152e385a572d2a"}, - {file = "multidict-4.6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0ffe4d4d28cbe9801952bfb52a8095dd9ffecebd93f84bdf973c76300de783c5"}, - {file = "multidict-4.6.1-cp38-cp38-win32.whl", hash = "sha256:87e26d8b89127c25659e962c61a4c655ec7445d19150daea0759516884ecb8b4"}, - {file = "multidict-4.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:c626029841ada34c030b94a00c573a0c7575fe66489cde148785b6535397d675"}, - {file = "multidict-4.6.1.tar.gz", hash = "sha256:5159c4975931a1a78bf6602bbebaa366747fce0a56cb2111f44789d2c45e379f"}, + {file = "multidict-4.7.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:ed5f3378c102257df9e2dc9ce6468dabf68bee9ec34969cfdc472631aba00316"}, + {file = "multidict-4.7.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:15a61c0df2d32487e06f6084eabb48fd9e8b848315e397781a70caf9670c9d78"}, + {file = "multidict-4.7.3-cp35-cp35m-win32.whl", hash = "sha256:d1f45e5bb126662ba66ee579831ce8837b1fd978115c9657e32eb3c75b92973d"}, + {file = "multidict-4.7.3-cp35-cp35m-win_amd64.whl", hash = "sha256:a02fade7b5476c4f88efe9593ff2f3286698d8c6d715ba4f426954f73f382026"}, + {file = "multidict-4.7.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:78bed18e7f1eb21f3d10ff3acde900b4d630098648fe1d65bb4abfb3e22c4900"}, + {file = "multidict-4.7.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0f04bf4c15d8417401a10a650c349ccc0285943681bfd87d3690587d7714a9b4"}, + {file = "multidict-4.7.3-cp36-cp36m-win32.whl", hash = "sha256:63ba2be08d82ea2aa8b0f7942a74af4908664d26cb4ff60c58eadb1e33e7da00"}, + {file = "multidict-4.7.3-cp36-cp36m-win_amd64.whl", hash = "sha256:3c5e2dcbe6b04cbb4303e47a896757a77b676c5e5db5528be7ff92f97ba7ab95"}, + {file = "multidict-4.7.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:c2bfc0db3166e68515bc4a2b9164f4f75ae9c793e9635f8651f2c9ffc65c8dad"}, + {file = "multidict-4.7.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c66d11870ae066499a3541963e6ce18512ca827c2aaeaa2f4e37501cee39ac5d"}, + {file = "multidict-4.7.3-cp37-cp37m-win32.whl", hash = "sha256:aacbde3a8875352a640efa2d1b96e5244a29b0f8df79cbf1ec6470e86fd84697"}, + {file = "multidict-4.7.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5e5fb8bfebf87f2e210306bf9dd8de2f1af6782b8b78e814060ae9254ab1f297"}, + {file = "multidict-4.7.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:5d2b32b890d9e933d3ced417924261802a857abdee9507b68c75014482145c03"}, + {file = "multidict-4.7.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cc7f2202b753f880c2e4123f9aacfdb94560ba893e692d24af271dac41f8b8d9"}, + {file = "multidict-4.7.3-cp38-cp38-win32.whl", hash = "sha256:bfcad6da0b8839f01a819602aaa5c5a5b4c85ecbfae9b261a31df3d9262fb31e"}, + {file = "multidict-4.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:73740fcdb38f0adcec85e97db7557615b50ec4e5a3e73e35878720bcee963382"}, + {file = "multidict-4.7.3.tar.gz", hash = "sha256:be813fb9e5ce41a5a99a29cdb857144a1bd6670883586f995b940a4878dc5238"}, ] psycopg2-binary = [ {file = "psycopg2-binary-2.8.4.tar.gz", hash = "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed"}, @@ -778,6 +952,40 @@ psycopg2-binary = [ pycparser = [ {file = "pycparser-2.19.tar.gz", hash = "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"}, ] +pycryptodome = [ + {file = "pycryptodome-3.9.4-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:6c2720696b10ae356040e888bde1239b8957fe18885ccf5e7b4e8dec882f0856"}, + {file = "pycryptodome-3.9.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:5c485ed6e9718ebcaa81138fa70ace9c563d202b56a8cee119b4085b023931f5"}, + {file = "pycryptodome-3.9.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:56fdd0e425f1b8fd3a00b6d96351f86226674974814c50534864d0124d48871f"}, + {file = "pycryptodome-3.9.4-cp27-cp27m-win32.whl", hash = "sha256:2de33ed0a95855735d5a0fc0c39603314df9e78ee8bbf0baa9692fb46b3b8bbb"}, + {file = "pycryptodome-3.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:eec0689509389f19875f66ae8dedd59f982240cdab31b9f78a8dc266011df93a"}, + {file = "pycryptodome-3.9.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:68fab8455efcbfe87c5d75015476f9b606227ffe244d57bfd66269451706e899"}, + {file = "pycryptodome-3.9.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4b9533d4166ca07abdd49ce9d516666b1df944997fe135d4b21ac376aa624aff"}, + {file = "pycryptodome-3.9.4-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:d3fe3f33ad52bf0c19ee6344b695ba44ffbfa16f3c29ca61116b48d97bd970fb"}, + {file = "pycryptodome-3.9.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:319e568baf86620b419d53063b18c216abf924875966efdfe06891b987196a45"}, + {file = "pycryptodome-3.9.4-cp34-cp34m-win32.whl", hash = "sha256:042ae873baadd0c33b4d699a5c5b976ade3233a979d972f98ca82314632d868c"}, + {file = "pycryptodome-3.9.4-cp34-cp34m-win_amd64.whl", hash = "sha256:a30f501bbb32e01a49ef9e09ca1260e5ab49bf33a257080ec553e08997acc487"}, + {file = "pycryptodome-3.9.4-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:b55c60c321ac91945c60a40ac9896ac7a3d432bb3e8c14006dfd82ad5871c331"}, + {file = "pycryptodome-3.9.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9d9945ac8375d5d8e60bd2a2e1df5882eaa315522eedf3ca868b1546dfa34eba"}, + {file = "pycryptodome-3.9.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:4372ec7518727172e1605c0843cdc5375d4771e447b8148c787b860260aae151"}, + {file = "pycryptodome-3.9.4-cp35-cp35m-win32.whl", hash = "sha256:0502876279772b1384b660ccc91563d04490d562799d8e2e06b411e2d81128a9"}, + {file = "pycryptodome-3.9.4-cp35-cp35m-win_amd64.whl", hash = "sha256:72166c2ac520a5dbd2d90208b9c279161ec0861662a621892bd52fb6ca13ab91"}, + {file = "pycryptodome-3.9.4-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:b4af098f2a50f8d048ab12cabb59456585c0acf43d90ee79782d2d6d0ed59dba"}, + {file = "pycryptodome-3.9.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:8a799bea3c6617736e914a2e77c409f52893d382f619f088f8a80e2e21f573c1"}, + {file = "pycryptodome-3.9.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7c52308ac5b834331b2f107a490b2c27de024a229b61df4cdc5c131d563dfe98"}, + {file = "pycryptodome-3.9.4-cp36-cp36m-win32.whl", hash = "sha256:63c103a22cbe9752f6ea9f1a0de129995bad91c4d03a66c67cffcf6ee0c9f1e1"}, + {file = "pycryptodome-3.9.4-cp36-cp36m-win_amd64.whl", hash = "sha256:54456cf85130e01674d21fb1ab89ffccacb138a8ade88d72fa2b0ac898d2798b"}, + {file = "pycryptodome-3.9.4-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:aec4d42deb836b8fb3ba32f2ba1ef0d33dd3dc9d430b1479ee7a914490d15b5e"}, + {file = "pycryptodome-3.9.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:896e9b6fd0762aa07b203c993fbbee7a1f1a4674c6886afd7bfa86f3d1be98a8"}, + {file = "pycryptodome-3.9.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:57b1b707363490c495ad0eeb38bd1b0e1697c497af25fad78d3a1ebf0477fd5b"}, + {file = "pycryptodome-3.9.4-cp37-cp37m-win32.whl", hash = "sha256:87d8d85b4792ca5e730fb7a519fbc3ed976c59dcf79c5204589c59afd56b9926"}, + {file = "pycryptodome-3.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:e3a79a30d15d9c7c284a7734036ee8abdb5ca3a6f5774d293cdc9e1358c1dc10"}, + {file = "pycryptodome-3.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:48821950ffb9c836858d8fa09d7840b6df52eadd387a3c5acece55cb387743f9"}, + {file = "pycryptodome-3.9.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cbfd97f9e060f0d30245cd29fa267a9a84de9da97559366fca0a3f7655acc63f"}, + {file = "pycryptodome-3.9.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9ef966c727de942de3e41aa8462c4b7b4bca70f19af5a3f99e31376589c11aac"}, + {file = "pycryptodome-3.9.4-cp38-cp38-win32.whl", hash = "sha256:a8ca2450394d3699c9f15ef25e8de9a24b401933716a1e39d37fa01f5fe3c58b"}, + {file = "pycryptodome-3.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:c53348358408d94869059e16fba5ff3bef8c52c25b18421472aba272b9bb450f"}, + {file = "pycryptodome-3.9.4.tar.gz", hash = "sha256:a168e73879619b467072509a223282a02c8047d932a48b74fbd498f27224aa04"}, +] pynacl = [ {file = "PyNaCl-1.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621"}, {file = "PyNaCl-1.3.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39"}, @@ -806,6 +1014,9 @@ pyreadline = [ {file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"}, {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, ] +pyrsistent = [ + {file = "pyrsistent-0.15.7.tar.gz", hash = "sha256:cdc7b5e3ed77bed61270a47d35434a30617b9becdf2478af76ad2c6ade307280"}, +] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, @@ -822,17 +1033,27 @@ pytz = [ {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, ] regex = [ - {file = "regex-2019.12.9-cp27-none-win32.whl", hash = "sha256:40b7d1291a56897927e08bb973f8c186c2feb14c7f708bfe7aaee09483e85a20"}, - {file = "regex-2019.12.9-cp27-none-win_amd64.whl", hash = "sha256:c203c9ee755e9656d0af8fab82754d5a664ebaf707b3f883c7eff6a3dd5151cf"}, - {file = "regex-2019.12.9-cp35-none-win32.whl", hash = "sha256:719978a9145d59fc78509ea1d1bb74243f93583ef2a34dcc5623cf8118ae9726"}, - {file = "regex-2019.12.9-cp35-none-win_amd64.whl", hash = "sha256:75cf3796f89f75f83207a5c6a6e14eaf57e0369ef0ffff8e22bf36bbcfa0f1de"}, - {file = "regex-2019.12.9-cp36-none-win32.whl", hash = "sha256:3dbd8333fd2ebd50977ac8747385a73aa1f546eb6b16fcd83d274470fe11f243"}, - {file = "regex-2019.12.9-cp36-none-win_amd64.whl", hash = "sha256:ad9e3c7260809c0d1ded100269f78ea0217c0704f1eaaf40a382008461848b45"}, - {file = "regex-2019.12.9-cp37-none-win32.whl", hash = "sha256:91235c98283d2bddf1a588f0fbc2da8afa37959294bbd18b76297bdf316ba4d6"}, - {file = "regex-2019.12.9-cp37-none-win_amd64.whl", hash = "sha256:aaffd68c4c1ed891366d5c390081f4bf6337595e76a157baf453603d8e53fbcb"}, - {file = "regex-2019.12.9-cp38-none-win32.whl", hash = "sha256:e865bc508e316a3a09d36c8621596e6599a203bc54f1cd41020a127ccdac468a"}, - {file = "regex-2019.12.9-cp38-none-win_amd64.whl", hash = "sha256:77396cf80be8b2a35db863cca4c1a902d88ceeb183adab328b81184e71a5eafe"}, - {file = "regex-2019.12.9.tar.gz", hash = "sha256:77a3799152951d6d14ae5720ca162c97c64f85d4755da585418eac216b736cad"}, + {file = "regex-2020.1.8-cp27-cp27m-win32.whl", hash = "sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161"}, + {file = "regex-2020.1.8-cp27-cp27m-win_amd64.whl", hash = "sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242"}, + {file = "regex-2020.1.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4eae742636aec40cf7ab98171ab9400393360b97e8f9da67b1867a9ee0889b26"}, + {file = "regex-2020.1.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bd25bb7980917e4e70ccccd7e3b5740614f1c408a642c245019cff9d7d1b6149"}, + {file = "regex-2020.1.8-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3e77409b678b21a056415da3a56abfd7c3ad03da71f3051bbcdb68cf44d3c34d"}, + {file = "regex-2020.1.8-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:07b39bf943d3d2fe63d46281d8504f8df0ff3fe4c57e13d1656737950e53e525"}, + {file = "regex-2020.1.8-cp36-cp36m-win32.whl", hash = "sha256:23e2c2c0ff50f44877f64780b815b8fd2e003cda9ce817a7fd00dea5600c84a0"}, + {file = "regex-2020.1.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27429b8d74ba683484a06b260b7bb00f312e7c757792628ea251afdbf1434003"}, + {file = "regex-2020.1.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0e182d2f097ea8549a249040922fa2b92ae28be4be4895933e369a525ba36576"}, + {file = "regex-2020.1.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e3cd21cc2840ca67de0bbe4071f79f031c81418deb544ceda93ad75ca1ee9f7b"}, + {file = "regex-2020.1.8-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ecc6de77df3ef68fee966bb8cb4e067e84d4d1f397d0ef6fce46913663540d77"}, + {file = "regex-2020.1.8-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:26ff99c980f53b3191d8931b199b29d6787c059f2e029b2b0c694343b1708c35"}, + {file = "regex-2020.1.8-cp37-cp37m-win32.whl", hash = "sha256:7bcd322935377abcc79bfe5b63c44abd0b29387f267791d566bbb566edfdd146"}, + {file = "regex-2020.1.8-cp37-cp37m-win_amd64.whl", hash = "sha256:10671601ee06cf4dc1bc0b4805309040bb34c9af423c12c379c83d7895622bb5"}, + {file = "regex-2020.1.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:98b8ed7bb2155e2cbb8b76f627b2fd12cf4b22ab6e14873e8641f266e0fb6d8f"}, + {file = "regex-2020.1.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6a6ba91b94427cd49cd27764679024b14a96874e0dc638ae6bdd4b1a3ce97be1"}, + {file = "regex-2020.1.8-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:6a6ae17bf8f2d82d1e8858a47757ce389b880083c4ff2498dba17c56e6c103b9"}, + {file = "regex-2020.1.8-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:0932941cdfb3afcbc26cc3bcf7c3f3d73d5a9b9c56955d432dbf8bbc147d4c5b"}, + {file = "regex-2020.1.8-cp38-cp38-win32.whl", hash = "sha256:d58e4606da2a41659c84baeb3cfa2e4c87a74cec89a1e7c56bee4b956f9d7461"}, + {file = "regex-2020.1.8-cp38-cp38-win_amd64.whl", hash = "sha256:e7c7661f7276507bce416eaae22040fd91ca471b5b33c13f8ff21137ed6f248c"}, + {file = "regex-2020.1.8.tar.gz", hash = "sha256:d0f424328f9822b0323b3b6f2e4b9c90960b24743d220763c7f07071e0778351"}, ] requests = [ {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, @@ -843,8 +1064,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.1.6-py3-none-any.whl", hash = "sha256:4d64607fafbd94b82e8de47f9e0c83ae60d0558c682850d05a4e90ce0f9e9081"}, - {file = "royalnet-5.1.6.tar.gz", hash = "sha256:bfdbf55895162dd0ef7cd18f4260e1574f0e5569cef9fc3d069338c71f52e18d"}, + {file = "royalnet-5.2.1-py3-none-any.whl", hash = "sha256:50f9dee08a39f3bf31ed5f0a1ca8666bd1627d7ca81ba8cee79f318fe777133f"}, + {file = "royalnet-5.2.1.tar.gz", hash = "sha256:e11b155f5952eb4df327892b07529c3f16a2426c76274d880d269e6b310389bd"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -858,7 +1079,7 @@ six = [ {file = "six-1.13.0.tar.gz", hash = "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.11.tar.gz", hash = "sha256:afa5541e9dea8ad0014251bc9d56171ca3d8b130c9627c6cb3681cff30be3f8a"}, + {file = "SQLAlchemy-1.3.12.tar.gz", hash = "sha256:bfb8f464a5000b567ac1d350b9090cf081180ec1ab4aa87e7bca12dab25320ec"}, ] starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, @@ -885,12 +1106,21 @@ tzlocal = [ {file = "tzlocal-2.0.0-py2.py3-none-any.whl", hash = "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048"}, {file = "tzlocal-2.0.0.tar.gz", hash = "sha256:949b9dd5ba4be17190a80c0268167d7e6c92c62b30026cf9764caf3e308e5590"}, ] +unidecode = [ + {file = "Unidecode-1.1.1-py2.py3-none-any.whl", hash = "sha256:1d7a042116536098d05d599ef2b8616759f02985c85b4fef50c78a5aaf10822a"}, + {file = "Unidecode-1.1.1.tar.gz", hash = "sha256:2b6aab710c2a1647e928e36d69c21e76b453cd455f4e2621000e54b2a9b8cce8"}, +] +unpaddedbase64 = [ + {file = "unpaddedbase64-1.1.0-py2-none-any.whl", hash = "sha256:8917367e4e915b7dce1a72a99db8798c9f3d0d9a74cdd9aafac6d7c65ca495c5"}, + {file = "unpaddedbase64-1.1.0-py2.py3-none-any.whl", hash = "sha256:81cb4eaaa28cc6a282dd3f2c3855eaa1fbaafa736b5ee64df69889e20540a339"}, +] urllib3 = [ {file = "urllib3-1.25.7-py2.py3-none-any.whl", hash = "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293"}, {file = "urllib3-1.25.7.tar.gz", hash = "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"}, ] uvicorn = [ - {file = "uvicorn-0.10.8.tar.gz", hash = "sha256:f4c34642618449f55e2bab8c6b22ff7615b520d2e7e23275be2ca894254327a3"}, + {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, + {file = "uvicorn-0.10.9.tar.gz", hash = "sha256:c010df69d16e27f1a18481316325b4fd23f562c1fac050915fc03a397d0f6b64"}, ] uvloop = [ {file = "uvloop-0.14.0-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd"}, @@ -947,6 +1177,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2019.11.28-py2.py3-none-any.whl", hash = "sha256:43d6b991a34934fec2be20b93d4774ccc8642db1e5f0b8f1569f53b8d769af48"}, - {file = "youtube_dl-2019.11.28.tar.gz", hash = "sha256:de2254dc38472b0e0e3ac4d1e95a9e636ec790af83e7b055e1e09f03eb61bb5c"}, + {file = "youtube_dl-2020.1.1-py2.py3-none-any.whl", hash = "sha256:3538410130b3adb4690955b2454bfe212d94babefd822aadae4a2b263c421be4"}, + {file = "youtube_dl-2020.1.1.tar.gz", hash = "sha256:0f8e62b5a3a5bb8bdf3d7ae3ec96c233f5110fa0ee1c9df51299b6636ebd4ff4"}, ] diff --git a/pyproject.toml b/pyproject.toml index cfa26d90..f50d0225 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.3" + version = "5.2.4" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -22,6 +22,7 @@ riotwatcher = "^2.7.1" royalspells = "^3.2" + markovify = "^0.8.0" [tool.poetry.dependencies.royalnet] version = "^5.1.6" @@ -34,7 +35,8 @@ "constellation", "sentry", "herald", - "coloredlogs" + "coloredlogs", + "matrix" ] # Development dependencies diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 7bee64cc..11cc504f 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -30,6 +30,7 @@ from .peertube import PeertubeCommand from .funkwhale import FunkwhaleCommand from .eval import EvalCommand from .exec import ExecCommand +from .markov import MarkovCommand # Enter the commands of your Pack here! available_commands = [ @@ -64,6 +65,7 @@ available_commands = [ EvalCommand, ExecCommand, FunkwhaleCommand, + MarkovCommand ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 9618b45b..90912da9 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -154,6 +154,7 @@ class EatCommand(Command): "nulla": "⬜️ Non hai mangiato {food}.\n[i]Hai ancora più fame.[/i]", "torta": "⬜️ Non hai mangiato niente.\n[i]La {food} è una menzogna![/i]", "cake": "⬜️ Non hai mangiato niente.\n[i]The {food} is a lie![/i]", + "markov": "🗨 Stai cercando di mangiare... un matematico russo di nome {food}?\n[i]Lo trovi un po' indigesto.[/i]", } async def run(self, args: CommandArgs, data: CommandData) -> None: diff --git a/royalpack/commands/markov.py b/royalpack/commands/markov.py new file mode 100644 index 00000000..f0db40d3 --- /dev/null +++ b/royalpack/commands/markov.py @@ -0,0 +1,35 @@ +from typing import * +from royalnet.commands import * +import markovify +import os +import re + + +class MarkovCommand(Command): + name: str = "markov" + + description: str = "Genera una frase da una catena di Markov." + + syntax: str = "[modello]" + + _texts: Dict[str, markovify.NewlineText] = {} + + def __init__(self, interface: CommandInterface): + super().__init__(interface) + files: List[str] = tuple(os.walk(self.config["Markov"]["models_directory"]))[0][2] + for file in files: + match = re.match("(\S+)\.json", file) + model_name = match.group(1) + with open(os.path.join(self.config["Markov"]["models_directory"], file)) as f: + self._texts[model_name] = markovify.NewlineText.from_json(f.read()) + + async def run(self, args: CommandArgs, data: CommandData) -> None: + model_name = args.optional(0, self.config["Markov"]["default_model"]) + try: + sentence = self._texts[model_name].make_sentence() + except KeyError: + raise InvalidInputError("Il modello richiesto non esiste.") + if sentence is None or sentence == "": + await data.reply(f"💭 Il bot ([c]{model_name}[/c])... non dice niente. Riprova!") + else: + await data.reply(f'💬 Il bot ([c]{model_name}[/c]) dice:\n{sentence}') diff --git a/royalpack/version.py b/royalpack/version.py index 08723330..f27de03a 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.3" +semantic = "5.2.4" From caa2fff26c959e7ed290e165923bdad7e3443647 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Jan 2020 03:34:27 +0100 Subject: [PATCH 009/227] fix bug and slip --- royalpack/commands/markov.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/royalpack/commands/markov.py b/royalpack/commands/markov.py index f0db40d3..d4d5babf 100644 --- a/royalpack/commands/markov.py +++ b/royalpack/commands/markov.py @@ -19,6 +19,8 @@ class MarkovCommand(Command): files: List[str] = tuple(os.walk(self.config["Markov"]["models_directory"]))[0][2] for file in files: match = re.match("(\S+)\.json", file) + if match is None: + continue model_name = match.group(1) with open(os.path.join(self.config["Markov"]["models_directory"], file)) as f: self._texts[model_name] = markovify.NewlineText.from_json(f.read()) From a80e94bb839ed8c5cd00f1befddc71043163943d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Jan 2020 13:41:31 +0100 Subject: [PATCH 010/227] fix a few bugs in markov --- pyproject.toml | 2 +- royalpack/commands/markov.py | 19 +++++++++++-------- royalpack/version.py | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f50d0225..b4a2fbc6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.4" + version = "5.2.5" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/markov.py b/royalpack/commands/markov.py index d4d5babf..47ca5ef2 100644 --- a/royalpack/commands/markov.py +++ b/royalpack/commands/markov.py @@ -16,16 +16,19 @@ class MarkovCommand(Command): def __init__(self, interface: CommandInterface): super().__init__(interface) - files: List[str] = tuple(os.walk(self.config["Markov"]["models_directory"]))[0][2] - for file in files: - match = re.match("(\S+)\.json", file) - if match is None: - continue - model_name = match.group(1) - with open(os.path.join(self.config["Markov"]["models_directory"], file)) as f: - self._texts[model_name] = markovify.NewlineText.from_json(f.read()) + if interface.name == "telegram": + files: List[str] = tuple(os.walk(self.config["Markov"]["models_directory"]))[0][2] + for file in files: + match = re.match(r"(\S+)\.json$", file) + if match is None: + continue + model_name = match.group(1) + with open(os.path.join(self.config["Markov"]["models_directory"], file)) as f: + self._texts[model_name] = markovify.NewlineText.from_json(f.read()) async def run(self, args: CommandArgs, data: CommandData) -> None: + if self.interface.name != "telegram": + raise UnsupportedError("[c]markov[/c] funziona solo su Telegram.") model_name = args.optional(0, self.config["Markov"]["default_model"]) try: sentence = self._texts[model_name].make_sentence() diff --git a/royalpack/version.py b/royalpack/version.py index f27de03a..843d1593 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.4" +semantic = "5.2.5" From 6514d56519086f2a7a4e0f59573c39223e173d97 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 10 Jan 2020 19:03:14 +0100 Subject: [PATCH 011/227] Add api_discord_play endpoint --- royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_discord_play.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 royalpack/stars/api_discord_play.py diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 209efcfa..a5f71714 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -6,6 +6,7 @@ from .api_diario_get import ApiDiarioGetStar from .api_discord_cv import ApiDiscordCvStar from .api_wiki_get import ApiWikiGetStar from .api_wiki_list import ApiUserListStar +from .api_discord_play import ApiDiscordPlayStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -16,6 +17,7 @@ available_page_stars = [ ApiDiscordCvStar, ApiWikiGetStar, ApiUserListStar, + ApiDiscordPlayStar, ] # Enter the ExceptionStars of your Pack here! diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py new file mode 100644 index 00000000..fc29674b --- /dev/null +++ b/royalpack/stars/api_discord_play.py @@ -0,0 +1,18 @@ +from typing import * +from starlette.requests import Request +from starlette.responses import * +from royalnet.constellation import * +from royalnet.utils import * + + +class ApiDiscordPlayStar(PageStar): + path = "/api/discord/play" + + async def page(self, request: Request) -> JSONResponse: + url = request.query_params.get("url", "") + try: + guild_id: Optional[int] = int(request.path_params.get("guild_id", None)) + except (ValueError, TypeError): + guild_id = None + response = await self.interface.call_herald_event("discord", "discord_play", url=url, guild_id=guild_id) + return JSONResponse(response) From f07f4486eef40de88cf7de1d221e4eb60d94bfc4 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 10 Jan 2020 19:04:52 +0100 Subject: [PATCH 012/227] Disable markov command --- royalpack/commands/markov.py | 49 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/royalpack/commands/markov.py b/royalpack/commands/markov.py index 47ca5ef2..f162f9bb 100644 --- a/royalpack/commands/markov.py +++ b/royalpack/commands/markov.py @@ -1,8 +1,8 @@ from typing import * from royalnet.commands import * -import markovify -import os -import re +# import markovify +# import os +# import re class MarkovCommand(Command): @@ -12,29 +12,30 @@ class MarkovCommand(Command): syntax: str = "[modello]" - _texts: Dict[str, markovify.NewlineText] = {} + # _texts: Dict[str, markovify.NewlineText] = {} def __init__(self, interface: CommandInterface): super().__init__(interface) - if interface.name == "telegram": - files: List[str] = tuple(os.walk(self.config["Markov"]["models_directory"]))[0][2] - for file in files: - match = re.match(r"(\S+)\.json$", file) - if match is None: - continue - model_name = match.group(1) - with open(os.path.join(self.config["Markov"]["models_directory"], file)) as f: - self._texts[model_name] = markovify.NewlineText.from_json(f.read()) + # if interface.name == "telegram": + # files: List[str] = tuple(os.walk(self.config["Markov"]["models_directory"]))[0][2] + # for file in files: + # match = re.match(r"(\S+)\.json$", file) + # if match is None: + # continue + # model_name = match.group(1) + # with open(os.path.join(self.config["Markov"]["models_directory"], file)) as f: + # self._texts[model_name] = markovify.NewlineText.from_json(f.read()) async def run(self, args: CommandArgs, data: CommandData) -> None: - if self.interface.name != "telegram": - raise UnsupportedError("[c]markov[/c] funziona solo su Telegram.") - model_name = args.optional(0, self.config["Markov"]["default_model"]) - try: - sentence = self._texts[model_name].make_sentence() - except KeyError: - raise InvalidInputError("Il modello richiesto non esiste.") - if sentence is None or sentence == "": - await data.reply(f"💭 Il bot ([c]{model_name}[/c])... non dice niente. Riprova!") - else: - await data.reply(f'💬 Il bot ([c]{model_name}[/c]) dice:\n{sentence}') + raise CommandError(f"{self} è disattivato. Riprova tra un po' di giorni!") + # if self.interface.name != "telegram": + # raise UnsupportedError("[c]markov[/c] funziona solo su Telegram.") + # model_name = args.optional(0, self.config["Markov"]["default_model"]) + # try: + # sentence = self._texts[model_name].make_sentence() + # except KeyError: + # raise InvalidInputError("Il modello richiesto non esiste.") + # if sentence is None or sentence == "": + # await data.reply(f"💭 Il bot ([c]{model_name}[/c])... non dice niente. Riprova!") + # else: + # await data.reply(f'💬 Il bot ([c]{model_name}[/c]) dice:\n{sentence}') From 0aff0e009012f2845aafc06714ce8b7b6d16b39a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 10 Jan 2020 19:06:15 +0100 Subject: [PATCH 013/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b4a2fbc6..5b658c8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.5" + version = "5.2.6" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 843d1593..2d87e352 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.5" +semantic = "5.2.6" From fe5b8a771276199c25a1835cbeec35517cfe9b4a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Jan 2020 03:27:21 +0100 Subject: [PATCH 014/227] Allow CORS for a fw instance --- royalpack/stars/api_discord_play.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index fc29674b..680ed5e3 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -15,4 +15,6 @@ class ApiDiscordPlayStar(PageStar): except (ValueError, TypeError): guild_id = None response = await self.interface.call_herald_event("discord", "discord_play", url=url, guild_id=guild_id) - return JSONResponse(response) + return JSONResponse(response, headers={ + "Access-Control-Allow-Origin": self.interface.config['Funkwhale']['instance_url'], + }) From a240eb9f20e6839f8e1a42123708364080f66ee6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Jan 2020 15:51:31 +0100 Subject: [PATCH 015/227] Fix bug? --- pyproject.toml | 2 +- royalpack/stars/api_discord_play.py | 7 ++++++- royalpack/version.py | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5b658c8c..98256425 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.6" + version = "5.2.8" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index 680ed5e3..194a89e3 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -3,6 +3,10 @@ from starlette.requests import Request from starlette.responses import * from royalnet.constellation import * from royalnet.utils import * +import logging + + +log = logging.getLogger(__name__) class ApiDiscordPlayStar(PageStar): @@ -11,9 +15,10 @@ class ApiDiscordPlayStar(PageStar): async def page(self, request: Request) -> JSONResponse: url = request.query_params.get("url", "") try: - guild_id: Optional[int] = int(request.path_params.get("guild_id", None)) + guild_id: Optional[int] = int(request.query_params.get("guild_id", None)) except (ValueError, TypeError): guild_id = None + log.info(f"Received request to play {url} on guild_id {guild_id} via web") response = await self.interface.call_herald_event("discord", "discord_play", url=url, guild_id=guild_id) return JSONResponse(response, headers={ "Access-Control-Allow-Origin": self.interface.config['Funkwhale']['instance_url'], diff --git a/royalpack/version.py b/royalpack/version.py index 2d87e352..29bba64a 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.6" +semantic = "5.2.8" From ef30a5b3699d281a5425512bb785d093eb2df235 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 12 Jan 2020 14:21:32 +0100 Subject: [PATCH 016/227] =?UTF-8?q?Fissato=20il=20bug=20del=20bot=20che=20?= =?UTF-8?q?non=20mette=20pi=C3=B9=20le=20canzoni?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- poetry.lock | 50 ++++++++++++++++---------------- pyproject.toml | 2 +- royalpack/events/discord_play.py | 35 +++++++++++++--------- 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/poetry.lock b/poetry.lock index fd6e11ea..6b7aeb0e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -295,7 +295,7 @@ description = "multidict implementation" name = "multidict" optional = false python-versions = ">=3.5" -version = "4.7.3" +version = "4.7.4" [[package]] category = "main" @@ -385,7 +385,7 @@ description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" optional = false python-versions = "*" -version = "12.2.0" +version = "12.3.0" [package.dependencies] certifi = "*" @@ -451,7 +451,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.2.1" +version = "5.2.4" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -723,7 +723,7 @@ python-versions = "*" version = "2020.1.1" [metadata] -content-hash = "bcb120a4e881fcde2001d4cda54ecd19c291ee6243afe7b71b4aed0b227d2f6a" +content-hash = "8713e8d5f419fe8df4c610273aed1529ca44d9d3e4af542b89807b76743f146b" python-versions = "^3.8" [metadata.files] @@ -897,23 +897,23 @@ matrix-nio = [ {file = "matrix-nio-0.6.tar.gz", hash = "sha256:25a4ac9d5e1435035f5c5b6e9a6b453ac66ade25cb455ba6bbe9cc3ae1e0ef50"}, ] multidict = [ - {file = "multidict-4.7.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:ed5f3378c102257df9e2dc9ce6468dabf68bee9ec34969cfdc472631aba00316"}, - {file = "multidict-4.7.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:15a61c0df2d32487e06f6084eabb48fd9e8b848315e397781a70caf9670c9d78"}, - {file = "multidict-4.7.3-cp35-cp35m-win32.whl", hash = "sha256:d1f45e5bb126662ba66ee579831ce8837b1fd978115c9657e32eb3c75b92973d"}, - {file = "multidict-4.7.3-cp35-cp35m-win_amd64.whl", hash = "sha256:a02fade7b5476c4f88efe9593ff2f3286698d8c6d715ba4f426954f73f382026"}, - {file = "multidict-4.7.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:78bed18e7f1eb21f3d10ff3acde900b4d630098648fe1d65bb4abfb3e22c4900"}, - {file = "multidict-4.7.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0f04bf4c15d8417401a10a650c349ccc0285943681bfd87d3690587d7714a9b4"}, - {file = "multidict-4.7.3-cp36-cp36m-win32.whl", hash = "sha256:63ba2be08d82ea2aa8b0f7942a74af4908664d26cb4ff60c58eadb1e33e7da00"}, - {file = "multidict-4.7.3-cp36-cp36m-win_amd64.whl", hash = "sha256:3c5e2dcbe6b04cbb4303e47a896757a77b676c5e5db5528be7ff92f97ba7ab95"}, - {file = "multidict-4.7.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:c2bfc0db3166e68515bc4a2b9164f4f75ae9c793e9635f8651f2c9ffc65c8dad"}, - {file = "multidict-4.7.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c66d11870ae066499a3541963e6ce18512ca827c2aaeaa2f4e37501cee39ac5d"}, - {file = "multidict-4.7.3-cp37-cp37m-win32.whl", hash = "sha256:aacbde3a8875352a640efa2d1b96e5244a29b0f8df79cbf1ec6470e86fd84697"}, - {file = "multidict-4.7.3-cp37-cp37m-win_amd64.whl", hash = "sha256:5e5fb8bfebf87f2e210306bf9dd8de2f1af6782b8b78e814060ae9254ab1f297"}, - {file = "multidict-4.7.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:5d2b32b890d9e933d3ced417924261802a857abdee9507b68c75014482145c03"}, - {file = "multidict-4.7.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cc7f2202b753f880c2e4123f9aacfdb94560ba893e692d24af271dac41f8b8d9"}, - {file = "multidict-4.7.3-cp38-cp38-win32.whl", hash = "sha256:bfcad6da0b8839f01a819602aaa5c5a5b4c85ecbfae9b261a31df3d9262fb31e"}, - {file = "multidict-4.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:73740fcdb38f0adcec85e97db7557615b50ec4e5a3e73e35878720bcee963382"}, - {file = "multidict-4.7.3.tar.gz", hash = "sha256:be813fb9e5ce41a5a99a29cdb857144a1bd6670883586f995b940a4878dc5238"}, + {file = "multidict-4.7.4-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:93166e0f5379cf6cd29746989f8a594fa7204dcae2e9335ddba39c870a287e1c"}, + {file = "multidict-4.7.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a8ed33e8f9b67e3b592c56567135bb42e7e0e97417a4b6a771e60898dfd5182b"}, + {file = "multidict-4.7.4-cp35-cp35m-win32.whl", hash = "sha256:a38baa3046cce174a07a59952c9f876ae8875ef3559709639c17fdf21f7b30dd"}, + {file = "multidict-4.7.4-cp35-cp35m-win_amd64.whl", hash = "sha256:9a7b115ee0b9b92d10ebc246811d8f55d0c57e82dbb6a26b23c9a9a6ad40ce0c"}, + {file = "multidict-4.7.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:dcfed56aa085b89d644af17442cdc2debaa73388feba4b8026446d168ca8dad7"}, + {file = "multidict-4.7.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f29b885e4903bd57a7789f09fe9d60b6475a6c1a4c0eca874d8558f00f9d4b51"}, + {file = "multidict-4.7.4-cp36-cp36m-win32.whl", hash = "sha256:13f3ebdb5693944f52faa7b2065b751cb7e578b8dd0a5bb8e4ab05ad0188b85e"}, + {file = "multidict-4.7.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4fba5204d32d5c52439f88437d33ad14b5f228e25072a192453f658bddfe45a7"}, + {file = "multidict-4.7.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a6d219f49821f4b2c85c6d426346a5d84dab6daa6f85ca3da6c00ed05b54022d"}, + {file = "multidict-4.7.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:63810343ea07f5cd86ba66ab66706243a6f5af075eea50c01e39b4ad6bc3c57a"}, + {file = "multidict-4.7.4-cp37-cp37m-win32.whl", hash = "sha256:26502cefa86d79b86752e96639352c7247846515c864d7c2eb85d036752b643c"}, + {file = "multidict-4.7.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5eee66f882ab35674944dfa0d28b57fa51e160b4dce0ce19e47f495fdae70703"}, + {file = "multidict-4.7.4-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:527124ef435f39a37b279653ad0238ff606b58328ca7989a6df372fd75d7fe26"}, + {file = "multidict-4.7.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:83c6ddf0add57c6b8a7de0bc7e2d656be3eefeff7c922af9a9aae7e49f225625"}, + {file = "multidict-4.7.4-cp38-cp38-win32.whl", hash = "sha256:6bd10adf9f0d6a98ccc792ab6f83d18674775986ba9bacd376b643fe35633357"}, + {file = "multidict-4.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb"}, + {file = "multidict-4.7.4.tar.gz", hash = "sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4"}, ] psycopg2-binary = [ {file = "psycopg2-binary-2.8.4.tar.gz", hash = "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed"}, @@ -1025,8 +1025,8 @@ python-multipart = [ {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, ] python-telegram-bot = [ - {file = "python-telegram-bot-12.2.0.tar.gz", hash = "sha256:346d42771c2b23384c59f5f41e05bd7e801a0ce118d8dcb95209bb73d5f694c5"}, - {file = "python_telegram_bot-12.2.0-py2.py3-none-any.whl", hash = "sha256:3beee89cba3bc3217566c96199f04776dd25f541ac8992da27fd247b2d208a14"}, + {file = "python-telegram-bot-12.3.0.tar.gz", hash = "sha256:41608512a3025a04ff7472efcaae344ad7533a77ae207685bb10fc2fc8282f7b"}, + {file = "python_telegram_bot-12.3.0-py2.py3-none-any.whl", hash = "sha256:5e2156f829402e41bb5ea7196e450bf7f121c5689c5100ae180507d72f3777f5"}, ] pytz = [ {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, @@ -1064,8 +1064,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.2.1-py3-none-any.whl", hash = "sha256:50f9dee08a39f3bf31ed5f0a1ca8666bd1627d7ca81ba8cee79f318fe777133f"}, - {file = "royalnet-5.2.1.tar.gz", hash = "sha256:e11b155f5952eb4df327892b07529c3f16a2426c76274d880d269e6b310389bd"}, + {file = "royalnet-5.2.4-py3-none-any.whl", hash = "sha256:074d741ab78b96c98803a0816fd8e2fc61ecae3017f7c41ea8af40fc3675d07b"}, + {file = "royalnet-5.2.4.tar.gz", hash = "sha256:a38f02fa6560a0c05896957aeb504894292eae0a2e3f607d696b242026fed863"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 98256425..a23cdfc0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ markovify = "^0.8.0" [tool.poetry.dependencies.royalnet] - version = "^5.1.6" + version = "^5.2.4" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index 883eb863..2ca09f0c 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -18,21 +18,28 @@ class DiscordPlayEvent(Event): **kwargs) -> dict: if not isinstance(self.serf, DiscordSerf): raise UnsupportedError() - client: discord.Client = self.serf.client - if len(self.serf.voice_players) == 1: - voice_player: VoicePlayer = self.serf.voice_players[0] + + # TODO: fix this in Royalnet sometime + candidate_players: List[VoicePlayer] = [] + for player in self.serf.voice_players: + player: VoicePlayer + if not player.voice_client.is_connected(): + continue + if guild_id is not None: + guild = self.serf.client.get_guild(guild_id) + if guild != player.voice_client.guild: + continue + candidate_players.append(player) + + if len(candidate_players) == 0: + raise UserError("Il bot non è in nessun canale vocale.\n" + "Evocalo prima con [c]summon[/c]!") + elif len(candidate_players) == 1: + voice_player = candidate_players[0] else: - if guild_id is None: - # TODO: trovare un modo per riprodurre canzoni su più server da Telegram - raise InvalidInputError("Non so in che Server riprodurre questo file...\n" - "Invia il comando su Discord, per favore!") - guild: discord.Guild = client.get_guild(guild_id) - if guild is None: - raise InvalidInputError("Impossibile trovare il Server specificato.") - voice_player: VoicePlayer = self.serf.find_voice_player(guild) - if voice_player is None: - raise UserError("Il bot non è in nessun canale vocale.\n" - "Evocalo prima con [c]summon[/c]!") + raise InvalidInputError("Non so in che Server riprodurre questo file...\n" + "Invia il comando su Discord, per favore!") + ytds = await YtdlDiscord.from_url(url) added: List[YtdlDiscord] = [] too_long: List[YtdlDiscord] = [] From 92290f791ea2258c97ed7b5532793c9d6c1e7a45 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 12 Jan 2020 14:24:53 +0100 Subject: [PATCH 017/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a23cdfc0..c71c69a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.8" + version = "5.2.9" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 29bba64a..3f54fdab 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.8" +semantic = "5.2.9" From ce14ed5652780ee9b30b168009fa81249b7306fd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 13 Jan 2020 14:51:06 +0100 Subject: [PATCH 018/227] Change play messages --- royalpack/commands/play.py | 40 ++++++++++++----------------- royalpack/events/discord_play.py | 37 +++++++++++++++++++++++--- royalpack/stars/api_discord_play.py | 9 ++++--- 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/royalpack/commands/play.py b/royalpack/commands/play.py index 90ca08e5..b12058d8 100644 --- a/royalpack/commands/play.py +++ b/royalpack/commands/play.py @@ -4,6 +4,7 @@ import discord from typing import * from royalnet.commands import * from royalnet.utils import * +from royalnet.backpack.tables import User, Discord class PlayCommand(Command): @@ -16,7 +17,7 @@ class PlayCommand(Command): syntax = "{url}" async def get_url(self, args: CommandArgs): - return args.joined() + return args.joined(require_at_least=1) async def run(self, args: CommandArgs, data: CommandData) -> None: # if not (url.startswith("http://") or url.startswith("https://")): @@ -33,30 +34,21 @@ class PlayCommand(Command): guild_id: Optional[int] = guild.id else: guild_id = None - response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_play", - url=await self.get_url(args), - guild_id=guild_id) - too_long: List[Dict[str, Any]] = response["too_long"] - if len(too_long) > 0: - await data.reply(f"⚠ {len(too_long)} file non {'è' if len(too_long) == 1 else 'sono'}" - f" stat{'o' if len(too_long) == 1 else 'i'} scaricat{'o' if len(too_long) == 1 else 'i'}" - f" perchè durava{'' if len(too_long) == 1 else 'no'}" - f" più di [c]{self.config['Play']['max_song_duration']}[/c] secondi.") + user: User = await data.get_author() + user_str = None - added: List[Dict[str, Any]] = response["added"] - if len(added) > 0: - reply = f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla coda:\n" - if self.interface.name == "discord": - await data.reply(reply) - for item in added: - embed = pickle.loads(base64.b64decode(bytes(item["stringified_base64_pickled_discord_embed"], - encoding="ascii"))) - # noinspection PyUnboundLocalVariable - await message.channel.send(embed=embed) + if user is not None: + try: + user_discord: Discord = user.discord[0] + except (AttributeError, IndexError): + user_str = str(user) else: - reply += numberemojiformat([a["title"] for a in added]) - await data.reply(reply) + user_str = str(f"<@{user_discord.discord_id}>") - if len(added) + len(too_long) == 0: - raise ExternalError("Nessun video trovato.") + self.loop.create_task(self.interface.call_herald_event("discord", "discord_play", + url=await self.get_url(args), + guild_id=guild_id, + user=user_str)) + + # await data.reply("✅ Richiesta di riproduzione inviata!") diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index 2ca09f0c..aaa5e380 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -6,6 +6,7 @@ from typing import * from royalnet.commands import * from royalnet.serf.discord import * from royalnet.bard import * +from royalnet.backpack.tables.users import User from ..utils import RoyalQueue @@ -15,18 +16,22 @@ class DiscordPlayEvent(Event): async def run(self, url: str, guild_id: Optional[int] = None, + user: Optional[str] = None, **kwargs) -> dict: if not isinstance(self.serf, DiscordSerf): raise UnsupportedError() + serf: DiscordSerf = self.serf + client: discord.Client = self.serf.client + # TODO: fix this in Royalnet sometime candidate_players: List[VoicePlayer] = [] - for player in self.serf.voice_players: + for player in serf.voice_players: player: VoicePlayer if not player.voice_client.is_connected(): continue if guild_id is not None: - guild = self.serf.client.get_guild(guild_id) + guild = client.get_guild(guild_id) if guild != player.voice_client.guild: continue candidate_players.append(player) @@ -37,8 +42,8 @@ class DiscordPlayEvent(Event): elif len(candidate_players) == 1: voice_player = candidate_players[0] else: - raise InvalidInputError("Non so in che Server riprodurre questo file...\n" - "Invia il comando su Discord, per favore!") + raise CommandError("Non so in che Server riprodurre questo file...\n" + "Invia il comando su Discord, per favore!") ytds = await YtdlDiscord.from_url(url) added: List[YtdlDiscord] = [] @@ -55,6 +60,30 @@ class DiscordPlayEvent(Event): await voice_player.start() else: raise CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") + + main_channel: discord.TextChannel = client.get_channel(self.config["Discord"]["main_channel_id"]) + + if len(added) > 0: + if user: + await main_channel.send(escape(f"▶️ {user} ha aggiunto {len(added)} file alla coda:")) + else: + await main_channel.send(escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" + f" coda:")) + for ytd in added: + await main_channel.send(embed=ytd.embed()) + + if len(too_long) > 0: + if user: + await main_channel.send(escape( + f"⚠ {len(too_long)} file non {'è' if len(too_long) == 1 else 'sono'}" + f" stat{'o' if len(too_long) == 1 else 'i'} scaricat{'o' if len(too_long) == 1 else 'i'}" + f" perchè durava{'' if len(too_long) == 1 else 'no'}" + f" più di [c]{self.config['Play']['max_song_duration']}[/c] secondi." + )) + + if len(added) + len(too_long) == 0: + raise + return { "added": [{ "title": ytd.info.title, diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index 194a89e3..88c87af0 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -2,7 +2,6 @@ from typing import * from starlette.requests import Request from starlette.responses import * from royalnet.constellation import * -from royalnet.utils import * import logging @@ -14,12 +13,16 @@ class ApiDiscordPlayStar(PageStar): async def page(self, request: Request) -> JSONResponse: url = request.query_params.get("url", "") + user = request.query_params.get("user") try: guild_id: Optional[int] = int(request.query_params.get("guild_id", None)) except (ValueError, TypeError): guild_id = None log.info(f"Received request to play {url} on guild_id {guild_id} via web") - response = await self.interface.call_herald_event("discord", "discord_play", url=url, guild_id=guild_id) + response = await self.interface.call_herald_event("discord", "discord_play", + url=url, + guild_id=guild_id, + user=user) return JSONResponse(response, headers={ - "Access-Control-Allow-Origin": self.interface.config['Funkwhale']['instance_url'], + "Access-Control-Allow-Origin": "*", }) From e35b1c473360accf38feb55de359cf757341a2dd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 13 Jan 2020 14:51:54 +0100 Subject: [PATCH 019/227] Swap buff symbols --- royalpack/commands/spell.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/spell.py b/royalpack/commands/spell.py index 6d68bf00..17063a10 100644 --- a/royalpack/commands/spell.py +++ b/royalpack/commands/spell.py @@ -39,7 +39,7 @@ class SpellCommand(Command): stats: rs.StatsComponent = spell.stats_component rows.append("Il caster riceve: ") for stat_name in stats.stat_changes: - rows.append(f"[b]{stats.stat_changes[stat_name]}{stat_name}[/b]") + rows.append(f"[b]{stat_name}{stats.stat_changes[stat_name]}[/b]") rows.append("") if spell.status_effect_component: From 67018e5a59b88775b08dda98f3cd050979cd4981 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 13 Jan 2020 14:53:05 +0100 Subject: [PATCH 020/227] Change !fw error message --- royalpack/commands/funkwhale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index cecf1d7b..3a5be8a2 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -20,5 +20,5 @@ class FunkwhaleCommand(PlayCommand): f"/api/v1/search?query={search}") as response: j = await response.json() if len(j["tracks"]) < 1: - raise InvalidInputError("Nessun video trovato.") + raise UserError("Nessun file audio trovato con il nome richiesto.") return f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}' From 9b4764c28b899b2e54c0d59be14d0c580de47b4e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 13 Jan 2020 14:54:48 +0100 Subject: [PATCH 021/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c71c69a4..e4361311 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.9" + version = "5.2.10" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 3f54fdab..a209ff24 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.9" +semantic = "5.2.10" From 5ec1b971b0051fd22924ba8aba2377aabea71177 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 14 Jan 2020 19:59:47 +0100 Subject: [PATCH 022/227] Remove /markov --- pyproject.toml | 1 - royalpack/commands/__init__.py | 2 -- royalpack/commands/markov.py | 41 ---------------------------------- 3 files changed, 44 deletions(-) delete mode 100644 royalpack/commands/markov.py diff --git a/pyproject.toml b/pyproject.toml index e4361311..b3496e42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,6 @@ riotwatcher = "^2.7.1" royalspells = "^3.2" - markovify = "^0.8.0" [tool.poetry.dependencies.royalnet] version = "^5.2.4" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 11cc504f..7bee64cc 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -30,7 +30,6 @@ from .peertube import PeertubeCommand from .funkwhale import FunkwhaleCommand from .eval import EvalCommand from .exec import ExecCommand -from .markov import MarkovCommand # Enter the commands of your Pack here! available_commands = [ @@ -65,7 +64,6 @@ available_commands = [ EvalCommand, ExecCommand, FunkwhaleCommand, - MarkovCommand ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/markov.py b/royalpack/commands/markov.py deleted file mode 100644 index f162f9bb..00000000 --- a/royalpack/commands/markov.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import * -from royalnet.commands import * -# import markovify -# import os -# import re - - -class MarkovCommand(Command): - name: str = "markov" - - description: str = "Genera una frase da una catena di Markov." - - syntax: str = "[modello]" - - # _texts: Dict[str, markovify.NewlineText] = {} - - def __init__(self, interface: CommandInterface): - super().__init__(interface) - # if interface.name == "telegram": - # files: List[str] = tuple(os.walk(self.config["Markov"]["models_directory"]))[0][2] - # for file in files: - # match = re.match(r"(\S+)\.json$", file) - # if match is None: - # continue - # model_name = match.group(1) - # with open(os.path.join(self.config["Markov"]["models_directory"], file)) as f: - # self._texts[model_name] = markovify.NewlineText.from_json(f.read()) - - async def run(self, args: CommandArgs, data: CommandData) -> None: - raise CommandError(f"{self} è disattivato. Riprova tra un po' di giorni!") - # if self.interface.name != "telegram": - # raise UnsupportedError("[c]markov[/c] funziona solo su Telegram.") - # model_name = args.optional(0, self.config["Markov"]["default_model"]) - # try: - # sentence = self._texts[model_name].make_sentence() - # except KeyError: - # raise InvalidInputError("Il modello richiesto non esiste.") - # if sentence is None or sentence == "": - # await data.reply(f"💭 Il bot ([c]{model_name}[/c])... non dice niente. Riprova!") - # else: - # await data.reply(f'💬 Il bot ([c]{model_name}[/c]) dice:\n{sentence}') From 8c0a1f6905ded9bf6f24e64d001d87438fead7ac Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 15 Jan 2020 00:49:17 +0100 Subject: [PATCH 023/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b3496e42..f70378bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.10" + version = "5.2.11" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index a209ff24..6c245cc1 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.10" +semantic = "5.2.11" From b83a6307ad5958c478b14ada824dc7895185846d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 16 Jan 2020 03:00:35 +0100 Subject: [PATCH 024/227] Update to Royalnet 5.3.1 and readd trivia --- poetry.lock | 48 ++------- pyproject.toml | 2 +- royalpack/commands/__init__.py | 2 + royalpack/commands/peertubeupdates.py | 2 + royalpack/commands/trivia.py | 144 ++++++++++++++++++++++++++ 5 files changed, 160 insertions(+), 38 deletions(-) create mode 100644 royalpack/commands/trivia.py diff --git a/poetry.lock b/poetry.lock index 6b7aeb0e..346ab49a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -253,17 +253,6 @@ sqlalchemy = ["sqlalchemy"] test = ["pytest-cov (>=2.6)", "pytest (>4.0)"] zmq = ["pyzmq"] -[[package]] -category = "main" -description = "A simple, extensible Markov chain generator. Uses include generating random semi-plausible sentences based on an existing text." -name = "markovify" -optional = false -python-versions = "*" -version = "0.8.0" - -[package.dependencies] -unidecode = "*" - [[package]] category = "main" description = "A Python Matrix client library, designed according to sans I/O principles." @@ -451,7 +440,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.2.4" +version = "5.3.1" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -564,8 +553,8 @@ category = "main" description = "Python 2 and 3 compatibility utilities" name = "six" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "1.13.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "1.14.0" [[package]] category = "main" @@ -641,14 +630,6 @@ version = "2.0.0" [package.dependencies] pytz = "*" -[[package]] -category = "main" -description = "ASCII transliterations of Unicode text" -name = "unidecode" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.1.1" - [[package]] category = "main" description = "Unpadded Base64" @@ -720,10 +701,10 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.1.1" +version = "2020.1.15" [metadata] -content-hash = "8713e8d5f419fe8df4c610273aed1529ca44d9d3e4af542b89807b76743f146b" +content-hash = "84e93ee35c496ee10d2c2552ad6c38ec257dca2c8f9a91d2b4e4e4940057588a" python-versions = "^3.8" [metadata.files] @@ -890,9 +871,6 @@ logbook = [ {file = "Logbook-1.5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0cf2cdbfb65a03b5987d19109dacad13417809dcf697f66e1a7084fb21744ea9"}, {file = "Logbook-1.5.3.tar.gz", hash = "sha256:66f454ada0f56eae43066f604a222b09893f98c1adc18df169710761b8f32fe8"}, ] -markovify = [ - {file = "markovify-0.8.0.tar.gz", hash = "sha256:c533a2e1aba8148bb98031b7159e8bf1a276c61db53d2e882ecb74fa5603a4f4"}, -] matrix-nio = [ {file = "matrix-nio-0.6.tar.gz", hash = "sha256:25a4ac9d5e1435035f5c5b6e9a6b453ac66ade25cb455ba6bbe9cc3ae1e0ef50"}, ] @@ -1064,8 +1042,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.2.4-py3-none-any.whl", hash = "sha256:074d741ab78b96c98803a0816fd8e2fc61ecae3017f7c41ea8af40fc3675d07b"}, - {file = "royalnet-5.2.4.tar.gz", hash = "sha256:a38f02fa6560a0c05896957aeb504894292eae0a2e3f607d696b242026fed863"}, + {file = "royalnet-5.3.1-py3-none-any.whl", hash = "sha256:5473524e906fefb90f54af5ce62a0685fcea7766e8971792bd0bf740d558e5a5"}, + {file = "royalnet-5.3.1.tar.gz", hash = "sha256:ced549977490bc92864d220ed3c277f8425f4201f181fe2913bcdd85f58a7f36"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1075,8 +1053,8 @@ sentry-sdk = [ {file = "sentry_sdk-0.13.5-py2.py3-none-any.whl", hash = "sha256:05285942901d38c7ce2498aba50d8e87b361fc603281a5902dda98f3f8c5e145"}, ] six = [ - {file = "six-1.13.0-py2.py3-none-any.whl", hash = "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd"}, - {file = "six-1.13.0.tar.gz", hash = "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"}, + {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, + {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] sqlalchemy = [ {file = "SQLAlchemy-1.3.12.tar.gz", hash = "sha256:bfb8f464a5000b567ac1d350b9090cf081180ec1ab4aa87e7bca12dab25320ec"}, @@ -1106,10 +1084,6 @@ tzlocal = [ {file = "tzlocal-2.0.0-py2.py3-none-any.whl", hash = "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048"}, {file = "tzlocal-2.0.0.tar.gz", hash = "sha256:949b9dd5ba4be17190a80c0268167d7e6c92c62b30026cf9764caf3e308e5590"}, ] -unidecode = [ - {file = "Unidecode-1.1.1-py2.py3-none-any.whl", hash = "sha256:1d7a042116536098d05d599ef2b8616759f02985c85b4fef50c78a5aaf10822a"}, - {file = "Unidecode-1.1.1.tar.gz", hash = "sha256:2b6aab710c2a1647e928e36d69c21e76b453cd455f4e2621000e54b2a9b8cce8"}, -] unpaddedbase64 = [ {file = "unpaddedbase64-1.1.0-py2-none-any.whl", hash = "sha256:8917367e4e915b7dce1a72a99db8798c9f3d0d9a74cdd9aafac6d7c65ca495c5"}, {file = "unpaddedbase64-1.1.0-py2.py3-none-any.whl", hash = "sha256:81cb4eaaa28cc6a282dd3f2c3855eaa1fbaafa736b5ee64df69889e20540a339"}, @@ -1177,6 +1151,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.1.1-py2.py3-none-any.whl", hash = "sha256:3538410130b3adb4690955b2454bfe212d94babefd822aadae4a2b263c421be4"}, - {file = "youtube_dl-2020.1.1.tar.gz", hash = "sha256:0f8e62b5a3a5bb8bdf3d7ae3ec96c233f5110fa0ee1c9df51299b6636ebd4ff4"}, + {file = "youtube_dl-2020.1.15-py2.py3-none-any.whl", hash = "sha256:28630dfa91ba5e74676cbc76cfc91cd820e6dacca6ca175e07e49df73607bf46"}, + {file = "youtube_dl-2020.1.15.tar.gz", hash = "sha256:74e341f05e23e1650f57a01a58346cfabe3c841ccb9852c859ed2a383655db2a"}, ] diff --git a/pyproject.toml b/pyproject.toml index f70378bf..33fa700f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ royalspells = "^3.2" [tool.poetry.dependencies.royalnet] - version = "^5.2.4" + version = "^5.3.1" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 7bee64cc..56589fd4 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -30,6 +30,7 @@ from .peertube import PeertubeCommand from .funkwhale import FunkwhaleCommand from .eval import EvalCommand from .exec import ExecCommand +from .trivia import TriviaCommand # Enter the commands of your Pack here! available_commands = [ @@ -64,6 +65,7 @@ available_commands = [ EvalCommand, ExecCommand, FunkwhaleCommand, + TriviaCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/peertubeupdates.py b/royalpack/commands/peertubeupdates.py index 03e37078..85423965 100644 --- a/royalpack/commands/peertubeupdates.py +++ b/royalpack/commands/peertubeupdates.py @@ -33,6 +33,8 @@ class PeertubeUpdatesCommand(Command): 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 ExternalError("Peertube is unavailable") j = await response.json() log.debug("Jsonfeed parsed successfully") return j diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py new file mode 100644 index 00000000..b195e43a --- /dev/null +++ b/royalpack/commands/trivia.py @@ -0,0 +1,144 @@ +from typing import * +import asyncio +import aiohttp +import random +import uuid +import html +import royalnet.commands as rc +import royalnet.utils as ru +from ..tables import TriviaScore +from royalnet.backpack.tables.users import User + + +class TriviaCommand(rc.Command): + name: str = "trivia" + + aliases = ["t"] + + description: str = "Manda una domanda dell'OpenTDB in chat." + + syntax = "[credits|scores]" + + _letter_emojis = ["🇦", "🇧", "🇨", "🇩"] + + _medal_emojis = ["🥇", "🥈", "🥉", "🔹"] + + _correct_emoji = "✅" + + _wrong_emoji = "❌" + + _answer_time = 17 + + _question_lock: bool = False + + def __init__(self, interface: rc.CommandInterface): + super().__init__(interface) + 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.correct_rate)): + if index > 3: + index = 3 + strings.append(f"{self._medal_emojis[index]} {ts.royal.username}" + 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"]} - {question["difficulty"].capitalize()}[/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)) + 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(User)).get(answerer_id) + if answerer.trivia_score is None: + ts = self.interface.alchemy.get(TriviaScore)(royal=answerer) + data.session.add(ts) + await ru.asyncify(data.session.commit) + 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 + results += f" {answerer} ({answerer.trivia_score.correct_answers}/{answerer.trivia_score.total_answers})\n" + await data.reply(results) + del self._answerers[question_id] + await ru.asyncify(data.session.commit) + self._question_lock = False From 8bd7911e770fff51631bdc7f5c319906aee44ebb Mon Sep 17 00:00:00 2001 From: Alby1 <30355916+Alby1@users.noreply.github.com> Date: Fri, 10 Jan 2020 17:49:51 +0100 Subject: [PATCH 025/227] La mia sul fiume --- royalpack/commands/eat.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 90912da9..a2b00c69 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -155,6 +155,8 @@ class EatCommand(Command): "torta": "⬜️ Non hai mangiato niente.\n[i]La {food} è una menzogna![/i]", "cake": "⬜️ Non hai mangiato niente.\n[i]The {food} is a lie![/i]", "markov": "🗨 Stai cercando di mangiare... un matematico russo di nome {food}?\n[i]Lo trovi un po' indigesto.[/i]", + "mia sul fiume": "☣️Preparata dal bot con le sue stesse mani, un piatto migliore di qualsiasi altro al mondo.\n[i]Anche se non sappiamo di cosa sia" + " fatto esattamente[/i]", } async def run(self, args: CommandArgs, data: CommandData) -> None: From 34ecc10d53daa37423b449a1b674703ea9dbf332 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 16 Jan 2020 03:04:33 +0100 Subject: [PATCH 026/227] Cambiata un po' la frase --- royalpack/commands/eat.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index a2b00c69..071f8df9 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -155,8 +155,9 @@ class EatCommand(Command): "torta": "⬜️ Non hai mangiato niente.\n[i]La {food} è una menzogna![/i]", "cake": "⬜️ Non hai mangiato niente.\n[i]The {food} is a lie![/i]", "markov": "🗨 Stai cercando di mangiare... un matematico russo di nome {food}?\n[i]Lo trovi un po' indigesto.[/i]", - "mia sul fiume": "☣️Preparata dal bot con le sue stesse mani, un piatto migliore di qualsiasi altro al mondo.\n[i]Anche se non sappiamo di cosa sia" - " fatto esattamente[/i]", + "mia sul fiume": "💧 Hai mangiato il miglior piatto al mondo, la {food}, esclusivo ai membri Royal Games.\n" + "[i]Nessuno, tranne il bot, sa di cosa è fatta esattamente, ma una cosa è certa: è " + "buonissima![/i]", } async def run(self, args: CommandArgs, data: CommandData) -> None: From 101df42970b386b1f439c7b792b7c000bc8103cd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 16 Jan 2020 03:07:38 +0100 Subject: [PATCH 027/227] Fix this meme --- royalpack/commands/funkwhale.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index 20f12600..45aa75db 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -5,9 +5,9 @@ import urllib.parse class FunkwhaleCommand(PlayCommand): - name: str = "fuckwhale" + name: str = "funkwhale" - aliases = ["funkwhale", "fw", "royalwhale", "rw"] + aliases = ["fuckwhale", "fw", "royalwhale", "rw"] description: str = "Cerca un video su RoyalWhale e lo aggiunge alla coda della chat vocale." From 803aab7dc84f58753dce10b12e10973bb311baf0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 16 Jan 2020 03:10:31 +0100 Subject: [PATCH 028/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 33fa700f..d53d5847 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.2.11" + version = "5.3" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 6c245cc1..7a0f9a9c 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.2.11" +semantic = "5.3" From 38c9d1f019dd75c61f09659b513dea3b21dc597f Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 17:50:53 +0100 Subject: [PATCH 029/227] Use scores for trivia --- royalpack/commands/trivia.py | 9 ++++++--- royalpack/tables/triviascores.py | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index b195e43a..cca233a8 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -46,10 +46,10 @@ class TriviaCommand(rc.Command): 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.correct_rate)): + 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.royal.username}" + strings.append(f"{self._medal_emojis[index]} {ts.royal.username}: [b]{ts.score:.0f}p[/b]" f" ({ts.correct_answers}/{ts.total_answers})") await data.reply("\n".join(strings)) return @@ -131,13 +131,16 @@ class TriviaCommand(rc.Command): ts = self.interface.alchemy.get(TriviaScore)(royal=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 else: results += self._wrong_emoji answerer.trivia_score.wrong_answers += 1 - results += f" {answerer} ({answerer.trivia_score.correct_answers}/{answerer.trivia_score.total_answers})\n" + 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) diff --git a/royalpack/tables/triviascores.py b/royalpack/tables/triviascores.py index 39d251ae..e808e89d 100644 --- a/royalpack/tables/triviascores.py +++ b/royalpack/tables/triviascores.py @@ -36,5 +36,9 @@ class TriviaScore: def correct_rate(self): return self.correct_answers / self.total_answers + @property + def score(self) -> float: + return (self.correct_answers + self.correct_answers * self.correct_rate) * 10 + def __repr__(self): return f"" From d6a306036aae72bd7b3825f82f831331285e6e5e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 17:55:18 +0100 Subject: [PATCH 030/227] Fix divisionbyzero --- royalpack/tables/triviascores.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/royalpack/tables/triviascores.py b/royalpack/tables/triviascores.py index e808e89d..49538544 100644 --- a/royalpack/tables/triviascores.py +++ b/royalpack/tables/triviascores.py @@ -34,6 +34,8 @@ class TriviaScore: @property def correct_rate(self): + if self.total_answers == 0: + return 0.0 return self.correct_answers / self.total_answers @property From 5951cfe87440a1432efbc3f8dc55198ef58b5d8b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 17:58:56 +0100 Subject: [PATCH 031/227] Hide difficulties --- royalpack/commands/trivia.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index cca233a8..7f7f98c9 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -64,7 +64,7 @@ class TriviaCommand(rc.Command): 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"]} - {question["difficulty"].capitalize()}[/b]\n' \ + text = f'❓ [b]{question["category"]}[/b]\n' \ f'{html.unescape(question["question"])}' # Prepare answers correct_answer: str = question["correct_answer"] From 40af5e44155df7b9dc34b5a3ed1a38997c4223a9 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 17:59:30 +0100 Subject: [PATCH 032/227] Increase answer time to 20 seconds --- royalpack/commands/trivia.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index 7f7f98c9..6167d3ae 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -27,7 +27,7 @@ class TriviaCommand(rc.Command): _wrong_emoji = "❌" - _answer_time = 17 + _answer_time = 20 _question_lock: bool = False From 0e0b88e6e7a4dd386e06477cf4e4058fdfa55837 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 18:00:28 +0100 Subject: [PATCH 033/227] Remove question lock --- royalpack/commands/trivia.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index 6167d3ae..51f9e79e 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -29,7 +29,7 @@ class TriviaCommand(rc.Command): _answer_time = 20 - _question_lock: bool = False + # _question_lock: bool = False def __init__(self, interface: rc.CommandInterface): super().__init__(interface) @@ -53,9 +53,9 @@ class TriviaCommand(rc.Command): 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 + # 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: @@ -144,4 +144,4 @@ class TriviaCommand(rc.Command): await data.reply(results) del self._answerers[question_id] await ru.asyncify(data.session.commit) - self._question_lock = False + # self._question_lock = False From 53824e990c799a5f676d255b717d4c28d77e1b04 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 18:21:57 +0100 Subject: [PATCH 034/227] Fix reminder bug --- royalpack/commands/reminder.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/royalpack/commands/reminder.py b/royalpack/commands/reminder.py index e5c63497..6c9c5c64 100644 --- a/royalpack/commands/reminder.py +++ b/royalpack/commands/reminder.py @@ -37,7 +37,7 @@ class ReminderCommand(Command): async def _remind(self, reminder): await sleep_until(reminder.datetime) if self.interface.name == "telegram": - chat_id: int = pickle.loads(reminder.raw_interface_data) + 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, @@ -45,7 +45,7 @@ class ReminderCommand(Command): parse_mode="HTML", disable_web_page_preview=True) elif self.interface.name == "discord": - channel_id: int = pickle.loads(reminder.raw_interface_data) + 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}")) @@ -70,7 +70,7 @@ class ReminderCommand(Command): return await data.reply(f"✅ Promemoria impostato per [b]{date.strftime('%Y-%m-%d %H:%M:%S')}[/b]") if self.interface.name == "telegram": - interface_data = pickle.dumps(data.update.effective_chat.id) + interface_data = pickle.dumps(data.message.chat.id) elif self.interface.name == "discord": interface_data = pickle.dumps(data.message.channel.id) else: From c839ea2aca25458da989f716522c135ccc5c0da8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 18:29:25 +0100 Subject: [PATCH 035/227] Fix cv bug --- royalpack/commands/cv.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/royalpack/commands/cv.py b/royalpack/commands/cv.py index b6b98009..9efdeefe 100644 --- a/royalpack/commands/cv.py +++ b/royalpack/commands/cv.py @@ -77,7 +77,8 @@ class CvCommand(Command): activity += f" | 📺 {mact['name']}" # Custom Status elif mact["type"] == 4: - activity += f" | ❓ {mact['state']}" + if "state" in activity: + activity += f" | ❓ {mact['state']}" else: raise ExternalError(f"Unknown Discord activity type: {mact['type']}") From 81a8f791fa3e7c10440c63cb5a9149fa4032e039 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 17 Jan 2020 18:42:24 +0100 Subject: [PATCH 036/227] Bump version (derp) --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d53d5847..3ecd5e71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.3" + version = "5.3.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 7a0f9a9c..7624bdbb 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.3" +semantic = "5.3.1" From 6623853a8da8086b0b416baed75b7eed8c7cae1e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 20 Jan 2020 19:04:59 +0100 Subject: [PATCH 037/227] Fix update -> message bugs --- royalpack/commands/ciaoruozi.py | 3 +-- royalpack/commands/diario.py | 3 +-- royalpack/commands/rage.py | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/royalpack/commands/ciaoruozi.py b/royalpack/commands/ciaoruozi.py index 65927064..9afc2b65 100644 --- a/royalpack/commands/ciaoruozi.py +++ b/royalpack/commands/ciaoruozi.py @@ -9,8 +9,7 @@ class CiaoruoziCommand(Command): async def run(self, args: CommandArgs, data: CommandData) -> None: if self.interface.name == "telegram": - update: telegram.Update = data.update - user: telegram.User = update.effective_user + user: telegram.User = data.message.from_user # Se sei Ruozi, salutati da solo! if user.id == 112437036: await data.reply("👋 Ciao me!") diff --git a/royalpack/commands/diario.py b/royalpack/commands/diario.py index 6ba99de9..3416109a 100644 --- a/royalpack/commands/diario.py +++ b/royalpack/commands/diario.py @@ -38,8 +38,7 @@ class DiarioCommand(Command): async def run(self, args: CommandArgs, data: CommandData) -> None: if self.interface.name == "telegram": - update: telegram.Update = data.update - message: telegram.Message = update.message + message: telegram.Message = data.message reply: telegram.Message = message.reply_to_message creator = await data.get_author() # noinspection PyUnusedLocal diff --git a/royalpack/commands/rage.py b/royalpack/commands/rage.py index fa4a991a..c76372d8 100644 --- a/royalpack/commands/rage.py +++ b/royalpack/commands/rage.py @@ -11,10 +11,10 @@ class RageCommand(Command): description: str = "Arrabbiati per qualcosa, come una software house californiana." _MAD = ["MADDEN MADDEN MADDEN MADDEN", - "EA bad, praise Geraldo!", - "Stai sfogando la tua ira sul bot!", - "Basta, io cambio gilda!", - "Fondiamo la RRYG!"] + "EA bad, praise Geraldo!", + "Stai sfogando la tua ira sul bot!", + "Basta, io cambio gilda!", + "Fondiamo la RRYG!"] async def run(self, args: CommandArgs, data: CommandData) -> None: await data.reply(f"😠 {random.sample(self._MAD, 1)[0]}") From 91e1ef6d1fb11c9aaffc700ae8fefc9dd1278d88 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 20 Jan 2020 22:47:45 +0100 Subject: [PATCH 038/227] Add steampowered command --- poetry.lock | 155 ++++++++++++++++++++++++++++- pyproject.toml | 1 + royalpack/commands/__init__.py | 2 + royalpack/commands/steampowered.py | 67 +++++++++++++ royalpack/tables/__init__.py | 2 + royalpack/tables/steam.py | 45 +++++++++ 6 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 royalpack/commands/steampowered.py create mode 100644 royalpack/tables/steam.py diff --git a/poetry.lock b/poetry.lock index 346ab49a..c4dd898d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -152,6 +152,44 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" version = "0.18.2" +[[package]] +category = "main" +description = "Coroutine-based network library" +name = "gevent" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.4.0" + +[package.dependencies] +cffi = ">=1.11.5" +greenlet = ">=0.4.14" + +[package.extras] +dnspython = ["dnspython", "idna"] +doc = ["repoze.sphinx.autointerface"] +events = ["zope.event", "zope.interface"] +test = ["zope.interface", "zope.event", "requests", "objgraph", "psutil", "futures", "mock", "coverage (>=5.0a3)", "coveralls (>=1.0)"] + +[[package]] +category = "main" +description = "Implements EventEmitter using gevent" +name = "gevent-eventemitter" +optional = false +python-versions = "*" +version = "2.1" + +[package.dependencies] +gevent = ">=1.3" + +[[package]] +category = "main" +description = "Lightweight in-process concurrent programming" +marker = "platform_python_implementation == \"CPython\"" +name = "greenlet" +optional = false +python-versions = "*" +version = "0.4.15" + [[package]] category = "main" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" @@ -286,6 +324,18 @@ optional = false python-versions = ">=3.5" version = "4.7.4" +[[package]] +category = "main" +description = "Protocol Buffers" +name = "protobuf" +optional = false +python-versions = "*" +version = "3.11.2" + +[package.dependencies] +setuptools = "*" +six = ">=1.9" + [[package]] category = "main" description = "psycopg2 - Python-PostgreSQL Database Adapter" @@ -587,6 +637,23 @@ 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" +optional = false +python-versions = "*" +version = "0.9.1" + +[package.dependencies] +cryptography = ">=1.3" +gevent = ">=1.2.0" +gevent-eventemitter = ">=2.0" +protobuf = ">=3.0.0" +requests = ">=2.9.1" +six = ">=1.10" +vdf = ">=2.0" + [[package]] category = "main" description = "A python wrapper for the Discord API" @@ -675,6 +742,14 @@ optional = false python-versions = "*" version = "0.14.0" +[[package]] +category = "main" +description = "Library for working with Valve's VDF text format" +name = "vdf" +optional = false +python-versions = "*" +version = "3.2" + [[package]] category = "main" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" @@ -704,7 +779,7 @@ python-versions = "*" version = "2020.1.15" [metadata] -content-hash = "84e93ee35c496ee10d2c2552ad6c38ec257dca2c8f9a91d2b4e4e4940057588a" +content-hash = "e5c540dccfd2912ee3a397f3fdce2ed537273be220eecff046af58fd12c65d66" python-versions = "^3.8" [metadata.files] @@ -829,6 +904,56 @@ ffmpeg-python = [ future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] +gevent = [ + {file = "gevent-1.4.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b7d3a285978b27b469c0ff5fb5a72bcd69f4306dbbf22d7997d83209a8ba917"}, + {file = "gevent-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:44089ed06a962a3a70e96353c981d628b2d4a2f2a75ea5d90f916a62d22af2e8"}, + {file = "gevent-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:0e1e5b73a445fe82d40907322e1e0eec6a6745ca3cea19291c6f9f50117bb7ea"}, + {file = "gevent-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:74b7528f901f39c39cdbb50cdf08f1a2351725d9aebaef212a29abfbb06895ee"}, + {file = "gevent-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0ff2b70e8e338cf13bedf146b8c29d475e2a544b5d1fe14045aee827c073842c"}, + {file = "gevent-1.4.0-cp34-cp34m-macosx_10_14_x86_64.whl", hash = "sha256:0774babec518a24d9a7231d4e689931f31b332c4517a771e532002614e270a64"}, + {file = "gevent-1.4.0-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:d752bcf1b98174780e2317ada12013d612f05116456133a6acf3e17d43b71f05"}, + {file = "gevent-1.4.0-cp34-cp34m-win32.whl", hash = "sha256:3249011d13d0c63bea72d91cec23a9cf18c25f91d1f115121e5c9113d753fa12"}, + {file = "gevent-1.4.0-cp34-cp34m-win_amd64.whl", hash = "sha256:d1e6d1f156e999edab069d79d890859806b555ce4e4da5b6418616322f0a3df1"}, + {file = "gevent-1.4.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7d0809e2991c9784eceeadef01c27ee6a33ca09ebba6154317a257353e3af922"}, + {file = "gevent-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:14b4d06d19d39a440e72253f77067d27209c67e7611e352f79fe69e0f618f76e"}, + {file = "gevent-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:53b72385857e04e7faca13c613c07cab411480822ac658d97fd8a4ddbaf715c8"}, + {file = "gevent-1.4.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:8d9ec51cc06580f8c21b41fd3f2b3465197ba5b23c00eb7d422b7ae0380510b0"}, + {file = "gevent-1.4.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2711e69788ddb34c059a30186e05c55a6b611cb9e34ac343e69cf3264d42fe1c"}, + {file = "gevent-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:e5bcc4270671936349249d26140c267397b7b4b1381f5ec8b13c53c5b53ab6e1"}, + {file = "gevent-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9f7a1e96fec45f70ad364e46de32ccacab4d80de238bd3c2edd036867ccd48ad"}, + {file = "gevent-1.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:50024a1ee2cf04645535c5ebaeaa0a60c5ef32e262da981f4be0546b26791950"}, + {file = "gevent-1.4.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4bfa291e3c931ff3c99a349d8857605dca029de61d74c6bb82bd46373959c942"}, + {file = "gevent-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:ab4dc33ef0e26dc627559786a4fba0c2227f125db85d970abbf85b77506b3f51"}, + {file = "gevent-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:896b2b80931d6b13b5d9feba3d4eebc67d5e6ec54f0cf3339d08487d55d93b0e"}, + {file = "gevent-1.4.0-pp260-pypy_41-macosx_10_14_x86_64.whl", hash = "sha256:107f4232db2172f7e8429ed7779c10f2ed16616d75ffbe77e0e0c3fcdeb51a51"}, + {file = "gevent-1.4.0-pp260-pypy_41-win32.whl", hash = "sha256:28a0c5417b464562ab9842dd1fb0cc1524e60494641d973206ec24d6ec5f6909"}, + {file = "gevent-1.4.0.tar.gz", hash = "sha256:1eb7fa3b9bd9174dfe9c3b59b7a09b768ecd496debfc4976a9530a3e15c990d1"}, +] +gevent-eventemitter = [ + {file = "gevent-eventemitter-2.1.tar.gz", hash = "sha256:00e6e688c6a255f7bdcef1d8c999e0d02d9ab87d3c6ff626e6dc1a09762107f4"}, + {file = "gevent_eventemitter-2.1-py2.py3-none-any.whl", hash = "sha256:30605a9fbb1f38b2511f188a2e7a1b4e9262f3c13bf810ac5b79cc0ba2900ff7"}, +] +greenlet = [ + {file = "greenlet-0.4.15-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99a26afdb82ea83a265137a398f570402aa1f2b5dfb4ac3300c026931817b163"}, + {file = "greenlet-0.4.15-cp27-cp27m-win32.whl", hash = "sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87"}, + {file = "greenlet-0.4.15-cp27-cp27m-win_amd64.whl", hash = "sha256:9854f612e1b59ec66804931df5add3b2d5ef0067748ea29dc60f0efdcda9a638"}, + {file = "greenlet-0.4.15-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ac57fcdcfb0b73bb3203b58a14501abb7e5ff9ea5e2edfa06bb03035f0cff248"}, + {file = "greenlet-0.4.15-cp33-cp33m-win32.whl", hash = "sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720"}, + {file = "greenlet-0.4.15-cp33-cp33m-win_amd64.whl", hash = "sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28"}, + {file = "greenlet-0.4.15-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939"}, + {file = "greenlet-0.4.15-cp34-cp34m-win32.whl", hash = "sha256:8b4572c334593d449113f9dc8d19b93b7b271bdbe90ba7509eb178923327b625"}, + {file = "greenlet-0.4.15-cp34-cp34m-win_amd64.whl", hash = "sha256:a9f145660588187ff835c55a7d2ddf6abfc570c2651c276d3d4be8a2766db490"}, + {file = "greenlet-0.4.15-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0"}, + {file = "greenlet-0.4.15-cp35-cp35m-win32.whl", hash = "sha256:a19bf883b3384957e4a4a13e6bd1ae3d85ae87f4beb5957e35b0be287f12f4e4"}, + {file = "greenlet-0.4.15-cp35-cp35m-win_amd64.whl", hash = "sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6"}, + {file = "greenlet-0.4.15-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8"}, + {file = "greenlet-0.4.15-cp36-cp36m-win32.whl", hash = "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0"}, + {file = "greenlet-0.4.15-cp36-cp36m-win_amd64.whl", hash = "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656"}, + {file = "greenlet-0.4.15-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214"}, + {file = "greenlet-0.4.15-cp37-cp37m-win32.whl", hash = "sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043"}, + {file = "greenlet-0.4.15-cp37-cp37m-win_amd64.whl", hash = "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304"}, + {file = "greenlet-0.4.15.tar.gz", hash = "sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc"}, +] h11 = [ {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, @@ -893,6 +1018,27 @@ multidict = [ {file = "multidict-4.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb"}, {file = "multidict-4.7.4.tar.gz", hash = "sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4"}, ] +protobuf = [ + {file = "protobuf-3.11.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3f509f7e50d806a434fe4a5fbf602516002a0f092889209fff7db82060efffc0"}, + {file = "protobuf-3.11.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4571da974019849201fc1ec6626b9cea54bd11b6bed140f8f737c0a33ea37de5"}, + {file = "protobuf-3.11.2-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:0329e86a397db2a83f9dcbe21d9be55a47f963cdabc893c3a24f4d3a8f117c37"}, + {file = "protobuf-3.11.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:56bd1d84fbf4505c7b73f04de987eef5682e5752c811141b0186a3809bfb396f"}, + {file = "protobuf-3.11.2-cp35-cp35m-win32.whl", hash = "sha256:919f0d6f6addc836d08658eba3b52be2e92fd3e76da3ce00c325d8e9826d17c7"}, + {file = "protobuf-3.11.2-cp35-cp35m-win_amd64.whl", hash = "sha256:14d6ac53df9cb5bb87c4f91b677c1bc5cec9c0fd44327f367a3c9562de2877c4"}, + {file = "protobuf-3.11.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6e96dffaf4d0a9a329e528b353ba62fd9ef13599688723d96bc9c165d0b6871e"}, + {file = "protobuf-3.11.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6b5b947dc8b3f2aec0eaad65b0b5113fcd642c358c31357c647da6281ee31104"}, + {file = "protobuf-3.11.2-cp36-cp36m-win32.whl", hash = "sha256:680c668d00b5eff08b86aef9e5ba9a705e621ea05d39071cfea8e28cb2400946"}, + {file = "protobuf-3.11.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9c7b19c30cf0644afd0e4218b13f637ce54382fdcb1c8f75bf3e84e49a5f6d0a"}, + {file = "protobuf-3.11.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d61b14a9090da77fe87e38ba4c6c43d3533dcbeb5d84f5474e7ac63c532dcc9c"}, + {file = "protobuf-3.11.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a2e6f57114933882ec701807f217df2fb4588d47f71f227c0a163446b930d507"}, + {file = "protobuf-3.11.2-cp37-cp37m-win32.whl", hash = "sha256:0a7219254afec0d488211f3d482d8ed57e80ae735394e584a98d8f30a8c88a36"}, + {file = "protobuf-3.11.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a6b970a2eccfcbabe1acf230fbf112face1c4700036c95e195f3554d7bcb04c1"}, + {file = "protobuf-3.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d6faf5dbefb593e127463f58076b62fcfe0784187be8fe1aa9167388f24a22a1"}, + {file = "protobuf-3.11.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bc45641cbcdea068b67438244c926f9fd3e5cbdd824448a4a64370610df7c593"}, + {file = "protobuf-3.11.2-py2.7.egg", hash = "sha256:557686c43fbd04f5f7c533f00feee9a37dcca7b5896e3ae3664a33864e6dd546"}, + {file = "protobuf-3.11.2-py2.py3-none-any.whl", hash = "sha256:180fc364b42907a1d2afa183ccbeffafe659378c236b1ec3daca524950bb918d"}, + {file = "protobuf-3.11.2.tar.gz", hash = "sha256:3d7a7d8d20b4e7a8f63f62de2d192cfd8b7a53c56caba7ece95367ca2b80c574"}, +] psycopg2-binary = [ {file = "psycopg2-binary-2.8.4.tar.gz", hash = "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed"}, {file = "psycopg2_binary-2.8.4-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6"}, @@ -1062,6 +1208,9 @@ sqlalchemy = [ starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, ] +steam = [ + {file = "steam-0.9.1.tar.gz", hash = "sha256:167240080ea23e346c11face96a6e9acc2827978c46c5ae25fa74e38031ff978"}, +] temp-discordpy-without-websockets-requirement = [ {file = "temp_discordpy_without_websockets_requirement-0.1-py3-none-any.whl", hash = "sha256:361ddcc6fb2ec469706fde56c46a3e14f02671cf0e27204ef6c3c4d89c7227ab"}, {file = "temp_discordpy_without_websockets_requirement-0.1.tar.gz", hash = "sha256:7db02603cde084c7d579d872389f60ffd3f34197d885e4ca722a92bc302cb33c"}, @@ -1107,6 +1256,10 @@ uvloop = [ {file = "uvloop-0.14.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09"}, {file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"}, ] +vdf = [ + {file = "vdf-3.2-py2.py3-none-any.whl", hash = "sha256:8e0d33ebe0bafd991be3236ce1bd211e368e9a2b8bc376dacd5f6b77066afb90"}, + {file = "vdf-3.2.tar.gz", hash = "sha256:83f3b509fe99a4d842b74af3d0b1742be99f7098dae1d3eb7ca57522986737d5"}, +] websockets = [ {file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"}, {file = "websockets-8.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170"}, diff --git a/pyproject.toml b/pyproject.toml index 3ecd5e71..50e1af4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ riotwatcher = "^2.7.1" royalspells = "^3.2" + steam = "^0.9.1" [tool.poetry.dependencies.royalnet] version = "^5.3.1" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 56589fd4..7f9ff50f 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -31,6 +31,7 @@ from .funkwhale import FunkwhaleCommand from .eval import EvalCommand from .exec import ExecCommand from .trivia import TriviaCommand +from .steampowered import SteampoweredCommand # Enter the commands of your Pack here! available_commands = [ @@ -66,6 +67,7 @@ available_commands = [ ExecCommand, FunkwhaleCommand, TriviaCommand, + SteampoweredCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py new file mode 100644 index 00000000..304fd994 --- /dev/null +++ b/royalpack/commands/steampowered.py @@ -0,0 +1,67 @@ +from typing import * +from royalnet.commands import * +from royalnet.utils import * +from ..tables.steam import Steam +import steam +import datetime + + +class SteampoweredCommand(Command): + name: str = "steampowered" + + description: str = "Connetti il tuo account di Steam!" + + syntax: str = "{profile}" + + def __init__(self, interface: CommandInterface): + super().__init__(interface) + if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: + raise ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") + self._api = steam.WebAPI(self.config["Steam"]["web_api_key"]) + + def _display(self, account: Steam): + string = f"ℹ️ [b]{account.persona_name}[/b]\n" \ + f"{account.profile_url}\n" \ + f"\n" \ + f"SteamID: [c]{account.steam_id}[/c]\n" \ + f"Created on: {account.account_creation_date}\n" + return string + + async def _update(self, account: Steam): + response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=account.steam_id) + r = response["response"]["players"][0] + account.persona_name = r["personaname"] + account.profile_url = r["profileurl"] + account.avatar = r["avatar"] + account.primary_clan_id = r["primaryclanid"] + account.account_creation_date = datetime.datetime.fromtimestamp(r["timecreated"]) + + async def run(self, args: CommandArgs, data: CommandData) -> None: + author = await data.get_author() + if len(args) > 0: + steamid = args.match("([0-9]+)")[0] + response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid) + r = response["response"]["players"][0] + steam_account = self.alchemy.get(Steam)( + user=author, + steam_id=int(steamid), + persona_name=r["personaname"], + profile_url=r["profileurl"], + avatar=r["avatarfull"], + primary_clan_id=r["primaryclanid"], + account_creation_date=datetime.datetime.fromtimestamp(r["timecreated"]) + ) + data.session.add(steam_account) + await data.session_commit() + await data.reply(f"↔️ Account {steam_account} connesso a {author}!") + else: + # Update and display the Steam info for the current account + if len(author.steam) == 0: + raise UserError("Nessun account di Steam trovato.") + message = "" + for account in author.steam: + await self._update(account) + message += self._display(account) + message += "\n" + await data.session_commit() + await data.reply(message) diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 5a201872..e8d4d37f 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -10,6 +10,7 @@ from .mmevents import MMEvent from .mmresponse import MMResponse from .leagueoflegends import LeagueOfLegends from .fiorygi import Fiorygi +from .steam import Steam # Enter the tables of your Pack here! available_tables = [ @@ -24,6 +25,7 @@ available_tables = [ MMResponse, LeagueOfLegends, Fiorygi, + Steam, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/steam.py b/royalpack/tables/steam.py new file mode 100644 index 00000000..a1dfddfc --- /dev/null +++ b/royalpack/tables/steam.py @@ -0,0 +1,45 @@ +from sqlalchemy import * +from sqlalchemy.orm import relationship, backref +from sqlalchemy.ext.declarative import declared_attr + + +class Steam: + __tablename__ = "steam" + + @declared_attr + def user_id(self): + return Column(Integer, ForeignKey("users.uid")) + + @declared_attr + def user(self): + return relationship("User", backref=backref("steam")) + + @declared_attr + def steam_id(self): + return Column(BigInteger, primary_key=True) + + @declared_attr + def persona_name(self): + return Column(String) + + @declared_attr + def profile_url(self): + return Column(String) + + @declared_attr + def avatar(self): + return Column(String) + + @declared_attr + def primary_clan_id(self): + return Column(BigInteger) + + @declared_attr + def account_creation_date(self): + return Column(DateTime) + + def __repr__(self): + return f"" + + def __str__(self): + return f"steam:{self.steam_id}" From 387cb902ed617331cec9e8f5c3c04922588e9e59 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 21 Jan 2020 00:54:55 +0100 Subject: [PATCH 039/227] Add steammatch command --- royalpack/commands/__init__.py | 2 + royalpack/commands/steammatch.py | 101 +++++++++++++++++++++++++++++ royalpack/commands/steampowered.py | 19 ++++-- royalpack/commands/userinfo.py | 27 ++++---- royalpack/tables/aliases.py | 7 ++ royalpack/tables/steam.py | 11 +++- 6 files changed, 144 insertions(+), 23 deletions(-) create mode 100644 royalpack/commands/steammatch.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 7f9ff50f..375e2600 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -32,6 +32,7 @@ from .eval import EvalCommand from .exec import ExecCommand from .trivia import TriviaCommand from .steampowered import SteampoweredCommand +from .steammatch import SteammatchCommand # Enter the commands of your Pack here! available_commands = [ @@ -68,6 +69,7 @@ available_commands = [ FunkwhaleCommand, TriviaCommand, SteampoweredCommand, + SteammatchCommand ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py new file mode 100644 index 00000000..32a105d6 --- /dev/null +++ b/royalpack/commands/steammatch.py @@ -0,0 +1,101 @@ +from typing import * +from royalnet.commands import * +from royalnet.utils import * +from ..tables import Alias, Steam +import steam +import requests.exceptions + + +class SteamGame: + def __init__(self, + appid=None, + name=None, + playtime_forever=None, + img_icon_url=None, + img_logo_url=None, + has_community_visible_stats=None, + playtime_windows_forever=None, + playtime_mac_forever=None, + playtime_linux_forever=None, + playtime_2weeks=None): + self.appid = appid + self.name = name + self.playtime_forever = playtime_forever + self.img_icon_url = img_icon_url + self.img_logo_url = img_logo_url + self.has_community_visible_stats = has_community_visible_stats + self.playtime_windows_forever = playtime_windows_forever + self.playtime_mac_forever = playtime_mac_forever + self.playtime_linux_forever = playtime_linux_forever + self.playtime_2weeks = playtime_2weeks + + def __hash__(self): + return self.appid + + def __eq__(self, other): + if isinstance(other, SteamGame): + return self.appid == other.appid + return False + + def __str__(self): + return self.name + + def __repr__(self): + return f"<{self.__class__.__qualname__} {self.appid} ({self.name})>" + + +class SteammatchCommand(Command): + name: str = "steammatch" + + description: str = "Vedi quali giochi hai in comune con uno o più membri!" + + syntax: str = "{royalnet_username}+" + + def __init__(self, interface: CommandInterface): + super().__init__(interface) + if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: + raise ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") + self._api = steam.WebAPI(self.config["Steam"]["web_api_key"]) + + async def run(self, args: CommandArgs, data: CommandData) -> None: + users = [] + + author = await data.get_author(error_if_none=True) + users.append(author) + + for arg in args: + user = await asyncify(Alias.find_by_alias, self.alchemy, data.session, arg) + users.append(user) + + if len(users) < 2: + raise InvalidInputError("Devi specificare almeno un altro utente!") + + shared_games: Optional[set] = None + for user in users: + user_games = set() + if len(user.steam) == 0: + raise UserError(f"{user} non ha un account Steam registrato!") + for steam_account in user.steam: + steam_account: Steam + try: + response = await asyncify(self._api.IPlayerService.GetOwnedGames, + steamid=steam_account._steamid, + include_appinfo=True, + include_played_free_games=True, + appids_filter=0) + except requests.exceptions.HTTPError: + raise ExternalError(f"L'account Steam di {user} è privato!") + games = response["response"]["games"] + for game in games: + user_games.add(SteamGame(**game)) + if shared_games is None: + shared_games = user_games + else: + shared_games = shared_games.intersection(user_games) + + message_rows = [f"🎮 Giochi in comune tra {andformat([str(user) for user in users], final=' e ')}:"] + for game in sorted(list(shared_games), key=lambda g: g.name): + message_rows.append(f"- {game}") + + message = "\n".join(message_rows) + await data.reply(message) diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 304fd994..cfa5186f 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -11,7 +11,7 @@ class SteampoweredCommand(Command): description: str = "Connetti il tuo account di Steam!" - syntax: str = "{profile}" + syntax: str = "{profile_url}" def __init__(self, interface: CommandInterface): super().__init__(interface) @@ -23,12 +23,16 @@ class SteampoweredCommand(Command): string = f"ℹ️ [b]{account.persona_name}[/b]\n" \ f"{account.profile_url}\n" \ f"\n" \ - f"SteamID: [c]{account.steam_id}[/c]\n" \ - f"Created on: {account.account_creation_date}\n" + f"SteamID: [c]{account.steamid.as_32}[/c]\n" \ + f"SteamID2: [c]{account.steamid.as_steam2}[/c]\n" \ + f"SteamID3: [c]{account.steamid.as_steam3}[/c]\n" \ + f"SteamID64: [c]{account.steamid.as_64}[/c]\n" \ + f"\n" \ + f"Created on: [b]{account.account_creation_date}[/b]\n" return string async def _update(self, account: Steam): - response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=account.steam_id) + response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=account._steamid) r = response["response"]["players"][0] account.persona_name = r["personaname"] account.profile_url = r["profileurl"] @@ -39,12 +43,13 @@ class SteampoweredCommand(Command): async def run(self, args: CommandArgs, data: CommandData) -> None: author = await data.get_author() if len(args) > 0: - steamid = args.match("([0-9]+)")[0] - response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid) + url = args.joined() + steamid64 = await asyncify(steam.steamid.steam64_from_url, url) + response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid64) r = response["response"]["players"][0] steam_account = self.alchemy.get(Steam)( user=author, - steam_id=int(steamid), + _steamid=int(steamid64), persona_name=r["personaname"], profile_url=r["profileurl"], avatar=r["avatarfull"], diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py index 125ae951..3efa2bfb 100644 --- a/royalpack/commands/userinfo.py +++ b/royalpack/commands/userinfo.py @@ -3,6 +3,7 @@ from royalnet.commands import * from royalnet.utils import * from royalnet.backpack.tables import User from sqlalchemy import func +from ..tables.aliases import Alias class UserinfoCommand(Command): @@ -19,27 +20,18 @@ class UserinfoCommand(Command): if username is None: user: User = await data.get_author(error_if_none=True) else: - found: Optional[User] = await asyncify( - data.session - .query(self.alchemy.get(User)) - .filter(func.lower(self.alchemy.get(User).username) == func.lower(username)) - .one_or_none - ) + found: Optional[User] = await asyncify(Alias.find_by_alias, self.alchemy, data.session, username) if not found: raise InvalidInputError("Utente non trovato.") else: user = found r = [ - f"ℹ️ [b]{user.username}[/b] (ID: {user.uid})", + f"ℹ️ [b]{user.username}[/b]", f"{user.role}", "", ] - if user.fiorygi: - r.append(f"{user.fiorygi}") - r.append("") - # Bios are a bit too long # if user.bio: # r.append(f"{user.bio}") @@ -50,6 +42,9 @@ class UserinfoCommand(Command): for account in user.discord: r.append(f"{account}") + for account in user.steam: + r.append(f"{account}") + for account in user.leagueoflegends: r.append(f"{account}") @@ -61,7 +56,13 @@ class UserinfoCommand(Command): r.append("") if user.trivia_score: - r.append(f"Trivia: [b]{user.trivia_score.correct_answers}[/b] risposte corrette / " - f"{user.trivia_score.total_answers} totali") + 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/aliases.py b/royalpack/tables/aliases.py index 2a1c99ec..0f4ec1f8 100644 --- a/royalpack/tables/aliases.py +++ b/royalpack/tables/aliases.py @@ -21,6 +21,13 @@ class Alias: def royal(self): return relationship("User", backref="aliases") + @classmethod + def find_by_alias(cls, alchemy, session, alias: str): + result = session.query(alchemy.get(cls)).filter_by(alias=alias.lower()).one_or_none() + if result is not None: + result = result.royal + return result + def __repr__(self): return f"" diff --git a/royalpack/tables/steam.py b/royalpack/tables/steam.py index a1dfddfc..4d165ec7 100644 --- a/royalpack/tables/steam.py +++ b/royalpack/tables/steam.py @@ -1,6 +1,7 @@ from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declared_attr +import steam class Steam: @@ -15,9 +16,13 @@ class Steam: return relationship("User", backref=backref("steam")) @declared_attr - def steam_id(self): + def _steamid(self): return Column(BigInteger, primary_key=True) + @property + def steamid(self): + return steam.SteamID(self._steamid) + @declared_attr def persona_name(self): return Column(String) @@ -39,7 +44,7 @@ class Steam: return Column(DateTime) def __repr__(self): - return f"" + return f"" def __str__(self): - return f"steam:{self.steam_id}" + return f"[c]steam:{self._steamid}[/c]" From 0b6139ac900391beb79dee58f57ccaef6a1b8ee6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 21 Jan 2020 00:57:04 +0100 Subject: [PATCH 040/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 50e1af4d..85cf4dce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.3.1" + version = "5.3.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 7624bdbb..5b656d04 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.3.1" +semantic = "5.3.2" From 7b4a3b8fb385c78868720cf7376cca0565109717 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 24 Jan 2020 01:07:11 +0100 Subject: [PATCH 041/227] Add dota command --- royalpack/commands/__init__.py | 4 +- royalpack/commands/dota.py | 152 ++++++++++++++++++++++++++ royalpack/commands/leagueoflegends.py | 51 +++++---- royalpack/commands/rage.py | 12 +- royalpack/commands/userinfo.py | 2 + royalpack/tables/__init__.py | 2 + royalpack/tables/dota.py | 81 ++++++++++++++ royalpack/utils/__init__.py | 6 + royalpack/utils/dotamedal.py | 21 ++++ royalpack/utils/dotarank.py | 46 ++++++++ royalpack/utils/dotastars.py | 20 ++++ 11 files changed, 365 insertions(+), 32 deletions(-) create mode 100644 royalpack/commands/dota.py create mode 100644 royalpack/tables/dota.py create mode 100644 royalpack/utils/dotamedal.py create mode 100644 royalpack/utils/dotarank.py create mode 100644 royalpack/utils/dotastars.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 375e2600..6826c821 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -33,6 +33,7 @@ from .exec import ExecCommand from .trivia import TriviaCommand from .steampowered import SteampoweredCommand from .steammatch import SteammatchCommand +from .dota import DotaCommand # Enter the commands of your Pack here! available_commands = [ @@ -69,7 +70,8 @@ available_commands = [ FunkwhaleCommand, TriviaCommand, SteampoweredCommand, - SteammatchCommand + SteammatchCommand, + DotaCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py new file mode 100644 index 00000000..8cf78eb1 --- /dev/null +++ b/royalpack/commands/dota.py @@ -0,0 +1,152 @@ +import asyncio +import logging +import sentry_sdk +import aiohttp +from typing import * +from royalnet.commands import * +from royalnet.utils import * +from royalnet.serf.telegram.escape import escape as tg_escape +from ..tables import Steam, Dota +from ..utils import DotaRank + +log = logging.getLogger(__name__) + + +class DotaCommand(Command): + name: str = "dota" + + aliases = ["dota2", "doto", "doto2"] + + description: str = "Visualizza le tue statistiche di Dota!" + + syntax: str = "" + + def __init__(self, interface: CommandInterface): + super().__init__(interface) + if self.interface.name == "telegram": + self.loop.create_task(self._updater(900)) + + async def _send(self, message): + client = self.serf.client + await self.serf.api_call(client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=tg_escape(message), + parse_mode="HTML", + disable_webpage_preview=True) + + @staticmethod + def _display(dota: Dota) -> str: + string = f"ℹ️ [b]{dota.steam}[/b]\n" + + if dota.rank: + string += f"{dota.rank}\n" + + string += f"\n" \ + f"Wins: [b]{dota.wins}[/b]\n" \ + f"Losses: [b]{dota.losses}[/b]\n" \ + f"\n" + + return string + + async def _notify(self, + obj: Dota, + attribute_name: str, + old_value: Any, + new_value: Any): + if attribute_name == "wins": + if old_value is None: + message = f"↔️ Account {obj} connesso a {obj.steam.user}!" + await self._send(message) + elif attribute_name == "rank": + old_rank: Optional[DotaRank] = old_value + new_rank: Optional[DotaRank] = new_value + if new_rank > old_rank: + message = f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new_value}[/b] su Dota 2! Congratulazioni!" + elif new_rank < old_rank: + message = f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new_value}[/b] su Dota 2." + else: + return + await self._send(message) + + @staticmethod + async def _change(obj: Dota, + attribute_name: str, + new_value: Any, + callback: Callable[[Dota, str, Any, Any], Awaitable[None]]): + old_value = obj.__getattribute__(attribute_name) + if old_value != new_value: + await callback(obj, attribute_name, old_value, new_value) + obj.__setattr__(attribute_name, new_value) + + async def _update(self, steam: Steam, db_session): + log.info(f"Updating: {steam}") + log.debug(f"Getting player data from OpenDota...") + async with aiohttp.ClientSession() as session: + # Get profile data + async with session.get(f"https://api.opendota.com/api/players/{steam.steamid.as_32}/") as response: + if response.status != 200: + raise ExternalError(f"OpenDota / returned {response.status}!") + p = await response.json() + # No such user + if "profile" not in p: + log.debug(f"Not found: {steam}") + return + # Get win/loss data + async with session.get(f"https://api.opendota.com/api/players/{steam.steamid.as_32}/wl") as response: + if response.status != 200: + raise ExternalError(f"OpenDota /wl returned {response.status}!") + wl = await response.json() + # No such user + if wl["win"] == 0 and wl["lose"] == 0: + log.debug(f"Not found: {steam}") + return + # Find the Dota record, if it exists + dota: Dota = steam.dota + if dota is None: + dota = self.alchemy.get(Dota)(steam=steam) + db_session.add(dota) + db_session.flush() + await self._change(dota, "wins", wl["win"], self._notify) + await self._change(dota, "losses", wl["lose"], self._notify) + if p["rank_tier"]: + await self._change(dota, "rank", DotaRank(rank_tier=p["rank_tier"]), self._notify) + else: + await self._change(dota, "rank", None, self._notify) + + async def _updater(self, period: int): + log.info(f"Started updater with {period}s period") + while True: + log.info(f"Updating...") + session = self.alchemy.Session() + log.info("") + steams = session.query(self.alchemy.get(Steam)).all() + for steam in steams: + try: + await self._update(steam, session) + except Exception as e: + sentry_sdk.capture_exception(e) + log.error(f"Error while updating {steam.user.username}: {e}") + await asyncio.sleep(1) + await asyncify(session.commit) + session.close() + log.info(f"Sleeping for {period}s") + await asyncio.sleep(period) + + async def run(self, args: CommandArgs, data: CommandData) -> None: + author = await data.get_author(error_if_none=True) + + found_something = False + + message = "" + for steam in author.steam: + dota = steam.dota + if dota is None: + continue + found_something = True + await self._update(steam) + message += self._display(steam) + message += "\n" + if not found_something: + if len(author.leagueoflegends) == 0: + raise UserError("Nessun account di Dota 2 trovato.") + await data.reply(message) diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 6efe6ec7..e5d05a1d 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -40,32 +40,31 @@ class LeagueoflegendsCommand(Command): attribute_name: str, old_value: typing.Any, new_value: typing.Any): - if self.interface.name == "telegram": - if isinstance(old_value, LeagueLeague): - # This is a rank change! - # Don't send messages for every rank change, send messages just if the TIER or RANK changes! - if old_value.tier == new_value.tier and old_value.rank == new_value.rank: - return - # Find the queue - queue_names = { - "rank_soloq": "Solo/Duo", - "rank_flexq": "Flex", - "rank_twtrq": "3v3", - "rank_tftq": "TFT" - } - # Prepare the message - if new_value > old_value: - message = f"📈 [b]{obj.user}[/b] è salito a {new_value} su League of Legends " \ - f"({queue_names[attribute_name]})! Congratulazioni!" - else: - message = f"📉 [b]{obj.user}[/b] è sceso a {new_value} su League of Legends " \ - f"({queue_names[attribute_name]})." - # Send the message - await self._send(message) - # Level up! - elif attribute_name == "summoner_level": - if new_value == 30 or (new_value >= 50 and (new_value % 25 == 0)): - await self._send(f"🆙 [b]{obj.user}[/b] è salito al livello [b]{new_value}[/b] su League of Legends!") + if isinstance(old_value, LeagueLeague): + # This is a rank change! + # Don't send messages for every rank change, send messages just if the TIER or RANK changes! + if old_value.tier == new_value.tier and old_value.rank == new_value.rank: + return + # Find the queue + queue_names = { + "rank_soloq": "Solo/Duo", + "rank_flexq": "Flex", + "rank_twtrq": "3v3", + "rank_tftq": "TFT" + } + # Prepare the message + if new_value > old_value: + message = f"📈 [b]{obj.user}[/b] è salito a {new_value} su League of Legends " \ + f"({queue_names[attribute_name]})! Congratulazioni!" + else: + message = f"📉 [b]{obj.user}[/b] è sceso a {new_value} su League of Legends " \ + f"({queue_names[attribute_name]})." + # Send the message + await self._send(message) + # Level up! + elif attribute_name == "summoner_level": + if new_value == 30 or (new_value >= 50 and (new_value % 25 == 0)): + await self._send(f"🆙 [b]{obj.user}[/b] è salito al livello [b]{new_value}[/b] su League of Legends!") @staticmethod async def _change(obj: LeagueOfLegends, diff --git a/royalpack/commands/rage.py b/royalpack/commands/rage.py index c76372d8..248d1162 100644 --- a/royalpack/commands/rage.py +++ b/royalpack/commands/rage.py @@ -10,11 +10,13 @@ class RageCommand(Command): description: str = "Arrabbiati per qualcosa, come una software house californiana." - _MAD = ["MADDEN MADDEN MADDEN MADDEN", - "EA bad, praise Geraldo!", - "Stai sfogando la tua ira sul bot!", - "Basta, io cambio gilda!", - "Fondiamo la RRYG!"] + _MAD = [ + "MADDEN MADDEN MADDEN MADDEN", + "EA bad, praise Geraldo!", + "Stai sfogando la tua ira sul bot!", + "Basta, io cambio gilda!", + "Fondiamo la RRYG!" + ] async def run(self, args: CommandArgs, data: CommandData) -> None: await data.reply(f"😠 {random.sample(self._MAD, 1)[0]}") diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py index 3efa2bfb..aacd28b1 100644 --- a/royalpack/commands/userinfo.py +++ b/royalpack/commands/userinfo.py @@ -44,6 +44,8 @@ class UserinfoCommand(Command): for account in user.steam: r.append(f"{account}") + if account.dota is not None: + r.append(f"{account.dota}") for account in user.leagueoflegends: r.append(f"{account}") diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index e8d4d37f..f6a90b78 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -11,6 +11,7 @@ from .mmresponse import MMResponse from .leagueoflegends import LeagueOfLegends from .fiorygi import Fiorygi from .steam import Steam +from .dota import Dota # Enter the tables of your Pack here! available_tables = [ @@ -26,6 +27,7 @@ available_tables = [ LeagueOfLegends, Fiorygi, Steam, + Dota, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/dota.py b/royalpack/tables/dota.py new file mode 100644 index 00000000..3ec2100d --- /dev/null +++ b/royalpack/tables/dota.py @@ -0,0 +1,81 @@ +from typing import * +from sqlalchemy import * +from sqlalchemy.orm import relationship, backref +from sqlalchemy.ext.declarative import declared_attr +from ..utils.dotamedal import DotaMedal +from ..utils.dotastars import DotaStars +from ..utils.dotarank import DotaRank +import steam + + +class Dota: + __tablename__ = "dota" + + @declared_attr + def _steamid(self): + return Column(BigInteger, ForeignKey("steam._steamid"), primary_key=True) + + @declared_attr + def steam(self): + return relationship("Steam", backref=backref("dota", uselist=False)) + + @property + def steamid(self): + return steam.SteamID(self._steamid) + + @declared_attr + def _rank_tier(self): + return Column(Integer) + + @property + def medal(self) -> Optional[DotaMedal]: + if self._rank_tier is None: + return None + return DotaMedal(self._rank_tier // 10) + + @medal.setter + def medal(self, value: DotaMedal): + if not isinstance(value, DotaMedal): + raise AttributeError("medal can only be set to DotaMedal objects.") + self._rank_tier = value.value * 10 + self.stars.value + + @property + def stars(self) -> Optional[DotaStars]: + if self._rank_tier is None: + return None + return DotaStars(self._rank_tier % 10) + + @stars.setter + def stars(self, value: DotaStars): + if not isinstance(value, DotaStars): + raise AttributeError("stars can only be set to DotaStars objects.") + self._rank_tier = self.medal.value * 10 + value.value + + @property + def rank(self) -> Optional[DotaRank]: + if self._rank_tier is None: + return None + return DotaRank(self.medal, self.stars) + + @rank.setter + def rank(self, value: Optional[DotaRank]): + if value is None: + self._rank_tier = None + return + if not isinstance(value, DotaRank): + raise AttributeError("rank can only be set to DotaRank objects (or None).") + self._rank_tier = value.rank_tier + + @declared_attr + def wins(self): + return Column(Integer) + + @declared_attr + def losses(self): + return Column(Integer) + + def __repr__(self): + return f"" + + def __str__(self): + return f"[c]dota:{self._steamid}[/c]" diff --git a/royalpack/utils/__init__.py b/royalpack/utils/__init__.py index 1dc3db68..4a9b5117 100644 --- a/royalpack/utils/__init__.py +++ b/royalpack/utils/__init__.py @@ -4,6 +4,9 @@ from .leaguetier import LeagueTier from .leaguerank import LeagueRank from .leagueleague import LeagueLeague from .royalqueue import RoyalQueue +from .dotamedal import DotaMedal +from .dotastars import DotaStars +from .dotarank import DotaRank __all__ = [ "MMChoice", @@ -13,4 +16,7 @@ __all__ = [ "LeagueRank", "LeagueLeague", "RoyalQueue", + "DotaMedal", + "DotaStars", + "DotaRank", ] diff --git a/royalpack/utils/dotamedal.py b/royalpack/utils/dotamedal.py new file mode 100644 index 00000000..865bf3c4 --- /dev/null +++ b/royalpack/utils/dotamedal.py @@ -0,0 +1,21 @@ +import enum + + +class DotaMedal(enum.Enum): + HERALD = 1 + GUARDIAN = 2 + CRUSADER = 3 + ARCHON = 4 + LEGEND = 5 + ANCIENT = 6 + DIVINE = 7 + IMMORTAL = 8 + + def __str__(self): + return self.name.capitalize() + + def __repr__(self): + return f"{self.__class__.__qualname__}.{self.name}" + + def __gt__(self, other): + return self.value > other.value diff --git a/royalpack/utils/dotarank.py b/royalpack/utils/dotarank.py new file mode 100644 index 00000000..46d3b5d0 --- /dev/null +++ b/royalpack/utils/dotarank.py @@ -0,0 +1,46 @@ +from .dotamedal import DotaMedal +from .dotastars import DotaStars + + +class DotaRank: + __slots__ = "medal", "stars" + + def __init__(self, medal: DotaMedal = None, stars: DotaStars = None, *, rank_tier: int = None): + if rank_tier is not None: + self.medal: DotaMedal = DotaMedal(rank_tier // 10) + self.stars: DotaStars = DotaStars(rank_tier % 10) + else: + if medal is None or stars is None: + raise AttributeError("Missing medal, stars or rank_tier.") + self.medal = medal + self.stars = stars + + def __gt__(self, other): + if other is None: + return True + if not isinstance(other, DotaRank): + raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}") + if self.medal > other.medal: + return True + elif self.medal < other.medal: + return False + elif self.stars > other.stars: + return True + return False + + def __eq__(self, other): + if other is None: + return False + if not isinstance(other, DotaRank): + raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}") + return self.medal == other.medal and self.stars == other.stars + + def __repr__(self): + return f"<{self.__class__.__qualname__}: {self.medal.name} {self.stars.name}>" + + def __str__(self): + return f"{self.medal} {self.stars}" + + @property + def rank_tier(self) -> int: + return (self.medal.value * 10 + self.stars.value) \ No newline at end of file diff --git a/royalpack/utils/dotastars.py b/royalpack/utils/dotastars.py new file mode 100644 index 00000000..1693c552 --- /dev/null +++ b/royalpack/utils/dotastars.py @@ -0,0 +1,20 @@ +import enum + + +class DotaStars(enum.Enum): + I = 1 + II = 2 + III = 3 + IV = 4 + V = 5 + VI = 6 + VII = 7 + + def __str__(self): + return self.name.upper() + + def __repr__(self): + return f"{self.__class__.__qualname__}.{self.name}" + + def __gt__(self, other): + return self.value > other.value From 798be9e9369e815d5e2515e949d37a3823a6f9dd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 24 Jan 2020 01:17:01 +0100 Subject: [PATCH 042/227] Fix bugs --- royalpack/commands/dota.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index 8cf78eb1..ff72c7d8 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -36,7 +36,7 @@ class DotaCommand(Command): @staticmethod def _display(dota: Dota) -> str: - string = f"ℹ️ [b]{dota.steam}[/b]\n" + string = f"ℹ️ [b]{dota.steam.persona_name}[/b]\n" if dota.rank: string += f"{dota.rank}\n" @@ -139,14 +139,12 @@ class DotaCommand(Command): message = "" for steam in author.steam: - dota = steam.dota - if dota is None: + await self._update(steam, data.session) + if steam.dota is None: continue found_something = True - await self._update(steam) - message += self._display(steam) + message += self._display(steam.dota) message += "\n" if not found_something: - if len(author.leagueoflegends) == 0: - raise UserError("Nessun account di Dota 2 trovato.") + raise UserError("Nessun account di Dota 2 trovato.") await data.reply(message) From fc3493ec71df89ed6eab4e23d9b0804b0fb515bc Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 24 Jan 2020 01:17:20 +0100 Subject: [PATCH 043/227] Bump version --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 85cf4dce..a5a80b75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.3.2" + version = "5.3.3" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 5b656d04..ff6c1d6b 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.3.2" +semantic = "5.3.3" From bda8c09cf335cc24d5e4531dfb036ad27c48bd2a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 24 Jan 2020 01:21:37 +0100 Subject: [PATCH 044/227] Update lock --- poetry.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index c4dd898d..1132deb6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -612,7 +612,7 @@ description = "Database Abstraction Library" name = "sqlalchemy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.12" +version = "1.3.13" [package.extras] mssql = ["pyodbc"] @@ -710,8 +710,8 @@ category = "main" description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -version = "1.25.7" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.8" [package.extras] brotli = ["brotlipy (>=0.6.0)"] @@ -776,7 +776,7 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.1.15" +version = "2020.1.24" [metadata] content-hash = "e5c540dccfd2912ee3a397f3fdce2ed537273be220eecff046af58fd12c65d66" @@ -1203,7 +1203,7 @@ six = [ {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.12.tar.gz", hash = "sha256:bfb8f464a5000b567ac1d350b9090cf081180ec1ab4aa87e7bca12dab25320ec"}, + {file = "SQLAlchemy-1.3.13.tar.gz", hash = "sha256:64a7b71846db6423807e96820993fa12a03b89127d278290ca25c0b11ed7b4fb"}, ] starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, @@ -1238,8 +1238,8 @@ unpaddedbase64 = [ {file = "unpaddedbase64-1.1.0-py2.py3-none-any.whl", hash = "sha256:81cb4eaaa28cc6a282dd3f2c3855eaa1fbaafa736b5ee64df69889e20540a339"}, ] urllib3 = [ - {file = "urllib3-1.25.7-py2.py3-none-any.whl", hash = "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293"}, - {file = "urllib3-1.25.7.tar.gz", hash = "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"}, + {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, + {file = "urllib3-1.25.8.tar.gz", hash = "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"}, ] uvicorn = [ {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, @@ -1304,6 +1304,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.1.15-py2.py3-none-any.whl", hash = "sha256:28630dfa91ba5e74676cbc76cfc91cd820e6dacca6ca175e07e49df73607bf46"}, - {file = "youtube_dl-2020.1.15.tar.gz", hash = "sha256:74e341f05e23e1650f57a01a58346cfabe3c841ccb9852c859ed2a383655db2a"}, + {file = "youtube_dl-2020.1.24-py2.py3-none-any.whl", hash = "sha256:3ba838c943744cd4f1669f74328b9c0f7814145b92dfcf59c3278caf8175886f"}, + {file = "youtube_dl-2020.1.24.tar.gz", hash = "sha256:82189f971fbe3f4b2e66a9aba7fb5bdd1b4b8c0876d7cd55382045f5555a5e44"}, ] From 930faed273e544fcd90453fa404319932cf0396d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 30 Jan 2020 00:27:27 +0100 Subject: [PATCH 045/227] smol update --- poetry.lock | 93 +++++++++++++----------------- pyproject.toml | 4 +- royalpack/commands/eat.py | 1 + royalpack/events/discord_summon.py | 6 ++ royalpack/version.py | 2 +- 5 files changed, 51 insertions(+), 55 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1132deb6..46606ef5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4,13 +4,13 @@ description = "Async http client/server framework (asyncio)" name = "aiohttp" optional = false python-versions = ">=3.5.3" -version = "3.5.4" +version = "3.6.2" [package.dependencies] async-timeout = ">=3.0,<4.0" attrs = ">=17.3.0" chardet = ">=2.0,<4.0" -multidict = ">=4.0,<5.0" +multidict = ">=4.5,<5.0" yarl = ">=1.0,<2.0" [package.extras] @@ -130,6 +130,22 @@ pytz = "*" regex = "*" tzlocal = "*" +[[package]] +category = "main" +description = "A python wrapper for the Discord API" +name = "discord.py" +optional = false +python-versions = ">=3.5.3" +version = "1.3.1" + +[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.0)", "sphinxcontrib-websupport"] +voice = ["PyNaCl (1.3.0)"] + [[package]] category = "main" description = "Python bindings for FFmpeg - with complex filtering support" @@ -490,7 +506,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.3.1" +version = "5.3.2" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -500,6 +516,10 @@ toml = ">=0.10.0,<0.11.0" optional = true version = ">=10.0,<11.0" +[package.dependencies."discord.py"] +optional = true +version = ">=1.3.1,<2.0.0" + [package.dependencies.ffmpeg_python] optional = true version = ">=0.2.0,<0.3.0" @@ -536,10 +556,6 @@ version = ">=1.3.10,<2.0.0" optional = true version = ">=0.12.13,<0.13.0" -[package.dependencies.temp_discordpy_without_websockets_requirement] -optional = true -version = "0.1" - [package.dependencies.uvicorn] optional = true version = ">=0.10.7,<0.11.0" @@ -558,7 +574,7 @@ alchemy_hard = ["sqlalchemy (>=1.3.10,<2.0.0)", "psycopg2 (>=2.8.4,<3.0.0)"] bard = ["ffmpeg_python (>=0.2.0,<0.3.0)", "youtube-dl"] 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 = ["temp_discordpy_without_websockets_requirement (0.1)", "pynacl (>=1.3.0,<2.0.0)"] +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)"] @@ -654,22 +670,6 @@ requests = ">=2.9.1" six = ">=1.10" vdf = ">=2.0" -[[package]] -category = "main" -description = "A python wrapper for the Discord API" -name = "temp-discordpy-without-websockets-requirement" -optional = false -python-versions = ">=3.5.3" -version = "0.1" - -[package.dependencies] -aiohttp = ">=3.3.0,<3.6.0" -websockets = ">=8.0" - -[package.extras] -docs = ["sphinx (1.8.5)", "sphinxcontrib-trio (1.1.0)", "sphinxcontrib-websupport"] -voice = ["PyNaCl (1.3.0)"] - [[package]] category = "main" description = "Python Library for Tom's Obvious, Minimal Language" @@ -784,28 +784,18 @@ content-hash = "e5c540dccfd2912ee3a397f3fdce2ed537273be220eecff046af58fd12c65d66 [metadata.files] aiohttp = [ - {file = "aiohttp-3.5.4-cp35-cp35m-macosx_10_10_x86_64.whl", hash = "sha256:199f1d106e2b44b6dacdf6f9245493c7d716b01d0b7fbe1959318ba4dc64d1f5"}, - {file = "aiohttp-3.5.4-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:0155af66de8c21b8dba4992aaeeabf55503caefae00067a3b1139f86d0ec50ed"}, - {file = "aiohttp-3.5.4-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:cc619d974c8c11fe84527e4b5e1c07238799a8c29ea1c1285149170524ba9303"}, - {file = "aiohttp-3.5.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:09654a9eca62d1bd6d64aa44db2498f60a5c1e0ac4750953fdd79d5c88955e10"}, - {file = "aiohttp-3.5.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:629102a193162e37102c50713e2e31dc9a2fe7ac5e481da83e5bb3c0cee700aa"}, - {file = "aiohttp-3.5.4-cp35-cp35m-win32.whl", hash = "sha256:acc89b29b5f4e2332d65cd1b7d10c609a75b88ef8925d487a611ca788432dfa4"}, - {file = "aiohttp-3.5.4-cp35-cp35m-win_amd64.whl", hash = "sha256:a25237abf327530d9561ef751eef9511ab56fd9431023ca6f4803f1994104d72"}, - {file = "aiohttp-3.5.4-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:87331d1d6810214085a50749160196391a712a13336cd02ce1c3ea3d05bcf8d5"}, - {file = "aiohttp-3.5.4-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:a5cbd7157b0e383738b8e29d6e556fde8726823dae0e348952a61742b21aeb12"}, - {file = "aiohttp-3.5.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:9cddaff94c0135ee627213ac6ca6d05724bfe6e7a356e5e09ec57bd3249510f6"}, - {file = "aiohttp-3.5.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:d4392defd4648badaa42b3e101080ae3313e8f4787cb517efd3f5b8157eaefd6"}, - {file = "aiohttp-3.5.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c2bec436a2b5dafe5eaeb297c03711074d46b6eb236d002c13c42f25c4a8ce9d"}, - {file = "aiohttp-3.5.4-cp36-cp36m-win32.whl", hash = "sha256:296f30dedc9f4b9e7a301e5cc963012264112d78a1d3094cd83ef148fdf33ca1"}, - {file = "aiohttp-3.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:9a02a04bbe581c8605ac423ba3a74999ec9d8bce7ae37977a3d38680f5780b6d"}, - {file = "aiohttp-3.5.4-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:b05bd85cc99b06740aad3629c2585bda7b83bd86e080b44ba47faf905fdf1300"}, - {file = "aiohttp-3.5.4-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:40d7ea570b88db017c51392349cf99b7aefaaddd19d2c78368aeb0bddde9d390"}, - {file = "aiohttp-3.5.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a97a516e02b726e089cffcde2eea0d3258450389bbac48cbe89e0f0b6e7b0366"}, - {file = "aiohttp-3.5.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e1c3c582ee11af7f63a34a46f0448fca58e59889396ffdae1f482085061a2889"}, - {file = "aiohttp-3.5.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:00d198585474299c9c3b4f1d5de1a576cc230d562abc5e4a0e81d71a20a6ca55"}, - {file = "aiohttp-3.5.4-cp37-cp37m-win32.whl", hash = "sha256:6d5ec9b8948c3d957e75ea14d41e9330e1ac3fed24ec53766c780f82805140dc"}, - {file = "aiohttp-3.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:368ed312550bd663ce84dc4b032a962fcb3c7cae099dbbd48663afc305e3b939"}, - {file = "aiohttp-3.5.4.tar.gz", hash = "sha256:9c4c83f4fa1938377da32bc2d59379025ceeee8e24b89f72fcbccd8ca22dc9bf"}, + {file = "aiohttp-3.6.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e"}, + {file = "aiohttp-3.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec"}, + {file = "aiohttp-3.6.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48"}, + {file = "aiohttp-3.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59"}, + {file = "aiohttp-3.6.2-cp36-cp36m-win32.whl", hash = "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a"}, + {file = "aiohttp-3.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17"}, + {file = "aiohttp-3.6.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a"}, + {file = "aiohttp-3.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd"}, + {file = "aiohttp-3.6.2-cp37-cp37m-win32.whl", hash = "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"}, + {file = "aiohttp-3.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654"}, + {file = "aiohttp-3.6.2-py3-none-any.whl", hash = "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4"}, + {file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"}, ] async-timeout = [ {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, @@ -897,6 +887,9 @@ dateparser = [ {file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"}, {file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"}, ] +"discord.py" = [ + {file = "discord.py-1.3.1-py3-none-any.whl", hash = "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360"}, +] 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"}, @@ -1188,8 +1181,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.3.1-py3-none-any.whl", hash = "sha256:5473524e906fefb90f54af5ce62a0685fcea7766e8971792bd0bf740d558e5a5"}, - {file = "royalnet-5.3.1.tar.gz", hash = "sha256:ced549977490bc92864d220ed3c277f8425f4201f181fe2913bcdd85f58a7f36"}, + {file = "royalnet-5.3.2-py3-none-any.whl", hash = "sha256:760814233a47c87c22d26d41d8f6a6a2dbd1f05663e1e924c5349f93838208de"}, + {file = "royalnet-5.3.2.tar.gz", hash = "sha256:0d35f21748a11229b7762b7e21c29f19da3ea2fa88672c19a1e17862b1597c5e"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1211,10 +1204,6 @@ starlette = [ steam = [ {file = "steam-0.9.1.tar.gz", hash = "sha256:167240080ea23e346c11face96a6e9acc2827978c46c5ae25fa74e38031ff978"}, ] -temp-discordpy-without-websockets-requirement = [ - {file = "temp_discordpy_without_websockets_requirement-0.1-py3-none-any.whl", hash = "sha256:361ddcc6fb2ec469706fde56c46a3e14f02671cf0e27204ef6c3c4d89c7227ab"}, - {file = "temp_discordpy_without_websockets_requirement-0.1.tar.gz", hash = "sha256:7db02603cde084c7d579d872389f60ffd3f34197d885e4ca722a92bc302cb33c"}, -] toml = [ {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, diff --git a/pyproject.toml b/pyproject.toml index a5a80b75..54bb489e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.3.3" + version = "5.3.4" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.3.1" + version = "^5.3.2" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 071f8df9..6259a497 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -158,6 +158,7 @@ class EatCommand(Command): "mia sul fiume": "💧 Hai mangiato il miglior piatto al mondo, la {food}, esclusivo ai membri Royal Games.\n" "[i]Nessuno, tranne il bot, sa di cosa è fatta esattamente, ma una cosa è certa: è " "buonissima![/i]", + "angelo": "👼 Oh mio dio! E' un {food}!\n[i]Ora hai un digramma ad onda blu.[/i]" } async def run(self, args: CommandArgs, data: CommandData) -> None: diff --git a/royalpack/events/discord_summon.py b/royalpack/events/discord_summon.py index 4f74f69d..1066d1b5 100644 --- a/royalpack/events/discord_summon.py +++ b/royalpack/events/discord_summon.py @@ -60,6 +60,12 @@ class DiscordSummonEvent(Event): # Connect to the channel try: await vp.connect(channel) + except OpusNotLoadedError: + raise ConfigurationError("libopus non è disponibile sul sistema in cui sta venendo eseguito questo bot," + " pertanto non è possibile con") + except DiscordTimeoutError: + raise ExternalError("Timeout durante la connessione al canale." + " Forse il bot non ha i permessi per entrarci?") except GuildAlreadyConnectedError: raise UserError("Il bot è già connesso in un canale vocale nel Server!\n" "Spostalo manualmente, o disconnettilo e riinvoca [c]summon[/c]!") diff --git a/royalpack/version.py b/royalpack/version.py index ff6c1d6b..71c01004 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.3.3" +semantic = "5.3.4" From a9217efa75cf8cba4dd66d7e77c5b57dcae72cb7 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 30 Jan 2020 00:29:38 +0100 Subject: [PATCH 046/227] smol update --- poetry.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 46606ef5..90e89fc4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -779,7 +779,7 @@ python-versions = "*" version = "2020.1.24" [metadata] -content-hash = "e5c540dccfd2912ee3a397f3fdce2ed537273be220eecff046af58fd12c65d66" +content-hash = "42c6027b2f63431368e45a56c73fb12bf5283dfd4c41bf3cb1862ef54d4f67ea" python-versions = "^3.8" [metadata.files] From c450d5e283d7d78fe9bebc8b6840aa419ee1dde3 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 30 Jan 2020 20:08:31 +0100 Subject: [PATCH 047/227] Improve play command (5.3.5) --- poetry.lock | 91 ++++++++++++++++++++++++++++++-- pyproject.toml | 4 +- royalpack/commands/funkwhale.py | 3 ++ royalpack/commands/play.py | 33 +++++++----- royalpack/events/discord_play.py | 10 ++-- royalpack/version.py | 2 +- 6 files changed, 116 insertions(+), 27 deletions(-) diff --git a/poetry.lock b/poetry.lock index 90e89fc4..d7686b77 100644 --- a/poetry.lock +++ b/poetry.lock @@ -130,6 +130,17 @@ pytz = "*" regex = "*" tzlocal = "*" +[[package]] +category = "main" +description = "A library to handle automated deprecations" +name = "deprecation" +optional = false +python-versions = "*" +version = "2.0.7" + +[package.dependencies] +packaging = "*" + [[package]] category = "main" description = "A python wrapper for the Discord API" @@ -146,6 +157,23 @@ websockets = ">=6.0,<7.0 || >7.0,<8.0 || >8.0,<8.0.1 || >8.0.1,<9.0" docs = ["sphinx (1.8.5)", "sphinxcontrib-trio (1.1.0)", "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" + +[package.dependencies] +deprecation = "*" +filetype = "*" + +[package.extras] +art-plugin = ["pylast", "requests", "pillow"] +display-plugin = ["grako"] +yaml-plugin = ["ruamel.yaml"] + [[package]] category = "main" description = "Python bindings for FFmpeg - with complex filtering support" @@ -160,6 +188,14 @@ 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.5" + [[package]] category = "main" description = "Clean single-source support for Python 3 and 2" @@ -340,6 +376,18 @@ optional = false python-versions = ">=3.5" version = "4.7.4" +[[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.1" + +[package.dependencies] +pyparsing = ">=2.0.2" +six = "*" + [[package]] category = "main" description = "Protocol Buffers" @@ -392,6 +440,14 @@ six = "*" 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.6" + [[package]] category = "main" description = "A python implmementation of GNU readline." @@ -506,7 +562,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.3.2" +version = "5.3.4" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -520,6 +576,10 @@ version = ">=10.0,<11.0" 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" @@ -571,7 +631,7 @@ version = "*" [package.extras] alchemy_easy = ["sqlalchemy (>=1.3.10,<2.0.0)", "psycopg2_binary (>=2.8.4,<3.0.0)"] alchemy_hard = ["sqlalchemy (>=1.3.10,<2.0.0)", "psycopg2 (>=2.8.4,<3.0.0)"] -bard = ["ffmpeg_python (>=0.2.0,<0.3.0)", "youtube-dl"] +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)"] @@ -779,7 +839,7 @@ python-versions = "*" version = "2020.1.24" [metadata] -content-hash = "42c6027b2f63431368e45a56c73fb12bf5283dfd4c41bf3cb1862ef54d4f67ea" +content-hash = "a2861f9b2781d6d02936f4dce63792690d7757812ac6a4f42fd7cc2932435e6f" python-versions = "^3.8" [metadata.files] @@ -887,13 +947,26 @@ dateparser = [ {file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"}, {file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"}, ] +deprecation = [ + {file = "deprecation-2.0.7-py2.py3-none-any.whl", hash = "sha256:dc9b4f252b7aca8165ce2764a71da92a653b5ffbf7a389461d7a640f6536ecb2"}, + {file = "deprecation-2.0.7.tar.gz", hash = "sha256:c0392f676a6146f0238db5744d73e786a43510d54033f80994ef2f4c9df192ed"}, +] "discord.py" = [ {file = "discord.py-1.3.1-py3-none-any.whl", hash = "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360"}, ] +eyed3 = [ + {file = "eyeD3-0.9-py2.py3-none-any.whl", hash = "sha256:6015669333df2115809102ccf1b29585115b5c233cf4530d9f995ad562634819"}, + {file = "eyeD3-0.9-py3.8.egg", hash = "sha256:8e3a7a2ce2932260f77c6234d624737807cdb4404f5bac3c5348c1f9da3d7250"}, + {file = "eyeD3-0.9.tar.gz", hash = "sha256:8874762fd4fd93fa64676185ccaa77ea8b3396aea65ba86bca7325f1136f9c8a"}, +] 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.5-py2.py3-none-any.whl", hash = "sha256:4967124d982a71700d94a08c49c4926423500e79382a92070f5ab248d44fe461"}, + {file = "filetype-1.0.5.tar.gz", hash = "sha256:17a3b885f19034da29640b083d767e0f13c2dcb5dcc267945c8b6e5a5a9013c7"}, +] future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] @@ -1011,6 +1084,10 @@ multidict = [ {file = "multidict-4.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb"}, {file = "multidict-4.7.4.tar.gz", hash = "sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4"}, ] +packaging = [ + {file = "packaging-20.1-py2.py3-none-any.whl", hash = "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73"}, + {file = "packaging-20.1.tar.gz", hash = "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334"}, +] protobuf = [ {file = "protobuf-3.11.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3f509f7e50d806a434fe4a5fbf602516002a0f092889209fff7db82060efffc0"}, {file = "protobuf-3.11.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4571da974019849201fc1ec6626b9cea54bd11b6bed140f8f737c0a33ea37de5"}, @@ -1126,6 +1203,10 @@ pynacl = [ {file = "PyNaCl-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:bf459128feb543cfca16a95f8da31e2e65e4c5257d2f3dfa8c0c1031139c9c92"}, {file = "PyNaCl-1.3.0.tar.gz", hash = "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c"}, ] +pyparsing = [ + {file = "pyparsing-2.4.6-py2.py3-none-any.whl", hash = "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"}, + {file = "pyparsing-2.4.6.tar.gz", hash = "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f"}, +] pyreadline = [ {file = "pyreadline-2.1.win-amd64.exe", hash = "sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"}, {file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"}, @@ -1181,8 +1262,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.3.2-py3-none-any.whl", hash = "sha256:760814233a47c87c22d26d41d8f6a6a2dbd1f05663e1e924c5349f93838208de"}, - {file = "royalnet-5.3.2.tar.gz", hash = "sha256:0d35f21748a11229b7762b7e21c29f19da3ea2fa88672c19a1e17862b1597c5e"}, + {file = "royalnet-5.3.4-py3-none-any.whl", hash = "sha256:25994b002d2883a91b1a885fb08419499873f67d482ea19f564051e296eb4e31"}, + {file = "royalnet-5.3.4.tar.gz", hash = "sha256:75800c9da52750dcd2d49e45bf527e92212b272d81467a63c9a375dadf24e11d"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 54bb489e..c71a9560 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.3.4" + version = "5.3.5" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.3.2" + version = "^5.3.4" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index f8c261a9..1c0507b1 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -13,6 +13,9 @@ class FunkwhaleCommand(PlayCommand): syntax = "{ricerca}" + def get_embed_color(self): + return 0x009FE3 + async def get_url(self, args): search = urllib.parse.quote(args.joined(require_at_least=1)) async with aiohttp.ClientSession() as session: diff --git a/royalpack/commands/play.py b/royalpack/commands/play.py index b12058d8..886bca37 100644 --- a/royalpack/commands/play.py +++ b/royalpack/commands/play.py @@ -1,9 +1,7 @@ -import pickle -import base64 import discord +import asyncio as aio from typing import * from royalnet.commands import * -from royalnet.utils import * from royalnet.backpack.tables import User, Discord @@ -17,14 +15,16 @@ class PlayCommand(Command): syntax = "{url}" async def get_url(self, args: CommandArgs): - return args.joined(require_at_least=1) + url = args.joined(require_at_least=1) + if not (url.startswith("http://") or url.startswith("https://")): + raise InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" + f" ([c]http://[/c] o [c]https://[/c]).") + return url + + def get_embed_color(self) -> Optional[int]: + return None async def run(self, args: CommandArgs, data: CommandData) -> None: - # if not (url.startswith("http://") or url.startswith("https://")): - # raise CommandError(f"Il comando [c]{self.interface.prefix}play[/c] funziona solo per riprodurre file da" - # f" un URL.\n" - # f"Se vuoi cercare un video, come misura temporanea puoi usare " - # f"[c]ytsearch:nomevideo[/c] o [c]scsearch:nomevideo[/c] come url.") if self.interface.name == "discord": message: discord.Message = data.message guild: discord.Guild = message.guild @@ -46,9 +46,14 @@ class PlayCommand(Command): else: user_str = str(f"<@{user_discord.discord_id}>") - self.loop.create_task(self.interface.call_herald_event("discord", "discord_play", - url=await self.get_url(args), - guild_id=guild_id, - user=user_str)) + play_task: aio.Task = self.loop.create_task( + self.interface.call_herald_event("discord", "discord_play", + url=await self.get_url(args), + guild_id=guild_id, + user=user_str, + force_color=self.get_embed_color()) + ) - # await data.reply("✅ Richiesta di riproduzione inviata!") + await data.reply("⌛ Attendi un attimo...") + + await play_task diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index aaa5e380..a2f444bd 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -17,6 +17,7 @@ class DiscordPlayEvent(Event): url: str, guild_id: Optional[int] = None, user: Optional[str] = None, + force_color: Optional[int] = None, **kwargs) -> dict: if not isinstance(self.serf, DiscordSerf): raise UnsupportedError() @@ -70,7 +71,10 @@ class DiscordPlayEvent(Event): await main_channel.send(escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" f" coda:")) for ytd in added: - await main_channel.send(embed=ytd.embed()) + embed: discord.Embed = ytd.embed() + if force_color: + embed._colour = discord.Colour(force_color) + await main_channel.send(embed=embed) if len(too_long) > 0: if user: @@ -87,12 +91,8 @@ class DiscordPlayEvent(Event): return { "added": [{ "title": ytd.info.title, - "stringified_base64_pickled_discord_embed": str(base64.b64encode(pickle.dumps(ytd.embed())), - encoding="ascii") } for ytd in added], "too_long": [{ "title": ytd.info.title, - "stringified_base64_pickled_discord_embed": str(base64.b64encode(pickle.dumps(ytd.embed())), - encoding="ascii") } for ytd in too_long] } diff --git a/royalpack/version.py b/royalpack/version.py index 71c01004..d2947091 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.3.4" +semantic = "5.3.5" From ea847631ac010dc0d5724e38311e4a3abb69acc6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 31 Jan 2020 01:47:44 +0100 Subject: [PATCH 048/227] Improve fiorygi (5.3.6) --- pyproject.toml | 2 +- royalpack/commands/__init__.py | 2 + royalpack/commands/magickfiorygi.py | 66 +++++++++++++++++++++++++ royalpack/tables/__init__.py | 2 + royalpack/tables/fiorygi.py | 2 +- royalpack/tables/fiorygitransactions.py | 30 +++++++++++ royalpack/version.py | 2 +- 7 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 royalpack/commands/magickfiorygi.py create mode 100644 royalpack/tables/fiorygitransactions.py diff --git a/pyproject.toml b/pyproject.toml index c71a9560..0ef12dfe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.3.5" + version = "5.3.6" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 6826c821..85ca8b39 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -34,6 +34,7 @@ from .trivia import TriviaCommand from .steampowered import SteampoweredCommand from .steammatch import SteammatchCommand from .dota import DotaCommand +from .magickfiorygi import MagickfiorygiCommand # Enter the commands of your Pack here! available_commands = [ @@ -72,6 +73,7 @@ available_commands = [ SteampoweredCommand, SteammatchCommand, DotaCommand, + MagickfiorygiCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py new file mode 100644 index 00000000..f63e8d1c --- /dev/null +++ b/royalpack/commands/magickfiorygi.py @@ -0,0 +1,66 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import royalnet.serf.telegram as rt +from ..tables import Alias, Fiorygi, FiorygiTransaction + + +class MagickfiorygiCommand(rc.Command): + name: str = "magickfiorygi" + + description: str = "Crea fiorygi dal nulla." + + syntax: str = "{destinatario} {quantità} {motivo}" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + author = await data.get_author(error_if_none=True) + if author.role != "Admin": + raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") + + user_arg = args[0] + qty_arg = args[1] + reason_arg = " ".join(args[2:]) + + if user_arg is None: + raise rc.InvalidInputError("Non hai specificato un destinatario!") + user = Alias.find_by_alias(self.alchemy, data.session, user_arg) + if user is None: + raise rc.InvalidInputError("L'utente specificato non esiste!") + + if qty_arg is None: + raise rc.InvalidInputError("Non hai specificato una quantità!") + try: + qty = int(qty_arg) + except ValueError: + raise rc.InvalidInputError("La quantità specificata non è un numero!") + if qty == 0: + raise rc.InvalidInputError("La quantità non può essere 0!") + + if reason_arg == "": + raise rc.InvalidInputError("Non hai specificato un motivo!") + + transaction = self.alchemy.get(FiorygiTransaction)( + user_id=user.uid, + change=qty, + reason=reason_arg + ) + data.session.add(transaction) + 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 qty > 0: + msg = f"💰 [b]{user_str}[/b] ha ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''} per [i]{reason_arg}[/i]!" + else: + msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason_arg}[/i]." + + client = self.serf.client + await self.serf.api_call(client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=rt.escape(msg), + parse_mode="HTML", + disable_webpage_preview=True) diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index f6a90b78..2e5a1eba 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -12,6 +12,7 @@ from .leagueoflegends import LeagueOfLegends from .fiorygi import Fiorygi from .steam import Steam from .dota import Dota +from .fiorygitransactions import FiorygiTransaction # Enter the tables of your Pack here! available_tables = [ @@ -28,6 +29,7 @@ available_tables = [ Fiorygi, Steam, Dota, + FiorygiTransaction, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/fiorygi.py b/royalpack/tables/fiorygi.py index 65392d2f..81120b9d 100644 --- a/royalpack/tables/fiorygi.py +++ b/royalpack/tables/fiorygi.py @@ -19,7 +19,7 @@ class Fiorygi: return Column(Integer, nullable=False, default=0) def __repr__(self): - return f"" + return f"<{self.__class__.__name__} di {self.user}: {self.fiorygi}>" def __str__(self): return f"{self.fiorygi} fioryg" + ("i" if self.fiorygi != 1 else "") diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py new file mode 100644 index 00000000..75701d0d --- /dev/null +++ b/royalpack/tables/fiorygitransactions.py @@ -0,0 +1,30 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr + + +class FiorygiTransaction: + __tablename__ = "fiorygitransactions" + + @declared_attr + def id(self): + return Column(Integer, primary_key=True) + + @declared_attr + def change(self): + return Column(Integer, nullable=False) + + @declared_attr + def user_id(self): + return Column(Integer, ForeignKey("fiorygi.user_id"), nullable=False) + + @declared_attr + def user(self): + return relationship("Fiorygi", backref=backref("transactions")) + + @declared_attr + def reason(self): + return Column(String, nullable=False, default="") + + def __repr__(self): + return f"<{self.__class__.__name__}: {self.change:+} to {self.user.username} for {self.reason}>" diff --git a/royalpack/version.py b/royalpack/version.py index d2947091..d4ff852a 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.3.5" +semantic = "5.3.6" From f33fb74e6d1c9d2f093a32c1e765ab44b525e7d2 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 3 Feb 2020 17:22:44 +0100 Subject: [PATCH 049/227] Support Royalnet 5.4 --- royalpack/events/discord_play.py | 43 ++++++++++++++++---------------- royalpack/utils/royalqueue.py | 2 +- royalpack/version.py | 2 +- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index a2f444bd..9af8e8a7 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -1,16 +1,15 @@ -import discord -import pickle -import base64 import datetime from typing import * -from royalnet.commands import * -from royalnet.serf.discord import * -from royalnet.bard import * -from royalnet.backpack.tables.users import User + +import discord +import royalnet.commands as rc +import royalnet.serf.discord as rsd +import royalnet.bard.discord as rbd + from ..utils import RoyalQueue -class DiscordPlayEvent(Event): +class DiscordPlayEvent(rc.Event): name = "discord_play" async def run(self, @@ -19,16 +18,16 @@ class DiscordPlayEvent(Event): user: Optional[str] = None, force_color: Optional[int] = None, **kwargs) -> dict: - if not isinstance(self.serf, DiscordSerf): - raise UnsupportedError() + if not isinstance(self.serf, rsd.DiscordSerf): + raise rc.UnsupportedError() - serf: DiscordSerf = self.serf + serf: rsd.DiscordSerf = self.serf client: discord.Client = self.serf.client # TODO: fix this in Royalnet sometime - candidate_players: List[VoicePlayer] = [] + candidate_players: List[rsd.VoicePlayer] = [] for player in serf.voice_players: - player: VoicePlayer + player: rsd.VoicePlayer if not player.voice_client.is_connected(): continue if guild_id is not None: @@ -38,17 +37,17 @@ class DiscordPlayEvent(Event): candidate_players.append(player) if len(candidate_players) == 0: - raise UserError("Il bot non è in nessun canale vocale.\n" + raise rc.UserError("Il bot non è in nessun canale vocale.\n" "Evocalo prima con [c]summon[/c]!") elif len(candidate_players) == 1: voice_player = candidate_players[0] else: - raise CommandError("Non so in che Server riprodurre questo file...\n" + raise rc.CommandError("Non so in che Server riprodurre questo file...\n" "Invia il comando su Discord, per favore!") - ytds = await YtdlDiscord.from_url(url) - added: List[YtdlDiscord] = [] - too_long: List[YtdlDiscord] = [] + ytds = await rbd.YtdlDiscord.from_url(url) + added: List[rbd.YtdlDiscord] = [] + too_long: List[rbd.YtdlDiscord] = [] if isinstance(voice_player.playing, RoyalQueue): for index, ytd in enumerate(ytds): if ytd.info.duration >= datetime.timedelta(seconds=self.config["Play"]["max_song_duration"]): @@ -60,15 +59,15 @@ class DiscordPlayEvent(Event): if not voice_player.voice_client.is_playing(): await voice_player.start() else: - raise CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") + raise rc.CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") main_channel: discord.TextChannel = client.get_channel(self.config["Discord"]["main_channel_id"]) if len(added) > 0: if user: - await main_channel.send(escape(f"▶️ {user} ha aggiunto {len(added)} file alla coda:")) + await main_channel.send(rsd.escape(f"▶️ {user} ha aggiunto {len(added)} file alla coda:")) else: - await main_channel.send(escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" + await main_channel.send(rsd.escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" f" coda:")) for ytd in added: embed: discord.Embed = ytd.embed() @@ -78,7 +77,7 @@ class DiscordPlayEvent(Event): if len(too_long) > 0: if user: - await main_channel.send(escape( + await main_channel.send(rsd.escape( f"⚠ {len(too_long)} file non {'è' if len(too_long) == 1 else 'sono'}" f" stat{'o' if len(too_long) == 1 else 'i'} scaricat{'o' if len(too_long) == 1 else 'i'}" f" perchè durava{'' if len(too_long) == 1 else 'no'}" diff --git a/royalpack/utils/royalqueue.py b/royalpack/utils/royalqueue.py index a70aa04a..373c7c37 100644 --- a/royalpack/utils/royalqueue.py +++ b/royalpack/utils/royalqueue.py @@ -1,6 +1,6 @@ import logging from typing import Optional, List, AsyncGenerator, Tuple, Any, Dict -from royalnet.bard import YtdlDiscord +from royalnet.bard.discord import YtdlDiscord from royalnet.serf.discord import Playable import discord diff --git a/royalpack/version.py b/royalpack/version.py index d4ff852a..03217183 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.3.6" +semantic = "5.4" From c4221e4137bae9841a51fb0b150b88baebb19944 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 4 Feb 2020 00:54:39 +0100 Subject: [PATCH 050/227] Fix the bot not playing music --- poetry.lock | 112 ++++++++++++++-------------- pyproject.toml | 4 +- royalpack/commands/magickfiorygi.py | 3 +- royalpack/commands/steammatch.py | 3 +- royalpack/commands/userinfo.py | 3 +- royalpack/events/discord_play.py | 4 +- royalpack/tables/__init__.py | 2 - royalpack/tables/aliases.py | 35 --------- royalpack/utils/royalqueue.py | 1 + royalpack/version.py | 2 +- 10 files changed, 66 insertions(+), 103 deletions(-) delete mode 100644 royalpack/tables/aliases.py diff --git a/poetry.lock b/poetry.lock index d7686b77..780de232 100644 --- a/poetry.lock +++ b/poetry.lock @@ -394,7 +394,7 @@ description = "Protocol Buffers" name = "protobuf" optional = false python-versions = "*" -version = "3.11.2" +version = "3.11.3" [package.dependencies] setuptools = "*" @@ -422,7 +422,7 @@ description = "Cryptographic library for Python" name = "pycryptodome" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.4" +version = "3.9.6" [[package]] category = "main" @@ -562,7 +562,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.3.4" +version = "5.4.1" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -839,7 +839,7 @@ python-versions = "*" version = "2020.1.24" [metadata] -content-hash = "a2861f9b2781d6d02936f4dce63792690d7757812ac6a4f42fd7cc2932435e6f" +content-hash = "d183e0b748d04946c8c44929a4515ac5ac2a8a9916928cd9a604e97128bd2d08" python-versions = "^3.8" [metadata.files] @@ -1089,25 +1089,25 @@ packaging = [ {file = "packaging-20.1.tar.gz", hash = "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334"}, ] protobuf = [ - {file = "protobuf-3.11.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3f509f7e50d806a434fe4a5fbf602516002a0f092889209fff7db82060efffc0"}, - {file = "protobuf-3.11.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4571da974019849201fc1ec6626b9cea54bd11b6bed140f8f737c0a33ea37de5"}, - {file = "protobuf-3.11.2-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:0329e86a397db2a83f9dcbe21d9be55a47f963cdabc893c3a24f4d3a8f117c37"}, - {file = "protobuf-3.11.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:56bd1d84fbf4505c7b73f04de987eef5682e5752c811141b0186a3809bfb396f"}, - {file = "protobuf-3.11.2-cp35-cp35m-win32.whl", hash = "sha256:919f0d6f6addc836d08658eba3b52be2e92fd3e76da3ce00c325d8e9826d17c7"}, - {file = "protobuf-3.11.2-cp35-cp35m-win_amd64.whl", hash = "sha256:14d6ac53df9cb5bb87c4f91b677c1bc5cec9c0fd44327f367a3c9562de2877c4"}, - {file = "protobuf-3.11.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6e96dffaf4d0a9a329e528b353ba62fd9ef13599688723d96bc9c165d0b6871e"}, - {file = "protobuf-3.11.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6b5b947dc8b3f2aec0eaad65b0b5113fcd642c358c31357c647da6281ee31104"}, - {file = "protobuf-3.11.2-cp36-cp36m-win32.whl", hash = "sha256:680c668d00b5eff08b86aef9e5ba9a705e621ea05d39071cfea8e28cb2400946"}, - {file = "protobuf-3.11.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9c7b19c30cf0644afd0e4218b13f637ce54382fdcb1c8f75bf3e84e49a5f6d0a"}, - {file = "protobuf-3.11.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d61b14a9090da77fe87e38ba4c6c43d3533dcbeb5d84f5474e7ac63c532dcc9c"}, - {file = "protobuf-3.11.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a2e6f57114933882ec701807f217df2fb4588d47f71f227c0a163446b930d507"}, - {file = "protobuf-3.11.2-cp37-cp37m-win32.whl", hash = "sha256:0a7219254afec0d488211f3d482d8ed57e80ae735394e584a98d8f30a8c88a36"}, - {file = "protobuf-3.11.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a6b970a2eccfcbabe1acf230fbf112face1c4700036c95e195f3554d7bcb04c1"}, - {file = "protobuf-3.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d6faf5dbefb593e127463f58076b62fcfe0784187be8fe1aa9167388f24a22a1"}, - {file = "protobuf-3.11.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bc45641cbcdea068b67438244c926f9fd3e5cbdd824448a4a64370610df7c593"}, - {file = "protobuf-3.11.2-py2.7.egg", hash = "sha256:557686c43fbd04f5f7c533f00feee9a37dcca7b5896e3ae3664a33864e6dd546"}, - {file = "protobuf-3.11.2-py2.py3-none-any.whl", hash = "sha256:180fc364b42907a1d2afa183ccbeffafe659378c236b1ec3daca524950bb918d"}, - {file = "protobuf-3.11.2.tar.gz", hash = "sha256:3d7a7d8d20b4e7a8f63f62de2d192cfd8b7a53c56caba7ece95367ca2b80c574"}, + {file = "protobuf-3.11.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481"}, + {file = "protobuf-3.11.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7"}, + {file = "protobuf-3.11.3-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a"}, + {file = "protobuf-3.11.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961"}, + {file = "protobuf-3.11.3-cp35-cp35m-win32.whl", hash = "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80"}, + {file = "protobuf-3.11.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306"}, + {file = "protobuf-3.11.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a"}, + {file = "protobuf-3.11.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151"}, + {file = "protobuf-3.11.3-cp36-cp36m-win32.whl", hash = "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab"}, + {file = "protobuf-3.11.3-cp36-cp36m-win_amd64.whl", hash = "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956"}, + {file = "protobuf-3.11.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2"}, + {file = "protobuf-3.11.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07"}, + {file = "protobuf-3.11.3-cp37-cp37m-win32.whl", hash = "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a"}, + {file = "protobuf-3.11.3-cp37-cp37m-win_amd64.whl", hash = "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee"}, + {file = "protobuf-3.11.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4"}, + {file = "protobuf-3.11.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0"}, + {file = "protobuf-3.11.3-py2.7.egg", hash = "sha256:2affcaba328c4662f3bc3c0e9576ea107906b2c2b6422344cdad961734ff6b93"}, + {file = "protobuf-3.11.3-py2.py3-none-any.whl", hash = "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f"}, + {file = "protobuf-3.11.3.tar.gz", hash = "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f"}, ] psycopg2-binary = [ {file = "psycopg2-binary-2.8.4.tar.gz", hash = "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed"}, @@ -1147,38 +1147,36 @@ pycparser = [ {file = "pycparser-2.19.tar.gz", hash = "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"}, ] pycryptodome = [ - {file = "pycryptodome-3.9.4-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:6c2720696b10ae356040e888bde1239b8957fe18885ccf5e7b4e8dec882f0856"}, - {file = "pycryptodome-3.9.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:5c485ed6e9718ebcaa81138fa70ace9c563d202b56a8cee119b4085b023931f5"}, - {file = "pycryptodome-3.9.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:56fdd0e425f1b8fd3a00b6d96351f86226674974814c50534864d0124d48871f"}, - {file = "pycryptodome-3.9.4-cp27-cp27m-win32.whl", hash = "sha256:2de33ed0a95855735d5a0fc0c39603314df9e78ee8bbf0baa9692fb46b3b8bbb"}, - {file = "pycryptodome-3.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:eec0689509389f19875f66ae8dedd59f982240cdab31b9f78a8dc266011df93a"}, - {file = "pycryptodome-3.9.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:68fab8455efcbfe87c5d75015476f9b606227ffe244d57bfd66269451706e899"}, - {file = "pycryptodome-3.9.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4b9533d4166ca07abdd49ce9d516666b1df944997fe135d4b21ac376aa624aff"}, - {file = "pycryptodome-3.9.4-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:d3fe3f33ad52bf0c19ee6344b695ba44ffbfa16f3c29ca61116b48d97bd970fb"}, - {file = "pycryptodome-3.9.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:319e568baf86620b419d53063b18c216abf924875966efdfe06891b987196a45"}, - {file = "pycryptodome-3.9.4-cp34-cp34m-win32.whl", hash = "sha256:042ae873baadd0c33b4d699a5c5b976ade3233a979d972f98ca82314632d868c"}, - {file = "pycryptodome-3.9.4-cp34-cp34m-win_amd64.whl", hash = "sha256:a30f501bbb32e01a49ef9e09ca1260e5ab49bf33a257080ec553e08997acc487"}, - {file = "pycryptodome-3.9.4-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:b55c60c321ac91945c60a40ac9896ac7a3d432bb3e8c14006dfd82ad5871c331"}, - {file = "pycryptodome-3.9.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9d9945ac8375d5d8e60bd2a2e1df5882eaa315522eedf3ca868b1546dfa34eba"}, - {file = "pycryptodome-3.9.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:4372ec7518727172e1605c0843cdc5375d4771e447b8148c787b860260aae151"}, - {file = "pycryptodome-3.9.4-cp35-cp35m-win32.whl", hash = "sha256:0502876279772b1384b660ccc91563d04490d562799d8e2e06b411e2d81128a9"}, - {file = "pycryptodome-3.9.4-cp35-cp35m-win_amd64.whl", hash = "sha256:72166c2ac520a5dbd2d90208b9c279161ec0861662a621892bd52fb6ca13ab91"}, - {file = "pycryptodome-3.9.4-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:b4af098f2a50f8d048ab12cabb59456585c0acf43d90ee79782d2d6d0ed59dba"}, - {file = "pycryptodome-3.9.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:8a799bea3c6617736e914a2e77c409f52893d382f619f088f8a80e2e21f573c1"}, - {file = "pycryptodome-3.9.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7c52308ac5b834331b2f107a490b2c27de024a229b61df4cdc5c131d563dfe98"}, - {file = "pycryptodome-3.9.4-cp36-cp36m-win32.whl", hash = "sha256:63c103a22cbe9752f6ea9f1a0de129995bad91c4d03a66c67cffcf6ee0c9f1e1"}, - {file = "pycryptodome-3.9.4-cp36-cp36m-win_amd64.whl", hash = "sha256:54456cf85130e01674d21fb1ab89ffccacb138a8ade88d72fa2b0ac898d2798b"}, - {file = "pycryptodome-3.9.4-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:aec4d42deb836b8fb3ba32f2ba1ef0d33dd3dc9d430b1479ee7a914490d15b5e"}, - {file = "pycryptodome-3.9.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:896e9b6fd0762aa07b203c993fbbee7a1f1a4674c6886afd7bfa86f3d1be98a8"}, - {file = "pycryptodome-3.9.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:57b1b707363490c495ad0eeb38bd1b0e1697c497af25fad78d3a1ebf0477fd5b"}, - {file = "pycryptodome-3.9.4-cp37-cp37m-win32.whl", hash = "sha256:87d8d85b4792ca5e730fb7a519fbc3ed976c59dcf79c5204589c59afd56b9926"}, - {file = "pycryptodome-3.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:e3a79a30d15d9c7c284a7734036ee8abdb5ca3a6f5774d293cdc9e1358c1dc10"}, - {file = "pycryptodome-3.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:48821950ffb9c836858d8fa09d7840b6df52eadd387a3c5acece55cb387743f9"}, - {file = "pycryptodome-3.9.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cbfd97f9e060f0d30245cd29fa267a9a84de9da97559366fca0a3f7655acc63f"}, - {file = "pycryptodome-3.9.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9ef966c727de942de3e41aa8462c4b7b4bca70f19af5a3f99e31376589c11aac"}, - {file = "pycryptodome-3.9.4-cp38-cp38-win32.whl", hash = "sha256:a8ca2450394d3699c9f15ef25e8de9a24b401933716a1e39d37fa01f5fe3c58b"}, - {file = "pycryptodome-3.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:c53348358408d94869059e16fba5ff3bef8c52c25b18421472aba272b9bb450f"}, - {file = "pycryptodome-3.9.4.tar.gz", hash = "sha256:a168e73879619b467072509a223282a02c8047d932a48b74fbd498f27224aa04"}, + {file = "pycryptodome-3.9.6-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:5029c46b0d41dfb763c3981c0af68eab029f06fe2b94f2299112fc18cf9e8d6d"}, + {file = "pycryptodome-3.9.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:95d324e603c5cec5d89e8595236bbf59ade5fe3a72d100ce61eebb323d598750"}, + {file = "pycryptodome-3.9.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2a57daef18a2022a5e4b6f7376c9ddd0c2d946e4b1f1e59b837f5bf295be7380"}, + {file = "pycryptodome-3.9.6-cp27-cp27m-win32.whl", hash = "sha256:a719bd708207fa219fcbf4c8ebbcbc52846045f78179d00445b429fdabdbc1c4"}, + {file = "pycryptodome-3.9.6-cp27-cp27m-win_amd64.whl", hash = "sha256:39e5ca2f66d1eac7abcba5ce1a03370d123dc6085620f1cd532dfee27e650178"}, + {file = "pycryptodome-3.9.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f4d2174e168d0eabd1fffaf88b4f62c2b6f30a67b8816f31024b8e48be3e2d75"}, + {file = "pycryptodome-3.9.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ec7d39589f9cfc2a8b83b1d2fc673441757c99d43283e97b2dd46e0e23730db8"}, + {file = "pycryptodome-3.9.6-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:9163fec630495c10c767991e3f8dab32f4427bfb2dfeaa59bb28fe3e52ba66f2"}, + {file = "pycryptodome-3.9.6-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:0a8d5f2dbb4bbe830ace54286b829bfa529f0853bedaab6225fcb2e6d1f7e356"}, + {file = "pycryptodome-3.9.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5817c0b3c263025d851da96b90cbc7e95348008f88b990e90d10683dba376666"}, + {file = "pycryptodome-3.9.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c41b7e10b72cef00cd63410f31fe50e72dc3a40eafbd146e288384fbe4208064"}, + {file = "pycryptodome-3.9.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f3204006869ab037604b1d9f045c4e84882ddd365e4ee8caa5eb1ff47a59188e"}, + {file = "pycryptodome-3.9.6-cp35-cp35m-win32.whl", hash = "sha256:cdb0ad83a5d6bac986a37fcb7562bcbef0aabae8ea19505bab5cf83c4d18af12"}, + {file = "pycryptodome-3.9.6-cp35-cp35m-win_amd64.whl", hash = "sha256:1259b8ca49662b8a941177357f08147d858595c0042e63ff81e9628e925b5c9d"}, + {file = "pycryptodome-3.9.6-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:09bf05a489fe10f9280a5e0163f195e7b9630cafb15f7d72fb9c8f5eb2afa84f"}, + {file = "pycryptodome-3.9.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:fcff8c9d88d58880f7eda2139c7c444552a38f98a9e77ba5970b6e78f54ac358"}, + {file = "pycryptodome-3.9.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9948c2d5c5c0ee45ed44cee0e2eba2ce60a03be006ed3074521f3da3be162e72"}, + {file = "pycryptodome-3.9.6-cp36-cp36m-win32.whl", hash = "sha256:79320f1fc5c9ca682869087c565bb29ca6f334692e940d7365771e9a94382e12"}, + {file = "pycryptodome-3.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:d8e480f65ac7105cbc288eec2417dc61eaac6ed6e75595aa15b8c7c77c53a68b"}, + {file = "pycryptodome-3.9.6-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:07daddb98f98f771ba027f8f835bdb675aeb84effe41ed5221f520b267429354"}, + {file = "pycryptodome-3.9.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:da2d581da279bc7408d38e16ff77754f5448c4352f2acfe530a5d14d8fc6934a"}, + {file = "pycryptodome-3.9.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:012ca77c2105600e3c6aef43188101ac1d95052c633a4ae8fbebffab20c25f8a"}, + {file = "pycryptodome-3.9.6-cp37-cp37m-win32.whl", hash = "sha256:05b4d865710f9a6378d3ada28195ff78e52642d3ecffe6fa9d379d870b9bf29d"}, + {file = "pycryptodome-3.9.6-cp37-cp37m-win_amd64.whl", hash = "sha256:9927aa8a8cb4af681279b6f28a1dcb14e0eb556c1aea8413a1e27608a8516e0c"}, + {file = "pycryptodome-3.9.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:de61091dd68326b600422cf731eb4810c4c6363f18a65bccd6061784b7454f5b"}, + {file = "pycryptodome-3.9.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:238d8b6dd27bd1a04816a68aa90a739e6dd23b192fcd83b50f9360958bff192a"}, + {file = "pycryptodome-3.9.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d516df693c195b8da3795e381429bd420e87081b7e6c2871c62c9897c812cda"}, + {file = "pycryptodome-3.9.6-cp38-cp38-win32.whl", hash = "sha256:3e486c5b7228e864665fc479e9f596b2547b5fe29c6f5c8ed3807784d06faed7"}, + {file = "pycryptodome-3.9.6-cp38-cp38-win_amd64.whl", hash = "sha256:887d08beca6368d3d70dc75126607ad76317a9fd07fe61323d8c3cb42add12b6"}, + {file = "pycryptodome-3.9.6.tar.gz", hash = "sha256:bc22ced26ebc46546798fa0141f4418f1db116dec517f0aeaecec87cf7b2416c"}, ] pynacl = [ {file = "PyNaCl-1.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621"}, @@ -1262,8 +1260,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.3.4-py3-none-any.whl", hash = "sha256:25994b002d2883a91b1a885fb08419499873f67d482ea19f564051e296eb4e31"}, - {file = "royalnet-5.3.4.tar.gz", hash = "sha256:75800c9da52750dcd2d49e45bf527e92212b272d81467a63c9a375dadf24e11d"}, + {file = "royalnet-5.4.1-py3-none-any.whl", hash = "sha256:e9b1e20275a7e5d78e15a7479b37df1945de5c5c26d5e55572f332cb0fde19d1"}, + {file = "royalnet-5.4.1.tar.gz", hash = "sha256:4bddbedf6f1b4b54bd45d9fc426dee3866317ebafcb1276e691f61d2793a03a5"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 0ef12dfe..8610fa4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.3.6" + version = "5.4.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.3.4" + version = "^5.4" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py index f63e8d1c..58c9fc1f 100644 --- a/royalpack/commands/magickfiorygi.py +++ b/royalpack/commands/magickfiorygi.py @@ -2,7 +2,8 @@ from typing import * import royalnet import royalnet.commands as rc import royalnet.serf.telegram as rt -from ..tables import Alias, Fiorygi, FiorygiTransaction +from royalnet.backpack.tables import Alias +from ..tables import Fiorygi, FiorygiTransaction class MagickfiorygiCommand(rc.Command): diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index 32a105d6..0e80c828 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -1,7 +1,8 @@ from typing import * from royalnet.commands import * from royalnet.utils import * -from ..tables import Alias, Steam +from royalnet.backpack.tables import Alias +from ..tables import Steam import steam import requests.exceptions diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py index aacd28b1..487bd072 100644 --- a/royalpack/commands/userinfo.py +++ b/royalpack/commands/userinfo.py @@ -1,9 +1,8 @@ from typing import * from royalnet.commands import * from royalnet.utils import * -from royalnet.backpack.tables import User +from royalnet.backpack.tables import User, Alias from sqlalchemy import func -from ..tables.aliases import Alias class UserinfoCommand(Command): diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index 9af8e8a7..a4e625f5 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -38,7 +38,7 @@ class DiscordPlayEvent(rc.Event): if len(candidate_players) == 0: raise rc.UserError("Il bot non è in nessun canale vocale.\n" - "Evocalo prima con [c]summon[/c]!") + "Evocalo prima con [c]summon[/c]!") elif len(candidate_players) == 1: voice_player = candidate_players[0] else: @@ -68,7 +68,7 @@ class DiscordPlayEvent(rc.Event): await main_channel.send(rsd.escape(f"▶️ {user} ha aggiunto {len(added)} file alla coda:")) else: await main_channel.send(rsd.escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" - f" coda:")) + f" coda:")) for ytd in added: embed: discord.Embed = ytd.embed() if force_color: diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 2e5a1eba..489127bd 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -1,6 +1,5 @@ # Imports go here! from .diario import Diario -from .aliases import Alias from .wikipages import WikiPage from .wikirevisions import WikiRevision from .bios import Bio @@ -17,7 +16,6 @@ from .fiorygitransactions import FiorygiTransaction # Enter the tables of your Pack here! available_tables = [ Diario, - Alias, WikiPage, WikiRevision, Bio, diff --git a/royalpack/tables/aliases.py b/royalpack/tables/aliases.py deleted file mode 100644 index 0f4ec1f8..00000000 --- a/royalpack/tables/aliases.py +++ /dev/null @@ -1,35 +0,0 @@ -from sqlalchemy import Column, \ - Integer, \ - String, \ - ForeignKey -from sqlalchemy.orm import relationship -from sqlalchemy.ext.declarative import declared_attr - - -class Alias: - __tablename__ = "aliases" - - @declared_attr - def royal_id(self): - return Column(Integer, ForeignKey("users.uid")) - - @declared_attr - def alias(self): - return Column(String, primary_key=True) - - @declared_attr - def royal(self): - return relationship("User", backref="aliases") - - @classmethod - def find_by_alias(cls, alchemy, session, alias: str): - result = session.query(alchemy.get(cls)).filter_by(alias=alias.lower()).one_or_none() - if result is not None: - result = result.royal - return result - - def __repr__(self): - return f"" - - def __str__(self): - return f"{self.alias}->{self.royal_id}" diff --git a/royalpack/utils/royalqueue.py b/royalpack/utils/royalqueue.py index 373c7c37..310ba55b 100644 --- a/royalpack/utils/royalqueue.py +++ b/royalpack/utils/royalqueue.py @@ -43,3 +43,4 @@ class RoyalQueue(Playable): log.debug(f"Deleting: {self.now_playing.ytdl_file}") await self.now_playing.ytdl_file.delete_asap() log.debug(f"Deleted successfully!") + self.now_playing = None diff --git a/royalpack/version.py b/royalpack/version.py index 03217183..1edc9d1e 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.4" +semantic = "5.4.1" From 5eec828be1a97b79a04efe8ab579496c760aef1f Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 8 Feb 2020 01:49:07 +0100 Subject: [PATCH 051/227] start work on 5.5 port --- poetry.lock | 120 ++++++++++++++++++---------- pyproject.toml | 2 +- royalpack/commands/diario.py | 6 +- royalpack/stars/api_diario_get.py | 24 +++--- royalpack/stars/api_diario_list.py | 52 ++++++------ royalpack/stars/api_discord_cv.py | 10 +-- royalpack/stars/api_discord_play.py | 20 ++--- 7 files changed, 135 insertions(+), 99 deletions(-) diff --git a/poetry.lock b/poetry.lock index 780de232..20cea5aa 100644 --- a/poetry.lock +++ b/poetry.lock @@ -38,6 +38,21 @@ dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.int 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" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.1.7" + +[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 = "Python package for providing Mozilla's CA Bundle." @@ -52,7 +67,7 @@ description = "Foreign Function Interface for Python calling C code." name = "cffi" optional = false python-versions = "*" -version = "1.13.2" +version = "1.14.0" [package.dependencies] pycparser = "*" @@ -285,7 +300,7 @@ description = "Human friendly output for text interfaces using Python" name = "humanfriendly" optional = false python-versions = "*" -version = "4.18" +version = "5.0" [package.dependencies] pyreadline = "*" @@ -562,12 +577,16 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.4.1" +version = "5.5a3" [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" + [package.dependencies.coloredlogs] optional = true version = ">=10.0,<11.0" @@ -629,8 +648,8 @@ optional = true version = "*" [package.extras] -alchemy_easy = ["sqlalchemy (>=1.3.10,<2.0.0)", "psycopg2_binary (>=2.8.4,<3.0.0)"] -alchemy_hard = ["sqlalchemy (>=1.3.10,<2.0.0)", "psycopg2 (>=2.8.4,<3.0.0)"] +alchemy_easy = ["sqlalchemy (>=1.3.10,<2.0.0)", "psycopg2_binary (>=2.8.4,<3.0.0)", "bcrypt (>=3.1.7,<4.0.0)"] +alchemy_hard = ["sqlalchemy (>=1.3.10,<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)"] @@ -839,7 +858,7 @@ python-versions = "*" version = "2020.1.24" [metadata] -content-hash = "d183e0b748d04946c8c44929a4515ac5ac2a8a9916928cd9a604e97128bd2d08" +content-hash = "7cb56343d564bb2209fbc1624f64ab008088537a3b23aeb3f93497ff0cebca63" python-versions = "^3.8" [metadata.files] @@ -865,44 +884,59 @@ attrs = [ {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, {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"}, +] certifi = [ {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, ] cffi = [ - {file = "cffi-1.13.2-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43"}, - {file = "cffi-1.13.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396"}, - {file = "cffi-1.13.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54"}, - {file = "cffi-1.13.2-cp27-cp27m-win32.whl", hash = "sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159"}, - {file = "cffi-1.13.2-cp27-cp27m-win_amd64.whl", hash = "sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97"}, - {file = "cffi-1.13.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579"}, - {file = "cffi-1.13.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc"}, - {file = "cffi-1.13.2-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f"}, - {file = "cffi-1.13.2-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858"}, - {file = "cffi-1.13.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42"}, - {file = "cffi-1.13.2-cp34-cp34m-win32.whl", hash = "sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b"}, - {file = "cffi-1.13.2-cp34-cp34m-win_amd64.whl", hash = "sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20"}, - {file = "cffi-1.13.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3"}, - {file = "cffi-1.13.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25"}, - {file = "cffi-1.13.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5"}, - {file = "cffi-1.13.2-cp35-cp35m-win32.whl", hash = "sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c"}, - {file = "cffi-1.13.2-cp35-cp35m-win_amd64.whl", hash = "sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b"}, - {file = "cffi-1.13.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04"}, - {file = "cffi-1.13.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652"}, - {file = "cffi-1.13.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57"}, - {file = "cffi-1.13.2-cp36-cp36m-win32.whl", hash = "sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e"}, - {file = "cffi-1.13.2-cp36-cp36m-win_amd64.whl", hash = "sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d"}, - {file = "cffi-1.13.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410"}, - {file = "cffi-1.13.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a"}, - {file = "cffi-1.13.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12"}, - {file = "cffi-1.13.2-cp37-cp37m-win32.whl", hash = "sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e"}, - {file = "cffi-1.13.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a"}, - {file = "cffi-1.13.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d"}, - {file = "cffi-1.13.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3"}, - {file = "cffi-1.13.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db"}, - {file = "cffi-1.13.2-cp38-cp38-win32.whl", hash = "sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506"}, - {file = "cffi-1.13.2-cp38-cp38-win_amd64.whl", hash = "sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba"}, - {file = "cffi-1.13.2.tar.gz", hash = "sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346"}, + {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"}, ] chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, @@ -1036,8 +1070,8 @@ httptools = [ {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, ] humanfriendly = [ - {file = "humanfriendly-4.18-py2.py3-none-any.whl", hash = "sha256:23057b10ad6f782e7bc3a20e3cb6768ab919f619bbdc0dd75691121bbde5591d"}, - {file = "humanfriendly-4.18.tar.gz", hash = "sha256:33ee8ceb63f1db61cce8b5c800c531e1a61023ac5488ccde2ba574a85be00a85"}, + {file = "humanfriendly-5.0-py2.py3-none-any.whl", hash = "sha256:eee2e57dea6185fee19914c7d8ba8bc3e488aee2a3c96a7668ce355e2ae275ae"}, + {file = "humanfriendly-5.0.tar.gz", hash = "sha256:b166d90b0fd2e7deafc5d20f64ddfdd4251189a1a6bdc5ed32c6678c79b546d5"}, ] hyperframe = [ {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, @@ -1260,8 +1294,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.4.1-py3-none-any.whl", hash = "sha256:e9b1e20275a7e5d78e15a7479b37df1945de5c5c26d5e55572f332cb0fde19d1"}, - {file = "royalnet-5.4.1.tar.gz", hash = "sha256:4bddbedf6f1b4b54bd45d9fc426dee3866317ebafcb1276e691f61d2793a03a5"}, + {file = "royalnet-5.5a3-py3-none-any.whl", hash = "sha256:26bb171a55913a42f06a06759df32cccf9edc18b41c9edfeb6022b230f4f85fb"}, + {file = "royalnet-5.5a3.tar.gz", hash = "sha256:8c362af1fde43fd67420ef6dc905527044cf0f3e8fc40d298c2a63afd52c92fe"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 8610fa4c..1fe6df6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.4" + version = "^5.5a3" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/diario.py b/royalpack/commands/diario.py index 3416109a..94b76e52 100644 --- a/royalpack/commands/diario.py +++ b/royalpack/commands/diario.py @@ -75,7 +75,7 @@ class DiarioCommand(Command): quoted_tg = await asyncify(data.session.query(self.alchemy.get(Telegram)) .filter_by(tg_id=reply.from_user.id) .one_or_none) - quoted_account = quoted_tg.royal if quoted_tg is not None else 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 @@ -127,7 +127,7 @@ class DiarioCommand(Command): ) else: quoted_alias = None - quoted_account = quoted_alias.royal if quoted_alias is not None else None + quoted_account = quoted_alias.user if quoted_alias is not None else None else: text = None quoted = None @@ -187,7 +187,7 @@ class DiarioCommand(Command): ) else: quoted_alias = None - quoted_account = quoted_alias.royal if quoted_alias is not None else 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 UserError("Il nome dell'autore è ambiguo, quindi la riga non è stata aggiunta.\n" "Per piacere, ripeti il comando con un nome più specifico!") diff --git a/royalpack/stars/api_diario_get.py b/royalpack/stars/api_diario_get.py index 966fc408..bbbaebc2 100644 --- a/royalpack/stars/api_diario_get.py +++ b/royalpack/stars/api_diario_get.py @@ -1,21 +1,19 @@ from starlette.requests import Request from starlette.responses import * -from royalnet.constellation import * +from royalnet.constellation.api import * from royalnet.utils import * from ..tables import * -class ApiDiarioGetStar(PageStar): - path = "/api/diario/get/{diario_id}" +class ApiDiarioGetStar(ApiStar): + path = "/api/diario/get/v1" - async def page(self, request: Request) -> JSONResponse: - diario_id_str = request.path_params.get("diario_id", "") + async def api(self, data: ApiData) -> dict: try: - diario_id = int(diario_id_str) - except (ValueError, TypeError): - return shoot(400, "Invalid diario_id") - async with self.alchemy.session_acm() as session: - entry: Diario = await asyncify(session.query(self.alchemy.get(Diario)).get, diario_id) - if entry is None: - return shoot(404, "No such user") - return JSONResponse(entry.json()) + diario_id = int(data["diario_id"]) + except ValueError: + raise InvalidParameterError("'diario_id' is not a valid int.") + entry: Diario = await asyncify(data.session.query(self.alchemy.get(Diario)).get, diario_id) + if entry is None: + raise NotFoundError("No such diario entry.") + return entry.json() diff --git a/royalpack/stars/api_diario_list.py b/royalpack/stars/api_diario_list.py index 74043b1a..3966bc2a 100644 --- a/royalpack/stars/api_diario_list.py +++ b/royalpack/stars/api_diario_list.py @@ -1,34 +1,36 @@ from starlette.requests import Request from starlette.responses import * -from royalnet.constellation import * +from royalnet.constellation.api import * from royalnet.utils import * from ..tables import * -class ApiDiarioListStar(PageStar): - path = "/api/diario/list" +class ApiDiarioListStar(ApiStar): + path = "/api/diario/list/v1" - async def page(self, request: Request) -> JSONResponse: - page_str = request.query_params.get("page", "0") + async def api(self, data: ApiData) -> dict: + page_str = data["page"] try: page = int(page_str) - except (ValueError, TypeError): - return shoot(400, "Invalid offset") - async with self.alchemy.session_acm() as session: - if page < 0: - page = -page-1 - entries: typing.List[Diario] = await asyncify( - session.query(self.alchemy.get(Diario)) - .order_by(self.alchemy.get(Diario).diario_id.desc()).limit(500) - .offset(page * 500) - .all - ) - else: - entries: typing.List[Diario] = await asyncify( - session.query(self.alchemy.get(Diario)) - .order_by(self.alchemy.get(Diario).diario_id) - .limit(500) - .offset(page * 500) - .all) - response = [entry.json() for entry in entries] - return JSONResponse(response) + except ValueError: + raise InvalidParameterError("'page' is not a valid int.") + if page < 0: + page = -page-1 + entries: typing.List[Diario] = await asyncify( + data.session + .query(self.alchemy.get(Diario)) + .order_by(self.alchemy.get(Diario).diario_id.desc()).limit(500) + .offset(page * 500) + .all + ) + else: + entries: typing.List[Diario] = await asyncify( + data.session + .query(self.alchemy.get(Diario)) + .order_by(self.alchemy.get(Diario).diario_id) + .limit(500) + .offset(page * 500) + .all + ) + response = [entry.json() for entry in entries] + return response diff --git a/royalpack/stars/api_discord_cv.py b/royalpack/stars/api_discord_cv.py index b6b4e8ef..1d1066b3 100644 --- a/royalpack/stars/api_discord_cv.py +++ b/royalpack/stars/api_discord_cv.py @@ -1,12 +1,12 @@ from starlette.requests import Request from starlette.responses import * -from royalnet.constellation import * +from royalnet.constellation.api import * from royalnet.utils import * -class ApiDiscordCvStar(PageStar): - path = "/api/discord/cv" +class ApiDiscordCvStar(ApiStar): + path = "/api/discord/cv/v1" - async def page(self, request: Request) -> JSONResponse: + async def api(self, data: ApiData) -> dict: response = await self.interface.call_herald_event("discord", "discord_cv") - return JSONResponse(response) + return response diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index 88c87af0..bffe053a 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -1,23 +1,25 @@ from typing import * from starlette.requests import Request from starlette.responses import * -from royalnet.constellation import * +from royalnet.constellation.api import * import logging log = logging.getLogger(__name__) -class ApiDiscordPlayStar(PageStar): +class ApiDiscordPlayStar(ApiStar): path = "/api/discord/play" - async def page(self, request: Request) -> JSONResponse: - url = request.query_params.get("url", "") - user = request.query_params.get("user") - try: - guild_id: Optional[int] = int(request.query_params.get("guild_id", None)) - except (ValueError, TypeError): - guild_id = None + async def api(self, data: ApiData) -> dict: + url = data["url"] + user = data.get("user") + guild_id_str = data.get("guild_id") + if guild_id_str: + try: + guild_id: Optional[int] = int(guild_id_str) + except (ValueError, TypeError): + raise InvalidParameterError("'guild_id' is not a valid int.") log.info(f"Received request to play {url} on guild_id {guild_id} via web") response = await self.interface.call_herald_event("discord", "discord_play", url=url, From da03f8e6adb166e85bc81706071438bcae317e8d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 9 Feb 2020 19:12:34 +0100 Subject: [PATCH 052/227] probably break some stuff --- royalpack/stars/__init__.py | 25 ++++++++++--------------- royalpack/stars/api_diario_get.py | 6 ++---- royalpack/stars/api_diario_list.py | 1 - royalpack/stars/api_discord_cv.py | 3 --- royalpack/stars/api_discord_play.py | 8 ++------ royalpack/stars/api_user_get.py | 20 ++++++++++---------- royalpack/stars/api_user_list.py | 12 ++++++------ royalpack/stars/api_wiki_get.py | 22 +++++++++++----------- royalpack/stars/api_wiki_list.py | 12 ++++++------ 9 files changed, 47 insertions(+), 62 deletions(-) diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index a5f71714..20c08bbd 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -1,29 +1,24 @@ # Imports go here! +from .api_diario_get import ApiDiarioGetStar +from .api_diario_list import ApiDiarioListStar from .api_user_list import ApiUserListStar from .api_user_get import ApiUserGetStar -from .api_diario_list import ApiDiarioListStar -from .api_diario_get import ApiDiarioGetStar from .api_discord_cv import ApiDiscordCvStar -from .api_wiki_get import ApiWikiGetStar -from .api_wiki_list import ApiUserListStar from .api_discord_play import ApiDiscordPlayStar +from .api_wiki_get import ApiWikiGetStar +from .api_wiki_list import ApiWikiListStar # Enter the PageStars of your Pack here! available_page_stars = [ - ApiUserListStar, - ApiUserGetStar, - ApiDiarioListStar, ApiDiarioGetStar, + ApiDiarioListStar, ApiDiscordCvStar, - ApiWikiGetStar, - ApiUserListStar, ApiDiscordPlayStar, -] - -# Enter the ExceptionStars of your Pack here! -available_exception_stars = [ - + ApiUserGetStar, + ApiUserListStar, + ApiWikiGetStar, + ApiWikiListStar, ] # Don't change this, it should automatically generate __all__ -__all__ = [star.__name__ for star in [*available_page_stars, *available_exception_stars]] +__all__ = [star.__name__ for star in available_page_stars] diff --git a/royalpack/stars/api_diario_get.py b/royalpack/stars/api_diario_get.py index bbbaebc2..6170241b 100644 --- a/royalpack/stars/api_diario_get.py +++ b/royalpack/stars/api_diario_get.py @@ -1,5 +1,3 @@ -from starlette.requests import Request -from starlette.responses import * from royalnet.constellation.api import * from royalnet.utils import * from ..tables import * @@ -10,9 +8,9 @@ class ApiDiarioGetStar(ApiStar): async def api(self, data: ApiData) -> dict: try: - diario_id = int(data["diario_id"]) + diario_id = int(data["id"]) except ValueError: - raise InvalidParameterError("'diario_id' is not a valid int.") + raise InvalidParameterError("'id' is not a valid int.") entry: Diario = await asyncify(data.session.query(self.alchemy.get(Diario)).get, diario_id) if entry is None: raise NotFoundError("No such diario entry.") diff --git a/royalpack/stars/api_diario_list.py b/royalpack/stars/api_diario_list.py index 3966bc2a..95b29b6f 100644 --- a/royalpack/stars/api_diario_list.py +++ b/royalpack/stars/api_diario_list.py @@ -1,4 +1,3 @@ -from starlette.requests import Request from starlette.responses import * from royalnet.constellation.api import * from royalnet.utils import * diff --git a/royalpack/stars/api_discord_cv.py b/royalpack/stars/api_discord_cv.py index 1d1066b3..a1b9f189 100644 --- a/royalpack/stars/api_discord_cv.py +++ b/royalpack/stars/api_discord_cv.py @@ -1,7 +1,4 @@ -from starlette.requests import Request -from starlette.responses import * from royalnet.constellation.api import * -from royalnet.utils import * class ApiDiscordCvStar(ApiStar): diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index bffe053a..881cae59 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -1,6 +1,4 @@ from typing import * -from starlette.requests import Request -from starlette.responses import * from royalnet.constellation.api import * import logging @@ -9,7 +7,7 @@ log = logging.getLogger(__name__) class ApiDiscordPlayStar(ApiStar): - path = "/api/discord/play" + path = "/api/discord/play/v1" async def api(self, data: ApiData) -> dict: url = data["url"] @@ -25,6 +23,4 @@ class ApiDiscordPlayStar(ApiStar): url=url, guild_id=guild_id, user=user) - return JSONResponse(response, headers={ - "Access-Control-Allow-Origin": "*", - }) + return response diff --git a/royalpack/stars/api_user_get.py b/royalpack/stars/api_user_get.py index c8b95e6d..f04d1288 100644 --- a/royalpack/stars/api_user_get.py +++ b/royalpack/stars/api_user_get.py @@ -3,19 +3,19 @@ from starlette.responses import * from royalnet.constellation import * from royalnet.utils import * from royalnet.backpack.tables import * +from royalnet.constellation.api import * -class ApiUserGetStar(PageStar): - path = "/api/user/get/{uid_str}" +class ApiUserGetStar(ApiStar): + path = "/api/user/get/v1" - async def page(self, request: Request) -> JSONResponse: - uid_str = request.path_params.get("uid_str", "") + async def api(self, data: ApiData) -> dict: + user_id_str = data["id"] try: - uid = int(uid_str) + user_id = int(user_id_str) except (ValueError, TypeError): - return shoot(400, "Invalid uid") - async with self.alchemy.session_acm() as session: - user: User = await asyncify(session.query(self.alchemy.get(User)).get, uid) + raise InvalidParameterError("'id' is not a valid int.") + user: User = await asyncify(data.session.query(self.alchemy.get(User)).get, user_id) if user is None: - return shoot(404, "No such user") - return JSONResponse(user.json()) + raise NotFoundError("No such user.") + return user.json() diff --git a/royalpack/stars/api_user_list.py b/royalpack/stars/api_user_list.py index f520472c..44b0aeff 100644 --- a/royalpack/stars/api_user_list.py +++ b/royalpack/stars/api_user_list.py @@ -3,12 +3,12 @@ from starlette.responses import * from royalnet.constellation import * from royalnet.utils import * from royalnet.backpack.tables import * +from royalnet.constellation.api import * -class ApiUserListStar(PageStar): - path = "/api/user/list" +class ApiUserListStar(ApiStar): + path = "/api/user/list/v1" - async def page(self, request: Request) -> JSONResponse: - async with self.alchemy.session_acm() as session: - users: typing.List[User] = await asyncify(session.query(self.alchemy.get(User)).all) - return JSONResponse([user.json() for user in users]) + async def api(self, data: ApiData) -> dict: + users: typing.List[User] = await asyncify(data.session.query(self.alchemy.get(User)).all) + return [user.json() for user in users] diff --git a/royalpack/stars/api_wiki_get.py b/royalpack/stars/api_wiki_get.py index 72f5d3c6..ee1127dd 100644 --- a/royalpack/stars/api_wiki_get.py +++ b/royalpack/stars/api_wiki_get.py @@ -4,19 +4,19 @@ from royalnet.constellation import * from royalnet.utils import * from ..tables import * import uuid +from royalnet.constellation.api import * -class ApiWikiGetStar(PageStar): - path = "/api/wiki/get/{wiki_page_uuid}" +class ApiWikiGetStar(ApiStar): + path = "/api/wiki/get/v1" - async def page(self, request: Request) -> JSONResponse: - wiki_page_uuid_str = request.path_params.get("wiki_page_uuid", "") + async def api(self, data: ApiData) -> dict: + wikipage_id_str = data["id"] try: - wiki_page_uuid = uuid.UUID(wiki_page_uuid_str) + wikipage_id = uuid.UUID(wikipage_id_str) except (ValueError, AttributeError, TypeError): - return shoot(400, "Invalid wiki_page_uuid") - async with self.alchemy.session_acm() as session: - wikipage: WikiPage = await asyncify(session.query(self.alchemy.get(WikiPage)).get, wiki_page_uuid) - if wikipage is None: - return shoot(404, "No such page") - return JSONResponse(wikipage.json_full()) + raise InvalidParameterError("'id' is not a valid UUID.") + wikipage: WikiPage = await asyncify(data.session.query(self.alchemy.get(WikiPage)).get, wikipage_id) + if wikipage is None: + raise NotFoundError("No such page.") + return wikipage.json_full() diff --git a/royalpack/stars/api_wiki_list.py b/royalpack/stars/api_wiki_list.py index a0789947..ca378635 100644 --- a/royalpack/stars/api_wiki_list.py +++ b/royalpack/stars/api_wiki_list.py @@ -4,12 +4,12 @@ from royalnet.constellation import * from royalnet.utils import * from royalnet.backpack.tables import * from ..tables import * +from royalnet.constellation.api import * -class ApiUserListStar(PageStar): - path = "/api/wiki/list" +class ApiWikiListStar(ApiData): + path = "/api/wiki/list/v1" - async def page(self, request: Request) -> JSONResponse: - async with self.alchemy.session_acm() as session: - pages: typing.List[WikiPage] = await asyncify(session.query(self.alchemy.get(WikiPage)).all) - return JSONResponse([page.json_list() for page in pages]) + async def api(self, data: ApiData) -> dict: + pages: typing.List[WikiPage] = await asyncify(data.session.query(self.alchemy.get(WikiPage)).all) + return [page.json_list() for page in pages] From 2d44594f6c8ade9cbe1ba35827462f0e95ba4da0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 10 Feb 2020 16:43:34 +0100 Subject: [PATCH 053/227] Clear init --- royalpack/__init__.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/royalpack/__init__.py b/royalpack/__init__.py index 23e63a6f..e69de29b 100644 --- a/royalpack/__init__.py +++ b/royalpack/__init__.py @@ -1,21 +0,0 @@ -# This is a template Pack __init__. You can use this without changing anything in other packages too! - -from . import commands, tables, stars, events -from .commands import available_commands -from .tables import available_tables -from .stars import available_page_stars, available_exception_stars -from .events import available_events - -from .version import semantic as __version__ - -__all__ = [ - "commands", - "tables", - "stars", - "events", - "available_commands", - "available_tables", - "available_page_stars", - "available_exception_stars", - "available_events", -] From c49c24bf162bbb22085fb242cb09d225e8e4343d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 11 Feb 2020 19:53:18 +0100 Subject: [PATCH 054/227] wiki is back --- poetry.lock | 49 ++++++++++++++-------- pyproject.toml | 2 +- royalpack/pycharm/test_apis.http | 70 +++++++++++++++++++++++++++++++ royalpack/stars/__init__.py | 6 +++ royalpack/stars/api_bio_get.py | 14 +++++++ royalpack/stars/api_bio_set.py | 23 ++++++++++ royalpack/stars/api_wiki_edit.py | 50 ++++++++++++++++++++++ royalpack/stars/api_wiki_list.py | 2 +- royalpack/tables/__init__.py | 6 --- royalpack/tables/bios.py | 11 +++-- royalpack/tables/mmevents.py | 52 ----------------------- royalpack/tables/mmresponse.py | 31 -------------- royalpack/tables/wikipages.py | 2 +- royalpack/tables/wikirevisions.py | 48 --------------------- royalpack/utils/__init__.py | 2 + royalpack/utils/finduser.py | 19 +++++++++ 16 files changed, 226 insertions(+), 161 deletions(-) create mode 100644 royalpack/pycharm/test_apis.http create mode 100644 royalpack/stars/api_bio_get.py create mode 100644 royalpack/stars/api_bio_set.py create mode 100644 royalpack/stars/api_wiki_edit.py delete mode 100644 royalpack/tables/mmevents.py delete mode 100644 royalpack/tables/mmresponse.py delete mode 100644 royalpack/tables/wikirevisions.py create mode 100644 royalpack/utils/finduser.py diff --git a/poetry.lock b/poetry.lock index 20cea5aa..76993f55 100644 --- a/poetry.lock +++ b/poetry.lock @@ -145,6 +145,14 @@ pytz = "*" regex = "*" tzlocal = "*" +[[package]] +category = "main" +description = "Decorators for Humans" +name = "decorator" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*" +version = "4.4.1" + [[package]] category = "main" description = "A library to handle automated deprecations" @@ -178,7 +186,7 @@ description = "Python audio data toolkit (ID3 and MP3)" name = "eyed3" optional = false python-versions = "*" -version = "0.9" +version = "0.9.2" [package.dependencies] deprecation = "*" @@ -271,10 +279,10 @@ description = "HTTP/2 State-Machine based protocol implementation" name = "h2" optional = false python-versions = "*" -version = "3.1.1" +version = "3.2.0" [package.dependencies] -hpack = ">=2.3,<4" +hpack = ">=3.0,<4" hyperframe = ">=5.2.0,<6" [[package]] @@ -300,7 +308,7 @@ description = "Human friendly output for text interfaces using Python" name = "humanfriendly" optional = false python-versions = "*" -version = "5.0" +version = "6.1" [package.dependencies] pyreadline = "*" @@ -511,11 +519,12 @@ description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" optional = false python-versions = "*" -version = "12.3.0" +version = "12.4.2" [package.dependencies] certifi = "*" cryptography = "*" +decorator = ">=4.4.0" future = ">=0.16.0" tornado = ">=5.1" @@ -577,7 +586,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.5a3" +version = "5.5a5" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -858,7 +867,7 @@ python-versions = "*" version = "2020.1.24" [metadata] -content-hash = "7cb56343d564bb2209fbc1624f64ab008088537a3b23aeb3f93497ff0cebca63" +content-hash = "03b83f374f0113316752e6df25d265ec5d45a2f932f73de1422c92ba06621f66" python-versions = "^3.8" [metadata.files] @@ -981,6 +990,10 @@ dateparser = [ {file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"}, {file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"}, ] +decorator = [ + {file = "decorator-4.4.1-py2.py3-none-any.whl", hash = "sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"}, + {file = "decorator-4.4.1.tar.gz", hash = "sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce"}, +] deprecation = [ {file = "deprecation-2.0.7-py2.py3-none-any.whl", hash = "sha256:dc9b4f252b7aca8165ce2764a71da92a653b5ffbf7a389461d7a640f6536ecb2"}, {file = "deprecation-2.0.7.tar.gz", hash = "sha256:c0392f676a6146f0238db5744d73e786a43510d54033f80994ef2f4c9df192ed"}, @@ -989,9 +1002,9 @@ deprecation = [ {file = "discord.py-1.3.1-py3-none-any.whl", hash = "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360"}, ] eyed3 = [ - {file = "eyeD3-0.9-py2.py3-none-any.whl", hash = "sha256:6015669333df2115809102ccf1b29585115b5c233cf4530d9f995ad562634819"}, - {file = "eyeD3-0.9-py3.8.egg", hash = "sha256:8e3a7a2ce2932260f77c6234d624737807cdb4404f5bac3c5348c1f9da3d7250"}, - {file = "eyeD3-0.9.tar.gz", hash = "sha256:8874762fd4fd93fa64676185ccaa77ea8b3396aea65ba86bca7325f1136f9c8a"}, + {file = "eyeD3-0.9.2-py2.py3-none-any.whl", hash = "sha256:14d387e74097b03163c15d071448924d6e9b700bf8b51276a2d7af4ea21cbe0a"}, + {file = "eyeD3-0.9.2-py3.8.egg", hash = "sha256:d6562a4a260f5085ee2c469a1904f358f6358e830ad84118032778befec8552e"}, + {file = "eyeD3-0.9.2.tar.gz", hash = "sha256:96f1dc92d29da529bf5a0caac6b62a3da2dae319409678491eb7f3e3e1c0359a"}, ] ffmpeg-python = [ {file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"}, @@ -1059,8 +1072,8 @@ h11 = [ {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, ] h2 = [ - {file = "h2-3.1.1-py2.py3-none-any.whl", hash = "sha256:ac377fcf586314ef3177bfd90c12c7826ab0840edeb03f0f24f511858326049e"}, - {file = "h2-3.1.1.tar.gz", hash = "sha256:b8a32bd282594424c0ac55845377eea13fa54fe4a8db012f3a198ed923dc3ab4"}, + {file = "h2-3.2.0-py2.py3-none-any.whl", hash = "sha256:61e0f6601fa709f35cdb730863b4e5ec7ad449792add80d1410d4174ed139af5"}, + {file = "h2-3.2.0.tar.gz", hash = "sha256:875f41ebd6f2c44781259005b157faed1a5031df3ae5aa7bcb4628a6c0782f14"}, ] hpack = [ {file = "hpack-3.0.0-py2.py3-none-any.whl", hash = "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89"}, @@ -1070,8 +1083,8 @@ httptools = [ {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, ] humanfriendly = [ - {file = "humanfriendly-5.0-py2.py3-none-any.whl", hash = "sha256:eee2e57dea6185fee19914c7d8ba8bc3e488aee2a3c96a7668ce355e2ae275ae"}, - {file = "humanfriendly-5.0.tar.gz", hash = "sha256:b166d90b0fd2e7deafc5d20f64ddfdd4251189a1a6bdc5ed32c6678c79b546d5"}, + {file = "humanfriendly-6.1-py2.py3-none-any.whl", hash = "sha256:5a57c973dd28a24f45ab723521c84b111fbe79e9d9fcdca6f9aeb668c18a0f40"}, + {file = "humanfriendly-6.1.tar.gz", hash = "sha256:b77d1aa8d73b6fe7e8860fa516fbc0e2aa85bff159d7525b0213353817cf1cfc"}, ] hyperframe = [ {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, @@ -1255,8 +1268,8 @@ python-multipart = [ {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, ] python-telegram-bot = [ - {file = "python-telegram-bot-12.3.0.tar.gz", hash = "sha256:41608512a3025a04ff7472efcaae344ad7533a77ae207685bb10fc2fc8282f7b"}, - {file = "python_telegram_bot-12.3.0-py2.py3-none-any.whl", hash = "sha256:5e2156f829402e41bb5ea7196e450bf7f121c5689c5100ae180507d72f3777f5"}, + {file = "python-telegram-bot-12.4.2.tar.gz", hash = "sha256:0a97cbca638f949582b4ee326170d2f8d7f4bf559a4e511132bb2203623e04ad"}, + {file = "python_telegram_bot-12.4.2-py2.py3-none-any.whl", hash = "sha256:d3cffd020af4094d07c11783f875e5c682072ba7f5bc21ce89ff0222f4e6d742"}, ] pytz = [ {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, @@ -1294,8 +1307,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.5a3-py3-none-any.whl", hash = "sha256:26bb171a55913a42f06a06759df32cccf9edc18b41c9edfeb6022b230f4f85fb"}, - {file = "royalnet-5.5a3.tar.gz", hash = "sha256:8c362af1fde43fd67420ef6dc905527044cf0f3e8fc40d298c2a63afd52c92fe"}, + {file = "royalnet-5.5a5-py3-none-any.whl", hash = "sha256:f913ec05849c56885bc2a455c6589d960e5af124aacc703bbd3a0e1f004d26b8"}, + {file = "royalnet-5.5a5.tar.gz", hash = "sha256:cbb22f322f6bc8ec0a6404a14d3faf046ad3fb74971917e4f87c16bb2aa300f7"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 1fe6df6a..9f328803 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.5a3" + version = "^5.5a6" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/pycharm/test_apis.http b/royalpack/pycharm/test_apis.http new file mode 100644 index 00000000..e51c3cb9 --- /dev/null +++ b/royalpack/pycharm/test_apis.http @@ -0,0 +1,70 @@ +POST http://localhost:44445/api/login/royalnet/v1 +Content-Type: application/json + +{ + "username": "Steffo", + "password": "ciao" +} + +### + +POST http://localhost:44445/api/token/create/v1 +Content-Type: application/json + +{ + "token": "NFFU4qg6-WxfAWMN-IW6dexEjNcLzNQNZJko2_pbTsE", + "duration": 31536000 +} + +### + +GET http://localhost:44445/api/bio/get/v1 +Content-Type: application/json + +{ + "token": "NFFU4qg6-WxfAWMN-IW6dexEjNcLzNQNZJko2_pbTsE", + "id": 1 +} + +### + +POST http://localhost:44445/api/bio/set/v1 +Content-Type: application/json + +{ + "token": "NFFU4qg6-WxfAWMN-IW6dexEjNcLzNQNZJko2_pbTsE", + "contents": "Ciao!" +} + +### + +GET http://localhost:44445/api/wiki/list/v1 + +### + +POST http://localhost:44445/api/wiki/edit/v1 +Content-Type: application/json + +{ + "token": "NFFU4qg6-WxfAWMN-IW6dexEjNcLzNQNZJko2_pbTsE", + "title": "Prova!", + "contents": "Questa è una pagina wiki di prova.", + "format": "text", + "theme": "default" +} + +### + +POST http://localhost:44445/api/wiki/edit/v1 +Content-Type: application/json + +{ + "id": "80d54849-fab1-4458-9d89-2429773118ef", + "token": "NFFU4qg6-WxfAWMN-IW6dexEjNcLzNQNZJko2_pbTsE", + "title": "Prova2", + "contents": "Questa è una pagina wiki di prova2.", + "format": "text", + "theme": "default" +} + +### diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 20c08bbd..0798d650 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -1,21 +1,27 @@ # Imports go here! +from .api_bio_get import ApiBioGetStar +from .api_bio_set import ApiBioSetStar from .api_diario_get import ApiDiarioGetStar from .api_diario_list import ApiDiarioListStar from .api_user_list import ApiUserListStar from .api_user_get import ApiUserGetStar from .api_discord_cv import ApiDiscordCvStar from .api_discord_play import ApiDiscordPlayStar +from .api_wiki_edit import ApiWikiEditStar from .api_wiki_get import ApiWikiGetStar from .api_wiki_list import ApiWikiListStar # Enter the PageStars of your Pack here! available_page_stars = [ + ApiBioGetStar, + ApiBioSetStar, ApiDiarioGetStar, ApiDiarioListStar, ApiDiscordCvStar, ApiDiscordPlayStar, ApiUserGetStar, ApiUserListStar, + ApiWikiEditStar, ApiWikiGetStar, ApiWikiListStar, ] diff --git a/royalpack/stars/api_bio_get.py b/royalpack/stars/api_bio_get.py new file mode 100644 index 00000000..56d2deee --- /dev/null +++ b/royalpack/stars/api_bio_get.py @@ -0,0 +1,14 @@ +from royalnet.utils import * +from royalnet.backpack.tables import * +from royalnet.constellation.api import * +from ..utils import find_user_api + + +class ApiBioGetStar(ApiStar): + path = "/api/bio/get/v1" + + async def api(self, data: ApiData) -> dict: + user = await find_user_api(data["id"], self.alchemy, data.session) + if user.bio is None: + raise NotFoundError("User has no bio set.") + return user.bio.json() diff --git a/royalpack/stars/api_bio_set.py b/royalpack/stars/api_bio_set.py new file mode 100644 index 00000000..5018eb9a --- /dev/null +++ b/royalpack/stars/api_bio_set.py @@ -0,0 +1,23 @@ +import royalnet.utils as ru +from royalnet.backpack.tables import * +from royalnet.constellation.api import * +from ..tables import Bio + + +class ApiBioSetStar(ApiStar): + path = "/api/bio/set/v1" + + methods = ["POST"] + + async def api(self, data: ApiData) -> ru.JSON: + contents = data["contents"] + BioT = self.alchemy.get(Bio) + user = await data.user() + bio = user.bio + if bio is None: + bio = BioT(user=user, contents=contents) + data.session.add(bio) + else: + bio.contents = contents + await data.session_commit() + return bio.json() diff --git a/royalpack/stars/api_wiki_edit.py b/royalpack/stars/api_wiki_edit.py new file mode 100644 index 00000000..74f20805 --- /dev/null +++ b/royalpack/stars/api_wiki_edit.py @@ -0,0 +1,50 @@ +import uuid +import royalnet.utils as ru +from royalnet.backpack.tables import * +from royalnet.constellation.api import * +from ..tables import WikiPage + + +class ApiWikiEditStar(ApiStar): + path = "/api/wiki/edit/v1" + + methods = ["POST"] + + async def api(self, data: ApiData) -> ru.JSON: + page_id = data.get("id") + title = data["title"] + contents = data["contents"] + format = data["format"] + theme = data["theme"] + + WikiPageT = self.alchemy.get(WikiPage) + + user = await data.user() + if not (user.role == "Admin" or user.role == "Member" or user.role == "Bot"): + raise ForbiddenError("You do not have sufficient permissions to edit this page.") + + if page_id is None: + page = WikiPageT( + page_id=uuid.uuid4(), + title=title, + contents=contents, + format=format, + theme=theme + ) + data.session.add(page) + else: + page = await ru.asyncify( + data.session + .query(WikiPageT) + .filter_by(page_id=uuid.UUID(page_id)) + .one_or_none + ) + if page is None: + raise NotFoundError(f"No page with the id {repr(page_id)} found.") + page.title = title + page.contents = contents + page.format = format + page.theme = theme + + await data.session_commit() + return page.json_full() diff --git a/royalpack/stars/api_wiki_list.py b/royalpack/stars/api_wiki_list.py index ca378635..21a02a71 100644 --- a/royalpack/stars/api_wiki_list.py +++ b/royalpack/stars/api_wiki_list.py @@ -7,7 +7,7 @@ from ..tables import * from royalnet.constellation.api import * -class ApiWikiListStar(ApiData): +class ApiWikiListStar(ApiStar): path = "/api/wiki/list/v1" async def api(self, data: ApiData) -> dict: diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 489127bd..a15e3c13 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -1,12 +1,9 @@ # Imports go here! from .diario import Diario from .wikipages import WikiPage -from .wikirevisions import WikiRevision from .bios import Bio from .reminders import Reminder from .triviascores import TriviaScore -from .mmevents import MMEvent -from .mmresponse import MMResponse from .leagueoflegends import LeagueOfLegends from .fiorygi import Fiorygi from .steam import Steam @@ -17,12 +14,9 @@ from .fiorygitransactions import FiorygiTransaction available_tables = [ Diario, WikiPage, - WikiRevision, Bio, Reminder, TriviaScore, - MMEvent, - MMResponse, LeagueOfLegends, Fiorygi, Steam, diff --git a/royalpack/tables/bios.py b/royalpack/tables/bios.py index 25a3a630..ebd6bf0d 100644 --- a/royalpack/tables/bios.py +++ b/royalpack/tables/bios.py @@ -10,19 +10,24 @@ class Bio: __tablename__ = "bios" @declared_attr - def royal_id(self): + def user_id(self): return Column(Integer, ForeignKey("users.uid"), primary_key=True) @declared_attr - def royal(self): + def user(self): return relationship("User", backref=backref("bio", uselist=False)) @declared_attr def contents(self): return Column(Text, nullable=False, default="") + def json(self) -> dict: + return { + "contents": self.contents + } + def __repr__(self): - return f"" + return f"" def __str__(self): return self.contents diff --git a/royalpack/tables/mmevents.py b/royalpack/tables/mmevents.py deleted file mode 100644 index f633c0f8..00000000 --- a/royalpack/tables/mmevents.py +++ /dev/null @@ -1,52 +0,0 @@ -import pickle -from sqlalchemy import * -from sqlalchemy.orm import relationship -from sqlalchemy.ext.declarative import declared_attr - - -class MMEvent: - __tablename__ = "mmevents" - - @declared_attr - def creator_id(self): - return Column(Integer, ForeignKey("users.uid"), nullable=False) - - @declared_attr - def creator(self): - return relationship("User", backref="mmevents_created") - - @declared_attr - def mmid(self): - return Column(Integer, primary_key=True) - - @declared_attr - def datetime(self): - return Column(DateTime, nullable=False) - - @declared_attr - def title(self): - return Column(String, nullable=False) - - @declared_attr - def description(self): - return Column(Text, nullable=False, default="") - - @declared_attr - def interface(self): - return Column(String, nullable=False) - - @declared_attr - def raw_interface_data(self): - # The default is a pickled None - return Column(Binary, nullable=False, default=b'\x80\x03N.') - - @property - def interface_data(self): - return pickle.loads(self.raw_interface_data) - - @interface_data.setter - def interface_data(self, value): - self.raw_interface_data = pickle.dumps(value) - - def __repr__(self): - return f"" diff --git a/royalpack/tables/mmresponse.py b/royalpack/tables/mmresponse.py deleted file mode 100644 index 4d04931a..00000000 --- a/royalpack/tables/mmresponse.py +++ /dev/null @@ -1,31 +0,0 @@ -from sqlalchemy import * -from sqlalchemy.orm import relationship -from sqlalchemy.ext.declarative import declared_attr -from ..utils import MMChoice - - -class MMResponse: - __tablename__ = "mmresponse" - - @declared_attr - def user_id(self): - return Column(Integer, ForeignKey("users.uid"), primary_key=True) - - @declared_attr - def user(self): - return relationship("User", backref="mmresponses_given") - - @declared_attr - def mmevent_id(self): - return Column(Integer, ForeignKey("mmevents.mmid"), primary_key=True) - - @declared_attr - def mmevent(self): - return relationship("MMEvent", backref="responses") - - @declared_attr - def choice(self): - return Column(Enum(MMChoice), nullable=False) - - def __repr__(self): - return f"" diff --git a/royalpack/tables/wikipages.py b/royalpack/tables/wikipages.py index c1fadfc9..facfdd02 100644 --- a/royalpack/tables/wikipages.py +++ b/royalpack/tables/wikipages.py @@ -31,7 +31,7 @@ class WikiPage: @declared_attr def theme(self): - return Column(String) + return Column(String, nullable=False, default="default") @property def page_short_id(self): diff --git a/royalpack/tables/wikirevisions.py b/royalpack/tables/wikirevisions.py deleted file mode 100644 index 456376d7..00000000 --- a/royalpack/tables/wikirevisions.py +++ /dev/null @@ -1,48 +0,0 @@ -from sqlalchemy import Column, \ - Integer, \ - Text, \ - DateTime, \ - ForeignKey -from sqlalchemy.dialects.postgresql import UUID -from sqlalchemy.orm import relationship -from sqlalchemy.ext.declarative import declared_attr - - -class WikiRevision: - """A wiki page revision. - - Warning: - Requires PostgreSQL!""" - __tablename__ = "wikirevisions" - - @declared_attr - def revision_id(self): - return Column(UUID(as_uuid=True), primary_key=True) - - @declared_attr - def page_id(self): - return Column(UUID(as_uuid=True), ForeignKey("wikipages.page_id"), nullable=False) - - @declared_attr - def page(self): - return relationship("WikiPage", foreign_keys=self.page_id, backref="revisions") - - @declared_attr - def author_id(self): - return Column(Integer, ForeignKey("users.uid"), nullable=False) - - @declared_attr - def author(self): - return relationship("User", foreign_keys=self.author_id, backref="wiki_contributions") - - @declared_attr - def timestamp(self): - return Column(DateTime, nullable=False) - - @declared_attr - def reason(self): - return Column(Text) - - @declared_attr - def diff(self): - return Column(Text) diff --git a/royalpack/utils/__init__.py b/royalpack/utils/__init__.py index 4a9b5117..ba204e8f 100644 --- a/royalpack/utils/__init__.py +++ b/royalpack/utils/__init__.py @@ -7,6 +7,7 @@ from .royalqueue import RoyalQueue from .dotamedal import DotaMedal from .dotastars import DotaStars from .dotarank import DotaRank +from .finduser import find_user_api __all__ = [ "MMChoice", @@ -19,4 +20,5 @@ __all__ = [ "DotaMedal", "DotaStars", "DotaRank", + "find_user_api", ] diff --git a/royalpack/utils/finduser.py b/royalpack/utils/finduser.py new file mode 100644 index 00000000..d13ea95b --- /dev/null +++ b/royalpack/utils/finduser.py @@ -0,0 +1,19 @@ +from typing import * +from royalnet.constellation.api import * +from royalnet.backpack.tables.users import User +from royalnet.utils import asyncify + +async def find_user_api(input: Union[int, str], alchemy, session): + if isinstance(input, int): + user_id = input + elif isinstance(input, str): + try: + user_id = int(input) + except ValueError: + raise InvalidParameterError(f"Invalid user id passed to {find_user_api.__name__}") + else: + raise TypeError(f"Invalid input type passed to {find_user_api.__name__}") + user: User = await asyncify(session.query(alchemy.get(User)).get, user_id) + if user is None: + raise NotFoundError("No such user.") + return user From 1aeb245c6d3b72ac3ee999376543fc5d27611461 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 11 Feb 2020 23:08:09 +0100 Subject: [PATCH 055/227] cose che la gente comune capisce --- pyproject.toml | 4 ++-- royalpack/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9f328803..48ac0b94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.4.1" + version = "5.5" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.5a6" + version = "^5.5" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/version.py b/royalpack/version.py index 1edc9d1e..63bf6999 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.4.1" +semantic = "5.5" From 5d23dc7229a74a2cb4dcb5b0236c9eb7abb2f9b7 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 11 Feb 2020 23:41:24 +0100 Subject: [PATCH 056/227] publish: 5.5.1 --- poetry.lock | 8 ++++---- publish.bat | 2 ++ pyproject.toml | 2 +- royalpack/commands/steammatch.py | 2 +- royalpack/commands/trivia.py | 4 ++-- royalpack/tables/triviascores.py | 4 ++-- royalpack/version.py | 2 +- 7 files changed, 13 insertions(+), 11 deletions(-) create mode 100644 publish.bat diff --git a/poetry.lock b/poetry.lock index 76993f55..a28748b7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -586,7 +586,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.5a5" +version = "5.5" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -867,7 +867,7 @@ python-versions = "*" version = "2020.1.24" [metadata] -content-hash = "03b83f374f0113316752e6df25d265ec5d45a2f932f73de1422c92ba06621f66" +content-hash = "df4780c4db22554a780094003cbfc212af50118fc8b404c9ca25a9c61613ddb5" python-versions = "^3.8" [metadata.files] @@ -1307,8 +1307,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.5a5-py3-none-any.whl", hash = "sha256:f913ec05849c56885bc2a455c6589d960e5af124aacc703bbd3a0e1f004d26b8"}, - {file = "royalnet-5.5a5.tar.gz", hash = "sha256:cbb22f322f6bc8ec0a6404a14d3faf046ad3fb74971917e4f87c16bb2aa300f7"}, + {file = "royalnet-5.5-py3-none-any.whl", hash = "sha256:1df345584d42ea43942606c57e24f8ffc96d0b5ef28296f78707d68dc2d21448"}, + {file = "royalnet-5.5.tar.gz", hash = "sha256:e076355fdf7d8730d258a055c22055ee8f309316a9efb3706da6896e0dc36e39"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/publish.bat b/publish.bat new file mode 100644 index 00000000..33490c42 --- /dev/null +++ b/publish.bat @@ -0,0 +1,2 @@ +git commit -am "publish: %1" +git push && poetry build && poetry publish && hub release create "%1" -m "Royalnet %1" \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 48ac0b94..d056bc39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.5" + version = "5.5.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index 0e80c828..13d59070 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -65,7 +65,7 @@ class SteammatchCommand(Command): users.append(author) for arg in args: - user = await asyncify(Alias.find_by_alias, self.alchemy, data.session, arg) + user = await Alias.find_user(self.alchemy, data.session, arg) users.append(user) if len(users) < 2: diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index 51f9e79e..26e28c05 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -49,7 +49,7 @@ class TriviaCommand(rc.Command): 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.royal.username}: [b]{ts.score:.0f}p[/b]" + 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 @@ -128,7 +128,7 @@ class TriviaCommand(rc.Command): for answerer_id in self._answerers[question_id]: answerer = data.session.query(self.alchemy.get(User)).get(answerer_id) if answerer.trivia_score is None: - ts = self.interface.alchemy.get(TriviaScore)(royal=answerer) + ts = self.interface.alchemy.get(TriviaScore)(user=answerer) data.session.add(ts) await ru.asyncify(data.session.commit) previous_score = answerer.trivia_score.score diff --git a/royalpack/tables/triviascores.py b/royalpack/tables/triviascores.py index 49538544..88bd2b13 100644 --- a/royalpack/tables/triviascores.py +++ b/royalpack/tables/triviascores.py @@ -9,11 +9,11 @@ class TriviaScore: __tablename__ = "triviascores" @declared_attr - def royal_id(self): + def user_id(self): return Column(Integer, ForeignKey("users.uid"), primary_key=True) @declared_attr - def royal(self): + def user(self): return relationship("User", backref=backref("trivia_score", uselist=False)) @declared_attr diff --git a/royalpack/version.py b/royalpack/version.py index 63bf6999..4a50633f 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.5" +semantic = "5.5.1" From 9b793d32900a5b6b0b9a55e8457600baa0ac2452 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 11 Feb 2020 23:51:22 +0100 Subject: [PATCH 057/227] Minor bugfix --- royalpack/commands/userinfo.py | 2 +- royalpack/tables/triviascores.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py index 487bd072..d77b8eff 100644 --- a/royalpack/commands/userinfo.py +++ b/royalpack/commands/userinfo.py @@ -19,7 +19,7 @@ class UserinfoCommand(Command): if username is None: user: User = await data.get_author(error_if_none=True) else: - found: Optional[User] = await asyncify(Alias.find_by_alias, self.alchemy, data.session, username) + found: Optional[User] = await Alias.find_user(self.alchemy, data.session, username) if not found: raise InvalidInputError("Utente non trovato.") else: diff --git a/royalpack/tables/triviascores.py b/royalpack/tables/triviascores.py index 88bd2b13..b5650b5e 100644 --- a/royalpack/tables/triviascores.py +++ b/royalpack/tables/triviascores.py @@ -43,4 +43,4 @@ class TriviaScore: return (self.correct_answers + self.correct_answers * self.correct_rate) * 10 def __repr__(self): - return f"" + return f"" From 7856c74c7b5f19be193c7c8551cc55d017767ee1 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 24 Feb 2020 01:50:54 +0100 Subject: [PATCH 058/227] Fix play API bug --- pyproject.toml | 2 +- royalpack/stars/api_discord_play.py | 2 ++ royalpack/version.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d056bc39..11c85e0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.5.1" + version = "5.5.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index 881cae59..26487dc5 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -18,6 +18,8 @@ class ApiDiscordPlayStar(ApiStar): guild_id: Optional[int] = int(guild_id_str) except (ValueError, TypeError): raise InvalidParameterError("'guild_id' is not a valid int.") + else: + guild_id = None log.info(f"Received request to play {url} on guild_id {guild_id} via web") response = await self.interface.call_herald_event("discord", "discord_play", url=url, diff --git a/royalpack/version.py b/royalpack/version.py index 4a50633f..6573d14b 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.5.1" +semantic = "5.5.2" From 174e682ebe4c92aeb3eceafbac730a20218a648e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 26 Feb 2020 19:19:01 +0100 Subject: [PATCH 059/227] fix magickfiorygi bug --- pyproject.toml | 2 +- royalpack/commands/magickfiorygi.py | 2 +- royalpack/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 11c85e0f..8b0dbdf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.5.2" + version = "5.5.3" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py index 58c9fc1f..994d03d9 100644 --- a/royalpack/commands/magickfiorygi.py +++ b/royalpack/commands/magickfiorygi.py @@ -24,7 +24,7 @@ class MagickfiorygiCommand(rc.Command): if user_arg is None: raise rc.InvalidInputError("Non hai specificato un destinatario!") - user = Alias.find_by_alias(self.alchemy, data.session, user_arg) + user = await Alias.find_user(self.alchemy, data.session, user_arg) if user is None: raise rc.InvalidInputError("L'utente specificato non esiste!") diff --git a/royalpack/version.py b/royalpack/version.py index 6573d14b..990ad572 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.5.2" +semantic = "5.5.3" From c833723bbd3e123e99c10410109147622cce69d0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 4 Mar 2020 19:57:34 +0100 Subject: [PATCH 060/227] Sort wikipages by name --- pyproject.toml | 2 +- royalpack/stars/api_wiki_list.py | 4 ++-- royalpack/version.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8b0dbdf0..27fd4a1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.5.3" + version = "5.5.4" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/api_wiki_list.py b/royalpack/stars/api_wiki_list.py index 21a02a71..c4a47095 100644 --- a/royalpack/stars/api_wiki_list.py +++ b/royalpack/stars/api_wiki_list.py @@ -10,6 +10,6 @@ from royalnet.constellation.api import * class ApiWikiListStar(ApiStar): path = "/api/wiki/list/v1" - async def api(self, data: ApiData) -> dict: + async def api(self, data: ApiData) -> JSON: pages: typing.List[WikiPage] = await asyncify(data.session.query(self.alchemy.get(WikiPage)).all) - return [page.json_list() for page in pages] + return [page.json_list() for page in sorted(pages, key=lambda p: p.title)] diff --git a/royalpack/version.py b/royalpack/version.py index 990ad572..28a1bf44 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.5.3" +semantic = "5.5.4" From 7192c77c385db3812a58e1c92066c35dc563e433 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 9 Mar 2020 21:21:07 +0100 Subject: [PATCH 061/227] Add docs to API Stars --- poetry.lock | 245 ++++++++++++++-------------- pyproject.toml | 4 +- royalpack/events/discord_play.py | 2 +- royalpack/stars/__init__.py | 4 - royalpack/stars/api_bio_get.py | 8 + royalpack/stars/api_bio_set.py | 12 +- royalpack/stars/api_diario_get.py | 8 + royalpack/stars/api_diario_list.py | 8 + royalpack/stars/api_discord_cv.py | 4 + royalpack/stars/api_discord_play.py | 10 ++ royalpack/stars/api_user_get.py | 21 --- royalpack/stars/api_user_list.py | 14 -- royalpack/stars/api_wiki_edit.py | 14 ++ royalpack/stars/api_wiki_get.py | 8 + royalpack/stars/api_wiki_list.py | 4 + 15 files changed, 202 insertions(+), 164 deletions(-) delete mode 100644 royalpack/stars/api_user_get.py delete mode 100644 royalpack/stars/api_user_list.py diff --git a/poetry.lock b/poetry.lock index a28748b7..db53d3d1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -85,8 +85,8 @@ category = "main" description = "Composable command line interface toolkit" name = "click" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "7.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1" [[package]] category = "main" @@ -137,12 +137,12 @@ description = "Date parsing library designed to parse dates from HTML pages" name = "dateparser" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.7.2" +version = "0.7.4" [package.dependencies] python-dateutil = "*" pytz = "*" -regex = "*" +regex = "!=2019.02.19" tzlocal = "*" [[package]] @@ -151,7 +151,7 @@ description = "Decorators for Humans" name = "decorator" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.4.1" +version = "4.4.2" [[package]] category = "main" @@ -170,7 +170,7 @@ description = "A python wrapper for the Discord API" name = "discord.py" optional = false python-versions = ">=3.5.3" -version = "1.3.1" +version = "1.3.2" [package.dependencies] aiohttp = ">=3.6.0,<3.7.0" @@ -186,7 +186,7 @@ description = "Python audio data toolkit (ID3 and MP3)" name = "eyed3" optional = false python-versions = "*" -version = "0.9.2" +version = "0.9.3" [package.dependencies] deprecation = "*" @@ -307,8 +307,8 @@ category = "main" description = "Human friendly output for text interfaces using Python" name = "humanfriendly" optional = false -python-versions = "*" -version = "6.1" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "8.1" [package.dependencies] pyreadline = "*" @@ -327,7 +327,7 @@ 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.8" +version = "2.9" [[package]] category = "main" @@ -397,7 +397,7 @@ description = "multidict implementation" name = "multidict" optional = false python-versions = ">=3.5" -version = "4.7.4" +version = "4.7.5" [[package]] category = "main" @@ -405,7 +405,7 @@ description = "Core utilities for Python packages" name = "packaging" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.1" +version = "20.3" [package.dependencies] pyparsing = ">=2.0.2" @@ -437,7 +437,7 @@ description = "C parser in Python" name = "pycparser" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.19" +version = "2.20" [[package]] category = "main" @@ -445,7 +445,7 @@ description = "Cryptographic library for Python" name = "pycryptodome" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.6" +version = "3.9.7" [[package]] category = "main" @@ -546,7 +546,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.1.8" +version = "2020.2.20" [[package]] category = "main" @@ -554,16 +554,16 @@ description = "Python HTTP for Humans." name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.22.0" +version = "2.23.0" [package.dependencies] certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.9" +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)", "idna (>=2.0.0)"] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] @@ -586,7 +586,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.5" +version = "5.6.2" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -772,7 +772,7 @@ description = "Tornado is a Python web framework and asynchronous networking lib name = "tornado" optional = false python-versions = ">= 3.5" -version = "6.0.3" +version = "6.0.4" [[package]] category = "main" @@ -864,10 +864,10 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.1.24" +version = "2020.3.8" [metadata] -content-hash = "df4780c4db22554a780094003cbfc212af50118fc8b404c9ca25a9c61613ddb5" +content-hash = "8d7780d1bc898479dda8255988247547650f4034a3ef6e37db47f7ccda1a9d5f" python-versions = "^3.8" [metadata.files] @@ -952,8 +952,8 @@ chardet = [ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] click = [ - {file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"}, - {file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"}, + {file = "click-7.1-py2.py3-none-any.whl", hash = "sha256:91eb2c43db0254aaf3b14a3c4e0db914a900aa09bbc33c6e87ede4a8f7c969dc"}, + {file = "click-7.1.tar.gz", hash = "sha256:482f552f2d5452b9eeffc44165e8b790dd53f75bcce099a812b65e0357e860e2"}, ] colorama = [ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, @@ -987,24 +987,24 @@ cryptography = [ {file = "cryptography-2.8.tar.gz", hash = "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651"}, ] dateparser = [ - {file = "dateparser-0.7.2-py2.py3-none-any.whl", hash = "sha256:983d84b5e3861cb0aa240cad07f12899bb10b62328aae188b9007e04ce37d665"}, - {file = "dateparser-0.7.2.tar.gz", hash = "sha256:e1eac8ef28de69a554d5fcdb60b172d526d61924b1a40afbbb08df459a36006b"}, + {file = "dateparser-0.7.4-py2.py3-none-any.whl", hash = "sha256:1b1f0e3034f82d1f92b45fa445826da6a36d67af8a1169e04869685594276011"}, + {file = "dateparser-0.7.4.tar.gz", hash = "sha256:fb5bfde4795fa4b179fe05c2c25b3981f785de26bec37e247dee1079c63d5689"}, ] decorator = [ - {file = "decorator-4.4.1-py2.py3-none-any.whl", hash = "sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"}, - {file = "decorator-4.4.1.tar.gz", hash = "sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce"}, + {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.0.7-py2.py3-none-any.whl", hash = "sha256:dc9b4f252b7aca8165ce2764a71da92a653b5ffbf7a389461d7a640f6536ecb2"}, {file = "deprecation-2.0.7.tar.gz", hash = "sha256:c0392f676a6146f0238db5744d73e786a43510d54033f80994ef2f4c9df192ed"}, ] "discord.py" = [ - {file = "discord.py-1.3.1-py3-none-any.whl", hash = "sha256:8bfe5628d31771744000f19135c386c74ac337479d7282c26cc1627b9d31f360"}, + {file = "discord.py-1.3.2-py3-none-any.whl", hash = "sha256:7424be26b07b37ecad4404d9383d685995a0e0b3df3f9c645bdd3a4d977b83b4"}, ] eyed3 = [ - {file = "eyeD3-0.9.2-py2.py3-none-any.whl", hash = "sha256:14d387e74097b03163c15d071448924d6e9b700bf8b51276a2d7af4ea21cbe0a"}, - {file = "eyeD3-0.9.2-py3.8.egg", hash = "sha256:d6562a4a260f5085ee2c469a1904f358f6358e830ad84118032778befec8552e"}, - {file = "eyeD3-0.9.2.tar.gz", hash = "sha256:96f1dc92d29da529bf5a0caac6b62a3da2dae319409678491eb7f3e3e1c0359a"}, + {file = "eyeD3-0.9.3-py2.py3-none-any.whl", hash = "sha256:82e838a45db298bedf5bfa284e936f9c2216550106d47673bafa1ae262292a36"}, + {file = "eyeD3-0.9.3-py3.8.egg", hash = "sha256:cb750a56163a55181a840bd5f6a78299de247c19c97160055c65e39066a3e422"}, + {file = "eyeD3-0.9.3.tar.gz", hash = "sha256:33020d86aa1ffb4a130e10c27d0c3f9fa05989b862d454e95195ff08eeb67375"}, ] ffmpeg-python = [ {file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"}, @@ -1083,16 +1083,16 @@ httptools = [ {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, ] humanfriendly = [ - {file = "humanfriendly-6.1-py2.py3-none-any.whl", hash = "sha256:5a57c973dd28a24f45ab723521c84b111fbe79e9d9fcdca6f9aeb668c18a0f40"}, - {file = "humanfriendly-6.1.tar.gz", hash = "sha256:b77d1aa8d73b6fe7e8860fa516fbc0e2aa85bff159d7525b0213353817cf1cfc"}, + {file = "humanfriendly-8.1-py2.py3-none-any.whl", hash = "sha256:3a831920e40e55ad49adb64c9179ed50c604cabca72cd300e7bd5b51310e4ebb"}, + {file = "humanfriendly-8.1.tar.gz", hash = "sha256:25c2108a45cfd1e8fbe9cdb30b825d34ef5d5675c8e11e4775c9aedbfb0bdee2"}, ] hyperframe = [ {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, {file = "hyperframe-5.2.0.tar.gz", hash = "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"}, ] idna = [ - {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, - {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, + {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, + {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, ] jsonschema = [ {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, @@ -1113,27 +1113,27 @@ matrix-nio = [ {file = "matrix-nio-0.6.tar.gz", hash = "sha256:25a4ac9d5e1435035f5c5b6e9a6b453ac66ade25cb455ba6bbe9cc3ae1e0ef50"}, ] multidict = [ - {file = "multidict-4.7.4-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:93166e0f5379cf6cd29746989f8a594fa7204dcae2e9335ddba39c870a287e1c"}, - {file = "multidict-4.7.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a8ed33e8f9b67e3b592c56567135bb42e7e0e97417a4b6a771e60898dfd5182b"}, - {file = "multidict-4.7.4-cp35-cp35m-win32.whl", hash = "sha256:a38baa3046cce174a07a59952c9f876ae8875ef3559709639c17fdf21f7b30dd"}, - {file = "multidict-4.7.4-cp35-cp35m-win_amd64.whl", hash = "sha256:9a7b115ee0b9b92d10ebc246811d8f55d0c57e82dbb6a26b23c9a9a6ad40ce0c"}, - {file = "multidict-4.7.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:dcfed56aa085b89d644af17442cdc2debaa73388feba4b8026446d168ca8dad7"}, - {file = "multidict-4.7.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f29b885e4903bd57a7789f09fe9d60b6475a6c1a4c0eca874d8558f00f9d4b51"}, - {file = "multidict-4.7.4-cp36-cp36m-win32.whl", hash = "sha256:13f3ebdb5693944f52faa7b2065b751cb7e578b8dd0a5bb8e4ab05ad0188b85e"}, - {file = "multidict-4.7.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4fba5204d32d5c52439f88437d33ad14b5f228e25072a192453f658bddfe45a7"}, - {file = "multidict-4.7.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a6d219f49821f4b2c85c6d426346a5d84dab6daa6f85ca3da6c00ed05b54022d"}, - {file = "multidict-4.7.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:63810343ea07f5cd86ba66ab66706243a6f5af075eea50c01e39b4ad6bc3c57a"}, - {file = "multidict-4.7.4-cp37-cp37m-win32.whl", hash = "sha256:26502cefa86d79b86752e96639352c7247846515c864d7c2eb85d036752b643c"}, - {file = "multidict-4.7.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5eee66f882ab35674944dfa0d28b57fa51e160b4dce0ce19e47f495fdae70703"}, - {file = "multidict-4.7.4-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:527124ef435f39a37b279653ad0238ff606b58328ca7989a6df372fd75d7fe26"}, - {file = "multidict-4.7.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:83c6ddf0add57c6b8a7de0bc7e2d656be3eefeff7c922af9a9aae7e49f225625"}, - {file = "multidict-4.7.4-cp38-cp38-win32.whl", hash = "sha256:6bd10adf9f0d6a98ccc792ab6f83d18674775986ba9bacd376b643fe35633357"}, - {file = "multidict-4.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb"}, - {file = "multidict-4.7.4.tar.gz", hash = "sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4"}, + {file = "multidict-4.7.5-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"}, + {file = "multidict-4.7.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35"}, + {file = "multidict-4.7.5-cp35-cp35m-win32.whl", hash = "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1"}, + {file = "multidict-4.7.5-cp35-cp35m-win_amd64.whl", hash = "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd"}, + {file = "multidict-4.7.5-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20"}, + {file = "multidict-4.7.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136"}, + {file = "multidict-4.7.5-cp36-cp36m-win32.whl", hash = "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e"}, + {file = "multidict-4.7.5-cp36-cp36m-win_amd64.whl", hash = "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78"}, + {file = "multidict-4.7.5-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8"}, + {file = "multidict-4.7.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab"}, + {file = "multidict-4.7.5-cp37-cp37m-win32.whl", hash = "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928"}, + {file = "multidict-4.7.5-cp37-cp37m-win_amd64.whl", hash = "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1"}, + {file = "multidict-4.7.5-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4"}, + {file = "multidict-4.7.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2"}, + {file = "multidict-4.7.5-cp38-cp38-win32.whl", hash = "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5"}, + {file = "multidict-4.7.5-cp38-cp38-win_amd64.whl", hash = "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969"}, + {file = "multidict-4.7.5.tar.gz", hash = "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e"}, ] packaging = [ - {file = "packaging-20.1-py2.py3-none-any.whl", hash = "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73"}, - {file = "packaging-20.1.tar.gz", hash = "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334"}, + {file = "packaging-20.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, + {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, ] protobuf = [ {file = "protobuf-3.11.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481"}, @@ -1191,39 +1191,40 @@ psycopg2-binary = [ {file = "psycopg2_binary-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f"}, ] pycparser = [ - {file = "pycparser-2.19.tar.gz", hash = "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"}, + {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, + {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] pycryptodome = [ - {file = "pycryptodome-3.9.6-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:5029c46b0d41dfb763c3981c0af68eab029f06fe2b94f2299112fc18cf9e8d6d"}, - {file = "pycryptodome-3.9.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:95d324e603c5cec5d89e8595236bbf59ade5fe3a72d100ce61eebb323d598750"}, - {file = "pycryptodome-3.9.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2a57daef18a2022a5e4b6f7376c9ddd0c2d946e4b1f1e59b837f5bf295be7380"}, - {file = "pycryptodome-3.9.6-cp27-cp27m-win32.whl", hash = "sha256:a719bd708207fa219fcbf4c8ebbcbc52846045f78179d00445b429fdabdbc1c4"}, - {file = "pycryptodome-3.9.6-cp27-cp27m-win_amd64.whl", hash = "sha256:39e5ca2f66d1eac7abcba5ce1a03370d123dc6085620f1cd532dfee27e650178"}, - {file = "pycryptodome-3.9.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f4d2174e168d0eabd1fffaf88b4f62c2b6f30a67b8816f31024b8e48be3e2d75"}, - {file = "pycryptodome-3.9.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ec7d39589f9cfc2a8b83b1d2fc673441757c99d43283e97b2dd46e0e23730db8"}, - {file = "pycryptodome-3.9.6-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:9163fec630495c10c767991e3f8dab32f4427bfb2dfeaa59bb28fe3e52ba66f2"}, - {file = "pycryptodome-3.9.6-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:0a8d5f2dbb4bbe830ace54286b829bfa529f0853bedaab6225fcb2e6d1f7e356"}, - {file = "pycryptodome-3.9.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5817c0b3c263025d851da96b90cbc7e95348008f88b990e90d10683dba376666"}, - {file = "pycryptodome-3.9.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c41b7e10b72cef00cd63410f31fe50e72dc3a40eafbd146e288384fbe4208064"}, - {file = "pycryptodome-3.9.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f3204006869ab037604b1d9f045c4e84882ddd365e4ee8caa5eb1ff47a59188e"}, - {file = "pycryptodome-3.9.6-cp35-cp35m-win32.whl", hash = "sha256:cdb0ad83a5d6bac986a37fcb7562bcbef0aabae8ea19505bab5cf83c4d18af12"}, - {file = "pycryptodome-3.9.6-cp35-cp35m-win_amd64.whl", hash = "sha256:1259b8ca49662b8a941177357f08147d858595c0042e63ff81e9628e925b5c9d"}, - {file = "pycryptodome-3.9.6-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:09bf05a489fe10f9280a5e0163f195e7b9630cafb15f7d72fb9c8f5eb2afa84f"}, - {file = "pycryptodome-3.9.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:fcff8c9d88d58880f7eda2139c7c444552a38f98a9e77ba5970b6e78f54ac358"}, - {file = "pycryptodome-3.9.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9948c2d5c5c0ee45ed44cee0e2eba2ce60a03be006ed3074521f3da3be162e72"}, - {file = "pycryptodome-3.9.6-cp36-cp36m-win32.whl", hash = "sha256:79320f1fc5c9ca682869087c565bb29ca6f334692e940d7365771e9a94382e12"}, - {file = "pycryptodome-3.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:d8e480f65ac7105cbc288eec2417dc61eaac6ed6e75595aa15b8c7c77c53a68b"}, - {file = "pycryptodome-3.9.6-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:07daddb98f98f771ba027f8f835bdb675aeb84effe41ed5221f520b267429354"}, - {file = "pycryptodome-3.9.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:da2d581da279bc7408d38e16ff77754f5448c4352f2acfe530a5d14d8fc6934a"}, - {file = "pycryptodome-3.9.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:012ca77c2105600e3c6aef43188101ac1d95052c633a4ae8fbebffab20c25f8a"}, - {file = "pycryptodome-3.9.6-cp37-cp37m-win32.whl", hash = "sha256:05b4d865710f9a6378d3ada28195ff78e52642d3ecffe6fa9d379d870b9bf29d"}, - {file = "pycryptodome-3.9.6-cp37-cp37m-win_amd64.whl", hash = "sha256:9927aa8a8cb4af681279b6f28a1dcb14e0eb556c1aea8413a1e27608a8516e0c"}, - {file = "pycryptodome-3.9.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:de61091dd68326b600422cf731eb4810c4c6363f18a65bccd6061784b7454f5b"}, - {file = "pycryptodome-3.9.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:238d8b6dd27bd1a04816a68aa90a739e6dd23b192fcd83b50f9360958bff192a"}, - {file = "pycryptodome-3.9.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d516df693c195b8da3795e381429bd420e87081b7e6c2871c62c9897c812cda"}, - {file = "pycryptodome-3.9.6-cp38-cp38-win32.whl", hash = "sha256:3e486c5b7228e864665fc479e9f596b2547b5fe29c6f5c8ed3807784d06faed7"}, - {file = "pycryptodome-3.9.6-cp38-cp38-win_amd64.whl", hash = "sha256:887d08beca6368d3d70dc75126607ad76317a9fd07fe61323d8c3cb42add12b6"}, - {file = "pycryptodome-3.9.6.tar.gz", hash = "sha256:bc22ced26ebc46546798fa0141f4418f1db116dec517f0aeaecec87cf7b2416c"}, + {file = "pycryptodome-3.9.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:0e10f352ccbbcb5bb2dc4ecaf106564e65702a717d72ab260f9ac4c19753cfc2"}, + {file = "pycryptodome-3.9.7-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9c739b7795ccf2ef1fdad8d44e539a39ad300ee6786e804ea7f0c6a786eb5343"}, + {file = "pycryptodome-3.9.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9977086e0f93adb326379897437373871b80501e1d176fec63c7f46fb300c862"}, + {file = "pycryptodome-3.9.7-cp27-cp27m-win32.whl", hash = "sha256:83295a3fb5cf50c48631eb5b440cb5e9832d8c14d81d1d45f4497b67a9987de8"}, + {file = "pycryptodome-3.9.7-cp27-cp27m-win_amd64.whl", hash = "sha256:b1e332587b3b195542e77681389c296e1837ca01240399d88803a075447d3557"}, + {file = "pycryptodome-3.9.7-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9378c309aec1f8cd8bad361ed0816a440151b97a2a3f6ffdaba1d1a1fb76873a"}, + {file = "pycryptodome-3.9.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4f94368ce2d65873a87ad867eb3bf63f4ba81eb97a9ee66d38c2b71ce5a7439"}, + {file = "pycryptodome-3.9.7-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:f655addaaaa9974108d4808f4150652589cada96074c87115c52e575bfcd87d5"}, + {file = "pycryptodome-3.9.7-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:9a94fca11fdc161460bd8659c15b6adef45c1b20da86402256eaf3addfaab324"}, + {file = "pycryptodome-3.9.7-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ea83bcd9d6c03248ebd46e71ac313858e0afd5aa2fa81478c0e653242f3eb476"}, + {file = "pycryptodome-3.9.7-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:07024fc364869eae8d6ac0d316e089956e6aeffe42dbdcf44fe1320d96becf7f"}, + {file = "pycryptodome-3.9.7-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:426c188c83c10df71f053e04b4003b1437bae5cb37606440e498b00f160d71d0"}, + {file = "pycryptodome-3.9.7-cp35-cp35m-win32.whl", hash = "sha256:d61b012baa8c2b659e9890011358455c0019a4108536b811602d2f638c40802a"}, + {file = "pycryptodome-3.9.7-cp35-cp35m-win_amd64.whl", hash = "sha256:1f4752186298caf2e9ff5354f2e694d607ca7342aa313a62005235d46e28cf04"}, + {file = "pycryptodome-3.9.7-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:767ad0fb5d23efc36a4d5c2fc608ac603f3de028909bcf59abc943e0d0bc5a36"}, + {file = "pycryptodome-3.9.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:2fbc472e0b567318fe2052281d5a8c0ae70099b446679815f655e9fbc18c3a65"}, + {file = "pycryptodome-3.9.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9230fcb5d948c3fb40049bace4d33c5d254f8232c2c0bba05d2570aea3ba4520"}, + {file = "pycryptodome-3.9.7-cp36-cp36m-win32.whl", hash = "sha256:8f06556a8f7ea7b1e42eff39726bb0dca1c251205debae64e6eebea3cd7b438a"}, + {file = "pycryptodome-3.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:d6e1bc5c94873bec742afe2dfadce0d20445b18e75c47afc0c115b19e5dd38dd"}, + {file = "pycryptodome-3.9.7-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:3ec3dc2f80f71fd0c955ce48b81bfaf8914c6f63a41a738f28885a1c4892968a"}, + {file = "pycryptodome-3.9.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cff31f5a8977534f255f729d5d2467526f2b10563a30bbdade92223e0bf264bd"}, + {file = "pycryptodome-3.9.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ed5761b37615a1f222c5345bbf45272ae2cf8c7dff88a4f53a1e9f977cbb6d95"}, + {file = "pycryptodome-3.9.7-cp37-cp37m-win32.whl", hash = "sha256:f011cd0062e54658b7086a76f8cf0f4222812acc66e219e196ea2d0a8849d0ed"}, + {file = "pycryptodome-3.9.7-cp37-cp37m-win_amd64.whl", hash = "sha256:626c0a1d4d83ec6303f970a17158114f75c3ba1736f7f2983f7b40a265861bd8"}, + {file = "pycryptodome-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be56bde3312e022d9d1d6afa124556460ad5c844c2fc63642f6af723c098d35"}, + {file = "pycryptodome-3.9.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c818dc1f3eace93ee50c2b6b5c2becf7c418fa5dd1ba6fc0ef7db279ea21d5e4"}, + {file = "pycryptodome-3.9.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:09b6d6bcc01a4eb1a2b4deeff5aa602a108ec5aed8ac75ae554f97d1d7f0a5ad"}, + {file = "pycryptodome-3.9.7-cp38-cp38-win32.whl", hash = "sha256:7ac729d9091ed5478af2b4a4f44f5335a98febbc008af619e4569a59fe503e40"}, + {file = "pycryptodome-3.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:c109a26a21f21f695d369ff9b87f5d43e0d6c768d8384e10bc74142bed2e092e"}, + {file = "pycryptodome-3.9.7.tar.gz", hash = "sha256:f1add21b6d179179b3c177c33d18a2186a09cc0d3af41ff5ed3f377360b869f2"}, ] pynacl = [ {file = "PyNaCl-1.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621"}, @@ -1276,39 +1277,39 @@ pytz = [ {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, ] regex = [ - {file = "regex-2020.1.8-cp27-cp27m-win32.whl", hash = "sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161"}, - {file = "regex-2020.1.8-cp27-cp27m-win_amd64.whl", hash = "sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4eae742636aec40cf7ab98171ab9400393360b97e8f9da67b1867a9ee0889b26"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bd25bb7980917e4e70ccccd7e3b5740614f1c408a642c245019cff9d7d1b6149"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3e77409b678b21a056415da3a56abfd7c3ad03da71f3051bbcdb68cf44d3c34d"}, - {file = "regex-2020.1.8-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:07b39bf943d3d2fe63d46281d8504f8df0ff3fe4c57e13d1656737950e53e525"}, - {file = "regex-2020.1.8-cp36-cp36m-win32.whl", hash = "sha256:23e2c2c0ff50f44877f64780b815b8fd2e003cda9ce817a7fd00dea5600c84a0"}, - {file = "regex-2020.1.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27429b8d74ba683484a06b260b7bb00f312e7c757792628ea251afdbf1434003"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0e182d2f097ea8549a249040922fa2b92ae28be4be4895933e369a525ba36576"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e3cd21cc2840ca67de0bbe4071f79f031c81418deb544ceda93ad75ca1ee9f7b"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ecc6de77df3ef68fee966bb8cb4e067e84d4d1f397d0ef6fce46913663540d77"}, - {file = "regex-2020.1.8-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:26ff99c980f53b3191d8931b199b29d6787c059f2e029b2b0c694343b1708c35"}, - {file = "regex-2020.1.8-cp37-cp37m-win32.whl", hash = "sha256:7bcd322935377abcc79bfe5b63c44abd0b29387f267791d566bbb566edfdd146"}, - {file = "regex-2020.1.8-cp37-cp37m-win_amd64.whl", hash = "sha256:10671601ee06cf4dc1bc0b4805309040bb34c9af423c12c379c83d7895622bb5"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:98b8ed7bb2155e2cbb8b76f627b2fd12cf4b22ab6e14873e8641f266e0fb6d8f"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6a6ba91b94427cd49cd27764679024b14a96874e0dc638ae6bdd4b1a3ce97be1"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:6a6ae17bf8f2d82d1e8858a47757ce389b880083c4ff2498dba17c56e6c103b9"}, - {file = "regex-2020.1.8-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:0932941cdfb3afcbc26cc3bcf7c3f3d73d5a9b9c56955d432dbf8bbc147d4c5b"}, - {file = "regex-2020.1.8-cp38-cp38-win32.whl", hash = "sha256:d58e4606da2a41659c84baeb3cfa2e4c87a74cec89a1e7c56bee4b956f9d7461"}, - {file = "regex-2020.1.8-cp38-cp38-win_amd64.whl", hash = "sha256:e7c7661f7276507bce416eaae22040fd91ca471b5b33c13f8ff21137ed6f248c"}, - {file = "regex-2020.1.8.tar.gz", hash = "sha256:d0f424328f9822b0323b3b6f2e4b9c90960b24743d220763c7f07071e0778351"}, + {file = "regex-2020.2.20-cp27-cp27m-win32.whl", hash = "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb"}, + {file = "regex-2020.2.20-cp27-cp27m-win_amd64.whl", hash = "sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc"}, + {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0"}, + {file = "regex-2020.2.20-cp36-cp36m-win32.whl", hash = "sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69"}, + {file = "regex-2020.2.20-cp36-cp36m-win_amd64.whl", hash = "sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce"}, + {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab"}, + {file = "regex-2020.2.20-cp37-cp37m-win32.whl", hash = "sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431"}, + {file = "regex-2020.2.20-cp37-cp37m-win_amd64.whl", hash = "sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux1_i686.whl", hash = "sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2"}, + {file = "regex-2020.2.20-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70"}, + {file = "regex-2020.2.20-cp38-cp38-win32.whl", hash = "sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d"}, + {file = "regex-2020.2.20-cp38-cp38-win_amd64.whl", hash = "sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa"}, + {file = "regex-2020.2.20.tar.gz", hash = "sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5"}, ] requests = [ - {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, - {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, + {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, + {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, ] riotwatcher = [ {file = "riotwatcher-2.7.1-py2.py3-none-any.whl", hash = "sha256:3fb03b20f768cea7830d54c6d301a8341c67223625ac8536d26d1c140af3dcb0"}, {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.5-py3-none-any.whl", hash = "sha256:1df345584d42ea43942606c57e24f8ffc96d0b5ef28296f78707d68dc2d21448"}, - {file = "royalnet-5.5.tar.gz", hash = "sha256:e076355fdf7d8730d258a055c22055ee8f309316a9efb3706da6896e0dc36e39"}, + {file = "royalnet-5.6.2-py3-none-any.whl", hash = "sha256:57c9c5de1bbc0a258af489c46eaca326a3b408fe7988fdf6e050f34d5feeaed3"}, + {file = "royalnet-5.6.2.tar.gz", hash = "sha256:b421b84d2cad1ea27016e300f7b005836dd6f5f14975e5b372a91f1f4d52dfd7"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1336,13 +1337,15 @@ toml = [ {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, ] tornado = [ - {file = "tornado-6.0.3-cp35-cp35m-win32.whl", hash = "sha256:c9399267c926a4e7c418baa5cbe91c7d1cf362d505a1ef898fde44a07c9dd8a5"}, - {file = "tornado-6.0.3-cp35-cp35m-win_amd64.whl", hash = "sha256:398e0d35e086ba38a0427c3b37f4337327231942e731edaa6e9fd1865bbd6f60"}, - {file = "tornado-6.0.3-cp36-cp36m-win32.whl", hash = "sha256:4e73ef678b1a859f0cb29e1d895526a20ea64b5ffd510a2307b5998c7df24281"}, - {file = "tornado-6.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:349884248c36801afa19e342a77cc4458caca694b0eda633f5878e458a44cb2c"}, - {file = "tornado-6.0.3-cp37-cp37m-win32.whl", hash = "sha256:559bce3d31484b665259f50cd94c5c28b961b09315ccd838f284687245f416e5"}, - {file = "tornado-6.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:abbe53a39734ef4aba061fca54e30c6b4639d3e1f59653f0da37a0003de148c7"}, - {file = "tornado-6.0.3.tar.gz", hash = "sha256:c845db36ba616912074c5b1ee897f8e0124df269468f25e4fe21fe72f6edd7a9"}, + {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"}, + {file = "tornado-6.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740"}, + {file = "tornado-6.0.4-cp36-cp36m-win32.whl", hash = "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673"}, + {file = "tornado-6.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a"}, + {file = "tornado-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6"}, + {file = "tornado-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b"}, + {file = "tornado-6.0.4-cp38-cp38-win32.whl", hash = "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52"}, + {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"}, + {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, ] tzlocal = [ {file = "tzlocal-2.0.0-py2.py3-none-any.whl", hash = "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048"}, @@ -1419,6 +1422,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.1.24-py2.py3-none-any.whl", hash = "sha256:3ba838c943744cd4f1669f74328b9c0f7814145b92dfcf59c3278caf8175886f"}, - {file = "youtube_dl-2020.1.24.tar.gz", hash = "sha256:82189f971fbe3f4b2e66a9aba7fb5bdd1b4b8c0876d7cd55382045f5555a5e44"}, + {file = "youtube_dl-2020.3.8-py2.py3-none-any.whl", hash = "sha256:f9d33129ea4941bea234cdba811c0f97e61c2235a877cf395a869aeea065e009"}, + {file = "youtube_dl-2020.3.8.tar.gz", hash = "sha256:1b098b7ae41551f46dbae70e56dbabdf39c8faf50e072d0c0b42c44d64afebf8"}, ] diff --git a/pyproject.toml b/pyproject.toml index 27fd4a1a..b7bcb24e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.5.4" + version = "5.5.5" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.5" + version = "^5.6" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index a4e625f5..0db80f3d 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -43,7 +43,7 @@ class DiscordPlayEvent(rc.Event): voice_player = candidate_players[0] else: raise rc.CommandError("Non so in che Server riprodurre questo file...\n" - "Invia il comando su Discord, per favore!") + "Invia il comando su Discord, per favore!") ytds = await rbd.YtdlDiscord.from_url(url) added: List[rbd.YtdlDiscord] = [] diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 0798d650..6ea70aed 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -3,8 +3,6 @@ from .api_bio_get import ApiBioGetStar from .api_bio_set import ApiBioSetStar from .api_diario_get import ApiDiarioGetStar from .api_diario_list import ApiDiarioListStar -from .api_user_list import ApiUserListStar -from .api_user_get import ApiUserGetStar from .api_discord_cv import ApiDiscordCvStar from .api_discord_play import ApiDiscordPlayStar from .api_wiki_edit import ApiWikiEditStar @@ -19,8 +17,6 @@ available_page_stars = [ ApiDiarioListStar, ApiDiscordCvStar, ApiDiscordPlayStar, - ApiUserGetStar, - ApiUserListStar, ApiWikiEditStar, ApiWikiGetStar, ApiWikiListStar, diff --git a/royalpack/stars/api_bio_get.py b/royalpack/stars/api_bio_get.py index 56d2deee..97d71112 100644 --- a/royalpack/stars/api_bio_get.py +++ b/royalpack/stars/api_bio_get.py @@ -7,6 +7,14 @@ from ..utils import find_user_api class ApiBioGetStar(ApiStar): path = "/api/bio/get/v1" + summary = "Get the bio of a Royalnet user." + + parameters = { + "id": "The user to get the bio of." + } + + tags = ["bio"] + async def api(self, data: ApiData) -> dict: user = await find_user_api(data["id"], self.alchemy, data.session) if user.bio is None: diff --git a/royalpack/stars/api_bio_set.py b/royalpack/stars/api_bio_set.py index 5018eb9a..49285ae8 100644 --- a/royalpack/stars/api_bio_set.py +++ b/royalpack/stars/api_bio_set.py @@ -7,7 +7,17 @@ from ..tables import Bio class ApiBioSetStar(ApiStar): path = "/api/bio/set/v1" - methods = ["POST"] + methods = ["PUT"] + + summary = "Set the bio of the logged in Royalnet user." + + parameters = { + "contents": "The contents of the bio." + } + + requires_auth = True + + tags = ["bio"] async def api(self, data: ApiData) -> ru.JSON: contents = data["contents"] diff --git a/royalpack/stars/api_diario_get.py b/royalpack/stars/api_diario_get.py index 6170241b..a0976edb 100644 --- a/royalpack/stars/api_diario_get.py +++ b/royalpack/stars/api_diario_get.py @@ -6,6 +6,14 @@ from ..tables import * class ApiDiarioGetStar(ApiStar): path = "/api/diario/get/v1" + summary = "Get the diario entry with a specific id." + + parameters = { + "id": "The id of the diario entry to get." + } + + tags = ["diario"] + async def api(self, data: ApiData) -> dict: try: diario_id = int(data["id"]) diff --git a/royalpack/stars/api_diario_list.py b/royalpack/stars/api_diario_list.py index 95b29b6f..0ca2b96b 100644 --- a/royalpack/stars/api_diario_list.py +++ b/royalpack/stars/api_diario_list.py @@ -7,6 +7,14 @@ from ..tables import * class ApiDiarioListStar(ApiStar): path = "/api/diario/list/v1" + summary = "Get a list of up to 500 diario entries." + + parameters = { + "page": "The diario page you want to get. Can be negative to get the entries in reverse order." + } + + tags = ["diario"] + async def api(self, data: ApiData) -> dict: page_str = data["page"] try: diff --git a/royalpack/stars/api_discord_cv.py b/royalpack/stars/api_discord_cv.py index a1b9f189..ac4d49de 100644 --- a/royalpack/stars/api_discord_cv.py +++ b/royalpack/stars/api_discord_cv.py @@ -4,6 +4,10 @@ from royalnet.constellation.api import * class ApiDiscordCvStar(ApiStar): path = "/api/discord/cv/v1" + summary = "Get the members status of a single Discord guild. Equivalent to calling /cv in a chat." + + tags = ["discord"] + async def api(self, data: ApiData) -> dict: response = await self.interface.call_herald_event("discord", "discord_cv") return response diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index 26487dc5..b87fe818 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -9,6 +9,16 @@ log = logging.getLogger(__name__) class ApiDiscordPlayStar(ApiStar): path = "/api/discord/play/v1" + summary = "Add a audio file to the RoyalQueue of a Discord Guild." + + parameters = { + "url": "The url of the audio file to add.", + "user": "The name to display in the File Added message.", + "guild_id": "The id of the guild owning the RoyalQueue to add the audio file to." + } + + tags = ["discord"] + async def api(self, data: ApiData) -> dict: url = data["url"] user = data.get("user") diff --git a/royalpack/stars/api_user_get.py b/royalpack/stars/api_user_get.py deleted file mode 100644 index f04d1288..00000000 --- a/royalpack/stars/api_user_get.py +++ /dev/null @@ -1,21 +0,0 @@ -from starlette.requests import Request -from starlette.responses import * -from royalnet.constellation import * -from royalnet.utils import * -from royalnet.backpack.tables import * -from royalnet.constellation.api import * - - -class ApiUserGetStar(ApiStar): - path = "/api/user/get/v1" - - async def api(self, data: ApiData) -> dict: - user_id_str = data["id"] - try: - user_id = int(user_id_str) - except (ValueError, TypeError): - raise InvalidParameterError("'id' is not a valid int.") - user: User = await asyncify(data.session.query(self.alchemy.get(User)).get, user_id) - if user is None: - raise NotFoundError("No such user.") - return user.json() diff --git a/royalpack/stars/api_user_list.py b/royalpack/stars/api_user_list.py deleted file mode 100644 index 44b0aeff..00000000 --- a/royalpack/stars/api_user_list.py +++ /dev/null @@ -1,14 +0,0 @@ -from starlette.requests import Request -from starlette.responses import * -from royalnet.constellation import * -from royalnet.utils import * -from royalnet.backpack.tables import * -from royalnet.constellation.api import * - - -class ApiUserListStar(ApiStar): - path = "/api/user/list/v1" - - async def api(self, data: ApiData) -> dict: - users: typing.List[User] = await asyncify(data.session.query(self.alchemy.get(User)).all) - return [user.json() for user in users] diff --git a/royalpack/stars/api_wiki_edit.py b/royalpack/stars/api_wiki_edit.py index 74f20805..866bf230 100644 --- a/royalpack/stars/api_wiki_edit.py +++ b/royalpack/stars/api_wiki_edit.py @@ -10,6 +10,20 @@ class ApiWikiEditStar(ApiStar): methods = ["POST"] + summary = "Edit the contents of a wiki page, or create a new one." + + parameters = { + "id": "The id of the wiki page to edit. Leave empty to create a new one.", + "title": "The new title of the wiki page.", + "contents": "The new contents of the wiki page.", + "format": "The format of the wiki page. The default is markdown.", + "theme": "The theme of the wiki page. The default is default." + } + + requires_auth = True + + tags = ["wiki"] + async def api(self, data: ApiData) -> ru.JSON: page_id = data.get("id") title = data["title"] diff --git a/royalpack/stars/api_wiki_get.py b/royalpack/stars/api_wiki_get.py index ee1127dd..3f0c843a 100644 --- a/royalpack/stars/api_wiki_get.py +++ b/royalpack/stars/api_wiki_get.py @@ -10,6 +10,14 @@ from royalnet.constellation.api import * class ApiWikiGetStar(ApiStar): path = "/api/wiki/get/v1" + summary = "Get information about a specific wiki page." + + parameters = { + "id": "The id of the wiki page to get information for." + } + + tags = ["wiki"] + async def api(self, data: ApiData) -> dict: wikipage_id_str = data["id"] try: diff --git a/royalpack/stars/api_wiki_list.py b/royalpack/stars/api_wiki_list.py index c4a47095..6592fdd6 100644 --- a/royalpack/stars/api_wiki_list.py +++ b/royalpack/stars/api_wiki_list.py @@ -10,6 +10,10 @@ from royalnet.constellation.api import * class ApiWikiListStar(ApiStar): path = "/api/wiki/list/v1" + summary = "Get a list of available wiki pages." + + tags = ["wiki"] + async def api(self, data: ApiData) -> JSON: pages: typing.List[WikiPage] = await asyncify(data.session.query(self.alchemy.get(WikiPage)).all) return [page.json_list() for page in sorted(pages, key=lambda p: p.title)] From b3699f02f40ca2bf84b927a0e6105bf94dc78d90 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 9 Mar 2020 21:33:44 +0100 Subject: [PATCH 062/227] publish: 5.5.5 --- royalpack/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/version.py b/royalpack/version.py index 28a1bf44..7d9f612a 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.5.4" +semantic = "5.5.5" From 50e188df3b808b6675951ec9fb7a47a5adafeeef Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 18 Mar 2020 17:35:08 +0100 Subject: [PATCH 063/227] Add fiorygi get star --- royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_fiorygi_get.py | 33 +++++++++++++++++++++++++ royalpack/tables/fiorygitransactions.py | 6 ++++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 royalpack/stars/api_fiorygi_get.py diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 6ea70aed..a36a1347 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -8,6 +8,7 @@ from .api_discord_play import ApiDiscordPlayStar from .api_wiki_edit import ApiWikiEditStar from .api_wiki_get import ApiWikiGetStar from .api_wiki_list import ApiWikiListStar +from .api_fiorygi_get import ApiFiorygiGetStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -20,6 +21,7 @@ available_page_stars = [ ApiWikiEditStar, ApiWikiGetStar, ApiWikiListStar, + ApiFiorygiGetStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_fiorygi_get.py b/royalpack/stars/api_fiorygi_get.py new file mode 100644 index 00000000..60da931b --- /dev/null +++ b/royalpack/stars/api_fiorygi_get.py @@ -0,0 +1,33 @@ +from typing import * +from royalnet.utils import * +from royalnet.backpack.tables import * +from royalnet.constellation.api import * +from ..utils import find_user_api +from ..tables import Fiorygi, FiorygiTransaction + + +class ApiFiorygiGetStar(ApiStar): + path = "/api/user/fiorygi/get/v1" + + summary = "Get the fiorygi of a Royalnet user." + + parameters = { + "id": "The user to get the fiorygi of." + } + + tags = ["user"] + + async def api(self, data: ApiData) -> JSON: + user: User = await find_user_api(data["id"], self.alchemy, data.session) + if user.fiorygi is None: + return { + "fiorygi": 0, + "transactions": [], + "warning": "No associated fiorygi table" + } + fiorygi: Fiorygi = user.fiorygi + transactions: JSON = sorted(fiorygi.transactions, key=lambda t: -t.id) + return { + "fiorygi": fiorygi.fiorygi, + "transactions": list(map(lambda t: {"id": t.id, "change": t.change, "reason": t.reason}, transactions)) + } diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py index 75701d0d..28fcbf73 100644 --- a/royalpack/tables/fiorygitransactions.py +++ b/royalpack/tables/fiorygitransactions.py @@ -19,9 +19,13 @@ class FiorygiTransaction: return Column(Integer, ForeignKey("fiorygi.user_id"), nullable=False) @declared_attr - def user(self): + def wallet(self): return relationship("Fiorygi", backref=backref("transactions")) + @property + def user(self): + return self.wallet.user + @declared_attr def reason(self): return Column(String, nullable=False, default="") From e1cd6bffd6012165079899e4e9fa05e05649d054 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 18 Mar 2020 18:06:15 +0100 Subject: [PATCH 064/227] Start work on a Brawlhalla command --- royalpack/tables/__init__.py | 2 ++ royalpack/tables/brawlhalla.py | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 royalpack/tables/brawlhalla.py diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index a15e3c13..ffd97efb 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -9,6 +9,7 @@ from .fiorygi import Fiorygi from .steam import Steam from .dota import Dota from .fiorygitransactions import FiorygiTransaction +from .brawlhalla import Brawlhalla # Enter the tables of your Pack here! available_tables = [ @@ -22,6 +23,7 @@ available_tables = [ Steam, Dota, FiorygiTransaction, + Brawlhalla, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/brawlhalla.py b/royalpack/tables/brawlhalla.py new file mode 100644 index 00000000..df90e723 --- /dev/null +++ b/royalpack/tables/brawlhalla.py @@ -0,0 +1,36 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr +import steam + + +class Brawlhalla: + __tablename__ = "brawlhalla" + + @declared_attr + def brawlhalla_id(self): + return Column(Integer, primary_key=True) + + @declared_attr + def _steamid(self): + return Column(BigInteger, ForeignKey("steam._steamid"), primary_key=True) + + @declared_attr + def steam(self): + return relationship("Steam", backref=backref("brawlhalla", uselist=False)) + + @property + def steamid(self): + return steam.SteamID(self._steamid) + + @declared_attr + def name(self): + return Column(String) + + @declared_attr + def rating_1v1(self): + return Column(Integer) + + @property + def tier_1v1(self): + return Column(String) From f9ec812790e123cfdbdfd190c5ba872834d03a50 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 19 Mar 2020 16:26:11 +0100 Subject: [PATCH 065/227] Add brawlhalla command --- royalpack/commands/__init__.py | 2 + royalpack/commands/brawlhalla.py | 143 ++++++++++++++++++ royalpack/commands/dota.py | 4 +- royalpack/commands/leagueoflegends.py | 2 +- royalpack/tables/brawlhalla.py | 29 +++- royalpack/tables/dota.py | 4 +- royalpack/tables/leagueoflegends.py | 2 +- royalpack/types/__init__.py | 27 ++++ royalpack/types/brawlhallametal.py | 23 +++ royalpack/types/brawlhallarank.py | 36 +++++ royalpack/types/brawlhallatier.py | 23 +++ royalpack/{utils => types}/dotamedal.py | 0 royalpack/{utils => types}/dotarank.py | 0 royalpack/{utils => types}/dotastars.py | 0 royalpack/{utils => types}/leagueleague.py | 0 royalpack/{utils => types}/leaguerank.py | 0 royalpack/{utils => types}/leaguetier.py | 0 royalpack/{utils => types}/mmchoice.py | 0 royalpack/{utils => types}/mminterfacedata.py | 0 royalpack/utils/__init__.py | 17 --- 20 files changed, 285 insertions(+), 27 deletions(-) create mode 100644 royalpack/commands/brawlhalla.py create mode 100644 royalpack/types/__init__.py create mode 100644 royalpack/types/brawlhallametal.py create mode 100644 royalpack/types/brawlhallarank.py create mode 100644 royalpack/types/brawlhallatier.py rename royalpack/{utils => types}/dotamedal.py (100%) rename royalpack/{utils => types}/dotarank.py (100%) rename royalpack/{utils => types}/dotastars.py (100%) rename royalpack/{utils => types}/leagueleague.py (100%) rename royalpack/{utils => types}/leaguerank.py (100%) rename royalpack/{utils => types}/leaguetier.py (100%) rename royalpack/{utils => types}/mmchoice.py (100%) rename royalpack/{utils => types}/mminterfacedata.py (100%) diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 85ca8b39..d3057a48 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -35,6 +35,7 @@ from .steampowered import SteampoweredCommand from .steammatch import SteammatchCommand from .dota import DotaCommand from .magickfiorygi import MagickfiorygiCommand +from .brawlhalla import BrawlhallaCommand # Enter the commands of your Pack here! available_commands = [ @@ -74,6 +75,7 @@ available_commands = [ SteammatchCommand, DotaCommand, MagickfiorygiCommand, + BrawlhallaCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py new file mode 100644 index 00000000..8f0da522 --- /dev/null +++ b/royalpack/commands/brawlhalla.py @@ -0,0 +1,143 @@ +import asyncio +import logging +import sentry_sdk +import aiohttp +from typing import * +from royalnet.commands import * +from royalnet.utils import * +from royalnet.serf.telegram.escape import escape as tg_escape +from ..tables import Steam, Brawlhalla +from ..types import BrawlhallaRank, BrawlhallaMetal, BrawlhallaTier + +log = logging.getLogger(__name__) + + +class BrawlhallaCommand(Command): + name: str = "brawlhalla" + + aliases = ["bh", "bruhalla", "bruhlalla"] + + description: str = "Visualizza le tue statistiche di Dota!" + + syntax: str = "" + + def __init__(self, interface: CommandInterface): + super().__init__(interface) + if self.interface.name == "telegram": + self.loop.create_task(self._updater(900)) + + async def _send(self, message): + client = self.serf.client + await self.serf.api_call(client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=tg_escape(message), + parse_mode="HTML", + disable_webpage_preview=True) + + @staticmethod + def _display(bh: Brawlhalla) -> str: + string = f"ℹ️ [b]{bh.name}[/b]\n\n" + + if bh.rank_1v1: + string += f"1v1: [b]{bh.rank_1v1}[/b]\n" + + return string + + async def _notify(self, + obj: Brawlhalla, + attribute_name: str, + old_value: Any, + new_value: Any): + if attribute_name == "rank_1v1": + old_rank: Optional[BrawlhallaRank] = old_value + new_rank: Optional[BrawlhallaRank] = new_value + if new_rank > old_rank: + message = f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla! Congratulazioni!" + elif new_rank < old_rank: + message = f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla." + else: + return + await self._send(message) + + @staticmethod + async def _change(obj: Brawlhalla, + attribute_name: str, + new_value: Any, + callback: Callable[[Brawlhalla, str, Any, Any], Awaitable[None]]): + old_value = obj.__getattribute__(attribute_name) + if old_value != new_value: + await callback(obj, attribute_name, old_value, new_value) + obj.__setattr__(attribute_name, new_value) + + async def _update(self, steam: Steam, db_session): + BrawlhallaT = self.alchemy.get(Brawlhalla) + log.info(f"Updating: {steam}") + async with aiohttp.ClientSession() as session: + bh: Brawlhalla = steam.brawlhalla + if bh is None: + log.debug(f"Checking if player has an account...") + async with session.get(f"https://api.brawlhalla.com/search?steamid={steam.steamid.as_64}&api_key={self.config['Brawlhalla']['api_key']}") as response: + if response.status != 200: + raise ExternalError(f"Brawlhalla API /search returned {response.status}!") + j = await response.json() + if j == {} or j == []: + log.debug("No account found.") + return + bh = BrawlhallaT( + steam=steam, + brawlhalla_id=j["brawlhalla_id"], + name=j["name"] + ) + db_session.add(bh) + message = f"↔️ Account {bh} connesso a {bh.steam.user}!" + await self._send(message) + async with session.get(f"https://api.brawlhalla.com/player/{bh.brawlhalla_id}/ranked?api_key={self.config['Brawlhalla']['api_key']}") as response: + if response.status != 200: + raise ExternalError(f"Brawlhalla API /ranked returned {response.status}!") + j = await response.json() + if j == {} or j == []: + log.debug("No ranked info found.") + else: + await self._change(bh, "rating_1v1", j["rating"], self._notify) + metal_name, tier_name = j["tier"].split(" ", 1) + metal = BrawlhallaMetal[metal_name.upper()] + tier = BrawlhallaTier(int(tier_name)) + rank = BrawlhallaRank(metal=metal, tier=tier) + await self._change(bh, "rank_1v1", rank, self._notify) + await asyncify(db_session.commit) + + async def _updater(self, period: int): + log.info(f"Started updater with {period}s period") + while True: + log.info(f"Updating...") + session = self.alchemy.Session() + log.info("") + steams = session.query(self.alchemy.get(Steam)).all() + for steam in steams: + try: + await self._update(steam, session) + except Exception as e: + sentry_sdk.capture_exception(e) + log.error(f"Error while updating {steam.user.username}: {e}") + await asyncio.sleep(1) + await asyncify(session.commit) + session.close() + log.info(f"Sleeping for {period}s") + await asyncio.sleep(period) + + async def run(self, args: CommandArgs, data: CommandData) -> None: + author = await data.get_author(error_if_none=True) + + found_something = False + + message = "" + for steam in author.steam: + await self._update(steam, data.session) + if steam.brawlhalla is None: + continue + found_something = True + message += self._display(steam.brawlhalla) + message += "\n" + if not found_something: + raise UserError("Nessun account di Brawlhalla trovato.") + await data.reply(message) diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index ff72c7d8..bfeea743 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -7,7 +7,7 @@ from royalnet.commands import * from royalnet.utils import * from royalnet.serf.telegram.escape import escape as tg_escape from ..tables import Steam, Dota -from ..utils import DotaRank +from ..types import DotaRank log = logging.getLogger(__name__) @@ -15,7 +15,7 @@ log = logging.getLogger(__name__) class DotaCommand(Command): name: str = "dota" - aliases = ["dota2", "doto", "doto2"] + aliases = ["dota2", "doto", "doto2", "dotka", "dotka2"] description: str = "Visualizza le tue statistiche di Dota!" diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index e5d05a1d..a54c7ee3 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -7,7 +7,7 @@ from royalnet.commands import * from royalnet.utils import * from royalnet.serf.telegram import * from ..tables import LeagueOfLegends -from ..utils import LeagueLeague +from ..types import LeagueLeague log = logging.getLogger(__name__) diff --git a/royalpack/tables/brawlhalla.py b/royalpack/tables/brawlhalla.py index df90e723..99d71cce 100644 --- a/royalpack/tables/brawlhalla.py +++ b/royalpack/tables/brawlhalla.py @@ -2,8 +2,10 @@ from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declared_attr import steam +from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal +# noinspection PyAttributeOutsideInit class Brawlhalla: __tablename__ = "brawlhalla" @@ -25,12 +27,33 @@ class Brawlhalla: @declared_attr def name(self): - return Column(String) + return Column(String, nullable=False) @declared_attr def rating_1v1(self): return Column(Integer) - @property + @declared_attr def tier_1v1(self): - return Column(String) + return Column(Enum(BrawlhallaTier)) + + @declared_attr + def metal_1v1(self): + return Column(Enum(BrawlhallaMetal)) + + @property + def rank_1v1(self): + return BrawlhallaRank(metal=self.metal_1v1, tier=self.tier_1v1) + + @rank_1v1.setter + def rank_1v1(self, value): + if not isinstance(value, BrawlhallaRank): + raise TypeError("rank_1v1 can only be set to BrawlhallaRank values.") + self.metal_1v1 = value.metal + self.tier_1v1 = value.tier + + def __repr__(self): + return f"" + + def __str__(self): + return f"[c]brawlhalla:{self.brawlhalla_id}[/c]" \ No newline at end of file diff --git a/royalpack/tables/dota.py b/royalpack/tables/dota.py index 3ec2100d..3c75b0b0 100644 --- a/royalpack/tables/dota.py +++ b/royalpack/tables/dota.py @@ -2,9 +2,7 @@ from typing import * from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declared_attr -from ..utils.dotamedal import DotaMedal -from ..utils.dotastars import DotaStars -from ..utils.dotarank import DotaRank +from ..types import DotaMedal, DotaStars, DotaRank import steam diff --git a/royalpack/tables/leagueoflegends.py b/royalpack/tables/leagueoflegends.py index 87763fc3..4636324a 100644 --- a/royalpack/tables/leagueoflegends.py +++ b/royalpack/tables/leagueoflegends.py @@ -1,7 +1,7 @@ from sqlalchemy import * from sqlalchemy.orm import relationship, composite from sqlalchemy.ext.declarative import declared_attr -from ..utils import LeagueRank, LeagueTier, LeagueLeague +from ..types import LeagueRank, LeagueTier, LeagueLeague class LeagueOfLegends: diff --git a/royalpack/types/__init__.py b/royalpack/types/__init__.py new file mode 100644 index 00000000..722f6b4e --- /dev/null +++ b/royalpack/types/__init__.py @@ -0,0 +1,27 @@ +from .mmchoice import MMChoice +from .mminterfacedata import MMInterfaceData, MMInterfaceDataTelegram +from .leaguetier import LeagueTier +from .leaguerank import LeagueRank +from .leagueleague import LeagueLeague +from .dotamedal import DotaMedal +from .dotastars import DotaStars +from .dotarank import DotaRank +from .brawlhallatier import BrawlhallaTier +from .brawlhallametal import BrawlhallaMetal +from .brawlhallarank import BrawlhallaRank + + +__all__ = [ + "MMChoice", + "MMInterfaceData", + "MMInterfaceDataTelegram", + "LeagueTier", + "LeagueRank", + "LeagueLeague", + "DotaMedal", + "DotaStars", + "DotaRank", + "BrawlhallaMetal", + "BrawlhallaRank", + "BrawlhallaTier", +] diff --git a/royalpack/types/brawlhallametal.py b/royalpack/types/brawlhallametal.py new file mode 100644 index 00000000..6ab20f92 --- /dev/null +++ b/royalpack/types/brawlhallametal.py @@ -0,0 +1,23 @@ +import enum + + +class BrawlhallaMetal(enum.Enum): + TIN = 0 + BRONZE = 1 + SILVER = 2 + GOLD = 3 + PLATINUM = 4 + DIAMOND = 5 + + def __str__(self): + return self.name.capitalize() + + def __repr__(self): + return f"{self.__class__.__qualname__}.{self.name}" + + def __gt__(self, other): + if other is None: + return True + if not isinstance(other, self.__class__): + raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}") + return self.value > other.value diff --git a/royalpack/types/brawlhallarank.py b/royalpack/types/brawlhallarank.py new file mode 100644 index 00000000..f1419dc1 --- /dev/null +++ b/royalpack/types/brawlhallarank.py @@ -0,0 +1,36 @@ +from .brawlhallametal import BrawlhallaMetal +from .brawlhallatier import BrawlhallaTier + + +class BrawlhallaRank: + __slots__ = "metal", "tier" + + def __init__(self, metal: BrawlhallaMetal, tier: BrawlhallaTier): + self.metal: BrawlhallaMetal = metal + self.tier: BrawlhallaTier = tier + + def __gt__(self, other): + if other is None: + return True + if not isinstance(other, self.__class__): + raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}") + if self.metal > other.metal: + return True + elif self.metal < other.metal: + return False + elif self.tier > other.tier: + return True + return False + + def __eq__(self, other): + if other is None: + return False + if not isinstance(other, self.__class__): + raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}") + return self.metal == other.metal and self.tier == other.tier + + def __repr__(self): + return f"<{self.__class__.__qualname__}: {self.metal} {self.tier}>" + + def __str__(self): + return f"{self.metal} {self.tier}" diff --git a/royalpack/types/brawlhallatier.py b/royalpack/types/brawlhallatier.py new file mode 100644 index 00000000..cac66713 --- /dev/null +++ b/royalpack/types/brawlhallatier.py @@ -0,0 +1,23 @@ +import enum + + +class BrawlhallaTier(enum.Enum): + ZERO = 0 + I = 1 + II = 2 + III = 3 + IV = 4 + V = 5 + + def __str__(self): + return str(self.value) + + def __repr__(self): + return f"{self.__class__.__qualname__}.{self.name}" + + def __gt__(self, other): + if other is None: + return True + if not isinstance(other, self.__class__): + raise TypeError(f"Can't compare {self.__class__.__qualname__} with {other.__class__.__qualname__}") + return self.value > other.value diff --git a/royalpack/utils/dotamedal.py b/royalpack/types/dotamedal.py similarity index 100% rename from royalpack/utils/dotamedal.py rename to royalpack/types/dotamedal.py diff --git a/royalpack/utils/dotarank.py b/royalpack/types/dotarank.py similarity index 100% rename from royalpack/utils/dotarank.py rename to royalpack/types/dotarank.py diff --git a/royalpack/utils/dotastars.py b/royalpack/types/dotastars.py similarity index 100% rename from royalpack/utils/dotastars.py rename to royalpack/types/dotastars.py diff --git a/royalpack/utils/leagueleague.py b/royalpack/types/leagueleague.py similarity index 100% rename from royalpack/utils/leagueleague.py rename to royalpack/types/leagueleague.py diff --git a/royalpack/utils/leaguerank.py b/royalpack/types/leaguerank.py similarity index 100% rename from royalpack/utils/leaguerank.py rename to royalpack/types/leaguerank.py diff --git a/royalpack/utils/leaguetier.py b/royalpack/types/leaguetier.py similarity index 100% rename from royalpack/utils/leaguetier.py rename to royalpack/types/leaguetier.py diff --git a/royalpack/utils/mmchoice.py b/royalpack/types/mmchoice.py similarity index 100% rename from royalpack/utils/mmchoice.py rename to royalpack/types/mmchoice.py diff --git a/royalpack/utils/mminterfacedata.py b/royalpack/types/mminterfacedata.py similarity index 100% rename from royalpack/utils/mminterfacedata.py rename to royalpack/types/mminterfacedata.py diff --git a/royalpack/utils/__init__.py b/royalpack/utils/__init__.py index ba204e8f..814c9eed 100644 --- a/royalpack/utils/__init__.py +++ b/royalpack/utils/__init__.py @@ -1,24 +1,7 @@ -from .mmchoice import MMChoice -from .mminterfacedata import MMInterfaceData, MMInterfaceDataTelegram -from .leaguetier import LeagueTier -from .leaguerank import LeagueRank -from .leagueleague import LeagueLeague from .royalqueue import RoyalQueue -from .dotamedal import DotaMedal -from .dotastars import DotaStars -from .dotarank import DotaRank from .finduser import find_user_api __all__ = [ - "MMChoice", - "MMInterfaceData", - "MMInterfaceDataTelegram", - "LeagueTier", - "LeagueRank", - "LeagueLeague", "RoyalQueue", - "DotaMedal", - "DotaStars", - "DotaRank", "find_user_api", ] From a4c472a79ed864e4a968c23f2d44bd0d5cf356e1 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 19 Mar 2020 16:30:57 +0100 Subject: [PATCH 066/227] publish: 5.6 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b7bcb24e..b1e849c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.5.5" + version = "5.6" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 7d9f612a..4705c69e 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.5.5" +semantic = "5.6" From 70d2b5fee5546cf9058efc943d9139907670e8eb Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 23 Mar 2020 02:55:25 +0100 Subject: [PATCH 067/227] Add diarioshuffle command and api_diario_random.py --- royalpack/commands/__init__.py | 2 ++ royalpack/commands/diarioshuffle.py | 28 +++++++++++++++++++++++ royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_diario_random.py | 34 ++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 royalpack/commands/diarioshuffle.py create mode 100644 royalpack/stars/api_diario_random.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index d3057a48..0df9b6f8 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -36,6 +36,7 @@ from .steammatch import SteammatchCommand from .dota import DotaCommand from .magickfiorygi import MagickfiorygiCommand from .brawlhalla import BrawlhallaCommand +from .diarioshuffle import DiarioshuffleCommand # Enter the commands of your Pack here! available_commands = [ @@ -76,6 +77,7 @@ available_commands = [ DotaCommand, MagickfiorygiCommand, BrawlhallaCommand, + DiarioshuffleCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/diarioshuffle.py b/royalpack/commands/diarioshuffle.py new file mode 100644 index 00000000..8baa7a37 --- /dev/null +++ b/royalpack/commands/diarioshuffle.py @@ -0,0 +1,28 @@ +from typing import * +from royalnet.commands import * +from royalnet.utils import * +from ..tables import Diario +from sqlalchemy import func + + +class DiarioshuffleCommand(Command): + name: str = "diarioshuffle" + + description: str = "Cita una riga casuale del diario." + + aliases = ["dis", "dishuffle", "dish"] + + syntax = "" + + async def run(self, args: CommandArgs, data: CommandData) -> None: + DiarioT = self.alchemy.get(Diario) + entry: List[Diario] = await asyncify( + data.session + .query(DiarioT) + .order_by(func.random()) + .limit(1) + .one_or_none + ) + if entry is None: + raise CommandError("Nessuna riga del diario trovata.") + await data.reply(f"ℹ️ {entry}") diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index a36a1347..140044c3 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -9,6 +9,7 @@ from .api_wiki_edit import ApiWikiEditStar from .api_wiki_get import ApiWikiGetStar from .api_wiki_list import ApiWikiListStar from .api_fiorygi_get import ApiFiorygiGetStar +from .api_diario_random import ApiDiarioRandomStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -22,6 +23,7 @@ available_page_stars = [ ApiWikiGetStar, ApiWikiListStar, ApiFiorygiGetStar, + ApiDiarioRandomStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_diario_random.py b/royalpack/stars/api_diario_random.py new file mode 100644 index 00000000..3a2fc413 --- /dev/null +++ b/royalpack/stars/api_diario_random.py @@ -0,0 +1,34 @@ +from typing import * +from royalnet.constellation.api import * +from royalnet.utils import * +from ..tables import * +from sqlalchemy import func + + +class ApiDiarioRandomStar(ApiStar): + path = "/api/diario/random/v1" + + summary = "Get random diario entries." + + parameters = { + "amount": "The number of diario entries to get." + } + + tags = ["diario"] + + async def api(self, data: ApiData) -> JSON: + DiarioT = self.alchemy.get(Diario) + try: + amount = int(data["amount"]) + except ValueError: + raise InvalidParameterError("'amount' is not a valid int.") + entries: List[Diario] = await asyncify( + data.session + .query(DiarioT) + .order_by(func.random()) + .limit(amount) + .all + ) + if len(entries) < amount: + raise NotFoundError("Not enough diario entries.") + return list(map(lambda e: e.json(), entries)) From 091203357c1a1914b2dd97a0cee77675767f8ae6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 23 Mar 2020 03:00:55 +0100 Subject: [PATCH 068/227] publish: 5.6.1 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b1e849c9..b4a6dd4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6" + version = "5.6.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 4705c69e..214a6363 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6" +semantic = "5.6.1" From fa039f35c3b33ea4df27ca40d721c3907a13dfa9 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 23 Mar 2020 22:38:37 +0100 Subject: [PATCH 069/227] Add initial polls support --- royalpack/commands/brawlhalla.py | 2 +- royalpack/stars/__init__.py | 6 +++ royalpack/stars/api_polls_create.py | 41 ++++++++++++++++++ royalpack/stars/api_polls_get.py | 34 +++++++++++++++ royalpack/stars/api_polls_list.py | 28 +++++++++++++ royalpack/tables/__init__.py | 6 +++ royalpack/tables/pollcomments.py | 41 ++++++++++++++++++ royalpack/tables/polls.py | 64 +++++++++++++++++++++++++++++ royalpack/tables/pollvotes.py | 33 +++++++++++++++ royalpack/types/__init__.py | 2 + royalpack/types/pollmood.py | 7 ++++ 11 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 royalpack/stars/api_polls_create.py create mode 100644 royalpack/stars/api_polls_get.py create mode 100644 royalpack/stars/api_polls_list.py create mode 100644 royalpack/tables/pollcomments.py create mode 100644 royalpack/tables/polls.py create mode 100644 royalpack/tables/pollvotes.py create mode 100644 royalpack/types/pollmood.py diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index 8f0da522..e1c7dcb4 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -39,7 +39,7 @@ class BrawlhallaCommand(Command): string = f"ℹ️ [b]{bh.name}[/b]\n\n" if bh.rank_1v1: - string += f"1v1: [b]{bh.rank_1v1}[/b]\n" + string += f"1v1: [b]{bh.rank_1v1}[/b] ({bh.rating_1v1} MMR)\n" return string diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 140044c3..db781e92 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -10,6 +10,9 @@ from .api_wiki_get import ApiWikiGetStar from .api_wiki_list import ApiWikiListStar from .api_fiorygi_get import ApiFiorygiGetStar from .api_diario_random import ApiDiarioRandomStar +from .api_polls_create import ApiPollsCreate +from .api_polls_get import ApiPollsGet +from .api_polls_list import ApiPollsList # Enter the PageStars of your Pack here! available_page_stars = [ @@ -24,6 +27,9 @@ available_page_stars = [ ApiWikiListStar, ApiFiorygiGetStar, ApiDiarioRandomStar, + ApiPollsCreate, + ApiPollsGet, + ApiPollsList, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_polls_create.py b/royalpack/stars/api_polls_create.py new file mode 100644 index 00000000..50105ee0 --- /dev/null +++ b/royalpack/stars/api_polls_create.py @@ -0,0 +1,41 @@ +from typing import * +import datetime +import uuid +from royalnet.utils import * +from royalnet.constellation.api import * +from ..tables import Poll + + +class ApiPollsCreate(ApiStar): + path = "/api/polls/create/v1" + + summary = "Create a new poll." + + parameters = { + "question": "The question to ask in the poll.", + "description": "A longer Markdown-formatted description.", + "expires": "A ISO timestamp of the expiration date for the poll.", + } + + requires_auth = True + + methods = ["POST"] + + tags = ["polls"] + + async def api(self, data: ApiData) -> JSON: + PollT = self.alchemy.get(Poll) + + poll = PollT( + id=uuid.uuid4(), + creator=await data.user(), + created=datetime.datetime.now(), + expires=datetime.datetime.fromisoformat(data["expires"]) if "expires" in data else None, + question=data["question"], + description=data.get("description"), + ) + + data.session.add(poll) + await data.session_commit() + + return poll.json() diff --git a/royalpack/stars/api_polls_get.py b/royalpack/stars/api_polls_get.py new file mode 100644 index 00000000..4208dfa7 --- /dev/null +++ b/royalpack/stars/api_polls_get.py @@ -0,0 +1,34 @@ +from typing import * +import datetime +from royalnet.utils import * +from royalnet.constellation.api import * +from ..tables import Poll +import uuid + + +class ApiPollsGet(ApiStar): + path = "/api/polls/get/v1" + + summary = "Get the poll with a specific id." + + parameters = { + "uuid": "The UUID of the poll to get.", + } + + requires_auth = True + + tags = ["polls"] + + async def api(self, data: ApiData) -> JSON: + PollT = self.alchemy.get(Poll) + + try: + pid = uuid.UUID(data["uuid"]) + except (ValueError, AttributeError, TypeError): + raise InvalidParameterError("'uuid' is not a valid UUID.") + + poll: Poll = await asyncify(data.session.query(PollT).get, pid) + if poll is None: + raise NotFoundError("No such page.") + + return poll.json() diff --git a/royalpack/stars/api_polls_list.py b/royalpack/stars/api_polls_list.py new file mode 100644 index 00000000..3b007362 --- /dev/null +++ b/royalpack/stars/api_polls_list.py @@ -0,0 +1,28 @@ +from typing import * +from royalnet.utils import * +from royalnet.constellation.api import * +from ..tables import Poll +import uuid + + +class ApiPollsList(ApiStar): + path = "/api/polls/list/v1" + + summary = "Get a list of all polls." + + requires_auth = True + + tags = ["polls"] + + async def api(self, data: ApiData) -> JSON: + PollT = self.alchemy.get(Poll) + + polls: List[Poll] = await asyncify(data.session.query(PollT).all) + + return list(map(lambda p: { + "id": p.id, + "question": p.question, + "creator": p.creator.json(), + "expires": p.expires.isoformat(), + "created": p.created.isoformat(), + }, polls)) diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index ffd97efb..87099de9 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -10,6 +10,9 @@ from .steam import Steam from .dota import Dota from .fiorygitransactions import FiorygiTransaction from .brawlhalla import Brawlhalla +from .polls import Poll +from .pollcomments import PollComment +from .pollvotes import PollVote # Enter the tables of your Pack here! available_tables = [ @@ -24,6 +27,9 @@ available_tables = [ Dota, FiorygiTransaction, Brawlhalla, + Poll, + PollComment, + PollVote, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/pollcomments.py b/royalpack/tables/pollcomments.py new file mode 100644 index 00000000..f39851de --- /dev/null +++ b/royalpack/tables/pollcomments.py @@ -0,0 +1,41 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr +from sqlalchemy.dialects.postgresql import UUID +from ..types import PollMood + + +class PollComment: + __tablename__ = "pollcomments" + + @declared_attr + def id(self): + return Column(Integer, primary_key=True) + + @declared_attr + def author_id(self): + return Column(Integer, ForeignKey("users.uid"), nullable=False) + + @declared_attr + def author(self): + return relationship("User", backref=backref("poll_comments_created")) + + @declared_attr + def poll_id(self): + return Column(UUID(as_uuid=True), ForeignKey("polls.id")) + + @declared_attr + def poll(self): + return relationship("Poll", backref=backref("comments")) + + @declared_attr + def posted(self): + return Column(DateTime, nullable=False) + + @declared_attr + def mood(self): + return Column(Enum(PollMood), nullable=False, default=PollMood.NEUTRAL) + + @declared_attr + def comment(self): + return Column(Text) diff --git a/royalpack/tables/polls.py b/royalpack/tables/polls.py new file mode 100644 index 00000000..d45d512d --- /dev/null +++ b/royalpack/tables/polls.py @@ -0,0 +1,64 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr +from sqlalchemy.dialects.postgresql import UUID + + +class Poll: + __tablename__ = "polls" + + @declared_attr + def id(self): + return Column(UUID(as_uuid=True), primary_key=True) + + @declared_attr + def question(self): + return Column(String, nullable=False) + + @declared_attr + def description(self): + return Column(Text, nullable=False, server_default="") + + @declared_attr + def creator_id(self): + return Column(Integer, ForeignKey("users.uid")) + + @declared_attr + def creator(self): + return relationship("User", backref=backref("polls_created")) + + @declared_attr + def expires(self): + return Column(DateTime) + + @declared_attr + def created(self): + return Column(DateTime, nullable=False) + + def json(self): + return { + "id": self.id, + "question": self.question, + "description": self.description, + "creator": self.creator.json(), + "expires": self.expires.isoformat(), + "created": self.created.isoformat(), + "votes": map( + lambda v: { + "caster": v.caster.json(), + "posted": v.posted.isoformat(), + "vote": v.vote.name + }, + sorted(self.votes, key=lambda v: v.posted) + ), + "comments": map( + lambda c: { + "id": c.id, + "comment": c.comment, + "creator": c.creator.json(), + "posted": c.posted.isoformat(), + "mood": c.mood.name, + }, + sorted(self.comments, key=lambda c: c.posted) + ) + } diff --git a/royalpack/tables/pollvotes.py b/royalpack/tables/pollvotes.py new file mode 100644 index 00000000..f4886c04 --- /dev/null +++ b/royalpack/tables/pollvotes.py @@ -0,0 +1,33 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr +from ..types import PollMood +from sqlalchemy.dialects.postgresql import UUID + + +class PollVote: + __tablename__ = "pollvotes" + + @declared_attr + def caster_id(self): + return Column(Integer, ForeignKey("users.uid"), primary_key=True) + + @declared_attr + def caster(self): + return relationship("User", backref=backref("poll_votes_cast")) + + @declared_attr + def poll_id(self): + return Column(UUID(as_uuid=True), ForeignKey("polls.id"), primary_key=True) + + @declared_attr + def poll(self): + return relationship("Poll", backref=backref("votes")) + + @declared_attr + def posted(self): + return Column(DateTime, nullable=False) + + @declared_attr + def vote(self): + return Column(Enum(PollMood), nullable=False, default=PollMood.NEUTRAL) diff --git a/royalpack/types/__init__.py b/royalpack/types/__init__.py index 722f6b4e..88f28a85 100644 --- a/royalpack/types/__init__.py +++ b/royalpack/types/__init__.py @@ -9,6 +9,7 @@ from .dotarank import DotaRank from .brawlhallatier import BrawlhallaTier from .brawlhallametal import BrawlhallaMetal from .brawlhallarank import BrawlhallaRank +from .pollmood import PollMood __all__ = [ @@ -24,4 +25,5 @@ __all__ = [ "BrawlhallaMetal", "BrawlhallaRank", "BrawlhallaTier", + "PollMood", ] diff --git a/royalpack/types/pollmood.py b/royalpack/types/pollmood.py new file mode 100644 index 00000000..e5bf11d4 --- /dev/null +++ b/royalpack/types/pollmood.py @@ -0,0 +1,7 @@ +import enum + + +class PollMood(enum.Enum): + POSITIVE = 1 + NEUTRAL = 0 + NEGATIVE = -1 From d6b4be55afd4477ffd03e141fde693a216125896 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 24 Mar 2020 00:02:55 +0100 Subject: [PATCH 070/227] Add brawlhalla duos --- royalpack/commands/brawlhalla.py | 88 ++++++++++++++++++++++++++---- royalpack/tables/__init__.py | 2 + royalpack/tables/brawlhalla.py | 34 +++++++++++- royalpack/tables/brawlhalladuos.py | 58 ++++++++++++++++++++ 4 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 royalpack/tables/brawlhalladuos.py diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index e1c7dcb4..7dd1461e 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -6,8 +6,9 @@ from typing import * from royalnet.commands import * from royalnet.utils import * from royalnet.serf.telegram.escape import escape as tg_escape -from ..tables import Steam, Brawlhalla +from ..tables import Steam, Brawlhalla, BrawlhallaDuo from ..types import BrawlhallaRank, BrawlhallaMetal, BrawlhallaTier +from sqlalchemy import or_, and_ log = logging.getLogger(__name__) @@ -36,15 +37,30 @@ class BrawlhallaCommand(Command): @staticmethod def _display(bh: Brawlhalla) -> str: - string = f"ℹ️ [b]{bh.name}[/b]\n\n" + string = [f"ℹ️ [b]{bh.name}[/b]", ""] if bh.rank_1v1: - string += f"1v1: [b]{bh.rank_1v1}[/b] ({bh.rating_1v1} MMR)\n" + string.append("👤 [b]1v1[/b]") + string.append(f"[b]{bh.rank_1v1}[/b] ({bh.rating_1v1} MMR)") + string.append("") - return string + duos = bh.duos + + if len(bh.duos) != 0: + string.append(f"👥 [b]2v2[/b]") + + for duo in bh.duos: + + other = duo.other(bh) + string.append(f"Con [b]{other.steam.user}[/b]: [b]{duo.rank_2v2}[/b] ({duo.rating_2v2} MMR)") + + if len(bh.duos) != 0: + string.append("") + + return "\n".join(string) async def _notify(self, - obj: Brawlhalla, + obj: Union[Brawlhalla, BrawlhallaDuo], attribute_name: str, old_value: Any, new_value: Any): @@ -53,17 +69,23 @@ class BrawlhallaCommand(Command): new_rank: Optional[BrawlhallaRank] = new_value if new_rank > old_rank: message = f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla! Congratulazioni!" - elif new_rank < old_rank: - message = f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla." else: - return + message = f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla." + await self._send(message) + elif attribute_name == "rank_2v2": + old_rank: Optional[BrawlhallaRank] = old_value + new_rank: Optional[BrawlhallaRank] = new_value + if new_rank > old_rank: + message = f"📈 [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono saliti a [b]{new_value}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla! Congratulazioni!" + else: + message = f"📉 [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono scesi a [b]{new_value}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla." await self._send(message) @staticmethod - async def _change(obj: Brawlhalla, + async def _change(obj: Union[Brawlhalla, BrawlhallaDuo], attribute_name: str, new_value: Any, - callback: Callable[[Brawlhalla, str, Any, Any], Awaitable[None]]): + callback: Callable[[Union[Brawlhalla, BrawlhallaDuo], str, Any, Any], Awaitable[None]]): old_value = obj.__getattribute__(attribute_name) if old_value != new_value: await callback(obj, attribute_name, old_value, new_value) @@ -71,6 +93,7 @@ class BrawlhallaCommand(Command): async def _update(self, steam: Steam, db_session): BrawlhallaT = self.alchemy.get(Brawlhalla) + DuoT = self.alchemy.get(BrawlhallaDuo) log.info(f"Updating: {steam}") async with aiohttp.ClientSession() as session: bh: Brawlhalla = steam.brawlhalla @@ -104,6 +127,48 @@ class BrawlhallaCommand(Command): tier = BrawlhallaTier(int(tier_name)) rank = BrawlhallaRank(metal=metal, tier=tier) await self._change(bh, "rank_1v1", rank, self._notify) + + for jduo in j.get("2v2", []): + bhduo: Optional[BrawlhallaDuo] = await asyncify( + db_session.query(DuoT) + .filter( + or_( + and_( + DuoT.id_one == jduo["brawlhalla_id_one"], + DuoT.id_two == jduo["brawlhalla_id_two"] + ), + and_( + DuoT.id_one == jduo["brawlhalla_id_two"], + DuoT.id_two == jduo["brawlhalla_id_one"] + ) + ) + ) + .one_or_none + ) + if bhduo is None: + if bh.brawlhalla_id == jduo["brawlhalla_id_one"]: + otherbh: Optional[Brawlhalla] = await asyncify( + db_session.query(BrawlhallaT).get, jduo["brawlhalla_id_two"] + ) + else: + otherbh: Optional[Brawlhalla] = await asyncify( + db_session.query(BrawlhallaT).get, jduo["brawlhalla_id_one"] + ) + if otherbh is None: + continue + bhduo = DuoT( + one=bh, + two=otherbh, + ) + + db_session.add(bhduo) + await self._change(bhduo, "rating_2v2", jduo["rating"], self._notify) + metal_name, tier_name = jduo["tier"].split(" ", 1) + metal = BrawlhallaMetal[metal_name.upper()] + tier = BrawlhallaTier(int(tier_name)) + rank = BrawlhallaRank(metal=metal, tier=tier) + await self._change(bhduo, "rank_2v2", rank, self._notify) + await asyncify(db_session.commit) async def _updater(self, period: int): @@ -117,8 +182,7 @@ class BrawlhallaCommand(Command): try: await self._update(steam, session) except Exception as e: - sentry_sdk.capture_exception(e) - log.error(f"Error while updating {steam.user.username}: {e}") + sentry_exc(e) await asyncio.sleep(1) await asyncify(session.commit) session.close() diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 87099de9..71db86ca 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -13,6 +13,7 @@ from .brawlhalla import Brawlhalla from .polls import Poll from .pollcomments import PollComment from .pollvotes import PollVote +from .brawlhalladuos import BrawlhallaDuo # Enter the tables of your Pack here! available_tables = [ @@ -30,6 +31,7 @@ available_tables = [ Poll, PollComment, PollVote, + BrawlhallaDuo, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/brawlhalla.py b/royalpack/tables/brawlhalla.py index 99d71cce..27b60d66 100644 --- a/royalpack/tables/brawlhalla.py +++ b/royalpack/tables/brawlhalla.py @@ -15,7 +15,7 @@ class Brawlhalla: @declared_attr def _steamid(self): - return Column(BigInteger, ForeignKey("steam._steamid"), primary_key=True) + return Column(BigInteger, ForeignKey("steam._steamid"), unique=True) @declared_attr def steam(self): @@ -52,6 +52,38 @@ class Brawlhalla: self.metal_1v1 = value.metal self.tier_1v1 = value.tier + @property + def duos(self): + return [*self._duos_one, *self._duos_two] + + @property + def rating_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].rating_2v2 + + @property + def tier_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].tier_2v2 + + @property + def metal_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].metal_2v2 + + @property + def rank_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].rank_2v2 + def __repr__(self): return f"" diff --git a/royalpack/tables/brawlhalladuos.py b/royalpack/tables/brawlhalladuos.py new file mode 100644 index 00000000..1561cc2d --- /dev/null +++ b/royalpack/tables/brawlhalladuos.py @@ -0,0 +1,58 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr +from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal + + +class BrawlhallaDuo: + __tablename__ = "brawlhalladuos" + + @declared_attr + def id_one(self): + return Column(Integer, ForeignKey("brawlhalla.brawlhalla_id"), primary_key=True) + + @declared_attr + def id_two(self): + return Column(Integer, ForeignKey("brawlhalla.brawlhalla_id"), primary_key=True) + + @declared_attr + def one(self): + return relationship("Brawlhalla", foreign_keys=self.id_one, backref=backref("_duos_one")) + + @declared_attr + def two(self): + return relationship("Brawlhalla", foreign_keys=self.id_two, backref=backref("_duos_two")) + + @declared_attr + def rating_2v2(self): + return Column(Integer) + + @declared_attr + def tier_2v2(self): + return Column(Enum(BrawlhallaTier)) + + @declared_attr + def metal_2v2(self): + return Column(Enum(BrawlhallaMetal)) + + @property + def rank_2v2(self): + return BrawlhallaRank(metal=self.metal_2v2, tier=self.tier_2v2) + + @rank_2v2.setter + def rank_2v2(self, value): + if not isinstance(value, BrawlhallaRank): + raise TypeError("rank_1v1 can only be set to BrawlhallaRank values.") + self.metal_2v2 = value.metal + self.tier_2v2 = value.tier + + def other(self, bh): + if bh == self.one: + return self.two + elif bh == self.two: + return self.one + else: + raise ValueError("Argument is unrelated to this duo.") + + def __repr__(self): + return f"" From 99c4207cafee35bda7ee82a076366af1272df7d3 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 24 Mar 2020 00:03:07 +0100 Subject: [PATCH 071/227] publish: 5.6.2 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b4a6dd4a..ae318a03 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6.1" + version = "5.6.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 214a6363..3e2df96c 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6.1" +semantic = "5.6.2" From 7db084c7244f8736bd53e274850d6be5dbf3a2a9 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 28 Mar 2020 18:38:28 +0100 Subject: [PATCH 072/227] Correggi la descrizione di Funkwhale --- royalpack/commands/funkwhale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index 1c0507b1..5571a017 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -9,7 +9,7 @@ class FunkwhaleCommand(PlayCommand): aliases = ["fuckwhale", "fw", "royalwhale", "rw"] - description: str = "Cerca un video su RoyalWhale e lo aggiunge alla coda della chat vocale." + description: str = "Cerca una canzone su RoyalWhale e aggiungila alla coda della chat vocale." syntax = "{ricerca}" From 36b06c574a09bf1d74a2b465818b5c5b83f22eff Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 28 Mar 2020 19:38:14 +0100 Subject: [PATCH 073/227] Add !funkwhaleplaylist command --- poetry.lock | 45 +++++++++++++----------- pyproject.toml | 4 +-- royalpack/commands/__init__.py | 2 ++ royalpack/commands/funkwhale.py | 4 +-- royalpack/commands/funkwhaleplaylist.py | 32 +++++++++++++++++ royalpack/commands/googlevideo.py | 4 +-- royalpack/commands/play.py | 13 ++++--- royalpack/commands/soundcloud.py | 4 +-- royalpack/commands/yahoovideo.py | 4 +-- royalpack/commands/youtube.py | 4 +-- royalpack/events/discord_play.py | 46 ++++++++++--------------- royalpack/version.py | 2 +- 12 files changed, 99 insertions(+), 65 deletions(-) create mode 100644 royalpack/commands/funkwhaleplaylist.py diff --git a/poetry.lock b/poetry.lock index db53d3d1..653e5c50 100644 --- a/poetry.lock +++ b/poetry.lock @@ -86,7 +86,7 @@ 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" +version = "7.1.1" [[package]] category = "main" @@ -186,7 +186,7 @@ description = "Python audio data toolkit (ID3 and MP3)" name = "eyed3" optional = false python-versions = "*" -version = "0.9.3" +version = "0.9.4" [package.dependencies] deprecation = "*" @@ -217,7 +217,7 @@ description = "Infer file type and MIME type of any file/buffer. No external dep name = "filetype" optional = false python-versions = "*" -version = "1.0.5" +version = "1.0.6" [[package]] category = "main" @@ -486,7 +486,7 @@ description = "Persistent/Functional/Immutable data structures" name = "pyrsistent" optional = false python-versions = "*" -version = "0.15.7" +version = "0.16.0" [package.dependencies] six = "*" @@ -586,7 +586,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.6.2" +version = "5.6.5" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -716,7 +716,7 @@ description = "Database Abstraction Library" name = "sqlalchemy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.13" +version = "1.3.15" [package.extras] mssql = ["pyodbc"] @@ -864,10 +864,10 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.3.8" +version = "2020.3.24" [metadata] -content-hash = "8d7780d1bc898479dda8255988247547650f4034a3ef6e37db47f7ccda1a9d5f" +content-hash = "f0931c9aade41f1ac239401a324cb550f0961b83c1759b5a84effb10e1bba7f2" python-versions = "^3.8" [metadata.files] @@ -952,8 +952,8 @@ chardet = [ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] click = [ - {file = "click-7.1-py2.py3-none-any.whl", hash = "sha256:91eb2c43db0254aaf3b14a3c4e0db914a900aa09bbc33c6e87ede4a8f7c969dc"}, - {file = "click-7.1.tar.gz", hash = "sha256:482f552f2d5452b9eeffc44165e8b790dd53f75bcce099a812b65e0357e860e2"}, + {file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"}, + {file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"}, ] colorama = [ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, @@ -1002,17 +1002,17 @@ deprecation = [ {file = "discord.py-1.3.2-py3-none-any.whl", hash = "sha256:7424be26b07b37ecad4404d9383d685995a0e0b3df3f9c645bdd3a4d977b83b4"}, ] eyed3 = [ - {file = "eyeD3-0.9.3-py2.py3-none-any.whl", hash = "sha256:82e838a45db298bedf5bfa284e936f9c2216550106d47673bafa1ae262292a36"}, - {file = "eyeD3-0.9.3-py3.8.egg", hash = "sha256:cb750a56163a55181a840bd5f6a78299de247c19c97160055c65e39066a3e422"}, - {file = "eyeD3-0.9.3.tar.gz", hash = "sha256:33020d86aa1ffb4a130e10c27d0c3f9fa05989b862d454e95195ff08eeb67375"}, + {file = "eyeD3-0.9.4-py2.py3-none-any.whl", hash = "sha256:4cba88297ded486ac5b127b4dd5944c453be52c015ed82400fde30907e2972f8"}, + {file = "eyeD3-0.9.4-py3.8.egg", hash = "sha256:b7ac8695d7acdbd67d5e6edc48e9e082faae40ed852cf3e0fcd6d878624ee8d4"}, + {file = "eyeD3-0.9.4.tar.gz", hash = "sha256:11099464e438c11a1d701e723a5065c1556fb59878ad9dce29f924dac3a07a96"}, ] 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.5-py2.py3-none-any.whl", hash = "sha256:4967124d982a71700d94a08c49c4926423500e79382a92070f5ab248d44fe461"}, - {file = "filetype-1.0.5.tar.gz", hash = "sha256:17a3b885f19034da29640b083d767e0f13c2dcb5dcc267945c8b6e5a5a9013c7"}, + {file = "filetype-1.0.6-py2.py3-none-any.whl", hash = "sha256:fd6d0ec56820acccf8c9fb6c3ba7e04a302f6ff6c70bcc09daf4842ae9e2ac30"}, + {file = "filetype-1.0.6.tar.gz", hash = "sha256:99d2b923921cadbe6e451249091ca7156b4beaee6e741bd711a582d4dd2f2881"}, ] future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, @@ -1065,6 +1065,9 @@ greenlet = [ {file = "greenlet-0.4.15-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214"}, {file = "greenlet-0.4.15-cp37-cp37m-win32.whl", hash = "sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043"}, {file = "greenlet-0.4.15-cp37-cp37m-win_amd64.whl", hash = "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304"}, + {file = "greenlet-0.4.15-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e538b8dae561080b542b0f5af64d47ef859f22517f7eca617bb314e0e03fd7ef"}, + {file = "greenlet-0.4.15-cp38-cp38-win32.whl", hash = "sha256:51155342eb4d6058a0ffcd98a798fe6ba21195517da97e15fca3db12ab201e6e"}, + {file = "greenlet-0.4.15-cp38-cp38-win_amd64.whl", hash = "sha256:7457d685158522df483196b16ec648b28f8e847861adb01a55d41134e7734122"}, {file = "greenlet-0.4.15.tar.gz", hash = "sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc"}, ] h11 = [ @@ -1259,7 +1262,7 @@ pyreadline = [ {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, ] pyrsistent = [ - {file = "pyrsistent-0.15.7.tar.gz", hash = "sha256:cdc7b5e3ed77bed61270a47d35434a30617b9becdf2478af76ad2c6ade307280"}, + {file = "pyrsistent-0.16.0.tar.gz", hash = "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"}, ] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, @@ -1308,8 +1311,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.6.2-py3-none-any.whl", hash = "sha256:57c9c5de1bbc0a258af489c46eaca326a3b408fe7988fdf6e050f34d5feeaed3"}, - {file = "royalnet-5.6.2.tar.gz", hash = "sha256:b421b84d2cad1ea27016e300f7b005836dd6f5f14975e5b372a91f1f4d52dfd7"}, + {file = "royalnet-5.6.5-py3-none-any.whl", hash = "sha256:ee5d1774fc507cc1be291fefe5716ee7e6bec80ccf1ffd5a6d2278721c7a477b"}, + {file = "royalnet-5.6.5.tar.gz", hash = "sha256:4555bbdf2bc4c75e90f2b465a022178ad6cd6302906c0c5adfe7a7d6e1dbcb06"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1323,7 +1326,7 @@ six = [ {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.13.tar.gz", hash = "sha256:64a7b71846db6423807e96820993fa12a03b89127d278290ca25c0b11ed7b4fb"}, + {file = "SQLAlchemy-1.3.15.tar.gz", hash = "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"}, ] starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, @@ -1422,6 +1425,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.3.8-py2.py3-none-any.whl", hash = "sha256:f9d33129ea4941bea234cdba811c0f97e61c2235a877cf395a869aeea065e009"}, - {file = "youtube_dl-2020.3.8.tar.gz", hash = "sha256:1b098b7ae41551f46dbae70e56dbabdf39c8faf50e072d0c0b42c44d64afebf8"}, + {file = "youtube_dl-2020.3.24-py2.py3-none-any.whl", hash = "sha256:c0be39ea9bca72fa02a0d2d043c5e9bd8ea8e0fe79705e891161d6fcd29da59e"}, + {file = "youtube_dl-2020.3.24.tar.gz", hash = "sha256:4b03efe439f7cae26eba909821d1df00a9a4eb82741cb2e8b78fe29702bd4633"}, ] diff --git a/pyproject.toml b/pyproject.toml index ae318a03..30d27335 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6.2" + version = "5.7" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.6" + version = "~5.6.5" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 0df9b6f8..3d102aea 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -37,6 +37,7 @@ from .dota import DotaCommand from .magickfiorygi import MagickfiorygiCommand from .brawlhalla import BrawlhallaCommand from .diarioshuffle import DiarioshuffleCommand +from .funkwhaleplaylist import FunkwhaleplaylistCommand # Enter the commands of your Pack here! available_commands = [ @@ -78,6 +79,7 @@ available_commands = [ MagickfiorygiCommand, BrawlhallaCommand, DiarioshuffleCommand, + FunkwhaleplaylistCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index 5571a017..8b2364a2 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -16,7 +16,7 @@ class FunkwhaleCommand(PlayCommand): def get_embed_color(self): return 0x009FE3 - async def get_url(self, args): + async def get_urls(self, args): search = urllib.parse.quote(args.joined(require_at_least=1)) async with aiohttp.ClientSession() as session: async with session.get(self.config["Funkwhale"]["instance_url"] + @@ -24,4 +24,4 @@ class FunkwhaleCommand(PlayCommand): j = await response.json() if len(j["tracks"]) < 1: raise UserError("Nessun file audio trovato con il nome richiesto.") - return f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}' + return [f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}'] diff --git a/royalpack/commands/funkwhaleplaylist.py b/royalpack/commands/funkwhaleplaylist.py new file mode 100644 index 00000000..8c9736bb --- /dev/null +++ b/royalpack/commands/funkwhaleplaylist.py @@ -0,0 +1,32 @@ +from .play import PlayCommand +from royalnet.commands import * +import aiohttp +import urllib.parse + + +class FunkwhaleplaylistCommand(PlayCommand): + name: str = "funkwhaleplaylist" + + aliases = ["fwp", "fwplaylist", "funkwhalep"] + + description: str = "Cerca una playlist su RoyalWhale e aggiungila alla coda della chat vocale." + + syntax = "{ricerca}" + + def get_embed_color(self): + return 0x009FE3 + + async def get_urls(self, args): + search = urllib.parse.quote(args.joined(require_at_least=1)) + async with aiohttp.ClientSession() as session: + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: + j = await response.json() + if len(j["results"]) < 1: + raise UserError("Nessuna playlist trovata con il nome richiesto.") + playlist = j["results"][0] + playlist_id = playlist["id"] + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/playlists/{playlist_id}/tracks") as response: + j = await response.json() + return list(map(lambda t: f'{self.config["Funkwhale"]["instance_url"]}{t["track"]["listen_url"]}', j["results"])) diff --git a/royalpack/commands/googlevideo.py b/royalpack/commands/googlevideo.py index d07fe2ae..27062794 100644 --- a/royalpack/commands/googlevideo.py +++ b/royalpack/commands/googlevideo.py @@ -10,7 +10,7 @@ class GooglevideoCommand(PlayCommand): syntax = "{ricerca}" - async def get_url(self, args): - return f"gvsearch:{args.joined()}" + async def get_urls(self, args): + return [f"gvsearch:{args.joined()}"] # Too bad gvsearch: always finds nothing. diff --git a/royalpack/commands/play.py b/royalpack/commands/play.py index 886bca37..c13bac9a 100644 --- a/royalpack/commands/play.py +++ b/royalpack/commands/play.py @@ -14,12 +14,12 @@ class PlayCommand(Command): syntax = "{url}" - async def get_url(self, args: CommandArgs): + async def get_urls(self, args: CommandArgs): url = args.joined(require_at_least=1) if not (url.startswith("http://") or url.startswith("https://")): raise InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" f" ([c]http://[/c] o [c]https://[/c]).") - return url + return [url] def get_embed_color(self) -> Optional[int]: return None @@ -46,14 +46,19 @@ class PlayCommand(Command): else: user_str = str(f"<@{user_discord.discord_id}>") + urls = await self.get_urls(args) + play_task: aio.Task = self.loop.create_task( self.interface.call_herald_event("discord", "discord_play", - url=await self.get_url(args), + urls=urls, guild_id=guild_id, user=user_str, force_color=self.get_embed_color()) ) - await data.reply("⌛ Attendi un attimo...") + if len(urls) > 1: + await data.reply("⌛ Attendi qualche minuto...") + else: + await data.reply("⌛ Attendi un attimo...") await play_task diff --git a/royalpack/commands/soundcloud.py b/royalpack/commands/soundcloud.py index 0090e3dd..f0e68061 100644 --- a/royalpack/commands/soundcloud.py +++ b/royalpack/commands/soundcloud.py @@ -10,5 +10,5 @@ class SoundcloudCommand(PlayCommand): syntax = "{ricerca}" - async def get_url(self, args): - return f"scsearch:{args.joined()}" + async def get_urls(self, args): + return [f"scsearch:{args.joined()}"] diff --git a/royalpack/commands/yahoovideo.py b/royalpack/commands/yahoovideo.py index 482b1042..a0ec05be 100644 --- a/royalpack/commands/yahoovideo.py +++ b/royalpack/commands/yahoovideo.py @@ -10,7 +10,7 @@ class YahoovideoCommand(PlayCommand): syntax = "{ricerca}" - async def get_url(self, args): - return f"yvsearch:{args.joined()}" + async def get_urls(self, args): + return [f"yvsearch:{args.joined()}"] # Too bad yvsearch: always finds nothing. diff --git a/royalpack/commands/youtube.py b/royalpack/commands/youtube.py index 870c8aca..f684a59a 100644 --- a/royalpack/commands/youtube.py +++ b/royalpack/commands/youtube.py @@ -10,5 +10,5 @@ class YoutubeCommand(PlayCommand): syntax = "{ricerca}" - async def get_url(self, args): - return f"ytsearch:{args.joined()}" + async def get_urls(self, args): + return [f"ytsearch:{args.joined()}"] diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index 0db80f3d..f122f3a4 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -13,7 +13,7 @@ class DiscordPlayEvent(rc.Event): name = "discord_play" async def run(self, - url: str, + urls: List[str], guild_id: Optional[int] = None, user: Optional[str] = None, force_color: Optional[int] = None, @@ -23,18 +23,8 @@ class DiscordPlayEvent(rc.Event): serf: rsd.DiscordSerf = self.serf client: discord.Client = self.serf.client - - # TODO: fix this in Royalnet sometime - candidate_players: List[rsd.VoicePlayer] = [] - for player in serf.voice_players: - player: rsd.VoicePlayer - if not player.voice_client.is_connected(): - continue - if guild_id is not None: - guild = client.get_guild(guild_id) - if guild != player.voice_client.guild: - continue - candidate_players.append(player) + guild: discord.Guild = client.get_guild(guild_id) if guild_id is not None else None + candidate_players: List[rsd.VoicePlayer] = serf.find_voice_players(guild) if len(candidate_players) == 0: raise rc.UserError("Il bot non è in nessun canale vocale.\n" @@ -45,21 +35,23 @@ class DiscordPlayEvent(rc.Event): raise rc.CommandError("Non so in che Server riprodurre questo file...\n" "Invia il comando su Discord, per favore!") - ytds = await rbd.YtdlDiscord.from_url(url) added: List[rbd.YtdlDiscord] = [] too_long: List[rbd.YtdlDiscord] = [] - if isinstance(voice_player.playing, RoyalQueue): - for index, ytd in enumerate(ytds): - if ytd.info.duration >= datetime.timedelta(seconds=self.config["Play"]["max_song_duration"]): - too_long.append(ytd) - continue - await ytd.convert_to_pcm() - added.append(ytd) - voice_player.playing.contents.append(ytd) - if not voice_player.voice_client.is_playing(): - await voice_player.start() - else: - raise rc.CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") + + for url in urls: + ytds = await rbd.YtdlDiscord.from_url(url) + if isinstance(voice_player.playing, RoyalQueue): + for index, ytd in enumerate(ytds): + if ytd.info.duration >= datetime.timedelta(seconds=self.config["Play"]["max_song_duration"]): + too_long.append(ytd) + continue + await ytd.convert_to_pcm() + added.append(ytd) + voice_player.playing.contents.append(ytd) + if not voice_player.voice_client.is_playing(): + await voice_player.start() + else: + raise rc.CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") main_channel: discord.TextChannel = client.get_channel(self.config["Discord"]["main_channel_id"]) @@ -85,7 +77,7 @@ class DiscordPlayEvent(rc.Event): )) if len(added) + len(too_long) == 0: - raise + raise rc.InvalidInputError("Non è stato aggiunto nessun file alla coda.") return { "added": [{ diff --git a/royalpack/version.py b/royalpack/version.py index 3e2df96c..4784f166 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6.2" +semantic = "5.7" From dea29e6d6d5b1385bb74c6c92e99b7cb14630803 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 28 Mar 2020 21:02:20 +0100 Subject: [PATCH 074/227] Start work on the pool, only commands are missing --- poetry.lock | 8 ++--- pyproject.toml | 2 +- royalpack/utils/royalpool.py | 55 +++++++++++++++++++++++++++++++++++ royalpack/utils/royalqueue.py | 15 ++++++++++ 4 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 royalpack/utils/royalpool.py diff --git a/poetry.lock b/poetry.lock index 653e5c50..ea403a6f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -586,7 +586,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.6.5" +version = "5.6.6" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -867,7 +867,7 @@ python-versions = "*" version = "2020.3.24" [metadata] -content-hash = "f0931c9aade41f1ac239401a324cb550f0961b83c1759b5a84effb10e1bba7f2" +content-hash = "424a17455e19b7aa11d52d3a37548275adae578539f501d59c111b7f43c79dc1" python-versions = "^3.8" [metadata.files] @@ -1311,8 +1311,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.6.5-py3-none-any.whl", hash = "sha256:ee5d1774fc507cc1be291fefe5716ee7e6bec80ccf1ffd5a6d2278721c7a477b"}, - {file = "royalnet-5.6.5.tar.gz", hash = "sha256:4555bbdf2bc4c75e90f2b465a022178ad6cd6302906c0c5adfe7a7d6e1dbcb06"}, + {file = "royalnet-5.6.6-py3-none-any.whl", hash = "sha256:2793af4c09c364403400012a1b6e76cb012ab90c105bd512e6d21219d9ec2bbd"}, + {file = "royalnet-5.6.6.tar.gz", hash = "sha256:c2fc05049cd1a5185941458cf519ad46d871e475d0bb5e2ead968f148d27d836"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 30d27335..f2cb4d8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "~5.6.5" + version = "~5.6.6" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/utils/royalpool.py b/royalpack/utils/royalpool.py new file mode 100644 index 00000000..c594ca3c --- /dev/null +++ b/royalpack/utils/royalpool.py @@ -0,0 +1,55 @@ +import logging +from typing import Optional, List, AsyncGenerator, Tuple, Any, Dict +from royalnet.bard.discord import YtdlDiscord +from royalnet.serf.discord import Playable +import discord +import random + + +log = logging.getLogger(__name__) + + +class RoyalPool(Playable): + """A pool of :class:`YtdlDiscord` that will be played in a loop.""" + def __init__(self, start_with: Optional[List[YtdlDiscord]] = None): + super().__init__() + self.full_pool: List[YtdlDiscord] = [] + self.remaining_pool: List[YtdlDiscord] = [] + self.now_playing: Optional[YtdlDiscord] = None + if start_with is not None: + self.full_pool = [*self.full_pool, *start_with] + log.debug(f"Created new {self.__class__.__qualname__} containing: {self.full_pool}") + + async def _generator(self) \ + -> AsyncGenerator[Optional["discord.AudioSource"], Tuple[Tuple[Any, ...], Dict[str, Any]]]: + yield + while True: + if len(self.remaining_pool) == 0: + if len(self.full_pool) == 0: + log.debug(f"Nothing in the pool, yielding None...") + yield None + continue + else: + self.remaining_pool = self.full_pool.copy() + random.shuffle(self.remaining_pool) + else: + log.debug(f"Dequeuing an item...") + # Get the first YtdlDiscord of the queue + self.now_playing: YtdlDiscord = self.remaining_pool.pop(0) + log.debug(f"Yielding FileAudioSource from: {self.now_playing}") + # Create a FileAudioSource from the YtdlDiscord + # If the file hasn't been fetched / downloaded / converted yet, it will do so before yielding + async with self.now_playing.spawn_audiosource() as fas: + # Yield the resulting AudioSource + yield fas + + async def destroy(self): + for file in self.full_pool: + log.debug(f"Deleting: {file}") + await file.delete_asap() + log.debug(f"Deleting: {file.ytdl_file}") + await file.ytdl_file.delete_asap() + log.debug(f"Deleted successfully!") + self.full_pool = [] + self.remaining_pool = [] + self.now_playing = None diff --git a/royalpack/utils/royalqueue.py b/royalpack/utils/royalqueue.py index 310ba55b..f1be3e96 100644 --- a/royalpack/utils/royalqueue.py +++ b/royalpack/utils/royalqueue.py @@ -44,3 +44,18 @@ class RoyalQueue(Playable): await self.now_playing.ytdl_file.delete_asap() log.debug(f"Deleted successfully!") self.now_playing = None + + async def destroy(self): + log.debug(f"Deleting: {self.now_playing}") + await self.now_playing.delete_asap() + log.debug(f"Deleting: {self.now_playing.ytdl_file}") + await self.now_playing.ytdl_file.delete_asap() + log.debug(f"Deleted successfully!") + self.now_playing = None + for file in self.contents: + log.debug(f"Deleting: {file}") + await file.delete_asap() + log.debug(f"Deleting: {file.ytdl_file}") + await file.ytdl_file.delete_asap() + log.debug(f"Deleted successfully!") + self.contents = [] From c80c5a33db01ac918fed104300264071cbb401d1 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 28 Mar 2020 21:51:21 +0100 Subject: [PATCH 075/227] Some voice changes, add voicestatus command --- royalpack/commands/__init__.py | 2 ++ royalpack/commands/queue.py | 2 +- royalpack/commands/voicestatus.py | 44 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 royalpack/commands/voicestatus.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 3d102aea..0586cea2 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -38,6 +38,7 @@ from .magickfiorygi import MagickfiorygiCommand from .brawlhalla import BrawlhallaCommand from .diarioshuffle import DiarioshuffleCommand from .funkwhaleplaylist import FunkwhaleplaylistCommand +from .voicestatus import VoicestatusCommand # Enter the commands of your Pack here! available_commands = [ @@ -80,6 +81,7 @@ available_commands = [ BrawlhallaCommand, DiarioshuffleCommand, FunkwhaleplaylistCommand, + VoicestatusCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/queue.py b/royalpack/commands/queue.py index 751e2180..8357d45b 100644 --- a/royalpack/commands/queue.py +++ b/royalpack/commands/queue.py @@ -11,7 +11,7 @@ class QueueCommand(Command): aliases = ["q"] - description: str = "Visualizza la coda di riproduzione attuale.." + description: str = "Visualizza la coda di riproduzione attuale." async def run(self, args: CommandArgs, data: CommandData) -> None: if self.interface.name == "discord": diff --git a/royalpack/commands/voicestatus.py b/royalpack/commands/voicestatus.py new file mode 100644 index 00000000..511a44ae --- /dev/null +++ b/royalpack/commands/voicestatus.py @@ -0,0 +1,44 @@ +from typing import * +import royalnet.serf.discord as rsd +import royalnet.commands as rc + + +class VoicestatusCommand(rc.Command): + name: str = "voicestatus" + + description: str = "Visualizza lo stato interno dei voice player del bot." + + syntax: str = "" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + if self.interface.name != "discord": + raise rc.UnsupportedError("Questo comando funziona solo su Discord.") + serf: rsd.DiscordSerf = self.interface.serf + + message = [] + for index, voice_player in enumerate(serf.voice_players): + message.append(f"🎵 [b]Voice Player #{index}[/b]") + + voice_client = voice_player.voice_client + if voice_client.is_connected(): + message.append(f"🔵 Connected") + else: + message.append(f"🔴 Disconnected") + if voice_client.is_playing(): + message.append(f"🔵 Playing") + else: + message.append(f"⚪ Not playing") + if voice_client.is_paused(): + message.append(f"⚪ Paused") + else: + message.append(f"🔵 Not paused") + + playable = voice_player.playing + message.append(f"🔉 {playable.__class__.__name__}") + + message.append("") + + if len(serf.voice_players) == 0: + message.append("[i]Nessun voice player.[/i]") + + await data.reply("\n".join(message)) From 61cb632929ad8a5ba75023ab492db24422c849b8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 28 Mar 2020 21:51:47 +0100 Subject: [PATCH 076/227] publish: 5.6.7 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f2cb4d8c..e9fd1723 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7" + version = "5.6.7" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 4784f166..b92f930f 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7" +semantic = "5.6.7" From 354cfb318c41ad4ae099184fc56fe6832a4291d6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 29 Mar 2020 00:14:55 +0100 Subject: [PATCH 077/227] Add playmode command --- royalpack/commands/__init__.py | 2 + royalpack/commands/playmode.py | 57 ++++++++++++++++++++++++++++ royalpack/events/__init__.py | 2 + royalpack/events/discord_playable.py | 48 +++++++++++++++++++++++ royalpack/utils/__init__.py | 2 + royalpack/utils/royalqueue.py | 13 ++++--- 6 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 royalpack/commands/playmode.py create mode 100644 royalpack/events/discord_playable.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 0586cea2..317dbe6a 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -39,6 +39,7 @@ from .brawlhalla import BrawlhallaCommand from .diarioshuffle import DiarioshuffleCommand from .funkwhaleplaylist import FunkwhaleplaylistCommand from .voicestatus import VoicestatusCommand +from .playmode import PlaymodeCommand # Enter the commands of your Pack here! available_commands = [ @@ -82,6 +83,7 @@ available_commands = [ DiarioshuffleCommand, FunkwhaleplaylistCommand, VoicestatusCommand, + PlaymodeCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/playmode.py b/royalpack/commands/playmode.py new file mode 100644 index 00000000..01d62a37 --- /dev/null +++ b/royalpack/commands/playmode.py @@ -0,0 +1,57 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import discord +from royalnet.backpack.tables import User, Discord + + +class PlaymodeCommand(rc.Command): + name: str = "playmode" + + aliases = ["pm"] + + description: str = "Seleziona la modalità di riproduzione musicale." + + syntax: str = "{queue|pool}" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + if self.interface.name == "discord": + message: discord.Message = data.message + guild: discord.Guild = message.guild + if guild is None: + guild_id = None + else: + guild_id: Optional[int] = guild.id + else: + guild_id = None + + user: User = await data.get_author() + user_str = None + + if user is not None: + try: + user_discord: Discord = user.discord[0] + except (AttributeError, IndexError): + user_str = str(user) + else: + user_str = str(f"<@{user_discord.discord_id}>") + + response = await self.interface.call_herald_event("discord", "discord_playmode", + playable_string=args[0], + guild_id=guild_id, + user=user_str) + + if response["name"] == "RoyalQueue": + await data.reply(f"✅ Modalità di riproduzione impostata a [b]Queue[/b]:\n" + f"- Riproduci le canzoni nell'ordine scelto\n" + f"- Rimuovi le canzoni dopo averle riprodotte") + + elif response["name"] == "RoyalPool": + await data.reply(f"✅ Modalità di riproduzione impostata a [b]Pool[/b]:\n" + f"- Aggiungi canzoni al pool con [c]!p[/c], [c]!yt[/c] e [c]!fw[/c]\n" + f"- Riproduci all'infinito canzoni casuali dal pool\n" + f"- Non è possibile rimuovere canzoni dal pool, [c]!skip[/c]parle manderà solo avanti il pool\n" + f"- Interrompi la riproduzione del pool cambiando modalità di riproduzione") + + else: + await data.reply(f"✅ Modalità di riproduzione impostata a [c]{response['name']}[/c]!") \ No newline at end of file diff --git a/royalpack/events/__init__.py b/royalpack/events/__init__.py index 64834fb5..f956ee21 100644 --- a/royalpack/events/__init__.py +++ b/royalpack/events/__init__.py @@ -5,6 +5,7 @@ from .discord_play import DiscordPlayEvent from .discord_skip import DiscordSkipEvent from .discord_queue import DiscordQueueEvent from .discord_pause import DiscordPauseEvent +from .discord_playable import DiscordPlaymodeEvent # Enter the commands of your Pack here! available_events = [ @@ -14,6 +15,7 @@ available_events = [ DiscordSkipEvent, DiscordQueueEvent, DiscordPauseEvent, + DiscordPlaymodeEvent, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/events/discord_playable.py b/royalpack/events/discord_playable.py new file mode 100644 index 00000000..2c395ad7 --- /dev/null +++ b/royalpack/events/discord_playable.py @@ -0,0 +1,48 @@ +import datetime +from typing import * + +import discord +import royalnet.commands as rc +import royalnet.serf.discord as rsd +import royalnet.bard.discord as rbd + +from ..utils import RoyalQueue, RoyalPool + + +class DiscordPlaymodeEvent(rc.Event): + name = "discord_playmode" + + async def run(self, + playable_string: str, + guild_id: Optional[int] = None, + user: Optional[str] = None, + **kwargs) -> dict: + if not isinstance(self.serf, rsd.DiscordSerf): + raise rc.UnsupportedError() + + serf: rsd.DiscordSerf = self.serf + client: discord.Client = self.serf.client + guild: discord.Guild = client.get_guild(guild_id) if guild_id is not None else None + candidate_players: List[rsd.VoicePlayer] = serf.find_voice_players(guild) + + if len(candidate_players) == 0: + raise rc.UserError("Il bot non è in nessun canale vocale.\n" + "Evocalo prima con [c]summon[/c]!") + elif len(candidate_players) == 1: + voice_player = candidate_players[0] + else: + raise rc.CommandError("Non so a che Server cambiare Playable...\n" + "Invia il comando su Discord, per favore!") + + if playable_string.upper() == "QUEUE": + playable = RoyalQueue() + elif playable_string.upper() == "POOL": + playable = RoyalPool() + else: + raise rc.InvalidInputError(f"Unknown playable '{playable_string.upper()}'") + + await voice_player.change_playing(playable) + + return { + "name": f"{playable.__class__.__qualname__}" + } diff --git a/royalpack/utils/__init__.py b/royalpack/utils/__init__.py index 814c9eed..619a095d 100644 --- a/royalpack/utils/__init__.py +++ b/royalpack/utils/__init__.py @@ -1,7 +1,9 @@ from .royalqueue import RoyalQueue from .finduser import find_user_api +from .royalpool import RoyalPool __all__ = [ "RoyalQueue", "find_user_api", + "RoyalPool", ] diff --git a/royalpack/utils/royalqueue.py b/royalpack/utils/royalqueue.py index f1be3e96..a8af9110 100644 --- a/royalpack/utils/royalqueue.py +++ b/royalpack/utils/royalqueue.py @@ -46,12 +46,13 @@ class RoyalQueue(Playable): self.now_playing = None async def destroy(self): - log.debug(f"Deleting: {self.now_playing}") - await self.now_playing.delete_asap() - log.debug(f"Deleting: {self.now_playing.ytdl_file}") - await self.now_playing.ytdl_file.delete_asap() - log.debug(f"Deleted successfully!") - self.now_playing = None + if self.now_playing is not None: + log.debug(f"Deleting: {self.now_playing}") + await self.now_playing.delete_asap() + log.debug(f"Deleting: {self.now_playing.ytdl_file}") + await self.now_playing.ytdl_file.delete_asap() + log.debug(f"Deleted successfully!") + self.now_playing = None for file in self.contents: log.debug(f"Deleting: {file}") await file.delete_asap() From 87f8c84eba83aeaed0b9fbf4b7bb1b8d24932888 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 29 Mar 2020 00:15:09 +0100 Subject: [PATCH 078/227] publish: 5.6.8 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e9fd1723..451bcc1b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6.7" + version = "5.6.8" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index b92f930f..e1a4e4ae 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6.7" +semantic = "5.6.8" From 9e129e7ad0db9ef8284c503b0305781b7dcb9eee Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 29 Mar 2020 21:19:58 +0200 Subject: [PATCH 079/227] Add lazy music commands --- royalpack/commands/__init__.py | 16 ++++ royalpack/commands/lazyfunkwhale.py | 27 +++++++ royalpack/commands/lazyfunkwhaleplaylist.py | 32 ++++++++ royalpack/commands/lazygooglevideo.py | 16 ++++ royalpack/commands/lazypeertube.py | 24 ++++++ royalpack/commands/lazyplay.py | 62 +++++++++++++++ royalpack/commands/lazysoundcloud.py | 14 ++++ royalpack/commands/lazyyahoovideo.py | 16 ++++ royalpack/commands/lazyyoutube.py | 14 ++++ royalpack/commands/peertube.py | 4 +- royalpack/events/__init__.py | 2 + royalpack/events/discord_lazy_play.py | 88 +++++++++++++++++++++ 12 files changed, 313 insertions(+), 2 deletions(-) create mode 100644 royalpack/commands/lazyfunkwhale.py create mode 100644 royalpack/commands/lazyfunkwhaleplaylist.py create mode 100644 royalpack/commands/lazygooglevideo.py create mode 100644 royalpack/commands/lazypeertube.py create mode 100644 royalpack/commands/lazyplay.py create mode 100644 royalpack/commands/lazysoundcloud.py create mode 100644 royalpack/commands/lazyyahoovideo.py create mode 100644 royalpack/commands/lazyyoutube.py create mode 100644 royalpack/events/discord_lazy_play.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 317dbe6a..b96c3acd 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -40,6 +40,14 @@ from .diarioshuffle import DiarioshuffleCommand from .funkwhaleplaylist import FunkwhaleplaylistCommand from .voicestatus import VoicestatusCommand from .playmode import PlaymodeCommand +from .lazyplay import LazyplayCommand +from .lazyfunkwhale import LazyfunkwhaleCommand +from .lazyfunkwhaleplaylist import LazyfunkwhaleplaylistCommand +from .lazygooglevideo import LazygooglevideoCommand +from .lazypeertube import LazypeertubeCommand +from .lazysoundcloud import LazysoundcloudCommand +from .lazyyahoovideo import LazyyahoovideoCommand +from .lazyyoutube import LazyyoutubeCommand # Enter the commands of your Pack here! available_commands = [ @@ -84,6 +92,14 @@ available_commands = [ FunkwhaleplaylistCommand, VoicestatusCommand, PlaymodeCommand, + LazyplayCommand, + LazyfunkwhaleCommand, + LazyfunkwhaleplaylistCommand, + LazygooglevideoCommand, + LazypeertubeCommand, + LazysoundcloudCommand, + LazyyahoovideoCommand, + LazyyoutubeCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/lazyfunkwhale.py b/royalpack/commands/lazyfunkwhale.py new file mode 100644 index 00000000..3b6d839e --- /dev/null +++ b/royalpack/commands/lazyfunkwhale.py @@ -0,0 +1,27 @@ +from .lazyplay import LazyplayCommand +from royalnet.commands import * +import aiohttp +import urllib.parse + + +class LazyfunkwhaleCommand(LazyplayCommand): + name: str = "lazyfunkwhale" + + aliases = ["lazyfuckwhale", "lfw", "lazyroyalwhale", "lrw"] + + description: str = "Cerca una canzone su RoyalWhale e aggiungila (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + def get_embed_color(self): + return 0x009FE3 + + async def get_urls(self, args): + search = urllib.parse.quote(args.joined(require_at_least=1)) + async with aiohttp.ClientSession() as session: + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/search?query={search}") as response: + j = await response.json() + if len(j["tracks"]) < 1: + raise UserError("Nessun file audio trovato con il nome richiesto.") + return [f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}'] diff --git a/royalpack/commands/lazyfunkwhaleplaylist.py b/royalpack/commands/lazyfunkwhaleplaylist.py new file mode 100644 index 00000000..8d6bf0e0 --- /dev/null +++ b/royalpack/commands/lazyfunkwhaleplaylist.py @@ -0,0 +1,32 @@ +from .lazyplay import LazyplayCommand +from royalnet.commands import * +import aiohttp +import urllib.parse + + +class LazyfunkwhaleplaylistCommand(LazyplayCommand): + name: str = "lazyfunkwhaleplaylist" + + aliases = ["lfwp", "lfwplaylist", "lazyfunkwhalep"] + + description: str = "Cerca una playlist su RoyalWhale e aggiungila (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + def get_embed_color(self): + return 0x009FE3 + + async def get_urls(self, args): + search = urllib.parse.quote(args.joined(require_at_least=1)) + async with aiohttp.ClientSession() as session: + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: + j = await response.json() + if len(j["results"]) < 1: + raise UserError("Nessuna playlist trovata con il nome richiesto.") + playlist = j["results"][0] + playlist_id = playlist["id"] + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/playlists/{playlist_id}/tracks") as response: + j = await response.json() + return list(map(lambda t: f'{self.config["Funkwhale"]["instance_url"]}{t["track"]["listen_url"]}', j["results"])) diff --git a/royalpack/commands/lazygooglevideo.py b/royalpack/commands/lazygooglevideo.py new file mode 100644 index 00000000..24ae7183 --- /dev/null +++ b/royalpack/commands/lazygooglevideo.py @@ -0,0 +1,16 @@ +from .lazyplay import LazyplayCommand + + +class LazygooglevideoCommand(LazyplayCommand): + name: str = "lazygooglevideo" + + aliases = ["lgv"] + + description: str = "Cerca un video su Google Video e lo aggiunge (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + async def get_urls(self, args): + return [f"gvsearch:{args.joined()}"] + + # Too bad gvsearch: always finds nothing. diff --git a/royalpack/commands/lazypeertube.py b/royalpack/commands/lazypeertube.py new file mode 100644 index 00000000..f3668a04 --- /dev/null +++ b/royalpack/commands/lazypeertube.py @@ -0,0 +1,24 @@ +from .lazyplay import LazyplayCommand +from royalnet.commands import * +import aiohttp +import urllib.parse + + +class LazypeertubeCommand(LazyplayCommand): + name: str = "lazypeertube" + + aliases = ["lpt", "lazyroyaltube", "lrt"] + + description: str = "Cerca un video su RoyalTube e lo aggiunge (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + async def get_urls(self, args): + search = urllib.parse.quote(args.joined(require_at_least=1)) + async with aiohttp.ClientSession() as session: + async with session.get(self.config["Peertube"]["instance_url"] + + f"/api/v1/search/videos?search={search}") as response: + j = await response.json() + if j["total"] < 1: + raise InvalidInputError("Nessun video trovato.") + return [f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}'] diff --git a/royalpack/commands/lazyplay.py b/royalpack/commands/lazyplay.py new file mode 100644 index 00000000..795c4d5e --- /dev/null +++ b/royalpack/commands/lazyplay.py @@ -0,0 +1,62 @@ +import discord +import asyncio as aio +from typing import * +from royalnet.commands import * +from royalnet.backpack.tables import User, Discord + + +class LazyplayCommand(Command): + name: str = "lazyplay" + + aliases = ["lp"] + + description: str = "Aggiunge un url alla coda della chat vocale, ma lo scarica solo quando sta per essere" \ + " riprodotto." + + syntax = "{url}" + + async def get_urls(self, args: CommandArgs): + url = args.joined(require_at_least=1) + if not (url.startswith("http://") or url.startswith("https://")): + raise InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" + f" ([c]http://[/c] o [c]https://[/c]).") + return [url] + + def get_embed_color(self) -> Optional[int]: + return None + + async def run(self, args: CommandArgs, data: CommandData) -> None: + if self.interface.name == "discord": + message: discord.Message = data.message + guild: discord.Guild = message.guild + if guild is None: + guild_id = None + else: + guild_id: Optional[int] = guild.id + else: + guild_id = None + + user: User = await data.get_author() + user_str = None + + if user is not None: + try: + user_discord: Discord = user.discord[0] + except (AttributeError, IndexError): + user_str = str(user) + else: + user_str = str(f"<@{user_discord.discord_id}>") + + urls = await self.get_urls(args) + + play_task: aio.Task = self.loop.create_task( + self.interface.call_herald_event("discord", "discord_lazy_play", + urls=urls, + guild_id=guild_id, + user=user_str, + force_color=self.get_embed_color()) + ) + + await data.reply("⌛ Attendi un attimo...") + + await play_task diff --git a/royalpack/commands/lazysoundcloud.py b/royalpack/commands/lazysoundcloud.py new file mode 100644 index 00000000..e3e181c5 --- /dev/null +++ b/royalpack/commands/lazysoundcloud.py @@ -0,0 +1,14 @@ +from .lazyplay import LazyplayCommand + + +class LazysoundcloudCommand(LazyplayCommand): + name: str = "lazysoundcloud" + + aliases = ["lsc"] + + description: str = "Cerca un video su SoundCloud e lo aggiunge (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + async def get_urls(self, args): + return [f"scsearch:{args.joined()}"] diff --git a/royalpack/commands/lazyyahoovideo.py b/royalpack/commands/lazyyahoovideo.py new file mode 100644 index 00000000..f0f4f1d5 --- /dev/null +++ b/royalpack/commands/lazyyahoovideo.py @@ -0,0 +1,16 @@ +from .lazyplay import LazyplayCommand + + +class LazyyahoovideoCommand(LazyplayCommand): + name: str = "lazyyahoovideo" + + aliases = ["lyv"] + + description: str = "Cerca un video su Yahoo Video e lo aggiunge (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + async def get_urls(self, args): + return [f"yvsearch:{args.joined()}"] + + # Too bad yvsearch: always finds nothing. diff --git a/royalpack/commands/lazyyoutube.py b/royalpack/commands/lazyyoutube.py new file mode 100644 index 00000000..cf6a56b9 --- /dev/null +++ b/royalpack/commands/lazyyoutube.py @@ -0,0 +1,14 @@ +from .lazyplay import LazyplayCommand + + +class LazyyoutubeCommand(LazyplayCommand): + name: str = "lazyyoutube" + + aliases = ["lyt"] + + description: str = "Cerca un video su YouTube e lo aggiunge (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + async def get_urls(self, args): + return [f"ytsearch:{args.joined()}"] diff --git a/royalpack/commands/peertube.py b/royalpack/commands/peertube.py index 9a8648dc..51b08fd8 100644 --- a/royalpack/commands/peertube.py +++ b/royalpack/commands/peertube.py @@ -13,7 +13,7 @@ class PeertubeCommand(PlayCommand): syntax = "{ricerca}" - async def get_url(self, args): + async def get_urls(self, args): search = urllib.parse.quote(args.joined(require_at_least=1)) async with aiohttp.ClientSession() as session: async with session.get(self.config["Peertube"]["instance_url"] + @@ -21,4 +21,4 @@ class PeertubeCommand(PlayCommand): j = await response.json() if j["total"] < 1: raise InvalidInputError("Nessun video trovato.") - return f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}' + return [f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}'] diff --git a/royalpack/events/__init__.py b/royalpack/events/__init__.py index f956ee21..6637fbe2 100644 --- a/royalpack/events/__init__.py +++ b/royalpack/events/__init__.py @@ -6,6 +6,7 @@ from .discord_skip import DiscordSkipEvent from .discord_queue import DiscordQueueEvent from .discord_pause import DiscordPauseEvent from .discord_playable import DiscordPlaymodeEvent +from .discord_lazy_play import DiscordLazyPlayEvent # Enter the commands of your Pack here! available_events = [ @@ -16,6 +17,7 @@ available_events = [ DiscordQueueEvent, DiscordPauseEvent, DiscordPlaymodeEvent, + DiscordLazyPlayEvent, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/events/discord_lazy_play.py b/royalpack/events/discord_lazy_play.py new file mode 100644 index 00000000..8b76a4ff --- /dev/null +++ b/royalpack/events/discord_lazy_play.py @@ -0,0 +1,88 @@ +import datetime +from typing import * + +import discord +import royalnet.commands as rc +import royalnet.serf.discord as rsd +import royalnet.bard.discord as rbd + +from ..utils import RoyalQueue + + +class DiscordLazyPlayEvent(rc.Event): + name = "discord_lazy_play" + + async def run(self, + urls: List[str], + guild_id: Optional[int] = None, + user: Optional[str] = None, + force_color: Optional[int] = None, + **kwargs) -> dict: + if not isinstance(self.serf, rsd.DiscordSerf): + raise rc.UnsupportedError() + + serf: rsd.DiscordSerf = self.serf + client: discord.Client = self.serf.client + guild: discord.Guild = client.get_guild(guild_id) if guild_id is not None else None + candidate_players: List[rsd.VoicePlayer] = serf.find_voice_players(guild) + + if len(candidate_players) == 0: + raise rc.UserError("Il bot non è in nessun canale vocale.\n" + "Evocalo prima con [c]summon[/c]!") + elif len(candidate_players) == 1: + voice_player = candidate_players[0] + else: + raise rc.CommandError("Non so in che Server riprodurre questo file...\n" + "Invia il comando su Discord, per favore!") + + added: List[rbd.YtdlDiscord] = [] + too_long: List[rbd.YtdlDiscord] = [] + + for url in urls: + ytds = await rbd.YtdlDiscord.from_url(url) + if isinstance(voice_player.playing, RoyalQueue): + for index, ytd in enumerate(ytds): + if ytd.info.duration >= datetime.timedelta(seconds=self.config["Play"]["max_song_duration"]): + too_long.append(ytd) + continue + added.append(ytd) + voice_player.playing.contents.append(ytd) + if not voice_player.voice_client.is_playing(): + await voice_player.start() + else: + raise rc.CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") + + main_channel: discord.TextChannel = client.get_channel(self.config["Discord"]["main_channel_id"]) + + if len(added) > 0: + if user: + await main_channel.send(rsd.escape(f"▶️ {user} ha aggiunto {len(added)} file _(lazy)_ alla coda:")) + else: + await main_channel.send(rsd.escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file " + f"_(lazy)_ alla coda:")) + for ytd in added: + embed: discord.Embed = ytd.embed() + if force_color: + embed._colour = discord.Colour(force_color) + await main_channel.send(embed=embed) + + if len(too_long) > 0: + if user: + await main_channel.send(rsd.escape( + f"⚠ {len(too_long)} file non {'è' if len(too_long) == 1 else 'sono'}" + f" stat{'o' if len(too_long) == 1 else 'i'} scaricat{'o' if len(too_long) == 1 else 'i'}" + f" perchè durava{'' if len(too_long) == 1 else 'no'}" + f" più di [c]{self.config['Play']['max_song_duration']}[/c] secondi." + )) + + if len(added) + len(too_long) == 0: + raise rc.InvalidInputError("Non è stato aggiunto nessun file alla coda.") + + return { + "added": [{ + "title": ytd.info.title, + } for ytd in added], + "too_long": [{ + "title": ytd.info.title, + } for ytd in too_long] + } From 0c6531f7b780836c3cb6b5d69b354ed246543f23 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 29 Mar 2020 21:22:49 +0200 Subject: [PATCH 080/227] publish: 5.6.9 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 451bcc1b..23aceef2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6.8" + version = "5.6.9" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index e1a4e4ae..4034bc9d 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6.8" +semantic = "5.6.9" From ca5b362cf27554ad23fed5f7ce77f908b4595aef Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 30 Mar 2020 01:33:07 +0200 Subject: [PATCH 081/227] publish: 5.6.10 --- pyproject.toml | 2 +- royalpack/events/discord_lazy_play.py | 12 +++++++++++- royalpack/events/discord_play.py | 13 ++++++++++++- royalpack/events/discord_playable.py | 4 ++-- royalpack/version.py | 2 +- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 23aceef2..0fe64829 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6.9" + version = "5.6.10" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/events/discord_lazy_play.py b/royalpack/events/discord_lazy_play.py index 8b76a4ff..1f776769 100644 --- a/royalpack/events/discord_lazy_play.py +++ b/royalpack/events/discord_lazy_play.py @@ -6,7 +6,7 @@ import royalnet.commands as rc import royalnet.serf.discord as rsd import royalnet.bard.discord as rbd -from ..utils import RoyalQueue +from ..utils import RoyalQueue, RoyalPool class DiscordLazyPlayEvent(rc.Event): @@ -49,6 +49,16 @@ class DiscordLazyPlayEvent(rc.Event): voice_player.playing.contents.append(ytd) if not voice_player.voice_client.is_playing(): await voice_player.start() + elif isinstance(voice_player.playing, RoyalPool): + for index, ytd in enumerate(ytds): + if ytd.info.duration >= datetime.timedelta(seconds=self.config["Play"]["max_song_duration"]): + too_long.append(ytd) + continue + added.append(ytd) + voice_player.playing.full_pool.append(ytd) + voice_player.playing.remaining_pool.append(ytd) + if not voice_player.voice_client.is_playing(): + await voice_player.start() else: raise rc.CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index f122f3a4..341830cf 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -6,7 +6,7 @@ import royalnet.commands as rc import royalnet.serf.discord as rsd import royalnet.bard.discord as rbd -from ..utils import RoyalQueue +from ..utils import RoyalQueue, RoyalPool class DiscordPlayEvent(rc.Event): @@ -50,6 +50,17 @@ class DiscordPlayEvent(rc.Event): voice_player.playing.contents.append(ytd) if not voice_player.voice_client.is_playing(): await voice_player.start() + elif isinstance(voice_player.playing, RoyalPool): + for index, ytd in enumerate(ytds): + if ytd.info.duration >= datetime.timedelta(seconds=self.config["Play"]["max_song_duration"]): + too_long.append(ytd) + continue + await ytd.convert_to_pcm() + added.append(ytd) + voice_player.playing.full_pool.append(ytd) + voice_player.playing.remaining_pool.append(ytd) + if not voice_player.voice_client.is_playing(): + await voice_player.start() else: raise rc.CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!") diff --git a/royalpack/events/discord_playable.py b/royalpack/events/discord_playable.py index 2c395ad7..ecd61cd3 100644 --- a/royalpack/events/discord_playable.py +++ b/royalpack/events/discord_playable.py @@ -35,9 +35,9 @@ class DiscordPlaymodeEvent(rc.Event): "Invia il comando su Discord, per favore!") if playable_string.upper() == "QUEUE": - playable = RoyalQueue() + playable = await RoyalQueue.create() elif playable_string.upper() == "POOL": - playable = RoyalPool() + playable = await RoyalPool.create() else: raise rc.InvalidInputError(f"Unknown playable '{playable_string.upper()}'") diff --git a/royalpack/version.py b/royalpack/version.py index 4034bc9d..5aceca21 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6.9" +semantic = "5.6.10" From 877fad5b2b6ad592e3622838cdb479cb167b3c52 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Apr 2020 16:56:52 +0200 Subject: [PATCH 082/227] Fix steampowered leaking API keys --- royalpack/commands/steampowered.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index cfa5186f..34156b2f 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -19,7 +19,8 @@ class SteampoweredCommand(Command): raise ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") self._api = steam.WebAPI(self.config["Steam"]["web_api_key"]) - def _display(self, account: Steam): + @staticmethod + def _display(account: Steam): string = f"ℹ️ [b]{account.persona_name}[/b]\n" \ f"{account.profile_url}\n" \ f"\n" \ @@ -31,8 +32,16 @@ class SteampoweredCommand(Command): f"Created on: [b]{account.account_creation_date}[/b]\n" return string + @staticmethod + async def _call(method, *args, **kwargs): + try: + await asyncify(method, *args, **kwargs) + except Exception: + raise ExternalError("Steam API request returned an error.") + async def _update(self, account: Steam): - response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=account._steamid) + # noinspection PyProtectedMember + response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=account._steamid) r = response["response"]["players"][0] account.persona_name = r["personaname"] account.profile_url = r["profileurl"] @@ -44,8 +53,8 @@ class SteampoweredCommand(Command): author = await data.get_author() if len(args) > 0: url = args.joined() - steamid64 = await asyncify(steam.steamid.steam64_from_url, url) - response = await asyncify(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid64) + steamid64 = await self._call(steam.steamid.steam64_from_url, url) + response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid64) r = response["response"]["players"][0] steam_account = self.alchemy.get(Steam)( user=author, From 96fff959a83dddccd1c50c0cf90770723e17f0c6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Apr 2020 17:00:30 +0200 Subject: [PATCH 083/227] Fix skip, queue and pause crashing the bot --- royalpack/events/discord_pause.py | 5 +++-- royalpack/events/discord_queue.py | 5 +++-- royalpack/events/discord_skip.py | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/royalpack/events/discord_pause.py b/royalpack/events/discord_pause.py index f7733f5c..501510c6 100644 --- a/royalpack/events/discord_pause.py +++ b/royalpack/events/discord_pause.py @@ -23,10 +23,11 @@ class DiscordPauseEvent(Event): guild: discord.Guild = client.get_guild(guild_id) if guild is None: raise InvalidInputError("Impossibile trovare il Server specificato.") - voice_player: VoicePlayer = self.serf.find_voice_player(guild) - if voice_player is None: + voice_players = self.serf.find_voice_players(guild) + if len(voice_players): raise UserError("Il bot non è in nessun canale vocale.\n" "Evocalo prima con [c]summon[/c]!") + voice_player = voice_players[0] if voice_player.voice_client.is_paused(): voice_player.voice_client.resume() diff --git a/royalpack/events/discord_queue.py b/royalpack/events/discord_queue.py index 6a668f05..3345e8dc 100644 --- a/royalpack/events/discord_queue.py +++ b/royalpack/events/discord_queue.py @@ -26,10 +26,11 @@ class DiscordQueueEvent(Event): guild: discord.Guild = client.get_guild(guild_id) if guild is None: raise InvalidInputError("Impossibile trovare il Server specificato.") - voice_player: VoicePlayer = self.serf.find_voice_player(guild) - if voice_player is None: + voice_players = self.serf.find_voice_players(guild) + if len(voice_players): raise UserError("Il bot non è in nessun canale vocale.\n" "Evocalo prima con [c]summon[/c]!") + voice_player = voice_players[0] if isinstance(voice_player.playing, RoyalQueue): now_playing = voice_player.playing.now_playing return { diff --git a/royalpack/events/discord_skip.py b/royalpack/events/discord_skip.py index cb186f35..e6537d86 100644 --- a/royalpack/events/discord_skip.py +++ b/royalpack/events/discord_skip.py @@ -23,10 +23,11 @@ class DiscordSkipEvent(Event): guild: discord.Guild = client.get_guild(guild_id) if guild is None: raise InvalidInputError("Impossibile trovare il Server specificato.") - voice_player: VoicePlayer = self.serf.find_voice_player(guild) - if voice_player is None: + voice_players = self.serf.find_voice_players(guild) + if len(voice_players): raise UserError("Il bot non è in nessun canale vocale.\n" "Evocalo prima con [c]summon[/c]!") + voice_player = voice_players[0] # Stop the playback of the current song voice_player.voice_client.stop() # Done! From ca068bb97f2c6697ef561fb5f3eaae6c09daac5d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Apr 2020 17:03:30 +0200 Subject: [PATCH 084/227] Fix fw.steffo.eu not adding songs to the queue --- royalpack/stars/api_discord_play.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index b87fe818..47d0bf6a 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -32,7 +32,7 @@ class ApiDiscordPlayStar(ApiStar): guild_id = None log.info(f"Received request to play {url} on guild_id {guild_id} via web") response = await self.interface.call_herald_event("discord", "discord_play", - url=url, + urls=[url], guild_id=guild_id, user=user) return response From 15c83da73bc6ff00ce73ebab8b96632ba3ed01b3 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Apr 2020 17:10:28 +0200 Subject: [PATCH 085/227] publish: 5.6.11 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0fe64829..d9cdc09a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6.10" + version = "5.6.11" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 5aceca21..fae88841 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6.10" +semantic = "5.6.11" From d5e38ae29a0a95c601edbfeac7b8959bc199b058 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 8 Apr 2020 18:56:16 +0200 Subject: [PATCH 086/227] Add funkwhalealbum and lazyfunkwhalealbum commands --- royalpack/commands/__init__.py | 4 ++++ royalpack/commands/funkwhalealbum.py | 28 ++++++++++++++++++++++++ royalpack/commands/lazyfunkwhalealbum.py | 28 ++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 royalpack/commands/funkwhalealbum.py create mode 100644 royalpack/commands/lazyfunkwhalealbum.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index b96c3acd..e997f6b8 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -48,6 +48,8 @@ from .lazypeertube import LazypeertubeCommand from .lazysoundcloud import LazysoundcloudCommand from .lazyyahoovideo import LazyyahoovideoCommand from .lazyyoutube import LazyyoutubeCommand +from .funkwhalealbum import FunkwhalealbumCommand +from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand # Enter the commands of your Pack here! available_commands = [ @@ -100,6 +102,8 @@ available_commands = [ LazysoundcloudCommand, LazyyahoovideoCommand, LazyyoutubeCommand, + FunkwhalealbumCommand, + LazyfunkwhalealbumCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/funkwhalealbum.py b/royalpack/commands/funkwhalealbum.py new file mode 100644 index 00000000..4965b2ce --- /dev/null +++ b/royalpack/commands/funkwhalealbum.py @@ -0,0 +1,28 @@ +from .play import PlayCommand +from royalnet.commands import * +import aiohttp +import urllib.parse + + +class FunkwhalealbumCommand(PlayCommand): + name: str = "funkwhalealbum" + + aliases = ["fwa", "fwalbum", "funkwhalea"] + + description: str = "Cerca un album su RoyalWhale e aggiungila alla coda della chat vocale." + + syntax = "{ricerca}" + + def get_embed_color(self): + return 0x009FE3 + + async def get_urls(self, args): + search = urllib.parse.quote(args.joined(require_at_least=1)) + async with aiohttp.ClientSession() as session: + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/search?query={search}") as response: + j = await response.json() + if len(j["albums"]) < 1: + raise UserError("Nessun file audio trovato con il nome richiesto.") + album = j["albums"][0] + return [f'{self.config["Funkwhale"]["instance_url"]}{track["listen_url"]}' for track in album["tracks"]] diff --git a/royalpack/commands/lazyfunkwhalealbum.py b/royalpack/commands/lazyfunkwhalealbum.py new file mode 100644 index 00000000..5de6d935 --- /dev/null +++ b/royalpack/commands/lazyfunkwhalealbum.py @@ -0,0 +1,28 @@ +from .lazyplay import LazyplayCommand +from royalnet.commands import * +import aiohttp +import urllib.parse + + +class LazyfunkwhalealbumCommand(LazyplayCommand): + name: str = "lazyfunkwhalealbum" + + aliases = ["lfwa", "lfwalbum", "lazyfunkwhalea"] + + description: str = "Cerca un album su RoyalWhale e aggiungilo (lazy) alla coda della chat vocale." + + syntax = "{ricerca}" + + def get_embed_color(self): + return 0x009FE3 + + async def get_urls(self, args): + search = urllib.parse.quote(args.joined(require_at_least=1)) + async with aiohttp.ClientSession() as session: + async with session.get(self.config["Funkwhale"]["instance_url"] + + f"/api/v1/search?query={search}") as response: + j = await response.json() + if len(j["albums"]) < 1: + raise UserError("Nessun file audio trovato con il nome richiesto.") + album = j["albums"][0] + return [f'{self.config["Funkwhale"]["instance_url"]}{track["listen_url"]}' for track in album["tracks"]] From 8560f850ebe1ee46a2caee47bfcc51325e6c3ab7 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 8 Apr 2020 18:56:41 +0200 Subject: [PATCH 087/227] Don't send more than 5 embeds at a time in the bot chat --- royalpack/events/discord_lazy_play.py | 6 ++++-- royalpack/events/discord_play.py | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/royalpack/events/discord_lazy_play.py b/royalpack/events/discord_lazy_play.py index 1f776769..cfdc6235 100644 --- a/royalpack/events/discord_lazy_play.py +++ b/royalpack/events/discord_lazy_play.py @@ -69,12 +69,14 @@ class DiscordLazyPlayEvent(rc.Event): await main_channel.send(rsd.escape(f"▶️ {user} ha aggiunto {len(added)} file _(lazy)_ alla coda:")) else: await main_channel.send(rsd.escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file " - f"_(lazy)_ alla coda:")) - for ytd in added: + f"[i](lazy)[/i] alla coda:")) + for ytd in added[:5]: embed: discord.Embed = ytd.embed() if force_color: embed._colour = discord.Colour(force_color) await main_channel.send(embed=embed) + if len(added) > 5: + await main_channel.send(f"e altri {len(added) - 5}!") if len(too_long) > 0: if user: diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index 341830cf..4018ef96 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -72,11 +72,13 @@ class DiscordPlayEvent(rc.Event): else: await main_channel.send(rsd.escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" f" coda:")) - for ytd in added: + for ytd in added[:5]: embed: discord.Embed = ytd.embed() if force_color: embed._colour = discord.Colour(force_color) await main_channel.send(embed=embed) + if len(added) > 5: + await main_channel.send(f"e altri {len(added) - 5}!") if len(too_long) > 0: if user: From f032f014c2fac8076a87ed0766554f6dd25c4a08 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 8 Apr 2020 22:00:57 +0200 Subject: [PATCH 088/227] Port old mm to the new bot framework --- poetry.lock | 199 +++++++++++----------- pyproject.toml | 2 +- royalpack/commands/__init__.py | 2 + royalpack/commands/matchmaking.py | 263 ++++++++++++++++++++++++++++++ royalpack/tables/__init__.py | 4 + royalpack/tables/mmevents.py | 52 ++++++ royalpack/tables/mmresponse.py | 31 ++++ royalpack/types/mmchoice.py | 4 +- 8 files changed, 452 insertions(+), 105 deletions(-) create mode 100644 royalpack/commands/matchmaking.py create mode 100644 royalpack/tables/mmevents.py create mode 100644 royalpack/tables/mmresponse.py diff --git a/poetry.lock b/poetry.lock index ea403a6f..e943f42c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -59,7 +59,7 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2019.11.28" +version = "2020.4.5.1" [[package]] category = "main" @@ -117,8 +117,8 @@ category = "main" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." name = "cryptography" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "2.8" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +version = "2.9" [package.dependencies] cffi = ">=1.8,<1.11.3 || >1.11.3" @@ -166,18 +166,18 @@ packaging = "*" [[package]] category = "main" -description = "A python wrapper for the Discord API" +description = "A Python wrapper for the Discord API" name = "discord.py" optional = false python-versions = ">=3.5.3" -version = "1.3.2" +version = "1.3.3" [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.0)", "sphinxcontrib-websupport"] +docs = ["sphinx (1.8.5)", "sphinxcontrib-trio (1.1.1)", "sphinxcontrib-websupport"] voice = ["PyNaCl (1.3.0)"] [[package]] @@ -186,7 +186,7 @@ description = "Python audio data toolkit (ID3 and MP3)" name = "eyed3" optional = false python-versions = "*" -version = "0.9.4" +version = "0.9.5" [package.dependencies] deprecation = "*" @@ -429,7 +429,7 @@ description = "psycopg2 - Python-PostgreSQL Database Adapter" name = "psycopg2-binary" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "2.8.4" +version = "2.8.5" [[package]] category = "main" @@ -469,7 +469,7 @@ description = "Python parsing module" name = "pyparsing" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.6" +version = "2.4.7" [[package]] category = "main" @@ -519,7 +519,7 @@ description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" optional = false python-versions = "*" -version = "12.4.2" +version = "12.5.1" [package.dependencies] certifi = "*" @@ -546,7 +546,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.2.20" +version = "2020.4.4" [[package]] category = "main" @@ -586,7 +586,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.6.6" +version = "5.7.1" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -716,7 +716,7 @@ description = "Database Abstraction Library" name = "sqlalchemy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.15" +version = "1.3.16" [package.extras] mssql = ["pyodbc"] @@ -867,7 +867,7 @@ python-versions = "*" version = "2020.3.24" [metadata] -content-hash = "424a17455e19b7aa11d52d3a37548275adae578539f501d59c111b7f43c79dc1" +content-hash = "e6f0356444aeacd4b2cfb077df236449d2ff8f4534fda39f846b30c2fff8e5d3" python-versions = "^3.8" [metadata.files] @@ -914,8 +914,8 @@ bcrypt = [ {file = "bcrypt-3.1.7.tar.gz", hash = "sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42"}, ] certifi = [ - {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, - {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, + {file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"}, + {file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"}, ] cffi = [ {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, @@ -964,27 +964,25 @@ coloredlogs = [ {file = "coloredlogs-10.0.tar.gz", hash = "sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"}, ] cryptography = [ - {file = "cryptography-2.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8"}, - {file = "cryptography-2.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2"}, - {file = "cryptography-2.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad"}, - {file = "cryptography-2.8-cp27-cp27m-win32.whl", hash = "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2"}, - {file = "cryptography-2.8-cp27-cp27m-win_amd64.whl", hash = "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912"}, - {file = "cryptography-2.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d"}, - {file = "cryptography-2.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42"}, - {file = "cryptography-2.8-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879"}, - {file = "cryptography-2.8-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d"}, - {file = "cryptography-2.8-cp34-abi3-manylinux2010_x86_64.whl", hash = "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9"}, - {file = "cryptography-2.8-cp34-cp34m-win32.whl", hash = "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c"}, - {file = "cryptography-2.8-cp34-cp34m-win_amd64.whl", hash = "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0"}, - {file = "cryptography-2.8-cp35-cp35m-win32.whl", hash = "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf"}, - {file = "cryptography-2.8-cp35-cp35m-win_amd64.whl", hash = "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793"}, - {file = "cryptography-2.8-cp36-cp36m-win32.whl", hash = "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595"}, - {file = "cryptography-2.8-cp36-cp36m-win_amd64.whl", hash = "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7"}, - {file = "cryptography-2.8-cp37-cp37m-win32.whl", hash = "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff"}, - {file = "cryptography-2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f"}, - {file = "cryptography-2.8-cp38-cp38-win32.whl", hash = "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e"}, - {file = "cryptography-2.8-cp38-cp38-win_amd64.whl", hash = "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13"}, - {file = "cryptography-2.8.tar.gz", hash = "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651"}, + {file = "cryptography-2.9-cp27-cp27m-macosx_10_9_intel.whl", hash = "sha256:ef9a55013676907df6c9d7dd943eb1770d014f68beaa7e73250fb43c759f4585"}, + {file = "cryptography-2.9-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2a2ad24d43398d89f92209289f15265107928f22a8d10385f70def7a698d6a02"}, + {file = "cryptography-2.9-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:95e1296e0157361fe2f5f0ed307fd31f94b0ca13372e3673fa95095a627636a1"}, + {file = "cryptography-2.9-cp27-cp27m-win32.whl", hash = "sha256:192ca04a36852a994ef21df13cca4d822adbbdc9d5009c0f96f1d2929e375d4f"}, + {file = "cryptography-2.9-cp27-cp27m-win_amd64.whl", hash = "sha256:ed1d0760c7e46436ec90834d6f10477ff09475c692ed1695329d324b2c5cd547"}, + {file = "cryptography-2.9-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:19ae795137682a9778892fb4390c07811828b173741bce91e30f899424b3934d"}, + {file = "cryptography-2.9-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d1bf5a1a0d60c7f9a78e448adcb99aa101f3f9588b16708044638881be15d6bc"}, + {file = "cryptography-2.9-cp35-abi3-macosx_10_9_intel.whl", hash = "sha256:1b9b535d6b55936a79dbe4990b64bb16048f48747c76c29713fea8c50eca2acf"}, + {file = "cryptography-2.9-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:7a279f33a081d436e90e91d1a7c338553c04e464de1c9302311a5e7e4b746088"}, + {file = "cryptography-2.9-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:49870684da168b90110bbaf86140d4681032c5e6a2461adc7afdd93be5634216"}, + {file = "cryptography-2.9-cp35-cp35m-win32.whl", hash = "sha256:6b91cab3841b4c7cb70e4db1697c69f036c8bc0a253edc0baa6783154f1301e4"}, + {file = "cryptography-2.9-cp35-cp35m-win_amd64.whl", hash = "sha256:587f98ce27ac4547177a0c6fe0986b8736058daffe9160dcf5f1bd411b7fbaa1"}, + {file = "cryptography-2.9-cp36-cp36m-win32.whl", hash = "sha256:cc20316e3f5a6b582fc3b029d8dc03aabeb645acfcb7fc1d9848841a33265748"}, + {file = "cryptography-2.9-cp36-cp36m-win_amd64.whl", hash = "sha256:3be7a5722d5bfe69894d3f7bbed15547b17619f3a88a318aab2e37f457524164"}, + {file = "cryptography-2.9-cp37-cp37m-win32.whl", hash = "sha256:7598974f6879a338c785c513e7c5a4329fbc58b9f6b9a6305035fca5b1076552"}, + {file = "cryptography-2.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5aca6f00b2f42546b9bdf11a69f248d1881212ce5b9e2618b04935b87f6f82a1"}, + {file = "cryptography-2.9-cp38-cp38-win32.whl", hash = "sha256:9fc9da390e98cb6975eadf251b6e5fa088820141061bf041cd5c72deba1dc526"}, + {file = "cryptography-2.9-cp38-cp38-win_amd64.whl", hash = "sha256:6b744039b55988519cc183149cceb573189b3e46e16ccf6f8c46798bb767c9dc"}, + {file = "cryptography-2.9.tar.gz", hash = "sha256:0cacd3ef5c604b8e5f59bf2582c076c98a37fe206b31430d0cd08138aff0986e"}, ] dateparser = [ {file = "dateparser-0.7.4-py2.py3-none-any.whl", hash = "sha256:1b1f0e3034f82d1f92b45fa445826da6a36d67af8a1169e04869685594276011"}, @@ -999,12 +997,13 @@ deprecation = [ {file = "deprecation-2.0.7.tar.gz", hash = "sha256:c0392f676a6146f0238db5744d73e786a43510d54033f80994ef2f4c9df192ed"}, ] "discord.py" = [ - {file = "discord.py-1.3.2-py3-none-any.whl", hash = "sha256:7424be26b07b37ecad4404d9383d685995a0e0b3df3f9c645bdd3a4d977b83b4"}, + {file = "discord.py-1.3.3-py3-none-any.whl", hash = "sha256:406871b06d86c3dc49fba63238519f28628dac946fef8a0e22988ff58ec05580"}, + {file = "discord.py-1.3.3.tar.gz", hash = "sha256:ad00e34c72d2faa8db2157b651d05f3c415d7d05078e7e41dc9e8dc240051beb"}, ] eyed3 = [ - {file = "eyeD3-0.9.4-py2.py3-none-any.whl", hash = "sha256:4cba88297ded486ac5b127b4dd5944c453be52c015ed82400fde30907e2972f8"}, - {file = "eyeD3-0.9.4-py3.8.egg", hash = "sha256:b7ac8695d7acdbd67d5e6edc48e9e082faae40ed852cf3e0fcd6d878624ee8d4"}, - {file = "eyeD3-0.9.4.tar.gz", hash = "sha256:11099464e438c11a1d701e723a5065c1556fb59878ad9dce29f924dac3a07a96"}, + {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"}, @@ -1160,38 +1159,36 @@ protobuf = [ {file = "protobuf-3.11.3.tar.gz", hash = "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f"}, ] psycopg2-binary = [ - {file = "psycopg2-binary-2.8.4.tar.gz", hash = "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed"}, - {file = "psycopg2_binary-2.8.4-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6"}, - {file = "psycopg2_binary-2.8.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4"}, - {file = "psycopg2_binary-2.8.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e"}, - {file = "psycopg2_binary-2.8.4-cp27-cp27m-win32.whl", hash = "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103"}, - {file = "psycopg2_binary-2.8.4-cp27-cp27m-win_amd64.whl", hash = "sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35"}, - {file = "psycopg2_binary-2.8.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9"}, - {file = "psycopg2_binary-2.8.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b"}, - {file = "psycopg2_binary-2.8.4-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309"}, - {file = "psycopg2_binary-2.8.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e"}, - {file = "psycopg2_binary-2.8.4-cp34-cp34m-win32.whl", hash = "sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29"}, - {file = "psycopg2_binary-2.8.4-cp34-cp34m-win_amd64.whl", hash = "sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49"}, - {file = "psycopg2_binary-2.8.4-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881"}, - {file = "psycopg2_binary-2.8.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e"}, - {file = "psycopg2_binary-2.8.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"}, - {file = "psycopg2_binary-2.8.4-cp35-cp35m-win32.whl", hash = "sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03"}, - {file = "psycopg2_binary-2.8.4-cp35-cp35m-win_amd64.whl", hash = "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e"}, - {file = "psycopg2_binary-2.8.4-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3"}, - {file = "psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d"}, - {file = "psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd"}, - {file = "psycopg2_binary-2.8.4-cp36-cp36m-win32.whl", hash = "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f"}, - {file = "psycopg2_binary-2.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7"}, - {file = "psycopg2_binary-2.8.4-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b"}, - {file = "psycopg2_binary-2.8.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964"}, - {file = "psycopg2_binary-2.8.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70"}, - {file = "psycopg2_binary-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03"}, - {file = "psycopg2_binary-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8"}, - {file = "psycopg2_binary-2.8.4-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b"}, - {file = "psycopg2_binary-2.8.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039"}, - {file = "psycopg2_binary-2.8.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103"}, - {file = "psycopg2_binary-2.8.4-cp38-cp38-win32.whl", hash = "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1"}, - {file = "psycopg2_binary-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f"}, + {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"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:08507efbe532029adee21b8d4c999170a83760d38249936038bd0602327029b5"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b9a8b391c2b0321e0cd7ec6b4cfcc3dd6349347bd1207d48bcb752aa6c553a66"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-win32.whl", hash = "sha256:3286541b9d85a340ee4ed42732d15fc1bb441dc500c97243a768154ab8505bb5"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-win_amd64.whl", hash = "sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ba13346ff6d3eb2dca0b6fa0d8a9d999eff3dcd9b55f3a890f12b0b6362b2b38"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:c8830b7d5f16fd79d39b21e3d94f247219036b29b30c8270314c46bf8b732389"}, + {file = "psycopg2_binary-2.8.5-cp34-cp34m-win32.whl", hash = "sha256:51f7823f1b087d2020d8e8c9e6687473d3d239ba9afc162d9b2ab6e80b53f9f9"}, + {file = "psycopg2_binary-2.8.5-cp34-cp34m-win_amd64.whl", hash = "sha256:107d9be3b614e52a192719c6bf32e8813030020ea1d1215daa86ded9a24d8b04"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:930315ac53dc65cbf52ab6b6d27422611f5fb461d763c531db229c7e1af6c0b3"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:6bb2dd006a46a4a4ce95201f836194eb6a1e863f69ee5bab506673e0ca767057"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3939cf75fc89c5e9ed836e228c4a63604dff95ad19aed2bbf71d5d04c15ed5ce"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-win32.whl", hash = "sha256:a20299ee0ea2f9cca494396ac472d6e636745652a64a418b39522c120fd0a0a4"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-win_amd64.whl", hash = "sha256:cc30cb900f42c8a246e2cb76539d9726f407330bc244ca7729c41a44e8d807fb"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:40abc319f7f26c042a11658bf3dd3b0b3bceccf883ec1c565d5c909a90204434"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:702f09d8f77dc4794651f650828791af82f7c2efd8c91ae79e3d9fe4bb7d4c98"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d1a8b01f6a964fec702d6b6dac1f91f2b9f9fe41b310cbb16c7ef1fac82df06d"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-win32.whl", hash = "sha256:17a0ea0b0eabf07035e5e0d520dabc7950aeb15a17c6d36128ba99b2721b25b1"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:e004db88e5a75e5fdab1620fb9f90c9598c2a195a594225ac4ed2a6f1c23e162"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:a34826d6465c2e2bbe9d0605f944f19d2480589f89863ed5f091943be27c9de4"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cac918cd7c4c498a60f5d2a61d4f0a6091c2c9490d81bc805c963444032d0dab"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7b832d76cc65c092abd9505cc670c4e3421fd136fb6ea5b94efbe4c146572505"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:bb0608694a91db1e230b4a314e8ed00ad07ed0c518f9a69b83af2717e31291a3"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:eb2f43ae3037f1ef5e19339c41cf56947021ac892f668765cd65f8ab9814192e"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:07cf82c870ec2d2ce94d18e70c13323c89f2f2a2628cbf1feee700630be2519a"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a69970ee896e21db4c57e398646af9edc71c003bc52a3cc77fb150240fefd266"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7036ccf715925251fac969f4da9ad37e4b7e211b1e920860148a10c0de963522"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-win32.whl", hash = "sha256:8f74e631b67482d504d7e9cf364071fc5d54c28e79a093ff402d5f8f81e23bfa"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:fa466306fcf6b39b8a61d003123d442b23707d635a5cb05ac4e1b62cc79105cd"}, ] pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, @@ -1253,8 +1250,8 @@ pynacl = [ {file = "PyNaCl-1.3.0.tar.gz", hash = "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c"}, ] pyparsing = [ - {file = "pyparsing-2.4.6-py2.py3-none-any.whl", hash = "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"}, - {file = "pyparsing-2.4.6.tar.gz", hash = "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f"}, + {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"}, @@ -1272,35 +1269,35 @@ python-multipart = [ {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, ] python-telegram-bot = [ - {file = "python-telegram-bot-12.4.2.tar.gz", hash = "sha256:0a97cbca638f949582b4ee326170d2f8d7f4bf559a4e511132bb2203623e04ad"}, - {file = "python_telegram_bot-12.4.2-py2.py3-none-any.whl", hash = "sha256:d3cffd020af4094d07c11783f875e5c682072ba7f5bc21ce89ff0222f4e6d742"}, + {file = "python-telegram-bot-12.5.1.tar.gz", hash = "sha256:6d69fb04dc8d83e01cb25a0d83aaa2a1a4b7d5b14cd38b9f8922a567b4a4a510"}, + {file = "python_telegram_bot-12.5.1-py2.py3-none-any.whl", hash = "sha256:af36fbf051415ded8b2633f27b71d292efcd85d58a647a1f138db191380144ff"}, ] pytz = [ {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, ] regex = [ - {file = "regex-2020.2.20-cp27-cp27m-win32.whl", hash = "sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb"}, - {file = "regex-2020.2.20-cp27-cp27m-win_amd64.whl", hash = "sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc"}, - {file = "regex-2020.2.20-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0"}, - {file = "regex-2020.2.20-cp36-cp36m-win32.whl", hash = "sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69"}, - {file = "regex-2020.2.20-cp36-cp36m-win_amd64.whl", hash = "sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce"}, - {file = "regex-2020.2.20-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab"}, - {file = "regex-2020.2.20-cp37-cp37m-win32.whl", hash = "sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431"}, - {file = "regex-2020.2.20-cp37-cp37m-win_amd64.whl", hash = "sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux1_i686.whl", hash = "sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2"}, - {file = "regex-2020.2.20-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70"}, - {file = "regex-2020.2.20-cp38-cp38-win32.whl", hash = "sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d"}, - {file = "regex-2020.2.20-cp38-cp38-win_amd64.whl", hash = "sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa"}, - {file = "regex-2020.2.20.tar.gz", hash = "sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5"}, + {file = "regex-2020.4.4-cp27-cp27m-win32.whl", hash = "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f"}, + {file = "regex-2020.4.4-cp27-cp27m-win_amd64.whl", hash = "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156"}, + {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3"}, + {file = "regex-2020.4.4-cp36-cp36m-win32.whl", hash = "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8"}, + {file = "regex-2020.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd"}, + {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948"}, + {file = "regex-2020.4.4-cp37-cp37m-win32.whl", hash = "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e"}, + {file = "regex-2020.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b"}, + {file = "regex-2020.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89"}, + {file = "regex-2020.4.4-cp38-cp38-win32.whl", hash = "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3"}, + {file = "regex-2020.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3"}, + {file = "regex-2020.4.4.tar.gz", hash = "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142"}, ] requests = [ {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, @@ -1311,8 +1308,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.6.6-py3-none-any.whl", hash = "sha256:2793af4c09c364403400012a1b6e76cb012ab90c105bd512e6d21219d9ec2bbd"}, - {file = "royalnet-5.6.6.tar.gz", hash = "sha256:c2fc05049cd1a5185941458cf519ad46d871e475d0bb5e2ead968f148d27d836"}, + {file = "royalnet-5.7.1-py3-none-any.whl", hash = "sha256:fc0c1933d5bb55b8e84e0e8034b5d2e341429527399e79f67eb2677f16cb03c8"}, + {file = "royalnet-5.7.1.tar.gz", hash = "sha256:332baf43b05b6c5abff8c6e37fdaad0b8b4d87202ebc162753dd7805ff7aea8e"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1326,7 +1323,7 @@ six = [ {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.15.tar.gz", hash = "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"}, + {file = "SQLAlchemy-1.3.16.tar.gz", hash = "sha256:7224e126c00b8178dfd227bc337ba5e754b197a3867d33b9f30dc0208f773d70"}, ] starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, diff --git a/pyproject.toml b/pyproject.toml index d9cdc09a..d9148103 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "~5.6.6" + version = "^5.7" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index e997f6b8..bb69797b 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -50,6 +50,7 @@ from .lazyyahoovideo import LazyyahoovideoCommand from .lazyyoutube import LazyyoutubeCommand from .funkwhalealbum import FunkwhalealbumCommand from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand +from .matchmaking import MatchmakingCommand # Enter the commands of your Pack here! available_commands = [ @@ -104,6 +105,7 @@ available_commands = [ LazyyoutubeCommand, FunkwhalealbumCommand, LazyfunkwhalealbumCommand, + MatchmakingCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py new file mode 100644 index 00000000..645185f0 --- /dev/null +++ b/royalpack/commands/matchmaking.py @@ -0,0 +1,263 @@ +import datetime +import re +import dateparser +import typing +from telegram import Bot as PTBBot +from telegram import Message as PTBMessage +from telegram import InlineKeyboardMarkup as InKM +from telegram import InlineKeyboardButton as InKB +from telegram.error import BadRequest, Unauthorized +from royalnet.commands import * +from royalnet.serf.telegram import TelegramSerf as TelegramBot +from royalnet.serf.telegram import escape as telegram_escape +from royalnet.utils import asyncify, sleep_until +from royalnet.backpack.tables import User +from ..tables import MMEvent, MMResponse +from ..types import MMChoice, MMInterfaceDataTelegram + + +class MatchmakingCommand(Command): + name: str = "matchmaking" + + description: str = "Cerca persone per una partita a qualcosa!" + + syntax: str = "[ {ora} ] {nome}\n[descrizione]" + + aliases = ["mm", "lfg"] + + tables = {MMEvent, MMResponse} + + def __init__(self, interface: CommandInterface): + super().__init__(interface) + # Find all relevant MMEvents and run them + session = self.alchemy.Session() + mmevents = ( + session.query(self.alchemy.get(MMEvent)) + .filter(self.alchemy.get(MMEvent).interface == self.interface.name, + self.alchemy.get(MMEvent).datetime > datetime.datetime.now()) + .all() + ) + for mmevent in mmevents: + self.interface.loop.create_task(self._run_mmevent(mmevent.mmid)) + + async def run(self, args: CommandArgs, data: CommandData) -> None: + # Create a new MMEvent and run it + if self.interface.name != "telegram": + raise UnsupportedError(f"{self.interface.prefix}matchmaking funziona solo su Telegram. Per ora.") + author = await data.get_author(error_if_none=True) + + try: + timestring, title, description = args.match(r"\[\s*([^]]+)\s*]\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) + except InvalidInputError: + timestring, title, description = args.match(r"\s*(.+?)\s*\n\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) + try: + dt: typing.Optional[datetime.datetime] = dateparser.parse(timestring, settings={ + "PREFER_DATES_FROM": "future" + }) + except OverflowError: + dt = None + if dt is None: + await data.reply("⚠️ La data che hai specificato non è valida.") + return + if dt <= datetime.datetime.now(): + await data.reply("⚠️ La data che hai specificato è nel passato.") + return + 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() + self.loop.create_task(self._run_mmevent(mmevent.mmid)) + await data.reply(f"✅ Evento [b]{mmevent.title}[/b] creato!") + + def _gen_mm_message(self, mmevent: MMEvent) -> str: + text = f"🌐 [{mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{mmevent.title}[/b]\n" + if mmevent.description: + text += f"{mmevent.description}\n" + text += "\n" + for response in mmevent.responses: + response: MMResponse + text += f"{response.choice.value} {response.user}\n" + return text + + def _gen_telegram_keyboard(self, mmevent: MMEvent): + return InKM([ + [ + InKB(f"{MMChoice.YES.value} Ci sarò!", + callback_data=f"mm{mmevent.mmid}_YES"), + InKB(f"{MMChoice.MAYBE.value} Forse...", + callback_data=f"mm{mmevent.mmid}_MAYBE"), + ], + [ + InKB(f"{MMChoice.LATE_SHORT.value} 10 min", + callback_data=f"mm{mmevent.mmid}_LATE_SHORT"), + InKB(f"{MMChoice.LATE_MEDIUM.value} 30 min", + callback_data=f"mm{mmevent.mmid}_LATE_MEDIUM"), + InKB(f"{MMChoice.LATE_LONG.value} 60 min", + callback_data=f"mm{mmevent.mmid}_LATE_LONG"), + ], + [ + InKB(f"{MMChoice.NO.value} Non mi interessa.", + callback_data=f"mm{mmevent.mmid}_NO"), + ] + ]) + + async def _update_telegram_mm_message(self, client: PTBBot, mmevent: MMEvent): + try: + await self.interface.serf.api_call(client.edit_message_text, + chat_id=self.config["Matchmaking"]["mm_chat_id"], + text=telegram_escape(self._gen_mm_message(mmevent)), + message_id=mmevent.interface_data.message_id, + parse_mode="HTML", + disable_web_page_preview=True, + reply_markup=self._gen_telegram_keyboard(mmevent)) + except BadRequest: + pass + + def _gen_mm_telegram_callback(self, client: PTBBot, mmid: int, choice: MMChoice): + async def callback(data: CommandData): + author = await data.get_author(error_if_none=True) + # Find the MMEvent with the current session + mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) + mmresponse: MMResponse = await asyncify( + data.session.query(self.alchemy.get(MMResponse)).filter_by(user=author, mmevent=mmevent).one_or_none) + if mmresponse is None: + mmresponse = self.alchemy.get(MMResponse)(user=author, mmevent=mmevent, choice=choice) + data.session.add(mmresponse) + else: + mmresponse.choice = choice + await data.session_commit() + await self._update_telegram_mm_message(client, mmevent) + return f"✅ Messaggio ricevuto!" + + return callback + + def _gen_event_start_message(self, mmevent: MMEvent): + text = f"🚩 L'evento [b]{mmevent.title}[/b] è iniziato!\n\n" + for response in mmevent.responses: + response: MMResponse + text += f"{response.choice.value} {response.user}\n" + return text + + def _gen_unauth_message(self, user: User): + return f"⚠️ Non sono autorizzato a mandare messaggi a [b]{user.username}[/b]!\n" \ + f"{user.telegram.mention()}, apri una chat privata con me e mandami un messaggio!" + + async def _run_mmevent(self, mmid: int): + """Run a MMEvent.""" + # Open a new Alchemy Session + session = self.alchemy.Session() + # Find the MMEvent with the current session + mmevent: MMEvent = await asyncify(session.query(self.alchemy.get(MMEvent)).get, mmid) + if mmevent is None: + raise ValueError("Invalid mmid.") + # Ensure the MMEvent hasn't already started + if mmevent.datetime <= datetime.datetime.now(): + raise ValueError("MMEvent has already started.") + # Ensure the MMEvent interface matches the current one + if mmevent.interface != self.interface.name: + raise ValueError("Invalid interface.") + # If the matchmaking message hasn't been sent yet, do so now + if mmevent.interface_data is None: + if self.interface.name == "telegram": + bot: TelegramBot = self.interface.serf + client: PTBBot = bot.client + # Send the keyboard + message: PTBMessage = await self.interface.serf.api_call( + client.send_message, + chat_id=self.config["Matchmaking"]["mm_chat_id"], + text=telegram_escape( + self._gen_mm_message(mmevent)), + parse_mode="HTML", + disable_webpage_preview=True, + reply_markup=self._gen_telegram_keyboard(mmevent) + ) + # Store message data in the interface data object + mmevent.interface_data = MMInterfaceDataTelegram(chat_id=self.config["Matchmaking"]["mm_chat_id"], + message_id=message.message_id) + await asyncify(session.commit) + else: + raise UnsupportedError() + # Register handlers for the keyboard events + if self.interface.name == "telegram": + bot: TelegramBot = self.interface.serf + client: PTBBot = bot.client + bot.register_keyboard_key(f"mm{mmevent.mmid}_YES", key=KeyboardKey( + interface=self.interface, + short=f"{MMChoice.YES.value}", + text="Ci sarò!", + callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.YES) + )) + bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_SHORT", key=KeyboardKey( + interface=self.interface, + short=f"{MMChoice.LATE_SHORT.value}", + text="10 min", + callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_SHORT) + )) + bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM", key=KeyboardKey( + interface=self.interface, + short=f"{MMChoice.LATE_MEDIUM.value}", + text="30 min", + callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_MEDIUM) + )) + bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG", key=KeyboardKey( + interface=self.interface, + short=f"{MMChoice.LATE_LONG.value}", + text="60 min", + callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_LONG) + )) + bot.register_keyboard_key(f"mm{mmevent.mmid}_MAYBE", key=KeyboardKey( + interface=self.interface, + short=f"{MMChoice.MAYBE.value}", + text="Forse...", + callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.MAYBE) + )) + bot.register_keyboard_key(f"mm{mmevent.mmid}_NO", key=KeyboardKey( + interface=self.interface, + short=f"{MMChoice.NO.value}", + text="Non mi interessa.", + callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.NO) + )) + else: + raise UnsupportedError() + # Sleep until the time of the event + await sleep_until(mmevent.datetime) + # Notify the positive answers of the event start + if self.interface.name == "telegram": + bot: TelegramBot = self.interface.serf + client: PTBBot = bot.client + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_YES") + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_MAYBE") + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_SHORT") + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM") + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG") + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_NO") + for response in mmevent.responses: + if response.choice == MMChoice.NO: + return + try: + await self.interface.serf.api_call(client.send_message, + chat_id=response.user.telegram[0].tg_id, + text=telegram_escape(self._gen_event_start_message(mmevent)), + parse_mode="HTML", + disable_webpage_preview=True) + except Unauthorized: + await self.interface.serf.api_call(client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=telegram_escape( + self._gen_unauth_message(response.user)), + parse_mode="HTML", + disable_webpage_preview=True) + else: + raise UnsupportedError() + # Delete the event message + if self.interface.name == "telegram": + await self.interface.serf.api_call(client.delete_message, + chat_id=mmevent.interface_data.chat_id, + message_id=mmevent.interface_data.message_id, + parse_mode="HTML", + disable_webpage_preview=True) + # The end! + await asyncify(session.close) diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 71db86ca..1359d360 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -14,6 +14,8 @@ from .polls import Poll from .pollcomments import PollComment from .pollvotes import PollVote from .brawlhalladuos import BrawlhallaDuo +from .mmevents import MMEvent +from .mmresponse import MMResponse # Enter the tables of your Pack here! available_tables = [ @@ -32,6 +34,8 @@ available_tables = [ PollComment, PollVote, BrawlhallaDuo, + MMEvent, + MMResponse, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/mmevents.py b/royalpack/tables/mmevents.py new file mode 100644 index 00000000..f633c0f8 --- /dev/null +++ b/royalpack/tables/mmevents.py @@ -0,0 +1,52 @@ +import pickle +from sqlalchemy import * +from sqlalchemy.orm import relationship +from sqlalchemy.ext.declarative import declared_attr + + +class MMEvent: + __tablename__ = "mmevents" + + @declared_attr + def creator_id(self): + return Column(Integer, ForeignKey("users.uid"), nullable=False) + + @declared_attr + def creator(self): + return relationship("User", backref="mmevents_created") + + @declared_attr + def mmid(self): + return Column(Integer, primary_key=True) + + @declared_attr + def datetime(self): + return Column(DateTime, nullable=False) + + @declared_attr + def title(self): + return Column(String, nullable=False) + + @declared_attr + def description(self): + return Column(Text, nullable=False, default="") + + @declared_attr + def interface(self): + return Column(String, nullable=False) + + @declared_attr + def raw_interface_data(self): + # The default is a pickled None + return Column(Binary, nullable=False, default=b'\x80\x03N.') + + @property + def interface_data(self): + return pickle.loads(self.raw_interface_data) + + @interface_data.setter + def interface_data(self, value): + self.raw_interface_data = pickle.dumps(value) + + def __repr__(self): + return f"" diff --git a/royalpack/tables/mmresponse.py b/royalpack/tables/mmresponse.py new file mode 100644 index 00000000..6135e46c --- /dev/null +++ b/royalpack/tables/mmresponse.py @@ -0,0 +1,31 @@ +from sqlalchemy import * +from sqlalchemy.orm import relationship +from sqlalchemy.ext.declarative import declared_attr +from ..types import MMChoice + + +class MMResponse: + __tablename__ = "mmresponse" + + @declared_attr + def user_id(self): + return Column(Integer, ForeignKey("users.uid"), primary_key=True) + + @declared_attr + def user(self): + return relationship("User", backref="mmresponses_given") + + @declared_attr + def mmevent_id(self): + return Column(Integer, ForeignKey("mmevents.mmid"), primary_key=True) + + @declared_attr + def mmevent(self): + return relationship("MMEvent", backref="responses") + + @declared_attr + def choice(self): + return Column(Enum(MMChoice), nullable=False) + + def __repr__(self): + return f"" diff --git a/royalpack/types/mmchoice.py b/royalpack/types/mmchoice.py index 5f54a507..955f19df 100644 --- a/royalpack/types/mmchoice.py +++ b/royalpack/types/mmchoice.py @@ -7,6 +7,4 @@ class MMChoice(enum.Enum): LATE_SHORT = "🕐" LATE_MEDIUM = "🕒" LATE_LONG = "🕗" - NO_TIME = "🔴" - NO_INTEREST = "❌" - NO_TECH = "❗️" + NO = "❌" From 49da9663bcf6818c670a49c5e4c4f74094776a16 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 8 Apr 2020 22:01:18 +0200 Subject: [PATCH 089/227] publish: 5.7.0 --- royalpack/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/version.py b/royalpack/version.py index fae88841..56feeb31 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.6.11" +semantic = "5.7.0" From 70cb4db2008ce4a278aaf5545eed30b05b999813 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 8 Apr 2020 22:01:29 +0200 Subject: [PATCH 090/227] publish: 5.7.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d9148103..481b011a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.6.11" + version = "5.7.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" From 7f647500b2730e63cfd8f8c9429a98fa4b50ed3c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Apr 2020 14:16:28 +0200 Subject: [PATCH 091/227] publish: 5.7.1 --- pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 8 ++++++-- royalpack/version.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 481b011a..4f5df0a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.0" + version = "5.7.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 645185f0..548f24c5 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -2,6 +2,7 @@ import datetime import re import dateparser import typing +import asyncio from telegram import Bot as PTBBot from telegram import Message as PTBMessage from telegram import InlineKeyboardMarkup as InKM @@ -83,6 +84,8 @@ class MatchmakingCommand(Command): return text def _gen_telegram_keyboard(self, mmevent: MMEvent): + if mmevent.datetime <= datetime.datetime.now(): + return None return InKM([ [ InKB(f"{MMChoice.YES.value} Ci sarò!", @@ -130,7 +133,7 @@ class MatchmakingCommand(Command): mmresponse.choice = choice await data.session_commit() await self._update_telegram_mm_message(client, mmevent) - return f"✅ Messaggio ricevuto!" + await data.reply(f"✅ Messaggio ricevuto!") return callback @@ -252,7 +255,8 @@ class MatchmakingCommand(Command): disable_webpage_preview=True) else: raise UnsupportedError() - # Delete the event message + # Delete the event message after 10 minutes + await asyncio.sleep(600) if self.interface.name == "telegram": await self.interface.serf.api_call(client.delete_message, chat_id=mmevent.interface_data.chat_id, diff --git a/royalpack/version.py b/royalpack/version.py index 56feeb31..d25d2258 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.0" +semantic = "5.7.1" From 8575f03e622024544e36ac1271450a4a49caeed6 Mon Sep 17 00:00:00 2001 From: Cookie <58516648+Cookie-CHR@users.noreply.github.com> Date: Thu, 9 Apr 2020 17:29:49 +0200 Subject: [PATCH 092/227] Update eat.py Aggiunti 4 o 5 cibi che mi sono venuti in mente ultimamente --- royalpack/commands/eat.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 6259a497..de695d21 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -28,8 +28,7 @@ class EatCommand(Command): "evilbalu": "🚹 Hai mangiato {food}.\n[i]Sa di snado.[/i]", "balubis": "🚹 Hai mangiato {food}.\n[i]Sa di acqua calda.[/i]", "goodbalu": "🚹 Hai mangiato {food}.\n[i]Sa di acqua calda.[/i]", - "chiara": "🚺 Hai mangiato {food}.\n[i]Sa un po' di biscotto, ma per lo più sa di curcuma, pepe e spezie" - " varie.[/i]", + "chiara": "🚺 Hai mangiato {food}.\n[i]Sa un po' di biscotto, ma per lo più sa di curcuma e pepe.[/i]", "fabio": "🚹 Hai mangiato {food}.\n[i]Sa di gelatina tuttigusti+1.[/i]", "proto": "🚹 Hai mangiato {food}.\n[i]Sa di gelatina tuttigusti+1.[/i]", "marco": "🚹 Hai mangiato {food}.\n[i]Sa di carlino <.<[/i]", @@ -74,11 +73,14 @@ class EatCommand(Command): "little salami": "🥓 Mmmh, tasty!\n[i]Cats can have {food} too![/i]", "a little salami": "🥓 Mmmh, tasty!\n[i]Cats can have {food} too![/i]", "pollo": '🍗 Il {food} che hai appena mangiato proveniva dallo spazio.\n[i]Coccodè?[/i]', + "pranzo di marco": '🍗 Hai mangiato il {food}.\n[i]Ti senti lactose-free, ma un po\' povero in calcio.[/i]', + "pranzo di mallllco": '🍗 Hai mangiato il {food}.\n[i]Ti senti lactose-free, ma un po\' povero in calcio.[/i]', "gnocchetti": "🥘 Ullà, sono duri 'sti {food}!\n[i]Fai fatica a digerirli.[/i]", "spam": "🥫 Hai mangiato {food}. La famosa carne in gelatina, ovviamente!\n[i]A questo proposito, di " "sicuro sarai interessato all'acquisto di 1087 scatole di Simmenthal in offerta speciale![/i]", "riso": "🍚 Hai mangiato del {food}. Non ci resta che il Pianto! \n[i]Ba dum tsss![/i]", "gelato": "🍨 Mangiando del {food}, hai invocato Steffo.\n[i]Cedigli ora il tuo gelato.[/i]", + "gelato di steffo": "🍨 Hai provato a rubare il {food}...\n[i]...Ma sei arrivato tardi: l'ha già mangiato.[/i]", "biscotto": "🍪 Hai mangiato un {food} di contrabbando.\n[i]L'Inquisizione non lo saprà mai![/i]", "biscotti": "🍪 Hai mangiato tanti {food} di contrabbando.\n[i]Attento! L'Inquisizione è sulle tue tracce![/i]", @@ -96,6 +98,7 @@ class EatCommand(Command): "kaffé": "☕️ Ma BUONGIORNISSIMOOO !!!!\n[i]Non si può iniziare la giornata senza un buon {food} !![/i]", "kaffe": "☕️ Ma BUONGIORNISSIMOOO !!!!\n[i]Non si può iniziare la giornata senza un buon {food} !![/i]", "birra": "🍺 Hai mangiato {food}.\n[i]Adesso sei un povero barbone alcolizzato.[/i]", + "martini": "🍸 Hai ordinato un {food}. Agitato, non mescolato.\n[i]Adesso hai licenza di uccidere![/i]", "redbull": "🍾 Hai mangiato {food}.\n[i]Adesso puoi volare![/i]", "red bull": "🍾 Hai mangiato {food}.\n[i]Adesso puoi volare![/i]", @@ -135,6 +138,10 @@ class EatCommand(Command): "royal bot": "🤖 Come osi provare a mangiarmi?!\n[i]Il {food} è arrabbiato con te.[/i]", "re": "👑 Hai mangiato il {food} avversario! \n[i]Scacco matto![/i]", "furry": "🐕 Hai mangiato {food}.\n[i]OwO[/i]", + "qualcosa che non mi piace": "🥦 Hai assaggiato il cibo, ma non ti piace proprio./n[i]Dai, mangialo, che ti" + " fa bene! In africa i bambini muoiono di fame, e tu... ![/i]", + "qualcosa che non ti piace": "🥦 Hai assaggiato il cibo, ma non ti piace proprio./n[i]Dai, mangialo, che ti" + " fa bene! In africa i bambini muoiono di fame, e tu... ![/i]", "polvere": "☁️ Hai mangiato la {food}.\n[i]Ti hanno proprio battuto![/i]", "giaroun": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "giarone": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", From 4a9087197e350d2de1e0f17e6274c8e1c6a3a015 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Apr 2020 20:44:04 +0200 Subject: [PATCH 093/227] Fix skip, queue and pause not working --- royalpack/events/discord_pause.py | 26 +++++++++++++++----------- royalpack/events/discord_queue.py | 26 +++++++++++++++----------- royalpack/events/discord_skip.py | 24 ++++++++++++++---------- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/royalpack/events/discord_pause.py b/royalpack/events/discord_pause.py index 501510c6..b5131f9f 100644 --- a/royalpack/events/discord_pause.py +++ b/royalpack/events/discord_pause.py @@ -1,33 +1,37 @@ import discord from typing import * -from royalnet.commands import * +import royalnet.commands as rc from royalnet.serf.discord import * -class DiscordPauseEvent(Event): +class DiscordPauseEvent(rc.Event): name = "discord_pause" async def run(self, guild_id: Optional[int] = None, **kwargs) -> dict: if not isinstance(self.serf, DiscordSerf): - raise UnsupportedError() + raise rc.UnsupportedError() client: discord.Client = self.serf.client if len(self.serf.voice_players) == 1: voice_player: VoicePlayer = self.serf.voice_players[0] else: if guild_id is None: # TODO: trovare un modo per riprodurre canzoni su più server da Telegram - raise InvalidInputError("Non so in che Server riprodurre questo file...\n" - "Invia il comando su Discord, per favore!") + raise rc.InvalidInputError("Non so in che Server riprodurre questo file...\n" + "Invia il comando su Discord, per favore!") guild: discord.Guild = client.get_guild(guild_id) if guild is None: - raise InvalidInputError("Impossibile trovare il Server specificato.") - voice_players = self.serf.find_voice_players(guild) - if len(voice_players): - raise UserError("Il bot non è in nessun canale vocale.\n" - "Evocalo prima con [c]summon[/c]!") - voice_player = voice_players[0] + raise rc.InvalidInputError("Impossibile trovare il Server specificato.") + candidate_players = self.serf.find_voice_players(guild) + if len(candidate_players) == 0: + raise rc.UserError("Il bot non è in nessun canale vocale.\n" + "Evocalo prima con [c]summon[/c]!") + elif len(candidate_players) == 1: + voice_player = candidate_players[0] + else: + raise rc.CommandError("Non so su che Server saltare canzone...\n" + "Invia il comando su Discord, per favore!") if voice_player.voice_client.is_paused(): voice_player.voice_client.resume() diff --git a/royalpack/events/discord_queue.py b/royalpack/events/discord_queue.py index 3345e8dc..63a0c59e 100644 --- a/royalpack/events/discord_queue.py +++ b/royalpack/events/discord_queue.py @@ -2,35 +2,39 @@ import discord import pickle import base64 from typing import * -from royalnet.commands import * +import royalnet.commands as rc from royalnet.serf.discord import * from ..utils import RoyalQueue -class DiscordQueueEvent(Event): +class DiscordQueueEvent(rc.Event): name = "discord_queue" async def run(self, guild_id: Optional[int] = None, **kwargs) -> dict: if not isinstance(self.serf, DiscordSerf): - raise UnsupportedError() + raise rc.UnsupportedError() client: discord.Client = self.serf.client if len(self.serf.voice_players) == 1: voice_player: VoicePlayer = self.serf.voice_players[0] else: if guild_id is None: # TODO: trovare un modo per riprodurre canzoni su più server da Telegram - raise InvalidInputError("Non so in che Server riprodurre questo file...\n" + raise rc.InvalidInputError("Non so in che Server riprodurre questo file...\n" "Invia il comando su Discord, per favore!") guild: discord.Guild = client.get_guild(guild_id) if guild is None: - raise InvalidInputError("Impossibile trovare il Server specificato.") - voice_players = self.serf.find_voice_players(guild) - if len(voice_players): - raise UserError("Il bot non è in nessun canale vocale.\n" - "Evocalo prima con [c]summon[/c]!") - voice_player = voice_players[0] + raise rc.InvalidInputError("Impossibile trovare il Server specificato.") + candidate_players = self.serf.find_voice_players(guild) + if len(candidate_players) == 0: + raise rc.UserError("Il bot non è in nessun canale vocale.\n" + "Evocalo prima con [c]summon[/c]!") + elif len(candidate_players) == 1: + voice_player = candidate_players[0] + else: + raise rc.CommandError("Non so di che Server visualizzare la coda...\n" + "Invia il comando su Discord, per favore!") if isinstance(voice_player.playing, RoyalQueue): now_playing = voice_player.playing.now_playing return { @@ -47,5 +51,5 @@ class DiscordQueueEvent(Event): } for ytd in voice_player.playing.contents] } else: - raise CommandError(f"Non so come visualizzare il contenuto di un " + raise rc.CommandError(f"Non so come visualizzare il contenuto di un " f"[c]{voice_player.playing.__class__.__qualname__}[/c].") diff --git a/royalpack/events/discord_skip.py b/royalpack/events/discord_skip.py index e6537d86..69ff7714 100644 --- a/royalpack/events/discord_skip.py +++ b/royalpack/events/discord_skip.py @@ -1,33 +1,37 @@ import discord from typing import * -from royalnet.commands import * +import royalnet.commands as rc from royalnet.serf.discord import * -class DiscordSkipEvent(Event): +class DiscordSkipEvent(rc.Event): name = "discord_skip" async def run(self, guild_id: Optional[int] = None, **kwargs) -> dict: if not isinstance(self.serf, DiscordSerf): - raise UnsupportedError() + raise rc.UnsupportedError() client: discord.Client = self.serf.client if len(self.serf.voice_players) == 1: voice_player: VoicePlayer = self.serf.voice_players[0] else: if guild_id is None: # TODO: trovare un modo per riprodurre canzoni su più server da Telegram - raise InvalidInputError("Non so in che Server riprodurre questo file...\n" + raise rc.InvalidInputError("Non so in che Server riprodurre questo file...\n" "Invia il comando su Discord, per favore!") guild: discord.Guild = client.get_guild(guild_id) if guild is None: - raise InvalidInputError("Impossibile trovare il Server specificato.") - voice_players = self.serf.find_voice_players(guild) - if len(voice_players): - raise UserError("Il bot non è in nessun canale vocale.\n" - "Evocalo prima con [c]summon[/c]!") - voice_player = voice_players[0] + raise rc.InvalidInputError("Impossibile trovare il Server specificato.") + candidate_players = self.serf.find_voice_players(guild) + if len(candidate_players) == 0: + raise rc.UserError("Il bot non è in nessun canale vocale.\n" + "Evocalo prima con [c]summon[/c]!") + elif len(candidate_players) == 1: + voice_player = candidate_players[0] + else: + raise rc.CommandError("Non so su che Server saltare canzone...\n" + "Invia il comando su Discord, per favore!") # Stop the playback of the current song voice_player.voice_client.stop() # Done! From 42050342bc975cd30e22db74202c2112774c67c0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Apr 2020 20:47:46 +0200 Subject: [PATCH 094/227] Sort matchmaking responses --- royalpack/commands/matchmaking.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 548f24c5..303e835b 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -73,12 +73,21 @@ class MatchmakingCommand(Command): self.loop.create_task(self._run_mmevent(mmevent.mmid)) await data.reply(f"✅ Evento [b]{mmevent.title}[/b] creato!") + _mmchoice_values = { + MMChoice.YES: 4, + MMChoice.LATE_SHORT: 3, + MMChoice.LATE_MEDIUM: 2, + MMChoice.LATE_LONG: 1, + MMChoice.MAYBE: 0, + MMChoice.NO: -1 + } + def _gen_mm_message(self, mmevent: MMEvent) -> str: text = f"🌐 [{mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{mmevent.title}[/b]\n" if mmevent.description: text += f"{mmevent.description}\n" text += "\n" - for response in mmevent.responses: + for response in sorted(mmevent.responses, key=lambda r: self._mmchoice_values[r.choice]): response: MMResponse text += f"{response.choice.value} {response.user}\n" return text @@ -249,14 +258,12 @@ class MatchmakingCommand(Command): except Unauthorized: await self.interface.serf.api_call(client.send_message, chat_id=self.config["Telegram"]["main_group_id"], - text=telegram_escape( - self._gen_unauth_message(response.user)), + text=telegram_escape(self._gen_unauth_message(response.user)), parse_mode="HTML", disable_webpage_preview=True) else: raise UnsupportedError() - # Delete the event message after 10 minutes - await asyncio.sleep(600) + # Delete the event message if self.interface.name == "telegram": await self.interface.serf.api_call(client.delete_message, chat_id=mmevent.interface_data.chat_id, From 3e113eaed622dd106683fe0750d70aa4fb05d1ff Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Apr 2020 20:59:22 +0200 Subject: [PATCH 095/227] Update /userinfo --- royalpack/commands/userinfo.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py index d77b8eff..44f52774 100644 --- a/royalpack/commands/userinfo.py +++ b/royalpack/commands/userinfo.py @@ -45,6 +45,8 @@ class UserinfoCommand(Command): 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}") From 1386aacef6caf4e27ef5b3ac3414f17de753c550 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Apr 2020 20:59:29 +0200 Subject: [PATCH 096/227] publish: 5.7.2 --- pyproject.toml | 4 ++-- royalpack/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4f5df0a8..2b854c4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.1" + version = "5.7.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.7" + version = "^5.7.2" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/version.py b/royalpack/version.py index d25d2258..1253273c 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.1" +semantic = "5.7.2" From 68c7283a9a8cd0ac3a8a28658af2c0e8a2de65a6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Apr 2020 00:22:52 +0200 Subject: [PATCH 097/227] Reverse sort in matchmaking events --- royalpack/commands/matchmaking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 303e835b..9a5e6801 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -87,7 +87,7 @@ class MatchmakingCommand(Command): if mmevent.description: text += f"{mmevent.description}\n" text += "\n" - for response in sorted(mmevent.responses, key=lambda r: self._mmchoice_values[r.choice]): + for response in sorted(mmevent.responses, key=lambda r: -self._mmchoice_values[r.choice]): response: MMResponse text += f"{response.choice.value} {response.user}\n" return text From b35fa89671f54188ce051d90dc654386231b0aa7 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Apr 2020 01:05:46 +0200 Subject: [PATCH 098/227] Catch errors in matchmaking --- poetry.lock | 92 +++++++++++++++++++------------ pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 7 +-- 3 files changed, 60 insertions(+), 41 deletions(-) diff --git a/poetry.lock b/poetry.lock index e943f42c..fa875965 100644 --- a/poetry.lock +++ b/poetry.lock @@ -232,18 +232,20 @@ category = "main" description = "Coroutine-based network library" name = "gevent" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.4.0" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +version = "1.5.0" [package.dependencies] -cffi = ">=1.11.5" +cffi = ">=1.12.2" greenlet = ">=0.4.14" [package.extras] -dnspython = ["dnspython", "idna"] -doc = ["repoze.sphinx.autointerface"] +dnspython = ["dnspython (>=1.16.0)", "idna"] +docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput"] events = ["zope.event", "zope.interface"] -test = ["zope.interface", "zope.event", "requests", "objgraph", "psutil", "futures", "mock", "coverage (>=5.0a3)", "coveralls (>=1.0)"] +monitor = ["psutil (>=5.6.1)", "psutil (5.6.3)"] +recommended = ["dnspython (>=1.16.0)", "idna", "zope.event", "zope.interface", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)"] +test = ["dnspython (>=1.16.0)", "idna", "zope.event", "zope.interface", "requests", "objgraph", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)", "futures", "mock", "coverage (<5.0)", "coveralls (>=1.7.0)"] [[package]] category = "main" @@ -519,7 +521,7 @@ description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" optional = false python-versions = "*" -version = "12.5.1" +version = "12.6" [package.dependencies] certifi = "*" @@ -586,7 +588,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.7.1" +version = "5.7.4" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -867,7 +869,7 @@ python-versions = "*" version = "2020.3.24" [metadata] -content-hash = "e6f0356444aeacd4b2cfb077df236449d2ff8f4534fda39f846b30c2fff8e5d3" +content-hash = "5ac785ed6a80e09159e8535a5ba5f53f8411c7e40185d2d06caf467e87c6936c" python-versions = "^3.8" [metadata.files] @@ -1017,29 +1019,29 @@ future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] gevent = [ - {file = "gevent-1.4.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b7d3a285978b27b469c0ff5fb5a72bcd69f4306dbbf22d7997d83209a8ba917"}, - {file = "gevent-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:44089ed06a962a3a70e96353c981d628b2d4a2f2a75ea5d90f916a62d22af2e8"}, - {file = "gevent-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:0e1e5b73a445fe82d40907322e1e0eec6a6745ca3cea19291c6f9f50117bb7ea"}, - {file = "gevent-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:74b7528f901f39c39cdbb50cdf08f1a2351725d9aebaef212a29abfbb06895ee"}, - {file = "gevent-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0ff2b70e8e338cf13bedf146b8c29d475e2a544b5d1fe14045aee827c073842c"}, - {file = "gevent-1.4.0-cp34-cp34m-macosx_10_14_x86_64.whl", hash = "sha256:0774babec518a24d9a7231d4e689931f31b332c4517a771e532002614e270a64"}, - {file = "gevent-1.4.0-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:d752bcf1b98174780e2317ada12013d612f05116456133a6acf3e17d43b71f05"}, - {file = "gevent-1.4.0-cp34-cp34m-win32.whl", hash = "sha256:3249011d13d0c63bea72d91cec23a9cf18c25f91d1f115121e5c9113d753fa12"}, - {file = "gevent-1.4.0-cp34-cp34m-win_amd64.whl", hash = "sha256:d1e6d1f156e999edab069d79d890859806b555ce4e4da5b6418616322f0a3df1"}, - {file = "gevent-1.4.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7d0809e2991c9784eceeadef01c27ee6a33ca09ebba6154317a257353e3af922"}, - {file = "gevent-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:14b4d06d19d39a440e72253f77067d27209c67e7611e352f79fe69e0f618f76e"}, - {file = "gevent-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:53b72385857e04e7faca13c613c07cab411480822ac658d97fd8a4ddbaf715c8"}, - {file = "gevent-1.4.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:8d9ec51cc06580f8c21b41fd3f2b3465197ba5b23c00eb7d422b7ae0380510b0"}, - {file = "gevent-1.4.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2711e69788ddb34c059a30186e05c55a6b611cb9e34ac343e69cf3264d42fe1c"}, - {file = "gevent-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:e5bcc4270671936349249d26140c267397b7b4b1381f5ec8b13c53c5b53ab6e1"}, - {file = "gevent-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9f7a1e96fec45f70ad364e46de32ccacab4d80de238bd3c2edd036867ccd48ad"}, - {file = "gevent-1.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:50024a1ee2cf04645535c5ebaeaa0a60c5ef32e262da981f4be0546b26791950"}, - {file = "gevent-1.4.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4bfa291e3c931ff3c99a349d8857605dca029de61d74c6bb82bd46373959c942"}, - {file = "gevent-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:ab4dc33ef0e26dc627559786a4fba0c2227f125db85d970abbf85b77506b3f51"}, - {file = "gevent-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:896b2b80931d6b13b5d9feba3d4eebc67d5e6ec54f0cf3339d08487d55d93b0e"}, - {file = "gevent-1.4.0-pp260-pypy_41-macosx_10_14_x86_64.whl", hash = "sha256:107f4232db2172f7e8429ed7779c10f2ed16616d75ffbe77e0e0c3fcdeb51a51"}, - {file = "gevent-1.4.0-pp260-pypy_41-win32.whl", hash = "sha256:28a0c5417b464562ab9842dd1fb0cc1524e60494641d973206ec24d6ec5f6909"}, - {file = "gevent-1.4.0.tar.gz", hash = "sha256:1eb7fa3b9bd9174dfe9c3b59b7a09b768ecd496debfc4976a9530a3e15c990d1"}, + {file = "gevent-1.5.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3c9229e4eac2df1ce2b097996d3ee318ea90eb11d9e4d7cb14558cbcf02b2262"}, + {file = "gevent-1.5.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:b34b42e86b764a9e948991af5fc43f6d39ee0148a8502ad4d9267ec1401e5401"}, + {file = "gevent-1.5.0-cp27-cp27m-win32.whl", hash = "sha256:608b13b4e2fa462175a53f61c907c24a179abb4d7902f25709a0f908105c22db"}, + {file = "gevent-1.5.0-cp27-cp27m-win_amd64.whl", hash = "sha256:4c6103fa852c352b4f906ea07008fabc06a1f5d2f2209b2f8fbae41227f80a79"}, + {file = "gevent-1.5.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8753de5a3501093508e6f89c347f37a847d7acf541ff28c977bbbedc2e917c13"}, + {file = "gevent-1.5.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:975047b90345f7d811977fb859a1455bd9768d584f32c23a06a4821dd9735d1c"}, + {file = "gevent-1.5.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:b94f8f25c6f6ddf9ee3266db9113928c1eca9b01378f8376928620243ee66358"}, + {file = "gevent-1.5.0-cp35-cp35m-win32.whl", hash = "sha256:cae2bffbda0f1641db20055506105d7c209f79ace0a32134359b3c65a0e9b02f"}, + {file = "gevent-1.5.0-cp35-cp35m-win_amd64.whl", hash = "sha256:ce7c562d02ad6c351799f4c8bf81207056118b01e04908de7aca49580f7f1ead"}, + {file = "gevent-1.5.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7593740e5faeb17d5c5a79e6f80c11a618cf5d250b93df1eafa38324ff275676"}, + {file = "gevent-1.5.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d3c93c39d4a23979d199741fc5610e3f75fc6fcc15f779dd2469e343368a5794"}, + {file = "gevent-1.5.0-cp36-cp36m-win32.whl", hash = "sha256:75dd068dfa83865f4a51121068b1644be9d61921fe1f5b79cf14cc86729f79b7"}, + {file = "gevent-1.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:82bd100f70699809be1848c0a04bed86bd817b0f79f67d7340205d23badc7096"}, + {file = "gevent-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c5972a6e8ef5b4ed06c719ab9ea40f76b35e399f76111621009cb8b2a5a20b9c"}, + {file = "gevent-1.5.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:25a094ecdc4f503e81b81b94e654a1a2343bfecafedf7b481e5aa6b0adb84206"}, + {file = "gevent-1.5.0-cp37-cp37m-win32.whl", hash = "sha256:f0fda50447a6f6f50ddc9b865ce7fc3d3389694b3a0648f059f7f5b639fc33d3"}, + {file = "gevent-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:33c08d6b4a906169727dc1b9dc709e40f8abd0a966d310bceabc790acd950a56"}, + {file = "gevent-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c182733b7445074f11cd2ccb9b6c19f6407167d551089b24db6c6823224e085f"}, + {file = "gevent-1.5.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:2f33b4f2d55b562d839e93e2355d7f9a6947a9c68e3044eab17a086a725601e6"}, + {file = "gevent-1.5.0-cp38-cp38-win32.whl", hash = "sha256:0eab938d65485b900b4f716a099a59459fc7e8b53b8af75bf6267a12f9830a66"}, + {file = "gevent-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:45a5af965cc969dd06128740f5999b9bdb440cb0ba4e9c066e5c17a2c33c89a8"}, + {file = "gevent-1.5.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:03385b7d2da0e3d3a7682d85a5f19356f7caa861787363fe12edd1d52227163f"}, + {file = "gevent-1.5.0.tar.gz", hash = "sha256:b2814258e3b3fb32786bb73af271ad31f51e1ac01f33b37426b66cb8491b4c29"}, ] gevent-eventemitter = [ {file = "gevent-eventemitter-2.1.tar.gz", hash = "sha256:00e6e688c6a255f7bdcef1d8c999e0d02d9ab87d3c6ff626e6dc1a09762107f4"}, @@ -1269,8 +1271,8 @@ python-multipart = [ {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, ] python-telegram-bot = [ - {file = "python-telegram-bot-12.5.1.tar.gz", hash = "sha256:6d69fb04dc8d83e01cb25a0d83aaa2a1a4b7d5b14cd38b9f8922a567b4a4a510"}, - {file = "python_telegram_bot-12.5.1-py2.py3-none-any.whl", hash = "sha256:af36fbf051415ded8b2633f27b71d292efcd85d58a647a1f138db191380144ff"}, + {file = "python-telegram-bot-12.6.tar.gz", hash = "sha256:a9b5615edc69216e75745dc25ff11fbe5be0104efbaad0772e0aa6a4bc2fc844"}, + {file = "python_telegram_bot-12.6-py2.py3-none-any.whl", hash = "sha256:c4278fe3aad0e30aa1d2e79850f22e7fa2f6951e1e20a1b0c4e6f335220bb0cf"}, ] pytz = [ {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, @@ -1308,8 +1310,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.7.1-py3-none-any.whl", hash = "sha256:fc0c1933d5bb55b8e84e0e8034b5d2e341429527399e79f67eb2677f16cb03c8"}, - {file = "royalnet-5.7.1.tar.gz", hash = "sha256:332baf43b05b6c5abff8c6e37fdaad0b8b4d87202ebc162753dd7805ff7aea8e"}, + {file = "royalnet-5.7.4-py3-none-any.whl", hash = "sha256:45b43975098bef0319056dff5d46456cea7d5a88611b4a9f28b5eae88e0d99f5"}, + {file = "royalnet-5.7.4.tar.gz", hash = "sha256:8957d4894c866f0384bfcc94dce7f1f047b1eaaf0ffe0e0ab83d29232493bb53"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1323,6 +1325,24 @@ six = [ {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] sqlalchemy = [ + {file = "SQLAlchemy-1.3.16-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:8d8c21e9d4efef01351bf28513648ceb988031be4159745a7ad1b3e28c8ff68a"}, + {file = "SQLAlchemy-1.3.16-cp27-cp27m-win32.whl", hash = "sha256:083e383a1dca8384d0ea6378bd182d83c600ed4ff4ec8247d3b2442cf70db1ad"}, + {file = "SQLAlchemy-1.3.16-cp27-cp27m-win_amd64.whl", hash = "sha256:128f6179325f7597a46403dde0bf148478f868df44841348dfc8d158e00db1f9"}, + {file = "SQLAlchemy-1.3.16-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:6056b671aeda3fc451382e52ab8a753c0d5f66ef2a5ccc8fa5ba7abd20988b4d"}, + {file = "SQLAlchemy-1.3.16-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7025c639ce7e170db845e94006cf5f404e243e6fc00d6c86fa19e8ad8d411880"}, + {file = "SQLAlchemy-1.3.16-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e18752cecaef61031252ca72031d4d6247b3212ebb84748fc5d1a0d2029c23ea"}, + {file = "SQLAlchemy-1.3.16-cp36-cp36m-win32.whl", hash = "sha256:0a690a6486658d03cc6a73536d46e796b6570ac1f8a7ec133f9e28c448b69828"}, + {file = "SQLAlchemy-1.3.16-cp36-cp36m-win_amd64.whl", hash = "sha256:d00b393f05dbd4ecd65c989b7f5a81110eae4baea7a6a4cdd94c20a908d1456e"}, + {file = "SQLAlchemy-1.3.16-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:114b6ace30001f056e944cebd46daef38fdb41ebb98f5e5940241a03ed6cad43"}, + {file = "SQLAlchemy-1.3.16-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:13d48cd8b925b6893a4e59b2dfb3e59a5204fd8c98289aad353af78bd214db49"}, + {file = "SQLAlchemy-1.3.16-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:211a1ce7e825f7142121144bac76f53ac28b12172716a710f4bf3eab477e730b"}, + {file = "SQLAlchemy-1.3.16-cp37-cp37m-win32.whl", hash = "sha256:68d78cf4a9dfade2e6cf57c4be19f7b82ed66e67dacf93b32bb390c9bed12749"}, + {file = "SQLAlchemy-1.3.16-cp37-cp37m-win_amd64.whl", hash = "sha256:2dc57ee80b76813759cccd1a7affedf9c4dbe5b065a91fb6092c9d8151d66078"}, + {file = "SQLAlchemy-1.3.16-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:43078c7ec0457387c79b8d52fff90a7ad352ca4c7aa841c366238c3e2cf52fdf"}, + {file = "SQLAlchemy-1.3.16-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb545da054e6297242a1bb1ba88e7a8ffb679f518258d66798ec712b82e4e07"}, + {file = "SQLAlchemy-1.3.16-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5b1bf3c2c2dca738235ce08079783ef04f1a7fc5b21cf24adaae77f2da4e73c3"}, + {file = "SQLAlchemy-1.3.16-cp38-cp38-win32.whl", hash = "sha256:3e625e283eecc15aee5b1ef77203bfb542563fa4a9aa622c7643c7b55438ff49"}, + {file = "SQLAlchemy-1.3.16-cp38-cp38-win_amd64.whl", hash = "sha256:7d98e0785c4cd7ae30b4a451416db71f5724a1839025544b4edbd92e00b91f0f"}, {file = "SQLAlchemy-1.3.16.tar.gz", hash = "sha256:7224e126c00b8178dfd227bc337ba5e754b197a3867d33b9f30dc0208f773d70"}, ] starlette = [ diff --git a/pyproject.toml b/pyproject.toml index 2b854c4d..01ea86e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.7.2" + version = "^5.7.4" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 9a5e6801..db277eab 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -11,7 +11,7 @@ from telegram.error import BadRequest, Unauthorized from royalnet.commands import * from royalnet.serf.telegram import TelegramSerf as TelegramBot from royalnet.serf.telegram import escape as telegram_escape -from royalnet.utils import asyncify, sleep_until +from royalnet.utils import asyncify, sleep_until, sentry_async_wrap from royalnet.backpack.tables import User from ..tables import MMEvent, MMResponse from ..types import MMChoice, MMInterfaceDataTelegram @@ -157,6 +157,7 @@ class MatchmakingCommand(Command): return f"⚠️ Non sono autorizzato a mandare messaggi a [b]{user.username}[/b]!\n" \ f"{user.telegram.mention()}, apri una chat privata con me e mandami un messaggio!" + @sentry_async_wrap() async def _run_mmevent(self, mmid: int): """Run a MMEvent.""" # Open a new Alchemy Session @@ -267,8 +268,6 @@ class MatchmakingCommand(Command): if self.interface.name == "telegram": await self.interface.serf.api_call(client.delete_message, chat_id=mmevent.interface_data.chat_id, - message_id=mmevent.interface_data.message_id, - parse_mode="HTML", - disable_webpage_preview=True) + message_id=mmevent.interface_data.message_id) # The end! await asyncify(session.close) From badaee2e70e7eb8e407ad59e4367df00d51ca2fd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Apr 2020 02:20:47 +0200 Subject: [PATCH 099/227] Add urls to some things --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 22 +++++++++++++--------- royalpack/commands/userinfo.py | 7 ++++--- royalpack/tables/diario.py | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/poetry.lock b/poetry.lock index fa875965..696d29c7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -588,7 +588,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.7.4" +version = "5.7.5" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -869,7 +869,7 @@ python-versions = "*" version = "2020.3.24" [metadata] -content-hash = "5ac785ed6a80e09159e8535a5ba5f53f8411c7e40185d2d06caf467e87c6936c" +content-hash = "06c91734690c9d27a1355db7d6de24bf0601896f7434c99558873f659e075c6a" python-versions = "^3.8" [metadata.files] @@ -1310,8 +1310,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.7.4-py3-none-any.whl", hash = "sha256:45b43975098bef0319056dff5d46456cea7d5a88611b4a9f28b5eae88e0d99f5"}, - {file = "royalnet-5.7.4.tar.gz", hash = "sha256:8957d4894c866f0384bfcc94dce7f1f047b1eaaf0ffe0e0ab83d29232493bb53"}, + {file = "royalnet-5.7.5-py3-none-any.whl", hash = "sha256:d85afa59524482f8fa72f984cb9ec24e5517a0dfd280812097e766073fb98529"}, + {file = "royalnet-5.7.5.tar.gz", hash = "sha256:785dad6a8b9afaf6517ec30f06441265a3a57acf033e199706f1bc3156cd843a"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 01ea86e1..97d7bcba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.7.4" + version = "^5.7.5" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index db277eab..7851399f 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -33,10 +33,11 @@ class MatchmakingCommand(Command): # Find all relevant MMEvents and run them session = self.alchemy.Session() mmevents = ( - session.query(self.alchemy.get(MMEvent)) - .filter(self.alchemy.get(MMEvent).interface == self.interface.name, - self.alchemy.get(MMEvent).datetime > datetime.datetime.now()) - .all() + session + .query(self.alchemy.get(MMEvent)) + .filter(self.alchemy.get(MMEvent).interface == self.interface.name, + self.alchemy.get(MMEvent).datetime > datetime.datetime.now()) + .all() ) for mmevent in mmevents: self.interface.loop.create_task(self._run_mmevent(mmevent.mmid)) @@ -71,7 +72,7 @@ class MatchmakingCommand(Command): data.session.add(mmevent) await data.session_commit() self.loop.create_task(self._run_mmevent(mmevent.mmid)) - await data.reply(f"✅ Evento [b]{mmevent.title}[/b] creato!") + await data.reply(f"✅ Matchmaking creato!") _mmchoice_values = { MMChoice.YES: 4, @@ -92,7 +93,8 @@ class MatchmakingCommand(Command): text += f"{response.choice.value} {response.user}\n" return text - def _gen_telegram_keyboard(self, mmevent: MMEvent): + @staticmethod + def _gen_telegram_keyboard(mmevent: MMEvent): if mmevent.datetime <= datetime.datetime.now(): return None return InKM([ @@ -142,18 +144,20 @@ class MatchmakingCommand(Command): mmresponse.choice = choice await data.session_commit() await self._update_telegram_mm_message(client, mmevent) - await data.reply(f"✅ Messaggio ricevuto!") + await data.reply(f"{choice.value} Messaggio ricevuto!") return callback - def _gen_event_start_message(self, mmevent: MMEvent): + @staticmethod + def _gen_event_start_message(mmevent: MMEvent): text = f"🚩 L'evento [b]{mmevent.title}[/b] è iniziato!\n\n" for response in mmevent.responses: response: MMResponse text += f"{response.choice.value} {response.user}\n" return text - def _gen_unauth_message(self, user: User): + @staticmethod + def _gen_unauth_message(user: User): return f"⚠️ Non sono autorizzato a mandare messaggi a [b]{user.username}[/b]!\n" \ f"{user.telegram.mention()}, apri una chat privata con me e mandami un messaggio!" diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py index 44f52774..e156a8e8 100644 --- a/royalpack/commands/userinfo.py +++ b/royalpack/commands/userinfo.py @@ -26,7 +26,7 @@ class UserinfoCommand(Command): user = found r = [ - f"ℹ️ [b]{user.username}[/b]", + f"ℹ️ [url=https://ryg.steffo.eu/#/user/{user.uid}]{user.username}[/url]", f"{user.role}", "", ] @@ -53,13 +53,14 @@ class UserinfoCommand(Command): r.append("") - r.append(f"Ha creato [b]{len(user.diario_created)}[/b] righe di diario, e vi compare in" + 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" + 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("") diff --git a/royalpack/tables/diario.py b/royalpack/tables/diario.py index 8422214d..fcd5166a 100644 --- a/royalpack/tables/diario.py +++ b/royalpack/tables/diario.py @@ -88,7 +88,7 @@ class Diario: text += f" da {str(self.creator)}" text += f" il {self.timestamp.strftime('%Y-%m-%d %H:%M')}):\n" if self.media_url is not None: - text += f"{self.media_url}\n" + text += f"[url={self.media_url}]Media[/url]\n" if self.text is not None: if self.spoiler: hidden = re.sub(r"\w", "█", self.text) From 124f4c8e53e9f7e8fc5e6b10a97a140a59a0e2f7 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Apr 2020 02:21:08 +0200 Subject: [PATCH 100/227] publish: 5.7.3 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 97d7bcba..8f8171a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.2" + version = "5.7.3" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 1253273c..c4bd3225 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.2" +semantic = "5.7.3" From f249a7ea5b8a1ecb739983ac1ad2334064cfcb84 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 21 Apr 2020 23:32:27 +0200 Subject: [PATCH 101/227] publish: 5.7.4 --- poetry.lock | 12 ++++++------ pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 4 ++-- royalpack/version.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/poetry.lock b/poetry.lock index 696d29c7..5789d48c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -521,7 +521,7 @@ description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" optional = false python-versions = "*" -version = "12.6" +version = "12.6.1" [package.dependencies] certifi = "*" @@ -588,7 +588,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.7.5" +version = "5.7.6" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -1271,8 +1271,8 @@ python-multipart = [ {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, ] python-telegram-bot = [ - {file = "python-telegram-bot-12.6.tar.gz", hash = "sha256:a9b5615edc69216e75745dc25ff11fbe5be0104efbaad0772e0aa6a4bc2fc844"}, - {file = "python_telegram_bot-12.6-py2.py3-none-any.whl", hash = "sha256:c4278fe3aad0e30aa1d2e79850f22e7fa2f6951e1e20a1b0c4e6f335220bb0cf"}, + {file = "python-telegram-bot-12.6.1.tar.gz", hash = "sha256:935397390910291c8e41d7f2a06a3bb13d1d74d78b59562be9f8a330d4527049"}, + {file = "python_telegram_bot-12.6.1-py2.py3-none-any.whl", hash = "sha256:c7bdb5788ad2edea5c5c1bc8e50967fad68aa35245c209baadf74fc8ad00ff06"}, ] pytz = [ {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, @@ -1310,8 +1310,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.7.5-py3-none-any.whl", hash = "sha256:d85afa59524482f8fa72f984cb9ec24e5517a0dfd280812097e766073fb98529"}, - {file = "royalnet-5.7.5.tar.gz", hash = "sha256:785dad6a8b9afaf6517ec30f06441265a3a57acf033e199706f1bc3156cd843a"}, + {file = "royalnet-5.7.6-py3-none-any.whl", hash = "sha256:7c37ebaf4ba15c3fbb292305476112bc01554fb1f1a0f616985ff5bf96ec0bae"}, + {file = "royalnet-5.7.6.tar.gz", hash = "sha256:2be381b35ccb1f30651021bbb3515cb8523bf3f98713a0bb861757747090f554"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index 8f8171a2..7e04a054 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.3" + version = "5.7.4" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 7851399f..4e9dd5a1 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -7,7 +7,7 @@ from telegram import Bot as PTBBot from telegram import Message as PTBMessage from telegram import InlineKeyboardMarkup as InKM from telegram import InlineKeyboardButton as InKB -from telegram.error import BadRequest, Unauthorized +from telegram.error import TelegramError from royalnet.commands import * from royalnet.serf.telegram import TelegramSerf as TelegramBot from royalnet.serf.telegram import escape as telegram_escape @@ -260,7 +260,7 @@ class MatchmakingCommand(Command): text=telegram_escape(self._gen_event_start_message(mmevent)), parse_mode="HTML", disable_webpage_preview=True) - except Unauthorized: + except TelegramError: await self.interface.serf.api_call(client.send_message, chat_id=self.config["Telegram"]["main_group_id"], text=telegram_escape(self._gen_unauth_message(response.user)), diff --git a/royalpack/version.py b/royalpack/version.py index c4bd3225..9198a640 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.3" +semantic = "5.7.4" From 6dc9e3aa30c7b96618b1f2190140b2173b0ed924 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 21 Apr 2020 23:41:59 +0200 Subject: [PATCH 102/227] publish: 5.7.5 --- pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 10 +++++----- royalpack/version.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7e04a054..a0909e9f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.4" + version = "5.7.5" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 4e9dd5a1..0beec996 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -255,11 +255,11 @@ class MatchmakingCommand(Command): if response.choice == MMChoice.NO: return try: - await self.interface.serf.api_call(client.send_message, - chat_id=response.user.telegram[0].tg_id, - text=telegram_escape(self._gen_event_start_message(mmevent)), - parse_mode="HTML", - disable_webpage_preview=True) + await asyncify(client.send_message, + chat_id=response.user.telegram[0].tg_id, + text=telegram_escape(self._gen_event_start_message(mmevent)), + parse_mode="HTML", + disable_webpage_preview=True) except TelegramError: await self.interface.serf.api_call(client.send_message, chat_id=self.config["Telegram"]["main_group_id"], diff --git a/royalpack/version.py b/royalpack/version.py index 9198a640..064a7eec 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.4" +semantic = "5.7.5" From d6d7845dbc74de259215a43a10e48b3b25fc28ff Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 26 Apr 2020 18:08:22 +0200 Subject: [PATCH 103/227] Update dota ranks every 2 hours --- royalpack/commands/dota.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index bfeea743..a640e327 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -24,7 +24,7 @@ class DotaCommand(Command): def __init__(self, interface: CommandInterface): super().__init__(interface) if self.interface.name == "telegram": - self.loop.create_task(self._updater(900)) + self.loop.create_task(self._updater(7200)) async def _send(self, message): client = self.serf.client From 9066def9a665cbf8253e0a1d3fcdf46a8f9f0a4d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 26 Apr 2020 18:09:06 +0200 Subject: [PATCH 104/227] Update brawlhalla ranks every 2 hours --- royalpack/commands/brawlhalla.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index 7dd1461e..77855951 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -25,7 +25,7 @@ class BrawlhallaCommand(Command): def __init__(self, interface: CommandInterface): super().__init__(interface) if self.interface.name == "telegram": - self.loop.create_task(self._updater(900)) + self.loop.create_task(self._updater(7200)) async def _send(self, message): client = self.serf.client From fc268d89e9e90bab96e4acc9e055225fdbebc3c8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 26 Apr 2020 18:12:11 +0200 Subject: [PATCH 105/227] Update leagueoflegends ranks every 2 hours --- royalpack/commands/leagueoflegends.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index a54c7ee3..2c583956 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -25,7 +25,7 @@ class LeagueoflegendsCommand(Command): super().__init__(interface) self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.config["Lol"]["token"]) if self.interface.name == "telegram": - self.loop.create_task(self._updater(900)) + self.loop.create_task(self._updater(7200)) async def _send(self, message): client = self.serf.client From 6022e2eea3e023a34a7cbae6a159db27a3f780d2 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 26 Apr 2020 18:12:56 +0200 Subject: [PATCH 106/227] publish: 5.7.6 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a0909e9f..ff651e34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.5" + version = "5.7.6" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 064a7eec..847122ef 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.5" +semantic = "5.7.6" From 8c2c49af71e3972c10198f122f58e020ec2f3ae9 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 26 Apr 2020 23:13:13 +0200 Subject: [PATCH 107/227] Refactor fiorygi spawning --- royalpack/commands/magickfiorygi.py | 28 +--------------- royalpack/events/__init__.py | 2 ++ royalpack/events/telegram_message.py | 28 ++++++++++++++++ royalpack/tables/fiorygitransactions.py | 43 +++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 royalpack/events/telegram_message.py diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py index 994d03d9..f9f8f0c7 100644 --- a/royalpack/commands/magickfiorygi.py +++ b/royalpack/commands/magickfiorygi.py @@ -34,34 +34,8 @@ class MagickfiorygiCommand(rc.Command): qty = int(qty_arg) except ValueError: raise rc.InvalidInputError("La quantità specificata non è un numero!") - if qty == 0: - raise rc.InvalidInputError("La quantità non può essere 0!") if reason_arg == "": raise rc.InvalidInputError("Non hai specificato un motivo!") - transaction = self.alchemy.get(FiorygiTransaction)( - user_id=user.uid, - change=qty, - reason=reason_arg - ) - data.session.add(transaction) - 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 qty > 0: - msg = f"💰 [b]{user_str}[/b] ha ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''} per [i]{reason_arg}[/i]!" - else: - msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason_arg}[/i]." - - client = self.serf.client - await self.serf.api_call(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=rt.escape(msg), - parse_mode="HTML", - disable_webpage_preview=True) + await FiorygiTransaction.spawn_fiorygi(data, user, qty, reason_arg) diff --git a/royalpack/events/__init__.py b/royalpack/events/__init__.py index 6637fbe2..380d5cb2 100644 --- a/royalpack/events/__init__.py +++ b/royalpack/events/__init__.py @@ -7,6 +7,7 @@ from .discord_queue import DiscordQueueEvent from .discord_pause import DiscordPauseEvent from .discord_playable import DiscordPlaymodeEvent from .discord_lazy_play import DiscordLazyPlayEvent +from .telegram_message import TelegramMessageEvent # Enter the commands of your Pack here! available_events = [ @@ -18,6 +19,7 @@ available_events = [ DiscordPauseEvent, DiscordPlaymodeEvent, DiscordLazyPlayEvent, + TelegramMessageEvent, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/events/telegram_message.py b/royalpack/events/telegram_message.py new file mode 100644 index 00000000..2e8412f5 --- /dev/null +++ b/royalpack/events/telegram_message.py @@ -0,0 +1,28 @@ +import logging +import telegram +from typing import * +from royalnet.serf.telegram.telegramserf import TelegramSerf, escape +from royalnet.commands import * + + +log = logging.getLogger(__name__) + + +class TelegramMessageEvent(Event): + name = "telegram_message" + + async def run(self, chat_id, text, **kwargs) -> dict: + if not self.interface.name == "telegram": + raise UnsupportedError() + + # noinspection PyTypeChecker + serf: TelegramSerf = self.interface.serf + + log.debug("Forwarding message from Herald to Telegram.") + await serf.api_call(serf.client.send_message, + chat_id=chat_id, + text=escape(text), + parse_mode="HTML", + disable_web_page_preview=True) + + return {} diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py index 28fcbf73..41b1f6c7 100644 --- a/royalpack/tables/fiorygitransactions.py +++ b/royalpack/tables/fiorygitransactions.py @@ -1,7 +1,15 @@ +from typing import * + from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declared_attr +from .fiorygi import Fiorygi +from royalnet.utils import asyncify + +if TYPE_CHECKING: + from royalnet.commands import CommandData + class FiorygiTransaction: __tablename__ = "fiorygitransactions" @@ -32,3 +40,38 @@ class FiorygiTransaction: def __repr__(self): return f"<{self.__class__.__name__}: {self.change:+} to {self.user.username} for {self.reason}>" + + @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)( + user_id=user.uid, + fiorygi=0 + )) + await data.session_commit() + + transaction = data._interface.alchemy.get(FiorygiTransaction)( + user_id=user.uid, + change=qty, + reason=reason + ) + data.session.add(transaction) + + 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 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 ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''}...? Per [i]{reason}[/i]...? 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) From 887411df6dca99f968b94740abdd214c54ea00aa Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 27 Apr 2020 00:26:57 +0200 Subject: [PATCH 108/227] Fiorygi may drop when answering mmevents --- royalpack/commands/matchmaking.py | 8 +++++--- royalpack/tables/fiorygitransactions.py | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 0beec996..8ad3dfd9 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -2,7 +2,7 @@ import datetime import re import dateparser import typing -import asyncio +import random from telegram import Bot as PTBBot from telegram import Message as PTBMessage from telegram import InlineKeyboardMarkup as InKM @@ -13,7 +13,7 @@ from royalnet.serf.telegram import TelegramSerf as TelegramBot from royalnet.serf.telegram import escape as telegram_escape from royalnet.utils import asyncify, sleep_until, sentry_async_wrap from royalnet.backpack.tables import User -from ..tables import MMEvent, MMResponse +from ..tables import MMEvent, MMResponse, FiorygiTransaction from ..types import MMChoice, MMInterfaceDataTelegram @@ -127,7 +127,7 @@ class MatchmakingCommand(Command): parse_mode="HTML", disable_web_page_preview=True, reply_markup=self._gen_telegram_keyboard(mmevent)) - except BadRequest: + except TelegramError: pass def _gen_mm_telegram_callback(self, client: PTBBot, mmid: int, choice: MMChoice): @@ -140,6 +140,8 @@ class MatchmakingCommand(Command): if mmresponse is None: mmresponse = self.alchemy.get(MMResponse)(user=author, mmevent=mmevent, choice=choice) data.session.add(mmresponse) + if random.randrange(14) == 0: + await FiorygiTransaction.spawn_fiorygi(data, author, 1, "aver risposto a un matchmaking") else: mmresponse.choice = choice await data.session_commit() diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py index 41b1f6c7..47c0cb94 100644 --- a/royalpack/tables/fiorygitransactions.py +++ b/royalpack/tables/fiorygitransactions.py @@ -68,7 +68,8 @@ class FiorygiTransaction: 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 ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''}...? Per [i]{reason}[/i]...? Cosa?" + msg = f"❓ [b]{user_str}[/b] ha ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''}...? " \ + f"Per [i]{reason}[/i]...? Cosa?" else: msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason}[/i]." From e6e680941960495b0b68dfb4999b2cec261b4fa8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 27 Apr 2020 00:28:12 +0200 Subject: [PATCH 109/227] Sort people in the mmevent start message --- royalpack/commands/matchmaking.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 8ad3dfd9..ddfc6de4 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -150,10 +150,9 @@ class MatchmakingCommand(Command): return callback - @staticmethod - def _gen_event_start_message(mmevent: MMEvent): + def _gen_event_start_message(self, mmevent: MMEvent): text = f"🚩 L'evento [b]{mmevent.title}[/b] è iniziato!\n\n" - for response in mmevent.responses: + for response in sorted(mmevent.responses, key=lambda r: -self._mmchoice_values[r.choice]): response: MMResponse text += f"{response.choice.value} {response.user}\n" return text From abb4ac87f11f66d0cefec1c7740fd324b6ac9894 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 27 Apr 2020 03:12:01 +0200 Subject: [PATCH 110/227] Collect anonymous cv stats --- royalpack/commands/__init__.py | 2 + royalpack/commands/cvstats.py | 129 +++++++++++++++++++++++++++++++++ royalpack/tables/__init__.py | 2 + royalpack/tables/cvstats.py | 47 ++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 royalpack/commands/cvstats.py create mode 100644 royalpack/tables/cvstats.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index bb69797b..ca50ac4b 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -51,6 +51,7 @@ from .lazyyoutube import LazyyoutubeCommand from .funkwhalealbum import FunkwhalealbumCommand from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand from .matchmaking import MatchmakingCommand +from .cvstats import CvstatsCommand # Enter the commands of your Pack here! available_commands = [ @@ -106,6 +107,7 @@ available_commands = [ FunkwhalealbumCommand, LazyfunkwhalealbumCommand, MatchmakingCommand, + CvstatsCommand ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/cvstats.py b/royalpack/commands/cvstats.py new file mode 100644 index 00000000..b590b7b9 --- /dev/null +++ b/royalpack/commands/cvstats.py @@ -0,0 +1,129 @@ +from typing import * +import logging +import asyncio +import datetime +import royalnet.commands as rc +from royalnet.utils import asyncify +from ..tables import Cvstats + + +log = logging.getLogger(__name__) + + +class CvstatsCommand(rc.Command): + name: str = "cvstats" + + description: str = "" + + syntax: str = "" + + def __init__(self, interface: rc.CommandInterface): + super().__init__(interface) + if self.interface.name == "discord": + 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"]: + return True + return False + + async def _update(self, db_session): + log.info(f"Gathering Cvstats...") + while True: + try: + response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_cv") + except rc.ConfigurationError: + await asyncio.sleep(10) + continue + else: + break + + users_total = 0 + members_total = 0 + users_online = 0 + members_online = 0 + users_connected = 0 + members_connected = 0 + users_playing = 0 + members_playing = 0 + + # noinspection PyUnboundLocalVariable + for m in response["guild"]["members"]: + users_total += 1 + if self._is_ryg_member(m): + members_total += 1 + + if m["status"]["main"] != "offline" and m["status"]["main"] != "idle": + users_online += 1 + if self._is_ryg_member(m): + members_online += 1 + + if m["voice"] is not None and not m["voice"]["afk"]: + users_connected += 1 + if self._is_ryg_member(m): + members_connected += 1 + + for mact in m["activities"]: + if mact.get("type") == 0: + users_playing += 1 + if self._is_ryg_member(m): + members_playing += 1 + + log.debug(f"Total users: {users_total}") + log.debug(f"Total members: {members_total}") + log.debug(f"Online users: {users_online}") + log.debug(f"Online members: {members_online}") + log.debug(f"Connected users: {users_connected}") + log.debug(f"Connected members: {members_connected}") + log.debug(f"Playing users: {users_playing}") + log.debug(f"Playing members: {members_playing}") + + CvstatsT = self.alchemy.get(Cvstats) + + cvstats = CvstatsT( + timestamp=datetime.datetime.now(), + users_total=users_total, + members_total=members_total, + users_online=users_online, + members_online=members_online, + users_connected=users_connected, + members_connected=members_connected, + users_playing=users_playing, + members_playing=members_playing + ) + + log.debug("Saving to database...") + db_session.add(cvstats) + await asyncify(db_session.commit) + log.debug("Done!") + + async def _updater(self, period: int): + log.info(f"Started updater with {period}s period") + while True: + log.info(f"Updating...") + session = self.alchemy.Session() + await self._update(session) + session.close() + log.info(f"Sleeping for {period}s") + await asyncio.sleep(period) + + 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() + + message = [ + f"ℹ️ [b]Statistiche[/b]", + f"Ultimo aggiornamento: [b]{cvstats.timestamp.strftime('%Y-%m-%d %H:%M')}[/b]", + f"Utenti totali: [b]{cvstats.users_total}[/b]", + f"Membri totali: [b]{cvstats.members_total}[/b]", + f"Utenti online: [b]{cvstats.users_online}[/b]", + f"Membri online: [b]{cvstats.members_online}[/b]", + f"Utenti connessi: [b]{cvstats.users_connected}[/b]", + f"Membri connessi: [b]{cvstats.members_connected}[/b]", + f"Utenti in gioco: [b]{cvstats.users_playing}[/b]", + f"Membri in gioco: [b]{cvstats.members_playing}[/b]" + ] + + await data.reply("\n".join(message)) diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 1359d360..6e8a6937 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -16,6 +16,7 @@ from .pollvotes import PollVote from .brawlhalladuos import BrawlhallaDuo from .mmevents import MMEvent from .mmresponse import MMResponse +from .cvstats import Cvstats # Enter the tables of your Pack here! available_tables = [ @@ -36,6 +37,7 @@ available_tables = [ BrawlhallaDuo, MMEvent, MMResponse, + Cvstats, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/cvstats.py b/royalpack/tables/cvstats.py new file mode 100644 index 00000000..f669347b --- /dev/null +++ b/royalpack/tables/cvstats.py @@ -0,0 +1,47 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr + + +class Cvstats: + __tablename__ = "cvstats" + + @declared_attr + def id(self): + return Column(Integer, primary_key=True) + + @declared_attr + def timestamp(self): + return Column(DateTime) + + @declared_attr + def members_connected(self): + return Column(Integer) + + @declared_attr + def users_connected(self): + return Column(Integer) + + @declared_attr + def members_online(self): + return Column(Integer) + + @declared_attr + def users_online(self): + return Column(Integer) + + @declared_attr + def members_playing(self): + return Column(Integer) + + @declared_attr + def users_playing(self): + return Column(Integer) + + @declared_attr + def members_total(self): + return Column(Integer) + + @declared_attr + def users_total(self): + return Column(Integer) From 2d0d018ba5a7d3feb6daec5b9941255a29fa5df9 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 27 Apr 2020 03:13:12 +0200 Subject: [PATCH 111/227] publish: 5.7.7 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ff651e34..0e7a8fd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.6" + version = "5.7.7" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 847122ef..9728ff9b 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.6" +semantic = "5.7.7" From f9f72c3c1ac402620948db6d89af7ec4cb3967b1 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 27 Apr 2020 15:33:31 +0200 Subject: [PATCH 112/227] publish: 5.7.8 --- pyproject.toml | 2 +- royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_cvstats_latest.py | 21 +++++++++++++++++++++ royalpack/tables/cvstats.py | 13 +++++++++++++ royalpack/version.py | 2 +- 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 royalpack/stars/api_cvstats_latest.py diff --git a/pyproject.toml b/pyproject.toml index 0e7a8fd1..7dafe867 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.7" + version = "5.7.8" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index db781e92..dc65f004 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -13,6 +13,7 @@ from .api_diario_random import ApiDiarioRandomStar from .api_polls_create import ApiPollsCreate from .api_polls_get import ApiPollsGet from .api_polls_list import ApiPollsList +from .api_cvstats_latest import ApiCvstatsLatestStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -30,6 +31,7 @@ available_page_stars = [ ApiPollsCreate, ApiPollsGet, ApiPollsList, + ApiCvstatsLatestStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_cvstats_latest.py b/royalpack/stars/api_cvstats_latest.py new file mode 100644 index 00000000..a2530339 --- /dev/null +++ b/royalpack/stars/api_cvstats_latest.py @@ -0,0 +1,21 @@ +import royalnet.utils as ru +from royalnet.backpack.tables import * +from royalnet.constellation.api import * +from ..tables import Cvstats + + +class ApiCvstatsLatestStar(ApiStar): + path = "/api/cvstats/latest/v1" + + methods = ["GET"] + + summary = "Get the latest 500 cvstats." + + tags = ["cvstats"] + + async def api(self, data: ApiData) -> ru.JSON: + CvstatsT = self.alchemy.get(Cvstats) + + cvstats = data.session.query(CvstatsT).order_by(CvstatsT.timestamp.desc()).limit(500).all() + + return list(map(lambda c: c.json(), cvstats)) diff --git a/royalpack/tables/cvstats.py b/royalpack/tables/cvstats.py index f669347b..1165d3bc 100644 --- a/royalpack/tables/cvstats.py +++ b/royalpack/tables/cvstats.py @@ -45,3 +45,16 @@ class Cvstats: @declared_attr def users_total(self): return Column(Integer) + + def json(self): + return { + "timestamp": self.timestamp.isoformat(), + "users_total": self.users_total, + "members_total": self.members_total, + "users_online": self.users_online, + "members_online": self.members_online, + "users_connected": self.users_connected, + "members_connected": self.members_connected, + "users_playing": self.users_playing, + "members_playing": self.members_playing, + } \ No newline at end of file diff --git a/royalpack/version.py b/royalpack/version.py index 9728ff9b..7534cdb9 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.7" +semantic = "5.7.8" From 8b9de800d4eb5fcc37d91d9b38d6ca672d27115a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 28 Apr 2020 20:03:22 +0200 Subject: [PATCH 113/227] Make updaters optional --- royalpack/commands/brawlhalla.py | 5 +---- royalpack/commands/dota.py | 2 +- royalpack/commands/leagueoflegends.py | 2 +- royalpack/commands/matchmaking.py | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index 77855951..714b9c01 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -24,7 +24,7 @@ class BrawlhallaCommand(Command): def __init__(self, interface: CommandInterface): super().__init__(interface) - if self.interface.name == "telegram": + if self.interface.name == "telegram" and self.config["Brawlhalla"]["updater"]: self.loop.create_task(self._updater(7200)) async def _send(self, message): @@ -44,13 +44,10 @@ class BrawlhallaCommand(Command): string.append(f"[b]{bh.rank_1v1}[/b] ({bh.rating_1v1} MMR)") string.append("") - duos = bh.duos - if len(bh.duos) != 0: string.append(f"👥 [b]2v2[/b]") for duo in bh.duos: - other = duo.other(bh) string.append(f"Con [b]{other.steam.user}[/b]: [b]{duo.rank_2v2}[/b] ({duo.rating_2v2} MMR)") diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index a640e327..e1f3c7dc 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -23,7 +23,7 @@ class DotaCommand(Command): def __init__(self, interface: CommandInterface): super().__init__(interface) - if self.interface.name == "telegram": + if self.interface.name == "telegram" and self.config["Dota"]["updater"]: self.loop.create_task(self._updater(7200)) async def _send(self, message): diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 2c583956..493289ab 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -24,7 +24,7 @@ class LeagueoflegendsCommand(Command): def __init__(self, interface: CommandInterface): super().__init__(interface) self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.config["Lol"]["token"]) - if self.interface.name == "telegram": + if self.interface.name == "telegram" and self.config["Lol"]["updater"]: self.loop.create_task(self._updater(7200)) async def _send(self, message): diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index ddfc6de4..fbe080fd 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -109,7 +109,7 @@ class MatchmakingCommand(Command): callback_data=f"mm{mmevent.mmid}_LATE_SHORT"), InKB(f"{MMChoice.LATE_MEDIUM.value} 30 min", callback_data=f"mm{mmevent.mmid}_LATE_MEDIUM"), - InKB(f"{MMChoice.LATE_LONG.value} 60 min", + InKB(f"{MMChoice.LATE_LONG.value} 60+ min", callback_data=f"mm{mmevent.mmid}_LATE_LONG"), ], [ From b0463436c4b65885ac4bd22cc2dd73d9e4949bbd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 00:52:05 +0200 Subject: [PATCH 114/227] Fix matchmaking.py --- royalpack/commands/matchmaking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index fbe080fd..bdccdb38 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -160,7 +160,7 @@ class MatchmakingCommand(Command): @staticmethod def _gen_unauth_message(user: User): return f"⚠️ Non sono autorizzato a mandare messaggi a [b]{user.username}[/b]!\n" \ - f"{user.telegram.mention()}, apri una chat privata con me e mandami un messaggio!" + f"{user.telegram[0].mention()}, apri una chat privata con me e mandami un messaggio!" @sentry_async_wrap() async def _run_mmevent(self, mmid: int): From 09cc7234506ebf5a219cbf9ebd2c08d52ecb8a9e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 01:35:58 +0200 Subject: [PATCH 115/227] publish: 5.7.9 --- poetry.lock | 143 ++++++++++++++++++++++--------------------- pyproject.toml | 4 +- royalpack/version.py | 2 +- 3 files changed, 75 insertions(+), 74 deletions(-) diff --git a/poetry.lock b/poetry.lock index 5789d48c..5639207d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -86,7 +86,7 @@ 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.1" +version = "7.1.2" [[package]] category = "main" @@ -118,7 +118,7 @@ description = "cryptography is a package which provides cryptographic recipes an name = "cryptography" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "2.9" +version = "2.9.2" [package.dependencies] cffi = ">=1.8,<1.11.3 || >1.11.3" @@ -159,7 +159,7 @@ description = "A library to handle automated deprecations" name = "deprecation" optional = false python-versions = "*" -version = "2.0.7" +version = "2.1.0" [package.dependencies] packaging = "*" @@ -217,7 +217,7 @@ description = "Infer file type and MIME type of any file/buffer. No external dep name = "filetype" optional = false python-versions = "*" -version = "1.0.6" +version = "1.0.7" [[package]] category = "main" @@ -233,7 +233,7 @@ description = "Coroutine-based network library" name = "gevent" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "1.5.0" +version = "20.4.0" [package.dependencies] cffi = ">=1.12.2" @@ -245,7 +245,7 @@ docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput"] events = ["zope.event", "zope.interface"] monitor = ["psutil (>=5.6.1)", "psutil (5.6.3)"] recommended = ["dnspython (>=1.16.0)", "idna", "zope.event", "zope.interface", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)"] -test = ["dnspython (>=1.16.0)", "idna", "zope.event", "zope.interface", "requests", "objgraph", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)", "futures", "mock", "coverage (<5.0)", "coveralls (>=1.7.0)"] +test = ["dnspython (>=1.16.0)", "idna", "zope.event", "zope.interface", "requests", "objgraph", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)", "futures", "mock", "contextvars (2.4)", "coverage (<5.0)", "coveralls (>=1.7.0)"] [[package]] category = "main" @@ -310,7 +310,7 @@ description = "Human friendly output for text interfaces using Python" name = "humanfriendly" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "8.1" +version = "8.2" [package.dependencies] pyreadline = "*" @@ -540,7 +540,7 @@ description = "World timezone definitions, modern and historical" name = "pytz" optional = false python-versions = "*" -version = "2019.3" +version = "2020.1" [[package]] category = "main" @@ -588,7 +588,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.7.6" +version = "5.7.7" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -801,11 +801,11 @@ description = "HTTP library with thread-safe connection pooling, file post, and name = "urllib3" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.8" +version = "1.25.9" [package.extras] brotli = ["brotlipy (>=0.6.0)"] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] @@ -838,7 +838,7 @@ description = "Library for working with Valve's VDF text format" name = "vdf" optional = false python-versions = "*" -version = "3.2" +version = "3.3" [[package]] category = "main" @@ -869,7 +869,7 @@ python-versions = "*" version = "2020.3.24" [metadata] -content-hash = "06c91734690c9d27a1355db7d6de24bf0601896f7434c99558873f659e075c6a" +content-hash = "c05aace99f49203f824c7f6cdc5ed816fd139935673d8b01c4275eb14f45e590" python-versions = "^3.8" [metadata.files] @@ -954,8 +954,8 @@ chardet = [ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] click = [ - {file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"}, - {file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"}, + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, ] colorama = [ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, @@ -966,25 +966,25 @@ coloredlogs = [ {file = "coloredlogs-10.0.tar.gz", hash = "sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"}, ] cryptography = [ - {file = "cryptography-2.9-cp27-cp27m-macosx_10_9_intel.whl", hash = "sha256:ef9a55013676907df6c9d7dd943eb1770d014f68beaa7e73250fb43c759f4585"}, - {file = "cryptography-2.9-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2a2ad24d43398d89f92209289f15265107928f22a8d10385f70def7a698d6a02"}, - {file = "cryptography-2.9-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:95e1296e0157361fe2f5f0ed307fd31f94b0ca13372e3673fa95095a627636a1"}, - {file = "cryptography-2.9-cp27-cp27m-win32.whl", hash = "sha256:192ca04a36852a994ef21df13cca4d822adbbdc9d5009c0f96f1d2929e375d4f"}, - {file = "cryptography-2.9-cp27-cp27m-win_amd64.whl", hash = "sha256:ed1d0760c7e46436ec90834d6f10477ff09475c692ed1695329d324b2c5cd547"}, - {file = "cryptography-2.9-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:19ae795137682a9778892fb4390c07811828b173741bce91e30f899424b3934d"}, - {file = "cryptography-2.9-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d1bf5a1a0d60c7f9a78e448adcb99aa101f3f9588b16708044638881be15d6bc"}, - {file = "cryptography-2.9-cp35-abi3-macosx_10_9_intel.whl", hash = "sha256:1b9b535d6b55936a79dbe4990b64bb16048f48747c76c29713fea8c50eca2acf"}, - {file = "cryptography-2.9-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:7a279f33a081d436e90e91d1a7c338553c04e464de1c9302311a5e7e4b746088"}, - {file = "cryptography-2.9-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:49870684da168b90110bbaf86140d4681032c5e6a2461adc7afdd93be5634216"}, - {file = "cryptography-2.9-cp35-cp35m-win32.whl", hash = "sha256:6b91cab3841b4c7cb70e4db1697c69f036c8bc0a253edc0baa6783154f1301e4"}, - {file = "cryptography-2.9-cp35-cp35m-win_amd64.whl", hash = "sha256:587f98ce27ac4547177a0c6fe0986b8736058daffe9160dcf5f1bd411b7fbaa1"}, - {file = "cryptography-2.9-cp36-cp36m-win32.whl", hash = "sha256:cc20316e3f5a6b582fc3b029d8dc03aabeb645acfcb7fc1d9848841a33265748"}, - {file = "cryptography-2.9-cp36-cp36m-win_amd64.whl", hash = "sha256:3be7a5722d5bfe69894d3f7bbed15547b17619f3a88a318aab2e37f457524164"}, - {file = "cryptography-2.9-cp37-cp37m-win32.whl", hash = "sha256:7598974f6879a338c785c513e7c5a4329fbc58b9f6b9a6305035fca5b1076552"}, - {file = "cryptography-2.9-cp37-cp37m-win_amd64.whl", hash = "sha256:5aca6f00b2f42546b9bdf11a69f248d1881212ce5b9e2618b04935b87f6f82a1"}, - {file = "cryptography-2.9-cp38-cp38-win32.whl", hash = "sha256:9fc9da390e98cb6975eadf251b6e5fa088820141061bf041cd5c72deba1dc526"}, - {file = "cryptography-2.9-cp38-cp38-win_amd64.whl", hash = "sha256:6b744039b55988519cc183149cceb573189b3e46e16ccf6f8c46798bb767c9dc"}, - {file = "cryptography-2.9.tar.gz", hash = "sha256:0cacd3ef5c604b8e5f59bf2582c076c98a37fe206b31430d0cd08138aff0986e"}, + {file = "cryptography-2.9.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e"}, + {file = "cryptography-2.9.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b"}, + {file = "cryptography-2.9.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365"}, + {file = "cryptography-2.9.2-cp27-cp27m-win32.whl", hash = "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"}, + {file = "cryptography-2.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55"}, + {file = "cryptography-2.9.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270"}, + {file = "cryptography-2.9.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf"}, + {file = "cryptography-2.9.2-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d"}, + {file = "cryptography-2.9.2-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785"}, + {file = "cryptography-2.9.2-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b"}, + {file = "cryptography-2.9.2-cp35-cp35m-win32.whl", hash = "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae"}, + {file = "cryptography-2.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b"}, + {file = "cryptography-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6"}, + {file = "cryptography-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3"}, + {file = "cryptography-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b"}, + {file = "cryptography-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e"}, + {file = "cryptography-2.9.2-cp38-cp38-win32.whl", hash = "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0"}, + {file = "cryptography-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5"}, + {file = "cryptography-2.9.2.tar.gz", hash = "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229"}, ] dateparser = [ {file = "dateparser-0.7.4-py2.py3-none-any.whl", hash = "sha256:1b1f0e3034f82d1f92b45fa445826da6a36d67af8a1169e04869685594276011"}, @@ -995,8 +995,8 @@ decorator = [ {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, ] deprecation = [ - {file = "deprecation-2.0.7-py2.py3-none-any.whl", hash = "sha256:dc9b4f252b7aca8165ce2764a71da92a653b5ffbf7a389461d7a640f6536ecb2"}, - {file = "deprecation-2.0.7.tar.gz", hash = "sha256:c0392f676a6146f0238db5744d73e786a43510d54033f80994ef2f4c9df192ed"}, + {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.3-py3-none-any.whl", hash = "sha256:406871b06d86c3dc49fba63238519f28628dac946fef8a0e22988ff58ec05580"}, @@ -1012,36 +1012,37 @@ ffmpeg-python = [ {file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"}, ] filetype = [ - {file = "filetype-1.0.6-py2.py3-none-any.whl", hash = "sha256:fd6d0ec56820acccf8c9fb6c3ba7e04a302f6ff6c70bcc09daf4842ae9e2ac30"}, - {file = "filetype-1.0.6.tar.gz", hash = "sha256:99d2b923921cadbe6e451249091ca7156b4beaee6e741bd711a582d4dd2f2881"}, + {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"}, ] gevent = [ - {file = "gevent-1.5.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3c9229e4eac2df1ce2b097996d3ee318ea90eb11d9e4d7cb14558cbcf02b2262"}, - {file = "gevent-1.5.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:b34b42e86b764a9e948991af5fc43f6d39ee0148a8502ad4d9267ec1401e5401"}, - {file = "gevent-1.5.0-cp27-cp27m-win32.whl", hash = "sha256:608b13b4e2fa462175a53f61c907c24a179abb4d7902f25709a0f908105c22db"}, - {file = "gevent-1.5.0-cp27-cp27m-win_amd64.whl", hash = "sha256:4c6103fa852c352b4f906ea07008fabc06a1f5d2f2209b2f8fbae41227f80a79"}, - {file = "gevent-1.5.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8753de5a3501093508e6f89c347f37a847d7acf541ff28c977bbbedc2e917c13"}, - {file = "gevent-1.5.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:975047b90345f7d811977fb859a1455bd9768d584f32c23a06a4821dd9735d1c"}, - {file = "gevent-1.5.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:b94f8f25c6f6ddf9ee3266db9113928c1eca9b01378f8376928620243ee66358"}, - {file = "gevent-1.5.0-cp35-cp35m-win32.whl", hash = "sha256:cae2bffbda0f1641db20055506105d7c209f79ace0a32134359b3c65a0e9b02f"}, - {file = "gevent-1.5.0-cp35-cp35m-win_amd64.whl", hash = "sha256:ce7c562d02ad6c351799f4c8bf81207056118b01e04908de7aca49580f7f1ead"}, - {file = "gevent-1.5.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7593740e5faeb17d5c5a79e6f80c11a618cf5d250b93df1eafa38324ff275676"}, - {file = "gevent-1.5.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d3c93c39d4a23979d199741fc5610e3f75fc6fcc15f779dd2469e343368a5794"}, - {file = "gevent-1.5.0-cp36-cp36m-win32.whl", hash = "sha256:75dd068dfa83865f4a51121068b1644be9d61921fe1f5b79cf14cc86729f79b7"}, - {file = "gevent-1.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:82bd100f70699809be1848c0a04bed86bd817b0f79f67d7340205d23badc7096"}, - {file = "gevent-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c5972a6e8ef5b4ed06c719ab9ea40f76b35e399f76111621009cb8b2a5a20b9c"}, - {file = "gevent-1.5.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:25a094ecdc4f503e81b81b94e654a1a2343bfecafedf7b481e5aa6b0adb84206"}, - {file = "gevent-1.5.0-cp37-cp37m-win32.whl", hash = "sha256:f0fda50447a6f6f50ddc9b865ce7fc3d3389694b3a0648f059f7f5b639fc33d3"}, - {file = "gevent-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:33c08d6b4a906169727dc1b9dc709e40f8abd0a966d310bceabc790acd950a56"}, - {file = "gevent-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c182733b7445074f11cd2ccb9b6c19f6407167d551089b24db6c6823224e085f"}, - {file = "gevent-1.5.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:2f33b4f2d55b562d839e93e2355d7f9a6947a9c68e3044eab17a086a725601e6"}, - {file = "gevent-1.5.0-cp38-cp38-win32.whl", hash = "sha256:0eab938d65485b900b4f716a099a59459fc7e8b53b8af75bf6267a12f9830a66"}, - {file = "gevent-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:45a5af965cc969dd06128740f5999b9bdb440cb0ba4e9c066e5c17a2c33c89a8"}, - {file = "gevent-1.5.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:03385b7d2da0e3d3a7682d85a5f19356f7caa861787363fe12edd1d52227163f"}, - {file = "gevent-1.5.0.tar.gz", hash = "sha256:b2814258e3b3fb32786bb73af271ad31f51e1ac01f33b37426b66cb8491b4c29"}, + {file = "gevent-20.4.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1ef086264e846371beb5742ebaeb148dc96adf72da2ff350ae5603421cdc2ad9"}, + {file = "gevent-20.4.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:2070c65896f89a85b39f49427d6132f7abd047129fc4da88b3670f0ba13b0cf7"}, + {file = "gevent-20.4.0-cp27-cp27m-win32.whl", hash = "sha256:de6c0cbcb890d0a79323961d3b593a0f2f54dcb9fe38ee5167f2d514e69e3c8c"}, + {file = "gevent-20.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:3b4c4d99f87c0d04b825879c5a91fbfa2b66da7c25b8689e9bdd9f4741d5f80d"}, + {file = "gevent-20.4.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8cca7ffd58559f8d51e5605ad73afcc6f348f9747d2fa539b336e70851b69b79"}, + {file = "gevent-20.4.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:b46399f6c9eccc2e6de1dc1057d362be840443e5439b06cce8b01d114ba1a7ec"}, + {file = "gevent-20.4.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:ee39caf14d66e619709cdfe3962bc68a234518e43ea8c811c0d67a864bc7c196"}, + {file = "gevent-20.4.0-cp35-cp35m-win32.whl", hash = "sha256:8a9aba59a3268f20c7b584119215bdc589cb81500d93dad4dab428eb02f72944"}, + {file = "gevent-20.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:6088bedd8b6bcdb815be322304a5d1c028ffa837d84e93b349928dadac62f354"}, + {file = "gevent-20.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c0b38a654c8fde5b9d9bd27ea3261aeefe36bc9244b170b6d3b11d72a2163bdb"}, + {file = "gevent-20.4.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e7d23d5f32c9db6ae49c4b58585618dcafd6ad0babae251c9c8297afebc4744b"}, + {file = "gevent-20.4.0-cp36-cp36m-win32.whl", hash = "sha256:0b84a8d6f088b29a74402728681c9f11864b95e49f5587a666e6fbf5c683e597"}, + {file = "gevent-20.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b0aea12de542f8fcd6882087bdd5b4d7dc8bb316d28181f6b012dd0b91583285"}, + {file = "gevent-20.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e0990009e7c1624f9a0f3335df1ab8d45678241c852659ac645b70ed8229097c"}, + {file = "gevent-20.4.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:c7a62d51c6dca84f91a91b940037523c926a516f0568f47dc1386bd1682cf4e9"}, + {file = "gevent-20.4.0-cp37-cp37m-win32.whl", hash = "sha256:d56f36eb98532d2bccc51cb0964c31e9fbd9b2282074c297dc9b006b047e2966"}, + {file = "gevent-20.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2fbe0bc43d8c5540153f06eece6235dda14e5f99bdd9183838396313100815d7"}, + {file = "gevent-20.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4572dc7907a0ac3c39b9f0898dbdf390ae3250baaae5f7395661fb844e2e23be"}, + {file = "gevent-20.4.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:956e82a5d0e90f8d71efe4cecccde602cfb657cd866c58bb953c9c30ca1b3d77"}, + {file = "gevent-20.4.0-cp38-cp38-win32.whl", hash = "sha256:38c45d8a3b647f56f8a68769a8ac4953be84a84735c7c7a4d7ca62022bd54036"}, + {file = "gevent-20.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:32813de352918fb652a3db805fd6e08e0a1666a1a9304eef95938c9c426f9573"}, + {file = "gevent-20.4.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:42cae3be36b7458f411bd589c66aaba27e4e611ec3d3621e37fd732fe383f9b6"}, + {file = "gevent-20.4.0-pp27-pypy_73-win32.whl", hash = "sha256:cea28f958bc4206ae092043e0775cd7a2bb2536bcbece292732c6484c1076c01"}, + {file = "gevent-20.4.0.tar.gz", hash = "sha256:c516cc5d70c3faf07f271d50930d144339c69fb80f3cac9b687aa964e518535e"}, ] gevent-eventemitter = [ {file = "gevent-eventemitter-2.1.tar.gz", hash = "sha256:00e6e688c6a255f7bdcef1d8c999e0d02d9ab87d3c6ff626e6dc1a09762107f4"}, @@ -1087,8 +1088,8 @@ httptools = [ {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, ] humanfriendly = [ - {file = "humanfriendly-8.1-py2.py3-none-any.whl", hash = "sha256:3a831920e40e55ad49adb64c9179ed50c604cabca72cd300e7bd5b51310e4ebb"}, - {file = "humanfriendly-8.1.tar.gz", hash = "sha256:25c2108a45cfd1e8fbe9cdb30b825d34ef5d5675c8e11e4775c9aedbfb0bdee2"}, + {file = "humanfriendly-8.2-py2.py3-none-any.whl", hash = "sha256:e78960b31198511f45fd455534ae7645a6207d33e512d2e842c766d15d9c8080"}, + {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, ] hyperframe = [ {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, @@ -1275,8 +1276,8 @@ python-telegram-bot = [ {file = "python_telegram_bot-12.6.1-py2.py3-none-any.whl", hash = "sha256:c7bdb5788ad2edea5c5c1bc8e50967fad68aa35245c209baadf74fc8ad00ff06"}, ] pytz = [ - {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, - {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, + {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, + {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, ] regex = [ {file = "regex-2020.4.4-cp27-cp27m-win32.whl", hash = "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f"}, @@ -1310,8 +1311,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.7.6-py3-none-any.whl", hash = "sha256:7c37ebaf4ba15c3fbb292305476112bc01554fb1f1a0f616985ff5bf96ec0bae"}, - {file = "royalnet-5.7.6.tar.gz", hash = "sha256:2be381b35ccb1f30651021bbb3515cb8523bf3f98713a0bb861757747090f554"}, + {file = "royalnet-5.7.7-py3-none-any.whl", hash = "sha256:e426c5fa21ee81deccd5ba35a17bd110d9de8382713b09851647fa71f3f9e3fa"}, + {file = "royalnet-5.7.7.tar.gz", hash = "sha256:6c7724296df890ea61f9f9f46efa4270e857dbe84a76521675fec7a163321bf5"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1376,8 +1377,8 @@ unpaddedbase64 = [ {file = "unpaddedbase64-1.1.0-py2.py3-none-any.whl", hash = "sha256:81cb4eaaa28cc6a282dd3f2c3855eaa1fbaafa736b5ee64df69889e20540a339"}, ] urllib3 = [ - {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, - {file = "urllib3-1.25.8.tar.gz", hash = "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"}, + {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, + {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, ] uvicorn = [ {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, @@ -1395,8 +1396,8 @@ uvloop = [ {file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"}, ] vdf = [ - {file = "vdf-3.2-py2.py3-none-any.whl", hash = "sha256:8e0d33ebe0bafd991be3236ce1bd211e368e9a2b8bc376dacd5f6b77066afb90"}, - {file = "vdf-3.2.tar.gz", hash = "sha256:83f3b509fe99a4d842b74af3d0b1742be99f7098dae1d3eb7ca57522986737d5"}, + {file = "vdf-3.3-py2.py3-none-any.whl", hash = "sha256:f88db3a3e66e7264da7fdacf0ffa1d99be52dd30510b2c1a1340171b227472e4"}, + {file = "vdf-3.3.tar.gz", hash = "sha256:9193901ce20ee08391c1d5044234b5da021d939b00ce879f5aae0a1a759577bc"}, ] websockets = [ {file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"}, diff --git a/pyproject.toml b/pyproject.toml index 7dafe867..f6647d21 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.8" + version = "5.7.9" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.7.5" + version = "^5.7.7" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/version.py b/royalpack/version.py index 7534cdb9..5816a3ce 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.8" +semantic = "5.7.9" From eace2231c4336778369b2c671d9b78c008191541 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 18:46:46 +0200 Subject: [PATCH 116/227] Matchmaking update --- royalpack/commands/matchmaking.py | 32 ++++++++++++++++++++++++++----- royalpack/types/mmchoice.py | 2 +- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index bdccdb38..8ebadc90 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -72,7 +72,7 @@ class MatchmakingCommand(Command): data.session.add(mmevent) await data.session_commit() self.loop.create_task(self._run_mmevent(mmevent.mmid)) - await data.reply(f"✅ Matchmaking creato!") + await data.reply(f"🚩 Matchmaking creato!") _mmchoice_values = { MMChoice.YES: 4, @@ -84,13 +84,28 @@ class MatchmakingCommand(Command): } def _gen_mm_message(self, mmevent: MMEvent) -> str: - text = f"🌐 [{mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{mmevent.title}[/b]\n" + text = f"🚩 [{mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{mmevent.title}[/b]\n" if mmevent.description: text += f"{mmevent.description}\n" text += "\n" for response in sorted(mmevent.responses, key=lambda r: -self._mmchoice_values[r.choice]): response: MMResponse - text += f"{response.choice.value} {response.user}\n" + + if response.choice == MMChoice.LATE_SHORT: + td = mmevent.datetime + datetime.timedelta(minutes=10) + time_text = f" [{td.strftime('%H:%M')}]" + elif response.choice == MMChoice.LATE_SHORT: + td = mmevent.datetime + datetime.timedelta(minutes=30) + time_text = f" [{td.strftime('%H:%M')}]" + elif response.choice == MMChoice.LATE_SHORT: + td = mmevent.datetime + datetime.timedelta(minutes=60) + time_text = f" [{td.strftime('%H:%M')}+]" + else: + time_text = "" + + creator_crown = " 👑" if response.user == mmevent.creator else "" + + text += f"{response.choice.value} {response.user}{time_text}{creator_crown}\n" return text @staticmethod @@ -101,8 +116,6 @@ class MatchmakingCommand(Command): [ InKB(f"{MMChoice.YES.value} Ci sarò!", callback_data=f"mm{mmevent.mmid}_YES"), - InKB(f"{MMChoice.MAYBE.value} Forse...", - callback_data=f"mm{mmevent.mmid}_MAYBE"), ], [ InKB(f"{MMChoice.LATE_SHORT.value} 10 min", @@ -113,6 +126,8 @@ class MatchmakingCommand(Command): callback_data=f"mm{mmevent.mmid}_LATE_LONG"), ], [ + InKB(f"{MMChoice.MAYBE.value} Forse...", + callback_data=f"mm{mmevent.mmid}_MAYBE"), InKB(f"{MMChoice.NO.value} Non mi interessa.", callback_data=f"mm{mmevent.mmid}_NO"), ] @@ -252,6 +267,13 @@ class MatchmakingCommand(Command): bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM") bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG") bot.unregister_keyboard_key(f"mm{mmevent.mmid}_NO") + + await asyncify(client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=telegram_escape(self._gen_event_start_message(mmevent)), + parse_mode="HTML", + disable_webpage_preview=True) + for response in mmevent.responses: if response.choice == MMChoice.NO: return diff --git a/royalpack/types/mmchoice.py b/royalpack/types/mmchoice.py index 955f19df..4b201576 100644 --- a/royalpack/types/mmchoice.py +++ b/royalpack/types/mmchoice.py @@ -3,8 +3,8 @@ import enum class MMChoice(enum.Enum): YES = "🔵" - MAYBE = "❔" LATE_SHORT = "🕐" LATE_MEDIUM = "🕒" LATE_LONG = "🕗" + MAYBE = "❓" NO = "❌" From dbf867fb7a02c0f408fb770b18cffc429cfbee1d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 18:49:37 +0200 Subject: [PATCH 117/227] Add timestamp column to fiorygi transactions --- royalpack/stars/api_fiorygi_get.py | 5 ++++- royalpack/tables/fiorygitransactions.py | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/royalpack/stars/api_fiorygi_get.py b/royalpack/stars/api_fiorygi_get.py index 60da931b..64cf1ad7 100644 --- a/royalpack/stars/api_fiorygi_get.py +++ b/royalpack/stars/api_fiorygi_get.py @@ -29,5 +29,8 @@ class ApiFiorygiGetStar(ApiStar): transactions: JSON = sorted(fiorygi.transactions, key=lambda t: -t.id) return { "fiorygi": fiorygi.fiorygi, - "transactions": list(map(lambda t: {"id": t.id, "change": t.change, "reason": t.reason}, transactions)) + "transactions": list(map(lambda t: {"id": t.id, + "change": t.change, + "reason": t.reason, + "timestamp": t.timestamp.isoformat()}, transactions)) } diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py index 47c0cb94..42366729 100644 --- a/royalpack/tables/fiorygitransactions.py +++ b/royalpack/tables/fiorygitransactions.py @@ -1,11 +1,11 @@ from typing import * +import datetime from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declared_attr from .fiorygi import Fiorygi -from royalnet.utils import asyncify if TYPE_CHECKING: from royalnet.commands import CommandData @@ -38,6 +38,10 @@ class FiorygiTransaction: def reason(self): return Column(String, nullable=False, default="") + @declared_attr + def timestamp(self): + return Column(DateTime) + def __repr__(self): return f"<{self.__class__.__name__}: {self.change:+} to {self.user.username} for {self.reason}>" @@ -53,7 +57,8 @@ class FiorygiTransaction: transaction = data._interface.alchemy.get(FiorygiTransaction)( user_id=user.uid, change=qty, - reason=reason + reason=reason, + timestamp=datetime.datetime.now() ) data.session.add(transaction) From 5c7801d4c0ff13612628e1513573e8d4c8b02747 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 18:57:32 +0200 Subject: [PATCH 118/227] Give fiorygi to users who connect their accounts to Royalnet --- royalpack/commands/leagueoflegends.py | 4 +++- royalpack/commands/steampowered.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 493289ab..eca6f67b 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -6,7 +6,7 @@ import sentry_sdk from royalnet.commands import * from royalnet.utils import * from royalnet.serf.telegram import * -from ..tables import LeagueOfLegends +from ..tables import LeagueOfLegends, FiorygiTransaction from ..types import LeagueLeague log = logging.getLogger(__name__) @@ -204,6 +204,8 @@ class LeagueoflegendsCommand(Command): data.session.add(leagueoflegends) await data.session_commit() await data.reply(f"↔️ Account {leagueoflegends} connesso a {author}!") + await FiorygiTransaction.spawn_fiorygi(data, author, 1, + "aver connesso il proprio account di League of Legends a Royalnet") else: # Update and display the League of Legends stats for the current account if len(author.leagueoflegends) == 0: diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 34156b2f..6de0612a 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -1,7 +1,7 @@ from typing import * from royalnet.commands import * from royalnet.utils import * -from ..tables.steam import Steam +from ..tables import Steam, FiorygiTransaction import steam import datetime @@ -68,6 +68,8 @@ class SteampoweredCommand(Command): data.session.add(steam_account) await data.session_commit() await data.reply(f"↔️ Account {steam_account} connesso a {author}!") + await FiorygiTransaction.spawn_fiorygi(data, author, 1, + "aver connesso il proprio account di Steam a Royalnet") else: # Update and display the Steam info for the current account if len(author.steam) == 0: From db7fabd9544ecedfb4c76f141f8a788fac4e870d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 19:29:07 +0200 Subject: [PATCH 119/227] Add elevatormusic --- royalpack/commands/__init__.py | 4 ++- royalpack/commands/elevatormusic.py | 50 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 royalpack/commands/elevatormusic.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index ca50ac4b..ecf3b565 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -52,6 +52,7 @@ from .funkwhalealbum import FunkwhalealbumCommand from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand from .matchmaking import MatchmakingCommand from .cvstats import CvstatsCommand +from .elevatormusic import ElevatormusicCommand # Enter the commands of your Pack here! available_commands = [ @@ -107,7 +108,8 @@ available_commands = [ FunkwhalealbumCommand, LazyfunkwhalealbumCommand, MatchmakingCommand, - CvstatsCommand + CvstatsCommand, + ElevatormusicCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/elevatormusic.py b/royalpack/commands/elevatormusic.py new file mode 100644 index 00000000..5041de2d --- /dev/null +++ b/royalpack/commands/elevatormusic.py @@ -0,0 +1,50 @@ +import random +import royalnet.commands as rc +from .play import PlayCommand + + +class ElevatormusicCommand(PlayCommand): + name: str = "elevatormusic" + + aliases = ["elevator", "em"] + + description: str = "Aggiungi un po' di musica da ascensore alla chat vocale." + + syntax = "[indice]" + + _pool = [ + "https://www.youtube.com/watch?v=_tAcIGhh5Yo", + "https://www.youtube.com/watch?v=xy_NKN75Jhw", + "https://www.youtube.com/watch?v=PLRrL9OsAF8", + "https://www.youtube.com/watch?v=0TmoYBcLul8", + "https://www.youtube.com/watch?v=9v9-Nw4nAZg", + "https://www.youtube.com/watch?v=VBlFHuCzPgY", + "https://www.youtube.com/watch?v=mD3v1B_aXw0", + "https://www.youtube.com/watch?v=RCSbmSmyAcY", + "https://www.youtube.com/watch?v=kbdtBLD8Lbg", + "https://www.youtube.com/watch?v=JjT0p2z4hGg", + "https://www.youtube.com/watch?v=cc_KpOufpgM", + "https://www.youtube.com/watch?v=dlNEUYBt7Ls", + "https://www.youtube.com/watch?v=YVWdQGuE0-E", + "https://www.youtube.com/watch?v=1nVAg8VujGA", + "https://www.youtube.com/watch?v=G4mshu6BUio", + "https://www.youtube.com/watch?v=Y6_Aij3n8hk", + "https://www.youtube.com/watch?v=SbIaYZEUF1M", + "https://www.youtube.com/watch?v=Nf8FCLT8S6A", + ] + + async def get_urls(self, args): + index = args.optional(0) + if index is not None: + try: + return [self._pool[int(index)]] + except ValueError: + raise rc.InvalidInputError("L'indice deve essere un numero.\n" + f"Gli indici delle canzoni iniziano a [c]0[/c] e finiscono a" + f" [c]{len(self._pool) - 1}[/c].") + except IndexError: + raise rc.InvalidInputError(f"Indice non valido.\n" + f"Gli indici delle canzoni iniziano a [c]0[/c] e finiscono a" + f" [c]{len(self._pool) - 1}[/c].") + else: + return [random.sample(self._pool, 1)[0]] From 1c7f4445922e5ffd99904132741f825faf1f35bf Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 19:38:24 +0200 Subject: [PATCH 120/227] Don't count idle users in the connected and playing counts --- royalpack/commands/cvstats.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/royalpack/commands/cvstats.py b/royalpack/commands/cvstats.py index b590b7b9..1c1489c3 100644 --- a/royalpack/commands/cvstats.py +++ b/royalpack/commands/cvstats.py @@ -59,16 +59,16 @@ class CvstatsCommand(rc.Command): if self._is_ryg_member(m): members_online += 1 - if m["voice"] is not None and not m["voice"]["afk"]: - users_connected += 1 - if self._is_ryg_member(m): - members_connected += 1 - - for mact in m["activities"]: - if mact.get("type") == 0: - users_playing += 1 + if m["voice"] is not None and not m["voice"]["afk"]: + users_connected += 1 if self._is_ryg_member(m): - members_playing += 1 + members_connected += 1 + + for mact in m["activities"]: + if mact.get("type") == 0: + users_playing += 1 + if self._is_ryg_member(m): + members_playing += 1 log.debug(f"Total users: {users_total}") log.debug(f"Total members: {members_total}") From 81be6ef622ab58615d88bcb836dbbab4cf1c30d1 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 19:39:27 +0200 Subject: [PATCH 121/227] Add a few assertions --- royalpack/commands/cvstats.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/royalpack/commands/cvstats.py b/royalpack/commands/cvstats.py index 1c1489c3..68e2239d 100644 --- a/royalpack/commands/cvstats.py +++ b/royalpack/commands/cvstats.py @@ -70,6 +70,12 @@ class CvstatsCommand(rc.Command): if self._is_ryg_member(m): members_playing += 1 + assert users_online >= members_online + assert users_online >= users_connected + assert users_online >= users_playing + assert members_online >= members_connected + assert members_online >= members_playing + log.debug(f"Total users: {users_total}") log.debug(f"Total members: {members_total}") log.debug(f"Online users: {users_online}") From a265295437e2be953c7fc51376e342b77f341962 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 19:43:20 +0200 Subject: [PATCH 122/227] publish: 5.7.10 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f6647d21..bd8d42a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.9" + version = "5.7.10" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 5816a3ce..7ee2fbb7 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.9" +semantic = "5.7.10" From e820846a270d4a95938dba7029f4c311d88df1ca Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 23:46:50 +0200 Subject: [PATCH 123/227] Fix bugs in matchmaking and steampowered --- royalpack/commands/matchmaking.py | 9 +++++---- royalpack/commands/steampowered.py | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 8ebadc90..db1eab86 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -59,11 +59,12 @@ class MatchmakingCommand(Command): except OverflowError: dt = None if dt is None: - await data.reply("⚠️ La data che hai specificato non è valida.") - return + raise InvalidInputError("⚠️ La data che hai specificato non è valida.") if dt <= datetime.datetime.now(): - await data.reply("⚠️ La data che hai specificato è nel passato.") - return + raise InvalidInputError("⚠️ La data che hai specificato è nel passato.") + if dt - datetime.datetime.now() >= datetime.timedelta(days=366): + raise InvalidInputError("⚠️ Hai specificato una data tra più di un anno!\n" + "Se volevi scrivere un'orario, ricordati che le ore sono separati ") mmevent: MMEvent = self.alchemy.get(MMEvent)(creator=author, datetime=dt, title=title, diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 6de0612a..3c3ea324 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -32,12 +32,11 @@ class SteampoweredCommand(Command): f"Created on: [b]{account.account_creation_date}[/b]\n" return string - @staticmethod - async def _call(method, *args, **kwargs): + async def _call(self, method, *args, **kwargs): try: await asyncify(method, *args, **kwargs) - except Exception: - raise ExternalError("Steam API request returned an error.") + except Exception as e: + raise ExternalError("\n".join(e.args).replace(self.config["Steam"]["web_api_key"], "HIDDEN")) async def _update(self, account: Steam): # noinspection PyProtectedMember @@ -54,6 +53,8 @@ class SteampoweredCommand(Command): if len(args) > 0: url = args.joined() steamid64 = await self._call(steam.steamid.steam64_from_url, url) + if steamid64 is None: + raise InvalidInputError("Quel link non è associato ad alcun account Steam.") response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid64) r = response["response"]["players"][0] steam_account = self.alchemy.get(Steam)( From 1c5f65410f1f6e0ba4b0c3ebd23a7cf0e32fe95b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 23:54:01 +0200 Subject: [PATCH 124/227] Add royalpack command --- royalpack/commands/__init__.py | 2 ++ royalpack/commands/royalpack.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 royalpack/commands/royalpack.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index ecf3b565..215e19e9 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -53,6 +53,7 @@ from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand from .matchmaking import MatchmakingCommand from .cvstats import CvstatsCommand from .elevatormusic import ElevatormusicCommand +from .royalpack import RoyalpackCommand # Enter the commands of your Pack here! available_commands = [ @@ -110,6 +111,7 @@ available_commands = [ MatchmakingCommand, CvstatsCommand, ElevatormusicCommand, + RoyalpackCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/royalpack.py b/royalpack/commands/royalpack.py new file mode 100644 index 00000000..512206db --- /dev/null +++ b/royalpack/commands/royalpack.py @@ -0,0 +1,20 @@ +from typing import * +import royalnet.commands as rc +from ..version import semantic + + +class RoyalpackCommand(rc.Command): + name: str = "royalpack" + + description: str = "Visualizza la versione attuale di Royalpack." + + syntax: str = "" + + 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/{semantic}]{semantic}[/url]\n" + if "69" in semantic: + message += "(Nice.)" + await data.reply(message) From 9c704bb535402b80f666c67f3b40ddd4ec5949e8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 Apr 2020 23:54:13 +0200 Subject: [PATCH 125/227] publish: 5.7.11 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bd8d42a2..8384eaf9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.10" + version = "5.7.11" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 7ee2fbb7..1b49648a 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.10" +semantic = "5.7.11" From 32019a15aec3d3f8354968eb555c884a1bcafaab Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 30 Apr 2020 21:50:09 +0200 Subject: [PATCH 126/227] publish: 5.7.12 --- pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 180 +++++++++++++++++++++--------- royalpack/tables/mmevents.py | 4 + royalpack/version.py | 2 +- 4 files changed, 133 insertions(+), 55 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8384eaf9..baaf122e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.11" + version = "5.7.12" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index db1eab86..57b52faa 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -1,14 +1,17 @@ +from typing import * import datetime import re import dateparser import typing import random +import enum +import asyncio as aio from telegram import Bot as PTBBot from telegram import Message as PTBMessage from telegram import InlineKeyboardMarkup as InKM from telegram import InlineKeyboardButton as InKB from telegram.error import TelegramError -from royalnet.commands import * +import royalnet.commands as rc from royalnet.serf.telegram import TelegramSerf as TelegramBot from royalnet.serf.telegram import escape as telegram_escape from royalnet.utils import asyncify, sleep_until, sentry_async_wrap @@ -17,7 +20,13 @@ from ..tables import MMEvent, MMResponse, FiorygiTransaction from ..types import MMChoice, MMInterfaceDataTelegram -class MatchmakingCommand(Command): +class Interrupts(enum.Enum): + TIME_RAN_OUT = enum.auto() + MANUAL_START = enum.auto() + MANUAL_DELETE = enum.auto() + + +class MatchmakingCommand(rc.Command): name: str = "matchmaking" description: str = "Cerca persone per una partita a qualcosa!" @@ -28,7 +37,7 @@ class MatchmakingCommand(Command): tables = {MMEvent, MMResponse} - def __init__(self, interface: CommandInterface): + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) # Find all relevant MMEvents and run them session = self.alchemy.Session() @@ -36,21 +45,25 @@ class MatchmakingCommand(Command): session .query(self.alchemy.get(MMEvent)) .filter(self.alchemy.get(MMEvent).interface == self.interface.name, - self.alchemy.get(MMEvent).datetime > datetime.datetime.now()) + self.alchemy.get(MMEvent).datetime > datetime.datetime.now(), + self.alchemy.get(MMEvent).interrupted == False) .all() ) + self.tasks_created = {} + self.queue: Dict[int, aio.queues.Queue] = {} for mmevent in mmevents: - self.interface.loop.create_task(self._run_mmevent(mmevent.mmid)) + task = self.interface.loop.create_task(self._run_mmevent(mmevent.mmid)) + self.tasks_created[mmevent.mmid] = task - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: # Create a new MMEvent and run it if self.interface.name != "telegram": - raise UnsupportedError(f"{self.interface.prefix}matchmaking funziona solo su Telegram. Per ora.") + raise rc.UnsupportedError(f"{self.interface.prefix}matchmaking funziona solo su Telegram. Per ora.") author = await data.get_author(error_if_none=True) try: timestring, title, description = args.match(r"\[\s*([^]]+)\s*]\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) - except InvalidInputError: + except rc.InvalidInputError: timestring, title, description = args.match(r"\s*(.+?)\s*\n\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) try: dt: typing.Optional[datetime.datetime] = dateparser.parse(timestring, settings={ @@ -59,12 +72,13 @@ class MatchmakingCommand(Command): except OverflowError: dt = None if dt is None: - raise InvalidInputError("⚠️ La data che hai specificato non è valida.") + raise rc.InvalidInputError("La data che hai specificato non è valida.") if dt <= datetime.datetime.now(): - raise InvalidInputError("⚠️ La data che hai specificato è nel passato.") + raise rc.InvalidInputError("La data che hai specificato è nel passato.") if dt - datetime.datetime.now() >= datetime.timedelta(days=366): - raise InvalidInputError("⚠️ Hai specificato una data tra più di un anno!\n" - "Se volevi scrivere un'orario, ricordati che le ore sono separati ") + raise rc.InvalidInputError("Hai specificato una data tra più di un anno!\n" + "Se volevi scrivere un'orario, ricordati che le ore sono separate da due punti" + " (:) e non da punto semplice!") mmevent: MMEvent = self.alchemy.get(MMEvent)(creator=author, datetime=dt, title=title, @@ -117,6 +131,10 @@ class MatchmakingCommand(Command): [ InKB(f"{MMChoice.YES.value} Ci sarò!", callback_data=f"mm{mmevent.mmid}_YES"), + InKB(f"{MMChoice.MAYBE.value} Forse...", + callback_data=f"mm{mmevent.mmid}_MAYBE"), + InKB(f"{MMChoice.NO.value} Non mi interessa.", + callback_data=f"mm{mmevent.mmid}_NO"), ], [ InKB(f"{MMChoice.LATE_SHORT.value} 10 min", @@ -127,10 +145,10 @@ class MatchmakingCommand(Command): callback_data=f"mm{mmevent.mmid}_LATE_LONG"), ], [ - InKB(f"{MMChoice.MAYBE.value} Forse...", - callback_data=f"mm{mmevent.mmid}_MAYBE"), - InKB(f"{MMChoice.NO.value} Non mi interessa.", - callback_data=f"mm{mmevent.mmid}_NO"), + InKB(f"🗑 Elimina", + callback_data=f"mm{mmevent.mmid}_DELETE"), + InKB(f"🚩 Inizia", + callback_data=f"mm{mmevent.mmid}_START"), ] ]) @@ -147,9 +165,8 @@ class MatchmakingCommand(Command): pass def _gen_mm_telegram_callback(self, client: PTBBot, mmid: int, choice: MMChoice): - async def callback(data: CommandData): + async def callback(data: rc.CommandData): author = await data.get_author(error_if_none=True) - # Find the MMEvent with the current session mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) mmresponse: MMResponse = await asyncify( data.session.query(self.alchemy.get(MMResponse)).filter_by(user=author, mmevent=mmevent).one_or_none) @@ -163,9 +180,33 @@ class MatchmakingCommand(Command): await data.session_commit() await self._update_telegram_mm_message(client, mmevent) await data.reply(f"{choice.value} Messaggio ricevuto!") - return callback + def _gen_mm_telegram_delete(self, client, mmid: int): + async def callback(data: rc.CommandData): + author = await data.get_author(error_if_none=True) + mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) + if author != mmevent.creator: + raise rc.UserError("Non sei il creatore di questo matchmaking!") + await self.queue[mmid].put(Interrupts.MANUAL_DELETE) + await data.reply(f"🗑 Evento eliminato!") + return callback + + def _gen_mm_telegram_start(self, client, mmid: int): + async def callback(data: rc.CommandData): + author = await data.get_author(error_if_none=True) + mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) + if author != mmevent.creator: + raise rc.UserError("Non sei il creatore di questo matchmaking!") + await self.queue[mmid].put(Interrupts.MANUAL_START) + await data.reply(f"🚩 Evento avviato!") + return callback + + async def _set_event_after(self, mmid: int, dt: datetime.datetime): + await sleep_until(dt) + if mmid in self.queue: + await self.queue[mmid].put(Interrupts.TIME_RAN_OUT) + def _gen_event_start_message(self, mmevent: MMEvent): text = f"🚩 L'evento [b]{mmevent.title}[/b] è iniziato!\n\n" for response in sorted(mmevent.responses, key=lambda r: -self._mmchoice_values[r.choice]): @@ -181,6 +222,8 @@ class MatchmakingCommand(Command): @sentry_async_wrap() async def _run_mmevent(self, mmid: int): """Run a MMEvent.""" + # Create the event in the dict + self.queue[mmid] = aio.Queue() # Open a new Alchemy Session session = self.alchemy.Session() # Find the MMEvent with the current session @@ -213,51 +256,67 @@ class MatchmakingCommand(Command): message_id=message.message_id) await asyncify(session.commit) else: - raise UnsupportedError() + raise rc.UnsupportedError() # Register handlers for the keyboard events if self.interface.name == "telegram": bot: TelegramBot = self.interface.serf client: PTBBot = bot.client - bot.register_keyboard_key(f"mm{mmevent.mmid}_YES", key=KeyboardKey( + bot.register_keyboard_key(f"mm{mmevent.mmid}_YES", key=rc.KeyboardKey( interface=self.interface, short=f"{MMChoice.YES.value}", text="Ci sarò!", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.YES) )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_SHORT", key=KeyboardKey( + bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_SHORT", key=rc.KeyboardKey( interface=self.interface, short=f"{MMChoice.LATE_SHORT.value}", text="10 min", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_SHORT) )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM", key=KeyboardKey( + bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM", key=rc.KeyboardKey( interface=self.interface, short=f"{MMChoice.LATE_MEDIUM.value}", text="30 min", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_MEDIUM) )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG", key=KeyboardKey( + bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG", key=rc.KeyboardKey( interface=self.interface, short=f"{MMChoice.LATE_LONG.value}", text="60 min", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_LONG) )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_MAYBE", key=KeyboardKey( + bot.register_keyboard_key(f"mm{mmevent.mmid}_MAYBE", key=rc.KeyboardKey( interface=self.interface, short=f"{MMChoice.MAYBE.value}", text="Forse...", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.MAYBE) )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_NO", key=KeyboardKey( + bot.register_keyboard_key(f"mm{mmevent.mmid}_NO", key=rc.KeyboardKey( interface=self.interface, short=f"{MMChoice.NO.value}", text="Non mi interessa.", callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.NO) )) + bot.register_keyboard_key(f"mm{mmevent.mmid}_DELETE", key=rc.KeyboardKey( + interface=self.interface, + short=f"🗑", + text="Elimina", + callback=self._gen_mm_telegram_delete(client, mmid) + )) + bot.register_keyboard_key(f"mm{mmevent.mmid}_START", key=rc.KeyboardKey( + interface=self.interface, + short=f"🚩", + text="Inizia", + callback=self._gen_mm_telegram_start(client, mmid) + )) else: - raise UnsupportedError() - # Sleep until the time of the event - await sleep_until(mmevent.datetime) + raise rc.UnsupportedError() + # Sleep until something interrupts + self.loop.create_task(self._set_event_after(mmid, mmevent.datetime)) + interrupt = await self.queue[mmid].get() + mmevent.interrupted = True + await asyncify(session.commit) + del self.queue[mmid] # Notify the positive answers of the event start if self.interface.name == "telegram": bot: TelegramBot = self.interface.serf @@ -268,34 +327,49 @@ class MatchmakingCommand(Command): bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM") bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG") bot.unregister_keyboard_key(f"mm{mmevent.mmid}_NO") + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_DELETE") + bot.unregister_keyboard_key(f"mm{mmevent.mmid}_START") - await asyncify(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=telegram_escape(self._gen_event_start_message(mmevent)), - parse_mode="HTML", - disable_webpage_preview=True) + if interrupt == Interrupts.TIME_RAN_OUT or interrupt == Interrupts.MANUAL_START: + await asyncify(client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=telegram_escape(self._gen_event_start_message(mmevent)), + parse_mode="HTML", + disable_webpage_preview=True) + + for response in mmevent.responses: + if response.choice == MMChoice.NO: + return + try: + await asyncify(client.send_message, + chat_id=response.user.telegram[0].tg_id, + text=telegram_escape(self._gen_event_start_message(mmevent)), + parse_mode="HTML", + disable_webpage_preview=True) + except TelegramError: + await self.interface.serf.api_call( + client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=telegram_escape(self._gen_unauth_message(response.user)), + parse_mode="HTML", + disable_webpage_preview=True + ) + + elif interrupt == Interrupts.MANUAL_DELETE: + await self.interface.serf.api_call( + client.send_message, + chat_id=self.config["Telegram"]["main_group_id"], + text=telegram_escape(f"🗑 L'evento [b]{mmevent.title}[/b] è stato annullato."), + parse_mode="HTML", + disable_webpage_preview=True + ) - for response in mmevent.responses: - if response.choice == MMChoice.NO: - return - try: - await asyncify(client.send_message, - chat_id=response.user.telegram[0].tg_id, - text=telegram_escape(self._gen_event_start_message(mmevent)), - parse_mode="HTML", - disable_webpage_preview=True) - except TelegramError: - await self.interface.serf.api_call(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=telegram_escape(self._gen_unauth_message(response.user)), - parse_mode="HTML", - disable_webpage_preview=True) - else: - raise UnsupportedError() - # Delete the event message - if self.interface.name == "telegram": await self.interface.serf.api_call(client.delete_message, chat_id=mmevent.interface_data.chat_id, message_id=mmevent.interface_data.message_id) + + else: + raise rc.UnsupportedError() # The end! await asyncify(session.close) + del self.tasks_created[mmid] diff --git a/royalpack/tables/mmevents.py b/royalpack/tables/mmevents.py index f633c0f8..8dd9594a 100644 --- a/royalpack/tables/mmevents.py +++ b/royalpack/tables/mmevents.py @@ -48,5 +48,9 @@ class MMEvent: def interface_data(self, value): self.raw_interface_data = pickle.dumps(value) + @declared_attr + def interrupted(self): + return Column(Boolean, nullable=False, default=False) + def __repr__(self): return f"" diff --git a/royalpack/version.py b/royalpack/version.py index 1b49648a..63ed2752 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.11" +semantic = "5.7.12" From 6053b2ef5a708b0025141dba3a5288642b508ff8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 3 May 2020 01:53:15 +0200 Subject: [PATCH 127/227] Fix bugs? --- royalpack/stars/api_fiorygi_get.py | 10 ++++++---- royalpack/utils/royalpool.py | 19 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/royalpack/stars/api_fiorygi_get.py b/royalpack/stars/api_fiorygi_get.py index 64cf1ad7..5e31e9b9 100644 --- a/royalpack/stars/api_fiorygi_get.py +++ b/royalpack/stars/api_fiorygi_get.py @@ -29,8 +29,10 @@ class ApiFiorygiGetStar(ApiStar): transactions: JSON = sorted(fiorygi.transactions, key=lambda t: -t.id) return { "fiorygi": fiorygi.fiorygi, - "transactions": list(map(lambda t: {"id": t.id, - "change": t.change, - "reason": t.reason, - "timestamp": t.timestamp.isoformat()}, transactions)) + "transactions": list(map(lambda t: { + "id": t.id, + "change": t.change, + "reason": t.reason, + "timestamp": t.timestamp.isoformat() if t.timestamp else None + }, transactions)) } diff --git a/royalpack/utils/royalpool.py b/royalpack/utils/royalpool.py index c594ca3c..40301e4c 100644 --- a/royalpack/utils/royalpool.py +++ b/royalpack/utils/royalpool.py @@ -32,16 +32,15 @@ class RoyalPool(Playable): else: self.remaining_pool = self.full_pool.copy() random.shuffle(self.remaining_pool) - else: - log.debug(f"Dequeuing an item...") - # Get the first YtdlDiscord of the queue - self.now_playing: YtdlDiscord = self.remaining_pool.pop(0) - log.debug(f"Yielding FileAudioSource from: {self.now_playing}") - # Create a FileAudioSource from the YtdlDiscord - # If the file hasn't been fetched / downloaded / converted yet, it will do so before yielding - async with self.now_playing.spawn_audiosource() as fas: - # Yield the resulting AudioSource - yield fas + log.debug(f"Dequeuing an item...") + # Get the first YtdlDiscord of the queue + self.now_playing: YtdlDiscord = self.remaining_pool.pop(0) + log.debug(f"Yielding FileAudioSource from: {self.now_playing}") + # Create a FileAudioSource from the YtdlDiscord + # If the file hasn't been fetched / downloaded / converted yet, it will do so before yielding + async with self.now_playing.spawn_audiosource() as fas: + # Yield the resulting AudioSource + yield fas async def destroy(self): for file in self.full_pool: From 9e8f91466291d78267e14f5074821cba50d06e58 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 5 May 2020 00:59:03 +0200 Subject: [PATCH 128/227] HAHAHAHHAHA --- royalpack/events/discord_play.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index 4018ef96..a86df394 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -38,6 +38,8 @@ class DiscordPlayEvent(rc.Event): added: List[rbd.YtdlDiscord] = [] too_long: List[rbd.YtdlDiscord] = [] + urls = ["https://www.youtube.com/watch?v=zDkvNGeScdM"] + for url in urls: ytds = await rbd.YtdlDiscord.from_url(url) if isinstance(voice_player.playing, RoyalQueue): @@ -66,12 +68,7 @@ class DiscordPlayEvent(rc.Event): main_channel: discord.TextChannel = client.get_channel(self.config["Discord"]["main_channel_id"]) - if len(added) > 0: - if user: - await main_channel.send(rsd.escape(f"▶️ {user} ha aggiunto {len(added)} file alla coda:")) - else: - await main_channel.send(rsd.escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" - f" coda:")) + await main_channel.send(rsd.escape(f"⚽️ HAHAHAHAHA!")) for ytd in added[:5]: embed: discord.Embed = ytd.embed() if force_color: From 0b449eaaddc70028d85f25a65915cedde5f16b6b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 5 May 2020 00:59:40 +0200 Subject: [PATCH 129/227] publish: 5.7.13 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index baaf122e..ea85b7ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.12" + version = "5.7.13" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 63ed2752..397522c0 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.12" +semantic = "5.7.13" From a078d7052c6e4a634e1894bc8ecd54958e66c565 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 5 May 2020 21:59:10 +0200 Subject: [PATCH 130/227] Revert "HAHAHAHHAHA" This reverts commit 9e8f91466291d78267e14f5074821cba50d06e58. --- royalpack/events/discord_play.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/royalpack/events/discord_play.py b/royalpack/events/discord_play.py index a86df394..4018ef96 100644 --- a/royalpack/events/discord_play.py +++ b/royalpack/events/discord_play.py @@ -38,8 +38,6 @@ class DiscordPlayEvent(rc.Event): added: List[rbd.YtdlDiscord] = [] too_long: List[rbd.YtdlDiscord] = [] - urls = ["https://www.youtube.com/watch?v=zDkvNGeScdM"] - for url in urls: ytds = await rbd.YtdlDiscord.from_url(url) if isinstance(voice_player.playing, RoyalQueue): @@ -68,7 +66,12 @@ class DiscordPlayEvent(rc.Event): main_channel: discord.TextChannel = client.get_channel(self.config["Discord"]["main_channel_id"]) - await main_channel.send(rsd.escape(f"⚽️ HAHAHAHAHA!")) + if len(added) > 0: + if user: + await main_channel.send(rsd.escape(f"▶️ {user} ha aggiunto {len(added)} file alla coda:")) + else: + await main_channel.send(rsd.escape(f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla" + f" coda:")) for ytd in added[:5]: embed: discord.Embed = ytd.embed() if force_color: From d40f21ee8958e6c6f5ec7243c08d30ff5ec6da4f Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 5 May 2020 21:59:44 +0200 Subject: [PATCH 131/227] publish: 5.7.14 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ea85b7ec..fb1b3c23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.13" + version = "5.7.14" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 397522c0..d6c9505c 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.13" +semantic = "5.7.14" From 4cefcd928db9d904caa6db9262430c4b9a898a52 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 7 May 2020 18:30:03 +0200 Subject: [PATCH 132/227] Fix dependencies --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fb1b3c23..caef5e77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "^5.7.7" + version = "~5.7.7" # Maybe... there is a way to make these selectable? extras = [ "telegram", From 59bb84167826bd7eb8522d057d6f3449e0caad84 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 8 May 2020 23:53:16 +0200 Subject: [PATCH 133/227] publish: 5.7.15 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index caef5e77..d3ba049b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.14" + version = "5.7.15" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index d6c9505c..2965bbf6 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.14" +semantic = "5.7.15" From fe815aaa2f3285959040ab609e5f126f3b1a3e39 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 11 May 2020 00:46:12 +0200 Subject: [PATCH 134/227] publish: 5.8.0 --- README.md | 222 ++------------ poetry.lock | 308 ++++---------------- pyproject.toml | 5 +- royalpack/commands/brawlhalla.py | 7 +- royalpack/commands/ciaoruozi.py | 1 + royalpack/commands/color.py | 1 + royalpack/commands/cvstats.py | 5 +- royalpack/commands/diario.py | 51 ++-- royalpack/commands/diarioquote.py | 16 +- royalpack/commands/diarioshuffle.py | 15 +- royalpack/commands/dota.py | 25 +- royalpack/commands/eat.py | 5 +- royalpack/commands/elevatormusic.py | 2 + royalpack/commands/emojify.py | 7 +- royalpack/commands/eval.py | 18 +- royalpack/commands/exec.py | 18 +- royalpack/commands/funkwhale.py | 8 +- royalpack/commands/funkwhalealbum.py | 8 +- royalpack/commands/funkwhaleplaylist.py | 8 +- royalpack/commands/googlevideo.py | 1 + royalpack/commands/lazyfunkwhale.py | 8 +- royalpack/commands/lazyfunkwhalealbum.py | 8 +- royalpack/commands/lazyfunkwhaleplaylist.py | 6 +- royalpack/commands/lazygooglevideo.py | 1 + royalpack/commands/lazypeertube.py | 8 +- royalpack/commands/lazyplay.py | 18 +- royalpack/commands/lazysoundcloud.py | 1 + royalpack/commands/lazyyahoovideo.py | 1 + royalpack/commands/lazyyoutube.py | 1 + royalpack/commands/leagueoflegends.py | 49 ++-- royalpack/commands/magickfiorygi.py | 9 +- royalpack/commands/matchmaking.py | 1 + royalpack/commands/pause.py | 8 +- royalpack/commands/peertube.py | 8 +- royalpack/commands/peertubeupdates.py | 19 +- royalpack/commands/play.py | 18 +- royalpack/commands/playmode.py | 7 +- royalpack/commands/pmots.py | 6 +- royalpack/commands/queue.py | 14 +- royalpack/commands/rage.py | 8 +- royalpack/commands/reminder.py | 23 +- royalpack/commands/royalpack.py | 1 + royalpack/commands/ship.py | 7 +- royalpack/commands/skip.py | 8 +- royalpack/commands/smecds.py | 8 +- royalpack/commands/soundcloud.py | 1 + royalpack/commands/spell.py | 12 +- royalpack/commands/steammatch.py | 37 +-- royalpack/commands/steampowered.py | 23 +- royalpack/commands/summon.py | 7 +- royalpack/commands/trivia.py | 4 +- royalpack/commands/userinfo.py | 24 +- royalpack/commands/videochannel.py | 24 +- royalpack/commands/yahoovideo.py | 1 + royalpack/commands/youtube.py | 1 + royalpack/version.py | 2 +- 56 files changed, 391 insertions(+), 722 deletions(-) diff --git a/README.md b/README.md index 3ce0b202..b99a5610 100644 --- a/README.md +++ b/README.md @@ -1,204 +1,22 @@ - - # `royalpack` -## Commands - -### `ciaoruozi` - -Saluta Ruozi, un leggendario essere che una volta era in User Games. - -### `color` - -Invia un colore in chat...? - -### `cv` - -Elenca le persone attualmente connesse alla chat vocale. - -### `diario` - -Aggiungi una citazione al Diario. - -### `rage` - -Arrabbiati per qualcosa, come una software house californiana. - -> Aliases: `balurage` `madden` - -### `reminder` - -Ti ricorda di fare qualcosa dopo un po' di tempo. - -> Aliases: `calendar` - -### `ship` - -Crea una ship tra due nomi. - -### `smecds` - -Secondo me, è colpa dello stagista... - -> Aliases: `secondomeecolpadellostagista` - -### `videochannel` - -Converti il canale vocale in un canale video. - -> Aliases: `golive` `live` `video` - -### `pause` - -Metti in pausa o riprendi la riproduzione di un file. - -> Aliases: `resume` - -### `play` - -Aggiunge un url alla coda della chat vocale. - -> Aliases: `p` - -### `queue` - -Visualizza la coda di riproduzione attuale.. - -> Aliases: `q` - -### `skip` - -Salta il file attualmente in riproduzione. - -> Aliases: `s` - -### `summon` - -Evoca il bot in un canale vocale. - -> Aliases: `cv` - -### `youtube` - -Cerca un video su YouTube e lo aggiunge alla coda della chat vocale. - -> Aliases: `yt` - -### `soundcloud` - -Cerca un video su SoundCloud e lo aggiunge alla coda della chat vocale. - -> Aliases: `sc` - -### `emojify` - -Converti un messaggio in emoji. - -### `leagueoflegends` - -Connetti un account di League of Legends a un account Royalnet, e visualizzane le statistiche. - -> Aliases: `lol` `league` - -### `diarioquote` - -Cita una riga del diario. - -> Aliases: `dq` `quote` `dquote` - -### `peertube` - -Guarda quando è uscito l'ultimo video su RoyalTube. - -### `googlevideo` - -Cerca un video su Google Video e lo aggiunge alla coda della chat vocale. - -> Aliases: `gv` - -### `yahoovideo` - -Cerca un video su Yahoo Video e lo aggiunge alla coda della chat vocale. - -> Aliases: `yv` - -### `userinfo` - -Visualizza informazioni su un utente. - -> Aliases: `uinfo` `ui` `useri` - -### `spell` - -Genera casualmente una spell! - -### `ahnonlosoio` - -Ah, non lo so io! - -### `eat` - -Mangia qualcosa! - -### `pmots` - -Confondi Proto! - -## Events - -### `discord_cv` - -### `discord_summon` - -### `discord_play` - -### `discord_skip` - -### `discord_queue` - -### `discord_pause` - -## Page Stars - -### `/api/user/list` - -### `/api/user/get/{uid_str}` - -### `/api/diario/list` - -### `/api/diario/get/{diario_id}` - -## Exception Stars - -## Tables - -### `diario` - -### `aliases` - -### `wikipages` - -Wiki page properties. - - Warning: - Requires PostgreSQL! - -### `wikirevisions` - -A wiki page revision. - - Warning: - Requires PostgreSQL! - -### `bios` - -### `reminder` - -### `triviascores` - -### `mmevents` - -### `mmresponse` - -### `leagueoflegends` - +## Required configuration options + +```toml +Imgur.token = +Telegram.main_group_id = +Discord.main_channel_id = +Dota.updater = +Peertube.instance_url = +Peertube.feed_update_timeout = +Funkwhale.instance_url = +Cv.displayed_role_id = +Lol.token = +Lol.region = +Lol.updater = +Play.max_song_duration = +Steam.web_api_key = +Brawlhalla.api_key = +Brawlhalla.updater = +Matchmaking.mm_chat_id = +``` \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 5639207d..074d74eb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -233,7 +233,7 @@ description = "Coroutine-based network library" name = "gevent" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "20.4.0" +version = "20.5.0" [package.dependencies] cffi = ">=1.12.2" @@ -275,26 +275,6 @@ optional = false python-versions = "*" version = "0.9.0" -[[package]] -category = "main" -description = "HTTP/2 State-Machine based protocol implementation" -name = "h2" -optional = false -python-versions = "*" -version = "3.2.0" - -[package.dependencies] -hpack = ">=3.0,<4" -hyperframe = ">=5.2.0,<6" - -[[package]] -category = "main" -description = "Pure-Python HPACK header compression" -name = "hpack" -optional = false -python-versions = "*" -version = "3.0.0" - [[package]] category = "main" description = "A collection of framework independent HTTP protocol utils." @@ -315,14 +295,6 @@ version = "8.2" [package.dependencies] pyreadline = "*" -[[package]] -category = "main" -description = "HTTP/2 framing layer for Python" -name = "hyperframe" -optional = false -python-versions = "*" -version = "5.2.0" - [[package]] category = "main" description = "Internationalized Domain Names in Applications (IDNA)" @@ -331,68 +303,6 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "2.9" -[[package]] -category = "main" -description = "An implementation of JSON Schema validation for Python" -name = "jsonschema" -optional = false -python-versions = "*" -version = "3.2.0" - -[package.dependencies] -attrs = ">=17.4.0" -pyrsistent = ">=0.14.0" -setuptools = "*" -six = ">=1.11.0" - -[package.extras] -format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] -format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] - -[[package]] -category = "main" -description = "A logging replacement for Python" -name = "logbook" -optional = false -python-versions = "*" -version = "1.5.3" - -[package.extras] -all = ["redis", "brotli", "pytest (>4.0)", "execnet (>=1.0.9)", "cython", "pyzmq", "pytest-cov (>=2.6)", "sqlalchemy", "jinja2"] -compression = ["brotli"] -dev = ["pytest-cov (>=2.6)", "pytest (>4.0)", "cython"] -execnet = ["execnet (>=1.0.9)"] -jinja = ["jinja2"] -redis = ["redis"] -sqlalchemy = ["sqlalchemy"] -test = ["pytest-cov (>=2.6)", "pytest (>4.0)"] -zmq = ["pyzmq"] - -[[package]] -category = "main" -description = "A Python Matrix client library, designed according to sans I/O principles." -name = "matrix-nio" -optional = false -python-versions = "*" -version = "0.6" - -[package.dependencies] -attrs = "*" -future = "*" -h11 = "*" -h2 = "*" -jsonschema = "*" -logbook = "*" -pycryptodome = "*" -unpaddedbase64 = "*" - -[package.dependencies.aiohttp] -python = ">=3.6" -version = "*" - -[package.extras] -e2e = ["python-olm (>=3.1.0)", "peewee (>=3.9.5)", "cachetools", "atomicwrites"] - [[package]] category = "main" description = "multidict implementation" @@ -441,14 +351,6 @@ 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 = "pycryptodome" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.7" - [[package]] category = "main" description = "Python binding to the Networking and Cryptography (NaCl) library" @@ -482,17 +384,6 @@ optional = false python-versions = "*" version = "2.1" -[[package]] -category = "main" -description = "Persistent/Functional/Immutable data structures" -name = "pyrsistent" -optional = false -python-versions = "*" -version = "0.16.0" - -[package.dependencies] -six = "*" - [[package]] category = "main" description = "Extensions to the standard Python datetime module" @@ -521,7 +412,7 @@ description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" optional = false python-versions = "*" -version = "12.6.1" +version = "12.7" [package.dependencies] certifi = "*" @@ -548,7 +439,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.4.4" +version = "2020.5.7" [[package]] category = "main" @@ -588,7 +479,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.7.7" +version = "5.8.7" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -614,10 +505,6 @@ version = ">=0.9,<0.10" optional = true version = ">=0.2.0,<0.3.0" -[package.dependencies.matrix-nio] -optional = true -version = ">=0.6,<0.7" - [package.dependencies.psycopg2_binary] optional = true version = ">=2.8.4,<3.0.0" @@ -782,19 +669,11 @@ description = "tzinfo object for the local timezone" name = "tzlocal" optional = false python-versions = "*" -version = "2.0.0" +version = "2.1" [package.dependencies] pytz = "*" -[[package]] -category = "main" -description = "Unpadded Base64" -name = "unpaddedbase64" -optional = false -python-versions = "*" -version = "1.1.0" - [[package]] category = "main" description = "HTTP library with thread-safe connection pooling, file post, and more." @@ -866,10 +745,10 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.3.24" +version = "2020.5.8" [metadata] -content-hash = "c05aace99f49203f824c7f6cdc5ed816fd139935673d8b01c4275eb14f45e590" +content-hash = "d8d544d6f79b7389ef160d65a596fd18e07ab31bd035d1ebfc2cf3dbb9c36a0f" python-versions = "^3.8" [metadata.files] @@ -1019,30 +898,28 @@ future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] gevent = [ - {file = "gevent-20.4.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1ef086264e846371beb5742ebaeb148dc96adf72da2ff350ae5603421cdc2ad9"}, - {file = "gevent-20.4.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:2070c65896f89a85b39f49427d6132f7abd047129fc4da88b3670f0ba13b0cf7"}, - {file = "gevent-20.4.0-cp27-cp27m-win32.whl", hash = "sha256:de6c0cbcb890d0a79323961d3b593a0f2f54dcb9fe38ee5167f2d514e69e3c8c"}, - {file = "gevent-20.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:3b4c4d99f87c0d04b825879c5a91fbfa2b66da7c25b8689e9bdd9f4741d5f80d"}, - {file = "gevent-20.4.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8cca7ffd58559f8d51e5605ad73afcc6f348f9747d2fa539b336e70851b69b79"}, - {file = "gevent-20.4.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:b46399f6c9eccc2e6de1dc1057d362be840443e5439b06cce8b01d114ba1a7ec"}, - {file = "gevent-20.4.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:ee39caf14d66e619709cdfe3962bc68a234518e43ea8c811c0d67a864bc7c196"}, - {file = "gevent-20.4.0-cp35-cp35m-win32.whl", hash = "sha256:8a9aba59a3268f20c7b584119215bdc589cb81500d93dad4dab428eb02f72944"}, - {file = "gevent-20.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:6088bedd8b6bcdb815be322304a5d1c028ffa837d84e93b349928dadac62f354"}, - {file = "gevent-20.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c0b38a654c8fde5b9d9bd27ea3261aeefe36bc9244b170b6d3b11d72a2163bdb"}, - {file = "gevent-20.4.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e7d23d5f32c9db6ae49c4b58585618dcafd6ad0babae251c9c8297afebc4744b"}, - {file = "gevent-20.4.0-cp36-cp36m-win32.whl", hash = "sha256:0b84a8d6f088b29a74402728681c9f11864b95e49f5587a666e6fbf5c683e597"}, - {file = "gevent-20.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b0aea12de542f8fcd6882087bdd5b4d7dc8bb316d28181f6b012dd0b91583285"}, - {file = "gevent-20.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e0990009e7c1624f9a0f3335df1ab8d45678241c852659ac645b70ed8229097c"}, - {file = "gevent-20.4.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:c7a62d51c6dca84f91a91b940037523c926a516f0568f47dc1386bd1682cf4e9"}, - {file = "gevent-20.4.0-cp37-cp37m-win32.whl", hash = "sha256:d56f36eb98532d2bccc51cb0964c31e9fbd9b2282074c297dc9b006b047e2966"}, - {file = "gevent-20.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2fbe0bc43d8c5540153f06eece6235dda14e5f99bdd9183838396313100815d7"}, - {file = "gevent-20.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4572dc7907a0ac3c39b9f0898dbdf390ae3250baaae5f7395661fb844e2e23be"}, - {file = "gevent-20.4.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:956e82a5d0e90f8d71efe4cecccde602cfb657cd866c58bb953c9c30ca1b3d77"}, - {file = "gevent-20.4.0-cp38-cp38-win32.whl", hash = "sha256:38c45d8a3b647f56f8a68769a8ac4953be84a84735c7c7a4d7ca62022bd54036"}, - {file = "gevent-20.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:32813de352918fb652a3db805fd6e08e0a1666a1a9304eef95938c9c426f9573"}, - {file = "gevent-20.4.0-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:42cae3be36b7458f411bd589c66aaba27e4e611ec3d3621e37fd732fe383f9b6"}, - {file = "gevent-20.4.0-pp27-pypy_73-win32.whl", hash = "sha256:cea28f958bc4206ae092043e0775cd7a2bb2536bcbece292732c6484c1076c01"}, - {file = "gevent-20.4.0.tar.gz", hash = "sha256:c516cc5d70c3faf07f271d50930d144339c69fb80f3cac9b687aa964e518535e"}, + {file = "gevent-20.5.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:efd9546468502a30ddd4699c3124ccb9d3099130f9b5ae1e2a54ad5b46e86120"}, + {file = "gevent-20.5.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff477b6d275396123faf8ce2d5b82f96d85ba264e0b9d4b56a2bac49d1b9adc"}, + {file = "gevent-20.5.0-cp27-cp27m-win32.whl", hash = "sha256:92edc18a357473e01a4e4a82c073ed3c99ceca6e3ce93c23668dd4a2401f07dc"}, + {file = "gevent-20.5.0-cp27-cp27m-win_amd64.whl", hash = "sha256:1dd95433be45e1115053878366e3f5332ae99c39cb345be23851327c062b9f4a"}, + {file = "gevent-20.5.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:fcb64f3a28420d1b872b7ef41b12e8a1a4dcadfc8eff3c09993ab0cdf52584a1"}, + {file = "gevent-20.5.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:4d2729dd4bf9c4d0f29482f53cdf9fc90a498aebb5cd7ae8b45d35657437d2ac"}, + {file = "gevent-20.5.0-cp35-cp35m-win32.whl", hash = "sha256:00b03601b8dd1ee2aa07811cb60a4befe36173b15d91c6e207e37f8d77dd6fac"}, + {file = "gevent-20.5.0-cp35-cp35m-win_amd64.whl", hash = "sha256:937d36730f2b0dee3387712074b1f15b802e2e074a3d7c6dcaf70521236d607c"}, + {file = "gevent-20.5.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:929c33df8e9bcbe31906024fcd21580bd018196dbd3249eb5b2f19d63e11092d"}, + {file = "gevent-20.5.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:52e5cd607749ed3b8aa0272cacf2c11deec61fca4c3bec57a9fea8c49316627d"}, + {file = "gevent-20.5.0-cp36-cp36m-win32.whl", hash = "sha256:15eae3cd450dac7dae7f4ac59e01db1378965c9ef565c39c5ae78c5a888f9ac9"}, + {file = "gevent-20.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9b4e940fc6071afebb86ba5f48dbb5f1fc3cb96ebeb8cf145eb5b499e9c6ee33"}, + {file = "gevent-20.5.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:e01d5373528e4ebdde66dc47a608d225fa3c4408ccd828d26c49b7ff75d82bd9"}, + {file = "gevent-20.5.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:31dc5d4ab8172cc00c4ff17cb18edee633babd961f64bf54214244d769bc3a74"}, + {file = "gevent-20.5.0-cp37-cp37m-win32.whl", hash = "sha256:0acc15ba2ac2a555529ad82d5a28fc85dbb6b2ff947657d67bebfd352e2b5c14"}, + {file = "gevent-20.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a7805934e8ce81610b61f806572c3d504cedd698cc8c9460d78d2893ba598c4a"}, + {file = "gevent-20.5.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5c604179cebcc57f10505d8db177b92a715907815a464b066e7eba322d1c33ac"}, + {file = "gevent-20.5.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:88c76df4967c5229f853aa67ad1b394d9e4f985b0359c9bc9879416bba3e7c68"}, + {file = "gevent-20.5.0-cp38-cp38-win32.whl", hash = "sha256:d07a2afe4215731eb57d5b257a2e7e7e170d8a7ae1f02f6d0682cd3403debea9"}, + {file = "gevent-20.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:28b7d83b4327ceb79668eca2049bf4b9ce66d5ace18a88335e3035b573f889fd"}, + {file = "gevent-20.5.0-pp27-pypy_73-win32.whl", hash = "sha256:38db524ea88d81d596b2cbb6948fced26654a15fec40ea4529224e239a6f45e8"}, + {file = "gevent-20.5.0.tar.gz", hash = "sha256:1dc7f1f6bc1f67d625e4272b01e717eba0b4fa024d2ff7934c8d320674d6f7fa"}, ] gevent-eventemitter = [ {file = "gevent-eventemitter-2.1.tar.gz", hash = "sha256:00e6e688c6a255f7bdcef1d8c999e0d02d9ab87d3c6ff626e6dc1a09762107f4"}, @@ -1076,14 +953,6 @@ h11 = [ {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, ] -h2 = [ - {file = "h2-3.2.0-py2.py3-none-any.whl", hash = "sha256:61e0f6601fa709f35cdb730863b4e5ec7ad449792add80d1410d4174ed139af5"}, - {file = "h2-3.2.0.tar.gz", hash = "sha256:875f41ebd6f2c44781259005b157faed1a5031df3ae5aa7bcb4628a6c0782f14"}, -] -hpack = [ - {file = "hpack-3.0.0-py2.py3-none-any.whl", hash = "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89"}, - {file = "hpack-3.0.0.tar.gz", hash = "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"}, -] httptools = [ {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, ] @@ -1091,32 +960,10 @@ humanfriendly = [ {file = "humanfriendly-8.2-py2.py3-none-any.whl", hash = "sha256:e78960b31198511f45fd455534ae7645a6207d33e512d2e842c766d15d9c8080"}, {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, ] -hyperframe = [ - {file = "hyperframe-5.2.0-py2.py3-none-any.whl", hash = "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40"}, - {file = "hyperframe-5.2.0.tar.gz", hash = "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"}, -] idna = [ {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, ] -jsonschema = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, -] -logbook = [ - {file = "Logbook-1.5.3-cp27-cp27m-win32.whl", hash = "sha256:56ee54c11df3377314cedcd6507638f015b4b88c0238c2e01b5eb44fd3a6ad1b"}, - {file = "Logbook-1.5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:2dc85f1510533fddb481e97677bb7bca913560862734c0b3b289bfed04f78c92"}, - {file = "Logbook-1.5.3-cp35-cp35m-win32.whl", hash = "sha256:94e2e11ff3c2304b0d09a36c6208e5ae756eb948b210e5cbd63cd8d27f911542"}, - {file = "Logbook-1.5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:97fee1bd9605f76335b169430ed65e15e457a844b2121bd1d90a08cf7e30aba0"}, - {file = "Logbook-1.5.3-cp36-cp36m-win32.whl", hash = "sha256:7c533eb728b3d220b1b5414ba4635292d149d79f74f6973b4aa744c850ca944a"}, - {file = "Logbook-1.5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:e18f7422214b1cf0240c56f884fd9c9b4ff9d0da2eabca9abccba56df7222f66"}, - {file = "Logbook-1.5.3-cp37-cp37m-win32.whl", hash = "sha256:8f76a2e7b1f72595f753228732f81ce342caf03babc3fed6bbdcf366f2f20f18"}, - {file = "Logbook-1.5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0cf2cdbfb65a03b5987d19109dacad13417809dcf697f66e1a7084fb21744ea9"}, - {file = "Logbook-1.5.3.tar.gz", hash = "sha256:66f454ada0f56eae43066f604a222b09893f98c1adc18df169710761b8f32fe8"}, -] -matrix-nio = [ - {file = "matrix-nio-0.6.tar.gz", hash = "sha256:25a4ac9d5e1435035f5c5b6e9a6b453ac66ade25cb455ba6bbe9cc3ae1e0ef50"}, -] multidict = [ {file = "multidict-4.7.5-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"}, {file = "multidict-4.7.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35"}, @@ -1197,38 +1044,6 @@ pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] -pycryptodome = [ - {file = "pycryptodome-3.9.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:0e10f352ccbbcb5bb2dc4ecaf106564e65702a717d72ab260f9ac4c19753cfc2"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9c739b7795ccf2ef1fdad8d44e539a39ad300ee6786e804ea7f0c6a786eb5343"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9977086e0f93adb326379897437373871b80501e1d176fec63c7f46fb300c862"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-win32.whl", hash = "sha256:83295a3fb5cf50c48631eb5b440cb5e9832d8c14d81d1d45f4497b67a9987de8"}, - {file = "pycryptodome-3.9.7-cp27-cp27m-win_amd64.whl", hash = "sha256:b1e332587b3b195542e77681389c296e1837ca01240399d88803a075447d3557"}, - {file = "pycryptodome-3.9.7-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9378c309aec1f8cd8bad361ed0816a440151b97a2a3f6ffdaba1d1a1fb76873a"}, - {file = "pycryptodome-3.9.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4f94368ce2d65873a87ad867eb3bf63f4ba81eb97a9ee66d38c2b71ce5a7439"}, - {file = "pycryptodome-3.9.7-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:f655addaaaa9974108d4808f4150652589cada96074c87115c52e575bfcd87d5"}, - {file = "pycryptodome-3.9.7-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:9a94fca11fdc161460bd8659c15b6adef45c1b20da86402256eaf3addfaab324"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ea83bcd9d6c03248ebd46e71ac313858e0afd5aa2fa81478c0e653242f3eb476"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:07024fc364869eae8d6ac0d316e089956e6aeffe42dbdcf44fe1320d96becf7f"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:426c188c83c10df71f053e04b4003b1437bae5cb37606440e498b00f160d71d0"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-win32.whl", hash = "sha256:d61b012baa8c2b659e9890011358455c0019a4108536b811602d2f638c40802a"}, - {file = "pycryptodome-3.9.7-cp35-cp35m-win_amd64.whl", hash = "sha256:1f4752186298caf2e9ff5354f2e694d607ca7342aa313a62005235d46e28cf04"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:767ad0fb5d23efc36a4d5c2fc608ac603f3de028909bcf59abc943e0d0bc5a36"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:2fbc472e0b567318fe2052281d5a8c0ae70099b446679815f655e9fbc18c3a65"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:9230fcb5d948c3fb40049bace4d33c5d254f8232c2c0bba05d2570aea3ba4520"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-win32.whl", hash = "sha256:8f06556a8f7ea7b1e42eff39726bb0dca1c251205debae64e6eebea3cd7b438a"}, - {file = "pycryptodome-3.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:d6e1bc5c94873bec742afe2dfadce0d20445b18e75c47afc0c115b19e5dd38dd"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:3ec3dc2f80f71fd0c955ce48b81bfaf8914c6f63a41a738f28885a1c4892968a"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cff31f5a8977534f255f729d5d2467526f2b10563a30bbdade92223e0bf264bd"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ed5761b37615a1f222c5345bbf45272ae2cf8c7dff88a4f53a1e9f977cbb6d95"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-win32.whl", hash = "sha256:f011cd0062e54658b7086a76f8cf0f4222812acc66e219e196ea2d0a8849d0ed"}, - {file = "pycryptodome-3.9.7-cp37-cp37m-win_amd64.whl", hash = "sha256:626c0a1d4d83ec6303f970a17158114f75c3ba1736f7f2983f7b40a265861bd8"}, - {file = "pycryptodome-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be56bde3312e022d9d1d6afa124556460ad5c844c2fc63642f6af723c098d35"}, - {file = "pycryptodome-3.9.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c818dc1f3eace93ee50c2b6b5c2becf7c418fa5dd1ba6fc0ef7db279ea21d5e4"}, - {file = "pycryptodome-3.9.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:09b6d6bcc01a4eb1a2b4deeff5aa602a108ec5aed8ac75ae554f97d1d7f0a5ad"}, - {file = "pycryptodome-3.9.7-cp38-cp38-win32.whl", hash = "sha256:7ac729d9091ed5478af2b4a4f44f5335a98febbc008af619e4569a59fe503e40"}, - {file = "pycryptodome-3.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:c109a26a21f21f695d369ff9b87f5d43e0d6c768d8384e10bc74142bed2e092e"}, - {file = "pycryptodome-3.9.7.tar.gz", hash = "sha256:f1add21b6d179179b3c177c33d18a2186a09cc0d3af41ff5ed3f377360b869f2"}, -] pynacl = [ {file = "PyNaCl-1.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621"}, {file = "PyNaCl-1.3.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39"}, @@ -1261,9 +1076,6 @@ pyreadline = [ {file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"}, {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, ] -pyrsistent = [ - {file = "pyrsistent-0.16.0.tar.gz", hash = "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"}, -] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, @@ -1272,35 +1084,35 @@ python-multipart = [ {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, ] python-telegram-bot = [ - {file = "python-telegram-bot-12.6.1.tar.gz", hash = "sha256:935397390910291c8e41d7f2a06a3bb13d1d74d78b59562be9f8a330d4527049"}, - {file = "python_telegram_bot-12.6.1-py2.py3-none-any.whl", hash = "sha256:c7bdb5788ad2edea5c5c1bc8e50967fad68aa35245c209baadf74fc8ad00ff06"}, + {file = "python-telegram-bot-12.7.tar.gz", hash = "sha256:218b0583afb8baeefe6f2f1ddd8f1bb1ae30f0af3ce9160a372abd2cdf258eef"}, + {file = "python_telegram_bot-12.7-py2.py3-none-any.whl", hash = "sha256:6878cc642114c8c116ceada41639a9df487f42d5478d9f34cae513cc5c260dee"}, ] pytz = [ {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, ] regex = [ - {file = "regex-2020.4.4-cp27-cp27m-win32.whl", hash = "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f"}, - {file = "regex-2020.4.4-cp27-cp27m-win_amd64.whl", hash = "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1"}, - {file = "regex-2020.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b"}, - {file = "regex-2020.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db"}, - {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156"}, - {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3"}, - {file = "regex-2020.4.4-cp36-cp36m-win32.whl", hash = "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8"}, - {file = "regex-2020.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a"}, - {file = "regex-2020.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468"}, - {file = "regex-2020.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6"}, - {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd"}, - {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948"}, - {file = "regex-2020.4.4-cp37-cp37m-win32.whl", hash = "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e"}, - {file = "regex-2020.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a"}, - {file = "regex-2020.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e"}, - {file = "regex-2020.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683"}, - {file = "regex-2020.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b"}, - {file = "regex-2020.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89"}, - {file = "regex-2020.4.4-cp38-cp38-win32.whl", hash = "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3"}, - {file = "regex-2020.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3"}, - {file = "regex-2020.4.4.tar.gz", hash = "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142"}, + {file = "regex-2020.5.7-cp27-cp27m-win32.whl", hash = "sha256:5493a02c1882d2acaaf17be81a3b65408ff541c922bfd002535c5f148aa29f74"}, + {file = "regex-2020.5.7-cp27-cp27m-win_amd64.whl", hash = "sha256:021a0ae4d2baeeb60a3014805a2096cb329bd6d9f30669b7ad0da51a9cb73349"}, + {file = "regex-2020.5.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4df91094ced6f53e71f695c909d9bad1cca8761d96fd9f23db12245b5521136e"}, + {file = "regex-2020.5.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7ce4a213a96d6c25eeae2f7d60d4dad89ac2b8134ec3e69db9bc522e2c0f9388"}, + {file = "regex-2020.5.7-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b059e2476b327b9794c792c855aa05531a3f3044737e455d283c7539bd7534d"}, + {file = "regex-2020.5.7-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:652ab4836cd5531d64a34403c00ada4077bb91112e8bcdae933e2eae232cf4a8"}, + {file = "regex-2020.5.7-cp36-cp36m-win32.whl", hash = "sha256:1e2255ae938a36e9bd7db3b93618796d90c07e5f64dd6a6750c55f51f8b76918"}, + {file = "regex-2020.5.7-cp36-cp36m-win_amd64.whl", hash = "sha256:8127ca2bf9539d6a64d03686fd9e789e8c194fc19af49b69b081f8c7e6ecb1bc"}, + {file = "regex-2020.5.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f7f2f4226db6acd1da228adf433c5c3792858474e49d80668ea82ac87cf74a03"}, + {file = "regex-2020.5.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2bc6a17a7fa8afd33c02d51b6f417fc271538990297167f68a98cae1c9e5c945"}, + {file = "regex-2020.5.7-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:b7c9f65524ff06bf70c945cd8d8d1fd90853e27ccf86026af2afb4d9a63d06b1"}, + {file = "regex-2020.5.7-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:fa09da4af4e5b15c0e8b4986a083f3fd159302ea115a6cc0649cd163435538b8"}, + {file = "regex-2020.5.7-cp37-cp37m-win32.whl", hash = "sha256:669a8d46764a09f198f2e91fc0d5acdac8e6b620376757a04682846ae28879c4"}, + {file = "regex-2020.5.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b5b5b2e95f761a88d4c93691716ce01dc55f288a153face1654f868a8034f494"}, + {file = "regex-2020.5.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0ff50843535593ee93acab662663cb2f52af8e31c3f525f630f1dc6156247938"}, + {file = "regex-2020.5.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:1b17bf37c2aefc4cac8436971fe6ee52542ae4225cfc7762017f7e97a63ca998"}, + {file = "regex-2020.5.7-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:04d6e948ef34d3eac133bedc0098364a9e635a7914f050edb61272d2ddae3608"}, + {file = "regex-2020.5.7-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5b741ecc3ad3e463d2ba32dce512b412c319993c1bb3d999be49e6092a769fb2"}, + {file = "regex-2020.5.7-cp38-cp38-win32.whl", hash = "sha256:099568b372bda492be09c4f291b398475587d49937c659824f891182df728cdf"}, + {file = "regex-2020.5.7-cp38-cp38-win_amd64.whl", hash = "sha256:3ab5e41c4ed7cd4fa426c50add2892eb0f04ae4e73162155cd668257d02259dd"}, + {file = "regex-2020.5.7.tar.gz", hash = "sha256:73a10404867b835f1b8a64253e4621908f0d71150eb4e97ab2e7e441b53e9451"}, ] requests = [ {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, @@ -1311,8 +1123,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.7.7-py3-none-any.whl", hash = "sha256:e426c5fa21ee81deccd5ba35a17bd110d9de8382713b09851647fa71f3f9e3fa"}, - {file = "royalnet-5.7.7.tar.gz", hash = "sha256:6c7724296df890ea61f9f9f46efa4270e857dbe84a76521675fec7a163321bf5"}, + {file = "royalnet-5.8.7-py3-none-any.whl", hash = "sha256:5fee088e02ec375b580af48e03894db2ca2edd10c19f7fcbfdacf0a6e07622e7"}, + {file = "royalnet-5.8.7.tar.gz", hash = "sha256:a72fd52e2ed9fa2a8163859ac93b517ec684348d44f5c0b09146c9880430f67b"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1369,12 +1181,8 @@ tornado = [ {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, ] tzlocal = [ - {file = "tzlocal-2.0.0-py2.py3-none-any.whl", hash = "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048"}, - {file = "tzlocal-2.0.0.tar.gz", hash = "sha256:949b9dd5ba4be17190a80c0268167d7e6c92c62b30026cf9764caf3e308e5590"}, -] -unpaddedbase64 = [ - {file = "unpaddedbase64-1.1.0-py2-none-any.whl", hash = "sha256:8917367e4e915b7dce1a72a99db8798c9f3d0d9a74cdd9aafac6d7c65ca495c5"}, - {file = "unpaddedbase64-1.1.0-py2.py3-none-any.whl", hash = "sha256:81cb4eaaa28cc6a282dd3f2c3855eaa1fbaafa736b5ee64df69889e20540a339"}, + {file = "tzlocal-2.1-py2.py3-none-any.whl", hash = "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4"}, + {file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"}, ] urllib3 = [ {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, @@ -1443,6 +1251,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.3.24-py2.py3-none-any.whl", hash = "sha256:c0be39ea9bca72fa02a0d2d043c5e9bd8ea8e0fe79705e891161d6fcd29da59e"}, - {file = "youtube_dl-2020.3.24.tar.gz", hash = "sha256:4b03efe439f7cae26eba909821d1df00a9a4eb82741cb2e8b78fe29702bd4633"}, + {file = "youtube_dl-2020.5.8-py2.py3-none-any.whl", hash = "sha256:0b5d3280522469968eb62eecb1f966f422b2be22f000a801bf87cb2172d8ea39"}, + {file = "youtube_dl-2020.5.8.tar.gz", hash = "sha256:22da6788b55b7b267c6d59bcdfaf10e67a9ac980976d50d29a670473ad2a05bb"}, ] diff --git a/pyproject.toml b/pyproject.toml index d3ba049b..31195f6f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.7.15" + version = "5.8.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "^0.9.1" [tool.poetry.dependencies.royalnet] - version = "~5.7.7" + version = "~5.8.7" # Maybe... there is a way to make these selectable? extras = [ "telegram", @@ -36,7 +36,6 @@ "sentry", "herald", "coloredlogs", - "matrix" ] # Development dependencies diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index 714b9c01..8c8601f1 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -1,14 +1,15 @@ +from typing import * + import asyncio import logging -import sentry_sdk import aiohttp -from typing import * from royalnet.commands import * from royalnet.utils import * from royalnet.serf.telegram.escape import escape as tg_escape +from sqlalchemy import or_, and_ + from ..tables import Steam, Brawlhalla, BrawlhallaDuo from ..types import BrawlhallaRank, BrawlhallaMetal, BrawlhallaTier -from sqlalchemy import or_, and_ log = logging.getLogger(__name__) diff --git a/royalpack/commands/ciaoruozi.py b/royalpack/commands/ciaoruozi.py index 9afc2b65..727b7cca 100644 --- a/royalpack/commands/ciaoruozi.py +++ b/royalpack/commands/ciaoruozi.py @@ -1,3 +1,4 @@ +from typing import * import telegram from royalnet.commands import * diff --git a/royalpack/commands/color.py b/royalpack/commands/color.py index a7432f45..d419f15a 100644 --- a/royalpack/commands/color.py +++ b/royalpack/commands/color.py @@ -1,3 +1,4 @@ +from typing import * from royalnet.commands import * diff --git a/royalpack/commands/cvstats.py b/royalpack/commands/cvstats.py index 68e2239d..eed97d70 100644 --- a/royalpack/commands/cvstats.py +++ b/royalpack/commands/cvstats.py @@ -3,7 +3,8 @@ import logging import asyncio import datetime import royalnet.commands as rc -from royalnet.utils import asyncify +import royalnet.utils as ru + from ..tables import Cvstats @@ -101,7 +102,7 @@ class CvstatsCommand(rc.Command): log.debug("Saving to database...") db_session.add(cvstats) - await asyncify(db_session.commit) + await ru.asyncify(db_session.commit) log.debug("Done!") async def _updater(self, period: int): diff --git a/royalpack/commands/diario.py b/royalpack/commands/diario.py index 94b76e52..1221e2b9 100644 --- a/royalpack/commands/diario.py +++ b/royalpack/commands/diario.py @@ -1,11 +1,12 @@ +from typing import * import re import datetime import telegram import aiohttp -from typing import * -from royalnet.commands import * -from royalnet.utils import asyncify -from royalnet.backpack.tables import * +import royalnet.commands as rc +import royalnet.utils as ru +import royalnet.backpack.tables as rbt + from ..tables import * @@ -13,7 +14,7 @@ async def to_imgur(imgur_api_key, photosizes: List[telegram.PhotoSize], caption= # Select the largest photo largest_photo = sorted(photosizes, key=lambda p: p.width * p.height)[-1] # Get the photo url - photo_file: telegram.File = await asyncify(largest_photo.get_file) + photo_file: telegram.File = await ru.asyncify(largest_photo.get_file) # Forward the url to imgur, as an upload async with aiohttp.request("post", "https://api.imgur.com/3/upload", data={ "image": photo_file.file_path, @@ -25,18 +26,18 @@ async def to_imgur(imgur_api_key, photosizes: List[telegram.PhotoSize], caption= }) as request: response = await request.json() if not response["success"]: - raise CommandError("Imgur returned an error in the image upload.") + raise rc.CommandError("Imgur returned an error in the image upload.") return response["data"]["link"] -class DiarioCommand(Command): +class DiarioCommand(rc.Command): name: str = "diario" description: str = "Aggiungi una citazione al Diario." syntax = "[!] \"{testo}\" --[autore], [contesto]" - async def run(self, args: CommandArgs, data: CommandData) -> None: + 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 @@ -70,11 +71,11 @@ class DiarioCommand(Command): media_url = None # Ensure there is a text or an image if not (text or media_url): - raise InvalidInputError("Il messaggio a cui hai risposto non contiene testo o immagini.") + 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 asyncify(data.session.query(self.alchemy.get(Telegram)) - .filter_by(tg_id=reply.from_user.id) - .one_or_none) + 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 @@ -121,9 +122,9 @@ class DiarioCommand(Command): context = None # Find if there's a Royalnet account associated with the quoted name if quoted is not None: - quoted_alias = await asyncify( - data.session.query(self.alchemy.get(Alias)) - .filter_by(alias=quoted.lower()).one_or_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 @@ -136,7 +137,7 @@ class DiarioCommand(Command): context = None # Ensure there is a text or an image if not (text or media_url): - raise InvalidInputError("Manca il testo o l'immagine da inserire nel diario.") + 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, @@ -147,7 +148,7 @@ class DiarioCommand(Command): media_url=media_url, spoiler=spoiler) data.session.add(diario) - await asyncify(data.session.commit) + await ru.asyncify(data.session.commit) await data.reply(f"✅ {str(diario)}") else: # Find the creator of the quotes @@ -172,7 +173,7 @@ class DiarioCommand(Command): timestamp = datetime.datetime.now() # Ensure there is some text if not text: - raise InvalidInputError("Manca il testo o l'immagine da inserire nel diario.") + raise rc.InvalidInputError("Manca il testo o l'immagine da inserire nel diario.") # Or a quoted if not quoted: quoted = None @@ -180,17 +181,17 @@ class DiarioCommand(Command): context = None # Find if there's a Royalnet account associated with the quoted name if quoted is not None: - quoted_alias = await asyncify( - data.session.query(self.alchemy.get(Alias)) - .filter_by(alias=quoted.lower()) - .one_or_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 UserError("Il nome dell'autore è ambiguo, quindi la riga non è stata aggiunta.\n" - "Per piacere, ripeti il comando con un nome più specifico!") + 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, @@ -201,5 +202,5 @@ class DiarioCommand(Command): media_url=None, spoiler=spoiler) data.session.add(diario) - await asyncify(data.session.commit) + await ru.asyncify(data.session.commit) await data.reply(f"✅ {str(diario)}") diff --git a/royalpack/commands/diarioquote.py b/royalpack/commands/diarioquote.py index c9be589d..4b35f725 100644 --- a/royalpack/commands/diarioquote.py +++ b/royalpack/commands/diarioquote.py @@ -1,9 +1,11 @@ -from royalnet.commands import * -from royalnet.utils import * +from typing import * +import royalnet.commands as rc +import royalnet.utils as ru + from ..tables import Diario -class DiarioquoteCommand(Command): +class DiarioquoteCommand(rc.Command): name: str = "diarioquote" description: str = "Cita una riga del diario." @@ -12,12 +14,12 @@ class DiarioquoteCommand(Command): syntax = "{id}" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: try: entry_id = int(args[0].lstrip("#")) except ValueError: - raise CommandError("L'id che hai specificato non è valido.") - entry: Diario = await asyncify(data.session.query(self.alchemy.get(Diario)).get, entry_id) + 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) if entry is None: - raise CommandError("Nessuna riga con quell'id trovata.") + 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 8baa7a37..8468a954 100644 --- a/royalpack/commands/diarioshuffle.py +++ b/royalpack/commands/diarioshuffle.py @@ -1,11 +1,12 @@ from typing import * -from royalnet.commands import * -from royalnet.utils import * -from ..tables import Diario +import royalnet.commands as rc +import royalnet.utils as ru from sqlalchemy import func +from ..tables import Diario -class DiarioshuffleCommand(Command): + +class DiarioshuffleCommand(rc.Command): name: str = "diarioshuffle" description: str = "Cita una riga casuale del diario." @@ -14,9 +15,9 @@ class DiarioshuffleCommand(Command): syntax = "" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: DiarioT = self.alchemy.get(Diario) - entry: List[Diario] = await asyncify( + entry: List[Diario] = await ru.asyncify( data.session .query(DiarioT) .order_by(func.random()) @@ -24,5 +25,5 @@ class DiarioshuffleCommand(Command): .one_or_none ) if entry is None: - raise CommandError("Nessuna riga del diario trovata.") + raise rc.CommandError("Nessuna riga del diario trovata.") await data.reply(f"ℹ️ {entry}") diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index e1f3c7dc..085fe900 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -1,18 +1,19 @@ +from typing import * import asyncio import logging import sentry_sdk import aiohttp -from typing import * -from royalnet.commands import * -from royalnet.utils import * -from royalnet.serf.telegram.escape import escape as tg_escape +import royalnet.commands as rc +import royalnet.utils as ru +import royalnet.serf.telegram as rst + from ..tables import Steam, Dota from ..types import DotaRank log = logging.getLogger(__name__) -class DotaCommand(Command): +class DotaCommand(rc.Command): name: str = "dota" aliases = ["dota2", "doto", "doto2", "dotka", "dotka2"] @@ -21,7 +22,7 @@ class DotaCommand(Command): syntax: str = "" - def __init__(self, interface: CommandInterface): + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) if self.interface.name == "telegram" and self.config["Dota"]["updater"]: self.loop.create_task(self._updater(7200)) @@ -30,7 +31,7 @@ class DotaCommand(Command): client = self.serf.client await self.serf.api_call(client.send_message, chat_id=self.config["Telegram"]["main_group_id"], - text=tg_escape(message), + text=rst.escape(message), parse_mode="HTML", disable_webpage_preview=True) @@ -85,7 +86,7 @@ class DotaCommand(Command): # Get profile data async with session.get(f"https://api.opendota.com/api/players/{steam.steamid.as_32}/") as response: if response.status != 200: - raise ExternalError(f"OpenDota / returned {response.status}!") + raise rc.ExternalError(f"OpenDota / returned {response.status}!") p = await response.json() # No such user if "profile" not in p: @@ -94,7 +95,7 @@ class DotaCommand(Command): # Get win/loss data async with session.get(f"https://api.opendota.com/api/players/{steam.steamid.as_32}/wl") as response: if response.status != 200: - raise ExternalError(f"OpenDota /wl returned {response.status}!") + raise rc.ExternalError(f"OpenDota /wl returned {response.status}!") wl = await response.json() # No such user if wl["win"] == 0 and wl["lose"] == 0: @@ -127,12 +128,12 @@ class DotaCommand(Command): sentry_sdk.capture_exception(e) log.error(f"Error while updating {steam.user.username}: {e}") await asyncio.sleep(1) - await asyncify(session.commit) + await ru.asyncify(session.commit) session.close() log.info(f"Sleeping for {period}s") await asyncio.sleep(period) - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: author = await data.get_author(error_if_none=True) found_something = False @@ -146,5 +147,5 @@ class DotaCommand(Command): message += self._display(steam.dota) message += "\n" if not found_something: - raise UserError("Nessun account di Dota 2 trovato.") + raise rc.UserError("Nessun account di Dota 2 trovato.") await data.reply(message) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index de695d21..03c249d5 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -165,7 +165,10 @@ class EatCommand(Command): "mia sul fiume": "💧 Hai mangiato il miglior piatto al mondo, la {food}, esclusivo ai membri Royal Games.\n" "[i]Nessuno, tranne il bot, sa di cosa è fatta esattamente, ma una cosa è certa: è " "buonissima![/i]", - "angelo": "👼 Oh mio dio! E' un {food}!\n[i]Ora hai un digramma ad onda blu.[/i]" + "angelo": "👼 Oh mio dio! E' un {food}!\n[i]Ora hai un digramma ad onda blu.[/i]", + + "terraria": "🌳 Hai provato a mangiare {food}, ma non ne sei stato all'Altezza (Coniglio).\n[i]Prova a mangiare qualcos'altro...[/i]", + "cooked fish": "🐟 Hai mangiato {food}.\n[i]Ora sei Well Fed per 20 minuti.[/i]" } async def run(self, args: CommandArgs, data: CommandData) -> None: diff --git a/royalpack/commands/elevatormusic.py b/royalpack/commands/elevatormusic.py index 5041de2d..52929e46 100644 --- a/royalpack/commands/elevatormusic.py +++ b/royalpack/commands/elevatormusic.py @@ -1,5 +1,7 @@ +from typing import * import random import royalnet.commands as rc + from .play import PlayCommand diff --git a/royalpack/commands/emojify.py b/royalpack/commands/emojify.py index 5aa9a2d6..4afe4ad7 100644 --- a/royalpack/commands/emojify.py +++ b/royalpack/commands/emojify.py @@ -1,8 +1,9 @@ +from typing import * import random -from royalnet.commands import * +import royalnet.commands as rc -class EmojifyCommand(Command): +class EmojifyCommand(rc.Command): name: str = "emojify" description: str = "Converti un messaggio in emoji." @@ -94,6 +95,6 @@ class EmojifyCommand(Command): new_string = new_string.replace(key, selected_emoji) return new_string - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: string = args.joined(require_at_least=1) await data.reply(self._emojify(string)) diff --git a/royalpack/commands/eval.py b/royalpack/commands/eval.py index dfd6a481..21de0da0 100644 --- a/royalpack/commands/eval.py +++ b/royalpack/commands/eval.py @@ -1,9 +1,9 @@ -import royalnet -from royalnet.commands import * -from royalnet.backpack.tables import * +from typing import * +import royalnet.commands as rc +import royalnet.backpack.tables as rbt -class EvalCommand(Command): +class EvalCommand(rc.Command): # oh god if there is a security vulnerability name: str = "eval" @@ -11,13 +11,13 @@ class EvalCommand(Command): syntax: str = "{espressione}" - async def run(self, args: CommandArgs, data: CommandData) -> None: - user: User = await data.get_author(error_if_none=True) - if user.role != "Admin": - raise CommandError("Non sei autorizzato a eseguire codice arbitrario!\n" + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + 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?)") try: result = eval(args.joined(require_at_least=1)) except Exception as e: - raise CommandError(f"Eval fallito: {e}") + raise rc.CommandError(f"Eval fallito: {e}") await data.reply(repr(result)) diff --git a/royalpack/commands/exec.py b/royalpack/commands/exec.py index 9823da51..65c3b013 100644 --- a/royalpack/commands/exec.py +++ b/royalpack/commands/exec.py @@ -1,9 +1,9 @@ -import royalnet -from royalnet.commands import * -from royalnet.backpack.tables import * +from typing import * +import royalnet.commands as rc +import royalnet.backpack.tables as rbt -class ExecCommand(Command): +class ExecCommand(rc.Command): # oh god if there is a security vulnerability name: str = "exec" @@ -11,13 +11,13 @@ class ExecCommand(Command): syntax: str = "{script}" - async def run(self, args: CommandArgs, data: CommandData) -> None: - user: User = await data.get_author(error_if_none=True) - if user.role != "Admin": - raise CommandError("Non sei autorizzato a eseguire codice arbitrario!\n" + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + 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?)") try: exec(args.joined(require_at_least=1)) except Exception as e: - raise CommandError(f"Esecuzione fallita: {e}") + raise rc.CommandError(f"Esecuzione fallita: {e}") await data.reply(f"✅ Fatto!") diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index 8b2364a2..644801c0 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -1,7 +1,9 @@ -from .play import PlayCommand -from royalnet.commands import * +from typing import * import aiohttp import urllib.parse +import royalnet.commands as rc + +from .play import PlayCommand class FunkwhaleCommand(PlayCommand): @@ -23,5 +25,5 @@ class FunkwhaleCommand(PlayCommand): f"/api/v1/search?query={search}") as response: j = await response.json() if len(j["tracks"]) < 1: - raise UserError("Nessun file audio trovato con il nome richiesto.") + raise rc.UserError("Nessun file audio trovato con il nome richiesto.") return [f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}'] diff --git a/royalpack/commands/funkwhalealbum.py b/royalpack/commands/funkwhalealbum.py index 4965b2ce..dacfa1f0 100644 --- a/royalpack/commands/funkwhalealbum.py +++ b/royalpack/commands/funkwhalealbum.py @@ -1,7 +1,9 @@ -from .play import PlayCommand -from royalnet.commands import * +from typing import * import aiohttp import urllib.parse +import royalnet.commands as rc + +from .play import PlayCommand class FunkwhalealbumCommand(PlayCommand): @@ -23,6 +25,6 @@ class FunkwhalealbumCommand(PlayCommand): f"/api/v1/search?query={search}") as response: j = await response.json() if len(j["albums"]) < 1: - raise UserError("Nessun file audio trovato con il nome richiesto.") + raise rc.UserError("Nessun file audio trovato con il nome richiesto.") album = j["albums"][0] return [f'{self.config["Funkwhale"]["instance_url"]}{track["listen_url"]}' for track in album["tracks"]] diff --git a/royalpack/commands/funkwhaleplaylist.py b/royalpack/commands/funkwhaleplaylist.py index 8c9736bb..d1c77045 100644 --- a/royalpack/commands/funkwhaleplaylist.py +++ b/royalpack/commands/funkwhaleplaylist.py @@ -1,7 +1,9 @@ -from .play import PlayCommand -from royalnet.commands import * +from typing import * import aiohttp import urllib.parse +import royalnet.commands as rc + +from .play import PlayCommand class FunkwhaleplaylistCommand(PlayCommand): @@ -23,7 +25,7 @@ class FunkwhaleplaylistCommand(PlayCommand): f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: j = await response.json() if len(j["results"]) < 1: - raise UserError("Nessuna playlist trovata con il nome richiesto.") + raise rc.UserError("Nessuna playlist trovata con il nome richiesto.") playlist = j["results"][0] playlist_id = playlist["id"] async with session.get(self.config["Funkwhale"]["instance_url"] + diff --git a/royalpack/commands/googlevideo.py b/royalpack/commands/googlevideo.py index 27062794..3ec38790 100644 --- a/royalpack/commands/googlevideo.py +++ b/royalpack/commands/googlevideo.py @@ -1,3 +1,4 @@ +from typing import * from .play import PlayCommand diff --git a/royalpack/commands/lazyfunkwhale.py b/royalpack/commands/lazyfunkwhale.py index 3b6d839e..6edc9b09 100644 --- a/royalpack/commands/lazyfunkwhale.py +++ b/royalpack/commands/lazyfunkwhale.py @@ -1,8 +1,10 @@ -from .lazyplay import LazyplayCommand -from royalnet.commands import * +from typing import * +import royalnet.commands as rc import aiohttp import urllib.parse +from .lazyplay import LazyplayCommand + class LazyfunkwhaleCommand(LazyplayCommand): name: str = "lazyfunkwhale" @@ -23,5 +25,5 @@ class LazyfunkwhaleCommand(LazyplayCommand): f"/api/v1/search?query={search}") as response: j = await response.json() if len(j["tracks"]) < 1: - raise UserError("Nessun file audio trovato con il nome richiesto.") + raise rc.UserError("Nessun file audio trovato con il nome richiesto.") return [f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}'] diff --git a/royalpack/commands/lazyfunkwhalealbum.py b/royalpack/commands/lazyfunkwhalealbum.py index 5de6d935..bf807f2f 100644 --- a/royalpack/commands/lazyfunkwhalealbum.py +++ b/royalpack/commands/lazyfunkwhalealbum.py @@ -1,8 +1,10 @@ -from .lazyplay import LazyplayCommand -from royalnet.commands import * +from typing import * +import royalnet.commands as rc import aiohttp import urllib.parse +from .lazyplay import LazyplayCommand + class LazyfunkwhalealbumCommand(LazyplayCommand): name: str = "lazyfunkwhalealbum" @@ -23,6 +25,6 @@ class LazyfunkwhalealbumCommand(LazyplayCommand): f"/api/v1/search?query={search}") as response: j = await response.json() if len(j["albums"]) < 1: - raise UserError("Nessun file audio trovato con il nome richiesto.") + raise rc.UserError("Nessun file audio trovato con il nome richiesto.") album = j["albums"][0] return [f'{self.config["Funkwhale"]["instance_url"]}{track["listen_url"]}' for track in album["tracks"]] diff --git a/royalpack/commands/lazyfunkwhaleplaylist.py b/royalpack/commands/lazyfunkwhaleplaylist.py index 8d6bf0e0..1fb2bcf6 100644 --- a/royalpack/commands/lazyfunkwhaleplaylist.py +++ b/royalpack/commands/lazyfunkwhaleplaylist.py @@ -1,7 +1,7 @@ -from .lazyplay import LazyplayCommand -from royalnet.commands import * import aiohttp import urllib.parse +import royalnet.commands as rc +from .lazyplay import LazyplayCommand class LazyfunkwhaleplaylistCommand(LazyplayCommand): @@ -23,7 +23,7 @@ class LazyfunkwhaleplaylistCommand(LazyplayCommand): f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: j = await response.json() if len(j["results"]) < 1: - raise UserError("Nessuna playlist trovata con il nome richiesto.") + raise rc.UserError("Nessuna playlist trovata con il nome richiesto.") playlist = j["results"][0] playlist_id = playlist["id"] async with session.get(self.config["Funkwhale"]["instance_url"] + diff --git a/royalpack/commands/lazygooglevideo.py b/royalpack/commands/lazygooglevideo.py index 24ae7183..e8bba83a 100644 --- a/royalpack/commands/lazygooglevideo.py +++ b/royalpack/commands/lazygooglevideo.py @@ -1,3 +1,4 @@ +from typing import * from .lazyplay import LazyplayCommand diff --git a/royalpack/commands/lazypeertube.py b/royalpack/commands/lazypeertube.py index f3668a04..691ce58c 100644 --- a/royalpack/commands/lazypeertube.py +++ b/royalpack/commands/lazypeertube.py @@ -1,8 +1,10 @@ -from .lazyplay import LazyplayCommand -from royalnet.commands import * +from typing import * +import royalnet.commands as rc import aiohttp import urllib.parse +from .lazyplay import LazyplayCommand + class LazypeertubeCommand(LazyplayCommand): name: str = "lazypeertube" @@ -20,5 +22,5 @@ class LazypeertubeCommand(LazyplayCommand): f"/api/v1/search/videos?search={search}") as response: j = await response.json() if j["total"] < 1: - raise InvalidInputError("Nessun video trovato.") + raise rc.InvalidInputError("Nessun video trovato.") return [f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}'] diff --git a/royalpack/commands/lazyplay.py b/royalpack/commands/lazyplay.py index 795c4d5e..2ee9b7f4 100644 --- a/royalpack/commands/lazyplay.py +++ b/royalpack/commands/lazyplay.py @@ -1,11 +1,11 @@ +from typing import * import discord import asyncio as aio -from typing import * -from royalnet.commands import * -from royalnet.backpack.tables import User, Discord +import royalnet.commands as rc +import royalnet.backpack.tables as rbt -class LazyplayCommand(Command): +class LazyplayCommand(rc.Command): name: str = "lazyplay" aliases = ["lp"] @@ -15,17 +15,17 @@ class LazyplayCommand(Command): syntax = "{url}" - async def get_urls(self, args: CommandArgs): + async def get_urls(self, args: rc.CommandArgs): url = args.joined(require_at_least=1) if not (url.startswith("http://") or url.startswith("https://")): - raise InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" + raise rc.InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" f" ([c]http://[/c] o [c]https://[/c]).") return [url] def get_embed_color(self) -> Optional[int]: return None - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: if self.interface.name == "discord": message: discord.Message = data.message guild: discord.Guild = message.guild @@ -36,12 +36,12 @@ class LazyplayCommand(Command): else: guild_id = None - user: User = await data.get_author() + user: rbt.User = await data.get_author() user_str = None if user is not None: try: - user_discord: Discord = user.discord[0] + user_discord: rbt.Discord = user.discord[0] except (AttributeError, IndexError): user_str = str(user) else: diff --git a/royalpack/commands/lazysoundcloud.py b/royalpack/commands/lazysoundcloud.py index e3e181c5..e297c0ce 100644 --- a/royalpack/commands/lazysoundcloud.py +++ b/royalpack/commands/lazysoundcloud.py @@ -1,3 +1,4 @@ +from typing import * from .lazyplay import LazyplayCommand diff --git a/royalpack/commands/lazyyahoovideo.py b/royalpack/commands/lazyyahoovideo.py index f0f4f1d5..a2e51389 100644 --- a/royalpack/commands/lazyyahoovideo.py +++ b/royalpack/commands/lazyyahoovideo.py @@ -1,3 +1,4 @@ +from typing import * from .lazyplay import LazyplayCommand diff --git a/royalpack/commands/lazyyoutube.py b/royalpack/commands/lazyyoutube.py index cf6a56b9..3dcb8f82 100644 --- a/royalpack/commands/lazyyoutube.py +++ b/royalpack/commands/lazyyoutube.py @@ -1,3 +1,4 @@ +from typing import * from .lazyplay import LazyplayCommand diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index eca6f67b..1331192c 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -1,18 +1,19 @@ -import typing +from typing import * import riotwatcher import logging import asyncio import sentry_sdk -from royalnet.commands import * -from royalnet.utils import * -from royalnet.serf.telegram import * +import royalnet.commands as rc +import royalnet.utils as ru +import royalnet.serf.telegram as rst + from ..tables import LeagueOfLegends, FiorygiTransaction from ..types import LeagueLeague log = logging.getLogger(__name__) -class LeagueoflegendsCommand(Command): +class LeagueoflegendsCommand(rc.Command): name: str = "leagueoflegends" aliases = ["lol", "league"] @@ -21,7 +22,7 @@ class LeagueoflegendsCommand(Command): syntax = "[nomeevocatore]" - def __init__(self, interface: CommandInterface): + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.config["Lol"]["token"]) if self.interface.name == "telegram" and self.config["Lol"]["updater"]: @@ -31,15 +32,15 @@ class LeagueoflegendsCommand(Command): client = self.serf.client await self.serf.api_call(client.send_message, chat_id=self.config["Telegram"]["main_group_id"], - text=escape(message), + text=rst.escape(message), parse_mode="HTML", disable_webpage_preview=True) async def _notify(self, obj: LeagueOfLegends, attribute_name: str, - old_value: typing.Any, - new_value: typing.Any): + old_value: Any, + new_value: Any): if isinstance(old_value, LeagueLeague): # This is a rank change! # Don't send messages for every rank change, send messages just if the TIER or RANK changes! @@ -69,9 +70,9 @@ class LeagueoflegendsCommand(Command): @staticmethod async def _change(obj: LeagueOfLegends, attribute_name: str, - new_value: typing.Any, - callback: typing.Callable[ - [LeagueOfLegends, str, typing.Any, typing.Any], typing.Awaitable[None]]): + new_value: Any, + callback: Callable[ + [LeagueOfLegends, str, Any, Any], Awaitable[None]]): old_value = obj.__getattribute__(attribute_name) if old_value != new_value: await callback(obj, attribute_name, old_value, new_value) @@ -80,8 +81,8 @@ class LeagueoflegendsCommand(Command): async def _update(self, lol: LeagueOfLegends): log.info(f"Updating: {lol}") log.debug(f"Getting summoner data: {lol}") - summoner = await asyncify(self._riotwatcher.summoner.by_id, region=self.config["Lol"]["region"], - encrypted_summoner_id=lol.summoner_id) + summoner = await ru.asyncify(self._riotwatcher.summoner.by_id, region=self.config["Lol"]["region"], + encrypted_summoner_id=lol.summoner_id) await self._change(lol, "profile_icon_id", summoner["profileIconId"], self._notify) await self._change(lol, "summoner_name", summoner["name"], self._notify) await self._change(lol, "puuid", summoner["puuid"], self._notify) @@ -89,8 +90,8 @@ class LeagueoflegendsCommand(Command): await self._change(lol, "summoner_id", summoner["id"], self._notify) await self._change(lol, "account_id", summoner["accountId"], self._notify) log.debug(f"Getting leagues data: {lol}") - leagues = await asyncify(self._riotwatcher.league.by_summoner, region=self.config["Lol"]["region"], - encrypted_summoner_id=lol.summoner_id) + leagues = await ru.asyncify(self._riotwatcher.league.by_summoner, region=self.config["Lol"]["region"], + encrypted_summoner_id=lol.summoner_id) soloq = LeagueLeague() flexq = LeagueLeague() twtrq = LeagueLeague() @@ -109,9 +110,9 @@ class LeagueoflegendsCommand(Command): await self._change(lol, "rank_twtrq", twtrq, self._notify) await self._change(lol, "rank_tftq", tftq, self._notify) log.debug(f"Getting mastery data: {lol}") - mastery = await asyncify(self._riotwatcher.champion_mastery.scores_by_summoner, - region=self.config["Lol"]["region"], - encrypted_summoner_id=lol.summoner_id) + mastery = await ru.asyncify(self._riotwatcher.champion_mastery.scores_by_summoner, + region=self.config["Lol"]["region"], + encrypted_summoner_id=lol.summoner_id) await self._change(lol, "mastery_score", mastery, self._notify) async def _updater(self, period: int): @@ -128,7 +129,7 @@ class LeagueoflegendsCommand(Command): sentry_sdk.capture_exception(e) log.error(f"Error while updating {lol.user.username}: {e}") await asyncio.sleep(1) - await asyncify(session.commit) + await ru.asyncify(session.commit) session.close() log.info(f"Sleeping for {period}s") await asyncio.sleep(period) @@ -149,7 +150,7 @@ class LeagueoflegendsCommand(Command): string += f"TFT: {lol.rank_tftq}\n" return string - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: author = await data.get_author(error_if_none=True) name = args.joined() @@ -159,10 +160,10 @@ class LeagueoflegendsCommand(Command): log.debug(f"Searching for: {name}") summoner = self._riotwatcher.summoner.by_name(region=self.config["Lol"]["region"], summoner_name=name) # Ensure the account isn't already connected to something else - leagueoflegends = await asyncify( + leagueoflegends = await ru.asyncify( data.session.query(self.alchemy.get(LeagueOfLegends)).filter_by(summoner_id=summoner["id"]).one_or_none) if leagueoflegends: - raise CommandError(f"L'account {leagueoflegends} è già registrato su Royalnet.") + raise rc.CommandError(f"L'account {leagueoflegends} è già registrato su Royalnet.") # Get rank information log.debug(f"Getting leagues data: {name}") leagues = self._riotwatcher.league.by_summoner(region=self.config["Lol"]["region"], @@ -209,7 +210,7 @@ class LeagueoflegendsCommand(Command): else: # Update and display the League of Legends stats for the current account if len(author.leagueoflegends) == 0: - raise UserError("Nessun account di League of Legends trovato.") + raise rc.UserError("Nessun account di League of Legends trovato.") message = "" for account in author.leagueoflegends: try: diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py index f9f8f0c7..03e3e494 100644 --- a/royalpack/commands/magickfiorygi.py +++ b/royalpack/commands/magickfiorygi.py @@ -1,9 +1,8 @@ from typing import * -import royalnet import royalnet.commands as rc -import royalnet.serf.telegram as rt -from royalnet.backpack.tables import Alias -from ..tables import Fiorygi, FiorygiTransaction +import royalnet.backpack.tables as rbt + +from ..tables import FiorygiTransaction class MagickfiorygiCommand(rc.Command): @@ -24,7 +23,7 @@ class MagickfiorygiCommand(rc.Command): if user_arg is None: raise rc.InvalidInputError("Non hai specificato un destinatario!") - user = await Alias.find_user(self.alchemy, data.session, user_arg) + user = await rbt.Alias.find_user(self.alchemy, data.session, user_arg) if user is None: raise rc.InvalidInputError("L'utente specificato non esiste!") diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 57b52faa..0e10f662 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -16,6 +16,7 @@ from royalnet.serf.telegram import TelegramSerf as TelegramBot from royalnet.serf.telegram import escape as telegram_escape from royalnet.utils import asyncify, sleep_until, sentry_async_wrap from royalnet.backpack.tables import User + from ..tables import MMEvent, MMResponse, FiorygiTransaction from ..types import MMChoice, MMInterfaceDataTelegram diff --git a/royalpack/commands/pause.py b/royalpack/commands/pause.py index d4f6fc6a..4c71820d 100644 --- a/royalpack/commands/pause.py +++ b/royalpack/commands/pause.py @@ -1,16 +1,16 @@ -import discord from typing import * -from royalnet.commands import * +import discord +import royalnet.commands as rc -class PauseCommand(Command): +class PauseCommand(rc.Command): name: str = "pause" aliases = ["resume"] description: str = "Metti in pausa o riprendi la riproduzione di un file." - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: if self.interface.name == "discord": message: discord.Message = data.message guild: discord.Guild = message.guild diff --git a/royalpack/commands/peertube.py b/royalpack/commands/peertube.py index 51b08fd8..20c112ec 100644 --- a/royalpack/commands/peertube.py +++ b/royalpack/commands/peertube.py @@ -1,8 +1,10 @@ -from .play import PlayCommand -from royalnet.commands import * +from typing import * +import royalnet.commands as rc import aiohttp import urllib.parse +from .play import PlayCommand + class PeertubeCommand(PlayCommand): name: str = "peertube" @@ -20,5 +22,5 @@ class PeertubeCommand(PlayCommand): f"/api/v1/search/videos?search={search}") as response: j = await response.json() if j["total"] < 1: - raise InvalidInputError("Nessun video trovato.") + raise rc.InvalidInputError("Nessun video trovato.") return [f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}'] diff --git a/royalpack/commands/peertubeupdates.py b/royalpack/commands/peertubeupdates.py index 85423965..6c19a196 100644 --- a/royalpack/commands/peertubeupdates.py +++ b/royalpack/commands/peertubeupdates.py @@ -1,16 +1,17 @@ +from typing import * import aiohttp import asyncio import datetime import logging import dateparser -from royalnet.commands import * -from royalnet.serf.telegram.escape import escape +import royalnet.commands as rc +import royalnet.serf.telegram as rst log = logging.getLogger(__name__) -class PeertubeUpdatesCommand(Command): +class PeertubeUpdatesCommand(rc.Command): name: str = "peertubeupdates" description: str = "Guarda quando è uscito l'ultimo video su PeerTube." @@ -21,7 +22,7 @@ class PeertubeUpdatesCommand(Command): _latest_date: datetime.datetime = None - def __init__(self, interface: CommandInterface): + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) if self.interface.name == "telegram": self.loop.create_task(self._ready_up()) @@ -34,7 +35,7 @@ class PeertubeUpdatesCommand(Command): "/feeds/videos.json?sort=-publishedAt&filter=local") as response: log.debug("Parsing jsonfeed") if response.status != 200: - raise ExternalError("Peertube is unavailable") + raise rc.ExternalError("Peertube is unavailable") j = await response.json() log.debug("Jsonfeed parsed successfully") return j @@ -43,14 +44,14 @@ class PeertubeUpdatesCommand(Command): client = self.interface.bot.client await self.interface.bot.safe_api_call(client.send_message, chat_id=self.config["Telegram"]["main_group_id"], - text=escape(message), + 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 ConfigurationError("url is not a jsonfeed") + raise rc.ConfigurationError("url is not a jsonfeed") videos = j["items"] for video in reversed(videos): date_modified = dateparser.parse(video["date_modified"]) @@ -74,7 +75,7 @@ class PeertubeUpdatesCommand(Command): f"{video['url']}") await asyncio.sleep(self.config["Peertube"]["feed_update_timeout"]) - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: if self.interface.name != "telegram": - raise UnsupportedError() + raise rc.UnsupportedError() await data.reply(f"ℹ️ Ultimo video caricato il: [b]{self._latest_date.isoformat()}[/b]") diff --git a/royalpack/commands/play.py b/royalpack/commands/play.py index c13bac9a..25abe910 100644 --- a/royalpack/commands/play.py +++ b/royalpack/commands/play.py @@ -1,11 +1,11 @@ +from typing import * import discord import asyncio as aio -from typing import * -from royalnet.commands import * -from royalnet.backpack.tables import User, Discord +import royalnet.commands as rc +import royalnet.backpack.tables as rbt -class PlayCommand(Command): +class PlayCommand(rc.Command): name: str = "play" aliases = ["p"] @@ -14,17 +14,17 @@ class PlayCommand(Command): syntax = "{url}" - async def get_urls(self, args: CommandArgs): + async def get_urls(self, args: rc.CommandArgs): url = args.joined(require_at_least=1) if not (url.startswith("http://") or url.startswith("https://")): - raise InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" + raise rc.InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" f" ([c]http://[/c] o [c]https://[/c]).") return [url] def get_embed_color(self) -> Optional[int]: return None - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: if self.interface.name == "discord": message: discord.Message = data.message guild: discord.Guild = message.guild @@ -35,12 +35,12 @@ class PlayCommand(Command): else: guild_id = None - user: User = await data.get_author() + user: rbt.User = await data.get_author() user_str = None if user is not None: try: - user_discord: Discord = user.discord[0] + user_discord: rbt.Discord = user.discord[0] except (AttributeError, IndexError): user_str = str(user) else: diff --git a/royalpack/commands/playmode.py b/royalpack/commands/playmode.py index 01d62a37..9ea12955 100644 --- a/royalpack/commands/playmode.py +++ b/royalpack/commands/playmode.py @@ -1,8 +1,7 @@ from typing import * -import royalnet import royalnet.commands as rc import discord -from royalnet.backpack.tables import User, Discord +import royalnet.backpack.tables as rbt class PlaymodeCommand(rc.Command): @@ -25,12 +24,12 @@ class PlaymodeCommand(rc.Command): else: guild_id = None - user: User = await data.get_author() + user: rbt.User = await data.get_author() user_str = None if user is not None: try: - user_discord: Discord = user.discord[0] + user_discord: rbt.Discord = user.discord[0] except (AttributeError, IndexError): user_str = str(user) else: diff --git a/royalpack/commands/pmots.py b/royalpack/commands/pmots.py index 91f5ea54..e32cd289 100644 --- a/royalpack/commands/pmots.py +++ b/royalpack/commands/pmots.py @@ -1,11 +1,11 @@ from typing import * -from royalnet.commands import * +import royalnet.commands as rc -class PmotsCommand(Command): +class PmotsCommand(rc.Command): name: str = "pmots" description: str = "Confondi Proto!" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: await data.reply("👣 pmots pmots") diff --git a/royalpack/commands/queue.py b/royalpack/commands/queue.py index 8357d45b..4ae2a39a 100644 --- a/royalpack/commands/queue.py +++ b/royalpack/commands/queue.py @@ -1,19 +1,19 @@ +from typing import * import pickle import base64 import discord -from typing import * -from royalnet.commands import * -from royalnet.utils import * +import royalnet.commands as rc +import royalnet.utils as ru -class QueueCommand(Command): +class QueueCommand(rc.Command): name: str = "queue" aliases = ["q"] description: str = "Visualizza la coda di riproduzione attuale." - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: if self.interface.name == "discord": message: discord.Message = data.message guild: discord.Guild = message.guild @@ -54,9 +54,9 @@ class QueueCommand(Command): # noinspection PyUnboundLocalVariable await message.channel.send(embed=embed) else: - reply += numberemojiformat([a["title"] for a in next_up[:5]]) + reply += ru.numberemojiformat([a["title"] for a in next_up[:5]]) await data.reply(reply) else: await data.reply("ℹ️ Non ci sono altri file in coda.") else: - raise CommandError(f"Non so come visualizzare il contenuto di un [c]{queue_type}[/c].") + raise rc.CommandError(f"Non so come visualizzare il contenuto di un [c]{queue_type}[/c].") diff --git a/royalpack/commands/rage.py b/royalpack/commands/rage.py index 248d1162..c9f84280 100644 --- a/royalpack/commands/rage.py +++ b/royalpack/commands/rage.py @@ -1,9 +1,9 @@ -import typing +from typing import * import random -from royalnet.commands import * +import royalnet.commands as rc -class RageCommand(Command): +class RageCommand(rc.Command): name: str = "rage" aliases = ["balurage", "madden"] @@ -18,5 +18,5 @@ class RageCommand(Command): "Fondiamo la RRYG!" ] - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: await data.reply(f"😠 {random.sample(self._MAD, 1)[0]}") diff --git a/royalpack/commands/reminder.py b/royalpack/commands/reminder.py index 6c9c5c64..48d7075a 100644 --- a/royalpack/commands/reminder.py +++ b/royalpack/commands/reminder.py @@ -1,18 +1,19 @@ -import typing +from typing import * import dateparser import datetime import pickle import telegram import discord from sqlalchemy import and_ -from royalnet.commands import * -from royalnet.utils import * +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 + from ..tables import Reminder -class ReminderCommand(Command): +class ReminderCommand(rc.Command): name: str = "reminder" aliases = ["calendar"] @@ -21,7 +22,7 @@ class ReminderCommand(Command): syntax: str = "[ {data} ] {messaggio}" - def __init__(self, interface: CommandInterface): + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) session = interface.alchemy.Session() reminders = ( @@ -35,7 +36,7 @@ class ReminderCommand(Command): interface.loop.create_task(self._remind(reminder)) async def _remind(self, reminder): - await sleep_until(reminder.datetime) + await ru.sleep_until(reminder.datetime) if self.interface.name == "telegram": chat_id: int = pickle.loads(reminder.interface_data) client: telegram.Bot = self.serf.client @@ -50,14 +51,14 @@ class ReminderCommand(Command): channel = client.get_channel(channel_id) await channel.send(discord_escape(f"❗️ {reminder.message}")) - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: try: date_str, reminder_text = args.match(r"\[\s*([^]]+)\s*]\s*([^\n]+)\s*") - except InvalidInputError: + except rc.InvalidInputError: date_str, reminder_text = args.match(r"\s*(.+?)\s*\n\s*([^\n]+)\s*") try: - date: typing.Optional[datetime.datetime] = dateparser.parse(date_str, settings={ + date: Optional[datetime.datetime] = dateparser.parse(date_str, settings={ "PREFER_DATES_FROM": "future" }) except OverflowError: @@ -74,7 +75,7 @@ class ReminderCommand(Command): elif self.interface.name == "discord": interface_data = pickle.dumps(data.message.channel.id) else: - raise UnsupportedError("This command does not support the current interface.") + 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, @@ -83,4 +84,4 @@ class ReminderCommand(Command): message=reminder_text) self.interface.loop.create_task(self._remind(reminder)) data.session.add(reminder) - await asyncify(data.session.commit) + await ru.asyncify(data.session.commit) diff --git a/royalpack/commands/royalpack.py b/royalpack/commands/royalpack.py index 512206db..063751d6 100644 --- a/royalpack/commands/royalpack.py +++ b/royalpack/commands/royalpack.py @@ -1,5 +1,6 @@ from typing import * import royalnet.commands as rc + from ..version import semantic diff --git a/royalpack/commands/ship.py b/royalpack/commands/ship.py index ec681438..276998f8 100644 --- a/royalpack/commands/ship.py +++ b/royalpack/commands/ship.py @@ -1,15 +1,16 @@ +from typing import * import re -from royalnet.commands import * +import royalnet.commands as rc -class ShipCommand(Command): +class ShipCommand(rc.Command): name: str = "ship" description: str = "Crea una ship tra due nomi." syntax = "{nomeuno} {nomedue}" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: name_one = args[0] name_two = args[1] if name_two == "+": diff --git a/royalpack/commands/skip.py b/royalpack/commands/skip.py index 8b9a0f38..277ad1c0 100644 --- a/royalpack/commands/skip.py +++ b/royalpack/commands/skip.py @@ -1,16 +1,16 @@ -import discord from typing import * -from royalnet.commands import * +import discord +import royalnet.commands as rc -class SkipCommand(Command): +class SkipCommand(rc.Command): name: str = "skip" aliases = ["s"] description: str = "Salta il file attualmente in riproduzione." - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: if self.interface.name == "discord": message: discord.Message = data.message guild: discord.Guild = message.guild diff --git a/royalpack/commands/smecds.py b/royalpack/commands/smecds.py index 7789cdf1..9305bf7d 100644 --- a/royalpack/commands/smecds.py +++ b/royalpack/commands/smecds.py @@ -1,9 +1,9 @@ -import typing +from typing import * import random -from royalnet.commands import * +import royalnet.commands as rc -class SmecdsCommand(Command): +class SmecdsCommand(rc.Command): name: str = "smecds" aliases = ["secondomeecolpadellostagista"] @@ -61,6 +61,6 @@ class SmecdsCommand(Command): "dello Slime God", "del salassato", "della salsa", "di Senjougahara", "di Sugar", "della Stampa", "della Stampante"] - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: ds = random.sample(self._DS_LIST, 1)[0] await data.reply(f"🤔 Secondo me, è colpa {ds}.") diff --git a/royalpack/commands/soundcloud.py b/royalpack/commands/soundcloud.py index f0e68061..b01d8ef7 100644 --- a/royalpack/commands/soundcloud.py +++ b/royalpack/commands/soundcloud.py @@ -1,3 +1,4 @@ +from typing import * from .play import PlayCommand diff --git a/royalpack/commands/spell.py b/royalpack/commands/spell.py index 17063a10..e815bfd2 100644 --- a/royalpack/commands/spell.py +++ b/royalpack/commands/spell.py @@ -1,19 +1,17 @@ from typing import * -from royalnet.commands import * -from royalnet.utils import * -from royalnet.backpack.tables import User -from sqlalchemy import func +import royalnet.commands as rc +import royalnet.utils as ru import royalspells as rs -class SpellCommand(Command): +class SpellCommand(rc.Command): name: str = "spell" description: str = "Genera casualmente una spell!" syntax = "{nome_spell}" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: spell_name = args.joined(require_at_least=1) spell = rs.Spell(spell_name) @@ -23,7 +21,7 @@ class SpellCommand(Command): dmg: rs.DamageComponent = spell.damage_component constant_str: str = f"{dmg.constant:+d}" if dmg.constant != 0 else "" rows.append(f"Danni: [b]{dmg.dice_number}d{dmg.dice_type}{constant_str}[/b]" - f" {andformat(dmg.damage_types, final=' e ')}") + f" {ru.andformat(dmg.damage_types, final=' e ')}") rows.append(f"Precisione: [b]{dmg.miss_chance}%[/b]") if dmg.repeat > 1: rows.append(f"Multiattacco: [b]×{dmg.repeat}[/b]") diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index 13d59070..99d27f80 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -1,10 +1,11 @@ from typing import * -from royalnet.commands import * -from royalnet.utils import * -from royalnet.backpack.tables import Alias -from ..tables import Steam import steam import requests.exceptions +import royalnet.commands as rc +import royalnet.utils as ru +import royalnet.backpack.tables as rbt + +from ..tables import Steam class SteamGame: @@ -45,47 +46,47 @@ class SteamGame: return f"<{self.__class__.__qualname__} {self.appid} ({self.name})>" -class SteammatchCommand(Command): +class SteammatchCommand(rc.Command): name: str = "steammatch" description: str = "Vedi quali giochi hai in comune con uno o più membri!" syntax: str = "{royalnet_username}+" - def __init__(self, interface: CommandInterface): + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: - raise ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") + raise rc.ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") self._api = steam.WebAPI(self.config["Steam"]["web_api_key"]) - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: users = [] author = await data.get_author(error_if_none=True) users.append(author) for arg in args: - user = await Alias.find_user(self.alchemy, data.session, arg) + user = await rbt.User.find(self.alchemy, data.session, arg) users.append(user) if len(users) < 2: - raise InvalidInputError("Devi specificare almeno un altro utente!") + raise rc.InvalidInputError("Devi specificare almeno un altro utente!") shared_games: Optional[set] = None for user in users: user_games = set() if len(user.steam) == 0: - raise UserError(f"{user} non ha un account Steam registrato!") + raise rc.UserError(f"{user} non ha un account Steam registrato!") for steam_account in user.steam: steam_account: Steam try: - response = await asyncify(self._api.IPlayerService.GetOwnedGames, - steamid=steam_account._steamid, - include_appinfo=True, - include_played_free_games=True, - appids_filter=0) + response = await ru.asyncify(self._api.IPlayerService.GetOwnedGames, + steamid=steam_account._steamid, + include_appinfo=True, + include_played_free_games=True, + appids_filter=0) except requests.exceptions.HTTPError: - raise ExternalError(f"L'account Steam di {user} è privato!") + raise rc.ExternalError(f"L'account Steam di {user} è privato!") games = response["response"]["games"] for game in games: user_games.add(SteamGame(**game)) @@ -94,7 +95,7 @@ class SteammatchCommand(Command): else: shared_games = shared_games.intersection(user_games) - message_rows = [f"🎮 Giochi in comune tra {andformat([str(user) for user in users], final=' e ')}:"] + message_rows = [f"🎮 Giochi in comune tra {ru.andformat([str(user) for user in users], final=' e ')}:"] for game in sorted(list(shared_games), key=lambda g: g.name): message_rows.append(f"- {game}") diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 3c3ea324..a29f1e82 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -1,22 +1,23 @@ from typing import * -from royalnet.commands import * -from royalnet.utils import * -from ..tables import Steam, FiorygiTransaction import steam import datetime +import royalnet.commands as rc +import royalnet.utils as ru + +from ..tables import Steam, FiorygiTransaction -class SteampoweredCommand(Command): +class SteampoweredCommand(rc.Command): name: str = "steampowered" description: str = "Connetti il tuo account di Steam!" syntax: str = "{profile_url}" - def __init__(self, interface: CommandInterface): + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: - raise ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") + raise rc.ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") self._api = steam.WebAPI(self.config["Steam"]["web_api_key"]) @staticmethod @@ -34,9 +35,9 @@ class SteampoweredCommand(Command): async def _call(self, method, *args, **kwargs): try: - await asyncify(method, *args, **kwargs) + await ru.asyncify(method, *args, **kwargs) except Exception as e: - raise ExternalError("\n".join(e.args).replace(self.config["Steam"]["web_api_key"], "HIDDEN")) + raise rc.ExternalError("\n".join(e.args).replace(self.config["Steam"]["web_api_key"], "HIDDEN")) async def _update(self, account: Steam): # noinspection PyProtectedMember @@ -48,13 +49,13 @@ class SteampoweredCommand(Command): account.primary_clan_id = r["primaryclanid"] account.account_creation_date = datetime.datetime.fromtimestamp(r["timecreated"]) - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: author = await data.get_author() if len(args) > 0: url = args.joined() steamid64 = await self._call(steam.steamid.steam64_from_url, url) if steamid64 is None: - raise InvalidInputError("Quel link non è associato ad alcun account Steam.") + raise rc.InvalidInputError("Quel link non è associato ad alcun account Steam.") response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid64) r = response["response"]["players"][0] steam_account = self.alchemy.get(Steam)( @@ -74,7 +75,7 @@ class SteampoweredCommand(Command): else: # Update and display the Steam info for the current account if len(author.steam) == 0: - raise UserError("Nessun account di Steam trovato.") + raise rc.UserError("Nessun account di Steam trovato.") message = "" for account in author.steam: await self._update(account) diff --git a/royalpack/commands/summon.py b/royalpack/commands/summon.py index 4fc2cd3b..18145a5a 100644 --- a/royalpack/commands/summon.py +++ b/royalpack/commands/summon.py @@ -1,8 +1,9 @@ +from typing import * +import royalnet.commands as rc import discord -from royalnet.commands import * -class SummonCommand(Command): +class SummonCommand(rc.Command): name: str = "summon" aliases = ["cv"] @@ -11,7 +12,7 @@ class SummonCommand(Command): syntax: str = "[nomecanale]" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: channel_name = args.joined() if self.interface.name == "discord": message: discord.Message = data.message diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index 26e28c05..d5226028 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -6,8 +6,8 @@ import uuid import html import royalnet.commands as rc import royalnet.utils as ru +import royalnet.backpack.tables as rbt from ..tables import TriviaScore -from royalnet.backpack.tables.users import User class TriviaCommand(rc.Command): @@ -126,7 +126,7 @@ class TriviaCommand(rc.Command): 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(User)).get(answerer_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) diff --git a/royalpack/commands/userinfo.py b/royalpack/commands/userinfo.py index e156a8e8..2917f569 100644 --- a/royalpack/commands/userinfo.py +++ b/royalpack/commands/userinfo.py @@ -1,11 +1,9 @@ from typing import * -from royalnet.commands import * -from royalnet.utils import * -from royalnet.backpack.tables import User, Alias -from sqlalchemy import func +import royalnet.commands as rc +import royalnet.backpack.tables as rbt -class UserinfoCommand(Command): +class UserinfoCommand(rc.Command): name: str = "userinfo" aliases = ["uinfo", "ui", "useri"] @@ -14,23 +12,27 @@ class UserinfoCommand(Command): syntax = "[username]" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: username = args.optional(0) if username is None: - user: User = await data.get_author(error_if_none=True) + user: rbt.User = await data.get_author(error_if_none=True) else: - found: Optional[User] = await Alias.find_user(self.alchemy, data.session, username) + found: Optional[rbt.User] = await rbt.User.find(self.alchemy, data.session, username) if not found: - raise InvalidInputError("Utente non trovato.") + raise rc.InvalidInputError("Utente non trovato.") else: user = found r = [ f"ℹ️ [url=https://ryg.steffo.eu/#/user/{user.uid}]{user.username}[/url]", - f"{user.role}", - "", + 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}") diff --git a/royalpack/commands/videochannel.py b/royalpack/commands/videochannel.py index c613591b..a8801510 100644 --- a/royalpack/commands/videochannel.py +++ b/royalpack/commands/videochannel.py @@ -1,9 +1,9 @@ -import typing +from typing import * import discord -from royalnet.commands import * +import royalnet.commands as rc -class VideochannelCommand(Command): +class VideochannelCommand(rc.Command): name: str = "videochannel" aliases = ["golive", "live", "video"] @@ -12,33 +12,33 @@ class VideochannelCommand(Command): syntax = "[nomecanale]" - async def run(self, args: CommandArgs, data: CommandData) -> None: + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: if self.interface.name != "discord": - raise UnsupportedError(f"{self} non è supportato su {self.interface.name}.") + raise rc.UnsupportedError(f"{self} non è supportato su {self.interface.name}.") bot: discord.Client = self.serf.client message: discord.Message = data.message channel_name: str = args.optional(0) if channel_name: - guild: typing.Optional[discord.Guild] = message.guild + guild: Optional[discord.Guild] = message.guild if guild is not None: - channels: typing.List[discord.abc.GuildChannel] = guild.channels + channels: List[discord.abc.GuildChannel] = guild.channels else: channels = bot.get_all_channels() - matching_channels: typing.List[discord.VoiceChannel] = [] + matching_channels: List[discord.VoiceChannel] = [] for channel in channels: if isinstance(channel, discord.VoiceChannel): if channel.name == channel_name: matching_channels.append(channel) if len(matching_channels) == 0: - raise InvalidInputError("Non esiste alcun canale vocale con il nome specificato.") + raise rc.InvalidInputError("Non esiste alcun canale vocale con il nome specificato.") elif len(matching_channels) > 1: - raise UserError("Esiste più di un canale vocale con il nome specificato.") + raise rc.UserError("Esiste più di un canale vocale con il nome specificato.") channel = matching_channels[0] else: author: discord.Member = message.author - voice: typing.Optional[discord.VoiceState] = author.voice + voice: Optional[discord.VoiceState] = author.voice if voice is None: - raise InvalidInputError("Non sei connesso a nessun canale vocale.") + raise rc.InvalidInputError("Non sei connesso a nessun canale vocale.") channel = voice.channel if author.is_on_mobile(): await data.reply(f"📹 Per entrare in modalità video, clicca qui:\n" diff --git a/royalpack/commands/yahoovideo.py b/royalpack/commands/yahoovideo.py index a0ec05be..0632152a 100644 --- a/royalpack/commands/yahoovideo.py +++ b/royalpack/commands/yahoovideo.py @@ -1,3 +1,4 @@ +from typing import * from .play import PlayCommand diff --git a/royalpack/commands/youtube.py b/royalpack/commands/youtube.py index f684a59a..29e05d72 100644 --- a/royalpack/commands/youtube.py +++ b/royalpack/commands/youtube.py @@ -1,3 +1,4 @@ +from typing import * from .play import PlayCommand diff --git a/royalpack/version.py b/royalpack/version.py index 2965bbf6..03998cec 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.7.15" +semantic = "5.8.0" From 2c80e899a847e652cd198b426c0e9b12569f1422 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 13 May 2020 20:44:14 +0200 Subject: [PATCH 135/227] Permetti agli admin di eliminare i matchmaking inutilizzati --- royalpack/commands/matchmaking.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 0e10f662..3fb7c6ec 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -185,9 +185,9 @@ class MatchmakingCommand(rc.Command): def _gen_mm_telegram_delete(self, client, mmid: int): async def callback(data: rc.CommandData): - author = await data.get_author(error_if_none=True) + author: User = await data.get_author(error_if_none=True) mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) - if author != mmevent.creator: + if author != mmevent.creator and "admin" not in author.roles: raise rc.UserError("Non sei il creatore di questo matchmaking!") await self.queue[mmid].put(Interrupts.MANUAL_DELETE) await data.reply(f"🗑 Evento eliminato!") @@ -197,7 +197,7 @@ class MatchmakingCommand(rc.Command): async def callback(data: rc.CommandData): author = await data.get_author(error_if_none=True) mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) - if author != mmevent.creator: + if author != mmevent.creator and "admin" not in author.roles: raise rc.UserError("Non sei il creatore di questo matchmaking!") await self.queue[mmid].put(Interrupts.MANUAL_START) await data.reply(f"🚩 Evento avviato!") From 2378cbb662d45e86e8ef4cb8c8238d08dda04901 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 13 May 2020 20:49:01 +0200 Subject: [PATCH 136/227] publish: 5.8.1 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 31195f6f..4d7c4ffa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.0" + version = "5.8.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 03998cec..3d6bddf3 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.0" +semantic = "5.8.1" From d05c2cd988e63fcf54cd4956f5157dc54ccc80b4 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 14 May 2020 00:11:48 +0200 Subject: [PATCH 137/227] Aggiungi nuovi comandi --- royalpack/commands/__init__.py | 4 +++ royalpack/commands/ciaoruozi.py | 2 +- royalpack/commands/givefiorygi.py | 44 +++++++++++++++++++++++++++++ royalpack/commands/help.py | 27 ++++++++++++++++++ royalpack/commands/magickfiorygi.py | 4 +-- royalpack/commands/matchmaking.py | 4 +-- 6 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 royalpack/commands/givefiorygi.py create mode 100644 royalpack/commands/help.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 215e19e9..7c743bfc 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -54,6 +54,8 @@ from .matchmaking import MatchmakingCommand from .cvstats import CvstatsCommand from .elevatormusic import ElevatormusicCommand from .royalpack import RoyalpackCommand +from .givefiorygi import GivefiorygiCommand +from .help import HelpCommand # Enter the commands of your Pack here! available_commands = [ @@ -112,6 +114,8 @@ available_commands = [ CvstatsCommand, ElevatormusicCommand, RoyalpackCommand, + GivefiorygiCommand, + HelpCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/ciaoruozi.py b/royalpack/commands/ciaoruozi.py index 727b7cca..be932f5b 100644 --- a/royalpack/commands/ciaoruozi.py +++ b/royalpack/commands/ciaoruozi.py @@ -6,7 +6,7 @@ from royalnet.commands import * class CiaoruoziCommand(Command): name: str = "ciaoruozi" - description: str = "Saluta Ruozi, un leggendario essere che una volta era in User Games." + 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": diff --git a/royalpack/commands/givefiorygi.py b/royalpack/commands/givefiorygi.py new file mode 100644 index 00000000..3511381f --- /dev/null +++ b/royalpack/commands/givefiorygi.py @@ -0,0 +1,44 @@ +from typing import * +import royalnet.commands as rc +import royalnet.backpack.tables as rbt + +from ..tables import FiorygiTransaction + + +class GivefiorygiCommand(rc.Command): + name: str = "givefiorygi" + + description: str = "Cedi fiorygi a un altro utente." + + syntax: str = "{destinatario} {quantità} {motivo}" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + author = await data.get_author(error_if_none=True) + + user_arg = args[0] + qty_arg = args[1] + reason_arg = " ".join(args[2:]) + + if user_arg is None: + raise rc.InvalidInputError("Non hai specificato un destinatario!") + user = await rbt.User.find(self.alchemy, data.session, user_arg) + if user is None: + raise rc.InvalidInputError("L'utente specificato non esiste!") + + if qty_arg is None: + raise rc.InvalidInputError("Non hai specificato una quantità!") + try: + qty = int(qty_arg) + except ValueError: + raise rc.InvalidInputError("La quantità specificata non è un numero!") + if qty <= 0: + raise rc.InvalidInputError("La quantità specificata deve essere almeno 1!") + + if reason_arg == "": + raise rc.InvalidInputError("Non hai specificato un motivo!") + + if author.fiorygi.fiorygi < qty: + raise rc.InvalidInputError("Non hai abbastanza fiorygi per effettuare la transazione!") + + await FiorygiTransaction.spawn_fiorygi(data, author, -qty, reason_arg) + await FiorygiTransaction.spawn_fiorygi(data, user, qty, reason_arg) diff --git a/royalpack/commands/help.py b/royalpack/commands/help.py new file mode 100644 index 00000000..0b5a3675 --- /dev/null +++ b/royalpack/commands/help.py @@ -0,0 +1,27 @@ +from typing import * +import royalnet +import royalnet.commands as rc + + +class HelpCommand(rc.Command): + name: str = "help" + + description: str = "Visualizza informazioni su un comando." + + syntax: str = "{comando}" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + name: str = args[0].lstrip(self.interface.prefix) + + try: + command: rc.Command = self.serf.commands[f"{self.interface.prefix}{name}"] + except KeyError: + raise rc.InvalidInputError("Il comando richiesto non esiste.") + + message = [ + f"[c]{self.interface.prefix}{command.name} {command.syntax}[/c]", + "", + f"{command.description}" + ] + + await data.reply("\n".join(message)) diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py index 03e3e494..3f98f64e 100644 --- a/royalpack/commands/magickfiorygi.py +++ b/royalpack/commands/magickfiorygi.py @@ -14,7 +14,7 @@ class MagickfiorygiCommand(rc.Command): async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: author = await data.get_author(error_if_none=True) - if author.role != "Admin": + if "banker" not in author.roles: raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") user_arg = args[0] @@ -23,7 +23,7 @@ class MagickfiorygiCommand(rc.Command): if user_arg is None: raise rc.InvalidInputError("Non hai specificato un destinatario!") - user = await rbt.Alias.find_user(self.alchemy, data.session, user_arg) + user = await rbt.User.find(self.alchemy, data.session, user_arg) if user is None: raise rc.InvalidInputError("L'utente specificato non esiste!") diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 3fb7c6ec..410adb2a 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -110,10 +110,10 @@ class MatchmakingCommand(rc.Command): if response.choice == MMChoice.LATE_SHORT: td = mmevent.datetime + datetime.timedelta(minutes=10) time_text = f" [{td.strftime('%H:%M')}]" - elif response.choice == MMChoice.LATE_SHORT: + elif response.choice == MMChoice.LATE_MEDIUM: td = mmevent.datetime + datetime.timedelta(minutes=30) time_text = f" [{td.strftime('%H:%M')}]" - elif response.choice == MMChoice.LATE_SHORT: + elif response.choice == MMChoice.LATE_LONG: td = mmevent.datetime + datetime.timedelta(minutes=60) time_text = f" [{td.strftime('%H:%M')}+]" else: From 37445585c5e37d8dd883c93c7dedb4ef941f40a6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 14 May 2020 01:08:36 +0200 Subject: [PATCH 138/227] Aggiungi un mostro --- royalpack/commands/givefiorygi.py | 8 +- royalpack/stars/__init__.py | 2 + royalpack/stars/api_cvstats_avg.py | 174 +++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 royalpack/stars/api_cvstats_avg.py diff --git a/royalpack/commands/givefiorygi.py b/royalpack/commands/givefiorygi.py index 3511381f..18bcda28 100644 --- a/royalpack/commands/givefiorygi.py +++ b/royalpack/commands/givefiorygi.py @@ -17,7 +17,6 @@ class GivefiorygiCommand(rc.Command): user_arg = args[0] qty_arg = args[1] - reason_arg = " ".join(args[2:]) if user_arg is None: raise rc.InvalidInputError("Non hai specificato un destinatario!") @@ -34,11 +33,8 @@ class GivefiorygiCommand(rc.Command): if qty <= 0: raise rc.InvalidInputError("La quantità specificata deve essere almeno 1!") - if reason_arg == "": - raise rc.InvalidInputError("Non hai specificato un motivo!") - if author.fiorygi.fiorygi < qty: raise rc.InvalidInputError("Non hai abbastanza fiorygi per effettuare la transazione!") - await FiorygiTransaction.spawn_fiorygi(data, author, -qty, reason_arg) - await FiorygiTransaction.spawn_fiorygi(data, user, qty, reason_arg) + await FiorygiTransaction.spawn_fiorygi(data, author, -qty, f"aver ceduto fiorygi a {user}") + await FiorygiTransaction.spawn_fiorygi(data, user, qty, f"aver ricevuto fiorygi da {user}") diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index dc65f004..6d144ff5 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -14,6 +14,7 @@ from .api_polls_create import ApiPollsCreate from .api_polls_get import ApiPollsGet from .api_polls_list import ApiPollsList from .api_cvstats_latest import ApiCvstatsLatestStar +from .api_cvstats_avg import ApiCvstatsAvgStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -32,6 +33,7 @@ available_page_stars = [ ApiPollsGet, ApiPollsList, ApiCvstatsLatestStar, + ApiCvstatsAvgStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_cvstats_avg.py b/royalpack/stars/api_cvstats_avg.py new file mode 100644 index 00000000..0346fb3b --- /dev/null +++ b/royalpack/stars/api_cvstats_avg.py @@ -0,0 +1,174 @@ +import royalnet.utils as ru +from royalnet.backpack.tables import * +from royalnet.constellation.api import * +from ..tables import Cvstats + + +class ApiCvstatsAvgStar(ApiStar): + path = "/api/cvstats/avg/v1" + + methods = ["GET"] + + summary = "Get some averages on the cvstats." + + tags = ["cvstats"] + + async def api(self, data: ApiData) -> ru.JSON: + results = data.session.execute(""" +SELECT * +FROM ( + SELECT date_part('hour', c.h) ph, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM ( + SELECT date_trunc('hour', c.timestamp) h, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM cvstats c + GROUP BY h + ) c + GROUP BY ph +) all_time +JOIN +( + SELECT date_part('hour', c.h) ph, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM ( + SELECT date_trunc('hour', c.timestamp) h, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM cvstats c + WHERE c.timestamp BETWEEN + NOW()::DATE-EXTRACT(DOW FROM NOW())::INTEGER-7 + AND NOW()::DATE-EXTRACT(DOW from NOW())::INTEGER + GROUP BY h + ) c + GROUP BY ph +) last_week ON last_week.ph = all_time.ph +JOIN +( + SELECT date_part('hour', c.h) ph, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM ( + SELECT date_trunc('hour', c.timestamp) h, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM cvstats c + WHERE c.timestamp BETWEEN + NOW()::DATE-EXTRACT(DOW FROM NOW())::INTEGER-30 + AND NOW()::DATE-EXTRACT(DOW from NOW())::INTEGER + GROUP BY h + ) c + GROUP BY ph +) last_month ON last_month.ph = all_time.ph +JOIN +( + SELECT date_part('hour', c.h) ph, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM ( + SELECT date_trunc('hour', c.timestamp) h, + AVG(c.members_connected) members_connected, + AVG(c.users_connected) users_connected, + AVG(c.members_online) members_online, + AVG(c.users_online) users_online, + AVG(c.members_playing) members_playing, + AVG(c.users_playing) users_playing, + AVG(c.members_total) members_total, + AVG(c.users_total) users_total + FROM cvstats c + WHERE c.timestamp BETWEEN + NOW()::DATE-EXTRACT(DOW FROM NOW())::INTEGER-1 + AND NOW()::DATE-EXTRACT(DOW from NOW())::INTEGER + GROUP BY h + ) c + GROUP BY ph +) last_day ON last_day.ph = all_time.ph; + """) + + return [{ + "h": r[0], + "all_time": { + "members_connected": float(r[1]), + "users_connected": float(r[2]), + "members_online": float(r[3]), + "users_online": float(r[4]), + "members_playing": float(r[5]), + "users_playing": float(r[6]), + "members_total": float(r[7]), + "users_total": float(r[8]) + }, + "last_week": { + "members_connected": float(r[10]), + "users_connected": float(r[11]), + "members_online": float(r[12]), + "users_online": float(r[13]), + "members_playing": float(r[14]), + "users_playing": float(r[15]), + "members_total": float(r[16]), + "users_total": float(r[17]) + }, + "last_month": { + "members_connected": float(r[19]), + "users_connected": float(r[20]), + "members_online": float(r[21]), + "users_online": float(r[22]), + "members_playing": float(r[23]), + "users_playing": float(r[24]), + "members_total": float(r[25]), + "users_total": float(r[26]) + }, + "last_day": { + "members_connected": float(r[28]), + "users_connected": float(r[29]), + "members_online": float(r[30]), + "users_online": float(r[31]), + "members_playing": float(r[32]), + "users_playing": float(r[33]), + "members_total": float(r[34]), + }, + } for r in sorted(results.fetchall(), key=lambda s: s[0])] From d71845a005e398477defa80e5f4bb2548b2bd15d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 14 May 2020 01:08:57 +0200 Subject: [PATCH 139/227] publish: 5.8.2 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4d7c4ffa..9dd5749b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.1" + version = "5.8.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 3d6bddf3..b5b36ad3 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.1" +semantic = "5.8.2" From 94886afb598f0d4f9e460c81e4ce6b7442c559ce Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 15 May 2020 19:30:43 +0200 Subject: [PATCH 140/227] Impedisci alla gente di inviarsi fiorygi da soli --- royalpack/commands/givefiorygi.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/royalpack/commands/givefiorygi.py b/royalpack/commands/givefiorygi.py index 18bcda28..87bf4965 100644 --- a/royalpack/commands/givefiorygi.py +++ b/royalpack/commands/givefiorygi.py @@ -23,6 +23,8 @@ class GivefiorygiCommand(rc.Command): user = await rbt.User.find(self.alchemy, data.session, user_arg) if user is None: raise rc.InvalidInputError("L'utente specificato non esiste!") + if user.uid == author.uid: + raise rc.InvalidInputError("Non puoi inviare fiorygi a te stesso!") if qty_arg is None: raise rc.InvalidInputError("Non hai specificato una quantità!") From c4edbd60ec17f9d08c87eef80aa2c64eda6637d9 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 15 May 2020 19:36:13 +0200 Subject: [PATCH 141/227] publish: 5.8.3 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9dd5749b..9e7f3275 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.2" + version = "5.8.3" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index b5b36ad3..e489a4b9 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.2" +semantic = "5.8.3" From 8f4ec1d1b915a95abb3c0ecd47a7447df32229d0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 19 May 2020 18:46:49 +0200 Subject: [PATCH 142/227] publish: 5.8.4 --- poetry.lock | 377 ++++++++++++++------------------- pyproject.toml | 4 +- royalpack/commands/__init__.py | 2 + royalpack/commands/pug.py | 26 +++ royalpack/version.py | 2 +- 5 files changed, 187 insertions(+), 224 deletions(-) create mode 100644 royalpack/commands/pug.py diff --git a/poetry.lock b/poetry.lock index 074d74eb..7f6ff3d5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -53,6 +53,14 @@ 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" +optional = false +python-versions = "~=3.5" +version = "4.1.0" + [[package]] category = "main" description = "Python package for providing Mozilla's CA Bundle." @@ -227,46 +235,6 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" version = "0.18.2" -[[package]] -category = "main" -description = "Coroutine-based network library" -name = "gevent" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "20.5.0" - -[package.dependencies] -cffi = ">=1.12.2" -greenlet = ">=0.4.14" - -[package.extras] -dnspython = ["dnspython (>=1.16.0)", "idna"] -docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput"] -events = ["zope.event", "zope.interface"] -monitor = ["psutil (>=5.6.1)", "psutil (5.6.3)"] -recommended = ["dnspython (>=1.16.0)", "idna", "zope.event", "zope.interface", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)"] -test = ["dnspython (>=1.16.0)", "idna", "zope.event", "zope.interface", "requests", "objgraph", "cffi (>=1.12.2)", "psutil (>=5.6.1)", "psutil (5.6.3)", "futures", "mock", "contextvars (2.4)", "coverage (<5.0)", "coveralls (>=1.7.0)"] - -[[package]] -category = "main" -description = "Implements EventEmitter using gevent" -name = "gevent-eventemitter" -optional = false -python-versions = "*" -version = "2.1" - -[package.dependencies] -gevent = ">=1.3" - -[[package]] -category = "main" -description = "Lightweight in-process concurrent programming" -marker = "platform_python_implementation == \"CPython\"" -name = "greenlet" -optional = false -python-versions = "*" -version = "0.4.15" - [[package]] category = "main" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" @@ -301,7 +269,7 @@ 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.9" +version = "2.8" [[package]] category = "main" @@ -309,7 +277,7 @@ description = "multidict implementation" name = "multidict" optional = false python-versions = ">=3.5" -version = "4.7.5" +version = "4.7.6" [[package]] category = "main" @@ -317,24 +285,12 @@ description = "Core utilities for Python packages" name = "packaging" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.3" +version = "20.4" [package.dependencies] pyparsing = ">=2.0.2" six = "*" -[[package]] -category = "main" -description = "Protocol Buffers" -name = "protobuf" -optional = false -python-versions = "*" -version = "3.11.3" - -[package.dependencies] -setuptools = "*" -six = ">=1.9" - [[package]] category = "main" description = "psycopg2 - Python-PostgreSQL Database Adapter" @@ -351,6 +307,14 @@ 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" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.9.7" + [[package]] category = "main" description = "Python binding to the Networking and Cryptography (NaCl) library" @@ -439,24 +403,24 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.5.7" +version = "2020.5.14" [[package]] category = "main" description = "Python HTTP for Humans." name = "requests" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.23.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.21.0" [package.dependencies] certifi = ">=2017.4.17" -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" +chardet = ">=3.0.2,<3.1.0" +idna = ">=2.5,<2.9" +urllib3 = ">=1.21.1,<1.25" [package.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] @@ -479,7 +443,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.8.7" +version = "5.8.9" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -605,7 +569,7 @@ description = "Database Abstraction Library" name = "sqlalchemy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.16" +version = "1.3.17" [package.extras] mssql = ["pyodbc"] @@ -636,16 +600,17 @@ description = "Module for interacting with various Steam features" name = "steam" optional = false python-versions = "*" -version = "0.9.1" +version = "1.0.0" [package.dependencies] -cryptography = ">=1.3" -gevent = ">=1.2.0" -gevent-eventemitter = ">=2.0" -protobuf = ">=3.0.0" -requests = ">=2.9.1" +cachetools = ">=3.0.0" +pycryptodomex = ">=3.7.0" +requests = ">=2.9.1,<2.22.0" six = ">=1.10" -vdf = ">=2.0" +vdf = ">=3.3" + +[package.extras] +client = ["gevent (>=1.3.0)", "protobuf (>=3.0.0)", "gevent-eventemitter (>=2.1)"] [[package]] category = "main" @@ -653,7 +618,7 @@ description = "Python Library for Tom's Obvious, Minimal Language" name = "toml" optional = false python-versions = "*" -version = "0.10.0" +version = "0.10.1" [[package]] category = "main" @@ -679,12 +644,11 @@ category = "main" description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.9" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" +version = "1.24.3" [package.extras] -brotli = ["brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] @@ -748,7 +712,7 @@ python-versions = "*" version = "2020.5.8" [metadata] -content-hash = "d8d544d6f79b7389ef160d65a596fd18e07ab31bd035d1ebfc2cf3dbb9c36a0f" +content-hash = "9245b7ae163a3746554cd31e3b20294d26aa3534cc78303a419ac54850db55cb" python-versions = "^3.8" [metadata.files] @@ -794,6 +758,10 @@ bcrypt = [ {file = "bcrypt-3.1.7-cp38-cp38-win_amd64.whl", hash = "sha256:6305557019906466fc42dbc53b46da004e72fd7a551c044a827e572c82191752"}, {file = "bcrypt-3.1.7.tar.gz", hash = "sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42"}, ] +cachetools = [ + {file = "cachetools-4.1.0-py3-none-any.whl", hash = "sha256:de5d88f87781602201cde465d3afe837546663b168e8b39df67411b0bf10cefc"}, + {file = "cachetools-4.1.0.tar.gz", hash = "sha256:1d057645db16ca7fe1f3bd953558897603d6f0b9c51ed9d11eb4d071ec4e2aab"}, +] certifi = [ {file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"}, {file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"}, @@ -897,58 +865,6 @@ filetype = [ future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, ] -gevent = [ - {file = "gevent-20.5.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:efd9546468502a30ddd4699c3124ccb9d3099130f9b5ae1e2a54ad5b46e86120"}, - {file = "gevent-20.5.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff477b6d275396123faf8ce2d5b82f96d85ba264e0b9d4b56a2bac49d1b9adc"}, - {file = "gevent-20.5.0-cp27-cp27m-win32.whl", hash = "sha256:92edc18a357473e01a4e4a82c073ed3c99ceca6e3ce93c23668dd4a2401f07dc"}, - {file = "gevent-20.5.0-cp27-cp27m-win_amd64.whl", hash = "sha256:1dd95433be45e1115053878366e3f5332ae99c39cb345be23851327c062b9f4a"}, - {file = "gevent-20.5.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:fcb64f3a28420d1b872b7ef41b12e8a1a4dcadfc8eff3c09993ab0cdf52584a1"}, - {file = "gevent-20.5.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:4d2729dd4bf9c4d0f29482f53cdf9fc90a498aebb5cd7ae8b45d35657437d2ac"}, - {file = "gevent-20.5.0-cp35-cp35m-win32.whl", hash = "sha256:00b03601b8dd1ee2aa07811cb60a4befe36173b15d91c6e207e37f8d77dd6fac"}, - {file = "gevent-20.5.0-cp35-cp35m-win_amd64.whl", hash = "sha256:937d36730f2b0dee3387712074b1f15b802e2e074a3d7c6dcaf70521236d607c"}, - {file = "gevent-20.5.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:929c33df8e9bcbe31906024fcd21580bd018196dbd3249eb5b2f19d63e11092d"}, - {file = "gevent-20.5.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:52e5cd607749ed3b8aa0272cacf2c11deec61fca4c3bec57a9fea8c49316627d"}, - {file = "gevent-20.5.0-cp36-cp36m-win32.whl", hash = "sha256:15eae3cd450dac7dae7f4ac59e01db1378965c9ef565c39c5ae78c5a888f9ac9"}, - {file = "gevent-20.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9b4e940fc6071afebb86ba5f48dbb5f1fc3cb96ebeb8cf145eb5b499e9c6ee33"}, - {file = "gevent-20.5.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:e01d5373528e4ebdde66dc47a608d225fa3c4408ccd828d26c49b7ff75d82bd9"}, - {file = "gevent-20.5.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:31dc5d4ab8172cc00c4ff17cb18edee633babd961f64bf54214244d769bc3a74"}, - {file = "gevent-20.5.0-cp37-cp37m-win32.whl", hash = "sha256:0acc15ba2ac2a555529ad82d5a28fc85dbb6b2ff947657d67bebfd352e2b5c14"}, - {file = "gevent-20.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a7805934e8ce81610b61f806572c3d504cedd698cc8c9460d78d2893ba598c4a"}, - {file = "gevent-20.5.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5c604179cebcc57f10505d8db177b92a715907815a464b066e7eba322d1c33ac"}, - {file = "gevent-20.5.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:88c76df4967c5229f853aa67ad1b394d9e4f985b0359c9bc9879416bba3e7c68"}, - {file = "gevent-20.5.0-cp38-cp38-win32.whl", hash = "sha256:d07a2afe4215731eb57d5b257a2e7e7e170d8a7ae1f02f6d0682cd3403debea9"}, - {file = "gevent-20.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:28b7d83b4327ceb79668eca2049bf4b9ce66d5ace18a88335e3035b573f889fd"}, - {file = "gevent-20.5.0-pp27-pypy_73-win32.whl", hash = "sha256:38db524ea88d81d596b2cbb6948fced26654a15fec40ea4529224e239a6f45e8"}, - {file = "gevent-20.5.0.tar.gz", hash = "sha256:1dc7f1f6bc1f67d625e4272b01e717eba0b4fa024d2ff7934c8d320674d6f7fa"}, -] -gevent-eventemitter = [ - {file = "gevent-eventemitter-2.1.tar.gz", hash = "sha256:00e6e688c6a255f7bdcef1d8c999e0d02d9ab87d3c6ff626e6dc1a09762107f4"}, - {file = "gevent_eventemitter-2.1-py2.py3-none-any.whl", hash = "sha256:30605a9fbb1f38b2511f188a2e7a1b4e9262f3c13bf810ac5b79cc0ba2900ff7"}, -] -greenlet = [ - {file = "greenlet-0.4.15-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99a26afdb82ea83a265137a398f570402aa1f2b5dfb4ac3300c026931817b163"}, - {file = "greenlet-0.4.15-cp27-cp27m-win32.whl", hash = "sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87"}, - {file = "greenlet-0.4.15-cp27-cp27m-win_amd64.whl", hash = "sha256:9854f612e1b59ec66804931df5add3b2d5ef0067748ea29dc60f0efdcda9a638"}, - {file = "greenlet-0.4.15-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ac57fcdcfb0b73bb3203b58a14501abb7e5ff9ea5e2edfa06bb03035f0cff248"}, - {file = "greenlet-0.4.15-cp33-cp33m-win32.whl", hash = "sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720"}, - {file = "greenlet-0.4.15-cp33-cp33m-win_amd64.whl", hash = "sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28"}, - {file = "greenlet-0.4.15-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939"}, - {file = "greenlet-0.4.15-cp34-cp34m-win32.whl", hash = "sha256:8b4572c334593d449113f9dc8d19b93b7b271bdbe90ba7509eb178923327b625"}, - {file = "greenlet-0.4.15-cp34-cp34m-win_amd64.whl", hash = "sha256:a9f145660588187ff835c55a7d2ddf6abfc570c2651c276d3d4be8a2766db490"}, - {file = "greenlet-0.4.15-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0"}, - {file = "greenlet-0.4.15-cp35-cp35m-win32.whl", hash = "sha256:a19bf883b3384957e4a4a13e6bd1ae3d85ae87f4beb5957e35b0be287f12f4e4"}, - {file = "greenlet-0.4.15-cp35-cp35m-win_amd64.whl", hash = "sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6"}, - {file = "greenlet-0.4.15-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8"}, - {file = "greenlet-0.4.15-cp36-cp36m-win32.whl", hash = "sha256:000546ad01e6389e98626c1367be58efa613fa82a1be98b0c6fc24b563acc6d0"}, - {file = "greenlet-0.4.15-cp36-cp36m-win_amd64.whl", hash = "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656"}, - {file = "greenlet-0.4.15-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214"}, - {file = "greenlet-0.4.15-cp37-cp37m-win32.whl", hash = "sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043"}, - {file = "greenlet-0.4.15-cp37-cp37m-win_amd64.whl", hash = "sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304"}, - {file = "greenlet-0.4.15-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e538b8dae561080b542b0f5af64d47ef859f22517f7eca617bb314e0e03fd7ef"}, - {file = "greenlet-0.4.15-cp38-cp38-win32.whl", hash = "sha256:51155342eb4d6058a0ffcd98a798fe6ba21195517da97e15fca3db12ab201e6e"}, - {file = "greenlet-0.4.15-cp38-cp38-win_amd64.whl", hash = "sha256:7457d685158522df483196b16ec648b28f8e847861adb01a55d41134e7734122"}, - {file = "greenlet-0.4.15.tar.gz", hash = "sha256:9416443e219356e3c31f1f918a91badf2e37acf297e2fa13d24d1cc2380f8fbc"}, -] h11 = [ {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, @@ -961,52 +877,31 @@ humanfriendly = [ {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, ] idna = [ - {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, - {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, + {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, + {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, ] multidict = [ - {file = "multidict-4.7.5-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"}, - {file = "multidict-4.7.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35"}, - {file = "multidict-4.7.5-cp35-cp35m-win32.whl", hash = "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1"}, - {file = "multidict-4.7.5-cp35-cp35m-win_amd64.whl", hash = "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd"}, - {file = "multidict-4.7.5-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20"}, - {file = "multidict-4.7.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136"}, - {file = "multidict-4.7.5-cp36-cp36m-win32.whl", hash = "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e"}, - {file = "multidict-4.7.5-cp36-cp36m-win_amd64.whl", hash = "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78"}, - {file = "multidict-4.7.5-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8"}, - {file = "multidict-4.7.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab"}, - {file = "multidict-4.7.5-cp37-cp37m-win32.whl", hash = "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928"}, - {file = "multidict-4.7.5-cp37-cp37m-win_amd64.whl", hash = "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1"}, - {file = "multidict-4.7.5-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4"}, - {file = "multidict-4.7.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2"}, - {file = "multidict-4.7.5-cp38-cp38-win32.whl", hash = "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5"}, - {file = "multidict-4.7.5-cp38-cp38-win_amd64.whl", hash = "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969"}, - {file = "multidict-4.7.5.tar.gz", hash = "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e"}, + {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"}, + {file = "multidict-4.7.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a"}, + {file = "multidict-4.7.6-cp35-cp35m-win32.whl", hash = "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5"}, + {file = "multidict-4.7.6-cp35-cp35m-win_amd64.whl", hash = "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3"}, + {file = "multidict-4.7.6-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87"}, + {file = "multidict-4.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2"}, + {file = "multidict-4.7.6-cp36-cp36m-win32.whl", hash = "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7"}, + {file = "multidict-4.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463"}, + {file = "multidict-4.7.6-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"}, + {file = "multidict-4.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255"}, + {file = "multidict-4.7.6-cp37-cp37m-win32.whl", hash = "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507"}, + {file = "multidict-4.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c"}, + {file = "multidict-4.7.6-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b"}, + {file = "multidict-4.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7"}, + {file = "multidict-4.7.6-cp38-cp38-win32.whl", hash = "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d"}, + {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.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, - {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, -] -protobuf = [ - {file = "protobuf-3.11.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481"}, - {file = "protobuf-3.11.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7"}, - {file = "protobuf-3.11.3-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a"}, - {file = "protobuf-3.11.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961"}, - {file = "protobuf-3.11.3-cp35-cp35m-win32.whl", hash = "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80"}, - {file = "protobuf-3.11.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306"}, - {file = "protobuf-3.11.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a"}, - {file = "protobuf-3.11.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151"}, - {file = "protobuf-3.11.3-cp36-cp36m-win32.whl", hash = "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab"}, - {file = "protobuf-3.11.3-cp36-cp36m-win_amd64.whl", hash = "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956"}, - {file = "protobuf-3.11.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2"}, - {file = "protobuf-3.11.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07"}, - {file = "protobuf-3.11.3-cp37-cp37m-win32.whl", hash = "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a"}, - {file = "protobuf-3.11.3-cp37-cp37m-win_amd64.whl", hash = "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee"}, - {file = "protobuf-3.11.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4"}, - {file = "protobuf-3.11.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0"}, - {file = "protobuf-3.11.3-py2.7.egg", hash = "sha256:2affcaba328c4662f3bc3c0e9576ea107906b2c2b6422344cdad961734ff6b93"}, - {file = "protobuf-3.11.3-py2.py3-none-any.whl", hash = "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f"}, - {file = "protobuf-3.11.3.tar.gz", hash = "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f"}, + {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"}, @@ -1044,6 +939,38 @@ pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] +pycryptodomex = [ + {file = "pycryptodomex-3.9.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:a3f2908666e6f74b8c4893f86dd02e16170f50e4a78ae7f3468b6208d54bc205"}, + {file = "pycryptodomex-3.9.7-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1537d2d15b604b303aef56e7f440895a1c81adbee786b91f1f06eddc34da5314"}, + {file = "pycryptodomex-3.9.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5cf306a17cccc327a33cdc3845629fa13f4573a4ec620ed607c79cf6785f2e27"}, + {file = "pycryptodomex-3.9.7-cp27-cp27m-win32.whl", hash = "sha256:37033976f72af829fe15f7fe5fe1dbed308cc43a98d9dd9d2a0a76de8ca5ee78"}, + {file = "pycryptodomex-3.9.7-cp27-cp27m-win_amd64.whl", hash = "sha256:ebfc2f885cafda076c31ae30fa0dd81e7e919ec34059a88d3018ed66e83fcce3"}, + {file = "pycryptodomex-3.9.7-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:5fff8da399af16a1855f58771223acbbdac720b9969cd03fc5013d2e9a7bd9a4"}, + {file = "pycryptodomex-3.9.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f7e5fc5e124200b19a14be33fb0099e956e6ebb5e25d287b0829ef0a78ed76c7"}, + {file = "pycryptodomex-3.9.7-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:e76e6638ead4a7d93262a24218f0ff3ff74de6b6c823b7e19dccb31b6a481978"}, + {file = "pycryptodomex-3.9.7-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:6b3a9a562688996f760b5077714c3ab8b62ca56061b6e9ab7906841e43e19f91"}, + {file = "pycryptodomex-3.9.7-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:4c93038ac011b36512cb0bf2ee3e2aec774e8bc81021d015917c89fe02bb0ee5"}, + {file = "pycryptodomex-3.9.7-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:87aa70daad6f039e814790a06422a3189311198b674b62f13933a2bdcb6b1bcc"}, + {file = "pycryptodomex-3.9.7-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3c3dd9d4c9c1e279d3945ae422895c901f98987333acc132dc094faf52afec35"}, + {file = "pycryptodomex-3.9.7-cp35-cp35m-win32.whl", hash = "sha256:59b0ea9cda5490f924771456912a225d8d9e678891f9f986661af718534719b2"}, + {file = "pycryptodomex-3.9.7-cp35-cp35m-win_amd64.whl", hash = "sha256:99be3a1df2b2b9f731ebe1c264a2c07c465e71cee68e35e1640b645b5213a755"}, + {file = "pycryptodomex-3.9.7-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:68650ce5b9f7152b8283302a4617269f821695a612692640dd247bd12ab21c0b"}, + {file = "pycryptodomex-3.9.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7e938ed51a59e29431ea86fab60423ada2757728db0f78952329fa02a789bd31"}, + {file = "pycryptodomex-3.9.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f5797a39933a3d41526da60856735e6684b2b71a8ca99d5f79555ca121be2f4b"}, + {file = "pycryptodomex-3.9.7-cp36-cp36m-win32.whl", hash = "sha256:e585d530764c459cbd5d460aed0288807bb881f376ca9a20e653645217895961"}, + {file = "pycryptodomex-3.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:45ee555fc5e28c119a46d44ce373f5237e54a35c61b750fb3a94446b09855dbc"}, + {file = "pycryptodomex-3.9.7-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:d2c3c280975638e2a2c2fd9cb36ab111980219757fa163a2755594b9448e4138"}, + {file = "pycryptodomex-3.9.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1d20ab8369b7558168fc014a0745c678613f9f486dae468cca2d68145196b8a4"}, + {file = "pycryptodomex-3.9.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:b1515ce3a8a2c3fa537d137c5ca5f8b7a902044d04e07d7c3aa26c3e026120fb"}, + {file = "pycryptodomex-3.9.7-cp37-cp37m-win32.whl", hash = "sha256:afb4c2fa3c6f492fd9a8b38d76e13f32d429b8e5e1e00238309391b5591cde0d"}, + {file = "pycryptodomex-3.9.7-cp37-cp37m-win_amd64.whl", hash = "sha256:c436919117c23355740c669f89720673578b9aa4569bbfe105f6c10101fc1966"}, + {file = "pycryptodomex-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fb350e31e55211fec8ddc89fc0256f3b9bc3b44b68a8bde1cf44b3b4e80c0e42"}, + {file = "pycryptodomex-3.9.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ae3d44a639fd11dbdeca47e35e94febb1ee8bc15daf26673331add37146e0b85"}, + {file = "pycryptodomex-3.9.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3c9b3fba037ea52c626060c5a87ee6de7e86c99e8a7c6ee07302539985d2bd64"}, + {file = "pycryptodomex-3.9.7-cp38-cp38-win32.whl", hash = "sha256:bf391b377413a197000b43ef2b74359974d8927d329a897c9f5ba7b63dca7b9c"}, + {file = "pycryptodomex-3.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:1ecc9db7409db67765eb008e558879d298406642d33ade43a6488224d23e8081"}, + {file = "pycryptodomex-3.9.7.tar.gz", hash = "sha256:50163324834edd0c9ce3e4512ded3e221c969086e10fdd5d3fdcaadac5e24a78"}, +] pynacl = [ {file = "PyNaCl-1.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621"}, {file = "PyNaCl-1.3.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39"}, @@ -1092,39 +1019,39 @@ pytz = [ {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, ] regex = [ - {file = "regex-2020.5.7-cp27-cp27m-win32.whl", hash = "sha256:5493a02c1882d2acaaf17be81a3b65408ff541c922bfd002535c5f148aa29f74"}, - {file = "regex-2020.5.7-cp27-cp27m-win_amd64.whl", hash = "sha256:021a0ae4d2baeeb60a3014805a2096cb329bd6d9f30669b7ad0da51a9cb73349"}, - {file = "regex-2020.5.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4df91094ced6f53e71f695c909d9bad1cca8761d96fd9f23db12245b5521136e"}, - {file = "regex-2020.5.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7ce4a213a96d6c25eeae2f7d60d4dad89ac2b8134ec3e69db9bc522e2c0f9388"}, - {file = "regex-2020.5.7-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b059e2476b327b9794c792c855aa05531a3f3044737e455d283c7539bd7534d"}, - {file = "regex-2020.5.7-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:652ab4836cd5531d64a34403c00ada4077bb91112e8bcdae933e2eae232cf4a8"}, - {file = "regex-2020.5.7-cp36-cp36m-win32.whl", hash = "sha256:1e2255ae938a36e9bd7db3b93618796d90c07e5f64dd6a6750c55f51f8b76918"}, - {file = "regex-2020.5.7-cp36-cp36m-win_amd64.whl", hash = "sha256:8127ca2bf9539d6a64d03686fd9e789e8c194fc19af49b69b081f8c7e6ecb1bc"}, - {file = "regex-2020.5.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f7f2f4226db6acd1da228adf433c5c3792858474e49d80668ea82ac87cf74a03"}, - {file = "regex-2020.5.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2bc6a17a7fa8afd33c02d51b6f417fc271538990297167f68a98cae1c9e5c945"}, - {file = "regex-2020.5.7-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:b7c9f65524ff06bf70c945cd8d8d1fd90853e27ccf86026af2afb4d9a63d06b1"}, - {file = "regex-2020.5.7-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:fa09da4af4e5b15c0e8b4986a083f3fd159302ea115a6cc0649cd163435538b8"}, - {file = "regex-2020.5.7-cp37-cp37m-win32.whl", hash = "sha256:669a8d46764a09f198f2e91fc0d5acdac8e6b620376757a04682846ae28879c4"}, - {file = "regex-2020.5.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b5b5b2e95f761a88d4c93691716ce01dc55f288a153face1654f868a8034f494"}, - {file = "regex-2020.5.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0ff50843535593ee93acab662663cb2f52af8e31c3f525f630f1dc6156247938"}, - {file = "regex-2020.5.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:1b17bf37c2aefc4cac8436971fe6ee52542ae4225cfc7762017f7e97a63ca998"}, - {file = "regex-2020.5.7-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:04d6e948ef34d3eac133bedc0098364a9e635a7914f050edb61272d2ddae3608"}, - {file = "regex-2020.5.7-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5b741ecc3ad3e463d2ba32dce512b412c319993c1bb3d999be49e6092a769fb2"}, - {file = "regex-2020.5.7-cp38-cp38-win32.whl", hash = "sha256:099568b372bda492be09c4f291b398475587d49937c659824f891182df728cdf"}, - {file = "regex-2020.5.7-cp38-cp38-win_amd64.whl", hash = "sha256:3ab5e41c4ed7cd4fa426c50add2892eb0f04ae4e73162155cd668257d02259dd"}, - {file = "regex-2020.5.7.tar.gz", hash = "sha256:73a10404867b835f1b8a64253e4621908f0d71150eb4e97ab2e7e441b53e9451"}, + {file = "regex-2020.5.14-cp27-cp27m-win32.whl", hash = "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e"}, + {file = "regex-2020.5.14-cp27-cp27m-win_amd64.whl", hash = "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577"}, + {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd"}, + {file = "regex-2020.5.14-cp36-cp36m-win32.whl", hash = "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994"}, + {file = "regex-2020.5.14-cp36-cp36m-win_amd64.whl", hash = "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c"}, + {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f"}, + {file = "regex-2020.5.14-cp37-cp37m-win32.whl", hash = "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929"}, + {file = "regex-2020.5.14-cp37-cp37m-win_amd64.whl", hash = "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe"}, + {file = "regex-2020.5.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7"}, + {file = "regex-2020.5.14-cp38-cp38-win32.whl", hash = "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927"}, + {file = "regex-2020.5.14-cp38-cp38-win_amd64.whl", hash = "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108"}, + {file = "regex-2020.5.14.tar.gz", hash = "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5"}, ] requests = [ - {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, - {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, + {file = "requests-2.21.0-py2.py3-none-any.whl", hash = "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"}, + {file = "requests-2.21.0.tar.gz", hash = "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e"}, ] riotwatcher = [ {file = "riotwatcher-2.7.1-py2.py3-none-any.whl", hash = "sha256:3fb03b20f768cea7830d54c6d301a8341c67223625ac8536d26d1c140af3dcb0"}, {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.8.7-py3-none-any.whl", hash = "sha256:5fee088e02ec375b580af48e03894db2ca2edd10c19f7fcbfdacf0a6e07622e7"}, - {file = "royalnet-5.8.7.tar.gz", hash = "sha256:a72fd52e2ed9fa2a8163859ac93b517ec684348d44f5c0b09146c9880430f67b"}, + {file = "royalnet-5.8.9-py3-none-any.whl", hash = "sha256:a64ed18c513b4ea708cc93db0db53099b6e9e40f63374b1bb8d924bf057e31c2"}, + {file = "royalnet-5.8.9.tar.gz", hash = "sha256:50b5a3453bd1018b8846018fd7ce64046b4b669cce780564a8a871cd8c569d6d"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1138,36 +1065,44 @@ six = [ {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.16-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:8d8c21e9d4efef01351bf28513648ceb988031be4159745a7ad1b3e28c8ff68a"}, - {file = "SQLAlchemy-1.3.16-cp27-cp27m-win32.whl", hash = "sha256:083e383a1dca8384d0ea6378bd182d83c600ed4ff4ec8247d3b2442cf70db1ad"}, - {file = "SQLAlchemy-1.3.16-cp27-cp27m-win_amd64.whl", hash = "sha256:128f6179325f7597a46403dde0bf148478f868df44841348dfc8d158e00db1f9"}, - {file = "SQLAlchemy-1.3.16-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:6056b671aeda3fc451382e52ab8a753c0d5f66ef2a5ccc8fa5ba7abd20988b4d"}, - {file = "SQLAlchemy-1.3.16-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:7025c639ce7e170db845e94006cf5f404e243e6fc00d6c86fa19e8ad8d411880"}, - {file = "SQLAlchemy-1.3.16-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e18752cecaef61031252ca72031d4d6247b3212ebb84748fc5d1a0d2029c23ea"}, - {file = "SQLAlchemy-1.3.16-cp36-cp36m-win32.whl", hash = "sha256:0a690a6486658d03cc6a73536d46e796b6570ac1f8a7ec133f9e28c448b69828"}, - {file = "SQLAlchemy-1.3.16-cp36-cp36m-win_amd64.whl", hash = "sha256:d00b393f05dbd4ecd65c989b7f5a81110eae4baea7a6a4cdd94c20a908d1456e"}, - {file = "SQLAlchemy-1.3.16-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:114b6ace30001f056e944cebd46daef38fdb41ebb98f5e5940241a03ed6cad43"}, - {file = "SQLAlchemy-1.3.16-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:13d48cd8b925b6893a4e59b2dfb3e59a5204fd8c98289aad353af78bd214db49"}, - {file = "SQLAlchemy-1.3.16-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:211a1ce7e825f7142121144bac76f53ac28b12172716a710f4bf3eab477e730b"}, - {file = "SQLAlchemy-1.3.16-cp37-cp37m-win32.whl", hash = "sha256:68d78cf4a9dfade2e6cf57c4be19f7b82ed66e67dacf93b32bb390c9bed12749"}, - {file = "SQLAlchemy-1.3.16-cp37-cp37m-win_amd64.whl", hash = "sha256:2dc57ee80b76813759cccd1a7affedf9c4dbe5b065a91fb6092c9d8151d66078"}, - {file = "SQLAlchemy-1.3.16-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:43078c7ec0457387c79b8d52fff90a7ad352ca4c7aa841c366238c3e2cf52fdf"}, - {file = "SQLAlchemy-1.3.16-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb545da054e6297242a1bb1ba88e7a8ffb679f518258d66798ec712b82e4e07"}, - {file = "SQLAlchemy-1.3.16-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5b1bf3c2c2dca738235ce08079783ef04f1a7fc5b21cf24adaae77f2da4e73c3"}, - {file = "SQLAlchemy-1.3.16-cp38-cp38-win32.whl", hash = "sha256:3e625e283eecc15aee5b1ef77203bfb542563fa4a9aa622c7643c7b55438ff49"}, - {file = "SQLAlchemy-1.3.16-cp38-cp38-win_amd64.whl", hash = "sha256:7d98e0785c4cd7ae30b4a451416db71f5724a1839025544b4edbd92e00b91f0f"}, - {file = "SQLAlchemy-1.3.16.tar.gz", hash = "sha256:7224e126c00b8178dfd227bc337ba5e754b197a3867d33b9f30dc0208f773d70"}, + {file = "SQLAlchemy-1.3.17-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:fe01bac7226499aedf472c62fa3b85b2c619365f3f14dd222ffe4f3aa91e5f98"}, + {file = "SQLAlchemy-1.3.17-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b50f45d0e82b4562f59f0e0ca511f65e412f2a97d790eea5f60e34e5f1aabc9a"}, + {file = "SQLAlchemy-1.3.17-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:ce2646e4c0807f3461be0653502bb48c6e91a5171d6e450367082c79e12868bf"}, + {file = "SQLAlchemy-1.3.17-cp27-cp27m-win32.whl", hash = "sha256:e4e2664232005bd306f878b0f167a31f944a07c4de0152c444f8c61bbe3cfb38"}, + {file = "SQLAlchemy-1.3.17-cp27-cp27m-win_amd64.whl", hash = "sha256:925b4fe5e7c03ed76912b75a9a41dfd682d59c0be43bce88d3b27f7f5ba028fb"}, + {file = "SQLAlchemy-1.3.17-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:869bbb637de58ab0a912b7f20e9192132f9fbc47fc6b5111cd1e0f6cdf5cf9b0"}, + {file = "SQLAlchemy-1.3.17-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:703c002277f0fbc3c04d0ae4989a174753a7554b2963c584ce2ec0cddcf2bc53"}, + {file = "SQLAlchemy-1.3.17-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:eb4fcf7105bf071c71068c6eee47499ab8d4b8f5a11fc35147c934f0faa60f23"}, + {file = "SQLAlchemy-1.3.17-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8d01e949a5d22e5c4800d59b50617c56125fc187fbeb8fa423e99858546de616"}, + {file = "SQLAlchemy-1.3.17-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a9e75e49a0f1583eee0ce93270232b8e7bb4b1edc89cc70b07600d525aef4f43"}, + {file = "SQLAlchemy-1.3.17-cp35-cp35m-win32.whl", hash = "sha256:a87d496884f40c94c85a647c385f4fd5887941d2609f71043e2b73f2436d9c65"}, + {file = "SQLAlchemy-1.3.17-cp35-cp35m-win_amd64.whl", hash = "sha256:6cd157ce74a911325e164441ff2d9b4e244659a25b3146310518d83202f15f7a"}, + {file = "SQLAlchemy-1.3.17-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:27e2efc8f77661c9af2681755974205e7462f1ae126f498f4fe12a8b24761d15"}, + {file = "SQLAlchemy-1.3.17-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:31c043d5211aa0e0773821fcc318eb5cbe2ec916dfbc4c6eea0c5188971988eb"}, + {file = "SQLAlchemy-1.3.17-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a9030cd30caf848a13a192c5e45367e3c6f363726569a56e75dc1151ee26d859"}, + {file = "SQLAlchemy-1.3.17-cp36-cp36m-win32.whl", hash = "sha256:f502ef245c492b391e0e23e94cba030ab91722dcc56963c85bfd7f3441ea2bbe"}, + {file = "SQLAlchemy-1.3.17-cp36-cp36m-win_amd64.whl", hash = "sha256:128bc917ed20d78143a45024455ff0aed7d3b96772eba13d5dbaf9cc57e5c41b"}, + {file = "SQLAlchemy-1.3.17-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:2a12f8be25b9ea3d1d5b165202181f2b7da4b3395289000284e5bb86154ce87c"}, + {file = "SQLAlchemy-1.3.17-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e8aa395482728de8bdcca9cc0faf3765ab483e81e01923aaa736b42f0294f570"}, + {file = "SQLAlchemy-1.3.17-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f35248f7e0d63b234a109dd72fbfb4b5cb6cb6840b221d0df0ecbf54ab087654"}, + {file = "SQLAlchemy-1.3.17-cp37-cp37m-win32.whl", hash = "sha256:ce1ddaadee913543ff0154021d31b134551f63428065168e756d90bdc4c686f5"}, + {file = "SQLAlchemy-1.3.17-cp37-cp37m-win_amd64.whl", hash = "sha256:9cb1819008f0225a7c066cac8bb0cf90847b2c4a6eb9ebb7431dbd00c56c06c5"}, + {file = "SQLAlchemy-1.3.17-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:65eb3b03229f684af0cf0ad3bcc771970c1260a82a791a8d07bffb63d8c95bcc"}, + {file = "SQLAlchemy-1.3.17-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8a0e0cd21da047ea10267c37caf12add400a92f0620c8bc09e4a6531a765d6d7"}, + {file = "SQLAlchemy-1.3.17-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:b7878e59ec31f12d54b3797689402ee3b5cfcb5598f2ebf26491732758751908"}, + {file = "SQLAlchemy-1.3.17-cp38-cp38-win32.whl", hash = "sha256:ce6c3d18b2a8ce364013d47b9cad71db815df31d55918403f8db7d890c9d07ae"}, + {file = "SQLAlchemy-1.3.17-cp38-cp38-win_amd64.whl", hash = "sha256:ed375a79f06cad285166e5be74745df1ed6845c5624aafadec4b7a29c25866ef"}, + {file = "SQLAlchemy-1.3.17.tar.gz", hash = "sha256:156a27548ba4e1fed944ff9fcdc150633e61d350d673ae7baaf6c25c04ac1f71"}, ] starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, ] steam = [ - {file = "steam-0.9.1.tar.gz", hash = "sha256:167240080ea23e346c11face96a6e9acc2827978c46c5ae25fa74e38031ff978"}, + {file = "steam-1.0.0.tar.gz", hash = "sha256:e02381de3ac428a4362c5f47c2ebb90b28791e320665b47ad0245817d9c05220"}, ] toml = [ - {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, - {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, - {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, + {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, + {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, ] tornado = [ {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"}, @@ -1185,8 +1120,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.24.3-py2.py3-none-any.whl", hash = "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"}, + {file = "urllib3-1.24.3.tar.gz", hash = "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4"}, ] uvicorn = [ {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, diff --git a/pyproject.toml b/pyproject.toml index 9e7f3275..3b50df1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.3" + version = "5.8.4" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -22,7 +22,7 @@ riotwatcher = "^2.7.1" royalspells = "^3.2" - steam = "^0.9.1" + steam = "*" [tool.poetry.dependencies.royalnet] version = "~5.8.7" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 7c743bfc..8125a946 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -56,6 +56,7 @@ from .elevatormusic import ElevatormusicCommand from .royalpack import RoyalpackCommand from .givefiorygi import GivefiorygiCommand from .help import HelpCommand +from .pug import PugCommand # Enter the commands of your Pack here! available_commands = [ @@ -116,6 +117,7 @@ available_commands = [ RoyalpackCommand, GivefiorygiCommand, HelpCommand, + PugCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/pug.py b/royalpack/commands/pug.py new file mode 100644 index 00000000..97b66834 --- /dev/null +++ b/royalpack/commands/pug.py @@ -0,0 +1,26 @@ +from typing import * +import royalnet.commands as rc +import aiohttp +import io + + +class PugCommand(rc.Command): + name: str = "pug" + + description: str = "Invia un carlino casuale in chat." + + syntax: str = "" + + aliases = ["carlino", "carlo", "mallllco"] + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + async with aiohttp.ClientSession() as session: + async with session.get("https://dog.ceo/api/breed/pug/images/random") as response: + result = await response.json() + assert "status" in result + assert result["status"] == "success" + assert "message" in result + url = result["message"] + async with session.get(url) as response: + img = await response.content.read() + await data.reply_image(image=io.BytesIO(img)) diff --git a/royalpack/version.py b/royalpack/version.py index e489a4b9..d208b76b 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.3" +semantic = "5.8.4" From cb37a65a81ffbccec430c6f9de00c70b0695847f Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 21 May 2020 15:16:03 +0200 Subject: [PATCH 143/227] Add treasures --- royalpack/commands/__init__.py | 4 +++ royalpack/commands/createtreasure.py | 43 ++++++++++++++++++++++++++++ royalpack/commands/treasure.py | 33 +++++++++++++++++++++ royalpack/tables/__init__.py | 2 ++ royalpack/tables/treasure.py | 23 +++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 royalpack/commands/createtreasure.py create mode 100644 royalpack/commands/treasure.py create mode 100644 royalpack/tables/treasure.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 8125a946..fca178ba 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -57,6 +57,8 @@ from .royalpack import RoyalpackCommand from .givefiorygi import GivefiorygiCommand from .help import HelpCommand from .pug import PugCommand +from .createtreasure import CreatetreasureCommand +from .treasure import TreasureCommand # Enter the commands of your Pack here! available_commands = [ @@ -118,6 +120,8 @@ available_commands = [ GivefiorygiCommand, HelpCommand, PugCommand, + CreatetreasureCommand, + TreasureCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/createtreasure.py b/royalpack/commands/createtreasure.py new file mode 100644 index 00000000..d49a75f8 --- /dev/null +++ b/royalpack/commands/createtreasure.py @@ -0,0 +1,43 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import royalnet.utils as ru +from ..tables import Treasure + + +class CreatetreasureCommand(rc.Command): + name: str = "createtreasure" + + description: str = "Crea un nuovo tesoro di Fiorygi." + + syntax: str = "{codice} {valore}" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + author = await data.get_author(error_if_none=True) + if "banker" not in author.roles: + raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") + + code = args[0] + try: + value = int(args[1]) + except ValueError: + raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.") + if value < 0: + raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.") + + TreasureT = self.alchemy.get(Treasure) + + treasure = await ru.asyncify(data.session.query(TreasureT).get, code) + if treasure is not None: + raise rc.UserError("Esiste già un Treasure con quel codice.") + + treasure = TreasureT( + code=code, + value=value, + redeemed_by=None + ) + data.session.add(treasure) + await data.session_commit() + + await data.delete_invoking() + await data.reply("✅ Tesoro creato!") diff --git a/royalpack/commands/treasure.py b/royalpack/commands/treasure.py new file mode 100644 index 00000000..70d58482 --- /dev/null +++ b/royalpack/commands/treasure.py @@ -0,0 +1,33 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import royalnet.utils as ru +from ..tables import Treasure, FiorygiTransaction + + +class TreasureCommand(rc.Command): + name: str = "treasure" + + description: str = "Riscatta un Treasure che hai trovato da qualche parte." + + syntax: str = "{code}" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + author = await data.get_author(error_if_none=True) + code = args[0] + + 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.redeemed_by = author + await data.session_commit() + await FiorygiTransaction.spawn_fiorygi(data, + author, + treasure.value, + f'aver trovato il tesoro "{treasure.code}"') + await data.reply("🤑 Tesoro riscattato!") diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 6e8a6937..6eac5697 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -17,6 +17,7 @@ from .brawlhalladuos import BrawlhallaDuo from .mmevents import MMEvent from .mmresponse import MMResponse from .cvstats import Cvstats +from .treasure import Treasure # Enter the tables of your Pack here! available_tables = [ @@ -38,6 +39,7 @@ available_tables = [ MMEvent, MMResponse, Cvstats, + Treasure, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/treasure.py b/royalpack/tables/treasure.py new file mode 100644 index 00000000..daf1018a --- /dev/null +++ b/royalpack/tables/treasure.py @@ -0,0 +1,23 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr + + +class Treasure: + __tablename__ = "treasures" + + @declared_attr + def code(self): + return Column(String, primary_key=True) + + @declared_attr + def redeemed_by_id(self): + return Column(Integer, ForeignKey("users.uid")) + + @declared_attr + def redeemed_by(self): + return relationship("User") + + @declared_attr + def value(self): + return Column(Integer, nullable=False) From 0c5ab3c1d8218f849862657a00cd040fc89d021f Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 21 May 2020 15:17:22 +0200 Subject: [PATCH 144/227] publish: 5.8.5 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3b50df1c..205eeefa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.4" + version = "5.8.5" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index d208b76b..8454abc1 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.4" +semantic = "5.8.5" From 78b435ccb1479d19afdbd6aeed2cc4b86d534d5b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 21 May 2020 18:56:20 +0200 Subject: [PATCH 145/227] publish: 5.8.6 --- pyproject.toml | 2 +- royalpack/commands/__init__.py | 2 +- royalpack/commands/givetreasure.py | 37 +++++++++++++++++ .../{createtreasure.py => magicktreasure.py} | 40 ++++++++++++------- royalpack/version.py | 2 +- 5 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 royalpack/commands/givetreasure.py rename royalpack/commands/{createtreasure.py => magicktreasure.py} (69%) diff --git a/pyproject.toml b/pyproject.toml index 205eeefa..9506e992 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.5" + version = "5.8.6" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index fca178ba..e6d40c58 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -57,7 +57,7 @@ from .royalpack import RoyalpackCommand from .givefiorygi import GivefiorygiCommand from .help import HelpCommand from .pug import PugCommand -from .createtreasure import CreatetreasureCommand +from .magicktreasure import CreatetreasureCommand from .treasure import TreasureCommand # Enter the commands of your Pack here! diff --git a/royalpack/commands/givetreasure.py b/royalpack/commands/givetreasure.py new file mode 100644 index 00000000..40a8b10d --- /dev/null +++ b/royalpack/commands/givetreasure.py @@ -0,0 +1,37 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import royalnet.utils as ru +from ..tables import Treasure, FiorygiTransaction +from .magicktreasure import MagicktreasureCommand + + +class GivetreasureCommand(MagicktreasureCommand): + name: str = "givetreasure" + + description: str = "Crea un nuovo Treasure di Fiorygi (usando il tuo credito)" + + syntax: str = "{codice} {valore}" + + async def _permission_check(self, author, code, value, data): + if "banker" not in author.roles: + raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") + 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): + TreasureT = self.alchemy.get(Treasure) + + treasure = await ru.asyncify(data.session.query(TreasureT).get, code) + if treasure is not None: + raise rc.UserError("Esiste già un Treasure con quel codice.") + + treasure = TreasureT( + code=code, + value=value, + redeemed_by=None + ) + + await FiorygiTransaction.spawn_fiorygi(data, author, -value, "aver creato un tesoro") + + return treasure diff --git a/royalpack/commands/createtreasure.py b/royalpack/commands/magicktreasure.py similarity index 69% rename from royalpack/commands/createtreasure.py rename to royalpack/commands/magicktreasure.py index d49a75f8..2b16b16f 100644 --- a/royalpack/commands/createtreasure.py +++ b/royalpack/commands/magicktreasure.py @@ -5,26 +5,19 @@ import royalnet.utils as ru from ..tables import Treasure -class CreatetreasureCommand(rc.Command): - name: str = "createtreasure" +class MagicktreasureCommand(rc.Command): + name: str = "magicktreasure" - description: str = "Crea un nuovo tesoro di Fiorygi." + description: str = "Crea un nuovo Treasure di Fiorygi (senza spendere i tuoi)." syntax: str = "{codice} {valore}" - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - author = await data.get_author(error_if_none=True) + async def _permission_check(self, author, code, value, data): if "banker" not in author.roles: raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") + return author - code = args[0] - try: - value = int(args[1]) - except ValueError: - raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.") - if value < 0: - raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.") - + async def _create_treasure(self, author, code, value, data): TreasureT = self.alchemy.get(Treasure) treasure = await ru.asyncify(data.session.query(TreasureT).get, code) @@ -36,8 +29,25 @@ class CreatetreasureCommand(rc.Command): value=value, redeemed_by=None ) + + return treasure + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + await data.delete_invoking() + author = await data.get_author(error_if_none=True) + + code = args[0] + try: + value = int(args[1]) + except ValueError: + raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.") + 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() - await data.delete_invoking() - await data.reply("✅ Tesoro creato!") + await data.reply("✅ Treasure creato!") diff --git a/royalpack/version.py b/royalpack/version.py index 8454abc1..206beda3 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.5" +semantic = "5.8.6" From d4f6475ea60bd1ff505a1fb8019f20131c45531c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 21 May 2020 18:59:31 +0200 Subject: [PATCH 146/227] publish: 5.8.7 --- pyproject.toml | 2 +- royalpack/commands/__init__.py | 6 ++++-- royalpack/version.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9506e992..21fc735b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.6" + version = "5.8.7" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index e6d40c58..48ce16ed 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -57,8 +57,9 @@ from .royalpack import RoyalpackCommand from .givefiorygi import GivefiorygiCommand from .help import HelpCommand from .pug import PugCommand -from .magicktreasure import CreatetreasureCommand +from .magicktreasure import MagicktreasureCommand from .treasure import TreasureCommand +from .givetreasure import GivetreasureCommand # Enter the commands of your Pack here! available_commands = [ @@ -120,8 +121,9 @@ available_commands = [ GivefiorygiCommand, HelpCommand, PugCommand, - CreatetreasureCommand, + MagicktreasureCommand, TreasureCommand, + GivetreasureCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/version.py b/royalpack/version.py index 206beda3..4a0eb5f0 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.6" +semantic = "5.8.7" From ca993087fee9cc0b64f1d1a78e3b2f5768b45a3a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 21 May 2020 19:09:40 +0200 Subject: [PATCH 147/227] publish: 5.8.8 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 21fc735b..49340c3a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.7" + version = "5.8.8" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 4a0eb5f0..a45c0f0b 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.7" +semantic = "5.8.8" From 49befa61bdfe8e6552e32ead4f02ffd6577526fe Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 22 May 2020 15:03:30 +0200 Subject: [PATCH 148/227] publish: 5.8.9 --- pyproject.toml | 2 +- royalpack/commands/givetreasure.py | 2 -- royalpack/version.py | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 49340c3a..5df58aec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.8" + version = "5.8.9" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/givetreasure.py b/royalpack/commands/givetreasure.py index 40a8b10d..554902b5 100644 --- a/royalpack/commands/givetreasure.py +++ b/royalpack/commands/givetreasure.py @@ -14,8 +14,6 @@ class GivetreasureCommand(MagicktreasureCommand): syntax: str = "{codice} {valore}" async def _permission_check(self, author, code, value, data): - if "banker" not in author.roles: - raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") if author.fiorygi.fiorygi < value: raise rc.UserError("Non hai abbastanza fiorygi per creare questo Treasure.") diff --git a/royalpack/version.py b/royalpack/version.py index a45c0f0b..d8460d48 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.8" +semantic = "5.8.9" From f3b4d674e5fe5fed5f9f699e35595662d4923095 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 24 May 2020 11:36:10 +0200 Subject: [PATCH 149/227] Make treasures case insensitive --- royalpack/commands/magicktreasure.py | 2 +- royalpack/commands/treasure.py | 2 +- royalpack/tables/fiorygitransactions.py | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/royalpack/commands/magicktreasure.py b/royalpack/commands/magicktreasure.py index 2b16b16f..8752d08a 100644 --- a/royalpack/commands/magicktreasure.py +++ b/royalpack/commands/magicktreasure.py @@ -36,7 +36,7 @@ class MagicktreasureCommand(rc.Command): await data.delete_invoking() author = await data.get_author(error_if_none=True) - code = args[0] + code = args[0].lower() try: value = int(args[1]) except ValueError: diff --git a/royalpack/commands/treasure.py b/royalpack/commands/treasure.py index 70d58482..bc7337d2 100644 --- a/royalpack/commands/treasure.py +++ b/royalpack/commands/treasure.py @@ -14,7 +14,7 @@ class TreasureCommand(rc.Command): async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: author = await data.get_author(error_if_none=True) - code = args[0] + code = args[0].lower() TreasureT = self.alchemy.get(Treasure) diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py index 42366729..406381e8 100644 --- a/royalpack/tables/fiorygitransactions.py +++ b/royalpack/tables/fiorygitransactions.py @@ -73,8 +73,7 @@ class FiorygiTransaction: 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 ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''}...? " \ - f"Per [i]{reason}[/i]...? Cosa?" + 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]." From 2a5a8a32c64ab9cc8663e28377ff9572a8d62415 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 24 May 2020 21:22:11 +0200 Subject: [PATCH 150/227] publish: 5.8.10 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5df58aec..9d1bc077 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.9" + version = "5.8.10" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index d8460d48..726be4e8 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.9" +semantic = "5.8.10" From 00e7b21f60c066b0f1fef084f6cdf1d17f971dae Mon Sep 17 00:00:00 2001 From: Cookie <58516648+Cookie-CHR@users.noreply.github.com> Date: Mon, 25 May 2020 23:22:19 +0200 Subject: [PATCH 151/227] Update eat.py Aggiunti molti nuovi cibi! --- royalpack/commands/eat.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 03c249d5..73e0c804 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -37,16 +37,28 @@ class EatCommand(Command): "maxsensei": "🚹 Hai mangiato {food}.\n[i]Sa di merda.[/i]", "steffo": "🚹 Hai mangiato {food}.\n[i]Sa di gelato e di Coca-Cola.[/i]", + # Sezione in cui mangi i professori dei membri Royal Games + "arrigo": "🖍 Hai mangiato {food}!\n[i]Ti scrive F: V→W sulla parete dello stomaco con i gessetti colorati.[\i]", + "bonisoli": "🖍 Hai mangiato {food}!\n[i]Ti scrive F: V→W sulla parete dello stomaco con i gessetti colorati.[\i]", + "montangero": "📝 Hai mangiato la {food}!\n[i]La digerisci in O(n!).[\i]", + "marongiu": "🔧 Hai mangiato {food}!\n[i]Il tuo apparato digerente viene trasformato in una pipeline.[/i]", + "mandreoli": "⚠️ Hai mangiato la {food}!\n[c]Error: Segmentation fault (core dumped)[\c]"; + "la rocca": "📊 Hai mangiato {food}!\n[i]Si distribuisce nel tuo intestino come una Normale.[\i]", + "villani": "🐜 Hai mangiato {food}!\n[i]Crea una rete neurale sfruttando i tuoi neuroni e le tue cellule.[\i]", + "novellani": "❓Volevi mangiare {food}...\n[i]...ma invece trovi solo Dell'Amico.[\i]", + # Sezione delle supercazzole "antani": "❔ Hai mangiato {food}. \n[i]Con tarapia tapioco o scherziamo? No, mi permetta. Noi siamo in 4.\n" "Come se fosse antani anche per lei soltanto in due, oppure in quattro anche scribàcchi confaldina?\n" "Come antifurto, per esempio.[/i]", "indice": "☝️ Hai mangiato l'{food}. \n[i]Ecco, lo alzi. Lo vede, lo vede che stuzzica?[/i]", - # sezione con piante e anmali + # Sezione con piante e animali "cactus": "🌵 Hai mangiato un {food}.\n[i]Gli hai tolto le spine prima, vero?[/i]", "tango": "🌳 Hai mangiato un {food}, e un albero insieme ad esso.\n[i]Senti le tue ferite curarsi...[/i]", "foglia": "🍁 Hai mangiato la {food}.\n[i]A te non la si fa![/i]", + "pug": "🐶 Hai provato a mangiare un {food}...\n[i]...Ma Mallllco si è precipitato in soccorso e lo ha salvato![/i]", + "carlino": "🐶 Hai provato a mangiare un {food}...\n[i]...Ma Mallllco si è precipitato in soccorso e lo ha salvato![/i]", "gatto": "🐱 Vieni fermato prima di poter compiere questo gesto orribile.\n" "[i]Il {food} verrà pettato da tutti per farlo riavere dal trauma.[/i]", "3 porcellini": "🐷 Hai mangiato i {food}.\n[i]La casa di mattoni non è bastata a fermarti![/i]", @@ -83,6 +95,9 @@ class EatCommand(Command): "gelato di steffo": "🍨 Hai provato a rubare il {food}...\n[i]...Ma sei arrivato tardi: l'ha già mangiato.[/i]", "biscotto": "🍪 Hai mangiato un {food} di contrabbando.\n[i]L'Inquisizione non lo saprà mai![/i]", "biscotti": "🍪 Hai mangiato tanti {food} di contrabbando.\n[i]Attento! L'Inquisizione è sulle tue tracce![/i]", + "crocchette di pollo": "🍗 Hai mangiato {food]!\n[i]Dio porco maledetto, infame, CAPRA, porca Madonna, Dio cane, " + "HAI PERSO. UN POMERIGGIO PER C- ooh se è questo dio cane, altro che sfondamento dei cieli *roba non capibile*, " + " sfondi tutti dio can lo distruggi, non ci rimane più niente.[\i]", # Sezione delle bevande "acqua": "💧 Hai bevuto un po' d'{food}.\n[i]Ti depura e ti fa fare tanta plin plin![/i}", @@ -147,7 +162,7 @@ class EatCommand(Command): "giarone": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "sasso": "🥌 Il {food} che hai mangiato era duro come un {food}.\n[i]Stai soffrendo di indigestione![/i]", "bomba": "💣 Hai mangiato una {food}. Speriamo fosse solo calorica!\n[i]3... 2... 1...[/i]", - "ass": "🕳 Hai mangiato {food}./n[i]Bleah! Lo sai cosa fa quel coso per sopravvivere?[/i]", + "ass": "🕳 Hai mangiato {food}.\n[i]Bleah! Lo sai cosa fa quel coso per sopravvivere?[/i]", "onion": "🗞 You ate the {food}. Ci sei proprio cascato!\n [i]Hai mai creduto a una notizia di Lercio," " invece?[/i]", "uranio": "☢️ L'{food} che hai mangiato era radioattivo.\n[i]Stai brillando di verde![/i]", @@ -166,6 +181,9 @@ class EatCommand(Command): "[i]Nessuno, tranne il bot, sa di cosa è fatta esattamente, ma una cosa è certa: è " "buonissima![/i]", "angelo": "👼 Oh mio dio! E' un {food}!\n[i]Ora hai un digramma ad onda blu.[/i]", + "unicode": "🍗 Hai mangiato {food}!\n๓ค 𝔫𝔬𝔫 [i]è[\i] 𝓼𝓾𝓬𝓬𝓮𝓼𝓼𝓸 𝕟𝕦𝕝𝕝𝕒.", + "eco": "🏔 Hai mangiato l'{food} eco eco!\n[i]Ma non è successo nulla ulla ulla.[\i]", + "disinfettante": "🧴Hai mangiato {food}!\n[i]Secondo Trump, ora sei molto più sano.[\i]", "terraria": "🌳 Hai provato a mangiare {food}, ma non ne sei stato all'Altezza (Coniglio).\n[i]Prova a mangiare qualcos'altro...[/i]", "cooked fish": "🐟 Hai mangiato {food}.\n[i]Ora sei Well Fed per 20 minuti.[/i]" From 8f38661172f816c28b18fe4bacaebbced5714ad7 Mon Sep 17 00:00:00 2001 From: Cookie <58516648+Cookie-CHR@users.noreply.github.com> Date: Wed, 27 May 2020 00:43:53 +0200 Subject: [PATCH 152/227] Update eat.py Fatte le modifiche richieste. --- royalpack/commands/eat.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 73e0c804..7722511a 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -38,14 +38,14 @@ class EatCommand(Command): "steffo": "🚹 Hai mangiato {food}.\n[i]Sa di gelato e di Coca-Cola.[/i]", # Sezione in cui mangi i professori dei membri Royal Games - "arrigo": "🖍 Hai mangiato {food}!\n[i]Ti scrive F: V→W sulla parete dello stomaco con i gessetti colorati.[\i]", - "bonisoli": "🖍 Hai mangiato {food}!\n[i]Ti scrive F: V→W sulla parete dello stomaco con i gessetti colorati.[\i]", - "montangero": "📝 Hai mangiato la {food}!\n[i]La digerisci in O(n!).[\i]", + "arrigo": "🖍 Hai mangiato {food}!\n[i]Ti scrive F: V→W sulla parete dello stomaco con i gessetti colorati.[/i]", + "bonisoli": "🖍 Hai mangiato {food}!\n[i]Ti scrive F: V→W sulla parete dello stomaco con i gessetti colorati.[/i]", + "montangero": "📝 Hai mangiato la {food}!\n[i]La digerisci in O(n!).[/i]", "marongiu": "🔧 Hai mangiato {food}!\n[i]Il tuo apparato digerente viene trasformato in una pipeline.[/i]", - "mandreoli": "⚠️ Hai mangiato la {food}!\n[c]Error: Segmentation fault (core dumped)[\c]"; - "la rocca": "📊 Hai mangiato {food}!\n[i]Si distribuisce nel tuo intestino come una Normale.[\i]", - "villani": "🐜 Hai mangiato {food}!\n[i]Crea una rete neurale sfruttando i tuoi neuroni e le tue cellule.[\i]", - "novellani": "❓Volevi mangiare {food}...\n[i]...ma invece trovi solo Dell'Amico.[\i]", + "mandreoli": "⚠️ Hai mangiato la {food}!\n[c]Error: Segmentation fault (core dumped)[/c]", + "la rocca": "📊 Hai mangiato {food}!\n[i]Si distribuisce nel tuo intestino come una Normale.[/i]", + "villani": "🐜 Hai mangiato {food}!\n[i]Crea una rete neurale sfruttando i tuoi neuroni e le tue cellule.[/i]", + "novellani": "❓Volevi mangiare {food}...\n[i]...ma invece trovi solo Dell'Amico.[/i]", # Sezione delle supercazzole "antani": "❔ Hai mangiato {food}. \n[i]Con tarapia tapioco o scherziamo? No, mi permetta. Noi siamo in 4.\n" @@ -96,8 +96,8 @@ class EatCommand(Command): "biscotto": "🍪 Hai mangiato un {food} di contrabbando.\n[i]L'Inquisizione non lo saprà mai![/i]", "biscotti": "🍪 Hai mangiato tanti {food} di contrabbando.\n[i]Attento! L'Inquisizione è sulle tue tracce![/i]", "crocchette di pollo": "🍗 Hai mangiato {food]!\n[i]Dio porco maledetto, infame, CAPRA, porca Madonna, Dio cane, " - "HAI PERSO. UN POMERIGGIO PER C- ooh se è questo dio cane, altro che sfondamento dei cieli *roba non capibile*, " - " sfondi tutti dio can lo distruggi, non ci rimane più niente.[\i]", + "HAI PERSO. UN POMERIGGIO PER C- ooh se è questo dio cane, altro che sfondamento dei cieli " + "*roba non capibile*, sfondi tutti dio can li distruggi, non ci rimane più niente.[/i]", # Sezione delle bevande "acqua": "💧 Hai bevuto un po' d'{food}.\n[i]Ti depura e ti fa fare tanta plin plin![/i}", @@ -181,9 +181,9 @@ class EatCommand(Command): "[i]Nessuno, tranne il bot, sa di cosa è fatta esattamente, ma una cosa è certa: è " "buonissima![/i]", "angelo": "👼 Oh mio dio! E' un {food}!\n[i]Ora hai un digramma ad onda blu.[/i]", - "unicode": "🍗 Hai mangiato {food}!\n๓ค 𝔫𝔬𝔫 [i]è[\i] 𝓼𝓾𝓬𝓬𝓮𝓼𝓼𝓸 𝕟𝕦𝕝𝕝𝕒.", - "eco": "🏔 Hai mangiato l'{food} eco eco!\n[i]Ma non è successo nulla ulla ulla.[\i]", - "disinfettante": "🧴Hai mangiato {food}!\n[i]Secondo Trump, ora sei molto più sano.[\i]", + "unicode": "🍗 Hai mangiato {food}!\n๓ค 𝔫𝔬𝔫 [i]è[/i] 𝓼𝓾𝓬𝓬𝓮𝓼𝓼𝓸 𝕟𝕦𝕝𝕝𝕒.", + "eco": "🏔 Hai mangiato l'{food} eco eco!\n[i]Ma non è successo nulla ulla ulla.[/i]", + "disinfettante": "🧴Hai mangiato {food}!\n[i]Secondo Trump, ora sei molto più sano.[/i]", "terraria": "🌳 Hai provato a mangiare {food}, ma non ne sei stato all'Altezza (Coniglio).\n[i]Prova a mangiare qualcos'altro...[/i]", "cooked fish": "🐟 Hai mangiato {food}.\n[i]Ora sei Well Fed per 20 minuti.[/i]" From 4a2dc9c73e17a5901dca808d3f766659cb522b94 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 28 May 2020 16:51:48 +0200 Subject: [PATCH 153/227] Raise ExternalError for 400+ response in funkwhale --- publish.bat | 2 +- royalpack/commands/funkwhale.py | 2 ++ royalpack/commands/funkwhalealbum.py | 2 ++ royalpack/commands/funkwhaleplaylist.py | 4 ++++ royalpack/commands/lazyfunkwhale.py | 2 ++ royalpack/commands/lazyfunkwhalealbum.py | 2 ++ royalpack/commands/lazyfunkwhaleplaylist.py | 4 ++++ 7 files changed, 17 insertions(+), 1 deletion(-) diff --git a/publish.bat b/publish.bat index 33490c42..6e32e926 100644 --- a/publish.bat +++ b/publish.bat @@ -1,2 +1,2 @@ git commit -am "publish: %1" -git push && poetry build && poetry publish && hub release create "%1" -m "Royalnet %1" \ No newline at end of file +git push && poetry build && poetry publish && hub release create "%1" -m "Royalnet %1" && sentry-cli releases deploys "%1" new --env production -n "GitHub %1" diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py index 644801c0..b46cdfeb 100644 --- a/royalpack/commands/funkwhale.py +++ b/royalpack/commands/funkwhale.py @@ -23,6 +23,8 @@ class FunkwhaleCommand(PlayCommand): async with aiohttp.ClientSession() as session: async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/search?query={search}") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() if len(j["tracks"]) < 1: raise rc.UserError("Nessun file audio trovato con il nome richiesto.") diff --git a/royalpack/commands/funkwhalealbum.py b/royalpack/commands/funkwhalealbum.py index dacfa1f0..fe132f56 100644 --- a/royalpack/commands/funkwhalealbum.py +++ b/royalpack/commands/funkwhalealbum.py @@ -23,6 +23,8 @@ class FunkwhalealbumCommand(PlayCommand): async with aiohttp.ClientSession() as session: async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/search?query={search}") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() if len(j["albums"]) < 1: raise rc.UserError("Nessun file audio trovato con il nome richiesto.") diff --git a/royalpack/commands/funkwhaleplaylist.py b/royalpack/commands/funkwhaleplaylist.py index d1c77045..bdd3eb33 100644 --- a/royalpack/commands/funkwhaleplaylist.py +++ b/royalpack/commands/funkwhaleplaylist.py @@ -23,6 +23,8 @@ class FunkwhaleplaylistCommand(PlayCommand): async with aiohttp.ClientSession() as session: async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() if len(j["results"]) < 1: raise rc.UserError("Nessuna playlist trovata con il nome richiesto.") @@ -30,5 +32,7 @@ class FunkwhaleplaylistCommand(PlayCommand): playlist_id = playlist["id"] async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/playlists/{playlist_id}/tracks") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() return list(map(lambda t: f'{self.config["Funkwhale"]["instance_url"]}{t["track"]["listen_url"]}', j["results"])) diff --git a/royalpack/commands/lazyfunkwhale.py b/royalpack/commands/lazyfunkwhale.py index 6edc9b09..fd3337fe 100644 --- a/royalpack/commands/lazyfunkwhale.py +++ b/royalpack/commands/lazyfunkwhale.py @@ -23,6 +23,8 @@ class LazyfunkwhaleCommand(LazyplayCommand): async with aiohttp.ClientSession() as session: async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/search?query={search}") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() if len(j["tracks"]) < 1: raise rc.UserError("Nessun file audio trovato con il nome richiesto.") diff --git a/royalpack/commands/lazyfunkwhalealbum.py b/royalpack/commands/lazyfunkwhalealbum.py index bf807f2f..631e088e 100644 --- a/royalpack/commands/lazyfunkwhalealbum.py +++ b/royalpack/commands/lazyfunkwhalealbum.py @@ -23,6 +23,8 @@ class LazyfunkwhalealbumCommand(LazyplayCommand): async with aiohttp.ClientSession() as session: async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/search?query={search}") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() if len(j["albums"]) < 1: raise rc.UserError("Nessun file audio trovato con il nome richiesto.") diff --git a/royalpack/commands/lazyfunkwhaleplaylist.py b/royalpack/commands/lazyfunkwhaleplaylist.py index 1fb2bcf6..caa9378d 100644 --- a/royalpack/commands/lazyfunkwhaleplaylist.py +++ b/royalpack/commands/lazyfunkwhaleplaylist.py @@ -21,6 +21,8 @@ class LazyfunkwhaleplaylistCommand(LazyplayCommand): async with aiohttp.ClientSession() as session: async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() if len(j["results"]) < 1: raise rc.UserError("Nessuna playlist trovata con il nome richiesto.") @@ -28,5 +30,7 @@ class LazyfunkwhaleplaylistCommand(LazyplayCommand): playlist_id = playlist["id"] async with session.get(self.config["Funkwhale"]["instance_url"] + f"/api/v1/playlists/{playlist_id}/tracks") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") j = await response.json() return list(map(lambda t: f'{self.config["Funkwhale"]["instance_url"]}{t["track"]["listen_url"]}', j["results"])) From f20c106a57cbbef68a8c65fa8afa1ae0152bbf86 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 28 May 2020 16:54:43 +0200 Subject: [PATCH 154/227] Fix steampowered commands --- royalpack/commands/steammatch.py | 4 ++-- royalpack/commands/steampowered.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index 99d27f80..25dc7e8a 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -1,5 +1,5 @@ from typing import * -import steam +import steam.webapi import requests.exceptions import royalnet.commands as rc import royalnet.utils as ru @@ -57,7 +57,7 @@ class SteammatchCommand(rc.Command): super().__init__(interface) if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: raise rc.ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") - self._api = steam.WebAPI(self.config["Steam"]["web_api_key"]) + self._api = steam.webapi.WebAPI(self.config["Steam"]["web_api_key"]) async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: users = [] diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index a29f1e82..900d29ff 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -1,5 +1,6 @@ from typing import * -import steam +import steam.steamid +import steam.webapi import datetime import royalnet.commands as rc import royalnet.utils as ru @@ -18,7 +19,7 @@ class SteampoweredCommand(rc.Command): super().__init__(interface) if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: raise rc.ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") - self._api = steam.WebAPI(self.config["Steam"]["web_api_key"]) + self._api = steam.webapi.WebAPI(self.config["Steam"]["web_api_key"]) @staticmethod def _display(account: Steam): From 4f1cf507797d2fde03e40995aeaba7b7ceae4685 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 28 May 2020 16:57:10 +0200 Subject: [PATCH 155/227] Raise ExternalError on 400+ responses for pug --- royalpack/commands/pug.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/royalpack/commands/pug.py b/royalpack/commands/pug.py index 97b66834..6846212b 100644 --- a/royalpack/commands/pug.py +++ b/royalpack/commands/pug.py @@ -16,6 +16,8 @@ class PugCommand(rc.Command): async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async with aiohttp.ClientSession() as session: async with session.get("https://dog.ceo/api/breed/pug/images/random") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") result = await response.json() assert "status" in result assert result["status"] == "success" From f2dde503304cd5519640d17696e521940b8b2280 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 28 May 2020 17:02:24 +0200 Subject: [PATCH 156/227] Update files --- publish.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/publish.bat b/publish.bat index 6e32e926..f0813a03 100644 --- a/publish.bat +++ b/publish.bat @@ -1,2 +1,2 @@ git commit -am "publish: %1" -git push && poetry build && poetry publish && hub release create "%1" -m "Royalnet %1" && sentry-cli releases deploys "%1" new --env production -n "GitHub %1" +git push && poetry build && poetry publish && hub release create "%1" -m "Royalnet %1" From e6f1cd5e9d3bde6bd9f699fe19528352032d1b36 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 28 May 2020 17:02:48 +0200 Subject: [PATCH 157/227] publish: 5.8.11 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9d1bc077..f69cc673 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.10" + version = "5.8.11" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 726be4e8..0e908a7b 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.10" +semantic = "5.8.11" From c5ea9232c0efee0387db1b7c22a7e11ff52dcdd4 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 29 May 2020 13:37:33 +0200 Subject: [PATCH 158/227] Supporta custom status in /cv --- royalpack/commands/cv.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/cv.py b/royalpack/commands/cv.py index 9efdeefe..3dbb3d4d 100644 --- a/royalpack/commands/cv.py +++ b/royalpack/commands/cv.py @@ -77,8 +77,15 @@ class CvCommand(Command): activity += f" | 📺 {mact['name']}" # Custom Status elif mact["type"] == 4: - if "state" in activity: - activity += f" | ❓ {mact['state']}" + if "emoji" in mact: + emoji = f"{mact['emoji']['name']}" + else: + emoji = f"❓" + if "state" in mact: + state = f" {mact['state']}" + else: + state = "" + activity += f" | {emoji}{state}" else: raise ExternalError(f"Unknown Discord activity type: {mact['type']}") From d2c5b1168259cb17eff0c243f280f67451ce057e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 29 May 2020 13:52:22 +0200 Subject: [PATCH 159/227] publish: 5.8.12 --- poetry.lock | 63 ++++++++++++++++++++------------------------ pyproject.toml | 2 +- royalpack/version.py | 2 +- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7f6ff3d5..b17b44f0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -320,8 +320,8 @@ category = "main" description = "Python binding to the Networking and Cryptography (NaCl) library" name = "pynacl" optional = false -python-versions = "*" -version = "1.3.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.4.0" [package.dependencies] cffi = ">=1.4.1" @@ -443,7 +443,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.8.9" +version = "5.8.13" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -561,7 +561,7 @@ description = "Python 2 and 3 compatibility utilities" name = "six" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.14.0" +version = "1.15.0" [[package]] category = "main" @@ -600,7 +600,7 @@ description = "Module for interacting with various Steam features" name = "steam" optional = false python-versions = "*" -version = "1.0.0" +version = "1.0.1" [package.dependencies] cachetools = ">=3.0.0" @@ -709,7 +709,7 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.5.8" +version = "2020.5.29" [metadata] content-hash = "9245b7ae163a3746554cd31e3b20294d26aa3534cc78303a419ac54850db55cb" @@ -972,27 +972,22 @@ pycryptodomex = [ {file = "pycryptodomex-3.9.7.tar.gz", hash = "sha256:50163324834edd0c9ce3e4512ded3e221c969086e10fdd5d3fdcaadac5e24a78"}, ] pynacl = [ - {file = "PyNaCl-1.3.0-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621"}, - {file = "PyNaCl-1.3.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39"}, - {file = "PyNaCl-1.3.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255"}, - {file = "PyNaCl-1.3.0-cp27-cp27m-win32.whl", hash = "sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f"}, - {file = "PyNaCl-1.3.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0"}, - {file = "PyNaCl-1.3.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1"}, - {file = "PyNaCl-1.3.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e"}, - {file = "PyNaCl-1.3.0-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1"}, - {file = "PyNaCl-1.3.0-cp34-abi3-manylinux1_i686.whl", hash = "sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786"}, - {file = "PyNaCl-1.3.0-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415"}, - {file = "PyNaCl-1.3.0-cp34-cp34m-win32.whl", hash = "sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b"}, - {file = "PyNaCl-1.3.0-cp34-cp34m-win_amd64.whl", hash = "sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae"}, - {file = "PyNaCl-1.3.0-cp35-cp35m-win32.whl", hash = "sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310"}, - {file = "PyNaCl-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a"}, - {file = "PyNaCl-1.3.0-cp36-cp36m-win32.whl", hash = "sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20"}, - {file = "PyNaCl-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b"}, - {file = "PyNaCl-1.3.0-cp37-cp37m-win32.whl", hash = "sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56"}, - {file = "PyNaCl-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715"}, - {file = "PyNaCl-1.3.0-cp38-cp38-win32.whl", hash = "sha256:53126cd91356342dcae7e209f840212a58dcf1177ad52c1d938d428eebc9fee5"}, - {file = "PyNaCl-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:bf459128feb543cfca16a95f8da31e2e65e4c5257d2f3dfa8c0c1031139c9c92"}, - {file = "PyNaCl-1.3.0.tar.gz", hash = "sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"}, + {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"}, + {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"}, + {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"}, + {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"}, + {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"}, + {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"}, + {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"}, + {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"}, + {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"}, + {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"}, + {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"}, @@ -1050,8 +1045,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.8.9-py3-none-any.whl", hash = "sha256:a64ed18c513b4ea708cc93db0db53099b6e9e40f63374b1bb8d924bf057e31c2"}, - {file = "royalnet-5.8.9.tar.gz", hash = "sha256:50b5a3453bd1018b8846018fd7ce64046b4b669cce780564a8a871cd8c569d6d"}, + {file = "royalnet-5.8.13-py3-none-any.whl", hash = "sha256:77bc201477db59e172caae049ba5edac5de7134cef5ef03d113636e4b9fd4f83"}, + {file = "royalnet-5.8.13.tar.gz", hash = "sha256:42c8772e03bdd9400990f853fe477d09759c547da2d300df536cd49f42159203"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1061,8 +1056,8 @@ sentry-sdk = [ {file = "sentry_sdk-0.13.5-py2.py3-none-any.whl", hash = "sha256:05285942901d38c7ce2498aba50d8e87b361fc603281a5902dda98f3f8c5e145"}, ] six = [ - {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, - {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, + {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, + {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] sqlalchemy = [ {file = "SQLAlchemy-1.3.17-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:fe01bac7226499aedf472c62fa3b85b2c619365f3f14dd222ffe4f3aa91e5f98"}, @@ -1098,7 +1093,7 @@ starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, ] steam = [ - {file = "steam-1.0.0.tar.gz", hash = "sha256:e02381de3ac428a4362c5f47c2ebb90b28791e320665b47ad0245817d9c05220"}, + {file = "steam-1.0.1.tar.gz", hash = "sha256:7a2635dc46a18a86f608c8b9f8e042126cf9bd7b8e8e9ca6dcacb0998cb56ec5"}, ] toml = [ {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, @@ -1186,6 +1181,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.5.8-py2.py3-none-any.whl", hash = "sha256:0b5d3280522469968eb62eecb1f966f422b2be22f000a801bf87cb2172d8ea39"}, - {file = "youtube_dl-2020.5.8.tar.gz", hash = "sha256:22da6788b55b7b267c6d59bcdfaf10e67a9ac980976d50d29a670473ad2a05bb"}, + {file = "youtube_dl-2020.5.29-py2.py3-none-any.whl", hash = "sha256:2d45840772ecc57e151b0be78dd89e9772b6aa29295746be38abb9c30dad5bb3"}, + {file = "youtube_dl-2020.5.29.tar.gz", hash = "sha256:1a3d84afa851dce2fccc2dfc0f9ffa0e22314ffba6d528b34b4a7fe3e0cf2264"}, ] diff --git a/pyproject.toml b/pyproject.toml index f69cc673..cd476830 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.11" + version = "5.8.12" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 0e908a7b..61bcbff4 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.11" +semantic = "5.8.12" From 33ce001a6fa97716adbcbe921d59d35101d50b7e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 4 Jun 2020 18:01:47 +0200 Subject: [PATCH 160/227] Fix cvstats query --- royalpack/stars/api_cvstats_avg.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/royalpack/stars/api_cvstats_avg.py b/royalpack/stars/api_cvstats_avg.py index 0346fb3b..7748bb12 100644 --- a/royalpack/stars/api_cvstats_avg.py +++ b/royalpack/stars/api_cvstats_avg.py @@ -63,9 +63,7 @@ JOIN AVG(c.members_total) members_total, AVG(c.users_total) users_total FROM cvstats c - WHERE c.timestamp BETWEEN - NOW()::DATE-EXTRACT(DOW FROM NOW())::INTEGER-7 - AND NOW()::DATE-EXTRACT(DOW from NOW())::INTEGER + WHERE c.timestamp > current_timestamp - interval '7 day' GROUP BY h ) c GROUP BY ph @@ -92,9 +90,7 @@ JOIN AVG(c.members_total) members_total, AVG(c.users_total) users_total FROM cvstats c - WHERE c.timestamp BETWEEN - NOW()::DATE-EXTRACT(DOW FROM NOW())::INTEGER-30 - AND NOW()::DATE-EXTRACT(DOW from NOW())::INTEGER + WHERE c.timestamp > current_timestamp - interval '30 day' GROUP BY h ) c GROUP BY ph @@ -121,9 +117,7 @@ JOIN AVG(c.members_total) members_total, AVG(c.users_total) users_total FROM cvstats c - WHERE c.timestamp BETWEEN - NOW()::DATE-EXTRACT(DOW FROM NOW())::INTEGER-1 - AND NOW()::DATE-EXTRACT(DOW from NOW())::INTEGER + WHERE c.timestamp > current_timestamp - interval '1 day' GROUP BY h ) c GROUP BY ph From 59fe98c41f6a1330e6c4f04ae5e4e06bc1b63c23 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 4 Jun 2020 18:02:55 +0200 Subject: [PATCH 161/227] Aggiungi un nuovo cibo a eat --- royalpack/commands/eat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 7722511a..3c368618 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -186,7 +186,8 @@ class EatCommand(Command): "disinfettante": "🧴Hai mangiato {food}!\n[i]Secondo Trump, ora sei molto più sano.[/i]", "terraria": "🌳 Hai provato a mangiare {food}, ma non ne sei stato all'Altezza (Coniglio).\n[i]Prova a mangiare qualcos'altro...[/i]", - "cooked fish": "🐟 Hai mangiato {food}.\n[i]Ora sei Well Fed per 20 minuti.[/i]" + "cooked fish": "🐟 Hai mangiato {food}.\n[i]Ora sei Well Fed per 20 minuti.[/i]", + "gestione": "🌐 Hai mangiato {food}, basato su Condivisione.\n[i]Fa ridere di sopra, ma fa anche riflettere di sotto.[/i]", } async def run(self, args: CommandArgs, data: CommandData) -> None: From 1c533fc01314429a6fcbfbe6389d45848155f986 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 4 Jun 2020 18:03:36 +0200 Subject: [PATCH 162/227] Aggiungi un nuovo cibo a eat --- royalpack/commands/eat.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index 3c368618..e24498b6 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -187,7 +187,8 @@ class EatCommand(Command): "terraria": "🌳 Hai provato a mangiare {food}, ma non ne sei stato all'Altezza (Coniglio).\n[i]Prova a mangiare qualcos'altro...[/i]", "cooked fish": "🐟 Hai mangiato {food}.\n[i]Ora sei Well Fed per 20 minuti.[/i]", - "gestione": "🌐 Hai mangiato {food}, basato su Condivisione.\n[i]Fa ridere di sopra, ma fa anche riflettere di sotto.[/i]", + "gestione": "🌐 Hai mangiato {food}, su cui si basa Condivisione.\n[i]Fa ridere di sotto, ma fa anche riflettere di sopra.[/i]", + "condivisione": "🌐 Hai mangiato {food}, basato su Gestione.\n[i]Fa ridere di sopra, ma fa anche riflettere di sotto.[/i]", } async def run(self, args: CommandArgs, data: CommandData) -> None: From b0e1bfd75c9caea06f55d8f1a4db8daaac05c59f Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 4 Jun 2020 18:03:50 +0200 Subject: [PATCH 163/227] publish: 5.8.3 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cd476830..49b4e350 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.12" + version = "5.8.13" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 61bcbff4..4deca9eb 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.12" +semantic = "5.8.13" From b6f7c253c77a4f45bf70fb14b91d1f686fc4674a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 6 Jun 2020 01:05:39 +0200 Subject: [PATCH 164/227] Fix steammatch command --- royalpack/commands/steammatch.py | 1 + 1 file changed, 1 insertion(+) diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index 25dc7e8a..f88c0993 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -84,6 +84,7 @@ class SteammatchCommand(rc.Command): steamid=steam_account._steamid, include_appinfo=True, include_played_free_games=True, + include_free_sub=True, appids_filter=0) except requests.exceptions.HTTPError: raise rc.ExternalError(f"L'account Steam di {user} è privato!") From a81f3bd9801b8465f6b33fc544f8a86d6d38e1e5 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 6 Jun 2020 02:00:43 +0200 Subject: [PATCH 165/227] Fix givefiorygi message --- royalpack/commands/givefiorygi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/givefiorygi.py b/royalpack/commands/givefiorygi.py index 87bf4965..b9f536fc 100644 --- a/royalpack/commands/givefiorygi.py +++ b/royalpack/commands/givefiorygi.py @@ -39,4 +39,4 @@ class GivefiorygiCommand(rc.Command): raise rc.InvalidInputError("Non hai abbastanza fiorygi per effettuare la transazione!") await FiorygiTransaction.spawn_fiorygi(data, author, -qty, f"aver ceduto fiorygi a {user}") - await FiorygiTransaction.spawn_fiorygi(data, user, qty, f"aver ricevuto fiorygi da {user}") + await FiorygiTransaction.spawn_fiorygi(data, user, qty, f"aver ricevuto fiorygi da {author}") From 3fe7e9483430f458f76a0d8aea1aabadc417fef1 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 6 Jun 2020 02:16:52 +0200 Subject: [PATCH 166/227] publish: 5.8.14 --- poetry.lock | 6 +++--- pyproject.toml | 2 +- royalpack/commands/__init__.py | 2 ++ royalpack/commands/cat.py | 28 ++++++++++++++++++++++++++++ royalpack/version.py | 2 +- 5 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 royalpack/commands/cat.py diff --git a/poetry.lock b/poetry.lock index b17b44f0..23f7ebe0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -709,7 +709,7 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.5.29" +version = "2020.6.6" [metadata] content-hash = "9245b7ae163a3746554cd31e3b20294d26aa3534cc78303a419ac54850db55cb" @@ -1181,6 +1181,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.5.29-py2.py3-none-any.whl", hash = "sha256:2d45840772ecc57e151b0be78dd89e9772b6aa29295746be38abb9c30dad5bb3"}, - {file = "youtube_dl-2020.5.29.tar.gz", hash = "sha256:1a3d84afa851dce2fccc2dfc0f9ffa0e22314ffba6d528b34b4a7fe3e0cf2264"}, + {file = "youtube_dl-2020.6.6-py2.py3-none-any.whl", hash = "sha256:813310fb7ab265c379e9aebb2bd6cde6995f9a8f22a06d2ff81c05dfab7da864"}, + {file = "youtube_dl-2020.6.6.tar.gz", hash = "sha256:74e6cc7395060fc39f0b8e21c1e4707486da904c96145bd875187bda2da83b04"}, ] diff --git a/pyproject.toml b/pyproject.toml index 49b4e350..73e6dbcf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.13" + version = "5.8.14" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 48ce16ed..fecb9e04 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -60,6 +60,7 @@ from .pug import PugCommand from .magicktreasure import MagicktreasureCommand from .treasure import TreasureCommand from .givetreasure import GivetreasureCommand +from .cat import CatCommand # Enter the commands of your Pack here! available_commands = [ @@ -124,6 +125,7 @@ available_commands = [ MagicktreasureCommand, TreasureCommand, GivetreasureCommand, + CatCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/cat.py b/royalpack/commands/cat.py new file mode 100644 index 00000000..fa45344a --- /dev/null +++ b/royalpack/commands/cat.py @@ -0,0 +1,28 @@ +from typing import * +import royalnet.commands as rc +import aiohttp +import io + + +class CatCommand(rc.Command): + name: str = "cat" + + description: str = "Invia un gatto casuale in chat." + + syntax: str = "" + + aliases = ["catto", "kat", "kitty", "kitten", "gatto", "miao", "garf", "basta"] + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + async with aiohttp.ClientSession() as session: + async with session.get("https://api.thecatapi.com/v1/images/search") as response: + if response.status >= 400: + raise rc.ExternalError(f"Request returned {response.status}") + result = await response.json() + assert len(result) == 1 + cat = result[0] + assert "url" in cat + url = cat["url"] + async with session.get(url) as response: + img = await response.content.read() + await data.reply_image(image=io.BytesIO(img)) diff --git a/royalpack/version.py b/royalpack/version.py index 4deca9eb..e6b5c2aa 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.13" +semantic = "5.8.14" From ab04e0910183ea3038ce1dc57ee1669e1b063828 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 9 Jun 2020 02:09:08 +0200 Subject: [PATCH 167/227] Handle events differently --- royalpack/commands/play.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/play.py b/royalpack/commands/play.py index 25abe910..5754efdc 100644 --- a/royalpack/commands/play.py +++ b/royalpack/commands/play.py @@ -18,7 +18,7 @@ class PlayCommand(rc.Command): url = args.joined(require_at_least=1) if not (url.startswith("http://") or url.startswith("https://")): raise rc.InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" - f" ([c]http://[/c] o [c]https://[/c]).") + f" ([c]http://[/c] o [c]https://[/c]).") return [url] def get_embed_color(self) -> Optional[int]: From 28da9a330c189d3e5aab6a9b3adad3bdd98adbb0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 9 Jun 2020 02:32:54 +0200 Subject: [PATCH 168/227] publish: 5.8.15 --- pyproject.toml | 4 ++-- royalpack/version.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 73e6dbcf..780a4e11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.14" + version = "5.8.15" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "*" [tool.poetry.dependencies.royalnet] - version = "~5.8.7" + version = "~5.8.14" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/version.py b/royalpack/version.py index e6b5c2aa..a63f7df8 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.14" +semantic = "5.8.15" From 90e60bc8271f5431eaa1400e660c25c13f537166 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 11 Jun 2020 14:21:11 +0200 Subject: [PATCH 169/227] IM STUPID --- royalpack/commands/steampowered.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 900d29ff..81275c09 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -36,7 +36,7 @@ class SteampoweredCommand(rc.Command): async def _call(self, method, *args, **kwargs): try: - await ru.asyncify(method, *args, **kwargs) + return await ru.asyncify(method, *args, **kwargs) except Exception as e: raise rc.ExternalError("\n".join(e.args).replace(self.config["Steam"]["web_api_key"], "HIDDEN")) From b1a2900b62d6c98d155e315209a68efe798508bd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 11 Jun 2020 14:21:44 +0200 Subject: [PATCH 170/227] publish: 5.8.16 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 780a4e11..d97ed7e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.15" + version = "5.8.16" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index a63f7df8..7151772d 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.15" +semantic = "5.8.16" From 7221f5f730278e0fe4c1998a316422982bc53260 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 11 Jun 2020 18:47:25 +0200 Subject: [PATCH 171/227] Let's try deleting before sending messages --- royalpack/commands/matchmaking.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 410adb2a..5ed3785a 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -331,6 +331,10 @@ class MatchmakingCommand(rc.Command): bot.unregister_keyboard_key(f"mm{mmevent.mmid}_DELETE") bot.unregister_keyboard_key(f"mm{mmevent.mmid}_START") + await self.interface.serf.api_call(client.delete_message, + chat_id=mmevent.interface_data.chat_id, + message_id=mmevent.interface_data.message_id) + if interrupt == Interrupts.TIME_RAN_OUT or interrupt == Interrupts.MANUAL_START: await asyncify(client.send_message, chat_id=self.config["Telegram"]["main_group_id"], @@ -364,11 +368,6 @@ class MatchmakingCommand(rc.Command): parse_mode="HTML", disable_webpage_preview=True ) - - await self.interface.serf.api_call(client.delete_message, - chat_id=mmevent.interface_data.chat_id, - message_id=mmevent.interface_data.message_id) - else: raise rc.UnsupportedError() # The end! From ba1a2a69d20bf31865a777d44ac501baadc792a2 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 14 Jun 2020 17:55:25 +0200 Subject: [PATCH 172/227] Use left join in cvstats --- pyproject.toml | 2 +- royalpack/stars/api_cvstats_avg.py | 6 +++--- royalpack/version.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d97ed7e9..37ac7ee7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.16" + version = "5.8.17" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/api_cvstats_avg.py b/royalpack/stars/api_cvstats_avg.py index 7748bb12..06664a24 100644 --- a/royalpack/stars/api_cvstats_avg.py +++ b/royalpack/stars/api_cvstats_avg.py @@ -41,7 +41,7 @@ FROM ( ) c GROUP BY ph ) all_time -JOIN +LEFT JOIN ( SELECT date_part('hour', c.h) ph, AVG(c.members_connected) members_connected, @@ -68,7 +68,7 @@ JOIN ) c GROUP BY ph ) last_week ON last_week.ph = all_time.ph -JOIN +LEFT JOIN ( SELECT date_part('hour', c.h) ph, AVG(c.members_connected) members_connected, @@ -95,7 +95,7 @@ JOIN ) c GROUP BY ph ) last_month ON last_month.ph = all_time.ph -JOIN +LEFT JOIN ( SELECT date_part('hour', c.h) ph, AVG(c.members_connected) members_connected, diff --git a/royalpack/version.py b/royalpack/version.py index 7151772d..52d8bc1f 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.16" +semantic = "5.8.17" From 73e740f137d24ddb5a3761d73b85f12ad118973c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 14 Jun 2020 18:15:11 +0200 Subject: [PATCH 173/227] publish: 5.8.18 --- pyproject.toml | 2 +- royalpack/stars/api_cvstats_avg.py | 62 +++++++++++++++--------------- royalpack/version.py | 2 +- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 37ac7ee7..8f36b19f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.17" + version = "5.8.18" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/api_cvstats_avg.py b/royalpack/stars/api_cvstats_avg.py index 06664a24..d4f78901 100644 --- a/royalpack/stars/api_cvstats_avg.py +++ b/royalpack/stars/api_cvstats_avg.py @@ -127,42 +127,42 @@ LEFT JOIN return [{ "h": r[0], "all_time": { - "members_connected": float(r[1]), - "users_connected": float(r[2]), - "members_online": float(r[3]), - "users_online": float(r[4]), - "members_playing": float(r[5]), - "users_playing": float(r[6]), - "members_total": float(r[7]), - "users_total": float(r[8]) + "members_connected": float(r[1]) if r[1] is not None else None, + "users_connected": float(r[2]) if r[2] is not None else None, + "members_online": float(r[3]) if r[3] is not None else None, + "users_online": float(r[4]) if r[4] is not None else None, + "members_playing": float(r[5]) if r[5] is not None else None, + "users_playing": float(r[6]) if r[6] is not None else None, + "members_total": float(r[7]) if r[7] is not None else None, + "users_total": float(r[8]) if r[8] is not None else None, }, "last_week": { - "members_connected": float(r[10]), - "users_connected": float(r[11]), - "members_online": float(r[12]), - "users_online": float(r[13]), - "members_playing": float(r[14]), - "users_playing": float(r[15]), - "members_total": float(r[16]), - "users_total": float(r[17]) + "members_connected": float(r[10]) if r[10] is not None else None, + "users_connected": float(r[11]) if r[11] is not None else None, + "members_online": float(r[12]) if r[12] is not None else None, + "users_online": float(r[13]) if r[13] is not None else None, + "members_playing": float(r[14]) if r[14] is not None else None, + "users_playing": float(r[15]) if r[15] is not None else None, + "members_total": float(r[16]) if r[16] is not None else None, + "users_total": float(r[17]) if r[17] is not None else None, }, "last_month": { - "members_connected": float(r[19]), - "users_connected": float(r[20]), - "members_online": float(r[21]), - "users_online": float(r[22]), - "members_playing": float(r[23]), - "users_playing": float(r[24]), - "members_total": float(r[25]), - "users_total": float(r[26]) + "members_connected": float(r[19]) if r[19] is not None else None, + "users_connected": float(r[20]) if r[20] is not None else None, + "members_online": float(r[21]) if r[21] is not None else None, + "users_online": float(r[22]) if r[22] is not None else None, + "members_playing": float(r[23]) if r[23] is not None else None, + "users_playing": float(r[24]) if r[24] is not None else None, + "members_total": float(r[25]) if r[25] is not None else None, + "users_total": float(r[26]) if r[26] is not None else None, }, "last_day": { - "members_connected": float(r[28]), - "users_connected": float(r[29]), - "members_online": float(r[30]), - "users_online": float(r[31]), - "members_playing": float(r[32]), - "users_playing": float(r[33]), - "members_total": float(r[34]), + "members_connected": float(r[28]) if r[28] is not None else None, + "users_connected": float(r[29]) if r[29] is not None else None, + "members_online": float(r[30]) if r[30] is not None else None, + "users_online": float(r[31]) if r[31] is not None else None, + "members_playing": float(r[32]) if r[32] is not None else None, + "users_playing": float(r[33]) if r[33] is not None else None, + "members_total": float(r[34]) if r[34] is not None else None, }, } for r in sorted(results.fetchall(), key=lambda s: s[0])] diff --git a/royalpack/version.py b/royalpack/version.py index 52d8bc1f..d6113090 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.17" +semantic = "5.8.18" From 2462539a508416ed167e64b36c7b8e74535fcc98 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 15 Jun 2020 21:29:58 +0200 Subject: [PATCH 174/227] 5.8.15 --- royalpack/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 royalpack/__init__.py diff --git a/royalpack/__init__.py b/royalpack/__init__.py deleted file mode 100644 index e69de29b..00000000 From 972f3caf780e510d1924303daa30c155de53f6b2 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 19 Jun 2020 02:08:00 +0200 Subject: [PATCH 175/227] ARTORIAS --- royalpack/stars/api_wiki_edit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/stars/api_wiki_edit.py b/royalpack/stars/api_wiki_edit.py index 866bf230..2c0f6d43 100644 --- a/royalpack/stars/api_wiki_edit.py +++ b/royalpack/stars/api_wiki_edit.py @@ -34,7 +34,7 @@ class ApiWikiEditStar(ApiStar): WikiPageT = self.alchemy.get(WikiPage) user = await data.user() - if not (user.role == "Admin" or user.role == "Member" or user.role == "Bot"): + if not ("admin" in user.roles or "member" in user.roles or "bot" in user.roles): raise ForbiddenError("You do not have sufficient permissions to edit this page.") if page_id is None: From 614d3274e7537d5cf7820744a569170a6262256e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 19 Jun 2020 02:09:09 +0200 Subject: [PATCH 176/227] publish: 5.8.19 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8f36b19f..5b63fea4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.18" + version = "5.8.19" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index d6113090..f862606d 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.18" +semantic = "5.8.19" From 630fc19179e740209045cf23bf05853ac41bfcdb Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 19 Jun 2020 17:39:46 +0200 Subject: [PATCH 177/227] publish: 5.8.20 --- pyproject.toml | 2 +- royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_user_get_ryg.py | 38 +++++++++++++++++++++++++++++ royalpack/tables/brawlhalla.py | 31 +++++++++++++++++------ royalpack/tables/dota.py | 17 +++++++++++-- royalpack/tables/leagueoflegends.py | 15 ++++++++++++ royalpack/tables/steam.py | 17 +++++++++++-- royalpack/tables/triviascores.py | 9 +++++++ royalpack/types/leagueleague.py | 13 ++++++++++ royalpack/version.py | 2 +- 10 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 royalpack/stars/api_user_get_ryg.py diff --git a/pyproject.toml b/pyproject.toml index 5b63fea4..99e47c53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.19" + version = "5.8.20" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 6d144ff5..84e76752 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -15,6 +15,7 @@ from .api_polls_get import ApiPollsGet from .api_polls_list import ApiPollsList from .api_cvstats_latest import ApiCvstatsLatestStar from .api_cvstats_avg import ApiCvstatsAvgStar +from .api_user_get_ryg import ApiUserGetRygStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -34,6 +35,7 @@ available_page_stars = [ ApiPollsList, ApiCvstatsLatestStar, ApiCvstatsAvgStar, + ApiUserGetRygStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_user_get_ryg.py b/royalpack/stars/api_user_get_ryg.py new file mode 100644 index 00000000..235d8210 --- /dev/null +++ b/royalpack/stars/api_user_get_ryg.py @@ -0,0 +1,38 @@ +import royalnet.constellation.api as rca +import royalnet.utils as ru +import royalnet.backpack.tables as rbt + + +class ApiUserGetRygStar(rca.ApiStar): + summary = "Ottieni le informazioni su un utente della Royal Games." + + description = "" + + methods = ["GET"] + + path = "/api/user/get/ryg/v1" + + requires_auth = False + + parameters = {"id": "L'id dell'utente di cui vuoi vedere le informazioni."} + + tags = ["user"] + + async def api(self, data: rca.ApiData) -> dict: + user_id_str = data["id"] + try: + user_id = int(user_id_str) + except (ValueError, TypeError): + raise rca.InvalidParameterError("'id' is not a valid int.") + user: rbt.User = await ru.asyncify(data.session.query(self.alchemy.get(rbt.User)).get, user_id) + if user is None: + raise rca.NotFoundError("No such user.") + result = { + **user.json(), + "bio": user.bio.json(), + "fiorygi": user.fiorygi.fiorygi if user.fiorygi is not None else None, + "steam": [steam.json() for steam in user.steam], + "leagueoflegends": [leagueoflegends.json() for leagueoflegends in user.leagueoflegends], + "trivia": user.trivia_score.json() if user.trivia_score is not None else None + } + return result diff --git a/royalpack/tables/brawlhalla.py b/royalpack/tables/brawlhalla.py index 27b60d66..e7803fb3 100644 --- a/royalpack/tables/brawlhalla.py +++ b/royalpack/tables/brawlhalla.py @@ -1,7 +1,7 @@ from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declared_attr -import steam +import steam.steamid from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal @@ -23,7 +23,7 @@ class Brawlhalla: @property def steamid(self): - return steam.SteamID(self._steamid) + return steam.steamid.SteamID(self._steamid) @declared_attr def name(self): @@ -58,34 +58,51 @@ class Brawlhalla: @property def rating_2v2(self): - duos = sorted(self.duos, key=lambda d: -d.rating) + duos = sorted(self.duos, key=lambda d: -d.rating_2v2) if len(duos) == 0: return None return duos[0].rating_2v2 @property def tier_2v2(self): - duos = sorted(self.duos, key=lambda d: -d.rating) + duos = sorted(self.duos, key=lambda d: -d.rating_2v2) if len(duos) == 0: return None return duos[0].tier_2v2 @property def metal_2v2(self): - duos = sorted(self.duos, key=lambda d: -d.rating) + duos = sorted(self.duos, key=lambda d: -d.rating_2v2) if len(duos) == 0: return None return duos[0].metal_2v2 @property def rank_2v2(self): - duos = sorted(self.duos, key=lambda d: -d.rating) + duos = sorted(self.duos, key=lambda d: -d.rating_2v2) if len(duos) == 0: return None return duos[0].rank_2v2 + def json(self): + one_rank = self.rank_1v1 + two_rank = self.rank_2v2 + return { + "name": self.name, + "1v1": { + "rating": self.rating_1v1, + "metal": one_rank.metal.name, + "tier": one_rank.tier.name + }, + "2v2": { + "rating": self.rating_2v2, + "metal": two_rank.metal.name, + "tier": two_rank.tier.name + } + } + def __repr__(self): return f"" def __str__(self): - return f"[c]brawlhalla:{self.brawlhalla_id}[/c]" \ No newline at end of file + return f"[c]brawlhalla:{self.brawlhalla_id}[/c]" diff --git a/royalpack/tables/dota.py b/royalpack/tables/dota.py index 3c75b0b0..5887d756 100644 --- a/royalpack/tables/dota.py +++ b/royalpack/tables/dota.py @@ -3,7 +3,7 @@ from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declared_attr from ..types import DotaMedal, DotaStars, DotaRank -import steam +import steam.steamid class Dota: @@ -19,7 +19,7 @@ class Dota: @property def steamid(self): - return steam.SteamID(self._steamid) + return steam.steamid.SteamID(self._steamid) @declared_attr def _rank_tier(self): @@ -72,6 +72,19 @@ class Dota: def losses(self): return Column(Integer) + def json(self): + rank = self.rank + + return { + "rank": { + "raw": self._rank_tier, + "medal": rank.medal.name, + "rank": rank.stars.name + }, + "wins": self.wins, + "losses": self.losses + } + def __repr__(self): return f"" diff --git a/royalpack/tables/leagueoflegends.py b/royalpack/tables/leagueoflegends.py index 4636324a..02618748 100644 --- a/royalpack/tables/leagueoflegends.py +++ b/royalpack/tables/leagueoflegends.py @@ -249,6 +249,21 @@ class LeagueOfLegends: def mastery_score(self): return Column(Integer, nullable=False, default=0) + def json(self): + return { + "region": self.region, + "profile_icon_id": self.profile_icon_id, + "summoner_name": self.summoner_name, + "puuid": self.puuid, + "summoner_level": self.summoner_level, + "summoner_id": self.summoner_id, + "account_id": self.account_id, + "soloq": self.rank_soloq.json() if self.rank_soloq is not None else None, + "twtrq": self.rank_twtrq.json() if self.rank_twtrq is not None else None, + "flexq": self.rank_flexq.json() if self.rank_flexq is not None else None, + "tftq": self.rank_tftq.json() if self.rank_tftq is not None else None, + } + def __repr__(self): return f"<{self.__class__.__qualname__} {str(self)}>" diff --git a/royalpack/tables/steam.py b/royalpack/tables/steam.py index 4d165ec7..24007241 100644 --- a/royalpack/tables/steam.py +++ b/royalpack/tables/steam.py @@ -1,7 +1,7 @@ from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declared_attr -import steam +import steam.steamid class Steam: @@ -21,7 +21,7 @@ class Steam: @property def steamid(self): - return steam.SteamID(self._steamid) + return steam.steamid.SteamID(self._steamid) @declared_attr def persona_name(self): @@ -43,6 +43,19 @@ class Steam: def account_creation_date(self): return Column(DateTime) + def json(self): + return { + "steamid": self._steamid, + "persona_name": self.persona_name, + "profile_url": self.profile_url, + "avatar": self.avatar, + "primary_clan_id": self.primary_clan_id, + "account_creation_date": self.account_creation_date.isoformat(), + + "dota": self.dota.json() if self.dota is not None else None, + "brawlhalla": self.brawlhalla.json() if self.brawlhalla is not None else None + } + def __repr__(self): return f"" diff --git a/royalpack/tables/triviascores.py b/royalpack/tables/triviascores.py index b5650b5e..8f240983 100644 --- a/royalpack/tables/triviascores.py +++ b/royalpack/tables/triviascores.py @@ -42,5 +42,14 @@ class TriviaScore: def score(self) -> float: return (self.correct_answers + self.correct_answers * self.correct_rate) * 10 + def json(self): + return { + "correct": self.correct_answers, + "wrong": self.wrong_answers, + "total": self.total_answers, + "rate": self.correct_rate, + "score": self.score + } + def __repr__(self): return f"" diff --git a/royalpack/types/leagueleague.py b/royalpack/types/leagueleague.py index 85c82c88..7a965346 100644 --- a/royalpack/types/leagueleague.py +++ b/royalpack/types/leagueleague.py @@ -150,3 +150,16 @@ class LeagueLeague: fresh_blood=d["freshBlood"], veteran=d["veteran"], ) + + def json(self): + return { + "tier": self.tier.name if self.tier is not None else None, + "rank": self.rank.name if self.tier is not None else None, + "points": self.points, + "wins": self.wins, + "losses": self.losses, + "inactive": self.inactive, + "hot_streak": self.hot_streak, + "fresh_blood": self.fresh_blood, + "veteran": self.veteran, + } diff --git a/royalpack/version.py b/royalpack/version.py index f862606d..0cf3cb22 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.19" +semantic = "5.8.20" From 6af7554b7ce364d40ffbe05cd6c1ec282ae59815 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 19 Jun 2020 18:16:50 +0200 Subject: [PATCH 178/227] publish: 5.8.22 --- pyproject.toml | 2 +- royalpack/stars/api_user_get_ryg.py | 2 +- royalpack/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 99e47c53..f75f6d8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.20" + version = "5.8.22" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/api_user_get_ryg.py b/royalpack/stars/api_user_get_ryg.py index 235d8210..ef5350de 100644 --- a/royalpack/stars/api_user_get_ryg.py +++ b/royalpack/stars/api_user_get_ryg.py @@ -29,7 +29,7 @@ class ApiUserGetRygStar(rca.ApiStar): raise rca.NotFoundError("No such user.") result = { **user.json(), - "bio": user.bio.json(), + "bio": user.bio.json() if user.bio is not None else None, "fiorygi": user.fiorygi.fiorygi if user.fiorygi is not None else None, "steam": [steam.json() for steam in user.steam], "leagueoflegends": [leagueoflegends.json() for leagueoflegends in user.leagueoflegends], diff --git a/royalpack/version.py b/royalpack/version.py index 0cf3cb22..3ad08f3f 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.20" +semantic = "5.8.22" From 5ad727ce21205c94665b78f1e03f0fede72dbb21 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 20 Jun 2020 03:49:48 +0200 Subject: [PATCH 179/227] publish: 5.8.23 --- pyproject.toml | 2 +- royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_user_find_ryg.py | 38 ++++++++++++++++++++++++++++ royalpack/stars/api_user_get_ryg.py | 6 ++++- royalpack/tables/brawlhalla.py | 6 +++-- royalpack/tables/dota.py | 2 +- royalpack/version.py | 2 +- 7 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 royalpack/stars/api_user_find_ryg.py diff --git a/pyproject.toml b/pyproject.toml index f75f6d8e..f3000f41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.22" + version = "5.8.23" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 84e76752..6137b1cc 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -16,6 +16,7 @@ from .api_polls_list import ApiPollsList from .api_cvstats_latest import ApiCvstatsLatestStar from .api_cvstats_avg import ApiCvstatsAvgStar from .api_user_get_ryg import ApiUserGetRygStar +from .api_user_find_ryg import ApiUserFindRygStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -36,6 +37,7 @@ available_page_stars = [ ApiCvstatsLatestStar, ApiCvstatsAvgStar, ApiUserGetRygStar, + ApiUserFindRygStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_user_find_ryg.py b/royalpack/stars/api_user_find_ryg.py new file mode 100644 index 00000000..60d3fe68 --- /dev/null +++ b/royalpack/stars/api_user_find_ryg.py @@ -0,0 +1,38 @@ +import royalnet.constellation.api as rca +import royalnet.utils as ru +import royalnet.backpack.tables as rbt +from .api_user_get_ryg import ApiUserGetRygStar + + +class ApiUserFindRygStar(ApiUserGetRygStar): + summary = "Ottieni le informazioni su un utente della Royal Games." + + description = "" + + methods = ["GET"] + + path = "/api/user/find/ryg/v1" + + requires_auth = False + + parameters = {"alias": "L'alias dell'utente di cui vuoi vedere le informazioni."} + + tags = ["user"] + + async def get_user(self, data: rca.ApiData): + user = await rbt.User.find(self.alchemy, data.session, data["alias"]) + if user is None: + raise rca.NotFoundError("No such user.") + return user + + async def api(self, data: rca.ApiData) -> dict: + user = await self.get_user(data) + result = { + **user.json(), + "bio": user.bio.json() if user.bio is not None else None, + "fiorygi": user.fiorygi.fiorygi if user.fiorygi is not None else None, + "steam": [steam.json() for steam in user.steam], + "leagueoflegends": [leagueoflegends.json() for leagueoflegends in user.leagueoflegends], + "trivia": user.trivia_score.json() if user.trivia_score is not None else None + } + return result diff --git a/royalpack/stars/api_user_get_ryg.py b/royalpack/stars/api_user_get_ryg.py index ef5350de..31d22350 100644 --- a/royalpack/stars/api_user_get_ryg.py +++ b/royalpack/stars/api_user_get_ryg.py @@ -18,7 +18,7 @@ class ApiUserGetRygStar(rca.ApiStar): tags = ["user"] - async def api(self, data: rca.ApiData) -> dict: + async def get_user(self, data: rca.ApiData): user_id_str = data["id"] try: user_id = int(user_id_str) @@ -27,6 +27,10 @@ class ApiUserGetRygStar(rca.ApiStar): user: rbt.User = await ru.asyncify(data.session.query(self.alchemy.get(rbt.User)).get, user_id) if user is None: raise rca.NotFoundError("No such user.") + return user + + async def api(self, data: rca.ApiData) -> dict: + user = await self.get_user(data) result = { **user.json(), "bio": user.bio.json() if user.bio is not None else None, diff --git a/royalpack/tables/brawlhalla.py b/royalpack/tables/brawlhalla.py index e7803fb3..aa8555eb 100644 --- a/royalpack/tables/brawlhalla.py +++ b/royalpack/tables/brawlhalla.py @@ -43,6 +43,8 @@ class Brawlhalla: @property def rank_1v1(self): + if self.metal_1v1 is None: + return None return BrawlhallaRank(metal=self.metal_1v1, tier=self.tier_1v1) @rank_1v1.setter @@ -93,12 +95,12 @@ class Brawlhalla: "rating": self.rating_1v1, "metal": one_rank.metal.name, "tier": one_rank.tier.name - }, + } if one_rank is not None else None, "2v2": { "rating": self.rating_2v2, "metal": two_rank.metal.name, "tier": two_rank.tier.name - } + } if two_rank is not None else None } def __repr__(self): diff --git a/royalpack/tables/dota.py b/royalpack/tables/dota.py index 5887d756..8ff9ccdc 100644 --- a/royalpack/tables/dota.py +++ b/royalpack/tables/dota.py @@ -80,7 +80,7 @@ class Dota: "raw": self._rank_tier, "medal": rank.medal.name, "rank": rank.stars.name - }, + } if self._rank_tier is not None else None, "wins": self.wins, "losses": self.losses } diff --git a/royalpack/version.py b/royalpack/version.py index 3ad08f3f..a756789d 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.22" +semantic = "5.8.23" From 6f259d15eccec0d82523543af5e46ff3ae897640 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 22 Jun 2020 19:27:11 +0200 Subject: [PATCH 180/227] publish: 5.9.2 --- poetry.lock | 109 +++++++++--------- pyproject.toml | 4 +- royalpack/stars/__init__.py | 36 ++---- royalpack/stars/api_bio.py | 45 ++++++++ royalpack/stars/api_bio_get.py | 22 ---- royalpack/stars/api_bio_set.py | 33 ------ royalpack/stars/api_cvstats_avg.py | 7 +- royalpack/stars/api_cvstats_latest.py | 7 +- .../{api_diario_get.py => api_diario.py} | 16 ++- royalpack/stars/api_diario_list.py | 13 ++- royalpack/stars/api_diario_random.py | 9 +- royalpack/stars/api_discord_cv.py | 8 +- royalpack/stars/api_discord_play.py | 15 ++- .../{api_fiorygi_get.py => api_fiorygi.py} | 20 ++-- royalpack/stars/api_poll.py | 63 ++++++++++ .../{api_polls_list.py => api_poll_list.py} | 13 +-- royalpack/stars/api_polls_create.py | 41 ------- royalpack/stars/api_polls_get.py | 34 ------ royalpack/stars/api_user_get_ryg.py | 42 ------- .../{api_user_find_ryg.py => api_user_ryg.py} | 33 ++++-- royalpack/stars/api_wiki_edit.py | 64 ---------- royalpack/stars/api_wiki_get.py | 30 ----- royalpack/stars/api_wiki_list.py | 19 --- royalpack/utils/__init__.py | 2 - royalpack/utils/finduser.py | 19 --- 25 files changed, 250 insertions(+), 454 deletions(-) create mode 100644 royalpack/stars/api_bio.py delete mode 100644 royalpack/stars/api_bio_get.py delete mode 100644 royalpack/stars/api_bio_set.py rename royalpack/stars/{api_diario_get.py => api_diario.py} (53%) rename royalpack/stars/{api_fiorygi_get.py => api_fiorygi.py} (66%) create mode 100644 royalpack/stars/api_poll.py rename royalpack/stars/{api_polls_list.py => api_poll_list.py} (71%) delete mode 100644 royalpack/stars/api_polls_create.py delete mode 100644 royalpack/stars/api_polls_get.py delete mode 100644 royalpack/stars/api_user_get_ryg.py rename royalpack/stars/{api_user_find_ryg.py => api_user_ryg.py} (52%) delete mode 100644 royalpack/stars/api_wiki_edit.py delete mode 100644 royalpack/stars/api_wiki_get.py delete mode 100644 royalpack/stars/api_wiki_list.py delete mode 100644 royalpack/utils/finduser.py diff --git a/poetry.lock b/poetry.lock index 23f7ebe0..34ff1acb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -67,7 +67,7 @@ description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false python-versions = "*" -version = "2020.4.5.1" +version = "2020.6.20" [[package]] category = "main" @@ -145,7 +145,7 @@ description = "Date parsing library designed to parse dates from HTML pages" name = "dateparser" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.7.4" +version = "0.7.6" [package.dependencies] python-dateutil = "*" @@ -269,7 +269,7 @@ 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.8" +version = "2.9" [[package]] category = "main" @@ -403,24 +403,24 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.5.14" +version = "2020.6.8" [[package]] category = "main" description = "Python HTTP for Humans." name = "requests" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.21.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.24.0" [package.dependencies] certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.9" -urllib3 = ">=1.21.1,<1.25" +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)", "idna (>=2.0.0)"] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] @@ -443,7 +443,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.8.13" +version = "5.9.1" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -600,12 +600,12 @@ description = "Module for interacting with various Steam features" name = "steam" optional = false python-versions = "*" -version = "1.0.1" +version = "1.0.2" [package.dependencies] cachetools = ">=3.0.0" pycryptodomex = ">=3.7.0" -requests = ">=2.9.1,<2.22.0" +requests = ">=2.9.1" six = ">=1.10" vdf = ">=3.3" @@ -644,11 +644,12 @@ category = "main" description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -version = "1.24.3" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.25.9" [package.extras] -secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] +brotli = ["brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] [[package]] @@ -709,10 +710,10 @@ description = "YouTube video downloader" name = "youtube-dl" optional = false python-versions = "*" -version = "2020.6.6" +version = "2020.6.16.1" [metadata] -content-hash = "9245b7ae163a3746554cd31e3b20294d26aa3534cc78303a419ac54850db55cb" +content-hash = "2e70b5afc7b2a39eb6a79be841489343c689c49f5a1f60659df93ca44cc0382e" python-versions = "^3.8" [metadata.files] @@ -763,8 +764,8 @@ cachetools = [ {file = "cachetools-4.1.0.tar.gz", hash = "sha256:1d057645db16ca7fe1f3bd953558897603d6f0b9c51ed9d11eb4d071ec4e2aab"}, ] certifi = [ - {file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"}, - {file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"}, + {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, + {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"}, @@ -834,8 +835,8 @@ cryptography = [ {file = "cryptography-2.9.2.tar.gz", hash = "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229"}, ] dateparser = [ - {file = "dateparser-0.7.4-py2.py3-none-any.whl", hash = "sha256:1b1f0e3034f82d1f92b45fa445826da6a36d67af8a1169e04869685594276011"}, - {file = "dateparser-0.7.4.tar.gz", hash = "sha256:fb5bfde4795fa4b179fe05c2c25b3981f785de26bec37e247dee1079c63d5689"}, + {file = "dateparser-0.7.6-py2.py3-none-any.whl", hash = "sha256:7552c994f893b5cb8fcf103b4cd2ff7f57aab9bfd2619fdf0cf571c0740fd90b"}, + {file = "dateparser-0.7.6.tar.gz", hash = "sha256:e875efd8c57c85c2d02b238239878db59ff1971f5a823457fcc69e493bf6ebfa"}, ] decorator = [ {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, @@ -877,8 +878,8 @@ humanfriendly = [ {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, ] idna = [ - {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, - {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, + {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, + {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, ] multidict = [ {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"}, @@ -1014,39 +1015,39 @@ pytz = [ {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, ] regex = [ - {file = "regex-2020.5.14-cp27-cp27m-win32.whl", hash = "sha256:e565569fc28e3ba3e475ec344d87ed3cd8ba2d575335359749298a0899fe122e"}, - {file = "regex-2020.5.14-cp27-cp27m-win_amd64.whl", hash = "sha256:d466967ac8e45244b9dfe302bbe5e3337f8dc4dec8d7d10f5e950d83b140d33a"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:27ff7325b297fb6e5ebb70d10437592433601c423f5acf86e5bc1ee2919b9561"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ea55b80eb0d1c3f1d8d784264a6764f931e172480a2f1868f2536444c5f01e01"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c9bce6e006fbe771a02bda468ec40ffccbf954803b470a0345ad39c603402577"}, - {file = "regex-2020.5.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:d881c2e657c51d89f02ae4c21d9adbef76b8325fe4d5cf0e9ad62f850f3a98fd"}, - {file = "regex-2020.5.14-cp36-cp36m-win32.whl", hash = "sha256:99568f00f7bf820c620f01721485cad230f3fb28f57d8fbf4a7967ec2e446994"}, - {file = "regex-2020.5.14-cp36-cp36m-win_amd64.whl", hash = "sha256:70c14743320a68c5dac7fc5a0f685be63bc2024b062fe2aaccc4acc3d01b14a1"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a7c37f048ec3920783abab99f8f4036561a174f1314302ccfa4e9ad31cb00eb4"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:89d76ce33d3266173f5be80bd4efcbd5196cafc34100fdab814f9b228dee0fa4"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:51f17abbe973c7673a61863516bdc9c0ef467407a940f39501e786a07406699c"}, - {file = "regex-2020.5.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ce5cc53aa9fbbf6712e92c7cf268274eaff30f6bd12a0754e8133d85a8fb0f5f"}, - {file = "regex-2020.5.14-cp37-cp37m-win32.whl", hash = "sha256:8044d1c085d49673aadb3d7dc20ef5cb5b030c7a4fa253a593dda2eab3059929"}, - {file = "regex-2020.5.14-cp37-cp37m-win_amd64.whl", hash = "sha256:c2062c7d470751b648f1cacc3f54460aebfc261285f14bc6da49c6943bd48bdd"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:329ba35d711e3428db6b45a53b1b13a0a8ba07cbbcf10bbed291a7da45f106c3"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:579ea215c81d18da550b62ff97ee187b99f1b135fd894a13451e00986a080cad"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:3a9394197664e35566242686d84dfd264c07b20f93514e2e09d3c2b3ffdf78fe"}, - {file = "regex-2020.5.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:ce367d21f33e23a84fb83a641b3834dd7dd8e9318ad8ff677fbfae5915a239f7"}, - {file = "regex-2020.5.14-cp38-cp38-win32.whl", hash = "sha256:1386e75c9d1574f6aa2e4eb5355374c8e55f9aac97e224a8a5a6abded0f9c927"}, - {file = "regex-2020.5.14-cp38-cp38-win_amd64.whl", hash = "sha256:7e61be8a2900897803c293247ef87366d5df86bf701083b6c43119c7c6c99108"}, - {file = "regex-2020.5.14.tar.gz", hash = "sha256:ce450ffbfec93821ab1fea94779a8440e10cf63819be6e176eb1973a6017aff5"}, + {file = "regex-2020.6.8-cp27-cp27m-win32.whl", hash = "sha256:fbff901c54c22425a5b809b914a3bfaf4b9570eee0e5ce8186ac71eb2025191c"}, + {file = "regex-2020.6.8-cp27-cp27m-win_amd64.whl", hash = "sha256:112e34adf95e45158c597feea65d06a8124898bdeac975c9087fe71b572bd938"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:92d8a043a4241a710c1cf7593f5577fbb832cf6c3a00ff3fc1ff2052aff5dd89"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bae83f2a56ab30d5353b47f9b2a33e4aac4de9401fb582b55c42b132a8ac3868"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b2ba0f78b3ef375114856cbdaa30559914d081c416b431f2437f83ce4f8b7f2f"}, + {file = "regex-2020.6.8-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:95fa7726d073c87141f7bbfb04c284901f8328e2d430eeb71b8ffdd5742a5ded"}, + {file = "regex-2020.6.8-cp36-cp36m-win32.whl", hash = "sha256:e3cdc9423808f7e1bb9c2e0bdb1c9dc37b0607b30d646ff6faf0d4e41ee8fee3"}, + {file = "regex-2020.6.8-cp36-cp36m-win_amd64.whl", hash = "sha256:c78e66a922de1c95a208e4ec02e2e5cf0bb83a36ceececc10a72841e53fbf2bd"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:08997a37b221a3e27d68ffb601e45abfb0093d39ee770e4257bd2f5115e8cb0a"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2f6f211633ee8d3f7706953e9d3edc7ce63a1d6aad0be5dcee1ece127eea13ae"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:55b4c25cbb3b29f8d5e63aeed27b49fa0f8476b0d4e1b3171d85db891938cc3a"}, + {file = "regex-2020.6.8-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:89cda1a5d3e33ec9e231ece7307afc101b5217523d55ef4dc7fb2abd6de71ba3"}, + {file = "regex-2020.6.8-cp37-cp37m-win32.whl", hash = "sha256:690f858d9a94d903cf5cada62ce069b5d93b313d7d05456dbcd99420856562d9"}, + {file = "regex-2020.6.8-cp37-cp37m-win_amd64.whl", hash = "sha256:1700419d8a18c26ff396b3b06ace315b5f2a6e780dad387e4c48717a12a22c29"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:654cb773b2792e50151f0e22be0f2b6e1c3a04c5328ff1d9d59c0398d37ef610"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:52e1b4bef02f4040b2fd547357a170fc1146e60ab310cdbdd098db86e929b387"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:cf59bbf282b627130f5ba68b7fa3abdb96372b24b66bdf72a4920e8153fc7910"}, + {file = "regex-2020.6.8-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5aaa5928b039ae440d775acea11d01e42ff26e1561c0ffcd3d805750973c6baf"}, + {file = "regex-2020.6.8-cp38-cp38-win32.whl", hash = "sha256:97712e0d0af05febd8ab63d2ef0ab2d0cd9deddf4476f7aa153f76feef4b2754"}, + {file = "regex-2020.6.8-cp38-cp38-win_amd64.whl", hash = "sha256:6ad8663c17db4c5ef438141f99e291c4d4edfeaacc0ce28b5bba2b0bf273d9b5"}, + {file = "regex-2020.6.8.tar.gz", hash = "sha256:e9b64e609d37438f7d6e68c2546d2cb8062f3adb27e6336bc129b51be20773ac"}, ] requests = [ - {file = "requests-2.21.0-py2.py3-none-any.whl", hash = "sha256:7bf2a778576d825600030a110f3c0e3e8edc51dfaafe1c146e39a2027784957b"}, - {file = "requests-2.21.0.tar.gz", hash = "sha256:502a824f31acdacb3a35b6690b5fbf0bc41d63a24a45c4004352b0242707598e"}, + {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, + {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, ] riotwatcher = [ {file = "riotwatcher-2.7.1-py2.py3-none-any.whl", hash = "sha256:3fb03b20f768cea7830d54c6d301a8341c67223625ac8536d26d1c140af3dcb0"}, {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.8.13-py3-none-any.whl", hash = "sha256:77bc201477db59e172caae049ba5edac5de7134cef5ef03d113636e4b9fd4f83"}, - {file = "royalnet-5.8.13.tar.gz", hash = "sha256:42c8772e03bdd9400990f853fe477d09759c547da2d300df536cd49f42159203"}, + {file = "royalnet-5.9.1-py3-none-any.whl", hash = "sha256:be5998c80d261d774ac7f70931cacb09c3e843ad838529aec51be54dc7091027"}, + {file = "royalnet-5.9.1.tar.gz", hash = "sha256:e1296389277b0773d2a0b73497165f869e413a22bcc046538b9030efd9090be2"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1093,7 +1094,7 @@ starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, ] steam = [ - {file = "steam-1.0.1.tar.gz", hash = "sha256:7a2635dc46a18a86f608c8b9f8e042126cf9bd7b8e8e9ca6dcacb0998cb56ec5"}, + {file = "steam-1.0.2.tar.gz", hash = "sha256:ca7c026848338ca2a004c0cb73d362c94e5c1a74815c8605d34fce3a6662f9c0"}, ] toml = [ {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, @@ -1115,8 +1116,8 @@ tzlocal = [ {file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"}, ] urllib3 = [ - {file = "urllib3-1.24.3-py2.py3-none-any.whl", hash = "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"}, - {file = "urllib3-1.24.3.tar.gz", hash = "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4"}, + {file = "urllib3-1.25.9-py2.py3-none-any.whl", hash = "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"}, + {file = "urllib3-1.25.9.tar.gz", hash = "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527"}, ] uvicorn = [ {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, @@ -1181,6 +1182,6 @@ yarl = [ {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, ] youtube-dl = [ - {file = "youtube_dl-2020.6.6-py2.py3-none-any.whl", hash = "sha256:813310fb7ab265c379e9aebb2bd6cde6995f9a8f22a06d2ff81c05dfab7da864"}, - {file = "youtube_dl-2020.6.6.tar.gz", hash = "sha256:74e6cc7395060fc39f0b8e21c1e4707486da904c96145bd875187bda2da83b04"}, + {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"}, ] diff --git a/pyproject.toml b/pyproject.toml index f3000f41..e15ff564 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.8.23" + version = "5.9.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "*" [tool.poetry.dependencies.royalnet] - version = "~5.8.14" + version = "~5.9.2" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 6137b1cc..7f6ec461 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -1,43 +1,31 @@ # Imports go here! -from .api_bio_get import ApiBioGetStar -from .api_bio_set import ApiBioSetStar -from .api_diario_get import ApiDiarioGetStar -from .api_diario_list import ApiDiarioListStar +from .api_bio import ApiBioSetStar +from .api_diario import ApiDiarioGetStar +from .api_diario_list import ApiDiarioPagesStar from .api_discord_cv import ApiDiscordCvStar from .api_discord_play import ApiDiscordPlayStar -from .api_wiki_edit import ApiWikiEditStar -from .api_wiki_get import ApiWikiGetStar -from .api_wiki_list import ApiWikiListStar -from .api_fiorygi_get import ApiFiorygiGetStar +from .api_fiorygi import ApiFiorygiStar from .api_diario_random import ApiDiarioRandomStar -from .api_polls_create import ApiPollsCreate -from .api_polls_get import ApiPollsGet -from .api_polls_list import ApiPollsList +from .api_poll import ApiPollStar +from .api_poll_list import ApiPollsListStar from .api_cvstats_latest import ApiCvstatsLatestStar from .api_cvstats_avg import ApiCvstatsAvgStar -from .api_user_get_ryg import ApiUserGetRygStar -from .api_user_find_ryg import ApiUserFindRygStar +from .api_user_ryg import ApiUserRygStar # Enter the PageStars of your Pack here! available_page_stars = [ - ApiBioGetStar, ApiBioSetStar, ApiDiarioGetStar, - ApiDiarioListStar, + ApiDiarioPagesStar, ApiDiscordCvStar, ApiDiscordPlayStar, - ApiWikiEditStar, - ApiWikiGetStar, - ApiWikiListStar, - ApiFiorygiGetStar, + ApiFiorygiStar, ApiDiarioRandomStar, - ApiPollsCreate, - ApiPollsGet, - ApiPollsList, + ApiPollStar, + ApiPollsListStar, ApiCvstatsLatestStar, ApiCvstatsAvgStar, - ApiUserGetRygStar, - ApiUserFindRygStar, + ApiUserRygStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_bio.py b/royalpack/stars/api_bio.py new file mode 100644 index 00000000..32b2baf4 --- /dev/null +++ b/royalpack/stars/api_bio.py @@ -0,0 +1,45 @@ +import royalnet.utils as ru +from royalnet.backpack.tables import * +from royalnet.constellation.api import * +from ..tables import Bio + + +class ApiBioSetStar(ApiStar): + path = "/api/bio/v2" + + methods = ["GET", "PUT"] + + parameters = { + "get": { + "uid": "The id of the user to get the bio of." + }, + "put": { + "contents": "The contents of the bio." + } + } + + auth = { + "get": False, + "put": True, + } + + tags = ["bio"] + + async def get(self, data: ApiData) -> ru.JSON: + """Get the bio of a specific user.""" + user = await User.find(self.alchemy, data.session, data.int("uid")) + return user.bio.json() if user.bio else None + + async def put(self, data: ApiData) -> ru.JSON: + """Set the bio of current user.""" + contents = data["contents"] + BioT = self.alchemy.get(Bio) + user = await data.user() + bio = user.bio + if bio is None: + bio = BioT(user=user, contents=contents) + data.session.add(bio) + else: + bio.contents = contents + await data.session_commit() + return bio.json() diff --git a/royalpack/stars/api_bio_get.py b/royalpack/stars/api_bio_get.py deleted file mode 100644 index 97d71112..00000000 --- a/royalpack/stars/api_bio_get.py +++ /dev/null @@ -1,22 +0,0 @@ -from royalnet.utils import * -from royalnet.backpack.tables import * -from royalnet.constellation.api import * -from ..utils import find_user_api - - -class ApiBioGetStar(ApiStar): - path = "/api/bio/get/v1" - - summary = "Get the bio of a Royalnet user." - - parameters = { - "id": "The user to get the bio of." - } - - tags = ["bio"] - - async def api(self, data: ApiData) -> dict: - user = await find_user_api(data["id"], self.alchemy, data.session) - if user.bio is None: - raise NotFoundError("User has no bio set.") - return user.bio.json() diff --git a/royalpack/stars/api_bio_set.py b/royalpack/stars/api_bio_set.py deleted file mode 100644 index 49285ae8..00000000 --- a/royalpack/stars/api_bio_set.py +++ /dev/null @@ -1,33 +0,0 @@ -import royalnet.utils as ru -from royalnet.backpack.tables import * -from royalnet.constellation.api import * -from ..tables import Bio - - -class ApiBioSetStar(ApiStar): - path = "/api/bio/set/v1" - - methods = ["PUT"] - - summary = "Set the bio of the logged in Royalnet user." - - parameters = { - "contents": "The contents of the bio." - } - - requires_auth = True - - tags = ["bio"] - - async def api(self, data: ApiData) -> ru.JSON: - contents = data["contents"] - BioT = self.alchemy.get(Bio) - user = await data.user() - bio = user.bio - if bio is None: - bio = BioT(user=user, contents=contents) - data.session.add(bio) - else: - bio.contents = contents - await data.session_commit() - return bio.json() diff --git a/royalpack/stars/api_cvstats_avg.py b/royalpack/stars/api_cvstats_avg.py index d4f78901..a9ccb6dd 100644 --- a/royalpack/stars/api_cvstats_avg.py +++ b/royalpack/stars/api_cvstats_avg.py @@ -7,13 +7,10 @@ from ..tables import Cvstats class ApiCvstatsAvgStar(ApiStar): path = "/api/cvstats/avg/v1" - methods = ["GET"] - - summary = "Get some averages on the cvstats." - tags = ["cvstats"] - async def api(self, data: ApiData) -> ru.JSON: + async def get(self, data: ApiData) -> ru.JSON: + """Get some averages on the cvstats.""" results = data.session.execute(""" SELECT * FROM ( diff --git a/royalpack/stars/api_cvstats_latest.py b/royalpack/stars/api_cvstats_latest.py index a2530339..16558d9e 100644 --- a/royalpack/stars/api_cvstats_latest.py +++ b/royalpack/stars/api_cvstats_latest.py @@ -7,13 +7,10 @@ from ..tables import Cvstats class ApiCvstatsLatestStar(ApiStar): path = "/api/cvstats/latest/v1" - methods = ["GET"] - - summary = "Get the latest 500 cvstats." - tags = ["cvstats"] - async def api(self, data: ApiData) -> ru.JSON: + async def get(self, data: ApiData) -> ru.JSON: + """Get the latest 500 cvstats recorded.""" CvstatsT = self.alchemy.get(Cvstats) cvstats = data.session.query(CvstatsT).order_by(CvstatsT.timestamp.desc()).limit(500).all() diff --git a/royalpack/stars/api_diario_get.py b/royalpack/stars/api_diario.py similarity index 53% rename from royalpack/stars/api_diario_get.py rename to royalpack/stars/api_diario.py index a0976edb..0347a080 100644 --- a/royalpack/stars/api_diario_get.py +++ b/royalpack/stars/api_diario.py @@ -4,21 +4,19 @@ from ..tables import * class ApiDiarioGetStar(ApiStar): - path = "/api/diario/get/v1" - - summary = "Get the diario entry with a specific id." + path = "/api/diario/v2" parameters = { - "id": "The id of the diario entry to get." + "get": { + "id": "The id of the diario entry to get." + } } tags = ["diario"] - async def api(self, data: ApiData) -> dict: - try: - diario_id = int(data["id"]) - except ValueError: - raise InvalidParameterError("'id' is not a valid int.") + async def get(self, data: ApiData) -> JSON: + """Get a specific diario entry.""" + diario_id = data.int("id") entry: Diario = await asyncify(data.session.query(self.alchemy.get(Diario)).get, diario_id) if entry is None: raise NotFoundError("No such diario entry.") diff --git a/royalpack/stars/api_diario_list.py b/royalpack/stars/api_diario_list.py index 0ca2b96b..3e20b75b 100644 --- a/royalpack/stars/api_diario_list.py +++ b/royalpack/stars/api_diario_list.py @@ -4,18 +4,19 @@ from royalnet.utils import * from ..tables import * -class ApiDiarioListStar(ApiStar): - path = "/api/diario/list/v1" - - summary = "Get a list of up to 500 diario entries." +class ApiDiarioPagesStar(ApiStar): + path = "/api/diario/pages/v1" parameters = { - "page": "The diario page you want to get. Can be negative to get the entries in reverse order." + "get": { + "page": "The diario page you want to get. Can be negative to get the entries in reverse order." + } } tags = ["diario"] - async def api(self, data: ApiData) -> dict: + async def get(self, data: ApiData) -> JSON: + """Get a diario page made of up to 500 diario entries.""" page_str = data["page"] try: page = int(page_str) diff --git a/royalpack/stars/api_diario_random.py b/royalpack/stars/api_diario_random.py index 3a2fc413..84540d58 100644 --- a/royalpack/stars/api_diario_random.py +++ b/royalpack/stars/api_diario_random.py @@ -8,15 +8,16 @@ from sqlalchemy import func class ApiDiarioRandomStar(ApiStar): path = "/api/diario/random/v1" - summary = "Get random diario entries." - parameters = { - "amount": "The number of diario entries to get." + "get": { + "amount": "The number of diario entries to get." + } } tags = ["diario"] - async def api(self, data: ApiData) -> JSON: + async def get(self, data: ApiData) -> JSON: + """Get random diario entries.""" DiarioT = self.alchemy.get(Diario) try: amount = int(data["amount"]) diff --git a/royalpack/stars/api_discord_cv.py b/royalpack/stars/api_discord_cv.py index ac4d49de..36e2f201 100644 --- a/royalpack/stars/api_discord_cv.py +++ b/royalpack/stars/api_discord_cv.py @@ -1,13 +1,15 @@ +import royalnet.utils as ru from royalnet.constellation.api import * class ApiDiscordCvStar(ApiStar): path = "/api/discord/cv/v1" - summary = "Get the members status of a single Discord guild. Equivalent to calling /cv in a chat." - tags = ["discord"] - async def api(self, data: ApiData) -> dict: + async def get(self, data: ApiData) -> ru.JSON: + """Get the members status of a single Discord guild. + + Equivalent to calling /cv in a chat.""" response = await self.interface.call_herald_event("discord", "discord_cv") return response diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index 47d0bf6a..4a869839 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -7,19 +7,22 @@ log = logging.getLogger(__name__) class ApiDiscordPlayStar(ApiStar): - path = "/api/discord/play/v1" + path = "/api/discord/play/v2" - summary = "Add a audio file to the RoyalQueue of a Discord Guild." + methods = ["POST"] parameters = { - "url": "The url of the audio file to add.", - "user": "The name to display in the File Added message.", - "guild_id": "The id of the guild owning the RoyalQueue to add the audio file to." + "post": { + "url": "The url of the audio file to add.", + "user": "The name to display in the File Added message.", + "guild_id": "The id of the guild owning the RoyalQueue to add the audio file to.", + } } tags = ["discord"] - async def api(self, data: ApiData) -> dict: + async def post(self, data: ApiData) -> dict: + """Add a audio file to the RoyalQueue of a Discord Guild.""" url = data["url"] user = data.get("user") guild_id_str = data.get("guild_id") diff --git a/royalpack/stars/api_fiorygi_get.py b/royalpack/stars/api_fiorygi.py similarity index 66% rename from royalpack/stars/api_fiorygi_get.py rename to royalpack/stars/api_fiorygi.py index 5e31e9b9..a8da8d35 100644 --- a/royalpack/stars/api_fiorygi_get.py +++ b/royalpack/stars/api_fiorygi.py @@ -2,23 +2,23 @@ from typing import * from royalnet.utils import * from royalnet.backpack.tables import * from royalnet.constellation.api import * -from ..utils import find_user_api -from ..tables import Fiorygi, FiorygiTransaction +from ..tables import Fiorygi -class ApiFiorygiGetStar(ApiStar): - path = "/api/user/fiorygi/get/v1" - - summary = "Get the fiorygi of a Royalnet user." +class ApiFiorygiStar(ApiStar): + path = "/api/fiorygi/v2" parameters = { - "id": "The user to get the fiorygi of." + "get": { + "uid": "The user to get the fiorygi of." + } } - tags = ["user"] + tags = ["fiorygi"] - async def api(self, data: ApiData) -> JSON: - user: User = await find_user_api(data["id"], self.alchemy, data.session) + async def get(self, data: ApiData) -> JSON: + """Get fiorygi information about a specific user.""" + user = await User.find(self.alchemy, data.session, data.int("uid")) if user.fiorygi is None: return { "fiorygi": 0, diff --git a/royalpack/stars/api_poll.py b/royalpack/stars/api_poll.py new file mode 100644 index 00000000..4426fa19 --- /dev/null +++ b/royalpack/stars/api_poll.py @@ -0,0 +1,63 @@ +from typing import * +import datetime +import uuid +from royalnet.utils import * +from royalnet.constellation.api import * +from ..tables import Poll + + +class ApiPollStar(ApiStar): + path = "/api/poll/v2" + + parameters = { + "get": { + "uuid": "The UUID of the poll to get.", + }, + "post": { + "question": "The question to ask in the poll.", + "description": "A longer Markdown-formatted description.", + "expires": "A ISO timestamp of the expiration date for the poll.", + } + } + + auth = { + "get": False, + "post": True + } + + methods = ["GET", "POST"] + + tags = ["poll"] + + async def get(self, data: ApiData) -> JSON: + """Get a specific poll.""" + PollT = self.alchemy.get(Poll) + + try: + pid = uuid.UUID(data["uuid"]) + except (ValueError, AttributeError, TypeError): + raise InvalidParameterError("'uuid' is not a valid UUID.") + + poll: Poll = await asyncify(data.session.query(PollT).get, pid) + if poll is None: + raise NotFoundError("No such page.") + + return poll.json() + + async def post(self, data: ApiData) -> JSON: + """Create a new poll.""" + PollT = self.alchemy.get(Poll) + + poll = PollT( + id=uuid.uuid4(), + creator=await data.user(), + created=datetime.datetime.now(), + expires=datetime.datetime.fromisoformat(data["expires"]) if "expires" in data else None, + question=data["question"], + description=data.get("description"), + ) + + data.session.add(poll) + await data.session_commit() + + return poll.json() diff --git a/royalpack/stars/api_polls_list.py b/royalpack/stars/api_poll_list.py similarity index 71% rename from royalpack/stars/api_polls_list.py rename to royalpack/stars/api_poll_list.py index 3b007362..e478f6e5 100644 --- a/royalpack/stars/api_polls_list.py +++ b/royalpack/stars/api_poll_list.py @@ -5,16 +5,13 @@ from ..tables import Poll import uuid -class ApiPollsList(ApiStar): - path = "/api/polls/list/v1" +class ApiPollsListStar(ApiStar): + path = "/api/poll/list/v2" - summary = "Get a list of all polls." + tags = ["poll"] - requires_auth = True - - tags = ["polls"] - - async def api(self, data: ApiData) -> JSON: + async def get(self, data: ApiData) -> JSON: + """Get a list of all polls.""" PollT = self.alchemy.get(Poll) polls: List[Poll] = await asyncify(data.session.query(PollT).all) diff --git a/royalpack/stars/api_polls_create.py b/royalpack/stars/api_polls_create.py deleted file mode 100644 index 50105ee0..00000000 --- a/royalpack/stars/api_polls_create.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import * -import datetime -import uuid -from royalnet.utils import * -from royalnet.constellation.api import * -from ..tables import Poll - - -class ApiPollsCreate(ApiStar): - path = "/api/polls/create/v1" - - summary = "Create a new poll." - - parameters = { - "question": "The question to ask in the poll.", - "description": "A longer Markdown-formatted description.", - "expires": "A ISO timestamp of the expiration date for the poll.", - } - - requires_auth = True - - methods = ["POST"] - - tags = ["polls"] - - async def api(self, data: ApiData) -> JSON: - PollT = self.alchemy.get(Poll) - - poll = PollT( - id=uuid.uuid4(), - creator=await data.user(), - created=datetime.datetime.now(), - expires=datetime.datetime.fromisoformat(data["expires"]) if "expires" in data else None, - question=data["question"], - description=data.get("description"), - ) - - data.session.add(poll) - await data.session_commit() - - return poll.json() diff --git a/royalpack/stars/api_polls_get.py b/royalpack/stars/api_polls_get.py deleted file mode 100644 index 4208dfa7..00000000 --- a/royalpack/stars/api_polls_get.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import * -import datetime -from royalnet.utils import * -from royalnet.constellation.api import * -from ..tables import Poll -import uuid - - -class ApiPollsGet(ApiStar): - path = "/api/polls/get/v1" - - summary = "Get the poll with a specific id." - - parameters = { - "uuid": "The UUID of the poll to get.", - } - - requires_auth = True - - tags = ["polls"] - - async def api(self, data: ApiData) -> JSON: - PollT = self.alchemy.get(Poll) - - try: - pid = uuid.UUID(data["uuid"]) - except (ValueError, AttributeError, TypeError): - raise InvalidParameterError("'uuid' is not a valid UUID.") - - poll: Poll = await asyncify(data.session.query(PollT).get, pid) - if poll is None: - raise NotFoundError("No such page.") - - return poll.json() diff --git a/royalpack/stars/api_user_get_ryg.py b/royalpack/stars/api_user_get_ryg.py deleted file mode 100644 index 31d22350..00000000 --- a/royalpack/stars/api_user_get_ryg.py +++ /dev/null @@ -1,42 +0,0 @@ -import royalnet.constellation.api as rca -import royalnet.utils as ru -import royalnet.backpack.tables as rbt - - -class ApiUserGetRygStar(rca.ApiStar): - summary = "Ottieni le informazioni su un utente della Royal Games." - - description = "" - - methods = ["GET"] - - path = "/api/user/get/ryg/v1" - - requires_auth = False - - parameters = {"id": "L'id dell'utente di cui vuoi vedere le informazioni."} - - tags = ["user"] - - async def get_user(self, data: rca.ApiData): - user_id_str = data["id"] - try: - user_id = int(user_id_str) - except (ValueError, TypeError): - raise rca.InvalidParameterError("'id' is not a valid int.") - user: rbt.User = await ru.asyncify(data.session.query(self.alchemy.get(rbt.User)).get, user_id) - if user is None: - raise rca.NotFoundError("No such user.") - return user - - async def api(self, data: rca.ApiData) -> dict: - user = await self.get_user(data) - result = { - **user.json(), - "bio": user.bio.json() if user.bio is not None else None, - "fiorygi": user.fiorygi.fiorygi if user.fiorygi is not None else None, - "steam": [steam.json() for steam in user.steam], - "leagueoflegends": [leagueoflegends.json() for leagueoflegends in user.leagueoflegends], - "trivia": user.trivia_score.json() if user.trivia_score is not None else None - } - return result diff --git a/royalpack/stars/api_user_find_ryg.py b/royalpack/stars/api_user_ryg.py similarity index 52% rename from royalpack/stars/api_user_find_ryg.py rename to royalpack/stars/api_user_ryg.py index 60d3fe68..39198429 100644 --- a/royalpack/stars/api_user_find_ryg.py +++ b/royalpack/stars/api_user_ryg.py @@ -1,31 +1,40 @@ import royalnet.constellation.api as rca import royalnet.utils as ru import royalnet.backpack.tables as rbt -from .api_user_get_ryg import ApiUserGetRygStar -class ApiUserFindRygStar(ApiUserGetRygStar): - summary = "Ottieni le informazioni su un utente della Royal Games." - - description = "" - +class ApiUserRygStar(rca.ApiStar): methods = ["GET"] - path = "/api/user/find/ryg/v1" + path = "/api/user/ryg/v2" - requires_auth = False - - parameters = {"alias": "L'alias dell'utente di cui vuoi vedere le informazioni."} + parameters = { + "get": { + "uid": "(Choose one) The id of the user to get information about.", + "alias": "(Choose one) The alias of the user to get information about.", + } + } tags = ["user"] async def get_user(self, data: rca.ApiData): - user = await rbt.User.find(self.alchemy, data.session, data["alias"]) + uid = data.int("uid", optional=True) + alias = data.str("alias", optional=True) + + if uid: + user = await rbt.User.find(self.alchemy, data.session, uid) + elif alias: + user = await rbt.User.find(self.alchemy, data.session, alias) + else: + raise rca.MissingParameterError("Neither uid or alias were specified.") + if user is None: raise rca.NotFoundError("No such user.") + return user - async def api(self, data: rca.ApiData) -> dict: + async def get(self, data: rca.ApiData) -> dict: + """Get Royalpack information about a user.""" user = await self.get_user(data) result = { **user.json(), diff --git a/royalpack/stars/api_wiki_edit.py b/royalpack/stars/api_wiki_edit.py deleted file mode 100644 index 2c0f6d43..00000000 --- a/royalpack/stars/api_wiki_edit.py +++ /dev/null @@ -1,64 +0,0 @@ -import uuid -import royalnet.utils as ru -from royalnet.backpack.tables import * -from royalnet.constellation.api import * -from ..tables import WikiPage - - -class ApiWikiEditStar(ApiStar): - path = "/api/wiki/edit/v1" - - methods = ["POST"] - - summary = "Edit the contents of a wiki page, or create a new one." - - parameters = { - "id": "The id of the wiki page to edit. Leave empty to create a new one.", - "title": "The new title of the wiki page.", - "contents": "The new contents of the wiki page.", - "format": "The format of the wiki page. The default is markdown.", - "theme": "The theme of the wiki page. The default is default." - } - - requires_auth = True - - tags = ["wiki"] - - async def api(self, data: ApiData) -> ru.JSON: - page_id = data.get("id") - title = data["title"] - contents = data["contents"] - format = data["format"] - theme = data["theme"] - - WikiPageT = self.alchemy.get(WikiPage) - - user = await data.user() - if not ("admin" in user.roles or "member" in user.roles or "bot" in user.roles): - raise ForbiddenError("You do not have sufficient permissions to edit this page.") - - if page_id is None: - page = WikiPageT( - page_id=uuid.uuid4(), - title=title, - contents=contents, - format=format, - theme=theme - ) - data.session.add(page) - else: - page = await ru.asyncify( - data.session - .query(WikiPageT) - .filter_by(page_id=uuid.UUID(page_id)) - .one_or_none - ) - if page is None: - raise NotFoundError(f"No page with the id {repr(page_id)} found.") - page.title = title - page.contents = contents - page.format = format - page.theme = theme - - await data.session_commit() - return page.json_full() diff --git a/royalpack/stars/api_wiki_get.py b/royalpack/stars/api_wiki_get.py deleted file mode 100644 index 3f0c843a..00000000 --- a/royalpack/stars/api_wiki_get.py +++ /dev/null @@ -1,30 +0,0 @@ -from starlette.requests import Request -from starlette.responses import * -from royalnet.constellation import * -from royalnet.utils import * -from ..tables import * -import uuid -from royalnet.constellation.api import * - - -class ApiWikiGetStar(ApiStar): - path = "/api/wiki/get/v1" - - summary = "Get information about a specific wiki page." - - parameters = { - "id": "The id of the wiki page to get information for." - } - - tags = ["wiki"] - - async def api(self, data: ApiData) -> dict: - wikipage_id_str = data["id"] - try: - wikipage_id = uuid.UUID(wikipage_id_str) - except (ValueError, AttributeError, TypeError): - raise InvalidParameterError("'id' is not a valid UUID.") - wikipage: WikiPage = await asyncify(data.session.query(self.alchemy.get(WikiPage)).get, wikipage_id) - if wikipage is None: - raise NotFoundError("No such page.") - return wikipage.json_full() diff --git a/royalpack/stars/api_wiki_list.py b/royalpack/stars/api_wiki_list.py deleted file mode 100644 index 6592fdd6..00000000 --- a/royalpack/stars/api_wiki_list.py +++ /dev/null @@ -1,19 +0,0 @@ -from starlette.requests import Request -from starlette.responses import * -from royalnet.constellation import * -from royalnet.utils import * -from royalnet.backpack.tables import * -from ..tables import * -from royalnet.constellation.api import * - - -class ApiWikiListStar(ApiStar): - path = "/api/wiki/list/v1" - - summary = "Get a list of available wiki pages." - - tags = ["wiki"] - - async def api(self, data: ApiData) -> JSON: - pages: typing.List[WikiPage] = await asyncify(data.session.query(self.alchemy.get(WikiPage)).all) - return [page.json_list() for page in sorted(pages, key=lambda p: p.title)] diff --git a/royalpack/utils/__init__.py b/royalpack/utils/__init__.py index 619a095d..bf359037 100644 --- a/royalpack/utils/__init__.py +++ b/royalpack/utils/__init__.py @@ -1,9 +1,7 @@ from .royalqueue import RoyalQueue -from .finduser import find_user_api from .royalpool import RoyalPool __all__ = [ "RoyalQueue", - "find_user_api", "RoyalPool", ] diff --git a/royalpack/utils/finduser.py b/royalpack/utils/finduser.py deleted file mode 100644 index d13ea95b..00000000 --- a/royalpack/utils/finduser.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import * -from royalnet.constellation.api import * -from royalnet.backpack.tables.users import User -from royalnet.utils import asyncify - -async def find_user_api(input: Union[int, str], alchemy, session): - if isinstance(input, int): - user_id = input - elif isinstance(input, str): - try: - user_id = int(input) - except ValueError: - raise InvalidParameterError(f"Invalid user id passed to {find_user_api.__name__}") - else: - raise TypeError(f"Invalid input type passed to {find_user_api.__name__}") - user: User = await asyncify(session.query(alchemy.get(User)).get, user_id) - if user is None: - raise NotFoundError("No such user.") - return user From b57c26046f4b386ee844f9fb3931061fb60752d0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 26 Jun 2020 16:13:11 +0200 Subject: [PATCH 181/227] publish: 5.9.1 --- poetry.lock | 135 +++++++++++++------------- pyproject.toml | 4 +- royalpack/events/discord_skip.py | 2 +- royalpack/stars/api_bio.py | 16 +-- royalpack/stars/api_cvstats_avg.py | 9 +- royalpack/stars/api_cvstats_latest.py | 8 +- royalpack/stars/api_diario.py | 13 +-- royalpack/stars/api_diario_list.py | 17 ++-- royalpack/stars/api_diario_random.py | 15 +-- royalpack/stars/api_discord_cv.py | 7 +- royalpack/stars/api_discord_play.py | 11 +-- royalpack/stars/api_fiorygi.py | 15 +-- royalpack/stars/api_poll.py | 20 ++-- royalpack/stars/api_poll_list.py | 12 +-- royalpack/stars/api_user_ryg.py | 6 +- royalpack/version.py | 2 +- 16 files changed, 146 insertions(+), 146 deletions(-) diff --git a/poetry.lock b/poetry.lock index 34ff1acb..3027676f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -313,7 +313,7 @@ description = "Cryptographic library for Python" name = "pycryptodomex" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.7" +version = "3.9.8" [[package]] category = "main" @@ -376,13 +376,12 @@ description = "We have made you a wrapper you can't refuse" name = "python-telegram-bot" optional = false python-versions = "*" -version = "12.7" +version = "12.8" [package.dependencies] certifi = "*" cryptography = "*" decorator = ">=4.4.0" -future = ">=0.16.0" tornado = ">=5.1" [package.extras] @@ -443,7 +442,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.9.1" +version = "5.10.0" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -569,7 +568,7 @@ description = "Database Abstraction Library" name = "sqlalchemy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.17" +version = "1.3.18" [package.extras] mssql = ["pyodbc"] @@ -713,7 +712,7 @@ python-versions = "*" version = "2020.6.16.1" [metadata] -content-hash = "2e70b5afc7b2a39eb6a79be841489343c689c49f5a1f60659df93ca44cc0382e" +content-hash = "a88c104db6c8828bc307d3db357aa02b6afd2ada8f6788a004bdb42417ad7207" python-versions = "^3.8" [metadata.files] @@ -941,36 +940,36 @@ pycparser = [ {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] pycryptodomex = [ - {file = "pycryptodomex-3.9.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:a3f2908666e6f74b8c4893f86dd02e16170f50e4a78ae7f3468b6208d54bc205"}, - {file = "pycryptodomex-3.9.7-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1537d2d15b604b303aef56e7f440895a1c81adbee786b91f1f06eddc34da5314"}, - {file = "pycryptodomex-3.9.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5cf306a17cccc327a33cdc3845629fa13f4573a4ec620ed607c79cf6785f2e27"}, - {file = "pycryptodomex-3.9.7-cp27-cp27m-win32.whl", hash = "sha256:37033976f72af829fe15f7fe5fe1dbed308cc43a98d9dd9d2a0a76de8ca5ee78"}, - {file = "pycryptodomex-3.9.7-cp27-cp27m-win_amd64.whl", hash = "sha256:ebfc2f885cafda076c31ae30fa0dd81e7e919ec34059a88d3018ed66e83fcce3"}, - {file = "pycryptodomex-3.9.7-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:5fff8da399af16a1855f58771223acbbdac720b9969cd03fc5013d2e9a7bd9a4"}, - {file = "pycryptodomex-3.9.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f7e5fc5e124200b19a14be33fb0099e956e6ebb5e25d287b0829ef0a78ed76c7"}, - {file = "pycryptodomex-3.9.7-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:e76e6638ead4a7d93262a24218f0ff3ff74de6b6c823b7e19dccb31b6a481978"}, - {file = "pycryptodomex-3.9.7-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:6b3a9a562688996f760b5077714c3ab8b62ca56061b6e9ab7906841e43e19f91"}, - {file = "pycryptodomex-3.9.7-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:4c93038ac011b36512cb0bf2ee3e2aec774e8bc81021d015917c89fe02bb0ee5"}, - {file = "pycryptodomex-3.9.7-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:87aa70daad6f039e814790a06422a3189311198b674b62f13933a2bdcb6b1bcc"}, - {file = "pycryptodomex-3.9.7-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3c3dd9d4c9c1e279d3945ae422895c901f98987333acc132dc094faf52afec35"}, - {file = "pycryptodomex-3.9.7-cp35-cp35m-win32.whl", hash = "sha256:59b0ea9cda5490f924771456912a225d8d9e678891f9f986661af718534719b2"}, - {file = "pycryptodomex-3.9.7-cp35-cp35m-win_amd64.whl", hash = "sha256:99be3a1df2b2b9f731ebe1c264a2c07c465e71cee68e35e1640b645b5213a755"}, - {file = "pycryptodomex-3.9.7-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:68650ce5b9f7152b8283302a4617269f821695a612692640dd247bd12ab21c0b"}, - {file = "pycryptodomex-3.9.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7e938ed51a59e29431ea86fab60423ada2757728db0f78952329fa02a789bd31"}, - {file = "pycryptodomex-3.9.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f5797a39933a3d41526da60856735e6684b2b71a8ca99d5f79555ca121be2f4b"}, - {file = "pycryptodomex-3.9.7-cp36-cp36m-win32.whl", hash = "sha256:e585d530764c459cbd5d460aed0288807bb881f376ca9a20e653645217895961"}, - {file = "pycryptodomex-3.9.7-cp36-cp36m-win_amd64.whl", hash = "sha256:45ee555fc5e28c119a46d44ce373f5237e54a35c61b750fb3a94446b09855dbc"}, - {file = "pycryptodomex-3.9.7-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:d2c3c280975638e2a2c2fd9cb36ab111980219757fa163a2755594b9448e4138"}, - {file = "pycryptodomex-3.9.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1d20ab8369b7558168fc014a0745c678613f9f486dae468cca2d68145196b8a4"}, - {file = "pycryptodomex-3.9.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:b1515ce3a8a2c3fa537d137c5ca5f8b7a902044d04e07d7c3aa26c3e026120fb"}, - {file = "pycryptodomex-3.9.7-cp37-cp37m-win32.whl", hash = "sha256:afb4c2fa3c6f492fd9a8b38d76e13f32d429b8e5e1e00238309391b5591cde0d"}, - {file = "pycryptodomex-3.9.7-cp37-cp37m-win_amd64.whl", hash = "sha256:c436919117c23355740c669f89720673578b9aa4569bbfe105f6c10101fc1966"}, - {file = "pycryptodomex-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fb350e31e55211fec8ddc89fc0256f3b9bc3b44b68a8bde1cf44b3b4e80c0e42"}, - {file = "pycryptodomex-3.9.7-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ae3d44a639fd11dbdeca47e35e94febb1ee8bc15daf26673331add37146e0b85"}, - {file = "pycryptodomex-3.9.7-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3c9b3fba037ea52c626060c5a87ee6de7e86c99e8a7c6ee07302539985d2bd64"}, - {file = "pycryptodomex-3.9.7-cp38-cp38-win32.whl", hash = "sha256:bf391b377413a197000b43ef2b74359974d8927d329a897c9f5ba7b63dca7b9c"}, - {file = "pycryptodomex-3.9.7-cp38-cp38-win_amd64.whl", hash = "sha256:1ecc9db7409db67765eb008e558879d298406642d33ade43a6488224d23e8081"}, - {file = "pycryptodomex-3.9.7.tar.gz", hash = "sha256:50163324834edd0c9ce3e4512ded3e221c969086e10fdd5d3fdcaadac5e24a78"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:c0d085c8187a1e4d3402f626c9e438b5861151ab132d8761d9c5ce6491a87761"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1714675fb4ac29a26ced38ca22eb8ffd923ac851b7a6140563863194d7158422"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c990f2c58f7c67688e9e86e6557ed05952669ff6f1343e77b459007d85f7df00"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-win32.whl", hash = "sha256:9fd758e5e2fe02d57860b85da34a1a1e7037155c4eadc2326fc7af02f9cae214"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-win_amd64.whl", hash = "sha256:b2d756620078570d3f940c84bc94dd30aa362b795cce8b2723300a8800b87f1c"}, + {file = "pycryptodomex-3.9.8-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2710fc8d83b3352b370db932b3710033b9d630b970ff5aaa3e7458b5336e3b32"}, + {file = "pycryptodomex-3.9.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2199708ebeed4b82eb45b10e1754292677f5a0df7d627ee91ea01290b9bab7e6"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:8044eae59301dd392fbb4a7c5d64e1aea8ef0be2540549807ecbe703d6233d68"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:06f5a458624c9b0e04c0086c7f84bcc578567dab0ddc816e0476b3057b18339f"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ccbbec59bf4b74226170c54476da5780c9176bae084878fc94d9a2c841218e34"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-win32.whl", hash = "sha256:e4e1c486bf226822c8dceac81d0ec59c0a2399dbd1b9e04f03c3efa3605db677"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-win_amd64.whl", hash = "sha256:2275a663c9e744ee4eace816ef2d446b3060554c5773a92fbc79b05bf47debda"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:93a75d1acd54efed314b82c952b39eac96ce98d241ad7431547442e5c56138aa"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e42860fbe1292668b682f6dabd225fbe2a7a4fa1632f0c39881c019e93dea594"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f60b3484ce4be04f5da3777c51c5140d3fe21cdd6674f2b6568f41c8130bcdeb"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-win32.whl", hash = "sha256:a2ee8ba99d33e1a434fcd27d7d0aa7964163efeee0730fe2efc9d60edae1fc71"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:58e19560814dabf5d788b95a13f6b98279cf41a49b1e49ee6cf6c79a57adb4c9"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:a2bc4e1a2e6ca3a18b2e0be6131a23af76fecb37990c159df6edc7da6df913e3"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4e0b27697fa1621c6d3d3b4edeec723c2e841285de6a8d378c1962da77b349be"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3caa32cf807422adf33c10c88c22e9e2e08b9d9d042f12e1e25fe23113dd618f"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-win32.whl", hash = "sha256:89be1bf55e50116fe7e493a7c0c483099770dd7f81b87ac8d04a43b1a203e259"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-win_amd64.whl", hash = "sha256:17272d06e4b2f6455ee2cbe93e8eb50d9450a5dc6223d06862ee1ea5d1235861"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea4d4b58f9bc34e224ef4b4604a6be03d72ef1f8c486391f970205f6733dbc46"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8fcdda24dddf47f716400d54fc7f75cadaaba1dd47cc127e59d752c9c0fc3c48"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ae6379350a09339109e9b6f419bb2c3f03d3e441f4b0f5b8ca699d47cc9ff7e"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-win32.whl", hash = "sha256:dc2bed32c7b138f1331794e454a953360c8cedf3ee62ae31f063822da6007489"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-win_amd64.whl", hash = "sha256:914fbb18e29c54585e6aa39d300385f90d0fa3b3cc02ed829b08f95c1acf60c2"}, + {file = "pycryptodomex-3.9.8-cp39-cp39-manylinux1_i686.whl", hash = "sha256:35b9c9177a9fe7288b19dd41554c9c8ca1063deb426dd5a02e7e2a7416b6bd11"}, + {file = "pycryptodomex-3.9.8-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:e070a1f91202ed34c396be5ea842b886f6fa2b90d2db437dc9fb35a26c80c060"}, + {file = "pycryptodomex-3.9.8.tar.gz", hash = "sha256:48cc2cfc251f04a6142badeb666d1ff49ca6fdfc303fd72579f62b768aaa52b9"}, ] pynacl = [ {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, @@ -1007,8 +1006,8 @@ python-multipart = [ {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, ] python-telegram-bot = [ - {file = "python-telegram-bot-12.7.tar.gz", hash = "sha256:218b0583afb8baeefe6f2f1ddd8f1bb1ae30f0af3ce9160a372abd2cdf258eef"}, - {file = "python_telegram_bot-12.7-py2.py3-none-any.whl", hash = "sha256:6878cc642114c8c116ceada41639a9df487f42d5478d9f34cae513cc5c260dee"}, + {file = "python-telegram-bot-12.8.tar.gz", hash = "sha256:327186c56469216207dcdf8706892e58e0a62e51ef46f5143268e387bbb4edc3"}, + {file = "python_telegram_bot-12.8-py2.py3-none-any.whl", hash = "sha256:7eebed539ccacf77896cff9e41d1f68746b8ff3ca4da1e2e59285e9c749cb050"}, ] pytz = [ {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, @@ -1046,8 +1045,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.9.1-py3-none-any.whl", hash = "sha256:be5998c80d261d774ac7f70931cacb09c3e843ad838529aec51be54dc7091027"}, - {file = "royalnet-5.9.1.tar.gz", hash = "sha256:e1296389277b0773d2a0b73497165f869e413a22bcc046538b9030efd9090be2"}, + {file = "royalnet-5.10.0-py3-none-any.whl", hash = "sha256:4d4d5360b71d509ec0ef64edd5c3767e378a7ce48ac1a224a0fa9fa3ea524aed"}, + {file = "royalnet-5.10.0.tar.gz", hash = "sha256:7fb7bd4b02f4f5a89b5085cfed0a1a3072d2081a3832ff5b949f06ad79e90635"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, @@ -1061,34 +1060,34 @@ six = [ {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.17-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:fe01bac7226499aedf472c62fa3b85b2c619365f3f14dd222ffe4f3aa91e5f98"}, - {file = "SQLAlchemy-1.3.17-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b50f45d0e82b4562f59f0e0ca511f65e412f2a97d790eea5f60e34e5f1aabc9a"}, - {file = "SQLAlchemy-1.3.17-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:ce2646e4c0807f3461be0653502bb48c6e91a5171d6e450367082c79e12868bf"}, - {file = "SQLAlchemy-1.3.17-cp27-cp27m-win32.whl", hash = "sha256:e4e2664232005bd306f878b0f167a31f944a07c4de0152c444f8c61bbe3cfb38"}, - {file = "SQLAlchemy-1.3.17-cp27-cp27m-win_amd64.whl", hash = "sha256:925b4fe5e7c03ed76912b75a9a41dfd682d59c0be43bce88d3b27f7f5ba028fb"}, - {file = "SQLAlchemy-1.3.17-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:869bbb637de58ab0a912b7f20e9192132f9fbc47fc6b5111cd1e0f6cdf5cf9b0"}, - {file = "SQLAlchemy-1.3.17-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:703c002277f0fbc3c04d0ae4989a174753a7554b2963c584ce2ec0cddcf2bc53"}, - {file = "SQLAlchemy-1.3.17-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:eb4fcf7105bf071c71068c6eee47499ab8d4b8f5a11fc35147c934f0faa60f23"}, - {file = "SQLAlchemy-1.3.17-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8d01e949a5d22e5c4800d59b50617c56125fc187fbeb8fa423e99858546de616"}, - {file = "SQLAlchemy-1.3.17-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a9e75e49a0f1583eee0ce93270232b8e7bb4b1edc89cc70b07600d525aef4f43"}, - {file = "SQLAlchemy-1.3.17-cp35-cp35m-win32.whl", hash = "sha256:a87d496884f40c94c85a647c385f4fd5887941d2609f71043e2b73f2436d9c65"}, - {file = "SQLAlchemy-1.3.17-cp35-cp35m-win_amd64.whl", hash = "sha256:6cd157ce74a911325e164441ff2d9b4e244659a25b3146310518d83202f15f7a"}, - {file = "SQLAlchemy-1.3.17-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:27e2efc8f77661c9af2681755974205e7462f1ae126f498f4fe12a8b24761d15"}, - {file = "SQLAlchemy-1.3.17-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:31c043d5211aa0e0773821fcc318eb5cbe2ec916dfbc4c6eea0c5188971988eb"}, - {file = "SQLAlchemy-1.3.17-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a9030cd30caf848a13a192c5e45367e3c6f363726569a56e75dc1151ee26d859"}, - {file = "SQLAlchemy-1.3.17-cp36-cp36m-win32.whl", hash = "sha256:f502ef245c492b391e0e23e94cba030ab91722dcc56963c85bfd7f3441ea2bbe"}, - {file = "SQLAlchemy-1.3.17-cp36-cp36m-win_amd64.whl", hash = "sha256:128bc917ed20d78143a45024455ff0aed7d3b96772eba13d5dbaf9cc57e5c41b"}, - {file = "SQLAlchemy-1.3.17-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:2a12f8be25b9ea3d1d5b165202181f2b7da4b3395289000284e5bb86154ce87c"}, - {file = "SQLAlchemy-1.3.17-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e8aa395482728de8bdcca9cc0faf3765ab483e81e01923aaa736b42f0294f570"}, - {file = "SQLAlchemy-1.3.17-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f35248f7e0d63b234a109dd72fbfb4b5cb6cb6840b221d0df0ecbf54ab087654"}, - {file = "SQLAlchemy-1.3.17-cp37-cp37m-win32.whl", hash = "sha256:ce1ddaadee913543ff0154021d31b134551f63428065168e756d90bdc4c686f5"}, - {file = "SQLAlchemy-1.3.17-cp37-cp37m-win_amd64.whl", hash = "sha256:9cb1819008f0225a7c066cac8bb0cf90847b2c4a6eb9ebb7431dbd00c56c06c5"}, - {file = "SQLAlchemy-1.3.17-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:65eb3b03229f684af0cf0ad3bcc771970c1260a82a791a8d07bffb63d8c95bcc"}, - {file = "SQLAlchemy-1.3.17-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8a0e0cd21da047ea10267c37caf12add400a92f0620c8bc09e4a6531a765d6d7"}, - {file = "SQLAlchemy-1.3.17-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:b7878e59ec31f12d54b3797689402ee3b5cfcb5598f2ebf26491732758751908"}, - {file = "SQLAlchemy-1.3.17-cp38-cp38-win32.whl", hash = "sha256:ce6c3d18b2a8ce364013d47b9cad71db815df31d55918403f8db7d890c9d07ae"}, - {file = "SQLAlchemy-1.3.17-cp38-cp38-win_amd64.whl", hash = "sha256:ed375a79f06cad285166e5be74745df1ed6845c5624aafadec4b7a29c25866ef"}, - {file = "SQLAlchemy-1.3.17.tar.gz", hash = "sha256:156a27548ba4e1fed944ff9fcdc150633e61d350d673ae7baaf6c25c04ac1f71"}, + {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"}, ] starlette = [ {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, diff --git a/pyproject.toml b/pyproject.toml index e15ff564..fb6f005b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.0" + version = "5.9.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -25,7 +25,7 @@ steam = "*" [tool.poetry.dependencies.royalnet] - version = "~5.9.2" + version = "~5.10.0" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/events/discord_skip.py b/royalpack/events/discord_skip.py index 69ff7714..d7ddc393 100644 --- a/royalpack/events/discord_skip.py +++ b/royalpack/events/discord_skip.py @@ -19,7 +19,7 @@ class DiscordSkipEvent(rc.Event): if guild_id is None: # TODO: trovare un modo per riprodurre canzoni su più server da Telegram raise rc.InvalidInputError("Non so in che Server riprodurre questo file...\n" - "Invia il comando su Discord, per favore!") + "Invia il comando su Discord, per favore!") guild: discord.Guild = client.get_guild(guild_id) if guild is None: raise rc.InvalidInputError("Impossibile trovare il Server specificato.") diff --git a/royalpack/stars/api_bio.py b/royalpack/stars/api_bio.py index 32b2baf4..ace47037 100644 --- a/royalpack/stars/api_bio.py +++ b/royalpack/stars/api_bio.py @@ -1,14 +1,12 @@ import royalnet.utils as ru -from royalnet.backpack.tables import * -from royalnet.constellation.api import * +import royalnet.backpack.tables as rbt +import royalnet.constellation.api as rca from ..tables import Bio -class ApiBioSetStar(ApiStar): +class ApiBioSetStar(rca.ApiStar): path = "/api/bio/v2" - methods = ["GET", "PUT"] - parameters = { "get": { "uid": "The id of the user to get the bio of." @@ -25,12 +23,14 @@ class ApiBioSetStar(ApiStar): tags = ["bio"] - async def get(self, data: ApiData) -> ru.JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get the bio of a specific user.""" - user = await User.find(self.alchemy, data.session, data.int("uid")) + user = await rbt.User.find(self.alchemy, data.session, data.int("uid")) return user.bio.json() if user.bio else None - async def put(self, data: ApiData) -> ru.JSON: + @rca.magic + async def put(self, data: rca.ApiData) -> ru.JSON: """Set the bio of current user.""" contents = data["contents"] BioT = self.alchemy.get(Bio) diff --git a/royalpack/stars/api_cvstats_avg.py b/royalpack/stars/api_cvstats_avg.py index a9ccb6dd..f65eb79b 100644 --- a/royalpack/stars/api_cvstats_avg.py +++ b/royalpack/stars/api_cvstats_avg.py @@ -1,15 +1,14 @@ +import royalnet.constellation.api as rca import royalnet.utils as ru -from royalnet.backpack.tables import * -from royalnet.constellation.api import * -from ..tables import Cvstats -class ApiCvstatsAvgStar(ApiStar): +class ApiCvstatsAvgStar(rca.ApiStar): path = "/api/cvstats/avg/v1" tags = ["cvstats"] - async def get(self, data: ApiData) -> ru.JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get some averages on the cvstats.""" results = data.session.execute(""" SELECT * diff --git a/royalpack/stars/api_cvstats_latest.py b/royalpack/stars/api_cvstats_latest.py index 16558d9e..4c6d426c 100644 --- a/royalpack/stars/api_cvstats_latest.py +++ b/royalpack/stars/api_cvstats_latest.py @@ -1,15 +1,15 @@ import royalnet.utils as ru -from royalnet.backpack.tables import * -from royalnet.constellation.api import * +import royalnet.constellation.api as rca from ..tables import Cvstats -class ApiCvstatsLatestStar(ApiStar): +class ApiCvstatsLatestStar(rca.ApiStar): path = "/api/cvstats/latest/v1" tags = ["cvstats"] - async def get(self, data: ApiData) -> ru.JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get the latest 500 cvstats recorded.""" CvstatsT = self.alchemy.get(Cvstats) diff --git a/royalpack/stars/api_diario.py b/royalpack/stars/api_diario.py index 0347a080..0e9246ec 100644 --- a/royalpack/stars/api_diario.py +++ b/royalpack/stars/api_diario.py @@ -1,9 +1,9 @@ -from royalnet.constellation.api import * -from royalnet.utils import * +import royalnet.constellation.api as rca +import royalnet.utils as ru from ..tables import * -class ApiDiarioGetStar(ApiStar): +class ApiDiarioGetStar(rca.ApiStar): path = "/api/diario/v2" parameters = { @@ -14,10 +14,11 @@ class ApiDiarioGetStar(ApiStar): tags = ["diario"] - async def get(self, data: ApiData) -> JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get a specific diario entry.""" diario_id = data.int("id") - entry: Diario = await asyncify(data.session.query(self.alchemy.get(Diario)).get, diario_id) + entry: Diario = await ru.asyncify(data.session.query(self.alchemy.get(Diario)).get, diario_id) if entry is None: - raise NotFoundError("No such diario entry.") + raise rca.NotFoundError("No such diario entry.") return entry.json() diff --git a/royalpack/stars/api_diario_list.py b/royalpack/stars/api_diario_list.py index 3e20b75b..7bc47f50 100644 --- a/royalpack/stars/api_diario_list.py +++ b/royalpack/stars/api_diario_list.py @@ -1,10 +1,10 @@ -from starlette.responses import * -from royalnet.constellation.api import * -from royalnet.utils import * +from typing import * +import royalnet.constellation.api as rca +import royalnet.utils as ru from ..tables import * -class ApiDiarioPagesStar(ApiStar): +class ApiDiarioPagesStar(rca.ApiStar): path = "/api/diario/pages/v1" parameters = { @@ -15,16 +15,17 @@ class ApiDiarioPagesStar(ApiStar): tags = ["diario"] - async def get(self, data: ApiData) -> JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get a diario page made of up to 500 diario entries.""" page_str = data["page"] try: page = int(page_str) except ValueError: - raise InvalidParameterError("'page' is not a valid int.") + raise rca.InvalidParameterError("'page' is not a valid int.") if page < 0: page = -page-1 - entries: typing.List[Diario] = await asyncify( + entries: List[Diario] = await ru.asyncify( data.session .query(self.alchemy.get(Diario)) .order_by(self.alchemy.get(Diario).diario_id.desc()).limit(500) @@ -32,7 +33,7 @@ class ApiDiarioPagesStar(ApiStar): .all ) else: - entries: typing.List[Diario] = await asyncify( + entries: List[Diario] = await ru.asyncify( data.session .query(self.alchemy.get(Diario)) .order_by(self.alchemy.get(Diario).diario_id) diff --git a/royalpack/stars/api_diario_random.py b/royalpack/stars/api_diario_random.py index 84540d58..a095c887 100644 --- a/royalpack/stars/api_diario_random.py +++ b/royalpack/stars/api_diario_random.py @@ -1,11 +1,11 @@ from typing import * -from royalnet.constellation.api import * -from royalnet.utils import * +import royalnet.constellation.api as rca +import royalnet.utils as ru from ..tables import * from sqlalchemy import func -class ApiDiarioRandomStar(ApiStar): +class ApiDiarioRandomStar(rca.ApiStar): path = "/api/diario/random/v1" parameters = { @@ -16,14 +16,15 @@ class ApiDiarioRandomStar(ApiStar): tags = ["diario"] - async def get(self, data: ApiData) -> JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get random diario entries.""" DiarioT = self.alchemy.get(Diario) try: amount = int(data["amount"]) except ValueError: - raise InvalidParameterError("'amount' is not a valid int.") - entries: List[Diario] = await asyncify( + raise rca.InvalidParameterError("'amount' is not a valid int.") + entries: List[Diario] = await ru.asyncify( data.session .query(DiarioT) .order_by(func.random()) @@ -31,5 +32,5 @@ class ApiDiarioRandomStar(ApiStar): .all ) if len(entries) < amount: - raise NotFoundError("Not enough diario entries.") + raise rca.NotFoundError("Not enough diario entries.") return list(map(lambda e: e.json(), entries)) diff --git a/royalpack/stars/api_discord_cv.py b/royalpack/stars/api_discord_cv.py index 36e2f201..1ee1108c 100644 --- a/royalpack/stars/api_discord_cv.py +++ b/royalpack/stars/api_discord_cv.py @@ -1,13 +1,14 @@ import royalnet.utils as ru -from royalnet.constellation.api import * +import royalnet.constellation.api as rca -class ApiDiscordCvStar(ApiStar): +class ApiDiscordCvStar(rca.ApiStar): path = "/api/discord/cv/v1" tags = ["discord"] - async def get(self, data: ApiData) -> ru.JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get the members status of a single Discord guild. Equivalent to calling /cv in a chat.""" diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py index 4a869839..3633d826 100644 --- a/royalpack/stars/api_discord_play.py +++ b/royalpack/stars/api_discord_play.py @@ -1,16 +1,14 @@ from typing import * -from royalnet.constellation.api import * +import royalnet.constellation.api as rca import logging log = logging.getLogger(__name__) -class ApiDiscordPlayStar(ApiStar): +class ApiDiscordPlayStar(rca.ApiStar): path = "/api/discord/play/v2" - methods = ["POST"] - parameters = { "post": { "url": "The url of the audio file to add.", @@ -21,7 +19,8 @@ class ApiDiscordPlayStar(ApiStar): tags = ["discord"] - async def post(self, data: ApiData) -> dict: + @rca.magic + async def post(self, data: rca.ApiData) -> dict: """Add a audio file to the RoyalQueue of a Discord Guild.""" url = data["url"] user = data.get("user") @@ -30,7 +29,7 @@ class ApiDiscordPlayStar(ApiStar): try: guild_id: Optional[int] = int(guild_id_str) except (ValueError, TypeError): - raise InvalidParameterError("'guild_id' is not a valid int.") + raise rca.InvalidParameterError("'guild_id' is not a valid int.") else: guild_id = None log.info(f"Received request to play {url} on guild_id {guild_id} via web") diff --git a/royalpack/stars/api_fiorygi.py b/royalpack/stars/api_fiorygi.py index a8da8d35..ecad8d55 100644 --- a/royalpack/stars/api_fiorygi.py +++ b/royalpack/stars/api_fiorygi.py @@ -1,11 +1,11 @@ from typing import * -from royalnet.utils import * -from royalnet.backpack.tables import * -from royalnet.constellation.api import * +import royalnet.utils as ru +import royalnet.backpack.tables as rbt +import royalnet.constellation.api as rca from ..tables import Fiorygi -class ApiFiorygiStar(ApiStar): +class ApiFiorygiStar(rca.ApiStar): path = "/api/fiorygi/v2" parameters = { @@ -16,9 +16,10 @@ class ApiFiorygiStar(ApiStar): tags = ["fiorygi"] - async def get(self, data: ApiData) -> JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get fiorygi information about a specific user.""" - user = await User.find(self.alchemy, data.session, data.int("uid")) + user = await rbt.User.find(self.alchemy, data.session, data.int("uid")) if user.fiorygi is None: return { "fiorygi": 0, @@ -26,7 +27,7 @@ class ApiFiorygiStar(ApiStar): "warning": "No associated fiorygi table" } fiorygi: Fiorygi = user.fiorygi - transactions: JSON = sorted(fiorygi.transactions, key=lambda t: -t.id) + transactions: ru.JSON = sorted(fiorygi.transactions, key=lambda t: -t.id) return { "fiorygi": fiorygi.fiorygi, "transactions": list(map(lambda t: { diff --git a/royalpack/stars/api_poll.py b/royalpack/stars/api_poll.py index 4426fa19..b60fe7cb 100644 --- a/royalpack/stars/api_poll.py +++ b/royalpack/stars/api_poll.py @@ -1,12 +1,12 @@ from typing import * import datetime import uuid -from royalnet.utils import * -from royalnet.constellation.api import * +import royalnet.utils as ru +import royalnet.constellation.api as rca from ..tables import Poll -class ApiPollStar(ApiStar): +class ApiPollStar(rca.ApiStar): path = "/api/poll/v2" parameters = { @@ -25,26 +25,26 @@ class ApiPollStar(ApiStar): "post": True } - methods = ["GET", "POST"] - tags = ["poll"] - async def get(self, data: ApiData) -> JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get a specific poll.""" PollT = self.alchemy.get(Poll) try: pid = uuid.UUID(data["uuid"]) except (ValueError, AttributeError, TypeError): - raise InvalidParameterError("'uuid' is not a valid UUID.") + raise rca.InvalidParameterError("'uuid' is not a valid UUID.") - poll: Poll = await asyncify(data.session.query(PollT).get, pid) + poll: Poll = await ru.asyncify(data.session.query(PollT).get, pid) if poll is None: - raise NotFoundError("No such page.") + raise rca.NotFoundError("No such page.") return poll.json() - async def post(self, data: ApiData) -> JSON: + @rca.magic + async def post(self, data: rca.ApiData) -> ru.JSON: """Create a new poll.""" PollT = self.alchemy.get(Poll) diff --git a/royalpack/stars/api_poll_list.py b/royalpack/stars/api_poll_list.py index e478f6e5..b686babf 100644 --- a/royalpack/stars/api_poll_list.py +++ b/royalpack/stars/api_poll_list.py @@ -1,20 +1,20 @@ from typing import * -from royalnet.utils import * -from royalnet.constellation.api import * +import royalnet.constellation.api as rca +import royalnet.utils as ru from ..tables import Poll -import uuid -class ApiPollsListStar(ApiStar): +class ApiPollsListStar(rca.ApiStar): path = "/api/poll/list/v2" tags = ["poll"] - async def get(self, data: ApiData) -> JSON: + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: """Get a list of all polls.""" PollT = self.alchemy.get(Poll) - polls: List[Poll] = await asyncify(data.session.query(PollT).all) + polls: List[Poll] = await ru.asyncify(data.session.query(PollT).all) return list(map(lambda p: { "id": p.id, diff --git a/royalpack/stars/api_user_ryg.py b/royalpack/stars/api_user_ryg.py index 39198429..5f0b42ea 100644 --- a/royalpack/stars/api_user_ryg.py +++ b/royalpack/stars/api_user_ryg.py @@ -1,11 +1,8 @@ -import royalnet.constellation.api as rca -import royalnet.utils as ru import royalnet.backpack.tables as rbt +import royalnet.constellation.api as rca class ApiUserRygStar(rca.ApiStar): - methods = ["GET"] - path = "/api/user/ryg/v2" parameters = { @@ -33,6 +30,7 @@ class ApiUserRygStar(rca.ApiStar): return user + @rca.magic async def get(self, data: rca.ApiData) -> dict: """Get Royalpack information about a user.""" user = await self.get_user(data) diff --git a/royalpack/version.py b/royalpack/version.py index a756789d..6c855539 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.8.23" +semantic = "5.9.1" From 4e6c2d9ed36b3ff1c094179c0933f85f8f6df28b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 28 Jun 2020 23:52:20 +0200 Subject: [PATCH 182/227] publish: 5.9.2 --- pyproject.toml | 2 +- royalpack/commands/eat.py | 2 +- royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_user_ryg_list.py | 23 +++++++++++++++++++++++ royalpack/version.py | 2 +- 5 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 royalpack/stars/api_user_ryg_list.py diff --git a/pyproject.toml b/pyproject.toml index fb6f005b..44a977ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.1" + version = "5.9.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/eat.py b/royalpack/commands/eat.py index e24498b6..a9766fcb 100644 --- a/royalpack/commands/eat.py +++ b/royalpack/commands/eat.py @@ -95,7 +95,7 @@ class EatCommand(Command): "gelato di steffo": "🍨 Hai provato a rubare il {food}...\n[i]...Ma sei arrivato tardi: l'ha già mangiato.[/i]", "biscotto": "🍪 Hai mangiato un {food} di contrabbando.\n[i]L'Inquisizione non lo saprà mai![/i]", "biscotti": "🍪 Hai mangiato tanti {food} di contrabbando.\n[i]Attento! L'Inquisizione è sulle tue tracce![/i]", - "crocchette di pollo": "🍗 Hai mangiato {food]!\n[i]Dio porco maledetto, infame, CAPRA, porca Madonna, Dio cane, " + "crocchette di pollo": "🍗 Hai mangiato {food}!\n[i]Dio porco maledetto, infame, CAPRA, porca Madonna, Dio cane, " "HAI PERSO. UN POMERIGGIO PER C- ooh se è questo dio cane, altro che sfondamento dei cieli " "*roba non capibile*, sfondi tutti dio can li distruggi, non ci rimane più niente.[/i]", diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 7f6ec461..429f8969 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -11,6 +11,7 @@ from .api_poll_list import ApiPollsListStar from .api_cvstats_latest import ApiCvstatsLatestStar from .api_cvstats_avg import ApiCvstatsAvgStar from .api_user_ryg import ApiUserRygStar +from .api_user_ryg_list import ApiUserRygListStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -26,6 +27,7 @@ available_page_stars = [ ApiCvstatsLatestStar, ApiCvstatsAvgStar, ApiUserRygStar, + ApiUserRygListStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_user_ryg_list.py b/royalpack/stars/api_user_ryg_list.py new file mode 100644 index 00000000..13dba55b --- /dev/null +++ b/royalpack/stars/api_user_ryg_list.py @@ -0,0 +1,23 @@ +from starlette.responses import * +import royalnet.utils as ru +import royalnet.backpack.tables as rbt +import royalnet.constellation.api as rca + + +class ApiUserRygListStar(rca.ApiStar): + path = "/api/user/ryg/list/v1" + + tags = ["user"] + + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: + """Get Royalpack information about all user.""" + users: typing.List[rbt.User] = await ru.asyncify(data.session.query(self.alchemy.get(rbt.User)).all) + return [{ + **user.json(), + "bio": user.bio.json() if user.bio is not None else None, + "fiorygi": user.fiorygi.fiorygi if user.fiorygi is not None else None, + "steam": [steam.json() for steam in user.steam], + "leagueoflegends": [leagueoflegends.json() for leagueoflegends in user.leagueoflegends], + "trivia": user.trivia_score.json() if user.trivia_score is not None else None + } for user in users] diff --git a/royalpack/version.py b/royalpack/version.py index 6c855539..62374c71 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.1" +semantic = "5.9.2" From d009f63a073221589295186ac0cf95fc62e7e814 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 1 Jul 2020 00:11:14 +0200 Subject: [PATCH 183/227] Add ping command --- royalpack/commands/__init__.py | 2 ++ royalpack/commands/ping.py | 55 ++++++++++++++++++++++++++++++++++ royalpack/events/__init__.py | 2 ++ royalpack/events/pong.py | 10 +++++++ 4 files changed, 69 insertions(+) create mode 100644 royalpack/commands/ping.py create mode 100644 royalpack/events/pong.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index fecb9e04..b7e3ee3d 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -61,6 +61,7 @@ from .magicktreasure import MagicktreasureCommand from .treasure import TreasureCommand from .givetreasure import GivetreasureCommand from .cat import CatCommand +from .ping import PingCommand # Enter the commands of your Pack here! available_commands = [ @@ -126,6 +127,7 @@ available_commands = [ TreasureCommand, GivetreasureCommand, CatCommand, + PingCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/ping.py b/royalpack/commands/ping.py new file mode 100644 index 00000000..d8f17b79 --- /dev/null +++ b/royalpack/commands/ping.py @@ -0,0 +1,55 @@ +import asyncio +from typing import * +import royalnet +import royalnet.commands as rc + + +class PingCommand(rc.Command): + name: str = "ping" + + description: str = "Display the status of the Herald network." + + syntax: str = "" + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + await data.reply("📶 Ping...") + + telegram_c = self.interface.call_herald_event("telegram", "pong") + discord_c = self.interface.call_herald_event("discord", "pong") + constellation_c = self.interface.call_herald_event("constellation", "pong") + + telegram_t = self.loop.create_task(telegram_c) + discord_t = self.loop.create_task(discord_c) + constellation_t = self.loop.create_task(constellation_c) + + await asyncio.sleep(10) + + try: + telegram_r = telegram_t.result() + except (asyncio.CancelledError, asyncio.InvalidStateError): + telegram_r = None + try: + discord_r = discord_t.result() + except (asyncio.CancelledError, asyncio.InvalidStateError): + discord_r = None + try: + constellation_r = constellation_t.result() + except (asyncio.CancelledError, asyncio.InvalidStateError): + constellation_r = None + + lines = ["📶 [b]Pong![/b]", ""] + + if telegram_r: + lines.append("🔵 Telegram") + else: + lines.append("🔴 Telegram") + if discord_r: + lines.append("🔵 Discord") + else: + lines.append("🔴 Discord") + if constellation_r: + lines.append("🔵 Constellation") + else: + lines.append("🔴 Constellation") + + await data.reply("\n".join(lines)) diff --git a/royalpack/events/__init__.py b/royalpack/events/__init__.py index 380d5cb2..03ae8b08 100644 --- a/royalpack/events/__init__.py +++ b/royalpack/events/__init__.py @@ -8,6 +8,7 @@ from .discord_pause import DiscordPauseEvent from .discord_playable import DiscordPlaymodeEvent from .discord_lazy_play import DiscordLazyPlayEvent from .telegram_message import TelegramMessageEvent +from .pong import PongEvent # Enter the commands of your Pack here! available_events = [ @@ -20,6 +21,7 @@ available_events = [ DiscordPlaymodeEvent, DiscordLazyPlayEvent, TelegramMessageEvent, + PongEvent, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/events/pong.py b/royalpack/events/pong.py new file mode 100644 index 00000000..d62e6026 --- /dev/null +++ b/royalpack/events/pong.py @@ -0,0 +1,10 @@ +from typing import * +import royalnet +import royalnet.commands as rc + + +class PongEvent(rc.Event): + name = "pong" + + async def run(self, **kwargs) -> dict: + return {"status": "connected"} From f31a4d36623879ea6eb5dd9e9a18de69604d252c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 1 Jul 2020 01:08:09 +0200 Subject: [PATCH 184/227] publish: 5.9.3 --- pyproject.toml | 2 +- royalpack/commands/ping.py | 43 +++++++++++--------------------------- royalpack/version.py | 2 +- 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 44a977ea..7b0f3a7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.2" + version = "5.9.3" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/ping.py b/royalpack/commands/ping.py index d8f17b79..a681bc1d 100644 --- a/royalpack/commands/ping.py +++ b/royalpack/commands/ping.py @@ -11,45 +11,26 @@ class PingCommand(rc.Command): syntax: str = "" + _targets = ["telegram", "discord", "matrix", "constellation"] + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: await data.reply("📶 Ping...") - telegram_c = self.interface.call_herald_event("telegram", "pong") - discord_c = self.interface.call_herald_event("discord", "pong") - constellation_c = self.interface.call_herald_event("constellation", "pong") + tasks = {} - telegram_t = self.loop.create_task(telegram_c) - discord_t = self.loop.create_task(discord_c) - constellation_t = self.loop.create_task(constellation_c) + for target in self._targets: + tasks[target] = self.loop.create_task(self.interface.call_herald_event(target, "pong")) await asyncio.sleep(10) - try: - telegram_r = telegram_t.result() - except (asyncio.CancelledError, asyncio.InvalidStateError): - telegram_r = None - try: - discord_r = discord_t.result() - except (asyncio.CancelledError, asyncio.InvalidStateError): - discord_r = None - try: - constellation_r = constellation_t.result() - except (asyncio.CancelledError, asyncio.InvalidStateError): - constellation_r = None - lines = ["📶 [b]Pong![/b]", ""] - if telegram_r: - lines.append("🔵 Telegram") - else: - lines.append("🔴 Telegram") - if discord_r: - lines.append("🔵 Discord") - else: - lines.append("🔴 Discord") - if constellation_r: - lines.append("🔵 Constellation") - else: - lines.append("🔴 Constellation") + for name, task in tasks.items(): + try: + print(task.result()) + except (asyncio.CancelledError, asyncio.InvalidStateError): + lines.append(f"🔴 [c]{name}[/c]") + else: + lines.append(f"🔵 [c]{name}[/c]") await data.reply("\n".join(lines)) diff --git a/royalpack/version.py b/royalpack/version.py index 62374c71..d6a72e3e 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.2" +semantic = "5.9.3" From a9739c1865f67cf0cef9fd688bb5011f3d0609bb Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 1 Jul 2020 16:47:30 +0200 Subject: [PATCH 185/227] publish: 5.9.4 --- royalpack/commands/ping.py | 9 +++++++-- royalpack/events/pong.py | 3 ++- royalpack/version.py | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/royalpack/commands/ping.py b/royalpack/commands/ping.py index a681bc1d..576f6e63 100644 --- a/royalpack/commands/ping.py +++ b/royalpack/commands/ping.py @@ -1,3 +1,4 @@ +import datetime import asyncio from typing import * import royalnet @@ -18,6 +19,7 @@ class PingCommand(rc.Command): tasks = {} + start = datetime.datetime.now() for target in self._targets: tasks[target] = self.loop.create_task(self.interface.call_herald_event(target, "pong")) @@ -27,10 +29,13 @@ class PingCommand(rc.Command): for name, task in tasks.items(): try: - print(task.result()) + d = task.result() except (asyncio.CancelledError, asyncio.InvalidStateError): lines.append(f"🔴 [c]{name}[/c]") else: - lines.append(f"🔵 [c]{name}[/c]") + end = datetime.datetime.fromtimestamp(d["timestamp"]) + delta = end - start + + lines.append(f"🔵 [c]{name}[/c] ({delta.microseconds // 1000} ms)") await data.reply("\n".join(lines)) diff --git a/royalpack/events/pong.py b/royalpack/events/pong.py index d62e6026..b6943e5d 100644 --- a/royalpack/events/pong.py +++ b/royalpack/events/pong.py @@ -1,10 +1,11 @@ from typing import * import royalnet import royalnet.commands as rc +import datetime class PongEvent(rc.Event): name = "pong" async def run(self, **kwargs) -> dict: - return {"status": "connected"} + return {"timestamp": datetime.datetime.now().timestamp()} diff --git a/royalpack/version.py b/royalpack/version.py index d6a72e3e..209315d0 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.3" +semantic = "5.9.4" From a104551f6c5f87b074876e11cd757b7968b7f85e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 1 Jul 2020 16:48:06 +0200 Subject: [PATCH 186/227] publish: 5.9.4 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7b0f3a7d..c677c900 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.3" + version = "5.9.4" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" From fdacd61093066eaad24dc53b32fd58144b05d25a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 1 Jul 2020 23:23:19 +0200 Subject: [PATCH 187/227] Update README --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index b99a5610..b48c9811 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,56 @@ # `royalpack` -## Required configuration options +## Configuration ```toml -Imgur.token = -Telegram.main_group_id = -Discord.main_channel_id = -Dota.updater = -Peertube.instance_url = -Peertube.feed_update_timeout = -Funkwhale.instance_url = -Cv.displayed_role_id = -Lol.token = -Lol.region = -Lol.updater = -Play.max_song_duration = -Steam.web_api_key = -Brawlhalla.api_key = -Brawlhalla.updater = -Matchmaking.mm_chat_id = +[Packs."royalpack"] + +# The main Telegram group +Telegram.main_group_id = -1001153723135 + +# The main Discord channel +Discord.main_channel_id = 566023556618518538 + +# A Imgur API token (https://apidocs.imgur.com/?version=latest) +Imgur.token = "1234567890abcde" + +# A Steam Web API key (https://steamcommunity.com/dev/apikey) +Steam.web_api_key = "123567890ABCDEF123567890ABCDEF12" + +# Should Royalnet automatically update the Dota ranks of all users? +Dota.updater = false + +# Should Royalnet automatically update the League of Legends ranks of all users? +Lol.updater = false + +# A League of Legends API token (https://developer.riotgames.com/) +Lol.token = "RGAPI-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + +# The region where your players are located +Lol.region = "euw1" + +# Should Royalnet automatically update the Brawlhalla ranks of all users? +Brawlhalla.updater = false + +# A Brawlhalla API key (https://dev.brawlhalla.com/) +Brawlhalla.api_key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + +# The Peertube instance you want to use for new video notifications +Peertube.instance_url = "https://pt.steffo.eu" + +# The delay in seconds between two new video checks +Peertube.feed_update_timeout = 300 + +# The Funkwhale instance you want to use for the fw commands +Funkwhale.instance_url = "https://fw.steffo.eu" + +# The id of the role that users should have to be displayed by default in cv +Cv.displayed_role_id = 424549048561958912 + +# The max duration of a song downloaded with the play commands +Play.max_song_duration = 7230 + +# The Telegram channel where matchmaking messages should be sent in +Matchmaking.mm_chat_id = -1001204402796 + ``` \ No newline at end of file From 6c7cfeb668f9267d71c57468749f93d6a5f30f5e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Jul 2020 21:40:33 +0200 Subject: [PATCH 188/227] publish: 5.9.5 --- poetry.lock | 20 +- pyproject.toml | 2 +- royalpack/commands/__init__.py | 2 +- royalpack/commands/matchmaking.py | 804 +++++++++++------- .../{royalpack.py => royalpackversion.py} | 2 +- royalpack/tables/mmevents.py | 2 +- royalpack/types/mmchoice.py | 2 +- royalpack/version.py | 2 +- 8 files changed, 494 insertions(+), 342 deletions(-) rename royalpack/commands/{royalpack.py => royalpackversion.py} (94%) diff --git a/poetry.lock b/poetry.lock index 3027676f..7bada1e4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -59,7 +59,7 @@ description = "Extensible memoizing collections and decorators" name = "cachetools" optional = false python-versions = "~=3.5" -version = "4.1.0" +version = "4.1.1" [[package]] category = "main" @@ -269,7 +269,7 @@ 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.9" +version = "2.10" [[package]] category = "main" @@ -442,7 +442,7 @@ description = "A multipurpose bot and web framework" name = "royalnet" optional = false python-versions = ">=3.8,<4.0" -version = "5.10.0" +version = "5.10.3" [package.dependencies] dateparser = ">=0.7.2,<0.8.0" @@ -712,7 +712,7 @@ python-versions = "*" version = "2020.6.16.1" [metadata] -content-hash = "a88c104db6c8828bc307d3db357aa02b6afd2ada8f6788a004bdb42417ad7207" +content-hash = "b0649ccbfdffd5947cbb0d4930182bd3b5edbf39181880db20e7b73ee85c9b02" python-versions = "^3.8" [metadata.files] @@ -759,8 +759,8 @@ bcrypt = [ {file = "bcrypt-3.1.7.tar.gz", hash = "sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42"}, ] cachetools = [ - {file = "cachetools-4.1.0-py3-none-any.whl", hash = "sha256:de5d88f87781602201cde465d3afe837546663b168e8b39df67411b0bf10cefc"}, - {file = "cachetools-4.1.0.tar.gz", hash = "sha256:1d057645db16ca7fe1f3bd953558897603d6f0b9c51ed9d11eb4d071ec4e2aab"}, + {file = "cachetools-4.1.1-py3-none-any.whl", hash = "sha256:513d4ff98dd27f85743a8dc0e92f55ddb1b49e060c2d5961512855cda2c01a98"}, + {file = "cachetools-4.1.1.tar.gz", hash = "sha256:bbaa39c3dede00175df2dc2b03d0cf18dd2d32a7de7beb68072d13043c9edb20"}, ] certifi = [ {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, @@ -877,8 +877,8 @@ humanfriendly = [ {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, ] idna = [ - {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, - {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, ] multidict = [ {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"}, @@ -1045,8 +1045,8 @@ riotwatcher = [ {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, ] royalnet = [ - {file = "royalnet-5.10.0-py3-none-any.whl", hash = "sha256:4d4d5360b71d509ec0ef64edd5c3767e378a7ce48ac1a224a0fa9fa3ea524aed"}, - {file = "royalnet-5.10.0.tar.gz", hash = "sha256:7fb7bd4b02f4f5a89b5085cfed0a1a3072d2081a3832ff5b949f06ad79e90635"}, + {file = "royalnet-5.10.3-py3-none-any.whl", hash = "sha256:1042a7383e26dbc76d03289d73f3c1b4d167cf860e272397b88ea54db0af513d"}, + {file = "royalnet-5.10.3.tar.gz", hash = "sha256:0232279024a3fd92c374770904443d5a0d7537dd0bf360e6c3f4e47068719fc0"}, ] royalspells = [ {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, diff --git a/pyproject.toml b/pyproject.toml index c677c900..6b6cfeba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "*" [tool.poetry.dependencies.royalnet] - version = "~5.10.0" + version = "~5.10.3" # Maybe... there is a way to make these selectable? extras = [ "telegram", diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index b7e3ee3d..64057b96 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -53,7 +53,7 @@ from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand from .matchmaking import MatchmakingCommand from .cvstats import CvstatsCommand from .elevatormusic import ElevatormusicCommand -from .royalpack import RoyalpackCommand +from .royalpackversion import RoyalpackCommand from .givefiorygi import GivefiorygiCommand from .help import HelpCommand from .pug import PugCommand diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 5ed3785a..8c556677 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -1,3 +1,4 @@ +import contextlib from typing import * import datetime import re @@ -6,16 +7,14 @@ import typing import random import enum import asyncio as aio -from telegram import Bot as PTBBot from telegram import Message as PTBMessage from telegram import InlineKeyboardMarkup as InKM from telegram import InlineKeyboardButton as InKB from telegram.error import TelegramError import royalnet.commands as rc -from royalnet.serf.telegram import TelegramSerf as TelegramBot from royalnet.serf.telegram import escape as telegram_escape from royalnet.utils import asyncify, sleep_until, sentry_async_wrap -from royalnet.backpack.tables import User +import logging from ..tables import MMEvent, MMResponse, FiorygiTransaction from ..types import MMChoice, MMInterfaceDataTelegram @@ -27,59 +26,492 @@ class Interrupts(enum.Enum): MANUAL_DELETE = enum.auto() +mmchoice_sorting = { + MMChoice.YES: -4, + MMChoice.LATE_SHORT: -3, + MMChoice.LATE_MEDIUM: -2, + MMChoice.LATE_LONG: -1, + MMChoice.MAYBE: 0, + MMChoice.NO: 1 +} + + +class MMTask: + def __init__(self, mmid: int, *, command: rc.Command): + log.debug(f"Creating task for: {mmid}") + + self.loop: aio.AbstractEventLoop = command.loop + self.task: Optional[aio.Task] = None + self.queue: aio.Queue = aio.Queue(loop=self.loop) + self.command: rc.Command = command + self.mmid: int = mmid + + self._session: Optional = None + self._EventT: Optional[Type[MMEvent]] = None + self._ResponseT: Optional[Type[MMResponse]] = None + self._mmevent: Optional[MMEvent] = None + + @property + def is_running(self): + return self.task is not None + + def get_response_line(self, response: MMResponse): + # noinspection PyListCreation + line = [] + + # Emoji + line.append(f"{response.choice.value}") + + # Mention the user if he said yes, otherwise just display his name + if response.choice == MMChoice.NO: + line.append(f"{response.user.telegram[0].name()}") + else: + line.append(f"{response.user.telegram[0].mention()}") + + # Late time + if response.choice == MMChoice.LATE_SHORT: + td = self._mmevent.datetime + datetime.timedelta(minutes=10) + line.append(f"[{td.strftime('%H:%M')}]") + + elif response.choice == MMChoice.LATE_MEDIUM: + td = self._mmevent.datetime + datetime.timedelta(minutes=30) + line.append(f"[{td.strftime('%H:%M')}]") + + elif response.choice == MMChoice.LATE_LONG: + td = self._mmevent.datetime + datetime.timedelta(minutes=60) + line.append(f"[{td.strftime('%H:%M')}+]") + + # Creator + if response.user == self._mmevent.creator: + line.append("👑") + + # Result + return " ".join(line) + + @property + def channel_text(self) -> str: + # noinspection PyListCreation + text = [] + + # First line + if self._mmevent.datetime is None: + text.append(f"🌐 [Prossimamente] [b]{self._mmevent.title}[/b]") + else: + text.append(f"🚩 [{self._mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{self._mmevent.title}[/b]") + + # Description + if self._mmevent.description: + text.append(f"{self._mmevent.description}") + + # Spacer + text.append("") + + # Responses + responses = sorted(self._mmevent.responses, key=lambda r: mmchoice_sorting[r.choice]) + for response in responses: + text.append(self.get_response_line(response)) + + # Result + return "\n".join(text) + + @property + def start_text(self) -> str: + # noinspection PyListCreation + text = [] + + # First line + if self._mmevent.datetime is None: + text.append(f"🌐 Le iscrizioni all'evento [b]{self._mmevent.title}[/b] sono terminate!") + else: + text.append(f"🚩 L'evento [b]{self._mmevent.title}[/b] è iniziato!") + + # Description + if self._mmevent.description: + text.append(f"{self._mmevent.description}") + + # Spacer + text.append("") + + # Responses + responses = sorted(self._mmevent.responses, key=lambda r: mmchoice_sorting[r.choice]) + for response in responses: + text.append(self.get_response_line(response)) + + # Result + return "\n".join(text) + + @property + def delete_text(self) -> str: + return f"🗑 L'evento [b]{self._mmevent.title}[/b] è stato eliminato." + + def get_answer_callback(self, choice: MMChoice): + async def callback(data: rc.CommandData): + # Find the user who clicked on the button + user = await data.get_author(error_if_none=True) + + # Get the related MMEvent + mmevent: MMEvent = await asyncify(data.session.query(self._EventT).get, self.mmid) + + # Check if the user had already responded + mmresponse: MMResponse = await asyncify( + data.session.query(self._ResponseT).filter_by(user=user, mmevent=mmevent).one_or_none + ) + + if mmresponse is None: + # If they didn't respond, create a new MMResponse + mmresponse = self._ResponseT(user=user, mmevent=mmevent, choice=choice) + data.session.add(mmresponse) + + # Drop fiorygi + if random.randrange(100) < self.command.config["Matchmaking"]["fiorygi_award_chance"]: + await FiorygiTransaction.spawn_fiorygi(data, user, 1, "aver risposto a un matchmaking") + else: + # Change their response + mmresponse.choice = choice + await data.session_commit() + + await self.telegram_channel_message_update() + + await data.reply(f"{choice.value} Hai risposto al matchmaking!") + return callback + + def get_delete_callback(self): + async def callback(data: rc.CommandData): + # Find the user who clicked on the button + user = await data.get_author(error_if_none=True) + + # Get the related MMEvent + mmevent: MMEvent = await asyncify(data.session.query(self._EventT).get, self.mmid) + + # Ensure the user has the required roles to start the matchmaking + if user != mmevent.creator and "admin" not in user.roles: + raise rc.UserError("Non hai i permessi per eliminare questo matchmaking!") + + # Interrupt the matchmaking with the MANUAL_DELETE reason + await self.queue.put(Interrupts.MANUAL_DELETE) + + await data.reply(f"🗑 Evento eliminato!") + return callback + + def get_start_callback(self): + async def callback(data: rc.CommandData): + # Find the user who clicked on the button + user = await data.get_author(error_if_none=True) + + # Get the related MMEvent + mmevent: MMEvent = await asyncify(data.session.query(self._EventT).get, self.mmid) + + # Ensure the user has the required roles to start the matchmaking + if user != mmevent.creator and "admin" not in user.roles: + raise rc.UserError("Non hai i permessi per eliminare questo matchmaking!") + + # Interrupt the matchmaking with the MANUAL_DELETE reason + await self.queue.put(Interrupts.MANUAL_START) + + await data.reply(f"🚩 Evento avviato!") + return callback + + @property + def royalnet_keyboard(self): + # noinspection PyListCreation + rows = [] + + rows.append([ + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.YES.value}", + text="Ci sarò!", + callback=self.get_answer_callback(MMChoice.YES) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.MAYBE.value}", + text="Forse...", + callback=self.get_answer_callback(MMChoice.MAYBE) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.NO.value}", + text="Non mi interessa.", + callback=self.get_answer_callback(MMChoice.NO) + ), + ]) + + if self._mmevent.datetime is not None: + rows.append([ + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.LATE_SHORT.value}", + text="10 min", + callback=self.get_answer_callback(MMChoice.LATE_SHORT) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.LATE_MEDIUM.value}", + text="30 min", + callback=self.get_answer_callback(MMChoice.LATE_MEDIUM) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.LATE_LONG.value}", + text="60 min", + callback=self.get_answer_callback(MMChoice.LATE_LONG) + ) + ]) + + rows.append([ + rc.KeyboardKey( + interface=self.command.interface, + short=f"🗑", + text="Elimina", + callback=self.get_delete_callback() + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"🚩", + text="Inizia", + callback=self.get_start_callback() + ), + ]) + + return rows + + @property + def telegram_keyboard(self): + # noinspection PyListCreation + rows = [] + key_id = 0 + + for r_row in self.royalnet_keyboard: + row = [] + for r_key in r_row: + # Generate a unique callback string + callback_str = f"mm{self.mmid}_{key_id}" + + # Create a InlineKeyboardButton with that callback string + row.append(InKB(f"{r_key.short} {r_key.text}", callback_data=callback_str)) + + # Increase the key_id + key_id += 1 + rows.append(row) + + # Return the resulting InlineKeyboardMarkup + return InKM(rows) + + def register_telegram_keyboard(self, inkm: InKM): + # noinspection PyListCreation + royalnet_keyboard = self.royalnet_keyboard + for x, row in enumerate(inkm.inline_keyboard): + for y, key in enumerate(row): + key: InKB + self.command.interface.serf.register_keyboard_key(key.callback_data, key=royalnet_keyboard[x][y]) + + def unregister_telegram_keyboard(self, inkm: InKM): + for row in inkm.inline_keyboard: + for key in row: + key: InKB + self.command.interface.serf.unregister_keyboard_key(key.callback_data) + + async def wait_until_due(self): + """When the event is due, interrupt the MMTask with the TIME_RAN_OUT reason.""" + if self._mmevent.datetime is None: + return + await sleep_until(self._mmevent.datetime) + await self.queue.put(Interrupts.TIME_RAN_OUT) + + @property + def telegram_channel_id(self): + return self.command.config["Matchmaking"]["mm_telegram_channel_id"] + + @property + def telegram_group_id(self): + return self.command.config["Matchmaking"]["mm_telegram_group_id"] + + @contextlib.asynccontextmanager + async def telegram_channel_message(self): + + # Generate the InlineKeyboardMarkup + inkm = self.telegram_keyboard + + # Bind the Royalnet buttons to the Telegram keyboard + log.debug(f"Registering keyboard for: {self.mmid}") + self.register_telegram_keyboard(inkm) + + # If the event has no associated interface data... + if self._mmevent.interface_data is None: + # Send the channel message + log.debug(f"Sending message for: {self.mmid}") + message: PTBMessage = await self.command.interface.serf.api_call( + self.command.interface.serf.client.send_message, + chat_id=self.telegram_channel_id, + text=telegram_escape(self.channel_text), + parse_mode="HTML", + disable_webpage_preview=True, + reply_markup=inkm + ) + + # Register the interface data on the database + self._mmevent.interface_data = MMInterfaceDataTelegram( + chat_id=self.telegram_channel_id, + message_id=message.message_id + ) + self._session.commit() + + # Wait until the event starts + yield + + # Delete the channel message + log.debug(f"Deleting message for: {self.mmid}") + await self.command.interface.serf.api_call( + self.command.interface.serf.client.delete_message, + chat_id=self._mmevent.interface_data.chat_id, + message_id=self._mmevent.interface_data.message_id + ) + + # Unregister the Telegram keyboard bindings + log.debug(f"Unregistering keyboard for: {self.mmid}") + self.unregister_telegram_keyboard(inkm) + + async def telegram_channel_message_update(self): + try: + await self.command.interface.serf.api_call( + self.command.interface.serf.client.edit_message_text, + chat_id=self._mmevent.interface_data.chat_id, + text=telegram_escape(self.channel_text), + message_id=self._mmevent.interface_data.message_id, + parse_mode="HTML", + disable_web_page_preview=True, + reply_markup=self.telegram_keyboard + ) + except TelegramError as e: + log.warning(f"TelegramError during update: {e}") + + async def telegram_group_message_start(self): + await self.command.interface.serf.api_call( + self.command.interface.serf.client.send_message, + chat_id=self.telegram_group_id, + text=telegram_escape(self.start_text), + parse_mode="HTML", + disable_webpage_preview=True + ) + + async def telegram_group_message_delete(self): + await self.command.interface.serf.api_call( + self.command.interface.serf.client.send_message, + chat_id=self.telegram_group_id, + text=telegram_escape(self.delete_text), + parse_mode="HTML", + disable_webpage_preview=True + ) + + def start(self): + log.debug(f"Starting task for: {self.mmid}") + self.task = self.loop.create_task(self.run()) + + @sentry_async_wrap() + async def run(self): + log.debug(f"Running task for: {self.mmid}") + + # Create a new session for the MMTask + self._session = self.command.alchemy.Session() + self._EventT = self.command.alchemy.get(MMEvent) + self._ResponseT = self.command.alchemy.get(MMResponse) + self._mmevent: MMEvent = self._session.query(self._EventT).get(self.mmid) + + if self._mmevent is None: + raise rc.InvalidInputError(f"No event exists with the mmid {self.mmid}.") + + if self._mmevent.interface != "telegram": + raise rc.UnsupportedError("Currently only the Telegram interface is supported.") + + async with self.telegram_channel_message(): + self.loop.create_task(self.wait_until_due()) + + # Sleep until something interrupts the task + interrupt = await self.queue.get() + + # Mark the event as interrupted + self._mmevent.interrupted = True + await self._session.commit() + + # Send a group notification if the MMEvent wasn't deleted + if interrupt != Interrupts.MANUAL_DELETE: + await self.telegram_group_message_start() + else: + await self.telegram_group_message_delete() + + # Close the database session + await asyncify(self._session.close) + + +log = logging.getLogger(__name__) + + class MatchmakingCommand(rc.Command): name: str = "matchmaking" description: str = "Cerca persone per una partita a qualcosa!" - syntax: str = "[ {ora} ] {nome}\n[descrizione]" + syntax: str = "" aliases = ["mm", "lfg"] - tables = {MMEvent, MMResponse} - def __init__(self, interface: rc.CommandInterface): super().__init__(interface) - # Find all relevant MMEvents and run them + + # Find all active MMEvents and run the tasks for them session = self.alchemy.Session() - mmevents = ( - session - .query(self.alchemy.get(MMEvent)) - .filter(self.alchemy.get(MMEvent).interface == self.interface.name, - self.alchemy.get(MMEvent).datetime > datetime.datetime.now(), - self.alchemy.get(MMEvent).interrupted == False) - .all() - ) - self.tasks_created = {} - self.queue: Dict[int, aio.queues.Queue] = {} - for mmevent in mmevents: - task = self.interface.loop.create_task(self._run_mmevent(mmevent.mmid)) - self.tasks_created[mmevent.mmid] = task + + # Create a new MMEvent and run it + if self.interface.name == "telegram": + MMEventT = self.alchemy.get(MMEvent) + active_mmevents = ( + session + .query(MMEventT) + .filter( + MMEventT.interface == self.interface.name, + MMEventT.interrupted == False + ) + .all() + ) + for mmevent in active_mmevents: + task = MMTask(mmevent.mmid, command=self) + task.start() + + @staticmethod + def _parse_args(args) -> Tuple[Optional[datetime.datetime], str, str]: + """Parse command arguments, either using the standard syntax or the Proto syntax.""" + try: + timestring, title, description = args.match(r"(?:\[\s*([^]]+)\s*]\s*)?([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) + except rc.InvalidInputError: + timestring, title, description = args.match(r"(?:\s*(.+?)\s*\n\s*)?([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) + if timestring is not None: + try: + dt: typing.Optional[datetime.datetime] = dateparser.parse(timestring, settings={ + "PREFER_DATES_FROM": "future" + }) + except OverflowError: + dt = None + if dt is None: + raise rc.InvalidInputError("La data che hai specificato non è valida.") + if dt <= datetime.datetime.now(): + raise rc.InvalidInputError("La data che hai specificato è nel passato.") + if dt - datetime.datetime.now() >= datetime.timedelta(days=366): + raise rc.InvalidInputError("Hai specificato una data tra più di un anno!\n" + "Se volevi scrivere un'orario, ricordati che le ore sono separate da " + "due punti (:) e non da punto semplice!") + else: + dt = None + return dt, title, description async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - # Create a new MMEvent and run it - if self.interface.name != "telegram": - raise rc.UnsupportedError(f"{self.interface.prefix}matchmaking funziona solo su Telegram. Per ora.") + """Handle a matchmaking command call.""" author = await data.get_author(error_if_none=True) - try: - timestring, title, description = args.match(r"\[\s*([^]]+)\s*]\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) - except rc.InvalidInputError: - timestring, title, description = args.match(r"\s*(.+?)\s*\n\s*([^\n]+)\s*\n?\s*(.+)?\s*", re.DOTALL) - try: - dt: typing.Optional[datetime.datetime] = dateparser.parse(timestring, settings={ - "PREFER_DATES_FROM": "future" - }) - except OverflowError: - dt = None - if dt is None: - raise rc.InvalidInputError("La data che hai specificato non è valida.") - if dt <= datetime.datetime.now(): - raise rc.InvalidInputError("La data che hai specificato è nel passato.") - if dt - datetime.datetime.now() >= datetime.timedelta(days=366): - raise rc.InvalidInputError("Hai specificato una data tra più di un anno!\n" - "Se volevi scrivere un'orario, ricordati che le ore sono separate da due punti" - " (:) e non da punto semplice!") + # Parse the arguments, either with the standard syntax or with the Proto syntax + 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, @@ -87,289 +519,9 @@ class MatchmakingCommand(rc.Command): interface=self.interface.name) data.session.add(mmevent) await data.session_commit() - self.loop.create_task(self._run_mmevent(mmevent.mmid)) + + # Create and run a task for the newly created MMEvent + task = MMTask(mmevent.mmid, command=self) + task.start() + await data.reply(f"🚩 Matchmaking creato!") - - _mmchoice_values = { - MMChoice.YES: 4, - MMChoice.LATE_SHORT: 3, - MMChoice.LATE_MEDIUM: 2, - MMChoice.LATE_LONG: 1, - MMChoice.MAYBE: 0, - MMChoice.NO: -1 - } - - def _gen_mm_message(self, mmevent: MMEvent) -> str: - text = f"🚩 [{mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{mmevent.title}[/b]\n" - if mmevent.description: - text += f"{mmevent.description}\n" - text += "\n" - for response in sorted(mmevent.responses, key=lambda r: -self._mmchoice_values[r.choice]): - response: MMResponse - - if response.choice == MMChoice.LATE_SHORT: - td = mmevent.datetime + datetime.timedelta(minutes=10) - time_text = f" [{td.strftime('%H:%M')}]" - elif response.choice == MMChoice.LATE_MEDIUM: - td = mmevent.datetime + datetime.timedelta(minutes=30) - time_text = f" [{td.strftime('%H:%M')}]" - elif response.choice == MMChoice.LATE_LONG: - td = mmevent.datetime + datetime.timedelta(minutes=60) - time_text = f" [{td.strftime('%H:%M')}+]" - else: - time_text = "" - - creator_crown = " 👑" if response.user == mmevent.creator else "" - - text += f"{response.choice.value} {response.user}{time_text}{creator_crown}\n" - return text - - @staticmethod - def _gen_telegram_keyboard(mmevent: MMEvent): - if mmevent.datetime <= datetime.datetime.now(): - return None - return InKM([ - [ - InKB(f"{MMChoice.YES.value} Ci sarò!", - callback_data=f"mm{mmevent.mmid}_YES"), - InKB(f"{MMChoice.MAYBE.value} Forse...", - callback_data=f"mm{mmevent.mmid}_MAYBE"), - InKB(f"{MMChoice.NO.value} Non mi interessa.", - callback_data=f"mm{mmevent.mmid}_NO"), - ], - [ - InKB(f"{MMChoice.LATE_SHORT.value} 10 min", - callback_data=f"mm{mmevent.mmid}_LATE_SHORT"), - InKB(f"{MMChoice.LATE_MEDIUM.value} 30 min", - callback_data=f"mm{mmevent.mmid}_LATE_MEDIUM"), - InKB(f"{MMChoice.LATE_LONG.value} 60+ min", - callback_data=f"mm{mmevent.mmid}_LATE_LONG"), - ], - [ - InKB(f"🗑 Elimina", - callback_data=f"mm{mmevent.mmid}_DELETE"), - InKB(f"🚩 Inizia", - callback_data=f"mm{mmevent.mmid}_START"), - ] - ]) - - async def _update_telegram_mm_message(self, client: PTBBot, mmevent: MMEvent): - try: - await self.interface.serf.api_call(client.edit_message_text, - chat_id=self.config["Matchmaking"]["mm_chat_id"], - text=telegram_escape(self._gen_mm_message(mmevent)), - message_id=mmevent.interface_data.message_id, - parse_mode="HTML", - disable_web_page_preview=True, - reply_markup=self._gen_telegram_keyboard(mmevent)) - except TelegramError: - pass - - def _gen_mm_telegram_callback(self, client: PTBBot, mmid: int, choice: MMChoice): - async def callback(data: rc.CommandData): - author = await data.get_author(error_if_none=True) - mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) - mmresponse: MMResponse = await asyncify( - data.session.query(self.alchemy.get(MMResponse)).filter_by(user=author, mmevent=mmevent).one_or_none) - if mmresponse is None: - mmresponse = self.alchemy.get(MMResponse)(user=author, mmevent=mmevent, choice=choice) - data.session.add(mmresponse) - if random.randrange(14) == 0: - await FiorygiTransaction.spawn_fiorygi(data, author, 1, "aver risposto a un matchmaking") - else: - mmresponse.choice = choice - await data.session_commit() - await self._update_telegram_mm_message(client, mmevent) - await data.reply(f"{choice.value} Messaggio ricevuto!") - return callback - - def _gen_mm_telegram_delete(self, client, mmid: int): - async def callback(data: rc.CommandData): - author: User = await data.get_author(error_if_none=True) - mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) - if author != mmevent.creator and "admin" not in author.roles: - raise rc.UserError("Non sei il creatore di questo matchmaking!") - await self.queue[mmid].put(Interrupts.MANUAL_DELETE) - await data.reply(f"🗑 Evento eliminato!") - return callback - - def _gen_mm_telegram_start(self, client, mmid: int): - async def callback(data: rc.CommandData): - author = await data.get_author(error_if_none=True) - mmevent: MMEvent = await asyncify(data.session.query(self.alchemy.get(MMEvent)).get, mmid) - if author != mmevent.creator and "admin" not in author.roles: - raise rc.UserError("Non sei il creatore di questo matchmaking!") - await self.queue[mmid].put(Interrupts.MANUAL_START) - await data.reply(f"🚩 Evento avviato!") - return callback - - async def _set_event_after(self, mmid: int, dt: datetime.datetime): - await sleep_until(dt) - if mmid in self.queue: - await self.queue[mmid].put(Interrupts.TIME_RAN_OUT) - - def _gen_event_start_message(self, mmevent: MMEvent): - text = f"🚩 L'evento [b]{mmevent.title}[/b] è iniziato!\n\n" - for response in sorted(mmevent.responses, key=lambda r: -self._mmchoice_values[r.choice]): - response: MMResponse - text += f"{response.choice.value} {response.user}\n" - return text - - @staticmethod - def _gen_unauth_message(user: User): - return f"⚠️ Non sono autorizzato a mandare messaggi a [b]{user.username}[/b]!\n" \ - f"{user.telegram[0].mention()}, apri una chat privata con me e mandami un messaggio!" - - @sentry_async_wrap() - async def _run_mmevent(self, mmid: int): - """Run a MMEvent.""" - # Create the event in the dict - self.queue[mmid] = aio.Queue() - # Open a new Alchemy Session - session = self.alchemy.Session() - # Find the MMEvent with the current session - mmevent: MMEvent = await asyncify(session.query(self.alchemy.get(MMEvent)).get, mmid) - if mmevent is None: - raise ValueError("Invalid mmid.") - # Ensure the MMEvent hasn't already started - if mmevent.datetime <= datetime.datetime.now(): - raise ValueError("MMEvent has already started.") - # Ensure the MMEvent interface matches the current one - if mmevent.interface != self.interface.name: - raise ValueError("Invalid interface.") - # If the matchmaking message hasn't been sent yet, do so now - if mmevent.interface_data is None: - if self.interface.name == "telegram": - bot: TelegramBot = self.interface.serf - client: PTBBot = bot.client - # Send the keyboard - message: PTBMessage = await self.interface.serf.api_call( - client.send_message, - chat_id=self.config["Matchmaking"]["mm_chat_id"], - text=telegram_escape( - self._gen_mm_message(mmevent)), - parse_mode="HTML", - disable_webpage_preview=True, - reply_markup=self._gen_telegram_keyboard(mmevent) - ) - # Store message data in the interface data object - mmevent.interface_data = MMInterfaceDataTelegram(chat_id=self.config["Matchmaking"]["mm_chat_id"], - message_id=message.message_id) - await asyncify(session.commit) - else: - raise rc.UnsupportedError() - # Register handlers for the keyboard events - if self.interface.name == "telegram": - bot: TelegramBot = self.interface.serf - client: PTBBot = bot.client - bot.register_keyboard_key(f"mm{mmevent.mmid}_YES", key=rc.KeyboardKey( - interface=self.interface, - short=f"{MMChoice.YES.value}", - text="Ci sarò!", - callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.YES) - )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_SHORT", key=rc.KeyboardKey( - interface=self.interface, - short=f"{MMChoice.LATE_SHORT.value}", - text="10 min", - callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_SHORT) - )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM", key=rc.KeyboardKey( - interface=self.interface, - short=f"{MMChoice.LATE_MEDIUM.value}", - text="30 min", - callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_MEDIUM) - )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG", key=rc.KeyboardKey( - interface=self.interface, - short=f"{MMChoice.LATE_LONG.value}", - text="60 min", - callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.LATE_LONG) - )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_MAYBE", key=rc.KeyboardKey( - interface=self.interface, - short=f"{MMChoice.MAYBE.value}", - text="Forse...", - callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.MAYBE) - )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_NO", key=rc.KeyboardKey( - interface=self.interface, - short=f"{MMChoice.NO.value}", - text="Non mi interessa.", - callback=self._gen_mm_telegram_callback(client, mmid, MMChoice.NO) - )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_DELETE", key=rc.KeyboardKey( - interface=self.interface, - short=f"🗑", - text="Elimina", - callback=self._gen_mm_telegram_delete(client, mmid) - )) - bot.register_keyboard_key(f"mm{mmevent.mmid}_START", key=rc.KeyboardKey( - interface=self.interface, - short=f"🚩", - text="Inizia", - callback=self._gen_mm_telegram_start(client, mmid) - )) - else: - raise rc.UnsupportedError() - # Sleep until something interrupts - self.loop.create_task(self._set_event_after(mmid, mmevent.datetime)) - interrupt = await self.queue[mmid].get() - mmevent.interrupted = True - await asyncify(session.commit) - del self.queue[mmid] - # Notify the positive answers of the event start - if self.interface.name == "telegram": - bot: TelegramBot = self.interface.serf - client: PTBBot = bot.client - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_YES") - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_MAYBE") - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_SHORT") - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_MEDIUM") - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_LATE_LONG") - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_NO") - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_DELETE") - bot.unregister_keyboard_key(f"mm{mmevent.mmid}_START") - - await self.interface.serf.api_call(client.delete_message, - chat_id=mmevent.interface_data.chat_id, - message_id=mmevent.interface_data.message_id) - - if interrupt == Interrupts.TIME_RAN_OUT or interrupt == Interrupts.MANUAL_START: - await asyncify(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=telegram_escape(self._gen_event_start_message(mmevent)), - parse_mode="HTML", - disable_webpage_preview=True) - - for response in mmevent.responses: - if response.choice == MMChoice.NO: - return - try: - await asyncify(client.send_message, - chat_id=response.user.telegram[0].tg_id, - text=telegram_escape(self._gen_event_start_message(mmevent)), - parse_mode="HTML", - disable_webpage_preview=True) - except TelegramError: - await self.interface.serf.api_call( - client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=telegram_escape(self._gen_unauth_message(response.user)), - parse_mode="HTML", - disable_webpage_preview=True - ) - - elif interrupt == Interrupts.MANUAL_DELETE: - await self.interface.serf.api_call( - client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=telegram_escape(f"🗑 L'evento [b]{mmevent.title}[/b] è stato annullato."), - parse_mode="HTML", - disable_webpage_preview=True - ) - else: - raise rc.UnsupportedError() - # The end! - await asyncify(session.close) - del self.tasks_created[mmid] diff --git a/royalpack/commands/royalpack.py b/royalpack/commands/royalpackversion.py similarity index 94% rename from royalpack/commands/royalpack.py rename to royalpack/commands/royalpackversion.py index 063751d6..bbd514ae 100644 --- a/royalpack/commands/royalpack.py +++ b/royalpack/commands/royalpackversion.py @@ -5,7 +5,7 @@ from ..version import semantic class RoyalpackCommand(rc.Command): - name: str = "royalpack" + name: str = "royalpackversion" description: str = "Visualizza la versione attuale di Royalpack." diff --git a/royalpack/tables/mmevents.py b/royalpack/tables/mmevents.py index 8dd9594a..2c393ad0 100644 --- a/royalpack/tables/mmevents.py +++ b/royalpack/tables/mmevents.py @@ -21,7 +21,7 @@ class MMEvent: @declared_attr def datetime(self): - return Column(DateTime, nullable=False) + return Column(DateTime) @declared_attr def title(self): diff --git a/royalpack/types/mmchoice.py b/royalpack/types/mmchoice.py index 4b201576..1a479dde 100644 --- a/royalpack/types/mmchoice.py +++ b/royalpack/types/mmchoice.py @@ -6,5 +6,5 @@ class MMChoice(enum.Enum): LATE_SHORT = "🕐" LATE_MEDIUM = "🕒" LATE_LONG = "🕗" - MAYBE = "❓" + MAYBE = "❔" NO = "❌" diff --git a/royalpack/version.py b/royalpack/version.py index 209315d0..af6edbc1 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.4" +semantic = "5.9.5" From 546691df1fa64654d5bac3803fe5d7ee7e46abfd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Jul 2020 21:42:01 +0200 Subject: [PATCH 189/227] publish: 5.9.5 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6b6cfeba..3a51255a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.4" + version = "5.9.5" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" From 81fa719115a9b585418724f9cb42e6d8a90fa313 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Jul 2020 22:00:46 +0200 Subject: [PATCH 190/227] publish: 5.9.6 --- pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 2 +- royalpack/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3a51255a..b2f7c55f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.5" + version = "5.9.6" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 8c556677..65716325 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -374,7 +374,7 @@ class MMTask: async def telegram_channel_message_update(self): try: - await self.command.interface.serf.api_call( + await asyncify( self.command.interface.serf.client.edit_message_text, chat_id=self._mmevent.interface_data.chat_id, text=telegram_escape(self.channel_text), diff --git a/royalpack/version.py b/royalpack/version.py index af6edbc1..5ff00f68 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.5" +semantic = "5.9.6" From e58860f3473874b7e7aaaef71350cb74f8142b08 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 2 Jul 2020 22:07:40 +0200 Subject: [PATCH 191/227] publish: 5.9.7 --- pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 10 ++++++++++ royalpack/version.py | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b2f7c55f..2ad0aa49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.6" + version = "5.9.7" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 65716325..2318cbf7 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -55,7 +55,12 @@ class MMTask: def is_running(self): return self.task is not None + def sync(self): + self._session.refresh(self._mmevent) + def get_response_line(self, response: MMResponse): + self.sync() + # noinspection PyListCreation line = [] @@ -90,6 +95,8 @@ class MMTask: @property def channel_text(self) -> str: + self.sync() + # noinspection PyListCreation text = [] @@ -116,6 +123,8 @@ class MMTask: @property def start_text(self) -> str: + self.sync() + # noinspection PyListCreation text = [] @@ -373,6 +382,7 @@ class MMTask: self.unregister_telegram_keyboard(inkm) async def telegram_channel_message_update(self): + log.debug(f"Updating message for: {self.mmid}") try: await asyncify( self.command.interface.serf.client.edit_message_text, diff --git a/royalpack/version.py b/royalpack/version.py index 5ff00f68..536e3396 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.6" +semantic = "5.9.7" From dadf5b94d9012238123ee72999f72c906557c2ca Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 5 Jul 2020 10:16:11 +0200 Subject: [PATCH 192/227] Add api_user_avatar.py --- royalpack/stars/__init__.py | 2 ++ royalpack/stars/api_user_avatar.py | 38 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 royalpack/stars/api_user_avatar.py diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 429f8969..9676dbf8 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -12,6 +12,7 @@ from .api_cvstats_latest import ApiCvstatsLatestStar from .api_cvstats_avg import ApiCvstatsAvgStar from .api_user_ryg import ApiUserRygStar from .api_user_ryg_list import ApiUserRygListStar +from .api_user_avatar import ApiUserAvatarStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -28,6 +29,7 @@ available_page_stars = [ ApiCvstatsAvgStar, ApiUserRygStar, ApiUserRygListStar, + ApiUserAvatarStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_user_avatar.py b/royalpack/stars/api_user_avatar.py new file mode 100644 index 00000000..9128ce8f --- /dev/null +++ b/royalpack/stars/api_user_avatar.py @@ -0,0 +1,38 @@ +import re +import royalnet.utils as ru +import royalnet.constellation.api as rca + + +url_validation = re.compile(r'^(?:http|ftp)s?://' + r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' + r'localhost|' + r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' + r'(?::\d+)?' + r'(?:/?|[/?]\S+)$', re.IGNORECASE) + + +class ApiUserAvatarStar(rca.ApiStar): + path = "/api/user/avatar/v2" + + parameters = { + "put": { + "avatar_url": "The url that the user wants to set as avatar." + } + } + + auth = { + "put": True, + } + + tags = ["user"] + + @rca.magic + async def put(self, data: rca.ApiData) -> ru.JSON: + """Set the avatar of current user.""" + avatar_url = data["avatar_url"] + user = await data.user() + if not re.match(url_validation, avatar_url): + raise rca.InvalidParameterError("avatar_url is not a valid url.") + user.avatar_url = avatar_url + await data.session_commit() + return user.json() From 96aab5d097d0263a6a29ab2bf939171b3426a275 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 5 Jul 2020 10:17:23 +0200 Subject: [PATCH 193/227] publish: 5.9.8 --- pyproject.toml | 2 +- royalpack/version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2ad0aa49..f76be9ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.7" + version = "5.9.8" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/version.py b/royalpack/version.py index 536e3396..39d3c208 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.7" +semantic = "5.9.8" From 3260417ebd4600cfb7c9ce3e4e32cc4ec276923b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 6 Jul 2020 01:38:19 +0200 Subject: [PATCH 194/227] publish: 5.9.9 --- pyproject.toml | 2 +- royalpack/commands/matchmaking.py | 2 +- royalpack/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f76be9ba..63a118b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.8" + version = "5.9.9" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index 2318cbf7..a4c3f5ee 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -442,7 +442,7 @@ class MMTask: # Mark the event as interrupted self._mmevent.interrupted = True - await self._session.commit() + self._session.commit() # Send a group notification if the MMEvent wasn't deleted if interrupt != Interrupts.MANUAL_DELETE: diff --git a/royalpack/version.py b/royalpack/version.py index 39d3c208..bdd6cc67 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.8" +semantic = "5.9.9" From 76af87725e5d6eb0493d059ff9a3e90cfffa9310 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 7 Jul 2020 02:13:19 +0200 Subject: [PATCH 195/227] Move MMTask to utils --- royalpack/commands/matchmaking.py | 452 +---------------------------- royalpack/utils/__init__.py | 2 + royalpack/utils/mmtask.py | 456 ++++++++++++++++++++++++++++++ 3 files changed, 460 insertions(+), 450 deletions(-) create mode 100644 royalpack/utils/mmtask.py diff --git a/royalpack/commands/matchmaking.py b/royalpack/commands/matchmaking.py index a4c3f5ee..fa601be5 100644 --- a/royalpack/commands/matchmaking.py +++ b/royalpack/commands/matchmaking.py @@ -1,460 +1,12 @@ -import contextlib from typing import * import datetime import re import dateparser import typing -import random -import enum -import asyncio as aio -from telegram import Message as PTBMessage -from telegram import InlineKeyboardMarkup as InKM -from telegram import InlineKeyboardButton as InKB -from telegram.error import TelegramError import royalnet.commands as rc -from royalnet.serf.telegram import escape as telegram_escape -from royalnet.utils import asyncify, sleep_until, sentry_async_wrap -import logging -from ..tables import MMEvent, MMResponse, FiorygiTransaction -from ..types import MMChoice, MMInterfaceDataTelegram - - -class Interrupts(enum.Enum): - TIME_RAN_OUT = enum.auto() - MANUAL_START = enum.auto() - MANUAL_DELETE = enum.auto() - - -mmchoice_sorting = { - MMChoice.YES: -4, - MMChoice.LATE_SHORT: -3, - MMChoice.LATE_MEDIUM: -2, - MMChoice.LATE_LONG: -1, - MMChoice.MAYBE: 0, - MMChoice.NO: 1 -} - - -class MMTask: - def __init__(self, mmid: int, *, command: rc.Command): - log.debug(f"Creating task for: {mmid}") - - self.loop: aio.AbstractEventLoop = command.loop - self.task: Optional[aio.Task] = None - self.queue: aio.Queue = aio.Queue(loop=self.loop) - self.command: rc.Command = command - self.mmid: int = mmid - - self._session: Optional = None - self._EventT: Optional[Type[MMEvent]] = None - self._ResponseT: Optional[Type[MMResponse]] = None - self._mmevent: Optional[MMEvent] = None - - @property - def is_running(self): - return self.task is not None - - def sync(self): - self._session.refresh(self._mmevent) - - def get_response_line(self, response: MMResponse): - self.sync() - - # noinspection PyListCreation - line = [] - - # Emoji - line.append(f"{response.choice.value}") - - # Mention the user if he said yes, otherwise just display his name - if response.choice == MMChoice.NO: - line.append(f"{response.user.telegram[0].name()}") - else: - line.append(f"{response.user.telegram[0].mention()}") - - # Late time - if response.choice == MMChoice.LATE_SHORT: - td = self._mmevent.datetime + datetime.timedelta(minutes=10) - line.append(f"[{td.strftime('%H:%M')}]") - - elif response.choice == MMChoice.LATE_MEDIUM: - td = self._mmevent.datetime + datetime.timedelta(minutes=30) - line.append(f"[{td.strftime('%H:%M')}]") - - elif response.choice == MMChoice.LATE_LONG: - td = self._mmevent.datetime + datetime.timedelta(minutes=60) - line.append(f"[{td.strftime('%H:%M')}+]") - - # Creator - if response.user == self._mmevent.creator: - line.append("👑") - - # Result - return " ".join(line) - - @property - def channel_text(self) -> str: - self.sync() - - # noinspection PyListCreation - text = [] - - # First line - if self._mmevent.datetime is None: - text.append(f"🌐 [Prossimamente] [b]{self._mmevent.title}[/b]") - else: - text.append(f"🚩 [{self._mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{self._mmevent.title}[/b]") - - # Description - if self._mmevent.description: - text.append(f"{self._mmevent.description}") - - # Spacer - text.append("") - - # Responses - responses = sorted(self._mmevent.responses, key=lambda r: mmchoice_sorting[r.choice]) - for response in responses: - text.append(self.get_response_line(response)) - - # Result - return "\n".join(text) - - @property - def start_text(self) -> str: - self.sync() - - # noinspection PyListCreation - text = [] - - # First line - if self._mmevent.datetime is None: - text.append(f"🌐 Le iscrizioni all'evento [b]{self._mmevent.title}[/b] sono terminate!") - else: - text.append(f"🚩 L'evento [b]{self._mmevent.title}[/b] è iniziato!") - - # Description - if self._mmevent.description: - text.append(f"{self._mmevent.description}") - - # Spacer - text.append("") - - # Responses - responses = sorted(self._mmevent.responses, key=lambda r: mmchoice_sorting[r.choice]) - for response in responses: - text.append(self.get_response_line(response)) - - # Result - return "\n".join(text) - - @property - def delete_text(self) -> str: - return f"🗑 L'evento [b]{self._mmevent.title}[/b] è stato eliminato." - - def get_answer_callback(self, choice: MMChoice): - async def callback(data: rc.CommandData): - # Find the user who clicked on the button - user = await data.get_author(error_if_none=True) - - # Get the related MMEvent - mmevent: MMEvent = await asyncify(data.session.query(self._EventT).get, self.mmid) - - # Check if the user had already responded - mmresponse: MMResponse = await asyncify( - data.session.query(self._ResponseT).filter_by(user=user, mmevent=mmevent).one_or_none - ) - - if mmresponse is None: - # If they didn't respond, create a new MMResponse - mmresponse = self._ResponseT(user=user, mmevent=mmevent, choice=choice) - data.session.add(mmresponse) - - # Drop fiorygi - if random.randrange(100) < self.command.config["Matchmaking"]["fiorygi_award_chance"]: - await FiorygiTransaction.spawn_fiorygi(data, user, 1, "aver risposto a un matchmaking") - else: - # Change their response - mmresponse.choice = choice - await data.session_commit() - - await self.telegram_channel_message_update() - - await data.reply(f"{choice.value} Hai risposto al matchmaking!") - return callback - - def get_delete_callback(self): - async def callback(data: rc.CommandData): - # Find the user who clicked on the button - user = await data.get_author(error_if_none=True) - - # Get the related MMEvent - mmevent: MMEvent = await asyncify(data.session.query(self._EventT).get, self.mmid) - - # Ensure the user has the required roles to start the matchmaking - if user != mmevent.creator and "admin" not in user.roles: - raise rc.UserError("Non hai i permessi per eliminare questo matchmaking!") - - # Interrupt the matchmaking with the MANUAL_DELETE reason - await self.queue.put(Interrupts.MANUAL_DELETE) - - await data.reply(f"🗑 Evento eliminato!") - return callback - - def get_start_callback(self): - async def callback(data: rc.CommandData): - # Find the user who clicked on the button - user = await data.get_author(error_if_none=True) - - # Get the related MMEvent - mmevent: MMEvent = await asyncify(data.session.query(self._EventT).get, self.mmid) - - # Ensure the user has the required roles to start the matchmaking - if user != mmevent.creator and "admin" not in user.roles: - raise rc.UserError("Non hai i permessi per eliminare questo matchmaking!") - - # Interrupt the matchmaking with the MANUAL_DELETE reason - await self.queue.put(Interrupts.MANUAL_START) - - await data.reply(f"🚩 Evento avviato!") - return callback - - @property - def royalnet_keyboard(self): - # noinspection PyListCreation - rows = [] - - rows.append([ - rc.KeyboardKey( - interface=self.command.interface, - short=f"{MMChoice.YES.value}", - text="Ci sarò!", - callback=self.get_answer_callback(MMChoice.YES) - ), - rc.KeyboardKey( - interface=self.command.interface, - short=f"{MMChoice.MAYBE.value}", - text="Forse...", - callback=self.get_answer_callback(MMChoice.MAYBE) - ), - rc.KeyboardKey( - interface=self.command.interface, - short=f"{MMChoice.NO.value}", - text="Non mi interessa.", - callback=self.get_answer_callback(MMChoice.NO) - ), - ]) - - if self._mmevent.datetime is not None: - rows.append([ - rc.KeyboardKey( - interface=self.command.interface, - short=f"{MMChoice.LATE_SHORT.value}", - text="10 min", - callback=self.get_answer_callback(MMChoice.LATE_SHORT) - ), - rc.KeyboardKey( - interface=self.command.interface, - short=f"{MMChoice.LATE_MEDIUM.value}", - text="30 min", - callback=self.get_answer_callback(MMChoice.LATE_MEDIUM) - ), - rc.KeyboardKey( - interface=self.command.interface, - short=f"{MMChoice.LATE_LONG.value}", - text="60 min", - callback=self.get_answer_callback(MMChoice.LATE_LONG) - ) - ]) - - rows.append([ - rc.KeyboardKey( - interface=self.command.interface, - short=f"🗑", - text="Elimina", - callback=self.get_delete_callback() - ), - rc.KeyboardKey( - interface=self.command.interface, - short=f"🚩", - text="Inizia", - callback=self.get_start_callback() - ), - ]) - - return rows - - @property - def telegram_keyboard(self): - # noinspection PyListCreation - rows = [] - key_id = 0 - - for r_row in self.royalnet_keyboard: - row = [] - for r_key in r_row: - # Generate a unique callback string - callback_str = f"mm{self.mmid}_{key_id}" - - # Create a InlineKeyboardButton with that callback string - row.append(InKB(f"{r_key.short} {r_key.text}", callback_data=callback_str)) - - # Increase the key_id - key_id += 1 - rows.append(row) - - # Return the resulting InlineKeyboardMarkup - return InKM(rows) - - def register_telegram_keyboard(self, inkm: InKM): - # noinspection PyListCreation - royalnet_keyboard = self.royalnet_keyboard - for x, row in enumerate(inkm.inline_keyboard): - for y, key in enumerate(row): - key: InKB - self.command.interface.serf.register_keyboard_key(key.callback_data, key=royalnet_keyboard[x][y]) - - def unregister_telegram_keyboard(self, inkm: InKM): - for row in inkm.inline_keyboard: - for key in row: - key: InKB - self.command.interface.serf.unregister_keyboard_key(key.callback_data) - - async def wait_until_due(self): - """When the event is due, interrupt the MMTask with the TIME_RAN_OUT reason.""" - if self._mmevent.datetime is None: - return - await sleep_until(self._mmevent.datetime) - await self.queue.put(Interrupts.TIME_RAN_OUT) - - @property - def telegram_channel_id(self): - return self.command.config["Matchmaking"]["mm_telegram_channel_id"] - - @property - def telegram_group_id(self): - return self.command.config["Matchmaking"]["mm_telegram_group_id"] - - @contextlib.asynccontextmanager - async def telegram_channel_message(self): - - # Generate the InlineKeyboardMarkup - inkm = self.telegram_keyboard - - # Bind the Royalnet buttons to the Telegram keyboard - log.debug(f"Registering keyboard for: {self.mmid}") - self.register_telegram_keyboard(inkm) - - # If the event has no associated interface data... - if self._mmevent.interface_data is None: - # Send the channel message - log.debug(f"Sending message for: {self.mmid}") - message: PTBMessage = await self.command.interface.serf.api_call( - self.command.interface.serf.client.send_message, - chat_id=self.telegram_channel_id, - text=telegram_escape(self.channel_text), - parse_mode="HTML", - disable_webpage_preview=True, - reply_markup=inkm - ) - - # Register the interface data on the database - self._mmevent.interface_data = MMInterfaceDataTelegram( - chat_id=self.telegram_channel_id, - message_id=message.message_id - ) - self._session.commit() - - # Wait until the event starts - yield - - # Delete the channel message - log.debug(f"Deleting message for: {self.mmid}") - await self.command.interface.serf.api_call( - self.command.interface.serf.client.delete_message, - chat_id=self._mmevent.interface_data.chat_id, - message_id=self._mmevent.interface_data.message_id - ) - - # Unregister the Telegram keyboard bindings - log.debug(f"Unregistering keyboard for: {self.mmid}") - self.unregister_telegram_keyboard(inkm) - - async def telegram_channel_message_update(self): - log.debug(f"Updating message for: {self.mmid}") - try: - await asyncify( - self.command.interface.serf.client.edit_message_text, - chat_id=self._mmevent.interface_data.chat_id, - text=telegram_escape(self.channel_text), - message_id=self._mmevent.interface_data.message_id, - parse_mode="HTML", - disable_web_page_preview=True, - reply_markup=self.telegram_keyboard - ) - except TelegramError as e: - log.warning(f"TelegramError during update: {e}") - - async def telegram_group_message_start(self): - await self.command.interface.serf.api_call( - self.command.interface.serf.client.send_message, - chat_id=self.telegram_group_id, - text=telegram_escape(self.start_text), - parse_mode="HTML", - disable_webpage_preview=True - ) - - async def telegram_group_message_delete(self): - await self.command.interface.serf.api_call( - self.command.interface.serf.client.send_message, - chat_id=self.telegram_group_id, - text=telegram_escape(self.delete_text), - parse_mode="HTML", - disable_webpage_preview=True - ) - - def start(self): - log.debug(f"Starting task for: {self.mmid}") - self.task = self.loop.create_task(self.run()) - - @sentry_async_wrap() - async def run(self): - log.debug(f"Running task for: {self.mmid}") - - # Create a new session for the MMTask - self._session = self.command.alchemy.Session() - self._EventT = self.command.alchemy.get(MMEvent) - self._ResponseT = self.command.alchemy.get(MMResponse) - self._mmevent: MMEvent = self._session.query(self._EventT).get(self.mmid) - - if self._mmevent is None: - raise rc.InvalidInputError(f"No event exists with the mmid {self.mmid}.") - - if self._mmevent.interface != "telegram": - raise rc.UnsupportedError("Currently only the Telegram interface is supported.") - - async with self.telegram_channel_message(): - self.loop.create_task(self.wait_until_due()) - - # Sleep until something interrupts the task - interrupt = await self.queue.get() - - # Mark the event as interrupted - self._mmevent.interrupted = True - self._session.commit() - - # Send a group notification if the MMEvent wasn't deleted - if interrupt != Interrupts.MANUAL_DELETE: - await self.telegram_group_message_start() - else: - await self.telegram_group_message_delete() - - # Close the database session - await asyncify(self._session.close) - - -log = logging.getLogger(__name__) +from ..tables import MMEvent +from ..utils import MMTask class MatchmakingCommand(rc.Command): diff --git a/royalpack/utils/__init__.py b/royalpack/utils/__init__.py index bf359037..554230b4 100644 --- a/royalpack/utils/__init__.py +++ b/royalpack/utils/__init__.py @@ -1,7 +1,9 @@ from .royalqueue import RoyalQueue from .royalpool import RoyalPool +from .mmtask import MMTask __all__ = [ "RoyalQueue", "RoyalPool", + "MMTask", ] diff --git a/royalpack/utils/mmtask.py b/royalpack/utils/mmtask.py new file mode 100644 index 00000000..0d0f3cbc --- /dev/null +++ b/royalpack/utils/mmtask.py @@ -0,0 +1,456 @@ +import contextlib +import random +from typing import * +import logging +import datetime +import enum +import asyncio as aio + +from telegram import InlineKeyboardMarkup as InKM +from telegram import InlineKeyboardButton as InKB +from telegram import Message as PTBMessage +from telegram import TelegramError + +import royalnet.commands as rc +import royalnet.utils as ru +import royalnet.serf.telegram as rst + +from ..types import MMChoice, MMInterfaceDataTelegram +from ..tables import MMEvent, MMResponse, FiorygiTransaction + + +class Interrupts(enum.Enum): + TIME_RAN_OUT = enum.auto() + MANUAL_START = enum.auto() + MANUAL_DELETE = enum.auto() + + +log = logging.getLogger(__name__) + + +mmchoice_sorting = { + MMChoice.YES: -4, + MMChoice.LATE_SHORT: -3, + MMChoice.LATE_MEDIUM: -2, + MMChoice.LATE_LONG: -1, + MMChoice.MAYBE: 0, + MMChoice.NO: 1 +} + + +class MMTask: + def __init__(self, mmid: int, *, command: rc.Command): + log.debug(f"Creating task for: {mmid}") + + self.loop: aio.AbstractEventLoop = command.loop + self.task: Optional[aio.Task] = None + self.queue: aio.Queue = aio.Queue(loop=self.loop) + self.command: rc.Command = command + self.mmid: int = mmid + + self._session: Optional = None + self._EventT: Optional[Type[MMEvent]] = None + self._ResponseT: Optional[Type[MMResponse]] = None + self._mmevent: Optional[MMEvent] = None + + @property + def is_running(self): + return self.task is not None + + def sync(self): + self._session.refresh(self._mmevent) + + def get_response_line(self, response: MMResponse): + self.sync() + + # noinspection PyListCreation + line = [] + + # Emoji + line.append(f"{response.choice.value}") + + # Mention the user if he said yes, otherwise just display his name + if response.choice == MMChoice.NO: + line.append(f"{response.user.telegram[0].name()}") + else: + line.append(f"{response.user.telegram[0].mention()}") + + # Late time + if response.choice == MMChoice.LATE_SHORT: + td = self._mmevent.datetime + datetime.timedelta(minutes=10) + line.append(f"[{td.strftime('%H:%M')}]") + + elif response.choice == MMChoice.LATE_MEDIUM: + td = self._mmevent.datetime + datetime.timedelta(minutes=30) + line.append(f"[{td.strftime('%H:%M')}]") + + elif response.choice == MMChoice.LATE_LONG: + td = self._mmevent.datetime + datetime.timedelta(minutes=60) + line.append(f"[{td.strftime('%H:%M')}+]") + + # Creator + if response.user == self._mmevent.creator: + line.append("👑") + + # Result + return " ".join(line) + + @property + def channel_text(self) -> str: + self.sync() + + # noinspection PyListCreation + text = [] + + # First line + if self._mmevent.datetime is None: + text.append(f"🌐 [Prossimamente] [b]{self._mmevent.title}[/b]") + else: + text.append(f"🚩 [{self._mmevent.datetime.strftime('%Y-%m-%d %H:%M')}] [b]{self._mmevent.title}[/b]") + + # Description + if self._mmevent.description: + text.append(f"{self._mmevent.description}") + + # Spacer + text.append("") + + # Responses + responses = sorted(self._mmevent.responses, key=lambda r: mmchoice_sorting[r.choice]) + for response in responses: + text.append(self.get_response_line(response)) + + # Result + return "\n".join(text) + + @property + def start_text(self) -> str: + self.sync() + + # noinspection PyListCreation + text = [] + + # First line + if self._mmevent.datetime is None: + text.append(f"🌐 Le iscrizioni all'evento [b]{self._mmevent.title}[/b] sono terminate!") + else: + text.append(f"🚩 L'evento [b]{self._mmevent.title}[/b] è iniziato!") + + # Description + if self._mmevent.description: + text.append(f"{self._mmevent.description}") + + # Spacer + text.append("") + + # Responses + responses = sorted(self._mmevent.responses, key=lambda r: mmchoice_sorting[r.choice]) + for response in responses: + text.append(self.get_response_line(response)) + + # Result + return "\n".join(text) + + @property + def delete_text(self) -> str: + return f"🗑 L'evento [b]{self._mmevent.title}[/b] è stato eliminato." + + def get_answer_callback(self, choice: MMChoice): + async def callback(data: rc.CommandData): + # Find the user who clicked on the button + user = await data.get_author(error_if_none=True) + + # Get the related MMEvent + mmevent: MMEvent = await ru.asyncify(data.session.query(self._EventT).get, self.mmid) + + # Check if the user had already responded + mmresponse: MMResponse = await ru.asyncify( + data.session.query(self._ResponseT).filter_by(user=user, mmevent=mmevent).one_or_none + ) + + if mmresponse is None: + # If they didn't respond, create a new MMResponse + mmresponse = self._ResponseT(user=user, mmevent=mmevent, choice=choice) + data.session.add(mmresponse) + + # Drop fiorygi + if random.randrange(100) < self.command.config["Matchmaking"]["fiorygi_award_chance"]: + await FiorygiTransaction.spawn_fiorygi(data, user, 1, "aver risposto a un matchmaking") + else: + # Change their response + mmresponse.choice = choice + await data.session_commit() + + await self.telegram_channel_message_update() + + await data.reply(f"{choice.value} Hai risposto al matchmaking!") + return callback + + def get_delete_callback(self): + async def callback(data: rc.CommandData): + # Find the user who clicked on the button + user = await data.get_author(error_if_none=True) + + # Get the related MMEvent + mmevent: MMEvent = await ru.asyncify(data.session.query(self._EventT).get, self.mmid) + + # Ensure the user has the required roles to start the matchmaking + if user != mmevent.creator and "admin" not in user.roles: + raise rc.UserError("Non hai i permessi per eliminare questo matchmaking!") + + # Interrupt the matchmaking with the MANUAL_DELETE reason + await self.queue.put(Interrupts.MANUAL_DELETE) + + await data.reply(f"🗑 Evento eliminato!") + return callback + + def get_start_callback(self): + async def callback(data: rc.CommandData): + # Find the user who clicked on the button + user = await data.get_author(error_if_none=True) + + # Get the related MMEvent + mmevent: MMEvent = await ru.asyncify(data.session.query(self._EventT).get, self.mmid) + + # Ensure the user has the required roles to start the matchmaking + if user != mmevent.creator and "admin" not in user.roles: + raise rc.UserError("Non hai i permessi per eliminare questo matchmaking!") + + # Interrupt the matchmaking with the MANUAL_DELETE reason + await self.queue.put(Interrupts.MANUAL_START) + + await data.reply(f"🚩 Evento avviato!") + return callback + + @property + def royalnet_keyboard(self): + # noinspection PyListCreation + rows = [] + + rows.append([ + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.YES.value}", + text="Ci sarò!", + callback=self.get_answer_callback(MMChoice.YES) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.MAYBE.value}", + text="Forse...", + callback=self.get_answer_callback(MMChoice.MAYBE) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.NO.value}", + text="Non mi interessa.", + callback=self.get_answer_callback(MMChoice.NO) + ), + ]) + + if self._mmevent.datetime is not None: + rows.append([ + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.LATE_SHORT.value}", + text="10 min", + callback=self.get_answer_callback(MMChoice.LATE_SHORT) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.LATE_MEDIUM.value}", + text="30 min", + callback=self.get_answer_callback(MMChoice.LATE_MEDIUM) + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"{MMChoice.LATE_LONG.value}", + text="60 min", + callback=self.get_answer_callback(MMChoice.LATE_LONG) + ) + ]) + + rows.append([ + rc.KeyboardKey( + interface=self.command.interface, + short=f"🗑", + text="Elimina", + callback=self.get_delete_callback() + ), + rc.KeyboardKey( + interface=self.command.interface, + short=f"🚩", + text="Inizia", + callback=self.get_start_callback() + ), + ]) + + return rows + + @property + def telegram_keyboard(self): + # noinspection PyListCreation + rows = [] + key_id = 0 + + for r_row in self.royalnet_keyboard: + row = [] + for r_key in r_row: + # Generate a unique callback string + callback_str = f"mm{self.mmid}_{key_id}" + + # Create a InlineKeyboardButton with that callback string + row.append(InKB(f"{r_key.short} {r_key.text}", callback_data=callback_str)) + + # Increase the key_id + key_id += 1 + rows.append(row) + + # Return the resulting InlineKeyboardMarkup + return InKM(rows) + + def register_telegram_keyboard(self, inkm: InKM): + # noinspection PyListCreation + royalnet_keyboard = self.royalnet_keyboard + for x, row in enumerate(inkm.inline_keyboard): + for y, key in enumerate(row): + key: InKB + self.command.interface.serf.register_keyboard_key(key.callback_data, key=royalnet_keyboard[x][y]) + + def unregister_telegram_keyboard(self, inkm: InKM): + for row in inkm.inline_keyboard: + for key in row: + key: InKB + self.command.interface.serf.unregister_keyboard_key(key.callback_data) + + async def wait_until_due(self): + """When the event is due, interrupt the MMTask with the TIME_RAN_OUT reason.""" + if self._mmevent.datetime is None: + return + await ru.sleep_until(self._mmevent.datetime) + await self.queue.put(Interrupts.TIME_RAN_OUT) + + @property + def telegram_channel_id(self): + return self.command.config["Matchmaking"]["mm_telegram_channel_id"] + + @property + def telegram_group_id(self): + return self.command.config["Matchmaking"]["mm_telegram_group_id"] + + @contextlib.asynccontextmanager + async def telegram_channel_message(self): + + # Generate the InlineKeyboardMarkup + inkm = self.telegram_keyboard + + # Bind the Royalnet buttons to the Telegram keyboard + log.debug(f"Registering keyboard for: {self.mmid}") + self.register_telegram_keyboard(inkm) + + # If the event has no associated interface data... + if self._mmevent.interface_data is None: + # Send the channel message + log.debug(f"Sending message for: {self.mmid}") + message: PTBMessage = await self.command.interface.serf.api_call( + self.command.interface.serf.client.send_message, + chat_id=self.telegram_channel_id, + text=rst.escape(self.channel_text), + parse_mode="HTML", + disable_webpage_preview=True, + reply_markup=inkm + ) + + # Register the interface data on the database + self._mmevent.interface_data = MMInterfaceDataTelegram( + chat_id=self.telegram_channel_id, + message_id=message.message_id + ) + self._session.commit() + + # Wait until the event starts + yield + + # Delete the channel message + log.debug(f"Deleting message for: {self.mmid}") + await self.command.interface.serf.api_call( + self.command.interface.serf.client.delete_message, + chat_id=self._mmevent.interface_data.chat_id, + message_id=self._mmevent.interface_data.message_id + ) + + # Unregister the Telegram keyboard bindings + log.debug(f"Unregistering keyboard for: {self.mmid}") + self.unregister_telegram_keyboard(inkm) + + async def telegram_channel_message_update(self): + log.debug(f"Updating message for: {self.mmid}") + try: + await ru.asyncify( + self.command.interface.serf.client.edit_message_text, + chat_id=self._mmevent.interface_data.chat_id, + text=rst.escape(self.channel_text), + message_id=self._mmevent.interface_data.message_id, + parse_mode="HTML", + disable_web_page_preview=True, + reply_markup=self.telegram_keyboard + ) + except TelegramError as e: + log.warning(f"TelegramError during update: {e}") + + async def telegram_group_message_start(self): + await self.command.interface.serf.api_call( + self.command.interface.serf.client.send_message, + chat_id=self.telegram_group_id, + text=rst.escape(self.start_text), + parse_mode="HTML", + disable_webpage_preview=True + ) + + async def telegram_group_message_delete(self): + await self.command.interface.serf.api_call( + self.command.interface.serf.client.send_message, + chat_id=self.telegram_group_id, + text=rst.escape(self.delete_text), + parse_mode="HTML", + disable_webpage_preview=True + ) + + def start(self): + log.debug(f"Starting task for: {self.mmid}") + self.task = self.loop.create_task(self.run()) + + @ru.sentry_async_wrap() + async def run(self): + log.debug(f"Running task for: {self.mmid}") + + # Create a new session for the MMTask + self._session = self.command.alchemy.Session() + self._EventT = self.command.alchemy.get(MMEvent) + self._ResponseT = self.command.alchemy.get(MMResponse) + self._mmevent: MMEvent = self._session.query(self._EventT).get(self.mmid) + + if self._mmevent is None: + raise rc.InvalidInputError(f"No event exists with the mmid {self.mmid}.") + + if self._mmevent.interface != "telegram": + raise rc.UnsupportedError("Currently only the Telegram interface is supported.") + + async with self.telegram_channel_message(): + self.loop.create_task(self.wait_until_due()) + + # Sleep until something interrupts the task + interrupt = await self.queue.get() + + # Mark the event as interrupted + self._mmevent.interrupted = True + self._session.commit() + + # Send a group notification if the MMEvent wasn't deleted + if interrupt != Interrupts.MANUAL_DELETE: + await self.telegram_group_message_start() + else: + await self.telegram_group_message_delete() + + # Close the database session + await ru.asyncify(self._session.close) \ No newline at end of file From 68a3c910b0710f60e577471dc35d7b330c527e9d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 7 Jul 2020 20:19:11 +0200 Subject: [PATCH 196/227] publish: 5.9.10 --- pyproject.toml | 2 +- royalpack/tables/steam.py | 5 ++++- royalpack/version.py | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 63a118b1..3cd729ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.9" + version = "5.9.10" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/tables/steam.py b/royalpack/tables/steam.py index 24007241..bbc0d4f3 100644 --- a/royalpack/tables/steam.py +++ b/royalpack/tables/steam.py @@ -45,7 +45,10 @@ class Steam: def json(self): return { - "steamid": self._steamid, + "steamid2": self.steamid.as_steam2, + "steamid3": self.steamid.as_steam3, + "steamid32": self.steamid.as_32, + "steamid64": self.steamid.as_64, "persona_name": self.persona_name, "profile_url": self.profile_url, "avatar": self.avatar, diff --git a/royalpack/version.py b/royalpack/version.py index bdd6cc67..9d75da72 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.9" +semantic = "5.9.10" From 632c3327b7b39660c0f1e5193b2da24d3887930c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 8 Jul 2020 02:55:15 +0200 Subject: [PATCH 197/227] publish: 5.10.0 --- README.md | 15 ++++++++++++--- pyproject.toml | 2 +- royalpack/commands/brawlhalla.py | 4 ++-- royalpack/commands/dota.py | 4 ++-- royalpack/commands/leagueoflegends.py | 7 ++++--- royalpack/version.py | 2 +- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b48c9811..3984eb38 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,16 @@ Imgur.token = "1234567890abcde" Steam.web_api_key = "123567890ABCDEF123567890ABCDEF12" # Should Royalnet automatically update the Dota ranks of all users? -Dota.updater = false +Dota.updater.enabled = false + +# How many seconds should there be between two Dota updates? +Dota.updater.delay = 86400 # Should Royalnet automatically update the League of Legends ranks of all users? -Lol.updater = false +Lol.updater.enabled = false + +# How many seconds should there be between two League of Legends updates? +Lol.updater.delay = 86400 # A League of Legends API token (https://developer.riotgames.com/) Lol.token = "RGAPI-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" @@ -30,7 +36,10 @@ Lol.token = "RGAPI-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" Lol.region = "euw1" # Should Royalnet automatically update the Brawlhalla ranks of all users? -Brawlhalla.updater = false +Brawlhalla.updater.enabled = false + +# How many seconds should there be between two League of Legends updates? +Brawlhalla.updater.delay = 86400 # A Brawlhalla API key (https://dev.brawlhalla.com/) Brawlhalla.api_key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA" diff --git a/pyproject.toml b/pyproject.toml index 3cd729ca..ab35fc65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.9.10" + version = "5.10.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index 8c8601f1..f83d8b08 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -25,8 +25,8 @@ class BrawlhallaCommand(Command): def __init__(self, interface: CommandInterface): super().__init__(interface) - if self.interface.name == "telegram" and self.config["Brawlhalla"]["updater"]: - self.loop.create_task(self._updater(7200)) + if self.interface.name == "telegram" and self.config["Brawlhalla"]["updater"]["enabled"]: + self.loop.create_task(self._updater(int(self.config["Brawlhalla"]["updater"]["delay"]))) async def _send(self, message): client = self.serf.client diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index 085fe900..4943e5e0 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -24,8 +24,8 @@ class DotaCommand(rc.Command): def __init__(self, interface: rc.CommandInterface): super().__init__(interface) - if self.interface.name == "telegram" and self.config["Dota"]["updater"]: - self.loop.create_task(self._updater(7200)) + if self.interface.name == "telegram" and self.config["Dota"]["updater"]["enabled"]: + self.loop.create_task(self._updater(int(self.config["Dota"]["updater"]["delay"]))) async def _send(self, message): client = self.serf.client diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 1331192c..f383a1ee 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -24,9 +24,10 @@ class LeagueoflegendsCommand(rc.Command): def __init__(self, interface: rc.CommandInterface): super().__init__(interface) - self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.config["Lol"]["token"]) - if self.interface.name == "telegram" and self.config["Lol"]["updater"]: - self.loop.create_task(self._updater(7200)) + self._riotwatcher: Optional[riotwatcher.RiotWatcher] = None + if self.interface.name == "telegram" and self.config["Lol"]["updater"]["enabled"]: + self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.config["Lol"]["token"]) + self.loop.create_task(self._updater(int(self.config["Lol"]["updater"]["delay"]))) async def _send(self, message): client = self.serf.client diff --git a/royalpack/version.py b/royalpack/version.py index 9d75da72..1d7bdf7b 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.9.10" +semantic = "5.10.0" From 2e88bc879cc87f9bc8121abfcb9ca501bf4dd2d4 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Jul 2020 04:13:54 +0200 Subject: [PATCH 198/227] Add more features to steam --- royalpack/commands/steampowered.py | 24 ++++++++++++++++++++++-- royalpack/tables/steam.py | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 81275c09..05c4c3be 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -23,8 +23,12 @@ class SteampoweredCommand(rc.Command): @staticmethod def _display(account: Steam): - string = f"ℹ️ [b]{account.persona_name}[/b]\n" \ - f"{account.profile_url}\n" \ + string = f"ℹ️ [url={account.profile_url}]{account.persona_name}[/url]\n" \ + f"[b]Level {account.account_level}[/b]\n" \ + f"\n" \ + f"Owned games: [b]{account.owned_games_count}[/b]\n" \ + f"Most played 2 weeks: [url=https://store.steampowered.com/app/{account.most_played_game_2weeks}]{account.most_played_game_2weeks}[/url]\n" \ + f"Most played forever: [url=https://store.steampowered.com/app/{account.most_played_game_forever}]{account.most_played_game_forever}[/url]\n" \ f"\n" \ f"SteamID: [c]{account.steamid.as_32}[/c]\n" \ f"SteamID2: [c]{account.steamid.as_steam2}[/c]\n" \ @@ -50,6 +54,22 @@ class SteampoweredCommand(rc.Command): account.primary_clan_id = r["primaryclanid"] account.account_creation_date = datetime.datetime.fromtimestamp(r["timecreated"]) + # noinspection PyProtectedMember + response = await self._call(self._api.IPlayerService.GetSteamLevel_v1, steamid=account._steamid) + account.account_level = response["response"]["player_level"] + + # noinspection PyProtectedMember + response = await self._call(self._api.IPlayerService.GetOwnedGames_v1, + steamid=account._steamid, + include_appinfo=False, + include_played_free_games=True, + include_free_sub=False, + appids_filter=None) + account.owned_games_count = response["response"]["game_count"] + if response["response"]["game_count"] >= 0: + account.most_played_game_2weeks = sorted(response["response"]["games"], key=lambda g: -g.get("playtime_2weeks", 0))[0]["appid"] + account.most_played_game_forever = sorted(response["response"]["games"], key=lambda g: -g.get("playtime_forever", 0))[0]["appid"] + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: author = await data.get_author() if len(args) > 0: diff --git a/royalpack/tables/steam.py b/royalpack/tables/steam.py index bbc0d4f3..3e2b2447 100644 --- a/royalpack/tables/steam.py +++ b/royalpack/tables/steam.py @@ -43,6 +43,22 @@ class Steam: def account_creation_date(self): return Column(DateTime) + @declared_attr + def account_level(self): + return Column(Integer, nullable=False, default=0) + + @declared_attr + def owned_games_count(self): + return Column(Integer, nullable=False, default=0) + + @declared_attr + def most_played_game_2weeks(self): + return Column(Integer, nullable=False, default=753) + + @declared_attr + def most_played_game_forever(self): + return Column(Integer, nullable=False, default=753) + def json(self): return { "steamid2": self.steamid.as_steam2, From bb1dcb9d3b6e620a5b5745931aa11ed8eef483a5 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Jul 2020 04:14:05 +0200 Subject: [PATCH 199/227] publish: 5.11.0 --- royalpack/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/version.py b/royalpack/version.py index 1d7bdf7b..2ee9ff43 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.10.0" +semantic = "5.11.0" From 47bc6e136dc1b80b39515d1c6dc4af5975f9815c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 9 Jul 2020 04:15:06 +0200 Subject: [PATCH 200/227] publish: 5.11.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ab35fc65..0b63bf4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.10.0" + version = "5.11.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" From 2e09b0e30ee168c2d987ea3ba7098a99d5bf0138 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Fri, 10 Jul 2020 14:14:50 +0200 Subject: [PATCH 201/227] publish: 5.11.1 --- pyproject.toml | 2 +- royalpack/commands/abstract/linker.py | 10 ++++++++++ royalpack/tables/steam.py | 4 ++++ royalpack/version.py | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 royalpack/commands/abstract/linker.py diff --git a/pyproject.toml b/pyproject.toml index 0b63bf4c..c21bb6f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.11.0" + version = "5.11.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/abstract/linker.py b/royalpack/commands/abstract/linker.py new file mode 100644 index 00000000..3f10327b --- /dev/null +++ b/royalpack/commands/abstract/linker.py @@ -0,0 +1,10 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import abc + + +class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + ... diff --git a/royalpack/tables/steam.py b/royalpack/tables/steam.py index 3e2b2447..1e4fedbd 100644 --- a/royalpack/tables/steam.py +++ b/royalpack/tables/steam.py @@ -70,6 +70,10 @@ class Steam: "avatar": self.avatar, "primary_clan_id": self.primary_clan_id, "account_creation_date": self.account_creation_date.isoformat(), + "account_level": self.account_level, + "owned_games_count": self.owned_games_count, + "most_played_game_2weeks": self.most_played_game_2weeks, + "most_played_game_forever": self.most_played_game_forever, "dota": self.dota.json() if self.dota is not None else None, "brawlhalla": self.brawlhalla.json() if self.brawlhalla is not None else None diff --git a/royalpack/version.py b/royalpack/version.py index 2ee9ff43..64511ad8 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.11.0" +semantic = "5.11.1" From 395313f9cb4aa2318ad3446477547c8b7d7e07e6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Jul 2020 02:14:38 +0200 Subject: [PATCH 202/227] Create abstract linkercommand --- pyproject.toml | 2 +- royalpack/commands/abstract/linker.py | 190 +++++++++++++++- royalpack/commands/brawlhalla.py | 285 +++++++++++------------- royalpack/commands/dota.py | 157 +++++-------- royalpack/commands/leagueoflegends.py | 302 +++++++++++--------------- royalpack/tables/brawlhalla.py | 4 +- royalpack/tables/dota.py | 4 +- royalpack/tables/leagueoflegends.py | 4 +- royalpack/types/__init__.py | 2 + royalpack/types/updatable.py | 2 + royalpack/version.py | 2 +- 11 files changed, 500 insertions(+), 454 deletions(-) create mode 100644 royalpack/types/updatable.py diff --git a/pyproject.toml b/pyproject.toml index c21bb6f4..b9ee9d51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.11.1" + version = "5.12.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/abstract/linker.py b/royalpack/commands/abstract/linker.py index 3f10327b..48963dd1 100644 --- a/royalpack/commands/abstract/linker.py +++ b/royalpack/commands/abstract/linker.py @@ -1,10 +1,198 @@ from typing import * -import royalnet import royalnet.commands as rc +import royalnet.utils as ru +import royalnet.serf.telegram as rst +import royalnet.backpack.tables as rbt import abc +import logging +import asyncio as aio +from ...types import Updatable + + +log = logging.getLogger(__name__) class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): + def __init__(self, interface: rc.CommandInterface): + super().__init__(interface) + + self.updater_task = None + if self.enabled(): + # Run updaters only on Telegram + if self.interface.name == "telegram": + 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) + + 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: + message = ["🔗 Account collegato!\n"] + created = await self.create(session=data.session, user=author, args=args) + message.append(self.describe(created)) + await data.session_commit() + 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.""" + return str(obj) + + @abc.abstractmethod + async def get_updatables_of_user(self, session, user: rbt.User) -> List[Updatable]: + """Get the updatables of a specific user.""" ... + + @abc.abstractmethod + async def get_updatables(self, session) -> List[Updatable]: + """Return a list of all objects that should be updated at this updater cycle.""" + ... + + @abc.abstractmethod + async def create(self, session, user: rbt.User, args) -> Updatable: + """Create a new updatable object for a user.""" + ... + + @abc.abstractmethod + async def update(self, session, obj, change: Callable[[str, Any], Awaitable[None]]): + """Update a single updatable object. Use the change method to change values on the object!""" + ... + + @abc.abstractmethod + async def on_increase(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + """Called when the attribute has increased from the old value.""" + ... + + @abc.abstractmethod + async def on_unchanged(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + """Called when the attribute stayed the same as the old value.""" + ... + + @abc.abstractmethod + async def on_decrease(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + """Called when the attribute has decreased from the old value.""" + ... + + @abc.abstractmethod + async def on_first(self, session, obj: Updatable, attribute: str, old: None, new: Any) -> None: + """Called when the attribute changed from None.""" + ... + + @abc.abstractmethod + async def on_reset(self, session, obj: Updatable, attribute: str, old: Any, new: None) -> None: + """Called when the attribute changed to None.""" + ... + + async def _change(self, + session, + obj, + attribute: str, + new) -> None: + """Set the value of an attribute of an object to a value, and call the corresponding method.""" + old = obj.__getattribute__(attribute) + if new == old: + await self.on_unchanged(session=session, + obj=obj, + attribute=attribute, + old=old, + new=new) + else: + if old is None: + await self.on_first(session=session, + obj=obj, + attribute=attribute, + old=old, + new=new) + elif new is None: + await self.on_reset(session=session, + obj=obj, + attribute=attribute, + old=old, + new=new) + elif new > old: + await self.on_increase(session=session, + obj=obj, + attribute=attribute, + old=old, + new=new) + else: + await self.on_decrease(session=session, + obj=obj, + attribute=attribute, + old=old, + new=new) + obj.__setattr__(attribute, new) + + def enabled(self) -> bool: + """Whether the updater is enabled or not.""" + return self.config[self.name]["updater"]["enabled"] + + def period(self) -> int: + """The time between two updater cycles.""" + return self.config[self.name]["updater"]["period"] + + def delay(self) -> int: + """The time between two object updates.""" + return self.config[self.name]["updater"]["rate"] + + def target(self) -> int: + """The id of the Telegram chat where notifications should be sent.""" + return self.config[self.name]["updater"]["target"] + + async def run_updater(self): + log.info(f"Starting updater: {self.name}") + + while True: + log.debug(f"Updater cycle: {self.name}") + session = self.alchemy.Session() + objects = await self.get_updatables(session) + + for obj in objects: + log.debug(f"Updating: {obj} ({self.name})") + + async def change(attribute: str, value: Any): + """A shortcut for self.__change.""" + await self._change(session=session, + obj=obj, + attribute=attribute, + new=value) + + try: + await self.update(session=session, + obj=obj, + change=change) + except Exception as e: + ru.sentry_exc(e) + + delay = self.delay() + log.debug(f"Waiting for: {delay} seconds (delay)") + await aio.sleep(delay) + + log.debug(f"Committing updates: {self.name}") + await ru.asyncify(session.commit) + session.close() + + period = self.period() + log.debug(f"Waiting for: {period} seconds (period)") + await aio.sleep(period) + + async def notify(self, message): + await self.serf.api_call(self.serf.client.send_message, + chat_id=self.target(), + text=rst.escape(message), + parse_mode="HTML", + disable_webpage_preview=True) diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index f83d8b08..f775aeb7 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -3,41 +3,145 @@ from typing import * import asyncio import logging import aiohttp + +from royalnet.backpack import tables as rbt from royalnet.commands import * from royalnet.utils import * -from royalnet.serf.telegram.escape import escape as tg_escape from sqlalchemy import or_, and_ +from .abstract.linker import LinkerCommand from ..tables import Steam, Brawlhalla, BrawlhallaDuo -from ..types import BrawlhallaRank, BrawlhallaMetal, BrawlhallaTier +from ..types import BrawlhallaRank, BrawlhallaMetal, BrawlhallaTier, Updatable log = logging.getLogger(__name__) -class BrawlhallaCommand(Command): +class BrawlhallaCommand(LinkerCommand): name: str = "brawlhalla" aliases = ["bh", "bruhalla", "bruhlalla"] - description: str = "Visualizza le tue statistiche di Dota!" + description: str = "Visualizza le tue statistiche di Brawlhalla." syntax: str = "" - def __init__(self, interface: CommandInterface): - super().__init__(interface) - if self.interface.name == "telegram" and self.config["Brawlhalla"]["updater"]["enabled"]: - self.loop.create_task(self._updater(int(self.config["Brawlhalla"]["updater"]["delay"]))) + async def get_updatables_of_user(self, session, user: rbt.User) -> List[Brawlhalla]: + return user.steam - async def _send(self, message): - client = self.serf.client - await self.serf.api_call(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=tg_escape(message), - parse_mode="HTML", - disable_webpage_preview=True) + async def get_updatables(self, session) -> List[Brawlhalla]: + return await asyncify(session.query(self.alchemy.get(Steam)).all) + + async def create(self, session, user: rbt.User, args) -> Updatable: + raise InvalidInputError("Brawlhalla accounts are automatically linked from Steam.") + + async def update(self, session, obj, change: Callable[[str, Any], Awaitable[None]]): + BrawlhallaT = self.alchemy.get(Brawlhalla) + DuoT = self.alchemy.get(BrawlhallaDuo) + log.info(f"Updating: {obj}") + async with aiohttp.ClientSession() as hcs: + bh: Brawlhalla = obj.brawlhalla + if bh is None: + log.debug(f"Checking if player has an account...") + async with hcs.get(f"https://api.brawlhalla.com/search?steamid={obj.steamid.as_64}&api_key={self.config['Brawlhalla']['api_key']}") as response: + if response.status != 200: + raise ExternalError(f"Brawlhalla API /search returned {response.status}!") + j = await response.json() + if j == {} or j == []: + log.debug("No account found.") + return + bh = BrawlhallaT( + steam=obj, + brawlhalla_id=j["brawlhalla_id"], + name=j["name"] + ) + session.add(bh) + session.flush() + + async with hcs.get(f"https://api.brawlhalla.com/player/{bh.brawlhalla_id}/ranked?api_key={self.config['Brawlhalla']['api_key']}") as response: + if response.status != 200: + raise ExternalError(f"Brawlhalla API /ranked returned {response.status}!") + j = await response.json() + if j == {} or j == []: + log.debug("No ranked info found.") + else: + await self._change(session=session, obj=bh, attribute="rating_1v1", new=j["rating"]) + metal_name, tier_name = j["tier"].split(" ", 1) + metal = BrawlhallaMetal[metal_name.upper()] + tier = BrawlhallaTier(int(tier_name)) + rank = BrawlhallaRank(metal=metal, tier=tier) + await self._change(session=session, obj=bh, attribute="rank_1v1", new=rank) + + for jduo in j.get("2v2", []): + bhduo: Optional[BrawlhallaDuo] = await asyncify( + session.query(DuoT) + .filter( + or_( + and_( + DuoT.id_one == jduo["brawlhalla_id_one"], + DuoT.id_two == jduo["brawlhalla_id_two"] + ), + and_( + DuoT.id_one == jduo["brawlhalla_id_two"], + DuoT.id_two == jduo["brawlhalla_id_one"] + ) + ) + ) + .one_or_none + ) + if bhduo is None: + if bh.brawlhalla_id == jduo["brawlhalla_id_one"]: + otherbh: Optional[Brawlhalla] = await asyncify( + session.query(BrawlhallaT).get, jduo["brawlhalla_id_two"] + ) + else: + otherbh: Optional[Brawlhalla] = await asyncify( + session.query(BrawlhallaT).get, jduo["brawlhalla_id_one"] + ) + if otherbh is None: + continue + bhduo = DuoT( + one=bh, + two=otherbh, + ) + + session.add(bhduo) + await self._change(session=session, obj=bhduo, attribute="rating_2v2", new=jduo["rating"]) + metal_name, tier_name = jduo["tier"].split(" ", 1) + metal = BrawlhallaMetal[metal_name.upper()] + tier = BrawlhallaTier(int(tier_name)) + rank = BrawlhallaRank(metal=metal, tier=tier) + await self._change(session=session, obj=bhduo, attribute="rank_2v2", new=rank) + + async def on_increase(self, session, obj: Union[Brawlhalla, BrawlhallaDuo], attribute: str, old: Any, new: Any) -> None: + if attribute == "rank_1v1": + await self.notify(f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla! Congratulazioni!") + elif attribute == "rank_2v2": + await self.notify(f"📈 [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono saliti a [b]{new}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla! Congratulazioni!") + + async def on_unchanged(self, session, obj: Union[Brawlhalla, BrawlhallaDuo], attribute: str, old: Any, new: Any) -> None: + pass + + async def on_decrease(self, session, obj: Union[Brawlhalla, BrawlhallaDuo], attribute: str, old: Any, new: Any) -> None: + if attribute == "rank_1v1": + await self.notify(f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla.") + elif attribute == "rank_2v2": + await self.notify(f"📉 [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono scesi a [b]{new}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla.") + + async def on_first(self, session, obj: Union[Brawlhalla, BrawlhallaDuo], attribute: str, old: None, new: Any) -> None: + if attribute == "rank_1v1": + await self.notify(f"🌟 [b]{obj.steam.user}[/b] si è classificato a [b]{new}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla!") + elif attribute == "rank_2v2": + await self.notify(f"🌟 [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] si sono classificati a [b]{new}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla!") + + async def on_reset(self, session, obj: Union[Brawlhalla, BrawlhallaDuo], attribute: str, old: Any, new: None) -> None: + if attribute == "rank_1v1": + await self.notify(f"⬜️ [b]{obj.steam.user}[/b] non ha più un rank su Brawlhalla.") + elif attribute == "rank_2v2": + await self.notify(f"⬜️ [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] non hanno più un rank su Brawlhalla.") + + def describe(self, obj: Steam) -> str: + bh = obj.brawlhalla - @staticmethod - def _display(bh: Brawlhalla) -> str: string = [f"ℹ️ [b]{bh.name}[/b]", ""] if bh.rank_1v1: @@ -56,150 +160,3 @@ class BrawlhallaCommand(Command): string.append("") return "\n".join(string) - - async def _notify(self, - obj: Union[Brawlhalla, BrawlhallaDuo], - attribute_name: str, - old_value: Any, - new_value: Any): - if attribute_name == "rank_1v1": - old_rank: Optional[BrawlhallaRank] = old_value - new_rank: Optional[BrawlhallaRank] = new_value - if new_rank > old_rank: - message = f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla! Congratulazioni!" - else: - message = f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla." - await self._send(message) - elif attribute_name == "rank_2v2": - old_rank: Optional[BrawlhallaRank] = old_value - new_rank: Optional[BrawlhallaRank] = new_value - if new_rank > old_rank: - message = f"📈 [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono saliti a [b]{new_value}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla! Congratulazioni!" - else: - message = f"📉 [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono scesi a [b]{new_value}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla." - await self._send(message) - - @staticmethod - async def _change(obj: Union[Brawlhalla, BrawlhallaDuo], - attribute_name: str, - new_value: Any, - callback: Callable[[Union[Brawlhalla, BrawlhallaDuo], str, Any, Any], Awaitable[None]]): - old_value = obj.__getattribute__(attribute_name) - if old_value != new_value: - await callback(obj, attribute_name, old_value, new_value) - obj.__setattr__(attribute_name, new_value) - - async def _update(self, steam: Steam, db_session): - BrawlhallaT = self.alchemy.get(Brawlhalla) - DuoT = self.alchemy.get(BrawlhallaDuo) - log.info(f"Updating: {steam}") - async with aiohttp.ClientSession() as session: - bh: Brawlhalla = steam.brawlhalla - if bh is None: - log.debug(f"Checking if player has an account...") - async with session.get(f"https://api.brawlhalla.com/search?steamid={steam.steamid.as_64}&api_key={self.config['Brawlhalla']['api_key']}") as response: - if response.status != 200: - raise ExternalError(f"Brawlhalla API /search returned {response.status}!") - j = await response.json() - if j == {} or j == []: - log.debug("No account found.") - return - bh = BrawlhallaT( - steam=steam, - brawlhalla_id=j["brawlhalla_id"], - name=j["name"] - ) - db_session.add(bh) - message = f"↔️ Account {bh} connesso a {bh.steam.user}!" - await self._send(message) - async with session.get(f"https://api.brawlhalla.com/player/{bh.brawlhalla_id}/ranked?api_key={self.config['Brawlhalla']['api_key']}") as response: - if response.status != 200: - raise ExternalError(f"Brawlhalla API /ranked returned {response.status}!") - j = await response.json() - if j == {} or j == []: - log.debug("No ranked info found.") - else: - await self._change(bh, "rating_1v1", j["rating"], self._notify) - metal_name, tier_name = j["tier"].split(" ", 1) - metal = BrawlhallaMetal[metal_name.upper()] - tier = BrawlhallaTier(int(tier_name)) - rank = BrawlhallaRank(metal=metal, tier=tier) - await self._change(bh, "rank_1v1", rank, self._notify) - - for jduo in j.get("2v2", []): - bhduo: Optional[BrawlhallaDuo] = await asyncify( - db_session.query(DuoT) - .filter( - or_( - and_( - DuoT.id_one == jduo["brawlhalla_id_one"], - DuoT.id_two == jduo["brawlhalla_id_two"] - ), - and_( - DuoT.id_one == jduo["brawlhalla_id_two"], - DuoT.id_two == jduo["brawlhalla_id_one"] - ) - ) - ) - .one_or_none - ) - if bhduo is None: - if bh.brawlhalla_id == jduo["brawlhalla_id_one"]: - otherbh: Optional[Brawlhalla] = await asyncify( - db_session.query(BrawlhallaT).get, jduo["brawlhalla_id_two"] - ) - else: - otherbh: Optional[Brawlhalla] = await asyncify( - db_session.query(BrawlhallaT).get, jduo["brawlhalla_id_one"] - ) - if otherbh is None: - continue - bhduo = DuoT( - one=bh, - two=otherbh, - ) - - db_session.add(bhduo) - await self._change(bhduo, "rating_2v2", jduo["rating"], self._notify) - metal_name, tier_name = jduo["tier"].split(" ", 1) - metal = BrawlhallaMetal[metal_name.upper()] - tier = BrawlhallaTier(int(tier_name)) - rank = BrawlhallaRank(metal=metal, tier=tier) - await self._change(bhduo, "rank_2v2", rank, self._notify) - - await asyncify(db_session.commit) - - async def _updater(self, period: int): - log.info(f"Started updater with {period}s period") - while True: - log.info(f"Updating...") - session = self.alchemy.Session() - log.info("") - steams = session.query(self.alchemy.get(Steam)).all() - for steam in steams: - try: - await self._update(steam, session) - except Exception as e: - sentry_exc(e) - await asyncio.sleep(1) - await asyncify(session.commit) - session.close() - log.info(f"Sleeping for {period}s") - await asyncio.sleep(period) - - async def run(self, args: CommandArgs, data: CommandData) -> None: - author = await data.get_author(error_if_none=True) - - found_something = False - - message = "" - for steam in author.steam: - await self._update(steam, data.session) - if steam.brawlhalla is None: - continue - found_something = True - message += self._display(steam.brawlhalla) - message += "\n" - if not found_something: - raise UserError("Nessun account di Brawlhalla trovato.") - await data.reply(message) diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index 4943e5e0..14b7850f 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -1,11 +1,10 @@ from typing import * -import asyncio import logging -import sentry_sdk import aiohttp import royalnet.commands as rc import royalnet.utils as ru -import royalnet.serf.telegram as rst +from royalnet.backpack import tables as rbt +from .abstract.linker import LinkerCommand from ..tables import Steam, Dota from ..types import DotaRank @@ -13,139 +12,91 @@ from ..types import DotaRank log = logging.getLogger(__name__) -class DotaCommand(rc.Command): +class DotaCommand(LinkerCommand): name: str = "dota" aliases = ["dota2", "doto", "doto2", "dotka", "dotka2"] - description: str = "Visualizza le tue statistiche di Dota!" + description: str = "Visualizza le tue statistiche di Dota." syntax: str = "" - def __init__(self, interface: rc.CommandInterface): - super().__init__(interface) - if self.interface.name == "telegram" and self.config["Dota"]["updater"]["enabled"]: - self.loop.create_task(self._updater(int(self.config["Dota"]["updater"]["delay"]))) - - async def _send(self, message): - client = self.serf.client - await self.serf.api_call(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=rst.escape(message), - parse_mode="HTML", - disable_webpage_preview=True) - - @staticmethod - def _display(dota: Dota) -> str: - string = f"ℹ️ [b]{dota.steam.persona_name}[/b]\n" - - if dota.rank: - string += f"{dota.rank}\n" - + def describe(self, obj: Steam) -> str: + string = f"ℹ️ [b]{obj.persona_name}[/b]\n" + if obj.dota.rank: + string += f"{obj.dota.rank}\n" string += f"\n" \ - f"Wins: [b]{dota.wins}[/b]\n" \ - f"Losses: [b]{dota.losses}[/b]\n" \ + f"Wins: [b]{obj.dota.wins}[/b]\n" \ + f"Losses: [b]{obj.dota.losses}[/b]\n" \ f"\n" - return string - async def _notify(self, - obj: Dota, - attribute_name: str, - old_value: Any, - new_value: Any): - if attribute_name == "wins": - if old_value is None: - message = f"↔️ Account {obj} connesso a {obj.steam.user}!" - await self._send(message) - elif attribute_name == "rank": - old_rank: Optional[DotaRank] = old_value - new_rank: Optional[DotaRank] = new_value - if new_rank > old_rank: - message = f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new_value}[/b] su Dota 2! Congratulazioni!" - elif new_rank < old_rank: - message = f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new_value}[/b] su Dota 2." - else: - return - await self._send(message) + async def get_updatables_of_user(self, session, user: rbt.User) -> List[Dota]: + return user.steam - @staticmethod - async def _change(obj: Dota, - attribute_name: str, - new_value: Any, - callback: Callable[[Dota, str, Any, Any], Awaitable[None]]): - old_value = obj.__getattribute__(attribute_name) - if old_value != new_value: - await callback(obj, attribute_name, old_value, new_value) - obj.__setattr__(attribute_name, new_value) + async def get_updatables(self, session) -> List[Dota]: + return await ru.asyncify(session.query(self.alchemy.get(Steam)).all) - async def _update(self, steam: Steam, db_session): - log.info(f"Updating: {steam}") + async def create(self, session, user: rbt.User, args): + raise rc.InvalidInputError("Dota accounts are automatically linked from Steam.") + + async def update(self, session, obj: Steam, change: Callable[[str, Any], Awaitable[None]]): log.debug(f"Getting player data from OpenDota...") - async with aiohttp.ClientSession() as session: + async with aiohttp.ClientSession() as hcs: # Get profile data - async with session.get(f"https://api.opendota.com/api/players/{steam.steamid.as_32}/") as response: + async with hcs.get(f"https://api.opendota.com/api/players/{obj.steamid.as_32}/") as response: if response.status != 200: raise rc.ExternalError(f"OpenDota / returned {response.status}!") p = await response.json() # No such user if "profile" not in p: - log.debug(f"Not found: {steam}") + log.debug(f"Not found: {obj}") return # Get win/loss data - async with session.get(f"https://api.opendota.com/api/players/{steam.steamid.as_32}/wl") as response: + async with hcs.get(f"https://api.opendota.com/api/players/{obj.steamid.as_32}/wl") as response: if response.status != 200: raise rc.ExternalError(f"OpenDota /wl returned {response.status}!") wl = await response.json() # No such user if wl["win"] == 0 and wl["lose"] == 0: - log.debug(f"Not found: {steam}") + log.debug(f"Not found: {obj}") return # Find the Dota record, if it exists - dota: Dota = steam.dota + dota: Dota = obj.dota if dota is None: - dota = self.alchemy.get(Dota)(steam=steam) - db_session.add(dota) - db_session.flush() - await self._change(dota, "wins", wl["win"], self._notify) - await self._change(dota, "losses", wl["lose"], self._notify) + # Autocreate the Dota record + dota = self.alchemy.get(Dota)(steam=obj) + session.add(dota) + session.flush() + + # Make a custom change function + async def change(attribute: str, new: Any): + await self._change(session=session, obj=dota, attribute=attribute, new=new) + + await change("wins", wl["win"]) + await change("losses", wl["lose"]) if p["rank_tier"]: - await self._change(dota, "rank", DotaRank(rank_tier=p["rank_tier"]), self._notify) + await change("rank", DotaRank(rank_tier=p["rank_tier"])) else: - await self._change(dota, "rank", None, self._notify) + await change("rank", None) - async def _updater(self, period: int): - log.info(f"Started updater with {period}s period") - while True: - log.info(f"Updating...") - session = self.alchemy.Session() - log.info("") - steams = session.query(self.alchemy.get(Steam)).all() - for steam in steams: - try: - await self._update(steam, session) - except Exception as e: - sentry_sdk.capture_exception(e) - log.error(f"Error while updating {steam.user.username}: {e}") - await asyncio.sleep(1) - await ru.asyncify(session.commit) - session.close() - log.info(f"Sleeping for {period}s") - await asyncio.sleep(period) + async def on_increase(self, session, obj: Dota, attribute: str, old: Any, new: Any) -> None: + if attribute == "rank": + await self.notify(f"📈 [b]{obj.steam.user}[/b] è salito a [b]{new}[/b] su Dota 2! Congratulazioni!") - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - author = await data.get_author(error_if_none=True) + async def on_unchanged(self, session, obj: Dota, attribute: str, old: Any, new: Any) -> None: + pass - found_something = False + async def on_decrease(self, session, obj: Dota, attribute: str, old: Any, new: Any) -> None: + if attribute == "rank": + await self.notify(f"📉 [b]{obj.steam.user}[/b] è sceso a [b]{new}[/b] su Dota 2.") - message = "" - for steam in author.steam: - await self._update(steam, data.session) - if steam.dota is None: - continue - found_something = True - message += self._display(steam.dota) - message += "\n" - if not found_something: - raise rc.UserError("Nessun account di Dota 2 trovato.") - await data.reply(message) + async def on_first(self, session, obj: Dota, attribute: str, old: None, new: Any) -> None: + if attribute == "wins": + await self.notify(f"↔️ Account {obj} connesso a {obj.steam.user}!") + elif attribute == "rank": + await self.notify(f"🌟 [b]{obj.steam.user}[/b] si è classificato [b]{new}[/b] su Dota 2!") + + async def on_reset(self, session, obj: Dota, attribute: str, old: Any, new: None) -> None: + if attribute == "rank": + await self.notify(f"⬜️ [b]{obj.steam.user}[/b] non ha più un rank su Dota 2.") diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index f383a1ee..55b4b574 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -6,93 +6,79 @@ import sentry_sdk import royalnet.commands as rc import royalnet.utils as ru import royalnet.serf.telegram as rst +from royalnet.backpack import tables as rbt +from .abstract.linker import LinkerCommand from ..tables import LeagueOfLegends, FiorygiTransaction -from ..types import LeagueLeague +from ..types import LeagueLeague, Updatable log = logging.getLogger(__name__) -class LeagueoflegendsCommand(rc.Command): +class LeagueoflegendsCommand(LinkerCommand): name: str = "leagueoflegends" aliases = ["lol", "league"] - description: str = "Connetti un account di League of Legends a un account Royalnet, e visualizzane le statistiche." + description: str = "Connetti un account di League of Legends a un account Royalnet, o visualizzane le statistiche." syntax = "[nomeevocatore]" + queue_names = { + "rank_soloq": "Solo/Duo", + "rank_flexq": "Flex", + "rank_twtrq": "3v3", + "rank_tftq": "TFT" + } + def __init__(self, interface: rc.CommandInterface): super().__init__(interface) self._riotwatcher: Optional[riotwatcher.RiotWatcher] = None - if self.interface.name == "telegram" and self.config["Lol"]["updater"]["enabled"]: - self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.config["Lol"]["token"]) - self.loop.create_task(self._updater(int(self.config["Lol"]["updater"]["delay"]))) + if self.interface.name == "telegram" and self.enabled(): + self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.token()) - async def _send(self, message): - client = self.serf.client - await self.serf.api_call(client.send_message, - chat_id=self.config["Telegram"]["main_group_id"], - text=rst.escape(message), - parse_mode="HTML", - disable_webpage_preview=True) + def token(self): + return self.config["leagueoflegends"]["token"] - async def _notify(self, - obj: LeagueOfLegends, - attribute_name: str, - old_value: Any, - new_value: Any): - if isinstance(old_value, LeagueLeague): - # This is a rank change! - # Don't send messages for every rank change, send messages just if the TIER or RANK changes! - if old_value.tier == new_value.tier and old_value.rank == new_value.rank: - return - # Find the queue - queue_names = { - "rank_soloq": "Solo/Duo", - "rank_flexq": "Flex", - "rank_twtrq": "3v3", - "rank_tftq": "TFT" - } - # Prepare the message - if new_value > old_value: - message = f"📈 [b]{obj.user}[/b] è salito a {new_value} su League of Legends " \ - f"({queue_names[attribute_name]})! Congratulazioni!" - else: - message = f"📉 [b]{obj.user}[/b] è sceso a {new_value} su League of Legends " \ - f"({queue_names[attribute_name]})." - # Send the message - await self._send(message) - # Level up! - elif attribute_name == "summoner_level": - if new_value == 30 or (new_value >= 50 and (new_value % 25 == 0)): - await self._send(f"🆙 [b]{obj.user}[/b] è salito al livello [b]{new_value}[/b] su League of Legends!") + def region(self): + return self.config["leagueoflegends"]["region"] - @staticmethod - async def _change(obj: LeagueOfLegends, - attribute_name: str, - new_value: Any, - callback: Callable[ - [LeagueOfLegends, str, Any, Any], Awaitable[None]]): - old_value = obj.__getattribute__(attribute_name) - if old_value != new_value: - await callback(obj, attribute_name, old_value, new_value) - obj.__setattr__(attribute_name, new_value) + def describe(self, obj: LeagueOfLegends) -> str: + string = f"ℹ️ [b]{obj.summoner_name}[/b]\n" \ + f"Lv. {obj.summoner_level}\n" \ + f"Mastery score: {obj.mastery_score}\n" \ + f"\n" + if obj.rank_soloq: + string += f"Solo: {obj.rank_soloq}\n" + if obj.rank_flexq: + string += f"Flex: {obj.rank_flexq}\n" + if obj.rank_twtrq: + string += f"3v3: {obj.rank_twtrq}\n" + if obj.rank_tftq: + string += f"TFT: {obj.rank_tftq}\n" + return string - async def _update(self, lol: LeagueOfLegends): - log.info(f"Updating: {lol}") - log.debug(f"Getting summoner data: {lol}") - summoner = await ru.asyncify(self._riotwatcher.summoner.by_id, region=self.config["Lol"]["region"], - encrypted_summoner_id=lol.summoner_id) - await self._change(lol, "profile_icon_id", summoner["profileIconId"], self._notify) - await self._change(lol, "summoner_name", summoner["name"], self._notify) - await self._change(lol, "puuid", summoner["puuid"], self._notify) - await self._change(lol, "summoner_level", summoner["summonerLevel"], self._notify) - await self._change(lol, "summoner_id", summoner["id"], self._notify) - await self._change(lol, "account_id", summoner["accountId"], self._notify) - log.debug(f"Getting leagues data: {lol}") - leagues = await ru.asyncify(self._riotwatcher.league.by_summoner, region=self.config["Lol"]["region"], - encrypted_summoner_id=lol.summoner_id) + async def get_updatables_of_user(self, session, user: rbt.User) -> List[LeagueOfLegends]: + return await ru.asyncify(session.query(self.alchemy.get(LeagueOfLegends)).filter_by(user=user).all) + + async def get_updatables(self, session) -> List[LeagueOfLegends]: + return await ru.asyncify(session.query(self.alchemy.get(LeagueOfLegends)).all) + + async def create(self, session, user: rbt.User, args) -> LeagueOfLegends: + name = args.joined() + + # Connect a new League of Legends account to Royalnet + log.debug(f"Searching for: {name}") + summoner = self._riotwatcher.summoner.by_name(region=self.region(), summoner_name=name) + # Ensure the account isn't already connected to something else + leagueoflegends = await ru.asyncify( + session.query(self.alchemy.get(LeagueOfLegends)).filter_by(summoner_id=summoner["id"]).one_or_none) + if leagueoflegends: + raise rc.CommandError(f"L'account {leagueoflegends} è già registrato su Royalnet.") + # Get rank information + log.debug(f"Getting leagues data: {name}") + leagues = self._riotwatcher.league.by_summoner(region=self.region(), + encrypted_summoner_id=summoner["id"]) soloq = LeagueLeague() flexq = LeagueLeague() twtrq = LeagueLeague() @@ -106,120 +92,80 @@ class LeagueoflegendsCommand(rc.Command): twtrq = LeagueLeague.from_dict(league) if league["queueType"] == "RANKED_TFT": tftq = LeagueLeague.from_dict(league) - await self._change(lol, "rank_soloq", soloq, self._notify) - await self._change(lol, "rank_flexq", flexq, self._notify) - await self._change(lol, "rank_twtrq", twtrq, self._notify) - await self._change(lol, "rank_tftq", tftq, self._notify) - log.debug(f"Getting mastery data: {lol}") + # Get mastery score + log.debug(f"Getting mastery data: {name}") + mastery = self._riotwatcher.champion_mastery.scores_by_summoner(region=self.region(), + encrypted_summoner_id=summoner["id"]) + # Create database row + leagueoflegends = self.alchemy.get(LeagueOfLegends)( + region=self.region(), + user=user, + profile_icon_id=summoner["profileIconId"], + summoner_name=summoner["name"], + puuid=summoner["puuid"], + summoner_level=summoner["summonerLevel"], + summoner_id=summoner["id"], + account_id=summoner["accountId"], + rank_soloq=soloq, + rank_flexq=flexq, + rank_twtrq=twtrq, + rank_tftq=tftq, + mastery_score=mastery + ) + session.add(leagueoflegends) + return leagueoflegends + + async def update(self, session, obj: LeagueOfLegends, change: Callable[[str, Any], Awaitable[None]]): + log.debug(f"Getting summoner data: {obj}") + summoner = await ru.asyncify(self._riotwatcher.summoner.by_id, region=self.region(), + encrypted_summoner_id=obj.summoner_id) + await change("profile_icon_id", summoner["profileIconId"]) + await change("summoner_name", summoner["name"]) + await change("puuid", summoner["puuid"]) + await change("summoner_level", summoner["summonerLevel"]) + await change("summoner_id", summoner["id"]) + await change("account_id", summoner["accountId"]) + log.debug(f"Getting leagues data: {obj}") + leagues = await ru.asyncify(self._riotwatcher.league.by_summoner, region=self.region(), + encrypted_summoner_id=obj.summoner_id) + soloq = LeagueLeague() + flexq = LeagueLeague() + twtrq = LeagueLeague() + tftq = LeagueLeague() + for league in leagues: + if league["queueType"] == "RANKED_SOLO_5x5": + soloq = LeagueLeague.from_dict(league) + if league["queueType"] == "RANKED_FLEX_SR": + flexq = LeagueLeague.from_dict(league) + if league["queueType"] == "RANKED_FLEX_TT": + twtrq = LeagueLeague.from_dict(league) + if league["queueType"] == "RANKED_TFT": + tftq = LeagueLeague.from_dict(league) + await change("rank_soloq", soloq) + await change("rank_flexq", flexq) + await change("rank_twtrq", twtrq) + await change("rank_tftq", tftq) + log.debug(f"Getting mastery data: {obj}") mastery = await ru.asyncify(self._riotwatcher.champion_mastery.scores_by_summoner, - region=self.config["Lol"]["region"], - encrypted_summoner_id=lol.summoner_id) - await self._change(lol, "mastery_score", mastery, self._notify) + region=self.region(), + encrypted_summoner_id=obj.summoner_id) + await change("mastery_score", mastery) - async def _updater(self, period: int): - log.info(f"Started updater with {period}s period") - while True: - log.info(f"Updating...") - session = self.alchemy.Session() - log.info("") - lols = session.query(self.alchemy.get(LeagueOfLegends)).all() - for lol in lols: - try: - await self._update(lol) - except Exception as e: - sentry_sdk.capture_exception(e) - log.error(f"Error while updating {lol.user.username}: {e}") - await asyncio.sleep(1) - await ru.asyncify(session.commit) - session.close() - log.info(f"Sleeping for {period}s") - await asyncio.sleep(period) + async def on_increase(self, session, obj: LeagueOfLegends, attribute: str, old: Any, new: Any) -> None: + if attribute in self.queue_names.keys(): + await self.notify(f"📈 [b]{obj.user}[/b] è salito a {new} su League of Legends ({self.queue_names[attribute]})! Congratulazioni!") - @staticmethod - def _display(lol: LeagueOfLegends) -> str: - string = f"ℹ️ [b]{lol.summoner_name}[/b]\n" \ - f"Lv. {lol.summoner_level}\n" \ - f"Mastery score: {lol.mastery_score}\n" \ - f"\n" - if lol.rank_soloq: - string += f"Solo: {lol.rank_soloq}\n" - if lol.rank_flexq: - string += f"Flex: {lol.rank_flexq}\n" - if lol.rank_twtrq: - string += f"3v3: {lol.rank_twtrq}\n" - if lol.rank_tftq: - string += f"TFT: {lol.rank_tftq}\n" - return string + async def on_unchanged(self, session, obj: LeagueOfLegends, attribute: str, old: Any, new: Any) -> None: + pass - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - author = await data.get_author(error_if_none=True) + async def on_decrease(self, session, obj: LeagueOfLegends, attribute: str, old: Any, new: Any) -> None: + if attribute in self.queue_names.keys(): + await self.notify(f"📉 [b]{obj.user}[/b] è sceso a {new} su League of Legends ({self.queue_names[attribute]}).") - name = args.joined() + async def on_first(self, session, obj: LeagueOfLegends, attribute: str, old: None, new: Any) -> None: + if attribute in self.queue_names.keys(): + await self.notify(f"🌟 [b]{obj.user}[/b] si è classificato {new} su League of Legends ({self.queue_names[attribute]}!") - if name: - # Connect a new League of Legends account to Royalnet - log.debug(f"Searching for: {name}") - summoner = self._riotwatcher.summoner.by_name(region=self.config["Lol"]["region"], summoner_name=name) - # Ensure the account isn't already connected to something else - leagueoflegends = await ru.asyncify( - data.session.query(self.alchemy.get(LeagueOfLegends)).filter_by(summoner_id=summoner["id"]).one_or_none) - if leagueoflegends: - raise rc.CommandError(f"L'account {leagueoflegends} è già registrato su Royalnet.") - # Get rank information - log.debug(f"Getting leagues data: {name}") - leagues = self._riotwatcher.league.by_summoner(region=self.config["Lol"]["region"], - encrypted_summoner_id=summoner["id"]) - soloq = LeagueLeague() - flexq = LeagueLeague() - twtrq = LeagueLeague() - tftq = LeagueLeague() - for league in leagues: - if league["queueType"] == "RANKED_SOLO_5x5": - soloq = LeagueLeague.from_dict(league) - if league["queueType"] == "RANKED_FLEX_SR": - flexq = LeagueLeague.from_dict(league) - if league["queueType"] == "RANKED_FLEX_TT": - twtrq = LeagueLeague.from_dict(league) - if league["queueType"] == "RANKED_TFT": - tftq = LeagueLeague.from_dict(league) - # Get mastery score - log.debug(f"Getting mastery data: {name}") - mastery = self._riotwatcher.champion_mastery.scores_by_summoner(region=self.config["Lol"]["region"], - encrypted_summoner_id=summoner["id"]) - # Create database row - leagueoflegends = self.alchemy.get(LeagueOfLegends)( - region=self.config["Lol"]["region"], - user=author, - profile_icon_id=summoner["profileIconId"], - summoner_name=summoner["name"], - puuid=summoner["puuid"], - summoner_level=summoner["summonerLevel"], - summoner_id=summoner["id"], - account_id=summoner["accountId"], - rank_soloq=soloq, - rank_flexq=flexq, - rank_twtrq=twtrq, - rank_tftq=tftq, - mastery_score=mastery - ) - log.debug(f"Saving to the DB: {name}") - data.session.add(leagueoflegends) - await data.session_commit() - await data.reply(f"↔️ Account {leagueoflegends} connesso a {author}!") - await FiorygiTransaction.spawn_fiorygi(data, author, 1, - "aver connesso il proprio account di League of Legends a Royalnet") - else: - # Update and display the League of Legends stats for the current account - if len(author.leagueoflegends) == 0: - raise rc.UserError("Nessun account di League of Legends trovato.") - message = "" - for account in author.leagueoflegends: - try: - await self._update(account) - message += self._display(account) - except riotwatcher.ApiError as e: - message += f"⚠️ [b]{account.summoner_name}[/b]\n" \ - f"{e}" - message += "\n" - await data.session_commit() - await data.reply(message) + async def on_reset(self, session, obj: LeagueOfLegends, attribute: str, old: Any, new: None) -> None: + if attribute in self.queue_names.keys(): + await self.notify(f"⬜️ [b]{obj.user}[/b] non ha più un rank su League of Legends ({self.queue_names[attribute]}).") diff --git a/royalpack/tables/brawlhalla.py b/royalpack/tables/brawlhalla.py index aa8555eb..cbc01466 100644 --- a/royalpack/tables/brawlhalla.py +++ b/royalpack/tables/brawlhalla.py @@ -2,11 +2,11 @@ from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declared_attr import steam.steamid -from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal +from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal, Updatable # noinspection PyAttributeOutsideInit -class Brawlhalla: +class Brawlhalla(Updatable): __tablename__ = "brawlhalla" @declared_attr diff --git a/royalpack/tables/dota.py b/royalpack/tables/dota.py index 8ff9ccdc..0064be95 100644 --- a/royalpack/tables/dota.py +++ b/royalpack/tables/dota.py @@ -2,11 +2,11 @@ from typing import * from sqlalchemy import * from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declared_attr -from ..types import DotaMedal, DotaStars, DotaRank +from ..types import DotaMedal, DotaStars, DotaRank, Updatable import steam.steamid -class Dota: +class Dota(Updatable): __tablename__ = "dota" @declared_attr diff --git a/royalpack/tables/leagueoflegends.py b/royalpack/tables/leagueoflegends.py index 02618748..c778c4a8 100644 --- a/royalpack/tables/leagueoflegends.py +++ b/royalpack/tables/leagueoflegends.py @@ -1,10 +1,10 @@ from sqlalchemy import * from sqlalchemy.orm import relationship, composite from sqlalchemy.ext.declarative import declared_attr -from ..types import LeagueRank, LeagueTier, LeagueLeague +from ..types import LeagueRank, LeagueTier, LeagueLeague, Updatable -class LeagueOfLegends: +class LeagueOfLegends(Updatable): __tablename__ = "leagueoflegends" @declared_attr diff --git a/royalpack/types/__init__.py b/royalpack/types/__init__.py index 88f28a85..ed67a89c 100644 --- a/royalpack/types/__init__.py +++ b/royalpack/types/__init__.py @@ -10,6 +10,7 @@ from .brawlhallatier import BrawlhallaTier from .brawlhallametal import BrawlhallaMetal from .brawlhallarank import BrawlhallaRank from .pollmood import PollMood +from .updatable import Updatable __all__ = [ @@ -26,4 +27,5 @@ __all__ = [ "BrawlhallaRank", "BrawlhallaTier", "PollMood", + "Updatable", ] diff --git a/royalpack/types/updatable.py b/royalpack/types/updatable.py new file mode 100644 index 00000000..db18377e --- /dev/null +++ b/royalpack/types/updatable.py @@ -0,0 +1,2 @@ +class Updatable: + pass diff --git a/royalpack/version.py b/royalpack/version.py index 64511ad8..25edae59 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.11.1" +semantic = "5.12.0" From 950642728b02babdf8e05a4e25a649ad52705ca6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Jul 2020 02:21:58 +0200 Subject: [PATCH 203/227] Fix readme --- README.md | 52 +++++++++++++++----------------- royalpack/commands/brawlhalla.py | 7 +++-- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 3984eb38..2840acf7 100644 --- a/README.md +++ b/README.md @@ -17,33 +17,6 @@ Imgur.token = "1234567890abcde" # A Steam Web API key (https://steamcommunity.com/dev/apikey) Steam.web_api_key = "123567890ABCDEF123567890ABCDEF12" -# Should Royalnet automatically update the Dota ranks of all users? -Dota.updater.enabled = false - -# How many seconds should there be between two Dota updates? -Dota.updater.delay = 86400 - -# Should Royalnet automatically update the League of Legends ranks of all users? -Lol.updater.enabled = false - -# How many seconds should there be between two League of Legends updates? -Lol.updater.delay = 86400 - -# A League of Legends API token (https://developer.riotgames.com/) -Lol.token = "RGAPI-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" - -# The region where your players are located -Lol.region = "euw1" - -# Should Royalnet automatically update the Brawlhalla ranks of all users? -Brawlhalla.updater.enabled = false - -# How many seconds should there be between two League of Legends updates? -Brawlhalla.updater.delay = 86400 - -# A Brawlhalla API key (https://dev.brawlhalla.com/) -Brawlhalla.api_key = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - # The Peertube instance you want to use for new video notifications Peertube.instance_url = "https://pt.steffo.eu" @@ -62,4 +35,29 @@ Play.max_song_duration = 7230 # The Telegram channel where matchmaking messages should be sent in Matchmaking.mm_chat_id = -1001204402796 +[Packs."royalpack"."dota".updater] +enabled = true +period = 86400 +delay = 1 +target = -1001153723135 + +[Packs."royalpack"."brawlhalla"] +token = "1234567890ABCDEFGHJKLMNOPQRST" + +[Packs."royalpack"."brawlhalla".updater] +enabled = true +period = 86400 +delay = 1 +target = -1001153723135 + +[Packs."royalpack"."leagueoflegends"] +token = "RGAPI-AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA" +region = "euw1" + +[Packs."royalpack"."leagueoflegends".updater] +enabled = true +period = 86400 +delay = 1 +target = -1001153723135 + ``` \ No newline at end of file diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index f775aeb7..b09d02a7 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -25,6 +25,9 @@ class BrawlhallaCommand(LinkerCommand): syntax: str = "" + def token(self): + return self.config['Brawlhalla']['token'] + async def get_updatables_of_user(self, session, user: rbt.User) -> List[Brawlhalla]: return user.steam @@ -42,7 +45,7 @@ class BrawlhallaCommand(LinkerCommand): bh: Brawlhalla = obj.brawlhalla if bh is None: log.debug(f"Checking if player has an account...") - async with hcs.get(f"https://api.brawlhalla.com/search?steamid={obj.steamid.as_64}&api_key={self.config['Brawlhalla']['api_key']}") as response: + async with hcs.get(f"https://api.brawlhalla.com/search?steamid={obj.steamid.as_64}&api_key={self.token()}") as response: if response.status != 200: raise ExternalError(f"Brawlhalla API /search returned {response.status}!") j = await response.json() @@ -57,7 +60,7 @@ class BrawlhallaCommand(LinkerCommand): session.add(bh) session.flush() - async with hcs.get(f"https://api.brawlhalla.com/player/{bh.brawlhalla_id}/ranked?api_key={self.config['Brawlhalla']['api_key']}") as response: + async with hcs.get(f"https://api.brawlhalla.com/player/{bh.brawlhalla_id}/ranked?api_key={self.token()}") as response: if response.status != 200: raise ExternalError(f"Brawlhalla API /ranked returned {response.status}!") j = await response.json() From 916dcbad230f5a79c3a785e780018d55a804fbff Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 11 Jul 2020 02:31:11 +0200 Subject: [PATCH 204/227] publish: 5.12.1 --- pyproject.toml | 2 +- royalpack/commands/brawlhalla.py | 2 +- royalpack/version.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b9ee9d51..5f732685 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.12.0" + version = "5.12.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index b09d02a7..1d1219db 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -26,7 +26,7 @@ class BrawlhallaCommand(LinkerCommand): syntax: str = "" def token(self): - return self.config['Brawlhalla']['token'] + return self.config['brawlhalla']['token'] async def get_updatables_of_user(self, session, user: rbt.User) -> List[Brawlhalla]: return user.steam diff --git a/royalpack/version.py b/royalpack/version.py index 25edae59..9b57ff27 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.12.0" +semantic = "5.12.1" From 22d534f3e8511c703d40469f9c43c092511e9370 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 01:38:10 +0200 Subject: [PATCH 205/227] Sort brawlhalla duos by rating --- royalpack/commands/brawlhalla.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index 1d1219db..e2a7e142 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -155,7 +155,7 @@ class BrawlhallaCommand(LinkerCommand): if len(bh.duos) != 0: string.append(f"👥 [b]2v2[/b]") - for duo in bh.duos: + for duo in sorted(bh.duos, key=lambda d: -d.rating_2v2): other = duo.other(bh) string.append(f"Con [b]{other.steam.user}[/b]: [b]{duo.rank_2v2}[/b] ({duo.rating_2v2} MMR)") From 28e98cef310718e08b939d1e899ee8c1c22e0207 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 02:50:00 +0200 Subject: [PATCH 206/227] Fix league and steam commands --- poetry.lock | 58 ++++----- pyproject.toml | 4 +- royalpack/commands/abstract/linker.py | 8 +- royalpack/commands/leagueoflegends.py | 38 ++---- royalpack/commands/steammatch.py | 4 +- royalpack/commands/steampowered.py | 164 ++++++++++++++------------ royalpack/tables/leagueoflegends.py | 101 +--------------- royalpack/version.py | 2 +- 8 files changed, 136 insertions(+), 243 deletions(-) diff --git a/poetry.lock b/poetry.lock index 7bada1e4..e07c448e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -178,7 +178,7 @@ description = "A Python wrapper for the Discord API" name = "discord.py" optional = false python-versions = ">=3.5.3" -version = "1.3.3" +version = "1.3.4" [package.dependencies] aiohttp = ">=3.6.0,<3.7.0" @@ -402,7 +402,7 @@ description = "Alternative regular expression module, to replace re." name = "regex" optional = false python-versions = "*" -version = "2020.6.8" +version = "2020.7.14" [[package]] category = "main" @@ -428,7 +428,7 @@ description = "RiotWatcher is a thin wrapper on top of the Riot Games API for Le name = "riotwatcher" optional = false python-versions = "*" -version = "2.7.1" +version = "3.0.0" [package.dependencies] requests = "*" @@ -712,7 +712,7 @@ python-versions = "*" version = "2020.6.16.1" [metadata] -content-hash = "b0649ccbfdffd5947cbb0d4930182bd3b5edbf39181880db20e7b73ee85c9b02" +content-hash = "ff4adf9a29095096d1daf6aa1decde76d0bd045d614b589d954199d1e512316e" python-versions = "^3.8" [metadata.files] @@ -846,8 +846,8 @@ deprecation = [ {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, ] "discord.py" = [ - {file = "discord.py-1.3.3-py3-none-any.whl", hash = "sha256:406871b06d86c3dc49fba63238519f28628dac946fef8a0e22988ff58ec05580"}, - {file = "discord.py-1.3.3.tar.gz", hash = "sha256:ad00e34c72d2faa8db2157b651d05f3c415d7d05078e7e41dc9e8dc240051beb"}, + {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"}, @@ -1014,35 +1014,35 @@ pytz = [ {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, ] regex = [ - {file = "regex-2020.6.8-cp27-cp27m-win32.whl", hash = "sha256:fbff901c54c22425a5b809b914a3bfaf4b9570eee0e5ce8186ac71eb2025191c"}, - {file = "regex-2020.6.8-cp27-cp27m-win_amd64.whl", hash = "sha256:112e34adf95e45158c597feea65d06a8124898bdeac975c9087fe71b572bd938"}, - {file = "regex-2020.6.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:92d8a043a4241a710c1cf7593f5577fbb832cf6c3a00ff3fc1ff2052aff5dd89"}, - {file = "regex-2020.6.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bae83f2a56ab30d5353b47f9b2a33e4aac4de9401fb582b55c42b132a8ac3868"}, - {file = "regex-2020.6.8-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b2ba0f78b3ef375114856cbdaa30559914d081c416b431f2437f83ce4f8b7f2f"}, - {file = "regex-2020.6.8-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:95fa7726d073c87141f7bbfb04c284901f8328e2d430eeb71b8ffdd5742a5ded"}, - {file = "regex-2020.6.8-cp36-cp36m-win32.whl", hash = "sha256:e3cdc9423808f7e1bb9c2e0bdb1c9dc37b0607b30d646ff6faf0d4e41ee8fee3"}, - {file = "regex-2020.6.8-cp36-cp36m-win_amd64.whl", hash = "sha256:c78e66a922de1c95a208e4ec02e2e5cf0bb83a36ceececc10a72841e53fbf2bd"}, - {file = "regex-2020.6.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:08997a37b221a3e27d68ffb601e45abfb0093d39ee770e4257bd2f5115e8cb0a"}, - {file = "regex-2020.6.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2f6f211633ee8d3f7706953e9d3edc7ce63a1d6aad0be5dcee1ece127eea13ae"}, - {file = "regex-2020.6.8-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:55b4c25cbb3b29f8d5e63aeed27b49fa0f8476b0d4e1b3171d85db891938cc3a"}, - {file = "regex-2020.6.8-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:89cda1a5d3e33ec9e231ece7307afc101b5217523d55ef4dc7fb2abd6de71ba3"}, - {file = "regex-2020.6.8-cp37-cp37m-win32.whl", hash = "sha256:690f858d9a94d903cf5cada62ce069b5d93b313d7d05456dbcd99420856562d9"}, - {file = "regex-2020.6.8-cp37-cp37m-win_amd64.whl", hash = "sha256:1700419d8a18c26ff396b3b06ace315b5f2a6e780dad387e4c48717a12a22c29"}, - {file = "regex-2020.6.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:654cb773b2792e50151f0e22be0f2b6e1c3a04c5328ff1d9d59c0398d37ef610"}, - {file = "regex-2020.6.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:52e1b4bef02f4040b2fd547357a170fc1146e60ab310cdbdd098db86e929b387"}, - {file = "regex-2020.6.8-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:cf59bbf282b627130f5ba68b7fa3abdb96372b24b66bdf72a4920e8153fc7910"}, - {file = "regex-2020.6.8-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:5aaa5928b039ae440d775acea11d01e42ff26e1561c0ffcd3d805750973c6baf"}, - {file = "regex-2020.6.8-cp38-cp38-win32.whl", hash = "sha256:97712e0d0af05febd8ab63d2ef0ab2d0cd9deddf4476f7aa153f76feef4b2754"}, - {file = "regex-2020.6.8-cp38-cp38-win_amd64.whl", hash = "sha256:6ad8663c17db4c5ef438141f99e291c4d4edfeaacc0ce28b5bba2b0bf273d9b5"}, - {file = "regex-2020.6.8.tar.gz", hash = "sha256:e9b64e609d37438f7d6e68c2546d2cb8062f3adb27e6336bc129b51be20773ac"}, + {file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"}, + {file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"}, + {file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"}, + {file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"}, + {file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"}, + {file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"}, + {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"}, + {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"}, + {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"}, ] requests = [ {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, ] riotwatcher = [ - {file = "riotwatcher-2.7.1-py2.py3-none-any.whl", hash = "sha256:3fb03b20f768cea7830d54c6d301a8341c67223625ac8536d26d1c140af3dcb0"}, - {file = "riotwatcher-2.7.1.tar.gz", hash = "sha256:5349271c7e00637b7619491a6070e66603705db60558ea2a690e7016f6e6d9a4"}, + {file = "riotwatcher-3.0.0-py2.py3-none-any.whl", hash = "sha256:f00346692cd05c82450d7cfbdbf94e0de9553179daf612d08d1ffb163a091945"}, + {file = "riotwatcher-3.0.0.tar.gz", hash = "sha256:bf8b8eb7e13c794730c18cd7846513cf22295a068204433117ce4d83a25b0fd2"}, ] royalnet = [ {file = "royalnet-5.10.3-py3-none-any.whl", hash = "sha256:1042a7383e26dbc76d03289d73f3c1b4d167cf860e272397b88ea54db0af513d"}, diff --git a/pyproject.toml b/pyproject.toml index 5f732685..ec7b0d96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.12.1" + version = "5.12.2" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -20,7 +20,7 @@ [tool.poetry.dependencies] python = "^3.8" - riotwatcher = "^2.7.1" + riotwatcher = "^3.0.0" royalspells = "^3.2" steam = "*" diff --git a/royalpack/commands/abstract/linker.py b/royalpack/commands/abstract/linker.py index 48963dd1..bdebb354 100644 --- a/royalpack/commands/abstract/linker.py +++ b/royalpack/commands/abstract/linker.py @@ -19,9 +19,7 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): self.updater_task = None if self.enabled(): - # Run updaters only on Telegram - if self.interface.name == "telegram": - self.updater_task = self.loop.create_task(self.run_updater()) + 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) @@ -139,7 +137,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"] + return self.config[self.name]["updater"]["enabled"] and self.interface.name == "telegram" def period(self) -> int: """The time between two updater cycles.""" @@ -147,7 +145,7 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): def delay(self) -> int: """The time between two object updates.""" - return self.config[self.name]["updater"]["rate"] + return self.config[self.name]["updater"]["delay"] def target(self) -> int: """The id of the Telegram chat where notifications should be sent.""" diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 55b4b574..cfb9aa7c 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -27,15 +27,15 @@ class LeagueoflegendsCommand(LinkerCommand): queue_names = { "rank_soloq": "Solo/Duo", "rank_flexq": "Flex", - "rank_twtrq": "3v3", - "rank_tftq": "TFT" } def __init__(self, interface: rc.CommandInterface): super().__init__(interface) - self._riotwatcher: Optional[riotwatcher.RiotWatcher] = None - if self.interface.name == "telegram" and self.enabled(): - self._riotwatcher = riotwatcher.RiotWatcher(api_key=self.token()) + self._lolwatcher: Optional[riotwatcher.RiotWatcher] = None + self._tftwatcher: Optional[riotwatcher.RiotWatcher] = None + if self.enabled(): + self._lolwatcher = riotwatcher.LolWatcher(api_key=self.token()) + self._tftwatcher = riotwatcher.TftWatcher(api_key=self.token()) def token(self): return self.config["leagueoflegends"]["token"] @@ -52,10 +52,6 @@ class LeagueoflegendsCommand(LinkerCommand): string += f"Solo: {obj.rank_soloq}\n" if obj.rank_flexq: string += f"Flex: {obj.rank_flexq}\n" - if obj.rank_twtrq: - string += f"3v3: {obj.rank_twtrq}\n" - if obj.rank_tftq: - string += f"TFT: {obj.rank_tftq}\n" return string async def get_updatables_of_user(self, session, user: rbt.User) -> List[LeagueOfLegends]: @@ -69,7 +65,7 @@ class LeagueoflegendsCommand(LinkerCommand): # Connect a new League of Legends account to Royalnet log.debug(f"Searching for: {name}") - summoner = self._riotwatcher.summoner.by_name(region=self.region(), summoner_name=name) + summoner = self._lolwatcher.summoner.by_name(region=self.region(), summoner_name=name) # Ensure the account isn't already connected to something else leagueoflegends = await ru.asyncify( session.query(self.alchemy.get(LeagueOfLegends)).filter_by(summoner_id=summoner["id"]).one_or_none) @@ -77,8 +73,8 @@ class LeagueoflegendsCommand(LinkerCommand): raise rc.CommandError(f"L'account {leagueoflegends} è già registrato su Royalnet.") # Get rank information log.debug(f"Getting leagues data: {name}") - leagues = self._riotwatcher.league.by_summoner(region=self.region(), - encrypted_summoner_id=summoner["id"]) + leagues = self._lolwatcher.league.by_summoner(region=self.region(), + encrypted_summoner_id=summoner["id"]) soloq = LeagueLeague() flexq = LeagueLeague() twtrq = LeagueLeague() @@ -94,8 +90,8 @@ class LeagueoflegendsCommand(LinkerCommand): tftq = LeagueLeague.from_dict(league) # Get mastery score log.debug(f"Getting mastery data: {name}") - mastery = self._riotwatcher.champion_mastery.scores_by_summoner(region=self.region(), - encrypted_summoner_id=summoner["id"]) + mastery = self._lolwatcher.champion_mastery.scores_by_summoner(region=self.region(), + encrypted_summoner_id=summoner["id"]) # Create database row leagueoflegends = self.alchemy.get(LeagueOfLegends)( region=self.region(), @@ -117,7 +113,7 @@ class LeagueoflegendsCommand(LinkerCommand): async def update(self, session, obj: LeagueOfLegends, change: Callable[[str, Any], Awaitable[None]]): log.debug(f"Getting summoner data: {obj}") - summoner = await ru.asyncify(self._riotwatcher.summoner.by_id, region=self.region(), + summoner = await ru.asyncify(self._lolwatcher.summoner.by_id, region=self.region(), encrypted_summoner_id=obj.summoner_id) await change("profile_icon_id", summoner["profileIconId"]) await change("summoner_name", summoner["name"]) @@ -126,27 +122,19 @@ class LeagueoflegendsCommand(LinkerCommand): await change("summoner_id", summoner["id"]) await change("account_id", summoner["accountId"]) log.debug(f"Getting leagues data: {obj}") - leagues = await ru.asyncify(self._riotwatcher.league.by_summoner, region=self.region(), + leagues = await ru.asyncify(self._lolwatcher.league.by_summoner, region=self.region(), encrypted_summoner_id=obj.summoner_id) soloq = LeagueLeague() flexq = LeagueLeague() - twtrq = LeagueLeague() - tftq = LeagueLeague() for league in leagues: if league["queueType"] == "RANKED_SOLO_5x5": soloq = LeagueLeague.from_dict(league) if league["queueType"] == "RANKED_FLEX_SR": flexq = LeagueLeague.from_dict(league) - if league["queueType"] == "RANKED_FLEX_TT": - twtrq = LeagueLeague.from_dict(league) - if league["queueType"] == "RANKED_TFT": - tftq = LeagueLeague.from_dict(league) await change("rank_soloq", soloq) await change("rank_flexq", flexq) - await change("rank_twtrq", twtrq) - await change("rank_tftq", tftq) log.debug(f"Getting mastery data: {obj}") - mastery = await ru.asyncify(self._riotwatcher.champion_mastery.scores_by_summoner, + mastery = await ru.asyncify(self._lolwatcher.champion_mastery.scores_by_summoner, region=self.region(), encrypted_summoner_id=obj.summoner_id) await change("mastery_score", mastery) diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index f88c0993..90cb2171 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -55,9 +55,7 @@ class SteammatchCommand(rc.Command): def __init__(self, interface: rc.CommandInterface): super().__init__(interface) - if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: - raise rc.ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") - self._api = steam.webapi.WebAPI(self.config["Steam"]["web_api_key"]) + self._api = steam.webapi.WebAPI(self.config["steampowered"]["token"]) async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: users = [] diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 05c4c3be..049aea32 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -4,103 +4,111 @@ import steam.webapi import datetime import royalnet.commands as rc import royalnet.utils as ru +import logging +from royalnet.backpack import tables as rbt + +from .abstract.linker import LinkerCommand from ..tables import Steam, FiorygiTransaction +from ..types import Updatable + +log = logging.getLogger(__name__) -class SteampoweredCommand(rc.Command): +class SteampoweredCommand(LinkerCommand): name: str = "steampowered" - description: str = "Connetti il tuo account di Steam!" + description: str = "Connetti e visualizza informazioni sul tuo account di Steam!" - syntax: str = "{profile_url}" + syntax: str = "{url_profilo}" def __init__(self, interface: rc.CommandInterface): super().__init__(interface) - if "Steam" not in self.config or "web_api_key" not in self.config["Steam"]: - raise rc.ConfigurationError("[c]Steam.web_api_key[/c] config option is missing!") - self._api = steam.webapi.WebAPI(self.config["Steam"]["web_api_key"]) + self._api = steam.webapi.WebAPI(self.token()) - @staticmethod - def _display(account: Steam): - string = f"ℹ️ [url={account.profile_url}]{account.persona_name}[/url]\n" \ - f"[b]Level {account.account_level}[/b]\n" \ - f"\n" \ - f"Owned games: [b]{account.owned_games_count}[/b]\n" \ - f"Most played 2 weeks: [url=https://store.steampowered.com/app/{account.most_played_game_2weeks}]{account.most_played_game_2weeks}[/url]\n" \ - f"Most played forever: [url=https://store.steampowered.com/app/{account.most_played_game_forever}]{account.most_played_game_forever}[/url]\n" \ - f"\n" \ - f"SteamID: [c]{account.steamid.as_32}[/c]\n" \ - f"SteamID2: [c]{account.steamid.as_steam2}[/c]\n" \ - f"SteamID3: [c]{account.steamid.as_steam3}[/c]\n" \ - f"SteamID64: [c]{account.steamid.as_64}[/c]\n" \ - f"\n" \ - f"Created on: [b]{account.account_creation_date}[/b]\n" - return string + def token(self): + return self.config["steampowered"]["token"] - async def _call(self, method, *args, **kwargs): - try: - return await ru.asyncify(method, *args, **kwargs) - except Exception as e: - raise rc.ExternalError("\n".join(e.args).replace(self.config["Steam"]["web_api_key"], "HIDDEN")) + async def get_updatables_of_user(self, session, user: rbt.User) -> List[Steam]: + return user.steam - async def _update(self, account: Steam): - # noinspection PyProtectedMember - response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=account._steamid) + async def get_updatables(self, session) -> List[Steam]: + return await ru.asyncify(session.query(self.alchemy.get(Steam)).all) + + async def create(self, session, user: rbt.User, args) -> Steam: + url = args.joined() + steamid64 = await self._call(steam.steamid.steam64_from_url, url) + if steamid64 is None: + raise rc.InvalidInputError("Quel link non è associato ad alcun account Steam.") + response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid64) r = response["response"]["players"][0] - account.persona_name = r["personaname"] - account.profile_url = r["profileurl"] - account.avatar = r["avatar"] - account.primary_clan_id = r["primaryclanid"] - account.account_creation_date = datetime.datetime.fromtimestamp(r["timecreated"]) + steam_account = self.alchemy.get(Steam)( + user=user, + _steamid=int(steamid64), + persona_name=r["personaname"], + profile_url=r["profileurl"], + avatar=r["avatarfull"], + primary_clan_id=r["primaryclanid"], + account_creation_date=datetime.datetime.fromtimestamp(r["timecreated"]) + ) + session.add(steam_account) + await ru.asyncify(session.commit) + return steam_account - # noinspection PyProtectedMember - response = await self._call(self._api.IPlayerService.GetSteamLevel_v1, steamid=account._steamid) - account.account_level = response["response"]["player_level"] - - # noinspection PyProtectedMember + async def update(self, session, obj: Steam, change: Callable[[str, Any], Awaitable[None]]): + response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=obj.steamid.as_64) + r = response["response"]["players"][0] + obj.persona_name = r["personaname"] + obj.profile_url = r["profileurl"] + obj.avatar = r["avatar"] + obj.primary_clan_id = r["primaryclanid"] + obj.account_creation_date = datetime.datetime.fromtimestamp(r["timecreated"]) + response = await self._call(self._api.IPlayerService.GetSteamLevel_v1, steamid=obj.steamid.as_64) + obj.account_level = response["response"]["player_level"] response = await self._call(self._api.IPlayerService.GetOwnedGames_v1, - steamid=account._steamid, + steamid=obj.steamid.as_64, include_appinfo=False, include_played_free_games=True, include_free_sub=False, appids_filter=None) - account.owned_games_count = response["response"]["game_count"] + obj.owned_games_count = response["response"]["game_count"] if response["response"]["game_count"] >= 0: - account.most_played_game_2weeks = sorted(response["response"]["games"], key=lambda g: -g.get("playtime_2weeks", 0))[0]["appid"] - account.most_played_game_forever = sorted(response["response"]["games"], key=lambda g: -g.get("playtime_forever", 0))[0]["appid"] + obj.most_played_game_2weeks = sorted(response["response"]["games"], key=lambda g: -g.get("playtime_2weeks", 0))[0]["appid"] + obj.most_played_game_forever = sorted(response["response"]["games"], key=lambda g: -g.get("playtime_forever", 0))[0]["appid"] - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - author = await data.get_author() - if len(args) > 0: - url = args.joined() - steamid64 = await self._call(steam.steamid.steam64_from_url, url) - if steamid64 is None: - raise rc.InvalidInputError("Quel link non è associato ad alcun account Steam.") - response = await self._call(self._api.ISteamUser.GetPlayerSummaries_v2, steamids=steamid64) - r = response["response"]["players"][0] - steam_account = self.alchemy.get(Steam)( - user=author, - _steamid=int(steamid64), - persona_name=r["personaname"], - profile_url=r["profileurl"], - avatar=r["avatarfull"], - primary_clan_id=r["primaryclanid"], - account_creation_date=datetime.datetime.fromtimestamp(r["timecreated"]) - ) - data.session.add(steam_account) - await data.session_commit() - await data.reply(f"↔️ Account {steam_account} connesso a {author}!") - await FiorygiTransaction.spawn_fiorygi(data, author, 1, - "aver connesso il proprio account di Steam a Royalnet") - else: - # Update and display the Steam info for the current account - if len(author.steam) == 0: - raise rc.UserError("Nessun account di Steam trovato.") - message = "" - for account in author.steam: - await self._update(account) - message += self._display(account) - message += "\n" - await data.session_commit() - await data.reply(message) + async def on_increase(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + pass + + async def on_unchanged(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + pass + + async def on_decrease(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + pass + + async def on_first(self, session, obj: Updatable, attribute: str, old: None, new: Any) -> None: + pass + + async def on_reset(self, session, obj: Updatable, attribute: str, old: Any, new: None) -> None: + pass + + def describe(self, obj: Steam): + return f"ℹ️ [url={obj.profile_url}]{obj.persona_name}[/url]\n" \ + f"[b]Level {obj.account_level}[/b]\n" \ + f"\n" \ + f"Owned games: [b]{obj.owned_games_count}[/b]\n" \ + f"Most played 2 weeks: [url=https://store.steampowered.com/app/{obj.most_played_game_2weeks}]{obj.most_played_game_2weeks}[/url]\n" \ + f"Most played forever: [url=https://store.steampowered.com/app/{obj.most_played_game_forever}]{obj.most_played_game_forever}[/url]\n" \ + f"\n" \ + f"SteamID32: [c]{obj.steamid.as_32}[/c]\n" \ + f"SteamID64: [c]{obj.steamid.as_64}[/c]\n" \ + f"SteamID2: [c]{obj.steamid.as_steam2}[/c]\n" \ + f"SteamID3: [c]{obj.steamid.as_steam3}[/c]\n" \ + f"\n" \ + f"Created on: [b]{obj.account_creation_date}[/b]\n" + + async def _call(self, method, *args, **kwargs): + log.debug(f"Calling {method}") + try: + return await ru.asyncify(method, *args, **kwargs) + except Exception as e: + raise rc.ExternalError("\n".join(e.args).replace(self.token(), "HIDDEN")) diff --git a/royalpack/tables/leagueoflegends.py b/royalpack/tables/leagueoflegends.py index c778c4a8..3871869d 100644 --- a/royalpack/tables/leagueoflegends.py +++ b/royalpack/tables/leagueoflegends.py @@ -147,104 +147,6 @@ class LeagueOfLegends(Updatable): self.rank_flexq_fresh_blood, self.rank_flexq_veteran) - @declared_attr - def rank_twtrq_tier(self): - return Column(Enum(LeagueTier)) - - @declared_attr - def rank_twtrq_rank(self): - return Column(Enum(LeagueRank)) - - @declared_attr - def rank_twtrq_points(self): - return Column(Integer) - - @declared_attr - def rank_twtrq_wins(self): - return Column(Integer) - - @declared_attr - def rank_twtrq_losses(self): - return Column(Integer) - - @declared_attr - def rank_twtrq_inactive(self): - return Column(Boolean) - - @declared_attr - def rank_twtrq_hot_streak(self): - return Column(Boolean) - - @declared_attr - def rank_twtrq_fresh_blood(self): - return Column(Boolean) - - @declared_attr - def rank_twtrq_veteran(self): - return Column(Boolean) - - @declared_attr - def rank_twtrq(self): - return composite(LeagueLeague, - self.rank_twtrq_tier, - self.rank_twtrq_rank, - self.rank_twtrq_points, - self.rank_twtrq_wins, - self.rank_twtrq_losses, - self.rank_twtrq_inactive, - self.rank_twtrq_hot_streak, - self.rank_twtrq_fresh_blood, - self.rank_twtrq_veteran) - - @declared_attr - def rank_tftq_tier(self): - return Column(Enum(LeagueTier)) - - @declared_attr - def rank_tftq_rank(self): - return Column(Enum(LeagueRank)) - - @declared_attr - def rank_tftq_points(self): - return Column(Integer) - - @declared_attr - def rank_tftq_wins(self): - return Column(Integer) - - @declared_attr - def rank_tftq_losses(self): - return Column(Integer) - - @declared_attr - def rank_tftq_inactive(self): - return Column(Boolean) - - @declared_attr - def rank_tftq_hot_streak(self): - return Column(Boolean) - - @declared_attr - def rank_tftq_fresh_blood(self): - return Column(Boolean) - - @declared_attr - def rank_tftq_veteran(self): - return Column(Boolean) - - @declared_attr - def rank_tftq(self): - return composite(LeagueLeague, - self.rank_tftq_tier, - self.rank_tftq_rank, - self.rank_tftq_points, - self.rank_tftq_wins, - self.rank_tftq_losses, - self.rank_tftq_inactive, - self.rank_tftq_hot_streak, - self.rank_tftq_fresh_blood, - self.rank_tftq_veteran) - @declared_attr def mastery_score(self): return Column(Integer, nullable=False, default=0) @@ -259,9 +161,8 @@ class LeagueOfLegends(Updatable): "summoner_id": self.summoner_id, "account_id": self.account_id, "soloq": self.rank_soloq.json() if self.rank_soloq is not None else None, - "twtrq": self.rank_twtrq.json() if self.rank_twtrq is not None else None, "flexq": self.rank_flexq.json() if self.rank_flexq is not None else None, - "tftq": self.rank_tftq.json() if self.rank_tftq is not None else None, + "mastery_score": self.mastery_score, } def __repr__(self): diff --git a/royalpack/version.py b/royalpack/version.py index 9b57ff27..160035fb 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1 @@ -semantic = "5.12.1" +semantic = "5.12.2" From 4948302324f24dd48143620477329c4314a08223 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 03:11:28 +0200 Subject: [PATCH 207/227] Add commands list --- royalpack/commands/help.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/royalpack/commands/help.py b/royalpack/commands/help.py index 0b5a3675..ca129d18 100644 --- a/royalpack/commands/help.py +++ b/royalpack/commands/help.py @@ -11,17 +11,27 @@ class HelpCommand(rc.Command): syntax: str = "{comando}" async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - name: str = args[0].lstrip(self.interface.prefix) + if len(args) == 0: + message = [ + "ℹ️ Comandi disponibili:" + ] - try: - command: rc.Command = self.serf.commands[f"{self.interface.prefix}{name}"] - except KeyError: - raise rc.InvalidInputError("Il comando richiesto non esiste.") + 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 = [ - f"[c]{self.interface.prefix}{command.name} {command.syntax}[/c]", - "", - f"{command.description}" - ] + await data.reply("\n".join(message)) + else: + name: str = args[0].lstrip(self.interface.prefix) - await data.reply("\n".join(message)) + try: + command: rc.Command = self.serf.commands[f"{self.interface.prefix}{name}"] + except KeyError: + raise rc.InvalidInputError("Il comando richiesto non esiste.") + + message = [ + f"ℹ️ [c]{self.interface.prefix}{command.name} {command.syntax}[/c]", + "", + f"{command.description}" + ] + + await data.reply("\n".join(message)) From e6f5170bd7ec550a29b46d3e4de763f210aecdcb Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 16:24:16 +0200 Subject: [PATCH 208/227] Add fortune command --- royalpack/commands/__init__.py | 180 +++++++++++++++++---------------- royalpack/commands/fortune.py | 44 ++++++++ 2 files changed, 135 insertions(+), 89 deletions(-) create mode 100644 royalpack/commands/fortune.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 64057b96..cc63c0eb 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -1,133 +1,135 @@ # Imports go here! +from .ahnonlosoio import AhnonlosoioCommand +from .brawlhalla import BrawlhallaCommand +from .cat import CatCommand from .ciaoruozi import CiaoruoziCommand from .color import ColorCommand from .cv import CvCommand +from .cvstats import CvstatsCommand from .diario import DiarioCommand -from .rage import RageCommand -from .reminder import ReminderCommand -from .ship import ShipCommand -from .smecds import SmecdsCommand -from .videochannel import VideochannelCommand -from .pause import PauseCommand -from .play import PlayCommand -from .queue import QueueCommand -from .skip import SkipCommand -from .summon import SummonCommand -from .youtube import YoutubeCommand -from .soundcloud import SoundcloudCommand -from .emojify import EmojifyCommand -from .leagueoflegends import LeagueoflegendsCommand from .diarioquote import DiarioquoteCommand -from .peertubeupdates import PeertubeUpdatesCommand -from .googlevideo import GooglevideoCommand -from .yahoovideo import YahoovideoCommand -from .userinfo import UserinfoCommand -from .spell import SpellCommand -from .ahnonlosoio import AhnonlosoioCommand +from .diarioshuffle import DiarioshuffleCommand +from .dota import DotaCommand from .eat import EatCommand -from .pmots import PmotsCommand -from .peertube import PeertubeCommand -from .funkwhale import FunkwhaleCommand +from .elevatormusic import ElevatormusicCommand +from .emojify import EmojifyCommand from .eval import EvalCommand from .exec import ExecCommand -from .trivia import TriviaCommand -from .steampowered import SteampoweredCommand -from .steammatch import SteammatchCommand -from .dota import DotaCommand -from .magickfiorygi import MagickfiorygiCommand -from .brawlhalla import BrawlhallaCommand -from .diarioshuffle import DiarioshuffleCommand +from .fortune import FortuneCommand +from .funkwhale import FunkwhaleCommand +from .funkwhalealbum import FunkwhalealbumCommand from .funkwhaleplaylist import FunkwhaleplaylistCommand -from .voicestatus import VoicestatusCommand -from .playmode import PlaymodeCommand -from .lazyplay import LazyplayCommand +from .givefiorygi import GivefiorygiCommand +from .givetreasure import GivetreasureCommand +from .googlevideo import GooglevideoCommand +from .help import HelpCommand from .lazyfunkwhale import LazyfunkwhaleCommand +from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand from .lazyfunkwhaleplaylist import LazyfunkwhaleplaylistCommand from .lazygooglevideo import LazygooglevideoCommand from .lazypeertube import LazypeertubeCommand +from .lazyplay import LazyplayCommand from .lazysoundcloud import LazysoundcloudCommand from .lazyyahoovideo import LazyyahoovideoCommand from .lazyyoutube import LazyyoutubeCommand -from .funkwhalealbum import FunkwhalealbumCommand -from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand -from .matchmaking import MatchmakingCommand -from .cvstats import CvstatsCommand -from .elevatormusic import ElevatormusicCommand -from .royalpackversion import RoyalpackCommand -from .givefiorygi import GivefiorygiCommand -from .help import HelpCommand -from .pug import PugCommand +from .leagueoflegends import LeagueoflegendsCommand +from .magickfiorygi import MagickfiorygiCommand from .magicktreasure import MagicktreasureCommand -from .treasure import TreasureCommand -from .givetreasure import GivetreasureCommand -from .cat import CatCommand +from .matchmaking import MatchmakingCommand +from .pause import PauseCommand +from .peertube import PeertubeCommand +from .peertubeupdates import PeertubeUpdatesCommand from .ping import PingCommand +from .play import PlayCommand +from .playmode import PlaymodeCommand +from .pmots import PmotsCommand +from .pug import PugCommand +from .queue import QueueCommand +from .rage import RageCommand +from .reminder import ReminderCommand +from .royalpackversion import RoyalpackCommand +from .ship import ShipCommand +from .skip import SkipCommand +from .smecds import SmecdsCommand +from .soundcloud import SoundcloudCommand +from .spell import SpellCommand +from .steammatch import SteammatchCommand +from .steampowered import SteampoweredCommand +from .summon import SummonCommand +from .treasure import TreasureCommand +from .trivia import TriviaCommand +from .userinfo import UserinfoCommand +from .videochannel import VideochannelCommand +from .voicestatus import VoicestatusCommand +from .yahoovideo import YahoovideoCommand +from .youtube import YoutubeCommand # Enter the commands of your Pack here! available_commands = [ + AhnonlosoioCommand, + BrawlhallaCommand, + CatCommand, CiaoruoziCommand, ColorCommand, CvCommand, + CvstatsCommand, DiarioCommand, - RageCommand, - ReminderCommand, - ShipCommand, - SmecdsCommand, - VideochannelCommand, - PauseCommand, - PlayCommand, - QueueCommand, - SkipCommand, - SummonCommand, - YoutubeCommand, - SoundcloudCommand, - EmojifyCommand, - LeagueoflegendsCommand, DiarioquoteCommand, - PeertubeUpdatesCommand, - GooglevideoCommand, - YahoovideoCommand, - UserinfoCommand, - SpellCommand, - AhnonlosoioCommand, + DiarioshuffleCommand, + DotaCommand, EatCommand, - PmotsCommand, - PeertubeCommand, + ElevatormusicCommand, + EmojifyCommand, EvalCommand, ExecCommand, + FortuneCommand, + FunkwhalealbumCommand, FunkwhaleCommand, - TriviaCommand, - SteampoweredCommand, - SteammatchCommand, - DotaCommand, - MagickfiorygiCommand, - BrawlhallaCommand, - DiarioshuffleCommand, FunkwhaleplaylistCommand, - VoicestatusCommand, - PlaymodeCommand, - LazyplayCommand, + GivefiorygiCommand, + GivetreasureCommand, + GooglevideoCommand, + HelpCommand, + LazyfunkwhalealbumCommand, LazyfunkwhaleCommand, LazyfunkwhaleplaylistCommand, LazygooglevideoCommand, LazypeertubeCommand, + LazyplayCommand, LazysoundcloudCommand, LazyyahoovideoCommand, LazyyoutubeCommand, - FunkwhalealbumCommand, - LazyfunkwhalealbumCommand, - MatchmakingCommand, - CvstatsCommand, - ElevatormusicCommand, - RoyalpackCommand, - GivefiorygiCommand, - HelpCommand, - PugCommand, + LeagueoflegendsCommand, + MagickfiorygiCommand, MagicktreasureCommand, - TreasureCommand, - GivetreasureCommand, - CatCommand, + MatchmakingCommand, + PauseCommand, + PeertubeCommand, + PeertubeUpdatesCommand, PingCommand, + PlayCommand, + PlaymodeCommand, + PmotsCommand, + PugCommand, + QueueCommand, + RageCommand, + ReminderCommand, + RoyalpackCommand, + ShipCommand, + SkipCommand, + SmecdsCommand, + SoundcloudCommand, + SpellCommand, + SteammatchCommand, + SteampoweredCommand, + SummonCommand, + TreasureCommand, + TriviaCommand, + UserinfoCommand, + VideochannelCommand, + VoicestatusCommand, + YahoovideoCommand, + YoutubeCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/fortune.py b/royalpack/commands/fortune.py new file mode 100644 index 00000000..8d446321 --- /dev/null +++ b/royalpack/commands/fortune.py @@ -0,0 +1,44 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import random +import datetime + + +class FortuneCommand(rc.Command): + name: str = "fortune" + + description: str = "Quanto sarai fortunato oggi?" + + syntax: str = "" + + _fortunes = [ + "😄 Oggi sarà una fantastica giornata!", + "😌 Oggi sarà una giornata molto chill e rilassante.", + "💰 Oggi sui tuoi alberi cresceranno più Stelline!", + "🍎 Oggi un unicorno ti lascerà la sua Blessed Apple!", + "📈 Oggi il tuo team in ranked sarà più amichevole e competente del solito!", + "🏝 Oggi potrai raggiungere l'Isola Miraggio!", + "🐱 Oggi vedrai più gatti del solito su Internet!", + "🐶 Oggi vedrai più cani del solito su Internet!", + "🐦 Oggi vedrai più uccelli del solito su Internet!", + "🐌 Oggi incontrerai una chiocciola sperduta!", + "🎁 Oggi i dispenser di regali in centro funzioneranno senza problemi!", + "🥕 Oggi il tuo raccolto avrà qualità Iridium Star!", + "🔴 Oggi troverai più oggetti di rarità rossa del solito!", + "✨ Oggi farai molti più multicast!", + "♦️ Oggi troverai una Leggendaria Dorata!", + "⭐️ Oggi la stella della RYG ti sembrerà un pochino più dritta!", + "💎 Oggi i tuoi avversari non riusciranno a deflettere i tuoi Emerald Splash!", + ] + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + author = await data.get_author() + today = datetime.date.today() + + h = author.uid * hash(today) + + r = random.Random(x=h) + + message = r.sample(self._fortunes, 1)[0] + await data.reply(message) From d70477ec6dd5cbaecb35089d3a7bf4dedb161e7d Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 16:29:43 +0200 Subject: [PATCH 209/227] Migrate /pug to /dog --- royalpack/commands/__init__.py | 4 ++-- royalpack/commands/{pug.py => dog.py} | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) rename royalpack/commands/{pug.py => dog.py} (64%) diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index cc63c0eb..9ce8b05e 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -43,7 +43,7 @@ from .ping import PingCommand from .play import PlayCommand from .playmode import PlaymodeCommand from .pmots import PmotsCommand -from .pug import PugCommand +from .dog import DogCommand from .queue import QueueCommand from .rage import RageCommand from .reminder import ReminderCommand @@ -110,7 +110,7 @@ available_commands = [ PlayCommand, PlaymodeCommand, PmotsCommand, - PugCommand, + DogCommand, QueueCommand, RageCommand, ReminderCommand, diff --git a/royalpack/commands/pug.py b/royalpack/commands/dog.py similarity index 64% rename from royalpack/commands/pug.py rename to royalpack/commands/dog.py index 6846212b..cd80ff52 100644 --- a/royalpack/commands/pug.py +++ b/royalpack/commands/dog.py @@ -4,18 +4,22 @@ import aiohttp import io -class PugCommand(rc.Command): - name: str = "pug" +class DogCommand(rc.Command): + name: str = "dog" - description: str = "Invia un carlino casuale in chat." + description: str = "Invia un cane della razza specificata in chat." - syntax: str = "" - - aliases = ["carlino", "carlo", "mallllco"] + syntax: str = "[razza]" async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + breed = args.joined() + if breed: + url = f"https://dog.ceo/api/breed/{breed}/images/random" + else: + url = f"https://dog.ceo/api/breeds/image/random" + async with aiohttp.ClientSession() as session: - async with session.get("https://dog.ceo/api/breed/pug/images/random") as response: + async with session.get(url) as response: if response.status >= 400: raise rc.ExternalError(f"Request returned {response.status}") result = await response.json() From 0326b48e33b5b5584796659754578169812167ff Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 16:32:02 +0200 Subject: [PATCH 210/227] Get version automatically --- royalpack/version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/royalpack/version.py b/royalpack/version.py index 160035fb..4430300e 100644 --- a/royalpack/version.py +++ b/royalpack/version.py @@ -1 +1,3 @@ -semantic = "5.12.2" +import pkg_resources + +semantic = pkg_resources.get_distribution("royalpack").version From 3a9e0b2597a9341c751e29b8ed95731efd41e1fd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 16:32:33 +0200 Subject: [PATCH 211/227] publish: 5.13.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ec7b0d96..3bb96ae2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.12.2" + version = "5.13.0" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" From c1b6fa968483b07218a1d14d6dafadb052138a50 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Jul 2020 16:53:14 +0200 Subject: [PATCH 212/227] Check if the breed exists --- royalpack/commands/dog.py | 153 +++++++++++++++++++++++++++++++++++++- 1 file changed, 151 insertions(+), 2 deletions(-) diff --git a/royalpack/commands/dog.py b/royalpack/commands/dog.py index cd80ff52..2179925e 100644 --- a/royalpack/commands/dog.py +++ b/royalpack/commands/dog.py @@ -9,12 +9,161 @@ class DogCommand(rc.Command): description: str = "Invia un cane della razza specificata in chat." - syntax: str = "[razza]" + syntax: str = "[razza|list]" + + _breeds = [ + "affenpinscher", + "african", + "airedale", + "akita", + "appenzeller", + "australian-shepherd", + "basenji", + "beagle", + "bluetick", + "borzoi", + "bouvier", + "boxer", + "brabancon", + "briard", + "buhund-norwegian", + "bulldog-boston", + "bulldog-english", + "bulldog-french", + "bullterrier-staffordshire", + "cairn", + "cattledog-australian", + "chihuahua", + "chow", + "clumber", + "cockapoo", + "collie-border", + "coonhound", + "corgi-cardigan", + "cotondetulear", + "dachshund", + "dalmatian", + "dane-great", + "deerhound-scottish", + "dhole", + "dingo", + "doberman", + "elkhound-norwegian", + "entlebucher", + "eskimo", + "finnish-lapphund", + "frise-bichon", + "germanshepherd", + "greyhound-italian", + "groenendael", + "havanese", + "hound-afghan", + "hound-basset", + "hound-blood", + "hound-english", + "hound-ibizan", + "hound-plott", + "hound-walker", + "husky", + "keeshond", + "kelpie", + "komondor", + "kuvasz", + "labrador", + "leonberg", + "lhasa", + "malamute", + "malinois", + "maltese", + "mastiff-bull", + "mastiff-english", + "mastiff-tibetan", + "mexicanhairless", + "mix", + "mountain-bernese", + "mountain-swiss", + "newfoundland", + "otterhound", + "ovcharka-caucasian", + "papillon", + "pekinese", + "pembroke", + "pinscher-miniature", + "pitbull", + "pointer-german", + "pointer-germanlonghair", + "pomeranian", + "poodle-miniature", + "poodle-standard", + "poodle-toy", + "pug", + "puggle", + "pyrenees", + "redbone", + "retriever-chesapeake", + "retriever-curly", + "retriever-flatcoated", + "retriever-golden", + "ridgeback-rhodesian", + "rottweiler", + "saluki", + "samoyed", + "schipperke", + "schnauzer-giant", + "schnauzer-miniature", + "setter-english", + "setter-gordon", + "setter-irish", + "sheepdog-english", + "sheepdog-shetland", + "shiba", + "shihtzu", + "spaniel-blenheim", + "spaniel-brittany", + "spaniel-cocker", + "spaniel-irish", + "spaniel-japanese", + "spaniel-sussex", + "spaniel-welsh", + "springer-english", + "stbernard", + "terrier-american", + "terrier-australian", + "terrier-bedlington", + "terrier-border", + "terrier-dandie", + "terrier-fox", + "terrier-irish", + "terrier-kerryblue", + "terrier-lakeland", + "terrier-norfolk", + "terrier-norwich", + "terrier-patterdale", + "terrier-russell", + "terrier-scottish", + "terrier-sealyham", + "terrier-silky", + "terrier-tibetan", + "terrier-toy", + "terrier-westhighland", + "terrier-wheaten", + "terrier-yorkshire", + "vizsla", + "waterdog-spanish", + "weimaraner", + "whippet", + "wolfhound-irish", + ] async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: breed = args.joined() if breed: - url = f"https://dog.ceo/api/breed/{breed}/images/random" + if breed == "list": + await data.reply("\n".join(["ℹ️ Razze disponibili:", [f"[c]{breed}[/c]" for breed in self._breeds]])) + if breed in self._breeds: + url = f"https://dog.ceo/api/breed/{breed}/images/random" + else: + raise rc.InvalidInputError("Questa razza non è disponibile.\n") else: url = f"https://dog.ceo/api/breeds/image/random" From 407add2bc887ca22ee52246fb71beb7e8815998b Mon Sep 17 00:00:00 2001 From: Cookie <58516648+Cookie-CHR@users.noreply.github.com> Date: Mon, 20 Jul 2020 13:30:26 +0200 Subject: [PATCH 213/227] Update fortune.py Aggiunte alcune predizioni --- royalpack/commands/fortune.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/royalpack/commands/fortune.py b/royalpack/commands/fortune.py index 8d446321..d662a1b8 100644 --- a/royalpack/commands/fortune.py +++ b/royalpack/commands/fortune.py @@ -22,6 +22,8 @@ class FortuneCommand(rc.Command): "🐱 Oggi vedrai più gatti del solito su Internet!", "🐶 Oggi vedrai più cani del solito su Internet!", "🐦 Oggi vedrai più uccelli del solito su Internet!", + "🔥 Oggi vedrai più flame del solito su Internet!", + "🤬 Oggi vedrai più discorsi politici del solito su Internet!", "🐌 Oggi incontrerai una chiocciola sperduta!", "🎁 Oggi i dispenser di regali in centro funzioneranno senza problemi!", "🥕 Oggi il tuo raccolto avrà qualità Iridium Star!", @@ -29,7 +31,14 @@ class FortuneCommand(rc.Command): "✨ Oggi farai molti più multicast!", "♦️ Oggi troverai una Leggendaria Dorata!", "⭐️ Oggi la stella della RYG ti sembrerà un pochino più dritta!", + "⭐️ Oggi la stella della RYG ti sembrerà anche più storta del solito!", "💎 Oggi i tuoi avversari non riusciranno a deflettere i tuoi Emerald Splash!", + "⁉️ Oggi le tue supercazzole prematureranno un po' più a sinistra!", + "🌅 Oggi sarà il giorno dopo ieri e il giorno prima di domani!", + "🤖 Oggi il Royal Bot ti dirà qualcosa di molto utile!", + "💤 Oggi rischierai di addormentarti più volte!", + "🥪 Oggi ti verrà fame fuori orario!", + "😓 Oggi dirai molte stupidaggini!", ] async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: From b7f099d499c1a11ff9782feb30726978199c6e0f Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 21 Jul 2020 22:43:20 +0200 Subject: [PATCH 214/227] Rimuovi tutti i comandi relativi alla chat vocale --- royalpack/commands/__init__.py | 52 ----------------- royalpack/commands/elevatormusic.py | 52 ----------------- royalpack/commands/funkwhale.py | 31 ---------- royalpack/commands/funkwhalealbum.py | 32 ----------- royalpack/commands/funkwhaleplaylist.py | 38 ------------ royalpack/commands/googlevideo.py | 17 ------ royalpack/commands/lazyfunkwhale.py | 31 ---------- royalpack/commands/lazyfunkwhalealbum.py | 32 ----------- royalpack/commands/lazyfunkwhaleplaylist.py | 36 ------------ royalpack/commands/lazygooglevideo.py | 17 ------ royalpack/commands/lazypeertube.py | 26 --------- royalpack/commands/lazyplay.py | 62 -------------------- royalpack/commands/lazysoundcloud.py | 15 ----- royalpack/commands/lazyyahoovideo.py | 17 ------ royalpack/commands/lazyyoutube.py | 15 ----- royalpack/commands/pause.py | 27 --------- royalpack/commands/peertube.py | 26 --------- royalpack/commands/play.py | 64 --------------------- royalpack/commands/playmode.py | 56 ------------------ royalpack/commands/queue.py | 62 -------------------- royalpack/commands/skip.py | 21 ------- royalpack/commands/soundcloud.py | 15 ----- royalpack/commands/summon.py | 29 ---------- royalpack/commands/videochannel.py | 49 ---------------- royalpack/commands/voicestatus.py | 44 -------------- royalpack/commands/yahoovideo.py | 17 ------ royalpack/commands/youtube.py | 15 ----- 27 files changed, 898 deletions(-) delete mode 100644 royalpack/commands/elevatormusic.py delete mode 100644 royalpack/commands/funkwhale.py delete mode 100644 royalpack/commands/funkwhalealbum.py delete mode 100644 royalpack/commands/funkwhaleplaylist.py delete mode 100644 royalpack/commands/googlevideo.py delete mode 100644 royalpack/commands/lazyfunkwhale.py delete mode 100644 royalpack/commands/lazyfunkwhalealbum.py delete mode 100644 royalpack/commands/lazyfunkwhaleplaylist.py delete mode 100644 royalpack/commands/lazygooglevideo.py delete mode 100644 royalpack/commands/lazypeertube.py delete mode 100644 royalpack/commands/lazyplay.py delete mode 100644 royalpack/commands/lazysoundcloud.py delete mode 100644 royalpack/commands/lazyyahoovideo.py delete mode 100644 royalpack/commands/lazyyoutube.py delete mode 100644 royalpack/commands/pause.py delete mode 100644 royalpack/commands/peertube.py delete mode 100644 royalpack/commands/play.py delete mode 100644 royalpack/commands/playmode.py delete mode 100644 royalpack/commands/queue.py delete mode 100644 royalpack/commands/skip.py delete mode 100644 royalpack/commands/soundcloud.py delete mode 100644 royalpack/commands/summon.py delete mode 100644 royalpack/commands/videochannel.py delete mode 100644 royalpack/commands/voicestatus.py delete mode 100644 royalpack/commands/yahoovideo.py delete mode 100644 royalpack/commands/youtube.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 9ce8b05e..e6d4b17a 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -11,58 +11,32 @@ from .diarioquote import DiarioquoteCommand from .diarioshuffle import DiarioshuffleCommand from .dota import DotaCommand from .eat import EatCommand -from .elevatormusic import ElevatormusicCommand from .emojify import EmojifyCommand from .eval import EvalCommand from .exec import ExecCommand from .fortune import FortuneCommand -from .funkwhale import FunkwhaleCommand -from .funkwhalealbum import FunkwhalealbumCommand -from .funkwhaleplaylist import FunkwhaleplaylistCommand from .givefiorygi import GivefiorygiCommand from .givetreasure import GivetreasureCommand -from .googlevideo import GooglevideoCommand from .help import HelpCommand -from .lazyfunkwhale import LazyfunkwhaleCommand -from .lazyfunkwhalealbum import LazyfunkwhalealbumCommand -from .lazyfunkwhaleplaylist import LazyfunkwhaleplaylistCommand -from .lazygooglevideo import LazygooglevideoCommand -from .lazypeertube import LazypeertubeCommand -from .lazyplay import LazyplayCommand -from .lazysoundcloud import LazysoundcloudCommand -from .lazyyahoovideo import LazyyahoovideoCommand -from .lazyyoutube import LazyyoutubeCommand from .leagueoflegends import LeagueoflegendsCommand from .magickfiorygi import MagickfiorygiCommand from .magicktreasure import MagicktreasureCommand from .matchmaking import MatchmakingCommand -from .pause import PauseCommand -from .peertube import PeertubeCommand from .peertubeupdates import PeertubeUpdatesCommand from .ping import PingCommand -from .play import PlayCommand -from .playmode import PlaymodeCommand from .pmots import PmotsCommand from .dog import DogCommand -from .queue import QueueCommand from .rage import RageCommand from .reminder import ReminderCommand from .royalpackversion import RoyalpackCommand from .ship import ShipCommand -from .skip import SkipCommand from .smecds import SmecdsCommand -from .soundcloud import SoundcloudCommand from .spell import SpellCommand from .steammatch import SteammatchCommand from .steampowered import SteampoweredCommand -from .summon import SummonCommand from .treasure import TreasureCommand from .trivia import TriviaCommand from .userinfo import UserinfoCommand -from .videochannel import VideochannelCommand -from .voicestatus import VoicestatusCommand -from .yahoovideo import YahoovideoCommand -from .youtube import YoutubeCommand # Enter the commands of your Pack here! available_commands = [ @@ -78,58 +52,32 @@ available_commands = [ DiarioshuffleCommand, DotaCommand, EatCommand, - ElevatormusicCommand, EmojifyCommand, EvalCommand, ExecCommand, FortuneCommand, - FunkwhalealbumCommand, - FunkwhaleCommand, - FunkwhaleplaylistCommand, GivefiorygiCommand, GivetreasureCommand, - GooglevideoCommand, HelpCommand, - LazyfunkwhalealbumCommand, - LazyfunkwhaleCommand, - LazyfunkwhaleplaylistCommand, - LazygooglevideoCommand, - LazypeertubeCommand, - LazyplayCommand, - LazysoundcloudCommand, - LazyyahoovideoCommand, - LazyyoutubeCommand, LeagueoflegendsCommand, MagickfiorygiCommand, MagicktreasureCommand, MatchmakingCommand, - PauseCommand, - PeertubeCommand, PeertubeUpdatesCommand, PingCommand, - PlayCommand, - PlaymodeCommand, PmotsCommand, DogCommand, - QueueCommand, RageCommand, ReminderCommand, RoyalpackCommand, ShipCommand, - SkipCommand, SmecdsCommand, - SoundcloudCommand, SpellCommand, SteammatchCommand, SteampoweredCommand, - SummonCommand, TreasureCommand, TriviaCommand, UserinfoCommand, - VideochannelCommand, - VoicestatusCommand, - YahoovideoCommand, - YoutubeCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/elevatormusic.py b/royalpack/commands/elevatormusic.py deleted file mode 100644 index 52929e46..00000000 --- a/royalpack/commands/elevatormusic.py +++ /dev/null @@ -1,52 +0,0 @@ -from typing import * -import random -import royalnet.commands as rc - -from .play import PlayCommand - - -class ElevatormusicCommand(PlayCommand): - name: str = "elevatormusic" - - aliases = ["elevator", "em"] - - description: str = "Aggiungi un po' di musica da ascensore alla chat vocale." - - syntax = "[indice]" - - _pool = [ - "https://www.youtube.com/watch?v=_tAcIGhh5Yo", - "https://www.youtube.com/watch?v=xy_NKN75Jhw", - "https://www.youtube.com/watch?v=PLRrL9OsAF8", - "https://www.youtube.com/watch?v=0TmoYBcLul8", - "https://www.youtube.com/watch?v=9v9-Nw4nAZg", - "https://www.youtube.com/watch?v=VBlFHuCzPgY", - "https://www.youtube.com/watch?v=mD3v1B_aXw0", - "https://www.youtube.com/watch?v=RCSbmSmyAcY", - "https://www.youtube.com/watch?v=kbdtBLD8Lbg", - "https://www.youtube.com/watch?v=JjT0p2z4hGg", - "https://www.youtube.com/watch?v=cc_KpOufpgM", - "https://www.youtube.com/watch?v=dlNEUYBt7Ls", - "https://www.youtube.com/watch?v=YVWdQGuE0-E", - "https://www.youtube.com/watch?v=1nVAg8VujGA", - "https://www.youtube.com/watch?v=G4mshu6BUio", - "https://www.youtube.com/watch?v=Y6_Aij3n8hk", - "https://www.youtube.com/watch?v=SbIaYZEUF1M", - "https://www.youtube.com/watch?v=Nf8FCLT8S6A", - ] - - async def get_urls(self, args): - index = args.optional(0) - if index is not None: - try: - return [self._pool[int(index)]] - except ValueError: - raise rc.InvalidInputError("L'indice deve essere un numero.\n" - f"Gli indici delle canzoni iniziano a [c]0[/c] e finiscono a" - f" [c]{len(self._pool) - 1}[/c].") - except IndexError: - raise rc.InvalidInputError(f"Indice non valido.\n" - f"Gli indici delle canzoni iniziano a [c]0[/c] e finiscono a" - f" [c]{len(self._pool) - 1}[/c].") - else: - return [random.sample(self._pool, 1)[0]] diff --git a/royalpack/commands/funkwhale.py b/royalpack/commands/funkwhale.py deleted file mode 100644 index b46cdfeb..00000000 --- a/royalpack/commands/funkwhale.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import * -import aiohttp -import urllib.parse -import royalnet.commands as rc - -from .play import PlayCommand - - -class FunkwhaleCommand(PlayCommand): - name: str = "funkwhale" - - aliases = ["fuckwhale", "fw", "royalwhale", "rw"] - - description: str = "Cerca una canzone su RoyalWhale e aggiungila alla coda della chat vocale." - - syntax = "{ricerca}" - - def get_embed_color(self): - return 0x009FE3 - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/search?query={search}") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - if len(j["tracks"]) < 1: - raise rc.UserError("Nessun file audio trovato con il nome richiesto.") - return [f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}'] diff --git a/royalpack/commands/funkwhalealbum.py b/royalpack/commands/funkwhalealbum.py deleted file mode 100644 index fe132f56..00000000 --- a/royalpack/commands/funkwhalealbum.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import * -import aiohttp -import urllib.parse -import royalnet.commands as rc - -from .play import PlayCommand - - -class FunkwhalealbumCommand(PlayCommand): - name: str = "funkwhalealbum" - - aliases = ["fwa", "fwalbum", "funkwhalea"] - - description: str = "Cerca un album su RoyalWhale e aggiungila alla coda della chat vocale." - - syntax = "{ricerca}" - - def get_embed_color(self): - return 0x009FE3 - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/search?query={search}") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - if len(j["albums"]) < 1: - raise rc.UserError("Nessun file audio trovato con il nome richiesto.") - album = j["albums"][0] - return [f'{self.config["Funkwhale"]["instance_url"]}{track["listen_url"]}' for track in album["tracks"]] diff --git a/royalpack/commands/funkwhaleplaylist.py b/royalpack/commands/funkwhaleplaylist.py deleted file mode 100644 index bdd3eb33..00000000 --- a/royalpack/commands/funkwhaleplaylist.py +++ /dev/null @@ -1,38 +0,0 @@ -from typing import * -import aiohttp -import urllib.parse -import royalnet.commands as rc - -from .play import PlayCommand - - -class FunkwhaleplaylistCommand(PlayCommand): - name: str = "funkwhaleplaylist" - - aliases = ["fwp", "fwplaylist", "funkwhalep"] - - description: str = "Cerca una playlist su RoyalWhale e aggiungila alla coda della chat vocale." - - syntax = "{ricerca}" - - def get_embed_color(self): - return 0x009FE3 - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - if len(j["results"]) < 1: - raise rc.UserError("Nessuna playlist trovata con il nome richiesto.") - playlist = j["results"][0] - playlist_id = playlist["id"] - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/playlists/{playlist_id}/tracks") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - return list(map(lambda t: f'{self.config["Funkwhale"]["instance_url"]}{t["track"]["listen_url"]}', j["results"])) diff --git a/royalpack/commands/googlevideo.py b/royalpack/commands/googlevideo.py deleted file mode 100644 index 3ec38790..00000000 --- a/royalpack/commands/googlevideo.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import * -from .play import PlayCommand - - -class GooglevideoCommand(PlayCommand): - name: str = "googlevideo" - - aliases = ["gv"] - - description: str = "Cerca un video su Google Video e lo aggiunge alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"gvsearch:{args.joined()}"] - - # Too bad gvsearch: always finds nothing. diff --git a/royalpack/commands/lazyfunkwhale.py b/royalpack/commands/lazyfunkwhale.py deleted file mode 100644 index fd3337fe..00000000 --- a/royalpack/commands/lazyfunkwhale.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import * -import royalnet.commands as rc -import aiohttp -import urllib.parse - -from .lazyplay import LazyplayCommand - - -class LazyfunkwhaleCommand(LazyplayCommand): - name: str = "lazyfunkwhale" - - aliases = ["lazyfuckwhale", "lfw", "lazyroyalwhale", "lrw"] - - description: str = "Cerca una canzone su RoyalWhale e aggiungila (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - def get_embed_color(self): - return 0x009FE3 - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/search?query={search}") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - if len(j["tracks"]) < 1: - raise rc.UserError("Nessun file audio trovato con il nome richiesto.") - return [f'{self.config["Funkwhale"]["instance_url"]}{j["tracks"][0]["listen_url"]}'] diff --git a/royalpack/commands/lazyfunkwhalealbum.py b/royalpack/commands/lazyfunkwhalealbum.py deleted file mode 100644 index 631e088e..00000000 --- a/royalpack/commands/lazyfunkwhalealbum.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import * -import royalnet.commands as rc -import aiohttp -import urllib.parse - -from .lazyplay import LazyplayCommand - - -class LazyfunkwhalealbumCommand(LazyplayCommand): - name: str = "lazyfunkwhalealbum" - - aliases = ["lfwa", "lfwalbum", "lazyfunkwhalea"] - - description: str = "Cerca un album su RoyalWhale e aggiungilo (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - def get_embed_color(self): - return 0x009FE3 - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/search?query={search}") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - if len(j["albums"]) < 1: - raise rc.UserError("Nessun file audio trovato con il nome richiesto.") - album = j["albums"][0] - return [f'{self.config["Funkwhale"]["instance_url"]}{track["listen_url"]}' for track in album["tracks"]] diff --git a/royalpack/commands/lazyfunkwhaleplaylist.py b/royalpack/commands/lazyfunkwhaleplaylist.py deleted file mode 100644 index caa9378d..00000000 --- a/royalpack/commands/lazyfunkwhaleplaylist.py +++ /dev/null @@ -1,36 +0,0 @@ -import aiohttp -import urllib.parse -import royalnet.commands as rc -from .lazyplay import LazyplayCommand - - -class LazyfunkwhaleplaylistCommand(LazyplayCommand): - name: str = "lazyfunkwhaleplaylist" - - aliases = ["lfwp", "lfwplaylist", "lazyfunkwhalep"] - - description: str = "Cerca una playlist su RoyalWhale e aggiungila (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - def get_embed_color(self): - return 0x009FE3 - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/playlists/?q={search}&ordering=-creation_date&playable=true") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - if len(j["results"]) < 1: - raise rc.UserError("Nessuna playlist trovata con il nome richiesto.") - playlist = j["results"][0] - playlist_id = playlist["id"] - async with session.get(self.config["Funkwhale"]["instance_url"] + - f"/api/v1/playlists/{playlist_id}/tracks") as response: - if response.status >= 400: - raise rc.ExternalError(f"Request returned {response.status}") - j = await response.json() - return list(map(lambda t: f'{self.config["Funkwhale"]["instance_url"]}{t["track"]["listen_url"]}', j["results"])) diff --git a/royalpack/commands/lazygooglevideo.py b/royalpack/commands/lazygooglevideo.py deleted file mode 100644 index e8bba83a..00000000 --- a/royalpack/commands/lazygooglevideo.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import * -from .lazyplay import LazyplayCommand - - -class LazygooglevideoCommand(LazyplayCommand): - name: str = "lazygooglevideo" - - aliases = ["lgv"] - - description: str = "Cerca un video su Google Video e lo aggiunge (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"gvsearch:{args.joined()}"] - - # Too bad gvsearch: always finds nothing. diff --git a/royalpack/commands/lazypeertube.py b/royalpack/commands/lazypeertube.py deleted file mode 100644 index 691ce58c..00000000 --- a/royalpack/commands/lazypeertube.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import * -import royalnet.commands as rc -import aiohttp -import urllib.parse - -from .lazyplay import LazyplayCommand - - -class LazypeertubeCommand(LazyplayCommand): - name: str = "lazypeertube" - - aliases = ["lpt", "lazyroyaltube", "lrt"] - - description: str = "Cerca un video su RoyalTube e lo aggiunge (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Peertube"]["instance_url"] + - f"/api/v1/search/videos?search={search}") as response: - j = await response.json() - if j["total"] < 1: - raise rc.InvalidInputError("Nessun video trovato.") - return [f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}'] diff --git a/royalpack/commands/lazyplay.py b/royalpack/commands/lazyplay.py deleted file mode 100644 index 2ee9b7f4..00000000 --- a/royalpack/commands/lazyplay.py +++ /dev/null @@ -1,62 +0,0 @@ -from typing import * -import discord -import asyncio as aio -import royalnet.commands as rc -import royalnet.backpack.tables as rbt - - -class LazyplayCommand(rc.Command): - name: str = "lazyplay" - - aliases = ["lp"] - - description: str = "Aggiunge un url alla coda della chat vocale, ma lo scarica solo quando sta per essere" \ - " riprodotto." - - syntax = "{url}" - - async def get_urls(self, args: rc.CommandArgs): - url = args.joined(require_at_least=1) - if not (url.startswith("http://") or url.startswith("https://")): - raise rc.InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" - f" ([c]http://[/c] o [c]https://[/c]).") - return [url] - - def get_embed_color(self) -> Optional[int]: - return None - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name == "discord": - message: discord.Message = data.message - guild: discord.Guild = message.guild - if guild is None: - guild_id = None - else: - guild_id: Optional[int] = guild.id - else: - guild_id = None - - user: rbt.User = await data.get_author() - user_str = None - - if user is not None: - try: - user_discord: rbt.Discord = user.discord[0] - except (AttributeError, IndexError): - user_str = str(user) - else: - user_str = str(f"<@{user_discord.discord_id}>") - - urls = await self.get_urls(args) - - play_task: aio.Task = self.loop.create_task( - self.interface.call_herald_event("discord", "discord_lazy_play", - urls=urls, - guild_id=guild_id, - user=user_str, - force_color=self.get_embed_color()) - ) - - await data.reply("⌛ Attendi un attimo...") - - await play_task diff --git a/royalpack/commands/lazysoundcloud.py b/royalpack/commands/lazysoundcloud.py deleted file mode 100644 index e297c0ce..00000000 --- a/royalpack/commands/lazysoundcloud.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import * -from .lazyplay import LazyplayCommand - - -class LazysoundcloudCommand(LazyplayCommand): - name: str = "lazysoundcloud" - - aliases = ["lsc"] - - description: str = "Cerca un video su SoundCloud e lo aggiunge (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"scsearch:{args.joined()}"] diff --git a/royalpack/commands/lazyyahoovideo.py b/royalpack/commands/lazyyahoovideo.py deleted file mode 100644 index a2e51389..00000000 --- a/royalpack/commands/lazyyahoovideo.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import * -from .lazyplay import LazyplayCommand - - -class LazyyahoovideoCommand(LazyplayCommand): - name: str = "lazyyahoovideo" - - aliases = ["lyv"] - - description: str = "Cerca un video su Yahoo Video e lo aggiunge (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"yvsearch:{args.joined()}"] - - # Too bad yvsearch: always finds nothing. diff --git a/royalpack/commands/lazyyoutube.py b/royalpack/commands/lazyyoutube.py deleted file mode 100644 index 3dcb8f82..00000000 --- a/royalpack/commands/lazyyoutube.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import * -from .lazyplay import LazyplayCommand - - -class LazyyoutubeCommand(LazyplayCommand): - name: str = "lazyyoutube" - - aliases = ["lyt"] - - description: str = "Cerca un video su YouTube e lo aggiunge (lazy) alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"ytsearch:{args.joined()}"] diff --git a/royalpack/commands/pause.py b/royalpack/commands/pause.py deleted file mode 100644 index 4c71820d..00000000 --- a/royalpack/commands/pause.py +++ /dev/null @@ -1,27 +0,0 @@ -from typing import * -import discord -import royalnet.commands as rc - - -class PauseCommand(rc.Command): - name: str = "pause" - - aliases = ["resume"] - - description: str = "Metti in pausa o riprendi la riproduzione di un file." - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name == "discord": - message: discord.Message = data.message - guild: discord.Guild = message.guild - guild_id: Optional[int] = guild.id - else: - guild_id = None - response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_pause", - guild_id=guild_id) - - if response["action"] == "paused": - await data.reply("⏸ Riproduzione messa in pausa.") - - elif response["action"] == "resumed": - await data.reply("▶️ Riproduzione ripresa!") diff --git a/royalpack/commands/peertube.py b/royalpack/commands/peertube.py deleted file mode 100644 index 20c112ec..00000000 --- a/royalpack/commands/peertube.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import * -import royalnet.commands as rc -import aiohttp -import urllib.parse - -from .play import PlayCommand - - -class PeertubeCommand(PlayCommand): - name: str = "peertube" - - aliases = ["pt", "royaltube", "rt"] - - description: str = "Cerca un video su RoyalTube e lo aggiunge alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - search = urllib.parse.quote(args.joined(require_at_least=1)) - async with aiohttp.ClientSession() as session: - async with session.get(self.config["Peertube"]["instance_url"] + - f"/api/v1/search/videos?search={search}") as response: - j = await response.json() - if j["total"] < 1: - raise rc.InvalidInputError("Nessun video trovato.") - return [f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}'] diff --git a/royalpack/commands/play.py b/royalpack/commands/play.py deleted file mode 100644 index 5754efdc..00000000 --- a/royalpack/commands/play.py +++ /dev/null @@ -1,64 +0,0 @@ -from typing import * -import discord -import asyncio as aio -import royalnet.commands as rc -import royalnet.backpack.tables as rbt - - -class PlayCommand(rc.Command): - name: str = "play" - - aliases = ["p"] - - description: str = "Aggiunge un url alla coda della chat vocale." - - syntax = "{url}" - - async def get_urls(self, args: rc.CommandArgs): - url = args.joined(require_at_least=1) - if not (url.startswith("http://") or url.startswith("https://")): - raise rc.InvalidInputError(f"L'URL specificato non inizia con il nome di un protocollo supportato" - f" ([c]http://[/c] o [c]https://[/c]).") - return [url] - - def get_embed_color(self) -> Optional[int]: - return None - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name == "discord": - message: discord.Message = data.message - guild: discord.Guild = message.guild - if guild is None: - guild_id = None - else: - guild_id: Optional[int] = guild.id - else: - guild_id = None - - user: rbt.User = await data.get_author() - user_str = None - - if user is not None: - try: - user_discord: rbt.Discord = user.discord[0] - except (AttributeError, IndexError): - user_str = str(user) - else: - user_str = str(f"<@{user_discord.discord_id}>") - - urls = await self.get_urls(args) - - play_task: aio.Task = self.loop.create_task( - self.interface.call_herald_event("discord", "discord_play", - urls=urls, - guild_id=guild_id, - user=user_str, - force_color=self.get_embed_color()) - ) - - if len(urls) > 1: - await data.reply("⌛ Attendi qualche minuto...") - else: - await data.reply("⌛ Attendi un attimo...") - - await play_task diff --git a/royalpack/commands/playmode.py b/royalpack/commands/playmode.py deleted file mode 100644 index 9ea12955..00000000 --- a/royalpack/commands/playmode.py +++ /dev/null @@ -1,56 +0,0 @@ -from typing import * -import royalnet.commands as rc -import discord -import royalnet.backpack.tables as rbt - - -class PlaymodeCommand(rc.Command): - name: str = "playmode" - - aliases = ["pm"] - - description: str = "Seleziona la modalità di riproduzione musicale." - - syntax: str = "{queue|pool}" - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name == "discord": - message: discord.Message = data.message - guild: discord.Guild = message.guild - if guild is None: - guild_id = None - else: - guild_id: Optional[int] = guild.id - else: - guild_id = None - - user: rbt.User = await data.get_author() - user_str = None - - if user is not None: - try: - user_discord: rbt.Discord = user.discord[0] - except (AttributeError, IndexError): - user_str = str(user) - else: - user_str = str(f"<@{user_discord.discord_id}>") - - response = await self.interface.call_herald_event("discord", "discord_playmode", - playable_string=args[0], - guild_id=guild_id, - user=user_str) - - if response["name"] == "RoyalQueue": - await data.reply(f"✅ Modalità di riproduzione impostata a [b]Queue[/b]:\n" - f"- Riproduci le canzoni nell'ordine scelto\n" - f"- Rimuovi le canzoni dopo averle riprodotte") - - elif response["name"] == "RoyalPool": - await data.reply(f"✅ Modalità di riproduzione impostata a [b]Pool[/b]:\n" - f"- Aggiungi canzoni al pool con [c]!p[/c], [c]!yt[/c] e [c]!fw[/c]\n" - f"- Riproduci all'infinito canzoni casuali dal pool\n" - f"- Non è possibile rimuovere canzoni dal pool, [c]!skip[/c]parle manderà solo avanti il pool\n" - f"- Interrompi la riproduzione del pool cambiando modalità di riproduzione") - - else: - await data.reply(f"✅ Modalità di riproduzione impostata a [c]{response['name']}[/c]!") \ No newline at end of file diff --git a/royalpack/commands/queue.py b/royalpack/commands/queue.py deleted file mode 100644 index 4ae2a39a..00000000 --- a/royalpack/commands/queue.py +++ /dev/null @@ -1,62 +0,0 @@ -from typing import * -import pickle -import base64 -import discord -import royalnet.commands as rc -import royalnet.utils as ru - - -class QueueCommand(rc.Command): - name: str = "queue" - - aliases = ["q"] - - description: str = "Visualizza la coda di riproduzione attuale." - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name == "discord": - message: discord.Message = data.message - guild: discord.Guild = message.guild - guild_id: Optional[int] = guild.id - else: - guild_id = None - response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_queue", - guild_id=guild_id) - - queue_type = response["type"] - if queue_type == "RoyalQueue": - next_up = response["next_up"] - now_playing = response["now_playing"] - await data.reply(f"ℹ️ La coda contiene {len(next_up)} file.\n\n") - - if now_playing is not None: - reply = f"Attualmente, sta venendo riprodotto:\n" - if self.interface.name == "discord": - await data.reply(reply) - embed = pickle.loads(base64.b64decode(bytes(now_playing["stringified_base64_pickled_discord_embed"], - encoding="ascii"))) - # noinspection PyUnboundLocalVariable - await message.channel.send(embed=embed) - else: - reply += f"▶️ {now_playing['title']}\n\n" - await data.reply(reply) - else: - await data.reply("⏹ Attualmente, non sta venendo riprodotto nulla.") - - reply = "" - if len(next_up) >= 1: - reply += "I prossimi file in coda sono:\n" - if self.interface.name == "discord": - await data.reply(reply) - for item in next_up[:5]: - embed = pickle.loads(base64.b64decode(bytes(item["stringified_base64_pickled_discord_embed"], - encoding="ascii"))) - # noinspection PyUnboundLocalVariable - await message.channel.send(embed=embed) - else: - reply += ru.numberemojiformat([a["title"] for a in next_up[:5]]) - await data.reply(reply) - else: - await data.reply("ℹ️ Non ci sono altri file in coda.") - else: - raise rc.CommandError(f"Non so come visualizzare il contenuto di un [c]{queue_type}[/c].") diff --git a/royalpack/commands/skip.py b/royalpack/commands/skip.py deleted file mode 100644 index 277ad1c0..00000000 --- a/royalpack/commands/skip.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import * -import discord -import royalnet.commands as rc - - -class SkipCommand(rc.Command): - name: str = "skip" - - aliases = ["s"] - - description: str = "Salta il file attualmente in riproduzione." - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name == "discord": - message: discord.Message = data.message - guild: discord.Guild = message.guild - guild_id: Optional[int] = guild.id - else: - guild_id = None - response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_skip", guild_id=guild_id) - await data.reply("⏩ File attuale saltato!") diff --git a/royalpack/commands/soundcloud.py b/royalpack/commands/soundcloud.py deleted file mode 100644 index b01d8ef7..00000000 --- a/royalpack/commands/soundcloud.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import * -from .play import PlayCommand - - -class SoundcloudCommand(PlayCommand): - name: str = "soundcloud" - - aliases = ["sc"] - - description: str = "Cerca un video su SoundCloud e lo aggiunge alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"scsearch:{args.joined()}"] diff --git a/royalpack/commands/summon.py b/royalpack/commands/summon.py deleted file mode 100644 index 18145a5a..00000000 --- a/royalpack/commands/summon.py +++ /dev/null @@ -1,29 +0,0 @@ -from typing import * -import royalnet.commands as rc -import discord - - -class SummonCommand(rc.Command): - name: str = "summon" - - aliases = ["cv"] - - description: str = "Evoca il bot in un canale vocale." - - syntax: str = "[nomecanale]" - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - channel_name = args.joined() - if self.interface.name == "discord": - message: discord.Message = data.message - guild_id = message.guild.id - user_id = message.author.id - else: - guild_id = None - user_id = None - response = await self.interface.call_herald_event("discord", "discord_summon", - channel_name=channel_name, guild_id=guild_id, user_id=user_id) - if self.interface.name == "discord": - await data.reply(f"✅ Mi sono connesso in <#{response['channel']['id']}>!") - else: - await data.reply(f"✅ Mi sono connesso in [b]#{response['channel']['name']}[/b]!") diff --git a/royalpack/commands/videochannel.py b/royalpack/commands/videochannel.py deleted file mode 100644 index a8801510..00000000 --- a/royalpack/commands/videochannel.py +++ /dev/null @@ -1,49 +0,0 @@ -from typing import * -import discord -import royalnet.commands as rc - - -class VideochannelCommand(rc.Command): - name: str = "videochannel" - - aliases = ["golive", "live", "video"] - - description: str = "Converti il canale vocale in un canale video." - - syntax = "[nomecanale]" - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name != "discord": - raise rc.UnsupportedError(f"{self} non è supportato su {self.interface.name}.") - bot: discord.Client = self.serf.client - message: discord.Message = data.message - channel_name: str = args.optional(0) - if channel_name: - guild: Optional[discord.Guild] = message.guild - if guild is not None: - channels: List[discord.abc.GuildChannel] = guild.channels - else: - channels = bot.get_all_channels() - matching_channels: List[discord.VoiceChannel] = [] - for channel in channels: - if isinstance(channel, discord.VoiceChannel): - if channel.name == channel_name: - matching_channels.append(channel) - if len(matching_channels) == 0: - raise rc.InvalidInputError("Non esiste alcun canale vocale con il nome specificato.") - elif len(matching_channels) > 1: - raise rc.UserError("Esiste più di un canale vocale con il nome specificato.") - channel = matching_channels[0] - else: - author: discord.Member = message.author - voice: Optional[discord.VoiceState] = author.voice - if voice is None: - raise rc.InvalidInputError("Non sei connesso a nessun canale vocale.") - channel = voice.channel - if author.is_on_mobile(): - await data.reply(f"📹 Per entrare in modalità video, clicca qui:\n" - f"\n" - f"[b]Attenzione: la modalità video non funziona su Android e iOS![/b]") - return - await data.reply(f"📹 Per entrare in modalità video, clicca qui:\n" - f"") diff --git a/royalpack/commands/voicestatus.py b/royalpack/commands/voicestatus.py deleted file mode 100644 index 511a44ae..00000000 --- a/royalpack/commands/voicestatus.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import * -import royalnet.serf.discord as rsd -import royalnet.commands as rc - - -class VoicestatusCommand(rc.Command): - name: str = "voicestatus" - - description: str = "Visualizza lo stato interno dei voice player del bot." - - syntax: str = "" - - async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: - if self.interface.name != "discord": - raise rc.UnsupportedError("Questo comando funziona solo su Discord.") - serf: rsd.DiscordSerf = self.interface.serf - - message = [] - for index, voice_player in enumerate(serf.voice_players): - message.append(f"🎵 [b]Voice Player #{index}[/b]") - - voice_client = voice_player.voice_client - if voice_client.is_connected(): - message.append(f"🔵 Connected") - else: - message.append(f"🔴 Disconnected") - if voice_client.is_playing(): - message.append(f"🔵 Playing") - else: - message.append(f"⚪ Not playing") - if voice_client.is_paused(): - message.append(f"⚪ Paused") - else: - message.append(f"🔵 Not paused") - - playable = voice_player.playing - message.append(f"🔉 {playable.__class__.__name__}") - - message.append("") - - if len(serf.voice_players) == 0: - message.append("[i]Nessun voice player.[/i]") - - await data.reply("\n".join(message)) diff --git a/royalpack/commands/yahoovideo.py b/royalpack/commands/yahoovideo.py deleted file mode 100644 index 0632152a..00000000 --- a/royalpack/commands/yahoovideo.py +++ /dev/null @@ -1,17 +0,0 @@ -from typing import * -from .play import PlayCommand - - -class YahoovideoCommand(PlayCommand): - name: str = "yahoovideo" - - aliases = ["yv"] - - description: str = "Cerca un video su Yahoo Video e lo aggiunge alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"yvsearch:{args.joined()}"] - - # Too bad yvsearch: always finds nothing. diff --git a/royalpack/commands/youtube.py b/royalpack/commands/youtube.py deleted file mode 100644 index 29e05d72..00000000 --- a/royalpack/commands/youtube.py +++ /dev/null @@ -1,15 +0,0 @@ -from typing import * -from .play import PlayCommand - - -class YoutubeCommand(PlayCommand): - name: str = "youtube" - - aliases = ["yt"] - - description: str = "Cerca un video su YouTube e lo aggiunge alla coda della chat vocale." - - syntax = "{ricerca}" - - async def get_urls(self, args): - return [f"ytsearch:{args.joined()}"] From f777f008c56dbcf47547da1d741df64654c7b5b0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 21 Jul 2020 23:12:14 +0200 Subject: [PATCH 215/227] Cambia la signature di linker.create --- royalpack/commands/abstract/linker.py | 12 +++++++++--- royalpack/commands/brawlhalla.py | 24 ++++++++++++++---------- royalpack/commands/dota.py | 2 +- royalpack/commands/leagueoflegends.py | 10 +++++++++- royalpack/commands/steampowered.py | 15 +++++++++++++-- 5 files changed, 46 insertions(+), 17 deletions(-) diff --git a/royalpack/commands/abstract/linker.py b/royalpack/commands/abstract/linker.py index bdebb354..ce3537ae 100644 --- a/royalpack/commands/abstract/linker.py +++ b/royalpack/commands/abstract/linker.py @@ -41,7 +41,7 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): await data.reply("\n".join(message)) else: message = ["🔗 Account collegato!\n"] - created = await self.create(session=data.session, user=author, args=args) + created = await self.create(session=data.session, user=author, args=args, data=data) message.append(self.describe(created)) await data.session_commit() await data.reply("\n".join(message)) @@ -61,8 +61,14 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): ... @abc.abstractmethod - async def create(self, session, user: rbt.User, args) -> Updatable: - """Create a new updatable object for a user.""" + async def create(self, + session, + user: rbt.User, + args: rc.CommandArgs, + data: Optional[rc.CommandData] = None) -> Updatable: + """Create a new updatable object for a user. + + This function is responsible for adding the object to the session.""" ... @abc.abstractmethod diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index e2a7e142..f7dfcb95 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -5,8 +5,8 @@ import logging import aiohttp from royalnet.backpack import tables as rbt -from royalnet.commands import * -from royalnet.utils import * +import royalnet.commands as rc +import royalnet.utils as ru from sqlalchemy import or_, and_ from .abstract.linker import LinkerCommand @@ -32,10 +32,14 @@ class BrawlhallaCommand(LinkerCommand): return user.steam async def get_updatables(self, session) -> List[Brawlhalla]: - return await asyncify(session.query(self.alchemy.get(Steam)).all) + return await ru.asyncify(session.query(self.alchemy.get(Steam)).all) - async def create(self, session, user: rbt.User, args) -> Updatable: - raise InvalidInputError("Brawlhalla accounts are automatically linked from Steam.") + async def create(self, + session, + user: rbt.User, + args: rc.CommandArgs, + data: Optional[rc.CommandData] = None) -> Brawlhalla: + raise rc.InvalidInputError("Brawlhalla accounts are automatically linked from Steam.") async def update(self, session, obj, change: Callable[[str, Any], Awaitable[None]]): BrawlhallaT = self.alchemy.get(Brawlhalla) @@ -47,7 +51,7 @@ class BrawlhallaCommand(LinkerCommand): log.debug(f"Checking if player has an account...") async with hcs.get(f"https://api.brawlhalla.com/search?steamid={obj.steamid.as_64}&api_key={self.token()}") as response: if response.status != 200: - raise ExternalError(f"Brawlhalla API /search returned {response.status}!") + raise rc.ExternalError(f"Brawlhalla API /search returned {response.status}!") j = await response.json() if j == {} or j == []: log.debug("No account found.") @@ -62,7 +66,7 @@ class BrawlhallaCommand(LinkerCommand): async with hcs.get(f"https://api.brawlhalla.com/player/{bh.brawlhalla_id}/ranked?api_key={self.token()}") as response: if response.status != 200: - raise ExternalError(f"Brawlhalla API /ranked returned {response.status}!") + raise rc.ExternalError(f"Brawlhalla API /ranked returned {response.status}!") j = await response.json() if j == {} or j == []: log.debug("No ranked info found.") @@ -75,7 +79,7 @@ class BrawlhallaCommand(LinkerCommand): await self._change(session=session, obj=bh, attribute="rank_1v1", new=rank) for jduo in j.get("2v2", []): - bhduo: Optional[BrawlhallaDuo] = await asyncify( + bhduo: Optional[BrawlhallaDuo] = await ru.asyncify( session.query(DuoT) .filter( or_( @@ -93,11 +97,11 @@ class BrawlhallaCommand(LinkerCommand): ) if bhduo is None: if bh.brawlhalla_id == jduo["brawlhalla_id_one"]: - otherbh: Optional[Brawlhalla] = await asyncify( + otherbh: Optional[Brawlhalla] = await ru.asyncify( session.query(BrawlhallaT).get, jduo["brawlhalla_id_two"] ) else: - otherbh: Optional[Brawlhalla] = await asyncify( + otherbh: Optional[Brawlhalla] = await ru.asyncify( session.query(BrawlhallaT).get, jduo["brawlhalla_id_one"] ) if otherbh is None: diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index 14b7850f..e394ecbb 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -37,7 +37,7 @@ class DotaCommand(LinkerCommand): async def get_updatables(self, session) -> List[Dota]: return await ru.asyncify(session.query(self.alchemy.get(Steam)).all) - async def create(self, session, user: rbt.User, args): + async def create(self, session, user: rbt.User, args: rc.CommandArgs, data: Optional[rc.CommandData] = None): raise rc.InvalidInputError("Dota accounts are automatically linked from Steam.") async def update(self, session, obj: Steam, change: Callable[[str, Any], Awaitable[None]]): diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index cfb9aa7c..40844eff 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -60,7 +60,7 @@ class LeagueoflegendsCommand(LinkerCommand): async def get_updatables(self, session) -> List[LeagueOfLegends]: return await ru.asyncify(session.query(self.alchemy.get(LeagueOfLegends)).all) - async def create(self, session, user: rbt.User, args) -> LeagueOfLegends: + async def create(self, session, user: rbt.User, args: rc.CommandArgs, data: Optional[rc.CommandData] = None) -> LeagueOfLegends: name = args.joined() # Connect a new League of Legends account to Royalnet @@ -108,6 +108,14 @@ class LeagueoflegendsCommand(LinkerCommand): rank_tftq=tftq, mastery_score=mastery ) + + await FiorygiTransaction.spawn_fiorygi( + data=data, + user=user, + qty=1, + reason="aver collegato a Royalnet il proprio account di League of Legends" + ) + session.add(leagueoflegends) return leagueoflegends diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 049aea32..eb44b7c0 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -35,7 +35,11 @@ class SteampoweredCommand(LinkerCommand): async def get_updatables(self, session) -> List[Steam]: return await ru.asyncify(session.query(self.alchemy.get(Steam)).all) - async def create(self, session, user: rbt.User, args) -> Steam: + async def create(self, + session, + user: rbt.User, + args: rc.CommandArgs, + data: Optional[rc.CommandData] = None) -> Steam: url = args.joined() steamid64 = await self._call(steam.steamid.steam64_from_url, url) if steamid64 is None: @@ -51,8 +55,15 @@ class SteampoweredCommand(LinkerCommand): primary_clan_id=r["primaryclanid"], account_creation_date=datetime.datetime.fromtimestamp(r["timecreated"]) ) + + await FiorygiTransaction.spawn_fiorygi( + data=data, + user=user, + qty=1, + reason="aver collegato a Royalnet il proprio account di League of Legends" + ) + session.add(steam_account) - await ru.asyncify(session.commit) return steam_account async def update(self, session, obj: Steam, change: Callable[[str, Any], Awaitable[None]]): From 19a062e482dd7146e5cf1f08b34a84fd914eaa51 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 21 Jul 2020 23:15:22 +0200 Subject: [PATCH 216/227] Cambia ancora la signature di linker.create --- royalpack/commands/abstract/linker.py | 8 ++++---- royalpack/commands/brawlhalla.py | 2 +- royalpack/commands/dota.py | 6 +++++- royalpack/commands/leagueoflegends.py | 6 +++++- royalpack/commands/steampowered.py | 2 +- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/royalpack/commands/abstract/linker.py b/royalpack/commands/abstract/linker.py index ce3537ae..198df1f8 100644 --- a/royalpack/commands/abstract/linker.py +++ b/royalpack/commands/abstract/linker.py @@ -40,11 +40,11 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): await data.session_commit() await data.reply("\n".join(message)) else: - message = ["🔗 Account collegato!\n"] created = await self.create(session=data.session, user=author, args=args, data=data) - message.append(self.describe(created)) await data.session_commit() - await data.reply("\n".join(message)) + 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.""" @@ -65,7 +65,7 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): session, user: rbt.User, args: rc.CommandArgs, - data: Optional[rc.CommandData] = None) -> Updatable: + data: Optional[rc.CommandData] = None) -> Optional[Updatable]: """Create a new updatable object for a user. This function is responsible for adding the object to the session.""" diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index f7dfcb95..a4d2939b 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -38,7 +38,7 @@ class BrawlhallaCommand(LinkerCommand): session, user: rbt.User, args: rc.CommandArgs, - data: Optional[rc.CommandData] = None) -> Brawlhalla: + data: Optional[rc.CommandData] = None) -> Optional[Brawlhalla]: raise rc.InvalidInputError("Brawlhalla accounts are automatically linked from Steam.") async def update(self, session, obj, change: Callable[[str, Any], Awaitable[None]]): diff --git a/royalpack/commands/dota.py b/royalpack/commands/dota.py index e394ecbb..917285e6 100644 --- a/royalpack/commands/dota.py +++ b/royalpack/commands/dota.py @@ -37,7 +37,11 @@ class DotaCommand(LinkerCommand): async def get_updatables(self, session) -> List[Dota]: return await ru.asyncify(session.query(self.alchemy.get(Steam)).all) - async def create(self, session, user: rbt.User, args: rc.CommandArgs, data: Optional[rc.CommandData] = None): + async def create(self, + session, + user: rbt.User, + args: rc.CommandArgs, + data: Optional[rc.CommandData] = None) -> Optional[Dota]: raise rc.InvalidInputError("Dota accounts are automatically linked from Steam.") async def update(self, session, obj: Steam, change: Callable[[str, Any], Awaitable[None]]): diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 40844eff..0925a9fb 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -60,7 +60,11 @@ class LeagueoflegendsCommand(LinkerCommand): async def get_updatables(self, session) -> List[LeagueOfLegends]: return await ru.asyncify(session.query(self.alchemy.get(LeagueOfLegends)).all) - async def create(self, session, user: rbt.User, args: rc.CommandArgs, data: Optional[rc.CommandData] = None) -> LeagueOfLegends: + async def create(self, + session, + user: rbt.User, + args: rc.CommandArgs, + data: Optional[rc.CommandData] = None) -> Optional[LeagueOfLegends]: name = args.joined() # Connect a new League of Legends account to Royalnet diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index eb44b7c0..662c61c7 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -39,7 +39,7 @@ class SteampoweredCommand(LinkerCommand): session, user: rbt.User, args: rc.CommandArgs, - data: Optional[rc.CommandData] = None) -> Steam: + data: Optional[rc.CommandData] = None) -> Optional[Steam]: url = args.joined() steamid64 = await self._call(steam.steamid.steam64_from_url, url) if steamid64 is None: From dff7127a3800358af1c04178f2c2fdfe5739a624 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 22 Jul 2020 00:16:57 +0200 Subject: [PATCH 217/227] Delete lock, as poetry broke Understandable, have a nice day --- poetry.lock | 1186 ------------------------------------------------ pyproject.toml | 2 +- 2 files changed, 1 insertion(+), 1187 deletions(-) delete mode 100644 poetry.lock diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index e07c448e..00000000 --- a/poetry.lock +++ /dev/null @@ -1,1186 +0,0 @@ -[[package]] -category = "main" -description = "Async http client/server framework (asyncio)" -name = "aiohttp" -optional = false -python-versions = ">=3.5.3" -version = "3.6.2" - -[package.dependencies] -async-timeout = ">=3.0,<4.0" -attrs = ">=17.3.0" -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" -optional = false -python-versions = ">=3.5.3" -version = "3.0.1" - -[[package]] -category = "main" -description = "Classes Without Boilerplate" -name = "attrs" -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"] -dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"] -docs = ["sphinx", "zope.interface"] -tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] - -[[package]] -category = "main" -description = "Modern password hashing for your software and your servers" -name = "bcrypt" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.1.7" - -[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" -optional = false -python-versions = "~=3.5" -version = "4.1.1" - -[[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." -name = "certifi" -optional = false -python-versions = "*" -version = "2020.6.20" - -[[package]] -category = "main" -description = "Foreign Function Interface for Python calling C code." -name = "cffi" -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]] -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 = "*" -version = "10.0" - -[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" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" -version = "2.9.2" - -[package.dependencies] -cffi = ">=1.8,<1.11.3 || >1.11.3" -six = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"] -docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] -idna = ["idna (>=2.1)"] -pep8test = ["flake8", "flake8-import-order", "pep8-naming"] -test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] - -[[package]] -category = "main" -description = "Date parsing library designed to parse dates from HTML pages" -name = "dateparser" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.7.6" - -[package.dependencies] -python-dateutil = "*" -pytz = "*" -regex = "!=2019.02.19" -tzlocal = "*" - -[[package]] -category = "main" -description = "Decorators for Humans" -name = "decorator" -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" -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"] - -[[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]] -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]] -category = "main" -description = "Human friendly output for text interfaces using Python" -name = "humanfriendly" -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]] -category = "main" -description = "multidict implementation" -name = "multidict" -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" -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" -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" -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" -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]] -category = "main" -description = "A python implmementation of GNU readline." -marker = "sys_platform == \"win32\"" -name = "pyreadline" -optional = false -python-versions = "*" -version = "2.1" - -[[package]] -category = "main" -description = "Extensions to the standard Python datetime module" -name = "python-dateutil" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -version = "2.8.1" - -[package.dependencies] -six = ">=1.5" - -[[package]] -category = "main" -description = "A streaming multipart parser for Python" -name = "python-multipart" -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" -optional = false -python-versions = "*" -version = "12.8" - -[package.dependencies] -certifi = "*" -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]] -category = "main" -description = "Alternative regular expression module, to replace re." -name = "regex" -optional = false -python-versions = "*" -version = "2020.7.14" - -[[package]] -category = "main" -description = "Python HTTP for Humans." -name = "requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.24.0" - -[package.dependencies] -certifi = ">=2017.4.17" -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" -optional = false -python-versions = "*" -version = "3.0.0" - -[package.dependencies] -requests = "*" - -[package.extras] -dev = ["coverage", "pre-commit", "pytest", "pytest-cov", "tox"] - -[[package]] -category = "main" -description = "A multipurpose bot and web framework" -name = "royalnet" -optional = false -python-versions = ">=3.8,<4.0" -version = "5.10.3" - -[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" - -[package.dependencies.coloredlogs] -optional = true -version = ">=10.0,<11.0" - -[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" - -[package.dependencies.pynacl] -optional = true -version = ">=1.3.0,<2.0.0" - -[package.dependencies.python-multipart] -optional = true -version = ">=0.0.5,<0.0.6" - -[package.dependencies.python_telegram_bot] -optional = true -version = ">=12.2.0,<13.0.0" - -[package.dependencies.sentry_sdk] -optional = true -version = ">=0.13.2,<0.14.0" - -[package.dependencies.sqlalchemy] -optional = true -version = ">=1.3.10,<2.0.0" - -[package.dependencies.starlette] -optional = true -version = ">=0.12.13,<0.13.0" - -[package.dependencies.uvicorn] -optional = true -version = ">=0.10.7,<0.11.0" - -[package.dependencies.websockets] -optional = true -version = ">=8.1,<9.0" - -[package.dependencies.youtube_dl] -optional = true -version = "*" - -[package.extras] -alchemy_easy = ["sqlalchemy (>=1.3.10,<2.0.0)", "psycopg2_binary (>=2.8.4,<3.0.0)", "bcrypt (>=3.1.7,<4.0.0)"] -alchemy_hard = ["sqlalchemy (>=1.3.10,<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" -optional = false -python-versions = "~=3.6" -version = "3.2" - -[[package]] -category = "main" -description = "Python client for Sentry (https://getsentry.com)" -name = "sentry-sdk" -optional = false -python-versions = "*" -version = "0.13.5" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.10.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -beam = ["beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -flask = ["flask (>=0.11)", "blinker (>=1.1)"] -pyspark = ["pyspark (>=2.4.4)"] -rq = ["0.6"] -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]] -category = "main" -description = "Database Abstraction Library" -name = "sqlalchemy" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.18" - -[package.extras] -mssql = ["pyodbc"] -mssql_pymssql = ["pymssql"] -mssql_pyodbc = ["pyodbc"] -mysql = ["mysqlclient"] -oracle = ["cx-oracle"] -postgresql = ["psycopg2"] -postgresql_pg8000 = ["pg8000"] -postgresql_psycopg2binary = ["psycopg2-binary"] -postgresql_psycopg2cffi = ["psycopg2cffi"] -pymysql = ["pymysql"] - -[[package]] -category = "main" -description = "The little ASGI library that shines." -name = "starlette" -optional = 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" -optional = false -python-versions = "*" -version = "1.0.2" - -[package.dependencies] -cachetools = ">=3.0.0" -pycryptodomex = ">=3.7.0" -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" -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" -optional = false -python-versions = ">= 3.5" -version = "6.0.4" - -[[package]] -category = "main" -description = "tzinfo object for the local timezone" -name = "tzlocal" -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" -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)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] - -[[package]] -category = "main" -description = "The lightning-fast ASGI server." -name = "uvicorn" -optional = false -python-versions = "*" -version = "0.10.9" - -[package.dependencies] -click = ">=7.0.0,<8.0.0" -h11 = ">=0.9.0,<0.10.0" -httptools = "0.0.13" -uvloop = ">=0.14.0" -websockets = ">=8.0.0,<9.0.0" - -[[package]] -category = "main" -description = "Fast implementation of asyncio event loop on top of libuv" -marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"pypy\"" -name = "uvloop" -optional = false -python-versions = "*" -version = "0.14.0" - -[[package]] -category = "main" -description = "Library for working with Valve's VDF text format" -name = "vdf" -optional = false -python-versions = "*" -version = "3.3" - -[[package]] -category = "main" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -name = "websockets" -optional = false -python-versions = ">=3.6.1" -version = "8.1" - -[[package]] -category = "main" -description = "Yet another URL library" -name = "yarl" -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 = "ff4adf9a29095096d1daf6aa1decde76d0bd045d614b589d954199d1e512316e" - python-versions = "^3.8" - -[metadata.files] -aiohttp = [ - {file = "aiohttp-3.6.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e"}, - {file = "aiohttp-3.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec"}, - {file = "aiohttp-3.6.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48"}, - {file = "aiohttp-3.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59"}, - {file = "aiohttp-3.6.2-cp36-cp36m-win32.whl", hash = "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a"}, - {file = "aiohttp-3.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17"}, - {file = "aiohttp-3.6.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a"}, - {file = "aiohttp-3.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd"}, - {file = "aiohttp-3.6.2-cp37-cp37m-win32.whl", hash = "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"}, - {file = "aiohttp-3.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654"}, - {file = "aiohttp-3.6.2-py3-none-any.whl", hash = "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4"}, - {file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"}, -] -async-timeout = [ - {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, - {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, -] -attrs = [ - {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, - {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, -] -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"}, -] -cachetools = [ - {file = "cachetools-4.1.1-py3-none-any.whl", hash = "sha256:513d4ff98dd27f85743a8dc0e92f55ddb1b49e060c2d5961512855cda2c01a98"}, - {file = "cachetools-4.1.1.tar.gz", hash = "sha256:bbaa39c3dede00175df2dc2b03d0cf18dd2d32a7de7beb68072d13043c9edb20"}, -] -certifi = [ - {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, - {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"}, -] -chardet = [ - {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, - {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, -] -click = [ - {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, - {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, -] -colorama = [ - {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, - {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, -] -coloredlogs = [ - {file = "coloredlogs-10.0-py2.py3-none-any.whl", hash = "sha256:34fad2e342d5a559c31b6c889e8d14f97cb62c47d9a2ae7b5ed14ea10a79eff8"}, - {file = "coloredlogs-10.0.tar.gz", hash = "sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"}, -] -cryptography = [ - {file = "cryptography-2.9.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:daf54a4b07d67ad437ff239c8a4080cfd1cc7213df57d33c97de7b4738048d5e"}, - {file = "cryptography-2.9.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3b3eba865ea2754738616f87292b7f29448aec342a7c720956f8083d252bf28b"}, - {file = "cryptography-2.9.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:c447cf087cf2dbddc1add6987bbe2f767ed5317adb2d08af940db517dd704365"}, - {file = "cryptography-2.9.2-cp27-cp27m-win32.whl", hash = "sha256:f118a95c7480f5be0df8afeb9a11bd199aa20afab7a96bcf20409b411a3a85f0"}, - {file = "cryptography-2.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:c4fd17d92e9d55b84707f4fd09992081ba872d1a0c610c109c18e062e06a2e55"}, - {file = "cryptography-2.9.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d0d5aeaedd29be304848f1c5059074a740fa9f6f26b84c5b63e8b29e73dfc270"}, - {file = "cryptography-2.9.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e4014639d3d73fbc5ceff206049c5a9a849cefd106a49fa7aaaa25cc0ce35cf"}, - {file = "cryptography-2.9.2-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:96c080ae7118c10fcbe6229ab43eb8b090fccd31a09ef55f83f690d1ef619a1d"}, - {file = "cryptography-2.9.2-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e993468c859d084d5579e2ebee101de8f5a27ce8e2159959b6673b418fd8c785"}, - {file = "cryptography-2.9.2-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:88c881dd5a147e08d1bdcf2315c04972381d026cdb803325c03fe2b4a8ed858b"}, - {file = "cryptography-2.9.2-cp35-cp35m-win32.whl", hash = "sha256:651448cd2e3a6bc2bb76c3663785133c40d5e1a8c1a9c5429e4354201c6024ae"}, - {file = "cryptography-2.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:726086c17f94747cedbee6efa77e99ae170caebeb1116353c6cf0ab67ea6829b"}, - {file = "cryptography-2.9.2-cp36-cp36m-win32.whl", hash = "sha256:091d31c42f444c6f519485ed528d8b451d1a0c7bf30e8ca583a0cac44b8a0df6"}, - {file = "cryptography-2.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:bb1f0281887d89617b4c68e8db9a2c42b9efebf2702a3c5bf70599421a8623e3"}, - {file = "cryptography-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:18452582a3c85b96014b45686af264563e3e5d99d226589f057ace56196ec78b"}, - {file = "cryptography-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:22e91636a51170df0ae4dcbd250d318fd28c9f491c4e50b625a49964b24fe46e"}, - {file = "cryptography-2.9.2-cp38-cp38-win32.whl", hash = "sha256:844a76bc04472e5135b909da6aed84360f522ff5dfa47f93e3dd2a0b84a89fa0"}, - {file = "cryptography-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:1dfa985f62b137909496e7fc182dac687206d8d089dd03eaeb28ae16eec8e7d5"}, - {file = "cryptography-2.9.2.tar.gz", hash = "sha256:a0c30272fb4ddda5f5ffc1089d7405b7a71b0b0f51993cb4e5dbb4590b2fc229"}, -] -dateparser = [ - {file = "dateparser-0.7.6-py2.py3-none-any.whl", hash = "sha256:7552c994f893b5cb8fcf103b4cd2ff7f57aab9bfd2619fdf0cf571c0740fd90b"}, - {file = "dateparser-0.7.6.tar.gz", hash = "sha256:e875efd8c57c85c2d02b238239878db59ff1971f5a823457fcc69e493bf6ebfa"}, -] -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"}, -] -h11 = [ - {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, - {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, -] -httptools = [ - {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, -] -humanfriendly = [ - {file = "humanfriendly-8.2-py2.py3-none-any.whl", hash = "sha256:e78960b31198511f45fd455534ae7645a6207d33e512d2e842c766d15d9c8080"}, - {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, -] -idna = [ - {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, - {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, -] -multidict = [ - {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"}, - {file = "multidict-4.7.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a"}, - {file = "multidict-4.7.6-cp35-cp35m-win32.whl", hash = "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5"}, - {file = "multidict-4.7.6-cp35-cp35m-win_amd64.whl", hash = "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3"}, - {file = "multidict-4.7.6-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87"}, - {file = "multidict-4.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2"}, - {file = "multidict-4.7.6-cp36-cp36m-win32.whl", hash = "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7"}, - {file = "multidict-4.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463"}, - {file = "multidict-4.7.6-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"}, - {file = "multidict-4.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255"}, - {file = "multidict-4.7.6-cp37-cp37m-win32.whl", hash = "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507"}, - {file = "multidict-4.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c"}, - {file = "multidict-4.7.6-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b"}, - {file = "multidict-4.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7"}, - {file = "multidict-4.7.6-cp38-cp38-win32.whl", hash = "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d"}, - {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"}, - {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:08507efbe532029adee21b8d4c999170a83760d38249936038bd0602327029b5"}, - {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b9a8b391c2b0321e0cd7ec6b4cfcc3dd6349347bd1207d48bcb752aa6c553a66"}, - {file = "psycopg2_binary-2.8.5-cp27-cp27m-win32.whl", hash = "sha256:3286541b9d85a340ee4ed42732d15fc1bb441dc500c97243a768154ab8505bb5"}, - {file = "psycopg2_binary-2.8.5-cp27-cp27m-win_amd64.whl", hash = "sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac"}, - {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ba13346ff6d3eb2dca0b6fa0d8a9d999eff3dcd9b55f3a890f12b0b6362b2b38"}, - {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:c8830b7d5f16fd79d39b21e3d94f247219036b29b30c8270314c46bf8b732389"}, - {file = "psycopg2_binary-2.8.5-cp34-cp34m-win32.whl", hash = "sha256:51f7823f1b087d2020d8e8c9e6687473d3d239ba9afc162d9b2ab6e80b53f9f9"}, - {file = "psycopg2_binary-2.8.5-cp34-cp34m-win_amd64.whl", hash = "sha256:107d9be3b614e52a192719c6bf32e8813030020ea1d1215daa86ded9a24d8b04"}, - {file = "psycopg2_binary-2.8.5-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:930315ac53dc65cbf52ab6b6d27422611f5fb461d763c531db229c7e1af6c0b3"}, - {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:6bb2dd006a46a4a4ce95201f836194eb6a1e863f69ee5bab506673e0ca767057"}, - {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3939cf75fc89c5e9ed836e228c4a63604dff95ad19aed2bbf71d5d04c15ed5ce"}, - {file = "psycopg2_binary-2.8.5-cp35-cp35m-win32.whl", hash = "sha256:a20299ee0ea2f9cca494396ac472d6e636745652a64a418b39522c120fd0a0a4"}, - {file = "psycopg2_binary-2.8.5-cp35-cp35m-win_amd64.whl", hash = "sha256:cc30cb900f42c8a246e2cb76539d9726f407330bc244ca7729c41a44e8d807fb"}, - {file = "psycopg2_binary-2.8.5-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:40abc319f7f26c042a11658bf3dd3b0b3bceccf883ec1c565d5c909a90204434"}, - {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:702f09d8f77dc4794651f650828791af82f7c2efd8c91ae79e3d9fe4bb7d4c98"}, - {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d1a8b01f6a964fec702d6b6dac1f91f2b9f9fe41b310cbb16c7ef1fac82df06d"}, - {file = "psycopg2_binary-2.8.5-cp36-cp36m-win32.whl", hash = "sha256:17a0ea0b0eabf07035e5e0d520dabc7950aeb15a17c6d36128ba99b2721b25b1"}, - {file = "psycopg2_binary-2.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:e004db88e5a75e5fdab1620fb9f90c9598c2a195a594225ac4ed2a6f1c23e162"}, - {file = "psycopg2_binary-2.8.5-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:a34826d6465c2e2bbe9d0605f944f19d2480589f89863ed5f091943be27c9de4"}, - {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cac918cd7c4c498a60f5d2a61d4f0a6091c2c9490d81bc805c963444032d0dab"}, - {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7b832d76cc65c092abd9505cc670c4e3421fd136fb6ea5b94efbe4c146572505"}, - {file = "psycopg2_binary-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:bb0608694a91db1e230b4a314e8ed00ad07ed0c518f9a69b83af2717e31291a3"}, - {file = "psycopg2_binary-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:eb2f43ae3037f1ef5e19339c41cf56947021ac892f668765cd65f8ab9814192e"}, - {file = "psycopg2_binary-2.8.5-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:07cf82c870ec2d2ce94d18e70c13323c89f2f2a2628cbf1feee700630be2519a"}, - {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a69970ee896e21db4c57e398646af9edc71c003bc52a3cc77fb150240fefd266"}, - {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7036ccf715925251fac969f4da9ad37e4b7e211b1e920860148a10c0de963522"}, - {file = "psycopg2_binary-2.8.5-cp38-cp38-win32.whl", hash = "sha256:8f74e631b67482d504d7e9cf364071fc5d54c28e79a093ff402d5f8f81e23bfa"}, - {file = "psycopg2_binary-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:fa466306fcf6b39b8a61d003123d442b23707d635a5cb05ac4e1b62cc79105cd"}, -] -pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, -] -pycryptodomex = [ - {file = "pycryptodomex-3.9.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:c0d085c8187a1e4d3402f626c9e438b5861151ab132d8761d9c5ce6491a87761"}, - {file = "pycryptodomex-3.9.8-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1714675fb4ac29a26ced38ca22eb8ffd923ac851b7a6140563863194d7158422"}, - {file = "pycryptodomex-3.9.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c990f2c58f7c67688e9e86e6557ed05952669ff6f1343e77b459007d85f7df00"}, - {file = "pycryptodomex-3.9.8-cp27-cp27m-win32.whl", hash = "sha256:9fd758e5e2fe02d57860b85da34a1a1e7037155c4eadc2326fc7af02f9cae214"}, - {file = "pycryptodomex-3.9.8-cp27-cp27m-win_amd64.whl", hash = "sha256:b2d756620078570d3f940c84bc94dd30aa362b795cce8b2723300a8800b87f1c"}, - {file = "pycryptodomex-3.9.8-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2710fc8d83b3352b370db932b3710033b9d630b970ff5aaa3e7458b5336e3b32"}, - {file = "pycryptodomex-3.9.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2199708ebeed4b82eb45b10e1754292677f5a0df7d627ee91ea01290b9bab7e6"}, - {file = "pycryptodomex-3.9.8-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:8044eae59301dd392fbb4a7c5d64e1aea8ef0be2540549807ecbe703d6233d68"}, - {file = "pycryptodomex-3.9.8-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:06f5a458624c9b0e04c0086c7f84bcc578567dab0ddc816e0476b3057b18339f"}, - {file = "pycryptodomex-3.9.8-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ccbbec59bf4b74226170c54476da5780c9176bae084878fc94d9a2c841218e34"}, - {file = "pycryptodomex-3.9.8-cp35-cp35m-win32.whl", hash = "sha256:e4e1c486bf226822c8dceac81d0ec59c0a2399dbd1b9e04f03c3efa3605db677"}, - {file = "pycryptodomex-3.9.8-cp35-cp35m-win_amd64.whl", hash = "sha256:2275a663c9e744ee4eace816ef2d446b3060554c5773a92fbc79b05bf47debda"}, - {file = "pycryptodomex-3.9.8-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:93a75d1acd54efed314b82c952b39eac96ce98d241ad7431547442e5c56138aa"}, - {file = "pycryptodomex-3.9.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e42860fbe1292668b682f6dabd225fbe2a7a4fa1632f0c39881c019e93dea594"}, - {file = "pycryptodomex-3.9.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f60b3484ce4be04f5da3777c51c5140d3fe21cdd6674f2b6568f41c8130bcdeb"}, - {file = "pycryptodomex-3.9.8-cp36-cp36m-win32.whl", hash = "sha256:a2ee8ba99d33e1a434fcd27d7d0aa7964163efeee0730fe2efc9d60edae1fc71"}, - {file = "pycryptodomex-3.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:58e19560814dabf5d788b95a13f6b98279cf41a49b1e49ee6cf6c79a57adb4c9"}, - {file = "pycryptodomex-3.9.8-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:a2bc4e1a2e6ca3a18b2e0be6131a23af76fecb37990c159df6edc7da6df913e3"}, - {file = "pycryptodomex-3.9.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4e0b27697fa1621c6d3d3b4edeec723c2e841285de6a8d378c1962da77b349be"}, - {file = "pycryptodomex-3.9.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3caa32cf807422adf33c10c88c22e9e2e08b9d9d042f12e1e25fe23113dd618f"}, - {file = "pycryptodomex-3.9.8-cp37-cp37m-win32.whl", hash = "sha256:89be1bf55e50116fe7e493a7c0c483099770dd7f81b87ac8d04a43b1a203e259"}, - {file = "pycryptodomex-3.9.8-cp37-cp37m-win_amd64.whl", hash = "sha256:17272d06e4b2f6455ee2cbe93e8eb50d9450a5dc6223d06862ee1ea5d1235861"}, - {file = "pycryptodomex-3.9.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea4d4b58f9bc34e224ef4b4604a6be03d72ef1f8c486391f970205f6733dbc46"}, - {file = "pycryptodomex-3.9.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8fcdda24dddf47f716400d54fc7f75cadaaba1dd47cc127e59d752c9c0fc3c48"}, - {file = "pycryptodomex-3.9.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ae6379350a09339109e9b6f419bb2c3f03d3e441f4b0f5b8ca699d47cc9ff7e"}, - {file = "pycryptodomex-3.9.8-cp38-cp38-win32.whl", hash = "sha256:dc2bed32c7b138f1331794e454a953360c8cedf3ee62ae31f063822da6007489"}, - {file = "pycryptodomex-3.9.8-cp38-cp38-win_amd64.whl", hash = "sha256:914fbb18e29c54585e6aa39d300385f90d0fa3b3cc02ed829b08f95c1acf60c2"}, - {file = "pycryptodomex-3.9.8-cp39-cp39-manylinux1_i686.whl", hash = "sha256:35b9c9177a9fe7288b19dd41554c9c8ca1063deb426dd5a02e7e2a7416b6bd11"}, - {file = "pycryptodomex-3.9.8-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:e070a1f91202ed34c396be5ea842b886f6fa2b90d2db437dc9fb35a26c80c060"}, - {file = "pycryptodomex-3.9.8.tar.gz", hash = "sha256:48cc2cfc251f04a6142badeb666d1ff49ca6fdfc303fd72579f62b768aaa52b9"}, -] -pynacl = [ - {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, - {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"}, - {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"}, - {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"}, - {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"}, - {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"}, - {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"}, - {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"}, - {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"}, - {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"}, - {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"}, - {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"}, - {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"}, - {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, - {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, -] -python-multipart = [ - {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, -] -python-telegram-bot = [ - {file = "python-telegram-bot-12.8.tar.gz", hash = "sha256:327186c56469216207dcdf8706892e58e0a62e51ef46f5143268e387bbb4edc3"}, - {file = "python_telegram_bot-12.8-py2.py3-none-any.whl", hash = "sha256:7eebed539ccacf77896cff9e41d1f68746b8ff3ca4da1e2e59285e9c749cb050"}, -] -pytz = [ - {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, - {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, -] -regex = [ - {file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"}, - {file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"}, - {file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"}, - {file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"}, - {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"}, - {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"}, - {file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"}, - {file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"}, - {file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"}, - {file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"}, - {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"}, - {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"}, - {file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"}, - {file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"}, - {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"}, - {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"}, - {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"}, - {file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"}, - {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"}, - {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"}, - {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"}, -] -requests = [ - {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, - {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, -] -riotwatcher = [ - {file = "riotwatcher-3.0.0-py2.py3-none-any.whl", hash = "sha256:f00346692cd05c82450d7cfbdbf94e0de9553179daf612d08d1ffb163a091945"}, - {file = "riotwatcher-3.0.0.tar.gz", hash = "sha256:bf8b8eb7e13c794730c18cd7846513cf22295a068204433117ce4d83a25b0fd2"}, -] -royalnet = [ - {file = "royalnet-5.10.3-py3-none-any.whl", hash = "sha256:1042a7383e26dbc76d03289d73f3c1b4d167cf860e272397b88ea54db0af513d"}, - {file = "royalnet-5.10.3.tar.gz", hash = "sha256:0232279024a3fd92c374770904443d5a0d7537dd0bf360e6c3f4e47068719fc0"}, -] -royalspells = [ - {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, -] -sentry-sdk = [ - {file = "sentry-sdk-0.13.5.tar.gz", hash = "sha256:c6b919623e488134a728f16326c6f0bcdab7e3f59e7f4c472a90eea4d6d8fe82"}, - {file = "sentry_sdk-0.13.5-py2.py3-none-any.whl", hash = "sha256:05285942901d38c7ce2498aba50d8e87b361fc603281a5902dda98f3f8c5e145"}, -] -six = [ - {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, - {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"}, -] -starlette = [ - {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, -] -steam = [ - {file = "steam-1.0.2.tar.gz", hash = "sha256:ca7c026848338ca2a004c0cb73d362c94e5c1a74815c8605d34fce3a6662f9c0"}, -] -toml = [ - {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, - {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, -] -tornado = [ - {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"}, - {file = "tornado-6.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740"}, - {file = "tornado-6.0.4-cp36-cp36m-win32.whl", hash = "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673"}, - {file = "tornado-6.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a"}, - {file = "tornado-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6"}, - {file = "tornado-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b"}, - {file = "tornado-6.0.4-cp38-cp38-win32.whl", hash = "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52"}, - {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"}, - {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, -] -tzlocal = [ - {file = "tzlocal-2.1-py2.py3-none-any.whl", hash = "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4"}, - {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"}, -] -uvicorn = [ - {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, - {file = "uvicorn-0.10.9.tar.gz", hash = "sha256:c010df69d16e27f1a18481316325b4fd23f562c1fac050915fc03a397d0f6b64"}, -] -uvloop = [ - {file = "uvloop-0.14.0-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd"}, - {file = "uvloop-0.14.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:4544dcf77d74f3a84f03dd6278174575c44c67d7165d4c42c71db3fdc3860726"}, - {file = "uvloop-0.14.0-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:b4f591aa4b3fa7f32fb51e2ee9fea1b495eb75b0b3c8d0ca52514ad675ae63f7"}, - {file = "uvloop-0.14.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f07909cd9fc08c52d294b1570bba92186181ca01fe3dc9ffba68955273dd7362"}, - {file = "uvloop-0.14.0-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:afd5513c0ae414ec71d24f6f123614a80f3d27ca655a4fcf6cabe50994cc1891"}, - {file = "uvloop-0.14.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e7514d7a48c063226b7d06617cbb12a14278d4323a065a8d46a7962686ce2e95"}, - {file = "uvloop-0.14.0-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:bcac356d62edd330080aed082e78d4b580ff260a677508718f88016333e2c9c5"}, - {file = "uvloop-0.14.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09"}, - {file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"}, -] -vdf = [ - {file = "vdf-3.3-py2.py3-none-any.whl", hash = "sha256:f88db3a3e66e7264da7fdacf0ffa1d99be52dd30510b2c1a1340171b227472e4"}, - {file = "vdf-3.3.tar.gz", hash = "sha256:9193901ce20ee08391c1d5044234b5da021d939b00ce879f5aae0a1a759577bc"}, -] -websockets = [ - {file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"}, - {file = "websockets-8.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170"}, - {file = "websockets-8.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8"}, - {file = "websockets-8.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb"}, - {file = "websockets-8.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5"}, - {file = "websockets-8.1-cp36-cp36m-win32.whl", hash = "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a"}, - {file = "websockets-8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5"}, - {file = "websockets-8.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989"}, - {file = "websockets-8.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d"}, - {file = "websockets-8.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779"}, - {file = "websockets-8.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8"}, - {file = "websockets-8.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422"}, - {file = "websockets-8.1-cp37-cp37m-win32.whl", hash = "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc"}, - {file = "websockets-8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308"}, - {file = "websockets-8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092"}, - {file = "websockets-8.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485"}, - {file = "websockets-8.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1"}, - {file = "websockets-8.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55"}, - {file = "websockets-8.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824"}, - {file = "websockets-8.1-cp38-cp38-win32.whl", hash = "sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36"}, - {file = "websockets-8.1-cp38-cp38-win_amd64.whl", hash = "sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b"}, - {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"}, -] diff --git a/pyproject.toml b/pyproject.toml index 3bb96ae2..a3090b3a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ steam = "*" [tool.poetry.dependencies.royalnet] - version = "~5.10.3" + version = "~5.10.4" # Maybe... there is a way to make these selectable? extras = [ "telegram", From 347fd489cab35829714ef83864c55c89916b5fd3 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 22 Jul 2020 01:39:04 +0200 Subject: [PATCH 218/227] Start work on the osu updater --- royalpack/commands/__init__.py | 2 + royalpack/commands/osu.py | 71 ++++++++++++++++++++++ royalpack/stars/__init__.py | 2 + royalpack/stars/api_auth_login_osu.py | 86 +++++++++++++++++++++++++++ royalpack/tables/__init__.py | 2 + royalpack/tables/osu.py | 55 +++++++++++++++++ royalpack/types/__init__.py | 2 + royalpack/types/oauth_refresh.py | 14 +++++ 8 files changed, 234 insertions(+) create mode 100644 royalpack/commands/osu.py create mode 100644 royalpack/stars/api_auth_login_osu.py create mode 100644 royalpack/tables/osu.py create mode 100644 royalpack/types/oauth_refresh.py diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index e6d4b17a..b1902a3f 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -37,6 +37,7 @@ 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! available_commands = [ @@ -78,6 +79,7 @@ available_commands = [ TreasureCommand, TriviaCommand, UserinfoCommand, + OsuCommand, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/commands/osu.py b/royalpack/commands/osu.py new file mode 100644 index 00000000..b8cc1ec7 --- /dev/null +++ b/royalpack/commands/osu.py @@ -0,0 +1,71 @@ +from typing import * +import itsdangerous + +from royalnet.backpack import tables as rbt +import royalnet.commands as rc + +from .abstract.linker import LinkerCommand +from ..types import Updatable +from ..stars.api_auth_login_osu import ApiAuthLoginOsuStar + + +class OsuCommand(LinkerCommand): + name = "osu" + + description = "Connetti e sincronizza il tuo account di osu!" + + @property + def client_id(self): + return self.config[self.name]['client_id'] + + @property + def client_secret(self): + return self.config[self.name]['client_secret'] + + @property + def base_url(self): + return self.config['base_url'] + + @property + def secret_key(self): + return self.config['secret_key'] + + async def get_updatables_of_user(self, session, user: rbt.User) -> List[Updatable]: + return [] + + async def get_updatables(self, session) -> List[Updatable]: + return [] + + async def create(self, + session, + user: rbt.User, + args: rc.CommandArgs, + data: Optional[rc.CommandData] = None) -> Optional[Updatable]: + serializer = itsdangerous.URLSafeSerializer(self.secret_key, salt="osu") + await data.reply("🔑 [b]Login necessario[/b]\n" + f"[url=https://osu.ppy.sh/oauth/authorize" + f"?client_id={self.client_id}" + f"&redirect_uri={self.base_url}{ApiAuthLoginOsuStar.path}" + f"&response_type=code" + f"&state={serializer.dumps(user.uid)}]" + f"Connetti osu! a Royalnet" + f"[/url]") + return None + + async def update(self, session, obj, change: Callable[[str, Any], Awaitable[None]]): + pass + + async def on_increase(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + pass + + async def on_unchanged(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + pass + + async def on_decrease(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: + pass + + async def on_first(self, session, obj: Updatable, attribute: str, old: None, new: Any) -> None: + pass + + async def on_reset(self, session, obj: Updatable, attribute: str, old: Any, new: None) -> None: + pass diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 9676dbf8..07a22617 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -13,6 +13,7 @@ from .api_cvstats_avg import ApiCvstatsAvgStar from .api_user_ryg import ApiUserRygStar from .api_user_ryg_list import ApiUserRygListStar from .api_user_avatar import ApiUserAvatarStar +from .api_auth_login_osu import ApiAuthLoginOsuStar # Enter the PageStars of your Pack here! available_page_stars = [ @@ -30,6 +31,7 @@ available_page_stars = [ ApiUserRygStar, ApiUserRygListStar, ApiUserAvatarStar, + ApiAuthLoginOsuStar, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/stars/api_auth_login_osu.py b/royalpack/stars/api_auth_login_osu.py new file mode 100644 index 00000000..4a9e3cc1 --- /dev/null +++ b/royalpack/stars/api_auth_login_osu.py @@ -0,0 +1,86 @@ +import royalnet.utils as ru +import royalnet.backpack.tables as rbt +import royalnet.constellation.api as rca +import itsdangerous +import aiohttp +import aiohttp.client_exceptions +import datetime +from ..types import oauth_refresh +from ..tables import Osu, FiorygiTransaction + + +class ApiAuthLoginOsuStar(rca.ApiStar): + path = "/api/auth/login/osu/v1" + + parameters = { + "get": { + "code": "The code returned by the osu! API.", + "state": "(Optional) The state payload generated by the osu! command to link a new account. " + "If missing, just login." + } + } + + auth = { + "get": False, + } + + tags = ["auth"] + + @property + def client_id(self): + return self.config['osu']['client_id'] + + @property + def client_secret(self): + return self.config['osu']['client_secret'] + + @property + def base_url(self): + return self.config['base_url'] + + @property + def secret_key(self): + return self.config['secret_key'] + + @rca.magic + async def get(self, data: rca.ApiData) -> ru.JSON: + """Login to Royalnet with your osu! account.""" + OsuT = self.alchemy.get(Osu) + + code = data.str("code") + state = data.str("state", optional=True) + + if state is not None: + serializer = itsdangerous.URLSafeSerializer(self.config["secret_key"], salt="osu") + uid = serializer.loads(state) + user = await rbt.User.find(self.alchemy, data.session, uid) + else: + user = None + + try: + t = await oauth_refresh(url="https://osu.ppy.sh/oauth/token", + client_id=self.client_id, + client_secret=self.client_secret, + redirect_uri=f"{self.base_url}{self.path}", + refresh_code=code) + except aiohttp.client_exceptions.ClientResponseError: + raise rca.ForbiddenError("osu! API returned an error in the OAuth token exchange") + + async with aiohttp.ClientSession(headers={"Authorization": f"Bearer {t['access_token']}"}) as session: + async with session.get("https://osu.ppy.sh/api/v2/me/") as response: + m = await response.json() + + if user is not None: + osu = OsuT( + user=user, + access_token=t["access_token"], + refresh_token=t["refresh_token"], + expiration_date=datetime.datetime.now() + datetime.timedelta(seconds=t["expires_in"]), + osu_id=m["id"], + username=m["username"] + ) + + data.session.add(osu) + await data.session_commit() + + raise rca.MethodNotImplementedError() diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 6eac5697..e951bb5c 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -18,6 +18,7 @@ from .mmevents import MMEvent from .mmresponse import MMResponse from .cvstats import Cvstats from .treasure import Treasure +from .osu import Osu # Enter the tables of your Pack here! available_tables = [ @@ -40,6 +41,7 @@ available_tables = [ MMResponse, Cvstats, Treasure, + Osu, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/osu.py b/royalpack/tables/osu.py new file mode 100644 index 00000000..bb19b5db --- /dev/null +++ b/royalpack/tables/osu.py @@ -0,0 +1,55 @@ +from typing import * +import aiohttp +import datetime +from sqlalchemy import * +from sqlalchemy.orm import relationship, backref +from sqlalchemy.ext.declarative import declared_attr + +from ..types import Updatable, oauth_refresh + + +# noinspection PyAttributeOutsideInit +class Osu(Updatable): + __tablename__ = "osu" + + @declared_attr + def user_id(self): + return Column(Integer, ForeignKey("users.uid")) + + @declared_attr + def user(self): + return relationship("User", backref=backref("osu")) + + @declared_attr + def access_token(self): + return Column(String, nullable=False) + + @declared_attr + def refresh_token(self): + return Column(String, nullable=False) + + @declared_attr + def expiration_date(self): + return Column(DateTime, nullable=False) + + @declared_attr + def osu_id(self): + return Column(Integer, primary_key=True) + + @declared_attr + def username(self): + return Column(String) + + async def refresh(self, *, client_id, client_secret, base_url, path): + j = await oauth_refresh(url="https://osu.ppy.sh/oauth/token", + client_id=client_id, + client_secret=client_secret, + redirect_uri=f"{base_url}{path}", + refresh_code=self.refresh_token) + self.access_token = j["access_token"] + self.refresh_token = j["refresh_token"] + self.expiration_date = datetime.datetime.now() + datetime.timedelta(seconds=j["expires_in"]) + + async def refresh_if_expired(self, *, client_id, client_secret, base_url, path): + if datetime.datetime.now() >= self.expiration_date: + await self.refresh(client_id=client_id, client_secret=client_secret, base_url=base_url, path=path) diff --git a/royalpack/types/__init__.py b/royalpack/types/__init__.py index ed67a89c..4e8f08a7 100644 --- a/royalpack/types/__init__.py +++ b/royalpack/types/__init__.py @@ -11,6 +11,7 @@ from .brawlhallametal import BrawlhallaMetal from .brawlhallarank import BrawlhallaRank from .pollmood import PollMood from .updatable import Updatable +from .oauth_refresh import oauth_refresh __all__ = [ @@ -28,4 +29,5 @@ __all__ = [ "BrawlhallaTier", "PollMood", "Updatable", + "oauth_refresh", ] diff --git a/royalpack/types/oauth_refresh.py b/royalpack/types/oauth_refresh.py new file mode 100644 index 00000000..62e3e6b2 --- /dev/null +++ b/royalpack/types/oauth_refresh.py @@ -0,0 +1,14 @@ +import aiohttp + + +async def oauth_refresh(*, url, client_id, client_secret, redirect_uri, refresh_code): + async with aiohttp.ClientSession() as session: + async with session.post(url, data={ + "client_id": client_id, + "client_secret": client_secret, + "code": refresh_code, + "grant_type": "authorization_code", + "redirect_uri": redirect_uri + }) as response: + j = await response.json() + return j From 673b05ddb37b457e8d35f8a3cc0a437fa7bfadc2 Mon Sep 17 00:00:00 2001 From: Cookie <58516648+Cookie-CHR@users.noreply.github.com> Date: Wed, 22 Jul 2020 14:21:06 +0200 Subject: [PATCH 219/227] aggiunto comando answer --- royalpack/commands/answer.py | 82 ++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 royalpack/commands/answer.py diff --git a/royalpack/commands/answer.py b/royalpack/commands/answer.py new file mode 100644 index 00000000..481147d4 --- /dev/null +++ b/royalpack/commands/answer.py @@ -0,0 +1,82 @@ +from typing import * +import royalnet +import royalnet.commands as rc +import random +import datetime + + +class AnswerCommand(rc.Command): + name: str = "answer" + + description: str = "Fai una domanda al bot, che possa essere risposta con un sì o un no: lui ti risponderà!" + + syntax: str = "" + + _answers = [ + #Cerchiamo di tenere bilanciate le tre colonne, o almeno le prime due. + #Se avete un'idea ma metterebbe troppe opzioni in un'unica categoria, mettetela sotto commento. + + #risposte "sì" + "Sì.", + "Decisamente sì!", + "Uhm, secondo me sì.", + "Sì! Sì! SÌ!", + "Yup.", + "👍", + "Direi proprio di sì.", + "Assolutamente sì.", + "Ma certo!", + "✔️", + "👌", + "Esatto!", + "Senz'altro!", + "Ovviamente.", + "Questa domanda ha risposta affermativa.", + "Hell yeah.", + + #risposte "no" + "No.", + "Decisamente no!", + "Uhm, secondo me sì.", + "No, no, e ancora NO!", + "Nope.", + "👎", + "Direi proprio di no.", + "Assolutamente no.", + "Certo che no!", + "✖️", + "🙅", + "Neanche per idea!", + "Neanche per sogno!", + "Niente affatto!", + "Questa domanda ha risposta negativa.", + "Hell no.", + + #risposte "boh" + "Boh.", + "E io che ne so?!", + "Non so proprio rispondere", + "Non lo so", + "Mi rifiuto di rispondere alla domanda!", + "Non parlerò senza il mio avvocato!", + "Dunno.", + "Perché lo chiedi a me?", + "🤷 Ah, non lo so io! ¯\_(ツ)_/¯", + "🤷", + "¯\_(ツ)_/¯", + "No idea.", + "Dunno.", + "Boooooh!", + "Non ne ho la più pallida idea.", + ] + + async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: + + h = hash(datetime.datetime.now()) + + r = random.Random(x=h) + + message = r.sample(self._answers, 1)[0] + await data.reply(message) + + From 14faa180edfc12ba1b45310ad25e00114b8d0c5d Mon Sep 17 00:00:00 2001 From: Cookie <58516648+Cookie-CHR@users.noreply.github.com> Date: Wed, 22 Jul 2020 14:27:30 +0200 Subject: [PATCH 220/227] added answer command Aggiunto answer --- royalpack/commands/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/royalpack/commands/__init__.py b/royalpack/commands/__init__.py index 9ce8b05e..6f93e051 100644 --- a/royalpack/commands/__init__.py +++ b/royalpack/commands/__init__.py @@ -1,5 +1,6 @@ # Imports go here! from .ahnonlosoio import AhnonlosoioCommand +from .answer import AnswerCommand from .brawlhalla import BrawlhallaCommand from .cat import CatCommand from .ciaoruozi import CiaoruoziCommand @@ -67,6 +68,7 @@ from .youtube import YoutubeCommand # Enter the commands of your Pack here! available_commands = [ AhnonlosoioCommand, + AnswerCommand, BrawlhallaCommand, CatCommand, CiaoruoziCommand, From aab1a7099ee688c27e31a76639f233a0a3755150 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 22 Jul 2020 16:21:51 +0200 Subject: [PATCH 221/227] Bump version --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a3090b3a..88791a82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.13.0" + version = "5.13.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -23,6 +23,8 @@ riotwatcher = "^3.0.0" royalspells = "^3.2" steam = "*" +sqlalchemy = "^1.3.18" +bcrypt = "^3.1.7" [tool.poetry.dependencies.royalnet] version = "~5.10.4" From 053c51714b63b5f457be73724b3312cfbb59375e Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 22 Jul 2020 16:22:03 +0200 Subject: [PATCH 222/227] Readd lockfile --- poetry.lock | 1188 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1188 insertions(+) create mode 100644 poetry.lock diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..378d7827 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1188 @@ +[[package]] +category = "main" +description = "Async http client/server framework (asyncio)" +name = "aiohttp" +optional = false +python-versions = ">=3.5.3" +version = "3.6.2" + +[package.dependencies] +async-timeout = ">=3.0,<4.0" +attrs = ">=17.3.0" +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" +optional = false +python-versions = ">=3.5.3" +version = "3.0.1" + +[[package]] +category = "main" +description = "Classes Without Boilerplate" +name = "attrs" +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"] +dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"] +docs = ["sphinx", "zope.interface"] +tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] + +[[package]] +category = "main" +description = "Modern password hashing for your software and your servers" +name = "bcrypt" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "3.1.7" + +[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" +optional = false +python-versions = "~=3.5" +version = "4.1.1" + +[[package]] +category = "main" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" +optional = false +python-versions = "*" +version = "2020.6.20" + +[[package]] +category = "main" +description = "Foreign Function Interface for Python calling C code." +name = "cffi" +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]] +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 = "*" +version = "10.0" + +[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" +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"] +docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +idna = ["idna (>=2.1)"] +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]] +category = "main" +description = "Date parsing library designed to parse dates from HTML pages" +name = "dateparser" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.7.6" + +[package.dependencies] +python-dateutil = "*" +pytz = "*" +regex = "!=2019.02.19" +tzlocal = "*" + +[[package]] +category = "main" +description = "Decorators for Humans" +name = "decorator" +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" +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"] + +[[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]] +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]] +category = "main" +description = "Human friendly output for text interfaces using Python" +name = "humanfriendly" +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]] +category = "main" +description = "multidict implementation" +name = "multidict" +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" +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" +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" +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" +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]] +category = "main" +description = "A python implmementation of GNU readline." +marker = "sys_platform == \"win32\"" +name = "pyreadline" +optional = false +python-versions = "*" +version = "2.1" + +[[package]] +category = "main" +description = "Extensions to the standard Python datetime module" +name = "python-dateutil" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +version = "2.8.1" + +[package.dependencies] +six = ">=1.5" + +[[package]] +category = "main" +description = "A streaming multipart parser for Python" +name = "python-multipart" +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" +optional = false +python-versions = "*" +version = "12.8" + +[package.dependencies] +certifi = "*" +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]] +category = "main" +description = "Alternative regular expression module, to replace re." +name = "regex" +optional = false +python-versions = "*" +version = "2020.7.14" + +[[package]] +category = "main" +description = "Python HTTP for Humans." +name = "requests" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.24.0" + +[package.dependencies] +certifi = ">=2017.4.17" +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" +optional = false +python-versions = "*" +version = "3.0.0" + +[package.dependencies] +requests = "*" + +[package.extras] +dev = ["coverage", "pre-commit", "pytest", "pytest-cov", "tox"] + +[[package]] +category = "main" +description = "A multipurpose bot and web framework" +name = "royalnet" +optional = false +python-versions = ">=3.8,<4.0" +version = "5.10.4" + +[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" + +[package.dependencies.coloredlogs] +optional = true +version = ">=10.0,<11.0" + +[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" + +[package.dependencies.pynacl] +optional = true +version = ">=1.3.0,<2.0.0" + +[package.dependencies.python-multipart] +optional = true +version = ">=0.0.5,<0.0.6" + +[package.dependencies.python_telegram_bot] +optional = true +version = ">=12.2.0,<13.0.0" + +[package.dependencies.sentry_sdk] +optional = true +version = ">=0.13.2,<0.14.0" + +[package.dependencies.sqlalchemy] +optional = true +version = ">=1.3.18,<2.0.0" + +[package.dependencies.starlette] +optional = true +version = ">=0.12.13,<0.13.0" + +[package.dependencies.uvicorn] +optional = true +version = ">=0.10.7,<0.11.0" + +[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" +optional = false +python-versions = "~=3.6" +version = "3.2" + +[[package]] +category = "main" +description = "Python client for Sentry (https://getsentry.com)" +name = "sentry-sdk" +optional = false +python-versions = "*" +version = "0.13.5" + +[package.dependencies] +certifi = "*" +urllib3 = ">=1.10.0" + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +beam = ["beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +flask = ["flask (>=0.11)", "blinker (>=1.1)"] +pyspark = ["pyspark (>=2.4.4)"] +rq = ["0.6"] +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]] +category = "main" +description = "Database Abstraction Library" +name = "sqlalchemy" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.3.18" + +[package.extras] +mssql = ["pyodbc"] +mssql_pymssql = ["pymssql"] +mssql_pyodbc = ["pyodbc"] +mysql = ["mysqlclient"] +oracle = ["cx-oracle"] +postgresql = ["psycopg2"] +postgresql_pg8000 = ["pg8000"] +postgresql_psycopg2binary = ["psycopg2-binary"] +postgresql_psycopg2cffi = ["psycopg2cffi"] +pymysql = ["pymysql"] + +[[package]] +category = "main" +description = "The little ASGI library that shines." +name = "starlette" +optional = 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" +optional = false +python-versions = "*" +version = "1.0.2" + +[package.dependencies] +cachetools = ">=3.0.0" +pycryptodomex = ">=3.7.0" +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" +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" +optional = false +python-versions = ">= 3.5" +version = "6.0.4" + +[[package]] +category = "main" +description = "tzinfo object for the local timezone" +name = "tzlocal" +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" +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)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] +socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] + +[[package]] +category = "main" +description = "The lightning-fast ASGI server." +name = "uvicorn" +optional = false +python-versions = "*" +version = "0.10.9" + +[package.dependencies] +click = ">=7.0.0,<8.0.0" +h11 = ">=0.9.0,<0.10.0" +httptools = "0.0.13" +uvloop = ">=0.14.0" +websockets = ">=8.0.0,<9.0.0" + +[[package]] +category = "main" +description = "Fast implementation of asyncio event loop on top of libuv" +marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"pypy\"" +name = "uvloop" +optional = false +python-versions = "*" +version = "0.14.0" + +[[package]] +category = "main" +description = "Library for working with Valve's VDF text format" +name = "vdf" +optional = false +python-versions = "*" +version = "3.3" + +[[package]] +category = "main" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +name = "websockets" +optional = false +python-versions = ">=3.6.1" +version = "8.1" + +[[package]] +category = "main" +description = "Yet another URL library" +name = "yarl" +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 = "6186dd82fb955af7343f43eaddc27c2eb6b9abe24b53e34bc41891e264658a89" +lock-version = "1.0" + python-versions = "^3.8" + +[metadata.files] +aiohttp = [ + {file = "aiohttp-3.6.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e"}, + {file = "aiohttp-3.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec"}, + {file = "aiohttp-3.6.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48"}, + {file = "aiohttp-3.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59"}, + {file = "aiohttp-3.6.2-cp36-cp36m-win32.whl", hash = "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a"}, + {file = "aiohttp-3.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17"}, + {file = "aiohttp-3.6.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a"}, + {file = "aiohttp-3.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd"}, + {file = "aiohttp-3.6.2-cp37-cp37m-win32.whl", hash = "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"}, + {file = "aiohttp-3.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654"}, + {file = "aiohttp-3.6.2-py3-none-any.whl", hash = "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4"}, + {file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"}, +] +async-timeout = [ + {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, + {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, +] +attrs = [ + {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, + {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, +] +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"}, +] +cachetools = [ + {file = "cachetools-4.1.1-py3-none-any.whl", hash = "sha256:513d4ff98dd27f85743a8dc0e92f55ddb1b49e060c2d5961512855cda2c01a98"}, + {file = "cachetools-4.1.1.tar.gz", hash = "sha256:bbaa39c3dede00175df2dc2b03d0cf18dd2d32a7de7beb68072d13043c9edb20"}, +] +certifi = [ + {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, + {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"}, +] +chardet = [ + {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, + {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, +] +click = [ + {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, + {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, +] +colorama = [ + {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, + {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, +] +coloredlogs = [ + {file = "coloredlogs-10.0-py2.py3-none-any.whl", hash = "sha256:34fad2e342d5a559c31b6c889e8d14f97cb62c47d9a2ae7b5ed14ea10a79eff8"}, + {file = "coloredlogs-10.0.tar.gz", hash = "sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"}, +] +cryptography = [ + {file = "cryptography-3.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ab49edd5bea8d8b39a44b3db618e4783ef84c19c8b47286bf05dfdb3efb01c83"}, + {file = "cryptography-3.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:124af7255ffc8e964d9ff26971b3a6153e1a8a220b9a685dc407976ecb27a06a"}, + {file = "cryptography-3.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:51e40123083d2f946794f9fe4adeeee2922b581fa3602128ce85ff813d85b81f"}, + {file = "cryptography-3.0-cp27-cp27m-win32.whl", hash = "sha256:dea0ba7fe6f9461d244679efa968d215ea1f989b9c1957d7f10c21e5c7c09ad6"}, + {file = "cryptography-3.0-cp27-cp27m-win_amd64.whl", hash = "sha256:8ecf9400d0893836ff41b6f977a33972145a855b6efeb605b49ee273c5e6469f"}, + {file = "cryptography-3.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0c608ff4d4adad9e39b5057de43657515c7da1ccb1807c3a27d4cf31fc923b4b"}, + {file = "cryptography-3.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:bec7568c6970b865f2bcebbe84d547c52bb2abadf74cefce396ba07571109c67"}, + {file = "cryptography-3.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:0cbfed8ea74631fe4de00630f4bb592dad564d57f73150d6f6796a24e76c76cd"}, + {file = "cryptography-3.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:a09fd9c1cca9a46b6ad4bea0a1f86ab1de3c0c932364dbcf9a6c2a5eeb44fa77"}, + {file = "cryptography-3.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ce82cc06588e5cbc2a7df3c8a9c778f2cb722f56835a23a68b5a7264726bb00c"}, + {file = "cryptography-3.0-cp35-cp35m-win32.whl", hash = "sha256:9367d00e14dee8d02134c6c9524bb4bd39d4c162456343d07191e2a0b5ec8b3b"}, + {file = "cryptography-3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:384d7c681b1ab904fff3400a6909261cae1d0939cc483a68bdedab282fb89a07"}, + {file = "cryptography-3.0-cp36-cp36m-win32.whl", hash = "sha256:4d355f2aee4a29063c10164b032d9fa8a82e2c30768737a2fd56d256146ad559"}, + {file = "cryptography-3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:45741f5499150593178fc98d2c1a9c6722df88b99c821ad6ae298eff0ba1ae71"}, + {file = "cryptography-3.0-cp37-cp37m-win32.whl", hash = "sha256:8ecef21ac982aa78309bb6f092d1677812927e8b5ef204a10c326fc29f1367e2"}, + {file = "cryptography-3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4b9303507254ccb1181d1803a2080a798910ba89b1a3c9f53639885c90f7a756"}, + {file = "cryptography-3.0-cp38-cp38-win32.whl", hash = "sha256:8713ddb888119b0d2a1462357d5946b8911be01ddbf31451e1d07eaa5077a261"}, + {file = "cryptography-3.0-cp38-cp38-win_amd64.whl", hash = "sha256:bea0b0468f89cdea625bb3f692cd7a4222d80a6bdafd6fb923963f2b9da0e15f"}, + {file = "cryptography-3.0.tar.gz", hash = "sha256:8e924dbc025206e97756e8903039662aa58aa9ba357d8e1d8fc29e3092322053"}, +] +dateparser = [ + {file = "dateparser-0.7.6-py2.py3-none-any.whl", hash = "sha256:7552c994f893b5cb8fcf103b4cd2ff7f57aab9bfd2619fdf0cf571c0740fd90b"}, + {file = "dateparser-0.7.6.tar.gz", hash = "sha256:e875efd8c57c85c2d02b238239878db59ff1971f5a823457fcc69e493bf6ebfa"}, +] +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"}, +] +h11 = [ + {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, + {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, +] +httptools = [ + {file = "httptools-0.0.13.tar.gz", hash = "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"}, +] +humanfriendly = [ + {file = "humanfriendly-8.2-py2.py3-none-any.whl", hash = "sha256:e78960b31198511f45fd455534ae7645a6207d33e512d2e842c766d15d9c8080"}, + {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"}, +] +idna = [ + {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, + {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, +] +multidict = [ + {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"}, + {file = "multidict-4.7.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a"}, + {file = "multidict-4.7.6-cp35-cp35m-win32.whl", hash = "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5"}, + {file = "multidict-4.7.6-cp35-cp35m-win_amd64.whl", hash = "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3"}, + {file = "multidict-4.7.6-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87"}, + {file = "multidict-4.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2"}, + {file = "multidict-4.7.6-cp36-cp36m-win32.whl", hash = "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7"}, + {file = "multidict-4.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463"}, + {file = "multidict-4.7.6-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"}, + {file = "multidict-4.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255"}, + {file = "multidict-4.7.6-cp37-cp37m-win32.whl", hash = "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507"}, + {file = "multidict-4.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c"}, + {file = "multidict-4.7.6-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b"}, + {file = "multidict-4.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7"}, + {file = "multidict-4.7.6-cp38-cp38-win32.whl", hash = "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d"}, + {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"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:08507efbe532029adee21b8d4c999170a83760d38249936038bd0602327029b5"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b9a8b391c2b0321e0cd7ec6b4cfcc3dd6349347bd1207d48bcb752aa6c553a66"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-win32.whl", hash = "sha256:3286541b9d85a340ee4ed42732d15fc1bb441dc500c97243a768154ab8505bb5"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27m-win_amd64.whl", hash = "sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ba13346ff6d3eb2dca0b6fa0d8a9d999eff3dcd9b55f3a890f12b0b6362b2b38"}, + {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:c8830b7d5f16fd79d39b21e3d94f247219036b29b30c8270314c46bf8b732389"}, + {file = "psycopg2_binary-2.8.5-cp34-cp34m-win32.whl", hash = "sha256:51f7823f1b087d2020d8e8c9e6687473d3d239ba9afc162d9b2ab6e80b53f9f9"}, + {file = "psycopg2_binary-2.8.5-cp34-cp34m-win_amd64.whl", hash = "sha256:107d9be3b614e52a192719c6bf32e8813030020ea1d1215daa86ded9a24d8b04"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:930315ac53dc65cbf52ab6b6d27422611f5fb461d763c531db229c7e1af6c0b3"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:6bb2dd006a46a4a4ce95201f836194eb6a1e863f69ee5bab506673e0ca767057"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3939cf75fc89c5e9ed836e228c4a63604dff95ad19aed2bbf71d5d04c15ed5ce"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-win32.whl", hash = "sha256:a20299ee0ea2f9cca494396ac472d6e636745652a64a418b39522c120fd0a0a4"}, + {file = "psycopg2_binary-2.8.5-cp35-cp35m-win_amd64.whl", hash = "sha256:cc30cb900f42c8a246e2cb76539d9726f407330bc244ca7729c41a44e8d807fb"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:40abc319f7f26c042a11658bf3dd3b0b3bceccf883ec1c565d5c909a90204434"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:702f09d8f77dc4794651f650828791af82f7c2efd8c91ae79e3d9fe4bb7d4c98"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d1a8b01f6a964fec702d6b6dac1f91f2b9f9fe41b310cbb16c7ef1fac82df06d"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-win32.whl", hash = "sha256:17a0ea0b0eabf07035e5e0d520dabc7950aeb15a17c6d36128ba99b2721b25b1"}, + {file = "psycopg2_binary-2.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:e004db88e5a75e5fdab1620fb9f90c9598c2a195a594225ac4ed2a6f1c23e162"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:a34826d6465c2e2bbe9d0605f944f19d2480589f89863ed5f091943be27c9de4"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cac918cd7c4c498a60f5d2a61d4f0a6091c2c9490d81bc805c963444032d0dab"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7b832d76cc65c092abd9505cc670c4e3421fd136fb6ea5b94efbe4c146572505"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:bb0608694a91db1e230b4a314e8ed00ad07ed0c518f9a69b83af2717e31291a3"}, + {file = "psycopg2_binary-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:eb2f43ae3037f1ef5e19339c41cf56947021ac892f668765cd65f8ab9814192e"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:07cf82c870ec2d2ce94d18e70c13323c89f2f2a2628cbf1feee700630be2519a"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a69970ee896e21db4c57e398646af9edc71c003bc52a3cc77fb150240fefd266"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7036ccf715925251fac969f4da9ad37e4b7e211b1e920860148a10c0de963522"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-win32.whl", hash = "sha256:8f74e631b67482d504d7e9cf364071fc5d54c28e79a093ff402d5f8f81e23bfa"}, + {file = "psycopg2_binary-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:fa466306fcf6b39b8a61d003123d442b23707d635a5cb05ac4e1b62cc79105cd"}, +] +pycparser = [ + {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, + {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, +] +pycryptodomex = [ + {file = "pycryptodomex-3.9.8-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:c0d085c8187a1e4d3402f626c9e438b5861151ab132d8761d9c5ce6491a87761"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1714675fb4ac29a26ced38ca22eb8ffd923ac851b7a6140563863194d7158422"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c990f2c58f7c67688e9e86e6557ed05952669ff6f1343e77b459007d85f7df00"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-win32.whl", hash = "sha256:9fd758e5e2fe02d57860b85da34a1a1e7037155c4eadc2326fc7af02f9cae214"}, + {file = "pycryptodomex-3.9.8-cp27-cp27m-win_amd64.whl", hash = "sha256:b2d756620078570d3f940c84bc94dd30aa362b795cce8b2723300a8800b87f1c"}, + {file = "pycryptodomex-3.9.8-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2710fc8d83b3352b370db932b3710033b9d630b970ff5aaa3e7458b5336e3b32"}, + {file = "pycryptodomex-3.9.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2199708ebeed4b82eb45b10e1754292677f5a0df7d627ee91ea01290b9bab7e6"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:8044eae59301dd392fbb4a7c5d64e1aea8ef0be2540549807ecbe703d6233d68"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:06f5a458624c9b0e04c0086c7f84bcc578567dab0ddc816e0476b3057b18339f"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ccbbec59bf4b74226170c54476da5780c9176bae084878fc94d9a2c841218e34"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-win32.whl", hash = "sha256:e4e1c486bf226822c8dceac81d0ec59c0a2399dbd1b9e04f03c3efa3605db677"}, + {file = "pycryptodomex-3.9.8-cp35-cp35m-win_amd64.whl", hash = "sha256:2275a663c9e744ee4eace816ef2d446b3060554c5773a92fbc79b05bf47debda"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:93a75d1acd54efed314b82c952b39eac96ce98d241ad7431547442e5c56138aa"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:e42860fbe1292668b682f6dabd225fbe2a7a4fa1632f0c39881c019e93dea594"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f60b3484ce4be04f5da3777c51c5140d3fe21cdd6674f2b6568f41c8130bcdeb"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-win32.whl", hash = "sha256:a2ee8ba99d33e1a434fcd27d7d0aa7964163efeee0730fe2efc9d60edae1fc71"}, + {file = "pycryptodomex-3.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:58e19560814dabf5d788b95a13f6b98279cf41a49b1e49ee6cf6c79a57adb4c9"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:a2bc4e1a2e6ca3a18b2e0be6131a23af76fecb37990c159df6edc7da6df913e3"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4e0b27697fa1621c6d3d3b4edeec723c2e841285de6a8d378c1962da77b349be"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3caa32cf807422adf33c10c88c22e9e2e08b9d9d042f12e1e25fe23113dd618f"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-win32.whl", hash = "sha256:89be1bf55e50116fe7e493a7c0c483099770dd7f81b87ac8d04a43b1a203e259"}, + {file = "pycryptodomex-3.9.8-cp37-cp37m-win_amd64.whl", hash = "sha256:17272d06e4b2f6455ee2cbe93e8eb50d9450a5dc6223d06862ee1ea5d1235861"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea4d4b58f9bc34e224ef4b4604a6be03d72ef1f8c486391f970205f6733dbc46"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8fcdda24dddf47f716400d54fc7f75cadaaba1dd47cc127e59d752c9c0fc3c48"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ae6379350a09339109e9b6f419bb2c3f03d3e441f4b0f5b8ca699d47cc9ff7e"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-win32.whl", hash = "sha256:dc2bed32c7b138f1331794e454a953360c8cedf3ee62ae31f063822da6007489"}, + {file = "pycryptodomex-3.9.8-cp38-cp38-win_amd64.whl", hash = "sha256:914fbb18e29c54585e6aa39d300385f90d0fa3b3cc02ed829b08f95c1acf60c2"}, + {file = "pycryptodomex-3.9.8-cp39-cp39-manylinux1_i686.whl", hash = "sha256:35b9c9177a9fe7288b19dd41554c9c8ca1063deb426dd5a02e7e2a7416b6bd11"}, + {file = "pycryptodomex-3.9.8-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:e070a1f91202ed34c396be5ea842b886f6fa2b90d2db437dc9fb35a26c80c060"}, + {file = "pycryptodomex-3.9.8.tar.gz", hash = "sha256:48cc2cfc251f04a6142badeb666d1ff49ca6fdfc303fd72579f62b768aaa52b9"}, +] +pynacl = [ + {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"}, + {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"}, + {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"}, + {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"}, + {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"}, + {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"}, + {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"}, + {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"}, + {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"}, + {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"}, + {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"}, + {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"}, + {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"}, + {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, + {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, +] +python-multipart = [ + {file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"}, +] +python-telegram-bot = [ + {file = "python-telegram-bot-12.8.tar.gz", hash = "sha256:327186c56469216207dcdf8706892e58e0a62e51ef46f5143268e387bbb4edc3"}, + {file = "python_telegram_bot-12.8-py2.py3-none-any.whl", hash = "sha256:7eebed539ccacf77896cff9e41d1f68746b8ff3ca4da1e2e59285e9c749cb050"}, +] +pytz = [ + {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, + {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, +] +regex = [ + {file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"}, + {file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"}, + {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"}, + {file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"}, + {file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"}, + {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"}, + {file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"}, + {file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"}, + {file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"}, + {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"}, + {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"}, + {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"}, +] +requests = [ + {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, + {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, +] +riotwatcher = [ + {file = "riotwatcher-3.0.0-py2.py3-none-any.whl", hash = "sha256:f00346692cd05c82450d7cfbdbf94e0de9553179daf612d08d1ffb163a091945"}, + {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"}, +] +royalspells = [ + {file = "royalspells-3.2.tar.gz", hash = "sha256:2bd4a9a66514532e35c02c3907425af48c7cb292364c4843c795719a82b25dfe"}, +] +sentry-sdk = [ + {file = "sentry-sdk-0.13.5.tar.gz", hash = "sha256:c6b919623e488134a728f16326c6f0bcdab7e3f59e7f4c472a90eea4d6d8fe82"}, + {file = "sentry_sdk-0.13.5-py2.py3-none-any.whl", hash = "sha256:05285942901d38c7ce2498aba50d8e87b361fc603281a5902dda98f3f8c5e145"}, +] +six = [ + {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, + {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"}, +] +starlette = [ + {file = "starlette-0.12.13.tar.gz", hash = "sha256:9597bc28e3c4659107c1c4a45ec32dc45e947d78fe56230222be673b2c36454a"}, +] +steam = [ + {file = "steam-1.0.2.tar.gz", hash = "sha256:ca7c026848338ca2a004c0cb73d362c94e5c1a74815c8605d34fce3a6662f9c0"}, +] +toml = [ + {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, + {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, +] +tornado = [ + {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"}, + {file = "tornado-6.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740"}, + {file = "tornado-6.0.4-cp36-cp36m-win32.whl", hash = "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673"}, + {file = "tornado-6.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a"}, + {file = "tornado-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6"}, + {file = "tornado-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b"}, + {file = "tornado-6.0.4-cp38-cp38-win32.whl", hash = "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52"}, + {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"}, + {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, +] +tzlocal = [ + {file = "tzlocal-2.1-py2.py3-none-any.whl", hash = "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4"}, + {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"}, +] +uvicorn = [ + {file = "uvicorn-0.10.9-py3-none-any.whl", hash = "sha256:dc7119b28e15c4c737315c5a570081b0a5a7d8d5c1e8a70a7be70043d88b23a7"}, + {file = "uvicorn-0.10.9.tar.gz", hash = "sha256:c010df69d16e27f1a18481316325b4fd23f562c1fac050915fc03a397d0f6b64"}, +] +uvloop = [ + {file = "uvloop-0.14.0-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd"}, + {file = "uvloop-0.14.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:4544dcf77d74f3a84f03dd6278174575c44c67d7165d4c42c71db3fdc3860726"}, + {file = "uvloop-0.14.0-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:b4f591aa4b3fa7f32fb51e2ee9fea1b495eb75b0b3c8d0ca52514ad675ae63f7"}, + {file = "uvloop-0.14.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f07909cd9fc08c52d294b1570bba92186181ca01fe3dc9ffba68955273dd7362"}, + {file = "uvloop-0.14.0-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:afd5513c0ae414ec71d24f6f123614a80f3d27ca655a4fcf6cabe50994cc1891"}, + {file = "uvloop-0.14.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e7514d7a48c063226b7d06617cbb12a14278d4323a065a8d46a7962686ce2e95"}, + {file = "uvloop-0.14.0-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:bcac356d62edd330080aed082e78d4b580ff260a677508718f88016333e2c9c5"}, + {file = "uvloop-0.14.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09"}, + {file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"}, +] +vdf = [ + {file = "vdf-3.3-py2.py3-none-any.whl", hash = "sha256:f88db3a3e66e7264da7fdacf0ffa1d99be52dd30510b2c1a1340171b227472e4"}, + {file = "vdf-3.3.tar.gz", hash = "sha256:9193901ce20ee08391c1d5044234b5da021d939b00ce879f5aae0a1a759577bc"}, +] +websockets = [ + {file = "websockets-8.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c"}, + {file = "websockets-8.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170"}, + {file = "websockets-8.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8"}, + {file = "websockets-8.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb"}, + {file = "websockets-8.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5"}, + {file = "websockets-8.1-cp36-cp36m-win32.whl", hash = "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a"}, + {file = "websockets-8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5"}, + {file = "websockets-8.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989"}, + {file = "websockets-8.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d"}, + {file = "websockets-8.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779"}, + {file = "websockets-8.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8"}, + {file = "websockets-8.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422"}, + {file = "websockets-8.1-cp37-cp37m-win32.whl", hash = "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc"}, + {file = "websockets-8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308"}, + {file = "websockets-8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092"}, + {file = "websockets-8.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485"}, + {file = "websockets-8.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1"}, + {file = "websockets-8.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55"}, + {file = "websockets-8.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824"}, + {file = "websockets-8.1-cp38-cp38-win32.whl", hash = "sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36"}, + {file = "websockets-8.1-cp38-cp38-win_amd64.whl", hash = "sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b"}, + {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"}, +] From 7afc8f81e54bb6c5e955fa9f45db0d3f1e5ccafd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 23 Jul 2020 01:14:25 +0200 Subject: [PATCH 223/227] Implement osu updater --- pyproject.toml | 4 +- royalpack/commands/osu.py | 92 +++++++++++++++++++++------ royalpack/stars/api_auth_login_osu.py | 17 ++++- royalpack/tables/osu.py | 41 +++++++++++- 4 files changed, 131 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a3090b3a..6934e240 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.13.0" + version = "5.13.1" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" @@ -23,6 +23,8 @@ riotwatcher = "^3.0.0" royalspells = "^3.2" steam = "*" + sqlalchemy = "^1.3.18" + bcrypt = "^3.1.7" [tool.poetry.dependencies.royalnet] version = "~5.10.4" diff --git a/royalpack/commands/osu.py b/royalpack/commands/osu.py index b8cc1ec7..b4e2561a 100644 --- a/royalpack/commands/osu.py +++ b/royalpack/commands/osu.py @@ -1,11 +1,14 @@ from typing import * import itsdangerous +import aiohttp from royalnet.backpack import tables as rbt 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 @@ -30,42 +33,93 @@ class OsuCommand(LinkerCommand): def secret_key(self): return self.config['secret_key'] - async def get_updatables_of_user(self, session, user: rbt.User) -> List[Updatable]: - return [] + async def get_updatables_of_user(self, session, user: rbt.User) -> List[Osu]: + return user.osu - async def get_updatables(self, session) -> List[Updatable]: - return [] + async def get_updatables(self, session) -> List[Osu]: + return await ru.asyncify(session.query(self.alchemy.get(Osu)).all) async def create(self, session, user: rbt.User, args: rc.CommandArgs, - data: Optional[rc.CommandData] = None) -> Optional[Updatable]: + data: Optional[rc.CommandData] = None) -> Optional[Osu]: serializer = itsdangerous.URLSafeSerializer(self.secret_key, salt="osu") + # TODO: Ensure the chat the link is being sent in is secure!!! await data.reply("🔑 [b]Login necessario[/b]\n" f"[url=https://osu.ppy.sh/oauth/authorize" f"?client_id={self.client_id}" f"&redirect_uri={self.base_url}{ApiAuthLoginOsuStar.path}" f"&response_type=code" f"&state={serializer.dumps(user.uid)}]" - f"Connetti osu! a Royalnet" + f"Connetti osu! all'account {user.username}" f"[/url]") return None - async def update(self, session, obj, change: Callable[[str, Any], Awaitable[None]]): + async def update(self, session, obj: Osu, change: Callable[[str, Any], Awaitable[None]]): + await obj.refresh_if_expired(client_id=self.client_id, + client_secret=self.client_secret, + base_url=self.base_url, + path=ApiAuthLoginOsuStar.path) + async with aiohttp.ClientSession(headers={"Authorization": f"Bearer {obj.access_token}"}) as session: + async with session.get("https://osu.ppy.sh/api/v2/me/osu") as response: + m = await response.json() + obj.avatar_url = m["avatar_url"] + obj.username = m["username"] + if "statistics" in m: + await change("standard_pp", m["statistics"].get("pp")) + async with session.get("https://osu.ppy.sh/api/v2/me/taiko") as response: + m = await response.json() + if "statistics" in m: + await change("taiko_pp", m["statistics"].get("pp")) + async with session.get("https://osu.ppy.sh/api/v2/me/fruits") as response: + m = await response.json() + if "statistics" in m: + await change("catch_pp", m["statistics"].get("pp")) + async with session.get("https://osu.ppy.sh/api/v2/me/mania") as response: + m = await response.json() + if "statistics" in m: + await change("mania_pp", m["statistics"].get("pp")) + + async def on_increase(self, session, obj: Osu, attribute: str, old: Any, new: Any) -> None: + if attribute == "standard_pp": + await self.notify(f"📈 [b]{obj.user}[/b] è salito a [b]{new:.0f}pp[/b] su [i]osu![/i]! Congratulazioni!") + elif attribute == "taiko_pp": + await self.notify(f"📈 [b]{obj.user}[/b] è salito a [b]{new:.0f}pp[/b] su [i]osu!taiko[/i]! Congratulazioni!") + elif attribute == "catch_pp": + await self.notify(f"📈 [b]{obj.user}[/b] è salito a [b]{new:.0f}pp[/b] su [i]osu!catch[/i]! Congratulazioni!") + elif attribute == "mania_pp": + await self.notify(f"📈 [b]{obj.user}[/b] è salito a [b]{new:.0f}pp[/b] su [i]osu!mania[/i]! Congratulazioni!") + + async def on_unchanged(self, session, obj: Osu, attribute: str, old: Any, new: Any) -> None: pass - async def on_increase(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: - pass + async def on_decrease(self, session, obj: Osu, attribute: str, old: Any, new: Any) -> None: + if attribute == "standard_pp": + await self.notify(f"📉 [b]{obj.user}[/b] è sceso a [b]{new:.0f}pp[/b] su [i]osu![/i].") + elif attribute == "taiko_pp": + await self.notify(f"📉 [b]{obj.user}[/b] è sceso a [b]{new:.0f}pp[/b] su [i]osu!taiko[/i].") + elif attribute == "catch_pp": + await self.notify(f"📉 [b]{obj.user}[/b] è sceso a [b]{new:.0f}pp[/b] su [i]osu!catch[/i].") + elif attribute == "mania_pp": + await self.notify(f"📉 [b]{obj.user}[/b] è sceso a [b]{new:.0f}pp[/b] su [i]osu!mania[/i].") - async def on_unchanged(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: - pass + async def on_first(self, session, obj: Osu, attribute: str, old: None, new: Any) -> None: + if attribute == "standard_pp": + await self.notify(f"⭐️ [b]{obj.user}[/b] ha guadagnato i suoi primi [b]{new:.0f}pp[/b] su [i]osu![/i]!") + elif attribute == "taiko_pp": + await self.notify(f"⭐️ [b]{obj.user}[/b] ha guadagnato i suoi primi [b]{new:.0f}pp[/b] su [i]osu!taiko[/i]!") + elif attribute == "catch_pp": + await self.notify(f"⭐️ [b]{obj.user}[/b] ha guadagnato i suoi primi [b]{new:.0f}pp[/b] su [i]osu!catch[/i]!") + elif attribute == "mania_pp": + await self.notify(f"⭐️ [b]{obj.user}[/b] ha guadagnato i suoi primi [b]{new:.0f}pp[/b] su [i]osu!mania[/i]!") - async def on_decrease(self, session, obj: Updatable, attribute: str, old: Any, new: Any) -> None: - pass - - async def on_first(self, session, obj: Updatable, attribute: str, old: None, new: Any) -> None: - pass - - async def on_reset(self, session, obj: Updatable, attribute: str, old: Any, new: None) -> None: - pass + async def on_reset(self, session, obj: Osu, attribute: str, old: Any, new: None) -> None: + if attribute == "standard_pp": + await self.notify(f"⬜️ [b]{obj.user}[/b] non è più classificato su [i]osu![/i].") + elif attribute == "taiko_pp": + await self.notify(f" ⬜️[b]{obj.user}[/b] non è più classificato su [i]osu!taiko[/i].") + elif attribute == "catch_pp": + await self.notify(f"⬜️ [b]{obj.user}[/b] non è più classificato su [i]osu!catch[/i].") + elif attribute == "mania_pp": + await self.notify(f"⬜️ [b]{obj.user}[/b] non è più classificato su [i]osu!mania[/i].") diff --git a/royalpack/stars/api_auth_login_osu.py b/royalpack/stars/api_auth_login_osu.py index 4a9e3cc1..ac3ba1a0 100644 --- a/royalpack/stars/api_auth_login_osu.py +++ b/royalpack/stars/api_auth_login_osu.py @@ -1,6 +1,7 @@ import royalnet.utils as ru import royalnet.backpack.tables as rbt import royalnet.constellation.api as rca +import royalnet.constellation.api.apierrors as rcae import itsdangerous import aiohttp import aiohttp.client_exceptions @@ -46,6 +47,7 @@ class ApiAuthLoginOsuStar(rca.ApiStar): async def get(self, data: rca.ApiData) -> ru.JSON: """Login to Royalnet with your osu! account.""" OsuT = self.alchemy.get(Osu) + TokenT = self.alchemy.get(rbt.Token) code = data.str("code") state = data.str("state", optional=True) @@ -81,6 +83,17 @@ class ApiAuthLoginOsuStar(rca.ApiStar): ) data.session.add(osu) - await data.session_commit() + else: + osu = await ru.asyncify( + data.session.query(OsuT).filter_by(osu_id=m["id"]).all + ) + if osu is None: + raise rcae.ForbiddenError("Unknown osu! account") + user = osu.user - raise rca.MethodNotImplementedError() + token: rbt.Token = TokenT.generate(alchemy=self.alchemy, user=user, expiration_delta=datetime.timedelta(days=7)) + + data.session.add(token) + await data.session_commit() + + return token.json() diff --git a/royalpack/tables/osu.py b/royalpack/tables/osu.py index bb19b5db..99179a7d 100644 --- a/royalpack/tables/osu.py +++ b/royalpack/tables/osu.py @@ -38,7 +38,27 @@ class Osu(Updatable): @declared_attr def username(self): - return Column(String) + return Column(String, nullable=False) + + @declared_attr + def avatar_url(self): + return Column(String, nullable=False) + + @declared_attr + def standard_pp(self): + return Column(Float) + + @declared_attr + def taiko_pp(self): + return Column(Float) + + @declared_attr + def catch_pp(self): + return Column(Float) + + @declared_attr + def mania_pp(self): + return Column(Float) async def refresh(self, *, client_id, client_secret, base_url, path): j = await oauth_refresh(url="https://osu.ppy.sh/oauth/token", @@ -53,3 +73,22 @@ class Osu(Updatable): async def refresh_if_expired(self, *, client_id, client_secret, base_url, path): if datetime.datetime.now() >= self.expiration_date: await self.refresh(client_id=client_id, client_secret=client_secret, base_url=base_url, path=path) + + def json(self) -> dict: + return { + "osu_id": self.osu_id, + "username": self.username, + "avatar_url": self.avatar_url, + "standard": { + "pp": self.standard_pp, + }, + "taiko": { + "pp": self.taiko_pp, + }, + "catch": { + "pp": self.catch_pp, + }, + "mania": { + "pp": self.mania_pp, + }, + } From 860d370901ddd54ab44c60a383fabec995e2735a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 23 Jul 2020 01:20:21 +0200 Subject: [PATCH 224/227] Migliora testo --- royalpack/commands/osu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalpack/commands/osu.py b/royalpack/commands/osu.py index b4e2561a..dff74519 100644 --- a/royalpack/commands/osu.py +++ b/royalpack/commands/osu.py @@ -52,7 +52,7 @@ class OsuCommand(LinkerCommand): f"&redirect_uri={self.base_url}{ApiAuthLoginOsuStar.path}" f"&response_type=code" f"&state={serializer.dumps(user.uid)}]" - f"Connetti osu! all'account {user.username}" + f"Connetti account di osu! a {user.username}" f"[/url]") return None From 4f5199c88f257f17301d3037196cf76382d916c5 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 23 Jul 2020 01:27:46 +0200 Subject: [PATCH 225/227] Permetti di disabilitare il login con osu --- royalpack/stars/api_auth_login_osu.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/royalpack/stars/api_auth_login_osu.py b/royalpack/stars/api_auth_login_osu.py index ac3ba1a0..51a2fb74 100644 --- a/royalpack/stars/api_auth_login_osu.py +++ b/royalpack/stars/api_auth_login_osu.py @@ -91,9 +91,12 @@ class ApiAuthLoginOsuStar(rca.ApiStar): raise rcae.ForbiddenError("Unknown osu! account") user = osu.user - token: rbt.Token = TokenT.generate(alchemy=self.alchemy, user=user, expiration_delta=datetime.timedelta(days=7)) + if self.config["osu"]["login"]["enabled"]: + token: rbt.Token = TokenT.generate(alchemy=self.alchemy, user=user, expiration_delta=datetime.timedelta(days=7)) + data.session.add(token) + await data.session_commit() - data.session.add(token) - await data.session_commit() - - return token.json() + return token.json() + else: + raise rcae.ForbiddenError("Account linked successfully; cannot use this account to generate a Royalnet" + " login token, as osu! login is currently disabled on this Royalnet instance.") \ No newline at end of file From cf6a09d5af51608f1e054375f23d34c7ed404f1c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 23 Jul 2020 01:29:05 +0200 Subject: [PATCH 226/227] Permetti di disabilitare il login con osu --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 2840acf7..bb419be5 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,15 @@ Play.max_song_duration = 7230 # The Telegram channel where matchmaking messages should be sent in Matchmaking.mm_chat_id = -1001204402796 +[Packs."royalpack"."steampowered"] +token = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + +[Packs."royalpack"."steampowered".updater] +enabled = false +period = 86400 +delay = 1 +target = -1001153723135 + [Packs."royalpack"."dota".updater] enabled = true period = 86400 @@ -60,4 +69,16 @@ period = 86400 delay = 1 target = -1001153723135 +[Packs."royalpack"."osu"] +client_id = 123456789 +client_secret = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + +[Packs."royalpack"."osu".login] +enabled = false + +[Packs."royalpack"."osu".updater] +enabled = true +period = 86400 +delay = 5 +target = -1001153723135 ``` \ No newline at end of file From 593677b0d52084f251af8afc4c740b7545687e82 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 23 Jul 2020 01:32:21 +0200 Subject: [PATCH 227/227] Change version stuff --- pyproject.toml | 2 +- royalpack/commands/royalpackversion.py | 10 +++++++--- royalpack/version.py | 3 --- 3 files changed, 8 insertions(+), 7 deletions(-) delete mode 100644 royalpack/version.py diff --git a/pyproject.toml b/pyproject.toml index 27278001..9dbe6bf6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "royalpack" - version = "5.13.2" + version = "5.13.4" description = "A Royalnet command pack for the Royal Games community" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/royalpack/commands/royalpackversion.py b/royalpack/commands/royalpackversion.py index bbd514ae..f2b17584 100644 --- a/royalpack/commands/royalpackversion.py +++ b/royalpack/commands/royalpackversion.py @@ -1,7 +1,7 @@ from typing import * -import royalnet.commands as rc -from ..version import semantic +import pkg_resources +import royalnet.commands as rc class RoyalpackCommand(rc.Command): @@ -11,11 +11,15 @@ class RoyalpackCommand(rc.Command): syntax: str = "" + @property + def royalpack_version(self): + 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/{semantic}]{semantic}[/url]\n" + message = f"ℹ️ Royalpack [url=https://github.com/Steffo99/royalpack/releases/tag/{self.royalpack_version}]{self.royalpack_version}[/url]\n" if "69" in semantic: message += "(Nice.)" await data.reply(message) diff --git a/royalpack/version.py b/royalpack/version.py deleted file mode 100644 index 4430300e..00000000 --- a/royalpack/version.py +++ /dev/null @@ -1,3 +0,0 @@ -import pkg_resources - -semantic = pkg_resources.get_distribution("royalpack").version