diff options
| author | Rapptz <[email protected]> | 2017-05-12 20:14:34 -0400 |
|---|---|---|
| committer | Rapptz <[email protected]> | 2017-05-12 20:14:34 -0400 |
| commit | b44bba6ee6e29b38d1e579c602821582e155ec3b (patch) | |
| tree | 355df44874b3e5f8ee4e825339cb57783e3677ca /docs/faq.rst | |
| parent | Rename abc.Callable to abc.Connectable. (diff) | |
| download | discord.py-b44bba6ee6e29b38d1e579c602821582e155ec3b.tar.xz discord.py-b44bba6ee6e29b38d1e579c602821582e155ec3b.zip | |
First pass at documentation reform.
Diffstat (limited to 'docs/faq.rst')
| -rw-r--r-- | docs/faq.rst | 174 |
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``. |