use payload known params instead of cached message, implement raw_bulk_message_deletion, on_raw_reaction_clear, on_raw_reaction_clear_emoji, helpers.is_upvote for better upvote emote checking

This commit is contained in:
Xevion
2021-02-15 03:40:23 -06:00
parent 69f1f42698
commit d99be7db9d
3 changed files with 74 additions and 27 deletions

View File

@@ -5,7 +5,7 @@ import discord
from discord.ext import commands
from discord.ext.commands import BucketType, Context, errors
from bot import checks, constants
from bot import checks, constants, helpers
from bot.bot import ContestBot
from bot.models import Guild, Period, PeriodStates, Submission
@@ -231,10 +231,7 @@ class ContestCog(commands.Cog):
with self.bot.get_session() as session:
guild: Guild = session.query(Guild).get(payload.guild_id)
# If the message was cached, check that it's in the correct channel.
if payload.cached_message is not None and payload.cached_message.channel.id != guild.submission_channel:
return
if payload.channel_id != guild.submission_channel: return
submission: Submission = session.query(Submission).get(payload.message_id)
if submission is None:
@@ -246,7 +243,19 @@ class ContestCog(commands.Cog):
@commands.Cog.listener()
async def on_raw_bulk_message_delete(self, payload: discord.RawBulkMessageDeleteEvent) -> None:
pass
deleted: List[int] = []
with self.bot.get_session() as session:
guild: Guild = session.query(Guild).get(payload.guild_id)
if payload.channel_id == guild.submission_channel:
for message_id in payload.message_ids:
submission: Submission = session.query(Submission).get(message_id)
if submission is not None:
deleted.append(message_id)
session.delete(submission)
if len(deleted) > 0:
logger.info(f'{len(deleted)} submissions deleted in bulk message deletion.')
logger.debug(f'Messages deleted: {", ".join(map(str, deleted))}')
@commands.Cog.listener()
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent) -> None:
@@ -258,7 +267,7 @@ class ContestCog(commands.Cog):
if payload.channel_id == guild.submission_channel:
channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
message: discord.PartialMessage = channel.get_partial_message(payload.message_id)
if payload.emoji.id != constants.Emoji.UPVOTE:
if not helpers.is_upvote(payload.emoji):
await message.remove_reaction(payload.emoji, payload.member)
else:
submission: Submission = session.query(Submission).get(payload.message_id)
@@ -285,7 +294,7 @@ class ContestCog(commands.Cog):
with self.bot.get_session() as session:
guild: Guild = session.query(Guild).get(payload.guild_id)
if payload.channel_id == guild.submission_channel and payload.emoji.id == constants.Emoji.UPVOTE:
if payload.channel_id == guild.submission_channel and helpers.is_upvote(payload.emoji):
submission: Submission = session.query(Submission).get(payload.message_id)
if submission is None:
logger.warning(f'Upvote reaction removed from message {payload.message_id}, but no Submission found in database.')
@@ -303,11 +312,37 @@ class ContestCog(commands.Cog):
@commands.Cog.listener()
async def on_raw_reaction_clear(self, payload: discord.RawReactionActionEvent) -> None:
pass
"""Deal with all emojis being cleared for a specific message. Remove all votes for a given submission and then re-add the bot's."""
with self.bot.get_session() as session:
guild: Guild = session.query(Guild).get(payload.guild_id)
if payload.channel_id == guild.submission_channel:
submission: Submission = session.query(Submission).get(payload.message_id)
if submission is None:
logger.warning(f'Witnessed reactions removed from message {payload.message_id}, but no Submission found in database.')
else:
submission.votes = 0
# TODO: Add helper function for getting partial/full messages easily given a payload or channel id and message id
channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
message: discord.PartialMessage = channel.get_partial_message(payload.message_id)
await message.add_reaction(self.bot.get_emoji(constants.Emoji.UPVOTE))
@commands.Cog.listener()
async def on_raw_reaction_clear_emoji(self, payload: discord.RawReactionClearEmojiEvent) -> None:
pass
"""Deal with a specific emoji being cleared for a message. If it was the upvote, clear votes for the submission and add back the bot's"""
with self.bot.get_session() as session:
guild: Guild = session.query(Guild).get(payload.guild_id)
if payload.channel_id == guild.submission_channel:
if helpers.is_upvote(payload.emoji):
submission: Submission = session.query(Submission).get(payload.message_id)
if submission is None:
logger.warning(
f'Witnessed all upvote reactions removed from message {payload.message_id}, but no Submission found in database.')
else:
submission.votes = 0
channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
message: discord.PartialMessage = channel.get_partial_message(payload.message_id)
await message.add_reaction(self.bot.get_emoji(constants.Emoji.UPVOTE))
def setup(bot) -> None:

13
bot/helpers.py Normal file
View File

@@ -0,0 +1,13 @@
from typing import Union
import discord
from bot import constants
def is_upvote(emoji: Union[discord.Emoji, discord.PartialEmoji, str]) -> bool:
"""Helper function for checking if the emoji returned is the upvote emoji the bot looks for."""
if isinstance(emoji, (discord.Emoji, discord.PartialEmoji)):
if emoji.id == constants.Emoji.UPVOTE:
return True
return False

View File

@@ -9,7 +9,7 @@ from sqlalchemy import Boolean, Column, DateTime, Enum, ForeignKey, Integer, Tex
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from bot import constants, exceptions
from bot import constants, exceptions, helpers
logger = logging.getLogger(__file__)
logger.setLevel(constants.LOGGING_LEVEL)
@@ -94,23 +94,22 @@ class Submission(Base):
saw_user = False
for reaction in message.reactions:
# Check that it's a custom Emoji and that the Emoji is the expected Upvote emoji
if isinstance(reaction.emoji, (discord.Emoji, discord.PartialEmoji)):
if reaction.emoji.id == constants.Emoji.UPVOTE:
# If a user was specified, look for him in the reactions
if user is not None:
reacting_user: Union[discord.Member, discord.User]
async for reacting_user in reaction.users():
# Check if the user who reacted to this emoji is the user we are looking for
if reacting_user.id == user.id:
saw_user = True
break
if helpers.is_upvote(reaction.emoji):
# If a user was specified, look for him in the reactions
if user is not None:
reacting_user: Union[discord.Member, discord.User]
async for reacting_user in reaction.users():
# Check if the user who reacted to this emoji is the user we are looking for
if reacting_user.id == user.id:
saw_user = True
break
# Tally the number of votes
votes = reaction.count - 1
if votes != self.votes:
# Make a racket if we counted wrong or somehow missed reactions
logger.warning(f'True vote count was off for Submission {self.id} by {votes - self.votes}.')
self.votes = votes
# Tally the number of votes
votes = reaction.count - 1
if votes != self.votes:
# Make a racket if we counted wrong or somehow missed reactions
logger.warning(f'True vote count was off for Submission {self.id} by {votes - self.votes}.')
self.votes = votes
return saw_user