From 8f6fdf33814d7a70af69cacb503e1e76ce23ffdf Mon Sep 17 00:00:00 2001 From: Interitio Date: Fri, 27 Sep 2024 00:36:12 +1000 Subject: [PATCH] feat(counters): Add details and initial refactor. --- data/schema.sql | 2 + src/modules/counters/cog.py | 132 +++++++++++++++++------------ src/modules/counters/data.py | 9 +- src/modules/counters/migration.sql | 2 + 4 files changed, 86 insertions(+), 59 deletions(-) create mode 100644 src/modules/counters/migration.sql diff --git a/data/schema.sql b/data/schema.sql index 504ae859..51d5fb5f 100644 --- a/data/schema.sql +++ b/data/schema.sql @@ -1454,6 +1454,7 @@ CREATE TABLE shoutouts( CREATE TABLE counters( counterid SERIAL PRIMARY KEY, name TEXT NOT NULL, + category TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE UNIQUE INDEX counters_name ON counters (name); @@ -1464,6 +1465,7 @@ CREATE TABLE counter_log( userid INTEGER NOT NULL, value INTEGER NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + details TEXT, context_str TEXT ); CREATE INDEX counter_log_counterid ON counter_log (counterid); diff --git a/src/modules/counters/cog.py b/src/modules/counters/cog.py index 9b1dd032..0e99aba9 100644 --- a/src/modules/counters/cog.py +++ b/src/modules/counters/cog.py @@ -25,6 +25,52 @@ class PERIOD(Enum): YEAR = ('this year', 'y', 'year', 'yearly') +def counter_cmd_factory( + counter: str, + response: str, + default_period: Optional[PERIOD] = PERIOD.STREAM, + context: Optional[str] = None +): + context = context or f"cmd: {counter}" + async def counter_cmd(cog, ctx: commands.Context, *, args: Optional[str] = None): + userid = int(ctx.author.id) + channelid = int((await ctx.channel.user()).id) + period, start_time = await cog.parse_period(userid, '', default=default_period) + + args = (args or '').strip(" 󠀀 ") + splits = args.split(maxsplit=1) + splits = [split.strip() for split in splits if split] + + details = None + amount = 1 + + if splits: + if splits[0].isdigit() or (splits[0].startswith('-') and splits[0][1:].isdigit()): + amount = int(splits[0]) + splits = splits[1:] + if splits: + details = ' '.join(splits) + + await cog.add_to_counter( + counter, userid, amount, + context=context, + details=details + ) + lb = await cog.leaderboard(counter, start_time=start_time) + user_total = lb.get(userid, 0) + total = sum(lb.values()) + await ctx.reply( + response.format( + total=total, + period=period, + period_name=period.value[0], + detailsorname=details or counter, + user_total=user_total, + ) + ) + return counter_cmd + + class CounterCog(LionCog): def __init__(self, bot: LionBot): self.bot = bot @@ -80,13 +126,19 @@ class CounterCog(LionCog): if row: await self.data.CounterEntry.table.delete_where(counterid=row.counterid) - async def add_to_counter(self, counter: str, userid: int, value: int, context: Optional[str]=None): + async def add_to_counter( + self, + counter: str, userid: int, value: int, + context: Optional[str]=None, + details: Optional[str]=None, + ): row = await self.fetch_counter(counter) return await self.data.CounterEntry.create( counterid=row.counterid, userid=userid, value=value, - context_str=context + context_str=context, + details=details ) async def leaderboard(self, counter: str, start_time=None): @@ -214,79 +266,47 @@ class CounterCog(LionCog): # Misc actual counter commands # TODO: Factor this out to a different module... - @commands.command() - async def tea(self, ctx: commands.Context, *, args: Optional[str]=None): - userid = int(ctx.author.id) - channelid = int((await ctx.channel.user()).id) - period, start_time = await self.parse_period(channelid, '') - counter = 'tea' + # TODO: Probably make these all alias commands - await self.add_to_counter( - counter, - userid, - 1, - context='cmd: tea' + tea_cmd = commands.command(name='tea')( + counter_cmd_factory( + 'tea', + "Enjoy your {detailsorname}! We have had {total} cups of tea {period_name}." ) - lb = await self.leaderboard(counter, start_time=start_time) - user_total = lb.get(userid, 0) - total = sum(lb.values()) - await ctx.reply(f"Enjoy your tea! We have had {total} cups of tea {period.value[0]}.") + ) @commands.command() async def tealb(self, ctx: commands.Context, *, args: str = ''): user = await ctx.channel.user() await ctx.reply(await self.formatted_lb('tea', args, int(user.id))) - @commands.command() - async def coffee(self, ctx: commands.Context, *, args: Optional[str]=None): - userid = int(ctx.author.id) - channelid = int((await ctx.channel.user()).id) - period, start_time = await self.parse_period(channelid, '') - counter = 'coffee' - - await self.add_to_counter( - counter, - userid, - 1, - context='cmd: coffee' + coffee_cmd = commands.command(name='coffee')( + counter_cmd_factory( + 'coffee', + "Enjoy your {detailsorname}! We have had {total} cups of coffee {period_name}." ) - lb = await self.leaderboard(counter, start_time=start_time) - user_total = lb.get(userid, 0) - total = sum(lb.values()) - await ctx.reply(f"Enjoy your coffee! We have had {total} cups of coffee {period.value[0]}.") + ) @commands.command() async def coffeelb(self, ctx: commands.Context, *, args: str = ''): user = await ctx.channel.user() await ctx.reply(await self.formatted_lb('coffee', args, int(user.id))) - @commands.command() - async def water(self, ctx: commands.Context, *, args: Optional[str]=None): - userid = int(ctx.author.id) - channelid = int((await ctx.channel.user()).id) - period, start_time = await self.parse_period(channelid, '') - counter = 'water' - - await self.add_to_counter( - counter, - userid, - 1, - context='cmd: water' + water_cmd = commands.command(name='water')( + counter_cmd_factory( + 'water', + "Good job hydrating! We have had {total} cups of tea {period_name}." ) - lb = await self.leaderboard(counter, start_time=start_time) - user_total = lb.get(userid, 0) - total = sum(lb.values()) - await ctx.reply(f"Good job hydrating! We have had {total} cups of water {period.value[0]}.") + ) @commands.command() async def waterlb(self, ctx: commands.Context, *, args: str = ''): user = await ctx.channel.user() await ctx.reply(await self.formatted_lb('water', args, int(user.id))) - @commands.command() - async def stuff(self, ctx: commands.Context, *, args: str = ''): - await ctx.reply(f"Stuff {args}") - - @cmds.hybrid_command('water') - async def d_water_cmd(self, ctx): - await ctx.reply(repr(ctx)) + stuff_cmd = commands.command(name='stuffcounter')( + counter_cmd_factory( + 'stuff', + "Good luck with {detailsorname}! We have done {total} stuffs {period_name}." + ) + ) diff --git a/src/modules/counters/data.py b/src/modules/counters/data.py index 8081c099..a7405053 100644 --- a/src/modules/counters/data.py +++ b/src/modules/counters/data.py @@ -10,7 +10,8 @@ class CounterData(Registry): CREATE TABLE counters( counterid SERIAL PRIMARY KEY, name TEXT NOT NULL, - created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + category TEXT ); CREATE UNIQUE INDEX counters_name ON counters (name); """ @@ -19,6 +20,7 @@ class CounterData(Registry): counterid = Integer(primary=True) name = String() + category = String() created_at = Timestamp() class CounterEntry(RowModel): @@ -31,7 +33,8 @@ class CounterData(Registry): userid INTEGER NOT NULL, value INTEGER NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), - context_str TEXT + context_str TEXT, + details TEXT ); CREATE INDEX counter_log_counterid ON counter_log (counterid); """ @@ -44,5 +47,5 @@ class CounterData(Registry): value = Integer() created_at = Timestamp() context_str = String() - + details = String() diff --git a/src/modules/counters/migration.sql b/src/modules/counters/migration.sql new file mode 100644 index 00000000..3a0220c0 --- /dev/null +++ b/src/modules/counters/migration.sql @@ -0,0 +1,2 @@ +ALTER TABLE counters ADD COLUMN category TEXT; +ALTER TABLE counter_log ADD COLUMN details TEXT;