diff --git a/kwaylon/kwaylon.py b/kwaylon/kwaylon.py index 0532cc4..0c74eed 100644 --- a/kwaylon/kwaylon.py +++ b/kwaylon/kwaylon.py @@ -3,11 +3,13 @@ import logging import re from datetime import timedelta, datetime from pathlib import Path +from typing import List -import nextcord as discord import pandas as pd from nextcord import Client, Message, TextChannel +from nextcord import Emoji from nextcord import RawReactionActionEvent +from nextcord import utils from . import jokes from .reactions import ReactionData @@ -32,11 +34,22 @@ class Kwaylon(Client): re.IGNORECASE ) + def text_channels(self) -> List[TextChannel]: + return [chan for chan in self.get_all_channels() if isinstance(chan, TextChannel)] + + def robotics_facility(self) -> TextChannel: + for chan in self.text_channels(): + if chan.name == 'robotics-facility' and chan.guild.name == 'Family Dinner': + return chan + + def kaylon_emoji(self) -> Emoji: + return utils.get(self.emojis, name='kaylon') + async def handle_ready(self): async def alive(): - channel: TextChannel = discord.utils.get(self.get_all_channels(), name='robotics-facility') + channel: TextChannel = self.robotics_facility() await channel.send('https://tenor.com/view/terminator-im-back-gif-19144173') - await channel.send(f"{discord.utils.get(self.emojis, name='kaylon')}") + await channel.send(self.kaylon_emoji()) # await alive() @@ -55,58 +68,53 @@ class Kwaylon(Client): await self.data.scan_messages(client=self, limit=self.limit, days=days) return - if (m := self.most_regex.match(message.clean_content)) is not None: - # await self.data.load_sql() - emoji = get_emoji_name(m.group('emoji')) - LOGGER.info(emoji) + if (most_match := self.most_regex.match(message.content)): + emoji_ref = most_match.group('emoji') + emoji_name = get_emoji_name(emoji_ref) + LOGGER.info(f'Most {emoji_name}') with self.data.connect() as con: - df = self.data.read_emoji(emoji, con) + df = self.data.read_emoji(emoji_name, con) con.close() + days = get_days(message.content) or 14 + df = filter_days(df, days) + if df.shape[0] > 0: - kwargs = {'days': 14} - if (day_match := re.search('(?P\d+) days', message.content)): - days = int(day_match.group('days')) - kwargs['days'] = days + LOGGER.info(f'{df.shape[0]} messages with {emoji_ref} after filtering') if 'leaderboard' in message.content: LOGGER.info(f'Building leaderboard') - res = f'{m.group("emoji")} totals, past {kwargs["days"]} days\n' - if (board := await self.leaderboard(df, **kwargs)) is not None: + res = f'{emoji_ref} totals, past {days} days\n' + if (board := await self.leaderboard(df)) is not None: res += board await message.reply(res) - LOGGER.info(f'Done') else: - LOGGER.info(f'Most {m.group("emoji")}') most = df.sort_values('count').iloc[-1] msg = await self.fetch_message(most) await message.reply(f'{msg.jump_url}') else: - await message.reply(f"NObody...gah, leave me alone!") + await message.reply(f"NObody (in the past {days} days)...gah, leave me alone!") + LOGGER.info(f'Done') + return for joke in self.jokes: - if (m := joke.scan(message)) is not None: + if (joke_match := joke.scan(message)) is not None: LOGGER.info(f'{joke.__class__.__name__} detected: {message.content}, {m.group()}') - await joke.respond(message, self, m) + await joke.respond(message, self, joke_match) - async def leaderboard(self, df: pd.DataFrame, days: int = 14) -> str: - start = (datetime.today() - timedelta(days=days)).astimezone() - valid_dates = df['datetime'] > start - df = df.loc[valid_dates] + async def leaderboard(self, df: pd.DataFrame) -> str: + df = df.groupby('auth_id').sum() + counts = df['count'].sort_values(ascending=False) + counts.index = [(await self.fetch_user(idx)).display_name for idx in counts.index] - if df.shape[0] > 0: - df = df.groupby('auth_id').sum() - counts = df['count'].sort_values(ascending=False) - counts.index = [(await self.fetch_user(idx)).display_name for idx in counts.index] + width = max([len(str(s)) for s in counts.index]) - width = max([len(str(s)) for s in counts.index]) - - res = '\n'.join( - f"`{str(name).ljust(width + 1)}with {cnt:<2.0f} total`" - for name, cnt in counts.iteritems() - ) - return res + res = '\n'.join( + f"`{str(name).ljust(width + 1)}with {cnt:<2.0f} total`" + for name, cnt in counts.iteritems() + ) + return res async def handle_raw_reaction(self, payload: RawReactionActionEvent): LOGGER.info(payload) @@ -130,3 +138,18 @@ def get_emoji_name(string: str) -> str: if (m := re.search('<:(?P\w+):(?P\d+)>', string)): string = m.group('name') return string.lower().strip() + + +day_regex = re.compile('(?P\d+) days') + + +def get_days(input_str): + if (m := day_regex.search(input_str)): + return int(m.group('days')) + + +def filter_days(df: pd.DataFrame, days: int) -> pd.DataFrame: + start = (datetime.today() - timedelta(days=days)).astimezone() + valid_dates = df['datetime'] > start + df = df.loc[valid_dates] + return df diff --git a/main.py b/main.py index 93fea5e..7fcf472 100644 --- a/main.py +++ b/main.py @@ -17,7 +17,11 @@ if __name__ == '__main__': @client.event async def on_ready(): await client.handle_ready() - # await client.data.scan_messages(client=client, limit=50) + await client.data.scan_messages( + client=client, + # limit=50, + days=1, + ) @client.event