First pass at documentation reform.
@ -47,11 +47,22 @@ class _Undefined:
|
||||
_undefined = _Undefined()
|
||||
|
||||
class Snowflake(metaclass=abc.ABCMeta):
|
||||
"""An ABC that details the common operations on a Discord model.
|
||||
|
||||
Almost all :ref:`Discord models <discord_api_models>` meet this
|
||||
abstract base class.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
id: int
|
||||
The model's unique ID.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def created_at(self):
|
||||
"""Returns the model's creation time in UTC."""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
@ -68,16 +79,39 @@ class Snowflake(metaclass=abc.ABCMeta):
|
||||
return NotImplemented
|
||||
|
||||
class User(metaclass=abc.ABCMeta):
|
||||
"""An ABC that details the common operations on a Discord user.
|
||||
|
||||
The following implement this ABC:
|
||||
|
||||
- :class:`User`
|
||||
- :class:`ClientUser`
|
||||
- :class:`Member`
|
||||
|
||||
This ABC must also implement :class:`abc.Snowflake`.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
name: str
|
||||
The user's username.
|
||||
discriminator: str
|
||||
The user's discriminator.
|
||||
avatar: Optional[str]
|
||||
The avatar hash the user has.
|
||||
bot: bool
|
||||
If the user is a bot account.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def display_name(self):
|
||||
"""Returns the user's display name."""
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def mention(self):
|
||||
"""Returns a string that allows you to mention the given user."""
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
@ -97,6 +131,20 @@ class User(metaclass=abc.ABCMeta):
|
||||
return NotImplemented
|
||||
|
||||
class PrivateChannel(metaclass=abc.ABCMeta):
|
||||
"""An ABC that details the common operations on a private Discord channel.
|
||||
|
||||
The follow implement this ABC:
|
||||
|
||||
- :class:`DMChannel`
|
||||
- :class:`GroupChannel`
|
||||
|
||||
This ABC must also implement :class:`abc.Snowflake`.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
me: :class:`ClientUser`
|
||||
The user presenting yourself.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
@classmethod
|
||||
@ -115,6 +163,25 @@ class PrivateChannel(metaclass=abc.ABCMeta):
|
||||
_Overwrites = namedtuple('_Overwrites', 'id allow deny type')
|
||||
|
||||
class GuildChannel:
|
||||
"""An ABC that details the common operations on a Discord guild channel.
|
||||
|
||||
The follow implement this ABC:
|
||||
|
||||
- :class:`TextChannel`
|
||||
- :class:`VoiceChannel`
|
||||
|
||||
This ABC must also implement :class:`abc.Snowflake`.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
name: str
|
||||
The channel name.
|
||||
guild: :class:`Guild`
|
||||
The guild the channel belongs to.
|
||||
position: int
|
||||
The position in the channel list. This is a number that starts at 0.
|
||||
e.g. the top channel is position 0.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
def __str__(self):
|
||||
@ -539,6 +606,20 @@ class GuildChannel:
|
||||
return result
|
||||
|
||||
class Messageable(metaclass=abc.ABCMeta):
|
||||
"""An ABC that details the common operations on a model that can send messages.
|
||||
|
||||
The follow implement this ABC:
|
||||
|
||||
- :class:`TextChannel`
|
||||
- :class:`DMChannel`
|
||||
- :class:`GroupChannel`
|
||||
- :class:`User`
|
||||
- :class:`Member`
|
||||
- :class:`~ext.commands.Context`
|
||||
|
||||
This ABC must also implement :class:`abc.Snowflake`.
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@asyncio.coroutine
|
||||
@ -728,7 +809,7 @@ class Messageable(metaclass=abc.ABCMeta):
|
||||
def history(self, *, limit=100, before=None, after=None, around=None, reverse=None):
|
||||
"""Return an :class:`AsyncIterator` that enables receiving the destination's message history.
|
||||
|
||||
You must have Read Message History permissions to use this.
|
||||
You must have :attr:`~Permissions.read_message_history` permissions to use this.
|
||||
|
||||
All parameters are optional.
|
||||
|
||||
@ -799,6 +880,13 @@ class Messageable(metaclass=abc.ABCMeta):
|
||||
|
||||
|
||||
class Connectable(metaclass=abc.ABCMeta):
|
||||
"""An ABC that details the common operations on a channel that can
|
||||
connect to a voice server.
|
||||
|
||||
The follow implement this ABC:
|
||||
|
||||
- :class:`VoiceChannel`
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
@abc.abstractmethod
|
||||
|
@ -428,7 +428,7 @@ class DMChannel(discord.abc.Messageable, Hashable):
|
||||
----------
|
||||
recipient: :class:`User`
|
||||
The user you are participating with in the direct message channel.
|
||||
me: :class:`User`
|
||||
me: :class:`ClientUser`
|
||||
The user presenting yourself.
|
||||
id: int
|
||||
The direct message channel ID.
|
||||
@ -507,7 +507,7 @@ class GroupChannel(discord.abc.Messageable, Hashable):
|
||||
----------
|
||||
recipients: list of :class:`User`
|
||||
The users you are participating with in the group channel.
|
||||
me: :class:`User`
|
||||
me: :class:`ClientUser`
|
||||
The user presenting yourself.
|
||||
id: int
|
||||
The group channel ID.
|
||||
|
@ -123,7 +123,7 @@ class Emoji(Hashable):
|
||||
|
||||
Deletes the custom emoji.
|
||||
|
||||
You must have :attr:`Permissions.manage_emojis` permission to
|
||||
You must have :attr:`~Permissions.manage_emojis` permission to
|
||||
do this.
|
||||
|
||||
Guild local emotes can only be deleted by user bots.
|
||||
@ -149,7 +149,7 @@ class Emoji(Hashable):
|
||||
|
||||
Edits the custom emoji.
|
||||
|
||||
You must have :attr:`Permissions.manage_emojis` permission to
|
||||
You must have :attr:`~Permissions.manage_emojis` permission to
|
||||
do this.
|
||||
|
||||
Guild local emotes can only be edited by user bots.
|
||||
|
@ -55,7 +55,7 @@ def when_mentioned_or(*prefixes):
|
||||
|
||||
See Also
|
||||
----------
|
||||
:func:`when_mentioned`
|
||||
:func:`.when_mentioned`
|
||||
"""
|
||||
def inner(bot, msg):
|
||||
r = list(prefixes)
|
||||
@ -212,17 +212,17 @@ class BotBase(GroupMixin):
|
||||
def check(self, func):
|
||||
"""A decorator that adds a global check to the bot.
|
||||
|
||||
A global check is similar to a :func:`check` that is applied
|
||||
A global check is similar to a :func:`.check` that is applied
|
||||
on a per command basis except it is run before any command checks
|
||||
have been verified and applies to every command the bot has.
|
||||
|
||||
.. info::
|
||||
.. note::
|
||||
|
||||
This function can either be a regular function or a coroutine.
|
||||
|
||||
Similar to a command :func:`check`\, this takes a single parameter
|
||||
of type :class:`Context` and can only raise exceptions derived from
|
||||
:exc:`CommandError`.
|
||||
Similar to a command :func:`.check`\, this takes a single parameter
|
||||
of type :class:`.Context` and can only raise exceptions derived from
|
||||
:exc:`.CommandError`.
|
||||
|
||||
Example
|
||||
---------
|
||||
@ -240,7 +240,7 @@ class BotBase(GroupMixin):
|
||||
def add_check(self, func):
|
||||
"""Adds a global check to the bot.
|
||||
|
||||
This is the non-decorator interface to :meth:`check`.
|
||||
This is the non-decorator interface to :meth:`.check`.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
@ -275,15 +275,15 @@ class BotBase(GroupMixin):
|
||||
|
||||
@asyncio.coroutine
|
||||
def is_owner(self, user):
|
||||
"""Checks if a :class:`User` or :class:`Member` is the owner of
|
||||
"""Checks if a :class:`.User` or :class:`.Member` is the owner of
|
||||
this bot.
|
||||
|
||||
If an :attr:`owner_id` is not set, it is fetched automatically
|
||||
through the use of :meth:`application_info`.
|
||||
through the use of :meth:`~.Bot.application_info`.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
user: :class:`abc.User`
|
||||
user: :class:`.abc.User`
|
||||
The user to check for.
|
||||
"""
|
||||
|
||||
@ -300,11 +300,11 @@ class BotBase(GroupMixin):
|
||||
called. This makes it a useful function to set up database
|
||||
connections or any type of set up required.
|
||||
|
||||
This pre-invoke hook takes a sole parameter, a :class:`Context`.
|
||||
This pre-invoke hook takes a sole parameter, a :class:`.Context`.
|
||||
|
||||
.. note::
|
||||
|
||||
The :meth:`before_invoke` and :meth:`after_invoke` hooks are
|
||||
The :meth:`~.Bot.before_invoke` and :meth:`~.Bot.after_invoke` hooks are
|
||||
only called if all checks and argument parsing procedures pass
|
||||
without error. If any check or argument parsing procedures fail
|
||||
then the hooks are not called.
|
||||
@ -316,7 +316,7 @@ class BotBase(GroupMixin):
|
||||
|
||||
Raises
|
||||
-------
|
||||
discord.ClientException
|
||||
:exc:`.ClientException`
|
||||
The coroutine is not actually a coroutine.
|
||||
"""
|
||||
if not asyncio.iscoroutinefunction(coro):
|
||||
@ -332,14 +332,14 @@ class BotBase(GroupMixin):
|
||||
called. This makes it a useful function to clean-up database
|
||||
connections or any type of clean up required.
|
||||
|
||||
This post-invoke hook takes a sole parameter, a :class:`Context`.
|
||||
This post-invoke hook takes a sole parameter, a :class:`.Context`.
|
||||
|
||||
.. note::
|
||||
|
||||
Similar to :meth:`before_invoke`\, this is not called unless
|
||||
Similar to :meth:`~.Bot.before_invoke`\, this is not called unless
|
||||
checks and argument parsing procedures succeed. This hook is,
|
||||
however, **always** called regardless of the internal command
|
||||
callback raising an error (i.e. :exc:`CommandInvokeError`\).
|
||||
callback raising an error (i.e. :exc:`.CommandInvokeError`\).
|
||||
This makes it ideal for clean-up scenarios.
|
||||
|
||||
Parameters
|
||||
@ -349,7 +349,7 @@ class BotBase(GroupMixin):
|
||||
|
||||
Raises
|
||||
-------
|
||||
discord.ClientException
|
||||
:exc:`.ClientException`
|
||||
The coroutine is not actually a coroutine.
|
||||
"""
|
||||
if not asyncio.iscoroutinefunction(coro):
|
||||
@ -361,7 +361,7 @@ class BotBase(GroupMixin):
|
||||
# listener registration
|
||||
|
||||
def add_listener(self, func, name=None):
|
||||
"""The non decorator alternative to :meth:`listen`.
|
||||
"""The non decorator alternative to :meth:`.listen`.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
@ -415,7 +415,7 @@ class BotBase(GroupMixin):
|
||||
def listen(self, name=None):
|
||||
"""A decorator that registers another function as an external
|
||||
event listener. Basically this allows you to listen to multiple
|
||||
events from different places e.g. such as :func:`discord.on_ready`
|
||||
events from different places e.g. such as :func:`.on_ready`
|
||||
|
||||
The functions being listened to must be a coroutine.
|
||||
|
||||
@ -438,7 +438,7 @@ class BotBase(GroupMixin):
|
||||
|
||||
Raises
|
||||
-------
|
||||
discord.ClientException
|
||||
:exc:`.ClientException`
|
||||
The function being listened to is not a coroutine.
|
||||
"""
|
||||
|
||||
@ -459,7 +459,7 @@ class BotBase(GroupMixin):
|
||||
into a singular class that shares some state or no state at all.
|
||||
|
||||
The cog can also have a ``__global_check`` member function that allows
|
||||
you to define a global check. See :meth:`check` for more info.
|
||||
you to define a global check. See :meth:`.check` for more info.
|
||||
|
||||
More information will be documented soon.
|
||||
|
||||
@ -515,7 +515,7 @@ class BotBase(GroupMixin):
|
||||
|
||||
Returns
|
||||
---------
|
||||
Set[:class:`Command`]
|
||||
Set[:class:`.Command`]
|
||||
A unique set of commands without aliases that belong
|
||||
to the cog.
|
||||
"""
|
||||
@ -675,27 +675,27 @@ class BotBase(GroupMixin):
|
||||
|
||||
Returns the invocation context from the message.
|
||||
|
||||
This is a more low-level counter-part for :meth:`process_message`
|
||||
This is a more low-level counter-part for :meth:`.process_commands`
|
||||
to allow users more fine grained control over the processing.
|
||||
|
||||
The returned context is not guaranteed to be a valid invocation
|
||||
context, :attr:`Context.valid` must be checked to make sure it is.
|
||||
context, :attr:`.Context.valid` must be checked to make sure it is.
|
||||
If the context is not valid then it is not a valid candidate to be
|
||||
invoked under :meth:`invoke`.
|
||||
invoked under :meth:`~.Bot.invoke`.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
message: :class:`discord.Message`
|
||||
The message to get the invocation context from.
|
||||
cls: type
|
||||
cls
|
||||
The factory class that will be used to create the context.
|
||||
By default, this is :class:`Context`. Should a custom
|
||||
class be provided, it must be similar enough to :class:`Context`\'s
|
||||
By default, this is :class:`.Context`. Should a custom
|
||||
class be provided, it must be similar enough to :class:`.Context`\'s
|
||||
interface.
|
||||
|
||||
Returns
|
||||
--------
|
||||
:class:`Context`
|
||||
:class:`.Context`
|
||||
The invocation context. The type of this can change via the
|
||||
``cls`` parameter.
|
||||
"""
|
||||
@ -732,7 +732,7 @@ class BotBase(GroupMixin):
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
ctx: :class:`Context`
|
||||
ctx: :class:`.Context`
|
||||
The invocation context to invoke.
|
||||
"""
|
||||
if ctx.command is not None:
|
||||
@ -756,12 +756,12 @@ class BotBase(GroupMixin):
|
||||
to the bot and other groups. Without this coroutine, none of the
|
||||
commands will be triggered.
|
||||
|
||||
By default, this coroutine is called inside the :func:`on_message`
|
||||
event. If you choose to override the :func:`on_message` event, then
|
||||
By default, this coroutine is called inside the :func:`.on_message`
|
||||
event. If you choose to override the :func:`.on_message` event, then
|
||||
you should invoke this coroutine as well.
|
||||
|
||||
This is built using other low level tools, and is equivalent to a
|
||||
call to :meth:`get_context` followed by a call to :meth:`invoke`.
|
||||
call to :meth:`~.Bot.get_context` followed by a call to :meth:`~.Bot.invoke`.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
@ -782,7 +782,10 @@ class Bot(BotBase, discord.Client):
|
||||
anything that you can do with a :class:`discord.Client` you can do with
|
||||
this bot.
|
||||
|
||||
This class also subclasses :class:`GroupMixin` to provide the functionality
|
||||
.. _deque: https://docs.python.org/3.4/library/collections.html#collections.deque
|
||||
.. _event loop: https://docs.python.org/3/library/asyncio-eventloops.html
|
||||
|
||||
This class also subclasses :class:`.GroupMixin` to provide the functionality
|
||||
to manage commands.
|
||||
|
||||
Attributes
|
||||
@ -799,18 +802,18 @@ class Bot(BotBase, discord.Client):
|
||||
The command prefix could also be a list or a tuple indicating that
|
||||
multiple checks for the prefix should be used and the first one to
|
||||
match will be the invocation prefix. You can get this prefix via
|
||||
:attr:`Context.prefix`.
|
||||
:attr:`.Context.prefix`.
|
||||
description : str
|
||||
The content prefixed into the default help message.
|
||||
self_bot : bool
|
||||
If ``True``, the bot will only listen to commands invoked by itself rather
|
||||
than ignoring itself. If ``False`` (the default) then the bot will ignore
|
||||
itself. This cannot be changed once initialised.
|
||||
formatter : :class:`HelpFormatter`
|
||||
formatter : :class:`.HelpFormatter`
|
||||
The formatter used to format the help message. By default, it uses a
|
||||
the :class:`HelpFormatter`. Check it for more info on how to override it.
|
||||
the :class:`.HelpFormatter`. Check it for more info on how to override it.
|
||||
If you want to change the help command completely (add aliases, etc) then
|
||||
a call to :meth:`remove_command` with 'help' as the argument would do the
|
||||
a call to :meth:`~.Bot.remove_command` with 'help' as the argument would do the
|
||||
trick.
|
||||
pm_help : Optional[bool]
|
||||
A tribool that indicates if the help command should PM the user instead of
|
||||
@ -823,7 +826,7 @@ class Bot(BotBase, discord.Client):
|
||||
A dictionary of options to pass in for the construction of the help command.
|
||||
This allows you to change the command behaviour without actually changing
|
||||
the implementation of the command. The attributes will be the same as the
|
||||
ones passed in the :class:`Command` constructor. Note that ``pass_context``
|
||||
ones passed in the :class:`.Command` constructor. Note that ``pass_context``
|
||||
will always be set to ``True`` regardless of what you pass in.
|
||||
command_not_found : str
|
||||
The format string used when the help command is invoked with a command that
|
||||
@ -833,16 +836,16 @@ class Bot(BotBase, discord.Client):
|
||||
The format string used when the help command is invoked with requests for a
|
||||
subcommand but the command does not have any subcommands. Defaults to
|
||||
``"Command {0.name} has no subcommands."``. The first format argument is the
|
||||
:class:`Command` attempted to get a subcommand and the second is the name.
|
||||
:class:`.Command` attempted to get a subcommand and the second is the name.
|
||||
owner_id: Optional[int]
|
||||
The ID that owns the bot. If this is not set and is then queried via
|
||||
:meth:`is_owner` then it is fetched automatically using
|
||||
:meth:`application_info`.
|
||||
:meth:`.is_owner` then it is fetched automatically using
|
||||
:meth:`~.Bot.application_info`.
|
||||
"""
|
||||
pass
|
||||
|
||||
class AutoShardedBot(BotBase, discord.AutoShardedClient):
|
||||
"""This is similar to :class:`Bot` except that it is derived from
|
||||
"""This is similar to :class:`.Bot` except that it is derived from
|
||||
:class:`discord.AutoShardedClient` instead.
|
||||
"""
|
||||
pass
|
||||
|
@ -40,7 +40,7 @@ class Context(discord.abc.Messageable):
|
||||
-----------
|
||||
message: :class:`discord.Message`
|
||||
The message that triggered the command being executed.
|
||||
bot: :class:`Bot`
|
||||
bot: :class:`.Bot`
|
||||
The bot that contains the command being executed.
|
||||
args: list
|
||||
The list of transformed arguments that were passed into the command.
|
||||
@ -53,13 +53,13 @@ class Context(discord.abc.Messageable):
|
||||
prefix: str
|
||||
The prefix that was used to invoke the command.
|
||||
command
|
||||
The command (i.e. :class:`Command` or its superclasses) that is being
|
||||
The command (i.e. :class:`.Command` or its superclasses) that is being
|
||||
invoked currently.
|
||||
invoked_with: str
|
||||
The command name that triggered this invocation. Useful for finding out
|
||||
which alias called the command.
|
||||
invoked_subcommand
|
||||
The subcommand (i.e. :class:`Command` or its superclasses) that was
|
||||
The subcommand (i.e. :class:`.Command` or its superclasses) that was
|
||||
invoked. If no valid subcommand was invoked then this is equal to
|
||||
`None`.
|
||||
subcommand_passed: Optional[str]
|
||||
@ -93,7 +93,7 @@ class Context(discord.abc.Messageable):
|
||||
Calls a command with the arguments given.
|
||||
|
||||
This is useful if you want to just call the callback that a
|
||||
:class:`Command` holds internally.
|
||||
:class:`.Command` holds internally.
|
||||
|
||||
Note
|
||||
------
|
||||
@ -101,7 +101,7 @@ class Context(discord.abc.Messageable):
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
command : :class:`Command`
|
||||
command : :class:`.Command`
|
||||
A command or superclass of a command that is going to be called.
|
||||
\*args
|
||||
The arguments to to use.
|
||||
|
@ -46,14 +46,14 @@ def _get_from_guilds(bot, getter, argument):
|
||||
return result
|
||||
|
||||
class Converter:
|
||||
"""The base class of custom converters that require the :class:`Context`
|
||||
"""The base class of custom converters that require the :class:`.Context`
|
||||
to be passed to be useful.
|
||||
|
||||
This allows you to implement converters that function similar to the
|
||||
special cased ``discord`` classes.
|
||||
|
||||
Classes that derive from this should override the :meth:`convert` method
|
||||
to do its conversion logic. This method must be a coroutine.
|
||||
Classes that derive from this should override the :meth:`~.Converter.convert`
|
||||
method to do its conversion logic. This method must be a coroutine.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
@ -62,15 +62,13 @@ class Converter:
|
||||
|
||||
The method to override to do conversion logic.
|
||||
|
||||
This can either be a coroutine or a regular function.
|
||||
|
||||
If an error is found while converting, it is recommended to
|
||||
raise a :class:`CommandError` derived exception as it will
|
||||
raise a :exc:`.CommandError` derived exception as it will
|
||||
properly propagate to the error handlers.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
ctx: :class:`Context`
|
||||
ctx: :class:`.Context`
|
||||
The invocation context that the argument is being used in.
|
||||
argument: str
|
||||
The argument that is being converted.
|
||||
@ -86,6 +84,20 @@ class IDConverter(Converter):
|
||||
return self._id_regex.match(argument)
|
||||
|
||||
class MemberConverter(IDConverter):
|
||||
"""Converts to a :class:`Member`.
|
||||
|
||||
All lookups are via the local guild. If in a DM context, then the lookup
|
||||
is done by the global cache.
|
||||
|
||||
The lookup strategy is as follows (in order):
|
||||
|
||||
1. Lookup by ID.
|
||||
2. Lookup by mention.
|
||||
3. Lookup by name#discrim
|
||||
4. Lookup by name
|
||||
5. Lookup by nickname
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
message = ctx.message
|
||||
@ -112,6 +124,17 @@ class MemberConverter(IDConverter):
|
||||
return result
|
||||
|
||||
class UserConverter(IDConverter):
|
||||
"""Converts to a :class:`User`.
|
||||
|
||||
All lookups are via the global user cache.
|
||||
|
||||
The lookup strategy is as follows (in order):
|
||||
|
||||
1. Lookup by ID.
|
||||
2. Lookup by mention.
|
||||
3. Lookup by name#discrim
|
||||
4. Lookup by name
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
match = self._get_id_match(argument) or re.match(r'<@!?([0-9]+)>$', argument)
|
||||
@ -141,6 +164,17 @@ class UserConverter(IDConverter):
|
||||
return result
|
||||
|
||||
class TextChannelConverter(IDConverter):
|
||||
"""Converts to a :class:`TextChannel`.
|
||||
|
||||
All lookups are via the local guild. If in a DM context, then the lookup
|
||||
is done by the global cache.
|
||||
|
||||
The lookup strategy is as follows (in order):
|
||||
|
||||
1. Lookup by ID.
|
||||
2. Lookup by mention.
|
||||
3. Lookup by name
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
bot = ctx.bot
|
||||
@ -170,6 +204,17 @@ class TextChannelConverter(IDConverter):
|
||||
return result
|
||||
|
||||
class VoiceChannelConverter(IDConverter):
|
||||
"""Converts to a :class:`VoiceChannel`.
|
||||
|
||||
All lookups are via the local guild. If in a DM context, then the lookup
|
||||
is done by the global cache.
|
||||
|
||||
The lookup strategy is as follows (in order):
|
||||
|
||||
1. Lookup by ID.
|
||||
2. Lookup by mention.
|
||||
3. Lookup by name
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
bot = ctx.bot
|
||||
@ -198,6 +243,17 @@ class VoiceChannelConverter(IDConverter):
|
||||
return result
|
||||
|
||||
class ColourConverter(Converter):
|
||||
"""Converts to a :class:`Colour`.
|
||||
|
||||
The following formats are accepted:
|
||||
|
||||
- ``0x<hex>``
|
||||
- ``#<hex>``
|
||||
- ``0x#<hex>``
|
||||
- Any of the ``classmethod`` in :class:`Colour`
|
||||
|
||||
- The ``_`` in the name can be optionally replaced with spaces.
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
arg = argument.replace('0x', '').lower()
|
||||
@ -208,12 +264,24 @@ class ColourConverter(Converter):
|
||||
value = int(arg, base=16)
|
||||
return discord.Colour(value=value)
|
||||
except ValueError:
|
||||
method = getattr(discord.Colour, arg, None)
|
||||
method = getattr(discord.Colour, arg.replace(' ', '_'), None)
|
||||
if method is None or not inspect.ismethod(method):
|
||||
raise BadArgument('Colour "{}" is invalid.'.format(arg))
|
||||
return method()
|
||||
|
||||
class RoleConverter(IDConverter):
|
||||
"""Converts to a :class:`Role`.
|
||||
|
||||
|
||||
All lookups are via the local guild. If in a DM context, then the lookup
|
||||
is done by the global cache.
|
||||
|
||||
The lookup strategy is as follows (in order):
|
||||
|
||||
1. Lookup by ID.
|
||||
2. Lookup by mention.
|
||||
3. Lookup by name
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
guild = ctx.message.guild
|
||||
@ -228,11 +296,16 @@ class RoleConverter(IDConverter):
|
||||
return result
|
||||
|
||||
class GameConverter(Converter):
|
||||
"""Converts to :class:`Game`."""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
return discord.Game(name=argument)
|
||||
|
||||
class InviteConverter(Converter):
|
||||
"""Converts to a :class:`Invite`.
|
||||
|
||||
This is done via an HTTP request using :meth:`.Bot.get_invite`.
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
try:
|
||||
@ -242,6 +315,18 @@ class InviteConverter(Converter):
|
||||
raise BadArgument('Invite is invalid or expired') from e
|
||||
|
||||
class EmojiConverter(IDConverter):
|
||||
"""Converts to a :class:`Emoji`.
|
||||
|
||||
|
||||
All lookups are via the local guild. If in a DM context, then the lookup
|
||||
is done by the global cache.
|
||||
|
||||
The lookup strategy is as follows (in order):
|
||||
|
||||
1. Lookup by ID.
|
||||
2. Lookup by extracting ID from the emoji.
|
||||
3. Lookup by name
|
||||
"""
|
||||
@asyncio.coroutine
|
||||
def convert(self, ctx, argument):
|
||||
match = self._get_id_match(argument) or re.match(r'<:[a-zA-Z0-9]+:([0-9]+)>$', argument)
|
||||
@ -272,6 +357,18 @@ class EmojiConverter(IDConverter):
|
||||
return result
|
||||
|
||||
class clean_content(Converter):
|
||||
"""Converts the argument to mention scrubbed version of
|
||||
said content.
|
||||
|
||||
This behaves similarly to :attr:`.Message.clean_content`.
|
||||
|
||||
Attributes
|
||||
------------
|
||||
fix_channel_mentions: bool
|
||||
Whether to clean channel mentions.
|
||||
use_nicknames: bool
|
||||
Whether to use nicknames when transforming mentions.
|
||||
"""
|
||||
def __init__(self, *, fix_channel_mentions=False, use_nicknames=True):
|
||||
self.fix_channel_mentions = fix_channel_mentions
|
||||
self.use_nicknames = use_nicknames
|
||||
|
@ -88,54 +88,54 @@ class Command:
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
name : str
|
||||
name: str
|
||||
The name of the command.
|
||||
callback : coroutine
|
||||
callback: coroutine
|
||||
The coroutine that is executed when the command is called.
|
||||
help : str
|
||||
help: str
|
||||
The long help text for the command.
|
||||
brief : str
|
||||
brief: str
|
||||
The short help text for the command. If this is not specified
|
||||
then the first line of the long help text is used instead.
|
||||
usage : str
|
||||
usage: str
|
||||
A replacement for arguments in the default help text.
|
||||
aliases : list
|
||||
aliases: list
|
||||
The list of aliases the command can be invoked under.
|
||||
pass_context : bool
|
||||
A boolean that indicates that the current :class:`Context` should
|
||||
pass_context: bool
|
||||
A boolean that indicates that the current :class:`.Context` should
|
||||
be passed as the **first parameter**. Defaults to `True`.
|
||||
enabled : bool
|
||||
enabled: bool
|
||||
A boolean that indicates if the command is currently enabled.
|
||||
If the command is invoked while it is disabled, then
|
||||
:exc:`DisabledCommand` is raised to the :func:`on_command_error`
|
||||
:exc:`.DisabledCommand` is raised to the :func:`.on_command_error`
|
||||
event. Defaults to ``True``.
|
||||
parent : Optional[command]
|
||||
parent: Optional[command]
|
||||
The parent command that this command belongs to. ``None`` is there
|
||||
isn't one.
|
||||
checks
|
||||
A list of predicates that verifies if the command could be executed
|
||||
with the given :class:`Context` as the sole parameter. If an exception
|
||||
with the given :class:`.Context` as the sole parameter. If an exception
|
||||
is necessary to be thrown to signal failure, then one derived from
|
||||
:exc:`CommandError` should be used. Note that if the checks fail then
|
||||
:exc:`CheckFailure` exception is raised to the :func:`on_command_error`
|
||||
:exc:`.CommandError` should be used. Note that if the checks fail then
|
||||
:exc:`.CheckFailure` exception is raised to the :func:`.on_command_error`
|
||||
event.
|
||||
description : str
|
||||
description: str
|
||||
The message prefixed into the default help command.
|
||||
hidden : bool
|
||||
hidden: bool
|
||||
If ``True``\, the default help command does not show this in the
|
||||
help output.
|
||||
rest_is_raw : bool
|
||||
rest_is_raw: bool
|
||||
If ``False`` and a keyword-only argument is provided then the keyword
|
||||
only argument is stripped and handled as if it was a regular argument
|
||||
that handles :exc:`MissingRequiredArgument` and default values in a
|
||||
that handles :exc:`.MissingRequiredArgument` and default values in a
|
||||
regular matter rather than passing the rest completely raw. If ``True``
|
||||
then the keyword-only argument will pass in the rest of the arguments
|
||||
in a completely raw matter. Defaults to ``False``.
|
||||
ignore_extra : bool
|
||||
ignore_extra: bool
|
||||
If ``True``\, ignores extraneous strings passed to a command if all its
|
||||
requirements are met (e.g. ``?foo a b c`` when only expecting ``a``
|
||||
and ``b``). Otherwise :func:`on_command_error` and local error handlers
|
||||
are called with :exc:`TooManyArguments`. Defaults to ``True``.
|
||||
and ``b``). Otherwise :func:`.on_command_error` and local error handlers
|
||||
are called with :exc:`.TooManyArguments`. Defaults to ``True``.
|
||||
"""
|
||||
def __init__(self, name, callback, **kwargs):
|
||||
self.name = name
|
||||
@ -418,7 +418,7 @@ class Command:
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
ctx: :class:`Context`
|
||||
ctx: :class:`.Context`
|
||||
The invocation context to reset the cooldown under.
|
||||
"""
|
||||
if self._buckets.valid:
|
||||
@ -439,8 +439,8 @@ class Command:
|
||||
def error(self, coro):
|
||||
"""A decorator that registers a coroutine as a local error handler.
|
||||
|
||||
A local error handler is an :func:`on_command_error` event limited to
|
||||
a single command. However, the :func:`on_command_error` is still
|
||||
A local error handler is an :func:`.on_command_error` event limited to
|
||||
a single command. However, the :func:`.on_command_error` is still
|
||||
invoked afterwards as the catch-all.
|
||||
|
||||
Parameters
|
||||
@ -463,13 +463,13 @@ class Command:
|
||||
def before_invoke(self, coro):
|
||||
"""A decorator that registers a coroutine as a pre-invoke hook.
|
||||
|
||||
A pre-invoke hook is called directly before :meth:`invoke` is
|
||||
A pre-invoke hook is called directly before the command is
|
||||
called. This makes it a useful function to set up database
|
||||
connections or any type of set up required.
|
||||
|
||||
This pre-invoke hook takes a sole parameter, a :class:`Context`.
|
||||
This pre-invoke hook takes a sole parameter, a :class:`.Context`.
|
||||
|
||||
See :meth:`Bot.before_invoke` for more info.
|
||||
See :meth:`.Bot.before_invoke` for more info.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
@ -478,7 +478,7 @@ class Command:
|
||||
|
||||
Raises
|
||||
-------
|
||||
discord.ClientException
|
||||
:exc:`.ClientException`
|
||||
The coroutine is not actually a coroutine.
|
||||
"""
|
||||
if not asyncio.iscoroutinefunction(coro):
|
||||
@ -490,13 +490,13 @@ class Command:
|
||||
def after_invoke(self, coro):
|
||||
"""A decorator that registers a coroutine as a post-invoke hook.
|
||||
|
||||
A post-invoke hook is called directly after :meth:`invoke` is
|
||||
A post-invoke hook is called directly after the command is
|
||||
called. This makes it a useful function to clean-up database
|
||||
connections or any type of clean up required.
|
||||
|
||||
This post-invoke hook takes a sole parameter, a :class:`Context`.
|
||||
This post-invoke hook takes a sole parameter, a :class:`.Context`.
|
||||
|
||||
See :meth:`Bot.after_invoke` for more info.
|
||||
See :meth:`.Bot.after_invoke` for more info.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
@ -505,7 +505,7 @@ class Command:
|
||||
|
||||
Raises
|
||||
-------
|
||||
discord.ClientException
|
||||
:exc:`.ClientException`
|
||||
The coroutine is not actually a coroutine.
|
||||
"""
|
||||
if not asyncio.iscoroutinefunction(coro):
|
||||
@ -577,11 +577,11 @@ class Command:
|
||||
"""|coro|
|
||||
|
||||
Checks if the command can be executed by checking all the predicates
|
||||
inside the :attr:`checks` attribute.
|
||||
inside the :attr:`.checks` attribute.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
ctx: :class:`Context`
|
||||
ctx: :class:`.Context`
|
||||
The ctx of the command currently being invoked.
|
||||
|
||||
Returns
|
||||
@ -613,12 +613,12 @@ class Command:
|
||||
|
||||
class GroupMixin:
|
||||
"""A mixin that implements common functionality for classes that behave
|
||||
similar to :class:`Group` and are allowed to register commands.
|
||||
similar to :class:`.Group` and are allowed to register commands.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
all_commands: dict
|
||||
A mapping of command name to :class:`Command` or superclass
|
||||
A mapping of command name to :class:`.Command` or superclass
|
||||
objects.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
@ -627,7 +627,7 @@ class GroupMixin:
|
||||
|
||||
@property
|
||||
def commands(self):
|
||||
"""Set[:class:`Command`]: A unique set of commands without aliases that are registered."""
|
||||
"""Set[:class:`.Command`]: A unique set of commands without aliases that are registered."""
|
||||
return set(self.all_commands.values())
|
||||
|
||||
def recursively_remove_all_commands(self):
|
||||
@ -637,11 +637,11 @@ class GroupMixin:
|
||||
self.remove_command(command.name)
|
||||
|
||||
def add_command(self, command):
|
||||
"""Adds a :class:`Command` or its superclasses into the internal list
|
||||
"""Adds a :class:`.Command` or its superclasses into the internal list
|
||||
of commands.
|
||||
|
||||
This is usually not called, instead the :meth:`command` or
|
||||
:meth:`group` shortcut decorators are used instead.
|
||||
This is usually not called, instead the :meth:`~.GroupMixin.command` or
|
||||
:meth:`~.GroupMixin.group` shortcut decorators are used instead.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
@ -650,10 +650,10 @@ class GroupMixin:
|
||||
|
||||
Raises
|
||||
-------
|
||||
discord.ClientException
|
||||
:exc:`.ClientException`
|
||||
If the command is already registered.
|
||||
TypeError
|
||||
If the command passed is not a subclass of :class:`Command`.
|
||||
If the command passed is not a subclass of :class:`.Command`.
|
||||
"""
|
||||
|
||||
if not isinstance(command, Command):
|
||||
@ -672,19 +672,19 @@ class GroupMixin:
|
||||
self.all_commands[alias] = command
|
||||
|
||||
def remove_command(self, name):
|
||||
"""Remove a :class:`Command` or subclasses from the internal list
|
||||
"""Remove a :class:`.Command` or subclasses from the internal list
|
||||
of commands.
|
||||
|
||||
This could also be used as a way to remove aliases.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
name : str
|
||||
name: str
|
||||
The name of the command to remove.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Command or subclass
|
||||
:class:`.Command` or subclass
|
||||
The command that was removed. If the name is not valid then
|
||||
`None` is returned instead.
|
||||
"""
|
||||
@ -711,7 +711,7 @@ class GroupMixin:
|
||||
yield from command.walk_commands()
|
||||
|
||||
def get_command(self, name):
|
||||
"""Get a :class:`Command` or subclasses from the internal list
|
||||
"""Get a :class:`.Command` or subclasses from the internal list
|
||||
of commands.
|
||||
|
||||
This could also be used as a way to get aliases.
|
||||
@ -745,8 +745,8 @@ class GroupMixin:
|
||||
return obj
|
||||
|
||||
def command(self, *args, **kwargs):
|
||||
"""A shortcut decorator that invokes :func:`command` and adds it to
|
||||
the internal command list via :meth:`add_command`.
|
||||
"""A shortcut decorator that invokes :func:`.command` and adds it to
|
||||
the internal command list via :meth:`~.GroupMixin.add_command`.
|
||||
"""
|
||||
def decorator(func):
|
||||
result = command(*args, **kwargs)(func)
|
||||
@ -756,8 +756,8 @@ class GroupMixin:
|
||||
return decorator
|
||||
|
||||
def group(self, *args, **kwargs):
|
||||
"""A shortcut decorator that invokes :func:`group` and adds it to
|
||||
the internal command list via :meth:`add_command`.
|
||||
"""A shortcut decorator that invokes :func:`.group` and adds it to
|
||||
the internal command list via :meth:`~.GroupMixin.add_command`.
|
||||
"""
|
||||
def decorator(func):
|
||||
result = group(*args, **kwargs)(func)
|
||||
@ -770,12 +770,12 @@ class Group(GroupMixin, Command):
|
||||
"""A class that implements a grouping protocol for commands to be
|
||||
executed as subcommands.
|
||||
|
||||
This class is a subclass of :class:`Command` and thus all options
|
||||
valid in :class:`Command` are valid in here as well.
|
||||
This class is a subclass of :class:`.Command` and thus all options
|
||||
valid in :class:`.Command` are valid in here as well.
|
||||
|
||||
Attributes
|
||||
-----------
|
||||
invoke_without_command : bool
|
||||
invoke_without_command: bool
|
||||
Indicates if the group callback should begin parsing and
|
||||
invocation only if no subcommand was found. Useful for
|
||||
making it an error handling function to tell the user that
|
||||
@ -820,25 +820,25 @@ class Group(GroupMixin, Command):
|
||||
# Decorators
|
||||
|
||||
def command(name=None, cls=None, **attrs):
|
||||
"""A decorator that transforms a function into a :class:`Command`
|
||||
or if called with :func:`group`, :class:`Group`.
|
||||
"""A decorator that transforms a function into a :class:`.Command`
|
||||
or if called with :func:`.group`, :class:`.Group`.
|
||||
|
||||
By default the ``help`` attribute is received automatically from the
|
||||
docstring of the function and is cleaned up with the use of
|
||||
``inspect.cleandoc``. If the docstring is ``bytes``, then it is decoded
|
||||
into ``str`` using utf-8 encoding.
|
||||
|
||||
All checks added using the :func:`check` & co. decorators are added into
|
||||
All checks added using the :func:`.check` & co. decorators are added into
|
||||
the function. There is no way to supply your own checks through this
|
||||
decorator.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
name : str
|
||||
name: str
|
||||
The name to create the command with. By default this uses the
|
||||
function name unchanged.
|
||||
cls
|
||||
The class to construct with. By default this is :class:`Command`.
|
||||
The class to construct with. By default this is :class:`.Command`.
|
||||
You usually do not change this.
|
||||
attrs
|
||||
Keyword arguments to pass into the construction of the class denoted
|
||||
@ -886,28 +886,28 @@ def command(name=None, cls=None, **attrs):
|
||||
return decorator
|
||||
|
||||
def group(name=None, **attrs):
|
||||
"""A decorator that transforms a function into a :class:`Group`.
|
||||
"""A decorator that transforms a function into a :class:`.Group`.
|
||||
|
||||
This is similar to the :func:`command` decorator but creates a
|
||||
:class:`Group` instead of a :class:`Command`.
|
||||
This is similar to the :func:`.command` decorator but creates a
|
||||
:class:`.Group` instead of a :class:`.Command`.
|
||||
"""
|
||||
return command(name=name, cls=Group, **attrs)
|
||||
|
||||
def check(predicate):
|
||||
"""A decorator that adds a check to the :class:`Command` or its
|
||||
subclasses. These checks could be accessed via :attr:`Command.checks`.
|
||||
"""A decorator that adds a check to the :class:`.Command` or its
|
||||
subclasses. These checks could be accessed via :attr:`.Command.checks`.
|
||||
|
||||
These checks should be predicates that take in a single parameter taking
|
||||
a :class:`Context`. If the check returns a ``False``\-like value then
|
||||
during invocation a :exc:`CheckFailure` exception is raised and sent to
|
||||
the :func:`on_command_error` event.
|
||||
a :class:`.Context`. If the check returns a ``False``\-like value then
|
||||
during invocation a :exc:`.CheckFailure` exception is raised and sent to
|
||||
the :func:`.on_command_error` event.
|
||||
|
||||
If an exception should be thrown in the predicate then it should be a
|
||||
subclass of :exc:`CommandError`. Any exception not subclassed from it
|
||||
subclass of :exc:`.CommandError`. Any exception not subclassed from it
|
||||
will be propagated while those subclassed will be sent to
|
||||
:func:`on_command_error`.
|
||||
:func:`.on_command_error`.
|
||||
|
||||
.. info::
|
||||
.. note::
|
||||
|
||||
These functions can either be regular functions or coroutines.
|
||||
|
||||
@ -960,7 +960,7 @@ def check(predicate):
|
||||
return decorator
|
||||
|
||||
def has_role(name):
|
||||
"""A :func:`check` that is added that checks if the member invoking the
|
||||
"""A :func:`.check` that is added that checks if the member invoking the
|
||||
command has the role specified via the name specified.
|
||||
|
||||
The name is case sensitive and must be exact. No normalisation is done in
|
||||
@ -971,7 +971,7 @@ def has_role(name):
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
name : str
|
||||
name: str
|
||||
The name of the role to check.
|
||||
"""
|
||||
|
||||
@ -985,11 +985,11 @@ def has_role(name):
|
||||
return check(predicate)
|
||||
|
||||
def has_any_role(*names):
|
||||
"""A :func:`check` that is added that checks if the member invoking the
|
||||
"""A :func:`.check` that is added that checks if the member invoking the
|
||||
command has **any** of the roles specified. This means that if they have
|
||||
one out of the three roles specified, then this check will return `True`.
|
||||
|
||||
Similar to :func:`has_role`\, the names passed in must be exact.
|
||||
Similar to :func:`.has_role`\, the names passed in must be exact.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
@ -1015,11 +1015,11 @@ def has_any_role(*names):
|
||||
return check(predicate)
|
||||
|
||||
def has_permissions(**perms):
|
||||
"""A :func:`check` that is added that checks if the member has any of
|
||||
"""A :func:`.check` that is added that checks if the member has any of
|
||||
the permissions necessary.
|
||||
|
||||
The permissions passed in must be exactly like the properties shown under
|
||||
:class:`discord.Permissions`.
|
||||
:class:`.discord.Permissions`.
|
||||
|
||||
Parameters
|
||||
------------
|
||||
@ -1045,7 +1045,7 @@ def has_permissions(**perms):
|
||||
return check(predicate)
|
||||
|
||||
def bot_has_role(name):
|
||||
"""Similar to :func:`has_role` except checks if the bot itself has the
|
||||
"""Similar to :func:`.has_role` except checks if the bot itself has the
|
||||
role.
|
||||
"""
|
||||
|
||||
@ -1059,7 +1059,7 @@ def bot_has_role(name):
|
||||
return check(predicate)
|
||||
|
||||
def bot_has_any_role(*names):
|
||||
"""Similar to :func:`has_any_role` except checks if the bot itself has
|
||||
"""Similar to :func:`.has_any_role` except checks if the bot itself has
|
||||
any of the roles listed.
|
||||
"""
|
||||
def predicate(ctx):
|
||||
@ -1072,7 +1072,7 @@ def bot_has_any_role(*names):
|
||||
return check(predicate)
|
||||
|
||||
def bot_has_permissions(**perms):
|
||||
"""Similar to :func:`has_permissions` except checks if the bot itself has
|
||||
"""Similar to :func:`.has_permissions` except checks if the bot itself has
|
||||
the permissions listed.
|
||||
"""
|
||||
def predicate(ctx):
|
||||
@ -1083,12 +1083,12 @@ def bot_has_permissions(**perms):
|
||||
return check(predicate)
|
||||
|
||||
def guild_only():
|
||||
"""A :func:`check` that indicates this command must only be used in a
|
||||
"""A :func:`.check` that indicates this command must only be used in a
|
||||
guild context only. Basically, no private messages are allowed when
|
||||
using the command.
|
||||
|
||||
This check raises a special exception, :exc:`NoPrivateMessage`
|
||||
that is derived from :exc:`CheckFailure`.
|
||||
This check raises a special exception, :exc:`.NoPrivateMessage`
|
||||
that is derived from :exc:`.CheckFailure`.
|
||||
"""
|
||||
|
||||
def predicate(ctx):
|
||||
@ -1099,13 +1099,13 @@ def guild_only():
|
||||
return check(predicate)
|
||||
|
||||
def is_owner():
|
||||
"""A :func:`check` that checks if the person invoking this command is the
|
||||
"""A :func:`.check` that checks if the person invoking this command is the
|
||||
owner of the bot.
|
||||
|
||||
This is powered by :meth:`Bot.is_owner`.
|
||||
This is powered by :meth:`.Bot.is_owner`.
|
||||
|
||||
This check raises a special exception, :exc:`NotOwner` that is derived
|
||||
from :exc:`CheckFailure`.
|
||||
This check raises a special exception, :exc:`.NotOwner` that is derived
|
||||
from :exc:`.CheckFailure`.
|
||||
"""
|
||||
|
||||
@asyncio.coroutine
|
||||
@ -1117,13 +1117,13 @@ def is_owner():
|
||||
return check(predicate)
|
||||
|
||||
def is_nsfw():
|
||||
"""A :func:`check` that checks if the channel is a NSFW channel."""
|
||||
"""A :func:`.check` that checks if the channel is a NSFW channel."""
|
||||
def pred(ctx):
|
||||
return isinstance(ctx.channel, discord.TextChannel) and ctx.channel.is_nsfw()
|
||||
return check(pred)
|
||||
|
||||
def cooldown(rate, per, type=BucketType.default):
|
||||
"""A decorator that adds a cooldown to a :class:`Command`
|
||||
"""A decorator that adds a cooldown to a :class:`.Command`
|
||||
or its subclasses.
|
||||
|
||||
A cooldown allows a command to only be used a specific amount
|
||||
@ -1137,8 +1137,8 @@ def cooldown(rate, per, type=BucketType.default):
|
||||
- ``BucketType.guild`` for a per-guild basis.
|
||||
- ``BucketType.channel`` for a per-channel basis.
|
||||
|
||||
If a cooldown is triggered, then :exc:`CommandOnCooldown` is triggered in
|
||||
:func:`on_command_error` and the local error handler.
|
||||
If a cooldown is triggered, then :exc:`.CommandOnCooldown` is triggered in
|
||||
:func:`.on_command_error` and the local error handler.
|
||||
|
||||
A command can only have a single cooldown.
|
||||
|
||||
|
@ -38,7 +38,7 @@ class CommandError(DiscordException):
|
||||
|
||||
This exception and exceptions derived from it are handled
|
||||
in a special way as they are caught and passed into a special event
|
||||
from :class:`Bot`\, :func:`on_command_error`.
|
||||
from :class:`.Bot`\, :func:`on_command_error`.
|
||||
"""
|
||||
def __init__(self, message=None, *args):
|
||||
if message is not None:
|
||||
@ -52,7 +52,7 @@ class UserInputError(CommandError):
|
||||
"""The base exception type for errors that involve errors
|
||||
regarding user input.
|
||||
|
||||
This inherits from :exc:`CommandError`.
|
||||
This inherits from :exc:`.CommandError`.
|
||||
"""
|
||||
pass
|
||||
|
||||
@ -80,7 +80,7 @@ class MissingRequiredArgument(UserInputError):
|
||||
|
||||
class TooManyArguments(UserInputError):
|
||||
"""Exception raised when the command was passed too many arguments and its
|
||||
:attr:`Command.ignore_extra` attribute was not set to ``True``.
|
||||
:attr:`.Command.ignore_extra` attribute was not set to ``True``.
|
||||
"""
|
||||
pass
|
||||
|
||||
@ -91,7 +91,7 @@ class BadArgument(UserInputError):
|
||||
pass
|
||||
|
||||
class CheckFailure(CommandError):
|
||||
"""Exception raised when the predicates in :attr:`Command.checks` have failed."""
|
||||
"""Exception raised when the predicates in :attr:`.Command.checks` have failed."""
|
||||
pass
|
||||
|
||||
class NoPrivateMessage(CheckFailure):
|
||||
@ -128,7 +128,7 @@ class CommandOnCooldown(CommandError):
|
||||
-----------
|
||||
cooldown: Cooldown
|
||||
A class with attributes ``rate``, ``per``, and ``type`` similar to
|
||||
the :func:`cooldown` decorator.
|
||||
the :func:`.cooldown` decorator.
|
||||
retry_after: float
|
||||
The amount of seconds to wait before you can retry again.
|
||||
"""
|
||||
|
@ -127,19 +127,19 @@ class HelpFormatter:
|
||||
"""The default base implementation that handles formatting of the help
|
||||
command.
|
||||
|
||||
To override the behaviour of the formatter, :meth:`format`
|
||||
To override the behaviour of the formatter, :meth:`~.HelpFormatter.format`
|
||||
should be overridden. A number of utility functions are provided for use
|
||||
inside that method.
|
||||
|
||||
Parameters
|
||||
Attributes
|
||||
-----------
|
||||
show_hidden : bool
|
||||
show_hidden: bool
|
||||
Dictates if hidden commands should be shown in the output.
|
||||
Defaults to ``False``.
|
||||
show_check_failure : bool
|
||||
Dictates if commands that have their :attr:`Command.checks` failed
|
||||
show_check_failure: bool
|
||||
Dictates if commands that have their :attr:`.Command.checks` failed
|
||||
shown. Defaults to ``False``.
|
||||
width : int
|
||||
width: int
|
||||
The maximum number of characters that fit in a line.
|
||||
Defaults to 80.
|
||||
"""
|
||||
@ -149,15 +149,15 @@ class HelpFormatter:
|
||||
self.show_check_failure = show_check_failure
|
||||
|
||||
def has_subcommands(self):
|
||||
"""bool : Specifies if the command has subcommands."""
|
||||
"""bool: Specifies if the command has subcommands."""
|
||||
return isinstance(self.command, GroupMixin)
|
||||
|
||||
def is_bot(self):
|
||||
"""bool : Specifies if the command being formatted is the bot itself."""
|
||||
"""bool: Specifies if the command being formatted is the bot itself."""
|
||||
return self.command is self.context.bot
|
||||
|
||||
def is_cog(self):
|
||||
"""bool : Specifies if the command being formatted is actually a cog."""
|
||||
"""bool: Specifies if the command being formatted is actually a cog."""
|
||||
return not self.is_bot() and not isinstance(self.command, Command)
|
||||
|
||||
def shorten(self, text):
|
||||
@ -168,7 +168,7 @@ class HelpFormatter:
|
||||
|
||||
@property
|
||||
def max_name_size(self):
|
||||
"""int : Returns the largest name length of a command or if it has subcommands
|
||||
"""int: Returns the largest name length of a command or if it has subcommands
|
||||
the largest subcommand name."""
|
||||
try:
|
||||
commands = self.command.all_commands if not self.is_cog() else self.context.bot.all_commands
|
||||
@ -202,8 +202,8 @@ class HelpFormatter:
|
||||
@asyncio.coroutine
|
||||
def filter_command_list(self):
|
||||
"""Returns a filtered list of commands based on the two attributes
|
||||
provided, :attr:`show_check_failure` and :attr:`show_hidden`. Also
|
||||
filters based on if :meth:`is_cog` is valid.
|
||||
provided, :attr:`show_check_failure` and :attr:`show_hidden`.
|
||||
Also filters based on if :meth:`~.HelpFormatter.is_cog` is valid.
|
||||
|
||||
Returns
|
||||
--------
|
||||
@ -262,13 +262,13 @@ class HelpFormatter:
|
||||
def format_help_for(self, context, command_or_bot):
|
||||
"""Formats the help page and handles the actual heavy lifting of how
|
||||
the help command looks like. To change the behaviour, override the
|
||||
:meth:`format` method.
|
||||
:meth:`~.HelpFormatter.format` method.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
context : :class:`Context`
|
||||
context: :class:`.Context`
|
||||
The context of the invoked help command.
|
||||
command_or_bot : :class:`Command` or :class:`Bot`
|
||||
command_or_bot: :class:`.Command` or :class:`.Bot`
|
||||
The bot or command that we are getting the help of.
|
||||
|
||||
Returns
|
||||
|
@ -566,7 +566,7 @@ class Guild(Hashable):
|
||||
|
||||
Edits the guild.
|
||||
|
||||
You must have the :attr:`Permissions.manage_guild` permission
|
||||
You must have the :attr:`~Permissions.manage_guild` permission
|
||||
to edit the guild.
|
||||
|
||||
Parameters
|
||||
@ -671,7 +671,7 @@ class Guild(Hashable):
|
||||
that got banned along with a ``reason`` field specifying
|
||||
why the user was banned that could be set to ``None``.
|
||||
|
||||
You must have :attr:`Permissions.ban_members` permission
|
||||
You must have :attr:`~Permissions.ban_members` permission
|
||||
to get this information.
|
||||
|
||||
Raises
|
||||
@ -701,7 +701,7 @@ class Guild(Hashable):
|
||||
The inactive members are denoted if they have not logged on in
|
||||
``days`` number of days and they have no roles.
|
||||
|
||||
You must have the :attr:`Permissions.kick_members` permission
|
||||
You must have the :attr:`~Permissions.kick_members` permission
|
||||
to use this.
|
||||
|
||||
To check how many members you would prune without actually pruning,
|
||||
@ -775,7 +775,7 @@ class Guild(Hashable):
|
||||
|
||||
Returns a list of all active instant invites from the guild.
|
||||
|
||||
You must have :attr:`Permissions.manage_guild` to get this information.
|
||||
You must have :attr:`~Permissions.manage_guild` to get this information.
|
||||
|
||||
Raises
|
||||
-------
|
||||
|
@ -458,7 +458,7 @@ class Member(discord.abc.Messageable):
|
||||
|
||||
Moves a member to a new voice channel (they must be connected first).
|
||||
|
||||
You must have the :attr:`Permissions.move_members` permission to
|
||||
You must have the :attr:`~Permissions.move_members` permission to
|
||||
use this.
|
||||
|
||||
This raises the same exceptions as :meth:`edit`.
|
||||
@ -478,7 +478,7 @@ class Member(discord.abc.Messageable):
|
||||
|
||||
Gives the member a number of :class:`Role`\s.
|
||||
|
||||
You must have the :attr:`Permissions.manage_roles` permission to
|
||||
You must have the :attr:`~Permissions.manage_roles` permission to
|
||||
use this.
|
||||
|
||||
Parameters
|
||||
@ -505,7 +505,7 @@ class Member(discord.abc.Messageable):
|
||||
|
||||
Removes :class:`Role`\s from this member.
|
||||
|
||||
You must have the :attr:`Permissions.manage_roles` permission to
|
||||
You must have the :attr:`~Permissions.manage_roles` permission to
|
||||
use this.
|
||||
|
||||
Parameters
|
||||
|
@ -413,7 +413,7 @@ class Message:
|
||||
Deletes the message.
|
||||
|
||||
Your own messages could be deleted without any proper permissions. However to
|
||||
delete other people's messages, you need the :attr:`Permissions.manage_messages`
|
||||
delete other people's messages, you need the :attr:`~Permissions.manage_messages`
|
||||
permission.
|
||||
|
||||
Parameters
|
||||
@ -475,7 +475,7 @@ class Message:
|
||||
def pin(self):
|
||||
"""|coro|
|
||||
|
||||
Pins the message. You must have :attr:`Permissions.manage_messages`
|
||||
Pins the message. You must have :attr:`~Permissions.manage_messages`
|
||||
permissions to do this in a non-private channel context.
|
||||
|
||||
Raises
|
||||
@ -496,7 +496,7 @@ class Message:
|
||||
def unpin(self):
|
||||
"""|coro|
|
||||
|
||||
Unpins the message. You must have :attr:`Permissions.manage_messages`
|
||||
Unpins the message. You must have :attr:`~Permissions.manage_messages`
|
||||
permissions to do this in a non-private channel context.
|
||||
|
||||
Raises
|
||||
@ -520,8 +520,8 @@ class Message:
|
||||
|
||||
The emoji may be a unicode emoji or a custom guild :class:`Emoji`.
|
||||
|
||||
You must have the :attr:`Permissions.add_reactions` permission to
|
||||
add new reactions to a message.
|
||||
You must have the :attr:`~Permissions.add_reactions` and
|
||||
:attr:`~Permissions.read_message_history` permissions to use this.
|
||||
|
||||
Parameters
|
||||
------------
|
||||
@ -560,7 +560,7 @@ class Message:
|
||||
The emoji may be a unicode emoji or a custom guild :class:`Emoji`.
|
||||
|
||||
If the reaction is not your own (i.e. ``member`` parameter is not you) then
|
||||
the :attr:`Permissions.manage_messages` permission is needed.
|
||||
the :attr:`~Permissions.manage_messages` permission is needed.
|
||||
|
||||
The ``member`` parameter must represent a member and meet
|
||||
the :class:`abc.Snowflake` abc.
|
||||
@ -601,7 +601,7 @@ class Message:
|
||||
|
||||
Removes all the reactions from the message.
|
||||
|
||||
You need :attr:`Permissions.manage_messages` permission
|
||||
You need :attr:`~Permissions.manage_messages` permission
|
||||
to use this.
|
||||
|
||||
Raises
|
||||
|
@ -197,7 +197,7 @@ class ClientUser(BaseUser):
|
||||
The user's unique ID.
|
||||
discriminator: str
|
||||
The user's discriminator. This is given when the username has conflicts.
|
||||
avatar: str
|
||||
avatar: Optional[str]
|
||||
The avatar hash the user has. Could be None.
|
||||
bot: bool
|
||||
Specifies if the user is a bot account.
|
||||
@ -404,7 +404,7 @@ class User(BaseUser, discord.abc.Messageable):
|
||||
The user's unique ID.
|
||||
discriminator: str
|
||||
The user's discriminator. This is given when the username has conflicts.
|
||||
avatar: str
|
||||
avatar: Optional[str]
|
||||
The avatar hash the user has. Could be None.
|
||||
bot: bool
|
||||
Specifies if the user is a bot account.
|
||||
|
@ -62,8 +62,8 @@ from .player import AudioPlayer, AudioSource
|
||||
class VoiceClient:
|
||||
"""Represents a Discord voice connection.
|
||||
|
||||
This client is created solely through :meth:`Client.join_voice_channel`
|
||||
and its only purpose is to transmit voice.
|
||||
You do not create these, you typically get them from
|
||||
e.g. :meth:`VoiceChannel.connect`.
|
||||
|
||||
Warning
|
||||
--------
|
||||
|
40
docs/_static/style.css
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
body {
|
||||
font-family: Georgia, 'Hiragino Mincho Pro', serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
code.descname, code.descclassname {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre, * pre {
|
||||
padding: 7px 0 7px 30px !important;
|
||||
margin: 15px 0 !important;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe6cc;
|
||||
border: 1px solid #ffd5aa;
|
||||
}
|
||||
|
||||
/* don't link-ify the FAQ page */
|
||||
a.toc-backref {
|
||||
text-decoration: none;
|
||||
color: #3E4349;
|
||||
}
|
||||
|
||||
code.xref {
|
||||
background-color: #ecf0f3;
|
||||
border-bottom: 1px dotted #222;
|
||||
}
|
415
docs/api.rst
@ -79,21 +79,22 @@ overriding the specific events. For example: ::
|
||||
import discord
|
||||
|
||||
class MyClient(discord.Client):
|
||||
async def on_message(self, message):
|
||||
if message.author != self.user:
|
||||
return
|
||||
|
||||
@asyncio.coroutine
|
||||
def on_message(self, message):
|
||||
yield from self.send_message(message.channel, 'Hello World!')
|
||||
if message.content.startswith('$hello'):
|
||||
await message.channel.send('Hello World!')
|
||||
|
||||
|
||||
If an event handler raises an exception, :func:`on_error` will be called
|
||||
to handle it, which defaults to print a traceback and ignore the exception.
|
||||
to handle it, which defaults to print a traceback and ignoring the exception.
|
||||
|
||||
.. warning::
|
||||
|
||||
All the events must be a |corourl|_. If they aren't, then you might get unexpected
|
||||
errors. In order to turn a function into a coroutine they must either be decorated
|
||||
with ``@asyncio.coroutine`` or in Python 3.5+ be defined using the ``async def``
|
||||
declaration.
|
||||
errors. In order to turn a function into a coroutine they must either be ``async def``
|
||||
functions or in 3.4 decorated with ``@asyncio.coroutine``.
|
||||
|
||||
The following two functions are examples of coroutine functions: ::
|
||||
|
||||
@ -104,14 +105,6 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
def on_ready():
|
||||
pass
|
||||
|
||||
Since this can be a potentially common mistake, there is a helper
|
||||
decorator, :meth:`Client.async_event` to convert a basic function
|
||||
into a coroutine and an event at the same time. Note that it is
|
||||
not necessary if you use ``async def``.
|
||||
|
||||
.. versionadded:: 0.7.0
|
||||
Subclassing to listen to events.
|
||||
|
||||
.. function:: on_connect()
|
||||
|
||||
Called when the client has successfully connected to Discord. This is not
|
||||
@ -164,48 +157,71 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
:param kwargs: The keyword arguments for the event that raised the
|
||||
execption.
|
||||
|
||||
.. function:: on_message(message)
|
||||
|
||||
Called when a message is created and sent to a guild.
|
||||
|
||||
:param message: A :class:`Message` of the current message.
|
||||
|
||||
.. function:: on_socket_raw_receive(msg)
|
||||
|
||||
Called whenever a message is received from the websocket, before
|
||||
it's processed.This event is always dispatched when a message is
|
||||
Called whenever a message is received from the WebSocket, before
|
||||
it's processed. This event is always dispatched when a message is
|
||||
received and the passed data is not processed in any way.
|
||||
|
||||
This is only really useful for grabbing the websocket stream and
|
||||
This is only really useful for grabbing the WebSocket stream and
|
||||
debugging purposes.
|
||||
|
||||
.. note::
|
||||
|
||||
This is only for the messages received from the client
|
||||
websocket. The voice websocket will not trigger this event.
|
||||
WebSocket. The voice WebSocket will not trigger this event.
|
||||
|
||||
:param msg: The message passed in from the websocket library.
|
||||
:param msg: The message passed in from the WebSocket library.
|
||||
Could be ``bytes`` for a binary message or ``str``
|
||||
for a regular message.
|
||||
|
||||
.. function:: on_socket_raw_send(payload)
|
||||
|
||||
Called whenever a send operation is done on the websocket before the
|
||||
message is sent. The passed parameter is the message that is to
|
||||
sent to the websocket.
|
||||
Called whenever a send operation is done on the WebSocket before the
|
||||
message is sent. The passed parameter is the message that is being
|
||||
sent to the WebSocket.
|
||||
|
||||
This is only really useful for grabbing the websocket stream and
|
||||
This is only really useful for grabbing the WebSocket stream and
|
||||
debugging purposes.
|
||||
|
||||
.. note::
|
||||
|
||||
This is only for the messages received from the client
|
||||
websocket. The voice websocket will not trigger this event.
|
||||
WebSocket. The voice WebSocket will not trigger this event.
|
||||
|
||||
:param payload: The message that is about to be passed on to the
|
||||
websocket library. It can be ``bytes`` to denote a binary
|
||||
WebSocket library. It can be ``bytes`` to denote a binary
|
||||
message or ``str`` to denote a regular text message.
|
||||
|
||||
.. function:: on_typing(channel, user, when)
|
||||
|
||||
Called when someone begins typing a message.
|
||||
|
||||
The ``channel`` parameter can be a :class:`abc.Messageable` instance.
|
||||
Which could either be :class:`TextChannel`, :class:`GroupChannel`, or
|
||||
:class:`DMChannel`.
|
||||
|
||||
If the ``channel`` is a :class:`TextChannel` then the ``user`` parameter
|
||||
is a :class:`Member`, otherwise it is a :class:`User`.
|
||||
|
||||
:param channel: The location where the typing originated from.
|
||||
:param user: The user that started typing.
|
||||
:param when: A ``datetime.datetime`` object representing when typing started.
|
||||
|
||||
.. function:: on_message(message)
|
||||
|
||||
Called when a :class:`Message` is created and sent.
|
||||
|
||||
.. warning::
|
||||
|
||||
Your bot's own messages and private messages are sent through this
|
||||
event. This can lead cases of 'recursion' depending on how your bot was
|
||||
programmed. If you want the bot to not reply to itself, consider
|
||||
checking the user IDs. Note that :class:`~ext.commands.Bot` does not
|
||||
have this problem.
|
||||
|
||||
:param message: A :class:`Message` of the current message.
|
||||
|
||||
.. function:: on_message_delete(message)
|
||||
|
||||
Called when a message is deleted. If the message is not found in the
|
||||
@ -218,7 +234,7 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
|
||||
.. function:: on_message_edit(before, after)
|
||||
|
||||
Called when a message receives an update event. If the message is not found
|
||||
Called when a :class:`Message` receives an update event. If the message is not found
|
||||
in the :attr:`Client.messages` cache, then these events will not be called.
|
||||
This happens if the message is too old or the client is participating in high
|
||||
traffic guilds. To fix this, increase the ``max_messages`` option of :class:`Client`.
|
||||
@ -228,7 +244,9 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
- A message has been pinned or unpinned.
|
||||
- The message content has been changed.
|
||||
- The message has received an embed.
|
||||
- For performance reasons, the embed guild does not do this in a "consistent" manner.
|
||||
|
||||
- For performance reasons, the embed server does not do this in a "consistent" manner.
|
||||
|
||||
- A call message has received an update to its participants or ending time.
|
||||
|
||||
:param before: A :class:`Message` of the previous version of the message.
|
||||
@ -242,7 +260,7 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
|
||||
.. note::
|
||||
|
||||
To get the message being reacted, access it via :attr:`Reaction.message`.
|
||||
To get the :class:`Message` being reacted, access it via :attr:`Reaction.message`.
|
||||
|
||||
:param reaction: A :class:`Reaction` showing the current state of the reaction.
|
||||
:param user: A :class:`User` or :class:`Member` of the user who added the reaction.
|
||||
@ -269,31 +287,51 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
:param message: The :class:`Message` that had its reactions cleared.
|
||||
:param reactions: A list of :class:`Reaction`\s that were removed.
|
||||
|
||||
.. function:: on_channel_delete(channel)
|
||||
on_channel_create(channel)
|
||||
.. function:: on_private_channel_delete(channel)
|
||||
on_private_channel_create(channel)
|
||||
|
||||
Called whenever a channel is removed or added from a guild.
|
||||
Called whenever a private channel is deleted or created.
|
||||
|
||||
Note that you can get the guild from :attr:`Channel.guild`.
|
||||
:func:`on_channel_create` could also pass in a :class:`PrivateChannel` depending
|
||||
on the value of :attr:`Channel.is_private`.
|
||||
:param channel: The :class:`abc.PrivateChannel` that got created or deleted.
|
||||
|
||||
:param channel: The :class:`Channel` that got added or deleted.
|
||||
.. function:: on_private_channel_update(before, after)
|
||||
|
||||
.. function:: on_channel_update(before, after)
|
||||
Called whenever a private group DM is updated. e.g. changed name or topic.
|
||||
|
||||
Called whenever a channel is updated. e.g. changed name, topic, permissions.
|
||||
:param before: The :class:`GroupChannel` that got updated with the old info.
|
||||
:param after: The :class:`GroupChannel` that got updated with the updated info.
|
||||
|
||||
:param before: The :class:`Channel` that got updated with the old info.
|
||||
:param after: The :class:`Channel` that got updated with the updated info.
|
||||
.. function:: on_private_channel_pins_update(channel, last_pin)
|
||||
|
||||
.. function:: on_channel_pins_update(channel, last_pin)
|
||||
Called whenever a message is pinned or unpinned from a private channel.
|
||||
|
||||
Called whenever a message is pinned or unpinned from a channel.
|
||||
|
||||
:param channel: The :class:`Channel` that had it's pins updated.
|
||||
:param channel: The :class:`abc.PrivateChannel` that had it's pins updated.
|
||||
:param last_pin: A ``datetime.datetime`` object representing when the latest message
|
||||
was pinned or ``None`` if there are no pins.
|
||||
was pinned or ``None`` if there are no pins.
|
||||
|
||||
.. function:: on_guild_channel_delete(channel)
|
||||
on_guild_channel_create(channel)
|
||||
|
||||
Called whenever a guild channel is deleted or created.
|
||||
|
||||
Note that you can get the guild from :attr:`~abc.GuildChannel.guild`.
|
||||
|
||||
:param channel: The :class:`abc.GuildChannel` that got created or deleted.
|
||||
|
||||
.. function:: on_guild_channel_update(before, after)
|
||||
|
||||
Called whenever a guild channel is updated. e.g. changed name, topic, permissions.
|
||||
|
||||
:param before: The :class:`abc.GuildChannel` that got updated with the old info.
|
||||
:param after: The :class:`abc.GuildChannel` that got updated with the updated info.
|
||||
|
||||
.. function:: on_guild_channel_pins_update(channel, last_pin)
|
||||
|
||||
Called whenever a message is pinned or unpinned from a guild channel.
|
||||
|
||||
:param channel: The :class:`abc.GuildChannel` that had it's pins updated.
|
||||
:param last_pin: A ``datetime.datetime`` object representing when the latest message
|
||||
was pinned or ``None`` if there are no pins.
|
||||
|
||||
.. function:: on_member_join(member)
|
||||
on_member_remove(member)
|
||||
@ -368,10 +406,11 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
:param before: The :class:`Role` that updated with the old info.
|
||||
:param after: The :class:`Role` that updated with the updated info.
|
||||
|
||||
.. function:: on_guild_emojis_update(before, after)
|
||||
.. function:: on_guild_emojis_update(guild, before, after)
|
||||
|
||||
Called when a :class:`Guild` adds or removes :class:`Emoji`.
|
||||
|
||||
:param guild: The :class:`Guild` who got their emojis updated.
|
||||
:param before: A list of :class:`Emoji` before the update.
|
||||
:param after: A list of :class:`Emoji` after the update.
|
||||
|
||||
@ -383,9 +422,9 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
|
||||
:param guild: The :class:`Guild` that has changed availability.
|
||||
|
||||
.. function:: on_voice_state_update(before, after)
|
||||
.. function:: on_voice_state_update(member, before, after)
|
||||
|
||||
Called when a :class:`Member` changes their voice state.
|
||||
Called when a :class:`Member` changes their :class:`VoiceState`.
|
||||
|
||||
The following, but not limited to, examples illustrate when this event is called:
|
||||
|
||||
@ -394,35 +433,25 @@ to handle it, which defaults to print a traceback and ignore the exception.
|
||||
- A member is muted or deafened by their own accord.
|
||||
- A member is muted or deafened by a guild administrator.
|
||||
|
||||
:param before: The :class:`Member` whose voice state changed prior to the changes.
|
||||
:param after: The :class:`Member` whose voice state changed after the changes.
|
||||
:param member: The :class:`Member` whose voice states changed.
|
||||
:param before: The :class:`VoiceState` prior to the changes.
|
||||
:param after: The :class:`VoiceState` after to the changes.
|
||||
|
||||
.. function:: on_member_ban(member)
|
||||
.. function:: on_member_ban(guild, user)
|
||||
|
||||
Called when a :class:`Member` gets banned from a :class:`Guild`.
|
||||
Called when user gets banned from a :class:`Guild`.
|
||||
|
||||
You can access the guild that the member got banned from via :attr:`Member.guild`.
|
||||
|
||||
:param member: The member that got banned.
|
||||
:param guild: The :class:`Guild` the user got banned from.
|
||||
:param user: The user that got banned.
|
||||
Can be either :class:`User` or :class:`Member` depending if
|
||||
the user was in the guild or not at the time of removal.
|
||||
|
||||
.. function:: on_member_unban(guild, user)
|
||||
|
||||
Called when a :class:`User` gets unbanned from a :class:`Guild`.
|
||||
|
||||
:param guild: The guild the user got unbanned from.
|
||||
:param user: The user that got unbanned.
|
||||
|
||||
.. function:: on_typing(channel, user, when)
|
||||
|
||||
Called when someone begins typing a message.
|
||||
|
||||
The ``channel`` parameter could either be a :class:`PrivateChannel` or a
|
||||
:class:`Channel`. If ``channel`` is a :class:`PrivateChannel` then the
|
||||
``user`` parameter is a :class:`User`, otherwise it is a :class:`Member`.
|
||||
|
||||
:param channel: The location where the typing originated from.
|
||||
:param user: The user that started typing.
|
||||
:param when: A ``datetime.datetime`` object representing when typing started.
|
||||
:param guild: The :class:`Guild` the user got unbanned from.
|
||||
:param user: The :class:`User` that got unbanned.
|
||||
|
||||
.. function:: on_group_join(channel, user)
|
||||
on_group_remove(channel, user)
|
||||
@ -1281,15 +1310,15 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
|
||||
.. attribute:: owner
|
||||
|
||||
*Union[:class:`Member`, :class:`User`]`* – The guild's owner. See also :attr:`Guild.owner`
|
||||
Union[:class:`Member`, :class:`User`] – The guild's owner. See also :attr:`Guild.owner`
|
||||
|
||||
.. attribute:: region
|
||||
|
||||
*:class:`GuildRegion`* – The guild's voice region. See also :attr:`Guild.region`.
|
||||
:class:`GuildRegion` – The guild's voice region. See also :attr:`Guild.region`.
|
||||
|
||||
.. attribute:: afk_channel
|
||||
|
||||
*Union[:class:`VoiceChannel`, :class:`Object`]* – The guild's AFK channel.
|
||||
Union[:class:`VoiceChannel`, :class:`Object`] – The guild's AFK channel.
|
||||
|
||||
If this could not be found, then it falls back to a :class:`Object`
|
||||
with the ID being set.
|
||||
@ -1310,20 +1339,20 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
|
||||
.. attribute:: widget_channel
|
||||
|
||||
*Union[:class:`TextChannel`, :class:`Object`]* – The widget's channel.
|
||||
Union[:class:`TextChannel`, :class:`Object`] – The widget's channel.
|
||||
|
||||
If this could not be found then it falls back to a :class:`Object`
|
||||
with the ID being set.
|
||||
|
||||
.. attribute:: verification_level
|
||||
|
||||
*:class:`VerificationLevel`* – The guild's verification level.
|
||||
:class:`VerificationLevel` – The guild's verification level.
|
||||
|
||||
See also :attr:`Guild.verification_level`.
|
||||
|
||||
.. attribute:: explicit_content_filter
|
||||
|
||||
*:class:`ContentFilter`* – The guild's content filter.
|
||||
:class:`ContentFilter` – The guild's content filter.
|
||||
|
||||
See also :attr:`Guild.explicit_content_filter`.
|
||||
|
||||
@ -1365,7 +1394,7 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
|
||||
.. attribute:: overwrites
|
||||
|
||||
*List[Tuple[target, :class:`PermissionOverwrite`]]* – A list of
|
||||
List[Tuple[target, :class:`PermissionOverwrite`]] – A list of
|
||||
permission overwrite tuples that represents a target and a
|
||||
:class:`PermissionOverwrite` for said target.
|
||||
|
||||
@ -1377,7 +1406,7 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
|
||||
.. attribute:: roles
|
||||
|
||||
*List[Union[:class:`Role`, :class:`Object`]]* – A list of roles being added or removed
|
||||
List[Union[:class:`Role`, :class:`Object`]] – A list of roles being added or removed
|
||||
from a member.
|
||||
|
||||
If a role is not found then it is a :class:`Object` with the ID and name being
|
||||
@ -1403,14 +1432,14 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
|
||||
.. attribute:: permissions
|
||||
|
||||
*:class:`Permissions`* – The permissions of a role.
|
||||
:class:`Permissions` – The permissions of a role.
|
||||
|
||||
See also :attr:`Role.permissions`.
|
||||
|
||||
.. attribute:: colour
|
||||
color
|
||||
|
||||
*:class:`Colour`* – The colour of a role.
|
||||
:class:`Colour` – The colour of a role.
|
||||
|
||||
See also :attr:`Role.colour`
|
||||
|
||||
@ -1434,14 +1463,14 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
|
||||
.. attribute:: channel
|
||||
|
||||
*Union[:class:`abc.GuildChannel`, :class:`Object`]* – A guild channel.
|
||||
Union[:class:`abc.GuildChannel`, :class:`Object`] – A guild channel.
|
||||
|
||||
If the channel is not found then it is a :class:`Object` with the ID
|
||||
being set. In some cases the channel name is also set.
|
||||
|
||||
.. attribute:: inviter
|
||||
|
||||
*:class:`User`* – The user who created the invite.
|
||||
:class:`User` – The user who created the invite.
|
||||
|
||||
See also :attr:`Invite.inviter`.
|
||||
|
||||
@ -1472,7 +1501,7 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
.. attribute:: allow
|
||||
deny
|
||||
|
||||
*:class:`Permissions`* – The permissions being allowed or denied.
|
||||
:class:`Permissions` – The permissions being allowed or denied.
|
||||
|
||||
.. attribute:: id
|
||||
|
||||
@ -1487,43 +1516,72 @@ this goal, it must make use of a couple of data classes that aid in this goal.
|
||||
.. this is currently missing the following keys: reason and application_id
|
||||
I'm not sure how to about porting these
|
||||
|
||||
.. _discord_api_data:
|
||||
.. _discord_api_abcs:
|
||||
|
||||
Data Classes
|
||||
--------------
|
||||
Abstract Base Classes
|
||||
-----------------------
|
||||
|
||||
Some classes are just there to be data containers, this lists them.
|
||||
An abstract base class (also known as an ``abc``) is a class that models can inherit
|
||||
to get their behaviour. The Python implementation of an `abc <https://docs.python.org/3/library/abc.html>`_ is
|
||||
slightly different in that you can register them at run-time. **Abstract base classes cannot be instantiated**.
|
||||
They are mainly there for usage with ``isinstance`` and ``issubclass``\.
|
||||
|
||||
.. note::
|
||||
This library has a module related to abstract base classes, some of which are actually from the ``abc`` standard
|
||||
module, others which are not.
|
||||
|
||||
With the exception of :class:`Object`, :class:`Colour`, and :class:`Permissions` the
|
||||
data classes listed below are **not intended to be created by users** and are also
|
||||
.. autoclass:: discord.abc.Snowflake
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.abc.User
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.abc.PrivateChannel
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.abc.GuildChannel
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.abc.Messageable
|
||||
:members:
|
||||
:exclude-members: history typing
|
||||
|
||||
.. autocomethod:: discord.abc.Messageable.history
|
||||
:async-for:
|
||||
|
||||
.. autocomethod:: discord.abc.Messageable.typing
|
||||
:async-with:
|
||||
|
||||
.. autoclass:: discord.abc.Connectable
|
||||
|
||||
.. _discord_api_models:
|
||||
|
||||
Discord Models
|
||||
---------------
|
||||
|
||||
Models are classes that are received from Discord and are not meant to be created by
|
||||
the user of the library.
|
||||
|
||||
.. danger::
|
||||
|
||||
The classes listed below are **not intended to be created by users** and are also
|
||||
**read-only**.
|
||||
|
||||
For example, this means that you should not make your own :class:`User` instances
|
||||
nor should you modify the :class:`User` instance yourself.
|
||||
|
||||
If you want to get one of these data classes instances they'd have to be through
|
||||
If you want to get one of these model classes instances they'd have to be through
|
||||
the cache, and a common way of doing so is through the :func:`utils.find` function
|
||||
or attributes of data classes that you receive from the events specified in the
|
||||
or attributes of model classes that you receive from the events specified in the
|
||||
:ref:`discord-api-events`.
|
||||
|
||||
.. note::
|
||||
|
||||
.. warning::
|
||||
|
||||
Nearly all data classes here have ``__slots__`` defined which means that it is
|
||||
impossible to have dynamic attributes to the data classes. The only exception
|
||||
to this rule is :class:`Object` which was designed with dynamic attributes in
|
||||
mind.
|
||||
Nearly all classes here have ``__slots__`` defined which means that it is
|
||||
impossible to have dynamic attributes to the data classes.
|
||||
|
||||
More information about ``__slots__`` can be found
|
||||
`in the official python documentation <https://docs.python.org/3/reference/datamodel.html#slots>`_.
|
||||
|
||||
Object
|
||||
~~~~~~~
|
||||
|
||||
.. autoclass:: Object
|
||||
:members:
|
||||
|
||||
ClientUser
|
||||
~~~~~~~~~~~~
|
||||
@ -1544,6 +1602,13 @@ User
|
||||
.. autoclass:: User
|
||||
:members:
|
||||
:inherited-members:
|
||||
:exclude-members: history typing
|
||||
|
||||
.. autocomethod:: history
|
||||
:async-for:
|
||||
|
||||
.. autocomethod:: typing
|
||||
:async-with:
|
||||
|
||||
Message
|
||||
~~~~~~~
|
||||
@ -1556,18 +1621,10 @@ Reaction
|
||||
|
||||
.. autoclass:: Reaction
|
||||
:members:
|
||||
:exclude-members: users
|
||||
|
||||
Embed
|
||||
~~~~~~
|
||||
|
||||
.. autoclass:: Embed
|
||||
:members:
|
||||
|
||||
File
|
||||
~~~~~
|
||||
|
||||
.. autoclass:: File
|
||||
:members:
|
||||
.. autocomethod:: users
|
||||
:async-for:
|
||||
|
||||
CallMessage
|
||||
~~~~~~~~~~~~
|
||||
@ -1586,6 +1643,10 @@ Guild
|
||||
|
||||
.. autoclass:: Guild
|
||||
:members:
|
||||
:exclude-members: audit_logs
|
||||
|
||||
.. autocomethod:: audit_logs
|
||||
:async-for:
|
||||
|
||||
Member
|
||||
~~~~~~
|
||||
@ -1593,6 +1654,13 @@ Member
|
||||
.. autoclass:: Member
|
||||
:members:
|
||||
:inherited-members:
|
||||
:exclude-members: history typing
|
||||
|
||||
.. autocomethod:: history
|
||||
:async-for:
|
||||
|
||||
.. autocomethod:: typing
|
||||
:async-with:
|
||||
|
||||
VoiceState
|
||||
~~~~~~~~~~~
|
||||
@ -1600,18 +1668,6 @@ VoiceState
|
||||
.. autoclass:: VoiceState
|
||||
:members:
|
||||
|
||||
Colour
|
||||
~~~~~~
|
||||
|
||||
.. autoclass:: Colour
|
||||
:members:
|
||||
|
||||
Game
|
||||
~~~~
|
||||
|
||||
.. autoclass:: Game
|
||||
:members:
|
||||
|
||||
Emoji
|
||||
~~~~~
|
||||
|
||||
@ -1624,25 +1680,19 @@ Role
|
||||
.. autoclass:: Role
|
||||
:members:
|
||||
|
||||
Permissions
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: Permissions
|
||||
:members:
|
||||
|
||||
PermissionOverwrite
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: PermissionOverwrite
|
||||
:members:
|
||||
|
||||
|
||||
TextChannel
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: TextChannel
|
||||
:members:
|
||||
:inherited-members:
|
||||
:exclude-members: history typing
|
||||
|
||||
.. autocomethod:: history
|
||||
:async-for:
|
||||
|
||||
.. autocomethod:: typing
|
||||
:async-with:
|
||||
|
||||
VoiceChannel
|
||||
~~~~~~~~~~~~~
|
||||
@ -1657,6 +1707,13 @@ DMChannel
|
||||
.. autoclass:: DMChannel
|
||||
:members:
|
||||
:inherited-members:
|
||||
:exclude-members: history typing
|
||||
|
||||
.. autocomethod:: history
|
||||
:async-for:
|
||||
|
||||
.. autocomethod:: typing
|
||||
:async-with:
|
||||
|
||||
GroupChannel
|
||||
~~~~~~~~~~~~
|
||||
@ -1664,6 +1721,13 @@ GroupChannel
|
||||
.. autoclass:: GroupChannel
|
||||
:members:
|
||||
:inherited-members:
|
||||
:exclude-members: history typing
|
||||
|
||||
.. autocomethod:: history
|
||||
:async-for:
|
||||
|
||||
.. autocomethod:: typing
|
||||
:async-with:
|
||||
|
||||
|
||||
Invite
|
||||
@ -1672,6 +1736,69 @@ Invite
|
||||
.. autoclass:: Invite
|
||||
:members:
|
||||
|
||||
.. _discord_api_data:
|
||||
|
||||
Data Classes
|
||||
--------------
|
||||
|
||||
Some classes are just there to be data containers, this lists them.
|
||||
|
||||
Unlike :ref:`models <discord_api_models>` you are allowed to create
|
||||
these yourself, even if they can also be used to hold attributes.
|
||||
|
||||
Nearly all classes here have ``__slots__`` defined which means that it is
|
||||
impossible to have dynamic attributes to the data classes.
|
||||
|
||||
The only exception to this rule is :class:`Object`, which is made with
|
||||
dynamic attributes in mind.
|
||||
|
||||
More information about ``__slots__`` can be found
|
||||
`in the official python documentation <https://docs.python.org/3/reference/datamodel.html#slots>`_.
|
||||
|
||||
|
||||
Object
|
||||
~~~~~~~
|
||||
|
||||
.. autoclass:: Object
|
||||
:members:
|
||||
|
||||
Embed
|
||||
~~~~~~
|
||||
|
||||
.. autoclass:: Embed
|
||||
:members:
|
||||
|
||||
File
|
||||
~~~~~
|
||||
|
||||
.. autoclass:: File
|
||||
:members:
|
||||
|
||||
Colour
|
||||
~~~~~~
|
||||
|
||||
.. autoclass:: Colour
|
||||
:members:
|
||||
|
||||
Game
|
||||
~~~~
|
||||
|
||||
.. autoclass:: Game
|
||||
:members:
|
||||
|
||||
Permissions
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: Permissions
|
||||
:members:
|
||||
|
||||
PermissionOverwrite
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. autoclass:: PermissionOverwrite
|
||||
:members:
|
||||
|
||||
|
||||
Exceptions
|
||||
------------
|
||||
|
||||
|
10
docs/conf.py
@ -34,6 +34,7 @@ sys.path.insert(0, os.path.abspath('..'))
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.extlinks',
|
||||
'sphinxcontrib.asyncio'
|
||||
]
|
||||
|
||||
if on_rtd:
|
||||
@ -115,7 +116,7 @@ exclude_patterns = ['_build']
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = 'friendly'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
@ -128,7 +129,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme = 'alabaster'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@ -159,7 +160,7 @@ html_theme = 'sphinx_rtd_theme'
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
# html_static_path = ['_static']
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
@ -304,3 +305,6 @@ texinfo_documents = [
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
def setup(app):
|
||||
app.add_stylesheet('style.css')
|
||||
|
92
docs/discord.rst
Normal file
@ -0,0 +1,92 @@
|
||||
.. _discord-intro:
|
||||
|
||||
Creating a Bot Account
|
||||
========================
|
||||
|
||||
In order to work with the library and the Discord API in general, we must first create a Discord Bot account.
|
||||
|
||||
Creating a Bot account is a pretty straightforward process.
|
||||
|
||||
1. Make sure you're logged on to the `Discord website <https://discordapp.com>`_.
|
||||
2. Navigate to the `application page <https://discordapp.com/developers/applications/me>`_
|
||||
3. Click on the "New App" button.
|
||||
|
||||
.. image:: /images/discord_new_app_button.png
|
||||
:alt: The new app button.
|
||||
|
||||
4. Give the application a name and a description if wanted and click "Create App".
|
||||
|
||||
- You can also put an avatar you want your bot to use, don't worry you can change this later.
|
||||
- **Leave the Redirect URI(s) blank** unless are creating a service.
|
||||
|
||||
.. image:: /images/discord_new_app_form.png
|
||||
:alt: The new application form filled in.
|
||||
5. Create a Bot User by clicking on the accompanying button and confirming it.
|
||||
|
||||
.. image:: /images/discord_create_bot_user_button.png
|
||||
:alt: The Create a Bot User button.
|
||||
6. Make sure that **Public Bot** is ticked if you want others to invite your bot.
|
||||
|
||||
- You should also make sure that **Require OAuth2 Code Grant** is unchecked unless you
|
||||
are developing a service that needs it. If you're unsure, then **leave it unchecked**.
|
||||
|
||||
.. figure:: /images/discord_finished_bot_user.png
|
||||
|
||||
How the Bot User options should look like for most people.
|
||||
|
||||
7. Click to reveal the token.
|
||||
|
||||
- **This is not the Client Secret**
|
||||
|
||||
.. figure:: /images/discord_reveal_token.png
|
||||
|
||||
How the token reveal button looks like.
|
||||
|
||||
And that's it. You now have a bot account and you can login with that token.
|
||||
|
||||
.. _discord_invite_bot:
|
||||
|
||||
Inviting Your Bot
|
||||
-------------------
|
||||
|
||||
So you've made a Bot User but it's not actually in any server.
|
||||
|
||||
If you want to invite your bot you must create an invite URL for your bot.
|
||||
|
||||
First, you must fetch the Client ID of the Bot. You can find this in the Bot's application page.
|
||||
|
||||
.. image:: /images/discord_client_id.png
|
||||
:alt: The Bot's Client ID.
|
||||
|
||||
Copy paste that into the pre-formatted URL:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
https://discordapp.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&scope=bot&permissions=0
|
||||
|
||||
Replace ``YOUR_CLIENT_ID`` with the Client ID we got in the previous step. For example,
|
||||
in the image above our client ID is 312718641634213889 so the resulting URL would be
|
||||
https://discordapp.com/oauth2/authorize?client_id=312718641634213889&scope=bot&permissions=0
|
||||
(note that this bot has been deleted).
|
||||
|
||||
Now you can click the link and invite your bot to any server you have "Manage Server" permissions on.
|
||||
|
||||
Adding Permissions
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In the above URL, you might have noticed an interesting bit, the ``permissions=0`` fragment.
|
||||
|
||||
Bot accounts can request specific permissions to be granted upon joining. When the bot joins
|
||||
the guild, they will be granted a managed role that contains the permissions you requested.
|
||||
If the permissions is 0, then no special role is created.
|
||||
|
||||
This ``permissions`` value is calculated based on bit-wise arithmetic. Thankfully, people have
|
||||
created a calculate that makes it easy to calculate the permissions necessary visually.
|
||||
|
||||
- https://discordapi.com/permissions.html
|
||||
- https://finitereality.github.io/permissions/
|
||||
|
||||
Feel free to use whichever is easier for you to grasp.
|
||||
|
||||
If you want to generate this URL dynamically at run-time inside your bot and using the
|
||||
:class:`discord.Permissions` interface, you can use :func:`discord.utils.oauth_url`.
|
197
docs/ext/commands/api.rst
Normal file
@ -0,0 +1,197 @@
|
||||
.. currentmodule:: discord
|
||||
|
||||
API Reference
|
||||
===============
|
||||
|
||||
The following section outlines the API of discord.py's command extension module.
|
||||
|
||||
Bot
|
||||
----
|
||||
|
||||
.. autoclass:: discord.ext.commands.Bot
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.AutoShardedBot
|
||||
:members:
|
||||
|
||||
Event Reference
|
||||
-----------------
|
||||
|
||||
These events function similar to :ref:`the regular events <discord-api-events>`, except they
|
||||
are custom to the command extension module.
|
||||
|
||||
.. function:: on_command_error(ctx, error)
|
||||
|
||||
An error handler that is called when an error is raised
|
||||
inside a command either through user input error, check
|
||||
failure, or an error in your own code.
|
||||
|
||||
A default one is provided (:meth:`.Bot.on_command_error`).
|
||||
|
||||
:param ctx: The invocation context.
|
||||
:type ctx: :class:`Context`
|
||||
:param error: The error that was raised.
|
||||
:type error: :class:`CommandError` derived
|
||||
|
||||
.. function:: on_command(ctx)
|
||||
|
||||
An event that is called when a command is found and is about to be invoked.
|
||||
|
||||
This event is called regardless of whether the command itself succeeds via
|
||||
error or completes.
|
||||
|
||||
:param ctx: The invocation context.
|
||||
:type ctx: :class:`Context`
|
||||
|
||||
.. function:: on_command_completion(ctx)
|
||||
|
||||
An event that is called when a command has completed its invocation.
|
||||
|
||||
This event is called only if the command succeeded, i.e. all checks have
|
||||
passed and the user input it correctly.
|
||||
|
||||
:param ctx: The invocation context.
|
||||
:type ctx: :class:`Context`
|
||||
|
||||
|
||||
Command
|
||||
--------
|
||||
|
||||
.. autofunction:: discord.ext.commands.command
|
||||
|
||||
.. autofunction:: discord.ext.commands.group
|
||||
|
||||
.. autoclass:: discord.ext.commands.Command
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.Group
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.GroupMixin
|
||||
:members:
|
||||
|
||||
|
||||
Formatters
|
||||
-----------
|
||||
|
||||
.. autoclass:: discord.ext.commands.Paginator
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.HelpFormatter
|
||||
:members:
|
||||
|
||||
Checks
|
||||
-------
|
||||
|
||||
.. autofunction:: discord.ext.commands.check
|
||||
|
||||
.. autofunction:: discord.ext.commands.has_role
|
||||
|
||||
.. autofunction:: discord.ext.commands.has_permissions
|
||||
|
||||
.. autofunction:: discord.ext.commands.has_any_role
|
||||
|
||||
.. autofunction:: discord.ext.commands.bot_has_role
|
||||
|
||||
.. autofunction:: discord.ext.commands.bot_has_permissions
|
||||
|
||||
.. autofunction:: discord.ext.commands.bot_has_any_role
|
||||
|
||||
.. autofunction:: discord.ext.commands.cooldown
|
||||
|
||||
.. autofunction:: discord.ext.commands.guild_only
|
||||
|
||||
.. autofunction:: discord.ext.commands.is_owner
|
||||
|
||||
.. autofunction:: discord.ext.commands.is_nsfw
|
||||
|
||||
Context
|
||||
--------
|
||||
|
||||
.. autoclass:: discord.ext.commands.Context
|
||||
:members:
|
||||
:exclude-members: history typing
|
||||
|
||||
.. autocomethod:: discord.ext.commands.Context.history
|
||||
:async-for:
|
||||
|
||||
.. autocomethod:: discord.ext.commands.Context.typing
|
||||
:async-with:
|
||||
|
||||
Converters
|
||||
------------
|
||||
|
||||
.. autoclass:: discord.ext.commands.Converter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.MemberConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.UserConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.TextChannelConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.InviteConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.RoleConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.GameConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.ColourConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.VoiceChannelConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.EmojiConverter
|
||||
:members:
|
||||
|
||||
.. autoclass:: discord.ext.commands.clean_content
|
||||
:members:
|
||||
|
||||
Errors
|
||||
-------
|
||||
|
||||
.. autoexception:: discord.ext.commands.CommandError
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.MissingRequiredArgument
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.BadArgument
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.NoPrivateMessage
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.CheckFailure
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.CommandNotFound
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.DisabledCommand
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.CommandInvokeError
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.TooManyArguments
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.UserInputError
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.CommandOnCooldown
|
||||
:members:
|
||||
|
||||
.. autoexception:: discord.ext.commands.NotOwner
|
||||
:members:
|
||||
|
13
docs/ext/commands/index.rst
Normal file
@ -0,0 +1,13 @@
|
||||
``discord.ext.commands`` -- Bot commands framework
|
||||
====================================================
|
||||
|
||||
``discord.py`` offers a lower level aspect on interacting with Discord. Often times, the library is used for the creation of
|
||||
bots. However this task can be daunting and confusing to get correctly the first time. Many times there comes a repetition in
|
||||
creating a bot command framework that is extensible, flexible, and powerful. For this reason, ``discord.py`` comes with an
|
||||
extension library that handles this for you.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
api
|
180
docs/faq.rst
@ -16,7 +16,7 @@ Coroutines
|
||||
Questions regarding coroutines and asyncio belong here.
|
||||
|
||||
I get a SyntaxError around the word ``async``\! What should I do?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This ``SyntaxError`` happens because you're using a Python version lower than 3.5. Python 3.4 uses ``@asyncio.coroutine`` and
|
||||
``yield from`` instead of ``async def`` and ``await``.
|
||||
@ -52,7 +52,7 @@ Where can I use ``await``\?
|
||||
You can only use ``await`` inside ``async def`` functions and nowhere else.
|
||||
|
||||
What does "blocking" mean?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In asynchronous programming a blocking call is essentially all the parts of the function that are not ``await``. Do not
|
||||
despair however, because not all forms of blocking are bad! Using blocking calls is inevitable, but you must work to make
|
||||
@ -78,13 +78,14 @@ Consider the following example: ::
|
||||
r = requests.get('http://random.cat/meow')
|
||||
if r.status_code == 200:
|
||||
js = r.json()
|
||||
await client.send_message(channel, js['file'])
|
||||
await channel.send(js['file'])
|
||||
|
||||
# good
|
||||
async with aiohttp.get('http://random.cat/meow') as r:
|
||||
if r.status == 200:
|
||||
js = await r.json()
|
||||
await client.send_message(channel, js['file'])
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get('http://random.cat/meow') as r:
|
||||
if r.status == 200:
|
||||
js = await r.json()
|
||||
await channel.send(js['file'])
|
||||
|
||||
General
|
||||
---------
|
||||
@ -103,37 +104,41 @@ following: ::
|
||||
How do I send a message to a specific channel?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you have its ID then you can do this in two ways, first is by using :class:`Object`\: ::
|
||||
You must fetch the channel directly and then call the appropriate method. Example: ::
|
||||
|
||||
await client.send_message(discord.Object(id='12324234183172'), 'hello')
|
||||
|
||||
The second way is by calling :meth:`Client.get_channel` directly: ::
|
||||
|
||||
await client.send_message(client.get_channel('12324234183172'), 'hello')
|
||||
|
||||
I'm passing IDs as integers and things are not working!
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In the library IDs must be of type ``str`` not of type ``int``. Wrap it in quotes.
|
||||
channel = client.get_channel('12324234183172')
|
||||
await channel.send('hello')
|
||||
|
||||
How do I upload an image?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are two ways of doing it. Both of which involve using :meth:`Client.send_file`.
|
||||
To upload something to Discord you have to use the :class:`File` object.
|
||||
|
||||
The first is by opening the file and passing it directly: ::
|
||||
A :class:`File` accepts two parameters, the file-like object (or file path) and the filename
|
||||
to pass to Discord when uploading.
|
||||
|
||||
with open('my_image.png', 'rb') as f:
|
||||
await client.send_file(channel, f)
|
||||
If you want to upload an image it's as simple as: ::
|
||||
|
||||
The second is by passing the file name directly: ::
|
||||
await channel.send(file=discord.File('my_file.png'))
|
||||
|
||||
If you have a file-like object you can do as follows: ::
|
||||
|
||||
with open('my_file.png', 'rb') as fp:
|
||||
await channel.send(file=discord.File(fp, 'new_filename.png'))
|
||||
|
||||
To upload multiple files, you can use the ``files`` keyword argument instead of ``file``\: ::
|
||||
|
||||
my_files = [
|
||||
discord.File('result.zip'),
|
||||
discord.File('teaser_graph.png'),
|
||||
]
|
||||
await channel.send(files=my_files)
|
||||
|
||||
await client.send_file(channel, 'my_image.png')
|
||||
|
||||
How can I add a reaction to a message?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You use the :meth:`Client.add_reaction` method.
|
||||
You use the :meth:`Message.add_reaction` method.
|
||||
|
||||
If you want to use unicode emoji, you must pass a valid unicode code point in a string. In your code, you can write this in a few different ways:
|
||||
|
||||
@ -141,16 +146,32 @@ If you want to use unicode emoji, you must pass a valid unicode code point in a
|
||||
- ``'\U0001F44D'``
|
||||
- ``'\N{THUMBS UP SIGN}'``
|
||||
|
||||
In case you want to use emoji that come from a message, you already get their code points in the content without needing to do anything special.
|
||||
You **cannot** send ``':thumbsup:'`` style shorthands.
|
||||
Quick example: ::
|
||||
|
||||
For custom emoji, you should pass an instance of :class:`discord.Emoji`. You can also pass a ``'name:id'`` string, but if you can use said emoji,
|
||||
you should be able to use :meth:`Client.get_all_emojis`/:attr:`Server.emojis` to find the one you're looking for.
|
||||
await message.add_reaction('\N{THUMBS UP SIGN}')
|
||||
|
||||
In case you want to use emoji that come from a message, you already get their code points in the content without needing
|
||||
to do anything special. You **cannot** send ``':thumbsup:'`` style shorthands.
|
||||
|
||||
For custom emoji, you should pass an instance of :class:`Emoji`. You can also pass a ``'name:id'`` string, but if you
|
||||
can use said emoji, you should be able to use :meth:`Client.get_emoji` to get an emoji via ID or use :func:`utils.find`/
|
||||
:func:`utils.get` on :attr:`Client.emojis` or :attr:`Guild.emojis` collections.
|
||||
|
||||
Quick example: ::
|
||||
|
||||
# if you have the ID already
|
||||
emoji = client.get_emoji(310177266011340803)
|
||||
await message.add_reaction(emoji)
|
||||
|
||||
# no ID, do a lookup
|
||||
emoji = discord.utils.get(guild.emojis, name='LUL')
|
||||
if emoji:
|
||||
await message.add_reaction(emoji)
|
||||
|
||||
How do I pass a coroutine to the player's "after" function?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A StreamPlayer is just a ``threading.Thread`` object that plays music. As a result it does not execute inside a coroutine.
|
||||
The library's music player launches on a separate thread, ergo it does not execute inside a coroutine.
|
||||
This does not mean that it is not possible to call a coroutine in the ``after`` parameter. To do so you must pass a callable
|
||||
that wraps up a couple of aspects.
|
||||
|
||||
@ -169,7 +190,7 @@ However, this function returns a ``concurrent.Future`` and to actually call it w
|
||||
this together we can do the following: ::
|
||||
|
||||
def my_after():
|
||||
coro = client.send_message(some_channel, 'Song is done!')
|
||||
coro = some_channel.send('Song is done!')
|
||||
fut = asyncio.run_coroutine_threadsafe(coro, client.loop)
|
||||
try:
|
||||
fut.result()
|
||||
@ -177,48 +198,44 @@ this together we can do the following: ::
|
||||
# an error happened sending the message
|
||||
pass
|
||||
|
||||
player = await voice.create_ytdl_player(url, after=my_after)
|
||||
player.start()
|
||||
|
||||
Why is my "after" function being called right away?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``after`` keyword argument expects a *function object* to be passed in. Similar to how ``threading.Thread`` expects a
|
||||
callable in its ``target`` keyword argument. This means that the following are invalid:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
player = await voice.create_ytdl_player(url, after=self.foo())
|
||||
other = await voice.create_ytdl_player(url, after=self.bar(10))
|
||||
|
||||
However the following are correct:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
player = await voice.create_ytdl_player(url, after=self.foo)
|
||||
other = await voice.create_ytdl_player(url, after=lambda: self.bar(10))
|
||||
|
||||
Basically, these functions should not be called.
|
||||
|
||||
voice.play(discord.FFmpegPCMAudio(url), after=my_after)
|
||||
|
||||
How do I run something in the background?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`Check the background_task.py example. <https://github.com/Rapptz/discord.py/blob/master/examples/background_task.py>`_
|
||||
`Check the background_task.py example. <https://github.com/Rapptz/discord.py/blob/rewrite/examples/background_task.py>`_
|
||||
|
||||
How do I get a specific User/Role/Channel/Server?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
How do I get a specific model?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are multiple ways of doing this. If you have a specific entity's ID then you can use
|
||||
There are multiple ways of doing this. If you have a specific model's ID then you can use
|
||||
one of the following functions:
|
||||
|
||||
- :meth:`Client.get_channel`
|
||||
- :meth:`Client.get_server`
|
||||
- :meth:`Server.get_member`
|
||||
- :meth:`Server.get_channel`
|
||||
- :meth:`Client.get_guild`
|
||||
- :meth:`Client.get_user`
|
||||
- :meth:`Client.get_emoji`
|
||||
- :meth:`Guild.get_member`
|
||||
- :meth:`Guild.get_channel`
|
||||
|
||||
The following use an HTTP request:
|
||||
|
||||
- :meth:`abc.Messageable.get_message`
|
||||
- :meth:`Client.get_user_info`
|
||||
|
||||
|
||||
If the functions above do not help you, then use of :func:`utils.find` or :func:`utils.get` would serve some use in finding
|
||||
specific entities. The documentation for those functions provide specific examples.
|
||||
specific models.
|
||||
|
||||
Quick example: ::
|
||||
|
||||
# find a guild by name
|
||||
guild = discord.utils.get(client.guilds, name='My Server')
|
||||
|
||||
# make sure to check if it's found
|
||||
if guild is not None:
|
||||
# find a channel by name
|
||||
channel = discord.utils.get(guild.text_channels, name='cool-channel')
|
||||
|
||||
Commands Extension
|
||||
-------------------
|
||||
@ -229,10 +246,10 @@ Is there any documentation for this?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Not at the moment. Writing documentation for stuff takes time. A lot of people get by reading the docstrings in the source
|
||||
code. Others get by via asking questions in the `Discord server <https://discord.gg/0SBTUU1wZTXZNJPa>`_. Others look at the
|
||||
code. Others get by via asking questions in the `Discord server <https://discord.gg/discord-api>`_. Others look at the
|
||||
source code of `other existing bots <https://github.com/Rapptz/RoboDanny>`_.
|
||||
|
||||
There is a `basic example <https://github.com/Rapptz/discord.py/blob/master/examples/basic_bot.py>`_ showcasing some
|
||||
There is a `basic example <https://github.com/Rapptz/discord.py/blob/rewrite/examples/basic_bot.py>`_ showcasing some
|
||||
functionality.
|
||||
|
||||
**Documentation is being worked on, it will just take some time to polish it**.
|
||||
@ -249,42 +266,36 @@ Overriding the default provided ``on_message`` forbids any extra commands from r
|
||||
|
||||
await bot.process_commands(message)
|
||||
|
||||
Can I use ``bot.say`` in other places aside from commands?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
No. They only work inside commands due to the way the magic involved works.
|
||||
|
||||
Why do my arguments require quotes?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In a simple command defined as: ::
|
||||
|
||||
@bot.command()
|
||||
async def echo(message: str):
|
||||
await bot.say(message)
|
||||
async def echo(ctx, message: str):
|
||||
await ctx.send(message)
|
||||
|
||||
Calling it via ``?echo a b c`` will only fetch the first argument and disregard the rest. To fix this you should either call
|
||||
it via ``?echo "a b c"`` or change the signature to have "consume rest" behaviour. Example: ::
|
||||
|
||||
@bot.command()
|
||||
async def echo(*, message: str):
|
||||
await bot.say(message)
|
||||
async def echo(ctx, *, message: str):
|
||||
await ctx.send(message)
|
||||
|
||||
This will allow you to use ``?echo a b c`` without needing the quotes.
|
||||
|
||||
How do I get the original ``message``\?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Ask the command to pass you the invocation context via ``pass_context``. This context will be passed as the first parameter.
|
||||
The :class:`~ext.commands.Context` contains an attribute, :attr:`~ext.commands.Context.message` to get the original
|
||||
message.
|
||||
|
||||
Example: ::
|
||||
|
||||
@bot.command(pass_context=True)
|
||||
@bot.command()
|
||||
async def joined_at(ctx, member: discord.Member = None):
|
||||
if member is None:
|
||||
member = ctx.message.author
|
||||
|
||||
await bot.say('{0} joined at {0.joined_at}'.format(member))
|
||||
member = member or ctx.author
|
||||
await ctx.send('{0} joined at {0.joined_at}'.format(member))
|
||||
|
||||
How do I make a subcommand?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -294,15 +305,14 @@ the group operating as "subcommands". These groups can be arbitrarily nested as
|
||||
|
||||
Example: ::
|
||||
|
||||
@bot.group(pass_context=True)
|
||||
@bot.group()
|
||||
async def git(ctx):
|
||||
if ctx.invoked_subcommand is None:
|
||||
await bot.say('Invalid git command passed...')
|
||||
|
||||
@git.command()
|
||||
async def push(remote: str, branch: str):
|
||||
await bot.say('Pushing to {} {}'.format(remote, branch))
|
||||
|
||||
async def push(ctx, remote: str, branch: str):
|
||||
await ctx.send('Pushing to {} {}'.format(remote, branch))
|
||||
|
||||
This could then be used as ``?git push origin master``.
|
||||
|
||||
|
BIN
docs/images/discord_client_id.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
docs/images/discord_create_bot_user_button.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
docs/images/discord_finished_bot_user.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
docs/images/discord_new_app_button.PNG
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
docs/images/discord_new_app_form.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
docs/images/discord_reveal_token.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
docs/images/snake.png
Normal file
After Width: | Height: | Size: 28 KiB |
@ -3,23 +3,55 @@
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to discord.py's documentation!
|
||||
======================================
|
||||
Welcome to the discord.py documentation
|
||||
=========================================
|
||||
|
||||
Contents:
|
||||
.. image:: /images/snake.png
|
||||
|
||||
discord.py is a modern, easy to use, feature-rich, and async ready API wrapper
|
||||
for Discord.
|
||||
|
||||
**Features:**
|
||||
|
||||
- Modern Pythonic API using ``async``\/``await`` syntax
|
||||
- Sane rate limit handling that prevents 429s
|
||||
- Implements the entirety of the Discord API
|
||||
- Command extension to aid with bot creation
|
||||
- Easy to use with an object oriented design
|
||||
- Optimised for both speed and memory
|
||||
|
||||
Documentation Contents
|
||||
-----------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
logging
|
||||
whats_new
|
||||
intro
|
||||
quickstart
|
||||
migrating
|
||||
logging
|
||||
api
|
||||
faq
|
||||
|
||||
Extensions
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
ext/commands/index.rst
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
Additional Information
|
||||
-----------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
discord
|
||||
faq
|
||||
whats_new
|
||||
|
||||
If you still can't find what you're looking for, try in one of the following pages:
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
|
112
docs/intro.rst
Normal file
@ -0,0 +1,112 @@
|
||||
.. currentmodule:: discord
|
||||
|
||||
.. _intro:
|
||||
|
||||
Introduction
|
||||
==============
|
||||
|
||||
This is the documentation for discord.py, a library for Python to aid
|
||||
in creating applications that utilise the Discord API.
|
||||
|
||||
Prerequisites
|
||||
---------------
|
||||
|
||||
discord.py works with Python 3.4.2 or higher. Support for earlier versions of Python
|
||||
is not provided. Python 2.7 or lower is not supported. Python 3.3 is not supported
|
||||
due to one of the dependencies (``aiohttp``) not supporting Python 3.3.
|
||||
|
||||
|
||||
.. _installing:
|
||||
|
||||
Installing
|
||||
-----------
|
||||
|
||||
You can get the library directly from PyPI: ::
|
||||
|
||||
python3 -m pip install -U discord.py
|
||||
|
||||
If you are using Windows, then the following should be used instead: ::
|
||||
|
||||
py -3 -m pip install -U discord.py
|
||||
|
||||
|
||||
To get voice support, you should use ``discord.py[voice]`` instead of ``discord.py``, e.g. ::
|
||||
|
||||
python3 -m pip install -U discord.py[voice]
|
||||
|
||||
On Linux environments, installing voice requires getting the following dependencies:
|
||||
|
||||
- libffi
|
||||
- libnacl
|
||||
- python3-dev
|
||||
|
||||
For a debian-based system, the following command will help get those dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ apt install libffi-dev libnacl-dev python3-dev
|
||||
|
||||
Remember to check your permissions!
|
||||
|
||||
Virtual Environments
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sometimes we don't want to pollute our system installs with a library or we want to maintain
|
||||
different versions of a library than the currently system installed one. Or we don't have permissions to
|
||||
install a library along side with the system installed ones. For this purpose, the standard library as
|
||||
of 3.3 comes with a concept called "Virtual Environment" to help maintain these separate versions.
|
||||
|
||||
A more in-depth tutorial is found on `the official documentation. <https://docs.python.org/3/tutorial/venv.html>`_
|
||||
|
||||
However, for the quick and dirty:
|
||||
|
||||
1. Go to your project's working directory:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd your-bot-source
|
||||
$ python3 -m venv bot-env
|
||||
|
||||
2. Activate the virtual environment:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ source bot-env/bin/activate
|
||||
|
||||
On Windows you activate it with:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ bot-env\Scripts\activate.bat
|
||||
|
||||
3. Use pip like usual:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ pip install -U discord.py
|
||||
|
||||
Congratulations. You now have a virtual environment all set up without messing with your system installation.
|
||||
|
||||
Basic Concepts
|
||||
---------------
|
||||
|
||||
discord.py revolves around the concept of :ref:`events <discord-api-events>`.
|
||||
An event is something you listen to and then respond to. For example, when a message
|
||||
happens, you will receive an event about it and you can then respond to it.
|
||||
|
||||
A quick example to showcase how events work:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import discord
|
||||
|
||||
class MyClient(discord.Client):
|
||||
async def on_ready(self):
|
||||
print('Logged on as {0}!'.format(self.user))
|
||||
|
||||
async def on_message(self, message):
|
||||
print('Message from {0.author}: {0.content}'.format(message))
|
||||
|
||||
client = MyClient()
|
||||
client.run('my token goes here')
|
||||
|
1153
docs/migrating.rst
322
docs/migrating_to_async.rst
Normal file
@ -0,0 +1,322 @@
|
||||
:orphan:
|
||||
|
||||
.. currentmodule:: discord
|
||||
|
||||
.. _migrating-to-async:
|
||||
|
||||
Migrating to v0.10.0
|
||||
======================
|
||||
|
||||
v0.10.0 is one of the biggest breaking changes in the library due to massive
|
||||
fundamental changes in how the library operates.
|
||||
|
||||
The biggest major change is that the library has dropped support to all versions prior to
|
||||
Python 3.4.2. This was made to support ``asyncio``, in which more detail can be seen
|
||||
:issue:`in the corresponding issue <50>`. To reiterate this, the implication is that
|
||||
**python version 2.7 and 3.3 are no longer supported**.
|
||||
|
||||
Below are all the other major changes from v0.9.0 to v0.10.0.
|
||||
|
||||
Event Registration
|
||||
--------------------
|
||||
|
||||
All events before were registered using :meth:`Client.event`. While this is still
|
||||
possible, the events must be decorated with ``@asyncio.coroutine``.
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@client.event
|
||||
def on_message(message):
|
||||
pass
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@client.event
|
||||
@asyncio.coroutine
|
||||
def on_message(message):
|
||||
pass
|
||||
|
||||
Or in Python 3.5+:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@client.event
|
||||
async def on_message(message):
|
||||
pass
|
||||
|
||||
Because there is a lot of typing, a utility decorator (:meth:`Client.async_event`) is provided
|
||||
for easier registration. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@client.async_event
|
||||
def on_message(message):
|
||||
pass
|
||||
|
||||
|
||||
Be aware however, that this is still a coroutine and your other functions that are coroutines must
|
||||
be decorated with ``@asyncio.coroutine`` or be ``async def``.
|
||||
|
||||
Event Changes
|
||||
--------------
|
||||
|
||||
Some events in v0.9.0 were considered pretty useless due to having no separate states. The main
|
||||
events that were changed were the ``_update`` events since previously they had no context on what
|
||||
was changed.
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def on_channel_update(channel): pass
|
||||
def on_member_update(member): pass
|
||||
def on_status(member): pass
|
||||
def on_server_role_update(role): pass
|
||||
def on_voice_state_update(member): pass
|
||||
def on_socket_raw_send(payload, is_binary): pass
|
||||
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def on_channel_update(before, after): pass
|
||||
def on_member_update(before, after): pass
|
||||
def on_server_role_update(before, after): pass
|
||||
def on_voice_state_update(before, after): pass
|
||||
def on_socket_raw_send(payload): pass
|
||||
|
||||
Note that ``on_status`` was removed. If you want its functionality, use :func:`on_member_update`.
|
||||
See :ref:`discord-api-events` for more information. Other removed events include ``on_socket_closed``, ``on_socket_receive``, and ``on_socket_opened``.
|
||||
|
||||
|
||||
Coroutines
|
||||
-----------
|
||||
|
||||
The biggest change that the library went through is that almost every function in :class:`Client`
|
||||
was changed to be a `coroutine <https://docs.python.org/3/library/asyncio-task.html>`_. Functions
|
||||
that are marked as a coroutine in the documentation must be awaited from or yielded from in order
|
||||
for the computation to be done. For example...
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
client.send_message(message.channel, 'Hello')
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
yield from client.send_message(message.channel, 'Hello')
|
||||
|
||||
# or in python 3.5+
|
||||
await client.send_message(message.channel, 'Hello')
|
||||
|
||||
In order for you to ``yield from`` or ``await`` a coroutine then your function must be decorated
|
||||
with ``@asyncio.coroutine`` or ``async def``.
|
||||
|
||||
Iterables
|
||||
----------
|
||||
|
||||
For performance reasons, many of the internal data structures were changed into a dictionary to support faster
|
||||
lookup. As a consequence, this meant that some lists that were exposed via the API have changed into iterables
|
||||
and not sequences. In short, this means that certain attributes now only support iteration and not any of the
|
||||
sequence functions.
|
||||
|
||||
The affected attributes are as follows:
|
||||
|
||||
- :attr:`Client.servers`
|
||||
- :attr:`Client.private_channels`
|
||||
- :attr:`Server.channels`
|
||||
- :attr:`Server.members`
|
||||
|
||||
Some examples of previously valid behaviour that is now invalid
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if client.servers[0].name == "test":
|
||||
# do something
|
||||
|
||||
Since they are no longer ``list``\s, they no longer support indexing or any operation other than iterating.
|
||||
In order to get the old behaviour you should explicitly cast it to a list.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
servers = list(client.servers)
|
||||
# work with servers
|
||||
|
||||
.. warning::
|
||||
|
||||
Due to internal changes of the structure, the order you receive the data in
|
||||
is not in a guaranteed order.
|
||||
|
||||
Enumerations
|
||||
------------
|
||||
|
||||
Due to dropping support for versions lower than Python 3.4.2, the library can now use
|
||||
`enumerations <https://docs.python.org/3/library/enum.html>`_ in places where it makes sense.
|
||||
|
||||
The common places where this was changed was in the server region, member status, and channel type.
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
server.region == 'us-west'
|
||||
member.status == 'online'
|
||||
channel.type == 'text'
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
server.region == discord.ServerRegion.us_west
|
||||
member.status = discord.Status.online
|
||||
channel.type == discord.ChannelType.text
|
||||
|
||||
The main reason for this change was to reduce the use of finicky strings in the API as this
|
||||
could give users a false sense of power. More information can be found in the :ref:`discord-api-enums` page.
|
||||
|
||||
Properties
|
||||
-----------
|
||||
|
||||
A lot of function calls that returned constant values were changed into Python properties for ease of use
|
||||
in format strings.
|
||||
|
||||
The following functions were changed into properties:
|
||||
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| Before | After |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``User.avatar_url()`` | :attr:`User.avatar_url` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``User.mention()`` | :attr:`User.mention` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Channel.mention()`` | :attr:`Channel.mention` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Channel.is_default_channel()`` | :attr:`Channel.is_default` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Role.is_everyone()`` | :attr:`Role.is_everyone` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Server.get_default_role()`` | :attr:`Server.default_role` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Server.icon_url()`` | :attr:`Server.icon_url` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Server.get_default_channel()`` | :attr:`Server.default_channel` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Message.get_raw_mentions()`` | :attr:`Message.raw_mentions` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
| ``Message.get_raw_channel_mentions()`` | :attr:`Message.raw_channel_mentions` |
|
||||
+----------------------------------------+--------------------------------------+
|
||||
|
||||
Member Management
|
||||
-------------------
|
||||
|
||||
Functions that involved banning and kicking were changed.
|
||||
|
||||
+--------------------------------+--------------------------+
|
||||
| Before | After |
|
||||
+--------------------------------+--------------------------+
|
||||
| ``Client.ban(server, user)`` | ``Client.ban(member)`` |
|
||||
+--------------------------------+--------------------------+
|
||||
| ``Client.kick(server, user)`` | ``Client.kick(member)`` |
|
||||
+--------------------------------+--------------------------+
|
||||
|
||||
.. migrating-renames:
|
||||
|
||||
Renamed Functions
|
||||
-------------------
|
||||
|
||||
Functions have been renamed.
|
||||
|
||||
+------------------------------------+-------------------------------------------+
|
||||
| Before | After |
|
||||
+------------------------------------+-------------------------------------------+
|
||||
| ``Client.set_channel_permissions`` | :meth:`Client.edit_channel_permissions` |
|
||||
+------------------------------------+-------------------------------------------+
|
||||
|
||||
All the :class:`Permissions` related attributes have been renamed and the `can_` prefix has been
|
||||
dropped. So for example, ``can_manage_messages`` has become ``manage_messages``.
|
||||
|
||||
Forced Keyword Arguments
|
||||
-------------------------
|
||||
|
||||
Since 3.0+ of Python, we can now force questions to take in forced keyword arguments. A keyword argument is when you
|
||||
explicitly specify the name of the variable and assign to it, for example: ``foo(name='test')``. Due to this support,
|
||||
some functions in the library were changed to force things to take said keyword arguments. This is to reduce errors of
|
||||
knowing the argument order and the issues that could arise from them.
|
||||
|
||||
The following parameters are now exclusively keyword arguments:
|
||||
|
||||
- :meth:`Client.send_message`
|
||||
- ``tts``
|
||||
- :meth:`Client.logs_from`
|
||||
- ``before``
|
||||
- ``after``
|
||||
- :meth:`Client.edit_channel_permissions`
|
||||
- ``allow``
|
||||
- ``deny``
|
||||
|
||||
In the documentation you can tell if a function parameter is a forced keyword argument if it is after ``\*,``
|
||||
in the function signature.
|
||||
|
||||
.. _migrating-running:
|
||||
|
||||
Running the Client
|
||||
--------------------
|
||||
|
||||
In earlier versions of discord.py, ``client.run()`` was a blocking call to the main thread
|
||||
that called it. In v0.10.0 it is still a blocking call but it handles the event loop for you.
|
||||
However, in order to do that you must pass in your credentials to :meth:`Client.run`.
|
||||
|
||||
Basically, before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
client.login('token')
|
||||
client.run()
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
client.run('token')
|
||||
|
||||
.. warning::
|
||||
|
||||
Like in the older ``Client.run`` function, the newer one must be the one of
|
||||
the last functions to call. This is because the function is **blocking**. Registering
|
||||
events or doing anything after :meth:`Client.run` will not execute until the function
|
||||
returns.
|
||||
|
||||
This is a utility function that abstracts the event loop for you. There's no need for
|
||||
the run call to be blocking and out of your control. Indeed, if you want control of the
|
||||
event loop then doing so is quite straightforward:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import discord
|
||||
import asyncio
|
||||
|
||||
client = discord.Client()
|
||||
|
||||
@asyncio.coroutine
|
||||
def main_task():
|
||||
yield from client.login('token')
|
||||
yield from client.connect()
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
try:
|
||||
loop.run_until_complete(main_task())
|
||||
except:
|
||||
loop.run_until_complete(client.logout())
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
|
||||
|
76
docs/quickstart.rst
Normal file
@ -0,0 +1,76 @@
|
||||
.. _quickstart:
|
||||
|
||||
.. currentmodule:: discord
|
||||
|
||||
Quickstart
|
||||
============
|
||||
|
||||
This page gives a brief introduction to the library. It assumes you have the library installed,
|
||||
if you don't check the :ref:`installing` portion.
|
||||
|
||||
A Minimal Bot
|
||||
---------------
|
||||
|
||||
Let's make a bot that replies to a specific message and walk you through it.
|
||||
|
||||
It looks something like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import discord
|
||||
|
||||
client = discord.Client()
|
||||
|
||||
@client.event
|
||||
async def on_ready():
|
||||
print('We have logged in as {0.user}'.format(self))
|
||||
|
||||
@client.event
|
||||
async def on_message(message):
|
||||
if message.author == client.user:
|
||||
return
|
||||
|
||||
if message.content.startswith('$hello'):
|
||||
await message.channel.send('Hello!')
|
||||
|
||||
client.run('your token here')
|
||||
|
||||
Let's name this file ``example_bot.py``. Make sure not to name it ``discord.py`` as that'll conflict
|
||||
with the library.
|
||||
|
||||
There's a lot going on here, so let's walk you through it step by step.
|
||||
|
||||
1. The first line just imports the library, if this raises a `ModuleNotFoundError` or `ImportError`
|
||||
then head on over to :ref:`installing` section to properly install.
|
||||
2. Next, we create an instance of a :class:`Client`. This client is our connection to Discord.
|
||||
3. We then use the :meth:`Client.event` decorator to register an event. This library has many events.
|
||||
Since this library is asynchronous, we do things in a "callback" style manner.
|
||||
|
||||
A callback is essentially a function that is called when something happens. In our case,
|
||||
the :func:`on_ready` event is called when the bot has finished logging in and setting things
|
||||
up and the :func:`on_message` event is called when the bot has received a message.
|
||||
4. Since the :func:`on_message` event triggers for *every* message received, we have to make
|
||||
sure that we ignore messages from ourselves. We do this by checking if the :attr:`Message.author`
|
||||
is the same as the :attr:`Client.user`.
|
||||
5. Afterwards, we check if the :class:`Message.content` starts with ``'$hello'``. If it is,
|
||||
then we reply in the channel it was used in with ``'Hello!'``.
|
||||
6. Finally, we run the bot with our login token. If you need help getting your token or creating a bot,
|
||||
look in the :ref:`discord-intro` section.
|
||||
|
||||
|
||||
Now that we've made a bot, we have to *run* the bot. Luckily, this is simple since this is just a
|
||||
Python script, we can run it directly.
|
||||
|
||||
On Windows:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ py -3 example_bot.py
|
||||
|
||||
On other systems:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python3 example_bot.py
|
||||
|
||||
Now you can try playing around with your basic bot.
|
@ -2,12 +2,26 @@
|
||||
|
||||
.. _whats_new:
|
||||
|
||||
What's New
|
||||
Changelog
|
||||
============
|
||||
|
||||
This page keeps a detailed human friendly rendering of what's new and changed
|
||||
in specific versions.
|
||||
|
||||
.. _vp0p16p6:
|
||||
|
||||
v0.16.6
|
||||
--------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~~
|
||||
|
||||
- Fix issue with :meth:`Client.create_server` that made it stop working.
|
||||
- Fix main thread being blocked upon calling ``StreamPlayer.stop``.
|
||||
- Handle HEARTBEAT_ACK and resume gracefully when it occurs.
|
||||
- Fix race condition when pre-emptively rate limiting that caused releasing an already released lock.
|
||||
- Fix invalid state errors when immediately cancelling a coroutine.
|
||||
|
||||
.. _vp0p16p1:
|
||||
|
||||
v0.16.1
|
||||
|
2
setup.py
@ -9,6 +9,7 @@ with open('requirements.txt') as f:
|
||||
|
||||
if on_rtd:
|
||||
requirements.append('sphinxcontrib-napoleon')
|
||||
requirements.append('sphinxcontrib-asyncio')
|
||||
|
||||
version = ''
|
||||
with open('discord/__init__.py') as f:
|
||||
@ -35,6 +36,7 @@ with open('README.md') as f:
|
||||
|
||||
extras_require = {
|
||||
'voice': ['PyNaCl==1.0.1'],
|
||||
'docs': ['sphinxcontrib-asyncio']
|
||||
}
|
||||
|
||||
setup(name='discord.py',
|
||||
|