Ejemplo n.º 1
0
    def record_account_creation_dates(self):
        # Build list of unrecorded members
        members = []
        for member in self.guild.members:
            if checker.has_role(member, Messaging.PLAYER_ROLE_NAME):
                members.append(member)
        members = zbot.db.get_unrecorded_members(members)

        # Map members with their account id
        players_info = wot_utils.get_players_info(
            [member.display_name for member in members], self.app_id
        )
        members_account_ids, members_account_data = {}, {}
        for player_name, account_id in players_info.items():
            for member in members:
                result = utils.PLAYER_NAME_PATTERN.match(member.display_name)
                if result:
                    display_name = result.group(1)
                    if display_name.lower() == player_name.lower():
                        members_account_ids[member] = account_id
                        members_account_data.setdefault(member, {})['display_name'] = display_name

        # Map members with their account creation date
        players_details = wot_utils.get_players_details(
            list(members_account_ids.values()), self.app_id
        )
        for member, account_id in members_account_ids.items():
            members_account_data[member].update(creation_date=players_details[account_id][0])
        zbot.db.update_accounts_data(members_account_data)
Ejemplo n.º 2
0
    async def check_contacts(self, context):
        await context.message.add_reaction(self.WORK_IN_PROGRESS_EMOJI)

        contacts_by_clan = {}
        for member in context.guild.members:
            if checker.has_role(member, Stats.CLAN_CONTACT_ROLE_NAME):
                clan_tag = member.display_name.split(' ')[-1]
                # Remove clan tag delimiters
                replacements = {(re.escape(char)): '' for char in ['[', ']']}
                pattern = re.compile('|'.join(replacements.keys()))
                clan_tag = pattern.sub(
                    lambda m: replacements[re.escape(m.group(0))], clan_tag)
                contacts_by_clan.setdefault(clan_tag, []).append(member)
        contacts = set([
            contact for contacts in contacts_by_clan.values()
            for contact in contacts
        ])

        await self.check_contacts_clan_tag(context, contacts)
        await self.check_clans_single_contact(context, contacts_by_clan)
        await self.check_contacts_recruiting_permissions(
            context, contacts_by_clan, self.app_id)

        await context.message.remove_reaction(self.WORK_IN_PROGRESS_EMOJI,
                                              self.user)
        await context.message.add_reaction(self.WORK_DONE_EMOJI)
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    async def check_players(self, context, add_reaction=True):
        add_reaction and await context.message.add_reaction(self.WORK_IN_PROGRESS_EMOJI)

        members = []
        for member in self.guild.members:
            if checker.has_role(member, self.PLAYER_ROLE_NAME):
                members.append(member)

        await self.check_players_matching_name(context, members, self.app_id)
        await self.check_players_unique_name(context, members)

        add_reaction and await context.message.remove_reaction(self.WORK_IN_PROGRESS_EMOJI, self.user)
        add_reaction and await context.message.add_reaction(self.WORK_DONE_EMOJI)
Ejemplo n.º 5
0
 async def check_everyone_clan_tag(context, members):
     """Check that no member has an unauthorized clan tag."""
     unauthorized_clan_tag_members = []
     for member in members:
         if re.search(r'[ ]*[\[{].{2,5}[\]}][ ]*', member.display_name) and \
                 not checker.has_role(member, Stats.CLAN_CONTACT_ROLE_NAME):
             unauthorized_clan_tag_members.append(member)
     if unauthorized_clan_tag_members:
         for block in utils.make_message_blocks([
             f"Le joueur {member.mention} arbore un tag de clan sans être contact de clan."
             for member in unauthorized_clan_tag_members
         ]):
             await context.send(block)
     else:
         await context.send("Aucun joueur n'arbore de tag de clan sans être contact de clan. :ok_hand: ")
     return unauthorized_clan_tag_members
