Beispiel #1
0
    async def prices(self, ctx, *, item_i=None):
        """
        Gets the price of an item and its history
        Example usage: .p t6.1 hunter hood or .price t4  hide
        :param ctx:
        :param item_i:
        :return:
        """
        try:
            log.info(f"{ctx.message.content}")
        except TypeError:
            pass
        if item_i is None:
            await ctx.send(
                "Please enter an object to be searched:\n e.g  ```.p t6.1 hunter hood\n.price t4 hide ```"
            )
            return
        start_measuring_time = time()
        item = Item(self, ctx, item=item_i)
        async with ctx.channel.typing():
            item.get_matches()
            await item.get_data()
            if item.matched is None:
                raise ItemNotFound(ctx)
            thumb_url = f"https://render.albiononline.com/v1/item/{item.matched}.png?count=1&quality=1"
            log.info(f"{item.matched}, {item.name}, ...matched...")
            try:
                current_prices = await c_price_table(item.current_prices)
            except json.decoder.JSONDecodeError:
                embed = Embed(color=0xFF0000)
                embed.set_thumbnail(
                    url="http://clipart-library.com/images/kTMK4787c.jpg")
                embed.add_field(
                    name="No Information Sent to Albie Bot",
                    value=
                    "Looks like the Albion-Data Project didn't send anything to Poor Albie Bot,\
                         They might be under heavy load. Try searching again,\
                         if this error persists drop me discord message.",
                    inline=False,
                )
                await ctx.send(embed=embed)

            current_buffer = await create_sell_buy_order(current_prices)

            # Historical Data
            try:
                history_buffer, h_data = await full_graph(item.price_history)
            except json.decoder.JSONDecodeError:
                embed = Embed(color=0xFF0000)
                embed.set_thumbnail(
                    url="http://clipart-library.com/images/kTMK4787c.jpg")
                embed.add_field(
                    name="No Information Sent to Albie Bot",
                    value=
                    "Looks like the Albion-Data Project didnt send anything to Poor Albie Bot,\
                         They might be under heavy load.\
                         Try seaching again, if this error persists drop me discord message.",
                    inline=False,
                )
                await ctx.send(embed=embed)

            # Get avg_stats
            average_sell_price, avg_sell_volume, best_city_to_sell = get_avg_stats(
                h_data)

            best_cs_str = (
                f"{best_city_to_sell[0]} ({c_game_currency(best_city_to_sell[1])})"
            )

            # Start embed object
            title = f"{item.name} (Enchant:{item.enchant})\n"
            buyorder_embed = Embed(
                color=0x98FB98,
                title=title,
                url=f"https://www.albiononline2d.com/en/item/id/{item.matched}",
            )
            buyorder_embed.set_thumbnail(url=thumb_url)

            # Current Data
            avg_s_current_price, avg_b_current_price, normalcheck_s, normalcheck_b = get_current_average_s(
                current_prices)
            if avg_s_current_price is not None:
                avg_s_cp = c_game_currency(avg_s_current_price)
                buyorder_embed.add_field(
                    name=f"Avg Current Sell Price ({normalcheck_s[0]})",
                    value=avg_s_cp,
                    inline=True,
                )
            if avg_b_current_price is not None:
                avg_b_cp = c_game_currency(avg_b_current_price)
                buyorder_embed.add_field(
                    name=f"Avg Current Buy Price ({normalcheck_b[0]})",
                    value=avg_b_cp,
                    inline=True,
                )

            filename = f'{item.matched.replace("@", "_")}_{datetime.datetime.today().strftime("%Y_%m_%d")}'

            if current_buffer is not None:
                current_buffer.seek(0)
                current_file = File(current_buffer, filename=f"{filename}.png")
                current_buffer.close()
                buyorder_embed.set_image(url=f"attachment://{filename}.png")
            else:
                buyorder_embed.description = "No Current Data Available!"
                buyorder_embed.colour = 0xFF0000

            history_embed = Embed(color=0x98FB98)
            if history_buffer is not None and h_data:
                history_buffer.seek(0)
                history_file = File(history_buffer,
                                    filename=f"{filename}H.png")
                history_buffer.close()
                history_embed.set_image(url=f"attachment://{filename}H.png")

                history_embed.add_field(
                    name="Avg Historical Price (Normal)",
                    value=average_sell_price,
                    inline=True,
                )
                history_embed.add_field(name="Avg Sell Volume",
                                        value=avg_sell_volume,
                                        inline=True)
            history_embed.set_footer(
                text=f"ID: {item.matched} || Best City Sales : {best_cs_str} ||\
                     |>\nSuggested Searches: {str([self.op_dict[x[0]]['LocalizedNames']['EN-US'] for x in item.results]).replace('[', '').replace(']', '')}"
            )
            if current_buffer is not None:
                await ctx.send(file=current_file, embed=buyorder_embed)
            else:
                await ctx.send(embed=buyorder_embed)

            stop_measuring_time = round(time() - start_measuring_time, 1)
            if history_buffer is None or not h_data:
                history_embed.colour = 0xFF0000
                history_embed.description = "No History Data available!"
                history_embed.set_footer(
                    text=
                    f"ID: {item.matched} || Best City Sales : {best_cs_str}|| Time: {stop_measuring_time}s\nSuggested Searches: {str([self.op_dict[x[0]]['LocalizedNames']['EN-US'] for x in item.results]).replace('[', '').replace(']', '')}"
                )
                await ctx.send(embed=history_embed)
            else:
                history_embed.set_footer(
                    text=
                    f"ID: {item.matched} || Best City Sales : {best_cs_str}|| Time: {stop_measuring_time}s\nSuggested Searches: {str([self.op_dict[x[0]]['LocalizedNames']['EN-US'] for x in item.results]).replace('[', '').replace(']', '')}"
                )
                await ctx.send(file=history_file, embed=history_embed)
            await ctx.send(embed=support_info)
def main():
    '''Runs the main function.

    usage: pre_push.py [-h] [-n] [-u] [-a]

    Check Reddit's API public endpoints for changes

    '''
    parser = argparse.ArgumentParser(
        description='Check dev/api endpoints for changes')
    parser.add_argument('-o',
                        '--output',
                        action='store',
                        help='File to write endpoints to.',
                        default='endpoints.json')
    parser.add_argument('-c',
                        '--check',
                        action='store_true',
                        help='Check if there are any changes,',
                        default=True)
    parser.add_argument('-e',
                        '--existing',
                        action='store',
                        help='File to existing endpoints')
    parser.add_argument('-p',
                        '--print',
                        action='store_true',
                        help='Print endpoints not in PRAW',
                        default=False)
    parser.add_argument('-d',
                        '--changes-dir',
                        action='store',
                        help='Dir to store changes',
                        default='changes')
    args = parser.parse_args()
    existingEndpoints = args.existing
    outputFilename = args.output
    check = args.check
    printDiff = args.print
    changesDir = args.changes_dir
    changes = False
    file = None
    try:
        if existingEndpoints and isfile(existingEndpoints):
            with open(existingEndpoints) as f:
                old_api = f.read()
                existing = loads(old_api)
        else:
            old_api = gist.files['API.json'].content
            existing = loads(old_api)
        parsed = parseEndpoints()
        current_api = dumps(parsed, indent=4)
        if check:
            if existing != parsed:
                changes = True
                if not isdir(changesDir):
                    mkdir(changesDir)
                currentChangesDir = datetime.now().strftime(
                    '%Y-%m-%d_%H-%M-%S')
                revisions = listdir(changesDir)
                revisions.sort()
                mkdir(join(changesDir, currentChangesDir))
                if len(revisions) > 1:
                    previous_revision = revisions[-1]
                with open(
                        join(changesDir, currentChangesDir,
                             'oldEndpoints.json'), 'w') as f:
                    dump(existing, f, indent=4)
                with open(
                        join(changesDir, currentChangesDir,
                             'oldEndpoints.json'), 'r') as f:
                    old = f.readlines()

                with open(
                        join(changesDir, currentChangesDir,
                             'newEndpoints.json'), 'w') as f:
                    f.write(current_api)
                with open(
                        join(changesDir, currentChangesDir,
                             'newEndpoints.json'), 'r') as f:
                    new = f.readlines()

                log.info('Changes were detected!')
                diff_string = ''.join(
                    list(
                        unified_diff(old,
                                     new,
                                     fromfile=f'API_{previous_revision}.json',
                                     tofile=f'API_{currentChangesDir}.json')))
                diff_file = io.BytesIO(diff_string.encode())
                diff_file.seek(0)
                gist.edit(
                    files={
                        'API.json': InputFileContent(current_api),
                        'changes.diff': InputFileContent(diff_string)
                    })
                file = File(diff_file, f"API_{currentChangesDir}.diff")
        if outputFilename:
            with open(outputFilename, 'w') as f:
                f.write(current_api)
        if printDiff:
            printEndpointsNotInPRAW(parsed)
    except Exception as error:
        log.exception(error)
    return changes, file
