async def medal(self, ctx, *, medal_name): """ Exibe detalhes de uma medalha da Star Wars Wiki """ await ctx.trigger_typing() try: leaderboard_data = await self.leaderboard_bot.get() medals = await self.leaderboard_bot.build_medals_info(*leaderboard_data) medal_info = [medal for medal in medals if medal['name'] == medal_name] if not medal_info: return await ctx.send(i(ctx, "Medal not found")) medal_info = medal_info[0] embed = discord.Embed( title=i(ctx, "Star Wars Wiki's medals"), description=medal_info['name'], colour=discord.Color.blurple(), timestamp=ctx.message.created_at ) embed.set_thumbnail(url=medal_info['image_url']) embed.add_field(name=i(ctx, 'Description'), value=medal_info['text']) embed.add_field(name=i(ctx, 'Points'), value=medal_info['points']) await ctx.send(embed=embed) except Exception as e: logging.warning(e, exc_info=True) return await ctx.send(i(ctx, "Something went wrong when trying to fetch Star Wars Wiki's leaderboard"))
async def xadrez_jogar(self, ctx, move, *, game): """ Faça uma jogada em sua partida atual Use anotação SAN ou UCI. Movimentos inválidos ou ambíguos são rejeitados. {user2_doc} """ async with ctx.channel.typing(): try: game = await self.chess_bot.make_move(game, move) except ChessException as e: return await ctx.send(i(ctx, e.message)) if self.chess_bot.is_game_over(game): pgn = self.chess_bot.generate_pgn(game) message = f'{i(ctx, "Game over!")}\n\n{pgn}' else: message = i(ctx, "That's your turn now, {}").format(game.current_player.name) board_png_bytes = self.chess_bot.build_png_board(game) await ctx.send( content=message, file=discord.File(board_png_bytes, 'board.png') ) evaluation = await self.chess_bot.eval_last_move(game) if evaluation["blunder"]: await ctx.send("👀") elif evaluation["mate_in"] and evaluation["mate_in"] in range(1, 4): sheev_msgs = [ i(ctx, "DEW IT!"), i(ctx, "Kill him! Kill him now!"), i(ctx, "Good, {username}, good!").format(username=game.current_player.name) ] await ctx.send(sheev_msgs[evaluation["mate_in"] - 1])
async def _new_item_confirmation_listener(self, reaction, user): confirm_emoji = '✅' cancel_emoji = '🚫' valid_emojis = [confirm_emoji, cancel_emoji] moderators_ids = os.environ.get('MODERATORS_IDS', '').split(',') if not reaction.message.embeds or reaction.message.author.id != self.client.user.id: return embed = reaction.message.embeds[0] if not (embed.title == i(reaction.message, 'New item suggestion') and str(user.id) in moderators_ids): return emoji = str(reaction) if emoji not in valid_emojis: return if emoji == confirm_emoji: profile_item = self.item_bot.build_profile_item( name=embed.description, price=next(int(field.value) for field in embed.fields if field.name == i(reaction.message, 'Price')), type=next(field.value for field in embed.fields if field.name == i(reaction.message, 'Type')) ) try: original_message = reaction.message.reference.cached_message if not original_message: original_message = await reaction.message.channel.fetch_message( reaction.message.reference.message_id) original_image = original_message.attachments[0] await self.item_bot.save_profile_item(profile_item, original_image.filename, await original_image.read()) result = i(reaction.message, 'New item added to the shop!') except discord.HTTPException: result = i(reaction.message, 'Could not find original message 😣') else: result = i(reaction.message, 'Operation canceled') await reaction.message.channel.send(content=f'{embed.author.name}: {result}')
async def _purchase_confirmation_listener(self, reaction, user): confirm_emoji = '✅' cancel_emoji = '🚫' valid_emojis = [confirm_emoji, cancel_emoji] if not reaction.message.embeds or reaction.message.author.id != self.client.user.id: return embed = reaction.message.embeds[0] if not (embed.title == i(reaction.message, 'Buy item') and str(user) == embed.author.name): return emoji = str(reaction) if emoji not in valid_emojis: return if emoji == confirm_emoji: try: economy_user = await self.palplatina.buy_item(user.id, embed.description) result = (i(reaction.message, 'Item bought. You now have {currency} palplatinas') .format(currency = economy_user.currency) ) except EconomyException as e: result = i(reaction.message, e.message) else: result = i(reaction.message, 'Operation canceled') await reaction.message.channel.send(content=f'{embed.author.name}: {result}')
async def comprar(self, ctx, *, profile_item_name): """ Compre um item para seu perfil Informe o nome do item que deseja comprar. Para que possa fazê-lo, é necessário \ que tenha palplatinas suficientes. """ profile_item = await self.palplatina.get_item(profile_item_name) if not profile_item: return await ctx.send(i(ctx, 'Item not found')) embed = discord.Embed( title=i(ctx, 'Buy item'), description=profile_item.name ) discord_file = None if profile_item.get_file_contents(): discord_file = discord.File(profile_item.file_path, 'item.png') embed.set_thumbnail(url="attachment://item.png") embed.set_author(name=ctx.author) embed.add_field(name=i(ctx, 'Price'), value=profile_item.price) embed.add_field(name=i(ctx, 'Your palplatinas'), value=await self.palplatina.get_currency(ctx.message.author.id)) message = await ctx.send(embed=embed, file=discord_file) await message.add_reaction('✅') await message.add_reaction('🚫')
async def profile_frame_color(self, ctx, color): try: await self.profile_bot.set_user_profile_frame_color( ctx.message.author.id, color) return await ctx.send( i(ctx, 'Profile color updated to {color}').format(color=color)) except ValueError: return await ctx.send(i(ctx, 'Invalid color'))
async def function_wrapper(this, ctx, *args, user2, **kwargs): try: game = this.chess_bot.find_current_game(ctx.author, user2) except MultipleGamesAtOnce as e: return await ctx.send(i(ctx, e.message).format(number_of_games=e.number_of_games)) except ChessException as e: return await ctx.send(i(ctx, e.message)) func_args = [this, ctx] + list(args) await func(*func_args, game=game, **kwargs)
async def send_astrology_triad(self, ctx, chart): sign = self.astrology_bot.get_sun_sign(chart) asc = self.astrology_bot.get_asc_sign(chart) moon = self.astrology_bot.get_moon_sign(chart) embed = discord.Embed(title=i(ctx, 'Your astrology chart'), description=i(ctx, 'Your astrology triad'), colour=discord.Color.blurple(), timestamp=ctx.message.created_at) embed.add_field(name=i(ctx, 'Solar sign'), value=sign) embed.add_field(name=i(ctx, 'Ascending sign'), value=asc) embed.add_field(name=i(ctx, 'Moon sign'), value=moon) await ctx.send(embed=embed)
async def xadrez_bot(self, ctx, cpu_level: int, color_schema=None): """ Inicie uma nova partida de xadrez contra o bot Passe o nível de dificuldade que desejar (de 0 a 20). \ Se quiser personalizar as cores do tabuleiro, passe o nome da cor que deseja usar \ (opções válidas: `blue`, `purple`, `green`, `red`, `gray` e `wood`). """ bot_info = await self.client.application_info() try: game = self.chess_bot.new_game( ctx.author, bot_info, cpu_level=cpu_level, color_schema=color_schema) await ctx.send(i(ctx, 'Game started! {}, play your move').format(game.player1.name)) except ChessException as e: await ctx.send(i(ctx, e.message))
async def itens(self, ctx): """ Veja os itens que você comprou """ user_profile_items = await self.palplatina.get_user_items(ctx.message.author.id) embed = discord.Embed( title=i(ctx, 'Your acquired items'), description=i(ctx, 'Browse through all your acquired items'), colour=discord.Color.green() ) for user_profile_item in user_profile_items: embed.add_field( name=user_profile_item.profile_item.name, value=i(ctx, 'Equipped') if user_profile_item.equipped else i(ctx, 'Not equipped') ) await ctx.send(embed=embed)
async def anime(self, ctx, *, query): """ Veja informações do anime buscado com MyAnimeList """ async with ctx.channel.typing(): try: result = self.anime_bot.get_anime(int(query)) except: try: search_result = self.anime_bot.search_anime(query)[0] result = self.anime_bot.get_anime( int(search_result["mal_id"])) except Exception as e: logging.warning(e, exc_info=True) return await ctx.send( i( ctx, "Something went wrong when searching for your anime" )) embed = discord.Embed(title=result.title, description=result.synopsis, colour=discord.Color.blurple(), timestamp=ctx.message.created_at, url=result.url) embed.set_image(url=result.image_url) embed.add_field(name='Type', value=result.type) embed.add_field(name='Genres', value=', '.join(result.genres)) embed.add_field(name='Score', value=result.score) embed.add_field(name='Num episodes', value=result.episodes) await ctx.send(embed=embed)
async def on_reaction_add(self, reaction, user): game = self.akinator_bot.get_user_game(user) message = reaction.message if not game or not message.embeds or message.author.id != self.client.user.id: return embed = message.embeds[0] if 'Akinator' not in embed.title or game.question != embed.description: return emoji = str(reaction) if emoji not in self.emoji_answers.values(): return answer = [k for k, v in self.emoji_answers.items() if v == emoji][0] async with message.channel.typing(): result = await self.akinator_bot.answer_question(game, answer) if isinstance(result, str): await self.send_embed(result, user, message.channel) else: self.akinator_bot.remove_user_game(user) embed = discord.Embed( title=i(message, "{username} thought of {name}").format( username=user.name, name=result.get("name")), description=result.get('description'), colour=discord.Color.blurple() ) embed.set_thumbnail(url=result.get('absolute_picture_path')) await message.channel.send(embed=embed)
async def _build_shop_embed(self, page_number, original_message, search_query=None): if search_query is None: search_query = ': '.join(original_message.content.split(': ')[1:]) profile_items, last_page = await self.palplatina.get_available_items(search_query, page_number-1) embed = discord.Embed( title=i(original_message, "Arnaldo's Emporium"), description=i(original_message, 'Browse through all available items'), colour=discord.Color.green() ) embed.set_thumbnail(url="attachment://hutt.gif") self.shop_paginated_embed_manager.last_page = last_page for profile_item in profile_items: embed.add_field( name=profile_item.name, value=f'{i(original_message, "Price")}: {profile_item.price}\n{i(original_message, "Type")}: {profile_item.type.name.capitalize()}' ) return embed
async def banco(self, ctx): """ Veja seu saldo de Palplatinas 💰 """ currency = await self.palplatina.get_currency(ctx.message.author.id) embed = discord.Embed( title=i(ctx, 'Daily!'), description=i(ctx, '{username} has {currency} palplatinas.').format( username=ctx.author.mention, currency=currency ), colour=discord.Color.greyple(), timestamp=ctx.message.created_at ) embed.set_thumbnail( url='https://cdn.discordapp.com/attachments/307920220406808576/800525198687731742/palplatina.png') await ctx.send(embed=embed)
async def _create_info_embed(self, ctx): bot_prefix = self.client.command_prefix bot_info = await self.client.application_info() bot_owner = bot_info.team.owner embed = discord.Embed(title=bot_info.name, description=bot_info.description, colour=discord.Color.blurple(), url=os.environ.get("BOT_HOMEPAGE")) embed.set_thumbnail(url=bot_info.icon_url) embed.add_field(name=i(ctx, 'Owner'), value=f'{bot_owner.name}#{bot_owner.discriminator}') if current_bot_version: embed.add_field(name=i(ctx, 'Current version'), value=current_bot_version) embed.add_field(name=i(ctx, 'Prefix'), value=bot_prefix) embed.add_field(name=i(ctx, 'Help cmd'), value=f'{bot_prefix}help') return embed
async def lang(self, ctx, language_code): """ Muda o idioma do bot no servidor atual Passe um código válido de idioma. Consulte os códigos válidos nesse link: \ https://www.gnu.org/software/gettext/manual/html_node/Usual-Language-Codes.html """ await cache.update_config(ctx.guild.id, language=language_code) return await ctx.send( i(ctx, 'Language updated to {lang}').format(lang=language_code))
async def xadrez_gif(self, ctx, game_id: str, move_number: int, *moves): """ Exibe um GIF animado com uma variante fornecida para o jogo em questão, a partir do lance fornecido É necessário passar o jogo em questão, identificado com seu UUID, e o número do lance a partir do qual \ a sequência fornecida se inicia, que deve ser uma sequência de lances em UCI ou SAN separados por espaço. Exemplo de uso: `xgif f63e5e4f-dd94-4439-a283-33a1c1a065a0 11 Nxf5 Qxf5 Qxf5 gxf5` """ async with ctx.channel.typing(): chess_game = await self.chess_bot.get_game_by_id(game_id) if not chess_game: return await ctx.send(i(ctx, "Game not found")) gif_bytes = await self.chess_bot.build_animated_sequence_gif( chess_game, move_number, moves) if not gif_bytes: return await ctx.send(i(ctx, "Invalid move for the given sequence")) return await ctx.send(file=discord.File(gif_bytes, 'variation.gif'))
async def xadrez_novo(self, ctx, user2: discord.User, color_schema=None): """ Inicie uma nova partida de xadrez com alguém Passe o usuário contra o qual deseja jogar para começar uma partida. \ Se quiser personalizar as cores do tabuleiro, passe o nome da cor que deseja usar \ (opções válidas: `blue`, `purple`, `green`, `red`, `gray` e `wood`). """ bot_info = await self.client.application_info() if user2.id == bot_info.id: return await ctx.send( i(ctx, "In order to play a game against the bot, use the command `{prefix}xadrez_bot`") .format(prefix=self.client.command_prefix) ) try: game = self.chess_bot.new_game(ctx.author, user2, color_schema=color_schema) await ctx.send(i(ctx, 'Game started! {}, play your move').format(game.player1.name)) except ChessException as e: await ctx.send(i(ctx, e.message))
async def gato(self, ctx): """ Mostra uma foto aleatória de gato 🐈 """ await ctx.trigger_typing() image_url = await random_cat() if not image_url: return await ctx.send(i(ctx, "Could not find a cat picture 😢")) embed = discord.Embed(title="Gato") embed.set_image(url=image_url) await ctx.send(embed=embed)
async def medals(self, ctx, page: int=1): """ Exibe as medalhas disponíveis da Star Wars Wiki """ await ctx.trigger_typing() try: return await self.medals_paginated_embed_manager.send_embed( await self._build_medals_embed(page, ctx), page, ctx) except Exception as e: logging.warning(e, exc_info=True) return await ctx.send(i(ctx, "Something went wrong when trying to fetch Star Wars Wiki's leaderboard"))
async def voto(self, ctx, *, args): """ Cria uma votação para as demais pessoas participarem A pergunta e as opções devem ser separadas por `;`. Você pode criar votações \ com até dez opções. Exemplo: `voto Quem é o melhor lorde Sith?;Darth Sidious;Darth Vader;Darth Tyranus` """ emoji_answers_vote = [ '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟' ] choices_limit = len(emoji_answers_vote) + 1 options = args.split(';') question = options[0] choices = options[1:choices_limit] embed = discord.Embed(title=i(ctx, 'Vote'), description=i( ctx, 'Vote on your colleague\'s proposition!'), colour=discord.Color.red()) embed.set_thumbnail( url= "https://cdn.discordapp.com/attachments/676574583083499532/752314249610657932/1280px-Flag_of_the_Galactic_Republic.png" ) embed.add_field( name=i(ctx, 'Democracy!'), value=i( ctx, 'I love democracy! {username} has summoned a vote! The proposition is **{question}**, and its options are:\n{options}' ).format(username=ctx.message.author.mention, question=question, options=''.join([ f'\n{emoji} - {choice}' for emoji, choice in zip(emoji_answers_vote, choices) ]))) response_msg = await ctx.send(embed=embed) for emoji in emoji_answers_vote[:len(choices)]: await response_msg.add_reaction(emoji)
async def loja(self, ctx, *, search_query=''): """ Veja os itens disponíveis para serem adquiridos """ page_number = 1 discord_file = discord.File( os.path.join('bot', 'images', 'arnaldo-o-hutt.gif'), 'hutt.gif') shop_embed = await self._build_shop_embed(page_number, ctx, search_query=search_query) await self.shop_paginated_embed_manager.send_embed( shop_embed, page_number, ctx, discord_file=discord_file, content=i(ctx, 'Results for: {}').format(search_query) )
async def xadrez_todos(self, ctx, page: int=0): """ Veja todas as partidas que estão sendo jogadas agora """ async with ctx.channel.typing(): png_bytes = await self.chess_bot.get_all_boards_png(page) if not png_bytes: await ctx.send( i(ctx, "No game is being played currently... ☹️ Start a new one with `{prefix}!xadrez_novo`") .format(prefix=self.client.command_prefix) ) else: await ctx.send(file=discord.File(png_bytes, 'boards.png'))
async def mapa_astral(self, ctx, date=None, time=None, *, city_name=None): """ Visualize ou crie via DM seu mapa astral Para criar seu mapa astral, envie esse comando em DM para o bot informando \ a data, hora e local de seu nascimento da seguinte forma: \ `YYYY/mm/dd HH:MM Nome da cidade`. Se já tiver criado seu mapa astral, envie esse comando sem argumentos para \ visualizá-lo em qualquer canal. Exemplo de uso para criação de mapa astral: `mapa_astral 2000/15/01 12:00 Brasília` Exemplo de uso para visualização de mapa criado: `mapa_astral` """ if not isinstance(ctx.channel, discord.channel.DMChannel): user_chart = await self.astrology_bot.get_user_chart(ctx.author.id) if not user_chart: return await ctx.send( i( ctx, 'You have not yet created your astrology chart. In order to do so, send this command to my DM 😁' )) return await self.send_astrology_triad(ctx, user_chart) try: await ctx.trigger_typing() chart = await self.astrology_bot.calc_chart( ctx.author.id, date, time, city_name) await self.astrology_bot.save_chart(ctx.author.id, chart) except AstrologyInvalidInput as e: return await ctx.send(i(ctx, e.message)) except Exception as e: logging.warning(e, exc_info=True) return await ctx.send( i( ctx, 'There has been a momentary failure. Please try again in a few moments. If this error persists, then this might be a bug 😬' )) await self.send_astrology_triad(ctx, chart)
async def daily(self, ctx): """ Receba sua recompensa diária em Palplatinas 🤑 """ received_daily, user = await self.palplatina.give_daily( ctx.message.author.id, ctx.message.author.name) if received_daily: palplatinas_embed = discord.Embed( title=i(ctx, 'Daily!'), description=i(ctx, 'You have received 300 palplatinas, enjoy!'), colour=discord.Color.greyple(), timestamp=ctx.message.created_at ) else: palplatinas_embed = discord.Embed( title=i(ctx, 'Daily!'), description=i(ctx, 'You have alredy collected your daily today. Ambition leads to the dark side of the Force, I like it.'), colour=discord.Color.greyple(), timestamp=user.daily_last_collected_at ) palplatinas_embed.set_thumbnail(url='https://cdn.discordapp.com/attachments/307920220406808576/800525198687731742/palplatina.png') palplatinas_embed.set_author(name=ctx.message.author) await ctx.send(embed=palplatinas_embed)
async def profile(self, ctx, user: discord.User = None): """ Exibe o seu perfil ou de um usuário informado """ await ctx.trigger_typing() selected_user = user if user else ctx.message.author user_avatar = await selected_user.avatar_url_as( size=128, static_format='png').read() image = await self.profile_bot.get_user_profile( selected_user.id, user_avatar, get_server_lang(ctx.message.guild.id)) if not image: return await ctx.send(i(ctx, 'Who are you?')) await ctx.send(file=discord.File(image, 'perfil.png'))
async def leaderboard(self, ctx, page: int=1): """ Exibe o leaderboard de medalhas da Star Wars Wiki """ await ctx.trigger_typing() try: leaderboard_data = await self.leaderboard_bot.get() leaderboard_result = self.leaderboard_bot.build_leaderboard(*leaderboard_data) leaderboard_img = await self.leaderboard_bot.draw_leaderboard(leaderboard_result, page) await ctx.send(file=discord.File(leaderboard_img, 'leaderboard.png')) except Exception as e: logging.warning(e, exc_info=True) return await ctx.send(i(ctx, "Something went wrong when trying to fetch Star Wars Wiki's leaderboard"))
async def xadrez_abandonar(self, ctx, *, game): """ Abandone a partida atual {user2_doc} """ async with ctx.channel.typing(): game = await self.chess_bot.resign(game) pgn = self.chess_bot.generate_pgn(game) board_png_bytes = self.chess_bot.build_png_board(game) await ctx.send( content=i(ctx, '{} has abandoned the game!').format(game.current_player.name)+f'\n{pgn}', file=discord.File(board_png_bytes, 'board.png') )
async def planetas(self, ctx, *, region=None): """ Lista todos os planetas disponíveis da região fornecida """ discord_file = discord.File( os.path.join('bot', 'images', 'arnaldo-o-hutt.gif'), 'hutt.gif') planets = await self.planets.list_of_planets(region=region) embed = discord.Embed( title=i(ctx, "Arnaldo's Emporium"), description=i(ctx, "Become a planet's senator"), colour=discord.Color.green() ) embed.set_thumbnail(url="attachment://hutt.gif") for planet in planets: embed.add_field( name=planet.name, value=f'{i(ctx, "Price")}: {planet.price}\n{i(ctx, "Region")}: {planet.region}\n'\ f'{i(ctx, "Climate")}: {planet.climate}\n{i(ctx, "Circuference")}: {planet.circuference}' ) await ctx.reply(embed=embed, file=discord_file, mention_author=False)
async def xadrez_puzzle(self, ctx, puzzle_id=None, move=''): """ Pratique um puzzle de xadrez Envie o comando sem argumentos para um novo puzzle. Para tentar uma jogada em um puzzle, \ envie o ID do puzzle como primeiro argumento e a jogada como segundo. Exemplo de novo puzzle: `xadrez_puzzle` Exemplo de jogada em puzzle existente: `xadrez_puzzle 557b7aa7e13823b82b9bc1e9 Qa2` """ await ctx.trigger_typing() if not puzzle_id: puzzle_dict = await self.puzzle_bot.get_random_puzzle() if 'error' in puzzle_dict: return await ctx.send( f'{i(ctx, "There has been an error when trying to fetch a new puzzle")}: {puzzle_dict["error"]}') puzzle = self.puzzle_bot.build_puzzle(puzzle_dict) if 'error' in puzzle: return await ctx.send( f'{i(ctx, "There has been an error when trying to build a new puzzle")}: {puzzle["error"]}') return await ctx.send(puzzle["id"], file=discord.File(self.chess_bot.build_png_board(puzzle["game"]), 'puzzle.png')) try: puzzle_result = self.puzzle_bot.validate_puzzle_move(puzzle_id, move) except ChessException as e: return await ctx.send(i(ctx, e.message)) if puzzle_result: if self.puzzle_bot.is_puzzle_over(puzzle_id): return await ctx.send(i(ctx, "Good job, puzzle solved 👍")) if puzzle_result or move == '': return await ctx.send(file=discord.File( self.chess_bot.build_png_board( self.puzzle_bot.puzzles[puzzle_id]["game"]), 'puzzle.png') ) return await ctx.send(i(ctx, "Wrong answer"))