Beispiel #1
0
    async def search(self, ctx: commands.Context, **flags):
        """Search pokémon from the marketplace."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        aggregations = await self.bot.get_cog("Pokemon").create_filter(
            flags, ctx, order_by=flags["order"])

        if aggregations is None:
            return

        # Filter pokemon

        def padn(p, idx, n):
            return " " * (len(str(n)) - len(str(idx))) + str(idx)

        num = await self.bot.mongo.fetch_market_count(aggregations=aggregations
                                                      )

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 20
            pokemon = await self.bot.mongo.fetch_market_list(
                pgstart, 20, aggregations=aggregations)

            pokemon = [(
                self.bot.mongo.EmbeddedPokemon.build_from_mongo(x["pokemon"]),
                x["_id"],
                x["price"],
            ) for x in pokemon]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            maxn = max(idx for x, idx, price in pokemon)
            page = [
                f"`{padn(p, idx, maxn)}` **{p:li}** • {p.iv_percentage * 100:.2f}% • {price:,} pc"
                for p, idx, price in pokemon
            ]

            # Send embed

            embed = self.bot.Embed(color=0xF44336)
            embed.title = f"Pokétwo Marketplace"
            embed.description = "\n".join(page)[:2048]

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}. (Page {pidx+1} of {math.ceil(num / 20)})"
            )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags["page"] - 1)
Beispiel #2
0
    async def send_bot_help(self, mapping):
        ctx = self.context
        ctx.invoked_with = "help"
        bot = ctx.bot

        def get_category(command):
            cog = command.cog
            return cog.qualified_name if cog is not None else "\u200bNo Category"

        pages = []
        total = 0

        filtered = await self.filter_commands(bot.commands,
                                              sort=True,
                                              key=get_category)

        for cog_name, commands in itertools.groupby(filtered,
                                                    key=get_category):
            commands = sorted(commands, key=lambda c: c.name)

            if len(commands) == 0:
                continue

            total += len(commands)
            cog = bot.get_cog(cog_name)
            description = ((cog and cog.description) if
                           (cog and cog.description) is not None else
                           discord.Embed.Empty)
            pages.append((cog, description, commands))

        async def get_page(pidx, clear):
            cogs = pages[min(len(pages) - 1, pidx *
                             6):min(len(pages) - 1, pidx * 6 + 6)]

            embed = self.make_default_embed(
                cogs,
                title=
                f"Pokétwo Command Categories (Page {pidx+1}/{len(pages)//6+1})",
                description=
                (f"Use `{self.clean_prefix}help <command>` for more info on a command.\n"
                 f"Use `{self.clean_prefix}help <category>` for more info on a category."
                 ),
            )

            # embed.set_author(name=f"Page {pidx + 1}/{len(pages)} ({total} commands)")

            return embed

        paginator = pagination.Paginator(get_page, len(pages) // 6 + 1)
        await paginator.send(bot, ctx, 0)
Beispiel #3
0
    async def moveset(self, ctx: commands.Context, *, search: str):
        """View all moves for your pokémon and how to get them."""

        search = search.strip()

        if len(search) > 0 and search[0] in "Nn#" and search[1:].isdigit():
            species = self.bot.data.species_by_number(int(search[1:]))
        else:
            species = self.bot.data.species_by_name(search)

            if species is None:
                converter = converters.Pokemon(raise_errors=False)
                pokemon = await converter.convert(ctx, search)
                if pokemon is not None:
                    species = pokemon.species

        if species is None:
            raise converters.PokemonConversionError(
                f"Please either enter the name of a pokémon species, nothing for your selected pokémon, a number for "
                f"a specific pokémon, `latest` for your latest pokémon. ",
                original=ValueError(),
            )

        async def get_page(pidx, clear):
            pgstart = (pidx) * 20
            pgend = min(pgstart + 20, len(species.moves))

            # Send embed

            embed = discord.Embed(color=0xE67D23)
            embed.title = f"{species} — Moveset"

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{pgend} out of {len(species.moves)}.")

            for move in species.moves[pgstart:pgend]:
                embed.add_field(name=move.move.name, value=move.text)

            for i in range(-pgend % 3):
                embed.add_field(name="‎", value="‎")

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(
                                             len(species.moves) / 20))
        await paginator.send(self.bot, ctx, 0)
Beispiel #4
0
    async def req(self, ctx: commands.Context, *args):

        if args[-1].isdigit():
            page = int(args[-1]) - 1
            args = args[:-1]
        else:
            page = 0

        try:
            badge = next(
                x for x in self.data if " ".join(args).lower() in x["name"].lower()
            )
        except StopIteration:
            await ctx.send("Couldn't find anything matching that query.")
            return

        image_name = badge["name"].replace(" ", "").lower()

        groups = []
        for x in badge["requirements"]:
            if x["depth"] == 0:
                groups.append([])
            groups[-1].append(x)

        async def get_page(idx):
            title = badge["name"]
            if badge.get("isEagle", False):
                title += " 🦅"

            lines = [f"**Requirement {idx + 1}**"]
            lines += [
                ("" if x["index"] == "" else f"{x['index']}. ") + x["text"]
                for x in groups[idx]
            ]

            embed = discord.Embed(
                title=title, description="\n\n".join(lines), color=0xF44336,
            )
            embed.set_thumbnail(
                url=f"http://t452.oliverni.com/merit-badges/{image_name}.png"
            )
            embed.set_footer(
                text=f"Displaying requirement {idx+1} out of {len(groups)}."
            )
            return embed

        paginator = pagination.Paginator(get_page, len(groups))
        await paginator.send(self.bot, ctx, page=page)
Beispiel #5
0
    async def collection(self, ctx: commands.Context, **flags):
        """Show users collection
        Queries: **id|amount|name|rarity|type|supertype|subtype|artist|set|series|evolvesfrom|hp**
        subtype = Item, Stage 1, Supporter, TAG TEAM, etc.
        supertype = Pokemon, Energy, Trainer
        series = Sword & Shield, POP, E-Card, Gym, NEO, etc.
        set = Darkness Ablaze, Rebel Clash, Unified Minds, etc.
        Examples:
        `<prefix>collection 3 --type Psychic --rarity rare, common`
        -> this will show page 3 the user's collection of psychic rares/commons
        `<prefix>collection --artist Ken Sugimori --rarity rare`
        -> show cards with artist ken sugimori with rare rarity
        `<prefix>collection --rarity rare --amount > 2 --hp > 50`
        -> rare cards with at least 2 amount and hp greater than 50
        **jp cards dont have hp information**
        """

        if flags['page'] < 1:
            return await ctx.send('Invalid page number')
        sort = await self.bot.db.get_user_sort(ctx.author)
        
        aggregations = await self.create_filter(flags, ctx)
        # dictionary with filters in em -- key, value = filter, values to filter
        num = await self.bot.db.get_user_cards_count(str(ctx.author.id), queries = aggregations)
        if num == 0:
            return await ctx.send('No cards matching this query')

        async def get_page(pidx, clear):
            pgstart = pidx * 20

            cards = await self.bot.db.get_user_cardsV2(str(ctx.author.id), pgstart, 20, queries = aggregations, sort = sort)

            if len(cards) == 0:
                return await ctx.send('No cards in this page')
            
            page = [
                f"{self.get_rarity_emoji(c['rarity'])}{''.join(self.get_energy_types_emoji(c['types']))} | **{c['id']}** | {c['name']} | **{c['amount']}**" 
                for c in cards
            ]

            embed = self.bot.Embed(color = discord.Color.dark_teal())
            embed.title = "Your cards"
            embed.description = '\n'.join(page)[:2048] # limit in embed
            embed.set_footer(text = f"Page {pidx+1} of {math.ceil(num/20)}")
            return embed
        paginator = pagination.Paginator(get_page, num_pages = math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags['page'] - 1)
Beispiel #6
0
    async def send_bot_help(self, mapping):
        ctx = self.context
        bot = ctx.bot

        def get_category(command):
            cog = command.cog
            return cog.qualified_name if cog is not None else "\u200bNo Category"

        pages = []
        total = 0

        filtered = await self.filter_commands(bot.commands,
                                              sort=True,
                                              key=get_category)

        for cog_name, commands in itertools.groupby(filtered,
                                                    key=get_category):
            commands = sorted(commands, key=lambda c: c.name)

            if len(commands) == 0:
                continue

            total += len(commands)
            cog = bot.get_cog(cog_name)
            description = (cog and cog.description) or discord.Embed.Empty
            pages.append((cog, description, commands))

        async def get_page(pidx, clear):
            cog, description, commands = pages[pidx]

            embed = self.make_page_embed(
                commands,
                title=(cog and cog.qualified_name or "Other") + " Commands",
                description=discord.Embed.Empty
                if cog is None else cog.description,
            )
            embed.set_author(
                name=f"Page {pidx + 1}/{len(pages)} ({total} commands)")

            return embed

        paginator = pagination.Paginator(get_page, len(pages))
        await paginator.send(bot, ctx, 0)
Beispiel #7
0
    async def send_trade(self, ctx: commands.Context, user: discord.Member):
        # TODO this code is pretty shit. although it does work

        trade = self.bot.trades[user.id]
        a, b = trade["items"].keys()

        done = False

        if trade[a] and trade[b] and not trade["executing"]:
            done = True
            trade["executing"] = True

        a = ctx.guild.get_member(a) or await ctx.guild.fetch_member(a)
        b = ctx.guild.get_member(b) or await ctx.guild.fetch_member(b)

        num_pages = max(
            math.ceil(len(x) / 20) for x in trade["items"].values())

        if done:
            execmsg = await ctx.send("Executing trade...")

        async def get_page(pidx, clear):
            embed = self.bot.Embed(color=0xE67D23)
            embed.title = f"Trade between {a.display_name} and {b.display_name}."

            if done:
                embed.title = (
                    f"✅ Completed trade between {a.display_name} and {b.display_name}."
                )

            embed.set_footer(
                text=
                f"Type `{ctx.prefix}trade add <number>` to add a pokémon, `{ctx.prefix}trade add <number> pc` to add Pokécoins, `{ctx.prefix}trade confirm` to confirm, or `{ctx.prefix}trade cancel` to cancel."
            )

            for i, fullside in trade["items"].items():
                mem = ctx.guild.get_member(i) or await ctx.guild.fetch_member(i
                                                                              )

                side = fullside[pidx * 20:(pidx + 1) * 20]

                if mem is None:
                    return await ctx.send("The trade has been canceled.")

                try:
                    maxn = max(x.idx for x in side if type(x) != int)
                except ValueError:
                    maxn = 0

                def padn(idx, n):
                    return " " * (len(str(n)) - len(str(idx))) + str(idx)

                def txt(p):
                    val = f"`{padn(p.idx, maxn)}` **{p.species}**"
                    if p.shiny:
                        val += " ✨"
                    val += f" • Lvl. {p.level} • {p.iv_percentage:.2%}"
                    return val

                val = "\n".join(
                    f"{x:,} Pokécoins" if type(x) == int else txt(x)
                    for x in side)

                if val == "":
                    if len(fullside) == 0:
                        val = "None"
                    else:
                        val = "None on this page"

                sign = "🟢" if trade[i] else "🔴"

                embed.add_field(name=f"{sign} {mem.display_name}", value=val)

            embed.set_footer(
                text=f"Showing page {pidx + 1} out of {num_pages}.")

            return embed

        # Check if done

        embeds = []

        if done:
            try:
                bothsides = list(enumerate(trade["items"].items()))

                for idx, tup in bothsides:
                    i, side = tup
                    mem = ctx.guild.get_member(
                        i) or await ctx.guild.fetch_member(i)
                    member = await self.db.fetch_member_info(mem)
                    if member.balance < sum(x for x in side if type(x) == int):
                        await ctx.send(
                            "The trade could not be executed as one user does not have enough Pokécoins."
                        )
                        del self.bot.trades[a.id]
                        del self.bot.trades[b.id]
                        return

                for idx, tup in bothsides:
                    i, side = tup

                    oidx, otup = bothsides[(idx + 1) % 2]
                    oi, oside = otup

                    mem = ctx.guild.get_member(
                        i) or await ctx.guild.fetch_member(i)
                    omem = ctx.guild.get_member(
                        oi) or await ctx.guild.fetch_member(oi)

                    member = await self.db.fetch_member_info(mem)
                    omember = await self.db.fetch_member_info(omem)

                    idxs = set()

                    num_pokes = len(list(x for x in side if type(x) != int))
                    idx = await self.db.fetch_next_idx(omem, num_pokes)

                    for x in side:
                        if type(x) == int:
                            await self.db.update_member(
                                mem, {"$inc": {
                                    "balance": -x
                                }})
                            await self.db.update_member(
                                omem, {"$inc": {
                                    "balance": x
                                }})
                        else:

                            pokemon = x

                            if pokemon.idx in idxs:
                                continue

                            idxs.add(pokemon.idx)

                            update = {
                                "$set": {
                                    "owner_id": omem.id,
                                    "idx": idx,
                                }
                            }
                            idx += 1

                            if (pokemon.species.trade_evolution
                                ) and pokemon.held_item != 13001:
                                evo = pokemon.species.trade_evolution
                                if (evo.trigger.item is None
                                        or evo.trigger.item.id
                                        == pokemon.held_item):
                                    evo_embed = self.bot.Embed(color=0xE67D23)
                                    evo_embed.title = (
                                        f"Congratulations {omem.display_name}!"
                                    )

                                    name = str(pokemon.species)

                                    if pokemon.nickname is not None:
                                        name += f' "{pokemon.nickname}"'

                                    evo_embed.add_field(
                                        name=f"The {name} is evolving!",
                                        value=
                                        f"The {name} has turned into a {evo.target}!",
                                    )

                                    update["$set"][
                                        "species_id"] = evo.target.id

                                    embeds.append(evo_embed)

                            await self.db.update_pokemon(
                                pokemon,
                                update,
                            )

            except:
                del self.bot.trades[a.id]
                del self.bot.trades[b.id]
                raise

            try:
                await execmsg.delete()
            except:
                pass

            try:
                await self.bot.mongo.db.logs.insert_one({
                    "event": "trade",
                    "users": [a.id, b.id],
                    "items": {
                        str(a.id): [
                            x if type(x) == int else x.id
                            for x in trade["items"][a.id]
                        ],
                        str(b.id): [
                            x if type(x) == int else x.id
                            for x in trade["items"][b.id]
                        ],
                    },
                })
            except:
                print("Error saving trading logs.")
                pass

            del self.bot.trades[a.id]
            del self.bot.trades[b.id]

        # Send msg

        paginator = pagination.Paginator(get_page, num_pages=num_pages)
        self.bot.loop.create_task(paginator.send(self.bot, ctx, 0))

        for evo_embed in embeds:
            await ctx.send(embed=evo_embed)
Beispiel #8
0
    async def search(self, ctx, **flags):
        """Search pokémon from auctions."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        aggregations = await self.bot.get_cog("Pokemon").create_filter(
            flags, ctx, order_by=flags["order"])

        if aggregations is None:
            return

        # Filter pokemon

        def padn(p, idx, n):
            return " " * (len(str(n)) - len(str(idx))) + str(idx)

        num = await self.bot.mongo.fetch_auction_count(
            ctx.guild, aggregations=aggregations)

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 15
            pokemon = await self.bot.mongo.fetch_auction_list(
                ctx.guild, pgstart, 15, aggregations=aggregations)

            pokemon = [(
                self.bot.mongo.EmbeddedPokemon.build_from_mongo(x["pokemon"]),
                x["_id"],
                x["current_bid"],
                x["bid_increment"],
                x.get("bidder_id", None),
                x["ends"],
            ) for x in pokemon]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            now = datetime.utcnow()

            maxn = max(x[1] for x in pokemon)
            page = [
                f"`{padn(p, idx, maxn)}` **{p:Li}** • {p.iv_percentage * 100:.2f}% • CB: {current_bid:,} • BI: {bid_interval:,} pc • {converters.strfdelta(ends - now, max_len=1)}"
                if bidder_id is not None else
                f"`{padn(p, idx, maxn)}` **{p:Li}** • {p.iv_percentage * 100:.2f}% • SB: {current_bid + bid_interval:,} pc • {converters.strfdelta(ends - now, max_len=1)}"
                for p, idx, current_bid, bid_interval, bidder_id, ends in
                pokemon
            ]

            # Send embed

            embed = self.bot.Embed(color=0x9CCFFF)
            embed.title = f"Auctions in {ctx.guild.name}"
            embed.description = "\n".join(page)[:2048]

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{min(pgstart + 15, num)} out of {num}. (Page {pidx+1} of {math.ceil(num / 15)})"
            )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 15))
        await paginator.send(self.bot, ctx, flags["page"] - 1)
