Exemplo n.º 1
0
    def build_raid_message(self, guild, raid_id, embed_texts):
        timestamp = int(
            select_one(self.conn, 'Raids', 'time',
                       raid_id))  # Why can't this return an int by itself?
        time = datetime.datetime.utcfromtimestamp(timestamp)
        name = select_one(self.conn, 'Raids', 'name', raid_id)
        tier = select_one(self.conn, 'Raids', 'tier', raid_id)
        boss = select_one(self.conn, 'Raids', 'boss', raid_id)
        roster = select_one(self.conn, 'Raids', 'roster', raid_id)
        player_ids = select(self.conn, 'Players', 'player_id', raid_id)
        if player_ids:
            number_of_players = len(player_ids)
        else:
            number_of_players = 0

        server_tz = TimeCog.get_server_time(guild)
        server_time = TimeCog.local_time(time, server_tz)
        header_time = TimeCog.format_time(server_time) + _(" server time")
        embed_title = _("{0} {1} at {2}").format(name, tier, header_time)
        embed_description = _("Bosses: {0}").format(boss)
        embed = discord.Embed(title=embed_title,
                              colour=discord.Colour(0x3498db),
                              description=embed_description)
        time_string = self.build_time_string(time, guild)
        embed.add_field(name=_("Time zones:"), value=time_string)
        if roster:
            result = select_rows(self.conn, 'Assignment', 'byname, class_name',
                                 raid_id)
            number_of_slots = len(result)
            # Add first half
            embed_name = _("Selected line up:")
            embed_text = ""
            for row in result[:number_of_slots // 2]:
                class_names = row[1].split(',')
                for class_name in class_names:
                    embed_text = embed_text + self.class_emojis_dict[class_name]
                embed_text = embed_text + ": " + row[0] + "\n"
            embed.add_field(name=embed_name, value=embed_text)
            # Add second half
            embed_name = "\u200B"
            embed_text = ""
            for row in result[number_of_slots // 2:]:
                class_names = row[1].split(',')
                for class_name in class_names:
                    embed_text = embed_text + self.class_emojis_dict[class_name]
                embed_text = embed_text + ": " + row[0] + "\n"
            embed.add_field(name=embed_name, value=embed_text)
        # Add a field for each embed text
        for i in range(len(embed_texts)):
            if i == 0:
                embed_name = _("The following {0} players are available:"
                               ).format(number_of_players)
            else:
                embed_name = "\u200B"
            embed.add_field(name=embed_name, value=embed_texts[i])
        embed.set_footer(text=_("Raid time in your local time (beta)"))
        embed.timestamp = time
        return embed
Exemplo n.º 2
0
 async def background_task(self):
     bot = self.bot
     raids = self.raids
     expiry_time = datetime.timedelta(
         seconds=7200)  # Delete raids after 2 hours.
     notify_seconds = 300  # Notify raiders 5 minutes before.
     notify_time = datetime.timedelta(seconds=notify_seconds)
     current_time = datetime.datetime.utcnow(
     )  # Raid time is stored in UTC.
     # Copy the list to iterate over.
     for raid_id in raids[:]:
         timestamp = int(select_one(self.conn, 'Raids', 'time', raid_id))
         time = datetime.datetime.utcfromtimestamp(timestamp)
         if current_time >= time - notify_time * 2:
             channel_id = select_one(self.conn, 'Raids', 'channel_id',
                                     raid_id)
             channel = bot.get_channel(channel_id)
             if not channel:
                 self.cleanup_old_raid(raid_id,
                                       "Raid channel has been deleted.")
                 continue
             try:
                 post = await channel.fetch_message(raid_id)
             except discord.NotFound:
                 self.cleanup_old_raid(raid_id,
                                       "Raid post already deleted.")
             except discord.Forbidden:
                 self.cleanup_old_raid(
                     raid_id,
                     "We are missing required permissions to see raid post."
                 )
             else:
                 if current_time > time + expiry_time:
                     await post.delete()
                     self.cleanup_old_raid(raid_id,
                                           "Deleted expired raid post.")
                 elif current_time < time - notify_time:
                     roster = select_one(self.conn, 'Raids', 'roster',
                                         raid_id)
                     if roster:
                         raid_start_msg = _("Gondor calls for aid! ")
                         players = select_rows(self.conn, 'Assignment',
                                               'player_id', raid_id)
                         for player in players:
                             player_id = player[0]
                             if player_id:
                                 raid_start_msg = raid_start_msg + "<@{0}> ".format(
                                     player_id)
                         raid_start_msg = raid_start_msg + _(
                             "will you answer the call? We are forming for the raid now."
                         )
                         await channel.send(raid_start_msg,
                                            delete_after=notify_seconds * 2)
     self.conn.commit()
Exemplo n.º 3
0
 def build_raid_players(self, raid_id, block_size=6):
     guild_id = select_one(self.conn, 'Raids', 'guild_id', raid_id)
     guild = self.bot.get_guild(guild_id)
     columns = 'raid_id, player_id, byname'
     for name in self.role_names:
         columns = columns + ", " + name
     result = select_rows(self.conn, 'players', columns, raid_id)
     player_strings = []
     if result:
         number_of_players = len(result)
         number_of_fields = ((number_of_players - 1) // block_size) + 1
         # Create the player strings
         for row in result:
             i = 2
             player_string = row[i] + " "
             for name in self.role_names:
                 i = i + 1
                 if row[i]:
                     player_string = player_string + self.class_emojis_dict[
                         name]
             player_string = player_string + "\n"
             player_strings.append(player_string)
         # Sort the strings by length
         player_strings.sort(key=len, reverse=True)
     else:
         number_of_players = 0
         number_of_fields = 1
     # Compute number of fields
     msg = [""] * number_of_fields
     # Add the players to the fields, spreading large strings.
     number_of_players_added = 0
     remainder = number_of_players % block_size
     if remainder:
         cap_index_last_field = number_of_fields * remainder
     else:
         cap_index_last_field = number_of_fields * block_size
     for player_string in player_strings:
         if number_of_players_added < cap_index_last_field:
             index = number_of_players_added % number_of_fields
         else:
             index = number_of_players_added % (number_of_fields - 1)
         number_of_players_added = number_of_players_added + 1
         msg[index] = msg[index] + player_string
     # Do not send an empty embed if there are no players.
     if msg[0] == "":
         msg[0] = "\u200B"
     # Check if the length does not exceed embed limit and split if we can.
     if len(max(msg, key=len)) >= 1024 and block_size >= 2:
         msg = self.build_raid_players(raid_id, block_size=block_size // 2)
     return msg
Exemplo n.º 4
0
    async def background_task(self):
        bot = self.bot
        expiry_time = 7200  # Delete raids after 2 hours.
        notify_time = 300  # Notify raiders 5 minutes before.
        current_time = datetime.datetime.utcnow().timestamp(
        )  # Raid time is stored in UTC.

        cutoff = current_time + 2 * notify_time
        raids = select_upcoming_raids(self.conn, cutoff)
        for raid in raids:
            raid_id = int(raid[0])
            channel_id = int(raid[1])
            timestamp = int(raid[2])
            roster = int(raid[3])
            channel = bot.get_channel(channel_id)
            if not channel:
                self.cleanup_old_raid(raid_id,
                                      "Raid channel has been deleted.")
                continue
            try:
                post = await channel.fetch_message(raid_id)
            except discord.NotFound:
                self.cleanup_old_raid(raid_id, "Raid post already deleted.")
            except discord.Forbidden:
                self.cleanup_old_raid(
                    raid_id,
                    "We are missing required permissions to see raid post.")
            else:
                if current_time > timestamp + expiry_time:
                    await post.delete()
                    self.cleanup_old_raid(raid_id,
                                          "Deleted expired raid post.")
                elif current_time < timestamp - notify_time:
                    raid_start_msg = _(
                        "Gondor calls for aid! Will you answer the call")
                    if roster:
                        players = select_rows(self.conn, 'Assignment',
                                              'player_id', raid_id)
                        for player in players:
                            player_id = player[0]
                            if player_id:
                                raid_start_msg = raid_start_msg + " <@{0}>".format(
                                    player_id)
                    raid_start_msg = raid_start_msg + _(
                        "? We are forming for the raid now.")
                    await channel.send(raid_start_msg,
                                       delete_after=notify_time * 2)
        self.conn.commit()
Exemplo n.º 5
0
    async def get_players(self, author, channel, raid_id):
        bot = self.bot

        def check(reaction, user):
            return user == author

        timeout = 60
        reaction_limit = 20
        reactions = alphabet_emojis()
        reactions = reactions[:reaction_limit]

        players = select_rows(self.conn, 'Assignment', 'player_id', raid_id)
        assigned_ids = [
            player[0] for player in players if player[0] is not None
        ]
        available = select_players(self.conn, 'player_id, byname', raid_id)
        default_name = _("<Available>")

        if not available:
            await channel.send(
                _("There are no players to assign for this raid!"),
                delete_after=10)
            return
        if len(available) > reaction_limit:
            available = available[:
                                  reaction_limit]  # This only works for the first 20 players.
            await channel.send(
                _("**Warning**: removing some noobs from available players!"),
                delete_after=10)
        msg_content = _(
            "Please select the player you want to assign a spot in the raid from the list below using the "
            "corresponding reaction. Assignment will finish after {0}s of no interaction."
        ).format(timeout)
        info_msg = await channel.send(msg_content)

        msg_content = _("Available players:\n*Please wait... Loading*")
        player_msg = await channel.send(msg_content)
        for reaction in reactions[:len(available)]:
            await player_msg.add_reaction(reaction)
        class_msg_content = _("Select the class for this player.")
        class_msg = await channel.send(class_msg_content)
        for reaction in self.class_emojis:
            await class_msg.add_reaction(reaction)

        while True:
            # Update player msg
            msg_content = _("Available players:\n")
            counter = 0
            for player in available:
                if player[0] in assigned_ids:
                    msg_content = msg_content + str(
                        reactions[counter]) + " ~~" + player[1] + "~~\n"
                else:
                    msg_content = msg_content + str(
                        reactions[counter]) + " " + player[1] + "\n"
                counter = counter + 1
            await player_msg.edit(content=msg_content)
            # Get player
            try:
                (reaction, user) = await bot.wait_for('reaction_add',
                                                      timeout=timeout,
                                                      check=check)
            except asyncio.TimeoutError:
                await channel.send(_("Player assignment finished!"),
                                   delete_after=10)
                break
            else:
                try:
                    index = reactions.index(reaction.emoji)
                except ValueError:
                    await class_msg.remove_reaction(reaction, user)
                    await channel.send(_("Please select a player first!"),
                                       delete_after=10)
                    continue
                else:
                    await player_msg.remove_reaction(reaction, user)
                    selected_player = available[index]
                    slot = select_one_player(self.conn, 'Assignment',
                                             'slot_id', selected_player[0],
                                             raid_id)
                    if slot is not None:
                        # Player already assigned a slot, remove player and reset slot.
                        class_names = ','.join(self.slots_class_names[slot])
                        assign_player(self.conn, raid_id, slot, None,
                                      default_name, class_names)
                        assigned_ids.remove(selected_player[0])
                        text = _("Removed {0} from the line up!").format(
                            selected_player[1])
                        await channel.send(text, delete_after=10)
                        await self.update_raid_post(raid_id, channel)
                        continue
            # Get class
            try:
                (reaction, user) = await bot.wait_for('reaction_add',
                                                      timeout=timeout,
                                                      check=check)
            except asyncio.TimeoutError:
                await channel.send(_("Player assignment finished!"),
                                   delete_after=10)
                break
            else:
                if str(reaction.emoji) in self.class_emojis:
                    await class_msg.remove_reaction(reaction, user)
                    signup = select_one_player(self.conn, 'Players',
                                               reaction.emoji.name,
                                               selected_player[0], raid_id)
                    if not signup:
                        text = _("{0} did not sign up with {1}!").format(
                            selected_player[1], str(reaction.emoji))
                        await channel.send(text, delete_after=10)
                        continue
                else:
                    await player_msg.remove_reaction(reaction, user)
                    await channel.send(
                        _("That is not a class, please start over!"),
                        delete_after=10)
                    continue
            # Check for free slot
            search = '%' + reaction.emoji.name + '%'
            slot_id = select_one_slot(self.conn, raid_id, search)
            if slot_id is None:
                await channel.send(
                    _("There are no slots available for the selected class."),
                    delete_after=10)
            else:
                assign_player(self.conn, raid_id, slot_id, *selected_player,
                              reaction.emoji.name)
                assigned_ids.append(selected_player[0])
                msg_content = _("Assigned {0} to {1}.").format(
                    selected_player[1], str(reaction.emoji))
                await channel.send(msg_content, delete_after=10)
                await self.update_raid_post(raid_id, channel)

        await info_msg.delete()
        await player_msg.delete()
        await class_msg.delete()
        return