diff --git a/src/bot.py b/src/bot.py index c3314573..4fe7916c 100644 --- a/src/bot.py +++ b/src/bot.py @@ -52,7 +52,11 @@ async def main(): shardname=shardname, db=db, config=conf, - initial_extensions=['utils', 'core', 'analytics', 'babel', 'tracking.voice', 'modules'], + initial_extensions=[ + 'utils', 'core', 'analytics', 'babel', + 'modules', + 'tracking.voice', 'tracking.text', + ], web_client=session, app_ipc=shard_talk, testing_guilds=conf.bot.getintlist('admin_guilds'), diff --git a/src/core/data.py b/src/core/data.py index 1085beb5..07990f5e 100644 --- a/src/core/data.py +++ b/src/core/data.py @@ -1,12 +1,28 @@ +from enum import Enum from itertools import chain from psycopg import sql from cachetools import TTLCache -from data import Table, Registry, Column, RowModel +from data import Table, Registry, Column, RowModel, RegisterEnum from data.models import WeakCache from data.columns import Integer, String, Bool, Timestamp +class RankType(Enum): + """ + Schema + ------ + CREATE TYPE RankType AS ENUM( + 'XP', + 'VOICE', + 'MESSAGE' + ); + """ + XP = 'XP', + VOICE = 'VOICE', + MESSAGE = 'MESSAGE', + + class CoreData(Registry, name="core"): class AppConfig(RowModel): """ @@ -141,7 +157,10 @@ class CoreData(Registry, name="core"): left_at TIMESTAMPTZ, locale TEXT, timezone TEXT, - force_locale BOOLEAN + force_locale BOOLEAN, + season_start TIMESTAMPTZ, + xp_per_period INTEGER, + xp_per_centiword INTEGER ); """ @@ -205,7 +224,16 @@ class CoreData(Registry, name="core"): locale = String() force_locale = Bool() - unranked_rows = Table('unranked_rows') + season_start = Timestamp() + rank_type: Column[RankType] = Column() + rank_channel = Integer() + dm_ranks = Bool() + + xp_per_period = Integer() + xp_per_centiword = Integer() + coins_per_centixp = Integer() + + allow_transfers = Bool() donator_roles = Table('donator_roles') diff --git a/src/core/lion.py b/src/core/lion.py index 3f9ea1fe..0abbc321 100644 --- a/src/core/lion.py +++ b/src/core/lion.py @@ -78,6 +78,35 @@ class Lions(LionCog): self.lion_guilds[guildid] = lguild return lguild + async def fetch_guilds(self, *guildids) -> dict[int, LionGuild]: + """ + Fetch (or create) multiple LionGuilds simultaneously, using cache where possible. + """ + guild_map = {} + missing = set() + for guildid in guildids: + lguild = self.lion_guilds.get(guildid, None) + guild_map[guildid] = lguild + if lguild is None: + missing.add(guildid) + + if missing: + rows = await self.data.Guild.fetch_where(guildid=list(missing)) + missing.difference_update(row.guildid for row in rows) + + if missing: + new_rows = await self.data.Guild.table.insert_many( + ('guildid',), + *((guildid,) for guildid in missing) + ).with_adapter(self.data.Guild._make_rows) + rows = (*rows, *new_rows) + + for row in rows: + guildid = row.guildid + self.lion_guilds[guildid] = guild_map[guildid] = LionGuild(self.bot, row) + + return guild_map + async def fetch_member(self, guildid, userid, member: Optional[discord.Member] = None) -> LionMember: """ Fetch the given LionMember, using cache for data if possible. diff --git a/src/core/lion_guild.py b/src/core/lion_guild.py index d7db44a6..4c23ffda 100644 --- a/src/core/lion_guild.py +++ b/src/core/lion_guild.py @@ -71,7 +71,7 @@ class LionGuild(Timezoned): @property def guild_mode(self): # TODO: Configuration, data, and settings for this... - return GuildMode.StudyGuild + return GuildMode.VoiceGuild @property def timezone(self) -> pytz.timezone: diff --git a/src/meta/logger.py b/src/meta/logger.py index 4c95d4e1..3beb707f 100644 --- a/src/meta/logger.py +++ b/src/meta/logger.py @@ -180,9 +180,10 @@ class LocalQueueHandler(QueueHandler): class WebHookHandler(logging.StreamHandler): - def __init__(self, webhook_url, batch=False, loop=None): + def __init__(self, webhook_url, prefix="", batch=False, loop=None): super().__init__() self.webhook_url = webhook_url + self.prefix = prefix self.batched = "" self.batch = batch self.loop = loop @@ -264,15 +265,16 @@ class WebHookHandler(logging.StreamHandler): async def _send(self, message, as_file=False): async with aiohttp.ClientSession() as session: webhook = Webhook.from_url(self.webhook_url, session=session) - if as_file or len(message) > 2000: + if as_file or len(message) > 1900: with StringIO(message) as fp: fp.seek(0) await webhook.send( + f"{self.prefix}\n`{message.splitlines()[0]}`", file=File(fp, filename="logs.md"), username=log_app.get() ) else: - await webhook.send(message, username=log_app.get()) + await webhook.send(self.prefix + '\n' + message, username=log_app.get()) handlers = [] @@ -281,12 +283,12 @@ if webhook := conf.logging['general_log']: handlers.append(handler) if webhook := conf.logging['error_log']: - handler = WebHookHandler(webhook, batch=False) + handler = WebHookHandler(webhook, prefix=conf.logging['error_prefix'], batch=False) handler.setLevel(logging.ERROR) handlers.append(handler) if webhook := conf.logging['critical_log']: - handler = WebHookHandler(webhook, batch=False) + handler = WebHookHandler(webhook, prefix=conf.logging['critical_prefix'], batch=False) handler.setLevel(logging.CRITICAL) handlers.append(handler)