Beispiel #9
0
    async def pokedex(self, ctx: commands.Context, **flags):
        """View your pokédex, or search for a pokémon species."""

        search_or_page = " ".join(flags["page"])

        if flags["orderd"] and flags["ordera"]:
            return await ctx.send(
                "You can use either --orderd or --ordera, but not both.")

        if flags["caught"] and flags["uncaught"]:
            return await ctx.send(
                "You can use either --caught or --uncaught, but not both.")

        if flags["mythical"] + flags["legendary"] + flags["ub"] > 1:
            return await ctx.send("You can't use more than one rarity flag!")

        if search_or_page is None:
            search_or_page = "1"

        if search_or_page.isdigit():
            pgstart = (int(search_or_page) - 1) * 20

            if pgstart >= 809 or pgstart < 0:
                return await ctx.send("There are no pokémon on this page.")

            num = await self.bot.mongo.fetch_pokedex_count(ctx.author)

            do_emojis = (ctx.guild is None or ctx.guild.me.permissions_in(
                ctx.channel).external_emojis)

            member = await self.bot.mongo.fetch_pokedex(ctx.author, 0, 810)
            pokedex = member.pokedex

            if not flags["uncaught"] and not flags["caught"]:
                for i in range(1, 810):
                    if str(i) not in pokedex:
                        pokedex[str(i)] = 0
            elif flags["uncaught"]:
                for i in range(1, 810):
                    if str(i) not in pokedex:
                        pokedex[str(i)] = 0
                    else:
                        del pokedex[str(i)]

            def include(key):
                if flags[
                        "legendary"] and key not in self.bot.data.list_legendary:
                    return False
                if flags["mythical"] and key not in self.bot.data.list_mythical:
                    return False
                if flags["ub"] and key not in self.bot.data.list_ub:
                    return False

                if flags["type"] and key not in self.bot.data.list_type(
                        flags["type"]):
                    return False

                return True

            pokedex = {
                int(k): v
                for k, v in pokedex.items() if include(int(k))
            }

            if flags["ordera"]:
                pokedex = sorted(pokedex.items(), key=itemgetter(1))
            elif flags["orderd"]:
                pokedex = sorted(pokedex.items(),
                                 key=itemgetter(1),
                                 reverse=True)
            else:
                pokedex = sorted(pokedex.items(), key=itemgetter(0))

            async def get_page(pidx, clear):
                pgstart = (pidx) * 20
                pgend = min(pgstart + 20, len(pokedex))

                # Send embed

                embed = self.bot.Embed(color=0xF44336)
                embed.title = f"Your pokédex"
                embed.description = f"You've caught {num} out of 809 pokémon!"

                embed.set_footer(
                    text=f"Showing {pgstart + 1}–{pgend} out of {len(pokedex)}."
                )

                # embed.description = (
                #     f"You've caught {len(member.pokedex)} out of 809 pokémon!"
                # )

                for k, v in pokedex[pgstart:pgend]:
                    species = self.bot.data.species_by_number(k)

                    if do_emojis:
                        text = f"{self.bot.sprites.cross} Not caught yet!"
                    else:
                        text = "Not caught yet!"

                    if v > 0:
                        if do_emojis:
                            text = f"{self.bot.sprites.check} {v} caught!"
                        else:
                            text = f"{v} caught!"

                    if do_emojis:
                        emoji = self.bot.sprites.get(k) + " "
                    else:
                        emoji = ""

                    embed.add_field(
                        name=f"{emoji}{species.name} #{species.id}",
                        value=text)

                if pgend != 809:
                    embed.add_field(name="‎", value="‎")

                return embed

            paginator = pagination.Paginator(get_page,
                                             num_pages=math.ceil(
                                                 len(pokedex) / 20))
            await paginator.send(self.bot, ctx, int(search_or_page) - 1)

        else:
            shiny = False

            if search_or_page[0] in "Nn#" and search_or_page[1:].isdigit():
                species = self.bot.data.species_by_number(
                    int(search_or_page[1:]))

            else:
                search = search_or_page

                if search_or_page.lower().startswith("shiny "):
                    shiny = True
                    search = search_or_page[6:]

                species = self.bot.data.species_by_name(search)
                if species is None:
                    return await ctx.send(
                        f"Could not find a pokemon matching `{search_or_page}`."
                    )

            member = await self.bot.mongo.fetch_pokedex(
                ctx.author, species.dex_number, species.dex_number + 1)

            embed = self.bot.Embed(color=0xF44336)
            embed.title = f"#{species.dex_number} — {species}"

            if species.description:
                embed.description = species.description.replace("\n", " ")

            if species.evolution_text:
                embed.add_field(name="Evolution",
                                value=species.evolution_text,
                                inline=False)

            if shiny:
                embed.title = f"#{species.dex_number} — ✨ {species}"
                embed.set_image(url=species.shiny_image_url)
            else:
                embed.set_image(url=species.image_url)

            base_stats = (
                f"**HP:** {species.base_stats.hp}",
                f"**Attack:** {species.base_stats.atk}",
                f"**Defense:** {species.base_stats.defn}",
                f"**Sp. Atk:** {species.base_stats.satk}",
                f"**Sp. Def:** {species.base_stats.sdef}",
                f"**Speed:** {species.base_stats.spd}",
            )

            embed.add_field(
                name="Names",
                value="\n".join(f"{x} {y}" for x, y in species.names),
                inline=False,
            )
            embed.add_field(name="Base Stats", value="\n".join(base_stats))
            embed.add_field(
                name="Appearance",
                value=
                f"Height: {species.height} m\nWeight: {species.weight} kg",
            )
            embed.add_field(name="Types", value="\n".join(species.types))

            text = "You haven't caught this pokémon yet!"
            if str(species.dex_number) in member.pokedex:
                text = f"You've caught {member.pokedex[str(species.dex_number)]} of this pokémon!"

            embed.set_footer(text=text)

            await ctx.send(embed=embed)
