import typing from datetime import datetime from discord import Reaction, RawReactionActionEvent, NotFound, HTTPException from discord.ext import commands from discord.ext.commands import BadArgument from features import vote class DateConverter(commands.Converter): async def convert(self, ctx, argument): try: dt = datetime.strptime(argument, "%d.%m.") dt = dt.replace(year=ctx.message.created_at.year) return dt except ValueError: raise BadArgument() class TimeConverter(commands.Converter): async def convert(self, ctx, argument): try: dt = datetime.strptime(argument, "%H:%M") d = ctx.message.created_at dt = dt.replace(year=d.year, month=d.month, day=d.day) return dt except ValueError: raise BadArgument() class Vote(commands.Cog): def __init__(self, bot): self.bot = bot self.voter = vote.Vote(bot) self.handled = [] @commands.cooldown(rate=5, per=20.0, type=commands.BucketType.user) @commands.command(rest_is_raw=True) async def vote(self, ctx, date: typing.Optional[DateConverter], time: typing.Optional[TimeConverter], *, message): await self.voter.handle_vote(ctx, date, time, message) def __handle(self, msg_id, user_id, emoji, add, raw): t = (msg_id, user_id,) if t in self.handled: self.handled.remove(t) return True if not raw: self.handled.append(t) return False async def handle_raw_reaction(self, payload: RawReactionActionEvent, added: bool): chan = await self.bot.fetch_channel(payload.channel_id) try: msg = await chan.fetch_message(payload.message_id) usr = await self.bot.fetch_user(payload.user_id) except NotFound: return False for r in msg.reactions: if str(r.emoji) == str(payload.emoji): await self.voter.handle_reaction(r, usr, added) return True return False @commands.Cog.listener() async def on_reaction_add(self, reaction: Reaction, user): if self.__handle(reaction.message.id, user.id, reaction.emoji, True, False): # print("Already handled") return # print("Handling") await self.voter.handle_reaction(reaction, user, True) @commands.Cog.listener() async def on_raw_reaction_add(self, payload: RawReactionActionEvent): if self.__handle(payload.message_id, payload.user_id, payload.emoji, True, True): # print("Already handled (in RAW)") return # print("Handling RAW") try: if not await self.handle_raw_reaction(payload, True): print("Couldn't find reaction, that is rather weird.") except HTTPException: # ignore HTTP Exceptions return @commands.Cog.listener() async def on_reaction_remove(self, reaction: Reaction, user): if self.__handle(reaction.message.id, user.id, reaction.emoji, False, False): # print("Already handled") return # print("Handling") await self.voter.handle_reaction(reaction, user, False) @commands.Cog.listener() async def on_raw_reaction_remove(self, payload: RawReactionActionEvent): if self.__handle(payload.message_id, payload.user_id, payload.emoji, False, True): # print("Already handled (in RAW)") return # print("Handling RAW") if not await self.handle_raw_reaction(payload, False): print("Couldn't find reaction, that is rather weird.") def setup(bot): bot.add_cog(Vote(bot))