Beispiel #3
0
    async def _analyze_message(self, message: discord.Message):
        if not self._active or not self._channels[message.channel].active:
            if message.content == Emojis.anchor:
                return await self.start_channel(message.channel)
            return

        if message.author.bot:
            return

        if not self._channels[message.channel].active:  # game already ended
            logger.debug("Game already ended")
            return

        if ((not message.author.voice or message.author.voice.channel !=
             self._voice_channel_description.object_reference) and not any(
                 role_descr.has_the_role(message.author)
                 for role_descr in self._ignored_roles_descriptions)):
            msg = self._messages["STAY_IN_AUDIO"].format(
                salle_marine_mention=self._voice_channel_description.
                object_reference.mention)
            await message.channel.send(msg)
            return

        channel = message.channel

        # Send a webhook message from character
        if self._channels[channel].count_messages % 10 == 2:
            if not self._channels[channel].webhook:
                self._channels[
                    channel].webhook = await self._character_description.get_instance(
                        channel)
            try:
                self._channels[channel].webhook.send(
                    random.choice(self._messages["CHARACTER_MESSAGES"]))
                if self._count_nb_correct(channel):
                    self._channels[channel].webhook.send(
                        random.choice(
                            self._messages["CHARACTER_MESSAGES_2"]).format(
                                nb_correct=self._count_nb_correct(channel)))
            except NotFound as err:
                logger.exception(err)
                self._channels[channel].webhook = None
            if self._channels[channel].count_messages == 10:
                self._channels[channel].webhook.send(
                    file=File(self._messages["CHARACTER_MESSAGE_FILE"]))
        self._channels[channel].count_messages += 1

        # Check forbidden answers (exact word check)
        if check_answer(message.content,
                        self._messages["FORBIDDEN_ANSWERS"],
                        options=[TextAnalysisOptions.STRICT_EQUAL]):
            await message.add_reaction(Emojis.interrobang)
            await channel.send(random.choice(self._messages["BAD_ANSWERS"]))
            self.reset_counter(channel)
            await message.add_reaction(Emojis.face_with_symbols_over_mouth)
            await asyncio.sleep(5)
            await message.add_reaction(Emojis.name_badge)
            await message.delete(delay=2)
            return

        # Check correct messages
        messages_to_check = (self._messages["MANDATORY_ANSWERS"],
                             self._messages["CORRECT_ANSWERS"],
                             self._messages["OPTIONAL_ANSWERS"])
        answers_to_update = (self._channels[channel].mandatory_answers,
                             self._channels[channel].correct_answers,
                             self._channels[channel].optional_answers)
        answers_to_send = (self._messages["GOOD_ANSWERS"],
                           self._messages["GOOD_ANSWERS"], None)
        for msg_to_check, dict_to_update, answer_list_to_send in zip(
                messages_to_check, answers_to_update, answers_to_send):
            ans = check_answer_and_return_it(message.content, msg_to_check)
            if ans is not None and ans not in dict_to_update:  # mandatory/correct/optional answer detected
                if answer_list_to_send:
                    await channel.send(random.choice(answer_list_to_send))
                dict_to_update.add(ans)
                return await self._check_and_handle_victory(channel)
Beispiel #4
0
 async def send_as_attachment(self, ctx, content=""):
     return await ctx.send(content=content,
                           file=File(self.get_buffer(), "image.png"))
Beispiel #5
0
 async def pull_meme(self, ctx):
     img = choice(glob('./data/smemes/*.jpg'))
     await ctx.send(file=File(img))
Beispiel #6
0
    async def collage(self,
                      ctx,
                      count: int = None,
                      canvas_w: int = 1920,
                      canvas_h: int = 1080):
        if count is None:
            count = ctx.guild.member_count // 2
        for param in [count, canvas_w, canvas_h]:
            if int(param) < 1:
                await ctx.send("Your parameters have to be positive integers.")
                return
        if int(count) > ctx.guild.member_count:
            await ctx.send(
                "Your count parameter is greater than the number of members in the server!"
            )
            return

        canvas = Image.new('RGBA', (canvas_w, canvas_h))
        step_size = ceil(sqrt((canvas_w * canvas_h) / count))
        img_num_w = floor(canvas_w / step_size)
        img_num_h = floor(canvas_h / step_size)
        actual_count = img_num_w * img_num_h
        actual_width = img_num_w * step_size
        actual_height = img_num_h * step_size

        await ctx.send(
            "Generating a collage of size {}x{}, containing {} profile pictures."
            .format(actual_width, actual_height, actual_count))

        power_of_two = 8
        while step_size > power_of_two:
            power_of_two *= 2
        size = power_of_two

        members = ctx.guild.members
        shuffle(members)

        left = 0
        top = 0
        async with ctx.channel.typing():
            for user in members:
                if user.bot:  # We don't care about showing bots
                    continue

                # Get the image
                img_asset = user.avatar_url_as(size=size)
                if "embed" in str(img_asset):
                    continue  # Ignores ones with embed
                try:
                    img = Image.open(BytesIO(
                        await img_asset.read()))  # Sets the image
                except errors.NotFound:
                    print("This user does not have an avatar.")
                    continue

                if step_size < size:  # If the image is too big, we want to resize it.
                    img = img.resize((step_size, step_size))

                canvas.paste(img, (left, top))  # Adds the image to the canvas
                # print("Top-left corner at ({}, {})".format(left, top))

                left += step_size
                if left + step_size > canvas_w:
                    if top == 0:
                        left_crop = left
                    left = 0
                    top += step_size
                    if top + step_size > canvas_h:
                        break  # Stop the loop early

            if top == 0:
                left_crop = left
            top_crop = top

            canvas = canvas.crop((0, 0, left_crop, top_crop))
            if not path.exists("collages/"):
                mkdir("collages/")
            canvas.save("collages/{}.png".format(ctx.message.guild.id))
            await ctx.channel.send(
                file=File("collages/{}.png".format(ctx.message.guild.id)))
Beispiel #7
0
def file_from_data_stream(data_stream):
    chart_file = File(data_stream, filename="pie_chart.png")
    data_stream.seek(0)
Beispiel #8
0
def discord_file(path, name, spoiler):
    return File(BytesIO(read_b(path)), filename=name, spoiler=spoiler)
Beispiel #9
0
async def levelUp(user: discord.Member = None, guild: discord.Guild = None):
    if user is None:
        print(
            "Error in 'KumosLab/Database/check.py' - User is None for 'levelUp'"
        )
        return
    if guild is None:
        print(
            "Error in 'KumosLab/Database/check.py' - Guild is None for 'levelUp'"
        )
        return

    try:
        user_xp = await KumosLab.Database.get.xp(user=user, guild=guild)
        lvl = 0

        while True:
            if user_xp < ((config['xp_per_level'] / 2 * (lvl**2)) +
                          (config['xp_per_level'] / 2 * lvl)):
                break
            lvl += 1
        user_xp -= ((config['xp_per_level'] / 2 * ((lvl - 1)**2)) +
                    (config['xp_per_level'] / 2 * (lvl - 1)))
        if await KumosLab.Database.get.level(user=user, guild=guild) != lvl:
            await KumosLab.Database.set.level(user=user,
                                              guild=guild,
                                              amount=lvl)

            background_image = load_image(config['level_up_background'])
            background = Editor(background_image).resize(
                (900, 270)).blur(amount=config['level_up_blur'])
            profile_image = load_image(str(user.avatar_url))
            profile = Editor(profile_image).resize((200, 200)).circle_image()

            poppins_big = Font.poppins(variant="bold", size=50)
            poppins_mediam = Font.poppins(variant="bold", size=40)
            poppins_regular = Font.poppins(variant="regular", size=30)

            card_left_shape = [(0, 0), (0, 270), (330, 270), (260, 0)]

            background.polygon(card_left_shape, "#2C2F33")
            border_image = load_image(await KumosLab.Database.get.border(
                user=user, guild=guild))
            border = Editor(border_image).resize((210, 210)).circle_image()
            background.paste(border, (40, 30))
            background.paste(profile, (45, 35))

            background.text((600, 30),
                            "LEVEL UP!",
                            font=poppins_big,
                            color="white",
                            align="center")
            background.text((600, 80),
                            str(user),
                            font=poppins_regular,
                            color="white",
                            align="center")
            background.text((600, 130),
                            f"LEVEL {lvl:,}",
                            font=poppins_mediam,
                            color="white",
                            align="center")
            background.text(
                (600, 170),
                f"{translate(user_xp)}/{translate(int(config['xp_per_level'] * 2 * ((1 / 2) * lvl)))} XP",
                font=poppins_regular,
                color="white",
                align="center")

            embed = discord.Embed()

            member = user
            if await KumosLab.Database.get.mainChannel(guild=guild) is None:
                channel = guild.system_channel
            else:
                channel = discord.utils.get(
                    member.guild.channels,
                    name=await
                    KumosLab.Database.get.mainChannel(guild=member.guild))
            if channel is None:
                return
            if config['level_up_ping'] is True:
                await channel.send(f"{user.mention},")

            level_roles = np.asarray(await
                                     KumosLab.Database.get.roles(guild=guild))
            level_roles_num = np.asarray(
                await KumosLab.Database.get.roleLevel(guild=guild))

            for i in range(len(level_roles)):
                if lvl == int(level_roles_num[i]):
                    await user.add_roles(
                        discord.utils.get(user.guild.roles,
                                          name=level_roles[i]))
                    background.text(
                        (620, 225),
                        f"ROLE UNLOCKED - {level_roles[i]}".replace(
                            "[", "").replace("]", "").replace("'", ''),
                        font=poppins_regular,
                        color="white",
                        align="center",
                    )

                    # remove the previous role
                    if i > 0:
                        await user.remove_roles(
                            discord.utils.get(user.guild.roles,
                                              name=level_roles[i - 1]))
                    else:
                        continue

            card = File(fp=background.image_bytes, filename="level_card.png")
            embed.set_image(url="attachment://level_card.png")
            await channel.send(file=card, embed=embed)
    except Exception as e:
        print(f"Error in 'KumosLab/Database/check.py' - {e}")