Beispiel #10
0
    async def pokemon(self, ctx: commands.Context, **flags):
        """View or filter the pokémon in your collection."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        member = await self.db.fetch_member_info(ctx.author)

        aggregations = await self.create_filter(flags,
                                                ctx,
                                                order_by=member.order_by)

        if aggregations is None:
            return

        # Filter pokemon

        do_emojis = ctx.guild.me.permissions_in(ctx.channel).external_emojis

        fixed_pokemon = False

        async def fix_pokemon():
            # TODO This is janky way of removing bad database entries, I should fix this

            nonlocal fixed_pokemon

            if fixed_pokemon:
                return

            await self.db.update_member(
                ctx.author,
                {"$pull": {
                    f"pokemon": {
                        "species_id": {
                            "$exists": False
                        }
                    }
                }},
            )
            await self.db.update_member(ctx.author,
                                        {"$pull": {
                                            f"pokemon": None
                                        }})

            fixed_pokemon = True

        def nick(p):
            if p.species is None:
                asyncio.create_task(fix_pokemon())
                return None

            name = str(p.species)

            if do_emojis:
                name = (
                    self.bot.sprites.get(p.species.dex_number, shiny=p.shiny) +
                    " " + name)

            if p.shiny:
                name += " ✨"

            if p.nickname is not None:
                name += ' "' + p.nickname + '"'

            if p.favorite:
                name += " ❤️"

            return name

        def padn(p, idx, n):
            return " " * (len(str(n)) - len(str(idx))) + str(idx)

        num = await self.db.fetch_pokemon_count(ctx.author,
                                                aggregations=aggregations)

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 20
            pokemon = await self.db.fetch_pokemon_list(
                ctx.author, pgstart, 20, aggregations=aggregations)

            pokemon = [(self.bot.mongo.Pokemon.build_from_mongo(x["pokemon"]),
                        x["idx"] + 1) for x in pokemon]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            maxn = max(idx for x, idx in pokemon)

            page = [
                f"`{padn(p, idx, maxn)}` **{txt}** • Lvl. {p.level} • {p.iv_percentage * 100:.2f}%"
                for p, idx in pokemon if (txt := nick(p)) is not None
            ]

            # Send embed

            embed = self.bot.Embed()
            embed.title = f"Your pokémon"
            embed.description = "\n".join(page)[:2048]

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}. (Page {pidx+1} of {math.ceil(num / 20)})"
            )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags["page"] - 1)
Beispiel #11
0
    async def search(self, ctx: commands.Context, **flags):
        """Search pokémon from the marketplace."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        member = await self.db.fetch_member_info(ctx.author)

        aggregations = await self.bot.get_cog("Pokemon").create_filter(
            flags, ctx, order_by=flags["order"])

        if aggregations is None:
            return

        # Filter pokemon

        do_emojis = ctx.guild.me.permissions_in(ctx.channel).external_emojis

        def nick(p):
            name = f"L{p.level} {p.species}"

            if do_emojis:
                name = (
                    self.bot.sprites.get(p.species.dex_number, shiny=p.shiny) +
                    " " + name)

            if p.shiny:
                name += " ✨"

            return name

        def padn(p, idx, n):
            return " " * (len(str(n)) - len(str(idx))) + str(idx)

        num = await self.db.fetch_market_count(aggregations=aggregations)

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 20
            pokemon = await self.db.fetch_market_list(
                pgstart, 20, aggregations=aggregations)

            pokemon = [(
                self.bot.mongo.EmbeddedPokemon.build_from_mongo(x["pokemon"]),
                x["_id"],
                x["price"],
            ) for x in pokemon]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            maxn = max(idx for x, idx, price in pokemon)
            page = [
                f"`{padn(p, idx, maxn)}` **{nick(p)}** • {p.iv_percentage * 100:.2f}% • {price:,} pc"
                for p, idx, price in pokemon
            ]

            # Send embed

            embed = self.bot.Embed()
            embed.title = f"Pokétwo Marketplace"
            embed.description = "\n".join(page)[:2048]

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}. (Page {pidx+1} of {math.ceil(num / 20)})"
            )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags["page"] - 1)
