diff --git a/royalpack/commands/givefiorygi.py b/royalpack/commands/givefiorygi.py index c1e29230..2a42fcc2 100644 --- a/royalpack/commands/givefiorygi.py +++ b/royalpack/commands/givefiorygi.py @@ -13,31 +13,35 @@ class GivefiorygiCommand(rc.Command): 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] - - if user_arg is None: - raise rc.InvalidInputError("Non hai specificato un destinatario!") async with data.session_acm() as session: - user = await rbt.User.find(self.alchemy, session, user_arg) - if user is None: - raise rc.InvalidInputError("L'utente specificato non esiste!") - if user.uid == author.uid: - raise rc.InvalidInputError("Non puoi inviare fiorygi a te stesso!") + author = await data.find_author(session=session, required=True) - 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!") + user_arg = args[0] + qty_arg = args[1] - if author.fiorygi.fiorygi < qty: - raise rc.InvalidInputError("Non hai abbastanza fiorygi per effettuare la transazione!") + if user_arg is None: + raise rc.InvalidInputError("Non hai specificato un destinatario!") + user = await rbt.User.find(alchemy=self.alchemy, session=session, identifier=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!") - 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 {author}") + 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 author.fiorygi.fiorygi < qty: + raise rc.InvalidInputError("Non hai abbastanza fiorygi per effettuare la transazione!") + + await FiorygiTransaction.spawn_fiorygi(author, -qty, f"aver ceduto fiorygi a {user}", + data=data, + session=session) + await FiorygiTransaction.spawn_fiorygi(user, qty, f"aver ricevuto fiorygi da {author}", + data=data, + session=session) diff --git a/royalpack/commands/givetreasure.py b/royalpack/commands/givetreasure.py index 92d0ad23..008221b6 100644 --- a/royalpack/commands/givetreasure.py +++ b/royalpack/commands/givetreasure.py @@ -30,6 +30,6 @@ class GivetreasureCommand(MagicktreasureCommand): redeemed_by=None ) - await FiorygiTransaction.spawn_fiorygi(data, author, -value, "aver creato un tesoro") + await FiorygiTransaction.spawn_fiorygi(author, -value, "aver creato un tesoro", data=data, session=session) return treasure diff --git a/royalpack/commands/leagueoflegends.py b/royalpack/commands/leagueoflegends.py index 049128c0..a481f487 100644 --- a/royalpack/commands/leagueoflegends.py +++ b/royalpack/commands/leagueoflegends.py @@ -115,6 +115,7 @@ class LeagueoflegendsCommand(LinkerCommand): await FiorygiTransaction.spawn_fiorygi( data=data, + session=session, user=user, qty=1, reason="aver collegato a Royalnet il proprio account di League of Legends" diff --git a/royalpack/commands/magickfiorygi.py b/royalpack/commands/magickfiorygi.py index cd86a010..24ef4a21 100644 --- a/royalpack/commands/magickfiorygi.py +++ b/royalpack/commands/magickfiorygi.py @@ -13,29 +13,29 @@ class MagickfiorygiCommand(rc.Command): 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 "banker" not in author.roles: - 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!") async with data.session_acm() as session: + author = await data.find_author(session=session, required=True) + if "banker" not in author.roles: + 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 = await rbt.User.find(self.alchemy, session, user_arg) - if user is None: - raise rc.InvalidInputError("L'utente specificato non esiste!") + 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_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 reason_arg == "": - raise rc.InvalidInputError("Non hai specificato un motivo!") + if reason_arg == "": + raise rc.InvalidInputError("Non hai specificato un motivo!") - await FiorygiTransaction.spawn_fiorygi(data, user, qty, reason_arg) + await FiorygiTransaction.spawn_fiorygi(user, qty, reason_arg, data=data, session=session) diff --git a/royalpack/commands/magicktreasure.py b/royalpack/commands/magicktreasure.py index e0872641..c9d12e96 100644 --- a/royalpack/commands/magicktreasure.py +++ b/royalpack/commands/magicktreasure.py @@ -34,17 +34,18 @@ class MagicktreasureCommand(rc.Command): 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].lower() - 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 with data.session_acm() as session: + author = await data.find_author(session=session, required=True) + + code = args[0].lower() + 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, session) treasure = await self._create_treasure(author, code, value, data, session) session.add(treasure) diff --git a/royalpack/commands/osu.py b/royalpack/commands/osu.py index 1a7f1c7c..e916cd46 100644 --- a/royalpack/commands/osu.py +++ b/royalpack/commands/osu.py @@ -117,7 +117,7 @@ class OsuCommand(LinkerCommand): 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].") + 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": diff --git a/royalpack/commands/ping.py b/royalpack/commands/ping.py index 8230b62a..6116444c 100644 --- a/royalpack/commands/ping.py +++ b/royalpack/commands/ping.py @@ -23,7 +23,7 @@ class PingCommand(rc.Command): for target in self._targets: tasks[target] = self.loop.create_task(self.serf.call_herald_event(target, "pong")) - await asyncio.sleep(10) + await asyncio.sleep(5) lines = ["📶 [b]Pong![/b]", ""] diff --git a/royalpack/commands/reminder.py b/royalpack/commands/reminder.py index cfa89d27..a1ea320f 100644 --- a/royalpack/commands/reminder.py +++ b/royalpack/commands/reminder.py @@ -34,7 +34,7 @@ class ReminderCommand(rc.Command): .all() ) for reminder in reminders: - self.loop.create_task(self._remind(reminder)) + self.serf.tasks.add(self._remind(reminder)) async def _remind(self, reminder): await ru.sleep_until(reminder.datetime) @@ -77,13 +77,13 @@ class ReminderCommand(rc.Command): interface_data = pickle.dumps(data.message.channel.id) else: raise rc.UnsupportedError("This command does not support the current interface.") - creator = await data.get_author() async with data.session_acm() as session: + creator = await data.find_author(session=session) reminder = self.alchemy.get(Reminder)(creator=creator, interface_name=self.serf.interface_name, interface_data=interface_data, datetime=date, message=reminder_text) - self.loop.create_task(self._remind(reminder)) + self.serf.tasks.add(self._remind(reminder)) session.add(reminder) await ru.asyncify(session.commit) diff --git a/royalpack/commands/steammatch.py b/royalpack/commands/steammatch.py index 1c859217..34f64a31 100644 --- a/royalpack/commands/steammatch.py +++ b/royalpack/commands/steammatch.py @@ -60,44 +60,44 @@ class SteammatchCommand(rc.Command): async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: users = [] - author = await data.get_author(error_if_none=True) - users.append(author) + async with data.session_acm() as session: + author = await data.find_author(session=session, required=True) + users.append(author) - for arg in args: - async with data.session_acm() as session: + for arg in args: user = await rbt.User.find(self.alchemy, session, arg) - users.append(user) + users.append(user) - if len(users) < 2: - raise rc.InvalidInputError("Devi specificare almeno un altro utente!") + if len(users) < 2: + 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 rc.UserError(f"{user} non ha un account Steam registrato!") - for steam_account in user.steam: - steam_account: Steam - try: - response = await ru.asyncify(self._api.IPlayerService.GetOwnedGames, - 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!") - 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) + shared_games: Optional[set] = None + for user in users: + user_games = set() + if len(user.steam) == 0: + raise rc.UserError(f"{user} non ha un account Steam registrato!") + for steam_account in user.steam: + steam_account: Steam + try: + response = await ru.asyncify(self._api.IPlayerService.GetOwnedGames, + 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!") + 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 {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}") + 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}") - message = "\n".join(message_rows) - await data.reply(message) + message = "\n".join(message_rows) + await data.reply(message) diff --git a/royalpack/commands/steampowered.py b/royalpack/commands/steampowered.py index 395f1d41..110ea52c 100644 --- a/royalpack/commands/steampowered.py +++ b/royalpack/commands/steampowered.py @@ -57,10 +57,12 @@ class SteampoweredCommand(LinkerCommand): ) await FiorygiTransaction.spawn_fiorygi( - data=data, user=user, qty=1, - reason="aver collegato a Royalnet il proprio account di League of Legends" + reason="aver collegato a Royalnet il proprio account di Steam", + + data=data, + session=session, ) session.add(steam_account) diff --git a/royalpack/commands/treasure.py b/royalpack/commands/treasure.py index 6b5ad7f3..83dc397c 100644 --- a/royalpack/commands/treasure.py +++ b/royalpack/commands/treasure.py @@ -13,11 +13,11 @@ class TreasureCommand(rc.Command): 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].lower() + TreasureT = self.alchemy.get(Treasure) async with data.session_acm() as session: - TreasureT = self.alchemy.get(Treasure) + author = await data.find_author(session=session, required=True) + code = args[0].lower() treasure = await ru.asyncify(session.query(TreasureT).get, code) if treasure is None: diff --git a/royalpack/commands/trivia.py b/royalpack/commands/trivia.py index 502818dd..d473fe90 100644 --- a/royalpack/commands/trivia.py +++ b/royalpack/commands/trivia.py @@ -94,7 +94,7 @@ class TriviaCommand(rc.Command): # Create the correct and wrong functions async def correct(data: rc.CommandData): - answerer_ = await data.get_author(error_if_none=True) + answerer_ = await data.find_author(session=session, required=True) try: self._answerers[question_id][answerer_.uid] = True except KeyError: @@ -102,7 +102,7 @@ class TriviaCommand(rc.Command): 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) + answerer_ = await data.find_author(session=session, required=True) try: self._answerers[question_id][answerer_.uid] = False except KeyError: diff --git a/royalpack/events/discord_cv.py b/royalpack/events/discord_cv.py index 376ab22d..d71c3b0f 100644 --- a/royalpack/events/discord_cv.py +++ b/royalpack/events/discord_cv.py @@ -88,5 +88,6 @@ class DiscordCvEvent(rc.HeraldEvent): "id": guild.id, "name": guild.name, "members": results, + "channels": channels, } } diff --git a/royalpack/stars/__init__.py b/royalpack/stars/__init__.py index 07a22617..bc24a864 100644 --- a/royalpack/stars/__init__.py +++ b/royalpack/stars/__init__.py @@ -3,7 +3,6 @@ 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_fiorygi import ApiFiorygiStar from .api_diario_random import ApiDiarioRandomStar from .api_poll import ApiPollStar @@ -21,7 +20,6 @@ available_page_stars = [ ApiDiarioGetStar, ApiDiarioPagesStar, ApiDiscordCvStar, - ApiDiscordPlayStar, ApiFiorygiStar, ApiDiarioRandomStar, ApiPollStar, diff --git a/royalpack/stars/api_auth_login_osu.py b/royalpack/stars/api_auth_login_osu.py index a725d468..4d6d0594 100644 --- a/royalpack/stars/api_auth_login_osu.py +++ b/royalpack/stars/api_auth_login_osu.py @@ -7,7 +7,7 @@ import aiohttp import aiohttp.client_exceptions import datetime from ..types import oauth_refresh -from ..tables import Osu, FiorygiTransaction +from ..tables import Osu class ApiAuthLoginOsuStar(rca.ApiStar): diff --git a/royalpack/stars/api_discord_cv.py b/royalpack/stars/api_discord_cv.py index 1ee1108c..8479bf3f 100644 --- a/royalpack/stars/api_discord_cv.py +++ b/royalpack/stars/api_discord_cv.py @@ -12,5 +12,5 @@ class ApiDiscordCvStar(rca.ApiStar): """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") + response = await self.constellation.call_herald_event("discord", "discord_cv") return response diff --git a/royalpack/stars/api_discord_play.py b/royalpack/stars/api_discord_play.py deleted file mode 100644 index 3633d826..00000000 --- a/royalpack/stars/api_discord_play.py +++ /dev/null @@ -1,40 +0,0 @@ -from typing import * -import royalnet.constellation.api as rca -import logging - - -log = logging.getLogger(__name__) - - -class ApiDiscordPlayStar(rca.ApiStar): - path = "/api/discord/play/v2" - - parameters = { - "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"] - - @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") - guild_id_str = data.get("guild_id") - if guild_id_str: - try: - guild_id: Optional[int] = int(guild_id_str) - except (ValueError, TypeError): - 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") - response = await self.interface.call_herald_event("discord", "discord_play", - urls=[url], - guild_id=guild_id, - user=user) - return response diff --git a/royalpack/stars/api_user_avatar.py b/royalpack/stars/api_user_avatar.py index 9128ce8f..c27b19f6 100644 --- a/royalpack/stars/api_user_avatar.py +++ b/royalpack/stars/api_user_avatar.py @@ -3,7 +3,7 @@ import royalnet.utils as ru import royalnet.constellation.api as rca -url_validation = re.compile(r'^(?:http|ftp)s?://' +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})' @@ -16,7 +16,7 @@ class ApiUserAvatarStar(rca.ApiStar): parameters = { "put": { - "avatar_url": "The url that the user wants to set as avatar." + "avatar_url": "The url that the user wants to set as avatar. MUST BE HTTPS/FTPS!" } } diff --git a/royalpack/tables/fiorygitransactions.py b/royalpack/tables/fiorygitransactions.py index 6f6cf224..1dd285b5 100644 --- a/royalpack/tables/fiorygitransactions.py +++ b/royalpack/tables/fiorygitransactions.py @@ -47,40 +47,44 @@ class FiorygiTransaction: 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): + async def spawn_fiorygi(cls, user, qty: int, reason: str, *, data: "CommandData", session): + FiorygiT = data.alchemy.get(cls) + FiorygiTransactionT = data.alchemy.get(FiorygiTransaction) + if user.fiorygi is None: - async with data.session_acm() as session: - session.add(data.alchemy.get(Fiorygi)( + session.add( + FiorygiT( user_id=user.uid, fiorygi=0 - )) - await ru.asyncify(session.commit) + ) + ) + await ru.asyncify(session.commit) - async with data.session_acm() as session: - transaction = data.alchemy.get(FiorygiTransaction)( + session.add( + FiorygiTransactionT( user_id=user.uid, change=qty, reason=reason, timestamp=datetime.datetime.now() ) - session.add(transaction) + ) - user.fiorygi.fiorygi += qty - await ru.asyncify(session.commit) + user.fiorygi.fiorygi += qty + await ru.asyncify(session.commit) - if len(user.telegram) > 0: - user_str = user.telegram[0].mention() - else: - user_str = user.username + if len(user.telegram) > 0: + user_str = user.telegram[0].mention() + else: + user_str = user.username - if qty > 0: - msg = f"💰 [b]{user_str}[/b] ha ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''} per [i]{reason}[/i]!" - elif qty == 0: - msg = f"❓ [b]{user_str}[/b] ha mantenuto i suoi fiorygi attuali per [i]{reason}[/i].\nWait, cosa?" - else: - msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason}[/i]." + if qty > 0: + msg = f"💰 [b]{user_str}[/b] ha ottenuto [b]{qty}[/b] fioryg{'i' if qty != 1 else ''} per [i]{reason}[/i]!" + elif qty == 0: + msg = f"❓ [b]{user_str}[/b] ha mantenuto i suoi fiorygi attuali per [i]{reason}[/i].\nWait, cosa?" + else: + msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason}[/i]." - await data.command.serf.call_herald_event( - "telegram", "telegram_message", - chat_id=data.command.config["Telegram"]["main_group_id"], - text=msg) + await data.command.serf.call_herald_event( + "telegram", "telegram_message", + chat_id=data.command.config["Telegram"]["main_group_id"], + text=msg) diff --git a/royalpack/types/oauth_refresh.py b/royalpack/types/oauth_refresh.py index 62e3e6b2..0047f656 100644 --- a/royalpack/types/oauth_refresh.py +++ b/royalpack/types/oauth_refresh.py @@ -7,8 +7,7 @@ async def oauth_refresh(*, url, client_id, client_secret, redirect_uri, refresh_ "client_id": client_id, "client_secret": client_secret, "code": refresh_code, - "grant_type": "authorization_code", - "redirect_uri": redirect_uri + "grant_type": "refresh_token" }) as response: j = await response.json() return j