Beispiel #10
0
async def show_storage(ctx, author, is_sorted=False, box=1, category=None):
    channel = ctx.message.channel
    categories = {
        "common": [10, 11, 13, 14, 16, 17, 19, 20, 21, 22, 23, 24, 27, 28, 29, 30, 32, 33, 39, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 60, 66, 67, 69, 70, 72, 73, 74, 75, 79, 80, 81, 82, 84, 85, 86, 87, 88, 90, 91, 92, 95, 96, 97, 98, 99, 100, 101, 102, 104, 109, 111, 114, 116, 118, 119, 120, 121, 129, 161, 162, 163, 164, 165, 167, 168, 170, 177, 179, 180, 183, 187, 188, 189, 191, 194, 195, 203, 206, 209, 216, 218, 220, 234, 261, 263, 264, 265, 266, 268, 270, 273, 274, 276, 278, 280, 283, 285, 287, 290, 293, 296, 300, 302, 303, 304, 307, 309, 311, 312, 313, 314, 315, 316, 318, 319, 320, 322, 324, 325, 327, 331, 339, 341, 353, 355, 366, 396, 399, 401, 403, 406, 412, 415, 417, 418, 420, 422, 425, 427, 431, 433, 434, 436, 449, 453, 456, 459, 504, 505, 506, 507, 509, 510, 519, 522, 524, 527, 529, 531, 532, 533, 535, 540, 541, 543, 546, 547, 548, 549, 550, 551, 557, 559, 560, 562, 568, 572, 573, 574, 575, 577, 578, 580, 581, 582, 583, 585, 587, 588, 590, 591, 592, 595, 596, 597, 598, 599, 600, 602, 605, 607, 618, 619, 629, 630, 659, 660, 661, 662, 664, 665, 667, 669, 670, 672,  674, 676, 677, 678, 679, 682, 684, 686, 687, 688, 690, 692, 694, 703],
        "uncommon": [12, 15, 18, 25, 35, 37, 40, 45, 58, 61, 63, 68, 76, 77, 89, 93, 103, 105, 106, 107, 108, 110, 112, 117, 166, 171, 178, 182, 184, 185, 186, 190, 192, 193, 198, 200, 202, 204, 207, 210, 211, 215, 217, 219, 221, 222, 223, 224, 227, 228, 231, 235, 236, 237, 238, 239, 240, 241, 262, 267, 269, 271, 275, 277, 279, 281, 284, 286, 288, 291, 294, 297, 298, 299, 301, 305, 308, 310, 317, 321, 323, 326, 328, 332, 335, 336, 337, 338, 340, 342, 343, 352, 354, 356, 357, 361, 363, 367, 368, 369, 370, 397, 400, 402, 404, 407, 408, 410, 413, 414, 416, 419, 421, 423, 426, 428, 432, 435, 437, 441, 446, 447, 450, 451, 454, 455, 457, 460, 508, 511, 512, 513, 514, 515, 516, 517, 520, 521, 523, 525, 528, 530, 534, 536, 538, 539, 542, 544, 552, 554, 556, 558, 561, 563, 564, 566, 569, 576, 579, 584, 586, 589, 593, 594, 601, 603, 606, 608, 609, 613, 616, 617, 620, 627, 628, 632, 636, 637, 663, 666, 668, 671, 673, 675, 680, 683, 685, 689, 691, 693, 695, 701, 702, 707, 708, 710],
        "rare": [1, 4, 7, 26, 31, 36, 38, 62, 64, 65, 71, 78, 94, 113, 122, 123, 124, 125, 126, 127, 128, 133, 134, 135, 136, 137, 138, 139, 140, 141, 152, 155, 158, 169, 172, 173, 174, 175, 181, 199, 201, 205, 208, 214, 225, 226, 229, 232, 233, 246, 247, 252, 253, 255, 256, 258, 259, 272, 282, 289, 292, 295, 306, 329, 333, 344, 345, 346, 347, 348, 349, 351, 358, 359, 360, 362, 364, 365, 371, 372, 374, 375, 387, 388, 390, 391, 393, 394, 398, 405, 409, 411, 424, 429, 430, 438, 439, 440, 443, 444, 448, 452, 458, 461, 470, 471, 476, 478, 495, 496, 498, 499, 501, 502, 518, 526, 537, 545, 553, 555, 565, 567, 570, 604, 610, 611, 614, 615, 622, 623, 624, 625, 626, 631, 633, 634, 650, 651, 653, 654, 656, 657, 681, 696, 698, 700, 704, 705, 709, 711, 712, 714],
        "ultra": [2, 3, 5, 6, 8, 9, 34, 59, 83, 115, 130, 131, 132, 142, 143, 147, 148, 149, 153, 154, 156, 157, 159, 160, 176, 196, 197, 212, 230, 242, 248, 254, 257, 260, 330, 334, 350, 373, 376, 389, 392, 395, 442, 445, 462, 463, 464, 465, 466, 467, 468, 469, 472, 473, 474, 475, 477, 479, 497, 500, 503, 571, 612, 621, 635, 652, 655, 658, 697, 699, 706, 713, 715, 720],
        "legendary": [144, 145, 146, 150, 151, 213, 243, 244, 245, 249, 250, 251, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386,480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 716, 717, 718, 719, 721],
        "eevee": [133, 134, 135, 136, 470, 197, 471, 700, 196, 471]
    }

    storage_list = database.get_storage(author)
    if is_sorted:
        storage_list = sorted(storage_list, key=lambda p: p['name']) 

    if category is None:
        storage = Image.open("img/storage/common.png")
    else:
        storage = Image.open("img/storage/{}.png".format(category))

    x1 = 0
    y1 = 34
    x2 = 40
    y2 = 64

    # for text drawing
    font = ImageFont.truetype("fonts/8bit.ttf", 10)
    draw = ImageDraw.Draw(storage)

    current_box = 1
    pokemon_count = 0
    for i, pkmn in enumerate(storage_list):
        id = pkmn["national_id"]
        if (category is None) or ( id in categories[category]):
            pokemon_count += 1
        elif id not in categories[category]:
            continue
        if current_box == box:
            shiny = pkmn["shiny"]
            
            area = (x1, y1, x2, y2)
            name = pkmn["name"].lower()

            # paste the pokemon image
            if shiny:
                image = Image.open("img/pokemon/shiny/{}.png".format(id))
            else:
                image = Image.open("img/pokemon/regular/{}.png".format(id))

            if pkmn["health"] == 0:
                image = image.convert('L')

            storage.paste(image, area, image)
            
            id = "[{}]".format(pkmn["national_id"])
            # draw pokemon info
            draw.text((x1 + 11, y1 + 31), id, (0, 0, 0), font=font)
            draw.text((x1 + 10, y1 + 30), id, (255, 255, 255), font=font)
        
            if pokemon_count % 6 == 0:
                # new row
                y1 += 34
                y2 += 34
                x1 = 0
                x2 = 40
            else:
                x1 += 32
                x2 += 32
        if pokemon_count % 30 == 0:
                current_box += 1

    total_pages = math.ceil(pokemon_count / 30)
    x1 = 0
    y1 = 34
    x2 = 40
    y2 = 64
    draw.text((x1 + 31 , y1 - 9), str(author) + " - {}/{}".format(box, total_pages), (0, 0, 0), font=font)
    draw.text((x1 + 30 , y1 - 10), str(author) + " - {}/{}".format(box, total_pages), (255, 255, 255), font=font)

    # create a temp file for the upload
    file, filename = tempfile.mkstemp(".png")
    # save the compiled image
    storage.save(filename)
    # upload with bot
    await channel.send(file=File(filename))
    os.close(file)
Beispiel #11
0
async def show_party(context): 
    author = context.message.author   
    party_list = database.get_party(author)
    channel = context.message.channel

    party = Image.open("img/partyarea2.png")

    x1 = 2
    y1 = 35
    x2 = 42
    y2 = 65

    # for text drawing
    font = ImageFont.truetype("fonts/8bit.ttf", 12)
    draw = ImageDraw.Draw(party)

    draw.text((x1 + 10 , y1 - 25), str(author) + "'s Party", (255, 255, 255), font=font)

    for pkmn in party_list:
        shiny = pkmn["shiny"]
        health_ratio = float(float(pkmn["health"]) / float(pkmn["hp"]))
        pkmn_id = pkmn["national_id"]
        area = (x1, y1, x2, y2)
        name = pkmn["name"].upper()

        # paste the pokemon image
        if shiny:  
            image = Image.open("img/pokemon/shiny/{}.png".format(pkmn_id))
        else:
            image = Image.open("img/pokemon/regular/{}.png".format(pkmn_id))
        if health_ratio == 0:
            image = image.convert('L')

        party.paste(image, area, image)
        
        name = "[{}] {}".format(pkmn["national_id"], name)
        # draw pokemon info
        if shiny:
            draw.text((x1 + 45, y1 + 5), name, (255,165,0), font=font)
            draw.text((x1 + 45, y1 + 5), name, (255,165,0), font=font)
        else:
            draw.text((x1 + 45, y1 + 5), name, (0, 0, 0), font=font)
        # draw health bars
        draw.rectangle([x1+ 45, y1+ 20, x1 + 145, y1+ 30], fill=(0,0,0))
        fill = (34,139,34)
        if  .25 <= health_ratio < .50:
            fill = (255,140,0)
        elif health_ratio < .25:
            fill = (255, 0, 0) 
        draw.rectangle([x1+ 45, y1+ 20, x1 + 45 + (health_ratio * 100), y1 + 30], fill=fill)
        health_txt = "{}/{}".format(pkmn["health"], pkmn["hp"])
        draw.text((x1 + 80, y1 + 20), health_txt, (255, 255, 255), font=font)
        y1 += 37
        y2 += 37

    # create a temp file for the upload
    file, filename = tempfile.mkstemp(".png")
    # save the compiled image
    party.save(filename)
    # upload with bot
    await channel.send(file=File(filename))
    os.close(file)