Beispiel #12
0
    async def market(self, ctx: commands.Context, **flags):
        """Market functions
        `market 3 --rarity rare --hp > 100 --sort` -> page 3 of rare cards with 100+ hp sorted by cost
        `market --mine` -> first page of user's market listings
        `market --remove <market_id>` -> remove the listing by market_id if it is by the user
        `market --show <market_id>` -> show card art of the listing
        `market --buy <market_id>` -> buy the market listing
        `market --rarity rare --cost < 100` -> show rare listings with cost less than 100
        """
        # Buy a market listing
        if flags['buy']:
            market_id = flags['buy']
            response, output = await self.bot.db.buy_from_market(
                ctx.author, market_id)
            if response:
                return await ctx.send(embed=await self.bot.embeds.get(
                    {
                        'type': 'GENERAL',
                        'title': 'Bought from Market',
                        'color': discord.Color.blue(),
                        'body': output,
                        'footer': f'Rich boi {str(ctx.author)}'
                    }))
            else:
                return await ctx.send(embed=await self.bot.embeds.get(
                    {
                        'type': 'GENERAL',
                        'title': 'Unable to buy from Market',
                        'color': discord.Color.red(),
                        'body': output,
                        'footer': f'Requested by {str(ctx.author)}'
                    }))

        # Remove user's market listing
        if flags['remove']:
            market_id = flags['remove']
            response, card = await self.bot.db.remove_from_market(
                ctx.author, market_id)
            if response:
                return await ctx.send(embed=await self.bot.embeds.get(
                    {
                        'type': 'GENERAL',
                        'title': 'Removed from Market',
                        'color': discord.Color.blue(),
                        'body': f'Removed {market_id} | {card} from market',
                        'footer': f'Requested by {str(ctx.author)}'
                    }))
            else:
                return await ctx.send(embed=await self.bot.embeds.get(
                    {
                        'type': 'GENERAL',
                        'title': 'Unable to remove from Market',
                        'color': discord.Color.blue(),
                        'body': 'Not valid, or not your market listing',
                        'footer': f'Requested by {str(ctx.author)}'
                    }))

        # Show card in listing
        if flags['show']:
            market_id = flags['show']
            listing = await self.bot.db.get_market_listing(market_id)
            if listing:
                picture_file = discord.File('data/images/{}.webp'.format(
                    listing['card_id']),
                                            filename='show.webp')
                embed = {
                    'type': 'GENERAL-ATTACHMENT-IMAGE',
                    'body':
                    f"{listing['card_name']} | {listing['rarity']} | {listing['card_id']}\n${listing['cost']} | {listing['amount']} cards",
                    'title':
                    'Showing Market Listing - {}'.format(listing['id']),
                    'color': discord.Color.green(),
                    'footer': 'Requested by {}'.format(str(ctx.author)),
                    'attachment': 'show.webp'
                }
                return await ctx.send(embed=await self.bot.embeds.get(embed),
                                      file=picture_file)
            else:  # market listing not found
                return await ctx.send(embed=await self.bot.embeds.get({
                    'type':
                    'GENERAL',
                    'title':
                    'Unable to show Market listing',
                    'color':
                    discord.Color.blue(),
                    'body':
                    'Not a valid market listing, make sure market id is correct',
                    'footer':
                    f'Requested by {str(ctx.author)}'
                }))

        if flags['page'] < 1:
            return await ctx.send('Invalid page number')
        aggregations = await self.create_filter(flags, ctx)
        num = await self.bot.db.get_market_count(queries=aggregations)
        if num == 0:
            return await ctx.send('No listings matching this query')

        async def get_page(pidx, clear):
            pgstart = pidx * 20

            listings = await self.bot.db.get_marketV2(pgstart,
                                                      20,
                                                      queries=aggregations,
                                                      sort=flags['sort'])

            if len(listings) == 0:
                return await ctx.send('No listings in this page')

            page = [
                f"`{l['market_id']}` | **${l['cost']}** | {l['rarity']} | {l['card_name']} | {l['card_id']} | {l['amount']}"
                for l in listings
            ]

            embed = self.bot.Embed(color=discord.Color.dark_teal())
            embed.title = "Market Listings"
            embed.description = '\n'.join(page)[:2048]  # limit in embed
            embed.set_footer(text=f"Page {pidx+1} of {math.ceil(num/20)}")
            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags['page'] - 1)
