Beispiel #1
0
    async def _twoslot_pob(self, equip, item_type):
        embed = Embed(color=self.bot.user_color)
        ##print(equip)
        try:
            if f'{item_type} 1' in equip and f'{item_type} 2' in equip:
                rwp1 = utils.ItemRender(
                    equip[f'{item_type} 1']['object'].rarity)
                wp1 = rwp1.render(equip[f'{item_type} 1']['object'])
                rwp2 = utils.ItemRender(
                    equip[f'{item_type} 2']['object'].rarity)
                wp2 = rwp2.render(equip[f'{item_type} 2']['object'])
                box = list(wp1.size)
                if wp2.size[1] > box[1]:
                    box[1] = wp2.size[1]
                box[0] = box[0] + wp2.size[0] + 2
                img = Image.new('RGBA', box, color='black')
                img.paste(wp1.convert('RGBA'), box=(0, 0))
                img.paste(wp2.convert('RGBA'), box=(wp1.size[0] + 2, 0))

            else:
                wp_n = f'{item_type} 1' if f'{item_type} 1' in equip else f'{item_type} 2'
                rwp = utils.ItemRender(equip[wp_n]['object'].rarity)
                img = rwp.render(equip[wp_n]['object'])

            image_fp = BytesIO()
            img.save(image_fp, 'png')
            image_fp.seek(0)
            file = File(image_fp, filename=f'{item_type.lower()}.png')

            slot_list = []
            if f'{item_type} 1' in equip and 'gems' in equip[f'{item_type} 1']:
                slot_list.append(f'{item_type} 1')

            if f'{item_type} 2' in equip and 'gems' in equip[f'{item_type} 2']:
                slot_list.append(f'{item_type} 2')

            for slot in slot_list:
                val_list = []
                for gem in equip[slot]['gems']:
                    val_list.append(
                        f" ㆍ {gem['level']}/{gem['quality']} {gem['name']}")
                embed.add_field(name=f"{slot} Gems",
                                value='\n'.join(val_list),
                                inline=True)

            return {'file': file, 'embed': embed}
        except KeyError:
            return None
Beispiel #2
0
 async def _oneslot_pob(self, equip, itemtype):
     embed = Embed(color=self.bot.user_color)
     if itemtype in equip:
         wp_n = itemtype
         rwp = utils.ItemRender(equip[wp_n]['object'].rarity)
         img = rwp.render(equip[wp_n]['object'])
         image_fp = BytesIO()
         img.save(image_fp, 'png')
         #print(image_fp.tell())
         image_fp.seek(0)
         file = File(image_fp,
                     filename=f"{itemtype.lower().replace(' ','')}.png")
         # upload = await self.bot.dump_channel.send(file=file)
         # embed.set_image(url=upload.attachments[0].url)
         #print(equip[wp_n])
         if 'gems' in equip[wp_n] and equip[wp_n]['gems']:
             val_list = []
             for gem in equip[wp_n]['gems']:
                 val_list.append(
                     f" - {gem['level']}/{gem['quality']} {gem['name']}")
             value = '\n'.join(val_list)
             embed.add_field(name=f"{wp_n} Gems", value=value, inline=True)
         return {'file': file, 'embed': embed}
     else:
         return None
