def __init__(self, argument):
compiled = re.compile(r"(?:(?P<hours>\d+)h)?(?:(?P<minutes>\d+)m)?(?:(?P<seconds>\d+)s)?")
self.original = argument
try:
self.seconds = int(argument)
except ValueError as e:
match = compiled.match(argument)
if match is None or not match.group(0):
raise commands.BadArgument('Failed to parse time.') from e
self.seconds = 0
hours = match.group('hours')
if hours is not None:
self.seconds += int(hours) * 3600
minutes = match.group('minutes')
if minutes is not None:
self.seconds += int(minutes) * 60
seconds = match.group('seconds')
if seconds is not None:
self.seconds += int(seconds)
if self.seconds < 0:
raise commands.BadArgument('I don\'t do negative time.')
if self.seconds > 604800: # 7 days
raise commands.BadArgument('That\'s a bit too far in the future for me.')
python类group()的实例源码
def convert(self, ctx, argument):
guild = ctx.message.guild
if not guild:
raise commands.NoPrivateMessage()
match = self._get_id_match(argument) or re.match(r'<@&([0-9]+)>$', argument)
params = dict(id=int(match.group(1))) if match else dict(name=argument)
result = discord.utils.get(guild.roles, **params)
if result is None:
return argument
return result
def gaf(self, ctx):
"""
Information on The Never Ending GAF
"""
await ctx.send("The Never Ending GAF is a small group of idiots that play games and insult each other. "
"\nWe reside on our Discord server, usually in the beloved cesspool intelligently "
"titled \"Channel 1\".\nFeel free to pop by, probably get told to piss off, and maybe "
"play some games."
"\nMore info and invite links: <http://www.neverendinggaf.com>")
def jc3(self, ctx):
"""Main command group for JoséCoin v3 commands.
NOTE: this should be REMOVED once JoséCoin v3 becomes stable.
"""
pass
def log(self, ctx):
"""Command group for managing logging."""
if ctx.invoked_subcommand is None:
await edit(ctx, content='\N{HEAVY EXCLAMATION MARK SYMBOL} ``on``, ``off``, ``status``, ``show``, ``key <word>``, ``guild``, ``channel``, ``blacklist channel``, ``blacklist <word>`` or ``blacklist user <user>``', ttl=5)
# Log On
def convert(self):
guild = self.ctx.bot.get_server(BLOB_GUILD_ID)
emojis = {e.id: e for e in guild.emojis}
m = EMOJI_REGEX.match(self.argument)
if m is not None:
emoji = emojis.get(m.group(1))
elif self.argument.isdigit():
emoji = emojis.get(self.argument)
else:
emoji = discord.utils.find(lambda e: e.name == self.argument, emojis.values())
if emoji is None:
raise commands.BadArgument('Not a valid blob emoji.')
return emoji
def partial_emoji(argument, *, regex=EMOJI_REGEX):
if argument.isdigit():
# assume it's an emoji ID
return int(argument)
m = regex.match(argument)
if m is None:
raise commands.BadArgument("That's not a custom emoji...")
return int(m.group(1))
def valid_rank(argument, *, _rank=_rank):
m = _rank.match(argument.strip('"'))
if m is None:
raise commands.BadArgument('Could not figure out mode or rank.')
mode = m.group('mode')
valid = {
'zones': 'Splat Zones',
'splat zones': 'Splat Zones',
'sz': 'Splat Zones',
'zone': 'Splat Zones',
'splat': 'Splat Zones',
'tower': 'Tower Control',
'control': 'Tower Control',
'tc': 'Tower Control',
'tower control': 'Tower Control',
'rain': 'Rainmaker',
'rainmaker': 'Rainmaker',
'rain maker': 'Rainmaker',
'rm': 'Rainmaker'
}
try:
mode = valid[mode.lower()]
except KeyError:
raise commands.BadArgument(f'Unknown Splatoon 2 mode: {mode}') from None
rank = m.group('rank').upper()
number = m.group('number')
if number:
number = int(number)
return mode, { 'rank': rank, 'number': number }
def idc_emoji_or_just_string(val):
match = re.match(r'<(?P<animated>a)?:(?P<name>[a-zA-Z0-9]+):(?P<id>[0-9]+)>$', val)
if match:
return FakeEmoji(match.group("name"), match.group("id"), bool(match.group("animated")))
return FakeEmoji(val.replace(':', ''), None, False) # guess it's not animated
def idc_emoji(val):
match = re.match(r'<(?P<animated>a)?:(?P<name>[a-zA-Z0-9]+):(?P<id>[0-9]+)>$', val)
if not match:
raise errors.BadArgument("Not a valid custom emoji")
return FakeEmoji(match.group("name"), match.group("id"), bool(match.group("animated")))
def _new_message(self, message):
"""Finds the message and checks it for regex"""
user = message.author
if message.server is None:
return
if message.server.id in self.json:
if self.json[message.server.id]['toggle'] is True:
roles = [r.name for r in user.roles]
bot_admin = settings.get_server_admin(message.server)
bot_mod = settings.get_server_mod(message.server)
if message.channel.id in self.json[message.server.id]['excluded_channels']:
return
elif user.id == settings.owner:
return
elif bot_admin in roles:
return
elif bot_mod in roles:
return
elif user.permissions_in(message.channel).manage_messages is True:
return
elif user == message.server.me:
return
if self.json[message.server.id]['strict']:
for match in self.regex_url.finditer(message.content):
if self.emoji_string not in match.group(0):
asyncio.sleep(0.5)
await self.bot.delete_message(message)
if self.json[message.server.id]['dm'] is True:
await self.bot.send_message(message.author, self.json[message.server.id]['message'])
break
elif self.regex.search(message.content) is not None or self.regex_discordme.search(message.content) is not None:
asyncio.sleep(0.5)
await self.bot.delete_message(message)
if self.json[message.server.id]['dm'] is True:
await self.bot.send_message(message.author, self.json[message.server.id]['message'])
def fetch_info(self, ctx, cmd, title):
data = await self.get_xml(cmd, title)
try:
root = ET.fromstring(data)
except ET.ParseError:
return await self.bot.say("I couldn't find anything!")
else:
if len(root) == 1:
entry = root[0]
else:
msg = "**Please choose one by giving its number.**\n"
msg += "\n".join(['{} - {}'.format(n + 1, entry[1].text)
for n, entry in enumerate(root) if n < 10])
await self.bot.say(msg)
check = lambda m: m.content.isdigit() and int(m.content) in range(1, len(root) + 1)
resp = await self.bot.wait_for_message(timeout=15, author=ctx.message.author,
check=check)
if resp is None:
return
entry = root[int(resp.content)-1]
link = 'http://myanimelist.net/{}/{}'.format(cmd, entry.find('id').text)
desc = "MAL [{}]({})".format(entry.find('title').text, link)
syn_raw = entry.find('synopsis').text
title = entry.find('title').text
if syn_raw:
replace = {'"': '\"', '<br />': '', '—': ' - ', ''': '\'',
'“': '\"', '”': '\"', '[i]': '*', '[/i]': '*', '[b]': '**',
'[/b]': '**', '[url=': '', ']': ' - ', '[/url]': ''}
rep_sorted = sorted(replace, key=lambda s: len(s[0]), reverse=True)
rep_escaped = [re.escape(replacement) for replacement in rep_sorted]
pattern = re.compile("|".join(rep_escaped), re.I)
synopsis = pattern.sub(lambda match: replace[match.group(0)],
entry.find('synopsis').text)
else:
synopsis = "There is not a synopsis for {}".format(title)
# Build Embed
embed = discord.Embed(colour=0x0066FF, description=desc)
embed.title = title
embed.set_thumbnail(url=entry.find('image').text)
embed.set_footer(text=synopsis)
for k in switcher:
spec = entry.find(k)
if spec is not None and spec.text is not None:
embed.add_field(name=k.capitalize(),
value=html.unescape(spec.text.replace('<br />', '')))
await self.bot.say(embed=embed)
def process_uesp(self, search, random = False, redirect = True):
# TODO: Add User-Agent
if random:
async with clients.aiohttp_session.get("http://en.uesp.net/w/api.php", params = {"action": "query", "list": "random", "rnnamespace": "0|" + '|'.join(str(i) for i in range(100, 152)) + "|200|201", "format": "json"}) as resp:
data = await resp.json()
search = data["query"]["random"][0]["title"]
else:
async with clients.aiohttp_session.get("http://en.uesp.net/w/api.php", params = {"action": "query", "list": "search", "srsearch": search, "srinfo": "suggestion", "srlimit": 1, "format": "json"}) as resp:
data = await resp.json()
try:
search = data["query"].get("searchinfo", {}).get("suggestion") or data["query"]["search"][0]["title"]
except IndexError:
await self.bot.embed_reply(":no_entry: Page not found")
return
async with clients.aiohttp_session.get("http://en.uesp.net/w/api.php", params = {"action": "query", "redirects": "", "prop": "info|revisions|images", "titles": search, "inprop": "url", "rvprop": "content", "format": "json"}) as resp:
data = await resp.json()
if "pages" not in data["query"]:
await self.bot.embed_reply(":no_entry: Error")
return
page_id = list(data["query"]["pages"].keys())[0]
page = data["query"]["pages"][page_id]
if "missing" in page:
await self.bot.embed_reply(":no_entry: Page not found")
elif "invalid" in page:
await self.bot.embed_reply(":no_entry: Error: {}".format(page["invalidreason"]))
elif redirect and "redirects" in data["query"]:
await self.process_wikipedia(data["query"]["redirects"][-1]["to"], redirect = False)
# TODO: Handle section links/tofragments
else:
description = page["revisions"][0]['*']
description = re.sub("\s+ \s+", ' ', description)
while re.findall("{{[^{]+?}}", description):
description = re.sub("{{[^{]+?}}", "", description)
while re.findall("{[^{]*?}", description):
description = re.sub("{[^{]*?}", "", description)
description = re.sub("<.+?>", "", description, flags = re.DOTALL)
description = re.sub("__.+?__", "", description)
description = description.strip()
description = '\n'.join(line.lstrip(':') for line in description.split('\n'))
while len(description) > 1024:
description = '\n'.join(description.split('\n')[:-1])
description = description.split("==")[0]
## description = description if len(description) <= 1024 else description[:1024] + "..."
description = re.sub("\[\[Category:.+?\]\]", "", description)
description = re.sub("\[\[(.+?)\|(.+?)\]\]|\[(.+?)[ ](.+?)\]", lambda match: "[{}](http://en.uesp.net/wiki/{})".format(match.group(2), match.group(1).replace(' ', '_')) if match.group(1) else "[{}]({})".format(match.group(4), match.group(3)), description)
description = description.replace("'''", "**").replace("''", "*")
description = re.sub("\n+", '\n', description)
thumbnail = data["query"]["pages"][page_id].get("thumbnail")
image_url = thumbnail["source"].replace("{}px".format(thumbnail["width"]), "1200px") if thumbnail else None
await self.bot.embed_reply(description, title = page["title"], title_url = page["fullurl"], image_url = image_url) # canonicalurl?
def show(self, ctx):
"""
Display the roster
The roster includes the name, Destiny 2 class,
and timezone of server members. Note that only
users who have set a role or timezone will be
displayed on the roster.
"""
manager = MessageManager(self.bot, ctx.author, ctx.channel, ctx.prefix, [ctx.message])
roster_groups = []
roster = self.bot.db.get_roster(ctx.guild.id)
if len(roster) != 0:
text = "```\n"
for row in roster:
# Add a single entry to the roster message
member = ctx.guild.get_member(row.get('user_id'))
role = row.get('role')
timezone = row.get('timezone')
if member:
name = member.display_name
formatted_name = (name[:16] + '..') if len(name) > 16 else name
role = role if role else "---"
timezone = timezone if timezone else "---"
text += '{:18} {:6} {:7}\n'.format(formatted_name, timezone, role)
# If the message is too big, place it into a group
if len(text) > 2000:
text += "```"
roster_groups.append(text)
text = "```\n"
# Add any remaining entries into a roster group
if len(text) > 5:
text += "```"
roster_groups.append(text)
# Send the initial roster message
embed_msg = discord.Embed(color=constants.BLUE)
embed_msg.title="{} Roster".format(ctx.guild.name)
embed_msg.description = roster_groups[0]
await manager.say(embed_msg, embed=True, delete=False)
# Send additional roster messages if the roster is too long
for group in roster_groups[1:]:
embed_msg = discord.Embed(color=constants.BLUE)
embed_msg.title="{} Roster (continued)".format(ctx.guild.name)
embed_msg.description = group
await manager.say(embed_msg, embed=True, delete=False)
else:
await manager.say("No roster exists yet. Use '{}roster settimezone' or '{}roster ".format(ctx.prefix, ctx.prefix)
+ "setclass' to add the first entry!")
await manager.clear()
def _remove(self, ctx, rolename, user: discord.Member=None):
"""Removes a role from user, defaults to author
Role name must be in quotes if there are spaces.
You will need a 'Bot Commander' role in order to use this"""
server = ctx.message.server
author = ctx.message.author
role = self._role_from_string(server, rolename)
if role is None:
await self.bot.say("Role not found.")
return
if user is None:
user = author
if role in user.roles:
try:
await self.bot.send_typing(channel)
await self.bot.remove_roles(user, role)
await asyncio.sleep(1)
await self.bot.say("Role successfully removed.")
except discord.Forbidden:
await self.bot.send_typing(channel)
await asyncio.sleep(1)
await self.bot.say("I don't have permissions to manage roles!")
else:
await self.bot.send_typing(channel)
await asyncio.sleep(1)
await self.bot.say("User does not have that role.")
#@commands.group(pass_context=True, no_pm=True)
#@checks.mod_or_permissions()
#async def welcome(self, ctx)
#"""Shows your server's current welcome message or changes it. Bot Commander required"""
#server = ctx.message.server
#lm = load_messages()
#wlc = lm[server.id]['welcome'].format('user')
#await self.bot.say("**your server's current welcome message:** `{}`".format(wlc))
#@welcome.command(pass_context=True, no_pm=True)
#@checks.mod_or_permissions()
#async def onjoin(self, ctx, args)
#"""Sets the server's welcome message to when a new user joins the server"""
#server= ctx.message.server
#lm = load_messages()
def create_environment(cog: 'Exec', ctx: DogbotContext) -> Dict[Any, Any]:
async def upload(file_name: str) -> Message:
"""Shortcut to upload a file."""
with open(file_name, 'rb') as fp:
return await ctx.send(file=discord.File(fp))
async def send(*args, **kwargs) -> Message:
"""Shortcut to send()."""
return await ctx.send(*args, **kwargs)
def better_dir(*args, **kwargs) -> List[str]:
"""dir(), but without magic methods."""
return [n for n in dir(*args, **kwargs) if not n.endswith('__') and not n.startswith('__')]
T = TypeVar('T')
def grabber(lst: List[T]) -> Callable[[int], T]:
"""Returns a function that, when called, grabs an item by ID from a list of objects with an ID."""
def _grabber_function(thing_id: int) -> T:
return discord.utils.get(lst, id=thing_id)
return _grabber_function
env = {
'bot': ctx.bot,
'ctx': ctx,
'msg': ctx.message,
'guild': ctx.guild,
'channel': ctx.channel,
'me': ctx.message.author,
'cog': cog,
# modules
'discord': discord,
'commands': commands,
'command': commands.command,
'group': commands.group,
# utilities
'_get': discord.utils.get,
'_find': discord.utils.find,
'_upload': upload,
'_send': send,
# grabbers
'_g': grabber(ctx.bot.guilds),
'_u': grabber(ctx.bot.users),
'_c': grabber(list(ctx.bot.get_all_channels())),
# last result
'_': cog.last_result,
'_p': cog.previous_code,
'dir': better_dir,
}
# add globals to environment
env.update(globals())
return env
def _do_command(*, thing):
_toggle_help = f"""
Sets whether or not I announce when someone {thing.action}s the server.
Specifying with no arguments will toggle it.
"""
_channel_help = f"""
Sets the channel where I will {thing}.
If no arguments are given, it shows the current channel.
This **must** be specified due to the fact that default channels
are no longer a thing. ([see here]({_DEFAULT_CHANNEL_CHANGE_URL}))
If this isn't specified, or the channel was deleted, the message
will not show.
"""
_delete_after_help = f"""
Sets the time it takes for {thing} messages to be auto-deleted.
Passing it with no arguments will return the current duration.
A number less than or equal 0 will disable automatic deletion.
"""
_message_help = f"""
Sets the bot's message when a member {thing.action}s this server.
The following special formats can be in the message:
`{{{{user}}}}` = The member that {thing.past_tense}. If one isn't placed,
it's placed at the beginning of the message.
`{{{{uid}}}}` = The ID of member that {thing.past_tense}.
`{{{{server}}}}` = The name of the server.
`{{{{count}}}}` = How many members are in the server now.
`{{{{countord}}}}` = Like `{{{{count}}}}`, but as an ordinal,
(e.g. instead of `5` it becomes `5th`.)
`{{{{time}}}}` = The date and time when the member {thing.past_tense}.
"""
@commands.group(name=thing.command_name, help=_toggle_help, invoke_without_command=True)
@_server_message_check()
async def group(self, ctx, enable: bool=None):
await self._toggle_config(ctx, enable, thing=thing)
@group.command(name='message', help=_message_help)
@_server_message_check()
async def group_message(self, ctx, *, message: special_message):
await self._message_config(ctx, message, thing=thing)
@group.command(name='channel', help=_channel_help)
@_server_message_check()
async def group_channel(self, ctx, *, channel: discord.TextChannel):
await self._channel_config(ctx, channel, thing=thing)
@group.command(name='delete', help=_delete_after_help)
@_server_message_check()
async def group_delete(self, ctx, *, duration: int):
await self._delete_after_config(ctx, duration, thing=thing)
return group, group_message, group_channel, group_delete
def check_emotes(self, message):
# check if setting is on in this server
# Let emotes happen in PMs always
server = message.server
# Filter unauthorized users, bots and empty messages
if not (self.bot.user_allowed(message) and message.content):
return
# Don't respond to commands
for m in self.bot.settings.get_prefixes(server):
if message.content.startswith(m):
return
if server is not None:
if server.id not in self.servers:
# default off
self.servers[server.id] = dict({"status": False})
if "emotes" not in self.servers[server.id]:
self.servers[server.id]["emotes"] = dict()
dataIO.save_json(self.data_path, self.servers)
# emotes is off, so ignore
if "status" not in self.servers[server.id]:
self.servers[server.id] = dict({"status": False})
if "emotes" not in self.servers[server.id]:
self.servers[server.id]["emotes"] = dict()
dataIO.save_json(self.data_path, self.servers)
if not self.servers[server.id]["status"]:
return
msg = message.content.lower().split()
listed = []
regexen = []
for n in sorted(self.servers[server.id]["emotes"]):
if not n[0].isalnum():
regexen.append(re.compile(r"\B"+n+r"\b"))
else:
regexen.append(re.compile(r"\b"+n+r"\b"))
for w, r in itertools.product(msg, regexen):
match = r.search(w)
if match:
listed.append(self.servers[server.id]["emotes"][match.group(0)])
pnglisted = list(filter(lambda n: not n.endswith('.gif'), listed))
giflisted = list(filter(lambda n: n.endswith('.gif'), listed))
if pnglisted and len(pnglisted) > 1:
ims = self.imgprocess(pnglisted)
await self.bot.send_file(message.channel, self.emote+ims)
elif pnglisted:
await self.bot.send_file(message.channel, self.emote+pnglisted[0])
if giflisted:
for ims in giflisted:
await self.bot.send_file(message.channel, self.emote+ims)
def add_twitch_url(self, ctx, url: str):
"""Saves your user's twitch URL
EXAMPLE: !twitch add MyTwitchName
RESULT: Saves your twitch URL; notifications will be sent to this server when you go live"""
await ctx.message.channel.trigger_typing()
# This uses a lookbehind to check if twitch.tv exists in the url given
# If it does, it matches twitch.tv/user and sets the url as that
# Then (in the else) add https://www. to that
# Otherwise if it doesn't match, we'll hit an AttributeError due to .group(0)
# This means that the url was just given as a user (or something complete invalid)
# So set URL as https://www.twitch.tv/[url]
# Even if this was invalid such as https://www.twitch.tv/google.com/
# For example, our next check handles that
try:
url = re.search("((?<=://)?twitch.tv/)+(.*)", url).group(0)
except AttributeError:
url = "https://www.twitch.tv/{}".format(url)
else:
url = "https://www.{}".format(url)
# Try to find the channel provided, we'll get a 404 response if it does not exist
status = await utils.request(url, attr='status')
if not status == 200:
await self.bot.say("That twitch user does not exist! "
"What would be the point of adding a nonexistant twitch user? Silly")
return
key = ctx.message.author.id
entry = {'twitch_url': url,
'servers': [ctx.message.server.id],
'notifications_on': 1,
'live': 0,
'member_id': key}
update = {'twitch_url': url}
# Check to see if this user has already saved a twitch URL
# If they have, update the URL, otherwise create a new entry
# Assuming they're not live, and notifications should be on
if not await utils.add_content('twitch', entry):
await utils.update_content('twitch', update, key)
await self.bot.say("I have just saved your twitch url {}".format(ctx.message.author.mention))
def picarto(self, ctx, member: discord.Member = None):
"""This command can be used to view Picarto stats about a certain member
EXAMPLE: !picarto @otherPerson
RESULT: Info about their picarto stream"""
# If member is not given, base information on the author
member = member or ctx.message.author
picarto_entry = await utils.get_content('picarto', member.id)
if picarto_entry is None:
await self.bot.say("That user does not have a picarto url setup!")
return
member_url = picarto_entry['picarto_url']
# Use regex to get the actual username so that we can make a request to the API
stream = re.search("(?<=picarto.tv/)(.*)", member_url).group(1)
url = BASE_URL + '/channel/{}'.format(stream)
payload = {'key': api_key}
data = await utils.request(url, payload=payload)
if data is None:
await self.bot.say("I couldn't connect to Picarto!")
return
# Not everyone has all these settings, so use this as a way to print information if it does, otherwise ignore it
things_to_print = ['channel', 'commissions_enabled', 'is_nsfw', 'program', 'tablet', 'followers',
'content_type']
embed = discord.Embed(title='{}\'s Picarto'.format(data['channel']), url=url)
if data['avatar_url']:
embed.set_thumbnail(url=data['avatar_url'])
for i, result in data.items():
if i in things_to_print and str(result):
i = i.title().replace('_', ' ')
embed.add_field(name=i, value=str(result))
# Social URL's can be given if a user wants them to show
# Print them if they exist, otherwise don't try to include them
for i, result in data['social_urls'].items():
embed.add_field(name=i.title(), value=result)
await self.bot.say(embed=embed)
def _add_entries(self, commands):
"""
Adds commands from a dict to the paginator
:param commands: the dict with commands
"""
for name, command in commands:
# skip aliases
if name in command.aliases:
continue
if isinstance(command, Group):
self._expand_group(command, '')
continue
entry = '**{0}** - {1}'.format(name, command.short_doc)
shortened = self.shorten(entry)
self._paginator.add_line(shortened)
def _expand_group(self, group, prefix):
"""
Recursively expands a Group into paginator
:param group: the Group to expand
:param prefix: prefix of the line
"""
if not isinstance(group, Group):
entry = '**{prefix}{0}** - {1}'.format(group.name, group.short_doc, prefix=prefix)
shortened = self.shorten(entry)
self._paginator.add_line(shortened)
else:
entry = '**{prefix}{0}** - {1}'.format(group.name, group.short_doc, prefix=prefix)
shortened = self.shorten(entry)
self._paginator.add_line(shortened)
for subcommand in group.commands.copy().values():
# Build the prefix with group name so we get a nice list
self._expand_group(subcommand, ' {prefix}{0} '.format(group.name, prefix=prefix))
def _add_subcommands_to_page(self, max_width, commands):
for name, command in commands:
if name in command.aliases:
# skip aliases
continue
entry = ' {0:<{width}} {1}'.format(name, command.short_doc, width=max_width)
shortened = self.shorten(entry)
self._paginator.add_line(shortened)
if isinstance(command,Group):
max_count = len(command.commands)
uni = "?"
for index,command in enumerate(command.commands,start = 1):
if index == max_count: uni = "?"
entry = ' {uni}{0:<{width}} {1}'.format(command.name, command.short_doc, width=max_width,uni=uni)
shortened = self.shorten(entry)
self._paginator.add_line(shortened)
def group(name=None, **attrs):
return commands.command(name=name, cls=Group, **attrs)
def imgwelcome_bonus(self, ctx):
"""Toggle display of additional text welcome messages when a user joins the server."""
if ctx.invoked_subcommand is None or isinstance(ctx.invoked_subcommand, commands.Group):
await send_cmd_help(ctx)
return
def imgwelcome_font(self, ctx):
"""Place your font files in the data/imgwelcome/fonts/ directory.
Valid font areas to change are: welcome, server and name.
"""
if ctx.invoked_subcommand is None or isinstance(ctx.invoked_subcommand, commands.Group):
await send_cmd_help(ctx)
return
def get_help(bot) -> tuple:
"""
Return a general Embed onject for help.
:param bot: the Yasen instance.
:return: a discord Embed object for general help.
"""
from bot import __title__ as name
prefix = bot.prefix
description = f'For detailed help please use {prefix}help [command_name]'
embed = Embed(colour=bot.colour, description=description)
embed.set_author(name=f'{name} Help', icon_url=bot.user.avatar_url)
cog_cmd = {}
all_help = {}
for command in bot.commands.values():
_name = command.name
for n in __resolve_alias(command):
all_help[n] = single_help(bot, command, _name)
cog_name = ' '.join(split_camel(command.cog_name) + ['Commands'])
if cog_name not in cog_cmd:
cog_cmd[cog_name] = []
cog_cmd[cog_name].append(f'`{_name}`')
if isinstance(command, Group):
for sub in command.commands.values():
_child_name = sub.name
full_name = f'{_name} {_child_name}'
all_help[full_name] = single_help(bot, sub, full_name)
cog_cmd[cog_name].append(full_name)
for key in sorted(cog_cmd.keys()):
embed.add_field(
name=key, value=', '.join(set(cog_cmd[key])), inline=False
)
return embed, all_help
def channel(self, ctx):
"""Channel based permissions
Will be overridden by role based permissions."""
if ctx.invoked_subcommand is None or \
isinstance(ctx.invoked_subcommand, commands.Group):
await send_cmd_help(ctx)
def role(self, ctx):
"""Role based permissions
Overrides channel based permissions"""
if ctx.invoked_subcommand is None or \
isinstance(ctx.invoked_subcommand, commands.Group):
await send_cmd_help(ctx)
def repo(self, ctx):
"""Repo management commands"""
if ctx.invoked_subcommand is None or \
isinstance(ctx.invoked_subcommand, commands.Group):
await self.bot.send_cmd_help(ctx)
return