mirror of
https://github.com/Xevion/contest-assistant.git
synced 2025-12-07 01:14:42 -06:00
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:
@@ -232,16 +232,20 @@ 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:
|
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 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)
|
|
||||||
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)
|
||||||
if submission is None:
|
if submission is None:
|
||||||
logger.warning(f'Upvote reaction added to message {payload.message_id}, but no Submission found in database.')
|
logger.warning(f'Upvote reaction added to message {payload.message_id}, but no Submission found in database.')
|
||||||
else:
|
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()
|
@commands.Cog.listener()
|
||||||
async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent) -> None:
|
async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent) -> None:
|
||||||
@@ -262,16 +266,16 @@ class ContestCog(commands.Cog):
|
|||||||
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.')
|
||||||
else:
|
else:
|
||||||
submission.votes -= 1
|
submission.decrement()
|
||||||
|
|
||||||
# Get the actual number of votes from the message
|
# Get the actual number of votes from the message
|
||||||
channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
|
channel: discord.TextChannel = self.bot.get_channel(payload.channel_id)
|
||||||
message: discord.Message = await channel.fetch_message(payload.message_id)
|
message: discord.Message = await channel.fetch_message(payload.message_id)
|
||||||
reaction: discord.Reaction
|
self_reacted = await submission.verify(await message.fetch(), self.bot.user)
|
||||||
for reaction in filter(lambda _reaction: isinstance(_reaction.emoji, (discord.Emoji, discord.PartialEmoji))
|
|
||||||
and _reaction.emoji.id == constants.Emoji.UPVOTE,
|
# Make sure our reaction exists
|
||||||
message.reactions):
|
if not self_reacted:
|
||||||
submission.set_votes(reaction.count)
|
await message.add_reaction(self.bot.get_emoji(constants.Emoji.UPVOTE))
|
||||||
|
|
||||||
@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:
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import datetime
|
|||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
import logging
|
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 import Boolean, Column, DateTime, Enum, ForeignKey, Integer, Text
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import relationship
|
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_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.
|
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."""
|
"""Sets the number of votes for this Submission."""
|
||||||
if self.votes != n:
|
saw_user = False
|
||||||
logger.warning(f'True vote count was off for Submission {self.id} by {n - self.votes}.')
|
for reaction in message.reactions:
|
||||||
self.votes = n
|
# 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):
|
class Period(Base):
|
||||||
|
|||||||
Reference in New Issue
Block a user