def fix_arg_order(*args):
tag, mode, region, platform = '', None, None, None
extras = []
for arg in args:
if arg is None or isinstance(arg, Mode):
continue
lower = arg.lower()
if '#' in arg or '@' in arg:
tag = arg
elif lower in REGIONS:
region = lower
elif lower in PLATFORMS:
platform = lower
else:
try:
Mode[lower]
except KeyError:
extras.append(arg)
else:
mode = lower
if extras:
raise commands.BadArgument('Invalid arguments: ' + ', '.join(extras))
return tag, mode, region, platform
python类BadArgument()的实例源码
def hex_or_rgb(arg):
s = arg.split(' ')
if len(s) == 1:
color = s[0]
if len(color) == 6:
color = f'0x{color}'
elif len(color) == 7:
color = color.replace('#', '0x')
try:
return discord.Color(int(color, 0))
except ValueError:
raise commands.BadArgument('A single argument must be passed as hex (`0x7289DA`, `#7289DA`, `7289DA`)')
elif len(s) == 3:
try:
rgb = [*map(int, s)]
except ValueError:
raise commands.BadArgument('Three arguments must be passed as RGB (`114 137 218`, `153 170 181`)')
if any(c < 0 or c > 255 for c in rgb):
raise commands.BadArgument('RGB colors must be in the range `[0, 255]`')
return discord.Color.from_rgb(*rgb)
raise commands.BadArgument('You must pass 1 (hex) or 3 (RGB) arguments.')
def integer(arg):
"""Attempts to return the arg converted to `int`.
Returns nearest whole number if arg represents a `float`.
Mainly to be used as typehint in commands.
"""
try:
int(arg)
except ValueError:
pass
else:
return int(arg)
try:
float(arg)
except ValueError:
pass
else:
return int(round(float(arg)))
raise BadArgument('Converting to "int" failed.')
def find_target(self, ctx, arg):
"""Returns the ID of the given target"""
if arg.casefold() in ('everyone', 'all'):
return discord.Object(id=0)
try:
return await MemberConverter().convert(ctx, arg)
except BadArgument:
pass
try:
return await RoleConverter().convert(ctx, arg)
except BadArgument:
pass
return None
def _get_quote(self, ctx, author_or_num=None):
sid = ctx.message.server.id
if type(author_or_num) is discord.Member:
return self._get_random_author_quote(ctx, author_or_num)
if author_or_num:
try:
quote_id = int(author_or_num)
if quote_id > 0 and quote_id <= len(self.quotes[sid]):
return (quote_id - 1, self.quotes[sid][quote_id - 1])
else:
raise commands.BadArgument("Quote #%i does not exist." % quote_id)
except ValueError:
pass
try:
author = commands.MemberConverter(ctx, author_or_num).convert()
except commands.errors.BadArgument:
author = author_or_num.strip(' \t\n\r\x0b\x0c-–—') # whitespace + dashes
return self._get_random_author_quote(ctx, author)
return self._get_random_quote(ctx)
def quote(self, ctx, *, author_or_num: str = None):
"""Say a stored quote!
Without any arguments, this command randomly selects from all stored
quotes. If you supply an author name, it randomly selects from among
that author's quotes. Finally, if given a number, that specific quote
will be said, assuming it exists. Use [p]lsquotes to show all quotes.
"""
sid = ctx.message.server.id
if sid not in self.quotes or len(self.quotes[sid]) == 0:
await self.bot.say("There are no quotes in this server!")
return
try:
quote = self._get_quote(ctx, author_or_num)
except commands.BadArgument:
if author_or_num.lower().strip() in ['me', 'myself', 'self']:
quote = self._get_quote(ctx, ctx.message.author)
else:
raise
await self.bot.say(self._format_quote(ctx, quote))
def convert(self, ctx: commands.Context, argument):
def finder(entry):
try:
user_id = int(argument)
except ValueError:
user_id = None
return (str(entry.user) == argument or # username#discriminator
entry.user.name == argument or # username
entry.user.id == user_id) # id
try:
entry = discord.utils.find(finder, await ctx.guild.bans())
if entry is None:
raise commands.BadArgument(
'Banned user not found. You can specify by ID, username, or username#discriminator.'
)
return entry.user
except discord.Forbidden:
raise commands.BadArgument("I can't view the bans for this server.")
def convert(self, ctx: DogbotContext, argument: str) -> str:
cog: 'Time' = ctx.command.instance
# resolve another user's timezone
try:
member = await MemberConverter().convert(ctx, argument)
timezone = await cog.get_timezone_for(member)
if timezone:
return timezone
except BadArgument:
pass
# hippo checking
blacklisted = list('`\\<>@')
if any(character in argument for character in blacklisted) or len(argument) > 30:
raise BadArgument("That doesn't look like a timezone.")
# actually check if it's a valid timezone with arrow's parser
try:
arrow.utcnow().to(argument)
except arrow.parser.ParserError:
raise BadArgument('Invalid timezone.')
return argument
def _check_role(ctx, role, thing):
if role.managed:
raise commands.BadArgument("This is an integration role, I can't assign this to anyone!")
# Assigning people with the @everyone role is not possible
if role.is_default():
message = ("Wow, good job. I'm just gonna grab some popcorn now..."
if ctx.message.mention_everyone else
"You're lucky that didn't do anything...")
raise commands.BadArgument(message)
if role.permissions.administrator:
message = ("This role has the Administrator permission. "
"It's very dangerous and can lead to terrible things. "
f"Are you sure you wanna make this {thing} role?")
try:
result = await ctx.ask_confirmation(message)
except asyncio.TimeoutError:
raise commands.BadArgument("Took too long. Aborting...")
else:
if not result:
raise commands.BadArgument("Aborted.")
def convert(self, ctx, arg):
if not ctx.guild:
raise commands.NoPrivateMessage
self_roles = await _get_self_roles(ctx)
if not self_roles:
message = ("This server has no self-assignable roles. "
f"Use `{ctx.prefix}asar` to add one.")
raise commands.BadArgument(message)
temp_guild = copy.copy(ctx.guild)
temp_guild.roles = self_roles
with temp_attr(ctx, 'guild', temp_guild):
try:
return await super().convert(ctx, arg)
except commands.BadArgument:
raise commands.BadArgument(f'{arg} is not a self-assignable role...')
def _parse_roles(self, ctx: Context, roles: str, is_primary: int = 0) -> List[Tuple]:
roles = roles.rstrip(", \t\n\r")
roles_arr = roles.split(",")
alias = None
rows = []
for r in roles_arr:
if "=" in r:
role, alias = r.split("=")
role = role.strip(" \t\n\r\"'")
alias = alias.strip(" \t\n\r\"'")
else:
role = r.strip(" \t\n\r\"'")
try:
role_conv = RoleConverter(ctx, role).convert()
except BadArgument as e:
# Unable to convert this role
msg = e.args[0]
print(msg)
await self.bot.say("Couldn't find role `{}` on this server".format(role))
continue
rows.append((role_conv, alias, is_primary))
return rows
def on_command_error(self, error, ctx):
if isinstance(error, commands.NoPrivateMessage):
await self.send_message(ctx.message.author, "\N{WARNING SIGN} Sorry, you can't use this command in a private message!")
elif isinstance(error, commands.DisabledCommand):
await self.send_message(ctx.message.author, "\N{WARNING SIGN} Sorry, this command is disabled!")
elif isinstance(error, commands.CommandOnCooldown):
await self.send_message(ctx.message.channel, f"{ctx.message.author.mention} slow down! Try again in {error.retry_after:.1f} seconds.")
elif isinstance(error, commands.MissingRequiredArgument) or isinstance(error, commands.BadArgument):
await self.send_message(ctx.message.channel, f"\N{WARNING SIGN} {error}")
elif isinstance(error, commands.CommandInvokeError):
original_name = error.original.__class__.__name__
print(f"In {paint(ctx.command.qualified_name, 'b_red')}:")
traceback.print_tb(error.original.__traceback__)
print(f"{paint(original_name, 'red')}: {error.original}")
else:
print(f"{paint(type(error).__name__, 'b_red')}: {error}")
def convert(self, ctx, arg):
bot = ctx.bot
try:
guild_id = int(arg)
except ValueError:
def is_guild(g):
return arg.lower() == g.name.lower()
guild = discord.utils.find(is_guild, bot.guilds)
if guild is None:
raise commands.BadArgument('Guild not found')
return guild
guild = bot.get_guild(guild_id)
if guild is None:
raise commands.BadArgument('Guild not found')
return guild
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_message(channel, "Truly, your wish is my command, but I cannot make head nor tail of the argument you provide.")
elif isinstance(error, commands.CommandNotFound):
# This is almost as ugly as Manta on Medusa
await bot.send_message(channel, "I fear I know not of this \"%s\". Is it perchance a new Hero?" % ctx.message.content[len(bot.settings["prefix"]):].partition(' ')[0])
elif isinstance(error, commands.CommandOnCooldown):
await bot.send_message(channel, random.choice(CDMESSAGES) + " (%ss remaining)" % int(error.retry_after))
elif isinstance(error, commands.NoPrivateMessage):
await bot.send_message(channel, "Truly, your wish is my command, but that order is not to be issued in secret. It must be invoked in a server.")
else:
try:
await bot.send_message(channel, "I fear some unprecedented disaster has occurred which I cannot myself resolve. Methinks you would do well to consult %s on this matter." % (await bot.get_owner()).mention)
except discord.NotFound:
await bot.send_message(channel, "I fear some unprecedented disaster has occurred which I cannot myself resolve.")
if isinstance(error, commands.CommandInvokeError):
print(repr(error.original))
else:
print(repr(error))
def convert(self, ctx, argument):
try:
m = await commands.MemberConverter().convert(ctx, argument)
can_execute = ctx.author.id == ctx.bot.owner_id or \
ctx.author == ctx.guild.owner or \
ctx.author.top_role > m.top_role
if not can_execute:
raise commands.BadArgument('You cannot do this action on this user due to role hierarchy.')
return m.id
except commands.BadArgument:
try:
return int(argument, base=10)
except ValueError:
raise commands.BadArgument(f"{argument} is not a valid member or member ID.") from None
def convert(self, ctx, argument):
cog = ctx.bot.get_cog('Splatoon')
if cog is None:
raise commands.BadArgument('Splatoon related commands seemingly disabled.')
query = argument.strip('"')
if len(query) < 4:
raise commands.BadArgument('Weapon name to query must be over 4 characters long.')
weapons = cog.get_weapons_named(query)
try:
weapon = await ctx.disambiguate(weapons, lambda w: w['name'])
except ValueError as e:
raise commands.BadArgument(str(e)) from None
else:
return weapon
def get_command_from_language(self, language):
cmds = {
'cpp': 'g++ -std=c++1z -O2 -Wall -Wextra -pedantic -pthread main.cpp -lstdc++fs && ./a.out',
'c': 'mv main.cpp main.c && gcc -std=c11 -O2 -Wall -Wextra -pedantic main.c && ./a.out',
'py': 'python main.cpp', # coliru has no python3
'python': 'python main.cpp',
'haskell': 'runhaskell main.cpp'
}
cpp = cmds['cpp']
for alias in ('cc', 'h', 'c++', 'h++', 'hpp'):
cmds[alias] = cpp
try:
return cmds[language]
except KeyError as e:
if language:
fmt = f'Unknown language to compile for: {language}'
else:
fmt = 'Could not find a language to compile with.'
raise commands.BadArgument(fmt) from e
def on_command_error(self,ctx,error):
if self.bot.user.id == 181503794532581376 or self.error_log:
print(error)
if isinstance(error, commands.MissingRequiredArgument):
await self.send_cmd_help(ctx)
elif isinstance(error,commands.BadArgument):
await self.send_cmd_help(ctx)
elif isinstance(error, commands.CommandInvokeError):
if isinstance(error.original,discord_error.Forbidden):
await ctx.send("I am sorry, I need a certain permission to run it...")
traceback.print_exception(type(error), error, error.__traceback__)
return utils.prRed(type(error.original))
errors = traceback.format_exception(type(error), error, error.__traceback__)
Current_Time = datetime.datetime.utcnow().strftime("%b/%d/%Y %H:%M:%S UTC")
utils.prRed(Current_Time)
utils.prRed("Error!")
traceback.print_exception(type(error), error, error.__traceback__)
cog_error = '```fix\nCogs:{0.command.cog_name}\tCommand:{0.command}\tAuthor:{0.message.author}-{0.message.author.id}\n' \
'Server:{0.message.guild.id}\n{0.message.clean_content}\nError:\n{1}```'.format(ctx,error)
msg ="```py\n{}```\n{}\n```py\n{}\n```".format(Current_Time + "\n"+ "ERROR!",cog_error,"".join(errors).replace("`",""))
if len(msg) >= 1900:
msg = await utils.send_hastebin(msg)
await self.bot.owner.send(msg)
await ctx.send("You either used the command incorrectly or an unexpected error occurred. A report has been sent to the creator so you can hope for a fix soon.")
def __error(self, ctx, exc):
if isinstance(exc, commands.BadArgument):
exc.handled = True
await ctx.send(exc)
return
elif not isinstance(exc, commands.CommandInvokeError):
return
if isinstance(exc.original, (NotFound, ServerError, NotInDB, NotPlayed, InvalidBTag)):
exc.handled = True
await ctx.send(exc.original)
return
def date(argument):
formats = ('%Y/%m/%d', '%Y-%m-%d')
for fmt in formats:
try:
return datetime.strptime(argument, fmt)
except ValueError:
continue
raise commands.BadArgument('Cannot convert to date. Expected YYYY/MM/DD or YYYY-MM-DD.')
def nostalgia_error(self, ctx, error):
if isinstance(error, commands.BadArgument):
await ctx.send(error)
def color_error(self, ctx, exc):
if isinstance(exc, commands.BadArgument):
await ctx.send(exc)
def cat_facts_error(self, ctx, exc):
if isinstance(exc, commands.BadArgument):
pass
else:
ctx.command = ctx.command.name
def on_command_error(e, ctx):
if isinstance(e, commands.MissingRequiredArgument):
await send_cmd_help(ctx)
elif isinstance(e, commands.BadArgument):
await send_cmd_help(ctx)
else:
raise(e)
def timer_goto(self, ctx: commands.Context, period_idx):
""" Skips to the n-th period, assuming the periods' indexes go
from 1 to the amount of them.
:param period_idx: The index of the period to start from, from 1 to n.
:type period_idx: 'next' or int such that 1 <= period_idx <= n,
n being the amount of periods set.
"""
channel = self.bot.spoof(ctx.message.author, lib.get_channel(ctx))
interface = self.bot.get_interface(channel)
if period_idx == "next":
idx = interface.timer.get_period(True) + 1
else:
try:
idx = int(period_idx)
except TypeError:
raise commands.BadArgument
label = interface.timer.goto(idx)
if label is not None:
log = send = "Moved to period number {!s} ({})".format(idx, label)
if interface.timer.get_state() != State.STOPPED:
await self.bot.edit_message(interface.list_message,
interface.timer.list_periods())
if interface.timer.get_state() == State.PAUSED:
await self.bot.edit_message(interface.time_message,
interface.timer.time())
else:
log = "Invalid period number entered when trying goto command."
send = "Invalid period number."
lib.log(log, channel_id=channel.id)
await self.bot.say(send, delete_after=self.bot.ans_lifespan)
def convert(self, ctx, emoji):
try:
return await super().convert(ctx, emoji)
except BadArgument:
return emoji
def convert(self, ctx, arg):
try:
return await self.channel_converter.convert(ctx, arg)
except BadArgument: pass
try:
return await (await self.member_converter.convert(ctx, arg)).create_dm()
except BadArgument: pass
raise BadArgument('Messageable "%s" not found.' % arg)
def _convert(arg):
for converter in (int, float, bool_):
try:
return converter(arg)
except (BadArgument, ValueError):
continue
if arg.casefold() in ('none', 'null', 'void'):
return None
return arg # default to string
def on_command_error(self, ctx, err):
if isinstance(err, errors.PermissionDenied):
await ctx.send('BAKA! You do not have my permission!')
elif isinstance(err, errors.MissingPermissions):
await ctx.send('BAKA! I require these permissions: %s' % ', '.join(err.args))
elif isinstance(err, commands.NoPrivateMessage):
await ctx.send('BAKA! This command does not work in private messages!')
elif isinstance(err, commands.BadArgument):
str_err = str(err)
if not str_err.endswith(('.', '!')):
str_err += '.'
await ctx.send('BAKA! %s' % str_err)
elif isinstance(err, commands.MissingRequiredArgument):
await ctx.send('BAKA! Missing required argument: `%s`' % err.args[0].partition(' ')[0])
elif isinstance(err, commands.TooManyArguments):
await ctx.send('BAKA! Too many arguments!')
elif isinstance(err, commands.CommandNotFound):
pass
else:
await ctx.send('```\n%s\n```' % ''.join(traceback.format_exception_only(type(err), err)).strip())
if isinstance(ctx.channel, discord.TextChannel):
log.error('Error in command <{0}> ({1.name!r}({1.id}) {2}({2.id}) {3}({3.id}) {4!r})'.format(ctx.command, ctx.guild, ctx.channel, ctx.author, ctx.message.content))
else:
log.error('Error in command <{0}> (DM {1}({1.id}) {2!r})'.format(ctx.command, ctx.channel.recipient, ctx.message.content))
log.error(''.join(traceback.format_exception(type(err), err, err.__traceback__)))
def member_by_substring(ctx: commands.Context, substring: str):
"""This searches for a member by substrings."""
try:
return await memberconverter.convert(ctx, substring)
except commands.CommandError:
pass
substring = substring.lower()
for member in ctx.guild.members:
if substring in member.name.lower() or substring in member.display_name.lower():
return member
raise commands.BadArgument(f"No user with substring `{substring}` was found.")