Beispiel #12
0
    async def readme(
        self,
        ctx: Context,
        operand: str = "",
        channel_id: str = "",
        msg_send_interval: int = 0,
    ):
        """
        Allows generating, sending and manipulation of JSON file containing the info needed
        to create and send the embeds for the #readme channel. Only ROOT_ROLE_ID users have
        the permissions need to use this command.
        """

        operand = operand.lower()

        # The supplied operand is incorrect.
        if not (operand in README_SEND_ALIASES + README_RECV_ALIASES):
            incorrect_operand_embed = Embed(
                colour=0x673AB7,
                description=":shrug: **Invalid readme operand supplied.**",
            )
            await ctx.message.delete()
            await ctx.send(embed=incorrect_operand_embed)

        # User missed out the channel_id for certain commands.
        elif channel_id == "" and operand in README_SEND_ALIASES:
            misssing_channel_embed = Embed(
                colour=0xFF5722,
                description=
                ":facepalm: **Whoops, you missed out the channel ID! Try again.**",
            )
            await ctx.message.delete()
            await ctx.send(embed=misssing_channel_embed)

        # Process the request.
        else:
            # Let's create a series of #readme-capable embeds. If something is uploaded,
            # It will attempt to use that file for the readme, if omitted, it will use
            # the default JSONifed readme file and send that into the channel instead.
            if operand in README_SEND_ALIASES:
                try:
                    # Much pain was had fixing this. Please, get some help and install mypy type checking.
                    channel_id: int = int(channel_id[2:-1] if channel_id[0] ==
                                          "<" else channel_id)

                    usr_confirmation_embed = Embed(
                        colour=0x4CAF50,
                        description=
                        ":white_check_mark: **Creating readme using uploaded config file.**",
                    )

                    # The user has uploaded a config.
                    if ctx.message.attachments != []:
                        json_file_location = [
                            _.url for _ in ctx.message.attachments
                        ][0]

                        # GETs the attachment data.
                        async with ClientSession() as session:
                            async with session.get(
                                    json_file_location) as response:
                                if response.status == 200:
                                    resp_text = await response.text()

                        json_config = load(StringIO(resp_text))
                        await ctx.send(embed=usr_confirmation_embed)

                    # No config uploaded, just use default config file.
                    else:
                        with open("cdbot/data/readme.json",
                                  "rb") as default_json:
                            json_config = load(default_json)

                        usr_confirmation_embed.description = (
                            ":ballot_box_with_check: "
                            "**Creating readme using default config file.**")
                        await ctx.send(embed=usr_confirmation_embed)

                    await ctx.message.delete()

                    for section in json_config:
                        # Initialise our message and embed variables each loop.
                        # This is to prevent leftover data from being re-sent.
                        msg_content, current_embed = None, None

                        # The part which handles general messages.
                        if "content" in json_config[section]:
                            msg_content = json_config[section]["content"]

                        # We have an embed. Call in the Seahawks.
                        if "embed" in json_config[section]:
                            current_embed = Embed()
                            msg_embed = json_config[section]["embed"]
                            if "title" in msg_embed:
                                current_embed.title = msg_embed["title"]
                            if "description" in msg_embed:
                                current_embed.description = msg_embed[
                                    "description"]
                            if "color" in msg_embed:
                                current_embed.colour = Colour(
                                    int(msg_embed["color"], 16))

                            # Parse the fields, if there are any.
                            if "fields" in msg_embed:
                                for current_field in msg_embed["fields"]:
                                    # Add the fields to the current embed.
                                    current_embed.add_field(
                                        name=current_field["name"],
                                        value=current_field["value"],
                                    )

                        # Send the message.
                        requested_channel = self.bot.get_channel(channel_id)

                        if msg_content is not None and current_embed is None:
                            await requested_channel.send(content=msg_content)
                        elif current_embed is not None and msg_content is None:
                            await requested_channel.send(embed=current_embed)
                        else:
                            await requested_channel.send(content=msg_content,
                                                         embed=current_embed)

                        # User has requested a delay between each message being sent.
                        if 0 < msg_send_interval < 901:
                            await sleep(msg_send_interval)

                    # Send the trailing embed message constant.
                    await requested_channel.send(content=END_README_MESSAGE)

                except (Exception):
                    parse_fail_embed = Embed(
                        colour=0x673AB7,
                        description=
                        ":x: **Error parsing JSON file, please ensure its valid!**",
                    )
                    await ctx.message.delete()
                    await ctx.send(embed=parse_fail_embed)

            # Pull the readme JSON constant files and slide it into the user's DMs.
            elif operand in README_RECV_ALIASES:

                # Slide it to the user's DMs.
                requesting_user = await self.bot.fetch_user(
                    ctx.message.author.id)

                await requesting_user.send(
                    content="Hey, here's your config file!",
                    file=File(fp="cdbot/data/readme.json",
                              filename="readme.json"),
                )

                await ctx.message.delete()
                await ctx.send(embed=Embed(
                    colour=0x009688,
                    description=":airplane: **Flying in, check your DMs!**",
                ))
Beispiel #13
0
 def convert_file(b64, i):
     bytesio = BytesIO()
     bytesio.write(base64.b64decode(b64))
     bytesio.seek(0)
     return File(bytesio, filename=f'output{i}.png')
Beispiel #14
0
 def get_image(self, ctx, elements, image_path):
     if image_path:
         elements['file'] = File(image_path)
Beispiel #15
0
async def draw(server: AbstractServer, msg: Message):
	try:
		gameData: PapGame = server.GetDatabase().getLiveGameForUserForGametype(
			discordID=msg.author.id,
			gameType="tic tac toe"
		)
		still_live = True

		resumeGame = TicTacToe(player1=None, player2=None, data=gameData, gameID=gameData.gameID)
		resumeGameID = gameData.gameID
		userIDs = gameData.userIDs

		if resumeGame.turn.user != msg.author.id:
			await msg.channel.send("Ehi bud it's not your turn yet")
		else:
			params = msg.content.split()
			pos = params[1]
			code = resumeGame.makeMove(pos)

			if code == 3:
				await msg.channel.send("That position is invalid, try again")
			elif code == 0:
				await msg.channel.send("The game is still going on")
			elif code == 1:
				await msg.channel.send(f"Congrats {msg.author.mention} you won")
				for userid in userIDs.split(','):
					if userid == msg.author.id:
						server.GetDatabase().saveStatsForUserInGuild(
							userID=str(userid),
							loss=True,
							gameType='tic tac toe')
					else:
						server.GetDatabase().saveStatsForUserInGuild(
							userID=str(userid),
							win=True,
							gameType='tic tac toe')
				still_live = False
			elif code == 10:
				await msg.channel.send("Sorry but you lost and our AI WON, ggs")
				server.GetDatabase().saveStatsForUserInGuild(
					userID=msg.author.id,
					loss=True,
					gameType='tic tac toe')
				still_live = False
			elif code == 100:
				await msg.channel.send("This is a tie")
				for userid in userIDs.split(','):
					server.GetDatabase().saveStatsForUserInGuild(
						userID=str(userid),
						tie=True,
						gameType='tic tac toe')
				still_live = False

			drawEmbed = embed(
				title="Tic Tac Toe",
				content="X: Player1 \tO: Player2",
				color=getColor(random=True)
			)
			file = File(
				f'{os.getcwd()}/modules/tic_tac_toe/src/tictactoe_images/{resumeGameID}.png',
				filename='test.png'
			)
			drawEmbed.set_image(url=f'attachment://test.png')
			# drawEmbed.add_field(name="game_status", value={'Still live' if still_live else 'Ended'}, inline=False)
			await msg.channel.send(file=file, embed=drawEmbed)
			updateGame = PapGame(
				gameData.gameID,
				[int(username) for username in (gameData.userIDs.replace(',', ' ').split(' '))],
				resumeGame.getData(),
				gameData.gameType,
				still_live
			)
			server.GetDatabase().setGame(
				updateGame
			)
	except GameNotFound:
		await msg.channel.send(f"There is no game for you bud.")
Beispiel #16
0
async def plot_graph2(ctx, iso2, name):
    data = await api_covid.CovidAPI().get_country_timeline2(iso2[0])
    if data is None:
        await send_error(ctx, "API Error!")
        return
    x_axis = []
    cases = []
    for x in data['data']['timeline']:
        try:
            x_axis.append(datetime.strptime(x['date'], '%Y-%m-%d'))
        except Exception:
            pass
    x_axis = x_axis[:450]
    for x in iso2:
        data = await api_covid.CovidAPI().get_country_timeline2(x)
        if data is None:
            await send_error(ctx, "API Error!")
            return
        arr = []
        for y in data['data']['timeline']:
            try:
                arr.append(y['confirmed'])
            except Exception:
                pass
        cases.append(arr[:450])
    col = ["red", "orange", "green", "blue", "yellow"]
    for i in range(0, len(iso2)):
        plt.plot(x_axis,
                 cases[i],
                 color=col[i],
                 linestyle='-',
                 marker='o',
                 markersize=4,
                 markerfacecolor=col[i],
                 label=name[i])

    plt.gcf().autofmt_xdate()
    plt.grid()
    plt.legend()
    ax = plt.axes()
    plt.setp(ax.get_xticklabels(), color="white")
    plt.setp(ax.get_yticklabels(), color="white")
    filename = "%s.png" % str(ctx.message.id)
    plt.savefig(filename, transparent=True)
    with open(filename, 'rb') as file:
        discord_file = File(BytesIO(file.read()), filename='plot.png')
    os.remove(filename)
    plt.clf()
    plt.close()
    embed = Embed(title=f"Linear graph for country {name}", color=Color.blue())
    embed.set_image(url="attachment://plot.png")
    embed.set_footer(text=send_banner(), icon_url=ctx.author.avatar_url)
    embed.add_field(
        name="Bot Invite Link",
        value=
        "[:envelope: Invite](https://discordapp.com/oauth2/authorize?client_id=694820915669893201&permissions=392257&scope=bot)",
        inline=True)
    embed.add_field(
        name="Bot Source code",
        value=
        "[:tools: GitHub](https://github.com/pseudocoder10/Covid19-Tracker)",
        inline=True)
    embed.add_field(
        name="Vote for me",
        value=
        "[:first_place: top.gg](https://top.gg/bot/694820915669893201/vote)",
        inline=True)
    await ctx.channel.send(embed=embed, file=discord_file)
