added the ability to read unicode emojis

This commit is contained in:
2021-08-11 15:17:02 -05:00
parent e459c84e1e
commit 58a2464cb4
2 changed files with 56 additions and 36 deletions

76
msg.py
View File

@@ -73,28 +73,29 @@ class MsgData:
LOGGER.info(f'Added message id {message.id} from {message.author}: {message.content}')
async def update_reaction(self, client: discord.Client, payload: RawReactionActionEvent):
if isinstance(payload.emoji, discord.PartialEmoji):
chan: discord.TextChannel = await client.fetch_channel(channel_id=payload.channel_id)
msg: discord.Message = await chan.fetch_message(id=payload.message_id)
idx = (msg.id, payload.emoji.name)
payload.emoji: discord.PartialEmoji = convert_emoji(payload.emoji)
LOGGER.info(repr(payload.emoji))
chan: discord.TextChannel = await client.fetch_channel(channel_id=payload.channel_id)
msg: discord.Message = await chan.fetch_message(payload.message_id)
idx = (msg.id, payload.emoji.name)
for reaction in msg.reactions:
if isinstance(reaction.emoji, discord.Emoji) and reaction.emoji.name == payload.emoji.name:
reactions = pd.Series(await reaction_dict(reaction))
for reaction in msg.reactions:
if isinstance(reaction.emoji, discord.Emoji) and reaction.emoji.name == payload.emoji.name:
reactions = pd.Series(await reaction_dict(reaction))
async with self.lock:
self.reactions.loc[pd.IndexSlice[idx], :] = reactions
LOGGER.info(f'Added {str(idx)}, {int(self.reactions.loc[pd.IndexSlice[idx], "count"])} total')
break
else:
# only reaches here if the remove action was to take off the last reaction of that type
if payload.event_type == 'REACTION_REMOVE':
try:
async with self.lock:
self.reactions.loc[pd.IndexSlice[idx], :] = reactions
LOGGER.info(f'Added {str(idx)}, {int(self.reactions.loc[pd.IndexSlice[idx], "count"])} total')
break
else:
# only reaches here if the remove action was to take off the last reaction of that type
if payload.event_type == 'REACTION_REMOVE':
try:
async with self.lock:
self.reactions = self.reactions.drop(idx, axis=0)
except KeyError as e:
LOGGER.info(f'{idx} not in index')
else:
LOGGER.info(f'Dropped {idx}')
self.reactions = self.reactions.drop(idx, axis=0)
except KeyError as e:
LOGGER.info(f'{idx} not in index')
else:
LOGGER.info(f'Dropped {idx}')
def emoji_messages(self, emoji_name: str, days: int):
return emoji_messages(msg_df=self.msgs, react_df=self.reactions, emoji_name=emoji_name, days=days)
@@ -148,6 +149,13 @@ class MsgData:
LOGGER.info(f'User: {user.mention}')
return f'{user.mention} with {data.iloc[0]["total"]:.0f} over the past {int(days)} days'
def convert_emoji(emoji):
try:
emoji.name.encode('ascii')
except UnicodeEncodeError as e:
emoji.name = emoji.name.encode('unicode-escape').decode('ascii')
return emoji
async def message_df(client: discord.Client, **kwargs):
return pd.DataFrame(
[message_dict(m) async for m in message_gen(client, **kwargs)]
@@ -191,34 +199,38 @@ async def reaction_series(msg: discord.Message):
return pd.DataFrame([
await reaction_dict(r)
for r in msg.reactions
if isinstance(r.emoji, discord.Emoji)
])
async def reaction_dict(r: discord.Reaction) -> Dict:
is_emoji = isinstance(r.emoji, (discord.Emoji, discord.PartialEmoji))
LOGGER.info(repr(r.emoji))
return {
'msg id': r.message.id,
'emoji': r.emoji.name,
'emoji id': r.emoji.id,
'emoji': r.emoji.name if is_emoji else r.emoji.encode('unicode-escape').decode('ascii'),
'emoji id': r.emoji.id if is_emoji else None,
'count': int(r.count),
# 'users': str(list(map(lambda u: u.display_name, (u for u in await r.users().flatten())))),
}
def emoji_messages(msg_df, react_df, emoji_name: str, days: int = 10) -> pd.DataFrame:
# get reactions with a cancellation emoji
reactions = react_df.loc[pd.IndexSlice[:, emoji_name], :]
reacted_msgs = msg_df.loc[reactions.index.get_level_values(0).to_list()]
try:
reactions = react_df.loc[pd.IndexSlice[:, emoji_name], :]
except KeyError as e:
LOGGER.error(f'Emoji not found in reactions DataFrame: {emoji_name}')
else:
reacted_msgs = msg_df.loc[reactions.index.get_level_values(0).to_list()]
reacted_msgs['count'] = reacted_msgs.index.to_series().apply(
lambda idx: reactions.loc[pd.IndexSlice[idx, emoji_name], 'count'])
reacted_msgs['count'] = reacted_msgs.index.to_series().apply(
lambda idx: reactions.loc[pd.IndexSlice[idx, emoji_name], 'count'])
# filter outdated messages
reacted_msgs = reacted_msgs[reacted_msgs['created'] >= (datetime.today() - timedelta(days=days)).astimezone()]
# filter outdated messages
reacted_msgs = reacted_msgs[reacted_msgs['created'] >= (datetime.today() - timedelta(days=days)).astimezone()]
reacted_msgs = reacted_msgs.sort_values('count', ascending=False)
reacted_msgs = reacted_msgs.sort_values('count', ascending=False)
return reacted_msgs
return reacted_msgs
def emoji_totals(edf: pd.DataFrame) -> pd.DataFrame:

View File

@@ -26,6 +26,7 @@ class RoboPage(discord.Client):
self.jokes = list(attrs)
self.lock = Lock()
self.emoji_regex = re.compile("^who is the most (?P<emoji>\w+)(?: in the past (?P<days>\d+) days)?\??$", re.IGNORECASE)
self.leaderboard_regex = re.compile('^most (?P<emoji>\w+) leaderboard$', re.IGNORECASE)
def run(self):
return super().run(os.getenv('DISCORD_TOKEN'))
@@ -37,8 +38,8 @@ class RoboPage(discord.Client):
self.data: msg.MsgData = await msg.MsgData.create(
client=self,
limit=3000,
# limit=20,
# limit=3000,
limit=20,
days=14,
)
self.data.to_sql('messages.db')
@@ -78,6 +79,7 @@ if __name__ == '__main__':
async def on_ready():
# print(len(list(client.get_all_members())))
await client.handle_ready()
print('\n'.join(client.data.reactions.index.get_level_values(1).drop_duplicates().sort_values()))
@client.event
@@ -88,13 +90,19 @@ if __name__ == '__main__':
@client.event
async def on_raw_reaction_add(payload):
LOGGER.info(payload)
await client.data.update_reaction(payload=payload, client=client)
try:
await client.data.update_reaction(payload=payload, client=client)
except AttributeError as e:
LOGGER.info(f'Robopage not initialized yet')
@client.event
async def on_raw_reaction_remove(payload):
LOGGER.info(payload)
await client.data.update_reaction(payload=payload, client=client)
try:
await client.data.update_reaction(payload=payload, client=client)
except AttributeError as e:
LOGGER.info(f'Robopage not initialized yet')
client.run()