from typing import Optional import asyncio import discord from discord.ext import commands as cmds from discord import app_commands as appcmds from meta import LionBot, LionCog, LionContext from meta.logger import log_wrap from utils.lib import utc_now from ..data import ProfilesData, UserProfile, DiscordProfileLink, Community, DiscordCommunityLink from ..profiles import ProfilesRegistry class ProfilesCog(LionCog): def __init__(self, bot: LionBot): self.bot = bot self.data = bot.db.load_registry(ProfilesData()) self.profiles = ProfilesRegistry(self.data) async def cog_load(self): await self.data.init() await self.bot.version_check(*self.data.VERSION) await self.profiles.init() async def bot_check_once(self, ctx: LionContext): profile = await self.fetch_profile(ctx.author, interaction=ctx.interaction, touch=True) ctx.profile = profile if ctx.guild: community = await self.fetch_community(ctx.guild, interaction=ctx.interaction, touch=True) ctx.community = community else: ctx.community = None return True @log_wrap(isolate=True, action="Fetch Profile") async def fetch_profile( self, user: discord.User | discord.Member, interaction: Optional[discord.Interaction] = None, touch: bool = False, ) -> UserProfile: """ Fetch or create the profile for the given user. """ async with self.bot.db.connection() as conn: self.bot.db.conn = conn async with conn.transaction(): profile = await self.profiles.get_profile_discord(user.id) if profile is None: # Create a new profile # Then link with discord args = { 'nickname': user.display_name, } if interaction: if interaction.locale: args['locale_hint'] = interaction.locale.language_code if user.avatar: args['avatar'] = user.avatar.url profile = await UserProfile.create(**args) await DiscordProfileLink.create(profileid=profile.profileid, userid=user.id) elif touch: await profile.update(last_seen=utc_now()) return profile @log_wrap(isolate=True, action="Fetch Community") async def fetch_community( self, guild: discord.Guild, interaction: Optional[discord.Interaction] = None, touch: bool = False, ) -> Community: """ Fetch or create the community for the given guild. """ async with self.bot.db.connection() as conn: self.bot.db.conn = conn async with conn.transaction(): comm = await self.profiles.get_community_discord(guild.id) if comm is None: # Create a new Community and link to Discord comm = await Community.create() await DiscordCommunityLink.create(guildid=guild.id, communityid=comm.communityid) elif touch: await comm.update(last_seen=utc_now()) return comm