Skip to content

Commit

Permalink
feat: update cogs guide, and few touch ups in other guides
Browse files Browse the repository at this point in the history
  • Loading branch information
FallenDeity committed Aug 15, 2024
1 parent 6c7e9f5 commit 4064673
Show file tree
Hide file tree
Showing 11 changed files with 622 additions and 139 deletions.
Binary file added docs/assets/cogs/hybrid-group.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/cogs/prefix-group.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/cogs/slash-group.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
480 changes: 388 additions & 92 deletions docs/cogs.md

Large diffs are not rendered by default.

65 changes: 41 additions & 24 deletions docs/embeds.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Embeds

## What is Embed?
## What is an Embed?

Discord Embed object is a message component that is used as a way of adding rich content with different structures and formatting styles
Discord Embed object is a message component that is used as a way of adding rich content with different structures and formatting styles. Discord embeds also allow you to use markdown in the fields and descriptions, which can be useful for formatting. Check out our [Markdown](./markdown-and-ansi.md) page for more information.

## Overview

Expand Down Expand Up @@ -31,22 +31,43 @@ async def foo(ctx: commands.Context):
await ctx.send(embed=embed)
```

!!! warning "Warning"
Almost all embed methods require keyword-only arguments

!!! info "Note"
Since most embed methods return the embed itself, you can nest them as follows:
Since most embed methods return the embed itself, you can chain them like this:
```py
discord.Embed(...).set_image(...).add_field(...)
```
Almost all methods have a default value of `None`, so you can skip them if you don't need them.

![Showcase](assets/embeds/1.png)

## Creating an Embed

To create an embed, you need to create an instance of the `discord.Embed` class. You can pass various parameters to the constructor to set the properties of the embed.

```py
embed = discord.Embed(
title="Title",
description="Description",
color=discord.Color.random(),
timestamp=datetime.datetime.utcnow()
)
```

- `title` - The title of the embed
- `description` - The description of the embed
- `color` - The color of the embed, you can use [`discord.Color`](https://discordpy.readthedocs.io/en/stable/api.html#colour) to set the color or construct colors using the following methods:
- `discord.Color.from_rgb(r, g, b)`
- `discord.Color.from_hsv(h, s, v)`
- `discord.Color.from_str("0x<HEX> | #<HEX> | 0x#<HEX> | rgb(r, g, b)")`
- `timestamp` - The timestamp of the embed, you can use `discord.utils.utcnow()` to get the current time

## Working with specific fields

---

### Getting a list of fields

*property* [Embed.fields](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.fields)
**property** [Embed.fields](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.fields)

```pycon title="Python Console Session"
>>> import discord
Expand All @@ -67,10 +88,9 @@ async def foo(ctx: commands.Context):
([pep8](https://peps.python.org/pep-0008/#descriptive-naming-styles))



### Appending a field

*method* [Embed.add_field](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.add_field)
**method** [Embed.add_field](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.add_field)

```pycon title="Python Console Session"
>>> import discord
Expand All @@ -84,7 +104,7 @@ async def foo(ctx: commands.Context):

### Inserting field at index

*method* [Embed.insert_field_at](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.insert_field_at)
**method** [Embed.insert_field_at](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.insert_field_at)

```pycon title="Python Console Session"
>>> import discord
Expand All @@ -99,7 +119,7 @@ async def foo(ctx: commands.Context):

### Changing field at index

*method* [Embed.set_field_at](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.set_field_at)
**method** [Embed.set_field_at](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.set_field_at)

```pycon title="Python Console Session"
>>> import discord
Expand All @@ -114,7 +134,7 @@ async def foo(ctx: commands.Context):

### Removing one field

*method* [Embed.remove_field](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.remove_field)
**method** [Embed.remove_field](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.remove_field)

```pycon title="Python Console Session"
>>> import discord
Expand All @@ -129,7 +149,7 @@ async def foo(ctx: commands.Context):

### Removing all fields

*method* [Embed.clear_fields](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.clear_fields)
**method** [Embed.clear_fields](https://discordpy.readthedocs.io/en/stable/api.html?#discord.Embed.clear_fields)

```pycon title="Python Console Session"
>>> import discord
Expand Down Expand Up @@ -197,21 +217,17 @@ async def foo(ctx: commands.Context):

## How to use local image for an embed image?

!!! info "Note"
It's a copy from [discord.py faq](https://discordpy.readthedocs.io/en/stable/faq.html#local-image)

Discord special-cases uploading an image attachment and using it within an embed so that it will not display separately, but instead in the embed’s thumbnail, image, footer or author icon.
Discord.py allows you to send images as attachments in messages. You can use the `discord.File` class to send images as attachments in messages. You can then use the `attachment://` protocol followed by the filename to reference the attachment in the embed.

To do so, upload the image normally with [abc.Messageable.send()](https://discordpy.readthedocs.io/en/stable/api.html#discord.abc.Messageable.send), and set the embed’s image URL to `attachment://image.png`, where `image.png` is the filename of the image you will send.

Quick example:
```py
file = discord.File("path/to/my/image.png", filename="image.png")
embed = discord.Embed()
embed.set_image(url="attachment://image.png")
await channel.send(file=file, embed=embed)
```

Always remember to also send pass the `file` object when sending the message, without it discord will not be able to find the image you are trying to refer to.

This comment has been minimized.

Copy link
@Snipy7374

Snipy7374 Aug 16, 2024

Collaborator

Idk why github is not letting me create a code suggestion, anyway

- Always remember to also send pass the `file` object when sending the message, without it discord will not be able to find the image you are trying to refer to.
+ Remember to pass the `file` object when sending the message, without it discord will not be able to find the image you are trying to refer to.

## Embed limits

!!! abstract ""
Expand All @@ -229,9 +245,10 @@ await channel.send(file=file, embed=embed)

The **total of characters** allowed in an embed is **6000**

## Embed generating website
## Embed Playgrounds

!!! warning "Warning"
We don't advise using the website to create embeds: it's best to do it on your own. But it's actually very comfortable.
- [Discord Embed Sandbox](https://cog-creators.github.io/discord-embed-sandbox/)
- [Embed Visualizer](https://leovoel.github.io/embed-visualizer/)

On this [site](https://cog-creators.github.io/discord-embed-sandbox/) you can generate discord.py code for creating an embed
!!! warning "Warning"
We don't advise using the website to create embeds: it's best to do it on your own and far more efficient and customizable. But however, the site can be a good playground for testing and learning.
38 changes: 38 additions & 0 deletions docs/markdown-and-ansi.md
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,44 @@ To have syntax highlighting in code blocks, you can specify the language after t
!!! tip "Tip"
Above were just a few examples, You can find a list of supported languages [here](https://highlightjs.org/static/demo/).

### Mentions

Discord supports mentioning users, roles, and channels in messages and a few other special mentions such as `@everyone` and `@here`.

| Mention Type | Code | Remarks |
|--------------|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| User | `<@user_id>` or `<@!user_id>` | Replace `user_id` with the user's id, this will ping the user. If the user is not found it will display `@unknown-user`. |
| Role | `<@&role_id>` | Replace `role_id` with the role's id, this will ping all the users with the role. If the role is not found it will display `@unknown-role`. |
| Channel | `<#channel_id>` | Replace `channel_id` with the channel's id, this will display the channel's name as a hyperlink making it easier to navigate to the channel. If the channel is not found it will display `#unknown`. |
| Everyone | `@everyone` | Pings everyone in the server. |
| Here | `@here` | Pings everyone in the server who is online. |

### Timestamps

You can use timestamps in messages and embeds to display the time in a user's local timezone, in a relative format, or in a specific format.

| Style | Format | Example Input | Example Output | Description |
|-------------|-------------------|--------------------|-----------------------------------|-----------------------------------------------------------------|
| t | `<t:timestamp:t>` | `<t:1633660800:t>` | `8:10 AM` | Short time format (HH:MM AM/PM) in the user's local timezone. |
| T | `<t:timestamp:T>` | `<t:1633660800:T>` | `8:10:00 AM` | Long time format (HH:MM:SS AM/PM) in the user's local timezone. |
| d | `<t:timestamp:d>` | `<t:1633660800:d>` | `10/8/2021` | Short date format (MM/DD/YYYY) in the user's local timezone. |
| D | `<t:timestamp:D>` | `<t:1633660800:D>` | `October 8, 2021` | Long date format (Month DD, YYYY) in the user's local timezone. |
| f (default) | `<t:timestamp:f>` | `<t:1633660800:f>` | `October 8, 2021 8:10 AM` | Short date and time format in the user's local timezone. |
| F | `<t:timestamp:F>` | `<t:1633660800:F>` | `Friday, October 8, 2021 8:10 AM` | Long date and time format in the user's local timezone. |
| R | `<t:timestamp:R>` | `<t:1633660800:R>` | `3 years ago` | Relative time format. |

```pycon
In [1]: import discord
...: import datetime
...:
...: timestamp = datetime.datetime(2021, 10, 8, 8, 10)
...: print(discord.utils.format_dt(timestamp, "f"))
<t:1633660800:f>

In [2]: print(discord.utils.format_dt(timestamp, "t"))
<t:1633660800:t>
```

## Conclusion

In this tutorial, we learned how to use markdown and ANSI highlighting in discord.py. We also learned how to use the `AnsiBuilder` class to create custom ANSI blocks.
Expand Down
94 changes: 72 additions & 22 deletions docs/tasks.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,73 @@
# Tasks

[Tasks](https://discordpy.readthedocs.io/en/stable/ext/tasks/index.html) in discord.py are helpers
for [asyncio.Task](https://docs.python.org/3/library/asyncio-task.html#task-object)
One of the most common things you will often find yourself needing is some sort of background task. This could be anything from updating a counter every minute to updating some leaderboard every hour or posting daily reminders.
To handle these tasks, discord.py provides a `tasks` extension that makes it easy to create and manage background tasks.

They are used for having a loop run in the background at a specified interval/time.
The `tasks` extension is a wrapper around the [`asyncio.Task`](https://docs.python.org/3/library/asyncio-task.html#task-object) class that allows you to run a coroutine in the background at a specified interval, with a lot of additional features like error handling, reconnect logic, exponential backoff, and more.

## Creating a task

To create a task you need to make an `async` function that you want to run in the task and apply `tasks.loop` decorator on it.

You can read about its parameters in [discord.py documentation](https://discordpy.readthedocs.io/en/stable/ext/tasks/index.html#discord.ext.tasks.loop)
It takes the following arguments:

```python
from discord.ext import tasks
- `seconds`: The number of seconds between each iteration.
- `minutes`: The number of minutes between each iteration.
- `hours`: The number of hours between each iteration.
- `time`: A `datetime.time` or a list of `datetime.time` objects representing the time(s) of day to run the task.
- `count`: The number of times to run the task. If `None`, the task will run indefinitely.
- `reconnect`: Whether to handle errors and restart the task using an exponential backoff strategy. Defaults to `True`. For more information see [here](https://github.com/Rapptz/discord.py/blob/ff638d393d0f5a83639ccc087bec9bf588b59a22/discord/backoff.py#L41-L108).
- `name`: The name of the task. If `None`, the function name will be used.

Then you can start it by using it's `start` method. This will schedule the task to run in the background.

@tasks.loop(seconds=10)
async def my_task():
print("Hello!")
```
=== "Using a Cog"
```python
from discord.ext import commands, tasks

Then you can start it by using it's `start` method. For example in `setup_hook`:
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot

```python
@bot.event
async def setup_hook():
my_task.start()
```
# you can start the task when the cog is loaded
async def cog_load(self):
self.my_task.start()

# you can stop the task when the cog is unloaded
async def cog_unload(self):
self.my_task.stop()

@tasks.loop(seconds=10)
async def my_task(self):
print("Hello!")

async def setup(bot):
bot.add_cog(MyCog(bot))
```
=== "Standalone"
```python
from discord.ext import tasks

@tasks.loop(seconds=10)
async def my_task():
print("Hello!")

@bot.event
async def setup_hook(): # setup_hook is called before the bot is started
my_task.start()

@my_task.before_loop
async def before_my_task():
await bot.wait_until_ready() # wait until the bot is ready
```
!!! note "Note"
The only requirement to schedule a task is to call the `start` method which you can call at an appropriate place in your code. A thing to note is that the task may start running before the bot is ready, so you may want to use `before_loop` to wait until the bot is ready if you are fetching any data from the discord API.

## Utility Decorators

### before_loop
---

### @before_loop

A decorator that registers a coroutine to be called before the loop starts running.

Expand All @@ -48,9 +85,9 @@ async def before_my_task():
print("preparing!")
```

### after_loop
### @after_loop

A decorator that registers a coroutine to be called after the loop finishes running.
A decorator that registers a coroutine to be called after the loop finishes running. You can use this to perform cleanup tasks.

```python
from discord.ext import tasks
Expand All @@ -66,7 +103,7 @@ async def after_my_task():
print("finished!")
```

### error
### @error

A decorator that registers a coroutine to be called if the task encounters an unhandled exception.

Expand Down Expand Up @@ -121,9 +158,22 @@ my_task.restart()
Adds exception types to be handled during the reconnect logic.

By default the exception types handled are those handled by `Client.connect()`, which includes a lot of internet disconnection errors.
This method is useful if you want to handle custom exceptions that are either raise by you or some third-party libraries.

This comment has been minimized.

Copy link
@Snipy7374

Snipy7374 Aug 16, 2024

Collaborator
- This method is useful if you want to handle custom exceptions that are either raise by you or some third-party libraries.
+ This method is useful if you want to handle custom exceptions that are either raised by you or some third-party libraries.

```python
my_task.add_exception_type(SomeCustomError, AnotherCustomError)
class SomeCustomError(Exception):
pass

@tasks.loop(seconds=10)
async def my_task():
connection = await some_third_party_library.connect()
print(connection)
if not connection:
raise SomeCustomError("Connection failed!")
# do something with connection
connection.close()

my_task.add_exception_type(SomeCustomError) # now SomeCustomError will be handled during the reconnect logic
```

### clear_exception_types
Expand Down Expand Up @@ -162,4 +212,4 @@ my_task.change_interval(seconds=15)

## Examples

Check out [discord.py tasks recipes](https://discordpy.readthedocs.io/en/stable/ext/tasks/index.html#recipes). There you can find a lot of examples
Check out [discord.py tasks recipes](https://discordpy.readthedocs.io/en/stable/ext/tasks/index.html#recipes) for some examples on how to use tasks in your bot.
1 change: 0 additions & 1 deletion docs/views.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ So keeping these methods in mind, let's create a view:
```py
from __future__ import annotations

import logging
import typing

import discord
Expand Down
9 changes: 9 additions & 0 deletions examples/hot-reload/cogs/sub_cogs/sub_cog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from discord.ext import commands


class SubCog(commands.Cog):
...


async def setup(bot: commands.Bot):
await bot.add_cog(SubCog())
19 changes: 19 additions & 0 deletions examples/hot-reload/cogs/super_cog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import discord
from discord import app_commands
from discord.ext import commands


class SuperCog(commands.GroupCog, name="foo", description="A super cog"):
_bar = app_commands.Group(name="bar", description="A bar group")

@app_commands.command()
async def foo(self, inter: discord.Interaction):
await inter.response.send_message("foo")

@_bar.command()
async def baz(self, inter: discord.Interaction):
await inter.response.send_message("baz")


async def setup(bot: commands.Bot):
await bot.add_cog(SuperCog())
Loading

0 comments on commit 4064673

Please sign in to comment.