Beispiel #17
0
 async def gacha(self, ctx, server: str = 'en'):
     from PIL import Image
     from PIL.ImageDraw import Draw
     from PIL.ImageFont import truetype
     from commands.apiFunctions import GetServerAPIKey, GetBestdoriAllGachasAPI, GetBestdoriGachaAPI, GetBestdoriCardAPI, GetBestdoriCharasAPI
     api = await GetBestdoriAllGachasAPI()
     gachas = []
     gachasEnd = []
     cardDetails = []
     CardIds = []
     CardCharaNames = []
     currentTime = await GetCurrentTime()
     ServerKey = await GetServerAPIKey(server)
     for x in list(api):
         if api[str(x)]['gachaName'][ServerKey] and api[str(x)]['closedAt'][
                 ServerKey] and api[str(x)]['publishedAt'][ServerKey]:
             closedAt = int(api[str(x)]['closedAt'][ServerKey])
             startAt = int(api[str(x)]['publishedAt'][ServerKey])
             gachaName = api[str(x)]['gachaName'][ServerKey]
             if 'Beginners' not in gachaName and '3+' not in gachaName and 'Head Start' not in gachaName:
                 if (closedAt > currentTime and currentTime > startAt):
                     gachaAPI = await GetBestdoriGachaAPI(x)
                     if gachaAPI['details'][0]:
                         for y in list(gachaAPI['details'][0]):
                             if (gachaAPI['details'][0][str(y)]['weight'] ==
                                     5000):
                                 CardApi = await GetBestdoriCardAPI(y)
                                 CardIds.append(y)
                                 cardChara = CardApi['characterId']
                                 cardAttr = CardApi['attribute']
                                 cardType = CardApi['type']
                                 charaApi = await GetBestdoriCharasAPI(
                                     cardChara)
                                 charaName = charaApi['characterName'][
                                     1]  # icons are stored in their english name
                                 cardInfo = cardType.capitalize(
                                 ) + " " + cardAttr.capitalize(
                                 ) + " " + charaName
                                 CardCharaNames.append(charaName.split()[0])
                                 cardDetails.append(cardInfo)
                                 cardDetails.append(
                                     f'https://bestdori.com/info/cards/{y}')
                     gachas.append(gachaName)
                     gachasEnd.append(
                         time.strftime("%d %b %Y",
                                       time.localtime(int(closedAt /
                                                          1000))))
     IconPaths = []
     for chara, id in zip(CardCharaNames, CardIds):
         IconPaths.append(f"data/img/icons/{chara.lower()}/4/{id}.png")
     images = [Image.open(x) for x in IconPaths]
     widths, heights = zip(*(i.size for i in images))
     total_width = sum(widths)
     max_height = max(heights)
     new_im = Image.new('RGBA', (int(total_width), max_height))
     x_offset = 0
     for im in images:
         new_im.paste(im, (x_offset, 0))
         x_offset += im.size[0]
     from discord import File
     import uuid
     FileName = str(uuid.uuid4()) + '.png'
     SavedFile = "data/img/imgTmp/" + FileName
     new_im.save(SavedFile)
     DiscordFileObject = File(SavedFile, filename=FileName)
     embed = discord.Embed()
     embed.add_field(name='Gacha', value='\n'.join(gachas), inline=True)
     embed.add_field(name='End', value='\n'.join(gachasEnd), inline=True)
     embed.add_field(name='Cards',
                     value='\n'.join(cardDetails),
                     inline=False)
     embed.set_image(url=f"attachment://{FileName}")
     await ctx.send(file=DiscordFileObject, embed=embed)
     os.remove(SavedFile)
Beispiel #18
0
async def plot_graph(ctx, iso2, num):
    data = await api_covid.CovidAPI().get_country_timeline(iso2)
    if data is None:
        await send_error(ctx, "API Error!")
        return
    x_axis = []
    cases = []
    deaths = []
    recovery = []
    for x in data['timelineitems'][0]:
        try:
            x_axis.append(datetime.strptime(str(x), '%m/%d/%y'))
            cases.append(data['timelineitems'][0][x]['total_cases'])
            deaths.append(data['timelineitems'][0][x]['total_deaths'])
            recovery.append(data['timelineitems'][0][x]['total_recoveries'])
        except Exception:
            pass
    plt.plot(x_axis,
             cases,
             color='yellow',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='yellow',
             label="Total Cases")
    plt.plot(x_axis,
             recovery,
             color='green',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='green',
             label="Total Recoveries")
    plt.plot(x_axis,
             deaths,
             color='red',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='red',
             label="Total Deaths")

    plt.gcf().autofmt_xdate()
    plt.grid()
    plt.legend()
    ax = plt.axes()
    plt.setp(ax.get_xticklabels(), color="white")
    plt.setp(ax.get_yticklabels(), color="white")
    filename = "%s.png" % str(ctx.message.id)
    plt.savefig(filename, transparent=True)
    with open(filename, 'rb') as file:
        discord_file = File(BytesIO(file.read()), filename='plot.png')
    os.remove(filename)
    plt.clf()
    plt.close()
    embed = Embed(
        title=
        f"Linear graph for country {data['countrytimelinedata'][0]['info']['title']}",
        color=Color.blue())
    embed.set_image(url="attachment://plot.png")
    embed.set_footer(text=send_banner(), icon_url=ctx.author.avatar_url)
    await ctx.channel.send(embed=embed, file=discord_file)
    if num == 0:
        return

    plt.plot(x_axis,
             cases,
             color='yellow',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='yellow',
             label="Total Cases")
    plt.plot(x_axis,
             recovery,
             color='green',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='green',
             label="Total Recoveries")
    plt.plot(x_axis,
             deaths,
             color='red',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='red',
             label="Total Deaths")

    plt.gcf().autofmt_xdate()
    plt.grid()
    plt.legend()
    ax = plt.axes()
    ax.set_yscale('log')
    plt.setp(ax.get_xticklabels(), color="white")
    plt.setp(ax.get_yticklabels(), color="white")
    filename = "%s.png" % str(ctx.message.id)
    plt.savefig(filename, transparent=True)
    with open(filename, 'rb') as file:
        discord_file = File(BytesIO(file.read()), filename='plot.png')
    os.remove(filename)
    plt.clf()
    plt.close()
    embed = Embed(
        title=
        f"Logarithmic graph for country {data['countrytimelinedata'][0]['info']['title']}",
        color=Color.blue())
    embed.set_image(url="attachment://plot.png")
    embed.set_footer(text=send_banner(), icon_url=ctx.author.avatar_url)
    await ctx.channel.send(embed=embed, file=discord_file)