Beispiel #13
0
    async def info(self, ctx: commands.Context, *,
                   pokemon: converters.Pokemon):
        """View a specific pokémon from your collection."""

        pokemon, pidx = pokemon

        num = await self.db.fetch_pokemon_count(ctx.author)

        async def get_page(pidx, clear):
            pokemon = await self.db.fetch_pokemon(ctx.author, pidx)

            if pokemon is None:
                return await clear("Couldn't find that pokémon!")

            embed = discord.Embed()
            embed.color = 0xF44336
            embed.title = f"Level {pokemon.level} {pokemon.species}"

            if pokemon.nickname is not None:
                embed.title += f' "{pokemon.nickname}"'

            extrafooter = ""

            if pokemon.shiny:
                embed.title += " ✨"
                embed.set_image(url=pokemon.species.shiny_image_url)
                extrafooter = " Note that we don't have artwork for all shiny pokémon yet! We're working hard to make all the shiny pokémon look shiny."
            else:
                embed.set_image(url=pokemon.species.image_url)

            embed.set_thumbnail(url=ctx.author.avatar_url)

            info = (
                f"**XP:** {pokemon.xp}/{pokemon.max_xp}",
                f"**Nature:** {pokemon.nature}",
            )

            embed.add_field(name="Details",
                            value="\n".join(info),
                            inline=False)

            stats = (
                f"**HP:** {pokemon.hp} – IV: {pokemon.iv_hp}/31",
                f"**Attack:** {pokemon.atk} – IV: {pokemon.iv_atk}/31",
                f"**Defense:** {pokemon.defn} – IV: {pokemon.iv_defn}/31",
                f"**Sp. Atk:** {pokemon.satk} – IV: {pokemon.iv_satk}/31",
                f"**Sp. Def:** {pokemon.sdef} – IV: {pokemon.iv_sdef}/31",
                f"**Speed:** {pokemon.spd} – IV: {pokemon.iv_spd}/31",
                f"**Total IV:** {pokemon.iv_percentage * 100:.2f}%",
            )

            embed.add_field(name="Stats", value="\n".join(stats), inline=False)

            if pokemon.held_item:
                item = models.GameData.item_by_number(pokemon.held_item)
                gguild = self.bot.get_guild(725819081835544596)
                emote = ""
                if item.emote is not None:
                    try:
                        e = next(
                            filter(lambda x: x.name == item.emote,
                                   gguild.emojis))
                        emote = f"{e} "
                    except StopIteration:
                        pass
                embed.add_field(name="Held Item",
                                value=f"{emote}{item.name}",
                                inline=False)

            embed.set_footer(
                text=f"Displaying pokémon {pidx + 1} out of {num}." +
                extrafooter)

            return embed

        paginator = pagination.Paginator(get_page, num_pages=num)
        await paginator.send(self.bot, ctx, pidx)
Beispiel #14
0
    async def pokemon(self, ctx: commands.Context, **flags):
        """View or filter the pokémon in your collection."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        aggregations = await self.create_filter(flags, ctx)

        if aggregations is None:
            return

        # # Filter pokemon

        # Pagination

        member = await self.db.fetch_member_info(ctx.author)

        aggregations.extend([
            {
                "$addFields": {
                    "sorting": constants.SORTING_FUNCTIONS[member.order_by]
                }
            },
            {
                "$sort": {
                    "sorting": 1
                }
            },
        ])

        do_emojis = ctx.channel.permissions_for(
            ctx.guild.get_member(self.bot.user.id)).external_emojis

        fixed_pokemon = False

        async def fix_pokemon():
            # TODO This is janky way of removing bad database entries, I should fix this

            nonlocal fixed_pokemon

            if fixed_pokemon:
                return

            await self.db.update_member(
                ctx.author,
                {"$pull": {
                    f"pokemon": {
                        "species_id": {
                            "$exists": False
                        }
                    }
                }},
            )
            await self.db.update_member(ctx.author,
                                        {"$pull": {
                                            f"pokemon": None
                                        }})

            fixed_pokemon = True

        def nick(p):
            if p.species is None:
                asyncio.create_task(fix_pokemon())
                return None

            if do_emojis:
                name = (str(
                    constants.EMOJIS.get(
                        p.species.dex_number, shiny=p.shiny)).replace(
                            "pokemon_sprite_", "").replace("_shiny", "") + " ")
            else:
                name = ""

            name += str(p.species)

            if p.shiny:
                name += " ✨"

            if p.nickname is not None:
                name += ' "' + p.nickname + '"'

            if p.favorite:
                name += " ❤️"

            return name

        def padn(p, idx, n):
            return " " * (len(str(n)) - len(str(idx))) + str(idx)

        num = await self.db.fetch_pokemon_count(ctx.author,
                                                aggregations=aggregations)

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 20
            pokemon = await self.db.fetch_pokemon_list(
                ctx.author, pgstart, 20, aggregations=aggregations)

            pokemon = [(mongo.Pokemon.build_from_mongo(x["pokemon"]),
                        x["idx"] + 1) for x in pokemon]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            maxn = max(idx for x, idx in pokemon)

            page = [
                f"`{padn(p, idx, maxn)}`⠀**{txt}**⠀•⠀Lvl. {p.level}⠀•⠀{p.iv_percentage * 100:.2f}%"
                for p, idx in pokemon if (txt := nick(p)) is not None
            ]

            # Send embed

            embed = discord.Embed()
            embed.color = 0xF44336
            embed.title = f"Your pokémon"
            embed.description = "\n".join(page)[:2048]

            if do_emojis:
                embed.set_footer(
                    text=
                    f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}."
                )
            else:
                embed.set_footer(
                    text=
                    f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}. Please give me permission to Use External Emojis! It'll make this menu look a lot better."
                )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags["page"] - 1)
Beispiel #15
0
    async def search(self, ctx: commands.Context, **flags):
        """Search pokémon from the marketplace."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        member = await self.bot.mongo.fetch_member_info(ctx.author)

        aggregations = await self.bot.get_cog("Pokemon").create_filter(
            flags, ctx, order_by=flags["order"])

        if aggregations is None:
            return

        # Filter pokemon

        do_emojis = (ctx.guild is None or ctx.guild.me.permissions_in(
            ctx.channel).external_emojis)

        def padn(p, idx, n):
            return " " * (len(str(n)) - len(str(idx))) + str(idx)

        num = await self.bot.mongo.fetch_auction_count(
            ctx.guild, aggregations=aggregations)

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 20
            pokemon = await self.bot.mongo.fetch_auction_list(
                ctx.guild, pgstart, 20, aggregations=aggregations)

            pokemon = [(
                self.bot.mongo.EmbeddedPokemon.build_from_mongo(x["pokemon"]),
                x["_id"],
                x["current_bid"],
                x["bid_increment"],
                x.get("bidder_id", None),
            ) for x in pokemon]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            maxn = max(idx for x, idx, price, _, bidder_id in pokemon)
            page = [
                f"`{padn(p, idx, maxn)}` **{p:li}** • {p.iv_percentage * 100:.2f}% • CB: {current_bid:,} pc • BI: {bid_interval:,} pc"
                if bidder_id is not None else
                f"`{padn(p, idx, maxn)}` **{p:li}** • {p.iv_percentage * 100:.2f}% • SB: {current_bid + bid_interval:,} pc"
                for p, idx, current_bid, bid_interval, bidder_id in pokemon
            ]

            # Send embed

            embed = self.bot.Embed(color=0xE67D23)
            embed.title = f"Auctions in {ctx.guild.name}"
            embed.description = "\n".join(page)[:2048]

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}. (Page {pidx+1} of {math.ceil(num / 20)})"
            )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags["page"] - 1)
Beispiel #16
0
    async def info(self, ctx: commands.Context, *,
                   pokemon: converters.Pokemon):
        """View a specific pokémon from your collection."""

        num = await self.bot.mongo.fetch_pokemon_count(ctx.author)

        if pokemon is None:
            return await ctx.send("Couldn't find that pokémon!")

        shift = 0

        async def get_page(pidx, clear, dir=0):
            nonlocal shift

            pokemon = await self.bot.mongo.fetch_pokemon(
                ctx.author, pidx + shift)
            while pokemon is None:
                shift += 1
                pokemon = await self.bot.mongo.fetch_pokemon(
                    ctx.author, pidx + shift)

            embed = self.bot.Embed(color=pokemon.color or 0xF44336)
            embed.title = f"{pokemon:lnf}"

            if pokemon.shiny:
                embed.set_image(url=pokemon.species.shiny_image_url)
            else:
                embed.set_image(url=pokemon.species.image_url)

            embed.set_thumbnail(url=ctx.author.avatar_url)

            info = (
                f"**XP:** {pokemon.xp}/{pokemon.max_xp}",
                f"**Nature:** {pokemon.nature}",
            )

            embed.add_field(name="Details",
                            value="\n".join(info),
                            inline=False)

            stats = (
                f"**HP:** {pokemon.hp} – IV: {pokemon.iv_hp}/31",
                f"**Attack:** {pokemon.atk} – IV: {pokemon.iv_atk}/31",
                f"**Defense:** {pokemon.defn} – IV: {pokemon.iv_defn}/31",
                f"**Sp. Atk:** {pokemon.satk} – IV: {pokemon.iv_satk}/31",
                f"**Sp. Def:** {pokemon.sdef} – IV: {pokemon.iv_sdef}/31",
                f"**Speed:** {pokemon.spd} – IV: {pokemon.iv_spd}/31",
                f"**Total IV:** {pokemon.iv_percentage * 100:.2f}%",
            )

            embed.add_field(name="Stats", value="\n".join(stats), inline=False)

            if pokemon.held_item:
                item = self.bot.data.item_by_number(pokemon.held_item)
                emote = ""
                if item.emote is not None:
                    emote = getattr(self.bot.sprites, item.emote) + " "
                embed.add_field(name="Held Item",
                                value=f"{emote}{item.name}",
                                inline=False)

            embed.set_footer(text=f"Displaying pokémon {pokemon.idx}.")

            return embed

        paginator = pagination.Paginator(get_page, num_pages=num)
        await paginator.send(self.bot, ctx, pokemon.idx)
Beispiel #17
0
    async def pokemon(self, ctx: commands.Context, **flags):
        """View or filter the pokémon in your collection."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        member = await self.bot.mongo.fetch_member_info(ctx.author)

        aggregations = await self.create_filter(flags,
                                                ctx,
                                                order_by=member.order_by)

        if aggregations is None:
            return

        # Filter pokemon

        do_emojis = (ctx.guild is None or ctx.guild.me.permissions_in(
            ctx.channel).external_emojis)

        fixed_pokemon = False

        def padn(p, n):
            return " " * (len(str(n)) - len(str(p.idx))) + str(p.idx)

        num = await self.bot.mongo.fetch_pokemon_count(
            ctx.author, aggregations=aggregations)

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 20
            pokemon = await self.bot.mongo.fetch_pokemon_list(
                ctx.author, pgstart, 20, aggregations=aggregations)

            pokemon = [
                self.bot.mongo.Pokemon.build_from_mongo(x["pokemon"])
                for x in pokemon
            ]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            maxn = max(x.idx for x in pokemon)

            page = [
                f"`{padn(p, maxn)}` **{p:nif}** • Lvl. {p.level} • {p.iv_percentage * 100:.2f}%"
                for p in pokemon
            ]

            # Send embed

            embed = self.bot.Embed(color=0xF44336)
            embed.title = f"Your pokémon"
            embed.description = "\n".join(page)[:2048]

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}. (Page {pidx+1} of {math.ceil(num / 20)})"
            )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags["page"] - 1)
Beispiel #18
0
    async def support(self, ctx: commands.Context, **flags):
        """Support Tickets Functions"""
        #print(flags)
        if 'answer' in flags and flags['answer'] and flags['close']:
            return await ctx.send("Can only do one at a time. `--answer` `--close`")
        elif 'answer' in flags and flags['answer']:
            # bot sends answer to user who sent the support ticket and closes it
            if 'id' not in flags and not flags['id']:
                return await ctx.send("Please indicate the id with the answer. `--id <id> --answer <message>`")
            answer = ' '.join(flags['answer'])
            cursor = self.bot.db.connection.cursor()
            cursor.execute("SELECT id, user_id, flags, message FROM support WHERE id = %s", flags['id'])
            out = cursor.fetchone()
            cursor.execute("DELETE FROM support where id = %s", flags['id'])
            self.bot.db.connection.commit()
            cursor.close()
            if out:
                embed = self.bot.Embed(color = 0x6CFF00)
                embed.title = f"Support Ticket Closed"
                embed.description = '\n'.join([
                    f"**ID:** {out[0]}",
                    f"**From user:** {'<@' + str(out[1]) + '>'}",
                    f"**Type:** {out[2]}",
                    f"**Message:** {out[3]}",
                    f"**Response:** {answer}"
                ])
                await ctx.send(embed = embed)
                # send dm
                member = self.bot.get_user(int(out[1]))
                if member:
                    return await member.send(embed = embed)
                else:
                    return await ctx.send("Closed ticket however user was not found. Bot is not in any server with the user!")
            else:
                return await ctx.send(f"No support ticket found with ID: {flags['id']}")
        elif 'id' in flags and flags['id'] and not flags['close']:
            cursor = self.bot.db.connection.cursor()
            cursor.execute("SELECT id, user_id, flags, message FROM support WHERE id = %s", flags['id'])
            out = cursor.fetchone()
            cursor.close()
            if out:
                embed = self.bot.Embed(color = 0x6CFF00)
                embed.title = f"Support Ticket"
                embed.description = f"**ID:** {out[0]}\n**Type:** {out[2]}\n**Message:** {out[3]}"
                return await ctx.send(embed = embed)
            else:
                return await ctx.send(f"No support ticket found with ID: {flags['id']}")
        elif flags['close'] and 'id' in flags and flags['id']:
            cursor = self.bot.db.connection.cursor()
            cursor.execute("DELETE FROM support where id = %s", flags['id'])
            self.bot.db.connection.commit()
            cursor.close()
            return await ctx.send(f"Support ID {flags['id']} closed")
        # list support tickets
        num = await self.bot.db.get_support_tickets(flags, count = True)
        if num == 0:
            return await ctx.send("No support tickets found")
        async def get_page(pidx, clear):
            pgstart = pidx * 20

            s_tickets = await self.bot.db.get_support_tickets(flags, pgstart, 20)

            if len(s_tickets) == 0:
                return await ctx.send('No tickets on this page')
            
            page = [
                f"`{s['id']}` | {s['flags']} | **{s['message'][:30]}**" 
                for s in s_tickets
            ]

            embed = self.bot.Embed(color = discord.Color.dark_teal())
            embed.title = "Support Tickets"
            embed.description = '\n'.join(page)[:2048] # limit in embed
            embed.set_footer(text = f"Page {pidx+1} of {math.ceil(num/20)}")
            return embed
        paginator = pagination.Paginator(get_page, num_pages = math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags['page'] - 1)
Beispiel #19
0
class Trading(commands.Cog):
    """For trading."""

    def __init__(self, bot: commands.Bot):
        self.bot = bot

        if not hasattr(self.bot, "trades"):
            self.bot.trades = {}

    @property
    def db(self) -> Database:
        return self.bot.get_cog("Database")

    async def send_trade(self, ctx: commands.Context, user: discord.Member):
        # TODO this code is pretty shit. although it does work

        trade = self.bot.trades[user.id]
        a, b = trade["items"].keys()

        done = False

        if trade[a] and trade[b]:
            done = True
            del self.bot.trades[a]
            del self.bot.trades[b]

        a = ctx.guild.get_member(a)
        b = ctx.guild.get_member(b)

        num_pages = max(math.ceil(len(x) / 20) for x in trade["items"].values())

        if done:
            execmsg = await ctx.send("Executing trade...")

        async def get_page(pidx, clear):
            embed = discord.Embed()
            embed.color = 0xF44336
            embed.title = f"Trade between {a.display_name} and {b.display_name}."

            if done:
                embed.title = (
                    f"✅ Completed trade between {a.display_name} and {b.display_name}."
                )

            embed.set_footer(
                text=f"Type `{ctx.prefix}trade add <number>` to add a pokémon, `{ctx.prefix}trade add <number> pc` to add Pokécoins, `{ctx.prefix}trade confirm` to confirm, or `{ctx.prefix}trade cancel` to cancel."
            )

            for i, fullside in trade["items"].items():
                mem = ctx.guild.get_member(i)

                side = fullside[pidx * 20 : (pidx + 1) * 20]

                if mem is None:
                    return await ctx.send("The trade has been canceled.")

                try:
                    maxn = max(x[1] + 1 for x in side if type(x) != int)
                except ValueError:
                    maxn = 0

                def padn(idx, n):
                    return " " * (len(str(n)) - len(str(idx))) + str(idx)

                def txt(x):
                    val = f"`{padn(x[1] + 1, maxn)}`⠀**{x[0].species}**"
                    if x[0].shiny:
                        val += " ✨"
                    val += f"⠀•⠀Lvl. {x[0].level}⠀•⠀{x[0].iv_percentage:.2%}"
                    return val

                val = "\n".join(
                    f"{x} Pokécoins" if type(x) == int else txt(x) for x in side
                )

                if val == "":
                    if len(fullside) == 0:
                        val = "None"
                    else:
                        val = "None on this page"

                sign = "🟢" if trade[i] else "🔴"

                embed.add_field(name=f"{sign} {mem.display_name}", value=val)

            embed.set_footer(text=f"Showing page {pidx + 1} out of {num_pages}.")

            return embed

        # Check if done

        embeds = []

        if done:
            bothsides = list(enumerate(trade["items"].items()))
            for idx, tup in bothsides:
                i, side = tup

                oidx, otup = bothsides[(idx + 1) % 2]
                oi, oside = otup

                mem = ctx.guild.get_member(i)
                omem = ctx.guild.get_member(oi)

                dec = 0

                member = await self.db.fetch_member_info(mem)
                omember = await self.db.fetch_member_info(omem)

                for x in side:
                    if type(x) == int:
                        await self.db.update_member(mem, {"$inc": {"balance": -x}})
                        await self.db.update_member(omem, {"$inc": {"balance": x}})
                    else:

                        pokemon, idx = x

                        if idx < member.selected:
                            dec += 1

                        if (
                            evo := pokemon.species.trade_evolution
                        ) and pokemon.held_item != 13001:
                            if (
                                evo.trigger.item is None
                                or evo.trigger.item.id == pokemon.held_item
                            ):
                                evo_embed = discord.Embed()
                                evo_embed.color = 0xF44336
                                evo_embed.title = f"Congratulations {omem.name}!"

                                name = str(pokemon.species)

                                if pokemon.nickname is not None:
                                    name += f' "{pokemon.nickname}"'

                                evo_embed.add_field(
                                    name=f"The {name} is evolving!",
                                    value=f"The {name} has turned into a {evo.target}!",
                                )

                                pokemon.species_id = evo.target.id

                                embeds.append(evo_embed)

                        await self.db.update_member(
                            mem, {"$unset": {f"pokemon.{idx}": 1}}
                        )

                        await self.db.update_member(
                            omem,
                            {
                                "$push": {
                                    "pokemon": {
                                        "species_id": pokemon.species.id,
                                        "level": pokemon.level,
                                        "xp": pokemon.xp,
                                        "nature": pokemon.nature,
                                        "iv_hp": pokemon.iv_hp,
                                        "iv_atk": pokemon.iv_atk,
                                        "iv_defn": pokemon.iv_defn,
                                        "iv_satk": pokemon.iv_satk,
                                        "iv_sdef": pokemon.iv_sdef,
                                        "iv_spd": pokemon.iv_spd,
                                        "shiny": pokemon.shiny,
                                        "held_item": pokemon.held_item,
                                    }
                                },
                            },
                        )

                await self.db.update_member(
                    mem, {"$inc": {f"selected": -dec}, "$pull": {"pokemon": None}},
                )

            await execmsg.delete()

        # Send msg

        paginator = pagination.Paginator(get_page, num_pages=num_pages)
        asyncio.create_task(paginator.send(self.bot, ctx, 0))

        for evo_embed in embeds:
            await ctx.send(embed=evo_embed)
Beispiel #20
0
    async def market(self, ctx: commands.Context, **flags):
        """View or filter the pokémon in your collection."""

        if flags["page"] < 1:
            return await ctx.send("Page must be positive!")

        member = await self.db.fetch_member_info(ctx.author)

        aggregations = await self.bot.get_cog("Pokemon").create_filter(
            flags, ctx)

        if aggregations is None:
            return

        # Filter pokemon

        fixed_pokemon = False

        async def fix_pokemon():
            # TODO This is janky way of removing bad database entries, I should fix this

            nonlocal fixed_pokemon

            if fixed_pokemon:
                return

            await self.db.update_member(
                ctx.author,
                {"$pull": {
                    f"pokemon": {
                        "species_id": {
                            "$exists": False
                        }
                    }
                }},
            )
            await self.db.update_member(ctx.author,
                                        {"$pull": {
                                            f"pokemon": None
                                        }})

            fixed_pokemon = True

        def nick(p):
            name = str(p.species)

            if p.shiny:
                name += " ✨"

            return name

        num = await self.db.fetch_market_count(aggregations=aggregations)

        if num == 0:
            return await ctx.send("Found no pokémon matching this search.")

        async def get_page(pidx, clear):

            pgstart = pidx * 20
            pokemon = await self.db.fetch_market_list(
                pgstart, 20, aggregations=aggregations)

            pokemon = [(mongo.Pokemon.build_from_mongo(x["pokemon"]), x["_id"],
                        x["price"]) for x in pokemon]

            if len(pokemon) == 0:
                return await clear("There are no pokémon on this page!")

            page = [
                f"`{id}` **L{p.level} {nick(p)}** • {p.iv_percentage:.2%} • **{price:,} pc**"
                for p, id, price in pokemon
            ]

            # Send embed

            embed = discord.Embed()
            embed.color = 0xF44336
            embed.title = f"Market"
            embed.description = "\n".join(page)[:2048]

            embed.set_footer(
                text=
                f"Showing {pgstart + 1}–{min(pgstart + 20, num)} out of {num}."
            )

            return embed

        paginator = pagination.Paginator(get_page,
                                         num_pages=math.ceil(num / 20))
        await paginator.send(self.bot, ctx, flags["page"] - 1)