From ecd4c92bb2aec33271dbe6e81054a0811d7783e7 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 19 Oct 2019 00:24:35 +0200 Subject: [PATCH] Rewrite all network code and make it work somehow --- royalnet/bots/generic.py | 13 +-- royalnet/packs/royal/commands/cv.py | 41 +++++----- royalnet/packs/royal/commands/dndspell.py | 3 +- royalnet/packs/royal/commands/pause.py | 38 ++++----- royalnet/packs/royal/commands/play.py | 44 +++++----- royalnet/packs/royal/commands/playmode.py | 73 ++++++++--------- royalnet/packs/royal/commands/queue.py | 82 +++++++++---------- royalnet/packs/royal/commands/skip.py | 41 +++++----- royalnet/packs/royal/commands/smecds.py | 4 +- royalnet/packs/royal/commands/soundcloud.py | 47 +++++------ royalnet/packs/royal/commands/summon.py | 37 ++++----- royalnet/packs/royal/commands/videochannel.py | 7 +- royalnet/packs/royal/commands/youtube.py | 45 +++++----- royalnet/packs/royal/commands/zawarudo.py | 46 +++++------ royalnet/utils/__init__.py | 21 ++++- 15 files changed, 272 insertions(+), 270 deletions(-) diff --git a/royalnet/bots/generic.py b/royalnet/bots/generic.py index 21b55c3a..7096da52 100644 --- a/royalnet/bots/generic.py +++ b/royalnet/bots/generic.py @@ -28,7 +28,8 @@ class GenericBot: self._Interface = self._interface_factory() self._Data = self._data_factory() self.commands = {} - self.network_handlers: typing.Dict[str, typing.Callable[[typing.Any], typing.Awaitable[typing.Dict]]] = {} + self.network_handlers: typing.Dict[str, typing.Callable[["GenericBot", typing.Any], + typing.Awaitable[typing.Dict]]] = {} for SelectedCommand in self.uninitialized_commands: interface = self._Interface() try: @@ -69,15 +70,17 @@ class GenericBot: async def call_herald_action(ci, destination: str, event_name: str, args: typing.Dict) -> typing.Dict: if self.network is None: - raise UnsupportedError("royalherald is not enabled on this bot") + raise UnsupportedError("Herald is not enabled on this bot") request: rh.Request = rh.Request(handler=event_name, data=args) response: rh.Response = await self.network.request(destination=destination, request=request) if isinstance(response, rh.ResponseFailure): - raise CommandError(f"royalherald action code failed: {response}") + raise CommandError(f"Herald action call failed:\n" + f"[p]{response}[/p]") elif isinstance(response, rh.ResponseSuccess): return response.data else: - raise TypeError(f"royalherald returned unknown response: {response}") + raise TypeError(f"Other Herald Link returned unknown response:\n" + f"[p]{response}[/p]") return GenericInterface @@ -103,7 +106,7 @@ class GenericBot: else: log.debug(f"Using {network_handler} as handler for {request.handler}") try: - response_data = await network_handler(**request.data) + response_data = await network_handler(self, **request.data) return rh.ResponseSuccess(data=response_data) except Exception as e: sentry_sdk.capture_exception(e) diff --git a/royalnet/packs/royal/commands/cv.py b/royalnet/packs/royal/commands/cv.py index 7a76b0aa..e3df914b 100644 --- a/royalnet/packs/royal/commands/cv.py +++ b/royalnet/packs/royal/commands/cv.py @@ -1,19 +1,22 @@ import discord import typing from royalnet.commands import * -from royalnet.utils import NetworkHandler, andformat +from royalnet.utils import andformat from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess -class CvNH(NetworkHandler): - message_type = "discord_cv" +class CvCommand(Command): + name: str = "cv" - @classmethod - async def discord(cls, bot: DiscordBot, data: dict): + description: str = "Elenca le persone attualmente connesse alla chat vocale." + + syntax: str = "[guildname] ['all']" + + @staticmethod + async def _legacy_cv_handler(bot: DiscordBot, guild_name: typing.Optional[str], everyone: bool): # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) else: guilds = bot.client.guilds if len(guilds) == 0: @@ -47,7 +50,7 @@ class CvNH(NetworkHandler): for member in members_in_channels[channel]: member: typing.Union[discord.User, discord.Member] # Ignore not-connected non-notable members - if not data["everyone"] and channel == 0 and len(member.roles) < 2: + if not everyone and channel == 0 and len(member.roles) < 2: continue # Ignore offline members if member.status == discord.Status.offline and member.voice is None: @@ -108,24 +111,20 @@ class CvNH(NetworkHandler): message += f" | ❓ Unknown activity" message += "\n" message += "\n" - return ResponseSuccess({"response": message}) + return {"response": message} - -class CvCommand(Command): - name: str = "cv" - - description: str = "Elenca le persone attualmente connesse alla chat vocale." - - syntax: str = "[guildname] ['all']" + _event_name = "_legacy_cv" def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler("discord_cv", CvNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_cv_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: # noinspection PyTypeChecker guild_name, everyone = args.match(r"(?:\[(.+)])?\s*(\S+)?\s*") - response = await self.interface.net_request(Request("discord_cv", {"guild_name": guild_name, - "everyone": bool(everyone)}), - destination="discord") + response = await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name, + "everyone": everyone + }) await data.reply(response["response"]) diff --git a/royalnet/packs/royal/commands/dndspell.py b/royalnet/packs/royal/commands/dndspell.py index 63fffcff..9e0c8c88 100644 --- a/royalnet/packs/royal/commands/dndspell.py +++ b/royalnet/packs/royal/commands/dndspell.py @@ -41,7 +41,8 @@ class DndspellCommand(Command): for spell in j["spell"]: self._dnddata.add(spell) - def _parse_spell(self, spell: dict) -> str: + @staticmethod + def _parse_spell(spell: dict) -> str: string = f'✨ [b]{spell["name"]}[/b]\n' if "source" in spell: string += f'[i]{spell["source"]}, page {spell["page"]}[/i]\n' diff --git a/royalnet/packs/royal/commands/pause.py b/royalnet/packs/royal/commands/pause.py index f02b4404..14147e0e 100644 --- a/royalnet/packs/royal/commands/pause.py +++ b/royalnet/packs/royal/commands/pause.py @@ -1,20 +1,21 @@ import typing import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess -class PauseNH(NetworkHandler): - message_type = "music_pause" +class PauseCommand(Command): + name: str = "pause" - # noinspection PyProtectedMember - @classmethod - async def discord(cls, bot: DiscordBot, data: dict): + description: str = "Mette in pausa o riprende la riproduzione della canzone attuale." + + syntax = "[ [guild] ]" + + @staticmethod + async def _legacy_pause_handler(bot: DiscordBot, guild_name: typing.Optional[str]): # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) else: guilds = bot.client.guilds if len(guilds) == 0: @@ -32,23 +33,20 @@ class PauseNH(NetworkHandler): voice_client._player.resume() else: voice_client._player.pause() - return ResponseSuccess({"resumed": resume}) + return {"resumed": resume} - -class PauseCommand(Command): - name: str = "pause" - - description: str = "Mette in pausa o riprende la riproduzione della canzone attuale." - - syntax = "[ [guild] ]" + _event_name = "_legacy_pause" def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(PauseNH.message_type, PauseNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_pause_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: - guild, = args.match(r"(?:\[(.+)])?") - response = await self.interface.net_request(Request("music_pause", {"guild_name": guild}), "discord") + guild_name, = args.match(r"(?:\[(.+)])?") + response = await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name + }) if response["resumed"]: await data.reply(f"▶️ Riproduzione ripresa.") else: diff --git a/royalnet/packs/royal/commands/play.py b/royalnet/packs/royal/commands/play.py index ce4b00c5..1602b2fa 100644 --- a/royalnet/packs/royal/commands/play.py +++ b/royalnet/packs/royal/commands/play.py @@ -3,21 +3,26 @@ import pickle import datetime import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler, asyncify +from royalnet.utils import asyncify from royalnet.audio import YtdlDiscord from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess -class PlayNH(NetworkHandler): - message_type = "music_play" +class PlayCommand(Command): + name: str = "play" - @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): + aliases = ["p"] + + description: str = "Aggiunge un url alla coda della chat vocale." + + syntax = "[ [guild] ] (url)" + + @staticmethod + async def _legacy_play_handler(bot: "DiscordBot", guild_name: typing.Optional[str], url: str): """Handle a play Royalnet request. That is, add audio to a PlayMode.""" # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) else: guilds = bot.client.guilds if len(guilds) == 0: @@ -35,7 +40,7 @@ class PlayNH(NetworkHandler): "outtmpl": f"./downloads/{datetime.datetime.now().timestamp()}_%(title)s.%(ext)s" } # Start downloading - dfiles: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, data["url"], **ytdl_args) + dfiles: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, url, **ytdl_args) await bot.add_to_music_data(dfiles, guild) # Create response dictionary response = { @@ -44,21 +49,14 @@ class PlayNH(NetworkHandler): "discord_embed_pickle": str(pickle.dumps(dfile.info.to_discord_embed())) } for dfile in dfiles] } - return ResponseSuccess(response) + return response - -class PlayCommand(Command): - name: str = "play" - - aliases = ["p"] - - description: str = "Aggiunge un url alla coda della chat vocale." - - syntax = "[ [guild] ] (url)" + _event_name = "_legacy_play" def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(PlayNH.message_type, PlayNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_play_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: guild_name, url = args.match(r"(?:\[(.+)])?\s*?") @@ -66,8 +64,10 @@ class PlayCommand(Command): raise CommandError("PlayCommand only accepts URLs.\n" "If you want to search a song on YouTube or Soundcloud, please use YoutubeCommand" " or SoundcloudCommand!") - response = await self.interface.net_request(Request("music_play", {"url": url, "guild_name": guild_name}), - "discord") + response: dict = await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name, + "url": url + }) if len(response["videos"]) == 0: raise CommandError(f"Nessun file trovato.") for video in response["videos"]: diff --git a/royalnet/packs/royal/commands/playmode.py b/royalnet/packs/royal/commands/playmode.py index edaf6c03..afd07c31 100644 --- a/royalnet/packs/royal/commands/playmode.py +++ b/royalnet/packs/royal/commands/playmode.py @@ -1,42 +1,8 @@ import typing -import pickle import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler from royalnet.audio.playmodes import Playlist, Pool, Layers from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess - - -class PlaymodeNH(NetworkHandler): - message_type = "music_playmode" - - @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): - """Handle a playmode Royalnet request. That is, change current PlayMode.""" - # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) - else: - guilds = bot.client.guilds - if len(guilds) == 0: - raise CommandError("No guilds with the specified name found.") - if len(guilds) > 1: - raise CommandError("Multiple guilds with the specified name found.") - guild = list(bot.client.guilds)[0] - # Delete the previous PlayMode, if it exists - if bot.music_data[guild] is not None: - bot.music_data[guild].delete() - # Create the new PlayMode - if data["mode_name"] == "playlist": - bot.music_data[guild] = Playlist() - elif data["mode_name"] == "pool": - bot.music_data[guild] = Pool() - elif data["mode_name"] == "layers": - bot.music_data[guild] = Layers() - else: - raise CommandError("Unknown PlayMode specified.") - return ResponseSuccess() class PlaymodeCommand(Command): @@ -48,13 +14,44 @@ class PlaymodeCommand(Command): syntax = "[ [guild] ] (mode)" + @staticmethod + async def _legacy_playmode_handler(bot: "DiscordBot", guild_name: typing.Optional[str], mode_name: str): + """Handle a playmode Royalnet request. That is, change current PlayMode.""" + # Find the matching guild + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) + else: + guilds = bot.client.guilds + if len(guilds) == 0: + raise CommandError("No guilds with the specified name found.") + if len(guilds) > 1: + raise CommandError("Multiple guilds with the specified name found.") + guild = list(bot.client.guilds)[0] + # Delete the previous PlayMode, if it exists + if bot.music_data[guild] is not None: + bot.music_data[guild].delete() + # Create the new PlayMode + if mode_name == "playlist": + bot.music_data[guild] = Playlist() + elif mode_name == "pool": + bot.music_data[guild] = Pool() + elif mode_name == "layers": + bot.music_data[guild] = Layers() + else: + raise CommandError("Unknown PlayMode specified.") + return {} + + _event_name = "_legacy_playmode" + def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(PlaymodeNH.message_type, PlaymodeNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_playmode_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: guild_name, mode_name = args.match(r"(?:\[(.+)])?\s*(\S+)\s*") - await self.interface.net_request(Request(PlaymodeNH.message_type, {"mode_name": mode_name, - "guild_name": guild_name}), - "discord") + await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name, + "mode_name": mode_name + }) await data.reply(f"🔃 Impostata la modalità di riproduzione a: [c]{mode_name}[/c].") diff --git a/royalnet/packs/royal/commands/queue.py b/royalnet/packs/royal/commands/queue.py index a501b3f1..a242d83f 100644 --- a/royalnet/packs/royal/commands/queue.py +++ b/royalnet/packs/royal/commands/queue.py @@ -2,46 +2,8 @@ import typing import pickle import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler, numberemojiformat +from royalnet.utils import numberemojiformat from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess - - -class QueueNH(NetworkHandler): - message_type = "music_queue" - - @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): - # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) - else: - guilds = bot.client.guilds - if len(guilds) == 0: - raise CommandError("No guilds with the specified name found.") - if len(guilds) > 1: - raise CommandError("Multiple guilds with the specified name found.") - guild = list(bot.client.guilds)[0] - # Check if the guild has a PlayMode - playmode = bot.music_data.get(guild) - if not playmode: - return ResponseSuccess({ - "type": None - }) - try: - queue = playmode.queue_preview() - except NotImplementedError: - return ResponseSuccess({ - "type": playmode.__class__.__name__ - }) - return ResponseSuccess({ - "type": playmode.__class__.__name__, - "queue": - { - "strings": [str(dfile.info) for dfile in queue], - "pickled_embeds": str(pickle.dumps([dfile.info.to_discord_embed() for dfile in queue])) - } - }) class QueueCommand(Command): @@ -53,13 +15,49 @@ class QueueCommand(Command): syntax = "[ [guild] ]" + @staticmethod + async def _legacy_queue_handler(bot: "DiscordBot", guild_name: typing.Optional[str]): + # Find the matching guild + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) + else: + guilds = bot.client.guilds + if len(guilds) == 0: + raise CommandError("No guilds with the specified name found.") + if len(guilds) > 1: + raise CommandError("Multiple guilds with the specified name found.") + guild = list(bot.client.guilds)[0] + # Check if the guild has a PlayMode + playmode = bot.music_data.get(guild) + if not playmode: + return { + "type": None + } + try: + queue = playmode.queue_preview() + except NotImplementedError: + return { + "type": playmode.__class__.__name__ + } + return { + "type": playmode.__class__.__name__, + "queue": + { + "strings": [str(dfile.info) for dfile in queue], + "pickled_embeds": str(pickle.dumps([dfile.info.to_discord_embed() for dfile in queue])) + } + } + + _event_name = "_legacy_queue" + def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(QueueNH.message_type, QueueNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_queue_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: - guild, = args.match(r"(?:\[(.+)])?") - response = await self.interface.net_request(Request(QueueNH.message_type, {"guild_name": guild}), "discord") + guild_name, = args.match(r"(?:\[(.+)])?") + response = await self.interface.call_herald_action("discord", self._event_name, {"guild_name": guild_name}) if response["type"] is None: await data.reply("ℹ️ Non c'è nessuna coda di riproduzione attiva al momento.") return diff --git a/royalnet/packs/royal/commands/skip.py b/royalnet/packs/royal/commands/skip.py index 008b3275..222486e7 100644 --- a/royalnet/packs/royal/commands/skip.py +++ b/royalnet/packs/royal/commands/skip.py @@ -1,19 +1,23 @@ import typing import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess -class SkipNH(NetworkHandler): - message_type = "music_skip" +class SkipCommand(Command): + name: str = "skip" - @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): + aliases = ["s", "next", "n"] + + description: str = "Salta la canzone attualmente in riproduzione in chat vocale." + + syntax: str = "[ [guild] ]" + + @staticmethod + async def _legacy_skip_handler(bot: "DiscordBot", guild_name: typing.Optional[str]): # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) else: guilds = bot.client.guilds if len(guilds) == 0: @@ -27,23 +31,18 @@ class SkipNH(NetworkHandler): raise CommandError("Nothing to skip") # noinspection PyProtectedMember voice_client._player.stop() - return ResponseSuccess() + return {} - -class SkipCommand(Command): - name: str = "skip" - - aliases = ["s", "next", "n"] - - description: str = "Salta la canzone attualmente in riproduzione in chat vocale." - - syntax: str = "[ [guild] ]" + _event_name = "_legacy_skip" def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(SkipNH.message_type, SkipNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_skip_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: - guild, = args.match(r"(?:\[(.+)])?") - await self.interface.net_request(Request(SkipNH.message_type, {"guild_name": guild}), "discord") + guild_name, = args.match(r"(?:\[(.+)])?") + await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name + }) await data.reply(f"⏩ Richiesto lo skip della canzone attuale.") diff --git a/royalnet/packs/royal/commands/smecds.py b/royalnet/packs/royal/commands/smecds.py index 9f4d6568..d83f453a 100644 --- a/royalnet/packs/royal/commands/smecds.py +++ b/royalnet/packs/royal/commands/smecds.py @@ -60,7 +60,9 @@ class SmecdsCommand(Command): "dei Sims", "di Sid", "delle Skullgirls", "di Sonic", "di Spiral (Knights)", "di Spore", "di Starbound", "di SimCity", "di Sensei", "di Ssssssssssssss... Boom! E' esploso il dizionario", "della scala", "di Sakura", "di Suzie", "di Shinji", "del senpai", "del support", "di Superman", "di Sekiro", - "dello Slime God", "del salassato", "della salsa"] + "dello Slime God", "del salassato", "della salsa", "di Senjougahara", "di Sugar", "della Stampa", + "della Stampante"] + SMECDS = "🤔 Secondo me, è colpa {ds}." async def run(self, args: CommandArgs, data: CommandData) -> None: diff --git a/royalnet/packs/royal/commands/soundcloud.py b/royalnet/packs/royal/commands/soundcloud.py index acc24ae1..70a1b654 100644 --- a/royalnet/packs/royal/commands/soundcloud.py +++ b/royalnet/packs/royal/commands/soundcloud.py @@ -3,21 +3,25 @@ import pickle import datetime import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler, asyncify +from royalnet.utils import asyncify from royalnet.audio import YtdlDiscord from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess -class SoundcloudNH(NetworkHandler): - message_type = "music_soundcloud" +class SoundcloudCommand(Command): + name: str = "soundcloud" - @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): - """Handle a play Royalnet request. That is, add audio to a PlayMode.""" + aliases = ["sc"] + + description: str = "Cerca una canzone su Soundcloud e la aggiunge alla coda della chat vocale." + + syntax = "[ [guild] ] (url)" + + @staticmethod + async def _legacy_soundcloud_handler(bot: "DiscordBot", guild_name: typing.Optional[str], search: str): # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) else: guilds = bot.client.guilds if len(guilds) == 0: @@ -34,40 +38,33 @@ class SoundcloudNH(NetworkHandler): "outtmpl": f"./downloads/{datetime.datetime.now().timestamp()}_%(title)s.%(ext)s" } # Start downloading - dfiles: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, f'scsearch:{data["search"]}', + dfiles: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, f'scsearch:{search}', **ytdl_args) await bot.add_to_music_data(dfiles, guild) # Create response dictionary - response = { + return { "videos": [{ "title": dfile.info.title, "discord_embed_pickle": str(pickle.dumps(dfile.info.to_discord_embed())) } for dfile in dfiles] } - return ResponseSuccess(response) - -class SoundcloudCommand(Command): - name: str = "soundcloud" - - aliases = ["sc"] - - description: str = "Cerca una canzone su Soundcloud e la aggiunge alla coda della chat vocale." - - syntax = "[ [guild] ] (url)" + _event_name = "_legacy_soundcloud" def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(SoundcloudNH.message_type, SoundcloudNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_soundcloud_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: guild_name, search = args.match(r"(?:\[(.+)])?\s*?") if search.startswith("http://") or search.startswith("https://"): raise CommandError("SoundcloudCommand only accepts search queries, and you've sent an URL.\n" "If you want to add a song from an url, please use PlayCommand!") - response = await self.interface.net_request(Request("music_soundcloud", {"search": search, - "guild_name": guild_name}), - "discord") + response = await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name, + "search": search + }) if len(response["videos"]) == 0: raise CommandError(f"Il video non può essere scaricato a causa di un blocco imposto da Soundcloud.") for video in response["videos"]: diff --git a/royalnet/packs/royal/commands/summon.py b/royalnet/packs/royal/commands/summon.py index 3a2d632f..a82c8c58 100644 --- a/royalnet/packs/royal/commands/summon.py +++ b/royalnet/packs/royal/commands/summon.py @@ -1,24 +1,7 @@ import typing import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess - - -class SummonNH(NetworkHandler): - message_type = "music_summon" - - @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): - """Handle a summon Royalnet request. - That is, join a voice channel, or move to a different one if that is not possible.""" - channels = bot.client.find_channel_by_name(data["channel_name"]) - channel = channels[0] - if not isinstance(channel, discord.VoiceChannel): - raise CommandError("Channel is not a voice channel") - bot.loop.create_task(bot.client.vc_connect_or_move(channel)) - return ResponseSuccess() class SummonCommand(Command): @@ -30,9 +13,23 @@ class SummonCommand(Command): syntax: str = "[nomecanale]" + @staticmethod + async def _legacy_summon_handler(bot: "DiscordBot", channel_name: str): + """Handle a summon Royalnet request. + That is, join a voice channel, or move to a different one if that is not possible.""" + channels = bot.client.find_channel_by_name(channel_name) + channel = channels[0] + if not isinstance(channel, discord.VoiceChannel): + raise CommandError("Channel is not a voice channel") + bot.loop.create_task(bot.client.vc_connect_or_move(channel)) + return {} + + _event_name = "_legacy_summon" + def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(SummonNH.message_type, SummonNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_summon_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: if self.interface.name == "discord": @@ -72,5 +69,7 @@ class SummonCommand(Command): await data.reply(f"✅ Mi sono connesso in [c]#{channel.name}[/c].") else: channel_name: str = args[0].lstrip("#") - await self.interface.net_request(Request(SummonNH.message_type, {"channel_name": channel_name}), "discord") + response = await self.interface.call_herald_action("discord", self._event_name, { + "channel_name": channel_name + }) await data.reply(f"✅ Mi sono connesso in [c]#{channel_name}[/c].") diff --git a/royalnet/packs/royal/commands/videochannel.py b/royalnet/packs/royal/commands/videochannel.py index 9ea1be2b..bbec1327 100644 --- a/royalnet/packs/royal/commands/videochannel.py +++ b/royalnet/packs/royal/commands/videochannel.py @@ -40,8 +40,11 @@ class VideochannelCommand(Command): raise CommandError("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[b]Attenzione: la modalità video non funziona su Discord per Android e iOS![/b]") + 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: ") + await data.reply(f"📹 Per entrare in modalità video, clicca qui:\n" + f"") else: raise UnsupportedError(f"This command is not supported on {self.interface.name.capitalize()}.") diff --git a/royalnet/packs/royal/commands/youtube.py b/royalnet/packs/royal/commands/youtube.py index 98861024..3a97f312 100644 --- a/royalnet/packs/royal/commands/youtube.py +++ b/royalnet/packs/royal/commands/youtube.py @@ -3,21 +3,25 @@ import pickle import datetime import discord from royalnet.commands import * -from royalnet.utils import NetworkHandler, asyncify +from royalnet.utils import asyncify from royalnet.audio import YtdlDiscord from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess -class YoutubeNH(NetworkHandler): - message_type = "music_youtube" +class YoutubeCommand(Command): + name: str = "youtube" + + aliases = ["yt"] + + description: str = "Cerca un video su YouTube e lo aggiunge alla coda della chat vocale." + + syntax = "[ [guild] ] (url)" @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): - """Handle a play Royalnet request. That is, add audio to a PlayMode.""" + async def _legacy_youtube_handler(cls, bot: "DiscordBot", guild_name: typing.Optional[str], search: str): # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) else: guilds = bot.client.guilds if len(guilds) == 0: @@ -34,39 +38,32 @@ class YoutubeNH(NetworkHandler): "outtmpl": f"./downloads/{datetime.datetime.now().timestamp()}_%(title)s.%(ext)s" } # Start downloading - dfiles: typing. List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, f'ytsearch:{data["search"]}', **ytdl_args) + dfiles: typing. List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, f'ytsearch:{search}', **ytdl_args) await bot.add_to_music_data(dfiles, guild) # Create response dictionary - response = { + return { "videos": [{ "title": dfile.info.title, "discord_embed_pickle": str(pickle.dumps(dfile.info.to_discord_embed())) } for dfile in dfiles] } - return ResponseSuccess(response) - -class YoutubeCommand(Command): - name: str = "youtube" - - aliases = ["yt"] - - description: str = "Cerca un video su YouTube e lo aggiunge alla coda della chat vocale." - - syntax = "[ [guild] ] (url)" + _event_name = "_legacy_youtube" def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(YoutubeNH.message_type, YoutubeNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_youtube_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: guild_name, search = args.match(r"(?:\[(.+)])?\s*?") if search.startswith("http://") or search.startswith("https://"): raise CommandError("YoutubeCommand only accepts search queries, and you've sent an URL.\n" "If you want to add a song from an url, please use PlayCommand!") - response = await self.interface.net_request(Request("music_youtube", {"search": search, - "guild_name": guild_name}), - "discord") + response = await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name, + "search": search + }) if len(response["videos"]) == 0: raise CommandError(f"Il video non può essere scaricato a causa di un blocco imposto da YouTube.") for video in response["videos"]: diff --git a/royalnet/packs/royal/commands/zawarudo.py b/royalnet/packs/royal/commands/zawarudo.py index 65aa8df2..e75e702e 100644 --- a/royalnet/packs/royal/commands/zawarudo.py +++ b/royalnet/packs/royal/commands/zawarudo.py @@ -3,26 +3,26 @@ import discord import asyncio import datetime from royalnet.commands import * -from royalnet.utils import NetworkHandler, asyncify +from royalnet.utils import asyncify from royalnet.audio import YtdlDiscord from royalnet.audio.playmodes import Playlist from royalnet.bots import DiscordBot -from royalherald import Request, ResponseSuccess -class ZawarudoNH(NetworkHandler): - message_type = "music_zawarudo" +class ZawarudoCommand(Command): + name: str = "zawarudo" - ytdl_args = { - "format": "bestaudio/best", - "outtmpl": f"./downloads/%(title)s.%(ext)s" - } + aliases = ["theworld", "world"] - @classmethod - async def discord(cls, bot: "DiscordBot", data: dict): + description: str = "Ferma il tempo!" + + syntax = "[ [guild] ] [1-9]" + + @staticmethod + async def _legacy_zawarudo_handler(bot: "DiscordBot", guild_name: typing.Optional[str], time: int): # Find the matching guild - if data["guild_name"]: - guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(data["guild_name"]) + if guild_name: + guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name) else: guilds = bot.client.guilds if len(guilds) == 0: @@ -57,7 +57,7 @@ class ZawarudoNH(NetworkHandler): if member.bot: continue await member.edit(mute=True) - await asyncio.sleep(data["time"]) + await asyncio.sleep(time) await bot.add_to_music_data(zw_end, guild) for member in affected: member: typing.Union[discord.User, discord.Member] @@ -66,21 +66,14 @@ class ZawarudoNH(NetworkHandler): await member.edit(mute=False) bot.music_data[guild] = old_playlist await bot.advance_music_data(guild) - return ResponseSuccess() + return {} - -class ZawarudoCommand(Command): - name: str = "zawarudo" - - aliases = ["theworld", "world"] - - description: str = "Ferma il tempo!" - - syntax = "[ [guild] ] [1-9]" + _event_name = "_legacy_zawarudo" def __init__(self, interface: CommandInterface): super().__init__(interface) - interface.register_net_handler(ZawarudoNH.message_type, ZawarudoNH) + if interface.name == "discord": + interface.register_herald_action(self._event_name, self._legacy_zawarudo_handler) async def run(self, args: CommandArgs, data: CommandData) -> None: guild_name, time = args.match(r"(?:\[(.+)])?\s*(.+)?") @@ -93,4 +86,7 @@ class ZawarudoCommand(Command): if time > 10: raise InvalidInputError("The World can stop time only for 10 seconds.") await data.reply(f"🕒 ZA WARUDO! TOKI WO TOMARE!") - await self.interface.net_request(Request(ZawarudoNH.message_type, {"time": time, "guild_name": guild_name}), "discord") + await self.interface.call_herald_action("discord", self._event_name, { + "guild_name": guild_name, + "time": time + }) diff --git a/royalnet/utils/__init__.py b/royalnet/utils/__init__.py index 4a548832..c1721cf1 100644 --- a/royalnet/utils/__init__.py +++ b/royalnet/utils/__init__.py @@ -5,10 +5,23 @@ from .escaping import telegram_escape, discord_escape from .safeformat import safeformat from .classdictjanitor import cdj from .sleepuntil import sleep_until -from .networkhandler import NetworkHandler from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat, splitstring, ordinalformat from .parse5etoolsentry import parse_5etools_entry -__all__ = ["asyncify", "safeformat", "cdj", "sleep_until", "plusformat", - "NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat", - "telegram_escape", "discord_escape", "splitstring", "parse_5etools_entry", "ordinalformat"] +__all__ = [ + "asyncify", + "safeformat", + "cdj", + "sleep_until", + "plusformat", + "andformat", + "plusformat", + "fileformat", + "ytdldateformat", + "numberemojiformat", + "telegram_escape", + "discord_escape", + "splitstring", + "parse_5etools_entry", + "ordinalformat", +]