added the ability to read unicode emojis
This commit is contained in:
76
msg.py
76
msg.py
@@ -73,28 +73,29 @@ class MsgData:
|
|||||||
LOGGER.info(f'Added message id {message.id} from {message.author}: {message.content}')
|
LOGGER.info(f'Added message id {message.id} from {message.author}: {message.content}')
|
||||||
|
|
||||||
async def update_reaction(self, client: discord.Client, payload: RawReactionActionEvent):
|
async def update_reaction(self, client: discord.Client, payload: RawReactionActionEvent):
|
||||||
if isinstance(payload.emoji, discord.PartialEmoji):
|
payload.emoji: discord.PartialEmoji = convert_emoji(payload.emoji)
|
||||||
chan: discord.TextChannel = await client.fetch_channel(channel_id=payload.channel_id)
|
LOGGER.info(repr(payload.emoji))
|
||||||
msg: discord.Message = await chan.fetch_message(id=payload.message_id)
|
chan: discord.TextChannel = await client.fetch_channel(channel_id=payload.channel_id)
|
||||||
idx = (msg.id, payload.emoji.name)
|
msg: discord.Message = await chan.fetch_message(payload.message_id)
|
||||||
|
idx = (msg.id, payload.emoji.name)
|
||||||
|
|
||||||
for reaction in msg.reactions:
|
for reaction in msg.reactions:
|
||||||
if isinstance(reaction.emoji, discord.Emoji) and reaction.emoji.name == payload.emoji.name:
|
if isinstance(reaction.emoji, discord.Emoji) and reaction.emoji.name == payload.emoji.name:
|
||||||
reactions = pd.Series(await reaction_dict(reaction))
|
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:
|
async with self.lock:
|
||||||
self.reactions.loc[pd.IndexSlice[idx], :] = reactions
|
self.reactions = self.reactions.drop(idx, axis=0)
|
||||||
LOGGER.info(f'Added {str(idx)}, {int(self.reactions.loc[pd.IndexSlice[idx], "count"])} total')
|
except KeyError as e:
|
||||||
break
|
LOGGER.info(f'{idx} not in index')
|
||||||
else:
|
else:
|
||||||
# only reaches here if the remove action was to take off the last reaction of that type
|
LOGGER.info(f'Dropped {idx}')
|
||||||
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}')
|
|
||||||
|
|
||||||
def emoji_messages(self, emoji_name: str, days: int):
|
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)
|
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}')
|
LOGGER.info(f'User: {user.mention}')
|
||||||
return f'{user.mention} with {data.iloc[0]["total"]:.0f} over the past {int(days)} days'
|
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):
|
async def message_df(client: discord.Client, **kwargs):
|
||||||
return pd.DataFrame(
|
return pd.DataFrame(
|
||||||
[message_dict(m) async for m in message_gen(client, **kwargs)]
|
[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([
|
return pd.DataFrame([
|
||||||
await reaction_dict(r)
|
await reaction_dict(r)
|
||||||
for r in msg.reactions
|
for r in msg.reactions
|
||||||
if isinstance(r.emoji, discord.Emoji)
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
async def reaction_dict(r: discord.Reaction) -> Dict:
|
async def reaction_dict(r: discord.Reaction) -> Dict:
|
||||||
|
is_emoji = isinstance(r.emoji, (discord.Emoji, discord.PartialEmoji))
|
||||||
|
LOGGER.info(repr(r.emoji))
|
||||||
return {
|
return {
|
||||||
'msg id': r.message.id,
|
'msg id': r.message.id,
|
||||||
'emoji': r.emoji.name,
|
'emoji': r.emoji.name if is_emoji else r.emoji.encode('unicode-escape').decode('ascii'),
|
||||||
'emoji id': r.emoji.id,
|
'emoji id': r.emoji.id if is_emoji else None,
|
||||||
'count': int(r.count),
|
'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:
|
def emoji_messages(msg_df, react_df, emoji_name: str, days: int = 10) -> pd.DataFrame:
|
||||||
# get reactions with a cancellation emoji
|
# get reactions with a cancellation emoji
|
||||||
reactions = react_df.loc[pd.IndexSlice[:, emoji_name], :]
|
try:
|
||||||
reacted_msgs = msg_df.loc[reactions.index.get_level_values(0).to_list()]
|
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(
|
reacted_msgs['count'] = reacted_msgs.index.to_series().apply(
|
||||||
lambda idx: reactions.loc[pd.IndexSlice[idx, emoji_name], 'count'])
|
lambda idx: reactions.loc[pd.IndexSlice[idx, emoji_name], 'count'])
|
||||||
|
|
||||||
# filter outdated messages
|
# filter outdated messages
|
||||||
reacted_msgs = reacted_msgs[reacted_msgs['created'] >= (datetime.today() - timedelta(days=days)).astimezone()]
|
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:
|
def emoji_totals(edf: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
|||||||
16
robopage.py
16
robopage.py
@@ -26,6 +26,7 @@ class RoboPage(discord.Client):
|
|||||||
self.jokes = list(attrs)
|
self.jokes = list(attrs)
|
||||||
self.lock = Lock()
|
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.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):
|
def run(self):
|
||||||
return super().run(os.getenv('DISCORD_TOKEN'))
|
return super().run(os.getenv('DISCORD_TOKEN'))
|
||||||
@@ -37,8 +38,8 @@ class RoboPage(discord.Client):
|
|||||||
|
|
||||||
self.data: msg.MsgData = await msg.MsgData.create(
|
self.data: msg.MsgData = await msg.MsgData.create(
|
||||||
client=self,
|
client=self,
|
||||||
limit=3000,
|
# limit=3000,
|
||||||
# limit=20,
|
limit=20,
|
||||||
days=14,
|
days=14,
|
||||||
)
|
)
|
||||||
self.data.to_sql('messages.db')
|
self.data.to_sql('messages.db')
|
||||||
@@ -78,6 +79,7 @@ if __name__ == '__main__':
|
|||||||
async def on_ready():
|
async def on_ready():
|
||||||
# print(len(list(client.get_all_members())))
|
# print(len(list(client.get_all_members())))
|
||||||
await client.handle_ready()
|
await client.handle_ready()
|
||||||
|
print('\n'.join(client.data.reactions.index.get_level_values(1).drop_duplicates().sort_values()))
|
||||||
|
|
||||||
|
|
||||||
@client.event
|
@client.event
|
||||||
@@ -88,13 +90,19 @@ if __name__ == '__main__':
|
|||||||
@client.event
|
@client.event
|
||||||
async def on_raw_reaction_add(payload):
|
async def on_raw_reaction_add(payload):
|
||||||
LOGGER.info(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
|
@client.event
|
||||||
async def on_raw_reaction_remove(payload):
|
async def on_raw_reaction_remove(payload):
|
||||||
LOGGER.info(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()
|
client.run()
|
||||||
|
|||||||
Reference in New Issue
Block a user