aboutsummaryrefslogtreecommitdiff
path: root/docs/faq.rst
diff options
context:
space:
mode:
authorRapptz <[email protected]>2017-05-12 20:14:34 -0400
committerRapptz <[email protected]>2017-05-12 20:14:34 -0400
commitb44bba6ee6e29b38d1e579c602821582e155ec3b (patch)
tree355df44874b3e5f8ee4e825339cb57783e3677ca /docs/faq.rst
parentRename abc.Callable to abc.Connectable. (diff)
downloaddiscord.py-b44bba6ee6e29b38d1e579c602821582e155ec3b.tar.xz
discord.py-b44bba6ee6e29b38d1e579c602821582e155ec3b.zip
First pass at documentation reform.
Diffstat (limited to 'docs/faq.rst')
-rw-r--r--docs/faq.rst174
1 files changed, 92 insertions, 82 deletions
diff --git a/docs/faq.rst b/docs/faq.rst
index 1525b3a6..fda5313b 100644
--- a/docs/faq.rst
+++ b/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')
+ channel = client.get_channel('12324234183172')
+ await channel.send('hello')
-The second way is by calling :meth:`Client.get_channel` directly: ::
+How do I upload an image?
+~~~~~~~~~~~~~~~~~~~~~~~~~~
- await client.send_message(client.get_channel('12324234183172'), 'hello')
+To upload something to Discord you have to use the :class:`File` object.
-I'm passing IDs as integers and things are not working!
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A :class:`File` accepts two parameters, the file-like object (or file path) and the filename
+to pass to Discord when uploading.
-In the library IDs must be of type ``str`` not of type ``int``. Wrap it in quotes.
+If you want to upload an image it's as simple as: ::
-How do I upload an image?
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+ await channel.send(file=discord.File('my_file.png'))
-There are two ways of doing it. Both of which involve using :meth:`Client.send_file`.
+If you have a file-like object you can do as follows: ::
-The first is by opening the file and passing it directly: ::
+ with open('my_file.png', 'rb') as fp:
+ await channel.send(file=discord.File(fp, 'new_filename.png'))
- with open('my_image.png', 'rb') as f:
- await client.send_file(channel, f)
+To upload multiple files, you can use the ``files`` keyword argument instead of ``file``\: ::
-The second is by passing the file name directly: ::
+ 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: ::
+
+ await message.add_reaction('\N{THUMBS UP SIGN}')
-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.
+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
+ voice.play(discord.FFmpegPCMAudio(url), after=my_after)
- player = await voice.create_ytdl_player(url, after=self.foo())
- other = await voice.create_ytdl_player(url, after=self.bar(10))
+How do I run something in the background?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-However the following are correct:
+`Check the background_task.py example. <https://github.com/Rapptz/discord.py/blob/rewrite/examples/background_task.py>`_
-.. code-block:: python
+How do I get a specific model?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- player = await voice.create_ytdl_player(url, after=self.foo)
- other = await voice.create_ytdl_player(url, after=lambda: self.bar(10))
+There are multiple ways of doing this. If you have a specific model's ID then you can use
+one of the following functions:
-Basically, these functions should not be called.
+- :meth:`Client.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:
-How do I run something in the background?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+- :meth:`abc.Messageable.get_message`
+- :meth:`Client.get_user_info`
-`Check the background_task.py example. <https://github.com/Rapptz/discord.py/blob/master/examples/background_task.py>`_
-How do I get a specific User/Role/Channel/Server?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+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 models.
-There are multiple ways of doing this. If you have a specific entity's ID then you can use
-one of the following functions:
+Quick example: ::
-- :meth:`Client.get_channel`
-- :meth:`Client.get_server`
-- :meth:`Server.get_member`
-- :meth:`Server.get_channel`
+ # find a guild by name
+ guild = discord.utils.get(client.guilds, name='My Server')
-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.
+ # 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``.