From 51e7ef80bea0279529d1c559d3b2da708c8580fb Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 24 Aug 2019 00:50:21 +0200 Subject: [PATCH] Port a few commands to the new format --- royalnet/bots/generic.py | 2 +- royalnet/commands/command.py | 2 +- royalnet/commands/royalgames/__init__.py | 8 +- royalnet/commands/royalgames/ciaoruozi.py | 35 ++--- royalnet/commands/royalgames/color.py | 20 +-- royalnet/commands/royalgames/cv.py | 43 +++--- .../commands/royalgames/{ => old}/author.py | 0 royalnet/commands/royalgames/old/ciaoruozi.py | 22 +++ royalnet/commands/royalgames/old/color.py | 14 ++ royalnet/commands/royalgames/old/cv.py | 127 ++++++++++++++++++ .../royalgames/{ => old}/dateparser.py | 0 .../royalgames/{ => old}/debug_create.py | 0 .../commands/royalgames/{ => old}/diario.py | 0 .../commands/royalgames/{ => old}/dlmusic.py | 0 .../royalgames/{ => old}/error_handler.py | 0 royalnet/commands/royalgames/{ => old}/id.py | 0 royalnet/commands/royalgames/{ => old}/kv.py | 0 .../commands/royalgames/{ => old}/kvactive.py | 0 .../commands/royalgames/{ => old}/kvroll.py | 0 .../commands/royalgames/{ => old}/missing.py | 0 .../commands/royalgames/{ => old}/null.py | 0 .../commands/royalgames/{ => old}/pause.py | 0 .../commands/royalgames/{ => old}/play.py | 0 .../commands/royalgames/{ => old}/playmode.py | 0 .../commands/royalgames/{ => old}/queue.py | 0 .../commands/royalgames/{ => old}/rage.py | 0 .../commands/royalgames/{ => old}/reminder.py | 0 .../royalgames/{ => old}/royalnetprofile.py | 0 .../commands/royalgames/{ => old}/ship.py | 0 .../commands/royalgames/{ => old}/skip.py | 0 .../commands/royalgames/{ => old}/smecds.py | 0 .../commands/royalgames/{ => old}/summon.py | 0 .../commands/royalgames/{ => old}/sync.py | 0 .../royalgames/{ => old}/videochannel.py | 0 .../royalgames/{ => old}/videoinfo.py | 0 royalnet/commands/royalgames/ping.py | 9 +- royalnet/royalgames.py | 5 +- 37 files changed, 232 insertions(+), 55 deletions(-) rename royalnet/commands/royalgames/{ => old}/author.py (100%) create mode 100644 royalnet/commands/royalgames/old/ciaoruozi.py create mode 100644 royalnet/commands/royalgames/old/color.py create mode 100644 royalnet/commands/royalgames/old/cv.py rename royalnet/commands/royalgames/{ => old}/dateparser.py (100%) rename royalnet/commands/royalgames/{ => old}/debug_create.py (100%) rename royalnet/commands/royalgames/{ => old}/diario.py (100%) rename royalnet/commands/royalgames/{ => old}/dlmusic.py (100%) rename royalnet/commands/royalgames/{ => old}/error_handler.py (100%) rename royalnet/commands/royalgames/{ => old}/id.py (100%) rename royalnet/commands/royalgames/{ => old}/kv.py (100%) rename royalnet/commands/royalgames/{ => old}/kvactive.py (100%) rename royalnet/commands/royalgames/{ => old}/kvroll.py (100%) rename royalnet/commands/royalgames/{ => old}/missing.py (100%) rename royalnet/commands/royalgames/{ => old}/null.py (100%) rename royalnet/commands/royalgames/{ => old}/pause.py (100%) rename royalnet/commands/royalgames/{ => old}/play.py (100%) rename royalnet/commands/royalgames/{ => old}/playmode.py (100%) rename royalnet/commands/royalgames/{ => old}/queue.py (100%) rename royalnet/commands/royalgames/{ => old}/rage.py (100%) rename royalnet/commands/royalgames/{ => old}/reminder.py (100%) rename royalnet/commands/royalgames/{ => old}/royalnetprofile.py (100%) rename royalnet/commands/royalgames/{ => old}/ship.py (100%) rename royalnet/commands/royalgames/{ => old}/skip.py (100%) rename royalnet/commands/royalgames/{ => old}/smecds.py (100%) rename royalnet/commands/royalgames/{ => old}/summon.py (100%) rename royalnet/commands/royalgames/{ => old}/sync.py (100%) rename royalnet/commands/royalgames/{ => old}/videochannel.py (100%) rename royalnet/commands/royalgames/{ => old}/videoinfo.py (100%) diff --git a/royalnet/bots/generic.py b/royalnet/bots/generic.py index 1ed2ed7a..2f84c3ba 100644 --- a/royalnet/bots/generic.py +++ b/royalnet/bots/generic.py @@ -24,10 +24,10 @@ class GenericBot: self._Interface = self._interface_factory() self._Data = self._data_factory() self.commands = {} + self.network_handlers: typing.Dict[str, typing.Type[NetworkHandler]] = {} for SelectedCommand in commands: interface = self._Interface() self.commands[f"{interface.prefix}{SelectedCommand.name}"] = SelectedCommand(interface) - self.network_handlers: typing.Dict[str, typing.Type[NetworkHandler]] = {} log.debug(f"Successfully bound commands") def _interface_factory(self) -> typing.Type[CommandInterface]: diff --git a/royalnet/commands/command.py b/royalnet/commands/command.py index 8a303e65..43897cdb 100644 --- a/royalnet/commands/command.py +++ b/royalnet/commands/command.py @@ -13,7 +13,7 @@ class Command: description: str = NotImplemented """A small description of the command, to be displayed when the command is being autocompleted.""" - syntax: str = NotImplemented + syntax: str = "" """The syntax of the command, to be displayed when a :py:exc:`royalnet.error.InvalidInputError` is raised, in the format ``(required_arg) [optional_arg]``.""" diff --git a/royalnet/commands/royalgames/__init__.py b/royalnet/commands/royalgames/__init__.py index 0b41e08e..472f55fc 100644 --- a/royalnet/commands/royalgames/__init__.py +++ b/royalnet/commands/royalgames/__init__.py @@ -4,5 +4,11 @@ These probably won't suit your needs, as they are tailored for the bots of the R may be useful to develop new ones.""" from .ping import PingCommand +from .ciaoruozi import CiaoruoziCommand +from .color import ColorCommand +from .cv import CvCommand -__all__ = ["PingCommand"] +__all__ = ["PingCommand", + "CiaoruoziCommand", + "ColorCommand", + "CvCommand"] diff --git a/royalnet/commands/royalgames/ciaoruozi.py b/royalnet/commands/royalgames/ciaoruozi.py index 2929512e..c23056f9 100644 --- a/royalnet/commands/royalgames/ciaoruozi.py +++ b/royalnet/commands/royalgames/ciaoruozi.py @@ -1,22 +1,25 @@ -from ..utils import Command, Call -from telegram import Update, User +import typing +import telegram +from ..command import Command +from ..commandinterface import CommandInterface +from ..commandargs import CommandArgs +from ..commanddata import CommandData class CiaoruoziCommand(Command): + name: str = "ciaoruozi" - command_name = "ciaoruozi" - command_description = "Saluta Ruozi, anche se non รจ piรน in RYG." - command_syntax = "" + description: str = "Saluta Ruozi, un leggendario essere che una volta era in Royal Games." - @classmethod - async def common(cls, call: "Call"): - await call.reply("๐Ÿ‘‹ Ciao Ruozi!") + syntax: str = "" - @classmethod - async def telegram(cls, call: Call): - update: Update = call.kwargs["update"] - user: User = update.effective_user - if user.id == 112437036: - await call.reply("๐Ÿ‘‹ Ciao me!") - else: - await call.reply("๐Ÿ‘‹ Ciao Ruozi!") + require_alchemy_tables: typing.Set = set() + + 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 + if user.id == 112437036: + await data.reply("๐Ÿ‘‹ Ciao me!") + return + await data.reply("๐Ÿ‘‹ Ciao Ruozi!") diff --git a/royalnet/commands/royalgames/color.py b/royalnet/commands/royalgames/color.py index ff9a458f..b711cb4f 100644 --- a/royalnet/commands/royalgames/color.py +++ b/royalnet/commands/royalgames/color.py @@ -1,14 +1,16 @@ -from ..utils import Command, Call +import typing +from ..command import Command +from ..commandinterface import CommandInterface +from ..commandargs import CommandArgs +from ..commanddata import CommandData class ColorCommand(Command): + name: str = "color" - command_name = "color" - command_description = "Invia un colore in chat...?" - command_syntax = "" + description: str = "Invia un colore in chat...?" - @classmethod - async def common(cls, call: Call): - await call.reply(""" - [i]I am sorry, unknown error occured during working with your request, Admin were notified[/i] - """) + async def run(self, args: CommandArgs, data: CommandData) -> None: + await data.reply(""" + [i]I am sorry, unknown error occured during working with your request, Admin were notified[/i] + """) diff --git a/royalnet/commands/royalgames/cv.py b/royalnet/commands/royalgames/cv.py index cd4c37d2..79b22760 100644 --- a/royalnet/commands/royalgames/cv.py +++ b/royalnet/commands/royalgames/cv.py @@ -1,11 +1,13 @@ -import typing import discord -import asyncio -from ..utils import Command, Call, NetworkHandler, andformat -from ..network import Request, ResponseSuccess -from ..error import NoneFoundError, TooManyFoundError -if typing.TYPE_CHECKING: - from ..bots import DiscordBot +import typing +from ..command import Command +from ..commandinterface import CommandInterface +from ..commandargs import CommandArgs +from ..commanddata import CommandData +from ...network import Request, ResponseSuccess +from ...utils import NetworkHandler, andformat +from ...bots import DiscordBot +from ...error import * class CvNH(NetworkHandler): @@ -41,14 +43,14 @@ class CvNH(NetworkHandler): # Edit the message, sorted by channel for channel in sorted(channels, key=lambda c: -c): members_in_channels[channel].sort(key=lambda x: x.nick if x.nick is not None else x.name) - if channel == 0: + if channel == 0 and len(members_in_channels[0]) > 0: message += "[b]Non in chat vocale:[/b]\n" else: message += f"[b]In #{channels[channel].name}:[/b]\n" for member in members_in_channels[channel]: member: typing.Union[discord.User, discord.Member] # Ignore not-connected non-notable members - if not data["full"] and channel == 0 and len(member.roles) < 2: + if not data["everyone"] and channel == 0 and len(member.roles) < 2: continue # Ignore offline members if member.status == discord.Status.offline and member.voice is None: @@ -113,15 +115,20 @@ class CvNH(NetworkHandler): class CvCommand(Command): + name: str = "cv" - command_name = "cv" - command_description = "Elenca le persone attualmente connesse alla chat vocale." - command_syntax = "[guildname]" + description: str = "Elenca le persone attualmente connesse alla chat vocale." - network_handlers = [CvNH] + syntax: str = "[guildname] " - @classmethod - async def common(cls, call: Call): - guild_name = call.args.optional(0) - response = await call.net_request(Request("discord_cv", {"guild_name": guild_name, "full": False}), "discord") - await call.reply(response["response"]) + def __init__(self, interface: CommandInterface): + super().__init__(interface) + interface.register_net_handler("discord_cv", CvNH) + + 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") + await data.reply(response["response"]) diff --git a/royalnet/commands/royalgames/author.py b/royalnet/commands/royalgames/old/author.py similarity index 100% rename from royalnet/commands/royalgames/author.py rename to royalnet/commands/royalgames/old/author.py diff --git a/royalnet/commands/royalgames/old/ciaoruozi.py b/royalnet/commands/royalgames/old/ciaoruozi.py new file mode 100644 index 00000000..2929512e --- /dev/null +++ b/royalnet/commands/royalgames/old/ciaoruozi.py @@ -0,0 +1,22 @@ +from ..utils import Command, Call +from telegram import Update, User + + +class CiaoruoziCommand(Command): + + command_name = "ciaoruozi" + command_description = "Saluta Ruozi, anche se non รจ piรน in RYG." + command_syntax = "" + + @classmethod + async def common(cls, call: "Call"): + await call.reply("๐Ÿ‘‹ Ciao Ruozi!") + + @classmethod + async def telegram(cls, call: Call): + update: Update = call.kwargs["update"] + user: User = update.effective_user + if user.id == 112437036: + await call.reply("๐Ÿ‘‹ Ciao me!") + else: + await call.reply("๐Ÿ‘‹ Ciao Ruozi!") diff --git a/royalnet/commands/royalgames/old/color.py b/royalnet/commands/royalgames/old/color.py new file mode 100644 index 00000000..ff9a458f --- /dev/null +++ b/royalnet/commands/royalgames/old/color.py @@ -0,0 +1,14 @@ +from ..utils import Command, Call + + +class ColorCommand(Command): + + command_name = "color" + command_description = "Invia un colore in chat...?" + command_syntax = "" + + @classmethod + async def common(cls, call: Call): + await call.reply(""" + [i]I am sorry, unknown error occured during working with your request, Admin were notified[/i] + """) diff --git a/royalnet/commands/royalgames/old/cv.py b/royalnet/commands/royalgames/old/cv.py new file mode 100644 index 00000000..cd4c37d2 --- /dev/null +++ b/royalnet/commands/royalgames/old/cv.py @@ -0,0 +1,127 @@ +import typing +import discord +import asyncio +from ..utils import Command, Call, NetworkHandler, andformat +from ..network import Request, ResponseSuccess +from ..error import NoneFoundError, TooManyFoundError +if typing.TYPE_CHECKING: + from ..bots import DiscordBot + + +class CvNH(NetworkHandler): + message_type = "discord_cv" + + @classmethod + async def discord(cls, bot: "DiscordBot", data: dict): + # Find the matching guild + if data["guild_name"]: + guild: discord.Guild = bot.client.find_guild_by_name(data["guild_name"]) + else: + if len(bot.client.guilds) == 0: + raise NoneFoundError("No guilds found") + if len(bot.client.guilds) > 1: + raise TooManyFoundError("Multiple guilds found") + guild = list(bot.client.guilds)[0] + # Edit the message, sorted by channel + discord_members = list(guild.members) + channels = {0: None} + members_in_channels = {0: []} + message = "" + # Find all the channels + for member in discord_members: + if member.voice is not None: + channel = members_in_channels.get(member.voice.channel.id) + if channel is None: + members_in_channels[member.voice.channel.id] = list() + channel = members_in_channels[member.voice.channel.id] + channels[member.voice.channel.id] = member.voice.channel + channel.append(member) + else: + members_in_channels[0].append(member) + # Edit the message, sorted by channel + for channel in sorted(channels, key=lambda c: -c): + members_in_channels[channel].sort(key=lambda x: x.nick if x.nick is not None else x.name) + if channel == 0: + message += "[b]Non in chat vocale:[/b]\n" + else: + message += f"[b]In #{channels[channel].name}:[/b]\n" + for member in members_in_channels[channel]: + member: typing.Union[discord.User, discord.Member] + # Ignore not-connected non-notable members + if not data["full"] and channel == 0 and len(member.roles) < 2: + continue + # Ignore offline members + if member.status == discord.Status.offline and member.voice is None: + continue + # Online status emoji + if member.bot: + message += "๐Ÿค– " + elif member.status == discord.Status.online: + message += "๐Ÿ”ต " + elif member.status == discord.Status.idle: + message += "โšซ๏ธ " + elif member.status == discord.Status.dnd: + message += "๐Ÿ”ด " + elif member.status == discord.Status.offline: + message += "โšช๏ธ " + # Voice + if channel != 0: + # Voice status + if member.voice.afk: + message += "๐Ÿ’ค " + elif member.voice.self_deaf or member.voice.deaf: + message += "๐Ÿ”‡ " + elif member.voice.self_mute or member.voice.mute: + message += "๐Ÿ”ˆ " + elif member.voice.self_video: + message += "๐Ÿ“บ " + else: + message += "๐Ÿ”Š " + # Nickname + if member.nick is not None: + message += f"[i]{member.nick}[/i]" + else: + message += member.name + # Game or stream + if member.activity is not None: + if member.activity.type == discord.ActivityType.playing: + message += f" | ๐ŸŽฎ {member.activity.name}" + # Rich presence + try: + if member.activity.state is not None: + message += f" ({member.activity.state}" \ + f" | {member.activity.details})" + except AttributeError: + pass + elif member.activity.type == discord.ActivityType.streaming: + message += f" | ๐Ÿ“ก {member.activity.url}" + elif member.activity.type == discord.ActivityType.listening: + if isinstance(member.activity, discord.Spotify): + if member.activity.title == member.activity.album: + message += f" | ๐ŸŽง {member.activity.title} ({andformat(member.activity.artists, final=' e ')})" + else: + message += f" | ๐ŸŽง {member.activity.title} ({member.activity.album} | {andformat(member.activity.artists, final=' e ')})" + else: + message += f" | ๐ŸŽง {member.activity.name}" + elif member.activity.type == discord.ActivityType.watching: + message += f" | ๐Ÿ“บ {member.activity.name}" + else: + message += f" | โ“ Unknown activity" + message += "\n" + message += "\n" + return ResponseSuccess({"response": message}) + + +class CvCommand(Command): + + command_name = "cv" + command_description = "Elenca le persone attualmente connesse alla chat vocale." + command_syntax = "[guildname]" + + network_handlers = [CvNH] + + @classmethod + async def common(cls, call: Call): + guild_name = call.args.optional(0) + response = await call.net_request(Request("discord_cv", {"guild_name": guild_name, "full": False}), "discord") + await call.reply(response["response"]) diff --git a/royalnet/commands/royalgames/dateparser.py b/royalnet/commands/royalgames/old/dateparser.py similarity index 100% rename from royalnet/commands/royalgames/dateparser.py rename to royalnet/commands/royalgames/old/dateparser.py diff --git a/royalnet/commands/royalgames/debug_create.py b/royalnet/commands/royalgames/old/debug_create.py similarity index 100% rename from royalnet/commands/royalgames/debug_create.py rename to royalnet/commands/royalgames/old/debug_create.py diff --git a/royalnet/commands/royalgames/diario.py b/royalnet/commands/royalgames/old/diario.py similarity index 100% rename from royalnet/commands/royalgames/diario.py rename to royalnet/commands/royalgames/old/diario.py diff --git a/royalnet/commands/royalgames/dlmusic.py b/royalnet/commands/royalgames/old/dlmusic.py similarity index 100% rename from royalnet/commands/royalgames/dlmusic.py rename to royalnet/commands/royalgames/old/dlmusic.py diff --git a/royalnet/commands/royalgames/error_handler.py b/royalnet/commands/royalgames/old/error_handler.py similarity index 100% rename from royalnet/commands/royalgames/error_handler.py rename to royalnet/commands/royalgames/old/error_handler.py diff --git a/royalnet/commands/royalgames/id.py b/royalnet/commands/royalgames/old/id.py similarity index 100% rename from royalnet/commands/royalgames/id.py rename to royalnet/commands/royalgames/old/id.py diff --git a/royalnet/commands/royalgames/kv.py b/royalnet/commands/royalgames/old/kv.py similarity index 100% rename from royalnet/commands/royalgames/kv.py rename to royalnet/commands/royalgames/old/kv.py diff --git a/royalnet/commands/royalgames/kvactive.py b/royalnet/commands/royalgames/old/kvactive.py similarity index 100% rename from royalnet/commands/royalgames/kvactive.py rename to royalnet/commands/royalgames/old/kvactive.py diff --git a/royalnet/commands/royalgames/kvroll.py b/royalnet/commands/royalgames/old/kvroll.py similarity index 100% rename from royalnet/commands/royalgames/kvroll.py rename to royalnet/commands/royalgames/old/kvroll.py diff --git a/royalnet/commands/royalgames/missing.py b/royalnet/commands/royalgames/old/missing.py similarity index 100% rename from royalnet/commands/royalgames/missing.py rename to royalnet/commands/royalgames/old/missing.py diff --git a/royalnet/commands/royalgames/null.py b/royalnet/commands/royalgames/old/null.py similarity index 100% rename from royalnet/commands/royalgames/null.py rename to royalnet/commands/royalgames/old/null.py diff --git a/royalnet/commands/royalgames/pause.py b/royalnet/commands/royalgames/old/pause.py similarity index 100% rename from royalnet/commands/royalgames/pause.py rename to royalnet/commands/royalgames/old/pause.py diff --git a/royalnet/commands/royalgames/play.py b/royalnet/commands/royalgames/old/play.py similarity index 100% rename from royalnet/commands/royalgames/play.py rename to royalnet/commands/royalgames/old/play.py diff --git a/royalnet/commands/royalgames/playmode.py b/royalnet/commands/royalgames/old/playmode.py similarity index 100% rename from royalnet/commands/royalgames/playmode.py rename to royalnet/commands/royalgames/old/playmode.py diff --git a/royalnet/commands/royalgames/queue.py b/royalnet/commands/royalgames/old/queue.py similarity index 100% rename from royalnet/commands/royalgames/queue.py rename to royalnet/commands/royalgames/old/queue.py diff --git a/royalnet/commands/royalgames/rage.py b/royalnet/commands/royalgames/old/rage.py similarity index 100% rename from royalnet/commands/royalgames/rage.py rename to royalnet/commands/royalgames/old/rage.py diff --git a/royalnet/commands/royalgames/reminder.py b/royalnet/commands/royalgames/old/reminder.py similarity index 100% rename from royalnet/commands/royalgames/reminder.py rename to royalnet/commands/royalgames/old/reminder.py diff --git a/royalnet/commands/royalgames/royalnetprofile.py b/royalnet/commands/royalgames/old/royalnetprofile.py similarity index 100% rename from royalnet/commands/royalgames/royalnetprofile.py rename to royalnet/commands/royalgames/old/royalnetprofile.py diff --git a/royalnet/commands/royalgames/ship.py b/royalnet/commands/royalgames/old/ship.py similarity index 100% rename from royalnet/commands/royalgames/ship.py rename to royalnet/commands/royalgames/old/ship.py diff --git a/royalnet/commands/royalgames/skip.py b/royalnet/commands/royalgames/old/skip.py similarity index 100% rename from royalnet/commands/royalgames/skip.py rename to royalnet/commands/royalgames/old/skip.py diff --git a/royalnet/commands/royalgames/smecds.py b/royalnet/commands/royalgames/old/smecds.py similarity index 100% rename from royalnet/commands/royalgames/smecds.py rename to royalnet/commands/royalgames/old/smecds.py diff --git a/royalnet/commands/royalgames/summon.py b/royalnet/commands/royalgames/old/summon.py similarity index 100% rename from royalnet/commands/royalgames/summon.py rename to royalnet/commands/royalgames/old/summon.py diff --git a/royalnet/commands/royalgames/sync.py b/royalnet/commands/royalgames/old/sync.py similarity index 100% rename from royalnet/commands/royalgames/sync.py rename to royalnet/commands/royalgames/old/sync.py diff --git a/royalnet/commands/royalgames/videochannel.py b/royalnet/commands/royalgames/old/videochannel.py similarity index 100% rename from royalnet/commands/royalgames/videochannel.py rename to royalnet/commands/royalgames/old/videochannel.py diff --git a/royalnet/commands/royalgames/videoinfo.py b/royalnet/commands/royalgames/old/videoinfo.py similarity index 100% rename from royalnet/commands/royalgames/videoinfo.py rename to royalnet/commands/royalgames/old/videoinfo.py diff --git a/royalnet/commands/royalgames/ping.py b/royalnet/commands/royalgames/ping.py index ddb29dc9..39687ef3 100644 --- a/royalnet/commands/royalgames/ping.py +++ b/royalnet/commands/royalgames/ping.py @@ -10,12 +10,5 @@ class PingCommand(Command): description: str = "Replies with a Pong!" - syntax: str = "" - - require_alchemy_tables: typing.Set = set() - - def __init__(self, interface: CommandInterface): - super().__init__(interface) - async def run(self, args: CommandArgs, data: CommandData) -> None: - await data.reply("Pong!") + await data.reply("๐Ÿ“ Pong!") diff --git a/royalnet/royalgames.py b/royalnet/royalgames.py index d0a2bb47..31d8e6b9 100644 --- a/royalnet/royalgames.py +++ b/royalnet/royalgames.py @@ -16,7 +16,10 @@ stream_handler = logging.StreamHandler() stream_handler.formatter = logging.Formatter("{asctime}\t{name}\t{levelname}\t{message}", style="{") log.addHandler(stream_handler) -commands = [PingCommand] +commands = [PingCommand, + ColorCommand, + CiaoruoziCommand, + CvCommand] # noinspection PyUnreachableCode if __debug__: