diff --git a/src/bot.py b/src/bot.py index f189460..ced8e29 100644 --- a/src/bot.py +++ b/src/bot.py @@ -7,6 +7,8 @@ from meta import CrocBot, conf, setup_main_logger, args from data import Database from constants import DATA_VERSION +from modules import setup + logger = logging.getLogger(__name__) @@ -30,10 +32,9 @@ async def main(): config=conf, dbconn=db, adapter=adapter, + setup=setup, ) - # await bot.load_module('modules') - try: await bot.start() finally: diff --git a/src/meta/crocbot.py b/src/meta/crocbot.py index de36f98..f532b4d 100644 --- a/src/meta/crocbot.py +++ b/src/meta/crocbot.py @@ -15,7 +15,7 @@ logger = logging.getLogger(__name__) class CrocBot(commands.Bot): - def __init__(self, *args, config: Conf, dbconn: Database, **kwargs): + def __init__(self, *args, config: Conf, dbconn: Database, setup=None, **kwargs): kwargs.setdefault('client_id', config.bot['client_id']) kwargs.setdefault('client_secret', config.bot['client_secret']) kwargs.setdefault('bot_id', config.bot['bot_id']) @@ -26,6 +26,7 @@ class CrocBot(commands.Bot): self.config = config self.dbconn = dbconn self.data: BotData = dbconn.load_registry(BotData()) + self._setup_hook = setup self.joined: dict[str, BotChannel] = {} @@ -63,6 +64,9 @@ class CrocBot(commands.Bot): url = self.get_auth_url(scopes) logger.info("User account authorisation url: %s", url) + if self._setup_hook is not None: + await self._setup_hook(self) + logger.info("Finished setup") def get_auth_url(self, scopes: Optional[Scopes] = None): diff --git a/src/modules/__init__.py b/src/modules/__init__.py index 8e286e1..ccce639 100644 --- a/src/modules/__init__.py +++ b/src/modules/__init__.py @@ -1,15 +1,3 @@ - -this_package = 'modules' - -active = [ - '.vstudio', -] - - -def prepare(bot): - for ext in active: - bot.load_module(this_package + ext) - async def setup(bot): - for ext in active: - await bot.load_module(this_package + ext) + from . import koans + await koans.setup(bot) diff --git a/src/modules/koans/__init__.py b/src/modules/koans/__init__.py new file mode 100644 index 0000000..4070a96 --- /dev/null +++ b/src/modules/koans/__init__.py @@ -0,0 +1,7 @@ +import logging + +logger = logging.getLogger(__name__) + +async def setup(bot): + from .component import KoanComponent + await bot.add_component(KoanComponent(bot)) diff --git a/src/modules/koans/component.py b/src/modules/koans/component.py new file mode 100644 index 0000000..b0fb7ce --- /dev/null +++ b/src/modules/koans/component.py @@ -0,0 +1,123 @@ +from typing import Optional +import random +import twitchio +from twitchio.ext import commands as cmds + +from datamodels import Koan, Communities + +from . import logger + + +class KoanComponent(cmds.Component): + def __init__(self, bot): + self.bot = bot + + @cmds.Component.listener() + async def event_message(self, payload: twitchio.ChatMessage) -> None: + print(f"[{payload.broadcaster.name}] - {payload.chatter.name}: {payload.text}") + + @cmds.group(invoke_fallback=True) + async def koans(self, ctx: cmds.Context) -> None: + """ + List the (names of the) koans in this channel. + + !koans + """ + community = await Communities.fetch_or_create(twitchid=ctx.channel.id, name=ctx.channel.name) + cid = community.communityid + + koans = await Koan.fetch_where(communityid=cid) + if koans: + names = ', '.join(koan.name for koan in koans) + await ctx.reply( + f"Koans: {names}" + ) + else: + await ctx.reply("No koans have been made in this channel!") + + @koans.command(name='add', aliases=['new', 'create']) + async def koans_add(self, ctx: cmds.Context, name: str, *, text: str): + """ + Add or overwrite a koan to this channel. + + !koans add wind This is a wind koan + """ + community = await Communities.fetch_or_create(twitchid=ctx.channel.id, name=ctx.channel.name) + cid = community.communityid + + name = name.lower() + + assert isinstance(ctx.author, twitchio.Chatter) + if (ctx.author.moderator or ctx.author.broadcaster): + # Delete the koan with this name if it exists + existing = await Koan.table.delete_where( + communityid=cid, + name=name, + ) + + # Insert the new koan + await Koan.create( + communityid=cid, + name=name, + message=text + ) + + # Ack + if existing: + await ctx.reply(f"Updated the koan '{name}'") + else: + await ctx.reply(f"Created the new koan '{name}'") + + @koans.command(name='del', aliases=['delete', 'rm', 'remove']) + async def koans_del(self, ctx: cmds.Context, name: str): + """ + Remove a koan from this channel by name. + + !koans del wind + """ + community = await Communities.fetch_or_create(twitchid=ctx.channel.id, name=ctx.channel.name) + cid = community.communityid + + name = name.lower() + + assert isinstance(ctx.author, twitchio.Chatter) + if (ctx.author.moderator or ctx.author.broadcaster): + # Delete the koan with this name if it exists + existing = await Koan.table.delete_where( + communityid=cid, + name=name, + ) + if existing: + await ctx.reply(f"Deleted the koan '{name}'") + else: + await ctx.reply(f"The koan '{name}' does not exist to delete!") + + @cmds.command(name='koan') + async def koan(self, ctx: cmds.Context, name: Optional[str] = None): + """ + Show a koan from this channel. Optionally by name. + + !koan + !koan wind + """ + community = await Communities.fetch_or_create(twitchid=ctx.channel.id, name=ctx.channel.name) + cid = community.communityid + + if name is not None: + name = name.lower() + koans = await Koan.fetch_where( + communityid=cid, + name=name + ) + if koans: + koan = koans[0] + await ctx.reply(koan.message) + else: + await ctx.reply(f"The requested koan '{name}' does not exist! Use '{ctx.prefix}koans' to see all the koans.") + else: + koans = await Koan.fetch_where(communityid=cid) + if koans: + koan = random.choice(koans) + await ctx.reply(koan.message) + else: + await ctx.reply("This channel doesn't have any koans!")