Beispiel #19
0
class Social(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self._cd = commands.CooldownMapping.from_cooldown(
            1, 86400.0, commands.BucketType.user)

    def get_gif(self, query: str) -> str:
        query = query.replace(' ', '%20')
        filters = 'contentfilter=medium&mediafilter=minimal&limit=1'
        res = requests.get(
            f'https://api.tenor.com/v1/random?q={query}&key={config.tenor_api_key}&{filters}'
        )
        if res.status_code == 200:
            obj = json.loads(res.content)
            url = obj['results'][0]['media'][0]['gif']['url']
            return url

        return ccp.error('Failed to reach Tenor servers')

    @commands.Cog.listener()
    async def on_message(self, msg):
        if msg.author.bot:
            return

        if not self.bot.users_.get(msg.author.id):
            return await self.bot.users_.insert(msg.author.id)

        # birthday stuff
        bday = self.bot.users_[msg.author.id]['birthday']
        today = datetime.date.today()
        if bday:
            if today.month == bday.month and today.day == bday.day:
                bucket = self._cd.get_bucket(msg)
                limited = bucket.update_rate_limit()
                if not limited:
                    embed = Embed(color=utils.Color.pinky)
                    embed.set_author(
                        name=f'Happy birthday, {msg.author.display_name}!',
                        icon_url='attachment://unknown.png')

                    await msg.reply(file=File('assets/cake.png',
                                              'unknown.png'),
                                    embed=embed)

    @command(name='birthday', aliases=['bday'], usage='birthday <mm/dd/yyyy>')
    async def birthday(self, ctx, date: str):
        '''Set your birthday.
        I will wish you happy birthday when the day comes!\n
        **Example:```yml\n♤birthday 1/1/2000```**
        '''
        m, d, y = date.split('/')
        if len(y) == 2:
            y = f'20{y}'

        bday = datetime.date(int(y), int(m), int(d))

        await self.bot.users_.update(ctx.author.id, 'birthday', bday)

        embed = Embed(color=utils.Color.pinky)
        embed.set_author(name=f'Birthday has been set to {date}',
                         icon_url='attachment://unknown.png')

        await ctx.reply(file=File('assets/cake.png', 'unknown.png'),
                        embed=embed,
                        mention_author=False)

    @command(name='boop', usage='boop <member>')
    @guild_only()
    async def boop(self, ctx, member: discord.Member):
        '''Boop someone!\n
        **Example:```yml\n♤boop @Tau#4272```**
        '''
        gif = self.get_gif('anime boop nose')
        if gif:
            recipient = 'themselves' if ctx.author == member else member.display_name
            embed = Embed(color=utils.Color.lilac)
            embed.set_author(
                name=f'{ctx.author.display_name} booped {recipient}!',
                icon_url=ctx.author.avatar_url)
            embed.set_image(url=gif)

            await ctx.send(embed=embed)

    @command(name='hug', usage='hug <member>')
    @guild_only()
    async def hug(self, ctx, member: discord.Member):
        '''Hug someone!\n
        **Example:```yml\n♤hug @Tau#4272```**
        '''
        gif = self.get_gif('anime hug cute')
        if gif:
            recipient = 'themselves' if ctx.author == member else member.display_name
            embed = Embed(color=utils.Color.lilac)
            embed.set_author(
                name=f'{ctx.author.display_name} hugged {recipient}!',
                icon_url=ctx.author.avatar_url)
            embed.set_image(url=gif)

            await ctx.send(embed=embed)

    @command(name='kiss', usage='kiss <member>')
    @guild_only()
    async def kiss(self, ctx, member: discord.Member):
        '''Kiss someone!\n
        **Example:```yml\n♤kiss @Tau#4272```**
        '''
        gif = self.get_gif('anime kiss')
        if gif:
            recipient = 'themselves' if ctx.author == member else member.display_name
            embed = Embed(color=utils.Color.pinky)
            embed.set_author(
                name=f'{ctx.author.display_name} kissed {recipient}!',
                icon_url=ctx.author.avatar_url)
            embed.set_image(url=gif)

            await ctx.send(embed=embed)

    @command(name='pat', aliases=['headpat'], usage='pat <member>')
    @guild_only()
    async def pat(self, ctx, member: discord.Member):
        '''Headpat someone!\n
        **Example:```yml\n♤pat @Tau#4272```**
        '''
        gif = self.get_gif('anime headpat')
        if gif:
            recipient = 'themselves' if ctx.author == member else member.display_name
            embed = Embed(color=utils.Color.lilac)
            embed.set_author(
                name=f'{ctx.author.display_name} patted {recipient}!',
                icon_url=ctx.author.avatar_url)
            embed.set_image(url=gif)

            await ctx.send(embed=embed)

    @command(name='slap', usage='slap <member>')
    @guild_only()
    async def slap(self, ctx, member: discord.Member):
        '''Slap someone! (not too hard tho)\n
        **Example:```yml\n♤slap @Tau#4272```**
        '''
        gif = self.get_gif('anime slap')
        if gif:
            recipient = 'themselves' if ctx.author == member else member.display_name
            embed = Embed(color=utils.Color.red)
            embed.set_author(
                name=f'{ctx.author.display_name} slapped {recipient}!',
                icon_url=ctx.author.avatar_url)
            embed.set_image(url=gif)

            await ctx.send(embed=embed)

    @command(name='server', aliases=['serverinfo'], usage='server')
    @commands.bot_has_permissions(external_emojis=True)
    @guild_only()
    async def server(self, ctx):
        '''Display server profile.
        If the server has a banner, it will be displayed here.
        This profile cannot be customized.\n
        **Example:```yml\n♤server```**
        '''
        guild = ctx.guild

        bots = 0
        statuses = dict(online=0, idle=0, dnd=0, streaming=0, offline=0)
        for member in guild.members:
            if member.bot: bots += 1
            if member.activity and member.activity.type == 'streaming':
                statuses['streaming'] += 1
                continue
            statuses[str(member.status)] += 1

        desc = (f'{guild.owner.mention} {Emoji.owner}\n\n'
                f'**Region:** {guild.region}\n'
                f'**Verification:** {guild.verification_level}\n\n')

        emojis = guild.emojis
        n = random.sample(emojis, 10 if len(emojis) > 10 else len(emojis))
        emojis = ''.join(str(e) for e in n)

        stats = f'**Humans:** `{guild.member_count-bots}` **Bots:** `{bots}`\n'
        for key in list(statuses.keys()):
            stats += f'{Emoji.statuses[key]} `{statuses[key]}` '

        embed = Embed(description=desc)
        embed.set_author(name=guild.name, icon_url=guild.icon_url)
        embed.add_field(name=f'Members `{guild.member_count}`',
                        value=stats,
                        inline=False)
        embed.add_field(name=f'Emoji `{len(guild.emojis)}`',
                        value=emojis,
                        inline=False)

        embed.set_image(url=guild.banner_url)
        embed.set_footer(text=f'ID: {guild.id}, created')
        embed.timestamp = guild.created_at

        await ctx.send(embed=embed)

    @command(name='leaderboard', aliases=['lb'], usage='leaderboard')
    @guild_only()
    async def leaderboard(self, ctx):
        '''Display leaderboard.\n
        **Example:```yml\n♤lb```**
        '''
        async with self.bot.pool.acquire() as con:
            records = await con.fetch(
                f'SELECT user_id, xp FROM members WHERE guild_id = {ctx.guild.id} ORDER BY xp DESC'
            )
            highscores = []
            for record in records:
                user_id, xp = record.values()
                member = ctx.guild.get_member(user_id)
                if member:
                    highscores.append((member, xp))
                    if len(highscores) == 10:
                        break

        embed = Embed(color=utils.Color.sky)
        embed.set_author(name='Leaderboard',
                         icon_url='attachment://unknown.png')
        inline = False
        for i, score in enumerate(highscores):
            member, xp = score
            name = escape_markdown(str(member))
            embed.add_field(
                name=f'**{i+1}.** {name}',
                value=f'**```yml\nLevel: {level(xp)}\nXP: {xp}```**',
                inline=inline)
            inline = True

        await ctx.send(file=File('assets/dot.png', 'unknown.png'), embed=embed)

    @command(name='profile',
             aliases=['card', 'info', 'user'],
             usage='profile [member]')
    @commands.bot_has_permissions(attach_files=True,
                                  external_emojis=True,
                                  manage_messages=True)
    @guild_only()
    async def profile(self, ctx, *, member: discord.Member = None):
        '''Display profile card.
        The accent color and the bio features may be customized.
        This only works with members within the server.\n
        **Example:```yml\n♤profile @Tau#4272\n♤profile 608367259123187741```**
        '''
        if not member:
            member = ctx.author

        if member.id == self.bot.user.id:
            ctx.command = self.bot.get_command('tau')
            return await self.bot.invoke(ctx)

        if member.bot:
            return

        message = await ctx.send(Emoji.loading)

        res = requests.get(str(member.avatar_url))
        with Image.open('assets/profile.png') as template, \
             Image.open('assets/border.png') as border, \
             Image.open(io.BytesIO(res.content)) as avatar:
            # Copy the template and initialize the draw object
            im = template.copy()
            draw = ImageDraw.Draw(im)

            xp = self.bot.members[member.id, ctx.guild.id]['xp']
            lvl = level(xp)
            accent = self.bot.users_[member.id]['accent']
            font = ImageFont.truetype('assets/font/Comfortaa-Bold.ttf', 200)
            font2 = ImageFont.truetype('assets/font/Comfortaa-Bold.ttf', 250)
            bigfont = ImageFont.truetype('assets/font/Comfortaa-Bold.ttf', 500)

            # Circular mask for avatar
            size = (512, 512)
            mask = Image.new('L', size, 0)
            draw_mask = ImageDraw.Draw(mask)
            draw_mask.ellipse((0, 0) + size, fill=255)
            avatar = ImageOps.fit(avatar, mask.size, centering=(0.5, 0.5))

            # Avatar
            w, h = avatar.size
            im.paste(avatar, (594 - w // 2, 378 - h // 2), mask)

            # Level
            w, h = bigfont.getsize(str(lvl))
            xo, yo = font.getoffset(str(lvl))
            draw.text((594 - w / 2 - xo / 2, 930 - h / 2 - yo / 2),
                      str(lvl),
                      font=bigfont,
                      fill=accent)

            # Fetch the rank of the member
            async with self.bot.pool.acquire() as con:
                async with con.transaction():
                    rank = 1
                    async for record in con.cursor(
                            'SELECT user_id FROM members ORDER BY xp DESC'):
                        if record['user_id'] == member.id:
                            break
                        rank += 1

            # To iterate over the different texts, I decided to use a
            # list of 2-tuples where the first index is the value of
            # the midpoint of the corresponding image on the y-axis
            # and the other is the integer value.
            text = [
                (252, rank),  # Global rank
                (624, xp),  # XP
                (978, self.bot.users_[member.id]['tickets'])  # Tickets
            ]
            for y, val in text:
                # Python has this neat trick to automatically interpolate
                # commas into integers if they're long enough.
                msg = f'{val:,}'

                # The text becomes taller, since the commas dip below the rest
                # of the letters. boost is to keep the text aligned with the
                # image. This will break if the font size is changed, as it
                # is a hard coded value.
                boost = 0
                if ',' in msg:
                    boost = 22

                _, h = font.getsize(msg)
                _, offset = font.getoffset(msg)
                draw.text((1600, y - h / 2 - offset / 2 + boost),
                          msg,
                          font=font,
                          fill=accent)

            # Progress bar
            # Calculate the length of the progress bar as a
            # percentage of the xp to next level
            currentxp = xp - levelxp(lvl)
            totalxp = levelxp(lvl + 1) - levelxp(lvl)
            ratio = currentxp / totalxp
            pos = 2500 * ratio + 129
            draw.rectangle([129, 1264, pos, 1666], fill=accent)

            # Progress bar text
            msg = f'{currentxp}/{totalxp}'
            x, _ = im.size
            w, h = font.getsize(msg)
            _, offset = font.getoffset(msg)
            draw.text((x / 2 - w / 2, 1465 - h / 2 - offset / 2),
                      msg,
                      font=font2,
                      fill=f'#ffffff')

            # Finalize by pasting the progress bar border
            # to prevent the corners of the rectangle
            # from jutting out.
            final = Image.alpha_composite(im, border)

            buffer = io.BytesIO()
            final.save(buffer, 'png')

            buffer.seek(0)

        # decorators
        dec = []
        if member == ctx.guild.owner:
            dec.append(Emoji.owner)

        if member.premium_since:
            dec.append(Emoji.boost)

        dec = ' '.join(dec)

        desc = f'{Emoji.statuses[str(member.status)]} **{escape_markdown(member.display_name)} {dec}\n`{member}`**\n\n'
        if bio := self.bot.users_[member.id]["bio"]:
            desc += f'**```yml\n{bio}```**'

        embed = Embed(description=desc)
        embed.set_image(url='attachment://unknown.png')
        embed.set_footer(text=f'ID: {member.id}, created')
        embed.timestamp = member.created_at

        await message.delete()
        await ctx.send(file=File(buffer, 'unknown.png'), embed=embed)
Beispiel #20
0
async def plot_graph1(ctx, iso2, num, name):
    data = await api_covid.CovidAPI().get_country_timeline2(iso2)
    if data is None:
        await send_error(ctx, "API Error!")
        return
    x_axis = []
    cases = []
    deaths = []
    recovery = []
    for x in data['data']['timeline']:
        try:
            x_axis.append(datetime.strptime(x['date'], '%Y-%m-%d'))
            cases.append(x['confirmed'])
            deaths.append(x['deaths'])
            recovery.append(x['recovered'])
        except Exception:
            pass
    plt.plot(x_axis,
             cases,
             color='yellow',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='yellow',
             label="Total Cases")
    plt.plot(x_axis,
             recovery,
             color='green',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='green',
             label="Total Recoveries")
    plt.plot(x_axis,
             deaths,
             color='red',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='red',
             label="Total Deaths")

    plt.gcf().autofmt_xdate()
    plt.grid()
    plt.legend()
    ax = plt.axes()
    plt.setp(ax.get_xticklabels(), color="white")
    plt.setp(ax.get_yticklabels(), color="white")
    filename = "%s.png" % str(ctx.message.id)
    plt.savefig(filename, transparent=True)
    with open(filename, 'rb') as file:
        discord_file = File(BytesIO(file.read()), filename='plot.png')
    os.remove(filename)
    plt.clf()
    plt.close()
    embed = Embed(title=f"Linear graph for country {name}", color=Color.blue())
    embed.set_image(url="attachment://plot.png")
    embed.set_footer(text=send_banner(), icon_url=ctx.author.avatar_url)
    if num == -1:
        return discord_file
    embed.add_field(
        name="Bot Invite Link",
        value=
        "[:envelope: Invite](https://discordapp.com/oauth2/authorize?client_id=694820915669893201&permissions=392257&scope=bot)",
        inline=True)
    embed.add_field(
        name="Bot Source code",
        value=
        "[:tools: GitHub](https://github.com/pseudocoder10/Covid19-Tracker)",
        inline=True)
    embed.add_field(
        name="Vote for me",
        value=
        "[:first_place: top.gg](https://top.gg/bot/694820915669893201/vote)",
        inline=True)
    await ctx.channel.send(embed=embed, file=discord_file)
    if num == 0:
        return

    plt.plot(x_axis,
             cases,
             color='yellow',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='yellow',
             label="Total Cases")
    plt.plot(x_axis,
             recovery,
             color='green',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='green',
             label="Total Recoveries")
    plt.plot(x_axis,
             deaths,
             color='red',
             linestyle='-',
             marker='o',
             markersize=4,
             markerfacecolor='red',
             label="Total Deaths")

    plt.gcf().autofmt_xdate()
    plt.grid()
    plt.legend()
    ax = plt.axes()
    ax.set_yscale('log')
    plt.setp(ax.get_xticklabels(), color="white")
    plt.setp(ax.get_yticklabels(), color="white")
    filename = "%s.png" % str(ctx.message.id)
    plt.savefig(filename, transparent=True)
    with open(filename, 'rb') as file:
        discord_file = File(BytesIO(file.read()), filename='plot.png')
    os.remove(filename)
    plt.clf()
    plt.close()
    embed = Embed(title=f"Logarithmic graph for country {name}",
                  color=Color.blue())
    embed.set_image(url="attachment://plot.png")
    embed.add_field(
        name="Bot Invite Link",
        value=
        "[:envelope: Invite](https://discordapp.com/oauth2/authorize?client_id=694820915669893201&permissions=392257&scope=bot)",
        inline=True)
    embed.add_field(
        name="Bot Source code",
        value=
        "[:tools: GitHub](https://github.com/pseudocoder10/Covid19-Tracker)",
        inline=True)
    embed.add_field(
        name="Vote for me",
        value=
        "[:first_place: top.gg](https://top.gg/bot/694820915669893201/vote)",
        inline=True)
    embed.set_footer(text=send_banner(), icon_url=ctx.author.avatar_url)
    await ctx.channel.send(embed=embed, file=discord_file)
Beispiel #21
0
    async def handle_new_message(self, smessage):
        if isinstance(smessage.channel, PrivateChannel):
            return

        url = await self.get_long_url(smessage.content)
        vmessage = self.get_vmessage(smessage)

        if vmessage:
            if url == vmessage.src_url:
                # message looks handled already
                return

            # url changed - delete old embed, start over
            vmessage.delete()

        if not url:
            # no url to handle
            return

        logging.info(f'url "{url}" detected...')

        vmessage = self.bot.database.VRedditMessage()
        vmessage.src_url = url
        vmessage.channel_did = smessage.channel.id
        vmessage.src_message_did = smessage.id
        vmessage.save()

        async with RedditVideo(url, self.settings.temp_directory) as video:
            try:
                await video.populate()
            except PostError:
                logging.info('No video found')
                return vmessage.delete()

            with smessage.channel.typing():
                filename = await video.get_video_file(max_file_size=8)
                if not filename:
                    # no video at this url
                    return vmessage.delete()

                if not vmessage.exists():
                    # check that nothing's changed since we started
                    return

                dmessage = await smessage.channel.send(
                    file=File(filename,
                              filename='reddit.mp4',
                              spoiler=video.spoiler or video.quarantine
                              or video.nsfw),
                    embed=self.get_embed(smessage, video))

        if vmessage.exists():
            vmessage.dest_message_did = dmessage.id
            vmessage.save()

            await asyncio.gather(dmessage.add_reaction('❌'),
                                 smessage.edit(suppress=True))

        else:
            # dang it, link deleted while we're uploading!
            await dmessage.delete()
Beispiel #22
0
async def chess_start(ctx):
    game.init()
    await ctx.send(file=File(game.png()))
Beispiel #23
0
 async def pdf(self, ctx):
     await ctx.send(file=File("deepwork.pdf"))
Beispiel #24
0
async def print_board(ctx):
    await ctx.send(file=File(game.png()))
Beispiel #25
0
    async def on_message(self, message):
        if not message.author.bot:
            if len(message.content) != 0:
                messageConverter = message.content.split()[0].lower()
                messageLower = message.content.lower()
            else:
                return
            try:
                if message.channel.guild.id == 285121209027264512:  # smro guild id
                    if not message.channel.guild.id in self.blacklistedAutoReplyChannels:
                        joinTime = message.author.joined_at
                        currentTime = datetime.now()
                        memberAge = currentTime - joinTime

                        greetingTags = ['hi', 'henyo', 'hello', 'hey']
                        helpTags = ['help', 'new', 'where', 'please']

                        if memberAge.days < 7 and any(
                                tags in messageLower
                                for tags in greetingTags) and any(
                                    tags in messageLower for tags in helpTags):
                            await message.channel.send(
                                f'Heya {message.author.mention}! \nForum Guides Section: https://www.shining-moon.com/ipb/index.php?/forum/45-guides/ \nHelheim Guide Section: https://www.shining-moon.com/ipb/index.php?/forum/82-helheim/ \nNiflheim Guide Section: https://www.shining-moon.com/ipb/index.php?/forum/58-niflheim/ \n\nFor build, equipment or any other guides check out the forum! \nNote: To access a major chunk of the forum you need a separate forum ID.',
                                delete_after=60)
            except AttributeError:
                print('A new SMRO member messaged in my DMs')

            if messageConverter == 'bye':
                await message.channel.send(f'Bye {message.author.mention}~~~')
            if messageConverter == 'revolution':
                await message.channel.send(
                    content='RISE UP BROTHERS!!',
                    file=File('./data/images/deuxvultchimkin.png'))

            if len(message.content) != 12:
                bestClassTags = ['best', 'class', 'start']
                fourthJobTags = ['4th', 'job', 'when']
                himmelCardTags = ['himmelmez', 'card', 'where', 'get']
                tempCircTags = ['temporal', 'circlet', 'when']
                resetEnchantTags = ['how', 'to', 'reset', 'enchant', 'of']
                homunAITags = ['homunculus', 'ai', 'not', 'working']

                if all(tags in messageLower for tags in bestClassTags):
                    await message.channel.send(
                        'Start with rebel! Easiest class to gear, level and fast zeny farm \n Guides: *make sure you have a forum ID to view these guides* \nNiflheim: https://www.shining-moon.com/ipb/index.php?/topic/8113-budget-rebel-for-farm/',
                        delete_after=20)

                if all(tags in messageLower for tags in fourthJobTags):
                    await message.channel.send(
                        'It\'s coming sooner than you think! Hold on to your seats little egglings we are on our way to <:SM2099:678243126812344332>',
                        delete_after=10)

                if all(tags in messageLower for tags in himmelCardTags):
                    await message.channel.send(
                        'Currently only obtainable from ECA <:SMeca:668824453588844554>\n Later available from Old Glast Heim Challenge Mode instance when it will be implemented (No ETA)',
                        delete_after=10)

                if all(tags in messageLower for tags in tempCircTags):
                    await message.channel.send(
                        'Available from Old Glast Heim Challenge Mode instance when it will be implemented (No ETA)',
                        delete_after=10)

                if all(tags in messageLower for tags in resetEnchantTags):
                    await message.channel.send(
                        'Most enchants that use the Lapine Box UI for enchants can be reset by using the same item again \nFor more details about enchanting check here: https://www.shining-moon.com/helheim/index.php/Lapine_Enchanting',
                        delete_after=10)

                if all(tags in messageLower for tags in homunAITags):
                    await message.channel.send(
                        'Homunculus AI was disabled in a kRO patch by kRO itself and thus we do not have it since we are on that patch. Homunculus AI returned in a later patch which is going to be the next update to SMRO.',
                        delete_after=180)
Beispiel #26
0
    async def ev(self, ctx: Context, *, content: str):
        '''
        Evaluates some Python code

        Gracefully stolen from Rapptz -> 
        https://github.com/Rapptz/RoboDanny/blob/rewrite/cogs/admin.py#L72-L117
        '''

        # Make the environment
        env = {
            'bot': self.bot,
            'ctx': ctx,
            'channel': ctx.channel,
            'author': ctx.author,
            'guild': ctx.guild,
            'message': ctx.message,
            '_': self._last_result,
            'self': self,
        }
        env.update(globals())

        # Make code and output string
        content = self.cleanup_code(content)
        stdout = StringIO()
        to_compile = f'async def func():\n{indent(content, "  ")}'

        # Make the function into existence
        try:
            exec(to_compile, env)
        except Exception as e:
            return await ctx.send(f'```py\n{e.__class__.__name__}: {e}\n```')

        # Grab the function we just made and run it
        func = env['func']
        try:
            # Shove stdout into StringIO
            with redirect_stdout(stdout):
                ret = await func()
        except Exception as e:
            # Oh no it caused an error
            value = stdout.getvalue()
            await ctx.send(f'```py\n{value}{format_exc()}\n```')
        else:
            # Oh no it didn't cause an error
            value = stdout.getvalue()

            # Give reaction just to show that it ran
            try:
                await ctx.message.add_reaction('\u2705')
            except:
                pass

            # If the function returned nothing
            if ret is None:
                # It might have printed something
                if value:
                    await ctx.send(f'```py\n{value}\n```')

            # If the function did return a value
            else:
                self._last_result = ret
                text = f'```py\n{value}{ret}\n```'
                if len(text) > 2000:
                    return await ctx.send(
                        file=File(StringIO('\n'.join(text.split('\n')[1:-1])),
                                  filename='ev.txt'))
                await ctx.send(text)
Beispiel #27
0
async def send_dccon(ctx, *args):
    log(from_text(ctx), 'send_dccon command')

    if not args or len(args) > 2:
        log(from_text(ctx), 'empty args')
        await ctx.channel.send(f'사용법을 참고해주세요. ({COMMAND_PREFIX}도움)')
        await ctx.channel.send('디시콘 패키지명이나 디시콘명에 공백이 있을 경우 큰따옴표로 묶어야 합니다.')
        return

    list_print_mode = False
    package_name = args[0]
    idx = 'list_print_mode'
    if len(args) == 2:
        idx = args[1]
    else:
        list_print_mode = True

    log(
        from_text(ctx),
        f'interpreted: {package_name}, {idx}. list_print_mode: {list_print_mode}'
    )

    ############################################################################################################
    # respect https://github.com/gw1021/dccon-downloader/blob/master/python/app.py#L7:L18

    # TODO: 변수명 간단히

    s = requests.Session()

    package_search_req = s.get(DCCON_SEARCH_URL + package_name)
    package_search_html = BeautifulSoup(package_search_req.text, 'html.parser')
    package_search_list = package_search_html.select(
        '#right_cont_wrap > div > div.dccon_listbox > ul > li')

    try:
        # pick first dccon package (bs4 obj) from search list
        target_package = package_search_list[0]
    except IndexError as e:  # maybe no search result w/ IndexError?
        log(from_text(ctx), 'error! (maybe no search result) : ' + str(e))
        await ctx.channel.send(f'"{package_name}" 디시콘 패키지 정보를 찾을 수 없습니다.')
    else:
        # get dccon number of target dccon package
        target_package_num = target_package.get('package_idx')
        log(from_text(ctx), 'processing with: ' + target_package_num)

        # for i in package_search_req.cookies:
        #     print(i.name, i.value)

        package_detail_req = s.post(
            DCCON_DETAILS_URL,
            # content-type: application/x-www-form-urlencoded; charset=UTF-8
            cookies={
                'ci_c': package_search_req.cookies['ci_c'],
                'PHPSESSID': package_search_req.cookies['PHPSESSID']
            },
            headers={
                'Content-Type':
                'application/x-www-form-urlencoded; charset=UTF-8',
                'Referer':
                DCCON_SEARCH_URL + str(package_name.encode('utf-8')),
                'Origin': DCCON_HOME_URL,
                'X-Requested-With': 'XMLHttpRequest'
            },
            data={
                'ci_t': package_search_req.cookies['ci_c'],
                'package_idx': target_package_num,
                'code': ''
            })

        # 에러 핸들링 여기서 해야함

        package_detail_json = package_detail_req.json()
        '''
            info /  'package_idx'
                    'seller_no'
                    'seller_id'
                    'title'
                    'category'
                    'path'
                    'description'
                    'price'
                    'period'
                    'icon_cnt'
                    'state'
                    'open'
                    'sale_count'
                    'reg_date'
                    'seller_name'
                    'code'
                    'seller_type'
                    'mandoo'
                    'main_img_path'
                    'list_img_path'
                    'reg_date_short'
                    
            detail /  () /  'idx'
                            'package_idx'
                            'title'
                            'sort'
                            'ext'
                            'path'
        '''

        # 검색 결과로 바꿔치기
        package_name = package_detail_json['info']['title']

        if list_print_mode:
            available_dccon_list = []
            for dccon in package_detail_json['detail']:
                available_dccon_list.append(dccon['title'])

            await ctx.channel.send(f'"{package_name}"에서 사용 가능한 디시콘 : ' +
                                   ', '.join(available_dccon_list).rstrip(', ')
                                   )
        else:
            succeed = False
            for dccon in package_detail_json['detail']:
                if dccon['title'] == idx:
                    dccon_img = "http://dcimg5.dcinside.com/dccon.php?no=" + \
                        dccon['path']
                    dccon_img_request = s.get(
                        dccon_img, headers={'Referer': DCCON_HOME_URL})

                    buffer = BytesIO(dccon_img_request.content)
                    filename = package_name + '_' + \
                        dccon['title'] + '.' + dccon['ext']

                    await ctx.channel.send(file=File(buffer, filename))
                    succeed = True
                    break

            if succeed:
                log(from_text(ctx), 'succeed')
            else:
                log(from_text(ctx), 'not found')

                await ctx.channel.send(
                    f'"{package_name}" 디시콘 패키지에서 "{idx}" 디시콘을 찾지 못했습니다.')
                await ctx.channel.send(
                    '인자로 패키지 이름만 넘길 경우 사용 가능한 디시콘 목록이 출력됩니다.')
    async def praise_audit(self, ctx: Context, after: str = None):
        await ctx.send(
            f"Fetching all the Praise from {ctx.guild.name} for the Audit..."
        )

        if after:
            dates = [int(char) for char in after.split("-")]
            after = datetime(dates[2], dates[1], dates[0])
        else:
            # praise from server creation date
            after = ctx.guild.created_at

        clean_msgs = [["To", "From", "Reason for Dishing", "Server", "Date", "Room"]]
        msg_logs = dict()
        praise_duration = f"from {after.strftime('%b-%d-%Y')}"
        # Ignore these channels, to reduce API calls
        # TODO: Re-implement this list to be more DRY, and be located in a config file
        skip_channels = [
            810183289863798815,  # join-here (TEC)
            831938823172653076,  # announcements (TEC)
            810180622336262197,  # tec-tokenholders
            810180622966325296,  # ECOSYSTEM
            810180622966325291,  # ECOSYSTEM
            810180622966325292,  # ECOSYSTEM
            810180622966325293,  # ECOSYSTEM
            810180622966325294,  # ECOSYSTEM
            810180622966325295,  # ECOSYSTEM
            857623810455109692,  # ECOSYSTEM
            778081852492873758,  # rules (CS)
            780557396778549330,  # announcements (CS)
            824917827831595028,  # claim-a-role (CS)
            778081852492873759,  # moderator-only (CS)
            778085977125158922,  # system-messages (CS)
            801882792942239818,  # praise-testing (CS)
        ]

        await ctx.send(f"Attempting to get praise {praise_duration}")
        for channel in ctx.guild.text_channels:

            await sleep(5)

            try:
                if channel.id in skip_channels:
                    await ctx.send(f"Skipping {channel.name}")
                    log.info(f"Skipping {channel.name} from praise-audit")
                else:
                    await ctx.send(f"Attempting to get praise in {channel.name}")
                    log.info(
                        f"Attempting to get praise in {channel.name} {praise_duration}"
                    )

                async for msg in channel.history(after=after, limit=None):
                    if msg.content.startswith("!praise"):
                        for person in msg.mentions:
                            timestamp = msg.created_at.strftime("%b-%d-%Y")
                            info = [
                                person.name + "#" + person.discriminator,
                                msg.author.name + "#" + msg.author.discriminator,
                                re.sub(
                                    r"(<@).*?>",
                                    "",
                                    utils.escape_mentions(msg.content)[8:],
                                )
                                .strip()
                                .replace("\n", " "),
                                msg.guild.name,
                                timestamp,
                                msg.channel.name,
                            ]
                            if timestamp not in msg_logs:
                                msg_logs[timestamp] = []

                            msg_logs[timestamp].append(info)
                            log.info(
                                f"Adding praise for: {person.name} - {msg.channel.name}"
                            )
            except Forbidden:
                log.error(
                    f"Missing perms... Skipping praise scraping from channel - {channel.name}"
                )
                continue
            else:
                continue

        for date in sorted(
            msg_logs.keys(), key=lambda x: datetime.strptime(x, "%b-%d-%Y")
        ):
            for msg_data in msg_logs[date]:
                clean_msgs.append(msg_data)

        with open(f"praise_audit_{ctx.guild.id}.csv", "w") as f:
            try:
                writer = csv.writer(f)
                log.info("Writing Praise...")
                writer.writerows(clean_msgs)
            except Exception as e:
                log.error(f"Error in writing Praise: {e}")

            log.info("Praise successfully written!")
        await ctx.send("Praise collected and written!")
        await ctx.send(
            f"Praise written! Here's all of the Praise in the server for the audit",
            file=File(
                f"praise_audit_{ctx.guild.id}.csv", f"{ctx.guild.name} praise.csv"
            ),
        )
Beispiel #29
0
    async def on_message(self, message, **kwargs):
        trans = self.trans
        mc = self.mc

        prefix = kwargs.get("prefix")
        lang = kwargs.get("lang")

        # Check if this is a valid command
        if not is_valid_command(message.content, commands, prefix):
            return
        else:
            self.stats.add(MESSAGE)

        def startswith(*matches):
            for match in matches:
                if message.content.startswith(match):
                    return True

            return False

        # !mc
        if startswith(prefix + "mc"):
            argument = message.content[len(prefix + "mc "):].strip(" ").lower()

            if not argument:
                await message.channel.send(trans.get("MSG_MC_PLSARUGMENTS", lang))
                return

            # !mc help
            if argument == "help":
                await message.channel.send(trans.get("MSG_MC_HELP", lang).replace("_", prefix))
                return

            # Argument is name
            if not is_number(argument.split(":")[0]):
                # Check for groupings
                gr = mc.get_group_by_name(argument)
                if gr:
                    data = gr
                # Not a group
                else:
                    data = mc.find_by_name(str(argument))

            # Argument is id and meta
            else:
                try:
                    i_type, i_meta = argument.split(":")
                except ValueError:
                    i_type, i_meta = argument, 0

                data = mc.find_by_id_meta(i_type, i_meta)

            if not data:
                await message.channel.send(trans.get("MSG_MC_NO_ITEMS", lang))
                self.stats.add(WRONG_ARG)
                return

            # One item, not a group
            if not isinstance(data, list):
                details = trans.get("MSG_MC_DETAILS", lang).format(data.get("name"), data.get("type"), data.get("meta"))

                # Details are uploaded simultaneously with the picture

                # No image
                path = mc.get_picture_path_by_item(data)
                if not path:
                    await message.channel.send(details)
                    self.stats.add(IMAGE_SENT)
                else:
                    with open(mc.get_picture_path_by_item(data), "rb") as pic:
                        await message.channel.send(details, file=File(pic))
                        self.stats.add(IMAGE_SENT)

            # Multiple items, a group
            else:
                combined = []
                for item in data:
                    details = trans.get("MSG_MC_DETAILS", lang).format(item.get("name"), item.get("type"), item.get("meta"))
                    combined.append(details)

                await message.channel.send("".join(combined))
Beispiel #30
0
 async def digipee(self, ctx):
     logger.log(EGG, f"{ctx.author.display_name} thinks Digi needs to pee.")
     with pkg_resources.open_binary(sizebot.data, "digipee.mp3") as f:
         # PERMISSION: requires attach_file
         await ctx.send(f"<@{ids.digiduncan}> also has to pee.",
                        file=File(f, "digipee.mp3"))