diff --git a/extensions/mute_sync.py b/extensions/mute_sync.py index db81594..cfdaf65 100644 --- a/extensions/mute_sync.py +++ b/extensions/mute_sync.py @@ -27,6 +27,7 @@ class MuteSync(commands.Cog): def __init__(self, bot): self.bot = bot self.mutes = {} # (discord id, uuid): datetime + self.guild_members: set[str] = set() self._sess: aiohttp.ClientSession | None = None self.mute_task: tuple[asyncio.Task, datetime] | None = None self._syncing = False @@ -98,6 +99,20 @@ async def get_discord_user(self, uuid): return int(data["data"]["userid"]) return None + async def get_minecraft_uuid(self, userid): + session = await self.get_session() + async with session.get( + f"{self.skykings_api_url}/user/info?userid={userid}", + headers={"Authorization": self.skykings_api_key}, + ) as resp: + if resp.status == 404: + return None + if resp.status != 200: + resp.raise_for_status() + data = await resp.json() + return data["data"]["uuid"] + return None + async def get_guild_mutes(self): # wait for this to be populated while self.bot.mineflayer_bot.bot.username is None: @@ -115,6 +130,7 @@ async def get_guild_mutes(self): guild = data["guild"] if guild is None: return [] + self.guild_members = set(member["uuid"] for member in guild["members"]) for member in guild["members"]: uuid = member["uuid"] discord_id = await self.get_discord_user(uuid) @@ -236,15 +252,23 @@ async def on_hypixel_guild_member_unmuted(self, _, player): # hypixel does not allow specific durations (e.g. 1d 1h, only 1h or 1d) await self.process_new_unmute(player) + @commands.Cog.listener() + async def on_hypixel_guild_member_join(self, player): + uuid = await self.get_uuid(player) + self.guild_members.add(uuid) + + @commands.Cog.listener() + async def on_hypixel_guild_member_leave(self, player): + uuid = await self.get_uuid(player) + if uuid in self.guild_members: + self.guild_members.remove(uuid) + @tasks.loop(hours=12) async def sync_task(self): - print("waiting for ready") await self.bot.wait_until_ready() - print("bot ready") guild = self.bot.get_channel(DiscordConfig.channel).guild if self.bot.mineflayer_bot is None or not self.bot.mineflayer_bot.is_ready(): await asyncio.sleep(.5) - print("mc ready") if not self._syncing: self._syncing = True await self.sync_mutes() @@ -258,6 +282,9 @@ async def on_sync_task_error(self, exc): async def on_member_join(self, member): if member.id is None: return + # is the user in our guild? + if member.guild.id != MuteSyncConfig.guild_id: + return # find the mute for (discord_id, uuid), expiry in dict(self.mutes).items(): if discord_id == member.id: @@ -272,6 +299,7 @@ async def on_member_update(self, before, after): return # check if mute is still valid valid = False + # if they have a current mute, they are obviously in our guild for (discord_id, uuid), expiry in dict(self.mutes).items(): if discord_id == after.id: if expiry > datetime.datetime.now(): @@ -280,9 +308,18 @@ async def on_member_update(self, before, after): role = after.guild.get_role(MuteSyncConfig.mute_role) await after.add_roles(role, reason="UPDATE: User has an active guild mute") break + # if they do not, they might be in a different guild. check if they are in our guild if not valid: if MuteSyncConfig.mute_role in [role.id for role in after.roles]: role = after.guild.get_role(MuteSyncConfig.mute_role) + uuid = await self.get_minecraft_uuid(after.id) + if uuid is None: + # not even verified, shouldn't have role + await after.remove_roles(role, reason="UPDATE: User has no active guild mute") + return + if uuid not in self.guild_members: + # not in our guild + return await after.remove_roles(role, reason="UPDATE: User has no active guild mute")