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 import commands
from discord.ext.commands import BucketType, Context, errors 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.bot import ContestBot
from bot.models import Guild, Period, PeriodStates, Submission from bot.models import Guild, Period, PeriodStates, Submission
@@ -231,10 +231,7 @@ class ContestCog(commands.Cog):
with self.bot.get_session() as session: with self.bot.get_session() as session:
guild: Guild = session.query(Guild).get(payload.guild_id) guild: Guild = session.query(Guild).get(payload.guild_id)
if payload.channel_id != guild.submission_channel: return
# 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
submission: Submission = session.query(Submission).get(payload.message_id) submission: Submission = session.query(Submission).get(payload.message_id)
if submission is None: if submission is None:
@@ -246,7 +243,19 @@ class ContestCog(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_raw_bulk_message_delete(self, payload: discord.RawBulkMessageDeleteEvent) -> None: 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() @commands.Cog.listener()
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent) -> None: 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: if payload.channel_id == guild.submission_channel:
channel: discord.TextChannel = self.bot.get_channel(payload.channel_id) channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
message: discord.PartialMessage = channel.get_partial_message(payload.message_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) await message.remove_reaction(payload.emoji, payload.member)
else: else:
submission: Submission = session.query(Submission).get(payload.message_id) submission: Submission = session.query(Submission).get(payload.message_id)
@@ -285,7 +294,7 @@ class ContestCog(commands.Cog):
with self.bot.get_session() as session: with self.bot.get_session() as session:
guild: Guild = session.query(Guild).get(payload.guild_id) 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) submission: Submission = session.query(Submission).get(payload.message_id)
if submission is None: if submission is None:
logger.warning(f'Upvote reaction removed from message {payload.message_id}, but no Submission found in database.') 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() @commands.Cog.listener()
async def on_raw_reaction_clear(self, payload: discord.RawReactionActionEvent) -> None: 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() @commands.Cog.listener()
async def on_raw_reaction_clear_emoji(self, payload: discord.RawReactionClearEmojiEvent) -> None: 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: 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.ext.declarative import declarative_base
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from bot import constants, exceptions from bot import constants, exceptions, helpers
logger = logging.getLogger(__file__) logger = logging.getLogger(__file__)
logger.setLevel(constants.LOGGING_LEVEL) logger.setLevel(constants.LOGGING_LEVEL)
@@ -94,23 +94,22 @@ class Submission(Base):
saw_user = False saw_user = False
for reaction in message.reactions: for reaction in message.reactions:
# Check that it's a custom Emoji and that the Emoji is the expected Upvote emoji # 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 helpers.is_upvote(reaction.emoji):
if reaction.emoji.id == constants.Emoji.UPVOTE: # If a user was specified, look for him in the reactions
# If a user was specified, look for him in the reactions if user is not None:
if user is not None: reacting_user: Union[discord.Member, discord.User]
reacting_user: Union[discord.Member, discord.User] async for reacting_user in reaction.users():
async for reacting_user in reaction.users(): # Check if the user who reacted to this emoji is the user we are looking for
# Check if the user who reacted to this emoji is the user we are looking for if reacting_user.id == user.id:
if reacting_user.id == user.id: saw_user = True
saw_user = True break
break
# Tally the number of votes # Tally the number of votes
votes = reaction.count - 1 votes = reaction.count - 1
if votes != self.votes: if votes != self.votes:
# Make a racket if we counted wrong or somehow missed reactions # 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}.') logger.warning(f'True vote count was off for Submission {self.id} by {votes - self.votes}.')
self.votes = votes self.votes = votes
return saw_user return saw_user