@@ -59,6 +59,13 @@ async def setup(bot: bot.TechSupportBot) -> None:
5959 ),
6060 default = [50 , 67 , 75 ],
6161 )
62+ config .add (
63+ key = "reminders_at" ,
64+ datatype = "list[int]" ,
65+ title = "The list of hours remaining in vote to remind non voters" ,
66+ description = "The list of hours remaining in vote to remind non voters" ,
67+ default = [36 , 6 ],
68+ )
6269 await bot .add_cog (Voting (bot = bot , extension_name = "voting" ))
6370 bot .add_extension_config ("voting" , config )
6471
@@ -651,10 +658,62 @@ async def execute(self: Self, config: munch.Munch, guild: discord.Guild) -> None
651658 .where (self .bot .models .Votes .guild_id == str (guild .id ))
652659 .gino .all ()
653660 )
661+ reminder_times = config .extensions .voting .reminders_at .value
662+
663+ timestamp_now = int (datetime .datetime .utcnow ().timestamp ())
664+
654665 for vote in active_votes :
655666 end_time = int ((vote .start_time + timedelta (hours = 72 )).timestamp ())
656- if end_time <= int (datetime .datetime .utcnow ().timestamp ()):
667+
668+ # End expired votes
669+ if end_time <= timestamp_now :
657670 await self .end_vote (vote , guild , config )
671+ continue
672+
673+ # Reminder checks
674+ for reminder_hour in reminder_times :
675+ reminder_timestamp = end_time - (reminder_hour * 3600 )
676+
677+ # To allow for some slight variation in time, give a 5 minute valid reminder window
678+ if abs (timestamp_now - reminder_timestamp ) <= 300 :
679+ await self .remind_vote (vote , guild , config , reminder_hour )
680+
681+ async def remind_vote (
682+ self : Self ,
683+ vote : munch .Munch ,
684+ guild : discord .Guild ,
685+ config : munch .Munch ,
686+ reminder_hour : int ,
687+ ) -> None :
688+ """This sends a reminder to vote, based on who hasn't voted in the current vote
689+ This will send based on configured reminder times
690+
691+ Args:
692+ vote (munch.Munch): The vote object we are reminding for
693+ guild (discord.Guild): The guild the vote is in
694+ config (munch.Munch): The guild config
695+ reminder_hour (int): The hours remining until the vote closes
696+ """
697+ # Get all eligible voters
698+ eligible_voters = [v for v in vote .vote_ids_eligible .split ("," ) if v ]
699+ # Get all voted voters
700+ voted_voters = [v for v in vote .vote_ids_all .split ("," ) if v ]
701+
702+ non_voters = [v for v in eligible_voters if v not in voted_voters ]
703+
704+ # Theoretically we can exceed the max length of a discord message. Cut at 60 just in case.
705+ # We would probably error somewhere else if 61 people ever could vote though
706+ mention_string = " " .join (f"<@{ v } >" for v in non_voters [:60 ])
707+
708+ embed = discord .Embed (
709+ title = "Remember to vote" ,
710+ description = f"Vote closes in around { reminder_hour } hours!" ,
711+ )
712+ embed .color = discord .Color .red ()
713+
714+ channel = await guild .fetch_channel (int (vote .thread_id ))
715+
716+ await channel .send (content = mention_string , embed = embed )
658717
659718 async def end_vote (
660719 self : Self , vote : munch .Munch , guild : discord .Guild , config : munch .Munch
0 commit comments