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
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)
async def send_as_attachment(self, ctx, content=""): return await ctx.send(content=content, file=File(self.get_buffer(), "image.png"))
async def pull_meme(self, ctx): img = choice(glob('./data/smemes/*.jpg')) await ctx.send(file=File(img))
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)))
def file_from_data_stream(data_stream): chart_file = File(data_stream, filename="pie_chart.png") data_stream.seek(0)
def discord_file(path, name, spoiler): return File(BytesIO(read_b(path)), filename=name, spoiler=spoiler)
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}")
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)
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)
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!**", ))
def convert_file(b64, i): bytesio = BytesIO() bytesio.write(base64.b64decode(b64)) bytesio.seek(0) return File(bytesio, filename=f'output{i}.png')
def get_image(self, ctx, elements, image_path): if image_path: elements['file'] = File(image_path)
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.")
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)
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)
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)
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)
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)
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()
async def chess_start(ctx): game.init() await ctx.send(file=File(game.png()))
async def pdf(self, ctx): await ctx.send(file=File("deepwork.pdf"))
async def print_board(ctx): await ctx.send(file=File(game.png()))
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)
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)
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" ), )
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))
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"))