Ejemplo n.º 6
0
    async def check_contacts(self, context, add_reaction=True):
        add_reaction and await context.message.add_reaction(self.WORK_IN_PROGRESS_EMOJI)

        contacts, contacts_by_clan = [], {}
        for member in self.guild.members:
            if checker.has_role(member, Stats.CLAN_CONTACT_ROLE_NAME):
                contacts.append(member)
                result = utils.PLAYER_NAME_PATTERN.match(member.display_name)
                if result:  # Malformed member names handled by check_players_matching_name
                    clan_tag = result.group(3)
                    if clan_tag:  # Missing clan tag handled by check_contacts_clan_tag
                        contacts_by_clan.setdefault(clan_tag, []).append(member)

        await self.check_contacts_clan_tag(context, contacts)
        await self.check_clans_single_contact(context, contacts_by_clan)
        await self.check_contacts_recruiting_permissions(context, contacts_by_clan, self.app_id)

        add_reaction and await context.message.remove_reaction(self.WORK_IN_PROGRESS_EMOJI, self.user)
        add_reaction and await context.message.add_reaction(self.WORK_DONE_EMOJI)
Ejemplo n.º 7
0
Archivo: admin.py Proyecto: Zedd7/ZBot
    async def inspect_recruitment(self,
                                  context,
                                  member: typing.Union[discord.Member,
                                                       str] = None,
                                  *,
                                  options=''):
        """Post the status of the recruitment announces monitoring."""
        if isinstance(member,
                      str):  # Option mistakenly captured as member name
            options += f" {member}"
            member = None
        require_contact_role = not utils.is_option_enabled(options, 'all')
        recruitment_channel = self.guild.get_channel(
            self.RECRUITMENT_CHANNEL_ID)
        zbot.db.update_recruitment_announces(
            await recruitment_channel.history().flatten())

        # Get the record of each author's last announce (deleted or not)
        author_last_announce_data = {}
        for announce_data in zbot.db.load_recruitment_announces_data(
                query={'author': member.id} if member else {},
                order=[('time', -1)]):
            # Associate each author with his/her last announce data
            if announce_data['author'] not in author_last_announce_data:
                author_last_announce_data[announce_data['author']] = {
                    'last_announce_time': announce_data['time'],
                    'message_id': announce_data['_id']
                }

        # Enhance announces data with additional information
        min_timespan = datetime.timedelta(
            # Apply a tolerance of 2 days for players interpreting the 30 days range as "one month".
            # This is a subtraction because the resulting value is the number of days to wait before posting again.
            days=self.MIN_RECRUITMENT_ANNOUNCE_TIMESPAN -
            self.RECRUITMENT_ANNOUNCE_TIMESPAN_TOLERANCE)
        today = utils.bot_tz_now()
        for author_id, announce_data in author_last_announce_data.items():
            last_announce_time_localized = converter.to_utc(
                announce_data['last_announce_time'])
            next_announce_time_localized = last_announce_time_localized + min_timespan
            author_last_announce_data[author_id] = {
                'last_announce_time': last_announce_time_localized,
                'next_announce_time': next_announce_time_localized,
                'is_time_elapsed': next_announce_time_localized <= today
            }

        # Bind the member to the announce data, filter, and order by date asc
        member_announce_data = {
            self.guild.get_member(author_id): _
            for author_id, _ in author_last_announce_data.items()
        }
        filtered_member_announce_data = {
            author: _
            for author, _ in member_announce_data.items()
            if author is not None  # Still member of the server
            and
            not checker.has_any_mod_role(context, author, print_error=False
                                         )  # Ignore moderation messages
            and (not require_contact_role
                 or checker.has_role(author, Stats.CLAN_CONTACT_ROLE_NAME))
        }
        ordered_member_announce_data = sorted(
            filtered_member_announce_data.items(),
            key=lambda elem: elem[1]['last_announce_time'])

        # Post the status of announces data
        if ordered_member_announce_data:
            await context.send("Statut du suivi des annonces de recrutement :")
            for block in utils.make_message_blocks([
                    f"• {author.mention} : {converter.to_human_format(announce_data['last_announce_time'])} "
                    +
                ("✅" if announce_data['is_time_elapsed'] else
                 f"⏳ (→ {converter.to_human_format(announce_data['next_announce_time'])})"
                 ) for author, announce_data in ordered_member_announce_data
            ]):
                await context.send(block)
        else:
            await context.send("Aucun suivi enregistré.")