def _player_str(self, player: BSPlayer, sort='trophies'): """Player profile as plain text.""" avatar = self.get_avatar(player) o = [ '{}'.format(avatar), '{} #{}'.format(bold(player.name), player.tag), '{}, {} #{}'.format(player.club.role, player.club.name, player.club.tag) if player.club else 'No Clan', '{} {} / {}'.format(self.get_emoji('bstrophy'), player.trophies, player.highestTrophies), '{emoji} {time} Best time as Boss'.format( emoji=self.get_emoji('bossfight'), time=inline(player.bestTimeAsBoss)), '{emoji} {time} Best Robo Rumble time'.format( emoji=self.get_emoji('roborumble'), time=inline(player.bestRoboRumbleTime)), # victories '{normal} {solo} {duo}'.format( normal='{emoji} {value} {name}'.format( emoji=self.get_emoji('battlelog'), value=inline(player.victories), name='Victories'), solo='{emoji} {value} {name}'.format( emoji=self.get_emoji('showdown'), value=inline(player.soloShowdownVictories), name='Solo SD'), duo='{emoji} {value} {name}'.format( emoji=self.get_emoji('duoshowdown'), value=inline(player.duoShowdownVictories), name='Duo SD'), ), # brawler stats 'Brawlers: {}'.format(len(player.brawlers)), 'Trophy per Brawler Level: {:.2f}'.format( player.trophies / sum([b.level for b in player.brawlers])), 'Trophy per Brawler: {:.2f}'.format(player.trophies / len(player.brawlers)), ] # brawlers brawlers = player.brawlers.copy() if sort == 'level': brawlers.sort(key=lambda x: x.level, reverse=True) elif sort == 'trophy_by_level': brawlers.sort(key=lambda x: x.trophies / x.level, reverse=True) for b in brawlers or []: o.append( '{emoji} `\u2800{trophies: >3} Lvl {level: >2} {trophy_per_level: >2.2f}\u2800` {name}' .format( emoji=self.get_emoji(b.name.lower().replace(' ', '')), trophies=b.trophies, pb=b.highestTrophies, level=b.level, name=b.name, trophy_per_level=b.trophies / b.level, )) return '\n'.join(o)
async def rmmirror(self, ctx, source_channel_id: str, dest_channel_id: str, docheck: bool=True): """Remove mirroring between two channels.""" if docheck and (not self.bot.get_channel(source_channel_id) or not self.bot.get_channel(dest_channel_id)): await self.bot.say(inline('Check your channel IDs, or maybe the bot is not in those servers')) return self.settings.rm_mirrored_channel(source_channel_id, dest_channel_id) await self.bot.say(inline('Done'))
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) oneliner = "Error in command '{}' - {}: {}".format( ctx.command.qualified_name, type(error.original).__name__, str(error.original)) await ctx.bot.send_message(channel, inline(oneliner)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "That command is not " "available in DMs.") else: logger.exception(type(error).__name__, exc_info=error)
async def on_ready(): owner_cog = bot.get_cog('Owner') total_cogs = len(owner_cog._list_cogs()) users = len(set(bot.get_all_members())) servers = len(bot.servers) channels = len([c for c in bot.get_all_channels()]) if not hasattr(bot, "uptime"): bot.uptime = int(time.perf_counter()) if settings.login_type == "token" and Settings.owner == "BOT.TOKEN": await set_bot_owner() print('-------') print("{} is now online.".format(bot.user.name)) print('-------') print("CONNECTED TO:") print("{} servers".format(SERVERS)) print("{} channels".format(CHANNELS)) print("{} users".format(USERS)) print("\n{}/{} active cogs with {} commands".format( len(bot.cogs), total_cogs, len(bot.commands))) prefix_label = "Prefixes:" if len(bot.command_prefix) > 1 else "Prefix:" print("{} {}\n".format(prefix_label, " ".join(bot.command_prefix))) if settings.login_type == "TOKEN": print("------") print("Use this URL to bring your bot into a server:") url = await get_oauth.url() bot.oauth_url = url print(url) print("------") await bot.get_cog('OWNER').disable_commands() @bot.event async defon_command(command, ctx): pass @bot.event async def on_message (message): if user_allowed(message): await bot.process_commands(message) @bot.event async defon_command_error(error, ctx): channel = ctx.message.channel if instance(error, commands.MissingRequiredArgument): await send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): logger.exception("exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original)) oneliner = "Error in command '{}' - {}: {}".format( ctx.command.qualified_name, type(error.original).__name__, str(error.original)) await ctx.bot.send_message(channel, inline(oneliner)) elif isinstance(error, commands.CommandNotFound): pass
async def inactivemonitor(self, ctx, timeout: int): """Enable/disable the activity monitor on this channel. Timeout is in seconds. Set to 0 to disable. Set the timeout >0 to have the bot automatically append '_inactive' to the channel name when the oldest message in the channel is greater than the timeout. """ channel = ctx.message.channel server = channel.server has_permissions = channel.permissions_for(server.me).manage_channels if not has_permissions: await self.bot.say(inline('I need manage channel permissions to do this')) return self.settings.set_inactivity_monitor_channel(server.id, channel.id, timeout) await self.bot.say(inline('done'))
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_message( channel, "Commande: Un Argument Requis Est Manquant") await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): bot.send_message(channel, "Commande: Mauvais Argument") await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "Commande: Est désactivée") elif isinstance(error, commands.CommandInvokeError): # A bit hacky, couldn't find a better way no_dms = "Impossible d'envoyer un message à cette utilisateur" is_help_cmd = ctx.command.qualified_name == "Help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ( "Je n'ai pas pu vous envoyer le message d'aide en MP. Soit" " vous m'avez bloqué ou vous avez désactivé les MP dans ce serveur." ) await bot.send_message(channel, msg) return bot.logger.exception( "\n\nRED.py\n\nException in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ( "\n\nRED.py\n\nErreur dans la commande '{}'.\n\nVérifiez votre console ou " "fichier journal pour les détails." "".format(ctx.command.qualified_name)) log = ("Exception dans la commande '{}'\n" "".format(ctx.command.qualified_name)) log += "".join( traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): await bot.send_message(channel, "Commande: Non Trouvée") pass elif isinstance(error, commands.CheckFailure): await bot.send_message( channel, "Erreur: Vérification de vos droits/permissions\n") pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "Commande: Pas Disponible En MP.") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message( channel, "Commande: Mode Recharge. " "Réessayez dans {:.2f}s" "".format(error.retry_after)) else: #bot.logger.exception(type(error).__name__, exc_info=error) m = exception(type(error).__name__, exc_info=error) bot.logger.exception(type(error).__name__, exc_info=error) await bot.send_message(channel, ">>>" + m)
async def on_command_error(error, ctx): print( colored('Error in command ', 'red') + colored('$' + str(ctx.command), 'yellow') + colored(' in channel ', 'red') + colored(str(ctx.message.server), 'green') + colored('#' + str(ctx.message.channel), 'blue')) channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): # A bit hacky, couldn't find a better way no_dms = "Cannot send messages to this user" is_help_cmd = ctx.command.qualified_name == "help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ("I couldn't send the help message to you in DM. Either" " you blocked me or you disabled DMs in this server.") await bot.send_message(channel, msg) return bot.logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ("Error in command '{}'. Check your console or " "logs for details." "".format(ctx.command.qualified_name)) log = ("Exception in command '{}'\n" "".format(ctx.command.qualified_name)) log += "".join( traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "That command is not " "available in DMs.") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message( channel, "This command is on cooldown. " "Try again in {:.2f}s" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
def embed_members(self, server=None, results=None, p_args=None): """Results by members""" results = sorted(results, key=lambda x: x["timestamp"]) count = 10 if p_args.count is not None: count = p_args.count most_common_author_ids = Counter([r["doc"].author.id for r in results]).most_common(count) # split results in channel ids by count author_channels = nested_dict() for author_id, count in most_common_author_ids: channel_ids = [] for result in results: doc = result["doc"] if doc.author.id == author_id: channel_ids.append(doc.channel.id) author_channels[author_id] = Counter(channel_ids).most_common() # embed embed = discord.Embed(title="{}: User activity by messages".format( server.name), description=self.description(p_args), color=random_discord_color()) max_count = 0 for rank, (author_id, count) in enumerate(most_common_author_ids, 1): max_count = max(count, max_count) # author name author = server.get_member(author_id) if author is None: author_name = 'User {}'.format(author_id) else: author_name = server.get_member(author_id).display_name inline_chart = self.inline_barchart(count, max_count) # channels channel_str = ', '.join([ '{}: {}'.format(server.get_channel(cid), count) for cid, count in author_channels[author_id] ]) # output field_name = '{}. {}: {}'.format(rank, author_name, count) field_value = '{}\n{}'.format(inline(inline_chart), channel_str) embed.add_field(name=field_name, value=field_value, inline=False) return embed
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "Cette commande est désactivée.") elif isinstance(error, commands.CommandInvokeError): # A bit hacky, couldn't find a better way no_dms = "Impossible d'envoyer un message à ce membre" is_help_cmd = ctx.command.qualified_name == "help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ( "Je ne peux pas envoyer le message d'aide en MP. " "Soit vous m'avez bloqué, soit vous refusez les MP des membres de ce serveur." ) await bot.send_message(channel, msg) return bot.logger.exception("Exception dans '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ( "Exception dans '{}'. Consultez la console pour obtenir des détails." "".format(ctx.command.qualified_name)) log = ("Exception dans '{}'\n" "".format(ctx.command.qualified_name)) log += "".join( traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message( channel, "Cette commande n'est pas utilisable en MP.") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message( channel, "Cette commande est en cooldown. " "Réessayez dans {:.2f}s" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): # A bit hacky, couldn't find a better way no_dms = "Cannot send messages to this user" is_help_cmd = ctx.command.qualified_name == "help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ( "Nao consigo enviar mensagem de ajuda para voce" " voce pode ter me bloqueado ou desativado as mensagem diretas." ) await bot.send_message(channel, msg) return bot.logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ("Error in command '{}'. Check your console or " "logs for details." "".format(ctx.command.qualified_name)) log = ("Exception in command '{}'\n" "".format(ctx.command.qualified_name)) log += "".join( traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "Esse comando nao esta " "disponivel em DM") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message( channel, "Esse comando esta em cooldown " "Tente novamente em {:.2f}s" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
async def trade_info(self, ctx): """List DB info.""" server = ctx.message.server items = self.settings.get_trades(server.id) author_ids = [item.author_id for item in items] o = [] o.append("Total trades: {}".format(len(items))) o.append("Added by:") for author_id, count in Counter(author_ids).most_common(): o.append( inline("{name:<16} {count:>6}".format( name=server.get_member(author_id).name, count=count))) for page in pagify('\n'.join(o)): await self.bot.say(page)
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "Ta komenda jest wyłączona z użytku.") elif isinstance(error, commands.CommandInvokeError): # Znajdź mi lepszy sposób no_dms = "Cannot send messages to this user" is_help_cmd = ctx.command.qualified_name == "help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ("Nie mogłem ci wysłać priva" " zablokowałeś mnie :(, lub coś posżło nie tak.") await bot.send_message(channel, msg) return bot.logger.exception("Błąd w komendzie '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ("Błąd w komendzie '{}'. Sprawdź konsole, albo " "log dla detali." "".format(ctx.command.qualified_name)) log = ("Błąd w komendzie '{}'\n" "".format(ctx.command.qualified_name)) log += "".join( traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "Ta komenda nie " "działa na priv.") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message( channel, "Woah, zwolnij trochę. " "Spróbuj za {:.2f}s" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): # A bit hacky, couldn't find a better way no_dms = "Cannot send messages to this user" is_help_cmd = ctx.command.qualified_name == "help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ("I couldn't send the help message to you in DM. Either" " you blocked me or you disabled DMs in this server.") await bot.send_message(channel, msg) return bot.logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ("Error in command '{}'. Check your console or " "logs for details." "".format(ctx.command.qualified_name)) log = ("Exception in command '{}'\n" "".format(ctx.command.qualified_name)) log += "".join(traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "That command is not " "available in DMs.") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message(channel, "This command is on cooldown. " "Try again in {:.2f}s" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): # A bit hacky, couldn't find a better way no_dms = "Cannot send messages to this user" is_help_cmd = ctx.command.qualified_name == "help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ("I couldn't send the help message to you in DM. Either" " you blocked me or you disabled DMs in this server.") await bot.send_message(channel, msg) return bot.logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ("Quelque chose a mal tourné. Si le problème persiste, contactez l'auteur. ") log = ("Exception in command '{}'\n" "".format(ctx.command.qualified_name)) log += "".join(traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "Commande non autorisée " "en message privé") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message(channel, "Vous ne pouvez pas utiliser cette commande pour les prochaines " "{:.2f} secondes" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): # A bit hacky, couldn't find a better way no_dms = "Cannot send messages to this user" is_help_cmd = ctx.command.qualified_name == "help" is_forbidden = isinstance(error.original, discord.Forbidden) if is_help_cmd and is_forbidden and error.original.text == no_dms: msg = ("I couldn't send the help message to you in DM. Either" " you blocked me or you disabled DMs in this server.") await bot.send_message(channel, msg) return bot.logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ("Something went wrong. If the issue persists, please contact the author. ") log = ("Exception in command '{}'\n" "".format(ctx.command.qualified_name)) log += "".join(traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "That command is not " "available in DMs.") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message(channel, "You cannot use this command again for the next " "{:.2f} seconds" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
async def on_command_error(error, ctx): if isinstance(error, commands.MissingRequiredArgument): await send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(ctx.message.channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) oneliner = "Error in command '{}' - {}: {}".format( ctx.command.qualified_name, type(error.original).__name__, str(error.original)) await ctx.bot.send_message(ctx.message.channel, inline(oneliner)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass else: logger.exception(type(error).__name__, exc_info=error)
async def on_command_error(error, ctx): channel = ctx.message.channel if isinstance(error, commands.MissingRequiredArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.BadArgument): await bot.send_cmd_help(ctx) elif isinstance(error, commands.DisabledCommand): await bot.send_message(channel, "That command is disabled.") elif isinstance(error, commands.CommandInvokeError): bot.logger.exception("Exception in command '{}'".format( ctx.command.qualified_name), exc_info=error.original) message = ("Error in command '{}'. Check your console or " "logs for details." "".format(ctx.command.qualified_name)) log = ("Exception in command '{}'\n" "".format(ctx.command.qualified_name)) log += "".join( traceback.format_exception(type(error), error, error.__traceback__)) bot._last_exception = log await ctx.bot.send_message(channel, inline(message)) elif isinstance(error, commands.CommandNotFound): pass elif isinstance(error, commands.CheckFailure): pass elif isinstance(error, commands.NoPrivateMessage): await bot.send_message(channel, "That command is not " "available in DMs.") elif isinstance(error, commands.CommandOnCooldown): await bot.send_message( channel, "This command is on cooldown. " "Try again in {:.2f}s" "".format(error.retry_after)) else: bot.logger.exception(type(error).__name__, exc_info=error)
async def racfaudit_run(self, ctx, *args): """Audit the entire RACF family. [p]racfaudit run [-h] [-x] [-d] [-c CLAN [CLAN ...]] optional arguments: -h, --help show this help message and exit -x, --exec Execute add/remove roles -d, --debug Debug -c CLAN [CLAN ...], --clan CLAN [CLAN ...] Clan(s) to show """ parser = self.run_args_parser() try: pargs = parser.parse_args(args) except SystemExit: await self.bot.send_cmd_help(ctx) return option_debug = pargs.debug option_exec = pargs.exec await self.bot.type() try: member_models = await self.family_member_models() except ClashRoyaleAPIError as e: await self.bot.say(e.status_message) return else: await self.bot.say("**100T Family Audit**") # Show settings if pargs.settings: await ctx.invoke(self.racfaudit_config) server = ctx.message.server # associate Discord user to member for member_model in member_models: tag = clean_tag(member_model.get('tag')) try: discord_id = self.players[tag]["user_id"] except KeyError: pass else: member_model['discord_member'] = server.get_member( discord_id) if option_debug: for member_model in member_models: print(member_model.get('tag'), member_model.get('discord_member')) """ Member processing. """ audit_results = { "elder_promotion_req": [], "coleader_promotion_req": [], "leader_promotion_req": [], "no_discord": [], "no_clan_role": [], "no_member_role": [], "not_in_our_clans": [], } # find member_models mismatch discord_members = [] for member_model in member_models: has_discord = member_model.get('discord_member') if has_discord is None: audit_results["no_discord"].append(member_model) if has_discord: discord_member = member_model.get('discord_member') discord_members.append(discord_member) # promotions is_elder = False is_coleader = False is_leader = False for r in discord_member.roles: if r.name.lower() == 'elder': is_elder = True if r.name.lower() == 'coleader': is_coleader = True if r.name.lower() == 'leader': is_leader = True if is_elder: if member_model.get('role').lower() != 'elder': audit_results["elder_promotion_req"].append( member_model) if is_coleader: if member_model.get('role').lower() != 'coleader': audit_results["coleader_promotion_req"].append( member_model) if is_leader: if member_model.get('role').lower() != 'leader': audit_results["leader_promotion_req"].append( member_model) # no clan role clan_name = member_model['clan']['name'] clan_role_name = self.clan_roles[clan_name] if clan_role_name not in [ r.name for r in discord_member.roles ]: audit_results["no_clan_role"].append({ "discord_member": discord_member, "member_model": member_model }) # no member role discord_role_names = [r.name for r in discord_member.roles] if 'Member' not in discord_role_names: audit_results["no_member_role"].append(discord_member) # find discord member with roles for user in server.members: user_roles = [r.name for r in user.roles] if 'Member' in user_roles: if user not in discord_members: audit_results['not_in_our_clans'].append(user) # show results def list_member(member_model): """member row""" clan = member_model.get('clan') clan_name = None if clan is not None: clan_name = clan.get('name') row = "**{name}** #{tag}, {clan_name}, {role}, {trophies}".format( name=member_model.get('name'), tag=member_model.get('tag'), clan_name=clan_name, role=get_role_name(member_model.get('role')), trophies=member_model.get('trophies')) return row out = [] for clan in self.config['clans']: await self.bot.type() await asyncio.sleep(0) display_output = False if pargs.clan: for c in pargs.clan: if c.lower() in clan['name'].lower(): display_output = True else: display_output = True if not display_output: continue if clan['type'] == 'Member': out.append("-" * 40) out.append(inline(clan.get('name'))) # no discord out.append(underline("Members without discord")) for member_model in audit_results["no_discord"]: try: if member_model['clan']['name'] == clan.get( 'name'): out.append(list_member(member_model)) except KeyError: pass # elders out.append(underline("Elders need promotion")) for member_model in audit_results["elder_promotion_req"]: try: if member_model['clan']['name'] == clan.get( 'name'): out.append(list_member(member_model)) except KeyError: pass # coleaders out.append(underline("Co-Leaders need promotion")) for member_model in audit_results[ "coleader_promotion_req"]: try: if member_model['clan']['name'] == clan.get( 'name'): out.append(list_member(member_model)) except KeyError: pass # clan role out.append(underline("No clan role")) for result in audit_results["no_clan_role"]: try: if result["member_model"]['clan'][ 'name'] == clan.get('name'): out.append(result['discord_member'].mention) except KeyError: pass # not in our clans out.append("-" * 40) out.append( underline( "Discord users not in our clans but with member roles")) for result in audit_results['not_in_our_clans']: out.append('`{}` {}'.format(result, result.id)) for page in pagify('\n'.join(out)): await self.bot.say(page) if option_exec: # change clan roles for result in audit_results["no_clan_role"]: try: member_model = result['member_model'] discord_member = result['discord_member'] clan_role_name = self.clan_roles[member_model['clan'] ['name']] other_clan_role_names = [ r for r in self.clan_roles.values() if r != clan_role_name ] for rname in other_clan_role_names: role = discord.utils.get(discord_member.roles, name=rname) if role is not None: await asyncio.sleep(0) await self.bot.remove_roles( discord_member, role) await self.bot.say("Remove {} from {}".format( role, discord_member)) role = discord.utils.get(server.roles, name=clan_role_name) await asyncio.sleep(0) await self.bot.add_roles(discord_member, role) await self.bot.say("Add {} to {}".format( role.name, discord_member)) except KeyError: pass member_role = discord.utils.get(server.roles, name='Member') visitor_role = discord.utils.get(server.roles, name='Visitor') for discord_member in audit_results["no_member_role"]: try: await asyncio.sleep(0) await self.bot.add_roles(discord_member, member_role) await self.bot.say("Add {} to {}".format( member_role, discord_member)) await self.bot.remove_roles(discord_member, visitor_role) except KeyError: pass # remove member roles from people who are not in our clans for result in audit_results['not_in_our_clans']: result_role_names = [r.name for r in result.roles] # ignore people with special if 'Special' in result_role_names: continue if 'Keep-Member' in result_role_names: continue if 'Leader-Emeritus' in result_role_names: continue to_remove_role_names = [] for role_name in ['Member', 'Tourney', 'Practice']: if role_name in result_role_names: to_remove_role_names.append(role_name) to_remove_roles = [ discord.utils.get(server.roles, name=rname) for rname in to_remove_role_names ] await asyncio.sleep(0) await self.bot.remove_roles(result, *to_remove_roles) await self.bot.say("Removed {} from {}".format( ", ".join(to_remove_role_names), result)) await self.bot.add_roles(result, visitor_role) await self.bot.say("Added Visitor to {}".format(result)) await self.bot.say("Audit finished.")
async def run_racfaudit(self, server: discord.Server, clan_filters=None) -> AuditResult: """Run audit and return results.""" audit_results = { "elder_promotion_req": [], "coleader_promotion_req": [], "leader_promotion_req": [], "no_discord": [], "no_clan_role": [], "no_member_role": [], "not_in_our_clans": [], } error = False out = [] try: member_models = await self.family_member_models() except ClashRoyaleAPIError as e: # await self.bot.say(e.status_message) error = True else: out.append("**100T Family Audit**") # associate Discord user to member for member_model in member_models: tag = clean_tag(member_model.get('tag')) try: discord_id = self.players[tag]["user_id"] except KeyError: pass else: member_model['discord_member'] = server.get_member(discord_id) # find member_models mismatch discord_members = [] for member_model in member_models: has_discord = member_model.get('discord_member') if has_discord is None: audit_results["no_discord"].append(member_model) if has_discord: discord_member = member_model.get('discord_member') discord_members.append(discord_member) # promotions is_elder = False is_coleader = False is_leader = False for r in discord_member.roles: if r.name.lower() == 'elder': is_elder = True if r.name.lower() == 'coleader': is_coleader = True if r.name.lower() == 'leader': is_leader = True if is_elder: if member_model.get('role').lower() != 'elder': audit_results["elder_promotion_req"].append(member_model) if is_coleader: if member_model.get('role').lower() != 'coleader': audit_results["coleader_promotion_req"].append(member_model) if is_leader: if member_model.get('role').lower() != 'leader': audit_results["leader_promotion_req"].append(member_model) # no clan role clan_name = member_model['clan']['name'] clan_role_name = self.clan_roles[clan_name] if clan_role_name not in [r.name for r in discord_member.roles]: audit_results["no_clan_role"].append({ "discord_member": discord_member, "member_model": member_model }) # no member role discord_role_names = [r.name for r in discord_member.roles] if 'Member' not in discord_role_names: audit_results["no_member_role"].append(discord_member) # find discord member with roles for user in server.members: user_roles = [r.name for r in user.roles] if 'Member' in user_roles: if user not in discord_members: audit_results['not_in_our_clans'].append(user) # show results def list_member(member_model): """member row""" clan = member_model.get('clan') clan_name = None if clan is not None: clan_name = clan.get('name') row = "**{name}** #{tag}, {clan_name}, {role}, {trophies}".format( name=member_model.get('name'), tag=member_model.get('tag'), clan_name=clan_name, role=get_role_name(member_model.get('role')), trophies=member_model.get('trophies') ) return row for clan in self.config['clans']: # await self.bot.type() await asyncio.sleep(0) display_output = False if clan_filters: for c in clan_filters: if c.lower() in clan['name'].lower(): display_output = True else: display_output = True if not display_output: continue if clan['type'] == 'Member': out.append("-" * 40) out.append(inline(clan.get('name'))) # no discord out.append(underline("Members without discord")) for member_model in audit_results["no_discord"]: try: if member_model['clan']['name'] == clan.get('name'): out.append(list_member(member_model)) except KeyError: pass # elders out.append(underline("Elders need promotion")) for member_model in audit_results["elder_promotion_req"]: try: if member_model['clan']['name'] == clan.get('name'): out.append(list_member(member_model)) except KeyError: pass # coleaders out.append(underline("Co-Leaders need promotion")) for member_model in audit_results["coleader_promotion_req"]: try: if member_model['clan']['name'] == clan.get('name'): out.append(list_member(member_model)) except KeyError: pass # clan role out.append(underline("No clan role")) for result in audit_results["no_clan_role"]: try: if result["member_model"]['clan']['name'] == clan.get('name'): out.append(result['discord_member'].mention) except KeyError: pass # not in our clans out.append("-" * 40) out.append(underline("Discord users not in our clans but with member roles")) for result in audit_results['not_in_our_clans']: out.append('`{}` {}'.format(result, result.id)) return AuditResult( audit_results=audit_results, output=out, error=error )
async def crladder_battle(self, ctx, member: discord.Member, name=None, force_update=False): """Report battle.""" server = ctx.message.server author = ctx.message.author await self.bot.type() try: if name is None: names = self.settings.get_series_names_by_member(server, member) if len(names) == 0: raise NoSuchSeries elif len(names) == 1: name = names[0] series = self.settings.get_series_by_name(server, name) else: raise PlayerInMultipleActiveSeries else: series = self.settings.get_series_by_name(server, name) except NoSuchSeries: await self.bot.say("Cannot find series.") return except PlayerInMultipleActiveSeries: await self.bot.say("Player is in multiple series. Please specify name of the series.") return else: if not self.settings.verify_player(series, author): await self.bot.say("You are not registered in this series.") return if not self.settings.verify_player(series, member): await self.bot.say("{} is not registered is this series.".format(member)) return try: battles = await self.settings.find_battles(series, author, member) except APIError as e: print(e.response) await self.bot.say("Error fetching results from API. Please try again later.") else: if len(battles) > 1: await self.bot.say("Found multiple battles. Using only last battle.") if len(battles) == 0: await self.bot.say("No battle found.") return battles = sorted(battles, key=lambda x: int(x.timestamp)) battle = battles[-1] save_battle = True if self.settings.is_battle_saved(server, name, battle): save_battle = False # force update for debugging if force_update: save_battle = True def match_1vs1(winner: Player, loser: Player, drawn=False): """Match score reporting.""" winner.rating, loser.rating = rate_1vs1(winner.rating, loser.rating, drawn=drawn) return winner, loser p_author = Player.from_dict(self.settings.get_player(server, name, author).copy()) p_member = Player.from_dict(self.settings.get_player(server, name, member).copy()) # print(p_author) p_author_rating_old = env.create_rating(mu=p_author.rating.mu, sigma=p_author.rating.sigma) p_member_rating_old = env.create_rating(mu=p_member.rating.mu, sigma=p_member.rating.sigma) if battle.winner > 0: color = discord.Color.green() p_author, p_member = match_1vs1(p_author, p_member) # print("p_author", p_author) # print("p_member", p_member) elif battle.winner == 0: color = discord.Color.light_grey() p_author, p_member = match_1vs1(p_author, p_member, drawn=True) elif battle.winner < 0: color = discord.Color.red() p_member, p_author = match_1vs1(p_member, p_author) # print("p_author", p_author) # print("p_member", p_member) else: color = discord.Color.gold() def display_rating(rating): # return rating.mu - rating.sigma * 3 return rating.mu em = discord.Embed( title="Battle: {} vs {}".format(author, member), description="Series: {}".format(name), color=color ) em.add_field( name="Result", value=battle.result ) em.add_field( name="Score", value="{} - {}".format(battle.team_crowns, battle.opponent_crowns) ) em.add_field( name="UTC Time", value=battle.timestamp_dt.isoformat() ) em.add_field( name=str(author), value=''.join([self.bot_emoji(key.replace('-', '')) for key in battle.team_deck]), inline=False ) if save_battle: em.add_field( name="Elo", value=inline("{:>10,.1f} -> {:>10,.1f}".format(display_rating(p_author_rating_old), p_author.rating_display)), inline=False ) em.add_field( name=str(member), value=''.join([self.bot_emoji(key.replace('-', '')) for key in battle.opponent_deck]), inline=False ) if save_battle: em.add_field( name="Elo", value=inline("{:>10,.1f} -> {:>10,.1f}".format(display_rating(p_member_rating_old), p_member.rating_display)), inline=False ) if not save_battle: em.add_field( name=":warning: Warning", value="This battle is not saved because it has already been registered.", inline=False ) await self.bot.say(embed=em) # save battle if save_battle: self.settings.save_battle( player1=p_author, player2=p_member, player1_old_rating=p_author_rating_old, player2_old_rating=p_member_rating_old, series=series, battle=battle ) updated = self.settings.update_player_rating(server, name, p_author) updated = self.settings.update_player_rating(server, name, p_member) await self.bot.say("Elo updated.")
async def crladder_info(self, ctx, name, *args): """Info about a series. Options: winloss: show TOTAL/W/D/L showall: show all registered players (default: False. Show only people with games) listids: Output all member ids at end """ server = ctx.message.server await self.bot.type() winloss = False showall = False listids = False if len(args): if 'winloss' in args: winloss = True if 'showall' in args: showall = True if 'listids' in args: listids = True try: series = self.settings.get_series(server, name=name) except NoSuchSeries: await self.bot.say("Cannot find a series named {}", format(name)) else: # calculate total wins/losses by player stats = self.calculate_stats(series) player_list = [] player_ids = [] players = [Player.from_dict(d) for d in series['players']] players = sorted(players, key=lambda p: p.rating_display, reverse=True) for p in players: member = server.get_member(p.discord_id) player_ids.append(p.discord_id) if member is not None: if showall or stats[p.tag]["games"] > 0: player_list.append("`{:_>4.0f}`\t`±{:4.0f}`\t{}".format(p.rating.mu, p.rating.sigma, member)) if winloss: record = '{:3,}.\t{:3,}W\t{:3,}D\t{:3,}L'.format( stats[p.tag]["games"], stats[p.tag]["wins"], stats[p.tag]["draws"], stats[p.tag]["losses"], ) player_list.append("\t{}".format(inline(record))) pages = grouper(30, player_list) color = random_discord_color() for index, page in enumerate(pages): lines = [p for p in page if p is not None] em = discord.Embed( title=name, description="Clash Royale ladder series.", color=color) if index == 0: em.add_field(name="Status", value=series.get('status', '_')) em.add_field(name="Players", value='\n'.join(lines), inline=False) await self.bot.say(embed=em) if listids: await self.bot.say('Participant IDs: {}'.format(' '.join(player_ids)))
def inline_barchart(count, max_count): """Inline bar chart.""" width = 30 bar_count = int(width * (count / max_count)) chart = '▇' * bar_count if bar_count > 0 else '░' return inline(chart)