Compare commits

...

1 Commits

Author SHA1 Message Date
fda6847671 Refactor with registry. 2025-09-03 23:43:12 +10:00
7 changed files with 127 additions and 49 deletions

View File

@@ -0,0 +1 @@
from .koans import *

View File

@@ -0,0 +1,20 @@
BEGIN;
-- Koan data {{{
INSERT INTO version_history (component, from_version, to_version, author)
VALUES ('KOANS', 0, 1, 'Initial Creation');
---- !koans lists koans. !koan gives a random koan. !koans add name ... !koans del name ...
CREATE TABLE koans(
koanid INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
communityid INTEGER NOT NULL REFERENCES communities ON UPDATE CASCADE ON DELETE CASCADE,
name TEXT NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
_timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TRIGGER koans_timestamp BEFORE UPDATE ON koans
FOR EACH ROW EXECUTE FUNCTION update_timestamp_column();
-- }}}
COMMIT;

View File

@@ -2,6 +2,4 @@ import logging
logger = logging.getLogger(__name__)
async def setup(bot):
from .component import KoanComponent
await bot.add_component(KoanComponent(bot))
from .twitch import setup as twitch_setup

View File

@@ -0,0 +1,32 @@
from data import Registry, RowModel
from data.columns import String, Timestamp, Integer
class Koan(RowModel):
"""
Schema
======
CREATE TABLE koans(
koanid INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
communityid INTEGER NOT NULL REFERENCES communities ON UPDATE CASCADE ON DELETE CASCADE,
name TEXT NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
_timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
"""
_tablename_ = 'koans'
_cache_ = {}
koanid = Integer(primary=True)
communityid = Integer()
name = String()
message = String()
created_at = Timestamp()
_timestamp = Timestamp()
class KoanData(Registry):
VERSION = ('KOANS', 1)
koans = Koan.table

View File

@@ -0,0 +1,34 @@
from typing import Optional
from .data import Koan, KoanData
class KoanRegistry:
def __init__(self, data: KoanData):
self.data = data
async def init(self):
await self.data.init()
async def get_community_koans(self, communityid: int) -> list[Koan]:
return await Koan.fetch_where(communityid=communityid)
async def get_koan(self, koanid: int) -> Optional[Koan]:
return await Koan.fetch(koanid)
async def get_koan_named(self, communityid: int, name: str) -> Optional[Koan]:
name = name.lower()
koans = await Koan.fetch_where(communityid=communityid, name=name)
if koans:
return koans[0]
else:
return None
async def create_koan(self, communityid: int, name: str, message: str) -> Koan:
name = name.lower()
await Koan.table.delete_where(communityid=communityid, name=name)
koan = await Koan.create(
communityid=communityid,
name=name,
message=message
)
return koan

5
koans/twitch/__init__.py Normal file
View File

@@ -0,0 +1,5 @@
from .. import logger
async def setup(bot):
from .component import KoanComponent
await bot.add_component(KoanComponent(bot))

View File

@@ -3,14 +3,23 @@ import random
import twitchio
from twitchio.ext import commands as cmds
from datamodels import Koan, Communities
from meta import Bot, Context
from . import logger
from ..koans import KoanRegistry
from ..data import KoanData
class KoanComponent(cmds.Component):
def __init__(self, bot):
def __init__(self, bot: Bot):
self.bot = bot
self.data = bot.dbconn.load_registry(KoanData())
self.koans = KoanRegistry(self.data)
async def component_load(self):
await self.data.init()
await self.bot.version_check(*self.data.VERSION)
await self.koans.init()
@cmds.Component.listener()
async def event_message(self, payload: twitchio.ChatMessage) -> None:
@@ -23,10 +32,11 @@ class KoanComponent(cmds.Component):
!koans
"""
community = await Communities.fetch_or_create(twitchid=ctx.channel.id, name=ctx.channel.name)
community = await self.bot.profiles.fetch_community(ctx.broadcaster)
cid = community.communityid
koans = await Koan.fetch_where(communityid=cid)
koans = await self.koans.get_community_koans(cid)
if koans:
names = ', '.join(koan.name for koan in koans)
await ctx.reply(
@@ -36,61 +46,43 @@ class KoanComponent(cmds.Component):
await ctx.reply("No koans have been made in this channel!")
@koans.command(name='add', aliases=['new', 'create'])
@cmds.is_moderator()
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)
community = await self.bot.profiles.fetch_community(ctx.broadcaster)
cid = community.communityid
name = name.lower()
existing = await self.koans.get_koan_named(cid, name)
await self.koans.create_koan(cid, name, text)
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}'")
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'])
@cmds.is_moderator()
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)
community = await self.bot.profiles.fetch_community(ctx.broadcaster)
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!")
koan = await self.koans.get_koan_named(cid, name)
if koan:
await koan.delete()
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):
@@ -100,22 +92,18 @@ class KoanComponent(cmds.Component):
!koan
!koan wind
"""
community = await Communities.fetch_or_create(twitchid=ctx.channel.id, name=ctx.channel.name)
community = await self.bot.profiles.fetch_community(ctx.broadcaster)
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]
koan = await self.koans.get_koan_named(cid, name)
if koan:
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)
koans = await self.koan.get_community_koans(communityid=cid)
if koans:
koan = random.choice(koans)
await ctx.reply(koan.message)