diff --git a/hyperfocus/twitch/component.py b/hyperfocus/twitch/component.py index 2f1bd44..423cb49 100644 --- a/hyperfocus/twitch/component.py +++ b/hyperfocus/twitch/component.py @@ -1,3 +1,4 @@ +import asyncio from string import punctuation import datetime as dt from datetime import datetime, timedelta @@ -40,6 +41,7 @@ class FocusComponent(cmds.Component): register_channel(self.channel.name, self.channel) self._last_deleted: dict[int, datetime] = {} + self.hyperfocus_lock = asyncio.Lock() # ----- API ----- async def component_load(self): @@ -88,6 +90,10 @@ class FocusComponent(cmds.Component): @cmds.Component.listener() async def event_message(self, payload: twitchio.ChatMessage): + async with self.hyperfocus_lock: + await self.handle_message(payload) + + async def handle_message(self, payload: twitchio.ChatMessage): # Check if chatter is currently hyperfocused profile = await self.bot.profiles.fetch_profile(payload.chatter, touch=True) hyperfocused = await self.get_hyperfocus(profile.profileid) @@ -173,35 +179,37 @@ class FocusComponent(cmds.Component): pid = profile.profileid comm = await self.bot.profiles.fetch_community(ctx.broadcaster, touch=True) - await Hyperfocuser.table.delete_where(profileid=pid) - focuser = await Hyperfocuser.create( - profileid=pid, - started_at=now, - ends_at=end_at, - started_in=comm.communityid, - ) + async with self.hyperfocus_lock: + await Hyperfocuser.table.delete_where(profileid=pid) + focuser = await Hyperfocuser.create( + profileid=pid, + started_at=now, + ends_at=end_at, + started_in=comm.communityid, + ) - await self.channel.send_hyperfocus_patch(comm.communityid, focuser) + await self.channel.send_hyperfocus_patch(comm.communityid, focuser) - minutes = ceil(dur / 60) - await ctx.reply( - f"{ctx.chatter.name} has gone into HYPERFOCUS! " - f"They will be in emote and command only mode for the next {minutes} minutes! " - "Use !unfocus to come back if you need to, best of luck! ☘️🍀☘️ " - ) + minutes = ceil(dur / 60) + await ctx.reply( + f"{ctx.chatter.name} has gone into HYPERFOCUS! " + f"They will be in emote and command only mode for the next {minutes} minutes! " + "Use !unfocus to come back if you need to, best of luck! ☘️🍀☘️ " + ) @cmds.command(name="unfocus") async def unfocus_cmd(self, ctx): profile = await self.bot.profiles.fetch_profile(ctx.chatter, touch=True) - row = await Hyperfocuser.fetch(profile.profileid) - if row: - await row.delete() - await self.channel.send_hyperfocus_del(profile.profileid) + async with self.hyperfocus_lock: + row = await Hyperfocuser.fetch(profile.profileid) + if row: + await row.delete() + await self.channel.send_hyperfocus_del(profile.profileid) - await ctx.reply( - "Welcome back from focus, hope it went well!" - " Remember to have a sip and stretch if you need it~" - ) + await ctx.reply( + "Welcome back from focus, hope it went well!" + " Remember to have a sip and stretch if you need it~" + ) @cmds.command(name="hyperfocused") async def hyperfocused_cmd(self, ctx, user: twitchio.User | None = None): @@ -209,22 +217,30 @@ class FocusComponent(cmds.Component): profile = await self.bot.profiles.fetch_profile(user, touch=False) - if hyper := (await self.get_hyperfocus(profile.profileid)): - durstr = strfdelta(hyper.ends_at - utc_now()) - await ctx.reply( - f"{user.name} is in HYPERFOCUS for another {durstr}! " - "They can only write emojis and commands in this time. Good luck!" - ) - elif own: - await ctx.reply( - "You are not hyperfocused!" - " Enter HYPERFOCUS mode for e.g. 10 minutes with '!hyperfocus 10'" - ) - else: - await ctx.reply(f"{user.name} is not hyperfocused!") + async with self.hyperfocus_lock: + if hyper := (await self.get_hyperfocus(profile.profileid)): + durstr = strfdelta(hyper.ends_at - utc_now()) + await ctx.reply( + f"{user.name} is in HYPERFOCUS for another {durstr}! " + "They can only write emojis and commands in this time. Good luck!" + ) + elif own: + await ctx.reply( + "You are not hyperfocused!" + " Enter HYPERFOCUS mode for e.g. 10 minutes with '!hyperfocus 10'" + ) + else: + await ctx.reply(f"{user.name} is not hyperfocused!") @cmds.command(name="addfocus") async def addfocus_cmd(self, ctx): await ctx.reply( "Add HYPERFOCUS to your channel by authorising me here: https://croccyfocus.thewisewolf.dev/invite" ) + + @cmds.command(name="focuslist") + @cmds.is_moderator() + async def focuslist_cmd(self, ctx): + comm = await self.bot.profiles.fetch_community(ctx.broadcaster, touch=True) + link = f"https://croccyfocus.thewisewolf.dev/widget/?community={comm}" + await ctx.reply(f"Browser source link for your channel's hyperfocus: {link}")