Move Submission votes count logic into model, add improved verification system, add verification that the bot is always reacting to the message (on every reaction add/removal)

This commit is contained in:
Xevion
2021-02-14 01:48:56 -06:00
parent bb28f38fd9
commit 2178a3ec99
2 changed files with 46 additions and 14 deletions

View File

@@ -232,16 +232,20 @@ 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:
if payload.emoji.id != constants.Emoji.UPVOTE:
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:
await message.remove_reaction(payload.emoji, payload.member)
else:
submission: Submission = session.query(Submission).get(payload.message_id)
if submission is None:
logger.warning(f'Upvote reaction added to message {payload.message_id}, but no Submission found in database.')
else:
submission.votes += 1
submission.increment()
# Make sure our reaction exists, verify vote count
self_reacted = await submission.verify(await message.fetch(), self.bot.user)
if not self_reacted:
await message.add_reaction(self.bot.get_emoji(constants.Emoji.UPVOTE))
@commands.Cog.listener()
async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent) -> None:
@@ -262,16 +266,16 @@ class ContestCog(commands.Cog):
if submission is None:
logger.warning(f'Upvote reaction removed from message {payload.message_id}, but no Submission found in database.')
else:
submission.votes -= 1
submission.decrement()
# Get the actual number of votes from the message
channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
message: discord.Message = await channel.fetch_message(payload.message_id)
reaction: discord.Reaction
for reaction in filter(lambda _reaction: isinstance(_reaction.emoji, (discord.Emoji, discord.PartialEmoji))
and _reaction.emoji.id == constants.Emoji.UPVOTE,
message.reactions):
submission.set_votes(reaction.count)
self_reacted = await submission.verify(await message.fetch(), self.bot.user)
# Make sure our reaction exists
if not self_reacted:
await message.add_reaction(self.bot.get_emoji(constants.Emoji.UPVOTE))
@commands.Cog.listener()
async def on_raw_reaction_clear(self, payload: discord.RawReactionActionEvent) -> None:

View File

@@ -2,8 +2,9 @@ import datetime
import enum
import functools
import logging
from typing import List
from typing import List, Optional, Union
import discord
from sqlalchemy import Boolean, Column, DateTime, Enum, ForeignKey, Integer, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
@@ -80,11 +81,38 @@ class Submission(Base):
period_id = Column(Integer, ForeignKey("period.id")) # The id of the period this Submission relates to.
period = relationship("Period", back_populates="submissions") # The period this submission was made in.
def set_votes(self, n: int) -> None:
def increment(self) -> None:
"""Increase the number of votes by one."""
self.votes += 1
def decrement(self) -> None:
"""Decrease the number of votes by one."""
self.votes -= 1
async def verify(self, message: discord.Message, user: Optional[Union[discord.ClientUser, discord.User]] = None) -> bool:
"""Sets the number of votes for this Submission."""
if self.votes != n:
logger.warning(f'True vote count was off for Submission {self.id} by {n - self.votes}.')
self.votes = n
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
# 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
class Period(Base):