Beispiel #3
0
    async def _twoslot_pob(self, equip, itemtype):
        embed = Embed(color=self.bot.user_color)
        if f'{itemtype} 1' in equip or f'{itemtype} 2' in equip:
            if f'{itemtype} 1' in equip and f'{itemtype} 2' in equip:
                rwp1 = utils.ItemRender(
                    equip[f'{itemtype} 1']['object'].rarity)
                wp1 = rwp1.render(equip[f'{itemtype} 1']['object'])
                rwp2 = utils.ItemRender(
                    equip[f'{itemtype} 2']['object'].rarity)
                wp2 = rwp2.render(equip[f'{itemtype} 2']['object'])
                box = list(wp1.size)
                if wp2.size[1] > box[1]:
                    box[1] = wp2.size[1]
                box[0] = box[0] + wp2.size[0] + 2
                img = Image.new('RGBA', box, color='black')
                img.paste(wp1.convert('RGBA'), box=(0, 0))
                img.paste(wp2.convert('RGBA'), box=(wp1.size[0] + 2, 0))
            else:
                wp_n = f'{itemtype} 1' if f'{itemtype} 1' in equip else f'{itemtype} 2'
                rwp = utils.ItemRender(equip[wp_n]['object'].rarity)
                img = rwp.render(equip[wp_n]['object'])
            image_fp = BytesIO()
            img.save(image_fp, 'png')
            #img.show()
            #print(image_fp.tell())
            image_fp.seek(0)
            file = File(image_fp, filename=f'{itemtype.lower()}.png')
            # upload = await self.bot.dump_channel.send(file=file)
            # embed.set_image(url=upload.attachments[0].url)

            slot_list = []
            if f'{itemtype} 1' in equip and 'gems' in equip[f'{itemtype} 1']:
                slot_list.append(f'{itemtype} 1')
            if f'{itemtype} 2' in equip and 'gems' in equip[f'{itemtype} 2']:
                slot_list.append(f'{itemtype} 2')
            for slot in slot_list:
                val_list = []
                for gem in equip[slot]['gems']:
                    val_list.append(
                        f" - {gem['level']}/{gem['quality']} {gem['name']}")
                value = '\n'.join(val_list)
                embed.add_field(name=f"{slot} Gems", value=value, inline=True)
            return {'file': file, 'embed': embed}
        else:
            return None
Beispiel #4
0
 async def link(self, ctx):
     """ Link items decorated with [[]] in chat """
     item_matches = self.re.findall(ctx.message.content)
     if not item_matches:
         return
     tasks = []
     print(item_matches)
     for item in item_matches[:5]:
         tasks.append(self.bot.loop.run_in_executor(None,
                                                    find_one, item.strip('[[').strip(']]'),
                                                    self.client, self.bot.loop))
     results = await asyncio.gather(*tasks)
     results = [x for x in results if x]
     images = []
     for result in results:
         if result.base == "Prophecy":
             flavor = 'prophecy'
         elif 'gem' in result.tags:
             flavor = 'gem'
             print(result.vendors)
         else:
             flavor = result.rarity
         r = utils.ItemRender(flavor)
         images.append(r.render(result))
     if len(images) > 1:
         box = [0, 0]
         for image in images:
             box[0] = box[0] + image.size[0]
             if image.size[1] > box[1]:
                 box[1] = image.size[1]
         box[0] = box[0] + (2*len(images))
         img = Image.new('RGBA', box, color='black')
         #img.show()
         paste_coords = [0, 0]
         for image in images:
             #image.show()
             img.paste(image.convert('RGBA'), box=paste_coords[:])
             paste_coords[0] = paste_coords[0] + image.size[0] + 2
     else:
         img = images[0]
     image_fp = BytesIO()
     img.save(image_fp, 'png')
     image_fp.seek(0)
     print("Image ready")
     await ctx.channel.send(file=File(image_fp, filename='image.png'))
Beispiel #5
0
    async def convert(self, ctx):
        """ Convert an item copied from PoB or PoETradeMacro to the Zana version """

        # Put my PoB item parser to good use
        try:
            pob_item = utils.parse_pob_item(ctx.message.content)
        except:
            print(ctx.message.content)
            return
        d = {}
        print(pob_item)
        await self.bot.loop.run_in_executor(None, utils._get_wiki_base,
                                            pob_item, d, self.client,
                                            "Chat Item")
        #print(d)
        #print(d['Chat Item'].energy_shield)
        #utils.modify_base_stats(d['Chat Item'])
        #print(d['Chat Item'].energy_shield)
        renderer = utils.ItemRender(d['Chat Item'].rarity)
        img = renderer.render(d['Chat Item'])
        image_fp = BytesIO()
        img.save(image_fp, 'png')
        image_fp.seek(0)
        file = File(image_fp, filename=f"converted.png")
        upload = await self.bot.dump_channel.send(file=file)
        em = Embed()
        em.set_author(name=f"{ctx.author.name}#{ctx.author.discriminator}",
                      icon_url=ctx.author.avatar_url)
        em.set_image(url=upload.attachments[0].url)
        try:
            await ctx.send(embed=em)
        except:
            try:
                await ctx.send(
                    f"**{ctx.author.name}#{ctx.author.discriminator}**:\n",
                    file=file)
            except:
                await ctx.error("`Attach Files` permission required",
                                delete_after=2)
Beispiel #6
0
    async def _oneslot_pob(self, equip, item_type):
        embed = Embed(color=self.bot.user_color)
        try:
            wp_n = item_type
            ##print(equip[wp_n], wp_n)
            rwp = utils.ItemRender(equip[wp_n]['object'].rarity)
            img = rwp.render(equip[wp_n]['object'])
            image_fp = BytesIO()
            img.save(image_fp, 'png')
            image_fp.seek(0)
            file = File(image_fp,
                        filename=f"{item_type.lower().replace(' ', '')}.png")

            if 'gems' in equip[wp_n] and equip[wp_n]['gems']:
                val_list = []
                for gem in equip[wp_n]['gems']:
                    val_list.append(
                        f" ㆍ {gem['level']}/{gem['quality']} {gem['name']}")
                value = '\n'.join(val_list)
                embed.add_field(name=f"{wp_n} Gems", value=value, inline=True)

            return {'file': file, 'embed': embed}
        except KeyError:
            return None
Beispiel #7
0
    async def poe(self, ctx, *, item: str):
        """Search for and post a POE <item> image"""
        item = Client().find_items({'_pageName': f'%{item}%'}, limit=1)
        if not item:
            return

        result = item[0]
        if result.base == "Prophecy":
            flavor = 'prophecy'
        elif 'gem' in result.tags:
            flavor = 'gem'
            # do some meta stufff here maybe?
        elif 'divination_card' in result.tags:
            flavor = 'unique'
            # possibly needs more here
        else:
            flavor = result.rarity
        r = poeutils.ItemRender(flavor)
        image = r.render(result)
        image_fp = BytesIO()
        image.save(image_fp, 'png')
        image_fp.seek(0)

        await ctx.send(file=discord.File(image_fp, result.name + ".png"))
Beispiel #8
0
    async def roll(self, ctx, *, item: str = None):
        """ 'Divine' any Unique item and test your luck! """
        if not item:
            return await ctx.error(
                "The correct format to use `roll` is\n`@Zana roll <itemname>`")
        unique = await self.bot.loop.run_in_executor(None, find_one, item,
                                                     self.client)
        unique = copy.copy(unique)
        if not unique:
            return await ctx.error(f"Couldn't find {item} on the wiki!")
        if unique.rarity.lower() != 'unique':
            return await ctx.error("You can only roll unique items!")
        base = await self.bot.loop.run_in_executor(None, find_one, unique.base,
                                                   self.client)
        base = copy.copy(base)
        implicits = utils.unescape_to_list(unique.implicits)
        explicits = utils.unescape_to_list(unique.explicits)
        decided_implicits = []
        decided_explicits = []
        for implicit in implicits:
            if '(' in implicit and ')' in implicit and 'hidden' not in implicit.lower(
            ):
                matches = self.pr_re.findall(implicit)
                match_dict = {}
                for match in matches:
                    stat = match[1:-1]
                    separator = stat.find('-', 1)
                    range_start = stat[:separator]
                    range_end = stat[separator + 1:]
                    if '.' in range_start or '.' in range_end:
                        randomized_stat = random.uniform(
                            float(range_start), float(range_end))
                    else:
                        randomized_stat = random.randint(
                            int(range_start), int(range_end))
                    if randomized_stat == 0:
                        continue
                    match_dict[match] = randomized_stat
                    new_impl = implicit

                for rep in match_dict:
                    new_impl = new_impl.replace(rep, str(match_dict[rep]))
                    if match_dict[rep] < 0:
                        new_impl = new_impl.replace('+', '')
                        new_impl = new_impl.replace('increased', 'reduced')

                if match_dict:
                    decided_implicits.append(new_impl)
            else:
                decided_implicits.append(implicit)

        for explicit in explicits:
            if '(' in explicit and ')' in explicit and 'hidden' not in explicit.lower(
            ):
                matches = self.pr_re.findall(explicit)
                match_dict = {}
                for match in matches:
                    stat = match[1:-1]
                    separator = stat.find('-', 1)
                    range_start = stat[:separator]
                    range_end = stat[separator + 1:]
                    if '.' in range_start or '.' in range_end:
                        randomized_stat = random.uniform(
                            float(range_start), float(range_end))
                    else:
                        randomized_stat = random.randint(
                            int(range_start), int(range_end))
                    if randomized_stat == 0:
                        continue
                    match_dict[match] = randomized_stat
                new_expl = explicit
                for rep in match_dict:
                    new_expl = new_expl.replace(rep, str(match_dict[rep]))
                    if match_dict[rep] < 0:
                        new_expl = new_expl.replace('+', '')
                        new_expl = new_expl.replace('increased', 'reduced')
                if match_dict:
                    decided_explicits.append(new_expl)
            else:
                decided_explicits.append(explicit)
        escaped_implicits = '<br>'.join(decided_implicits)
        escaped_explicits = '<br>'.join(decided_explicits)
        base.implicits = escaped_implicits
        unique.implicits = escaped_implicits
        base.explicits = escaped_explicits
        unique.explicits = escaped_explicits
        try:
            utils.modify_base_stats(base)
            if 'weapon' in unique.tags:
                unique.attack_speed = base.attack_speed
                unique.critical_chance = base.critical_chance
                unique.range = base.range
                unique.fire_min = base.fire_min
                unique.fire_max = base.fire_max
                unique.cold_min = base.cold_min
                unique.cold_max = base.cold_max
                unique.lightning_min = base.lightning_min
                unique.lightning_max = base.lightning_max
                unique.chaos_min = base.chaos_min
                unique.chaos_max = base.chaos_max
                unique.physical_min = base.physical_min
                unique.physical_max = base.physical_max
            else:
                unique.armour = base.armour
                unique.evasion = base.evasion
                unique.energy_shield = base.energy_shield

        except Exception:
            pass
        renderer = utils.ItemRender('unique')
        img = renderer.render(unique)
        image_fp = BytesIO()
        img.save(image_fp, 'png')
        image_fp.seek(0)
        try:
            f = File(image_fp, filename=f'image{round(time.time())}.png')
            await ctx.channel.send(file=f)
        except Exception:
            await ctx.error("`Attach Files` permission required")
Beispiel #9
0
    async def convert(self, ctx):
        """ Convert an item copied from PoB or PoETradeMacro to the Zana version. """

        # Put my PoB item parser to good use
        try:
            pob_item = utils.parse_pob_item(ctx.message.content)
        except:
            return
        d = {}
        await self.bot.loop.run_in_executor(None, utils._get_wiki_base,
                                            pob_item, d, self.client,
                                            "Chat Item")
        renderer = utils.ItemRender(d['Chat Item'].rarity)
        img = renderer.render(d['Chat Item'])
        image_fp = BytesIO()
        img.save(image_fp, 'png')
        image_fp.seek(0)
        file = File(image_fp, filename=f"converted.png")
        upload = await self.bot.dump_channel.send(file=file)
        embed = Embed(
            description="*Click the reaction below for raw item text.*")
        embed.set_author(name=f"{ctx.author.name}#{ctx.author.discriminator}",
                         icon_url=ctx.author.avatar_url)
        embed.set_image(url=upload.attachments[0].url)
        embed.set_footer(
            text=
            "Don't want your items converted? An admin can disable it using @Zana disable_conversion."
        )
        try:
            embed_msg = await ctx.send(embed=embed)
            embed_id = embed_msg.id
            try:
                await ctx.message.delete()
            except Exception:
                #Funny thing is, error is an embed, if someone removes that perm,
                #the error doesn't go through as well
                await ctx.error("`Manage Messages` required to delete",
                                delete_after=2)
            env_emoji = '📩'
            try:
                await embed_msg.add_reaction(env_emoji)
            except Exception:
                return

            def check(_payload):
                try:
                    check_one = _payload.emoji == env_emoji
                    check_two = _payload.message_id == embed_id
                    check_thr = _payload.user_id != self.bot.user.id
                    return all([check_one, check_two, check_thr])
                except Exception:
                    return False

            while True:
                payload = await self.bot.wait_for('raw_reaction_add',
                                                  check=check)
                try:
                    await embed_msg.remove_reaction(payload)
                except Exception:
                    pass

                try:
                    await user.send(f"```\n{ctx.message.content}\n```")
                except Exception:
                    pass
        except Exception:
            try:
                await ctx.send(
                    f"**{ctx.author.name}#{ctx.author.discriminator}**:\n",
                    file=file)
            except Exception:
                await ctx.error("`Attach Files` permission required",
                                delete_after=2)
            else:
                try:
                    await ctx.message.delete()
                except Exception:
                    await ctx.error("`Manage Messages` required to delete",
                                    delete_after=2)
Beispiel #10
0
    async def link(self, ctx):
        """ Link items decorated with [[]] in chat. """
        item_matches = self.br_re.findall(ctx.message.content)
        if not item_matches:
            return
        tasks = []

        # Because my poe lib is actually completely blocking, i wrote a find_once func and
        # I just run instances of find_one in executor + gather

        ##print(item_matches)
        for item in item_matches[:5]:
            tasks.append(
                self.bot.loop.run_in_executor(None, find_one,
                                              item.strip('[[]]'), self.client))

        results = await self._item_search(ctx, item_matches[:5])
        print(results)

        images = []
        meta = []

        ##print(results)

        for result in results:
            if isinstance(result, dict):
                matches = result.get('matches')
                if matches and len(matches) < 2:
                    ctx.message.content = f"[[{matches[0][0]}]]"
                    self.bot.loop.create_task(self.link.invoke(ctx))
                else:
                    continue

            # TODO: clarify this statement
            if not isinstance(result, PassiveSkill):
                if result.base == "Prophecy":
                    flavor = 'prophecy'
                elif 'gem' in result.tags:
                    flavor = 'gem'
                    dt = {'name': f"{result.name} vendors"}
                    ven_str = ""
                    for vendor in result.vendors:
                        classes = "Available to all classes" if vendor[
                            'classes'] == '' else vendor['classes']
                        siosa = True if vendor['act'] == '3' and vendor[
                            'classes'] == '' else False
                        ven_info = self.vendor_info[vendor[
                            'act']] if not siosa else self.vendor_info['Siosa']
                        ven_str += f"**Act {vendor['act']}** ㆍ {classes} ㆍ {ven_info}\n"
                    dt['value'] = ven_str
                    meta.append(dt)

                elif 'divination_card' in result.tags:
                    # Lib has a different render function for div cards as they don't fit the standard stats and sorting
                    # method, might change in the future but would be extremely unneat code-wise.
                    r = utils.ItemRender('unique')
                    images.append(r.render_divcard(result))
                    try:
                        reward = await self.bot.loop.run_in_executor(
                            None, find_one, result.reward, self.client)

                        if reward.base == "Prophecy":
                            i_render = utils.ItemRender('prophecy')
                            images.append(i_render.render(reward))
                        elif 'gem' in reward.tags:
                            i_render = utils.ItemRender('gem')
                            images.append(i_render.render(reward))
                        elif 'divination_card' in reward.tags:
                            i_render = utils.ItemRender('unique')
                            images.append(i_render.render_divcard(reward))
                        else:
                            i_render = utils.ItemRender(reward.rarity)
                            images.append(i_render.render(reward))
                    except Exception:
                        pass

                    if result.drop.areas:
                        txt = '\n'.join([
                            f'\u2022 {x}' for x in result.drop.areas.split(',')
                        ])
                        if len(txt) <= 1024:
                            meta.append({
                                'name': f"{result.name} Drop Locations",
                                'value': txt
                            })
                        else:
                            loc_list = result.drop.areas.split(',')
                            txt = '\n'.join([
                                f'\u2022 {x}'
                                for x in loc_list[:(len(loc_list) // 2) - 1]
                            ])
                            txt += f"\n[...More](http://poewiki.net/wiki/{quote_plus(result.name).replace('+', '%20')})"
                            meta.append({
                                'name': f"{result.name} Drop Locations",
                                'value': txt
                            })
                    continue
                else:
                    flavor = result.rarity
            else:
                flavor = 'normal'

            if 'divination_card' not in result.tags:
                r = utils.ItemRender(flavor)
                images.append(r.render(result))

        results = [x for x in results if not isinstance(x, dict)]
        ##print(results[0].implicits)
        ##print(results[0].explicits)

        # Stitch images together, traditionally 5 images tops, but as div cards can feature their reward as an image
        # Possible max images can be 10
        # R.I.P that one time where we stitched headhunters for image width of 69700
        if len(results) < 2 and isinstance(results[0], dict):
            return

        if len(images) > 1:
            box = [0, 0]
            for image in images:
                box[0] = box[0] + image.size[0]
                if image.size[1] > box[1]:
                    box[1] = image.size[1]
            box[0] = box[0] + (2 * len(images))
            img = Image.new('RGBA', box, color='black')
            paste_coords = [0, 0]

            for image in images:
                img.paste(image.convert('RGBA'), box=paste_coords[:])
                paste_coords[0] = paste_coords[0] + image.size[0] + 2

        else:
            img = images[0]
        image_fp = BytesIO()
        img.save(image_fp, 'png')
        image_fp.seek(0)

        embed = Embed(color=self.bot.user_color)
        links = []
        for item in results:
            links.append(
                f"\u2022 [{item.name}](http://poewiki.net/wiki/{quote_plus(item.name).replace('+', '%20')})"
            )
        embed.add_field(name="Wiki Links", value='\n'.join(links))
        embed.set_image(url="attachment://image.png")

        # Meta is basically only used for gems to show vendor info, might add more stuff later, good base to build on
        if meta:
            for m in meta:
                embed.add_field(name=m['name'],
                                value=m['value'] or "None",
                                inline=True)

        try:
            await ctx.channel.send(file=File(image_fp, filename='image.png'),
                                   embed=embed)
        except Exception:
            await ctx.error("`Attach Files` permission required",
                            delete_after=2)
Beispiel #11
0
    async def buy(self, ctx, *, item_plus_league: str = None):
        """ List the 3 lowest priced items with whisper and price info. """
        verified_item, league = await self._search_api(ctx, item_plus_league)
        if isinstance(verified_item, dict):
            price = utils.item_price(verified_item['matches'][0][0], league)
            iname = verified_item['matches'][0][0]
        else:
            price = utils.item_price(verified_item.name, league)
            iname = verified_item.name
        lowest = price.lowest()
        tasks = []
        for item in lowest:
            tasks.append(
                self.bot.loop.run_in_executor(None, utils.parse_poe_char_api,
                                              {'items': [item['item']]},
                                              self.client, True))
        results = await asyncio.gather(*tasks)
        files = {'files': [], 'indexes': []}
        sockets = {'sockets': [], 'indexes': []}
        for ind, item in enumerate(results):
            if not item['equipped']['items_objects']:
                continue
            if 'sockets' in lowest[ind]['item'] and lowest[ind]['item'][
                    'sockets']:
                socks = {}
                for sock in lowest[ind]['item']['sockets']:
                    if not sock['group'] in socks:
                        socks[sock['group']] = []
                    socks[sock['group']].append(sock['sColour'])
                sock_strs = []
                for val in socks.values():
                    sock_strs.append('-'.join(val))
                sockets['sockets'].append('\n'.join(sock_strs))
                sockets['indexes'].append(ind)
            result = item['equipped']['items_objects']
            if not isinstance(result, PassiveSkill):
                if result.base == "Prophecy":
                    flavor = 'prophecy'
                elif 'gem' in result.tags:
                    flavor = 'gem'
                elif 'divination_card' in result.tags:
                    # Lib has a different render function for div cards as they don't fit the standard stats and sorting
                    # method, might change in the future but would be extremely unneat code-wise.
                    r = utils.ItemRender('unique')
                    img = r.render_divcard(result)
                else:
                    flavor = result.rarity
            else:
                flavor = 'normal'
            if 'divination_card' not in result.tags:
                r = utils.ItemRender(flavor)
                img = r.render(result)
            image_fp = BytesIO()
            img.save(image_fp, 'png')
            image_fp.seek(0)
            files['files'].append(
                File(
                    image_fp,
                    filename=f"{result.name.lower().replace(' ', '')}{ind}.png"
                ))
            files['indexes'].append(ind)

        if files:
            upload = await self.bot.dump_channel.send(files=files['files'])
            upload.attachments.reverse()
        else:
            upload = None
        embed_dict = dict.fromkeys(self.reaction_emojis[:-1])
        price = ', '.join([
            f"*{entry['listing']['price']['amount']} "
            f"{entry['listing']['price']['currency']}*" for entry in lowest
        ])
        sockets['sockets'].reverse()
        for ind, react in enumerate(embed_dict):
            embed = Embed(title=f"Lowest 3 Listings for {iname}",
                          description=f"Prices: {price}",
                          color=self.bot.user_color)
            try:
                if ind in files['indexes']:
                    embed.set_image(url=upload.attachments.pop().url)
            except (IndexError, AttributeError):
                pass

            embed.add_field(
                name="Price",
                value=f"{lowest[ind]['listing']['price']['amount']} "
                f"{lowest[ind]['listing']['price']['currency']}")
            if ind in sockets['indexes']:
                embed.add_field(name="Sockets", value=sockets['sockets'].pop())
            embed.add_field(name="Whisper",
                            value=f"`{lowest[ind]['listing']['whisper']}`")
            embed_dict[react] = embed

        await responsive_embed(self.bot,
                               embed_dict,
                               ctx,
                               timeout=60 * 5,
                               use_dict_emojis=True)
Beispiel #12
0
    async def link(self, ctx):
        """ Link items decorated with [[]] in chat """
        item_matches = self.re.findall(ctx.message.content)
        if not item_matches:
            return
        tasks = []
        print(item_matches)

        # Because my poe lib is actually completely blocking, i wrote a find_once func and
        # I just run instances of find_ones in executor + gather
        for item in item_matches[:5]:
            tasks.append(
                self.bot.loop.run_in_executor(
                    None, find_one, f"{item.strip('[[').strip(']]')}",
                    self.client, self.bot.loop))
        results = await asyncio.gather(*tasks)

        # Results are returned as None for invalid items from find_one, so remove None-s
        results = [x for x in results if x]

        new_selections = []
        for result in results:
            if isinstance(result, dict):
                if len(result['matches']) and len(result['matches']) > 2:
                    em = Embed(
                        title="Item not found",
                        description=
                        f"""Couldn't find anything for *"{result['name']}"*, did you mean:\n """
                        + "\n".join(f'\u2022 *{x[0]}*'
                                    for x in result['matches']))
                    msg = await ctx.channel.send(embed=em)

                    def check(reaction, user):
                        try:
                            return reaction.emoji in self.reaction_emojis \
                                   and reaction.message.id == msg.id \
                                   and user.id != self.bot.user.id
                        except:
                            return False

                    for emoji in self.reaction_emojis:
                        await msg.add_reaction(emoji)
                    try:
                        reaction, user = await self.bot.wait_for(
                            'reaction_add', check=check, timeout=20)
                    except asyncio.TimeoutError:
                        return await msg.delete()
                    if reaction.emoji == self.reaction_emojis[-1]:
                        return await msg.delete()
                    new_selections.append(
                        result['matches'][self.reaction_emojis.index(
                            reaction.emoji)][0])
                    await msg.delete()
        tasks = []
        print(new_selections)
        for new in new_selections:
            tasks.append(
                self.bot.loop.run_in_executor(None, find_one, new, self.client,
                                              self.bot.loop))
        new_results = await asyncio.gather(*tasks)

        results.extend(new_results)

        images = []
        meta = []

        print(results)

        for result in results:
            if isinstance(result, dict):
                if len(result['matches']) and len(result['matches']) < 2:
                    ctx.message.content = f"[[{result['matches'][0][0]}]]"
                    self.bot.loop.create_task(self.link.invoke(ctx))
                else:
                    continue
            if not isinstance(result, PassiveSkill):
                if result.base == "Prophecy":
                    flavor = 'prophecy'
                elif 'gem' in result.tags:
                    flavor = 'gem'
                    print(result.vendors)
                    dt = {'name': f"{result.name} vendors"}
                    venstr = ""
                    for vendor in result.vendors:
                        classes = "Available to all classes" if vendor[
                            'classes'] == '' else vendor['classes']
                        siosa = True if vendor['act'] == '3' and vendor[
                            'classes'] == '' else False
                        venstr += f"**Act {vendor['act']}** - {classes} - " \
                                  f"{self.vendor_info[vendor['act']] if not siosa else self.vendor_info['Siosa']}\n"
                    dt['value'] = venstr
                    meta.append(dt)
                elif 'divination_card' in result.tags:
                    # Lib has a different render function for div cards as they don't fit the standard stats and sorting
                    # method, might change in the future but would be extremely unneat code-wise.
                    r = utils.ItemRender('unique')
                    images.append(r.render_divcard(result))
                    try:
                        reward = await self.bot.loop.run_in_executor(
                            None, find_one, result.reward, self.client,
                            self.bot.loop)
                        if reward.base == "Prophecy":
                            i_render = utils.ItemRender('prophecy')
                            images.append(i_render.render(reward))
                        elif 'gem' in reward.tags:
                            i_render = utils.ItemRender('gem')
                            images.append(i_render.render(reward))
                        elif 'divination_card' in reward.tags:
                            i_render = utils.ItemRender('unique')
                            images.append(i_render.render_divcard(reward))
                        else:
                            i_render = utils.ItemRender(reward.rarity)
                            images.append(i_render.render(reward))
                    except:
                        pass
                    if result.drop.areas:
                        meta.append({
                            'name':
                            f"{result.name} Drop Locations",
                            'value':
                            '\n'.join([
                                f'\u2022 {x}'
                                for x in result.drop.areas.split(',')
                            ])
                        })

                    continue
                else:
                    flavor = result.rarity
            else:
                flavor = 'normal'
            if 'divination_card' not in result.tags:
                r = utils.ItemRender(flavor)
                images.append(r.render(result))

        results = [x for x in results if not isinstance(x, dict)]

        # Stitch images together, traditionally 5 images tops, but as div cards can feature their reward as an image
        # Possible max images can be 10
        # R.I.P that one time where we stitched headhunters for image width of 69700
        if len(results) < 2 and isinstance(results[0], dict):
            return
        if len(images) > 1:
            box = [0, 0]
            for image in images:
                box[0] = box[0] + image.size[0]
                if image.size[1] > box[1]:
                    box[1] = image.size[1]
            box[0] = box[0] + (2 * len(images))
            img = Image.new('RGBA', box, color='black')
            #img.show()
            paste_coords = [0, 0]
            for image in images:
                #image.show()
                img.paste(image.convert('RGBA'), box=paste_coords[:])
                paste_coords[0] = paste_coords[0] + image.size[0] + 2
        else:
            img = images[0]
        image_fp = BytesIO()
        img.save(image_fp, 'png')
        image_fp.seek(0)
        print("Image ready")

        em = Embed(color=self.bot.user_color)
        links = []
        for item in results:
            links.append(
                f"\u2022 [{item.name}](http://pathofexile.gamepedia.com/{quote_plus(item.name).replace('+','%20')})"
            )
        em.add_field(name="Wiki Links", value='\n'.join(links))
        em.set_image(url="attachment://image.png")
        # Meta basically only used for gems to show vendor info, might add more stuff later, good base to build on
        if meta:
            for m in meta:
                em.add_field(name=m['name'],
                             value=m['value'] or "None",
                             inline=True)
        try:
            await ctx.channel.send(file=File(image_fp, filename='image.png'),
                                   embed=em)
        except:
            await ctx.error("`Attach Files` permission required",
                            delete_after=2)