import twitchio from meta import Bot from ..customcmd.client import ExecClient from ..customcmd.data import CustomCmd, CustomCmdData from .context import CustomContext, CustomCmdUser class TwitchCmdClient(ExecClient): def __init__(self, bot: Bot, data: CustomCmdData): super().__init__() self.bot = bot self.data = data async def process_message(self, message: twitchio.ChatMessage): # Check the prefixes in this community # Or get the 'possible' prefixes in this context, which should be mostly cached prefixes = await self.get_prefixes(message) prefixes = sorted(prefixes, key=len, reverse=True) content = message.text if message.reply: # Strip the hidden mention prefix from the start of the message prefix = message.reply.parent_user.mention content = content[len(prefix) + 1 :] # If we start with a valid prefix, parse out a command name if prefix := next((p for p in prefixes if content.startswith(p)), None): # Strip the valid prefix content = content[len(prefix) :].strip() if not content: # Exit early, no command return # Extract possible command word maybe_command, *args = content.split() maybe_command = maybe_command.lower() # Lookup command words in this community (cache?) comm = await self.bot.profiles.fetch_community(message.broadcaster) cmdmap = await self.get_commands_in(comm.communityid) if cmd := cmdmap.get(maybe_command): # We now finally have a command. # Read the arguments, build the context, run the command. # TODO: Check the permissions and log etc. # TODO: Exception handling, as usual # TODO: Nice string reprs ctx = CustomContext( bot=self.bot, args=args, alias=maybe_command, used_prefix=prefix, message=message, initial_globals={ "author": CustomCmdUser(message.chatter), "channel": CustomCmdUser(message.broadcaster), }, ) result = await self.run_command(ctx, cmd.response) if result: await message.broadcaster.send_message(result, sender=self.bot.user) async def get_prefixes(self, message: twitchio.ChatMessage): # TODO: return ("!",) async def get_commands_in(self, communityid: int) -> dict[str, CustomCmd]: """ Get the custom commands in this community. Returns a map of {alias -> CustomCommand} """ # TODO: Alias support commands = await CustomCmd.fetch_where(communityid=communityid) return {cmd.name: cmd for cmd in commands}