async def prepare_seed(default_seed=None): seed = default_seed if default_seed else random.randrange( 10**6) # 6 digits seed random.seed(seed) logger.debug( f"Picking winners using seed = {seed} ({utils.get_current_time()})" )
async def celebrate_account_anniversaries(self): # Check if not running above frequency today = utils.bot_tz_now() last_anniversaries_celebration = zbot.db.get_metadata('last_anniversaries_celebration') if last_anniversaries_celebration: last_anniversaries_celebration_localized = converter.to_utc(last_anniversaries_celebration) if last_anniversaries_celebration_localized.date() == converter.to_utc(today).date(): logger.debug(f"Prevented sending anniversaries celebration because running above defined frequency.") return # Get anniversary data self.record_account_creation_dates() account_anniversaries = zbot.db.get_anniversary_account_ids( today, self.MIN_ACCOUNT_CREATION_DATE ) member_anniversaries = {} for years, account_ids in account_anniversaries.items(): for account_id in account_ids: member = self.guild.get_member(account_id) if member and checker.has_role(member, Messaging.PLAYER_ROLE_NAME): member_anniversaries.setdefault(years, []).append(member) # Remove celebration emojis in names from previous anniversaries for member in self.guild.members: if self.CELEBRATION_EMOJI in member.display_name: try: await member.edit( nick=member.display_name.replace(self.CELEBRATION_EMOJI, '').rstrip() ) except (discord.Forbidden, discord.HTTPException): pass # Add celebration emojis for today's anniversaries for year, members in member_anniversaries.items(): for member in members: try: await member.edit( nick=member.display_name + " " + self.CELEBRATION_EMOJI * year ) except (discord.Forbidden, discord.HTTPException): pass # Announce anniversaries (after updating names to refresh the cache) celebration_channel = self.guild.get_channel(self.CELEBRATION_CHANNEL_ID) if member_anniversaries: await celebration_channel.send("**Voici les anniversaires du jour !** 🎂") for year in sorted(member_anniversaries.keys(), reverse=True): for member in member_anniversaries[year]: await celebration_channel.send( f" • {member.mention} fête ses **{year}** ans sur World of Tanks ! 🥳" ) zbot.db.update_metadata('last_anniversaries_celebration', today)
async def announce_results( results: dict, src_message: discord.Message, channel: discord.TextChannel, is_exclusive, required_role_name, organizer: discord.User = None, dest_message: discord.Message = None ): announcement_embed = discord.Embed( title="Résultats du sondage", description=f"[Cliquez ici pour accéder au sondage 🗳️]({src_message.jump_url})", color=Poll.EMBED_COLOR ) # Compute ranking of votes count: {votes_count: position, votes_count: position, ...} votes_ranking = {k: v for v, k in enumerate(sorted(set(results.values()), reverse=True), start=1)} # Compute ranking of emojis: {emoji: position, emoji: position, ...} emoji_ranking = {emoji: votes_ranking[vote_count] for emoji, vote_count in results.items()} ranking_medals = {1: "🥇", 2: "🥈", 3: "🥉"} for emoji, vote_count in results.items(): rank = emoji_ranking[emoji] medal_message = f" {ranking_medals.get(rank, '')}" if vote_count > 0 else "" announcement_embed.add_field( name=f"{emoji}\u2000**# {rank}**", value=f"Votes: **{vote_count}**{medal_message}" ) if organizer: announcement_embed.set_author( name=f"Organisateur : @{organizer.display_name}", icon_url=organizer.avatar_url) if dest_message: # Poll simulation await dest_message.edit(embed=announcement_embed) else: # Assessment of a poll dest_message = await channel.send(embed=announcement_embed) embed = discord.Embed( title="Sondage clôturé", description=f"[Cliquez ici pour accéder aux résultats 📊]({dest_message.jump_url})" + (f"\n\n{src_message.embeds[0].description}" if src_message.embeds[0].description else ""), color=Poll.EMBED_COLOR ) embed.add_field(name="Choix multiple", value="✅" if not is_exclusive else "❌") embed.add_field( name="Rôle requis", value=utils.try_get( src_message.guild.roles, error=exceptions.UnknownRole(required_role_name), name=required_role_name ).mention if required_role_name else "Aucun" ) if organizer: embed.set_author( name=f"Organisateur : @{organizer.display_name}", icon_url=organizer.avatar_url) await src_message.edit(embed=embed) logger.debug(f"Poll results: {results}")
async def send_automessage(self): # Check if not running above frequency now = utils.bot_tz_now() last_automessage_date = zbot.db.get_metadata('last_automessage_date') if last_automessage_date: last_automessage_date_localized = converter.to_utc(last_automessage_date) if not utils.is_time_almost_elapsed(last_automessage_date_localized, now, self.AUTOMESSAGE_FREQUENCY): logger.debug(f"Prevented sending automessage because running above defined frequency.") return # Get automessages data automessages_data = zbot.db.load_automessages( {'automessage_id': { '$ne': zbot.db.get_metadata('last_automessage_id') # Don't post the same message twice in a row }}, ['automessage_id', 'channel_id', 'message'] ) if not automessages_data: # At most a single automessage exists automessages_data = zbot.db.load_automessages( # Load it anyway {}, ['automessage_id', 'channel_id', 'message'] ) if not automessages_data: # Not automessage exists return # Abort automessage_data = random.choice(automessages_data) automessage_id = automessage_data['automessage_id'] message = automessage_data['message'] channel = self.guild.get_channel(automessage_data['channel_id']) last_channel_message = (await channel.history(limit=1).flatten())[0] # Run halt checks on target channel if last_channel_message.author == self.user: # Avoid spamming an channel # Check if the cooldown between two bot messages has expired last_channel_message_date_localized = converter.to_utc(last_channel_message.created_at) cooldown_expired = last_channel_message_date_localized < now - self.AUTOMESSAGE_COOLDOWN if not cooldown_expired: logger.debug(f"Skipped automessage of id {automessage_id} as cooldown has not expired yet.") return else: # Avoid interrupting conversations is_channel_quiet, attempt_count = False, 0 while not is_channel_quiet: # Wait for the channel to be quiet to send the message now = utils.bot_tz_now() last_channel_message_date_localized = converter.to_utc(last_channel_message.created_at) is_channel_quiet = last_channel_message_date_localized < now - self.AUTOMESSAGE_WAIT if not is_channel_quiet: attempt_count += 1 if attempt_count < 3: logger.debug( f"Pausing automessage of id {automessage_id} for {self.AUTOMESSAGE_WAIT.seconds} " f"seconds while waiting for quietness in target channel." ) await asyncio.sleep(self.AUTOMESSAGE_WAIT.seconds) # Sleep for the duration of the delay else: # After 3 failed attempts, skip logger.debug(f"Skipped automessage of id {automessage_id} after 3 waits for quietness.") return # All checks passed, send the automessage zbot.db.update_metadata('last_automessage_id', automessage_id) zbot.db.update_metadata('last_automessage_date', now) await channel.send(message)
def __init__(self, bot): super().__init__(bot) today = converter.get_tz_aware_datetime_now() anniversary_celebration_time = self.TIMEZONE.localize( datetime.datetime.combine(today, datetime.time(9, 0, 0))) last_anniversaries_celebration = zbot.db.get_metadata( 'last_anniversaries_celebration') if not last_anniversaries_celebration \ or last_anniversaries_celebration.date() != anniversary_celebration_time.date(): scheduler.schedule_volatile_job( anniversary_celebration_time, self.celebrate_account_anniversaries, interval=datetime.timedelta(days=1)) else: logger.debug( f"Prevented sending anniversaries celebration because running above defined frequency." ) self.send_automessage.start()
async def announce_winners(winners: [discord.User], players: [discord.User], message, organizer: discord.User = None): embed = discord.Embed( title="Résultats du tirage au sort 🎉", description=f"Gagnant(s) parmi {len(players)} participant(s):\n" + utils.make_user_list(winners, "\n"), color=Lottery.EMBED_COLOR) if organizer: embed.set_author(name=f"Organisateur : @{organizer.display_name}", icon_url=organizer.avatar_url) await message.edit(embed=embed) if organizer: # DM winners unreachable_winners = [] for winner in winners: if not await utils.try_dm( winner, f"Félicitations ! Tu as été tiré au sort lors de la loterie organisée " f"par {organizer.display_name} ({organizer.mention}) !\n" f"Contacte cette personne par MP pour obtenir ta récompense :wink:" + f"\nLien : {message.jump_url}"): unreachable_winners.append(winner) # DM organizer winner_list = utils.make_user_list(winners) await utils.try_dm( organizer, f"Les gagnants de la loterie sont: {winner_list}\n" f"Lien : {message.jump_url}") if unreachable_winners: unreachable_winner_list = utils.make_user_list( unreachable_winners) await utils.try_dm( organizer, f"Les gagnants suivants ont bloqué les MPs et n'ont " f"pas pu être contactés: {unreachable_winner_list}") # Log players and winners player_list = utils.make_user_list(players, mention=False) winner_list = utils.make_user_list(winners, mention=False) logger.debug(f"Players: {player_list}") logger.debug(f"Winners: {winner_list}")
async def record_server_stats(self): now = utils.bot_tz_now() last_server_stats_record_date = zbot.db.get_metadata( 'last_server_stats_record') if last_server_stats_record_date: last_server_stats_record_date_localized = converter.to_utc( last_server_stats_record_date) if not utils.is_time_almost_elapsed( last_server_stats_record_date_localized, now, self.SERVER_STATS_RECORD_FREQUENCY, tolerance=datetime.timedelta(minutes=5)): logger.debug( f"Prevented recording server stats because running above define frequency." ) return await self.record_member_count(now) await self.record_message_count(now) zbot.db.update_metadata('last_server_stats_record', now)