From 4bf208784e21a97e29474a7b5e7283d1105b14c9 Mon Sep 17 00:00:00 2001 From: Matteo Bertucci Date: Fri, 12 Nov 2021 09:27:15 +0100 Subject: Content: update help channel claiming system This commit changes the following inside the help channel guide: * Only one help channel can be claimed at the same time * You can use the search to find your channel * The channel will close after 10 minutes if someone else sends a message --- .../apps/content/resources/guides/pydis-guides/help-channel-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 8b7c5584..fe1c4747 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -42,14 +42,14 @@ There are always 3 available help channels waiting to be claimed in the **Python In order to claim one, simply start typing your question into one of these channels. Once your question has been posted, you have claimed this channel, and the channel will be moved down to the **Python Help: Occupied** category. -If you're unable to type into these channels, this means you're currently **on cooldown**. In order to prevent someone from claiming all the channels for themselves, **we only allow someone to claim a new help channel every 15 minutes**. However, if you close your help channel using the `!dormant` command, this cooldown is reset early. +If you're unable to type into these channels, this means you're currently **on cooldown**. In order to prevent someone from claiming all the channels for themselves, **we only allow someone to claim a single help channel at the same time**. You can search in the top right corner of your Discord client `from:yourusername#xxxx` to find back your channel. ![Channel available message](/static/images/content/help_channels/available_message.png) *This message is always posted when a channel becomes available for use.* ## Q: For how long is the channel mine? -The channel is yours until it has been inactive for **30 minutes**. When this happens, we move the channel down to the **Python Help: Dormant** category, and make the channel read-only. After a while, the channel will be rotated back into **Python Help: Available** for the next question. Please try to resist the urge to continue bumping the channel so that it never gets marked as inactive. If nobody is answering your question, you should try to reformulate the question to increase your chances of getting help. +The channel is yours until it has been inactive for **10 minutes**, or 30 minutes until someone participate in the channel. When this happens, we move the channel down to the **Python Help: Dormant** category, and make the channel read-only. After a while, the channel will be rotated back into **Python Help: Available** for the next question. Please try to resist the urge to continue bumping the channel so that it never gets marked as inactive. If nobody is answering your question, you should try to reformulate the question to increase your chances of getting help. ![Channel dormant message](/static/images/content/help_channels/dormant_message.png) *You'll see this message in your channel when the channel is marked as inactive.* -- cgit v1.2.3 From c1593a66e1fe8739ba881f76736330459d0ffc8e Mon Sep 17 00:00:00 2001 From: mina Date: Thu, 23 Dec 2021 13:13:26 -0500 Subject: Fix markdown error linking to recommended editors --- .../guides/python-guides/creating-python-environment-windows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/creating-python-environment-windows.md b/pydis_site/apps/content/resources/guides/python-guides/creating-python-environment-windows.md index 356d63bd..635c384f 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/creating-python-environment-windows.md +++ b/pydis_site/apps/content/resources/guides/python-guides/creating-python-environment-windows.md @@ -29,7 +29,7 @@ You will also need a text editor for writing Python programs, and for subsequent Powerful programs called integrated development environments (IDEs) like PyCharm and Visual Studio Code contain text editors, but they also contain many other features with uses that aren't immediately obvious to new programmers. [Notepad++](https://notepad-plus-plus.org/) is a popular text editor for both beginners and advanced users who prefer a simpler interface. -Other editors we recommend can be found (https://pythondiscord.com/resources/tools/#editors)[here]. +Other editors we recommend can be found [here](https://pythondiscord.com/resources/tools/#editors). ## Installing Git Bash Git is a command line program that helps you keep track of changes to your code, among other things. -- cgit v1.2.3 From 0dc2e2a1c8bb7f8ee51bc37a311d3b60473fbad6 Mon Sep 17 00:00:00 2001 From: mina Date: Thu, 23 Dec 2021 16:25:56 -0500 Subject: Update wording in topical and general help channel sections --- .../guides/pydis-guides/help-channel-guide.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index fe1c4747..5b0c773c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -22,17 +22,15 @@ If your question fits into the domain of one of our topical help channels, and i ![List of topical help channels](/static/images/content/help_channels/topical_channels.png) -Some of the topical help channels have a broad scope, so they can cover many (somewhat) related topics. +Some of the topical help channels have a broad scope, so they can cover many related topics. For example, `#data-science-and-ai` covers scientific Python, statistics, and machine learning, while `#algos-and-data-structs` covers everything from data structures and algorithms to maths. -To help you navigate this, we've added a list of suggested topics in the topic of every channel. -If you're not sure where to post, feel free to ask us which channel is relevant for a topic in `#community-meta`. +Each channel on the server has a channel description which briefly describes the topics covered by that channel. If you're not sure where to post, feel free to ask us which channel is appropriate in `#community-meta`. # General Help Channels -Our general help channels move at a fast pace, and attract a far more diverse spectrum of helpers. -This is a great choice for a generic Python question, and a good choice if you need an answer as soon as possible. -It's particularly important to [ask good questions](../asking-good-questions) when asking in these channels, or you risk not getting an answer and having your help channel be claimed by someone else. +Our general help channels cycle quickly, with the advantage of attracting a more diverse spectrum of helpers, and getting individual attention and help for your question. These channels are a great choice for generic Python questions, but they can be used for domain-specific Python help as well. +Be sure to [ask good questions](../asking-good-questions) in order to give yourself the best chances of getting help. ## How To Claim a Channel @@ -40,12 +38,12 @@ There are always 3 available help channels waiting to be claimed in the **Python ![Available help channels](/static/images/content/help_channels/available_channels.png) -In order to claim one, simply start typing your question into one of these channels. Once your question has been posted, you have claimed this channel, and the channel will be moved down to the **Python Help: Occupied** category. +This message is posted when a channel becomes available for use: +![Channel available message](/static/images/content/help_channels/available_message.png) -If you're unable to type into these channels, this means you're currently **on cooldown**. In order to prevent someone from claiming all the channels for themselves, **we only allow someone to claim a single help channel at the same time**. You can search in the top right corner of your Discord client `from:yourusername#xxxx` to find back your channel. +In order to claim one, simply start typing your question into one of these channels. Once your question is posted, you have claimed this channel it will be moved down to the **Occupied Help Channels** category. -![Channel available message](/static/images/content/help_channels/available_message.png) -*This message is always posted when a channel becomes available for use.* +At this point you will have the **Help Cooldown** role which will remain on your profile until your help channel is closed (with the `!closed` command) or goes dormant due to inactivity. ## Q: For how long is the channel mine? -- cgit v1.2.3 From 5403f81215c7ea51aaebfc29148f8c9104b92430 Mon Sep 17 00:00:00 2001 From: mina Date: Thu, 23 Dec 2021 16:29:23 -0500 Subject: Add Frequently Asked Questions header --- .../apps/content/resources/guides/pydis-guides/help-channel-guide.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 5b0c773c..0f5a4f9c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -45,6 +45,8 @@ In order to claim one, simply start typing your question into one of these chann At this point you will have the **Help Cooldown** role which will remain on your profile until your help channel is closed (with the `!closed` command) or goes dormant due to inactivity. +# Frequently Asked Questions + ## Q: For how long is the channel mine? The channel is yours until it has been inactive for **10 minutes**, or 30 minutes until someone participate in the channel. When this happens, we move the channel down to the **Python Help: Dormant** category, and make the channel read-only. After a while, the channel will be rotated back into **Python Help: Available** for the next question. Please try to resist the urge to continue bumping the channel so that it never gets marked as inactive. If nobody is answering your question, you should try to reformulate the question to increase your chances of getting help. -- cgit v1.2.3 From 75cde82850b683a563a23cbed813bfcb0322e92e Mon Sep 17 00:00:00 2001 From: mina Date: Thu, 23 Dec 2021 16:55:59 -0500 Subject: Update channel dormancy timings --- .../content/resources/guides/pydis-guides/help-channel-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 0f5a4f9c..c0c7f896 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -47,12 +47,12 @@ At this point you will have the **Help Cooldown** role which will remain on your # Frequently Asked Questions -## Q: For how long is the channel mine? +## Q: How long does my help channel stay active? -The channel is yours until it has been inactive for **10 minutes**, or 30 minutes until someone participate in the channel. When this happens, we move the channel down to the **Python Help: Dormant** category, and make the channel read-only. After a while, the channel will be rotated back into **Python Help: Available** for the next question. Please try to resist the urge to continue bumping the channel so that it never gets marked as inactive. If nobody is answering your question, you should try to reformulate the question to increase your chances of getting help. +The channel remains open for **30 minutes** after your last message, but if another user posts in your channel, the closing will be delayed by 10 minutes. +*You'll see this message in your channel once it goes dormant:* ![Channel dormant message](/static/images/content/help_channels/dormant_message.png) -*You'll see this message in your channel when the channel is marked as inactive.* ## Q: I don't need my help channel anymore, my question was answered. What do I do? -- cgit v1.2.3 From 0219d94eb449f99dabf1f26dcf77f07ef92d13e0 Mon Sep 17 00:00:00 2001 From: mina Date: Thu, 23 Dec 2021 17:05:08 -0500 Subject: Add "no one answered me" question and answer --- .../content/resources/guides/pydis-guides/help-channel-guide.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index c0c7f896..e74cc43f 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -54,6 +54,12 @@ The channel remains open for **30 minutes** after your last message, but if anot *You'll see this message in your channel once it goes dormant:* ![Channel dormant message](/static/images/content/help_channels/dormant_message.png) +## Q: No one answered my question. How come? + +The server has users active all over the world and all hours of the day, but some days are less active than others. If no one answered your question, feel free to claim another help channel a little later. + +If you still feel like your question is being overlooked, read our guide on [asking good questions](../asking-good-questions) to incease your chances of getting a response. + ## Q: I don't need my help channel anymore, my question was answered. What do I do? Once you have finished with your help channel you or a staff member can run `!dormant`. This will move the channel to the **Python Help: Dormant** category where it will sit until it is returned to circulation. You will only be able to run the command if you claimed the channel from the available category, you cannot close channels belonging to others. -- cgit v1.2.3 From 72234b1a2b6585e998d85cebd31d3b5ed7986cec Mon Sep 17 00:00:00 2001 From: mina Date: Thu, 23 Dec 2021 17:12:18 -0500 Subject: Edit "how do I close my channel" question and answer --- .../apps/content/resources/guides/pydis-guides/help-channel-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index e74cc43f..5f41f442 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -62,7 +62,7 @@ If you still feel like your question is being overlooked, read our guide on [ask ## Q: I don't need my help channel anymore, my question was answered. What do I do? -Once you have finished with your help channel you or a staff member can run `!dormant`. This will move the channel to the **Python Help: Dormant** category where it will sit until it is returned to circulation. You will only be able to run the command if you claimed the channel from the available category, you cannot close channels belonging to others. +Go ahead and move your channel to the dormant category by running the `!closed` command. You will only be able to run this command in your own help channel, and likewise no one will be able to prematurely close your claimed help channel (with the exception of staff). ## Q: Are only Helpers supposed to answer questions? -- cgit v1.2.3 From 415b3c0827eb9e0346f6c156d68cff9ddbe55a3a Mon Sep 17 00:00:00 2001 From: mina Date: Thu, 23 Dec 2021 17:33:30 -0500 Subject: Edit "can only Helpers help?" answer and question Remove screenshot of occupied help channels because it doesn't serve much purpose, and help can also be provided in topical channels. --- .../resources/guides/pydis-guides/help-channel-guide.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 5f41f442..7c537a13 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -29,8 +29,8 @@ Each channel on the server has a channel description which briefly describes the # General Help Channels -Our general help channels cycle quickly, with the advantage of attracting a more diverse spectrum of helpers, and getting individual attention and help for your question. These channels are a great choice for generic Python questions, but they can be used for domain-specific Python help as well. -Be sure to [ask good questions](../asking-good-questions) in order to give yourself the best chances of getting help. +Our general help channels cycle quickly, with the advantage of attracting a more diverse spectrum of helpers, and getting individual attention and help for your question. These channels are a great choice for generic Python questions, but they can be used for domain-specific Python help as well. +Be sure to [ask good questions](../asking-good-questions) in order to give yourself the best chances of getting help. ## How To Claim a Channel @@ -64,13 +64,11 @@ If you still feel like your question is being overlooked, read our guide on [ask Go ahead and move your channel to the dormant category by running the `!closed` command. You will only be able to run this command in your own help channel, and likewise no one will be able to prematurely close your claimed help channel (with the exception of staff). -## Q: Are only Helpers supposed to answer questions? +## Q: Can only Helpers answer help questions? -Absolutely not. We strongly encourage all members of the community to help answer questions. If you'd like to help answer some questions, simply head over to one of the help channels that are currently in use. These can be found in the **Python Help: Occupied** category. +Definitely not! We encourage all members of the community to participate in giving help. If you'd like to help answer some questions, head over to the **Occupied Help Channels** or **Topical Chat/Help** categories. -![Occupied help channels](/static/images/content/help_channels/occupied_channels.png) - -Anyone can type in these channels, and users who are particularly helpful [may be offered a chance to join the staff on Python Discord](/pages/server-info/roles/#note-regarding-staff-roles). +Before jumping in, please read our guide on [helping others](../helping-others) which explains our expectations for the culture and quailty of help that we aim for on the server. ## Q: I lost my help channel! -- cgit v1.2.3 From fe9011e32c6bedb222858dca510a10c3cf1e1dac Mon Sep 17 00:00:00 2001 From: minalike Date: Mon, 31 Jan 2022 00:17:30 -0500 Subject: Update content Update some screenshot images to reflect emoji used in category names Break up some of the FAQ questions into smaller questions Mention the !helpdm on command added in 2021 Mention the channel claimed embed added in 2022 Culling of content to focus on information pertaining to getting help --- .../guides/pydis-guides/help-channel-guide.md | 64 +++++++++++++-------- .../content/help_channels/available_message.png | Bin 36279 -> 89386 bytes .../content/help_channels/claimed_channel.png | Bin 0 -> 26100 bytes .../content/help_channels/dormant_channels.png | Bin 6975 -> 22386 bytes .../content/help_channels/topical_channels.png | Bin 29231 -> 66126 bytes 5 files changed, 39 insertions(+), 25 deletions(-) create mode 100644 pydis_site/static/images/content/help_channels/claimed_channel.png (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 7c537a13..98b4705d 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -10,14 +10,13 @@ relevant_links: On the 5th of April 2020, we introduced a new help channel system at Python Discord. This article is a supplementary guide to explain precisely where to go to find help. -We have two different kinds of help channels in our community - **Topical help channels**, and **general help channels**. -Where you should go depends on what you need help with. -These channels also attract different helpers, and move at different speeds, which affects the kind of help you're likely to receive, and how fast you get that help. +We have two different kinds of help channels in our community: **topical help channels** and **general help channels**. +The topical channels can be great for longer and broader discussions, whereas a general help channel might be more appropriate for specific troubleshooting. Individual topical channels may have a narrower audience than the general help channels, but that may also be to your advantage if the audience is very familiar with the area of Python you are struggling with. # Topical Help Channels The topical help channels move at a slower pace than the general help channels. -They also sometimes attract domain experts - for example, `#async-and-concurrency` has CPython contributors who helped write asyncio, and in `#game-development` you can find the creators and maintainers of several game frameworks. +They also sometimes attract domain experts. For example, `#async-and-concurrency` has CPython contributors who helped write asyncio, and in `#game-development` you can find the creators and maintainers of several game frameworks. If your question fits into the domain of one of our topical help channels, and if you're not in a big hurry, then this is probably the best place to ask for help. ![List of topical help channels](/static/images/content/help_channels/topical_channels.png) @@ -29,51 +28,66 @@ Each channel on the server has a channel description which briefly describes the # General Help Channels -Our general help channels cycle quickly, with the advantage of attracting a more diverse spectrum of helpers, and getting individual attention and help for your question. These channels are a great choice for generic Python questions, but they can be used for domain-specific Python help as well. -Be sure to [ask good questions](../asking-good-questions) in order to give yourself the best chances of getting help. +Our general help channels cycle quickly, with the advantage of attracting a more diverse spectrum of helpers, and getting individual focus and attention on your question. These channels are a great choice for generic Python help, but can be used for domain-specific Python help as well. -## How To Claim a Channel +## How to Claim a Channel -There are always 3 available help channels waiting to be claimed in the **Python Help: Available** category. +There are always three help channels waiting to be claimed in the **Available Help Channels** category. ![Available help channels](/static/images/content/help_channels/available_channels.png) +*The Available Help Channels category is always at the top of the server's channel list.* -This message is posted when a channel becomes available for use: -![Channel available message](/static/images/content/help_channels/available_message.png) +![Available message](/static/images/content/help_channels/available_message.png) +*This message indicates that a channel is available.* -In order to claim one, simply start typing your question into one of these channels. Once your question is posted, you have claimed this channel it will be moved down to the **Occupied Help Channels** category. +In order to claim one, simply ask your question into one of the available channels. Be sure to [ask good questions](../asking-good-questions) in order to give yourself the best chances of getting help! -At this point you will have the **Help Cooldown** role which will remain on your profile until your help channel is closed (with the `!closed` command) or goes dormant due to inactivity. +![Channel claimed embed](/static/images/content/help_channels/claimed_channel.png) +*This messages indicates that you've claimed the channel.* -# Frequently Asked Questions +At this point you will have the **Help Cooldown** role which will remain on your profile until your help channel is closed (with the `!close` command) or goes dormant due to inactivity. This ensures that users can claim only one help channel at any given time, giving everyone a chance to have their question seen. -## Q: How long does my help channel stay active? +## Frequently Asked Questions -The channel remains open for **30 minutes** after your last message, but if another user posts in your channel, the closing will be delayed by 10 minutes. +### Q: How long does my help channel stay active? + +The channel remains open for **30 minutes** after your last message, or 10 minutes after the last message sent by another user (whichever time comes later). -*You'll see this message in your channel once it goes dormant:* ![Channel dormant message](/static/images/content/help_channels/dormant_message.png) +*You'll see this message in your channel once it goes dormant.* +### Q: No one answered my question. How come? -## Q: No one answered my question. How come? +The server has users active all over the world and all hours of the day, but some time periods are less active than others. It's also possible that the users that read your question didn't have the knowledge required to help you. If no one responded, feel free to claim another help channel a little later. -The server has users active all over the world and all hours of the day, but some days are less active than others. If no one answered your question, feel free to claim another help channel a little later. +If you feel like your question is continuously being overlooked, read our guide on [asking good questions](../asking-good-questions) to incease your chances of getting a response. -If you still feel like your question is being overlooked, read our guide on [asking good questions](../asking-good-questions) to incease your chances of getting a response. +### Q: My question was answered. What do I do? -## Q: I don't need my help channel anymore, my question was answered. What do I do? +Go ahead use the `!close` command if you've satisfactorily solved your problem. You will only be able to run this command in your own help channel, and no one (outside of staff) will be able to close your channel for you. -Go ahead and move your channel to the dormant category by running the `!closed` command. You will only be able to run this command in your own help channel, and likewise no one will be able to prematurely close your claimed help channel (with the exception of staff). +Closing your help channel once you are finished leads to less occupied channels, which means more attention can be given to other users that still need help. -## Q: Can only Helpers answer help questions? +### Q: Can only Helpers answer help questions? Definitely not! We encourage all members of the community to participate in giving help. If you'd like to help answer some questions, head over to the **Occupied Help Channels** or **Topical Chat/Help** categories. Before jumping in, please read our guide on [helping others](../helping-others) which explains our expectations for the culture and quailty of help that we aim for on the server. -## Q: I lost my help channel! +Tip: run the `!helpdm on` command in `#bot-commands` to get notified via DM with jumplinks to help channels you're participating in. + +### Q: What are the available, occupied, and dormant categories? + +The three help channels under **Available Help Channels** are free for anyone to claim. Claimed channels are then moved to **Occupied Help Channels**. Once they close, they are moved to the **Python Help: Dormant** category until they are needed again for **Available Help Channels**. + +### Q: Can I save my help session for future reference? + +Yes! Because the help channels are continuously cycled in and out without being deleted, this means you can always refer to a previous help session if you found one particularly helpful. + +Tip: reply to a message and run the `.bm` command to get bookmarks sent to you via DM for future reference. + +### Q: I lost my help channel! -No need to panic. -Your channel was probably just marked as dormant. +No need to panic. Your channel was probably just closed due to inactivity. All the dormant help channels are still available at the bottom of the channel list, in the **Python Help: Dormant** category, and also through search. If you're not sure what the name of your help channel was, you can easily find it by using the Discord Search feature. Try searching for `from:` to find the last messages sent by yourself, and from there you will be able to jump directly into the channel by pressing the Jump button on your message. diff --git a/pydis_site/static/images/content/help_channels/available_message.png b/pydis_site/static/images/content/help_channels/available_message.png index 05f6ec7d..09668c9b 100644 Binary files a/pydis_site/static/images/content/help_channels/available_message.png and b/pydis_site/static/images/content/help_channels/available_message.png differ diff --git a/pydis_site/static/images/content/help_channels/claimed_channel.png b/pydis_site/static/images/content/help_channels/claimed_channel.png new file mode 100644 index 00000000..777e31ea Binary files /dev/null and b/pydis_site/static/images/content/help_channels/claimed_channel.png differ diff --git a/pydis_site/static/images/content/help_channels/dormant_channels.png b/pydis_site/static/images/content/help_channels/dormant_channels.png index 2c53de87..7c9ba61e 100644 Binary files a/pydis_site/static/images/content/help_channels/dormant_channels.png and b/pydis_site/static/images/content/help_channels/dormant_channels.png differ diff --git a/pydis_site/static/images/content/help_channels/topical_channels.png b/pydis_site/static/images/content/help_channels/topical_channels.png index 63b48e7b..43530cbe 100644 Binary files a/pydis_site/static/images/content/help_channels/topical_channels.png and b/pydis_site/static/images/content/help_channels/topical_channels.png differ -- cgit v1.2.3 From 64723d375280365cb14ff6fe890a9627a9697bb5 Mon Sep 17 00:00:00 2001 From: minalike Date: Sun, 20 Feb 2022 17:52:46 -0500 Subject: Add table of content and final edits --- .../guides/pydis-guides/help-channel-guide.md | 34 ++++++++++------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 98b4705d..010335fd 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -6,17 +6,15 @@ relevant_links: Asking Good Questions: ../asking-good-questions Role Guide: /pages/server-info/roles Helping Others: ../helping-others +toc: 3 --- -On the 5th of April 2020, we introduced a new help channel system at Python Discord. This article is a supplementary guide to explain precisely where to go to find help. - -We have two different kinds of help channels in our community: **topical help channels** and **general help channels**. -The topical channels can be great for longer and broader discussions, whereas a general help channel might be more appropriate for specific troubleshooting. Individual topical channels may have a narrower audience than the general help channels, but that may also be to your advantage if the audience is very familiar with the area of Python you are struggling with. +At Python Discord we have two different kinds of help channels: **topical help channels** and **general help channels**. # Topical Help Channels -The topical help channels move at a slower pace than the general help channels. -They also sometimes attract domain experts. For example, `#async-and-concurrency` has CPython contributors who helped write asyncio, and in `#game-development` you can find the creators and maintainers of several game frameworks. +In topical channels, users can ask for help regarding specific domains or areas of Python. +These channels also sometimes attract domain experts. For example, `#async-and-concurrency` has CPython contributors who helped write asyncio, and in `#game-development` you can find the creators and maintainers of several game frameworks. If your question fits into the domain of one of our topical help channels, and if you're not in a big hurry, then this is probably the best place to ask for help. ![List of topical help channels](/static/images/content/help_channels/topical_channels.png) @@ -28,7 +26,7 @@ Each channel on the server has a channel description which briefly describes the # General Help Channels -Our general help channels cycle quickly, with the advantage of attracting a more diverse spectrum of helpers, and getting individual focus and attention on your question. These channels are a great choice for generic Python help, but can be used for domain-specific Python help as well. +General help channels can be used for all Python-related help, and have the advantage of attracting a more diverse spectrum of helpers, and getting individual focus and attention on your question. These channels are a great choice for generic Python help, but can be used for domain-specific Python help as well. ## How to Claim a Channel @@ -40,34 +38,34 @@ There are always three help channels waiting to be claimed in the **Available He ![Available message](/static/images/content/help_channels/available_message.png) *This message indicates that a channel is available.* -In order to claim one, simply ask your question into one of the available channels. Be sure to [ask good questions](../asking-good-questions) in order to give yourself the best chances of getting help! +In order to claim one, simply ask your question in one of the available channels. Be sure to [ask questions with enough information](../asking-good-questions) in order to give yourself the best chances of getting help! ![Channel claimed embed](/static/images/content/help_channels/claimed_channel.png) *This messages indicates that you've claimed the channel.* -At this point you will have the **Help Cooldown** role which will remain on your profile until your help channel is closed (with the `!close` command) or goes dormant due to inactivity. This ensures that users can claim only one help channel at any given time, giving everyone a chance to have their question seen. +At this point you will have the **Help Cooldown** role which will remain on your profile until you close your help channel. This ensures that users can claim only one help channel at any given time, giving everyone a chance to have their question seen. -## Frequently Asked Questions +# Frequently Asked Questions -### Q: How long does my help channel stay active? +### How long does my help channel stay active? The channel remains open for **30 minutes** after your last message, or 10 minutes after the last message sent by another user (whichever time comes later). ![Channel dormant message](/static/images/content/help_channels/dormant_message.png) *You'll see this message in your channel once it goes dormant.* -### Q: No one answered my question. How come? +### No one answered my question. How come? -The server has users active all over the world and all hours of the day, but some time periods are less active than others. It's also possible that the users that read your question didn't have the knowledge required to help you. If no one responded, feel free to claim another help channel a little later. +The server has users active all over the world and all hours of the day, but some time periods are less active than others. It's also possible that the users that read your question didn't have the knowledge required to help you. If no one responded, feel free to claim another help channel a little later, or try an appropriate topical channel. If you feel like your question is continuously being overlooked, read our guide on [asking good questions](../asking-good-questions) to incease your chances of getting a response. -### Q: My question was answered. What do I do? +### My question was answered. What do I do? Go ahead use the `!close` command if you've satisfactorily solved your problem. You will only be able to run this command in your own help channel, and no one (outside of staff) will be able to close your channel for you. Closing your help channel once you are finished leads to less occupied channels, which means more attention can be given to other users that still need help. -### Q: Can only Helpers answer help questions? +### Can only Helpers answer help questions? Definitely not! We encourage all members of the community to participate in giving help. If you'd like to help answer some questions, head over to the **Occupied Help Channels** or **Topical Chat/Help** categories. @@ -75,17 +73,17 @@ Before jumping in, please read our guide on [helping others](../helping-others) Tip: run the `!helpdm on` command in `#bot-commands` to get notified via DM with jumplinks to help channels you're participating in. -### Q: What are the available, occupied, and dormant categories? +### What are the available, occupied, and dormant categories? The three help channels under **Available Help Channels** are free for anyone to claim. Claimed channels are then moved to **Occupied Help Channels**. Once they close, they are moved to the **Python Help: Dormant** category until they are needed again for **Available Help Channels**. -### Q: Can I save my help session for future reference? +### Can I save my help session for future reference? Yes! Because the help channels are continuously cycled in and out without being deleted, this means you can always refer to a previous help session if you found one particularly helpful. Tip: reply to a message and run the `.bm` command to get bookmarks sent to you via DM for future reference. -### Q: I lost my help channel! +### I lost my help channel! No need to panic. Your channel was probably just closed due to inactivity. All the dormant help channels are still available at the bottom of the channel list, in the **Python Help: Dormant** category, and also through search. -- cgit v1.2.3 From 16a9727d414ed931cc74fa49f86a52f288399fa1 Mon Sep 17 00:00:00 2001 From: mina Date: Mon, 21 Feb 2022 15:59:45 -0500 Subject: Fixup: final wording and typo --- .../apps/content/resources/guides/pydis-guides/help-channel-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 010335fd..2be845d3 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -26,7 +26,7 @@ Each channel on the server has a channel description which briefly describes the # General Help Channels -General help channels can be used for all Python-related help, and have the advantage of attracting a more diverse spectrum of helpers, and getting individual focus and attention on your question. These channels are a great choice for generic Python help, but can be used for domain-specific Python help as well. +General help channels can be used for all Python-related help, and have the advantage of attracting a more diverse spectrum of helpers. There is also the added benefit of receiving individual focus and attention on your question. These channels are a great choice for generic Python help, but can be used for domain-specific Python help as well. ## How to Claim a Channel @@ -57,7 +57,7 @@ The channel remains open for **30 minutes** after your last message, or 10 minut The server has users active all over the world and all hours of the day, but some time periods are less active than others. It's also possible that the users that read your question didn't have the knowledge required to help you. If no one responded, feel free to claim another help channel a little later, or try an appropriate topical channel. -If you feel like your question is continuously being overlooked, read our guide on [asking good questions](../asking-good-questions) to incease your chances of getting a response. +If you feel like your question is continuously being overlooked, read our guide on [asking good questions](../asking-good-questions) to increase your chances of getting a response. ### My question was answered. What do I do? -- cgit v1.2.3 From 63fa1c03977435a2aa92325f8872e2d222d9e28a Mon Sep 17 00:00:00 2001 From: Krypton Date: Wed, 9 Mar 2022 15:42:05 +0100 Subject: Create discord-messages-with-colors.md --- .../python-guides/discord-messages-with-colors.md | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md new file mode 100644 index 00000000..60ea8656 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -0,0 +1,64 @@ +--- +title: Discord messages with colors +description: A guide on how to add colors to your codeblocks on Discord +--- + +Discord is now slowly rolling out the ability to send colored messages within code blocks. It uses the ANSI color codes, so if you've tried to print colored text in your terminal or console with Python or other languages then it will be easy for you. + +To be able to send a colored text, you need to use the `ansi` language for your code block and provide a prefix of this format before writing your text: +``` +\u001b[{format};{color}m +``` +*The `\u001b` is the unicode for ESCAPE/ESC, see .* ***If you want to use it yourself without bots, then you need to copy paste the character from the website.*** + +After you've written this, you can type and text you wish, and if you want to reset the color back to normal, then you need to use `\u001b[0m` as prefix. + +Here is the list of values you can use to replace `{format}`: + +* 0: Normal +* 1: **Bold** +* 4: Underline + +Here is the list of values you can use to replace `{color}`: + +*The following values will change the **text** color.* + +* 30: Gray +* 31: Red +* 32: Green +* 33: Yellow +* 34: Blue +* 35: Pink +* 36: Cyan +* 37: White + +*The following values will change the **text background** color.* + +* 40: Some very dark blue +* 41: Orange +* 42: Gray +* 43: Light gray +* 44: Even lighter gray +* 45: Indigo +* 46: Again some gray +* 47: White + +Let's take an example, I want a bold green colored text with the very dark blue background. +I simply use `\u001b[0;40m` (background color) and `\u001b[1;32m` (text color) as prefix. Note that the order is **important**, first you give the background color and then the text color.
+Alternatively you can also directly combine them into a single prefix like the following: `\u001b[1;40;32m` and you can also use multiple values. Something like `\u001b[1;40;4;32m` would underline the text, make it bold, make it green and have a dark blue background. + +Raw message:
+\`\`\`ansi
+\u001b[0;40m\u001b[1;32mThat's some cool formatted text right?
+or
+\u001b[1;40;32mThat's some cool formatted text right?
+\`\`\` + +Result:
+![Background and text color](https://media.discordapp.net/attachments/739937507768270939/930460020603224084/Background-Text-Color.png) + +The way the colors look like on Discord is shown in the image below ^^ + +Note: If the change as not been brought to you yet, or other users, then you can use other code blocks in the meantime to get colored text. See this gist: + +![ANSI Colors](https://media.discordapp.net/attachments/739937507768270939/930825555803263016/ANSI-Colors.png) -- cgit v1.2.3 From 934218e86b8e72ee999e7c086aa0ec7cabf08408 Mon Sep 17 00:00:00 2001 From: Krypton Date: Thu, 10 Mar 2022 10:26:23 +0100 Subject: Update discord-messages-with-colors.md --- .../resources/guides/python-guides/discord-messages-with-colors.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index 60ea8656..30f40948 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -1,5 +1,5 @@ --- -title: Discord messages with colors +title: Discord Messages with Colors description: A guide on how to add colors to your codeblocks on Discord --- @@ -57,8 +57,7 @@ or
Result:
![Background and text color](https://media.discordapp.net/attachments/739937507768270939/930460020603224084/Background-Text-Color.png) -The way the colors look like on Discord is shown in the image below ^^ +The way the colors look like on Discord is shown in the image below: +![ANSI Colors](https://media.discordapp.net/attachments/739937507768270939/930825555803263016/ANSI-Colors.png) Note: If the change as not been brought to you yet, or other users, then you can use other code blocks in the meantime to get colored text. See this gist: - -![ANSI Colors](https://media.discordapp.net/attachments/739937507768270939/930825555803263016/ANSI-Colors.png) -- cgit v1.2.3 From 40bb274538b80eacc7e2435391af9a87d90ab23d Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 13 Mar 2022 16:15:49 -0400 Subject: Preliminary structure --- .../resources/guides/pydis-guides/contributing.md | 55 ++++++++++++++++++---- 1 file changed, 46 insertions(+), 9 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 4013962c..2f4cce9d 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -4,7 +4,7 @@ description: A guide to contributing to our open source projects. icon: fab fa-github --- -Our projects on Python Discord are open source and [available on Github](https://github.com/python-discord). If you would like to contribute, consider one of the following projects: +Our projects on Python Discord are open source and [available on GitHub](https://github.com/python-discord). If you would like to contribute, consider one of the following projects:
@@ -91,14 +91,6 @@ Our projects on Python Discord are open source and [available on Github](https:/
-If you don't understand anything or need clarification, feel free to ask any staff member with the **@PyDis Core Developers** role in the server. We're always happy to help! - -### Useful Resources - -[Guidelines](./contributing-guidelines/) - General guidelines you should follow when contributing to our projects.
-[Style Guide](./style-guide/) - Information regarding the code styles you should follow when working on our projects.
-[Review Guide](../code-reviews-primer/) - A guide to get you started on doing code reviews. - ## Contributors Community We are very happy to have many members in our community that contribute to [our open source projects](https://github.com/python-discord/). Whether it's writing code, reviewing pull requests, or contributing graphics for our events, it’s great to see so many people being motivated to help out. @@ -114,3 +106,48 @@ As it’s difficult to precisely quantify contributions, we’ve come up with th - The member has a positive influence in our contributors subcommunity. The role will be assigned at the discretion of the Admin Team in consultation with the Core Developers Team. + + +# How do I start contributing? + Completing these steps will have you ready to make your first contribution. If you've already been using Git or GitHub feel free to skip those steps, but please make sure to read about the PyDis contributing process and ettiquette. If you are here looking for the answer to a specific question, check out the sub-articles in the top right of the page to see a list of our guides. + + + +### Fork the repo + GitHub is a website based on the Git version control system that stores project files in the cloud. The people working on the project can use GitHub as a central place for sending their changes, getting their teammates' changes, and communicating with each other. Forking the repository that you want to work on will create a copy under your own GitHub account. You'll make your changes to this copy, then later we can bring them back to the PyDis repository. + + [Check out our guide on forking a GitHub repo](./forking-repository/) + +### Clone the repo + Now that you have your own fork you could make changes to it directly on GitHub, but that's not a convenient way to write code. Instead you can use Git to clone the repo to your local machine, commit changes to it there, then push those changes to GitHub. + + [Check out our guide on forking a GitHub repo](./forking-repository/) + +### Set up the project + You have the source code on your local computer, but how do you actually run it? + + [Sir Lancebot](./sir-lancebot/) + + [Python Bot](./bot/) + + [Site](./site/) + +### Ettiquette + [Guidelines](./contributing-guidelines/) +### Read the style guide + [Style Guide](./style-guide/) + +### Open a pull request + +### The review process + [Review Guide](../code-reviews-primer/) +### Create an issue + + +### Learn the basics of Git + Git is a *Version Control System*, software for carefully tracking changes to the files in a project. Git allows the same project to be worked on by people in different places. You can make changes to your local code and then distribute those changes to the other people working on the project. + + [Check out these resources to get started using Git](./working-with-git/) + + +If you don't understand anything or need clarification, feel free to ask any staff member with the **@PyDis Core Developers** role in the server. We're always happy to help! -- cgit v1.2.3 From 92b1f701b3d1b159b3353db954ce06fe631e56bc Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 13 Mar 2022 16:27:45 -0400 Subject: Move Contributors role info to the Roles page --- .../resources/guides/pydis-guides/contributing.md | 17 ----------------- pydis_site/apps/content/resources/server-info/roles.md | 8 ++++++-- 2 files changed, 6 insertions(+), 19 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 2f4cce9d..596afb53 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -91,23 +91,6 @@ Our projects on Python Discord are open source and [available on GitHub](https:/ -## Contributors Community -We are very happy to have many members in our community that contribute to [our open source projects](https://github.com/python-discord/). -Whether it's writing code, reviewing pull requests, or contributing graphics for our events, it’s great to see so many people being motivated to help out. -As a token of our appreciation, those who have made significant contributions to our projects will receive a special **@Contributors** role on our server that makes them stand out from other members. -That way, they can also serve as guides to others who are looking to start contributing to our open source projects or open source in general. - -#### Guidelines for the @Contributors Role - -One question we get a lot is what the requirements for the **@Contributors** role are. -As it’s difficult to precisely quantify contributions, we’ve come up with the following guidelines for the role: - -- The member has made several significant contributions to our projects. -- The member has a positive influence in our contributors subcommunity. - -The role will be assigned at the discretion of the Admin Team in consultation with the Core Developers Team. - - # How do I start contributing? Completing these steps will have you ready to make your first contribution. If you've already been using Git or GitHub feel free to skip those steps, but please make sure to read about the PyDis contributing process and ettiquette. If you are here looking for the answer to a specific question, check out the sub-articles in the top right of the page to see a list of our guides. diff --git a/pydis_site/apps/content/resources/server-info/roles.md b/pydis_site/apps/content/resources/server-info/roles.md index 716f5b1e..d9e0af15 100644 --- a/pydis_site/apps/content/resources/server-info/roles.md +++ b/pydis_site/apps/content/resources/server-info/roles.md @@ -28,8 +28,12 @@ There are multiple requirements listed there for getting the role. This includes writing pull requests for open issues, and also for reviewing open pull requests (**we really need reviewers!**) **How to get it:** Contribute to the projects! -There is no minimum requirements, but the role is **not** assigned for every single contribution. -Read more about this in the [Guidelines for the Contributors Role](/pages/contributing/#guidelines-for-the-contributors-role) on the Contributing page. +It’s difficult to precisely quantify contributions, but we’ve come up with the following guidelines for the role: + +- The member has made several significant contributions to our projects. +- The member has a positive influence in our contributors subcommunity. + +The role will be assigned at the discretion of the Admin Team in consultation with the Core Developers Team. Check out our [walkthrough](/pages/contributing/) to get started contributing. --- -- cgit v1.2.3 From 0de454f00fd7de1991a68078eea99a3b8e7004b1 Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 13 Mar 2022 18:11:16 -0400 Subject: Remove forking and cloning sections in set-up guides --- .../guides/pydis-guides/contributing/bot.md | 27 ---------------------- .../pydis-guides/contributing/sir-lancebot.md | 19 --------------- .../guides/pydis-guides/contributing/site.md | 12 ---------- .../pydis-guides/contributing/working-with-git.md | 6 +++-- 4 files changed, 4 insertions(+), 60 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 2aa10aa3..0f783ef6 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -7,33 +7,6 @@ toc: 3 The purpose of this guide is to get you a running local version of [the Python bot](https://github.com/python-discord/bot). This page will focus on the quickest steps one can take, with mentions of alternatives afterwards. -### Clone The Repository -First things first, to run the bot's code and make changes to it, you need a local version of it (on your computer). - -
- - -
-
- -You will need to create a fork of [the project](https://github.com/python-discord/bot), and clone the fork. -Once this is done, you will have completed the first step towards having a running version of the bot. - -#### Working on the Repository Directly -If you are a member of the organisation (a member of [this list](https://github.com/orgs/python-discord/people), or in our particular case, server staff), you can clone the project repository without creating a fork, and work on a feature branch instead. - --- ### Set Up a Test Server diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index e3cd8f0c..6e5a9199 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -41,16 +41,6 @@ The requirements for Docker are: * This is only a required step for linux. Docker comes bundled with docker-compose on Mac OS and Windows. --- - -# Fork the Project -You will need your own remote (online) copy of the project repository, known as a *fork*. - -- [**Learn how to create a fork of the repository here.**](../forking-repository) - -You will do all your work in the fork rather than directly in the main repository. - ---- - # Development Environment 1. Once you have your fork, you will need to [**clone the repository to your computer**](../cloning-repository). 2. After cloning, proceed to [**install the project's dependencies**](../installing-project-dependencies). (This is not required if using Docker) @@ -121,13 +111,4 @@ After installing project dependencies use the poetry command `poetry run task st $ poetry run task start ``` ---- - -# Working with Git -Now that you have everything setup, it is finally time to make changes to the bot! If you have not yet [read the contributing guidelines](https://github.com/python-discord/sir-lancebot/blob/main/CONTRIBUTING.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. - -Notably, version control of our projects is done using Git and Github. It can be intimidating at first, so feel free to ask for any help in the server. - -[**Click here to see the basic Git workflow when contributing to one of our projects.**](../working-with-git/) - Have fun! diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index f2c3bd95..7eda027a 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -26,18 +26,6 @@ Without Docker: - [PostgreSQL](https://www.postgresql.org/download/) - Note that if you wish, the webserver can run on the host and still use Docker for PostgreSQL. ---- -# Fork the project - -You will need access to a copy of the git repository of your own that will allow you to edit the code and push your commits to. -Creating a copy of a repository under your own account is called a _fork_. - -- [Learn how to create a fork of the repository here.](../forking-repository/) - -This is where all your changes and commits will be pushed to, and from where your PRs will originate from. - -For any Core Developers, since you have write permissions already to the original repository, you can just create a feature branch to push your commits to instead. - --- # Development environment diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/working-with-git.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/working-with-git.md index 26c89b56..59c57859 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/working-with-git.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/working-with-git.md @@ -19,5 +19,7 @@ Below are links to regular workflows for working with Git using PyCharm or the C **Resources to learn Git** * [The Git Book](https://git-scm.com/book) -* [Corey Schafer's Youtube Tutorials](https://www.youtube.com/watch?v=HVsySz-h9r4&list=PL-osiE80TeTuRUfjRe54Eea17-YfnOOAx) -* [GitHub Git Resources Portal](https://try.github.io/) +* [Corey Schafer's YouTube tutorials](https://www.youtube.com/watch?v=HVsySz-h9r4&list=PL-osiE80TeTuRUfjRe54Eea17-YfnOOAx) +* [GitHub Git resources portal](https://try.github.io/) +* [Git cheatsheet](https://education.github.com/git-cheat-sheet-education.pdf) +* [Learn Git branching](https://learngitbranching.js.org) -- cgit v1.2.3 From 35081bc351bde2ee338a855d33d719d689930e1f Mon Sep 17 00:00:00 2001 From: Robin5605 Date: Mon, 14 Mar 2022 22:49:58 -0500 Subject: Migrate VPS services pin by Python bot to site --- .../resources/guides/python-guides/vps-services.md | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/vps-services.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md new file mode 100644 index 00000000..c153e876 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -0,0 +1,25 @@ +--- +title: VPS Services +description: On different VPS services +--- +If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). +This is a list of VPS services that are sufficient for running Discord bots. + +* https://www.scaleway.com/ + * Based in Europe. +* https://www.digitalocean.com/ + * US-based. + * Considered by many to be the gold standard. + * Locations available across the world. +* https://www.ovh.co.uk/ + * France and Canadian locations available. +* https://www.time4vps.eu/ + * Seemingly based in Lithuania. +* https://www.linode.com/ + * Cheap VPS. +* https://www.vultr.com/ + * US-based, DigitalOcean-like. +* https://galaxygate.net/ + * A reliable, affordable, and trusted host. + +There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi (any model, except perhaps one of the particularly less powerful ones). \ No newline at end of file -- cgit v1.2.3 From 831f56f71d76741276d13e20954f46088e754d18 Mon Sep 17 00:00:00 2001 From: Robin5605 Date: Mon, 14 Mar 2022 23:07:45 -0500 Subject: Fix end of file --- pydis_site/apps/content/resources/guides/python-guides/vps-services.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index c153e876..02feb8e6 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -22,4 +22,4 @@ This is a list of VPS services that are sufficient for running Discord bots. * https://galaxygate.net/ * A reliable, affordable, and trusted host. -There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi (any model, except perhaps one of the particularly less powerful ones). \ No newline at end of file +There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi (any model, except perhaps one of the particularly less powerful ones). -- cgit v1.2.3 From fa78e75321966e6c4180c9e844d0522a8966d155 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Fri, 18 Mar 2022 23:00:08 +0400 Subject: Add custom help command --- .../guides/python-guides/discordpy_help_command.md | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md b/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md new file mode 100644 index 00000000..f2c672af --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md @@ -0,0 +1,34 @@ +# Custom Help Command + + + +### First, a [basic walkthrough](https://gist.github.com/InterStella0/b78488fb28cadf279dfd3164b9f0cf96) by Stella#2000 on subclassing the HelpCommand will provide some foundational knowledge required before attempting a more customizable help command. + +--- + +## Custom Subclass of Help Command +### If this does not fit your needs and you require a more customizable help command, you can subclass HelpCommand and add individual command details. Below is a basic demonstration: + +```python +class MyHelpCommand(commands.HelpCommand): + async def command_callback(self, ctx, *,command=None): + if command: + await ctx.send(f"This is the help page for the command {command} ") + else: + await ctx.send("This is the front page for the bots help command") +bot.help_command = MyHelpCommand() +``` +--- +### You can handle when there is no command and make a fancy embed; a page that describes the bot and shows a list of commands is usually ideal here, however if a command is passed in, you can get display detailed information of the command with reference from the following documentations below: + +* [Get the command object](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot.get_command) + +* [Get the command name](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.name) + +* [Get the command aliases](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.aliases) + +* [Get the command brief](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.brief) + +* [Get the command usage](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.usage) + +* Get the command cooldown - `command_object._buckets._cooldown.per.` -- cgit v1.2.3 From 939aa26d0b2788b84b35e434cfefa287b28b3428 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Sat, 19 Mar 2022 17:03:55 +0400 Subject: Add custom help command --- .../resources/guides/python-guides/discordpy_help_command.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md b/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md index f2c672af..58d75918 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md @@ -1,13 +1,17 @@ -# Custom Help Command +--- +title: Custom Help Command +description: "Overwrite discord.py's help command to implement custom functionality" +--- +# Custom Help Command -### First, a [basic walkthrough](https://gist.github.com/InterStella0/b78488fb28cadf279dfd3164b9f0cf96) by Stella#2000 on subclassing the HelpCommand will provide some foundational knowledge required before attempting a more customizable help command. + First, a [basic walkthrough](https://gist.github.com/InterStella0/b78488fb28cadf279dfd3164b9f0cf96) by Stella#2000 on subclassing the HelpCommand will provide some foundational knowledge required before attempting a more customizable help command. --- ## Custom Subclass of Help Command -### If this does not fit your needs and you require a more customizable help command, you can subclass HelpCommand and add individual command details. Below is a basic demonstration: +If this does not fit your needs and you require a more customizable help command, you can subclass HelpCommand and add individual command details. Below is a basic demonstration: ```python class MyHelpCommand(commands.HelpCommand): @@ -19,7 +23,7 @@ class MyHelpCommand(commands.HelpCommand): bot.help_command = MyHelpCommand() ``` --- -### You can handle when there is no command and make a fancy embed; a page that describes the bot and shows a list of commands is usually ideal here, however if a command is passed in, you can get display detailed information of the command with reference from the following documentations below: +You can handle when there is no command and make a fancy embed; a page that describes the bot and shows a list of commands is usually ideal here, however if a command is passed in, you can get display detailed information of the command with reference from the following documentations below: * [Get the command object](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot.get_command) -- cgit v1.2.3 From 36b43f94cb1f8c622914048696efec8ccdeb608f Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sat, 19 Mar 2022 23:42:45 -0400 Subject: Add guide for pull requests and reviews This covers the GitHub UI for opening a pull request, getting it reviewed, and draft PRs. --- .../pydis-guides/contributing/pull-requests.md | 41 +++++++++++++++++++++ .../images/content/contributing/pull_request.png | Bin 0 -> 10190 bytes 2 files changed, 41 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md create mode 100644 pydis_site/static/images/content/contributing/pull_request.png (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md new file mode 100644 index 00000000..f7dee491 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md @@ -0,0 +1,41 @@ +--- +title: Pull Requests +description: A guide for opening pull requests. +--- + +As stated in our [Contributing Guidelines](../contributing-guidelines/), do not open a pull request if you aren't assigned to an approved issue. You can check out our [Issues Guide](../issues/) for help with opening an issue or getting assigned to an existing one. +{: .notification .is-warning } + + +Before opening a pull request you should have: + +1. Committed your changes to your local repository +2. [Linted](../contributing-guidelines/#linting-and-pre-commit) your code +3. Tested your changes +4. Pushed the branch to your fork of the project on GitHub + +## Opening a Pull Request + +Navigate to your fork on GitHub and make sure you're on the branch with your changes. Click on `Contribute` and then `Open pull request`. + +![Pull Request UI](/static/images/content/contributing/pull_request.png) + +In the page that it opened, write an overview of the changes you made and why. This should explain how you resolved the issue that spawned this PR and highlight any differences from the proposed implementation. You should also [link the issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue). + +At this stage you can also request reviews from individual contributors. If someone showed interest in the issue or has specific knowledge about it, they may be a good reviewer. It isn't necessary to request your reviewers; someone will review your PR either way. + +## The Review Process + +Before your changes are merged, your PR needs to be reviewed by other contributors. They will read the issue and your description of your PR, look at your code, test it, and then leave comments on the PR if they find any problems, possibly with suggested changes. Sometimes this can feel intrusive or insulting, but remember that the reviewers are there to help you make your code better. + +#### If the PR is already open, how do I make changes to it? + +A pull request is between a source branch and a target branch. Updating the source branch with new commits will automatically update the PR to include those commits; they'll even show up in the comment thread of the PR. Sometimes for small changes the reviewer will even write the suggested code themself, in which case you can simply accept them with the click of a button. + +If you truly disagree with a reviewer's suggestion, leave a reply in the thread explaining why or proposing an alternative change. Also feel free to ask questions if you want clarification about suggested changes or just want to discuss them further. + +## Draft Pull Requests + +GitHub [provides a PR feature](https://github.blog/2019-02-14-introducing-draft-pull-requests/) that allows the PR author to mark it as a draft when opening it. This provides both a visual and functional indicator that the contents of the PR are in a draft state and not yet ready for formal review. This is helpful when you want people to see the changes you're making before you're ready for the final pull request. + +This feature should be utilized in place of the traditional method of prepending `[WIP]` to the PR title. diff --git a/pydis_site/static/images/content/contributing/pull_request.png b/pydis_site/static/images/content/contributing/pull_request.png new file mode 100644 index 00000000..87b7ffbe Binary files /dev/null and b/pydis_site/static/images/content/contributing/pull_request.png differ -- cgit v1.2.3 From d198b3e02236e65bc2d8fceb9d7d8776dc306b87 Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 20 Mar 2022 14:56:05 -0400 Subject: Split up Supplemental Info and touch up Contrib Guidelines Created new pages: * Linting * Logging * Writing Good Commit Messages Moved Draft PR section to new pull requests guide Moved type hinting section to style guide --- .../contributing/contributing-guidelines.md | 25 +++--- .../contributing-guidelines/commit-messages.md | 15 ++++ .../supplemental-information.md | 99 ---------------------- .../guides/pydis-guides/contributing/linting.md | 14 +++ .../guides/pydis-guides/contributing/logging.md | 31 +++++++ .../pydis-guides/contributing/pull-requests.md | 2 +- .../pydis-guides/contributing/style-guide.md | 24 +++--- 7 files changed, 82 insertions(+), 128 deletions(-) create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md delete mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/logging.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md index de1777f2..f13b05be 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md @@ -4,22 +4,15 @@ description: Guidelines to adhere to when contributing to our projects. --- Thank you for your interest in our projects! +This page contains the golden rules to follow when contributing. If you have questions about how to get started contributing, check out our [in-depth walkthrough](../../contributing/). -If you are interested in contributing, **this page contains the golden rules to follow when contributing.** -Supplemental information [can be found here](./supplemental-information/). -Do note that failing to comply with our guidelines may lead to a rejection of the contribution. - -If you are confused by any of these rules, feel free to ask us in the `#dev-contrib` channel in our [Discord server.](https://discord.gg/python) - -# The Golden Rules of Contributing - -1. **Lint before you push.** We have simple but strict style rules that are enforced through linting. -You must always lint your code before committing or pushing. -[Using tools](./supplemental-information/#linting-and-pre-commit) such as `flake8` and `pre-commit` can make this easier. -Make sure to follow our [style guide](../style-guide/) when contributing. +1. **Lint before you push.** +We have simple but strict style rules that are enforced through linting. +[Set up a pre-commit hook](../linting/) to lint your code when you commit it. +Not all of the style rules are enforced by linting, so make sure to read the [style guide](../style-guide/) as well. 2. **Make great commits.** Great commits should be atomic, with a commit message explaining what and why. -More on that can be found in [this section](./supplemental-information/#writing-good-commit-messages). +Check out [Writing Good Commit Messages](/commit-messages) for details. 3. **Do not open a pull request if you aren't assigned to the issue.** If someone is already working on it, consider offering to collaborate with that person. 4. **Use assets licensed for public use.** @@ -28,4 +21,8 @@ Whenever the assets are images, audio or even code, they must have a license com We aim to foster a welcoming and friendly environment on our open source projects. We take violations of our Code of Conduct very seriously, and may respond with moderator action. -Welcome to our projects! +
+ +Failing to comply with our guidelines may lead to a rejection of the contribution. +If you have questions about any of the rules, feel free to ask us in the `#dev-contrib` channel in our [Discord server](https://discord.gg/python). +{: .notification .is-warning } diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md new file mode 100644 index 00000000..ba476b65 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md @@ -0,0 +1,15 @@ +--- +title: Writing Good Commit Messages +description: Information about logging in our projects. +--- + +A well-structured git log is key to a project's maintainability; it provides insight into when and *why* things were done for future maintainers of the project. + +Commits should be as narrow in scope as possible. +Commits that span hundreds of lines across multiple unrelated functions and/or files are very hard for maintainers to follow. +After about a week they'll probably be hard for you to follow, too. + +Please also avoid making minor commits for fixing typos or linting errors. +[Don’t forget to lint before you push!](https://soundcloud.com/lemonsaurusrex/lint-before-you-push) + +A more in-depth guide to writing great commit messages can be found in Chris Beam's [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/). diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md deleted file mode 100644 index e64e4fc6..00000000 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/supplemental-information.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Supplemental Information -description: Additional information related to our contributing guidelines. ---- - -This page contains additional information concerning a specific part of our development pipeline. - -## Writing Good Commit Messages - -A well-structured git log is key to a project's maintainability; it provides insight into when and *why* things were done for future maintainers of the project. - -Commits should be as narrow in scope as possible. -Commits that span hundreds of lines across multiple unrelated functions and/or files are very hard for maintainers to follow. -After about a week they'll probably be hard for you to follow, too. - -Please also avoid making minor commits for fixing typos or linting errors. -*[Don’t forget to lint before you push!](https://soundcloud.com/lemonsaurusrex/lint-before-you-push)* - -A more in-depth guide to writing great commit messages can be found in Chris Beam's *[How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/).* - -## Code Style - -All of our projects have a certain project-wide style that contributions should attempt to maintain consistency with. -During PR review, it's not unusual for style adjustments to be requested. - -[This page](../../style-guide/) will reference the differences between our projects and what is recommended by [PEP 8.](https://www.python.org/dev/peps/pep-0008/) - -## Linting and Pre-commit - -On most of our projects, we use `flake8` and `pre-commit` to ensure that the code style is consistent across the code base. - -Running `flake8` will warn you about any potential style errors in your contribution. -You must always check it **before pushing**. -Your commit will be rejected by the build server if it fails to lint. - -**Some style rules are not enforced by flake8. Make sure to read the [style guide](../../style-guide/).** - -`pre-commit` is a powerful tool that helps you automatically lint before you commit. -If the linter complains, the commit is aborted so that you can fix the linting errors before committing again. -That way, you never commit the problematic code in the first place! - -Please refer to the project-specific documentation to see how to setup and run those tools. -In most cases, you can install pre-commit using `poetry run task precommit`, and lint using `poetry run task lint`. - -## Type Hinting - -[PEP 484](https://www.python.org/dev/peps/pep-0484/) formally specifies type hints for Python functions, added to the Python Standard Library in version 3.5. -Type hints are recognized by most modern code editing tools and provide useful insight into both the input and output types of a function, preventing the user from having to go through the codebase to determine these types. - -For example: - -```python -import typing - -def foo(input_1: int, input_2: typing.Dict[str, str]) -> bool: - ... -``` - -This tells us that `foo` accepts an `int` and a `dict`, with `str` keys and values, and returns a `bool`. - -If the project is running Python 3.9 or above, you can use `dict` instead of `typing.Dict`. -See [PEP 585](https://www.python.org/dev/peps/pep-0585/) for more information. - -All function declarations should be type hinted in code contributed to the PyDis organization. - -## Logging - -Instead of using `print` statements for logging, we use the built-in [`logging`](https://docs.python.org/3/library/logging.html) module. -Here is an example usage: - -```python -import logging - -log = logging.getLogger(__name__) # Get a logger bound to the module name. -# This line is usually placed under the import statements at the top of the file. - -log.trace("This is a trace log.") -log.warning("BEEP! This is a warning.") -log.critical("It is about to go down!") -``` - -Print statements should be avoided when possible. -Our projects currently defines logging levels as follows, from lowest to highest severity: - -- **TRACE:** These events should be used to provide a *verbose* trace of every step of a complex process. This is essentially the `logging` equivalent of sprinkling `print` statements throughout the code. -- **Note:** This is a PyDis-implemented logging level. It may not be available on every project. -- **DEBUG:** These events should add context to what's happening in a development setup to make it easier to follow what's going while workig on a project. This is in the same vein as **TRACE** logging but at a much lower level of verbosity. -- **INFO:** These events are normal and don't need direct attention but are worth keeping track of in production, like checking which cogs were loaded during a start-up. -- **WARNING:** These events are out of the ordinary and should be fixed, but can cause a failure. -- **ERROR:** These events can cause a failure in a specific part of the application and require urgent attention. -- **CRITICAL:** These events can cause the whole application to fail and require immediate intervention. - -Any logging above the **INFO** level will trigger a [Sentry](https://sentry.io) issue and alert the Core Developer team. - -## Draft Pull Requests - -Github [provides a PR feature](https://github.blog/2019-02-14-introducing-draft-pull-requests/) that allows the PR author to mark it as a Draft when opening it. This provides both a visual and functional indicator that the contents of the PR are in a draft state and not yet ready for formal review. - -This feature should be utilized in place of the traditional method of prepending `[WIP]` to the PR title. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md new file mode 100644 index 00000000..48f1cafc --- /dev/null +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md @@ -0,0 +1,14 @@ +--- +title: Linting +description: A guide for linting and setting up pre-commit. +--- + +Your commit will be rejected by the build server if it fails to lint. +On most of our projects, we use `flake8` and `pre-commit` to ensure that the code style is consistent across the code base. + +`pre-commit` is a powerful tool that helps you automatically lint before you commit. +If the linter complains, the commit is aborted so that you can fix the linting errors before committing again. +That way, you never commit the problematic code in the first place! + +Please refer to the project-specific documentation to see how to setup and run those tools. +In most cases, you can install pre-commit using `poetry run task precommit`, and lint using `poetry run task lint`. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/logging.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/logging.md new file mode 100644 index 00000000..1291a7a4 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/logging.md @@ -0,0 +1,31 @@ +--- +title: Logging +description: Information about logging in our projects. +--- + +Instead of using `print` statements for logging, we use the built-in [`logging`](https://docs.python.org/3/library/logging.html) module. +Here is an example usage: + +```python +import logging + +log = logging.getLogger(__name__) # Get a logger bound to the module name. +# This line is usually placed under the import statements at the top of the file. + +log.trace("This is a trace log.") +log.warning("BEEP! This is a warning.") +log.critical("It is about to go down!") +``` + +Print statements should be avoided when possible. +Our projects currently defines logging levels as follows, from lowest to highest severity: + +- **TRACE:** These events should be used to provide a *verbose* trace of every step of a complex process. This is essentially the `logging` equivalent of sprinkling `print` statements throughout the code. +- **Note:** This is a PyDis-implemented logging level. It may not be available on every project. +- **DEBUG:** These events should add context to what's happening in a development setup to make it easier to follow what's going while workig on a project. This is in the same vein as **TRACE** logging but at a much lower level of verbosity. +- **INFO:** These events are normal and don't need direct attention but are worth keeping track of in production, like checking which cogs were loaded during a start-up. +- **WARNING:** These events are out of the ordinary and should be fixed, but can cause a failure. +- **ERROR:** These events can cause a failure in a specific part of the application and require urgent attention. +- **CRITICAL:** These events can cause the whole application to fail and require immediate intervention. + +Any logging above the **INFO** level will trigger a [Sentry](https://sentry.io) issue and alert the Core Developer team. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md index f7dee491..a9b6385e 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/pull-requests.md @@ -10,7 +10,7 @@ As stated in our [Contributing Guidelines](../contributing-guidelines/), do not Before opening a pull request you should have: 1. Committed your changes to your local repository -2. [Linted](../contributing-guidelines/#linting-and-pre-commit) your code +2. [Linted](../linting/) your code 3. Tested your changes 4. Pushed the branch to your fork of the project on GitHub diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md index f9962990..4dba45c8 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md @@ -191,21 +191,17 @@ Present tense defines that the work being done is now, in the present, rather th **Use:** "Build an information embed."
**Don't use:** "Built an information embed." or "Will build an information embed." -# Type Annotations -Functions are required to have type annotations as per the style defined in [PEP 484](https://www.python.org/dev/peps/pep-0484/). +# Type Hinting +Functions are required to have type annotations as per the style defined in [PEP 484](https://www.python.org/dev/peps/pep-0484/). Type hints are recognized by most modern code editing tools and provide useful insight into both the input and output types of a function, preventing the user from having to go through the codebase to determine these types. -A function without annotations might look like: -```py -def divide(a, b): - """Divide the two given arguments.""" - return a / b -``` - -With annotations, the arguments and the function are annotated with their respective types: -```py -def divide(a: int, b: int) -> float: - """Divide the two given arguments.""" - return a / b +A function with type hints looks like: +```python +def foo(input_1: int, input_2: dict[str, int]) -> bool: + ... ``` +This tells us that `foo` accepts an `int` and a `dict`, with `str` keys and `int` values, and returns a `bool`. In previous examples, we have purposely omitted annotations to keep focus on the specific points they represent. + +> **Note:** if the project is running Python 3.8 or below you have to use `typing.Dict` instead of `dict`, but our three main projects are all >=3.9. +> See [PEP 585](https://www.python.org/dev/peps/pep-0585/) for more information. -- cgit v1.2.3 From 79694efe7bb13a9d6791844e7a836b7f4350308d Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 20 Mar 2022 17:08:08 -0400 Subject: Write walkthrough --- .../resources/guides/pydis-guides/contributing.md | 60 +++++++++++++--------- 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 596afb53..759ed1dc 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -92,45 +92,57 @@ Our projects on Python Discord are open source and [available on GitHub](https:/ # How do I start contributing? - Completing these steps will have you ready to make your first contribution. If you've already been using Git or GitHub feel free to skip those steps, but please make sure to read about the PyDis contributing process and ettiquette. If you are here looking for the answer to a specific question, check out the sub-articles in the top right of the page to see a list of our guides. + Unsure of what contributing to open source projects involves? Have questions about how to use GitHub? Just need to know about our contribution etiquette? Completing these steps will have you ready to make your first contribution. + Feel free to skip any steps you're already familiar with, but please make sure not to miss the [Contributing Guidelines](#5-read-our-contributing-guidelines). + If you are here looking for the answer to a specific question, check out the sub-articles in the top right of the page to see a list of our guides. -### Fork the repo - GitHub is a website based on the Git version control system that stores project files in the cloud. The people working on the project can use GitHub as a central place for sending their changes, getting their teammates' changes, and communicating with each other. Forking the repository that you want to work on will create a copy under your own GitHub account. You'll make your changes to this copy, then later we can bring them back to the PyDis repository. +### 1. Learn the basics of Git + Git is a _Version Control System_, software for carefully tracking changes to the files in a project. Git allows the same project to be worked on by people in different places. You can make changes to your local code and then distribute those changes to the other people working on the project. - [Check out our guide on forking a GitHub repo](./forking-repository/) + Check out these [**resources to get started using Git**](./working-with-git/). -### Clone the repo - Now that you have your own fork you could make changes to it directly on GitHub, but that's not a convenient way to write code. Instead you can use Git to clone the repo to your local machine, commit changes to it there, then push those changes to GitHub. +### 2. Fork the repo + GitHub is a website based on the Git version control system that stores project files in the cloud. The people working on the project can use GitHub as a central place for sending their changes, getting their teammates' changes, and communicating with each other. Forking the repository that you want to work on will create a copy under your own GitHub account. You'll make your changes to this copy, then later we can bring them back to the PyDis repository. - [Check out our guide on forking a GitHub repo](./forking-repository/) + Check out our [**guide on forking a GitHub repo**](./forking-repository/). -### Set up the project - You have the source code on your local computer, but how do you actually run it? +### 3. Clone the repo + Now that you have your own fork you need to be able to make changes to the code. You can clone the repo to your local machine, commit changes to it there, then push those changes to GitHub. - [Sir Lancebot](./sir-lancebot/) + Check out our [**guide on cloning a GitHub repo**](./cloning-repository/). - [Python Bot](./bot/) +### 4. Set up the project + You have the source code on your local computer, now how do you actually run it? We have detailed guides on setting up the environment for each of our projects: - [Site](./site/) + * [**Sir Lancebot**](./sir-lancebot/) -### Ettiquette - [Guidelines](./contributing-guidelines/) -### Read the style guide - [Style Guide](./style-guide/) + * [**Python Bot**](./bot/) -### Open a pull request + * [**Site**](./site/) -### The review process - [Review Guide](../code-reviews-primer/) -### Create an issue +### 5. Read our Contributing Guidelines + We have a few short rules that all contributors must follow. Make sure you read and follow them while working on our projects. + [**Contributing Guidelines**](./contributing-guidelines/). -### Learn the basics of Git - Git is a *Version Control System*, software for carefully tracking changes to the files in a project. Git allows the same project to be worked on by people in different places. You can make changes to your local code and then distribute those changes to the other people working on the project. + As mentioned in the Contributing Guidelines, we have a simple style guide for our projects based on PEP 8. Give it a read to keep your code consistent with the rest of the codebase. - [Check out these resources to get started using Git](./working-with-git/) + [**Style Guide**](./style-guide/) +### 6. Create an issue + The first step to any new contribution is an issue describing a problem with the current codebase or proposing a new feature. All the open issues are viewable on the GitHub repositories, for instance here is the [issues page for Sir Lancebot](https://github.com/python-discord/sir-lancebot/issues). If you have an idea that you want to implement, open a new issue (and check out our [**guide on writing an issue**](./issues/)). Otherwise you can browse the unassigned issues and ask to be assigned to one that you're interested in, either in the comments on the issue or in the`#dev-contrib`channel on Discord. -If you don't understand anything or need clarification, feel free to ask any staff member with the **@PyDis Core Developers** role in the server. We're always happy to help! + Don't move forward until your issue is approved by a Core Developer. Issues are not guaranteed to be approved so your work may be wasted. + {: .notification .is-warning } + +### 7. Open a pull request + After your issue has been approved and you've written your code and tested it, it's time to open a pull request. Pull requests are a feature in GitHub; you can think of them as asking the project maintainers to accept your changes. This gives other contributors a chance to review your code and make any needed changes before it's merged into the main branch of the project. + + Check out our [**Pull Request Guide**](./contributing/pull-requests/) for help with opening a pull request and going through the review process. + + Check out our [**Code Review Guide**](../code-reviews-primer/) to learn how to be a star reviewer. Reviewing PRs is a vital part of open source development, and we always need more reviewers! + +### That's it! +Thank you for contributing to our community projects. If you don't understand anything or need clarification, feel free to ask a question in the`dev-contrib`channel and keep an eye out for staff members with the **@PyDis Core Developers** role in the server. We're always happy to help! -- cgit v1.2.3 From e76e0a5f2d80a4f5ec31fe015155b0349f9f607b Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 20 Mar 2022 18:55:16 -0400 Subject: Fix PR page link --- pydis_site/apps/content/resources/guides/pydis-guides/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 759ed1dc..51991d9c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -140,7 +140,7 @@ Our projects on Python Discord are open source and [available on GitHub](https:/ ### 7. Open a pull request After your issue has been approved and you've written your code and tested it, it's time to open a pull request. Pull requests are a feature in GitHub; you can think of them as asking the project maintainers to accept your changes. This gives other contributors a chance to review your code and make any needed changes before it's merged into the main branch of the project. - Check out our [**Pull Request Guide**](./contributing/pull-requests/) for help with opening a pull request and going through the review process. + Check out our [**Pull Request Guide**](./pull-requests/) for help with opening a pull request and going through the review process. Check out our [**Code Review Guide**](../code-reviews-primer/) to learn how to be a star reviewer. Reviewing PRs is a vital part of open source development, and we always need more reviewers! -- cgit v1.2.3 From 506ac4281dd150eefc4864a00838ac97aa71f14f Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:15:50 -0500 Subject: Add hyperlinks Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> --- .../content/resources/guides/python-guides/vps-services.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index 02feb8e6..07e70e9a 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -5,21 +5,21 @@ description: On different VPS services If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). This is a list of VPS services that are sufficient for running Discord bots. -* https://www.scaleway.com/ +* [https://www.scaleway.com](https://www.scaleway.com) * Based in Europe. -* https://www.digitalocean.com/ +* [https://www.digitalocean.com](https://www.digitalocean.com) * US-based. * Considered by many to be the gold standard. * Locations available across the world. -* https://www.ovh.co.uk/ +* [https://www.ovh.co.uk](https://www.ovh.co.uk) * France and Canadian locations available. -* https://www.time4vps.eu/ +* [https://www.time4vps.eu](https://www.time4vps.eu) * Seemingly based in Lithuania. -* https://www.linode.com/ +* [https://www.linode.com](https://www.linode.com) * Cheap VPS. -* https://www.vultr.com/ +* [https://www.vultr.com](https://www.vultr.com) * US-based, DigitalOcean-like. -* https://galaxygate.net/ +* [https://galaxygate.net](https://galaxygate.net) * A reliable, affordable, and trusted host. There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi (any model, except perhaps one of the particularly less powerful ones). -- cgit v1.2.3 From cf8ce93e34ab543fdc9e4df83aa4583128c2ddc0 Mon Sep 17 00:00:00 2001 From: Shom770 <82843611+Shom770@users.noreply.github.com> Date: Mon, 21 Mar 2022 18:42:04 -0400 Subject: add token safety pin --- .../guides/python-guides/keeping-tokens-safe.md | 21 +++++++++++++++++++++ .../resources/guides/python-guides/token-reset.png | Bin 0 -> 132625 bytes 2 files changed, 21 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md create mode 100644 pydis_site/apps/content/resources/guides/python-guides/token-reset.png (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md new file mode 100644 index 00000000..8e283d70 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md @@ -0,0 +1,21 @@ +--- +title: Keeping Discord Bot Tokens Safe +description: How to keep your bot tokens safe and safety measures you can take. +--- +It's **very** important to keep a bot token safe, primarily because anyone who has the bot token can do whatever they want with the bot -- such as destroying servers your bot has been added to and getting your bot banned from the API. + +# How to Avoid Leaking your Token +To help prevent leaking your token, you should ensure that you don't upload it to an open source program/website, such as replit and github, as they show your code publicly. The best practice for storing tokens is generally utilising .env files ([click here](https://vcokltfre.dev/tips/tokens/.) for more information on storing tokens safely) + +# What should I do if my token does get leaked? + +If for whatever reason your token gets leaked, you should immediately follow these steps: +- Go to the list of [Discord Bot Applications](https://discord.com/developers/applications) you have and select the bot application that had the token leaked. +- Select the Bot (1) tab on the left-hand side, next to a small image of a puzzle piece. After doing so you should see a small section named TOKEN (under your bot USERNAME and next to his avatar image) +- Press the Regenerate (2) option to regen your bot token. +![token_reset.png](token-reset.png) + +Following these steps will create a new token for your bot, making it secure again and terminating any connections from the leaked token. + +# Summary +Make sure you keep your token secure by storing it safely, not sending it to anyone you don't trust, and regenerating your token if it does get leaked. \ No newline at end of file diff --git a/pydis_site/apps/content/resources/guides/python-guides/token-reset.png b/pydis_site/apps/content/resources/guides/python-guides/token-reset.png new file mode 100644 index 00000000..bd672b93 Binary files /dev/null and b/pydis_site/apps/content/resources/guides/python-guides/token-reset.png differ -- cgit v1.2.3 From 9ba4891e6e47f7f498eafa61e4a1d5e301f2426a Mon Sep 17 00:00:00 2001 From: Shom770 <82843611+Shom770@users.noreply.github.com> Date: Mon, 21 Mar 2022 18:59:26 -0400 Subject: fixing image not appearing --- .../guides/python-guides/keeping-tokens-safe.md | 3 ++- .../resources/guides/python-guides/token-reset.png | Bin 132625 -> 0 bytes 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 pydis_site/apps/content/resources/guides/python-guides/token-reset.png (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md index 8e283d70..e37039d1 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md +++ b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md @@ -13,7 +13,8 @@ If for whatever reason your token gets leaked, you should immediately follow the - Go to the list of [Discord Bot Applications](https://discord.com/developers/applications) you have and select the bot application that had the token leaked. - Select the Bot (1) tab on the left-hand side, next to a small image of a puzzle piece. After doing so you should see a small section named TOKEN (under your bot USERNAME and next to his avatar image) - Press the Regenerate (2) option to regen your bot token. -![token_reset.png](token-reset.png) + +![Steps to Take to Reset your Discord Bot](https://cdn.discordapp.com/attachments/343944376055103488/845290595793764392/regen_token.png) Following these steps will create a new token for your bot, making it secure again and terminating any connections from the leaked token. diff --git a/pydis_site/apps/content/resources/guides/python-guides/token-reset.png b/pydis_site/apps/content/resources/guides/python-guides/token-reset.png deleted file mode 100644 index bd672b93..00000000 Binary files a/pydis_site/apps/content/resources/guides/python-guides/token-reset.png and /dev/null differ -- cgit v1.2.3 From 45d13700c5421d056e89797c77f7730419300242 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:02:03 +0400 Subject: Add custom help command --- .../resources/guides/python-guides/discordpy_help_command.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md b/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md index 58d75918..39a45063 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md @@ -3,9 +3,6 @@ title: Custom Help Command description: "Overwrite discord.py's help command to implement custom functionality" --- -# Custom Help Command - - First, a [basic walkthrough](https://gist.github.com/InterStella0/b78488fb28cadf279dfd3164b9f0cf96) by Stella#2000 on subclassing the HelpCommand will provide some foundational knowledge required before attempting a more customizable help command. --- @@ -23,7 +20,7 @@ class MyHelpCommand(commands.HelpCommand): bot.help_command = MyHelpCommand() ``` --- -You can handle when there is no command and make a fancy embed; a page that describes the bot and shows a list of commands is usually ideal here, however if a command is passed in, you can get display detailed information of the command with reference from the following documentations below: +You can handle when a user does not pass a command name when invoking the help command and make a fancy and customized embed; here a page that describes the bot and shows a list of commands is generally used, however if a command is passed in, you can display detailed information of the command. Below are references from the documentation below that can be utilised: * [Get the command object](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot.get_command) @@ -35,4 +32,4 @@ You can handle when there is no command and make a fancy embed; a page that des * [Get the command usage](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.usage) -* Get the command cooldown - `command_object._buckets._cooldown.per.` +* Get the command cooldown - `command_object._buckets._cooldown.per` -- cgit v1.2.3 From 00a17a53c542b6de263691219c38438393d9f806 Mon Sep 17 00:00:00 2001 From: Robin5605 Date: Tue, 22 Mar 2022 12:33:13 -0500 Subject: Update VPS services content --- .../resources/guides/python-guides/vps-services.md | 53 +++++++++++++--------- 1 file changed, 32 insertions(+), 21 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index 07e70e9a..4dfca732 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -1,25 +1,36 @@ --- -title: VPS Services -description: On different VPS services + title: VPS Services + description: On different VPS services --- -If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). -This is a list of VPS services that are sufficient for running Discord bots. -* [https://www.scaleway.com](https://www.scaleway.com) - * Based in Europe. -* [https://www.digitalocean.com](https://www.digitalocean.com) - * US-based. - * Considered by many to be the gold standard. - * Locations available across the world. -* [https://www.ovh.co.uk](https://www.ovh.co.uk) - * France and Canadian locations available. -* [https://www.time4vps.eu](https://www.time4vps.eu) - * Seemingly based in Lithuania. -* [https://www.linode.com](https://www.linode.com) - * Cheap VPS. -* [https://www.vultr.com](https://www.vultr.com) - * US-based, DigitalOcean-like. -* [https://galaxygate.net](https://galaxygate.net) - * A reliable, affordable, and trusted host. +If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS).This is a list of VPS services that are sufficient for running Discord bots. + +* Europe + * [netcup](https://www.netcup.eu/) + * Germany & Austria data centres. + * Great affiliate program. + * [Yandex Cloud](https://cloud.yandex.ru/) + * Vladimir, Ryazan, and Moscow region data centres. + * [Scaleway](https://www.scaleway.com/) + * France data centre. + * [Time 4 VPS](https://www.time4vps.eu/) + * Lithuania data centre. +* US + * [GalaxyGate](https://galaxygate.net/) + * New York data centre. + * Great affiliate program. +* Global + * [Linode](https://www.linode.com/) + * Global data centre options. + * [Digital Ocean](https://www.digitalocean.com/) + * Global data centre options. + * [OVHcloud](https://www.ovhcloud.com/) + * Global data centre options. + * [Vultr](https://www.vultr.com/) + * Global data centre options. + +--- +Free hosts +There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. +Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi. -There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi (any model, except perhaps one of the particularly less powerful ones). -- cgit v1.2.3 From aedf67e6f141288f1f8b00bbd0e46cae1eb16a6c Mon Sep 17 00:00:00 2001 From: Robin5605 Date: Tue, 22 Mar 2022 14:22:27 -0500 Subject: Fix EOF --- pydis_site/apps/content/resources/guides/python-guides/vps-services.md | 1 - 1 file changed, 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index 4dfca732..95951134 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -33,4 +33,3 @@ If you need to run your bot 24/7 (with no downtime), you should consider using a Free hosts There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi. - -- cgit v1.2.3 From 682613bcf56ea6aefac8b15b56064a16732894a4 Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Tue, 22 Mar 2022 23:51:36 -0500 Subject: Remove starting whitespaces Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/vps-services.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index 95951134..90306057 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -1,6 +1,6 @@ --- - title: VPS Services - description: On different VPS services +title: VPS Services +description: On different VPS services --- If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS).This is a list of VPS services that are sufficient for running Discord bots. -- cgit v1.2.3 From 50d6efdb1c452f1265cec83a76e8ab631d37ba22 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Wed, 23 Mar 2022 10:31:12 +0400 Subject: Add documentation on subclassing bot --- .../guides/python-guides/subclassing_bot.md | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md new file mode 100644 index 00000000..f22f98f5 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -0,0 +1,51 @@ +--- +title: Subclassing Bot +description: "Subclassing the Bot to add more functionability and customisability." +--- + +## Basic Subclassing +First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [Bot](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. + +## The benefits of subclassing bot +Subclassing Bot can be very beneficial as it provides you with more control and customisability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be overriden to add more functionality. + +There are two ways to subclass `commands.Bot`, as shown below: +```py +class CustomBot(commands.Bot): + def __init__(self): + super().__init__( + command_prefix = #your prefix here as a string + intents = #your intents here + #other kwargs can be put here + ) + #custom bot attributes can be set here, for example: + self.db = self.loop.run_until_complete(aiosqlite.connect("Your database file name")) + self.launch_time = datetime.datetime.utcnow() + self.example_integer = 5 + +bot = CustomBot() +``` +Or +```py +class CustomBot(commands.Bot): + def __init__(self, *args, **kwargs): #the key-word arguments are not specified here, unlike the example above + + super().__init__(*args, **kwargs) + #custom bot attributes can be set here, for example: + self.example_string = 'This is an example!' + + #You can add a custom bot method, anyhting can be done in this function. This is an example: + def hello(self): + return 'Hello World' + +#Here you set the *args and **kwargs +bot = CustomBot(command_prefix="!", intents=discord.Intents.default()) + +@bot.command() +async def example(ctx): + print(bot.hello()) + # In this case, this will print Hello World! +``` +With either of the above examples, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. + +To access the custom bot attributes set in the subclass, in the main bot file (in the context of the above example), `bot.variable_name` would be used, and as for cogs, it would be `self.bot.variable_name`. For the custom methods set, in the main file it would be `bot.custom_method()` in the main file and `self.bot.custom_method()` in a cog file. -- cgit v1.2.3 From 80d87b861ae585222bc09cc8bf5b305dea8b49a1 Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Wed, 23 Mar 2022 12:40:55 -0500 Subject: Add single space after quotes --- .../resources/guides/python-guides/subclassing_bot.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index f22f98f5..5f1e7ccf 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -14,11 +14,11 @@ There are two ways to subclass `commands.Bot`, as shown below: class CustomBot(commands.Bot): def __init__(self): super().__init__( - command_prefix = #your prefix here as a string - intents = #your intents here - #other kwargs can be put here + command_prefix = # your prefix here as a string + intents = # your intents here + # other kwargs can be put here ) - #custom bot attributes can be set here, for example: + # custom bot attributes can be set here, for example: self.db = self.loop.run_until_complete(aiosqlite.connect("Your database file name")) self.launch_time = datetime.datetime.utcnow() self.example_integer = 5 @@ -28,17 +28,17 @@ bot = CustomBot() Or ```py class CustomBot(commands.Bot): - def __init__(self, *args, **kwargs): #the key-word arguments are not specified here, unlike the example above + def __init__(self, *args, **kwargs): # the key-word arguments are not specified here, unlike the example above super().__init__(*args, **kwargs) - #custom bot attributes can be set here, for example: + # custom bot attributes can be set here, for example: self.example_string = 'This is an example!' - #You can add a custom bot method, anyhting can be done in this function. This is an example: + # You can add a custom bot method, anything can be done in this function. This is an example: def hello(self): return 'Hello World' -#Here you set the *args and **kwargs +# Here you set the *args and **kwargs bot = CustomBot(command_prefix="!", intents=discord.Intents.default()) @bot.command() -- cgit v1.2.3 From 806ce3fdf433d05b9d480a3d7ca2332dac951194 Mon Sep 17 00:00:00 2001 From: Krypton Date: Wed, 23 Mar 2022 22:35:32 +0100 Subject: Update discord-messages-with-colors.md --- .../python-guides/discord-messages-with-colors.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index 30f40948..c8e50d71 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -3,13 +3,13 @@ title: Discord Messages with Colors description: A guide on how to add colors to your codeblocks on Discord --- -Discord is now slowly rolling out the ability to send colored messages within code blocks. It uses the ANSI color codes, so if you've tried to print colored text in your terminal or console with Python or other languages then it will be easy for you. +Discord is now slowly rolling out the ability to send colored text within code blocks. This is done using ANSI color codes which is also how you print colored text in your terminal. -To be able to send a colored text, you need to use the `ansi` language for your code block and provide a prefix of this format before writing your text: -``` +To send colored text in a code block you need to first specify the `ansi` language and use the prefixes similar to the one below: +```ansi \u001b[{format};{color}m ``` -*The `\u001b` is the unicode for ESCAPE/ESC, see .* ***If you want to use it yourself without bots, then you need to copy paste the character from the website.*** +*`\u001b` is the unicode escape for ESCAPE/ESC, meant to be used in the source of your bot (see ).* ***If you wish to send colored text without using your bot you need to copy the character from the website.*** After you've written this, you can type and text you wish, and if you want to reset the color back to normal, then you need to use `\u001b[0m` as prefix. @@ -34,13 +34,13 @@ Here is the list of values you can use to replace `{color}`: *The following values will change the **text background** color.* -* 40: Some very dark blue +* 40: Firefly dark blue * 41: Orange -* 42: Gray -* 43: Light gray -* 44: Even lighter gray +* 42: Marble blue +* 43: Greyish turquoise +* 44: Gray * 45: Indigo -* 46: Again some gray +* 46: Light gray * 47: White Let's take an example, I want a bold green colored text with the very dark blue background. @@ -54,7 +54,8 @@ or
\u001b[1;40;32mThat's some cool formatted text right?
\`\`\` -Result:
+Result: + ![Background and text color](https://media.discordapp.net/attachments/739937507768270939/930460020603224084/Background-Text-Color.png) The way the colors look like on Discord is shown in the image below: -- cgit v1.2.3 From caaecf572615e9177fe53c6f81212d7a7ca6d2f6 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Thu, 24 Mar 2022 13:26:21 +0400 Subject: Update subclassing_bot.md --- .../guides/python-guides/subclassing_bot.md | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 5f1e7ccf..0f9dbf78 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -14,31 +14,40 @@ There are two ways to subclass `commands.Bot`, as shown below: class CustomBot(commands.Bot): def __init__(self): super().__init__( - command_prefix = # your prefix here as a string - intents = # your intents here - # other kwargs can be put here + command_prefix = #your prefix here as a string + intents = #your intents here + #other kwargs can be put here ) - # custom bot attributes can be set here, for example: - self.db = self.loop.run_until_complete(aiosqlite.connect("Your database file name")) + #custom bot attributes can be set here, for example: self.launch_time = datetime.datetime.utcnow() self.example_integer = 5 + + async def start(self, *args, **kwargs): + # here you are overriding the default start method. You can do some code here for example establish a database connection + #as shown in this example below + self.db = await aiosqlite.connect('database file name.db') + await super().start(*args, **kwargs) + + bot = CustomBot() +token = YOUR_TOKEN_HERE +bot.run(token) ``` Or ```py class CustomBot(commands.Bot): - def __init__(self, *args, **kwargs): # the key-word arguments are not specified here, unlike the example above + def __init__(self, *args, **kwargs): #the key-word arguments are not specified here, unlike the example above super().__init__(*args, **kwargs) - # custom bot attributes can be set here, for example: + #custom bot attributes can be set here, for example: self.example_string = 'This is an example!' - # You can add a custom bot method, anything can be done in this function. This is an example: + #You can add a custom bot method, anyhting can be done in this function. This is an example: def hello(self): return 'Hello World' -# Here you set the *args and **kwargs +#Here you set the *args and **kwargs bot = CustomBot(command_prefix="!", intents=discord.Intents.default()) @bot.command() -- cgit v1.2.3 From 134c304672a925600663e85ee2d76bc84c8db20f Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Thu, 24 Mar 2022 14:22:12 +0400 Subject: Delete discordpy_help_command.md --- .../guides/python-guides/discordpy_help_command.md | 35 ---------------------- 1 file changed, 35 deletions(-) delete mode 100644 pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md b/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md deleted file mode 100644 index 39a45063..00000000 --- a/pydis_site/apps/content/resources/guides/python-guides/discordpy_help_command.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Custom Help Command -description: "Overwrite discord.py's help command to implement custom functionality" ---- - - First, a [basic walkthrough](https://gist.github.com/InterStella0/b78488fb28cadf279dfd3164b9f0cf96) by Stella#2000 on subclassing the HelpCommand will provide some foundational knowledge required before attempting a more customizable help command. - ---- - -## Custom Subclass of Help Command -If this does not fit your needs and you require a more customizable help command, you can subclass HelpCommand and add individual command details. Below is a basic demonstration: - -```python -class MyHelpCommand(commands.HelpCommand): - async def command_callback(self, ctx, *,command=None): - if command: - await ctx.send(f"This is the help page for the command {command} ") - else: - await ctx.send("This is the front page for the bots help command") -bot.help_command = MyHelpCommand() -``` ---- -You can handle when a user does not pass a command name when invoking the help command and make a fancy and customized embed; here a page that describes the bot and shows a list of commands is generally used, however if a command is passed in, you can display detailed information of the command. Below are references from the documentation below that can be utilised: - -* [Get the command object](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot.get_command) - -* [Get the command name](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.name) - -* [Get the command aliases](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.aliases) - -* [Get the command brief](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.brief) - -* [Get the command usage](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Command.usage) - -* Get the command cooldown - `command_object._buckets._cooldown.per` -- cgit v1.2.3 From 1017676bea05d423d86a29c2ede769a6288a3d4a Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sat, 26 Mar 2022 22:33:03 -0400 Subject: Fix commit-messages link --- .../guides/pydis-guides/contributing/contributing-guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md index f13b05be..1917ee43 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md @@ -12,7 +12,7 @@ We have simple but strict style rules that are enforced through linting. Not all of the style rules are enforced by linting, so make sure to read the [style guide](../style-guide/) as well. 2. **Make great commits.** Great commits should be atomic, with a commit message explaining what and why. -Check out [Writing Good Commit Messages](/commit-messages) for details. +Check out [Writing Good Commit Messages](./commit-messages) for details. 3. **Do not open a pull request if you aren't assigned to the issue.** If someone is already working on it, consider offering to collaborate with that person. 4. **Use assets licensed for public use.** -- cgit v1.2.3 From 15a32db18b72291913cf80b9fc85ac578b824f34 Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 27 Mar 2022 00:06:14 -0400 Subject: Make small wording improvements --- .../apps/content/resources/guides/pydis-guides/contributing.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 51991d9c..4b53d978 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -92,7 +92,7 @@ Our projects on Python Discord are open source and [available on GitHub](https:/ # How do I start contributing? - Unsure of what contributing to open source projects involves? Have questions about how to use GitHub? Just need to know about our contribution etiquette? Completing these steps will have you ready to make your first contribution. + Unsure of what contributing to open source projects involves? Have questions about how to use GitHub? Just need to know about our contribution etiquette? Completing these steps will have you ready to make your first contribution no matter your starting point. Feel free to skip any steps you're already familiar with, but please make sure not to miss the [Contributing Guidelines](#5-read-our-contributing-guidelines). @@ -107,7 +107,6 @@ Our projects on Python Discord are open source and [available on GitHub](https:/ GitHub is a website based on the Git version control system that stores project files in the cloud. The people working on the project can use GitHub as a central place for sending their changes, getting their teammates' changes, and communicating with each other. Forking the repository that you want to work on will create a copy under your own GitHub account. You'll make your changes to this copy, then later we can bring them back to the PyDis repository. Check out our [**guide on forking a GitHub repo**](./forking-repository/). - ### 3. Clone the repo Now that you have your own fork you need to be able to make changes to the code. You can clone the repo to your local machine, commit changes to it there, then push those changes to GitHub. @@ -145,4 +144,4 @@ Our projects on Python Discord are open source and [available on GitHub](https:/ Check out our [**Code Review Guide**](../code-reviews-primer/) to learn how to be a star reviewer. Reviewing PRs is a vital part of open source development, and we always need more reviewers! ### That's it! -Thank you for contributing to our community projects. If you don't understand anything or need clarification, feel free to ask a question in the`dev-contrib`channel and keep an eye out for staff members with the **@PyDis Core Developers** role in the server. We're always happy to help! +Thank you for contributing to our community projects. If there's anything you don't understand or you just want to discuss with other contributors, come visit the`dev-contrib`channel to ask questions. Keep an eye out for staff members with the **@PyDis Core Developers** role in the server; we're always happy to help! -- cgit v1.2.3 From d167c7dc53031fd936fa0ee438d6a240bf45fb76 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:16:57 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 0f9dbf78..f6d554eb 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -1,6 +1,6 @@ --- title: Subclassing Bot -description: "Subclassing the Bot to add more functionability and customisability." +description: "Subclassing the Bot to add more functionality and customisability." --- ## Basic Subclassing -- cgit v1.2.3 From 087a8f84e992ce2cbde910b4381ed1d052b88c40 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:17:06 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index f6d554eb..6b798400 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -14,8 +14,8 @@ There are two ways to subclass `commands.Bot`, as shown below: class CustomBot(commands.Bot): def __init__(self): super().__init__( - command_prefix = #your prefix here as a string - intents = #your intents here + command_prefix=#your prefix here as a string + intents=#your intents here #other kwargs can be put here ) #custom bot attributes can be set here, for example: -- cgit v1.2.3 From 93413138d1342a110c50a2f77f74253f5c06fdd4 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:17:15 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 6b798400..bd8cbdc8 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -18,7 +18,7 @@ class CustomBot(commands.Bot): intents=#your intents here #other kwargs can be put here ) - #custom bot attributes can be set here, for example: + # custom bot attributes can be set here, for example: self.launch_time = datetime.datetime.utcnow() self.example_integer = 5 -- cgit v1.2.3 From dd55548bf67a670e74b8a3a0424241eecd0f2d48 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:17:22 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index bd8cbdc8..be9bb6e8 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -25,7 +25,7 @@ class CustomBot(commands.Bot): async def start(self, *args, **kwargs): # here you are overriding the default start method. You can do some code here for example establish a database connection - #as shown in this example below + # as shown in this example below self.db = await aiosqlite.connect('database file name.db') await super().start(*args, **kwargs) -- cgit v1.2.3 From 9d0391b330adfbc994e1b1a344dbc1e4f1a2c76d Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:17:30 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index be9bb6e8..37f7a9d2 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -37,7 +37,7 @@ bot.run(token) Or ```py class CustomBot(commands.Bot): - def __init__(self, *args, **kwargs): #the key-word arguments are not specified here, unlike the example above + def __init__(self, *args, **kwargs): # the key-word arguments are not specified here, unlike the example above super().__init__(*args, **kwargs) #custom bot attributes can be set here, for example: -- cgit v1.2.3 From 671660b8f0a930b2c80801df0e2c62ef8c86da83 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:17:37 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 37f7a9d2..49ad59f0 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -43,7 +43,7 @@ class CustomBot(commands.Bot): #custom bot attributes can be set here, for example: self.example_string = 'This is an example!' - #You can add a custom bot method, anyhting can be done in this function. This is an example: + # You can add a custom bot method, anyhting can be done in this function. This is an example: def hello(self): return 'Hello World' -- cgit v1.2.3 From f228039ff07aeac48729074c5eb1efeb16b043b4 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:18:08 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 49ad59f0..1efbb571 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -40,7 +40,7 @@ class CustomBot(commands.Bot): def __init__(self, *args, **kwargs): # the key-word arguments are not specified here, unlike the example above super().__init__(*args, **kwargs) - #custom bot attributes can be set here, for example: + # custom bot attributes can be set here, for example: self.example_string = 'This is an example!' # You can add a custom bot method, anyhting can be done in this function. This is an example: -- cgit v1.2.3 From 7f78aa493590e9533905b942c6b18653fc0108ea Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:18:53 +0400 Subject: Update subclassing_bot.md --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 1efbb571..060dfacb 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -47,7 +47,7 @@ class CustomBot(commands.Bot): def hello(self): return 'Hello World' -#Here you set the *args and **kwargs +# Here you set the *args and **kwargs bot = CustomBot(command_prefix="!", intents=discord.Intents.default()) @bot.command() -- cgit v1.2.3 From b08d93869e7e3a2f032b02e711d95fcde6216aa2 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 28 Mar 2022 09:20:05 +0400 Subject: Update subclassing_bot.md --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 060dfacb..381f25f1 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -14,9 +14,9 @@ There are two ways to subclass `commands.Bot`, as shown below: class CustomBot(commands.Bot): def __init__(self): super().__init__( - command_prefix=#your prefix here as a string - intents=#your intents here - #other kwargs can be put here + command_prefix= # Your prefix here as a string + intents= # Your intents here + # Other kwargs can be put here ) # custom bot attributes can be set here, for example: self.launch_time = datetime.datetime.utcnow() -- cgit v1.2.3 From 08d5e01be09e482f92a96cf00bc007e60dfa2c98 Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Thu, 31 Mar 2022 10:46:33 -0500 Subject: Make "free hosts" a header Co-authored-by: Shom770 <82843611+Shom770@users.noreply.github.com> --- pydis_site/apps/content/resources/guides/python-guides/vps-services.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index 90306057..b8a6f8fd 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -30,6 +30,6 @@ If you need to run your bot 24/7 (with no downtime), you should consider using a * Global data centre options. --- -Free hosts +# Free hosts There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi. -- cgit v1.2.3 From 0cc092741ea35b5810d57d4d768dcb0e021603bd Mon Sep 17 00:00:00 2001 From: Robin5605 Date: Thu, 31 Mar 2022 10:50:38 -0500 Subject: Remove extraneous bullet points in "global" --- .../apps/content/resources/guides/python-guides/vps-services.md | 4 ---- 1 file changed, 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index b8a6f8fd..bd4af0a5 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -21,13 +21,9 @@ If you need to run your bot 24/7 (with no downtime), you should consider using a * Great affiliate program. * Global * [Linode](https://www.linode.com/) - * Global data centre options. * [Digital Ocean](https://www.digitalocean.com/) - * Global data centre options. * [OVHcloud](https://www.ovhcloud.com/) - * Global data centre options. * [Vultr](https://www.vultr.com/) - * Global data centre options. --- # Free hosts -- cgit v1.2.3 From 1e916a0515940caa95f34fc0bc04a040b36c214d Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Thu, 31 Mar 2022 11:52:57 -0500 Subject: Add space Co-authored-by: Hassan Abouelela --- pydis_site/apps/content/resources/guides/python-guides/vps-services.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md index bd4af0a5..0acd3e55 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -3,7 +3,7 @@ title: VPS Services description: On different VPS services --- -If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS).This is a list of VPS services that are sufficient for running Discord bots. +If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). This is a list of VPS services that are sufficient for running Discord bots. * Europe * [netcup](https://www.netcup.eu/) -- cgit v1.2.3 From 1005229e825a5f2449168bcae2b85667c5799265 Mon Sep 17 00:00:00 2001 From: Krypton Date: Fri, 1 Apr 2022 18:15:19 +0200 Subject: Added Discord embed limits guide (#690) Co-authored-by: Krypton Co-authored-by: Krypton Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> --- .../guides/python-guides/discord-embed-limits.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/discord-embed-limits.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-embed-limits.md b/pydis_site/apps/content/resources/guides/python-guides/discord-embed-limits.md new file mode 100644 index 00000000..ca97462b --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-embed-limits.md @@ -0,0 +1,21 @@ +--- +title: Discord Embed Limits +description: A guide that shows the limits of embeds in Discord and how to avoid them. +--- + +If you plan on using embed responses for your bot you should know the limits of the embeds on Discord or you will get `Invalid Form Body` errors: + +- Embed **title** is limited to **256 characters** +- Embed **description** is limited to **4096 characters** +- An embed can contain a maximum of **25 fields** +- A **field name/title** is limited to **256 character** and the **value of the field** is limited to **1024 characters** +- Embed **footer** is limited to **2048 characters** +- Embed **author name** is limited to **256 characters** +- The **total of characters** allowed in an embed is **6000** + +Now if you need to get over this limit (for example for a help command), you would need to use pagination. +There are several ways to do that: + +- A library called **[disputils](https://pypi.org/project/disputils)** +- An experimental library made by the discord.py developer called **[discord-ext-menus](https://github.com/Rapptz/discord-ext-menus)** +- Make your own setup using **[wait_for()](https://discordpy.readthedocs.io/en/stable/ext/commands/api.html#discord.ext.commands.Bot.wait_for)** and wait for a reaction to be added -- cgit v1.2.3 From 306a906c850324a4a31a62d82d5348a18f3f2e5e Mon Sep 17 00:00:00 2001 From: Shom770 <82843611+Shom770@users.noreply.github.com> Date: Sat, 2 Apr 2022 12:16:13 -0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/keeping-tokens-safe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md index e37039d1..6b5dae34 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md +++ b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md @@ -12,7 +12,7 @@ To help prevent leaking your token, you should ensure that you don't upload it t If for whatever reason your token gets leaked, you should immediately follow these steps: - Go to the list of [Discord Bot Applications](https://discord.com/developers/applications) you have and select the bot application that had the token leaked. - Select the Bot (1) tab on the left-hand side, next to a small image of a puzzle piece. After doing so you should see a small section named TOKEN (under your bot USERNAME and next to his avatar image) -- Press the Regenerate (2) option to regen your bot token. +- Press the Regenerate option to regen your bot token. ![Steps to Take to Reset your Discord Bot](https://cdn.discordapp.com/attachments/343944376055103488/845290595793764392/regen_token.png) -- cgit v1.2.3 From 788c8fc1b3fc54fa35dc8282b8a1267314e85a77 Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Thu, 7 Apr 2022 22:44:09 -0400 Subject: Replace difficulty badges with more description --- .../resources/guides/pydis-guides/contributing.md | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 4b53d978..e4b3e621 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -19,11 +19,7 @@ Our projects on Python Discord are open source and [available on GitHub](https:/
- Our community-driven Discord bot. -
-
- Difficulty - Beginner + Sir Lancebot has a collection of self-contained, for-fun features. If you're new to Discord bots or contributing, this is a great place to start!
- The community and moderation Discord bot. -
-
- Difficulty - Intermediate + Called @Python on the server, this bot handles moderation tools, help channels, and other critical features for our community.
- The website, subdomains and API. -
-
- Difficulty - Advanced + This website itself! This project is built with Django and includes our API, which is used by various services such as @Python.
# How do I start contributing? - Unsure of what contributing to open source projects involves? Have questions about how to use GitHub? Just need to know about our contribution etiquette? Completing these steps will have you ready to make your first contribution no matter your starting point. +Unsure of what contributing to open source projects involves? Have questions about how to use GitHub? Just need to know about our contribution etiquette? Completing these steps will have you ready to make your first contribution no matter your starting point. - Feel free to skip any steps you're already familiar with, but please make sure not to miss the [Contributing Guidelines](#5-read-our-contributing-guidelines). +Feel free to skip any steps you're already familiar with, but please make sure not to miss the [Contributing Guidelines](#5-read-our-contributing-guidelines). - If you are here looking for the answer to a specific question, check out the sub-articles in the top right of the page to see a list of our guides. +If you are here looking for the answer to a specific question, check out the sub-articles in the top right of the page to see a list of our guides. - **Note:** We use Git to keep track of changes to the files in our projects. Git allows you to make changes to your local code and then distribute those changes to the other people working on the project. You'll use Git in a couple steps of the contributing process. You can refer to this [**guide on using Git**](./working-with-git/). - {: .notification } +**Note:** We use Git to keep track of changes to the files in our projects. Git allows you to make changes to your local code and then distribute those changes to the other people working on the project. You'll use Git in a couple steps of the contributing process. You can refer to this [**guide on using Git**](./working-with-git/). +{: .notification } ### 1. Fork and clone the repo GitHub is a website based on Git that stores project files in the cloud. We use GitHub as a central place for sending changes, reviewing others' changes, and communicating with each other. You'll need to create a copy of the repository under your own GitHub account, aka "fork" it. You'll make your changes to this copy, which can then later be merged into the Python Discord repository. -- cgit v1.2.3 From d4150fdf04b3712655239a4fd77ee066f0920eda Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 24 Apr 2022 15:13:28 -0400 Subject: Move link to issue guide to match others --- pydis_site/apps/content/resources/guides/pydis-guides/contributing.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index fa829c9f..e19e2cea 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -117,7 +117,9 @@ As mentioned in the Contributing Guidelines, we have a simple style guide for ou [**Style Guide**](./style-guide/) ### 4. Create an issue -The first step to any new contribution is an issue describing a problem with the current codebase or proposing a new feature. All the open issues are viewable on the GitHub repositories, for instance here is the [issues page for Sir Lancebot](https://github.com/python-discord/sir-lancebot/issues). If you have an idea that you want to implement, open a new issue (and check out our [**guide on writing an issue**](./issues/)). Otherwise you can browse the unassigned issues and ask to be assigned to one that you're interested in, either in the comments on the issue or in the [`#dev-contrib`](https://discord.gg/2h3qBv8Xaa) channel on Discord. +The first step to any new contribution is an issue describing a problem with the current codebase or proposing a new feature. All the open issues are viewable on the GitHub repositories, for instance here is the [issues page for Sir Lancebot](https://github.com/python-discord/sir-lancebot/issues). If you have something that you want to implement open a new issue to present your idea. Otherwise you can browse the unassigned issues and ask to be assigned to one that you're interested in, either in the comments on the issue or in the [`#dev-contrib`](https://discord.gg/2h3qBv8Xaa) channel on Discord. + +[**How to write a good issue**](./issues/) Don't move forward until your issue is approved by a Core Developer. Issues are not guaranteed to be approved so your work may be wasted. {: .notification .is-warning } -- cgit v1.2.3 From 371a5b7650b4fbea1ff30e0afd63563882f33b3f Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 24 Apr 2022 15:14:08 -0400 Subject: Revert "Make it clearer what forking is" This reverts commit 32cf915246fbec5d3dc792d717b50af635108ca3. --- pydis_site/apps/content/resources/guides/pydis-guides/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index e19e2cea..db466029 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -90,7 +90,7 @@ If you are here looking for the answer to a specific question, check out the sub {: .notification } ### 1. Fork and clone the repo -GitHub is a website based on Git that stores project files in the cloud. We use GitHub as a central place for sending changes, reviewing others' changes, and communicating with each other. You'll need to create a copy of the repository under your own GitHub account, aka "fork" it. You'll make your changes to this copy, which can then later be merged into the Python Discord repository. +GitHub is a website based on Git that stores project files in the cloud. We use GitHub as a central place for sending changes, reviewing others' changes, and communicating with each other. You'll need to fork the repository to create a copy under your own GitHub account. You'll make your changes to this copy, which can then later be merged into the Python Discord repository. Check out our [**guide on forking a GitHub repo**](./forking-repository/). -- cgit v1.2.3 From d75612d9431c330481a16d61d43aaefea733eb8f Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 24 Apr 2022 15:15:59 -0400 Subject: Make it more clear what forking is --- pydis_site/apps/content/resources/guides/pydis-guides/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index db466029..bed2ffa1 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -90,7 +90,7 @@ If you are here looking for the answer to a specific question, check out the sub {: .notification } ### 1. Fork and clone the repo -GitHub is a website based on Git that stores project files in the cloud. We use GitHub as a central place for sending changes, reviewing others' changes, and communicating with each other. You'll need to fork the repository to create a copy under your own GitHub account. You'll make your changes to this copy, which can then later be merged into the Python Discord repository. +GitHub is a website based on Git that stores project files in the cloud. We use GitHub as a central place for sending changes, reviewing others' changes, and communicating with each other. You'll need to create a copy under your own GitHub account, a.k.a. "fork" it. You'll make your changes to this copy, which can then later be merged into the Python Discord repository. Check out our [**guide on forking a GitHub repo**](./forking-repository/). -- cgit v1.2.3 From fa1dd4058e8606f165df5ff7902d9215eeec4679 Mon Sep 17 00:00:00 2001 From: Krypton Date: Thu, 28 Apr 2022 19:00:06 +0200 Subject: Using static images --- .../python-guides/discord-messages-with-colors.md | 8 ++++---- .../content/discord_colored_messages/ansi-colors.png | Bin 0 -> 33579 bytes .../images/content/discord_colored_messages/result.png | Bin 0 -> 13740 bytes 3 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 pydis_site/static/images/content/discord_colored_messages/ansi-colors.png create mode 100644 pydis_site/static/images/content/discord_colored_messages/result.png (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index c8e50d71..6845ce76 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -48,17 +48,17 @@ I simply use `\u001b[0;40m` (background color) and `\u001b[1;32m` (text color) a Alternatively you can also directly combine them into a single prefix like the following: `\u001b[1;40;32m` and you can also use multiple values. Something like `\u001b[1;40;4;32m` would underline the text, make it bold, make it green and have a dark blue background. Raw message:
-\`\`\`ansi
+\`\`\`ansi \u001b[0;40m\u001b[1;32mThat's some cool formatted text right?
-or
+or \u001b[1;40;32mThat's some cool formatted text right?
\`\`\` Result: -![Background and text color](https://media.discordapp.net/attachments/739937507768270939/930460020603224084/Background-Text-Color.png) +![Background and text color result](/static/images/content/discord_colored_messages/result.png) The way the colors look like on Discord is shown in the image below: -![ANSI Colors](https://media.discordapp.net/attachments/739937507768270939/930825555803263016/ANSI-Colors.png) +![ANSI Colors](/static/images/content/discord_colored_messages/ansi-colors.png) Note: If the change as not been brought to you yet, or other users, then you can use other code blocks in the meantime to get colored text. See this gist: diff --git a/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png b/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png new file mode 100644 index 00000000..32af146f Binary files /dev/null and b/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png differ diff --git a/pydis_site/static/images/content/discord_colored_messages/result.png b/pydis_site/static/images/content/discord_colored_messages/result.png new file mode 100644 index 00000000..a666804e Binary files /dev/null and b/pydis_site/static/images/content/discord_colored_messages/result.png differ -- cgit v1.2.3 From e3067dc451a3a5da02a90d61791c1c7c5731cab0 Mon Sep 17 00:00:00 2001 From: Krypton Date: Thu, 28 Apr 2022 19:17:00 +0200 Subject: Removed `
`'s and used code block for raw message --- .../python-guides/discord-messages-with-colors.md | 15 +++++++++------ .../discord_colored_messages/ansi-colors.png | Bin 33579 -> 43004 bytes 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index 6845ce76..9a69973e 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -44,15 +44,18 @@ Here is the list of values you can use to replace `{color}`: * 47: White Let's take an example, I want a bold green colored text with the very dark blue background. -I simply use `\u001b[0;40m` (background color) and `\u001b[1;32m` (text color) as prefix. Note that the order is **important**, first you give the background color and then the text color.
+I simply use `\u001b[0;40m` (background color) and `\u001b[1;32m` (text color) as prefix. Note that the order is **important**, first you give the background color and then the text color. + Alternatively you can also directly combine them into a single prefix like the following: `\u001b[1;40;32m` and you can also use multiple values. Something like `\u001b[1;40;4;32m` would underline the text, make it bold, make it green and have a dark blue background. -Raw message:
-\`\`\`ansi -\u001b[0;40m\u001b[1;32mThat's some cool formatted text right?
+Raw message: +````nohighlight +```ansi +\u001b[0;40m\u001b[1;32mThat's some cool formatted text right? or -\u001b[1;40;32mThat's some cool formatted text right?
-\`\`\` +\u001b[1;40;32mThat's some cool formatted text right? +``` +```` Result: diff --git a/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png b/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png index 32af146f..d7176393 100644 Binary files a/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png and b/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png differ -- cgit v1.2.3 From 5202bcda5d79f203a67b59990f0ed3d6c87044b2 Mon Sep 17 00:00:00 2001 From: Krypton Date: Thu, 28 Apr 2022 19:34:41 +0200 Subject: Sentences check --- .../resources/guides/python-guides/discord-messages-with-colors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index 9a69973e..f4a747c9 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -11,7 +11,7 @@ To send colored text in a code block you need to first specify the `ansi` langua ``` *`\u001b` is the unicode escape for ESCAPE/ESC, meant to be used in the source of your bot (see ).* ***If you wish to send colored text without using your bot you need to copy the character from the website.*** -After you've written this, you can type and text you wish, and if you want to reset the color back to normal, then you need to use `\u001b[0m` as prefix. +After you've written this, you can now type the text you wish to color. If you want to reset the color back to normal, then you need to use the `\u001b[0m` prefix again. Here is the list of values you can use to replace `{format}`: -- cgit v1.2.3 From 8f433372ce889b9a61355ca64a23ca11417d920f Mon Sep 17 00:00:00 2001 From: Krypton Date: Thu, 28 Apr 2022 19:37:42 +0200 Subject: Fixed image not at new line --- .../resources/guides/python-guides/discord-messages-with-colors.md | 1 + 1 file changed, 1 insertion(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index f4a747c9..e414ff39 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -62,6 +62,7 @@ Result: ![Background and text color result](/static/images/content/discord_colored_messages/result.png) The way the colors look like on Discord is shown in the image below: + ![ANSI Colors](/static/images/content/discord_colored_messages/ansi-colors.png) Note: If the change as not been brought to you yet, or other users, then you can use other code blocks in the meantime to get colored text. See this gist: -- cgit v1.2.3 From d25d4ed61c6cb4b8ee310e1647ab91fdd8fe83be Mon Sep 17 00:00:00 2001 From: Xithrius <15021300+Xithrius@users.noreply.github.com> Date: Thu, 28 Apr 2022 11:19:05 -0700 Subject: Don't do JSON as a database, kids. (#700) Migrate no-JSON-as-a-database pinned message to site --- .../python-guides/why-not-json-as-database.md | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md b/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md new file mode 100644 index 00000000..ae34c2b4 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md @@ -0,0 +1,28 @@ +--- +title: Why JSON is unsuitable as a database +description: The many reasons why you shouldn't use JSON as a database, and instead opt for SQL. +relevant_links: + Tips on Storing Data: https://tutorial.vcokltfre.dev/tips/storage/ +--- + +JSON, quite simply, is not a database. It's not designed to be a data storage format, +rather a wayof transmitting data over a network. It's also often used as a way of doing configuration files for programs. + +There is no redundancy built in to JSON. JSON is just a format, and Python has libraries for it +like json and ujson that let you load and dump it, sometimes to files, but that's all it does, write data to a file. +There is no sort of DBMS (Database Management System), which means no sort of sophistication in how the data is stored, +or built in ways to keep it safe and backed up, there's no built in encryption either - bear in mind +in larger applications encryption may be necessary for GDPR/relevant data protection regulations compliance. + +JSON, unlike relational databases, has no way to store relational data, +which is a very commonly needed way of storing data. +Relational data, as the name may suggest, is data that relates to other data. +For example if you have a table of users and a table of servers, the server table will probably have an owner field, +where you'd reference a user from the users table. (**This is only relevant for relational data**). + +JSON is primarily a KV (key-value) format, for example `{"a": "b"}` where `a` is the key and `b` is the value, +but what if you want to search not by that key but by a sub-key? Well, instead of being able to quickly use `var[key]`, +which in a Python dictionary has a constant return time (for more info look up hash tables), +you now have to iterate through every object in the dictionary and compare to find what you're looking for. +Most relational database systems, like MySQL, MariaDB, and PostgreSQL have ways of indexing secondary fields +apart from the primary key so that you can easily search by multiple attributes. -- cgit v1.2.3 From ad41d8d2a58b73bd4402f945f0ae8fcc7b49bda4 Mon Sep 17 00:00:00 2001 From: Krypton Date: Thu, 28 Apr 2022 22:20:52 +0200 Subject: Using hyperlink for gist link at the bottom --- .../resources/guides/python-guides/discord-messages-with-colors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index e414ff39..62ff61f9 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -65,4 +65,4 @@ The way the colors look like on Discord is shown in the image below: ![ANSI Colors](/static/images/content/discord_colored_messages/ansi-colors.png) -Note: If the change as not been brought to you yet, or other users, then you can use other code blocks in the meantime to get colored text. See this gist: +Note: If the change as not been brought to you yet, or other users, then you can use other code blocks in the meantime to get colored text. See **[this gist](https://gist.github.com/matthewzring/9f7bbfd102003963f9be7dbcf7d40e51)**. -- cgit v1.2.3 From ebdba4488b7def58614dc221215a2430d6df6ecf Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Wed, 4 May 2022 20:00:15 +0400 Subject: Add recommended hosting service page (#712) * add article discussing free hosting services * add hsoting and VPS services article * Merge branch 'pinned_messages' of https://github.com/Diabolical5777/site into pinned_messages * Delete free_hosting_services.md * Update pydis_site/apps/content/resources/guides/python-guides/vps_services.md Co-authored-by: Bluenix * Update pydis_site/apps/content/resources/guides/python-guides/vps_services.md Co-authored-by: Bluenix * Update pydis_site/apps/content/resources/guides/python-guides/vps_services.md Co-authored-by: Bluenix * add vps and hosting service guide * Update pydis_site/apps/content/resources/guides/python-guides/vps_services.md Co-authored-by: Bluenix * add article on VPS and free hosting services * Update vps_services.md * Update vps_services.md Co-authored-by: Bluenix Co-authored-by: ChrisJL --- .../resources/guides/python-guides/vps_services.md | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/vps_services.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps_services.md b/pydis_site/apps/content/resources/guides/python-guides/vps_services.md new file mode 100644 index 00000000..710fd914 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/vps_services.md @@ -0,0 +1,58 @@ +--- +title: VPS and Free Hosting Service for Discord bots +description: This article lists recommended VPS services and covers the disasdvantages of utilising a free hosting service to run a discord bot. +toc: 2 +--- + +## Recommended VPS services + +If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). Here is a list of VPS services that are sufficient for running Discord bots. + +* Europe + * [netcup](https://www.netcup.eu/) + * Germany & Austria data centres. + * Great affiliate program. + * [Yandex Cloud](https://cloud.yandex.ru/) + * Vladimir, Ryazan, and Moscow region data centres. + * [Scaleway](https://www.scaleway.com/) + * France data centre. + * [Time 4 VPS](https://www.time4vps.eu/) + * Lithuania data centre. +* US + * [GalaxyGate](https://galaxygate.net/) + * New York data centre. + * Great affiliate program. +* Global + * [Linode](https://www.linode.com/) + * [Digital Ocean](https://www.digitalocean.com/) + * [OVHcloud](https://www.ovhcloud.com/) + * [Vultr](https://www.vultr.com/) + + +## Why not to use free hosting services for bots? +While these may seem like nice and free services, it has a lot more caveats than you may think. For example, the drawbacks of using common free hosting services to host a discord bot are discussed below. + +### Replit + +- The machines are super underpowered, resulting in your bot lagging a lot as it gets bigger. + +- You need to run a webserver alongside your bot to prevent it from being shut off. This uses extra machine power. + +- Repl.it uses an ephemeral file system. This means any file you saved through your bot will be overwritten when you next launch. + +- They use a shared IP for everything running on the service. +This one is important - if someone is running a user bot on their service and gets banned, everyone on that IP will be banned. Including you. + +### Heroku +- Bots are not what the platform is designed for. Heroku is designed to provide web servers (like Django, Flask, etc). This is why they give you a domain name and open a port on their local emulator. + +- Heroku's environment is heavily containerized, making it significantly underpowered for a standard use case. + +- Heroku's environment is volatile. In order to handle the insane amount of users trying to use it for their own applications, Heroku will dispose your environment every time your application dies unless you pay. + +- Heroku has minimal system dependency control. If any of your Python requirements need C bindings (such as PyNaCl + binding to libsodium, or lxml binding to libxml), they are unlikely to function properly, if at all, in a native + environment. As such, you often need to resort to adding third-party buildpacks to facilitate otherwise normal + CPython extension functionality. (This is the reason why voice doesn't work natively on heroku) + +- Heroku only offers a limited amount of time on their free programme for your applications. If you exceed this limit, which you probably will, they'll shut down your application until your free credit resets. -- cgit v1.2.3 From 56648f34bb48b40668a4ae48f4117fcbaaadea23 Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sat, 7 May 2022 21:52:57 -0400 Subject: Add 'Next steps' section to ends of the setup guides --- .../resources/guides/pydis-guides/contributing/bot.md | 12 ++++++++---- .../guides/pydis-guides/contributing/sir-lancebot.md | 6 ++++++ .../resources/guides/pydis-guides/contributing/site.md | 9 +++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 0f783ef6..e98db596 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -543,10 +543,7 @@ Now that you have everything setup, it is finally time to make changes to the bo #### Working with Git -If you have not yet [read the contributing guidelines](../contributing-guidelines), now is a good time. -Contributions that do not adhere to the guidelines may be rejected. - -Notably, version control of our projects is done using Git and Github. +Version control of our projects is done using Git and Github. It can be intimidating at first, so feel free to ask for any help in the server. [**Click here to see the basic Git workflow when contributing to one of our projects.**](../working-with-git/) @@ -637,4 +634,11 @@ The following is a list of all available environment variables used by the bot: | `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. +--- + +# Next steps +Now that you have everything setup, it is finally time to make changes to the bot! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. + +If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project) is for you. + Have fun! diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index 1621abb6..f5f1ae4c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -110,5 +110,11 @@ After installing project dependencies use the poetry command `poetry run task st ```shell $ poetry run task start ``` +--- + +# Next steps +Now that you have everything setup, it is finally time to make changes to the bot! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. + +If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project) is for you. Have fun! diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 7eda027a..00115516 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -166,3 +166,12 @@ The website is configured through the following environment variables: - **`STATIC_ROOT`**: The root in which `python manage.py collectstatic` collects static files. Optional, defaults to `/app/staticfiles` for the standard Docker deployment. + +--- + +# Next steps +Now that you have everything setup, it is finally time to make changes to the site! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. + +If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project) is for you. + +Have fun! -- cgit v1.2.3 From 2b45c6c0b13b1183051659b7ea3660b1d6efc90b Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sat, 7 May 2022 22:57:24 -0400 Subject: Add reminders at tops of set-up guides to fork and clone --- .../resources/guides/pydis-guides/contributing/bot.md | 2 ++ .../guides/pydis-guides/contributing/sir-lancebot.md | 12 +++++++----- .../resources/guides/pydis-guides/contributing/site.md | 7 ++++--- 3 files changed, 13 insertions(+), 8 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index e98db596..ad446cc8 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -5,6 +5,8 @@ icon: fab fa-github toc: 3 --- The purpose of this guide is to get you a running local version of [the Python bot](https://github.com/python-discord/bot). +You should have already forked the repository and cloned it to your local machine. If not, check out our [detailed walkthrough](../#1-fork-and-clone-the-repo). + This page will focus on the quickest steps one can take, with mentions of alternatives afterwards. --- diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index f5f1ae4c..c9566d23 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -5,10 +5,11 @@ icon: fab fa-github toc: 1 --- -> Before contributing, please ensure you read the [contributing guidelines](../contributing-guidelines) in full. +You should have already forked the [`sir-lancebot`](https://github.com/python-discord/sir-lancebot) repository and cloned it to your local machine. If not, check out our [detailed walkthrough](../#1-fork-and-clone-the-repo). ---- -# Requirements +Remember to ensure that you have read the [contributing guidelines](../contributing-guidelines) in full before you start contributing. + +### Requirements - [Python 3.9](https://www.python.org/downloads/) - [Poetry](https://github.com/python-poetry/poetry#installation) - [Git](https://git-scm.com/downloads) @@ -16,6 +17,8 @@ toc: 1 - [MacOS Installer](https://git-scm.com/download/mac) or `brew install git` - [Linux](https://git-scm.com/download/linux) +--- + ## Using Gitpod Sir Lancebot can be edited and tested on Gitpod. Gitpod will automatically install the correct dependencies and Python version, so you can get straight to coding. @@ -42,8 +45,7 @@ The requirements for Docker are: --- # Development Environment -1. Once you have your fork, you will need to [**clone the repository to your computer**](../cloning-repository). -2. After cloning, proceed to [**install the project's dependencies**](../installing-project-dependencies). (This is not required if using Docker) +If you aren't using Docker, you will need to [install the project's dependencies](../installing-project-dependencies) yourself. --- # Test Server and Bot Account diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 00115516..520e41ad 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -5,7 +5,9 @@ icon: fab fa-github toc: 1 --- -# Requirements +You should have already forked the [`site`](https://github.com/python-discord/site) repository and cloned it to your local machine. If not, check out our [detailed walkthrough](../#1-fork-and-clone-the-repo). + +### Requirements - [Python 3.9](https://www.python.org/downloads/) - [Poetry](https://python-poetry.org/docs/#installation) @@ -29,8 +31,7 @@ Without Docker: --- # Development environment -1. [Clone your fork to a local project directory](../cloning-repository/) -2. [Install the project's dependencies](../installing-project-dependencies/) +[Install the project's dependencies](../installing-project-dependencies/) ## Without Docker -- cgit v1.2.3 From 0cce77e26b19949ed14da740f3bb9ed843af4255 Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 8 May 2022 12:06:26 -0400 Subject: Add note that staff members can create feature branches --- pydis_site/apps/content/resources/guides/pydis-guides/contributing.md | 2 ++ 1 file changed, 2 insertions(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index bed2ffa1..d67a827f 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -92,6 +92,8 @@ If you are here looking for the answer to a specific question, check out the sub ### 1. Fork and clone the repo GitHub is a website based on Git that stores project files in the cloud. We use GitHub as a central place for sending changes, reviewing others' changes, and communicating with each other. You'll need to create a copy under your own GitHub account, a.k.a. "fork" it. You'll make your changes to this copy, which can then later be merged into the Python Discord repository. +*Note: Members of the Python Discord staff can create feature branches directly on the repo without forking it.* + Check out our [**guide on forking a GitHub repo**](./forking-repository/). Now that you have your own fork you need to be able to make changes to the code. You can clone the repo to your local machine, commit changes to it there, then push those changes to GitHub. -- cgit v1.2.3 From 2470557cb6f4ce9eb10bdf1759f67b03e1506b6e Mon Sep 17 00:00:00 2001 From: Cam Caswell Date: Sun, 8 May 2022 12:33:59 -0400 Subject: Add Making Changes step --- .../apps/content/resources/guides/pydis-guides/contributing.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index d67a827f..6231fe87 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -126,7 +126,12 @@ The first step to any new contribution is an issue describing a problem with the Don't move forward until your issue is approved by a Core Developer. Issues are not guaranteed to be approved so your work may be wasted. {: .notification .is-warning } -### 5. Open a pull request +### 5. Make changes +Now it is time to make the changes to fulfill your approved issue. You should create a new Git branch for your feature; that way you can keep your main branch up to date with ours and even work on multiple features at once in separate branches. + +This is a good time to review [how to write good commit messages](./contributing-guidelines/commit-messages) if you haven't already. + +### 6. Open a pull request After your issue has been approved and you've written your code and tested it, it's time to open a pull request. Pull requests are a feature in GitHub; you can think of them as asking the project maintainers to accept your changes. This gives other contributors a chance to review your code and make any needed changes before it's merged into the main branch of the project. Check out our [**Pull Request Guide**](./pull-requests/) for help with opening a pull request and going through the review process. -- cgit v1.2.3 From 958408461607e20f888fdef0eb16fa7bd05b8568 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Mon, 20 Jun 2022 16:11:30 +0400 Subject: Update subclassing_bot.md --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 -- 1 file changed, 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 381f25f1..93d65b35 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -56,5 +56,3 @@ async def example(ctx): # In this case, this will print Hello World! ``` With either of the above examples, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. - -To access the custom bot attributes set in the subclass, in the main bot file (in the context of the above example), `bot.variable_name` would be used, and as for cogs, it would be `self.bot.variable_name`. For the custom methods set, in the main file it would be `bot.custom_method()` in the main file and `self.bot.custom_method()` in a cog file. -- cgit v1.2.3 From 4ec0fb3e6102c0f5a99c51afcec38eb5d0dfa6ae Mon Sep 17 00:00:00 2001 From: Blue-Puddle Date: Tue, 28 Jun 2022 06:23:50 +0100 Subject: added discord-app-commands.md --- .../guides/python-guides/discord-app-commands.md | 451 +++++++++++++++++++++ 1 file changed, 451 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md new file mode 100644 index 00000000..79d224a1 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -0,0 +1,451 @@ +--- +title: Slash Commands with discord.py! +description: A simple guide to creating slash commands within discord.py! +--- +# DISCORD.PY RESUMPTION CHANGES + +--- + +Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). + +# Why this gist? + +--- + +This Gist is being created as an update to slash commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! + +# What Are Slash Commands? + +--- + +Slash Commands are the exciting way to build and interact with bots on Discord. With Slash Commands, all you have to do is type / and you're ready to use your favourite bot. You can easily see all the commands a bot has, and validation and error handling help you get the command right the first time. + +# Install the latest version for discord.py + +--- +To use slash commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! +And make sure to uninstall any third party libraries that support slash commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! + +The latest and up-to-date usable discord.py version can be installed using `pip install -U git+https://github.com/Rapptz/discord.py`. + +If you get an error such as: `'git' is not recognized...`. [Install git](https://git-scm.com/downloads) for your platform. Go through the required steps for installing git and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U git+https://github.com/Rapptz/discord.py` again to install discord.py 2.0. +**BEFORE MIGRATING TO DISCORD.PY 2.0, PLEASE READ THE CONSEQUENCES OF THE UPDATE [HERE](https://discordpy.readthedocs.io/en/latest/migrating.html)**. + +# Basic Structure for Discord.py Slash Commands! + +--- + +### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. +Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create slash commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. + +# Fundamentals for this gist! + +--- + + +The fundamental for this gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot class which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. +Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. + +__**FOLLOWING IS THE EXAMPLE OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ + +```python +import discord + +'''This is one way of creating a "setup_hook" method''' + +class SlashClient(discord.Client): + def __init__(self) -> None: + super().__init__(intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + #perform tasks + +'''Another way of creating a "setup_hook" is as follows''' + +client = discord.Client(intents=discord.Intents.default()) +async def my_setup_hook() -> None: + #perform tasks + +client.setup_hook = my_setup_hook +``` + +# Basic Slash Command application using discord.py. + +#### The `CommandTree` class resides within the `app_commands` of discord.py package. +--- + +## Slash Command Application with a Client + +```python +import discord + +class SlashClient(discord.Client): + def __init__(self) -> None: + super().__init__(intents=discord.Intents.default()) + self.tree = discord.app_commands.CommandTree(self) + + async def setup_hook(self) -> None: + self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) + await self.tree.sync() + +client = SlashClient() + +@client.tree.command(name="ping", description="...") +async def _ping(interaction: discord.Interaction) -> None: + await interaction.response.send_message("pong") + +client.run("token") +``` + + +__**EXPLANATION**__ + +- `import discord` imports the **discord.py** package. +- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. +- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. +- Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. +- And the classic old `client.run("token")` is used to connect the client to the discord gateway. +- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. I will discuss about how to handle this issue later following the gist. + +## Slash Command Application with a Bot + +```python +import discord + +class SlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix=".", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) + await self.tree.sync() + +bot = SlashBot() + +@bot.tree.command(name="ping", description="...") +async def _ping(interaction: discord.Interaction) -> None: + await interaction.response.send_message("pong") + +bot.run("token") +``` + +The above example shows a basic slash commands within discord.py using the Bot class. + +__**EXPLANATION**__ + +Most of the explanation is the same as the prior example which featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. + +- The `SlashBot` class now subclasses `discord.ext.commands.Bot` following the passing in of the required arguments to its `__init__` method. +- `discord.ext.commands.Bot` already consists of an instance of the `CommandTree` class which can be accessed using the `tree` property. + +# Slash Commands within a Cog! + +--- + +A cog is a collection of commands, listeners, and optional state to help group commands together. More information on them can be found on the [Cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs) page. + +## An Example to using cogs with discord.py for slash commands! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashCog(commands.Cog): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashCog(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ + +- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` directory from the **discord.py** root directory. `from discord.ext import commands` imports the commands extension. +- Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). +- `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. +- Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for slash commands with **self** added as the first parameter to the function as it is a method of a class. +- The next up lines are mostly the same. +- Talking about the first line inside the `setup_hook` is the `add_cog` method of the **Bot** class. And since **self** acts as the **instance** of the current class, we use **self** to use the `add_cog` method of the **Bot** class as we are inside a subclassed class of the **Bot** class. Then we pass in **self** to the `add_cog` method as the `__init__` function of the **MySlashCog** cog accepts a `Bot` object. +- After that we instantiate the `MySlashBot` class and run the bot using the **run** method which executes our setup_hook function and our commands get loaded and synced. The bot is now ready to use! + +# An Example to using groups with discord.py for slash commands! + +--- + +## An example with optional group! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashGroupCog(commands.Cog): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + #-------------------------------------------------------- + group = app_commands.Group(name="uwu", description="...") + #-------------------------------------------------------- + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.) -> None: + await interaction.response.send_message("pong!") + + @group.command(name="command", description="...") + async def _cmd(self, interaction: discord.Interaction) -> None: + await interaction.response.send_message("uwu") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashGroupCog(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ +- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. + +--- + +## An example with a **Group** subclass! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashGroup(commands.GroupCog, name="uwu"): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + super().__init__() + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.) -> None: + await interaction.response.send_message("pong!") + + @app_commands.command(name="command", description="...") + async def _cmd(self, interaction: discord.Interaction) -> None: + await interaction.response.send_message("uwu") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashGroup(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ +- The only difference here too is that the `MySlashGroup` class directly subclasses the **GroupCog** class from discord.ext.commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. + + +# Some common methods and features used for slash commands. + +--- + +### A common function used for slash commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix=".", intents=discord.Intents.default()) +#sync the commands + +@bot.tree.command(name="echo", description="...") +@app_commands.describe(text="The text to send!", channel="The channel to send the message in!") +async def _echo(interaction: discord.Interaction, text: str, channel: discord.TextChannel=None): + channel = interaction.channel or channel + await channel.send(text) +``` + +### Another common issue that most people come across is the time duraction of sending a message with `send_message`. This issue can be tackled by deferring the interaction response using the `defer` method of the `InteractionResponse` class. An example for fixing this issue is shown below. + +```python +import discord +from discord.ext import commands +import asyncio + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync the commands + +@bot.tree.command(name="time", description="...") +async def _time(interaction: discord.Interaction, time_to_wait: int): + # ------------------------------------------------------------- + await interaction.response.defer(ephemeral=True, thinking=True) + # ------------------------------------------------------------- + await interaction.edit_original_message(content=f"I will notify you after {time_to_wait} seconds have passed!") + await asyncio.sleep(time_to_wait) + await interaction.edit_original_message(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") +``` + +# Checking for Permissions and Roles! + +--- + +To add a permissions check to a command, the methods are imported through `discord.app_commands.checks`. To check for a member's permissions, the function can be decorated with the [discord.app_commands.checks.has_permissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=has_permissions#discord.app_commands.checks.has_permissions) method. An example to this as follows. + +```py +from discord import app_commands +from discord.ext import commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +@app_commands.checks.has_permissions(manage_messages=True, manage_channels=True) #example permissions +async def _ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +``` + +If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! I will discuss about making an error handler later in the gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). + +Other methods that you can decorate the commands with are - +- `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. +- `has_role` | This checks if the slash command user has the required role or not. Only **ONE** role name or role ID can be passed to this. If the name is being passed, make sure to have the exact same name as the role name. This raises a [MissingRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingRole) exception. +- To pass in several role names or role IDs, `has_any_role` can be used to decorate a command. This raises two exceptions -> [MissingAnyRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingAnyRole) and [NoPrivateMessage](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.NoPrivateMessage) + + +# Adding cooldowns to slash commands! + +--- + +Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. +An example is as follows. + +```python +from discord.ext import commands +import discord + +class Bot(commands.Bot): + def __init__(self): + super().__init__(command_prefix="uwu", intents=discord.Intents.all()) + + + async def setup_hook(self): + self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) + await self.tree.sync() + + +bot = Bot() + +@bot.tree.command(name="ping") +# ----------------------------------------- +@discord.app_commands.checks.cooldown(1, 30) +# ----------------------------------------- +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +bot.run("token") +``` + +__**EXPLANATION**__ +- The first argument the `cooldown` method takes is the amount of times the command can be run in a specific period of time. +- The second argument it takes is the period of time in which the command can be run the specified number of times. +- The `CommandOnCooldown` exception can be handled using an error handler. I will discuss about making an error handler for slash commands later in the gist. + + +# Handling errors for slash commands! + +--- + +The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the slash commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). +An example to creating an error handler for slash commands is as follows. + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +app_commands.checks.cooldown(1, 30) +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +async def on_tree_error(interaction: discord.Interaction, error: app_commands.AppCommandError): + if isinstance(error, app_commands.CommandOnCooldown): + return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") + + elif isinstance(..., ...): + ... + + else: + raise error + +bot.tree.on_error = on_tree_error + +bot.run("token") +``` + +__**EXPLANATION**__ + +First we create a simple function named as `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here I have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. After creating the error handler function, we set the function as the error handler for the slash commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. + +### Creating an error handler for a specific error! + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +app_commands.checks.cooldown(1, 30) +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +@ping.error +async def ping_error(interaction: discord.Interaction, error: app_commands.AppCommandError): + if isinstance(error, app_commands.CommandOnCooldown): + return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") + + elif isinstance(..., ...): + ... + + else: + raise error + +bot.run("token") +``` + +__**EXPLANATION**__ + +Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. \ No newline at end of file -- cgit v1.2.3 From 1e59d608eb5f54b238aa55587a7bc9bfa32346d4 Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Tue, 28 Jun 2022 13:20:06 -0500 Subject: Fix EOF Add a newline at the end of file --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 79d224a1..57423fa4 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -448,4 +448,4 @@ bot.run("token") __**EXPLANATION**__ -Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. \ No newline at end of file +Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. -- cgit v1.2.3 From ce144ef99340339af732d41aa56714022f8a023f Mon Sep 17 00:00:00 2001 From: Robin5605 Date: Tue, 28 Jun 2022 13:47:01 -0500 Subject: Fix trailing whitespaces --- .../guides/python-guides/discord-app-commands.md | 56 +++++++++++----------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 57423fa4..e6095252 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -56,12 +56,12 @@ import discord class SlashClient(discord.Client): def __init__(self) -> None: super().__init__(intents=discord.Intents.default()) - + async def setup_hook(self) -> None: #perform tasks '''Another way of creating a "setup_hook" is as follows''' - + client = discord.Client(intents=discord.Intents.default()) async def my_setup_hook() -> None: #perform tasks @@ -83,7 +83,7 @@ class SlashClient(discord.Client): def __init__(self) -> None: super().__init__(intents=discord.Intents.default()) self.tree = discord.app_commands.CommandTree(self) - + async def setup_hook(self) -> None: self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) await self.tree.sync() @@ -100,11 +100,11 @@ client.run("token") __**EXPLANATION**__ -- `import discord` imports the **discord.py** package. -- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. -- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. -- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. +- `import discord` imports the **discord.py** package. +- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. +- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. - Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. - And the classic old `client.run("token")` is used to connect the client to the discord gateway. - Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. I will discuss about how to handle this issue later following the gist. @@ -117,7 +117,7 @@ import discord class SlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix=".", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) await self.tree.sync() @@ -156,20 +156,20 @@ from discord import app_commands class MySlashCog(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot = bot - + @app_commands.command(name="ping", description="...") async def _ping(self, interaction: discord.Interaction): await interaction.response.send_message("pong!") - + class MySlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix="!", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: await self.add_cog(MySlashCog(self)) await self.tree.copy_global_to(discord.Object(id=123456789098765432)) await self.tree.sync() - + bot = MySlashBot() bot.run("token") @@ -207,20 +207,20 @@ class MySlashGroupCog(commands.Cog): @app_commands.command(name="ping", description="...") async def _ping(self, interaction: discord.) -> None: await interaction.response.send_message("pong!") - + @group.command(name="command", description="...") async def _cmd(self, interaction: discord.Interaction) -> None: await interaction.response.send_message("uwu") - + class MySlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix="!", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: await self.add_cog(MySlashGroupCog(self)) await self.tree.copy_global_to(discord.Object(id=123456789098765432)) await self.tree.sync() - + bot = MySlashBot() bot.run("token") @@ -246,20 +246,20 @@ class MySlashGroup(commands.GroupCog, name="uwu"): @app_commands.command(name="ping", description="...") async def _ping(self, interaction: discord.) -> None: await interaction.response.send_message("pong!") - + @app_commands.command(name="command", description="...") async def _cmd(self, interaction: discord.Interaction) -> None: await interaction.response.send_message("uwu") - + class MySlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix="!", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: await self.add_cog(MySlashGroup(self)) await self.tree.copy_global_to(discord.Object(id=123456789098765432)) await self.tree.sync() - + bot = MySlashBot() bot.run("token") @@ -271,7 +271,7 @@ __**EXPLANATION**__ # Some common methods and features used for slash commands. ---- +--- ### A common function used for slash commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. @@ -353,13 +353,13 @@ import discord class Bot(commands.Bot): def __init__(self): super().__init__(command_prefix="uwu", intents=discord.Intents.all()) - - + + async def setup_hook(self): - self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) + self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) await self.tree.sync() - - + + bot = Bot() @bot.tree.command(name="ping") @@ -374,7 +374,7 @@ bot.run("token") __**EXPLANATION**__ - The first argument the `cooldown` method takes is the amount of times the command can be run in a specific period of time. -- The second argument it takes is the period of time in which the command can be run the specified number of times. +- The second argument it takes is the period of time in which the command can be run the specified number of times. - The `CommandOnCooldown` exception can be handled using an error handler. I will discuss about making an error handler for slash commands later in the gist. -- cgit v1.2.3 From b6ac1f2f7c402411a29f1cfee10d79abb7c001d0 Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 15:59:16 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index e6095252..431ab095 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -102,7 +102,7 @@ __**EXPLANATION**__ - `import discord` imports the **discord.py** package. - `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. -- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commands, and binds it to the `discord.Client` subclass instance, so wherever you have access to it, you will also have access to the command tree. - Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. - Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. - Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. -- cgit v1.2.3 From b237e81890836343295bd84b80ff5b34ef05ab92 Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 15:59:26 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../resources/guides/python-guides/discord-app-commands.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 431ab095..1a6e2453 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -6,7 +6,15 @@ description: A simple guide to creating slash commands within discord.py! --- -Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). +Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library include: + +- Buttons support +- Select Menus support +- Forms (AKA Modals) +- Slash commands (AKA Application Commands) +...and a bunch more handy features! + +All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). # Why this gist? -- cgit v1.2.3 From 823a6d2e3ebe7667b6bb2e2cc49635b4684cefcc Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 16:00:51 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md A good point indeed Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 1a6e2453..d5f204b0 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -111,7 +111,7 @@ __**EXPLANATION**__ - `import discord` imports the **discord.py** package. - `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. - Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commands, and binds it to the `discord.Client` subclass instance, so wherever you have access to it, you will also have access to the command tree. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. **Without calling this method, your changes will only be saved locally and will NOT show up on Discord!** - Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. - Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. - And the classic old `client.run("token")` is used to connect the client to the discord gateway. -- cgit v1.2.3 From 2a8b2f4b764c83584972224ad2cf8c625e6712e1 Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 16:01:33 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index d5f204b0..7d7239e2 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -133,7 +133,7 @@ class SlashBot(commands.Bot): bot = SlashBot() @bot.tree.command(name="ping", description="...") -async def _ping(interaction: discord.Interaction) -> None: +async def ping(interaction: discord.Interaction) -> None: await interaction.response.send_message("pong") bot.run("token") -- cgit v1.2.3 From 7e5fe0bab6e2b97d2fc4e855d05573ca02801caf Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 16:03:16 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 7d7239e2..1f5a0ff3 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -166,7 +166,7 @@ class MySlashCog(commands.Cog): self.bot = bot @app_commands.command(name="ping", description="...") - async def _ping(self, interaction: discord.Interaction): + async def ping(self, interaction: discord.Interaction): await interaction.response.send_message("pong!") class MySlashBot(commands.Bot): -- cgit v1.2.3 From fff37e8bfd0f3ace81235a00b0d343cd8ba21383 Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 16:03:36 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md quite alright Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 1f5a0ff3..65c0b025 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -410,7 +410,7 @@ async def on_tree_error(interaction: discord.Interaction, error: app_commands.Ap if isinstance(error, app_commands.CommandOnCooldown): return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - elif isinstance(..., ...): + elif isinstance(error, ...): ... else: -- cgit v1.2.3 From ca3cb63131839258cdec5d28317a90193a15f082 Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 16:03:57 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 65c0b025..02a56ba6 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -436,7 +436,7 @@ bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) #sync commands @bot.tree.command(name="ping") -app_commands.checks.cooldown(1, 30) +@app_commands.checks.cooldown(1, 30) async def ping(interaction: discord.Interaction): await interaction.response.send_message("pong!") -- cgit v1.2.3 From 9344c927c4e4deba148202f23b7803c775d698a6 Mon Sep 17 00:00:00 2001 From: Ash <92868529+Ash-02014@users.noreply.github.com> Date: Fri, 1 Jul 2022 16:05:07 +0100 Subject: Update pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/discord-app-commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md index 02a56ba6..917c63a1 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md @@ -445,7 +445,7 @@ async def ping_error(interaction: discord.Interaction, error: app_commands.AppCo if isinstance(error, app_commands.CommandOnCooldown): return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - elif isinstance(..., ...): + elif isinstance(error, ...): ... else: -- cgit v1.2.3 From 7475676fddb5b815e8ff24de3b5d094cda66439e Mon Sep 17 00:00:00 2001 From: Blue-Puddle Date: Fri, 1 Jul 2022 16:15:16 +0100 Subject: add app_commands.md --- .../resources/guides/python-guides/app_commands.md | 448 ++++++++++++++++++++ .../guides/python-guides/discord-app-commands.md | 459 --------------------- 2 files changed, 448 insertions(+), 459 deletions(-) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/app_commands.md delete mode 100644 pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md new file mode 100644 index 00000000..d97b849a --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -0,0 +1,448 @@ +# DISCORD.PY RESUMATION CHANGES + +--- + +Upon resumation of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumation can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). + +# Why this gist? + +--- + +This Gist is being created as an update to slash commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! + +# What Are Slash Commands? + +--- + +Slash Commands are the exciting way to build and interact with bots on Discord. With Slash Commands, all you have to do is type / and you're ready to use your favourite bot. You can easily see all the commands a bot has, and validation and error handling help you get the command right the first time. + +# Install the latest version for discord.py + +--- +To use slash commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! +And make sure to uninstall any third party libraries that support slash commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! + +The latest and up-to-date usable discord.py version can be installed using `pip install -U git+https://github.com/Rapptz/discord.py`. + +If you get an error such as: `'git' is not recognized...`. [Install git](https://git-scm.com/downloads) for your platform. Go through the required steps for installing git and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U git+https://github.com/Rapptz/discord.py` again to install discord.py 2.0. +**BEFORE MIGRATING TO DISCORD.PY 2.0, PLEASE READ THE CONSEQUENCES OF THE UPDATE [HERE](https://discordpy.readthedocs.io/en/latest/migrating.html)**. + +# Basic Structure for Discord.py Slash Commands! + +--- + +### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. +Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create slash commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. + +# Fundamentals for this gist! + +--- + + +The fundamental for this gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot class which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. +Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. + +__**FOLLOWING IS THE EXAMPLE OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ + +```python +import discord + +'''This is one way of creating a "setup_hook" method''' + +class SlashClient(discord.Client): + def __init__(self) -> None: + super().__init__(intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + #perform tasks + +'''Another way of creating a "setup_hook" is as follows''' + +client = discord.Client(intents=discord.Intents.default()) +async def my_setup_hook() -> None: + #perform tasks + +client.setup_hook = my_setup_hook +``` + +# Basic Slash Command application using discord.py. + +#### The `CommandTree` class resides within the `app_commands` of discord.py package. +--- + +## Slash Command Application with a Client + +```python +import discord + +class SlashClient(discord.Client): + def __init__(self) -> None: + super().__init__(intents=discord.Intents.default()) + self.tree = discord.app_commands.CommandTree(self) + + async def setup_hook(self) -> None: + self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) + await self.tree.sync() + +client = SlashClient() + +@client.tree.command(name="ping", description="...") +async def _ping(interaction: discord.Interaction) -> None: + await interaction.response.send_message("pong") + +client.run("token") +``` + + +__**EXPLANATION**__ + +- `import discord` imports the **discord.py** package. +- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. +- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. +- Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. +- And the classic old `client.run("token")` is used to connect the client to the discord gateway. +- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. I will discuss about how to handle this issue later following the gist. + +## Slash Command Application with a Bot + +```python +import discord + +class SlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix=".", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) + await self.tree.sync() + +bot = SlashBot() + +@bot.tree.command(name="ping", description="...") +async def _ping(interaction: discord.Interaction) -> None: + await interaction.response.send_message("pong") + +bot.run("token") +``` + +The above example shows a basic slash commands within discord.py using the Bot class. + +__**EXPLANATION**__ + +Most of the explanation is the same as the prior example which featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. + +- The `SlashBot` class now subclasses `discord.ext.commands.Bot` following the passing in of the required arguments to its `__init__` method. +- `discord.ext.commands.Bot` already consists of an instance of the `CommandTree` class which can be accessed using the `tree` property. + +# Slash Commands within a Cog! + +--- + +A cog is a collection of commands, listeners, and optional state to help group commands together. More information on them can be found on the [Cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs) page. + +## An Example to using cogs with discord.py for slash commands! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashCog(commands.Cog): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashCog(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ + +- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` directory from the **discord.py** root directory. `from discord.ext import commands` imports the commands extension. +- Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). +- `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. +- Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for slash commands with **self** added as the first parameter to the function as it is a method of a class. +- The next up lines are mostly the same. +- Talking about the first line inside the `setup_hook` is the `add_cog` method of the **Bot** class. And since **self** acts as the **instance** of the current class, we use **self** to use the `add_cog` method of the **Bot** class as we are inside a subclassed class of the **Bot** class. Then we pass in **self** to the `add_cog` method as the `__init__` function of the **MySlashCog** cog accepts a `Bot` object. +- After that we instantiate the `MySlashBot` class and run the bot using the **run** method which executes our setup_hook function and our commands get loaded and synced. The bot is now ready to use! + +# An Example to using groups with discord.py for slash commands! + +--- + +## An example with optional group! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashGroupCog(commands.Cog): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + #-------------------------------------------------------- + group = app_commands.Group(name="uwu", description="...") + #-------------------------------------------------------- + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.) -> None: + await interaction.response.send_message("pong!") + + @group.command(name="command", description="...") + async def _cmd(self, interaction: discord.Interaction) -> None: + await interaction.response.send_message("uwu") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashGroupCog(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ +- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. + +--- + +## An example with a **Group** subclass! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashGroup(app_commands.Group, name="uwu"): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + super().__init__() + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.) -> None: + await interaction.response.send_message("pong!") + + @app_commands.command(name="command", description="...") + async def _cmd(self, interaction: discord.Interaction) -> None: + await interaction.response.send_message("uwu") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashGroup(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ +- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. + + +# Some common methods and features used for slash commands. + +--- + +### A common function used for slash commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix=".", intents=discord.Intents.default()) +#sync the commands + +@bot.tree.command(name="echo", description="...") +@app_commands.describe(text="The text to send!", channel="The channel to send the message in!") +async def _echo(interaction: discord.Interaction, text: str, channel: discord.TextChannel=None): + channel = interaction.channel or channel + await channel.send(text) +``` + +### Another common issue that most people come across is the time duraction of sending a message with `send_message`. This issue can be tackled by deferring the interaction response using the `defer` method of the `InteractionResponse` class. An example for fixing this issue is shown below. + +```python +import discord +from discord.ext import commands +import asyncio + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync the commands + +@bot.tree.command(name="time", description="...") +async def _time(interaction: discord.Interaction, time_to_wait: int): + # ------------------------------------------------------------- + await interaction.response.defer(ephemeral=True, thinking=True) + # ------------------------------------------------------------- + await interaction.edit_original_message(content=f"I will notify you after {time_to_wait} seconds have passed!") + await asyncio.sleep(time_to_wait) + await interaction.edit_original_message(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") +``` + +# Checking for Permissions and Roles! + +--- + +To add a permissions check to a command, the methods are imported through `discord.app_commands.checks`. To check for a member's permissions, the function can be decorated with the [discord.app_commands.checks.has_permissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=has_permissions#discord.app_commands.checks.has_permissions) method. An example to this as follows. + +```py +from discord import app_commands +from discord.ext import commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +@app_commands.checks.has_permissions(manage_messages=True, manage_channels=True) #example permissions +async def _ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +``` + +If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! I will discuss about making an error handler later in the gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). + +Other methods that you can decorate the commands with are - +- `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. +- `has_role` | This checks if the slash command user has the required role or not. Only **ONE** role name or role ID can be passed to this. If the name is being passed, make sure to have the exact same name as the role name. This raises a [MissingRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingRole) exception. +- To pass in several role names or role IDs, `has_any_role` can be used to decorate a command. This raises two exceptions -> [MissingAnyRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingAnyRole) and [NoPrivateMessage](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.NoPrivateMessage) + + +# Adding cooldowns to slash commands! + +--- + +Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. +An example is as follows. + +```python +from discord.ext import commands +import discord + +class Bot(commands.Bot): + def __init__(self): + super().__init__(command_prefix="uwu", intents=discord.Intents.all()) + + + async def setup_hook(self): + self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) + await self.tree.sync() + + +bot = Bot() + +@bot.tree.command(name="ping") +# ----------------------------------------- +@discord.app_commands.checks.cooldown(1, 30) +# ----------------------------------------- +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +bot.run("token") +``` + +__**EXPLANATION**__ +- The first argument the `cooldown` method takes is the amount of times the command can be run in a specific period of time. +- The second argument it takes is the period of time in which the command can be run the specified number of times. +- The `CommandOnCooldown` exception can be handled using an error handler. I will discuss about making an error handler for slash commands later in the gist. + + +# Handling errors for slash commands! + +--- + +The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the slash commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). +An example to creating an error handler for slash commands is as follows. + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +@app_commands.checks.cooldown(1, 30) +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +async def on_tree_error(interaction: discord.Interaction, error: app_commands.AppCommandError): + if isinstance(error, app_commands.CommandOnCooldown): + return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") + + elif isinstance(..., ...): + ... + + else: + raise error + +bot.tree.on_error = on_tree_error + +bot.run("token") +``` + +__**EXPLANATION**__ + +First we create a simple function named as `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here I have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displayed unhandled errors, i.e. the ones which have not been specificed manually. If this is **removed**, you will not be able to see any exceptions raised due to slash commands and makes debugging the code harder. +After creating the error handler function, we set the function as the error handler for the slash commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. + +### Creating an error handler for a specific error! + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +app_commands.checks.cooldown(1, 30) +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +@ping.error +async def ping_error(interaction: discord.Interaction, error: app_commands.AppCommandError): + if isinstance(error, app_commands.CommandOnCooldown): + return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") + + elif isinstance(error, ...): + ... + + else: + raise error + +bot.run("token") +``` + +__**EXPLANATION**__ + +Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. \ No newline at end of file diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md deleted file mode 100644 index 917c63a1..00000000 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-app-commands.md +++ /dev/null @@ -1,459 +0,0 @@ ---- -title: Slash Commands with discord.py! -description: A simple guide to creating slash commands within discord.py! ---- -# DISCORD.PY RESUMPTION CHANGES - ---- - -Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library include: - -- Buttons support -- Select Menus support -- Forms (AKA Modals) -- Slash commands (AKA Application Commands) -...and a bunch more handy features! - -All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). - -# Why this gist? - ---- - -This Gist is being created as an update to slash commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! - -# What Are Slash Commands? - ---- - -Slash Commands are the exciting way to build and interact with bots on Discord. With Slash Commands, all you have to do is type / and you're ready to use your favourite bot. You can easily see all the commands a bot has, and validation and error handling help you get the command right the first time. - -# Install the latest version for discord.py - ---- -To use slash commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! -And make sure to uninstall any third party libraries that support slash commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! - -The latest and up-to-date usable discord.py version can be installed using `pip install -U git+https://github.com/Rapptz/discord.py`. - -If you get an error such as: `'git' is not recognized...`. [Install git](https://git-scm.com/downloads) for your platform. Go through the required steps for installing git and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U git+https://github.com/Rapptz/discord.py` again to install discord.py 2.0. -**BEFORE MIGRATING TO DISCORD.PY 2.0, PLEASE READ THE CONSEQUENCES OF THE UPDATE [HERE](https://discordpy.readthedocs.io/en/latest/migrating.html)**. - -# Basic Structure for Discord.py Slash Commands! - ---- - -### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. -Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create slash commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. - -# Fundamentals for this gist! - ---- - - -The fundamental for this gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot class which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. -Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. - -__**FOLLOWING IS THE EXAMPLE OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ - -```python -import discord - -'''This is one way of creating a "setup_hook" method''' - -class SlashClient(discord.Client): - def __init__(self) -> None: - super().__init__(intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - #perform tasks - -'''Another way of creating a "setup_hook" is as follows''' - -client = discord.Client(intents=discord.Intents.default()) -async def my_setup_hook() -> None: - #perform tasks - -client.setup_hook = my_setup_hook -``` - -# Basic Slash Command application using discord.py. - -#### The `CommandTree` class resides within the `app_commands` of discord.py package. ---- - -## Slash Command Application with a Client - -```python -import discord - -class SlashClient(discord.Client): - def __init__(self) -> None: - super().__init__(intents=discord.Intents.default()) - self.tree = discord.app_commands.CommandTree(self) - - async def setup_hook(self) -> None: - self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) - await self.tree.sync() - -client = SlashClient() - -@client.tree.command(name="ping", description="...") -async def _ping(interaction: discord.Interaction) -> None: - await interaction.response.send_message("pong") - -client.run("token") -``` - - -__**EXPLANATION**__ - -- `import discord` imports the **discord.py** package. -- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. -- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commands, and binds it to the `discord.Client` subclass instance, so wherever you have access to it, you will also have access to the command tree. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. **Without calling this method, your changes will only be saved locally and will NOT show up on Discord!** -- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. -- Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. -- And the classic old `client.run("token")` is used to connect the client to the discord gateway. -- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. I will discuss about how to handle this issue later following the gist. - -## Slash Command Application with a Bot - -```python -import discord - -class SlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix=".", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) - await self.tree.sync() - -bot = SlashBot() - -@bot.tree.command(name="ping", description="...") -async def ping(interaction: discord.Interaction) -> None: - await interaction.response.send_message("pong") - -bot.run("token") -``` - -The above example shows a basic slash commands within discord.py using the Bot class. - -__**EXPLANATION**__ - -Most of the explanation is the same as the prior example which featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. - -- The `SlashBot` class now subclasses `discord.ext.commands.Bot` following the passing in of the required arguments to its `__init__` method. -- `discord.ext.commands.Bot` already consists of an instance of the `CommandTree` class which can be accessed using the `tree` property. - -# Slash Commands within a Cog! - ---- - -A cog is a collection of commands, listeners, and optional state to help group commands together. More information on them can be found on the [Cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs) page. - -## An Example to using cogs with discord.py for slash commands! - -```python -import discord -from discord.ext import commands -from discord import app_commands - -class MySlashCog(commands.Cog): - def __init__(self, bot: commands.Bot) -> None: - self.bot = bot - - @app_commands.command(name="ping", description="...") - async def ping(self, interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -class MySlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix="!", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - await self.add_cog(MySlashCog(self)) - await self.tree.copy_global_to(discord.Object(id=123456789098765432)) - await self.tree.sync() - -bot = MySlashBot() - -bot.run("token") -``` - -__**EXPLANATION**__ - -- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` directory from the **discord.py** root directory. `from discord.ext import commands` imports the commands extension. -- Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). -- `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. -- Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for slash commands with **self** added as the first parameter to the function as it is a method of a class. -- The next up lines are mostly the same. -- Talking about the first line inside the `setup_hook` is the `add_cog` method of the **Bot** class. And since **self** acts as the **instance** of the current class, we use **self** to use the `add_cog` method of the **Bot** class as we are inside a subclassed class of the **Bot** class. Then we pass in **self** to the `add_cog` method as the `__init__` function of the **MySlashCog** cog accepts a `Bot` object. -- After that we instantiate the `MySlashBot` class and run the bot using the **run** method which executes our setup_hook function and our commands get loaded and synced. The bot is now ready to use! - -# An Example to using groups with discord.py for slash commands! - ---- - -## An example with optional group! - -```python -import discord -from discord.ext import commands -from discord import app_commands - -class MySlashGroupCog(commands.Cog): - def __init__(self, bot: commands.Bot) -> None: - self.bot = bot - - #-------------------------------------------------------- - group = app_commands.Group(name="uwu", description="...") - #-------------------------------------------------------- - - @app_commands.command(name="ping", description="...") - async def _ping(self, interaction: discord.) -> None: - await interaction.response.send_message("pong!") - - @group.command(name="command", description="...") - async def _cmd(self, interaction: discord.Interaction) -> None: - await interaction.response.send_message("uwu") - -class MySlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix="!", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - await self.add_cog(MySlashGroupCog(self)) - await self.tree.copy_global_to(discord.Object(id=123456789098765432)) - await self.tree.sync() - -bot = MySlashBot() - -bot.run("token") -``` - -__**EXPLANATION**__ -- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. - ---- - -## An example with a **Group** subclass! - -```python -import discord -from discord.ext import commands -from discord import app_commands - -class MySlashGroup(commands.GroupCog, name="uwu"): - def __init__(self, bot: commands.Bot) -> None: - self.bot = bot - super().__init__() - - @app_commands.command(name="ping", description="...") - async def _ping(self, interaction: discord.) -> None: - await interaction.response.send_message("pong!") - - @app_commands.command(name="command", description="...") - async def _cmd(self, interaction: discord.Interaction) -> None: - await interaction.response.send_message("uwu") - -class MySlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix="!", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - await self.add_cog(MySlashGroup(self)) - await self.tree.copy_global_to(discord.Object(id=123456789098765432)) - await self.tree.sync() - -bot = MySlashBot() - -bot.run("token") -``` - -__**EXPLANATION**__ -- The only difference here too is that the `MySlashGroup` class directly subclasses the **GroupCog** class from discord.ext.commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. - - -# Some common methods and features used for slash commands. - ---- - -### A common function used for slash commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. - -```python -from discord.ext import commands -from discord import app_commands -import discord - -bot = commands.Bot(command_prefix=".", intents=discord.Intents.default()) -#sync the commands - -@bot.tree.command(name="echo", description="...") -@app_commands.describe(text="The text to send!", channel="The channel to send the message in!") -async def _echo(interaction: discord.Interaction, text: str, channel: discord.TextChannel=None): - channel = interaction.channel or channel - await channel.send(text) -``` - -### Another common issue that most people come across is the time duraction of sending a message with `send_message`. This issue can be tackled by deferring the interaction response using the `defer` method of the `InteractionResponse` class. An example for fixing this issue is shown below. - -```python -import discord -from discord.ext import commands -import asyncio - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync the commands - -@bot.tree.command(name="time", description="...") -async def _time(interaction: discord.Interaction, time_to_wait: int): - # ------------------------------------------------------------- - await interaction.response.defer(ephemeral=True, thinking=True) - # ------------------------------------------------------------- - await interaction.edit_original_message(content=f"I will notify you after {time_to_wait} seconds have passed!") - await asyncio.sleep(time_to_wait) - await interaction.edit_original_message(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") -``` - -# Checking for Permissions and Roles! - ---- - -To add a permissions check to a command, the methods are imported through `discord.app_commands.checks`. To check for a member's permissions, the function can be decorated with the [discord.app_commands.checks.has_permissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=has_permissions#discord.app_commands.checks.has_permissions) method. An example to this as follows. - -```py -from discord import app_commands -from discord.ext import commands -import discord - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync commands - -@bot.tree.command(name="ping") -@app_commands.checks.has_permissions(manage_messages=True, manage_channels=True) #example permissions -async def _ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -``` - -If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! I will discuss about making an error handler later in the gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). - -Other methods that you can decorate the commands with are - -- `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. -- `has_role` | This checks if the slash command user has the required role or not. Only **ONE** role name or role ID can be passed to this. If the name is being passed, make sure to have the exact same name as the role name. This raises a [MissingRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingRole) exception. -- To pass in several role names or role IDs, `has_any_role` can be used to decorate a command. This raises two exceptions -> [MissingAnyRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingAnyRole) and [NoPrivateMessage](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.NoPrivateMessage) - - -# Adding cooldowns to slash commands! - ---- - -Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. -An example is as follows. - -```python -from discord.ext import commands -import discord - -class Bot(commands.Bot): - def __init__(self): - super().__init__(command_prefix="uwu", intents=discord.Intents.all()) - - - async def setup_hook(self): - self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) - await self.tree.sync() - - -bot = Bot() - -@bot.tree.command(name="ping") -# ----------------------------------------- -@discord.app_commands.checks.cooldown(1, 30) -# ----------------------------------------- -async def ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -bot.run("token") -``` - -__**EXPLANATION**__ -- The first argument the `cooldown` method takes is the amount of times the command can be run in a specific period of time. -- The second argument it takes is the period of time in which the command can be run the specified number of times. -- The `CommandOnCooldown` exception can be handled using an error handler. I will discuss about making an error handler for slash commands later in the gist. - - -# Handling errors for slash commands! - ---- - -The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the slash commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). -An example to creating an error handler for slash commands is as follows. - -```python -from discord.ext import commands -from discord import app_commands -import discord - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync commands - -@bot.tree.command(name="ping") -app_commands.checks.cooldown(1, 30) -async def ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -async def on_tree_error(interaction: discord.Interaction, error: app_commands.AppCommandError): - if isinstance(error, app_commands.CommandOnCooldown): - return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - - elif isinstance(error, ...): - ... - - else: - raise error - -bot.tree.on_error = on_tree_error - -bot.run("token") -``` - -__**EXPLANATION**__ - -First we create a simple function named as `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here I have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. After creating the error handler function, we set the function as the error handler for the slash commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. - -### Creating an error handler for a specific error! - -```python -from discord.ext import commands -from discord import app_commands -import discord - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync commands - -@bot.tree.command(name="ping") -@app_commands.checks.cooldown(1, 30) -async def ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -@ping.error -async def ping_error(interaction: discord.Interaction, error: app_commands.AppCommandError): - if isinstance(error, app_commands.CommandOnCooldown): - return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - - elif isinstance(error, ...): - ... - - else: - raise error - -bot.run("token") -``` - -__**EXPLANATION**__ - -Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. -- cgit v1.2.3 From 589ffad6935a155df4751401f884c523c777b6c6 Mon Sep 17 00:00:00 2001 From: Blue-Puddle Date: Fri, 1 Jul 2022 16:20:33 +0100 Subject: fix app_commands.md --- pydis_site/apps/content/resources/guides/python-guides/app_commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md index d97b849a..821ac577 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -411,7 +411,7 @@ bot.run("token") __**EXPLANATION**__ -First we create a simple function named as `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here I have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displayed unhandled errors, i.e. the ones which have not been specificed manually. If this is **removed**, you will not be able to see any exceptions raised due to slash commands and makes debugging the code harder. +First we create a simple function named as `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here I have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displaying unhandled errors, i.e. the ones which have not been handled manually. If this is **removed**, you will not be able to see any exceptions raised by slash commands and makes debugging the code harder. After creating the error handler function, we set the function as the error handler for the slash commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. ### Creating an error handler for a specific error! -- cgit v1.2.3 From c7b1134cd222541a1d9e56fdc89014f9742eeeaa Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Sun, 10 Jul 2022 20:37:56 +0400 Subject: Update subclassing_bot.md --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 93d65b35..e8b5354a 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -10,7 +10,7 @@ First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a- Subclassing Bot can be very beneficial as it provides you with more control and customisability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be overriden to add more functionality. There are two ways to subclass `commands.Bot`, as shown below: -```py +```python class CustomBot(commands.Bot): def __init__(self): super().__init__( @@ -35,7 +35,7 @@ token = YOUR_TOKEN_HERE bot.run(token) ``` Or -```py +```python class CustomBot(commands.Bot): def __init__(self, *args, **kwargs): # the key-word arguments are not specified here, unlike the example above -- cgit v1.2.3 From 563a632600bac29a45f4ae5153ae0bd9461f4561 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Sun, 10 Jul 2022 20:38:16 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Bluenix --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index e8b5354a..fc1cdb7d 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -1,6 +1,6 @@ --- title: Subclassing Bot -description: "Subclassing the Bot to add more functionality and customisability." +description: "Subclassing the discord.py Bot class to add more functionality and customisability." --- ## Basic Subclassing -- cgit v1.2.3 From f922b76b570062bcef4ec3e9ceffcefe0d60a0d6 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Sun, 10 Jul 2022 20:38:45 +0400 Subject: Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md Co-authored-by: Bluenix --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index fc1cdb7d..91df2199 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -4,7 +4,7 @@ description: "Subclassing the discord.py Bot class to add more functionality and --- ## Basic Subclassing -First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [Bot](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. +First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [`Bot`](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. ## The benefits of subclassing bot Subclassing Bot can be very beneficial as it provides you with more control and customisability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be overriden to add more functionality. -- cgit v1.2.3 From 2d4ba1aa119b6a740ce103d7df39fb0492322252 Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Mon, 18 Jul 2022 23:24:03 +0300 Subject: Create docker-hosting-guide.md --- .../guides/python-guides/docker-hosting-guide.md | 194 +++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md new file mode 100644 index 00000000..3ae732e9 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -0,0 +1,194 @@ +## Contents +1. [You will learn](#you-will-learn) +2. [Introduction](#introduction) +3. [Installing Docker](#installing-docker) +4. [Creating Dockerfile](#creating-dockerfile) +5. [Building Image and Running Container](#building-image-and-running-container) +6. [Creating Volumes](#creating-volumes) +7. [Using GitHub Actions for full automation](#using-github-actions-for-full-automation) + +## You will learn +- how to write Dockerfile +- how to build Docker image and run the container +- how to use docker-compose +- how to make docker keep the files throughout the container's runs +- how to parse environment variables into container +- how to use GitHub Actions for automation +- how to setup self hosted runner +- how to use runner secrets + +## Introduction +Let's say you have got a nice discord bot written in python and you have a VPS to host it on. Now the only question is how to run it 24/7. You might have been suggested to use *screen multiplexer*, but it has some disadvantages: +1. Every time you update the bot you have to SSH to your server, attach to screen, shutdown the bot, run `git pull` and run the bot again. You might have good extensions management that allows you to update the bot without restarting it, but there are some other cons as well +2. If you update some dependencies, you have to update them manually +3. The bot doesn't run in an isolated environment, which is not good for security + +But there's a nice and easy solution to these problems - **Docker**! Docker is a containerization utility that automates some stuff like dependencies update and running the application in the background. So let's get started. + +## Installing Docker +The best way to install the docker is to use the [convenience script](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) provided by Docker developers themselves. You just need 2 lines: +```shell +$ curl -fsSL https://get.docker.com -o get-docker.sh +$ sudo sh get-docker.sh +``` + +## Creating Dockerfile +To tell Docker what it has to do to run the application, we need to create a file named `Dockerfile` in our project's root. + +1. First we need to specify the *base image*. Doing that will make Docker install some apps we need to run our bot, for example the Python interpreter +```dockerfile +FROM python:3.10-bullseye +``` +2. Next, we need to copy our requirements to some directory *inside the container*. Let's call it `/app` +```dockerfile +COPY requirements.txt /app/ +``` +3. Now we need to set the directory as working and install the requirements +```dockerfile +WORKDIR /app +RUN pip install -r requirements.txt +``` +4. The only thing that is left to do is to copy the rest of project's files and run the main executable +```dockerfile +COPY . . +CMD ["python3", "main.py"] +``` + +The final version of Dockerfile looks like this: +```dockerfile +FROM python:3.10-bullseye +COPY requirements.txt /app/ +WORKDIR /app +RUN pip install -r requirements.txt +COPY . . +CMD ["python3", "main.py"] +``` + +## Building Image and Running Container +Now update the project on your VPS and we can run the bot with Docker. +1. Build the image (dot at the end is very important) +```shell +$ docker build -t mybot . +``` +2. Run the container +```shell +$ docker run -d --name mybot mybot:latest +``` +3. Read bot logs (keep in mind that this utility only allows to read STDERR) +```shell +$ docker logs -f mybot +``` +If everything went successfully, your bot will go online and will keep running! + +## Using docker-compose +Just 2 commands to run a container is cool but we can shorten it down to just 1 simple command. For that, create a `docker-compose.yml` file in project's root and fill it with the following contents: +```yml +version: "3.8" +services: + main: + build: . + container-name: mybot +``` +Update the project on VPS, remove the previous container with `docker rm -f mybot` and run this command +```shell +docker-compose up -d --build +``` +Now the docker will automatically build the image for you and run the container. + +## Creating Volumes +The files creating during container run are destroyed after its recreation. To prevent some files from getting destroyed, we need to use *volumes* that basically save the files from directory inside of container somewhere on drive. +1. Create a new directory somewhere and copy path to it +```shell +$ mkdir mybot-data && echo $(pwd)/mybot-data +``` +My path is `/home/exenifix/mybot-data`, yours is most likely different. +2. In your project, store the files that need to be persistant in a separate directory (eg. `data`) +3. Add the `volumes` construction to `docker-compose` so it looks like this: +```yml +version: "3.8" +services: + main: + build: . + container-name: mybot + volumes: + - /home/exenifix/mybot-data:/app/data +``` +The path before the colon `:` is the directory *on drive* and the second path is the directory *inside of container*. All the files saved in container in that directory will be saved on drive's directory as well and Docker will be accessing them *from drive*. + +## Using GitHub Actions for full automation +Now it's time to fully automate the process and make Docker update the bot automatically on every commit or release. For that, we will use a **GitHub Actions workflow**, which basically runs some commands when we need to. You may read more about them [here](https://docs.github.com/en/actions/using-workflows). + +### Create repository secret +We will not have the ability to use `.env` files with the workflow, so it's better to store the environment variables as **actions secrets**. +1. Head to your repository page -> Settings -> Secrets -> Actions +2. Press `New repository secret` +3. Give it a name like `TOKEN` and paste the value +Now we will be able to access its value in workflow like `${{ secrets.TOKEN }}`. However, we also need to parse the variable into container now. Edit `docker-compose` so it looks like this: +```yml +version: "3.8" +services: + main: + build: . + container-name: mybot + volumes: + - /home/exenifix/mybot-data:/app/data + environment: + - TOKEN +``` + +### Setup self-hosted runner +To run the workflow on our VPS, we will need to register it as *self hosted runner*. +1. Head to Settings -> Actions -> Runners +2. Press `New self-hosted runner` +3. Select runner image and architecture +4. Follow the instructions but don't run the runner +5. Instead, create a service +```shell +$ sudo ./svc.sh install +$ sudo ./svc.sh start +``` +Now we have registered our VPS as a self-hosted runner and we can run the workflow on it now. + +### Write a workflow +Create a new file `.github/workflows/runner.yml` and paste the following content into it (it is easy to understand so I am not going to give many comments) +```yml +name: Docker Runner + +on: + push: + branches: [ master ] + +jobs: + run: + runs-on: self-hosted + environment: production + + steps: + - uses: actions/checkout@v3 + + - name: Run Container + run: docker-compose up -d --build + env: + TOKEN: ${{ secrets.TOKEN }} + + - name: Cleanup Unused Images + run: docker image prune -f +``` + +Run `docker rm -f mybot` (it only needs to be done once) and push to GitHub. Now if you open `Actions` tab on your repository, you should see a workflow running your bot. Congratulations! + +### Displaying logs in actions terminal +There's a nice utility for reading docker container's logs and stopping upon meeting a certain phrase and it might be useful for you as well. +1. Install the utility on your VPS with +```shell +$ pip install exendlr +``` +2. Add a step to your workflow that would show the logs until it meets `"ready"` phrase. I recommend putting it before the cleanup. +```yml +- name: Display Logs + run: python3 -m exendlr mybot "ready" +``` +Now you should see the logs of your bot until the stop phrase is met. + +**WARNING** +> The utility only reads from STDERR and redirects to STDERR, if you are using STDOUT for logs, it will not work and will be waiting for stop phrase forever. The utility automatically exits if bot's container is stopped (eg. error occured during starting) or if a log line contains a stop phrase. Make sure that your bot 100% displays a stop phrase when it's ready otherwise your workflow will get stuck. -- cgit v1.2.3 From 2f7aecada0165428017b24baf03ba0a95049a932 Mon Sep 17 00:00:00 2001 From: Exenifix Date: Mon, 18 Jul 2022 23:34:51 +0300 Subject: Updated a docker guide --- .../guides/python-guides/docker-hosting-guide.md | 123 +++++++++++++++++---- 1 file changed, 101 insertions(+), 22 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 3ae732e9..b6735586 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -1,4 +1,10 @@ +--- +title: How to host a bot with Docker and GitHub Actions on Ubuntu VPS +description: This guide shows how to host a bot with Docker and GitHub Actions on Ubuntu VPS +--- + ## Contents + 1. [You will learn](#you-will-learn) 2. [Introduction](#introduction) 3. [Installing Docker](#installing-docker) @@ -8,53 +14,75 @@ 7. [Using GitHub Actions for full automation](#using-github-actions-for-full-automation) ## You will learn + - how to write Dockerfile - how to build Docker image and run the container - how to use docker-compose - how to make docker keep the files throughout the container's runs - how to parse environment variables into container - how to use GitHub Actions for automation -- how to setup self hosted runner +- how to setup self-hosted runner - how to use runner secrets ## Introduction -Let's say you have got a nice discord bot written in python and you have a VPS to host it on. Now the only question is how to run it 24/7. You might have been suggested to use *screen multiplexer*, but it has some disadvantages: -1. Every time you update the bot you have to SSH to your server, attach to screen, shutdown the bot, run `git pull` and run the bot again. You might have good extensions management that allows you to update the bot without restarting it, but there are some other cons as well + +Let's say you have got a nice discord bot written in python and you have a VPS to host it on. Now the only question is +how to run it 24/7. You might have been suggested to use *screen multiplexer*, but it has some disadvantages: + +1. Every time you update the bot you have to SSH to your server, attach to screen, shutdown the bot, run `git pull` and + run the bot again. You might have good extensions management that allows you to update the bot without restarting it, + but there are some other cons as well 2. If you update some dependencies, you have to update them manually 3. The bot doesn't run in an isolated environment, which is not good for security -But there's a nice and easy solution to these problems - **Docker**! Docker is a containerization utility that automates some stuff like dependencies update and running the application in the background. So let's get started. +But there's a nice and easy solution to these problems - **Docker**! Docker is a containerization utility that automates +some stuff like dependencies update and running the application in the background. So let's get started. ## Installing Docker -The best way to install the docker is to use the [convenience script](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) provided by Docker developers themselves. You just need 2 lines: + +The best way to install the docker is to use +the [convenience script](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) provided +by Docker developers themselves. You just need 2 lines: + ```shell $ curl -fsSL https://get.docker.com -o get-docker.sh $ sudo sh get-docker.sh ``` ## Creating Dockerfile -To tell Docker what it has to do to run the application, we need to create a file named `Dockerfile` in our project's root. -1. First we need to specify the *base image*. Doing that will make Docker install some apps we need to run our bot, for example the Python interpreter +To tell Docker what it has to do to run the application, we need to create a file named `Dockerfile` in our project's +root. + +1. First we need to specify the *base image*. Doing that will make Docker install some apps we need to run our bot, for + example the Python interpreter + ```dockerfile FROM python:3.10-bullseye ``` + 2. Next, we need to copy our requirements to some directory *inside the container*. Let's call it `/app` + ```dockerfile COPY requirements.txt /app/ ``` + 3. Now we need to set the directory as working and install the requirements + ```dockerfile WORKDIR /app RUN pip install -r requirements.txt ``` + 4. The only thing that is left to do is to copy the rest of project's files and run the main executable + ```dockerfile COPY . . CMD ["python3", "main.py"] ``` The final version of Dockerfile looks like this: + ```dockerfile FROM python:3.10-bullseye COPY requirements.txt /app/ @@ -65,71 +93,103 @@ CMD ["python3", "main.py"] ``` ## Building Image and Running Container + Now update the project on your VPS and we can run the bot with Docker. + 1. Build the image (dot at the end is very important) + ```shell $ docker build -t mybot . ``` + 2. Run the container + ```shell $ docker run -d --name mybot mybot:latest ``` + 3. Read bot logs (keep in mind that this utility only allows to read STDERR) + ```shell $ docker logs -f mybot ``` + If everything went successfully, your bot will go online and will keep running! ## Using docker-compose -Just 2 commands to run a container is cool but we can shorten it down to just 1 simple command. For that, create a `docker-compose.yml` file in project's root and fill it with the following contents: + +Just 2 commands to run a container is cool but we can shorten it down to just 1 simple command. For that, create +a `docker-compose.yml` file in project's root and fill it with the following contents: + ```yml version: "3.8" services: main: build: . - container-name: mybot + container_name: mybot ``` + Update the project on VPS, remove the previous container with `docker rm -f mybot` and run this command + ```shell docker-compose up -d --build ``` + Now the docker will automatically build the image for you and run the container. ## Creating Volumes -The files creating during container run are destroyed after its recreation. To prevent some files from getting destroyed, we need to use *volumes* that basically save the files from directory inside of container somewhere on drive. + +The files creating during container run are destroyed after its recreation. To prevent some files from getting +destroyed, we need to use *volumes* that basically save the files from directory inside of container somewhere on drive. + 1. Create a new directory somewhere and copy path to it + ```shell $ mkdir mybot-data && echo $(pwd)/mybot-data ``` + My path is `/home/exenifix/mybot-data`, yours is most likely different. + 2. In your project, store the files that need to be persistant in a separate directory (eg. `data`) 3. Add the `volumes` construction to `docker-compose` so it looks like this: + ```yml version: "3.8" services: main: build: . - container-name: mybot + container_name: mybot volumes: - /home/exenifix/mybot-data:/app/data ``` -The path before the colon `:` is the directory *on drive* and the second path is the directory *inside of container*. All the files saved in container in that directory will be saved on drive's directory as well and Docker will be accessing them *from drive*. + +The path before the colon `:` is the directory *on drive* and the second path is the directory *inside of container*. +All the files saved in container in that directory will be saved on drive's directory as well and Docker will be +accessing them *from drive*. ## Using GitHub Actions for full automation -Now it's time to fully automate the process and make Docker update the bot automatically on every commit or release. For that, we will use a **GitHub Actions workflow**, which basically runs some commands when we need to. You may read more about them [here](https://docs.github.com/en/actions/using-workflows). + +Now it's time to fully automate the process and make Docker update the bot automatically on every commit or release. For +that, we will use a **GitHub Actions workflow**, which basically runs some commands when we need to. You may read more +about them [here](https://docs.github.com/en/actions/using-workflows). ### Create repository secret -We will not have the ability to use `.env` files with the workflow, so it's better to store the environment variables as **actions secrets**. + +We will not have the ability to use `.env` files with the workflow, so it's better to store the environment variables +as **actions secrets**. + 1. Head to your repository page -> Settings -> Secrets -> Actions 2. Press `New repository secret` 3. Give it a name like `TOKEN` and paste the value -Now we will be able to access its value in workflow like `${{ secrets.TOKEN }}`. However, we also need to parse the variable into container now. Edit `docker-compose` so it looks like this: + Now we will be able to access its value in workflow like `${{ secrets.TOKEN }}`. However, we also need to parse the + variable into container now. Edit `docker-compose` so it looks like this: + ```yml version: "3.8" services: main: build: . - container-name: mybot + container_name: mybot volumes: - /home/exenifix/mybot-data:/app/data environment: @@ -137,20 +197,27 @@ services: ``` ### Setup self-hosted runner + To run the workflow on our VPS, we will need to register it as *self hosted runner*. + 1. Head to Settings -> Actions -> Runners 2. Press `New self-hosted runner` 3. Select runner image and architecture 4. Follow the instructions but don't run the runner 5. Instead, create a service + ```shell $ sudo ./svc.sh install $ sudo ./svc.sh start ``` + Now we have registered our VPS as a self-hosted runner and we can run the workflow on it now. ### Write a workflow -Create a new file `.github/workflows/runner.yml` and paste the following content into it (it is easy to understand so I am not going to give many comments) + +Create a new file `.github/workflows/runner.yml` and paste the following content into it (it is easy to understand so I +am not going to give many comments) + ```yml name: Docker Runner @@ -175,20 +242,32 @@ jobs: run: docker image prune -f ``` -Run `docker rm -f mybot` (it only needs to be done once) and push to GitHub. Now if you open `Actions` tab on your repository, you should see a workflow running your bot. Congratulations! +Run `docker rm -f mybot` (it only needs to be done once) and push to GitHub. Now if you open `Actions` tab on your +repository, you should see a workflow running your bot. Congratulations! ### Displaying logs in actions terminal -There's a nice utility for reading docker container's logs and stopping upon meeting a certain phrase and it might be useful for you as well. + +There's a nice utility for reading docker container's logs and stopping upon meeting a certain phrase and it might be +useful for you as well. + 1. Install the utility on your VPS with + ```shell $ pip install exendlr ``` -2. Add a step to your workflow that would show the logs until it meets `"ready"` phrase. I recommend putting it before the cleanup. + +2. Add a step to your workflow that would show the logs until it meets `"ready"` phrase. I recommend putting it before + the cleanup. + ```yml - name: Display Logs run: python3 -m exendlr mybot "ready" ``` -Now you should see the logs of your bot until the stop phrase is met. + +Now you should see the logs of your bot until the stop phrase is met. **WARNING** -> The utility only reads from STDERR and redirects to STDERR, if you are using STDOUT for logs, it will not work and will be waiting for stop phrase forever. The utility automatically exits if bot's container is stopped (eg. error occured during starting) or if a log line contains a stop phrase. Make sure that your bot 100% displays a stop phrase when it's ready otherwise your workflow will get stuck. +> The utility only reads from STDERR and redirects to STDERR, if you are using STDOUT for logs, it will not work and +> will be waiting for stop phrase forever. The utility automatically exits if bot's container is stopped (eg. error +> occured during starting) or if a log line contains a stop phrase. Make sure that your bot 100% displays a stop phrase +> when it's ready otherwise your workflow will get stuck. -- cgit v1.2.3 From ab6c82e5f6f6681fd73daeabfb8c4019ef3eb086 Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Sun, 24 Jul 2022 11:27:32 +0300 Subject: Additional explanation about docker base image Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/docker-hosting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index b6735586..c03ae68e 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -54,7 +54,7 @@ $ sudo sh get-docker.sh To tell Docker what it has to do to run the application, we need to create a file named `Dockerfile` in our project's root. -1. First we need to specify the *base image*. Doing that will make Docker install some apps we need to run our bot, for +1. First we need to specify the *base image*, which is the OS that the docker container will be running. Doing that will make Docker install some apps we need to run our bot, for example the Python interpreter ```dockerfile -- cgit v1.2.3 From ff10aa547c2e3589801c73f6898a808dd1688718 Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Sun, 24 Jul 2022 11:28:10 +0300 Subject: Changed "requirements" to external dependencies Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../apps/content/resources/guides/python-guides/docker-hosting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index c03ae68e..5e2e40a3 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -61,7 +61,7 @@ root. FROM python:3.10-bullseye ``` -2. Next, we need to copy our requirements to some directory *inside the container*. Let's call it `/app` +2. Next, we need to copy our Python project's external dependencies to some directory *inside the container*. Let's call it `/app` ```dockerfile COPY requirements.txt /app/ -- cgit v1.2.3 From 13886286414b3603d423f054b91a51cb5f0029d2 Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Sun, 24 Jul 2022 12:05:11 +0300 Subject: Removed unnecessary combination Co-authored-by: Robin <74519799+Robin5605@users.noreply.github.com> --- .../content/resources/guides/python-guides/docker-hosting-guide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 5e2e40a3..67542f20 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -145,7 +145,8 @@ destroyed, we need to use *volumes* that basically save the files from directory 1. Create a new directory somewhere and copy path to it ```shell -$ mkdir mybot-data && echo $(pwd)/mybot-data +$ mkdir mybot-data +$ echo $(pwd)/mybot-data ``` My path is `/home/exenifix/mybot-data`, yours is most likely different. -- cgit v1.2.3 From fa7143f04da204cbeedb76e269e2f527e1cbb4e8 Mon Sep 17 00:00:00 2001 From: Exenifix Date: Sun, 24 Jul 2022 12:09:14 +0300 Subject: Updated the guide as requested --- .../guides/python-guides/docker-hosting-guide.md | 35 +++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 67542f20..a42d11c1 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -102,18 +102,29 @@ Now update the project on your VPS and we can run the bot with Docker. $ docker build -t mybot . ``` +- the `-t` flag specifies a **tag** that will be assigned to the image. With it, we can easily run the image that the tag was assigned to. +- the dot at the end is basically the path to search for Dockerfile. The dot means current directory (`./`) + 2. Run the container ```shell $ docker run -d --name mybot mybot:latest ``` +- `-d` flag tells Docker to run the container in detached mode, meaning it will run the container but will not give us any output from it. If we don't +provide it, the `run` will be giving us the output until the application exits. Discord bots aren't supposed to exit after certain time, so we do need this flag +- `--name` assigns a name to the container. By default, container is identified by id that is not human-readable. To conveniently refer to container when needed, +we can assign it a name +- `mybot:latest` means "latest version of `mybot` image" + 3. Read bot logs (keep in mind that this utility only allows to read STDERR) ```shell $ docker logs -f mybot ``` +- `-f` flag tells the docker to keep reading logs as they appear in container and is called "follow mode". To exit press `CTRL + C`. + If everything went successfully, your bot will go online and will keep running! ## Using docker-compose @@ -129,6 +140,12 @@ services: container_name: mybot ``` +- `version` tells Docker what version of `docker-compose` to use. You may check all the versions [here](https://docs.docker.com/compose/compose-file/compose-versioning/) +- `services` contains services to build and run. Read more about services [here](https://docs.docker.com/compose/compose-file/#services-top-level-element) +- `main` is a service. We can call it whatever we would like to, not necessarily `main` +- `build: .` is a path to search from Dockerfile, just like `docker build` command's dot +- `container_name: mybot` is a container name to use for a bot, just like `docker run --name mybot` + Update the project on VPS, remove the previous container with `docker rm -f mybot` and run this command ```shell @@ -137,6 +154,16 @@ docker-compose up -d --build Now the docker will automatically build the image for you and run the container. +### Why docker-compose +The main purpose of `docker-compose` is mostly to allow running several images at once within one container. Mostly we don't need this in discord bots. +For us, it has the following benefits: +- we can build and run the container just with one command +- if we need to parse some environment variables or volumes (more about them further in tutorial) our run command would look like this +```shell +$ docker run -d --name mybot -e TOKEN=... -e WEATHER_API_APIKEY=... -e SOME_USEFUL_ENVIRONMENT_VARIABLE=... --net=host -v /home/exenifix/bot-data/data:/app/data -v /home/exenifix/bot-data/images:/app/data/images +``` +This is pretty long and unreadable. `docker-compose` allows us to transfer those flags into single config file and still use just one short command to run the container. + ## Creating Volumes The files creating during container run are destroyed after its recreation. To prevent some files from getting @@ -149,7 +176,7 @@ $ mkdir mybot-data $ echo $(pwd)/mybot-data ``` -My path is `/home/exenifix/mybot-data`, yours is most likely different. +My path is `/home/exenifix/mybot-data`, yours is most likely **different**! 2. In your project, store the files that need to be persistant in a separate directory (eg. `data`) 3. Add the `volumes` construction to `docker-compose` so it looks like this: @@ -164,7 +191,7 @@ services: - /home/exenifix/mybot-data:/app/data ``` -The path before the colon `:` is the directory *on drive* and the second path is the directory *inside of container*. +The path before the colon `:` is the directory *on server's drive, outside of container*, and the second path is the directory *inside of container*. All the files saved in container in that directory will be saved on drive's directory as well and Docker will be accessing them *from drive*. @@ -177,11 +204,11 @@ about them [here](https://docs.github.com/en/actions/using-workflows). ### Create repository secret We will not have the ability to use `.env` files with the workflow, so it's better to store the environment variables -as **actions secrets**. +as **actions secrets**. Let's add your discord bot's token as a secret 1. Head to your repository page -> Settings -> Secrets -> Actions 2. Press `New repository secret` -3. Give it a name like `TOKEN` and paste the value +3. Give it a name like `TOKEN` and paste the token Now we will be able to access its value in workflow like `${{ secrets.TOKEN }}`. However, we also need to parse the variable into container now. Edit `docker-compose` so it looks like this: -- cgit v1.2.3 From 2fbc05dd55f20a92ec4e2e43bfbb2e653f24f552 Mon Sep 17 00:00:00 2001 From: Exenifix Date: Sun, 24 Jul 2022 12:10:41 +0300 Subject: Guide linting applied --- .../guides/python-guides/docker-hosting-guide.md | 45 +++++++++++++++------- 1 file changed, 31 insertions(+), 14 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index a42d11c1..5fb55caf 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -54,14 +54,16 @@ $ sudo sh get-docker.sh To tell Docker what it has to do to run the application, we need to create a file named `Dockerfile` in our project's root. -1. First we need to specify the *base image*, which is the OS that the docker container will be running. Doing that will make Docker install some apps we need to run our bot, for +1. First we need to specify the *base image*, which is the OS that the docker container will be running. Doing that will + make Docker install some apps we need to run our bot, for example the Python interpreter ```dockerfile FROM python:3.10-bullseye ``` -2. Next, we need to copy our Python project's external dependencies to some directory *inside the container*. Let's call it `/app` +2. Next, we need to copy our Python project's external dependencies to some directory *inside the container*. Let's call + it `/app` ```dockerfile COPY requirements.txt /app/ @@ -102,7 +104,8 @@ Now update the project on your VPS and we can run the bot with Docker. $ docker build -t mybot . ``` -- the `-t` flag specifies a **tag** that will be assigned to the image. With it, we can easily run the image that the tag was assigned to. +- the `-t` flag specifies a **tag** that will be assigned to the image. With it, we can easily run the image that the + tag was assigned to. - the dot at the end is basically the path to search for Dockerfile. The dot means current directory (`./`) 2. Run the container @@ -111,10 +114,13 @@ $ docker build -t mybot . $ docker run -d --name mybot mybot:latest ``` -- `-d` flag tells Docker to run the container in detached mode, meaning it will run the container but will not give us any output from it. If we don't -provide it, the `run` will be giving us the output until the application exits. Discord bots aren't supposed to exit after certain time, so we do need this flag -- `--name` assigns a name to the container. By default, container is identified by id that is not human-readable. To conveniently refer to container when needed, -we can assign it a name +- `-d` flag tells Docker to run the container in detached mode, meaning it will run the container but will not give us + any output from it. If we don't + provide it, the `run` will be giving us the output until the application exits. Discord bots aren't supposed to exit + after certain time, so we do need this flag +- `--name` assigns a name to the container. By default, container is identified by id that is not human-readable. To + conveniently refer to container when needed, + we can assign it a name - `mybot:latest` means "latest version of `mybot` image" 3. Read bot logs (keep in mind that this utility only allows to read STDERR) @@ -123,7 +129,8 @@ we can assign it a name $ docker logs -f mybot ``` -- `-f` flag tells the docker to keep reading logs as they appear in container and is called "follow mode". To exit press `CTRL + C`. +- `-f` flag tells the docker to keep reading logs as they appear in container and is called "follow mode". To exit + press `CTRL + C`. If everything went successfully, your bot will go online and will keep running! @@ -140,8 +147,10 @@ services: container_name: mybot ``` -- `version` tells Docker what version of `docker-compose` to use. You may check all the versions [here](https://docs.docker.com/compose/compose-file/compose-versioning/) -- `services` contains services to build and run. Read more about services [here](https://docs.docker.com/compose/compose-file/#services-top-level-element) +- `version` tells Docker what version of `docker-compose` to use. You may check all the + versions [here](https://docs.docker.com/compose/compose-file/compose-versioning/) +- `services` contains services to build and run. Read more about + services [here](https://docs.docker.com/compose/compose-file/#services-top-level-element) - `main` is a service. We can call it whatever we would like to, not necessarily `main` - `build: .` is a path to search from Dockerfile, just like `docker build` command's dot - `container_name: mybot` is a container name to use for a bot, just like `docker run --name mybot` @@ -155,14 +164,21 @@ docker-compose up -d --build Now the docker will automatically build the image for you and run the container. ### Why docker-compose -The main purpose of `docker-compose` is mostly to allow running several images at once within one container. Mostly we don't need this in discord bots. + +The main purpose of `docker-compose` is mostly to allow running several images at once within one container. Mostly we +don't need this in discord bots. For us, it has the following benefits: + - we can build and run the container just with one command -- if we need to parse some environment variables or volumes (more about them further in tutorial) our run command would look like this +- if we need to parse some environment variables or volumes (more about them further in tutorial) our run command would + look like this + ```shell $ docker run -d --name mybot -e TOKEN=... -e WEATHER_API_APIKEY=... -e SOME_USEFUL_ENVIRONMENT_VARIABLE=... --net=host -v /home/exenifix/bot-data/data:/app/data -v /home/exenifix/bot-data/images:/app/data/images ``` -This is pretty long and unreadable. `docker-compose` allows us to transfer those flags into single config file and still use just one short command to run the container. + +This is pretty long and unreadable. `docker-compose` allows us to transfer those flags into single config file and still +use just one short command to run the container. ## Creating Volumes @@ -191,7 +207,8 @@ services: - /home/exenifix/mybot-data:/app/data ``` -The path before the colon `:` is the directory *on server's drive, outside of container*, and the second path is the directory *inside of container*. +The path before the colon `:` is the directory *on server's drive, outside of container*, and the second path is the +directory *inside of container*. All the files saved in container in that directory will be saved on drive's directory as well and Docker will be accessing them *from drive*. -- cgit v1.2.3 From 507676aece37d9d468cf3565915d9a146bdf2ad4 Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Mon, 1 Aug 2022 10:11:54 +0300 Subject: Update pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md Co-authored-by: Vivek Ashokkumar --- .../apps/content/resources/guides/python-guides/docker-hosting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 5fb55caf..e3d9dffd 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -114,7 +114,7 @@ $ docker build -t mybot . $ docker run -d --name mybot mybot:latest ``` -- `-d` flag tells Docker to run the container in detached mode, meaning it will run the container but will not give us +- `-d` flag tells Docker to run the container in detached mode, meaning it will run the container in the background of your terminal and not give us any output from it. If we don't provide it, the `run` will be giving us the output until the application exits. Discord bots aren't supposed to exit after certain time, so we do need this flag -- cgit v1.2.3 From 0f94b8e58e3357161973a37ba2e26be9740ffdb2 Mon Sep 17 00:00:00 2001 From: Exenifix Date: Mon, 1 Aug 2022 10:18:27 +0300 Subject: Added additional explanation about branch name --- .../content/resources/guides/python-guides/docker-hosting-guide.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index e3d9dffd..36686119 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -260,15 +260,16 @@ Now we have registered our VPS as a self-hosted runner and we can run the workfl ### Write a workflow -Create a new file `.github/workflows/runner.yml` and paste the following content into it (it is easy to understand so I -am not going to give many comments) +Create a new file `.github/workflows/runner.yml` and paste the following content into it. Please pay attention to the `branches` instruction. +The GitHub's standard main branch name is `main`, however it may be named `master` or something else if you edited its name. Make sure to put +the correct branch name, otherwise it won't work. More about GitHub workflows syntax [here](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) ```yml name: Docker Runner on: push: - branches: [ master ] + branches: [ main ] jobs: run: -- cgit v1.2.3 From b572522d0afe0b856ac22239de3e67e9e8d1c721 Mon Sep 17 00:00:00 2001 From: Exenifix Date: Mon, 1 Aug 2022 10:22:27 +0300 Subject: Some grammar mistakes fix --- .../resources/guides/python-guides/docker-hosting-guide.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 36686119..6590cc99 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -21,7 +21,7 @@ description: This guide shows how to host a bot with Docker and GitHub Actions o - how to make docker keep the files throughout the container's runs - how to parse environment variables into container - how to use GitHub Actions for automation -- how to setup self-hosted runner +- how to set up self-hosted runner - how to use runner secrets ## Introduction @@ -96,7 +96,7 @@ CMD ["python3", "main.py"] ## Building Image and Running Container -Now update the project on your VPS and we can run the bot with Docker. +Now update the project on your VPS, so we can run the bot with Docker. 1. Build the image (dot at the end is very important) @@ -136,7 +136,7 @@ If everything went successfully, your bot will go online and will keep running! ## Using docker-compose -Just 2 commands to run a container is cool but we can shorten it down to just 1 simple command. For that, create +Just 2 commands to run a container is cool, but we can shorten it down to just 1 simple command. For that, create a `docker-compose.yml` file in project's root and fill it with the following contents: ```yml @@ -194,7 +194,7 @@ $ echo $(pwd)/mybot-data My path is `/home/exenifix/mybot-data`, yours is most likely **different**! -2. In your project, store the files that need to be persistant in a separate directory (eg. `data`) +2. In your project, store the files that need to be persistent in a separate directory (eg. `data`) 3. Add the `volumes` construction to `docker-compose` so it looks like this: ```yml @@ -243,7 +243,7 @@ services: ### Setup self-hosted runner -To run the workflow on our VPS, we will need to register it as *self hosted runner*. +To run the workflow on our VPS, we will need to register it as *self-hosted runner*. 1. Head to Settings -> Actions -> Runners 2. Press `New self-hosted runner` @@ -314,6 +314,6 @@ Now you should see the logs of your bot until the stop phrase is met. **WARNING** > The utility only reads from STDERR and redirects to STDERR, if you are using STDOUT for logs, it will not work and -> will be waiting for stop phrase forever. The utility automatically exits if bot's container is stopped (eg. error -> occured during starting) or if a log line contains a stop phrase. Make sure that your bot 100% displays a stop phrase +> will be waiting for stop phrase forever. The utility automatically exits if bot's container is stopped (e.g. error +> occurred during starting) or if a log line contains a stop phrase. Make sure that your bot 100% displays a stop phrase > when it's ready otherwise your workflow will get stuck. -- cgit v1.2.3 From a8b5cd676ce95b1b148d2cc37e008d24762ab9d7 Mon Sep 17 00:00:00 2001 From: Exenifix Date: Mon, 1 Aug 2022 10:24:33 +0300 Subject: Linting applied --- .../resources/guides/python-guides/docker-hosting-guide.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 6590cc99..103ddbbd 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -114,7 +114,8 @@ $ docker build -t mybot . $ docker run -d --name mybot mybot:latest ``` -- `-d` flag tells Docker to run the container in detached mode, meaning it will run the container in the background of your terminal and not give us +- `-d` flag tells Docker to run the container in detached mode, meaning it will run the container in the background of + your terminal and not give us any output from it. If we don't provide it, the `run` will be giving us the output until the application exits. Discord bots aren't supposed to exit after certain time, so we do need this flag @@ -260,9 +261,12 @@ Now we have registered our VPS as a self-hosted runner and we can run the workfl ### Write a workflow -Create a new file `.github/workflows/runner.yml` and paste the following content into it. Please pay attention to the `branches` instruction. -The GitHub's standard main branch name is `main`, however it may be named `master` or something else if you edited its name. Make sure to put -the correct branch name, otherwise it won't work. More about GitHub workflows syntax [here](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) +Create a new file `.github/workflows/runner.yml` and paste the following content into it. Please pay attention to +the `branches` instruction. +The GitHub's standard main branch name is `main`, however it may be named `master` or something else if you edited its +name. Make sure to put +the correct branch name, otherwise it won't work. More about GitHub workflows +syntax [here](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions) ```yml name: Docker Runner -- cgit v1.2.3 From acd4238fcb9c0135a548eb9bad43923fc41e983e Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Mon, 15 Aug 2022 17:40:24 -0500 Subject: Migrate on_command_error pin As part of the migration of the #discord-bots pinned content from discord to the site, this PR migrates the pin regarding `on_command_error` of the discord.py library "eating" (silencing) unhandled errors. --- .../guides/python-guides/proper-error-handling.md | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md b/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md new file mode 100644 index 00000000..9307169d --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md @@ -0,0 +1,70 @@ +--- +title: Proper error handling in discord.py +description: Are you not getting any errors? This might be why! +--- +If you're not recieving any errors in your console, even though you know you should be, try this: + +# With bot subclass: +```py +import discord +from discord.ext import commands + +import traceback +import sys + +class MyBot(commands.Bot): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + async def on_command_error(self, ctx: commands.Context, error): + # Handle your errors here + if isinstance(error, commands.MemberNotFound): + await ctx.send("I could not find member '{error.argument}'. Please try again") + + elif isinstance(error, commands.MissingRequiredArgument): + await ctx.send(f"'{error.param.name}' is a required argument.") + else: + # All unhandled errors will print their original traceback + print(f'Ignoring exception in command {ctx.command}:', file=sys.stderr) + traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) + +bot = MyBot(command_prefix="!", intents=discord.Intents.default()) + +bot.run("token") +``` + +# Without bot subclass +```py +import discord +from discord.ext import commands + +import traceback +import sys + +async def on_command_error(self, ctx: commands.Context, error): + # Handle your errors here + if isinstance(error, commands.MemberNotFound): + await ctx.send("I could not find member '{error.argument}'. Please try again") + + elif isinstance(error, commands.MissingRequiredArgument): + await ctx.send(f"'{error.param.name}' is a required argument.") + else: + # All unhandled errors will print their original traceback + print(f'Ignoring exception in command {ctx.command}:', file=sys.stderr) + traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +bot.on_command_error = on_command_error + +bot.run("token") +``` + + +Make sure to import `traceback` and `sys`! + +------------------------------------------------------------------------------------------------------------- + +Useful Links: +- [FAQ](https://discordpy.readthedocs.io/en/latest/faq.html) +- [Simple Error Handling](https://gist.github.com/EvieePy/7822af90858ef65012ea500bcecf1612) -- cgit v1.2.3 From d64ed9b4d269d9731267c6d7b088555ea3cf4e31 Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Mon, 15 Aug 2022 17:51:04 -0500 Subject: Update proper-error-handling.md --- .../content/resources/guides/python-guides/proper-error-handling.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md b/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md index 9307169d..e0606625 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md +++ b/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md @@ -16,7 +16,7 @@ class MyBot(commands.Bot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - + async def on_command_error(self, ctx: commands.Context, error): # Handle your errors here if isinstance(error, commands.MemberNotFound): @@ -28,7 +28,7 @@ class MyBot(commands.Bot): # All unhandled errors will print their original traceback print(f'Ignoring exception in command {ctx.command}:', file=sys.stderr) traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) - + bot = MyBot(command_prefix="!", intents=discord.Intents.default()) bot.run("token") @@ -65,6 +65,6 @@ Make sure to import `traceback` and `sys`! ------------------------------------------------------------------------------------------------------------- -Useful Links: +Useful Links: - [FAQ](https://discordpy.readthedocs.io/en/latest/faq.html) - [Simple Error Handling](https://gist.github.com/EvieePy/7822af90858ef65012ea500bcecf1612) -- cgit v1.2.3 From 20a7264d4e7f88f690b592199a9bedc691e7f9a8 Mon Sep 17 00:00:00 2001 From: Rohan Shah <57906961+rshah713@users.noreply.github.com> Date: Tue, 30 Aug 2022 20:10:45 -0400 Subject: Fix grammar in contributing guide (#771) --- pydis_site/apps/content/resources/guides/pydis-guides/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 6231fe87..2822d046 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -119,7 +119,7 @@ As mentioned in the Contributing Guidelines, we have a simple style guide for ou [**Style Guide**](./style-guide/) ### 4. Create an issue -The first step to any new contribution is an issue describing a problem with the current codebase or proposing a new feature. All the open issues are viewable on the GitHub repositories, for instance here is the [issues page for Sir Lancebot](https://github.com/python-discord/sir-lancebot/issues). If you have something that you want to implement open a new issue to present your idea. Otherwise you can browse the unassigned issues and ask to be assigned to one that you're interested in, either in the comments on the issue or in the [`#dev-contrib`](https://discord.gg/2h3qBv8Xaa) channel on Discord. +The first step to any new contribution is an issue describing a problem with the current codebase or proposing a new feature. All the open issues are viewable on the GitHub repositories, for instance here is the [issues page for Sir Lancebot](https://github.com/python-discord/sir-lancebot/issues). If you have something that you want to implement open a new issue to present your idea. Otherwise, you can browse the unassigned issues and ask to be assigned to one that you're interested in, either in the comments on the issue or in the [`#dev-contrib`](https://discord.gg/2h3qBv8Xaa) channel on Discord. [**How to write a good issue**](./issues/) -- cgit v1.2.3 From 67ba14c97026c1955a573710a957cc81a688b767 Mon Sep 17 00:00:00 2001 From: Exenifix Date: Thu, 22 Sep 2022 15:34:26 +0300 Subject: Minor change to "you will learn" section --- .../guides/python-guides/docker-hosting-guide.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 103ddbbd..d77a91b6 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -13,16 +13,16 @@ description: This guide shows how to host a bot with Docker and GitHub Actions o 6. [Creating Volumes](#creating-volumes) 7. [Using GitHub Actions for full automation](#using-github-actions-for-full-automation) -## You will learn +## You will learn how to -- how to write Dockerfile -- how to build Docker image and run the container -- how to use docker-compose -- how to make docker keep the files throughout the container's runs -- how to parse environment variables into container -- how to use GitHub Actions for automation -- how to set up self-hosted runner -- how to use runner secrets +- write Dockerfile +- build Docker image and run the container +- use docker-compose +- make docker keep the files throughout the container's runs +- parse environment variables into container +- use GitHub Actions for automation +- set up self-hosted runner +- use runner secrets ## Introduction @@ -40,7 +40,7 @@ some stuff like dependencies update and running the application in the backgroun ## Installing Docker -The best way to install the docker is to use +The best way to install Docker is to use the [convenience script](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script) provided by Docker developers themselves. You just need 2 lines: -- cgit v1.2.3 From 9c816143fe58595c7ff4e810e350c229bfb1e1c2 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Sun, 21 Aug 2022 23:12:04 +0400 Subject: Upgrade To 3.10 All dependencies and code are already ready for 3.10, all that's necessary is to update the number. Signed-off-by: Hassan Abouelela --- .github/workflows/lint-test.yaml | 2 +- Dockerfile | 2 +- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 2 +- .../apps/content/resources/guides/pydis-guides/contributing/site.md | 2 +- .../content/resources/guides/pydis-guides/contributing/style-guide.md | 3 --- pyproject.toml | 2 +- 6 files changed, 5 insertions(+), 8 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/.github/workflows/lint-test.yaml b/.github/workflows/lint-test.yaml index 0e3f121c..168a8383 100644 --- a/.github/workflows/lint-test.yaml +++ b/.github/workflows/lint-test.yaml @@ -19,7 +19,7 @@ jobs: uses: HassanAbouelela/actions/setup-python@setup-python_v1.3.1 with: dev: true - python_version: '3.9' + python_version: '3.10' # Start the database early to give it a chance to get ready before # we start running tests. diff --git a/Dockerfile b/Dockerfile index 1d50e11d..454e58d5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/chrislovering/python-poetry-base:3.9-slim +FROM ghcr.io/chrislovering/python-poetry-base:3.10-slim # Allow service to handle stops gracefully STOPSIGNAL SIGQUIT diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index ad446cc8..633289f2 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -507,7 +507,7 @@ You can start several services together: `docker-compose up web snekbox redis`. ##### Setting Up a Development Environment The bot's code is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: -1. Make sure you have [Python 3.9](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. +1. Make sure you have [Python 3.10](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. 2. [Install Poetry](https://github.com/python-poetry/poetry#installation). 3. [Install the dependencies](../installing-project-dependencies). diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 520e41ad..9786698b 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -9,7 +9,7 @@ You should have already forked the [`site`](https://github.com/python-discord/si ### Requirements -- [Python 3.9](https://www.python.org/downloads/) +- [Python 3.10](https://www.python.org/downloads/) - [Poetry](https://python-poetry.org/docs/#installation) - `pip install poetry` - [Git](https://git-scm.com/downloads) diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md index 4dba45c8..b26c467c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/style-guide.md @@ -202,6 +202,3 @@ def foo(input_1: int, input_2: dict[str, int]) -> bool: This tells us that `foo` accepts an `int` and a `dict`, with `str` keys and `int` values, and returns a `bool`. In previous examples, we have purposely omitted annotations to keep focus on the specific points they represent. - -> **Note:** if the project is running Python 3.8 or below you have to use `typing.Dict` instead of `dict`, but our three main projects are all >=3.9. -> See [PEP 585](https://www.python.org/dev/peps/pep-0585/) for more information. diff --git a/pyproject.toml b/pyproject.toml index ec8091e4..1f78ef2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ authors = ["Python Discord "] license = "MIT" [tool.poetry.dependencies] -python = "3.9.*" +python = "3.10.*" django = "4.0" # 4.1 blocked by upstream bug, wait for 4.1.1: https://code.djangoproject.com/ticket/33919 django-environ = "0.9.0" django-filter = "22.1" -- cgit v1.2.3 From 5377fc16bd752a65f49757b7b806308236dd2d04 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Sat, 16 Jul 2022 23:58:02 +0100 Subject: Add info about working with snekbox 3.11 on bot --- .../content/resources/guides/pydis-guides/contributing/bot.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 633289f2..02316bca 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -88,6 +88,7 @@ urls: # Snekbox snekbox_eval_api: "http://localhost:8060/eval" + snekbox_311_eval_api: "http://localhost:8065/eval" ##### << Replace the following � characters with the channel IDs in your test server >> ##### # This assumes the template was used: https://discord.new/zmHtscpYN9E3 @@ -481,10 +482,14 @@ You are now almost ready to run the Python bot. The simplest way to do so is wit In your `config.yml` file: * Set `urls.site` to `"web:8000"`. -* If you wish to work with snekbox set `urls.snekbox_eval_api` to `"http://snekbox:8060/eval"`. +* If you wish to work with snekbox set the following: + * `urls.snekbox_eval_api` to `"http://snekbox:8060/eval"` + * `urls.snekbox_311_eval_api` to `"http://snekbox-311:8060/eval"`. Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker-compose up`. +If working with snekbox you can run `docker-compose --profile 3.10 up` to also start up a 3.10 snekbox container, in addition to the default 3.11 container! + After pulling the images and building the containers, your bot will start. Enter your server and type `!help` (or whatever prefix you chose instead of `!`). Your bot is now running, but this method makes debugging with an IDE a fairly involved process. For additional running methods, continue reading the following sections. @@ -494,12 +499,13 @@ The advantage of this method is that you can run the bot's code in your preferre * Append the following line to your `.env` file: `BOT_API_KEY=badbot13m0n8f570f942013fc818f234916ca531`. * In your `config.yml` file, set `urls.site` to `"localhost:8000"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. -* To work with snekbox, set `urls.snekbox_eval_api` to `"http://localhost:8060/eval"` +* To work with snekbox, set `urls.snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls.snekbox_311_eval_api` to `"http://localhost:8065/eval"` You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: * `docker-compose up web` to start the site container. This is required. * `docker-compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. +* `docker-compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. * `docker-compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). You can start several services together: `docker-compose up web snekbox redis`. -- cgit v1.2.3 From 3370c8763ad86198e3b010d72bdf1b14b7f8ff7b Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Wed, 19 Oct 2022 21:06:51 -0500 Subject: Use 4 spaces as tab Uses 4 spaces for a tab rather than two, as is convention --- .../guides/python-guides/proper-error-handling.md | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md b/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md index e0606625..74b0f59b 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md +++ b/pydis_site/apps/content/resources/guides/python-guides/proper-error-handling.md @@ -14,20 +14,20 @@ import sys class MyBot(commands.Bot): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) - async def on_command_error(self, ctx: commands.Context, error): - # Handle your errors here - if isinstance(error, commands.MemberNotFound): - await ctx.send("I could not find member '{error.argument}'. Please try again") + async def on_command_error(self, ctx: commands.Context, error): + # Handle your errors here + if isinstance(error, commands.MemberNotFound): + await ctx.send("I could not find member '{error.argument}'. Please try again") - elif isinstance(error, commands.MissingRequiredArgument): - await ctx.send(f"'{error.param.name}' is a required argument.") - else: - # All unhandled errors will print their original traceback - print(f'Ignoring exception in command {ctx.command}:', file=sys.stderr) - traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) + elif isinstance(error, commands.MissingRequiredArgument): + await ctx.send(f"'{error.param.name}' is a required argument.") + else: + # All unhandled errors will print their original traceback + print(f'Ignoring exception in command {ctx.command}:', file=sys.stderr) + traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) bot = MyBot(command_prefix="!", intents=discord.Intents.default()) @@ -43,16 +43,16 @@ import traceback import sys async def on_command_error(self, ctx: commands.Context, error): - # Handle your errors here - if isinstance(error, commands.MemberNotFound): - await ctx.send("I could not find member '{error.argument}'. Please try again") - - elif isinstance(error, commands.MissingRequiredArgument): - await ctx.send(f"'{error.param.name}' is a required argument.") - else: - # All unhandled errors will print their original traceback - print(f'Ignoring exception in command {ctx.command}:', file=sys.stderr) - traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) + # Handle your errors here + if isinstance(error, commands.MemberNotFound): + await ctx.send("I could not find member '{error.argument}'. Please try again") + + elif isinstance(error, commands.MissingRequiredArgument): + await ctx.send(f"'{error.param.name}' is a required argument.") + else: + # All unhandled errors will print their original traceback + print(f'Ignoring exception in command {ctx.command}:', file=sys.stderr) + traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) bot.on_command_error = on_command_error -- cgit v1.2.3 From 6bde7d973e4b156b644ed1b4bcdab6d61be43ff2 Mon Sep 17 00:00:00 2001 From: Gustav Odinger <65498475+gustavwilliam@users.noreply.github.com> Date: Tue, 25 Oct 2022 06:46:09 +0200 Subject: Update off-topic etiquette to reflect server size (#785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With more than 350k members, saying that we have “tens of thousands of members” seems like an understatement. --- .../apps/content/resources/guides/pydis-guides/off-topic-etiquette.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/off-topic-etiquette.md b/pydis_site/apps/content/resources/guides/pydis-guides/off-topic-etiquette.md index f8031834..5e785cd9 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/off-topic-etiquette.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/off-topic-etiquette.md @@ -5,7 +5,7 @@ icon: fab fa-discord --- ## Why do we need off-topic etiquette? -Everyone wants to have good conversations in our off-topic channels, but with tens of thousands of members, this might mean different things to different people. +Everyone wants to have good conversations in our off-topic channels, but with hundreds of thousands of members, this might mean different things to different people. To facilitate the best experience for everyone, here are some guidelines on conversation etiquette. ## Three things you shouldn't do -- cgit v1.2.3 From 98ea7a8650bc7195700993bf3e94cf0a48a43cd5 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 12 Nov 2022 19:55:18 -0800 Subject: Resolved a bunch of requests --- .../resources/guides/python-guides/app_commands.md | 58 +++++++++++----------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md index 821ac577..d81a037c 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -2,25 +2,25 @@ --- -Upon resumation of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumation can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). +Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumation can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). # Why this gist? --- -This Gist is being created as an update to slash commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! +This Gist is being created as an update to Slash Commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! # What Are Slash Commands? --- -Slash Commands are the exciting way to build and interact with bots on Discord. With Slash Commands, all you have to do is type / and you're ready to use your favourite bot. You can easily see all the commands a bot has, and validation and error handling help you get the command right the first time. +Slash Commands are the exciting new way to build and interact with bots on Discord. With Slash Commands, all you have to do is type / and you're ready to use your favourite bot. You can easily see all the commands a bot has, and validation and error handling help you get the command right the first time. -# Install the latest version for discord.py +# Install the latest version of discord.py --- -To use slash commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! -And make sure to uninstall any third party libraries that support slash commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! +To use Slash Commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! +And make sure to uninstall any third party libraries that support Slash Commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! The latest and up-to-date usable discord.py version can be installed using `pip install -U git+https://github.com/Rapptz/discord.py`. @@ -32,14 +32,14 @@ If you get an error such as: `'git' is not recognized...`. [Install git](https:/ --- ### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. -Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create slash commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. +Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create Slash Commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. # Fundamentals for this gist! --- -The fundamental for this gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot class which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. +The fundamental for this gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. __**FOLLOWING IS THE EXAMPLE OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ @@ -54,13 +54,13 @@ class SlashClient(discord.Client): super().__init__(intents=discord.Intents.default()) async def setup_hook(self) -> None: - #perform tasks + ... '''Another way of creating a "setup_hook" is as follows''' client = discord.Client(intents=discord.Intents.default()) async def my_setup_hook() -> None: - #perform tasks + ... client.setup_hook = my_setup_hook ``` @@ -99,11 +99,11 @@ __**EXPLANATION**__ - `import discord` imports the **discord.py** package. - `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. - Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the slash commands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. - Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. - Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. - And the classic old `client.run("token")` is used to connect the client to the discord gateway. -- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. I will discuss about how to handle this issue later following the gist. +- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the gist. ## Slash Command Application with a Bot @@ -127,7 +127,7 @@ async def _ping(interaction: discord.Interaction) -> None: bot.run("token") ``` -The above example shows a basic slash commands within discord.py using the Bot class. +The above example shows a basic Slash Commands within discord.py using the Bot class. __**EXPLANATION**__ @@ -142,7 +142,7 @@ Most of the explanation is the same as the prior example which featured `SlashCl A cog is a collection of commands, listeners, and optional state to help group commands together. More information on them can be found on the [Cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs) page. -## An Example to using cogs with discord.py for slash commands! +## An Example to using cogs with discord.py for Slash Commands! ```python import discord @@ -176,12 +176,12 @@ __**EXPLANATION**__ - Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` directory from the **discord.py** root directory. `from discord.ext import commands` imports the commands extension. - Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). - `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. -- Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for slash commands with **self** added as the first parameter to the function as it is a method of a class. +- Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for Slash Commands with **self** added as the first parameter to the function as it is a method of a class. - The next up lines are mostly the same. - Talking about the first line inside the `setup_hook` is the `add_cog` method of the **Bot** class. And since **self** acts as the **instance** of the current class, we use **self** to use the `add_cog` method of the **Bot** class as we are inside a subclassed class of the **Bot** class. Then we pass in **self** to the `add_cog` method as the `__init__` function of the **MySlashCog** cog accepts a `Bot` object. - After that we instantiate the `MySlashBot` class and run the bot using the **run** method which executes our setup_hook function and our commands get loaded and synced. The bot is now ready to use! -# An Example to using groups with discord.py for slash commands! +# An Example to using groups with discord.py for Slash Commands! --- @@ -265,11 +265,11 @@ __**EXPLANATION**__ - The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. -# Some common methods and features used for slash commands. +# Some common methods and features used for Slash Commands. --- -### A common function used for slash commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. +### A common function used for Slash Commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. ```python from discord.ext import commands @@ -286,7 +286,7 @@ async def _echo(interaction: discord.Interaction, text: str, channel: discord.Te await channel.send(text) ``` -### Another common issue that most people come across is the time duraction of sending a message with `send_message`. This issue can be tackled by deferring the interaction response using the `defer` method of the `InteractionResponse` class. An example for fixing this issue is shown below. +### Another common issue that most people come across is the time duration of sending a message with `send_message`. This issue can be tackled by deferring the interaction response using the `defer` method of the `InteractionResponse` class. An example for fixing this issue is shown below. ```python import discord @@ -327,7 +327,7 @@ async def _ping(interaction: discord.Interaction): ``` -If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! I will discuss about making an error handler later in the gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). +If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! We will discuss making an error handler later in the gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). Other methods that you can decorate the commands with are - - `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. @@ -335,7 +335,7 @@ Other methods that you can decorate the commands with are - - To pass in several role names or role IDs, `has_any_role` can be used to decorate a command. This raises two exceptions -> [MissingAnyRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingAnyRole) and [NoPrivateMessage](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.NoPrivateMessage) -# Adding cooldowns to slash commands! +# Adding cooldowns to Slash Commands! --- @@ -369,17 +369,17 @@ bot.run("token") ``` __**EXPLANATION**__ -- The first argument the `cooldown` method takes is the amount of times the command can be run in a specific period of time. +- The first argument the `cooldown` method takes is the number of times this command can be invoked in a particular unit of time (Which will be defined in the following argument). - The second argument it takes is the period of time in which the command can be run the specified number of times. -- The `CommandOnCooldown` exception can be handled using an error handler. I will discuss about making an error handler for slash commands later in the gist. +- The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the gist. -# Handling errors for slash commands! +# Handling errors for Slash Commands! --- -The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the slash commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). -An example to creating an error handler for slash commands is as follows. +The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the Slash Commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). +An example to creating an error handler for Slash Commands is as follows. ```python from discord.ext import commands @@ -411,8 +411,8 @@ bot.run("token") __**EXPLANATION**__ -First we create a simple function named as `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here I have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displaying unhandled errors, i.e. the ones which have not been handled manually. If this is **removed**, you will not be able to see any exceptions raised by slash commands and makes debugging the code harder. -After creating the error handler function, we set the function as the error handler for the slash commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. +First we create a simple asynchronous function named `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here we have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displaying unhandled errors, i.e. the ones which have not been handled manually. If this is **removed**, you will not be able to see any exceptions raised by Slash Commands and makes debugging the code harder. +After creating the error handler function, we set the function as the error handler for the Slash Commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. ### Creating an error handler for a specific error! @@ -445,4 +445,4 @@ bot.run("token") __**EXPLANATION**__ -Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. \ No newline at end of file +Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. -- cgit v1.2.3 From f5641894f5645bc41c01708bfb8ffe16d372e449 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 12 Nov 2022 19:57:08 -0800 Subject: Appeased the formatter --- .../resources/guides/python-guides/app_commands.md | 58 +++++++++++----------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md index d81a037c..c319ebb1 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -52,12 +52,12 @@ import discord class SlashClient(discord.Client): def __init__(self) -> None: super().__init__(intents=discord.Intents.default()) - + async def setup_hook(self) -> None: ... '''Another way of creating a "setup_hook" is as follows''' - + client = discord.Client(intents=discord.Intents.default()) async def my_setup_hook() -> None: ... @@ -79,7 +79,7 @@ class SlashClient(discord.Client): def __init__(self) -> None: super().__init__(intents=discord.Intents.default()) self.tree = discord.app_commands.CommandTree(self) - + async def setup_hook(self) -> None: self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) await self.tree.sync() @@ -96,11 +96,11 @@ client.run("token") __**EXPLANATION**__ -- `import discord` imports the **discord.py** package. -- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. -- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. -- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. +- `import discord` imports the **discord.py** package. +- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. +- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. - Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. - And the classic old `client.run("token")` is used to connect the client to the discord gateway. - Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the gist. @@ -113,7 +113,7 @@ import discord class SlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix=".", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) await self.tree.sync() @@ -152,20 +152,20 @@ from discord import app_commands class MySlashCog(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot = bot - + @app_commands.command(name="ping", description="...") async def _ping(self, interaction: discord.Interaction): await interaction.response.send_message("pong!") - + class MySlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix="!", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: await self.add_cog(MySlashCog(self)) await self.tree.copy_global_to(discord.Object(id=123456789098765432)) await self.tree.sync() - + bot = MySlashBot() bot.run("token") @@ -203,20 +203,20 @@ class MySlashGroupCog(commands.Cog): @app_commands.command(name="ping", description="...") async def _ping(self, interaction: discord.) -> None: await interaction.response.send_message("pong!") - + @group.command(name="command", description="...") async def _cmd(self, interaction: discord.Interaction) -> None: await interaction.response.send_message("uwu") - + class MySlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix="!", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: await self.add_cog(MySlashGroupCog(self)) await self.tree.copy_global_to(discord.Object(id=123456789098765432)) await self.tree.sync() - + bot = MySlashBot() bot.run("token") @@ -242,20 +242,20 @@ class MySlashGroup(app_commands.Group, name="uwu"): @app_commands.command(name="ping", description="...") async def _ping(self, interaction: discord.) -> None: await interaction.response.send_message("pong!") - + @app_commands.command(name="command", description="...") async def _cmd(self, interaction: discord.Interaction) -> None: await interaction.response.send_message("uwu") - + class MySlashBot(commands.Bot): def __init__(self) -> None: super().__init__(command_prefix="!", intents=discord.Intents.default()) - + async def setup_hook(self) -> None: await self.add_cog(MySlashGroup(self)) await self.tree.copy_global_to(discord.Object(id=123456789098765432)) await self.tree.sync() - + bot = MySlashBot() bot.run("token") @@ -267,7 +267,7 @@ __**EXPLANATION**__ # Some common methods and features used for Slash Commands. ---- +--- ### A common function used for Slash Commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. @@ -349,13 +349,13 @@ import discord class Bot(commands.Bot): def __init__(self): super().__init__(command_prefix="uwu", intents=discord.Intents.all()) - - + + async def setup_hook(self): - self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) + self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) await self.tree.sync() - - + + bot = Bot() @bot.tree.command(name="ping") @@ -370,7 +370,7 @@ bot.run("token") __**EXPLANATION**__ - The first argument the `cooldown` method takes is the number of times this command can be invoked in a particular unit of time (Which will be defined in the following argument). -- The second argument it takes is the period of time in which the command can be run the specified number of times. +- The second argument it takes is the period of time in which the command can be run the specified number of times. - The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the gist. @@ -412,7 +412,7 @@ bot.run("token") __**EXPLANATION**__ First we create a simple asynchronous function named `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here we have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displaying unhandled errors, i.e. the ones which have not been handled manually. If this is **removed**, you will not be able to see any exceptions raised by Slash Commands and makes debugging the code harder. -After creating the error handler function, we set the function as the error handler for the Slash Commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. +After creating the error handler function, we set the function as the error handler for the Slash Commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. ### Creating an error handler for a specific error! -- cgit v1.2.3 From 45a47e5f1c791ae3ae31e6b295716eaffae7bb56 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 12 Nov 2022 20:05:25 -0800 Subject: Appeased the formatter --- .../resources/guides/python-guides/keeping-tokens-safe.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md index 8e9f7075..9d523b4b 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md +++ b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md @@ -2,14 +2,14 @@ title: Keeping Discord Bot Tokens Safe description: How to keep your bot tokens safe and safety measures you can take. --- -It's **very** important to keep a bot token safe, -primarily because anyone who has the bot token can do whatever they want with the bot -- +It's **very** important to keep a bot token safe, +primarily because anyone who has the bot token can do whatever they want with the bot -- such as destroying servers your bot has been added to and getting your bot banned from the API. # How to Avoid Leaking your Token -To help prevent leaking your token, -you should ensure that you don't upload it to an open source program/website, -such as replit and github, as they show your code publicly. +To help prevent leaking your token, +you should ensure that you don't upload it to an open source program/website, +such as replit and github, as they show your code publicly. The best practice for storing tokens is generally utilising .env files ([click here](https://vcokltfre.dev/tips/tokens/.) for more information on storing tokens safely). @@ -26,4 +26,4 @@ Following these steps will create a new token for your bot, making it secure aga The old token will stop working though, so make sure to replace the old token with the new one in your code if you haven't already. # Summary -Make sure you keep your token secure by storing it safely, not sending it to anyone you don't trust, and regenerating your token if it does get leaked. \ No newline at end of file +Make sure you keep your token secure by storing it safely, not sending it to anyone you don't trust, and regenerating your token if it does get leaked. -- cgit v1.2.3 From 0d59f046eac4a73f82885c84269ac02edf3d2bfe Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 12 Nov 2022 20:25:45 -0800 Subject: Migrated from #discord-bot pin --- .../guides/python-guides/fix-ssl-certificate.md | 23 +++++++++++++++++++++ .../images/content/fix-ssl-certificate/pem.png | Bin 0 -> 45703 bytes 2 files changed, 23 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md create mode 100644 pydis_site/static/images/content/fix-ssl-certificate/pem.png (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md b/pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md new file mode 100644 index 00000000..ea141838 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md @@ -0,0 +1,23 @@ +--- +title: Fixing an SSL Certificate Verification Error. +description: A guide on fixing verification of an SSL certificate. +--- + +We're fixing the error Python specifies as [ssl.SSLCertVerificationError](https://docs.python.org/3/library/ssl.html#ssl.SSLCertVerificationError). + +# How to fix SSL Certificate issue on Windows + +Firstly, try updating your OS, wouldn't hurt to try. + +Now, if you're still having an issue, you would need to download the certificate for the SSL. + +The SSL Certificate, Sectigo (cert vendor) provides a download link of [certificate](https://crt.sh/?id=2835394). You should find it in the bottom left corner, where it's saying Download Certificate: *PEM*. + +A picture where to find the certificate in the website is: +![location of certificate](/static/images/content/fix-ssl-certificate/pem.png) + +You have to setup the certificate yourself. To do that you can just click on it, or if that doesn't work, refer to [this link](https://portal.threatpulse.com/docs/sol/Solutions/ManagePolicy/SSL/ssl_chrome_cert_ta.htm) + +# How to fix SSL Certificate issue on Mac + +Navigate to your `Applications/Python 3.x/` folder and double-click the `Install Certificates.command` to fix this. diff --git a/pydis_site/static/images/content/fix-ssl-certificate/pem.png b/pydis_site/static/images/content/fix-ssl-certificate/pem.png new file mode 100644 index 00000000..d63d018d Binary files /dev/null and b/pydis_site/static/images/content/fix-ssl-certificate/pem.png differ -- cgit v1.2.3 From f4b3a0d006a07dd6f32c6105021f39c56ddfeadd Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 12 Nov 2022 20:55:26 -0800 Subject: Made stuff and things even better --- .../guides/python-guides/fix-ssl-certificate.md | 4 ++-- .../images/content/fix-ssl-certificate/pem.png | Bin 13988 -> 11619 bytes 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md b/pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md index ea141838..096e3a90 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md +++ b/pydis_site/apps/content/resources/guides/python-guides/fix-ssl-certificate.md @@ -1,5 +1,5 @@ --- -title: Fixing an SSL Certificate Verification Error. +title: Fixing an SSL Certificate Verification Error description: A guide on fixing verification of an SSL certificate. --- @@ -11,7 +11,7 @@ Firstly, try updating your OS, wouldn't hurt to try. Now, if you're still having an issue, you would need to download the certificate for the SSL. -The SSL Certificate, Sectigo (cert vendor) provides a download link of [certificate](https://crt.sh/?id=2835394). You should find it in the bottom left corner, where it's saying Download Certificate: *PEM*. +The SSL Certificate, Sectigo (cert vendor) provides a download link of an [SSL certificate](https://crt.sh/?id=2835394). You should find it in the bottom left corner, shown below: A picture where to find the certificate in the website is: ![location of certificate](/static/images/content/fix-ssl-certificate/pem.png) diff --git a/pydis_site/static/images/content/fix-ssl-certificate/pem.png b/pydis_site/static/images/content/fix-ssl-certificate/pem.png index cb902bb3..face520f 100644 Binary files a/pydis_site/static/images/content/fix-ssl-certificate/pem.png and b/pydis_site/static/images/content/fix-ssl-certificate/pem.png differ -- cgit v1.2.3 From 5a25a5233241bd6ca5b574d6a8bb9bd85790ca35 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sat, 19 Nov 2022 15:55:57 -0800 Subject: Appeased review requests. --- .../resources/guides/python-guides/app_commands.md | 49 +++++++++++----------- 1 file changed, 25 insertions(+), 24 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md index c319ebb1..ed6b24cd 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -2,19 +2,19 @@ --- -Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py gist regarding resumation can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). +Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://Gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). -# Why this gist? +# Why this Gist? --- This Gist is being created as an update to Slash Commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! -# What Are Slash Commands? +# What are Slash Commands? --- -Slash Commands are the exciting new way to build and interact with bots on Discord. With Slash Commands, all you have to do is type / and you're ready to use your favourite bot. You can easily see all the commands a bot has, and validation and error handling help you get the command right the first time. +Slash Commands are the exciting new way to build and interact with bots on Discord. As soon as you type "/", you can easily see all the commands a bot has. It also comes with autocomplete, validation and error handling, which will all help you get the command right the first time. # Install the latest version of discord.py @@ -22,27 +22,28 @@ Slash Commands are the exciting new way to build and interact with bots on Disco To use Slash Commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! And make sure to uninstall any third party libraries that support Slash Commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! -The latest and up-to-date usable discord.py version can be installed using `pip install -U git+https://github.com/Rapptz/discord.py`. +The latest and up-to-date usable discord.py version can be installed using `pip install -U discord.py`. If you get an error such as: `'git' is not recognized...`, it means that you don't have it installed on your platform. In that case, you will need to do do so by going through the required steps for [installing git](https://git-scm.com/downloads) and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U discord.py` again to install discord.py 2.0. -If you get an error such as: `'git' is not recognized...`. [Install git](https://git-scm.com/downloads) for your platform. Go through the required steps for installing git and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U git+https://github.com/Rapptz/discord.py` again to install discord.py 2.0. **BEFORE MIGRATING TO DISCORD.PY 2.0, PLEASE READ THE CONSEQUENCES OF THE UPDATE [HERE](https://discordpy.readthedocs.io/en/latest/migrating.html)**. -# Basic Structure for Discord.py Slash Commands! +# Basic structure for discord.py Slash Commands! --- ### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create Slash Commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. -# Fundamentals for this gist! +# Fundamentals for this Gist! --- -The fundamental for this gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. +The fundamental for this Gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. -__**FOLLOWING IS THE EXAMPLE OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ +__**THE FOLLOWING ARE EXAMPLES OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ + +Note that the default intents are defined [here](https://discordpy.readthedocs.io/en/stable/api.html?highlight=discord%20intents%20default#discord.Intents.default) to have all intents enabled except presences, members, and message_content. ```python import discord @@ -67,7 +68,7 @@ client.setup_hook = my_setup_hook # Basic Slash Command application using discord.py. -#### The `CommandTree` class resides within the `app_commands` of discord.py package. +#### The `CommandTree` class resides within the `app_commands` of the discord.py package. --- ## Slash Command Application with a Client @@ -98,14 +99,14 @@ __**EXPLANATION**__ - `import discord` imports the **discord.py** package. - `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. -- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commaands. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. **Essential to creation of commands** Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. - Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. - Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. - And the classic old `client.run("token")` is used to connect the client to the discord gateway. -- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the gist. +- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the Gist. -## Slash Command Application with a Bot +## Slash Command application with the Bot class ```python import discord @@ -131,7 +132,7 @@ The above example shows a basic Slash Commands within discord.py using the Bot c __**EXPLANATION**__ -Most of the explanation is the same as the prior example which featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. +Most of the explanation is the same as the prior example that featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. - The `SlashBot` class now subclasses `discord.ext.commands.Bot` following the passing in of the required arguments to its `__init__` method. - `discord.ext.commands.Bot` already consists of an instance of the `CommandTree` class which can be accessed using the `tree` property. @@ -173,7 +174,7 @@ bot.run("token") __**EXPLANATION**__ -- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` directory from the **discord.py** root directory. `from discord.ext import commands` imports the commands extension. +- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` module from the **discord.py** root module. `from discord.ext import commands` imports the commands extension. - Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). - `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. - Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for Slash Commands with **self** added as the first parameter to the function as it is a method of a class. @@ -223,7 +224,7 @@ bot.run("token") ``` __**EXPLANATION**__ -- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. +- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` reGisters a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are reGistered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. --- @@ -262,7 +263,7 @@ bot.run("token") ``` __**EXPLANATION**__ -- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. +- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically reGisters all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. # Some common methods and features used for Slash Commands. @@ -282,7 +283,7 @@ bot = commands.Bot(command_prefix=".", intents=discord.Intents.default()) @bot.tree.command(name="echo", description="...") @app_commands.describe(text="The text to send!", channel="The channel to send the message in!") async def _echo(interaction: discord.Interaction, text: str, channel: discord.TextChannel=None): - channel = interaction.channel or channel + channel = channel or interaction.channel await channel.send(text) ``` @@ -327,7 +328,7 @@ async def _ping(interaction: discord.Interaction): ``` -If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! We will discuss making an error handler later in the gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). +If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! We will discuss making an error handler later in the Gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). Other methods that you can decorate the commands with are - - `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. @@ -339,7 +340,7 @@ Other methods that you can decorate the commands with are - --- -Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. +Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and reGister a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. An example is as follows. ```python @@ -369,9 +370,9 @@ bot.run("token") ``` __**EXPLANATION**__ -- The first argument the `cooldown` method takes is the number of times this command can be invoked in a particular unit of time (Which will be defined in the following argument). +- The first argument is the number of times this command can be invoked before the cooldown is triggered. - The second argument it takes is the period of time in which the command can be run the specified number of times. -- The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the gist. +- The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the Gist. # Handling errors for Slash Commands! -- cgit v1.2.3 From 2c6ce25b38e67e5c7755c0cea8a14d8dcd2a3ae0 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sun, 20 Nov 2022 05:27:29 -0800 Subject: I can't spell --- .../content/resources/guides/python-guides/app_commands.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md index ed6b24cd..9880beb5 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -2,7 +2,7 @@ --- -Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://Gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). +Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). # Why this Gist? @@ -22,7 +22,7 @@ Slash Commands are the exciting new way to build and interact with bots on Disco To use Slash Commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! And make sure to uninstall any third party libraries that support Slash Commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! -The latest and up-to-date usable discord.py version can be installed using `pip install -U discord.py`. If you get an error such as: `'git' is not recognized...`, it means that you don't have it installed on your platform. In that case, you will need to do do so by going through the required steps for [installing git](https://git-scm.com/downloads) and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U discord.py` again to install discord.py 2.0. +The latest and up-to-date usable discord.py version can be installed using `pip install -U discord.py`. If you get an error such as: `'git' is not recognized...`, it means that you don't have git installed on your platform. In that case, you will need to do so by going through the required steps for [installing git](https://git-scm.com/downloads) and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U discord.py` again to install discord.py 2.0 **BEFORE MIGRATING TO DISCORD.PY 2.0, PLEASE READ THE CONSEQUENCES OF THE UPDATE [HERE](https://discordpy.readthedocs.io/en/latest/migrating.html)**. @@ -224,7 +224,7 @@ bot.run("token") ``` __**EXPLANATION**__ -- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` reGisters a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are reGistered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. +- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. --- @@ -263,8 +263,7 @@ bot.run("token") ``` __**EXPLANATION**__ -- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically reGisters all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. - +- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. # Some common methods and features used for Slash Commands. @@ -340,7 +339,7 @@ Other methods that you can decorate the commands with are - --- -Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and reGister a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. +Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. An example is as follows. ```python -- cgit v1.2.3 From 0179ae50cbb49c83eeca4493e14a67e813ef3772 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sun, 20 Nov 2022 06:11:52 -0800 Subject: Appeased the requests from reviews. --- .../setting-different-statuses-on-your-bot.md | 39 +++++++++++----------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md b/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md index 53390416..b44c55e1 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md @@ -1,13 +1,22 @@ --- -title: Setting Different Statuses to Set Your Bot +title: Setting Different Statuses on Your Bot description: How to personalize your Discord bot status --- + +You've probably seen a bot or two have a status message under their username in the member bar set to something such as `Playing Commands: .help`. + +This guide shows how to set such a presence, so your bot can have one as well. + **Please note:** -If you want to change the bot status, it is suggested to not do it during the on_ready event, since it would be called -many times and making an API call on that event has a chance to disconnect the bot. -Instead, set the desired status using the activity / status kwarg of commands.Bot, for example -`bot = commands.Bot(command_prefix="!", activity=..., status=...)` +If you want to change the bot status, it is suggested to not do so during the on_ready event, since it would be called many times and making an API call on that event has a chance to disconnect the bot. + +Instead, set the desired status using the activity / status kwarg of commands.Bot, for example: +```python +bot = commands.Bot(command_prefix="!", activity=..., status=...) +``` + +The following are examples of what you can put into the `activity` keyword argument. #### Setting 'Playing' Status ```python @@ -29,19 +38,9 @@ await client.change_presence(activity=discord.Activity(type=discord.ActivityType await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="a movie")) ``` -#### Add Optional Status as Well: - -* status=discord.Status.\ - -####Available Statuses: - -* do_not_disturb(red icon) - - -* idle(yellow icon) - - -* online(default, green icon) - +### Add Optional Status as Well: -* offline(gray icon) +* `discord.Status.online` (default, green icon) +* `discord.Status.idle` (yellow icon) +* `discord.Status.do_not_disturb` (red icon) +* `discord.Status.offline` (gray icon) -- cgit v1.2.3 From 7e12ad290b0a5c1d9f5ca0bb4ba0f20983552270 Mon Sep 17 00:00:00 2001 From: wookie184 Date: Sun, 20 Nov 2022 14:17:42 +0000 Subject: Changes from proofread --- .../resources/guides/python-guides/app_commands.md | 63 ++++++---------------- 1 file changed, 16 insertions(+), 47 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md index 9880beb5..1354a136 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md @@ -1,44 +1,33 @@ -# DISCORD.PY RESUMATION CHANGES - --- - -Upon resumption of the most popular discord API wrapper library for python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with addition of features to the library. Some additions to the library are -> Buttons support, Select Menus Support, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch of more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). - -# Why this Gist? - +title: Discord.py 2.0 changes +description: Changes and new features in version 2.0 of discord.py --- -This Gist is being created as an update to Slash Commands (app commands) with explanation and examples. This Gist mainly focuses on **SLASH COMMANDS** for discord.py 2.0 (and above)! +Upon the return of the most popular discord API wrapper library for Python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with additions of features to the library. Additions to the library include support for Buttons, Select Menus, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). -# What are Slash Commands? ---- +# Install the latest version of discord.py -Slash Commands are the exciting new way to build and interact with bots on Discord. As soon as you type "/", you can easily see all the commands a bot has. It also comes with autocomplete, validation and error handling, which will all help you get the command right the first time. +Before you can make use of any of the new 2.0 features, you need to install the latest version of discord.py. Make sure that the version is 2.0 or above! +Also, make sure to uninstall any third party libraries intended to add slash-command support to pre-2.0 discord.py, as they are no longer necessary and will likely cause issues. -# Install the latest version of discord.py +The latest and most up-to-date stable discord.py version can be installed using `pip install -U discord.py`. ---- -To use Slash Commands with discord.py. The latest up-to-date version has to be installed. Make sure that the version is 2.0 or above! -And make sure to uninstall any third party libraries that support Slash Commands for discord.py (if any) as a few of them [monkey patch](https://en.wikipedia.org/wiki/Monkey_patch#:~:text=A%20monkey%20patch%20is%20a,running%20instance%20of%20the%20program) discord.py! +**Before migrating to discord.py 2.0, make sure you read the migration guide [here](https://discordpy.readthedocs.io/en/latest/migrating.html) as there are lots of breaking changes.**. +{: .notification .is-warning } -The latest and up-to-date usable discord.py version can be installed using `pip install -U discord.py`. If you get an error such as: `'git' is not recognized...`, it means that you don't have git installed on your platform. In that case, you will need to do so by going through the required steps for [installing git](https://git-scm.com/downloads) and make sure to enable the `add to path` option while in the installation wizard. After installing git you can run `pip install -U discord.py` again to install discord.py 2.0 +# What are Slash Commands? -**BEFORE MIGRATING TO DISCORD.PY 2.0, PLEASE READ THE CONSEQUENCES OF THE UPDATE [HERE](https://discordpy.readthedocs.io/en/latest/migrating.html)**. +Slash Commands are an exciting new way to build and interact with bots on Discord. As soon as you type "/", you can easily see all the commands a bot has. It also comes with autocomplete, validation and error handling, which will all help users of your bot get the command right the first time. # Basic structure for discord.py Slash Commands! ---- - ### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create Slash Commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. # Fundamentals for this Gist! ---- - - -The fundamental for this Gist will remain to be the `setup_hook`. The `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. +One new feature added in discord.py v2 is `setup_hook`. `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. __**THE FOLLOWING ARE EXAMPLES OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ @@ -48,7 +37,7 @@ Note that the default intents are defined [here](https://discordpy.readthedocs.i ```python import discord -'''This is one way of creating a "setup_hook" method''' +# You can create the setup_hook directly in the class definition class SlashClient(discord.Client): def __init__(self) -> None: @@ -57,7 +46,7 @@ class SlashClient(discord.Client): async def setup_hook(self) -> None: ... -'''Another way of creating a "setup_hook" is as follows''' +# Or add it to the client after creating it client = discord.Client(intents=discord.Intents.default()) async def my_setup_hook() -> None: @@ -69,7 +58,6 @@ client.setup_hook = my_setup_hook # Basic Slash Command application using discord.py. #### The `CommandTree` class resides within the `app_commands` of the discord.py package. ---- ## Slash Command Application with a Client @@ -139,8 +127,6 @@ Most of the explanation is the same as the prior example that featured `SlashCli # Slash Commands within a Cog! ---- - A cog is a collection of commands, listeners, and optional state to help group commands together. More information on them can be found on the [Cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs) page. ## An Example to using cogs with discord.py for Slash Commands! @@ -184,8 +170,6 @@ __**EXPLANATION**__ # An Example to using groups with discord.py for Slash Commands! ---- - ## An example with optional group! ```python @@ -226,8 +210,6 @@ bot.run("token") __**EXPLANATION**__ - The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. ---- - ## An example with a **Group** subclass! ```python @@ -267,8 +249,6 @@ __**EXPLANATION**__ # Some common methods and features used for Slash Commands. ---- - ### A common function used for Slash Commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. ```python @@ -308,8 +288,6 @@ async def _time(interaction: discord.Interaction, time_to_wait: int): # Checking for Permissions and Roles! ---- - To add a permissions check to a command, the methods are imported through `discord.app_commands.checks`. To check for a member's permissions, the function can be decorated with the [discord.app_commands.checks.has_permissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=has_permissions#discord.app_commands.checks.has_permissions) method. An example to this as follows. ```py @@ -337,8 +315,6 @@ Other methods that you can decorate the commands with are - # Adding cooldowns to Slash Commands! ---- - Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. An example is as follows. @@ -350,7 +326,6 @@ class Bot(commands.Bot): def __init__(self): super().__init__(command_prefix="uwu", intents=discord.Intents.all()) - async def setup_hook(self): self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) await self.tree.sync() @@ -376,8 +351,6 @@ __**EXPLANATION**__ # Handling errors for Slash Commands! ---- - The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the Slash Commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). An example to creating an error handler for Slash Commands is as follows. @@ -397,10 +370,8 @@ async def ping(interaction: discord.Interaction): async def on_tree_error(interaction: discord.Interaction, error: app_commands.AppCommandError): if isinstance(error, app_commands.CommandOnCooldown): return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - - elif isinstance(..., ...): + elif isinstance(error, ...): ... - else: raise error @@ -433,10 +404,8 @@ async def ping(interaction: discord.Interaction): async def ping_error(interaction: discord.Interaction, error: app_commands.AppCommandError): if isinstance(error, app_commands.CommandOnCooldown): return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - elif isinstance(error, ...): ... - else: raise error @@ -445,4 +414,4 @@ bot.run("token") __**EXPLANATION**__ -Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. Please do not call the `error` method. +Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. You should not need to call the `error` method manually. -- cgit v1.2.3 From 58845b3653d6a4864c9d32a2950e3e3f8e74c2c5 Mon Sep 17 00:00:00 2001 From: wookie184 Date: Sun, 20 Nov 2022 14:19:08 +0000 Subject: Rename file for consistency --- .../resources/guides/python-guides/app-commands.md | 417 +++++++++++++++++++++ .../resources/guides/python-guides/app_commands.md | 417 --------------------- 2 files changed, 417 insertions(+), 417 deletions(-) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/app-commands.md delete mode 100644 pydis_site/apps/content/resources/guides/python-guides/app_commands.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/app-commands.md new file mode 100644 index 00000000..1354a136 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/app-commands.md @@ -0,0 +1,417 @@ +--- +title: Discord.py 2.0 changes +description: Changes and new features in version 2.0 of discord.py +--- + +Upon the return of the most popular discord API wrapper library for Python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with additions of features to the library. Additions to the library include support for Buttons, Select Menus, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). + + +# Install the latest version of discord.py + +Before you can make use of any of the new 2.0 features, you need to install the latest version of discord.py. Make sure that the version is 2.0 or above! +Also, make sure to uninstall any third party libraries intended to add slash-command support to pre-2.0 discord.py, as they are no longer necessary and will likely cause issues. + +The latest and most up-to-date stable discord.py version can be installed using `pip install -U discord.py`. + +**Before migrating to discord.py 2.0, make sure you read the migration guide [here](https://discordpy.readthedocs.io/en/latest/migrating.html) as there are lots of breaking changes.**. +{: .notification .is-warning } + +# What are Slash Commands? + +Slash Commands are an exciting new way to build and interact with bots on Discord. As soon as you type "/", you can easily see all the commands a bot has. It also comes with autocomplete, validation and error handling, which will all help users of your bot get the command right the first time. + +# Basic structure for discord.py Slash Commands! + +### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. +Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create Slash Commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. + +# Fundamentals for this Gist! + +One new feature added in discord.py v2 is `setup_hook`. `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. +Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. + +__**THE FOLLOWING ARE EXAMPLES OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ + +Note that the default intents are defined [here](https://discordpy.readthedocs.io/en/stable/api.html?highlight=discord%20intents%20default#discord.Intents.default) to have all intents enabled except presences, members, and message_content. + +```python +import discord + +# You can create the setup_hook directly in the class definition + +class SlashClient(discord.Client): + def __init__(self) -> None: + super().__init__(intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + ... + +# Or add it to the client after creating it + +client = discord.Client(intents=discord.Intents.default()) +async def my_setup_hook() -> None: + ... + +client.setup_hook = my_setup_hook +``` + +# Basic Slash Command application using discord.py. + +#### The `CommandTree` class resides within the `app_commands` of the discord.py package. + +## Slash Command Application with a Client + +```python +import discord + +class SlashClient(discord.Client): + def __init__(self) -> None: + super().__init__(intents=discord.Intents.default()) + self.tree = discord.app_commands.CommandTree(self) + + async def setup_hook(self) -> None: + self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) + await self.tree.sync() + +client = SlashClient() + +@client.tree.command(name="ping", description="...") +async def _ping(interaction: discord.Interaction) -> None: + await interaction.response.send_message("pong") + +client.run("token") +``` + + +__**EXPLANATION**__ + +- `import discord` imports the **discord.py** package. +- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. +- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commands. +- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. **Essential to creation of commands** Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. +- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. +- Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. +- And the classic old `client.run("token")` is used to connect the client to the discord gateway. +- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the Gist. + +## Slash Command application with the Bot class + +```python +import discord + +class SlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix=".", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) + await self.tree.sync() + +bot = SlashBot() + +@bot.tree.command(name="ping", description="...") +async def _ping(interaction: discord.Interaction) -> None: + await interaction.response.send_message("pong") + +bot.run("token") +``` + +The above example shows a basic Slash Commands within discord.py using the Bot class. + +__**EXPLANATION**__ + +Most of the explanation is the same as the prior example that featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. + +- The `SlashBot` class now subclasses `discord.ext.commands.Bot` following the passing in of the required arguments to its `__init__` method. +- `discord.ext.commands.Bot` already consists of an instance of the `CommandTree` class which can be accessed using the `tree` property. + +# Slash Commands within a Cog! + +A cog is a collection of commands, listeners, and optional state to help group commands together. More information on them can be found on the [Cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs) page. + +## An Example to using cogs with discord.py for Slash Commands! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashCog(commands.Cog): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashCog(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ + +- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` module from the **discord.py** root module. `from discord.ext import commands` imports the commands extension. +- Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). +- `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. +- Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for Slash Commands with **self** added as the first parameter to the function as it is a method of a class. +- The next up lines are mostly the same. +- Talking about the first line inside the `setup_hook` is the `add_cog` method of the **Bot** class. And since **self** acts as the **instance** of the current class, we use **self** to use the `add_cog` method of the **Bot** class as we are inside a subclassed class of the **Bot** class. Then we pass in **self** to the `add_cog` method as the `__init__` function of the **MySlashCog** cog accepts a `Bot` object. +- After that we instantiate the `MySlashBot` class and run the bot using the **run** method which executes our setup_hook function and our commands get loaded and synced. The bot is now ready to use! + +# An Example to using groups with discord.py for Slash Commands! + +## An example with optional group! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashGroupCog(commands.Cog): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + #-------------------------------------------------------- + group = app_commands.Group(name="uwu", description="...") + #-------------------------------------------------------- + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.) -> None: + await interaction.response.send_message("pong!") + + @group.command(name="command", description="...") + async def _cmd(self, interaction: discord.Interaction) -> None: + await interaction.response.send_message("uwu") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashGroupCog(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ +- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. + +## An example with a **Group** subclass! + +```python +import discord +from discord.ext import commands +from discord import app_commands + +class MySlashGroup(app_commands.Group, name="uwu"): + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + super().__init__() + + @app_commands.command(name="ping", description="...") + async def _ping(self, interaction: discord.) -> None: + await interaction.response.send_message("pong!") + + @app_commands.command(name="command", description="...") + async def _cmd(self, interaction: discord.Interaction) -> None: + await interaction.response.send_message("uwu") + +class MySlashBot(commands.Bot): + def __init__(self) -> None: + super().__init__(command_prefix="!", intents=discord.Intents.default()) + + async def setup_hook(self) -> None: + await self.add_cog(MySlashGroup(self)) + await self.tree.copy_global_to(discord.Object(id=123456789098765432)) + await self.tree.sync() + +bot = MySlashBot() + +bot.run("token") +``` + +__**EXPLANATION**__ +- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. + +# Some common methods and features used for Slash Commands. + +### A common function used for Slash Commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix=".", intents=discord.Intents.default()) +#sync the commands + +@bot.tree.command(name="echo", description="...") +@app_commands.describe(text="The text to send!", channel="The channel to send the message in!") +async def _echo(interaction: discord.Interaction, text: str, channel: discord.TextChannel=None): + channel = channel or interaction.channel + await channel.send(text) +``` + +### Another common issue that most people come across is the time duration of sending a message with `send_message`. This issue can be tackled by deferring the interaction response using the `defer` method of the `InteractionResponse` class. An example for fixing this issue is shown below. + +```python +import discord +from discord.ext import commands +import asyncio + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync the commands + +@bot.tree.command(name="time", description="...") +async def _time(interaction: discord.Interaction, time_to_wait: int): + # ------------------------------------------------------------- + await interaction.response.defer(ephemeral=True, thinking=True) + # ------------------------------------------------------------- + await interaction.edit_original_message(content=f"I will notify you after {time_to_wait} seconds have passed!") + await asyncio.sleep(time_to_wait) + await interaction.edit_original_message(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") +``` + +# Checking for Permissions and Roles! + +To add a permissions check to a command, the methods are imported through `discord.app_commands.checks`. To check for a member's permissions, the function can be decorated with the [discord.app_commands.checks.has_permissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=has_permissions#discord.app_commands.checks.has_permissions) method. An example to this as follows. + +```py +from discord import app_commands +from discord.ext import commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +@app_commands.checks.has_permissions(manage_messages=True, manage_channels=True) #example permissions +async def _ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +``` + +If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! We will discuss making an error handler later in the Gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). + +Other methods that you can decorate the commands with are - +- `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. +- `has_role` | This checks if the slash command user has the required role or not. Only **ONE** role name or role ID can be passed to this. If the name is being passed, make sure to have the exact same name as the role name. This raises a [MissingRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingRole) exception. +- To pass in several role names or role IDs, `has_any_role` can be used to decorate a command. This raises two exceptions -> [MissingAnyRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingAnyRole) and [NoPrivateMessage](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.NoPrivateMessage) + + +# Adding cooldowns to Slash Commands! + +Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. +An example is as follows. + +```python +from discord.ext import commands +import discord + +class Bot(commands.Bot): + def __init__(self): + super().__init__(command_prefix="uwu", intents=discord.Intents.all()) + + async def setup_hook(self): + self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) + await self.tree.sync() + + +bot = Bot() + +@bot.tree.command(name="ping") +# ----------------------------------------- +@discord.app_commands.checks.cooldown(1, 30) +# ----------------------------------------- +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +bot.run("token") +``` + +__**EXPLANATION**__ +- The first argument is the number of times this command can be invoked before the cooldown is triggered. +- The second argument it takes is the period of time in which the command can be run the specified number of times. +- The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the Gist. + + +# Handling errors for Slash Commands! + +The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the Slash Commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). +An example to creating an error handler for Slash Commands is as follows. + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +@app_commands.checks.cooldown(1, 30) +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +async def on_tree_error(interaction: discord.Interaction, error: app_commands.AppCommandError): + if isinstance(error, app_commands.CommandOnCooldown): + return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") + elif isinstance(error, ...): + ... + else: + raise error + +bot.tree.on_error = on_tree_error + +bot.run("token") +``` + +__**EXPLANATION**__ + +First we create a simple asynchronous function named `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here we have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displaying unhandled errors, i.e. the ones which have not been handled manually. If this is **removed**, you will not be able to see any exceptions raised by Slash Commands and makes debugging the code harder. +After creating the error handler function, we set the function as the error handler for the Slash Commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. + +### Creating an error handler for a specific error! + +```python +from discord.ext import commands +from discord import app_commands +import discord + +bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) +#sync commands + +@bot.tree.command(name="ping") +app_commands.checks.cooldown(1, 30) +async def ping(interaction: discord.Interaction): + await interaction.response.send_message("pong!") + +@ping.error +async def ping_error(interaction: discord.Interaction, error: app_commands.AppCommandError): + if isinstance(error, app_commands.CommandOnCooldown): + return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") + elif isinstance(error, ...): + ... + else: + raise error + +bot.run("token") +``` + +__**EXPLANATION**__ + +Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. You should not need to call the `error` method manually. diff --git a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md b/pydis_site/apps/content/resources/guides/python-guides/app_commands.md deleted file mode 100644 index 1354a136..00000000 --- a/pydis_site/apps/content/resources/guides/python-guides/app_commands.md +++ /dev/null @@ -1,417 +0,0 @@ ---- -title: Discord.py 2.0 changes -description: Changes and new features in version 2.0 of discord.py ---- - -Upon the return of the most popular discord API wrapper library for Python, `discord.py`, while catching on to the latest features of the discord API, there have been numerous changes with additions of features to the library. Additions to the library include support for Buttons, Select Menus, Forms (AKA Modals), Slash Commands (AKA Application Commands) and a bunch more handy features! All the changes can be found [here](https://discordpy.readthedocs.io/en/latest/migrating.html). Original discord.py Gist regarding resumption can be found [here](https://gist.github.com/Rapptz/c4324f17a80c94776832430007ad40e6). - - -# Install the latest version of discord.py - -Before you can make use of any of the new 2.0 features, you need to install the latest version of discord.py. Make sure that the version is 2.0 or above! -Also, make sure to uninstall any third party libraries intended to add slash-command support to pre-2.0 discord.py, as they are no longer necessary and will likely cause issues. - -The latest and most up-to-date stable discord.py version can be installed using `pip install -U discord.py`. - -**Before migrating to discord.py 2.0, make sure you read the migration guide [here](https://discordpy.readthedocs.io/en/latest/migrating.html) as there are lots of breaking changes.**. -{: .notification .is-warning } - -# What are Slash Commands? - -Slash Commands are an exciting new way to build and interact with bots on Discord. As soon as you type "/", you can easily see all the commands a bot has. It also comes with autocomplete, validation and error handling, which will all help users of your bot get the command right the first time. - -# Basic structure for discord.py Slash Commands! - -### Note that Slash Commands in discord.py are also referred to as **Application Commmands** and **App Commands** and every *interaction* is a *webhook*. -Slash commands in discord.py are held by a container, [CommandTree](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=commandtree#discord.app_commands.CommandTree). A command tree is required to create Slash Commands in discord.py. This command tree provides a `command` method which decorates an asynchronous function indicating to discord.py that the decorated function is intended to be a slash command. This asynchronous function expects a default argument which acts as the interaction which took place that invoked the slash command. This default argument is an instance of the **Interaction** class from discord.py. Further up, the command logic takes over the behaviour of the slash command. - -# Fundamentals for this Gist! - -One new feature added in discord.py v2 is `setup_hook`. `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. -Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. - -__**THE FOLLOWING ARE EXAMPLES OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ - -Note that the default intents are defined [here](https://discordpy.readthedocs.io/en/stable/api.html?highlight=discord%20intents%20default#discord.Intents.default) to have all intents enabled except presences, members, and message_content. - -```python -import discord - -# You can create the setup_hook directly in the class definition - -class SlashClient(discord.Client): - def __init__(self) -> None: - super().__init__(intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - ... - -# Or add it to the client after creating it - -client = discord.Client(intents=discord.Intents.default()) -async def my_setup_hook() -> None: - ... - -client.setup_hook = my_setup_hook -``` - -# Basic Slash Command application using discord.py. - -#### The `CommandTree` class resides within the `app_commands` of the discord.py package. - -## Slash Command Application with a Client - -```python -import discord - -class SlashClient(discord.Client): - def __init__(self) -> None: - super().__init__(intents=discord.Intents.default()) - self.tree = discord.app_commands.CommandTree(self) - - async def setup_hook(self) -> None: - self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) - await self.tree.sync() - -client = SlashClient() - -@client.tree.command(name="ping", description="...") -async def _ping(interaction: discord.Interaction) -> None: - await interaction.response.send_message("pong") - -client.run("token") -``` - - -__**EXPLANATION**__ - -- `import discord` imports the **discord.py** package. -- `class SlashClient(discord.Client)` is a class subclassing **Client**. Though there is no particular reason except readability to subclass the **Client** class, using the `Client.setup_hook = my_func` is equally valid. -- Next up `super().__init__(...)` runs the `__init__` function of the **Client** class, this is equivalent to `discord.Client(...)`. Then, `self.tree = discord.app_commands.CommandTree(self)` creates a CommandTree which acts as the container for slash commands. -- Then in the `setup_hook`, `self.tree.copy_global_to(...)` adds the slash command to the guild of which the ID is provided as a `discord.Object` object. **Essential to creation of commands** Further up, `self.tree.sync()` updates the API with any changes to the Slash Commands. -- Finishing up with the **Client** subclass, we create an instance of the subclassed Client class which here has been named as `SlashClient` with `client = SlashClient()`. -- Then using the `command` method of the `CommandTree` we decorate a function with it as `client.tree` is an instance of `CommandTree` for the current application. The command function takes a default argument as said, which acts as the interaction that took place. Catching up is `await interaction.response.send_message("pong")` which sends back a message to the slash command invoker. -- And the classic old `client.run("token")` is used to connect the client to the discord gateway. -- Note that the `send_message` is a method of the `InteractionResponse` class and `interaction.response` in this case is an instance of the `InteractionResponse` object. The `send_message` method will not function if the response is not sent within 3 seconds of command invocation. We will discuss how to handle this issue later following the Gist. - -## Slash Command application with the Bot class - -```python -import discord - -class SlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix=".", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - self.tree.copy_global_to(guild=discord.Object(id=12345678900987654)) - await self.tree.sync() - -bot = SlashBot() - -@bot.tree.command(name="ping", description="...") -async def _ping(interaction: discord.Interaction) -> None: - await interaction.response.send_message("pong") - -bot.run("token") -``` - -The above example shows a basic Slash Commands within discord.py using the Bot class. - -__**EXPLANATION**__ - -Most of the explanation is the same as the prior example that featured `SlashClient` which was a subclass of **discord.Client**. Though some minor changes are discussed below. - -- The `SlashBot` class now subclasses `discord.ext.commands.Bot` following the passing in of the required arguments to its `__init__` method. -- `discord.ext.commands.Bot` already consists of an instance of the `CommandTree` class which can be accessed using the `tree` property. - -# Slash Commands within a Cog! - -A cog is a collection of commands, listeners, and optional state to help group commands together. More information on them can be found on the [Cogs](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs) page. - -## An Example to using cogs with discord.py for Slash Commands! - -```python -import discord -from discord.ext import commands -from discord import app_commands - -class MySlashCog(commands.Cog): - def __init__(self, bot: commands.Bot) -> None: - self.bot = bot - - @app_commands.command(name="ping", description="...") - async def _ping(self, interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -class MySlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix="!", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - await self.add_cog(MySlashCog(self)) - await self.tree.copy_global_to(discord.Object(id=123456789098765432)) - await self.tree.sync() - -bot = MySlashBot() - -bot.run("token") -``` - -__**EXPLANATION**__ - -- Firstly, `import discord` imports the **discord.py** package. `from discord import app_commands` imports the `app_commands` module from the **discord.py** root module. `from discord.ext import commands` imports the commands extension. -- Further up, `class MySlashCog(commands.Cog)` is a class subclassing the `Cog` class. You can read more about this [here](https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html#ext-commands-cogs). -- `def __init__(self, bot: commands.Bot): self.bot = bot` is the constructor method of the class that is always run when the class is instantiated and that is why we pass in a **Bot** object whenever we create an instance of the cog class. -- Following up is the `@app_commands.command(name="ping", description="...")` decorator. This decorator basically functions the same as a `bot.tree.command` but since the cog currently does not have a **bot**, the `app_commands.command` decorator is used instead. The next two lines follow the same structure for Slash Commands with **self** added as the first parameter to the function as it is a method of a class. -- The next up lines are mostly the same. -- Talking about the first line inside the `setup_hook` is the `add_cog` method of the **Bot** class. And since **self** acts as the **instance** of the current class, we use **self** to use the `add_cog` method of the **Bot** class as we are inside a subclassed class of the **Bot** class. Then we pass in **self** to the `add_cog` method as the `__init__` function of the **MySlashCog** cog accepts a `Bot` object. -- After that we instantiate the `MySlashBot` class and run the bot using the **run** method which executes our setup_hook function and our commands get loaded and synced. The bot is now ready to use! - -# An Example to using groups with discord.py for Slash Commands! - -## An example with optional group! - -```python -import discord -from discord.ext import commands -from discord import app_commands - -class MySlashGroupCog(commands.Cog): - def __init__(self, bot: commands.Bot) -> None: - self.bot = bot - - #-------------------------------------------------------- - group = app_commands.Group(name="uwu", description="...") - #-------------------------------------------------------- - - @app_commands.command(name="ping", description="...") - async def _ping(self, interaction: discord.) -> None: - await interaction.response.send_message("pong!") - - @group.command(name="command", description="...") - async def _cmd(self, interaction: discord.Interaction) -> None: - await interaction.response.send_message("uwu") - -class MySlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix="!", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - await self.add_cog(MySlashGroupCog(self)) - await self.tree.copy_global_to(discord.Object(id=123456789098765432)) - await self.tree.sync() - -bot = MySlashBot() - -bot.run("token") -``` - -__**EXPLANATION**__ -- The only difference used here is `group = app_commands.Group(name="uwu", description="...")` and `group.command`. `app_commands.Group` is used to initiate a group while `group.command` registers a command under a group. For example, the ping command can be run using **/ping** but this is not the case for group commands. They are registered with the format of `group_name command_name`. So here, the **command** command of the **uwu** group would be run using **/uwu command**. Note that only group commands can have a single space between them. - -## An example with a **Group** subclass! - -```python -import discord -from discord.ext import commands -from discord import app_commands - -class MySlashGroup(app_commands.Group, name="uwu"): - def __init__(self, bot: commands.Bot) -> None: - self.bot = bot - super().__init__() - - @app_commands.command(name="ping", description="...") - async def _ping(self, interaction: discord.) -> None: - await interaction.response.send_message("pong!") - - @app_commands.command(name="command", description="...") - async def _cmd(self, interaction: discord.Interaction) -> None: - await interaction.response.send_message("uwu") - -class MySlashBot(commands.Bot): - def __init__(self) -> None: - super().__init__(command_prefix="!", intents=discord.Intents.default()) - - async def setup_hook(self) -> None: - await self.add_cog(MySlashGroup(self)) - await self.tree.copy_global_to(discord.Object(id=123456789098765432)) - await self.tree.sync() - -bot = MySlashBot() - -bot.run("token") -``` - -__**EXPLANATION**__ -- The only difference here too is that the `MySlashGroup` class directly subclasses the **Group** class from discord.app_commands which automatically registers all the methods within the group class to be commands of that specific group. So now, the commands such as `ping` can be run using **/uwu ping** and `command` using **/uwu command**. - -# Some common methods and features used for Slash Commands. - -### A common function used for Slash Commands is the `describe` function. This is used to add descriptions to the arguments of a slash command. The command function can decorated with this function. It goes by the following syntax as shown below. - -```python -from discord.ext import commands -from discord import app_commands -import discord - -bot = commands.Bot(command_prefix=".", intents=discord.Intents.default()) -#sync the commands - -@bot.tree.command(name="echo", description="...") -@app_commands.describe(text="The text to send!", channel="The channel to send the message in!") -async def _echo(interaction: discord.Interaction, text: str, channel: discord.TextChannel=None): - channel = channel or interaction.channel - await channel.send(text) -``` - -### Another common issue that most people come across is the time duration of sending a message with `send_message`. This issue can be tackled by deferring the interaction response using the `defer` method of the `InteractionResponse` class. An example for fixing this issue is shown below. - -```python -import discord -from discord.ext import commands -import asyncio - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync the commands - -@bot.tree.command(name="time", description="...") -async def _time(interaction: discord.Interaction, time_to_wait: int): - # ------------------------------------------------------------- - await interaction.response.defer(ephemeral=True, thinking=True) - # ------------------------------------------------------------- - await interaction.edit_original_message(content=f"I will notify you after {time_to_wait} seconds have passed!") - await asyncio.sleep(time_to_wait) - await interaction.edit_original_message(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") -``` - -# Checking for Permissions and Roles! - -To add a permissions check to a command, the methods are imported through `discord.app_commands.checks`. To check for a member's permissions, the function can be decorated with the [discord.app_commands.checks.has_permissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=has_permissions#discord.app_commands.checks.has_permissions) method. An example to this as follows. - -```py -from discord import app_commands -from discord.ext import commands -import discord - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync commands - -@bot.tree.command(name="ping") -@app_commands.checks.has_permissions(manage_messages=True, manage_channels=True) #example permissions -async def _ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -``` - -If the check fails, it will raise a `MissingPermissions` error which can be handled within an app commands error handler! We will discuss making an error handler later in the Gist. All the permissions can be found [here](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discord%20permissions#discord.Permissions). - -Other methods that you can decorate the commands with are - -- `bot_has_permissions` | This checks if the bot has the required permissions for executing the slash command. This raises a [BotMissingPermissions](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.BotMissingPermissions) exception. -- `has_role` | This checks if the slash command user has the required role or not. Only **ONE** role name or role ID can be passed to this. If the name is being passed, make sure to have the exact same name as the role name. This raises a [MissingRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingRole) exception. -- To pass in several role names or role IDs, `has_any_role` can be used to decorate a command. This raises two exceptions -> [MissingAnyRole](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.MissingAnyRole) and [NoPrivateMessage](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=app_commands%20checks%20has_role#discord.app_commands.NoPrivateMessage) - - -# Adding cooldowns to Slash Commands! - -Slash Commands within discord.py can be applied cooldowns to in order to prevent spamming of the commands. This can be done through the `discord.app_commands.checks.cooldown` method which can be used to decorate a slash command function and register a cooldown to the function. This raises a [CommandOnCooldown](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=checks%20cooldown#discord.app_commands.CommandOnCooldown) exception if the command is currently on cooldown. -An example is as follows. - -```python -from discord.ext import commands -import discord - -class Bot(commands.Bot): - def __init__(self): - super().__init__(command_prefix="uwu", intents=discord.Intents.all()) - - async def setup_hook(self): - self.tree.copy_global_to(guild=discord.Object(id=12345678909876543)) - await self.tree.sync() - - -bot = Bot() - -@bot.tree.command(name="ping") -# ----------------------------------------- -@discord.app_commands.checks.cooldown(1, 30) -# ----------------------------------------- -async def ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -bot.run("token") -``` - -__**EXPLANATION**__ -- The first argument is the number of times this command can be invoked before the cooldown is triggered. -- The second argument it takes is the period of time in which the command can be run the specified number of times. -- The `CommandOnCooldown` exception can be handled using an error handler. We will discuss making an error handler for Slash Commands later in the Gist. - - -# Handling errors for Slash Commands! - -The Slash Commands exceptions can be handled by overwriting the `on_error` method of the `CommandTree`. The error handler takes two arguments. The first argument is the `Interaction` that took place when the error occurred and the second argument is the error that occurred when the Slash Commands was invoked. The error is an instance of [discord.app_commands.AppCommandError](https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=appcommanderror#discord.app_commands.AppCommandError) which is a subclass of [DiscordException](https://discordpy.readthedocs.io/en/latest/api.html?highlight=discordexception#discord.DiscordException). -An example to creating an error handler for Slash Commands is as follows. - -```python -from discord.ext import commands -from discord import app_commands -import discord - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync commands - -@bot.tree.command(name="ping") -@app_commands.checks.cooldown(1, 30) -async def ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -async def on_tree_error(interaction: discord.Interaction, error: app_commands.AppCommandError): - if isinstance(error, app_commands.CommandOnCooldown): - return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - elif isinstance(error, ...): - ... - else: - raise error - -bot.tree.on_error = on_tree_error - -bot.run("token") -``` - -__**EXPLANATION**__ - -First we create a simple asynchronous function named `on_tree_error` here. To which the first two required arguments are passed, `Interaction` which is named as `interaction` here and `AppCommandError` which is named as `error` here. Then using simple functions and keywords, we make an error handler like above. Here we have used the `isinstance` function which takes in an object and a base class as the second argument, this function returns a bool value. The `raise error` is just for displaying unhandled errors, i.e. the ones which have not been handled manually. If this is **removed**, you will not be able to see any exceptions raised by Slash Commands and makes debugging the code harder. -After creating the error handler function, we set the function as the error handler for the Slash Commands. Here, `bot.tree.on_error = on_tree_error` overwrites the default `on_error` method of the **CommandTree** class with our custom error handler which has been named as `on_tree_error` here. - -### Creating an error handler for a specific error! - -```python -from discord.ext import commands -from discord import app_commands -import discord - -bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) -#sync commands - -@bot.tree.command(name="ping") -app_commands.checks.cooldown(1, 30) -async def ping(interaction: discord.Interaction): - await interaction.response.send_message("pong!") - -@ping.error -async def ping_error(interaction: discord.Interaction, error: app_commands.AppCommandError): - if isinstance(error, app_commands.CommandOnCooldown): - return await interaction.response.send_message(f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!") - elif isinstance(error, ...): - ... - else: - raise error - -bot.run("token") -``` - -__**EXPLANATION**__ - -Here the command name is simply used to access the `error` method to decorate a function which acts as the `on_error` but for a specific command. You should not need to call the `error` method manually. -- cgit v1.2.3 From 4844ab4b138d75cc830ccfd0d06464351a030a12 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sun, 20 Nov 2022 14:02:14 -0800 Subject: Partial requested reviews resolved --- .../apps/content/resources/guides/python-guides/app-commands.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/app-commands.md index 1354a136..3afe342a 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app-commands.md @@ -279,9 +279,9 @@ bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) @bot.tree.command(name="time", description="...") async def _time(interaction: discord.Interaction, time_to_wait: int): # ------------------------------------------------------------- - await interaction.response.defer(ephemeral=True, thinking=True) + await interaction.response.defer(ephemeral=True) # ------------------------------------------------------------- - await interaction.edit_original_message(content=f"I will notify you after {time_to_wait} seconds have passed!") + await interaction.edit_original_response(content=f"I will notify you after {time_to_wait} seconds have passed!") await asyncio.sleep(time_to_wait) await interaction.edit_original_message(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") ``` @@ -396,7 +396,7 @@ bot = commands.Bot(command_prefix="!", intents=discord.Intents.default()) #sync commands @bot.tree.command(name="ping") -app_commands.checks.cooldown(1, 30) +@app_commands.checks.cooldown(1, 30) async def ping(interaction: discord.Interaction): await interaction.response.send_message("pong!") -- cgit v1.2.3 From f1ed4a68c49af1706f60156e2793e96294a851a8 Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Sun, 20 Nov 2022 21:55:28 -0600 Subject: Delete vps-services.md (#799) --- .../resources/guides/python-guides/vps-services.md | 31 ---------------------- 1 file changed, 31 deletions(-) delete mode 100644 pydis_site/apps/content/resources/guides/python-guides/vps-services.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md deleted file mode 100644 index 0acd3e55..00000000 --- a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: VPS Services -description: On different VPS services ---- - -If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). This is a list of VPS services that are sufficient for running Discord bots. - -* Europe - * [netcup](https://www.netcup.eu/) - * Germany & Austria data centres. - * Great affiliate program. - * [Yandex Cloud](https://cloud.yandex.ru/) - * Vladimir, Ryazan, and Moscow region data centres. - * [Scaleway](https://www.scaleway.com/) - * France data centre. - * [Time 4 VPS](https://www.time4vps.eu/) - * Lithuania data centre. -* US - * [GalaxyGate](https://galaxygate.net/) - * New York data centre. - * Great affiliate program. -* Global - * [Linode](https://www.linode.com/) - * [Digital Ocean](https://www.digitalocean.com/) - * [OVHcloud](https://www.ovhcloud.com/) - * [Vultr](https://www.vultr.com/) - ---- -# Free hosts -There are no reliable free options for VPS hosting. If you would rather not pay for a hosting service, you can consider self-hosting. -Any modern hardware should be sufficient for running a bot. An old computer with a few GB of ram could be suitable, or a Raspberry Pi. -- cgit v1.2.3 From 21d817b3ee4617808261d4d73d487e5957e06c82 Mon Sep 17 00:00:00 2001 From: Scott Noyes Date: Tue, 29 Nov 2022 13:55:47 -0600 Subject: minor grammar plural noun "things" requires plural verb "are" --- .../apps/content/resources/guides/pydis-guides/asking-good-questions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/asking-good-questions.md b/pydis_site/apps/content/resources/guides/pydis-guides/asking-good-questions.md index 971989a9..b08ba7c6 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/asking-good-questions.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/asking-good-questions.md @@ -26,7 +26,7 @@ If none of the above steps help you or you're not sure how to do some of the abo # A Good Question -When you're ready to ask a question, there's a few things you should have to hand before forming a query. +When you're ready to ask a question, there are a few things you should have to hand before forming a query. * A code example that illustrates your problem * If possible, make this a minimal example rather than an entire application -- cgit v1.2.3 From 708012cb08cc85440b9849259d12556f59adecd4 Mon Sep 17 00:00:00 2001 From: Robin <74519799+Robin5605@users.noreply.github.com> Date: Fri, 2 Dec 2022 17:25:25 -0600 Subject: Rename vps_services.md to vps-services.md (#808) Rename `vps_services.md` to `vps-services.md` (notice the dash) to not have to update old messages linking here --- .../resources/guides/python-guides/vps-services.md | 58 ++++++++++++++++++++++ .../resources/guides/python-guides/vps_services.md | 58 ---------------------- 2 files changed, 58 insertions(+), 58 deletions(-) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/vps-services.md delete mode 100644 pydis_site/apps/content/resources/guides/python-guides/vps_services.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps-services.md b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md new file mode 100644 index 00000000..710fd914 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/vps-services.md @@ -0,0 +1,58 @@ +--- +title: VPS and Free Hosting Service for Discord bots +description: This article lists recommended VPS services and covers the disasdvantages of utilising a free hosting service to run a discord bot. +toc: 2 +--- + +## Recommended VPS services + +If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). Here is a list of VPS services that are sufficient for running Discord bots. + +* Europe + * [netcup](https://www.netcup.eu/) + * Germany & Austria data centres. + * Great affiliate program. + * [Yandex Cloud](https://cloud.yandex.ru/) + * Vladimir, Ryazan, and Moscow region data centres. + * [Scaleway](https://www.scaleway.com/) + * France data centre. + * [Time 4 VPS](https://www.time4vps.eu/) + * Lithuania data centre. +* US + * [GalaxyGate](https://galaxygate.net/) + * New York data centre. + * Great affiliate program. +* Global + * [Linode](https://www.linode.com/) + * [Digital Ocean](https://www.digitalocean.com/) + * [OVHcloud](https://www.ovhcloud.com/) + * [Vultr](https://www.vultr.com/) + + +## Why not to use free hosting services for bots? +While these may seem like nice and free services, it has a lot more caveats than you may think. For example, the drawbacks of using common free hosting services to host a discord bot are discussed below. + +### Replit + +- The machines are super underpowered, resulting in your bot lagging a lot as it gets bigger. + +- You need to run a webserver alongside your bot to prevent it from being shut off. This uses extra machine power. + +- Repl.it uses an ephemeral file system. This means any file you saved through your bot will be overwritten when you next launch. + +- They use a shared IP for everything running on the service. +This one is important - if someone is running a user bot on their service and gets banned, everyone on that IP will be banned. Including you. + +### Heroku +- Bots are not what the platform is designed for. Heroku is designed to provide web servers (like Django, Flask, etc). This is why they give you a domain name and open a port on their local emulator. + +- Heroku's environment is heavily containerized, making it significantly underpowered for a standard use case. + +- Heroku's environment is volatile. In order to handle the insane amount of users trying to use it for their own applications, Heroku will dispose your environment every time your application dies unless you pay. + +- Heroku has minimal system dependency control. If any of your Python requirements need C bindings (such as PyNaCl + binding to libsodium, or lxml binding to libxml), they are unlikely to function properly, if at all, in a native + environment. As such, you often need to resort to adding third-party buildpacks to facilitate otherwise normal + CPython extension functionality. (This is the reason why voice doesn't work natively on heroku) + +- Heroku only offers a limited amount of time on their free programme for your applications. If you exceed this limit, which you probably will, they'll shut down your application until your free credit resets. diff --git a/pydis_site/apps/content/resources/guides/python-guides/vps_services.md b/pydis_site/apps/content/resources/guides/python-guides/vps_services.md deleted file mode 100644 index 710fd914..00000000 --- a/pydis_site/apps/content/resources/guides/python-guides/vps_services.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: VPS and Free Hosting Service for Discord bots -description: This article lists recommended VPS services and covers the disasdvantages of utilising a free hosting service to run a discord bot. -toc: 2 ---- - -## Recommended VPS services - -If you need to run your bot 24/7 (with no downtime), you should consider using a virtual private server (VPS). Here is a list of VPS services that are sufficient for running Discord bots. - -* Europe - * [netcup](https://www.netcup.eu/) - * Germany & Austria data centres. - * Great affiliate program. - * [Yandex Cloud](https://cloud.yandex.ru/) - * Vladimir, Ryazan, and Moscow region data centres. - * [Scaleway](https://www.scaleway.com/) - * France data centre. - * [Time 4 VPS](https://www.time4vps.eu/) - * Lithuania data centre. -* US - * [GalaxyGate](https://galaxygate.net/) - * New York data centre. - * Great affiliate program. -* Global - * [Linode](https://www.linode.com/) - * [Digital Ocean](https://www.digitalocean.com/) - * [OVHcloud](https://www.ovhcloud.com/) - * [Vultr](https://www.vultr.com/) - - -## Why not to use free hosting services for bots? -While these may seem like nice and free services, it has a lot more caveats than you may think. For example, the drawbacks of using common free hosting services to host a discord bot are discussed below. - -### Replit - -- The machines are super underpowered, resulting in your bot lagging a lot as it gets bigger. - -- You need to run a webserver alongside your bot to prevent it from being shut off. This uses extra machine power. - -- Repl.it uses an ephemeral file system. This means any file you saved through your bot will be overwritten when you next launch. - -- They use a shared IP for everything running on the service. -This one is important - if someone is running a user bot on their service and gets banned, everyone on that IP will be banned. Including you. - -### Heroku -- Bots are not what the platform is designed for. Heroku is designed to provide web servers (like Django, Flask, etc). This is why they give you a domain name and open a port on their local emulator. - -- Heroku's environment is heavily containerized, making it significantly underpowered for a standard use case. - -- Heroku's environment is volatile. In order to handle the insane amount of users trying to use it for their own applications, Heroku will dispose your environment every time your application dies unless you pay. - -- Heroku has minimal system dependency control. If any of your Python requirements need C bindings (such as PyNaCl - binding to libsodium, or lxml binding to libxml), they are unlikely to function properly, if at all, in a native - environment. As such, you often need to resort to adding third-party buildpacks to facilitate otherwise normal - CPython extension functionality. (This is the reason why voice doesn't work natively on heroku) - -- Heroku only offers a limited amount of time on their free programme for your applications. If you exceed this limit, which you probably will, they'll shut down your application until your free credit resets. -- cgit v1.2.3 From ce18f5ac487af9a46e7417ba20560803f3e7afab Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Sun, 4 Dec 2022 13:10:10 +0300 Subject: Update pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md Co-authored-by: Vivek Ashokkumar --- .../apps/content/resources/guides/python-guides/docker-hosting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index d77a91b6..09e180b3 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -153,7 +153,7 @@ services: - `services` contains services to build and run. Read more about services [here](https://docs.docker.com/compose/compose-file/#services-top-level-element) - `main` is a service. We can call it whatever we would like to, not necessarily `main` -- `build: .` is a path to search from Dockerfile, just like `docker build` command's dot +- `build: .` is a path to search for Dockerfile, just like `docker build` command's dot - `container_name: mybot` is a container name to use for a bot, just like `docker run --name mybot` Update the project on VPS, remove the previous container with `docker rm -f mybot` and run this command -- cgit v1.2.3 From 09d6de47e57e110952e0d19d2e629bff34346dde Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Sun, 4 Dec 2022 13:14:59 +0300 Subject: Update pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md Co-authored-by: Vivek Ashokkumar --- .../apps/content/resources/guides/python-guides/docker-hosting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 09e180b3..395a6c46 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -226,7 +226,7 @@ as **actions secrets**. Let's add your discord bot's token as a secret 1. Head to your repository page -> Settings -> Secrets -> Actions 2. Press `New repository secret` -3. Give it a name like `TOKEN` and paste the token +3. Give it a name like `TOKEN` and paste the token. Now we will be able to access its value in workflow like `${{ secrets.TOKEN }}`. However, we also need to parse the variable into container now. Edit `docker-compose` so it looks like this: -- cgit v1.2.3 From 0574eb2842880f73b05d3fbf31f5d4cda346aecf Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Sun, 4 Dec 2022 13:15:21 +0300 Subject: Update pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md Co-authored-by: Vivek Ashokkumar --- .../apps/content/resources/guides/python-guides/docker-hosting-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 395a6c46..a52788f6 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -170,7 +170,7 @@ The main purpose of `docker-compose` is mostly to allow running several images a don't need this in discord bots. For us, it has the following benefits: -- we can build and run the container just with one command +- we can build and run the container with just one command - if we need to parse some environment variables or volumes (more about them further in tutorial) our run command would look like this -- cgit v1.2.3 From 45fdd797bdfef5df8e8acc371a0586c36fac4a55 Mon Sep 17 00:00:00 2001 From: Exenifix <89513380+Exenifix@users.noreply.github.com> Date: Sun, 4 Dec 2022 13:26:24 +0300 Subject: Updates for docker hosting guide --- .../guides/python-guides/docker-hosting-guide.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index a52788f6..57d86e99 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -17,7 +17,7 @@ description: This guide shows how to host a bot with Docker and GitHub Actions o - write Dockerfile - build Docker image and run the container -- use docker-compose +- use Docker Compose - make docker keep the files throughout the container's runs - parse environment variables into container - use GitHub Actions for automation @@ -33,7 +33,7 @@ how to run it 24/7. You might have been suggested to use *screen multiplexer*, b run the bot again. You might have good extensions management that allows you to update the bot without restarting it, but there are some other cons as well 2. If you update some dependencies, you have to update them manually -3. The bot doesn't run in an isolated environment, which is not good for security +3. The bot doesn't run in an isolated environment, which is not good for security. But there's a nice and easy solution to these problems - **Docker**! Docker is a containerization utility that automates some stuff like dependencies update and running the application in the background. So let's get started. @@ -135,7 +135,7 @@ $ docker logs -f mybot If everything went successfully, your bot will go online and will keep running! -## Using docker-compose +## Using Docker Compose Just 2 commands to run a container is cool, but we can shorten it down to just 1 simple command. For that, create a `docker-compose.yml` file in project's root and fill it with the following contents: @@ -148,7 +148,7 @@ services: container_name: mybot ``` -- `version` tells Docker what version of `docker-compose` to use. You may check all the +- `version` tells Docker what version of Compose to use. You may check all the versions [here](https://docs.docker.com/compose/compose-file/compose-versioning/) - `services` contains services to build and run. Read more about services [here](https://docs.docker.com/compose/compose-file/#services-top-level-element) @@ -159,15 +159,15 @@ services: Update the project on VPS, remove the previous container with `docker rm -f mybot` and run this command ```shell -docker-compose up -d --build +docker compose up -d --build ``` Now the docker will automatically build the image for you and run the container. ### Why docker-compose -The main purpose of `docker-compose` is mostly to allow running several images at once within one container. Mostly we -don't need this in discord bots. +The main purpose of Compose is to run several services at once. Mostly we +don't need this in discord bots, however. For us, it has the following benefits: - we can build and run the container with just one command @@ -178,7 +178,7 @@ For us, it has the following benefits: $ docker run -d --name mybot -e TOKEN=... -e WEATHER_API_APIKEY=... -e SOME_USEFUL_ENVIRONMENT_VARIABLE=... --net=host -v /home/exenifix/bot-data/data:/app/data -v /home/exenifix/bot-data/images:/app/data/images ``` -This is pretty long and unreadable. `docker-compose` allows us to transfer those flags into single config file and still +This is pretty long and unreadable. Compose allows us to transfer those flags into single config file and still use just one short command to run the container. ## Creating Volumes @@ -196,7 +196,7 @@ $ echo $(pwd)/mybot-data My path is `/home/exenifix/mybot-data`, yours is most likely **different**! 2. In your project, store the files that need to be persistent in a separate directory (eg. `data`) -3. Add the `volumes` construction to `docker-compose` so it looks like this: +3. Add `volumes` to `docker-compose.yaml` so it looks like this: ```yml version: "3.8" @@ -284,7 +284,7 @@ jobs: - uses: actions/checkout@v3 - name: Run Container - run: docker-compose up -d --build + run: docker compose up -d --build env: TOKEN: ${{ secrets.TOKEN }} -- cgit v1.2.3 From 61c0077f442386f7524e251994e3f9ba8b6651ab Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Tue, 6 Dec 2022 23:25:40 +0100 Subject: Fix 404 for commit message document Closes #809. --- .../guides/pydis-guides/contributing/commit-messages.md | 15 +++++++++++++++ .../pydis-guides/contributing/contributing-guidelines.md | 2 +- .../contributing/contributing-guidelines/_info.yml | 2 -- .../contributing-guidelines/commit-messages.md | 15 --------------- 4 files changed, 16 insertions(+), 18 deletions(-) create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/commit-messages.md delete mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/_info.yml delete mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/commit-messages.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/commit-messages.md new file mode 100644 index 00000000..ba476b65 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/commit-messages.md @@ -0,0 +1,15 @@ +--- +title: Writing Good Commit Messages +description: Information about logging in our projects. +--- + +A well-structured git log is key to a project's maintainability; it provides insight into when and *why* things were done for future maintainers of the project. + +Commits should be as narrow in scope as possible. +Commits that span hundreds of lines across multiple unrelated functions and/or files are very hard for maintainers to follow. +After about a week they'll probably be hard for you to follow, too. + +Please also avoid making minor commits for fixing typos or linting errors. +[Don’t forget to lint before you push!](https://soundcloud.com/lemonsaurusrex/lint-before-you-push) + +A more in-depth guide to writing great commit messages can be found in Chris Beam's [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/). diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md index 73c5dcab..d1e4250d 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines.md @@ -12,7 +12,7 @@ We have simple but strict style rules that are enforced through linting. Not all of the style rules are enforced by linting, so make sure to read the [style guide](../style-guide/) as well. 2. **Make great commits.** Great commits should be atomic, with a commit message explaining what and why. -Check out [Writing Good Commit Messages](./commit-messages) for details. +Check out [Writing Good Commit Messages](../commit-messages/) for details. 3. **Do not open a pull request if you aren't assigned to the issue.** If someone is already working on it, consider offering to collaborate with that person. 4. **Use assets licensed for public use.** diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/_info.yml b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/_info.yml deleted file mode 100644 index 80c8e772..00000000 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/_info.yml +++ /dev/null @@ -1,2 +0,0 @@ -title: Contributing Guidelines -description: Guidelines to adhere to when contributing to our projects. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md deleted file mode 100644 index ba476b65..00000000 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/contributing-guidelines/commit-messages.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Writing Good Commit Messages -description: Information about logging in our projects. ---- - -A well-structured git log is key to a project's maintainability; it provides insight into when and *why* things were done for future maintainers of the project. - -Commits should be as narrow in scope as possible. -Commits that span hundreds of lines across multiple unrelated functions and/or files are very hard for maintainers to follow. -After about a week they'll probably be hard for you to follow, too. - -Please also avoid making minor commits for fixing typos or linting errors. -[Don’t forget to lint before you push!](https://soundcloud.com/lemonsaurusrex/lint-before-you-push) - -A more in-depth guide to writing great commit messages can be found in Chris Beam's [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/). -- cgit v1.2.3 From ad7410b02bac80d4d3f4171988be0ba38820a7e2 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Sun, 11 Dec 2022 02:39:35 -0800 Subject: Reviews fully resolved, but unsure about defer --- pydis_site/apps/content/resources/guides/python-guides/app-commands.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/app-commands.md b/pydis_site/apps/content/resources/guides/python-guides/app-commands.md index 3afe342a..713cd650 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/app-commands.md +++ b/pydis_site/apps/content/resources/guides/python-guides/app-commands.md @@ -29,6 +29,7 @@ Slash commands in discord.py are held by a container, [CommandTree](https://disc One new feature added in discord.py v2 is `setup_hook`. `setup_hook` is a special asynchronous method of the Client and Bot classes which can be overwritten to perform numerous tasks. This method is safe to use as it is always triggered before any events are dispatched, i.e. this method is triggered before the *IDENTIFY* payload is sent to the discord gateway. Note that methods of the Bot class such as `change_presence` will not work in setup_hook as the current application does not have an active connection to the gateway at this point. +A full list of commands you can't use in setup_hook can be found [here](https://discord.com/developers/docs/topics/gateway-events#send-events). __**THE FOLLOWING ARE EXAMPLES OF HOW A `SETUP_HOOK` FUNCTION CAN BE DEFINED**__ @@ -283,7 +284,7 @@ async def _time(interaction: discord.Interaction, time_to_wait: int): # ------------------------------------------------------------- await interaction.edit_original_response(content=f"I will notify you after {time_to_wait} seconds have passed!") await asyncio.sleep(time_to_wait) - await interaction.edit_original_message(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") + await interaction.edit_original_response(content=f"{interaction.user.mention}, {time_to_wait} seconds have already passed!") ``` # Checking for Permissions and Roles! -- cgit v1.2.3 From 63f1d78927626ef2f5c0d81e6283dee73ac7c167 Mon Sep 17 00:00:00 2001 From: kosayoda Date: Sun, 11 Dec 2022 11:44:04 -0500 Subject: Add tips that showcase markdown quirks. --- .../pydis-guides/how-to-contribute-a-page.md | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md index 716250b1..4639b4d2 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md @@ -215,3 +215,44 @@ To use a custom label in the table of contents for a heading, set the `data-toc- ```markdown # Header 1 {: data-toc-label="Header One" } ``` + +## Tips + +### Nested/Unhighlighted Code Blocks +To nest code blocks, increase the number of ticks in the outer block by 1. To remove highlighting from code blocks (ie. no dark background), you can use the `nohighlight` language. +`````nohighlight +````nohighlight +```python +print("Some inner code block text.") +``` +```` +````` + +### Images in Lists +To properly indent images in lists, keep the image on the line directly after the previous line and add `
` to the end of the text, like this: + +```markdown +1. List item text one.
+![Image text one](image/link/one) + +2. List item text two.
+![Image text two](image/link/two) +``` + +### Keeping Text In The Same Paragraph +You can also use `
` to break lines while keeping them in the same paragraph (avoiding the vertical spacing added between paragraphs). + +```nohighlight +##### Same line, same paragraph +Line A +Line B + +##### Different line, different paragraph +Line A + +Line B + +##### Different line, same paragraph +Line A
+Line B +``` -- cgit v1.2.3 From 7f80bdcf2f7ca862570cfa0c78ee7a2b764ac2fa Mon Sep 17 00:00:00 2001 From: kosayoda Date: Sun, 11 Dec 2022 11:46:54 -0500 Subject: Point showcase link to an actual example. The example pointed to by the previous link is no more, so let's find another example. --- .../content/resources/guides/pydis-guides/how-to-contribute-a-page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md index 4639b4d2..0d14ef41 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md @@ -169,7 +169,7 @@ path = os.path.join("foo", "bar") ### HTML Attributes To add HTML attributes to certain lines/paragraphs, [see this page](https://python-markdown.github.io/extensions/attr_list/#the-list) for the format and where to put it. -This can be useful for setting the image size when adding an image using markdown (see the [Image Captions](#image-captions) section for an example), or for adding bulma styles to certain elements (like the warning notification [here](/pages/guides/pydis-guides/contributing/sir-lancebot#setup-instructions)).
+This can be useful for setting the image size when adding an image using markdown (see the [Image Captions](#image-captions) section for an example), or for adding bulma styles to certain elements (like the warning notification [here](/pages/guides/pydis-guides/contributing/sir-lancebot#run-with-docker)).
**This should be used sparingly, as it reduces readability and simplicity of the article.** --- -- cgit v1.2.3 From d584c7cffac8bff1dfa98a7b22f3fbfabbc73498 Mon Sep 17 00:00:00 2001 From: kosayoda Date: Sun, 11 Dec 2022 11:49:55 -0500 Subject: Kaizen: Ensure consistent formatting and wording. --- .../apps/content/resources/guides/pydis-guides/contributing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 2822d046..07e9a7bd 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -112,16 +112,16 @@ You have the source code on your local computer, now how do you actually run it? ### 3. Read our Contributing Guidelines We have a few short rules that all contributors must follow. Make sure you read and follow them while working on our projects. -[**Contributing Guidelines**](./contributing-guidelines/). +[**Read our Contributing Guidelines here.**](./contributing-guidelines/) As mentioned in the Contributing Guidelines, we have a simple style guide for our projects based on PEP 8. Give it a read to keep your code consistent with the rest of the codebase. -[**Style Guide**](./style-guide/) +[**Read our Style Guide here.**](./style-guide/) ### 4. Create an issue The first step to any new contribution is an issue describing a problem with the current codebase or proposing a new feature. All the open issues are viewable on the GitHub repositories, for instance here is the [issues page for Sir Lancebot](https://github.com/python-discord/sir-lancebot/issues). If you have something that you want to implement open a new issue to present your idea. Otherwise, you can browse the unassigned issues and ask to be assigned to one that you're interested in, either in the comments on the issue or in the [`#dev-contrib`](https://discord.gg/2h3qBv8Xaa) channel on Discord. -[**How to write a good issue**](./issues/) +[**Find out how to write a good issue here.**](./issues/) Don't move forward until your issue is approved by a Core Developer. Issues are not guaranteed to be approved so your work may be wasted. {: .notification .is-warning } -- cgit v1.2.3 From 2889b53d33bd5f4b38e5e28746ee81c252d64be8 Mon Sep 17 00:00:00 2001 From: Xithrius Date: Mon, 12 Dec 2022 02:54:10 -0800 Subject: Confirmation with the reader on when to set status --- .../guides/python-guides/setting-different-statuses-on-your-bot.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md b/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md index b44c55e1..45c7b37c 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/setting-different-statuses-on-your-bot.md @@ -5,11 +5,13 @@ description: How to personalize your Discord bot status You've probably seen a bot or two have a status message under their username in the member bar set to something such as `Playing Commands: .help`. -This guide shows how to set such a presence, so your bot can have one as well. +This guide shows how to set such a status, so your bot can have one as well. **Please note:** -If you want to change the bot status, it is suggested to not do so during the on_ready event, since it would be called many times and making an API call on that event has a chance to disconnect the bot. +If you want to change the bot status, it is suggested to not do so during the `on_ready` event, since it would be called many times and making an API call on that event has a chance to disconnect the bot. + +The status should not have a problem being set during runtime with `change_presence`, in the examples shown below. Instead, set the desired status using the activity / status kwarg of commands.Bot, for example: ```python -- cgit v1.2.3 From 318a2980035e60362035693fadb8bfa278ae9c29 Mon Sep 17 00:00:00 2001 From: Amrou Bellalouna Date: Thu, 29 Dec 2022 00:51:08 +0100 Subject: Update help channels guide (#814) Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> --- .../guides/pydis-guides/help-channel-guide.md | 79 ++++++++++++--------- .../guides/pydis-guides/helping-others.md | 4 +- .../content/help_channels/available_channels.png | Bin 6556 -> 0 bytes .../content/help_channels/available_message.png | Bin 89386 -> 0 bytes .../content/help_channels/claimed_channel.png | Bin 26100 -> 0 bytes .../content/help_channels/dormant_channels.png | Bin 22386 -> 0 bytes .../content/help_channels/help-system-category.png | Bin 0 -> 7425 bytes .../content/help_channels/new-post-button.png | Bin 0 -> 15804 bytes .../images/content/help_channels/new-post-form.png | Bin 0 -> 35364 bytes .../help_channels/newly-created-thread-example.png | Bin 0 -> 149793 bytes .../content/help_channels/occupied_channels.png | Bin 10950 -> 0 bytes .../content/help_channels/question-example.png | Bin 0 -> 45436 bytes 12 files changed, 47 insertions(+), 36 deletions(-) delete mode 100644 pydis_site/static/images/content/help_channels/available_channels.png delete mode 100644 pydis_site/static/images/content/help_channels/available_message.png delete mode 100644 pydis_site/static/images/content/help_channels/claimed_channel.png delete mode 100644 pydis_site/static/images/content/help_channels/dormant_channels.png create mode 100644 pydis_site/static/images/content/help_channels/help-system-category.png create mode 100644 pydis_site/static/images/content/help_channels/new-post-button.png create mode 100644 pydis_site/static/images/content/help_channels/new-post-form.png create mode 100644 pydis_site/static/images/content/help_channels/newly-created-thread-example.png delete mode 100644 pydis_site/static/images/content/help_channels/occupied_channels.png create mode 100644 pydis_site/static/images/content/help_channels/question-example.png (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md index 2be845d3..bef2df9b 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/help-channel-guide.md @@ -9,7 +9,7 @@ relevant_links: toc: 3 --- -At Python Discord we have two different kinds of help channels: **topical help channels** and **general help channels**. +At Python Discord we have two different kinds of help channels: **topical help channels** and **help forum posts**. # Topical Help Channels @@ -24,71 +24,82 @@ For example, `#data-science-and-ai` covers scientific Python, statistics, and ma Each channel on the server has a channel description which briefly describes the topics covered by that channel. If you're not sure where to post, feel free to ask us which channel is appropriate in `#community-meta`. -# General Help Channels +# Help Forum Posts -General help channels can be used for all Python-related help, and have the advantage of attracting a more diverse spectrum of helpers. There is also the added benefit of receiving individual focus and attention on your question. These channels are a great choice for generic Python help, but can be used for domain-specific Python help as well. +Help forum posts can be used for all Python-related help, and have the advantage of attracting a more diverse spectrum of helpers. There is also the added benefit of receiving individual focus and attention on your question. These posts are a great choice for generic Python help, but can be used for domain-specific Python help as well. -## How to Claim a Channel +## How to Create A New Post -There are always three help channels waiting to be claimed in the **Available Help Channels** category. +There are 4 easy needed steps to make this happen -![Available help channels](/static/images/content/help_channels/available_channels.png) -*The Available Help Channels category is always at the top of the server's channel list.* +1. Navigate to the **Python Help System** category.
+![Python help system category](/static/images/content/help_channels/help-system-category.png) +2. Open the **python-help** forum channel. +3. Click on the **New Post** button in the top-right corner.
+![New post button](/static/images/content/help_channels/new-post-button.png) +4. Choose a brief title that best describes your issue, along with a message explaining it more in details, and **post** it. +Note that you can also choose one or more tags which can help attract experts of that tag easily.
+![New post form](/static/images/content/help_channels/new-post-form.png) -![Available message](/static/images/content/help_channels/available_message.png) -*This message indicates that a channel is available.* +Be sure to [ask questions with enough information](../asking-good-questions) in order to give yourself the best chances of getting help! -In order to claim one, simply ask your question in one of the available channels. Be sure to [ask questions with enough information](../asking-good-questions) in order to give yourself the best chances of getting help! +At this point you will have the **Help Cooldown** role which will remain on your profile until you close your newly created post. This ensures that users can only have one post at any given time, giving everyone a chance to have their question seen. -![Channel claimed embed](/static/images/content/help_channels/claimed_channel.png) -*This messages indicates that you've claimed the channel.* +# Frequently Asked Questions -At this point you will have the **Help Cooldown** role which will remain on your profile until you close your help channel. This ensures that users can claim only one help channel at any given time, giving everyone a chance to have their question seen. +### I created a new help post, what happens now? +Once you click on `Post`, these events take place:
+1. A new channel will be created for you, and you'll have an `OP` next to you username, which tells people you're the `Original Poster`, or in other words, the owner of the help topic in that channel.
+2. Your original question/message will always be the first one in that channel.
+3. Our Python bot will send a message reminding you of what you should include in your question/message in case you could have missed anything.
+4. People will be able to jump on that channel, and you can have a discussion with anyone who's volunteering to help you by asking as many followup questions as you want.
-# Frequently Asked Questions +#### Example +Suppose we're trying to find the minimum value in a list of integers. +Once we've chosen our title and message content, we are ready to make a new post.

+![Filled form example](/static/images/content/help_channels/question-example.png)

+Note how we've checked the **Algos & data structs** tag here, whose circumference is highlighted in blue, since this is a question about an algorithm to find the minimum.
+This will greatly help others pinpoint where they can help you best based on a combination of your title and tag from a first glance.

+Once you click on post, a new channel is created, and you can see the original message on top along with the `OP` tag next to the poster's avatar.
+You will also see the message that our Python bot sends instantly right after yours.

+![Newly created thread example](/static/images/content/help_channels/newly-created-thread-example.png) -### How long does my help channel stay active? +### How long does my help post stay active? -The channel remains open for **30 minutes** after your last message, or 10 minutes after the last message sent by another user (whichever time comes later). +The post remains open for **30 minutes** after your last message, or 10 minutes after the last message sent by another user (whichever time comes later). ![Channel dormant message](/static/images/content/help_channels/dormant_message.png) -*You'll see this message in your channel once it goes dormant.* +*You'll see this message in your post once it goes dormant.* + ### No one answered my question. How come? -The server has users active all over the world and all hours of the day, but some time periods are less active than others. It's also possible that the users that read your question didn't have the knowledge required to help you. If no one responded, feel free to claim another help channel a little later, or try an appropriate topical channel. +The server has users active all over the world and all hours of the day, but some time periods are less active than others. It's also possible that the users that read your question didn't have the knowledge required to help you. If no one responded, feel free to open another post a little later, or try an appropriate topical channel. If you feel like your question is continuously being overlooked, read our guide on [asking good questions](../asking-good-questions) to increase your chances of getting a response. ### My question was answered. What do I do? -Go ahead use the `!close` command if you've satisfactorily solved your problem. You will only be able to run this command in your own help channel, and no one (outside of staff) will be able to close your channel for you. +Go ahead and use one of the `!close` or `!solved` commands if you've satisfactorily solved your problem. You will only be able to run this command in your own post, and no one (outside of staff) will be able to close your post for you. -Closing your help channel once you are finished leads to less occupied channels, which means more attention can be given to other users that still need help. +Closing your post once you are finished leads to less occupied ones, which means more attention can be given to other users that still need help. ### Can only Helpers answer help questions? -Definitely not! We encourage all members of the community to participate in giving help. If you'd like to help answer some questions, head over to the **Occupied Help Channels** or **Topical Chat/Help** categories. +Definitely not! We encourage all members of the community to participate in giving help. If you'd like to help answer some questions, you can either browse all posts in the **python-help** forum channel or head over to the **Topical Chat/Help** category. Before jumping in, please read our guide on [helping others](../helping-others) which explains our expectations for the culture and quailty of help that we aim for on the server. -Tip: run the `!helpdm on` command in `#bot-commands` to get notified via DM with jumplinks to help channels you're participating in. - -### What are the available, occupied, and dormant categories? - -The three help channels under **Available Help Channels** are free for anyone to claim. Claimed channels are then moved to **Occupied Help Channels**. Once they close, they are moved to the **Python Help: Dormant** category until they are needed again for **Available Help Channels**. +Tip: run the `!helpdm on` command in the `#bot-commands` channel to get notified via DM with jumplinks to help posts you're participating in. ### Can I save my help session for future reference? -Yes! Because the help channels are continuously cycled in and out without being deleted, this means you can always refer to a previous help session if you found one particularly helpful. +Yes! Because the help posts are only closed without being deleted, this means you can always refer to a previous help session if you found one particularly helpful. Tip: reply to a message and run the `.bm` command to get bookmarks sent to you via DM for future reference. -### I lost my help channel! +### I lost my help post! -No need to panic. Your channel was probably just closed due to inactivity. -All the dormant help channels are still available at the bottom of the channel list, in the **Python Help: Dormant** category, and also through search. -If you're not sure what the name of your help channel was, you can easily find it by using the Discord Search feature. +No need to panic. Your post was probably just closed due to inactivity. +All the dormant help posts are still available at the bottom of the **python-help** forum channel and also through search in the **Python Help System** category. +If you're not sure what the title of your help post was, you can easily find it by using the Discord Search feature. Try searching for `from:` to find the last messages sent by yourself, and from there you will be able to jump directly into the channel by pressing the Jump button on your message. - -![Dormant help channels](/static/images/content/help_channels/dormant_channels.png) -*The dormant help channels can be found at the bottom of the channel list.* diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/helping-others.md b/pydis_site/apps/content/resources/guides/pydis-guides/helping-others.md index a7f1ce1d..9f0d947f 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/helping-others.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/helping-others.md @@ -9,7 +9,7 @@ relevant_links: toc: 2 --- -Python Discord has a lot of people asking questions, be it in the help channels, topical channels, or any other part of the server. +Python Discord has a lot of people asking questions, be it in the help forum, topical channels, or any other part of the server. Therefore, you might sometimes want to give people the answers you have in mind. But you might not be sure how best to approach the issue, or maybe you'd like to see how others handle it. This article aims to present a few of the general principles which guide the staff on a day-to-day basis on the server. @@ -64,7 +64,7 @@ At other times, it might not be as obvious, and it might be a good idea to kindl The path is often more important than the answer. Your goal should primarily be to allow the helpee to apply, at least to a degree, the concepts you introduce in your answer. Otherwise, they might keep struggling with the same problem over and over again. -That means that simply showing your answer might close the help channel for the moment, but won't be very helpful in the long-term. +That means that simply showing your answer might close the help post for the moment, but won't be very helpful in the long-term. A common approach is to walk the helpee through to an answer: diff --git a/pydis_site/static/images/content/help_channels/available_channels.png b/pydis_site/static/images/content/help_channels/available_channels.png deleted file mode 100644 index 0b9cfd03..00000000 Binary files a/pydis_site/static/images/content/help_channels/available_channels.png and /dev/null differ diff --git a/pydis_site/static/images/content/help_channels/available_message.png b/pydis_site/static/images/content/help_channels/available_message.png deleted file mode 100644 index 09668c9b..00000000 Binary files a/pydis_site/static/images/content/help_channels/available_message.png and /dev/null differ diff --git a/pydis_site/static/images/content/help_channels/claimed_channel.png b/pydis_site/static/images/content/help_channels/claimed_channel.png deleted file mode 100644 index 777e31ea..00000000 Binary files a/pydis_site/static/images/content/help_channels/claimed_channel.png and /dev/null differ diff --git a/pydis_site/static/images/content/help_channels/dormant_channels.png b/pydis_site/static/images/content/help_channels/dormant_channels.png deleted file mode 100644 index 7c9ba61e..00000000 Binary files a/pydis_site/static/images/content/help_channels/dormant_channels.png and /dev/null differ diff --git a/pydis_site/static/images/content/help_channels/help-system-category.png b/pydis_site/static/images/content/help_channels/help-system-category.png new file mode 100644 index 00000000..bea5a92c Binary files /dev/null and b/pydis_site/static/images/content/help_channels/help-system-category.png differ diff --git a/pydis_site/static/images/content/help_channels/new-post-button.png b/pydis_site/static/images/content/help_channels/new-post-button.png new file mode 100644 index 00000000..4ceabf0f Binary files /dev/null and b/pydis_site/static/images/content/help_channels/new-post-button.png differ diff --git a/pydis_site/static/images/content/help_channels/new-post-form.png b/pydis_site/static/images/content/help_channels/new-post-form.png new file mode 100644 index 00000000..3e90bf7d Binary files /dev/null and b/pydis_site/static/images/content/help_channels/new-post-form.png differ diff --git a/pydis_site/static/images/content/help_channels/newly-created-thread-example.png b/pydis_site/static/images/content/help_channels/newly-created-thread-example.png new file mode 100644 index 00000000..d7b1eed4 Binary files /dev/null and b/pydis_site/static/images/content/help_channels/newly-created-thread-example.png differ diff --git a/pydis_site/static/images/content/help_channels/occupied_channels.png b/pydis_site/static/images/content/help_channels/occupied_channels.png deleted file mode 100644 index 6ccb4ed6..00000000 Binary files a/pydis_site/static/images/content/help_channels/occupied_channels.png and /dev/null differ diff --git a/pydis_site/static/images/content/help_channels/question-example.png b/pydis_site/static/images/content/help_channels/question-example.png new file mode 100644 index 00000000..da181351 Binary files /dev/null and b/pydis_site/static/images/content/help_channels/question-example.png differ -- cgit v1.2.3 From 10b4612696ea203949b9def89f47e8b6440b28ce Mon Sep 17 00:00:00 2001 From: Krypton Date: Mon, 9 Jan 2023 19:08:14 +0100 Subject: Update ANSI guide with new pictures, formatting & titles --- .../python-guides/discord-messages-with-colors.md | 23 +++++++++++++++------ .../discord_colored_messages/ansi-colors.png | Bin 43004 -> 100261 bytes .../content/discord_colored_messages/result.png | Bin 13740 -> 9608 bytes 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md index 62ff61f9..0e88490e 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discord-messages-with-colors.md @@ -3,9 +3,10 @@ title: Discord Messages with Colors description: A guide on how to add colors to your codeblocks on Discord --- -Discord is now slowly rolling out the ability to send colored text within code blocks. This is done using ANSI color codes which is also how you print colored text in your terminal. +Discord is now *slowly rolling out* the ability to send colored messages within code blocks. It uses the ANSI color codes, so if you've tried to print colored text in your terminal or console with Python or other languages then it will be easy for you. -To send colored text in a code block you need to first specify the `ansi` language and use the prefixes similar to the one below: +## Quick Explanation +To be able to send a colored text, you need to use the `ansi` language for your code block and provide a prefix of this format before writing your text: ```ansi \u001b[{format};{color}m ``` @@ -13,15 +14,17 @@ To send colored text in a code block you need to first specify the `ansi` langua After you've written this, you can now type the text you wish to color. If you want to reset the color back to normal, then you need to use the `\u001b[0m` prefix again. +## Formats Here is the list of values you can use to replace `{format}`: * 0: Normal * 1: **Bold** * 4: Underline +## Colors Here is the list of values you can use to replace `{color}`: -*The following values will change the **text** color.* +### Text Colors * 30: Gray * 31: Red @@ -32,7 +35,7 @@ Here is the list of values you can use to replace `{color}`: * 36: Cyan * 37: White -*The following values will change the **text background** color.* +### Background Colors * 40: Firefly dark blue * 41: Orange @@ -43,7 +46,9 @@ Here is the list of values you can use to replace `{color}`: * 46: Light gray * 47: White -Let's take an example, I want a bold green colored text with the very dark blue background. +## Example + +Let's take an example, I want a bold green colored text with the firefly dark blue background. I simply use `\u001b[0;40m` (background color) and `\u001b[1;32m` (text color) as prefix. Note that the order is **important**, first you give the background color and then the text color. Alternatively you can also directly combine them into a single prefix like the following: `\u001b[1;40;32m` and you can also use multiple values. Something like `\u001b[1;40;4;32m` would underline the text, make it bold, make it green and have a dark blue background. @@ -61,8 +66,14 @@ Result: ![Background and text color result](/static/images/content/discord_colored_messages/result.png) +### ANSI Colors Showcase + The way the colors look like on Discord is shown in the image below: ![ANSI Colors](/static/images/content/discord_colored_messages/ansi-colors.png) -Note: If the change as not been brought to you yet, or other users, then you can use other code blocks in the meantime to get colored text. See **[this gist](https://gist.github.com/matthewzring/9f7bbfd102003963f9be7dbcf7d40e51)**. +*Message sent to get the output of above can be found [here](https://gist.github.com/kkrypt0nn/a02506f3712ff2d1c8ca7c9e0aed7c06#file-ansi-colors-showcase-md).* + +#### Disclaimer + +***Note**: The change has been brought to all stable desktop clients. Since syntax highlighting on mobile is far behind, ANSI is not supported on mobile as well. Refer to [this gist](https://gist.github.com/matthewzring/9f7bbfd102003963f9be7dbcf7d40e51) for other syntax highlighting methods.* diff --git a/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png b/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png index d7176393..d980ab4c 100644 Binary files a/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png and b/pydis_site/static/images/content/discord_colored_messages/ansi-colors.png differ diff --git a/pydis_site/static/images/content/discord_colored_messages/result.png b/pydis_site/static/images/content/discord_colored_messages/result.png index a666804e..41ed555c 100644 Binary files a/pydis_site/static/images/content/discord_colored_messages/result.png and b/pydis_site/static/images/content/discord_colored_messages/result.png differ -- cgit v1.2.3 From 4ecef08c9c40b169f2cf1dfba0fbe19a5b0bfba5 Mon Sep 17 00:00:00 2001 From: vcokltfre Date: Mon, 13 Feb 2023 23:52:07 +0000 Subject: fix: change other references of vcokltfre.dev to vco.sh --- .../apps/content/resources/guides/python-guides/keeping-tokens-safe.md | 2 +- .../content/resources/guides/python-guides/why-not-json-as-database.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md index 9d523b4b..92eb52a3 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md +++ b/pydis_site/apps/content/resources/guides/python-guides/keeping-tokens-safe.md @@ -11,7 +11,7 @@ To help prevent leaking your token, you should ensure that you don't upload it to an open source program/website, such as replit and github, as they show your code publicly. The best practice for storing tokens is generally utilising .env files -([click here](https://vcokltfre.dev/tips/tokens/.) for more information on storing tokens safely). +([click here](https://tutorial.vco.sh/tips/tokens/) for more information on storing tokens safely). # What should I do if my token does get leaked? diff --git a/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md b/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md index ae34c2b4..6d9f433e 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md +++ b/pydis_site/apps/content/resources/guides/python-guides/why-not-json-as-database.md @@ -2,7 +2,7 @@ title: Why JSON is unsuitable as a database description: The many reasons why you shouldn't use JSON as a database, and instead opt for SQL. relevant_links: - Tips on Storing Data: https://tutorial.vcokltfre.dev/tips/storage/ + Tips on Storing Data: https://tutorial.vco.sh/tips/storage/ --- JSON, quite simply, is not a database. It's not designed to be a data storage format, -- cgit v1.2.3 From d091b1d9a54f049fa8f51d9cdfed9724283e3d72 Mon Sep 17 00:00:00 2001 From: Ibrahim2750mi Date: Wed, 22 Feb 2023 03:50:07 +0530 Subject: Contributing Page->Sir Lancebot: update description + Removes typo for the `Admins` role being spelt `Admin` + Added the `TRASHCAN_EMOJI` as needed + Added code blocks for channel names --- .../guides/pydis-guides/contributing/sir-lancebot.md | 3 ++- .../contributing/sir-lancebot/env-var-reference.md | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index c9566d23..9e48c624 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -59,7 +59,7 @@ You will need your own test server and bot account on Discord to test your chang * `#dev-log` * `#sir-lancebot-commands` 4. Create the following roles: - * `@Admin` + * `@Admins` 5. Note down the IDs for your server, as well as any channels and roles created. * [**Learn how to obtain the ID of a server, channel or role here.**](../setting-test-server-and-bot-account#obtain-the-ids) @@ -81,6 +81,7 @@ The following variables are needed for running Sir Lancebot: | `CHANNEL_ANNOUNCEMENTS` | ID of the `#announcements` channel | | `CHANNEL_DEVLOG` | ID of the `#dev-log` channel | | `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the `#sir-lancebot-commands` channel | +| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of `\:emoji:`. | [**Full environment variable reference for this project.**](./env-var-reference) diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md index 51587aac..09ec9394 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md @@ -10,12 +10,12 @@ The following variables are needed for running Sir Lancebot: | -------- | -------- | | `BOT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | | `BOT_GUILD` | ID of the Discord Server | -| `BOT_ADMIN_ROLE_ID` | ID of the role @Admins | -| `ROLE_HELPERS` | ID of the role @Helpers | -| `CHANNEL_ANNOUNCEMENTS` | ID of the #announcements channel | -| `CHANNEL_DEVLOG` | ID of the #dev-log channel | -| `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the #sir-lancebot-commands channel | -| `CHANNEL_REDDIT` | ID of the #reddit channel | +| `BOT_ADMIN_ROLE_ID` | ID of the role `@Admins` | +| `ROLE_HELPERS` | ID of the role `@Helpers` | +| `CHANNEL_ANNOUNCEMENTS` | ID of the `#announcements` channel | +| `CHANNEL_DEVLOG` | ID of the `#dev-log` channel | +| `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the `#sir-lancebot-commands` channel | +| `CHANNEL_REDDIT` | ID of the `#reddit` channel | --- ## Debug Variables @@ -66,8 +66,8 @@ These variables might come in handy while working on certain cogs: | Advent of Code | `AOC_ROLE_ID` | ID of the advent of code role. | Advent of Code | `AOC_IGNORED_DAYS` | Comma separated list of days to ignore while calculating score. | | Advent of Code | `AOC_YEAR` | Debug variable to change the year used for AoC. | -| Advent of Code | `AOC_CHANNEL_ID` | The ID of the #advent-of-code channel | -| Advent of Code | `AOC_COMMANDS_CHANNEL_ID` | The ID of the #advent-of-code-commands channel | +| Advent of Code | `AOC_CHANNEL_ID` | The ID of the `#advent-of-code` channel | +| Advent of Code | `AOC_COMMANDS_CHANNEL_ID` | The ID of the `#advent-of-code-commands` channel | | Advent of Code | `AOC_FALLBACK_SESSION` | | | Advent of Code | `AOC_SESSION_COOKIE` | | | Valentines | `LOVEFEST_ROLE_ID` | | -- cgit v1.2.3 From 29e46df0376a4329933ca35968369ec1affae449 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 00:51:17 +0100 Subject: add guide to install a specific dependency group with poetry This sets up the stage to install the needed bootstrapping script dependencies --- .../installing-project-dependencies.md | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md index 26d6de30..862f0add 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md @@ -39,3 +39,27 @@ $ poetry run task precommit ![PyCharm Poetry Environment](/static/images/content/contributing/pycharm_poetry.png)
6. PyCharm will automatically install the packages required into a virtual environment.
![PyCharm Project Interpreter](/static/images/content/contributing/pycharm_poetry_success.png) + + +## Installing specific dependency groups + +In some cases, like when you'll be using the configuration bootstrapping script, you might need to install extra dependencies that are +not necessary for the bot project to function. +These dependency are put in a separate optional group likewise: + +```text +[tool.poetry.group.group-name] +... +[tool.poetry.group.group-name.dependencies] +pytest = "^6.0.0" +pytest-mock = "*" +``` + +To install them, you simply need to run the following command +--- + +```shell +$ poetry install --only {{group-name}} +``` + +--- \ No newline at end of file -- cgit v1.2.3 From 35227dbebf1c71c6a75036a0535839698ccd648d Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 00:56:06 +0100 Subject: add the Scaffolding the configuration section --- .../guides/pydis-guides/contributing/bot.md | 68 +++++++++++++++++----- 1 file changed, 54 insertions(+), 14 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 02316bca..0b82265b 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -16,8 +16,7 @@ The Python bot is tightly coupled with the Python Discord server, so to have a f It's possible to set the bot to use a single channel for all cogs, but that will cause extreme spam and will be difficult to work with. You can start your own server and set up channels as you see fit, but for your convenience we have a template for a development server you can use: [https://discord.new/zmHtscpYN9E3](https://discord.new/zmHtscpYN9E3). -Keep in mind that this is not a mirror of the Python server, but a reduced version for testing purposes. A lot of the channels in the Python server were merged. - +Keep in mind that this is not an exact mirror of the Python server, but a reduced version for testing purposes. --- ### Set Up a Bot Account @@ -38,7 +37,47 @@ If your bot fails to start with a `PrivilegedIntentsRequired` exception, this in ### Configure the Bot You now have both the bot's code and a server to run it on. It's time you to connect the two by changing the bot's configurations. -#### config.yml +#### Scaffolding the configuration +To make setup much easier, there is a file called `bootstrap_config.py` that represents a script to bootstrap the configuration for you and help you get started immediately +without having to spend much time copying ids from your newly created server into your configuration file. + +**Note** + +This phase can be skipped and done manually, but would require extra manual work. + +##### 1. Script setup +##### 1.1. Environment variables +You will need to create a file called `.env` which will contain two required values for the script to work: `BOT_TOKEN` and `GUILD_ID` +Inside, add the following two lines: + +```text +BOT_TOKEN=YourDiscordBotTokenHere +GUILD_ID=YourDiscordTestServerIdHere +``` +See [here](../creating-bot-account) for help with obtaining the bot token and [here](obtaining-discord-ids.md#guild-id) for help with obtaining the guild's id + +**Note** + +The `.env` file will be ignored by commits. +##### 1.2 Setting up the script environment +The bootstrapping script is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: +1. Make sure you follow steps `1` and `2` [here](#setting-up-a-development-environment) +2. [Install the `config-bootstrap` dependency group](installing-project-dependencies.md#installing-specific-dependency-groups). + +#### 2. Running the script + +Once the script setup phase is complete, all that is left is to run it. +To do this, you'll simply need to run the `configure` poetry task like thise + +```shell +$ poetry run task configure +``` + +Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory. +This file will contain the extracted ids from your newly created server which are necessary for your bot to run. +Congratulations, you have finished the configuration & can now start [running your bot](#run-it-) + +#### .env.server Entering the directory of the cloned code, you will find a file named `config-default.yml`. This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify. @@ -629,18 +668,19 @@ If you find any bugs in the bot or would like to request a feature, feel free to ### Appendix: Full ENV File Options The following is a list of all available environment variables used by the bot: -| Variable | Required | Description | -| -------- | -------- | -------- | -| `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | -| `BOT_API_KEY` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | -| `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | +| Variable | Required | Description | +|----------------------| -------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | +| `GUILD_ID` | Always | Your Discord test server's id (see [Set Up a Bot Account](#set-up-a-bot-account)). | +| `BOT_API_KEY` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | +| `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | | `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | -| `BOT_DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. -| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | -| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | -| `GITHUB_API_KEY` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. -| `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. -| `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. +| `BOT_DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. +| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | +| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | +| `GITHUB_API_KEY` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. +| `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. +| `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. --- -- cgit v1.2.3 From a0191ddf19e2d6f54fe00ef389d6e83be46b3c8c Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 01:08:16 +0100 Subject: fix typo in "Installing specific dependency groups" section --- .../pydis-guides/contributing/installing-project-dependencies.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md index 862f0add..9ad24034 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md @@ -43,9 +43,9 @@ $ poetry run task precommit ## Installing specific dependency groups -In some cases, like when you'll be using the configuration bootstrapping script, you might need to install extra dependencies that are +In some cases, like when you'll be using the configuration bootstrapping script, you might need to install extra dependencies that are not necessary for the bot project to function. -These dependency are put in a separate optional group likewise: +These dependencies are generally put in a separate optional group likewise: ```text [tool.poetry.group.group-name] @@ -62,4 +62,4 @@ To install them, you simply need to run the following command $ poetry install --only {{group-name}} ``` ---- \ No newline at end of file +--- -- cgit v1.2.3 From a847bd445a74c6f0386df025d1e83d803b95a561 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 01:09:47 +0100 Subject: appease linter --- .../guides/pydis-guides/contributing/bot.md | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 0b82265b..6abc34d8 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -43,7 +43,7 @@ without having to spend much time copying ids from your newly created server int **Note** -This phase can be skipped and done manually, but would require extra manual work. +This phase can be skipped and done manually, but would require extra manual work. ##### 1. Script setup ##### 1.1. Environment variables @@ -668,19 +668,19 @@ If you find any bugs in the bot or would like to request a feature, feel free to ### Appendix: Full ENV File Options The following is a list of all available environment variables used by the bot: -| Variable | Required | Description | -|----------------------| -------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | -| `GUILD_ID` | Always | Your Discord test server's id (see [Set Up a Bot Account](#set-up-a-bot-account)). | -| `BOT_API_KEY` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | -| `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | +| Variable | Required | Description | +|----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | +| `GUILD_ID` | Always | Your Discord test server's id (see [Set Up a Bot Account](#set-up-a-bot-account)). | +| `BOT_API_KEY` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | +| `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | | `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | -| `BOT_DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. -| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | -| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | -| `GITHUB_API_KEY` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. -| `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. -| `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. +| `BOT_DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. | +| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | +| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | +| `GITHUB_API_KEY` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. | +| `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | +| `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. | --- -- cgit v1.2.3 From f197b0462112fb2160f330eda8d267ff6d242e24 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 01:35:48 +0100 Subject: add a first explanation of how the `.env.server` should be used --- .../guides/pydis-guides/contributing/bot.md | 55 ++++++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 6abc34d8..62e3b64f 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -78,13 +78,60 @@ This file will contain the extracted ids from your newly created server which ar Congratulations, you have finished the configuration & can now start [running your bot](#run-it-) #### .env.server -Entering the directory of the cloned code, you will find a file named `config-default.yml`. +All server configuration values are saved in a file called `.env.server`, which needs to be at the root directory of the cloned code. This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify. -To run the bot in your test server, you will need to override some of those configurations. -Create and open a new file in the directory called `config.yml`. Alternatively, copy the `config-default.yml` file and rename the copy to `config.yml`. -The bot will first look at the items in `config.yml`, and will fall back to `config-default.yml` only if necessary. Note that you don't have to specify all items in `config.yml`, just the ones you want to override such as channel IDs. +If you decided to use the bootstrapping script, you'll find that this file has already been created (which we recommend), +otherwise you'll need to create it manually. + +To run the bot in your test server, you will **only** need to add the **necessary** configuration values for the channels/roles/categories, etc. +that you'll be using for testing + +Let's take an example where we suppose we'll only be testing a feature that needs the `announcements` channel. + +`constants.py` + +```py + +from pydantic import Field + +class EnvConfig: + # Defines from where & how Pydantic will be looking for env variables + ... + +class _Channels(EnvConfig): + + EnvConfig.Config.env_prefix = "channels." + + announcements: int = Field(default=123) + changelog: int = Field(default=456) + +# Instantiate the class & load the configuration +Channels = _Channels() +``` + +`.env.server` file + +```text +channels.announcements=789 +``` + +When you launch your bot, `pydantic` will load up the server constants from the `.env.server` file if they exist. + +Each constants class will define its own prefix, which will make `pydantic` look for variables that will look like `{{env_prefix}}{{attribute_name}}` in the environment files + +In our example, this will imply that pydantic will look for both `channels.announcements` and `channels.changelog` in the `.env.server` file. + +As you can see here, only `channels.announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic` +to use the value **789** for the `announcements` attribute instead of the default **456**, and use the default value for the `changelog` attribute + +```python +>>> Channels.announcements +789 +>>> Channels.changelong +456 +``` See [here](../obtaining-discord-ids) for help with obtaining Discord IDs. -- cgit v1.2.3 From 99aa19f9b8e8610c688c418448ecabdcc463b4f2 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 10:51:21 +0100 Subject: make the notes inline --- .../content/resources/guides/pydis-guides/contributing/bot.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 62e3b64f..129adceb 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -41,9 +41,7 @@ You now have both the bot's code and a server to run it on. It's time you to con To make setup much easier, there is a file called `bootstrap_config.py` that represents a script to bootstrap the configuration for you and help you get started immediately without having to spend much time copying ids from your newly created server into your configuration file. -**Note** - -This phase can be skipped and done manually, but would require extra manual work. +**Note**: This phase can be skipped and done manually, but would require extra manual work. ##### 1. Script setup ##### 1.1. Environment variables @@ -56,9 +54,7 @@ GUILD_ID=YourDiscordTestServerIdHere ``` See [here](../creating-bot-account) for help with obtaining the bot token and [here](obtaining-discord-ids.md#guild-id) for help with obtaining the guild's id -**Note** - -The `.env` file will be ignored by commits. +**Note**: The `.env` file will be ignored by commits. ##### 1.2 Setting up the script environment The bootstrapping script is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: 1. Make sure you follow steps `1` and `2` [here](#setting-up-a-development-environment) -- cgit v1.2.3 From abf77eba35116e4ed0a2a234ed4a2235bc54ca85 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 11:10:20 +0100 Subject: divide config into auto & manual sections --- .../resources/guides/pydis-guides/contributing/bot.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 129adceb..01571353 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -36,8 +36,9 @@ If your bot fails to start with a `PrivilegedIntentsRequired` exception, this in ### Configure the Bot You now have both the bot's code and a server to run it on. It's time you to connect the two by changing the bot's configurations. +This can be done either automatically or manually, and we'll be detailing the steps for both. -#### Scaffolding the configuration +#### Automatic configuration To make setup much easier, there is a file called `bootstrap_config.py` that represents a script to bootstrap the configuration for you and help you get started immediately without having to spend much time copying ids from your newly created server into your configuration file. @@ -63,17 +64,24 @@ The bootstrapping script is Python code like any other. To run it locally, you w #### 2. Running the script Once the script setup phase is complete, all that is left is to run it. -To do this, you'll simply need to run the `configure` poetry task like thise +To do this, you'll simply need to run the `configure` poetry task like this ```shell $ poetry run task configure ``` +or, without poetry and from the root directory + +```shell +python3 -m bootstrap_config +``` + Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory. This file will contain the extracted ids from your newly created server which are necessary for your bot to run. Congratulations, you have finished the configuration & can now start [running your bot](#run-it-) -#### .env.server +#### Manual configuration +##### .env.server All server configuration values are saved in a file called `.env.server`, which needs to be at the root directory of the cloned code. This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify. @@ -529,11 +537,11 @@ We understand this is tedious and are working on a better solution for setting u
-#### .env +##### .env The second file you need to create is the one containing the environment variables, and needs to be named `.env`. Inside, add the line `BOT_TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token. -The `.env` file will be ignored by commits. +**Note**: The `.env` file will be ignored by commits. --- -- cgit v1.2.3 From 496da05cccc16dbb71fbf4ff116d562c8c3cc134 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 12:16:46 +0100 Subject: blunt replacement of the embedded .yaml config --- .../guides/pydis-guides/contributing/bot.md | 748 +++++++++++---------- 1 file changed, 397 insertions(+), 351 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 01571353..7ab26008 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -141,7 +141,7 @@ See [here](../obtaining-discord-ids) for help with obtaining Discord IDs.

-- cgit v1.2.3 From 7d372a3b12fd6cbff9b2d928ece6ad6f45c9bb2d Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 12:45:55 +0100 Subject: update recommendeations of values that need overriding --- .../guides/pydis-guides/contributing/bot.md | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 7ab26008..cec2ab63 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -549,22 +549,22 @@ filters.ping_everyone=true
-If you don't wish to use the provided `config.yml` above, these are the main sections in `config-default.yml` that need overriding: -* `guild.id` -* `guild.categories` -* `guild.channels` -* `guild.roles` -* `guild.webhooks` -* `style.emojis` +If you don't wish to use the provided `env.server` above, the main values that need overriding are **all** the ones prefixed with: + +* `guild.` +* `categories.` +* `channels.` +* `roles.` +* `webhooks.` +* `emojis.` Additionally: -* At this stage, set `bot.redis.use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). -* Set `urls.site_api` to `!JOIN [*DOMAIN, "/api"]`. +* At this stage, set `redis.use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). * Set `urls.site_schema` and `urls.site_api_schema` to `"http://"`. -We understand this is tedious and are working on a better solution for setting up test servers. +We understand this is tedious which is why we **recommend** using the [automatic configuration setup](#automatic-configuration)
-- cgit v1.2.3 From 281bbf34f9e25dde8af1e99cb7971348a589d689 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 12:58:30 +0100 Subject: update all mentions of config & default-config.yaml --- .../resources/guides/pydis-guides/contributing/bot.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index cec2ab63..6f717b9b 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -615,7 +615,7 @@ You are now almost ready to run the Python bot. The simplest way to do so is wit
-In your `config.yml` file: +In your `.env.server` file: * Set `urls.site` to `"web:8000"`. * If you wish to work with snekbox set the following: @@ -634,7 +634,7 @@ Your bot is now running, but this method makes debugging with an IDE a fairly in The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. * Append the following line to your `.env` file: `BOT_API_KEY=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `config.yml` file, set `urls.site` to `"localhost:8000"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* In your `.env.server` file, set `urls.site` to `"localhost:8000"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. * To work with snekbox, set `urls.snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls.snekbox_311_eval_api` to `"http://localhost:8065/eval"` You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: @@ -679,7 +679,7 @@ You can run additional services on the host, but this guide won't go over how to If possible, prefer to start the services through Docker to replicate the production environment as much as possible. The site, however, is a mandatory service for the bot. -Refer to the [previous section](#with-the-bot-running-locally) and the [site contributing guide](../site) to learn how to start it on the host, in which case you will need to change `urls.site` in `config.yml` to wherever the site is being hosted. +Refer to the [previous section](#with-the-bot-running-locally) and the [site contributing guide](../site) to learn how to start it on the host, in which case you will need to change `urls.site` in `.env.server` to wherever the site is being hosted. --- ### Development Tips @@ -721,15 +721,15 @@ We are always open to more statistics so add as many as you can! --- ### Optional: Working with Redis -In [Configure the Bot](#configyml) you were asked to set `bot.redis.use_fakeredis` to `true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. +In [Configure the Bot](#envserver) you were asked to set `redis.use_fakeredis` to `true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. -If you are working on a feature that relies on Redis, you will need to enable Redis to make sure persistency is achieved for the feature across restarts. The first step towards that is going to `config.yml` and setting `bot.redis.use_fakeredis` to `false`. +If you are working on a feature that relies on Redis, you will need to enable Redis to make sure persistency is achieved for the feature across restarts. The first step towards that is going to `.env.server` and setting `redis.use_fakeredis` to `false`. #### Starting Redis in Docker (Recommended) -If you're using the Docker image provided in the project's Docker Compose, open your `config.yml` file. If you're running the bot in Docker, set `bot.redis.host` to `redis`, and if you're running it on the host set it to `localhost`. Set `bot.redis.password` to `null`. +If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis.host` to `redis`, and if you're running it on the host set it to `localhost`. Set `bot.redis.password` to `""`. #### Starting Redis Using Other Methods -You can run your own instance of Redis, but in that case you will need to correctly set `bot.redis.host` and `bot.redis.port`, and the `bot.redis.password` value in `config-default.yml` should not be overridden. Then, enter the `.env` file, and set `REDIS_PASSWORD` to whatever password you set. +You can run your own instance of Redis, but in that case you will need to correctly set `redis.host` and `redis.port`, and the `redis.password` value in `constants.py` should not be overridden. Then, enter the `.env` file, and set `REDIS_PASSWORD` to whatever password you set. --- -- cgit v1.2.3 From 36ce014fe91553bd3ddd9411ff25be58209cd755 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 13:00:56 +0100 Subject: update info of the `GUILD_ID` env var --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 6f717b9b..6d9be90e 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -768,7 +768,8 @@ The following is a list of all available environment variables used by the bot: | Variable | Required | Description | |----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | -| `GUILD_ID` | Always | Your Discord test server's id (see [Set Up a Bot Account](#set-up-a-bot-account)). | +| `GUILD_ID` | When using the bootstrapping script | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | +| `GUILD_ID` | When using the bootstrapping script | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | | `BOT_API_KEY` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | | `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | | `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | -- cgit v1.2.3 From 217d874ba0c66d3e2708e899863f34bee65ad9dd Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 13:04:24 +0100 Subject: remove duplicated line in appendix --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 1 - 1 file changed, 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 6d9be90e..a2b58443 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -769,7 +769,6 @@ The following is a list of all available environment variables used by the bot: |----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | | `GUILD_ID` | When using the bootstrapping script | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | -| `GUILD_ID` | When using the bootstrapping script | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | | `BOT_API_KEY` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | | `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | | `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | -- cgit v1.2.3 From a5e68bc4962a0c2e7b71a7f59cbdccf3b220725a Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 13:09:45 +0100 Subject: update guide links --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index a2b58443..0a7a116c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -53,13 +53,13 @@ Inside, add the following two lines: BOT_TOKEN=YourDiscordBotTokenHere GUILD_ID=YourDiscordTestServerIdHere ``` -See [here](../creating-bot-account) for help with obtaining the bot token and [here](obtaining-discord-ids.md#guild-id) for help with obtaining the guild's id +See [here](../creating-bot-account) for help with obtaining the bot token and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's id **Note**: The `.env` file will be ignored by commits. ##### 1.2 Setting up the script environment The bootstrapping script is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: 1. Make sure you follow steps `1` and `2` [here](#setting-up-a-development-environment) -2. [Install the `config-bootstrap` dependency group](installing-project-dependencies.md#installing-specific-dependency-groups). +2. [Install the `config-bootstrap` dependency group](../installing-project-dependencies#installing-specific-dependency-groups). #### 2. Running the script -- cgit v1.2.3 From 4364bad23223ae6e271d9d60ef30787be2be7d51 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 13:11:50 +0100 Subject: update the run it link --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 0a7a116c..dba4b280 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -47,6 +47,7 @@ without having to spend much time copying ids from your newly created server int ##### 1. Script setup ##### 1.1. Environment variables You will need to create a file called `.env` which will contain two required values for the script to work: `BOT_TOKEN` and `GUILD_ID` + Inside, add the following two lines: ```text @@ -58,6 +59,7 @@ See [here](../creating-bot-account) for help with obtaining the bot token and [h **Note**: The `.env` file will be ignored by commits. ##### 1.2 Setting up the script environment The bootstrapping script is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: + 1. Make sure you follow steps `1` and `2` [here](#setting-up-a-development-environment) 2. [Install the `config-bootstrap` dependency group](../installing-project-dependencies#installing-specific-dependency-groups). @@ -78,7 +80,8 @@ python3 -m bootstrap_config Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory. This file will contain the extracted ids from your newly created server which are necessary for your bot to run. -Congratulations, you have finished the configuration & can now start [running your bot](#run-it-) + +**Congratulations**, you have finished the configuration & can now start [running your bot](#run-it) #### Manual configuration ##### .env.server -- cgit v1.2.3 From 493adc94f96f7444e9b449795d397d2213a78788 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 13:14:00 +0100 Subject: put constants.py inside code tags --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index dba4b280..709b57b3 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -578,7 +578,7 @@ We understand this is tedious which is why we **recommend** using the [automatic
-- cgit v1.2.3 From 2af659981711cabf817f0f4b1805b4aa98ff69f2 Mon Sep 17 00:00:00 2001 From: Amrou Date: Sat, 25 Feb 2023 13:25:18 +0100 Subject: add old config comments --- .../resources/guides/pydis-guides/contributing/bot.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index a6d41bb6..eb87c183 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -155,6 +155,10 @@ See [here](../obtaining-discord-ids) for help with obtaining Discord IDs.
                 
 
+##### <<  Replace the following � characters with the channel IDs in your test server  >> #####
+#  This assumes the template was used: https://discord.new/zmHtscpYN9E3
+
+
 # Channels configuration
 channels.announcements=�
 channels.changelog=�
@@ -232,6 +236,9 @@ channels.big_brother_logs=�
 channels.duck_pond=�
 channels.roles=�
 
+##### << Replace the following � characters with the role IDs in your test server >> #####
+
+
 # Roles configuration
 
 roles.advent_of_code=�
@@ -273,7 +280,7 @@ roles.patreon_tier_1=�
 roles.patreon_tier_2=�
 roles.patreon_tier_3=�
 
-
+##### << Replace the following � characters with the category IDs in your test server >> #####
 
 # Categories configuration
 
@@ -287,12 +294,15 @@ categories.voice=�
 ### 2021 Summer Code Jam
 categories.summer_code_jam=�
 
+##### << Replace the following � character with the ID of your test server >> #####
 
 # Guild configuration
 guild.id=�
 guild.invite="https://discord.gg/python"
 
 
+##### << Replace the following � characters with the webhook IDs in your test server >> #####
+
 # Webhooks configuration
 
 webhooks.big_brother.id=�
@@ -435,6 +445,10 @@ urls.site_api_schema="http://"
 urls.connect_max_retries=3
 urls.connect_cooldown=5
 
+##### << The bot shouldn't fail without these, but commands adding specific emojis won't work. >> #####
+##### << You should at least set the trashcan. Set the incidents emojis if relevant. >> #####
+
+
 
 # Emojis configuration
 emojis.badge_bug_hunter="<:bug_hunter_lvl1:743882896372269137>"
@@ -531,6 +545,8 @@ icons.voice_state_blue="https://cdn.discordapp.com/emojis/656899769662439456.png
 icons.voice_state_green="https://cdn.discordapp.com/emojis/656899770094452754.png"
 icons.voice_state_red="https://cdn.discordapp.com/emojis/656899769905709076.png"
 
+##### << Optional - If you don't care about the filtering, help channel and py-news cogs, ignore the rest of this file >> #####
+
 # Filters configuration
 filters.filter_domains=true
 filters.filter_everyone_ping=true
-- 
cgit v1.2.3


From a82c4bfc0babdcf52cd67c59eebdc5b1e9c5d47d Mon Sep 17 00:00:00 2001
From: Ibrahim 
Date: Sun, 26 Feb 2023 00:01:28 +0530
Subject: Update description of `TRASHCAN_EMOJI` according to review

---
 .../content/resources/guides/pydis-guides/contributing/sir-lancebot.md | 2 +-
 .../guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
index 9e48c624..8b97cf06 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
@@ -81,7 +81,7 @@ The following variables are needed for running Sir Lancebot:
 | `CHANNEL_ANNOUNCEMENTS` | ID of the `#announcements` channel |
 | `CHANNEL_DEVLOG` | ID of the `#dev-log` channel |
 | `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the `#sir-lancebot-commands` channel |
-| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of `\:emoji:`. |
+| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of sending `\:emoji:` on discord. |
 
 [**Full environment variable reference for this project.**](./env-var-reference)
 
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
index 09ec9394..3862fb2e 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md
@@ -32,8 +32,7 @@ Additionally, you may find the following environment variables useful during dev
 | `REDIS_PASSWORD` | |
 | `USE_FAKEREDIS` | If the FakeRedis module should be used. Set this to true if you don't have a Redis database setup. |
 | `BOT_SENTRY_DSN` | The DSN of the sentry monitor. |
-| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of `\:emoji:`. |
-
+| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of sending `\:emoji:` on discord. |
 
 ---
 ## Tokens/APIs
-- 
cgit v1.2.3


From e1100b443844d4e9935e661e63ba352d867fd647 Mon Sep 17 00:00:00 2001
From: Amrou 
Date: Sat, 25 Feb 2023 19:53:33 +0100
Subject: remove usage of the Field class

---
 .../apps/content/resources/guides/pydis-guides/contributing/bot.md  | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index eb87c183..dbded02a 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -101,8 +101,6 @@ Let's take an example where we suppose we'll only be testing a feature that need
 
 ```py
 
-from pydantic import Field
-
 class EnvConfig:
     # Defines from where & how Pydantic will be looking for env variables
     ...
@@ -111,8 +109,8 @@ class _Channels(EnvConfig):
 
     EnvConfig.Config.env_prefix = "channels."
 
-    announcements: int = Field(default=123)
-    changelog: int = Field(default=456)
+    announcements = 123
+    changelog = 456
 
 # Instantiate the class & load the configuration
 Channels = _Channels()
-- 
cgit v1.2.3


From 67db760b8c05f9d2ec57930edfabedcb4ab11978 Mon Sep 17 00:00:00 2001
From: Amrou 
Date: Sun, 26 Feb 2023 01:18:26 +0100
Subject: update appendix to use the "." separator

---
 .../guides/pydis-guides/contributing/bot.md        | 38 +++++++++++-----------
 1 file changed, 19 insertions(+), 19 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index dbded02a..83f541e1 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -46,13 +46,13 @@ without having to spend much time copying ids from your newly created server int
 
 ##### 1. Script setup
 ##### 1.1. Environment variables
-You will need to create a file called `.env` which will contain two required values for the script to work: `BOT_TOKEN` and `GUILD_ID`
+You will need to create a file called `.env` which will contain two required values for the script to work: `BOT.TOKEN` and `GUILD.ID`
 
 Inside, add the following two lines:
 
 ```text
-BOT_TOKEN=YourDiscordBotTokenHere
-GUILD_ID=YourDiscordTestServerIdHere
+BOT.TOKEN=YourDiscordBotTokenHere
+GUILD.ID=YourDiscordTestServerIdHere
 ```
 See [here](../creating-bot-account) for help with obtaining the bot token and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's id
 
@@ -604,7 +604,7 @@ We understand this is tedious which is why we **recommend** using the [automatic
 
 ##### .env
 The second file you need to create is the one containing the environment variables, and needs to be named `.env`.
-Inside, add the line `BOT_TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token.
+Inside, add the line `BOT.TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token.
 
 **Note**: The `.env` file will be ignored by commits.
 
@@ -652,7 +652,7 @@ Your bot is now running, but this method makes debugging with an IDE a fairly in
 #### With the Bot Running Locally
 The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker.
 
-* Append the following line to your `.env` file: `BOT_API_KEY=badbot13m0n8f570f942013fc818f234916ca531`.
+* Append the following line to your `.env` file: `API_KEYS.SITE_API=badbot13m0n8f570f942013fc818f234916ca531`.
 * In your `.env.server` file, set `urls.site` to `"localhost:8000"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set.
 * To work with snekbox, set `urls.snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls.snekbox_311_eval_api` to `"http://localhost:8065/eval"`
 
@@ -748,7 +748,7 @@ If you are working on a feature that relies on Redis, you will need to enable Re
 If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis.host` to `redis`, and if you're running it on the host set it to `localhost`. Set `bot.redis.password` to `""`.
 
 #### Starting Redis Using Other Methods
-You can run your own instance of Redis, but in that case you will need to correctly set `redis.host` and `redis.port`, and the `redis.password` value in `constants.py` should not be overridden. Then, enter the `.env` file, and set `REDIS_PASSWORD` to whatever password you set.
+You can run your own instance of Redis, but in that case you will need to correctly set `redis.host` and `redis.port`, and the `redis.password` value in `constants.py` should not be overridden. Then, enter the `.env` file, and set `REDIS.PASSWORD` to whatever password you set.
 
 ---
 
@@ -784,19 +784,19 @@ If you find any bugs in the bot or would like to request a feature, feel free to
 ### Appendix: Full ENV File Options
 The following is a list of all available environment variables used by the bot:
 
-| Variable             | Required                                        | Description                                                                                                                                                                                                                                         |
-|----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `BOT_TOKEN`          | Always                                          | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)).                                                                                                                                                               |
-| `GUILD_ID`           | When using the bootstrapping script             | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)).                                                                                                                                                                  |
-| `BOT_API_KEY`        | When running bot without Docker                 | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below.                                                                |
-| `BOT_SENTRY_DSN`     | When connecting the bot to sentry               | The DSN of the sentry monitor.                                                                                                                                                                                                                      |
-| `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. |
-| `BOT_DEBUG`          | In production                                   | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default.                                                                                                                        |
-| `REDIS_PASSWORD`     | When not using FakeRedis                        | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)).                                                                                                                                   |
-| `USE_METRICITY`      | When using Metricity                            | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default.                                                                |
-| `GITHUB_API_KEY`     | When you wish to interact with GitHub           | The API key to interact with GitHub, for example to download files for the branding manager.                                                                                                                                                        |
-| `METABASE_USERNAME`  | When you wish to interact with Metabase         | The username for a Metabase admin account.                                                                                                                                                                                                          |
-| `METABASE_PASSWORD`  | When you wish to interact with Metabase         | The password for a Metabase admin account.                                                                                                                                                                                                          |
+| Variable            | Required                                        | Description                                                                                                                                                                                                                                         |
+|---------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `BOT.TOKEN`         | Always                                          | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)).                                                                                                                                                               |
+| `GUILD.ID`          | When using the bootstrapping script             | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)).                                                                                                                                                                  |
+| `API_KEYS.SITE_API` | When running bot without Docker                 | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below.                                                                |
+| `SENTRY_DSN`        | When connecting the bot to sentry               | The DSN of the sentry monitor.                                                                                                                                                                                                                      |
+| `TRACE_LOGGERS `    | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. |
+| `DEBUG`             | In production                                   | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default.                                                                                                                        |
+| `REDIS.PASSWORD`    | When not using FakeRedis                        | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)).                                                                                                                                   |
+| `USE_METRICITY`     | When using Metricity                            | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default.                                                                |
+| `API_KEYS.GITHUB`   | When you wish to interact with GitHub           | The API key to interact with GitHub, for example to download files for the branding manager.                                                                                                                                                        |
+| `METABASE.USERNAME` | When you wish to interact with Metabase         | The username for a Metabase admin account.                                                                                                                                                                                                          |
+| `METABASE.PASSWORD` | When you wish to interact with Metabase         | The password for a Metabase admin account.                                                                                                                                                                                                          |
 
 ---
 
-- 
cgit v1.2.3


From 70f354c43ad77ed5c5bbce7b81e4dd743e90362d Mon Sep 17 00:00:00 2001
From: Amrou 
Date: Sun, 26 Feb 2023 01:22:39 +0100
Subject: prefix sentry_dsn & trace_loggers with `bot.`

---
 .../guides/pydis-guides/contributing/bot.md        | 26 +++++++++++-----------
 1 file changed, 13 insertions(+), 13 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index 83f541e1..f20a2829 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -784,19 +784,19 @@ If you find any bugs in the bot or would like to request a feature, feel free to
 ### Appendix: Full ENV File Options
 The following is a list of all available environment variables used by the bot:
 
-| Variable            | Required                                        | Description                                                                                                                                                                                                                                         |
-|---------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `BOT.TOKEN`         | Always                                          | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)).                                                                                                                                                               |
-| `GUILD.ID`          | When using the bootstrapping script             | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)).                                                                                                                                                                  |
-| `API_KEYS.SITE_API` | When running bot without Docker                 | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below.                                                                |
-| `SENTRY_DSN`        | When connecting the bot to sentry               | The DSN of the sentry monitor.                                                                                                                                                                                                                      |
-| `TRACE_LOGGERS `    | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. |
-| `DEBUG`             | In production                                   | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default.                                                                                                                        |
-| `REDIS.PASSWORD`    | When not using FakeRedis                        | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)).                                                                                                                                   |
-| `USE_METRICITY`     | When using Metricity                            | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default.                                                                |
-| `API_KEYS.GITHUB`   | When you wish to interact with GitHub           | The API key to interact with GitHub, for example to download files for the branding manager.                                                                                                                                                        |
-| `METABASE.USERNAME` | When you wish to interact with Metabase         | The username for a Metabase admin account.                                                                                                                                                                                                          |
-| `METABASE.PASSWORD` | When you wish to interact with Metabase         | The password for a Metabase admin account.                                                                                                                                                                                                          |
+| Variable             | Required                                        | Description                                                                                                                                                                                                                                         |
+|----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `BOT.TOKEN`          | Always                                          | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)).                                                                                                                                                               |
+| `GUILD.ID`           | When using the bootstrapping script             | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)).                                                                                                                                                                  |
+| `API_KEYS.SITE_API`  | When running bot without Docker                 | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below.                                                                |
+| `BOT.SENTRY_DSN`     | When connecting the bot to sentry               | The DSN of the sentry monitor.                                                                                                                                                                                                                      |
+| `BOT.TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. |
+| `DEBUG`              | In production                                   | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default.                                                                                                                        |
+| `REDIS.PASSWORD`     | When not using FakeRedis                        | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)).                                                                                                                                   |
+| `USE_METRICITY`      | When using Metricity                            | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default.                                                                |
+| `API_KEYS.GITHUB`    | When you wish to interact with GitHub           | The API key to interact with GitHub, for example to download files for the branding manager.                                                                                                                                                        |
+| `METABASE.USERNAME`  | When you wish to interact with Metabase         | The username for a Metabase admin account.                                                                                                                                                                                                          |
+| `METABASE.PASSWORD`  | When you wish to interact with Metabase         | The password for a Metabase admin account.                                                                                                                                                                                                          |
 
 ---
 
-- 
cgit v1.2.3


From 7378c288ad261714eb8111875134f36bf42b299e Mon Sep 17 00:00:00 2001
From: Ibrahim 
Date: Tue, 28 Feb 2023 01:51:59 +0530
Subject: remove trashcan emoji from required variables

---
 .../content/resources/guides/pydis-guides/contributing/sir-lancebot.md   | 1 -
 1 file changed, 1 deletion(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
index 8b97cf06..142e6534 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
@@ -81,7 +81,6 @@ The following variables are needed for running Sir Lancebot:
 | `CHANNEL_ANNOUNCEMENTS` | ID of the `#announcements` channel |
 | `CHANNEL_DEVLOG` | ID of the `#dev-log` channel |
 | `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the `#sir-lancebot-commands` channel |
-| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of sending `\:emoji:` on discord. |
 
 [**Full environment variable reference for this project.**](./env-var-reference)
 
-- 
cgit v1.2.3


From bfa955417ae582a797c31dd462bb0279fb67c64e Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Tue, 28 Feb 2023 09:36:53 +0100
Subject: Update the note about ignoring .env

---
 .../apps/content/resources/guides/pydis-guides/contributing/bot.md    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index f20a2829..03c2444b 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -56,7 +56,7 @@ GUILD.ID=YourDiscordTestServerIdHere
 ```
 See [here](../creating-bot-account) for help with obtaining the bot token and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's id
 
-**Note**: The `.env` file will be ignored by commits.
+**Note**: The `.env` is and should remain ignored by git, otherwise you risk pushing sensitive information.
 ##### 1.2 Setting up the script environment
 The bootstrapping script is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed:
 
@@ -606,7 +606,7 @@ We understand this is tedious which is why we **recommend** using the [automatic
 The second file you need to create is the one containing the environment variables, and needs to be named `.env`.
 Inside, add the line `BOT.TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token.
 
-**Note**: The `.env` file will be ignored by commits.
+**Note**: The `.env` is and should remain ignored by git, otherwise you risk pushing sensitive information.
 
 ---
 
-- 
cgit v1.2.3


From 30033da4c74df1ae47e30f4a63eef7085b06712f Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Tue, 28 Feb 2023 09:40:56 +0100
Subject: Use "Python program" instead of "Python code" to describe the script

---
 .../apps/content/resources/guides/pydis-guides/contributing/bot.md     | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index 03c2444b..c3189bbe 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -58,7 +58,8 @@ See [here](../creating-bot-account) for help with obtaining the bot token and [h
 
 **Note**: The `.env` is and should remain ignored by git, otherwise you risk pushing sensitive information.
 ##### 1.2 Setting up the script environment
-The bootstrapping script is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed:
+The bootstrapping script is a Python program so you will need a compatible Python version and the necessary dependencies installed,
+which are all detailed here:
 
 1. Make sure you follow steps `1` and `2` [here](#setting-up-a-development-environment)
 2. [Install the `config-bootstrap` dependency group](../installing-project-dependencies#installing-specific-dependency-groups).
-- 
cgit v1.2.3


From fefe1e7b80ee6d8f162695d47260d818a414e034 Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Tue, 28 Feb 2023 09:45:03 +0100
Subject: Mention that only necessary component IDs needs to be added when
 configuring manually

---
 .../apps/content/resources/guides/pydis-guides/contributing/bot.md   | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index c3189bbe..4322d0a6 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -93,8 +93,9 @@ It also contains configurations such as how long it takes for a help channel to
 If you decided to use the bootstrapping script, you'll find that this file has already been created (which we recommend),
 otherwise you'll need to create it manually.
 
-To run the bot in your test server, you will **only** need to add the **necessary** configuration values for the channels/roles/categories, etc.
-that you'll be using for testing
+If you decide to set the configuration values manually, you will **only** need to set the values for the channels, roles, categories, etc. 
+that are used by the component you are developing.
+
 
 Let's take an example where we suppose we'll only be testing a feature that needs the `announcements` channel.
 
-- 
cgit v1.2.3


From 1c23a1715496332a25f2548e208e4e09c31d8be9 Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Tue, 28 Feb 2023 09:50:15 +0100
Subject: use concrete ids for the channel examples

---
 .../resources/guides/pydis-guides/contributing/bot.md        | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index 4322d0a6..c991d432 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -111,8 +111,8 @@ class _Channels(EnvConfig):
 
     EnvConfig.Config.env_prefix = "channels."
 
-    announcements = 123
-    changelog = 456
+    announcements = 1079790565794779156
+    changelog = 1077877318564991006
 
 # Instantiate the class & load the configuration
 Channels = _Channels()
@@ -121,7 +121,7 @@ Channels = _Channels()
 `.env.server` file
 
 ```text
-channels.announcements=789
+channels.announcements=1077875228002234398
 ```
 
 When you launch your bot, `pydantic` will load up the server constants from the `.env.server` file if they exist.
@@ -131,13 +131,13 @@ Each constants class will define its own prefix, which will make `pydantic` look
 In our example, this will imply that pydantic will look for both `channels.announcements` and `channels.changelog` in the `.env.server` file.
 
 As you can see here, only `channels.announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic`
-to use the value **789** for the `announcements` attribute instead of the default **456**, and use the default value for the `changelog` attribute
+to use the value **1077875228002234398** for the `announcements` attribute instead of the default **1079790565794779156**, and use the default value for the `changelog` attribute
 
 ```python
 >>> Channels.announcements
-789
+1077875228002234398
 >>> Channels.changelong
-456
+1077877318564991006
 ```
 
 See [here](../obtaining-discord-ids) for help with obtaining Discord IDs.
-- 
cgit v1.2.3


From a3a54a1c69463429520d8cf8530f8c3e95b5c86f Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Tue, 28 Feb 2023 09:53:01 +0100
Subject: Appease linter

---
 .../apps/content/resources/guides/pydis-guides/contributing/bot.md      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index c991d432..65f0d818 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -93,7 +93,7 @@ It also contains configurations such as how long it takes for a help channel to
 If you decided to use the bootstrapping script, you'll find that this file has already been created (which we recommend),
 otherwise you'll need to create it manually.
 
-If you decide to set the configuration values manually, you will **only** need to set the values for the channels, roles, categories, etc. 
+If you decide to set the configuration values manually, you will **only** need to set the values for the channels, roles, categories, etc.
 that are used by the component you are developing.
 
 
-- 
cgit v1.2.3


From 3001c2d43cbf10975bef9de1687c56882428f96f Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Tue, 28 Feb 2023 15:03:31 +0100
Subject: bump python version to 3.10

---
 .../content/resources/guides/pydis-guides/contributing/sir-lancebot.md  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
index c9566d23..b4756be2 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
@@ -10,7 +10,7 @@ You should have already forked the [`sir-lancebot`](https://github.com/python-di
 Remember to ensure that you have read the [contributing guidelines](../contributing-guidelines) in full before you start contributing.
 
 ### Requirements
-- [Python 3.9](https://www.python.org/downloads/)
+- [Python 3.10](https://www.python.org/downloads/)
 - [Poetry](https://github.com/python-poetry/poetry#installation)
 - [Git](https://git-scm.com/downloads)
     - [Windows Installer](https://git-scm.com/download/win)
-- 
cgit v1.2.3


From 6e687e4228d7f757c6a09d462c866974cfdbacb0 Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Tue, 28 Feb 2023 15:08:06 +0100
Subject: add wildcard for patch version

---
 .../content/resources/guides/pydis-guides/contributing/sir-lancebot.md  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
index b4756be2..fdc0e257 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md
@@ -10,7 +10,7 @@ You should have already forked the [`sir-lancebot`](https://github.com/python-di
 Remember to ensure that you have read the [contributing guidelines](../contributing-guidelines) in full before you start contributing.
 
 ### Requirements
-- [Python 3.10](https://www.python.org/downloads/)
+- [Python 3.10.*](https://www.python.org/downloads/)
 - [Poetry](https://github.com/python-poetry/poetry#installation)
 - [Git](https://git-scm.com/downloads)
     - [Windows Installer](https://git-scm.com/download/win)
-- 
cgit v1.2.3


From adc8540bd1ded4134552b42dadb13a8ff228f660 Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Thu, 2 Mar 2023 14:48:24 +0100
Subject: update all instances of bootstrap_config with botstrap

---
 .../apps/content/resources/guides/pydis-guides/contributing/bot.md    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index 65f0d818..85198f8b 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -39,7 +39,7 @@ You now have both the bot's code and a server to run it on. It's time you to con
 This can be done either automatically or manually, and we'll be detailing the steps for both.
 
 #### Automatic configuration
-To make setup much easier, there is a file called `bootstrap_config.py` that represents a script to bootstrap the configuration for you and help you get started immediately
+To make setup much easier, there is a file called `botstrap.py` that represents a script to bootstrap the configuration for you and help you get started immediately
 without having to spend much time copying ids from your newly created server into your configuration file.
 
 **Note**: This phase can be skipped and done manually, but would require extra manual work.
@@ -76,7 +76,7 @@ $ poetry run task configure
 or, without poetry and from the root directory
 
 ```shell
-python3 -m bootstrap_config
+python3 -m botstrap
 ```
 
 Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory.
-- 
cgit v1.2.3


From 2fc356c15e281240bff766a2a83ae92c6742c199 Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Thu, 2 Mar 2023 15:01:53 +0100
Subject: add a section that details help forum setup

---
 .../resources/guides/pydis-guides/contributing/bot.md  | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index 85198f8b..7aa18ccc 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -612,6 +612,24 @@ Inside, add the line `BOT.TOKEN=YourDiscordBotTokenHere`. See [here](../creating
 
 ---
 
+### Working with the help forum
+If you will be working on a feature that includes the python help forum, you will need to use `Forum Channels`.
+
+Forum channels cannot be included in a template, which is why this needs to be done by hand for the time being.
+
+To activate forum channels, your Discord server needs to have the community feature.
+If that's not the case already, here are the steps required to do it:
+1. Go to server settings
+2. Scroll down to the `COMMUNITY` section and click on `Enable Community`
+3. Click on `Get Started` and fill out the necessary info
+
+Once the previous steps are done, all that is left is to:
+1. Create a new channel
+2. Choose the `Forum` type
+3. [Copy its ID](../obtaining-discord-ids#channel-id)
+4. Add the following line to the `.env.server` file: `channels.python_help={newly_created_forum_channel_id}` 
+
+
 ### Run it!
 #### With Docker
 You are now almost ready to run the Python bot. The simplest way to do so is with Docker.
-- 
cgit v1.2.3


From df9181f99ac329044ec40016a6a82ba8ef7dcc4e Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Thu, 2 Mar 2023 15:22:51 +0100
Subject: appease linter

---
 .../apps/content/resources/guides/pydis-guides/contributing/bot.md      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index 7aa18ccc..272ba10a 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -627,7 +627,7 @@ Once the previous steps are done, all that is left is to:
 1. Create a new channel
 2. Choose the `Forum` type
 3. [Copy its ID](../obtaining-discord-ids#channel-id)
-4. Add the following line to the `.env.server` file: `channels.python_help={newly_created_forum_channel_id}` 
+4. Add the following line to the `.env.server` file: `channels.python_help={newly_created_forum_channel_id}`
 
 
 ### Run it!
-- 
cgit v1.2.3


From 47308422a2a34d9fc66f0c5f7b423b12a775d919 Mon Sep 17 00:00:00 2001
From: shtlrs 
Date: Wed, 8 Mar 2023 12:38:37 +0100
Subject: update prefix to underscore: _

---
 .../guides/pydis-guides/contributing/bot.md        | 616 ++++++++++-----------
 1 file changed, 308 insertions(+), 308 deletions(-)

(limited to 'pydis_site/apps/content/resources/guides')

diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
index 272ba10a..07881543 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md
@@ -46,13 +46,13 @@ without having to spend much time copying ids from your newly created server int
 
 ##### 1. Script setup
 ##### 1.1. Environment variables
-You will need to create a file called `.env` which will contain two required values for the script to work: `BOT.TOKEN` and `GUILD.ID`
+You will need to create a file called `.env` which will contain two required values for the script to work: `BOT_TOKEN` and `GUILD_ID`
 
 Inside, add the following two lines:
 
 ```text
-BOT.TOKEN=YourDiscordBotTokenHere
-GUILD.ID=YourDiscordTestServerIdHere
+BOT_TOKEN=YourDiscordBotTokenHere
+GUILD_ID=YourDiscordTestServerIdHere
 ```
 See [here](../creating-bot-account) for help with obtaining the bot token and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's id
 
@@ -109,7 +109,7 @@ class EnvConfig:
 
 class _Channels(EnvConfig):
 
-    EnvConfig.Config.env_prefix = "channels."
+    EnvConfig.Config.env_prefix = "channels_"
 
     announcements = 1079790565794779156
     changelog = 1077877318564991006
@@ -121,16 +121,16 @@ Channels = _Channels()
 `.env.server` file
 
 ```text
-channels.announcements=1077875228002234398
+channels_announcements=1077875228002234398
 ```
 
 When you launch your bot, `pydantic` will load up the server constants from the `.env.server` file if they exist.
 
 Each constants class will define its own prefix, which will make `pydantic` look for variables that will look like `{{env_prefix}}{{attribute_name}}` in the environment files
 
-In our example, this will imply that pydantic will look for both `channels.announcements` and `channels.changelog` in the `.env.server` file.
+In our example, this will imply that pydantic will look for both `channels_announcements` and `channels_changelog` in the `.env.server` file.
 
-As you can see here, only `channels.announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic`
+As you can see here, only `channels_announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic`
 to use the value **1077875228002234398** for the `announcements` attribute instead of the default **1079790565794779156**, and use the default value for the `changelog` attribute
 
 ```python
@@ -160,290 +160,290 @@ See [here](../obtaining-discord-ids) for help with obtaining Discord IDs.
 
 
 # Channels configuration
-channels.announcements=�
-channels.changelog=�
-channels.mailing_lists=�
-channels.python_events=�
-channels.python_news=�
-channels.reddit=�
-
-channels.dev_contrib=�
-channels.dev_core=�
-channels.dev_log=�
-
-channels.meta=�
-channels.python_general=�
-
-channels.help_system_forum=�
-
-channels.attachment_log=�
-channels.filter_log=�
-channels.message_log=�
-channels.mod_log=�
-channels.nomination_archive=�
-channels.user_log=�
-channels.voice_log=�
-
-channels.off_topic_0=�
-channels.off_topic_1=�
-channels.off_topic_2=�
-
-channels.bot_commands=�
-channels.discord_bots=�
-channels.esoteric=�
-channels.voice_gate=�
-channels.code_jam_planning=�
+channels_announcements=�
+channels_changelog=�
+channels_mailing_lists=�
+channels_python_events=�
+channels_python_news=�
+channels_reddit=�
+
+channels_dev_contrib=�
+channels_dev_core=�
+channels_dev_log=�
+
+channels_meta=�
+channels_python_general=�
+
+channels_help_system_forum=�
+
+channels_attachment_log=�
+channels_filter_log=�
+channels_message_log=�
+channels_mod_log=�
+channels_nomination_archive=�
+channels_user_log=�
+channels_voice_log=�
+
+channels_off_topic_0=�
+channels_off_topic_1=�
+channels_off_topic_2=�
+
+channels_bot_commands=�
+channels_discord_bots=�
+channels_esoteric=�
+channels_voice_gate=�
+channels_code_jam_planning=�
 
 ### Staff
-channels.admins=�
-channels.admin_spam=�
-channels.defcon=�
-channels.helpers=�
-channels.incidents=�
-channels.incidents_archive=�
-channels.mod_alerts=�
-channels.mod_meta=�
-channels.mods=�
-channels.nominations=�
-channels.nomination_voting=�
-channels.organisation=�
+channels_admins=�
+channels_admin_spam=�
+channels_defcon=�
+channels_helpers=�
+channels_incidents=�
+channels_incidents_archive=�
+channels_mod_alerts=�
+channels_mod_meta=�
+channels_mods=�
+channels_nominations=�
+channels_nomination_voting=�
+channels_organisation=�
 
 ### Staff announcement channels
-channels.admin_announcements=�
-channels.mod_announcements=�
-channels.staff_announcements=�
-channels.staff_info=�
-channels.staff_lounge=�
+channels_admin_announcements=�
+channels_mod_announcements=�
+channels_staff_announcements=�
+channels_staff_info=�
+channels_staff_lounge=�
 
 ### Voice Channels
-channels.admins_voice=�
-channels.code_help_voice_0=�
-channels.code_help_voice_1=�
-channels.general_voice_0=�
-channels.general_voice_1=�
-channels.staff_voice=�
+channels_admins_voice=�
+channels_code_help_voice_0=�
+channels_code_help_voice_1=�
+channels_general_voice_0=�
+channels_general_voice_1=�
+channels_staff_voice=�
 
-channels.black_formatter=�
+channels_black_formatter=�
 
 ### Voice Chat
-channels.code_help_chat_0=�
-channels.code_help_chat_1=�
-channels.staff_voice_chat=�
-channels.voice_chat_0=�
-channels.voice_chat_1=�
+channels_code_help_chat_0=�
+channels_code_help_chat_1=�
+channels_staff_voice_chat=�
+channels_voice_chat_0=�
+channels_voice_chat_1=�
 
-channels.big_brother_logs=�
-channels.duck_pond=�
-channels.roles=�
+channels_big_brother_logs=�
+channels_duck_pond=�
+channels_roles=�
 
 ##### << Replace the following � characters with the role IDs in your test server >> #####
 
 
 # Roles configuration
 
-roles.advent_of_code=�
-roles.announcements=�
-roles.lovefest=�
-roles.pyweek_announcements=�
-roles.revival_of_code=�
-roles.legacy_help_channels_access=�
-
-roles.contributors=�
-roles.help_cooldown=�
-roles.muted=�
-roles.partners=�
-roles.python_community=�
-roles.sprinters=�
-roles.voice_verified=�
+roles_advent_of_code=�
+roles_announcements=�
+roles_lovefest=�
+roles_pyweek_announcements=�
+roles_revival_of_code=�
+roles_legacy_help_channels_access=�
+
+roles_contributors=�
+roles_help_cooldown=�
+roles_muted=�
+roles_partners=�
+roles_python_community=�
+roles_sprinters=�
+roles_voice_verified=�
 
 ### Streaming
-roles.video=�
+roles_video=�
 
 ### Staff
-roles.admins=�
-roles.core_developers=�
-roles.code_jam_event_team=�
-roles.devops=�
-roles.domain_leads=�
-roles.events_lead=�
-roles.helpers=�
-roles.moderators=�
-roles.mod_team=�
-roles.owners=�
-roles.project_leads=�
+roles_admins=�
+roles_core_developers=�
+roles_code_jam_event_team=�
+roles_devops=�
+roles_domain_leads=�
+roles_events_lead=�
+roles_helpers=�
+roles_moderators=�
+roles_mod_team=�
+roles_owners=�
+roles_project_leads=�
 
 ### Code Jam
-roles.jammers=�
+roles_jammers=�
 
 ### Patreon
-roles.patreon_tier_1=�
-roles.patreon_tier_2=�
-roles.patreon_tier_3=�
+roles_patreon_tier_1=�
+roles_patreon_tier_2=�
+roles_patreon_tier_3=�
 
 ##### << Replace the following � characters with the category IDs in your test server >> #####
 
 # Categories configuration
 
-categories.logs=�
-categories.moderators=�
-categories.modmail=�
-categories.appeals=�
-categories.appeals2=�
-categories.voice=�
+categories_logs=�
+categories_moderators=�
+categories_modmail=�
+categories_appeals=�
+categories_appeals2=�
+categories_voice=�
 
 ### 2021 Summer Code Jam
-categories.summer_code_jam=�
+categories_summer_code_jam=�
 
 ##### << Replace the following � character with the ID of your test server >> #####
 
 # Guild configuration
-guild.id=�
-guild.invite="https://discord.gg/python"
+guild_id=�
+guild_invite="https://discord.gg/python"
 
 
 ##### << Replace the following � characters with the webhook IDs in your test server >> #####
 
 # Webhooks configuration
 
-webhooks.big_brother.id=�
-webhooks.dev_log.id=�
-webhooks.duck_pond.id=�
-webhooks.incidents.id=�
-webhooks.incidents_archive.id=�
-webhooks.python_news.id=�
+webhooks_big_brother_id=�
+webhooks_dev_log_id=�
+webhooks_duck_pond_id=�
+webhooks_incidents_id=�
+webhooks_incidents_archive_id=�
+webhooks_python_news_id=�
 
 # Big brother configuration
-big_brother.header_message_limit=15
-big_brother.log_delay=15
+big_brother_header_message_limit=15
+big_brother_log_delay=15
 
 # Code Block configuration
 
-code_block.cooldown_seconds=300
-code_block.minimum_lines=4
+code_block_cooldown_seconds=300
+code_block_minimum_lines=4
 
 
 # Colours configuration
 
-colours.blue=0x3775a8
-colours.bright_green=0x01d277
-colours.orange=0xe67e22
-colours.pink=0xcf84e0
-colours.purple=0xb734eb
-colours.soft_green=0x68c290
-colours.soft_orange=0xf9cb54
-colours.soft_red=0xcd6d6d
-colours.white=0xfffffe
-colours.yellow=0xffd241
+colours_blue=0x3775a8
+colours_bright_green=0x01d277
+colours_orange=0xe67e22
+colours_pink=0xcf84e0
+colours_purple=0xb734eb
+colours_soft_green=0x68c290
+colours_soft_orange=0xf9cb54
+colours_soft_red=0xcd6d6d
+colours_white=0xfffffe
+colours_yellow=0xffd241
 
 # Free configuration
-free.activity_timeout=600
-free.cooldown_per=60.0
-free.cooldown_rate=1
+free_activity_timeout=600
+free_cooldown_per=60.0
+free_cooldown_rate=1
 
 # Antispam configuration
-antispam.rules.attachments.interval=10
-antispam.rules.attachments.max=10
+antispam_rules_attachments_interval=10
+antispam_rules_attachments_max=10
 
-antispam.rules.burst.interval=10
-antispam.rules.burst.max=7
+antispam_rules_burst_interval=10
+antispam_rules_burst_max=7
 
-antispam.rules.chars.interval=5
-antispam.rules.chars.max=200
+antispam_rules_chars_interval=5
+antispam_rules_chars_max=200
 
-antispam.rules.discord_emojis.interval=10
-antispam.rules.discord_emojis.max=20
+antispam_rules_discord_emojis_interval=10
+antispam_rules_discord_emojis_max=20
 
-antispam.rules.duplicates.interval=10
-antispam.rules.duplicates.max=3
+antispam_rules_duplicates_interval=10
+antispam_rules_duplicates_max=3
 
-antispam.rules.links.interval=10
-antispam.rules.links.max=10
+antispam_rules_links_interval=10
+antispam_rules_links_max=10
 
-antispam.rules.mentions.interval=10
-antispam.rules.mentions.max=5
+antispam_rules_mentions_interval=10
+antispam_rules_mentions_max=5
 
-antispam.rules.newlines.interval=10
-antispam.rules.newlines.max=100
-antispam.rules.newlines.max_consecutive=10
+antispam_rules_newlines_interval=10
+antispam_rules_newlines_max=100
+antispam_rules_newlines_max_consecutive=10
 
-antispam.rules.role_mentions.interval=10
-antispam.rules.role_mentions.max=3
+antispam_rules_role_mentions_interval=10
+antispam_rules_role_mentions_max=3
 
 
-antispam.cache_size=100
-antispam.clean_offending=true
-antispam.ping_everyone=true
-antispam.punishment.remove_after=600
+antispam_cache_size=100
+antispam_clean_offending=true
+antispam_ping_everyone=true
+antispam_punishment_remove_after=600
 
 
 # Help channels configuration
-help_channels.enable=true
-help_channels.idle_minutes=30
-help_channels.deleted_idle_minutes=5
+help_channels_enable=true
+help_channels_idle_minutes=30
+help_channels_deleted_idle_minutes=5
 
 # Redirect output configuration
-redirect_output.delete_delay=15
-redirect_output.delete_invocation=true
+redirect_output_delete_delay=15
+redirect_output_delete_invocation=true
 
 # Duck pond configuration
-duckpond.threshold=7
+duckpond_threshold=7
 
 # Python news configuration
-python_news.mail_lists=
+python_news_mail_lists=
 
 # Voice gate configuration
-voice_gate.bot_message_delete_delay=10
-voice_gate.minimum_activity_blocks=3
-voice_gate.minimum_days_member=3
-voice_gate.minimum_messages=50
-voice_gate.voice_ping_delete_delay=60
+voice_gate_bot_message_delete_delay=10
+voice_gate_minimum_activity_blocks=3
+voice_gate_minimum_days_member=3
+voice_gate_minimum_messages=50
+voice_gate_voice_ping_delete_delay=60
 
 # Branding configuration
-branding.cycle_frequency=3
+branding_cycle_frequency=3
 
 # Video permisions configuration
-video_permission.default_permission_duration=5
+video_permission_default_permission_duration=5
 
 # Redis configuration
-redis.host="redis.default.svc.cluster.local"
-redis.port=6379
-redis.use_fakeredis=false  # If this is true, Bot will use fakeredis.aioredis
+redis_host="redis.default.svc.cluster.local"
+redis_port=6379
+redis_use_fakeredis=false  # If this is true, Bot will use fakeredis.aioredis
 
 # Cleaning configuration
-clean.message_limit=10000
+clean_message_limit=10000
 
 # Stats configuration
-stats.presence_update_timeout=30
-stats.statsd_host="graphite.default.svc.cluster.local"
+stats_presence_update_timeout=30
+stats_statsd_host="graphite.default.svc.cluster.local"
 
 # Cooldowns configuration
-cooldowns.tags=60
+cooldowns_tags=60
 
 # Metabase configuration
-metabase.base_url="http://metabase.default.svc.cluster.local"
-metabase.public_url="https://metabase.pythondiscord.com"
-metabase.max_session_age=20_160
+metabase_base_url="http://metabase.default.svc.cluster.local"
+metabase_public_url="https://metabase.pythondiscord.com"
+metabase_max_session_age=20_160
 
 # URLs configuration
 
-urls.snekbox_eval_api="http://snekbox.default.svc.cluster.local/eval"
-urls.snekbox_311_eval_api="http://snekbox-311.default.svc.cluster.local/eval"
+urls_snekbox_eval_api="http://snekbox.default.svc.cluster.local/eval"
+urls_snekbox_311_eval_api="http://snekbox-311.default.svc.cluster.local/eval"
 
 # Discord API
-urls.discord_api="https://discordapp.com/api/v7/"
+urls_discord_api="https://discordapp.com/api/v7/"
 
 # Misc endpoints
-urls.bot_avatar="https://raw.githubusercontent.com/python-discord/branding/main/logos/logo_circle/logo_circle.png"
-urls.github_bot_repo=https://github.com/python-discord/bot
+urls_bot_avatar="https://raw.githubusercontent.com/python-discord/branding/main/logos/logo_circle/logo_circle.png"
+urls_github_bot_repo=https://github.com/python-discord/bot
 
 # Site
-urls.site="pythondiscord.com"
-urls.site_schema="https://"
-urls.site_api="site.default.svc.cluster.local/api"
-urls.site_api_schema="http://"
+urls_site="pythondiscord.com"
+urls_site_schema="https://"
+urls_site_api="site.default.svc.cluster.local/api"
+urls_site_api_schema="http://"
 
-urls.connect_max_retries=3
-urls.connect_cooldown=5
+urls_connect_max_retries=3
+urls_connect_cooldown=5
 
 ##### << The bot shouldn't fail without these, but commands adding specific emojis won't work. >> #####
 ##### << You should at least set the trashcan. Set the incidents emojis if relevant. >> #####
@@ -451,119 +451,119 @@ urls.connect_cooldown=5
 
 
 # Emojis configuration
-emojis.badge_bug_hunter="<:bug_hunter_lvl1:743882896372269137>"
-emojis.badge_bug_hunter_level_2="<:bug_hunter_lvl2:743882896611344505>"
-emojis.badge_early_supporter="<:early_supporter:743882896909140058>"
-emojis.badge_hypesquad="<:hypesquad_events:743882896892362873>"
-emojis.badge_hypesquad_balance="<:hypesquad_balance:743882896460480625>"
-emojis.badge_hypesquad_bravery="<:hypesquad_bravery:743882896745693335>"
-emojis.badge_hypesquad_brilliance="<:hypesquad_brilliance:743882896938631248>"
-emojis.badge_partner="<:partner:748666453242413136>"
-emojis.badge_staff="<:discord_staff:743882896498098226>"
-emojis.badge_verified_bot_developer="<:verified_bot_dev:743882897299210310>"
-emojis.verified_bot="<:verified_bot:811645219220750347>"
-emojis.bot="<:bot:812712599464443914>"
-
-emojis.defcon_shutdown="<:defcondisabled:470326273952972810>"  # noqa: E704
-emojis.defcon_unshutdown="<:defconenabled:470326274213150730>"  # noqa: E704
-emojis.defcon_update="<:defconsettingsupdated:470326274082996224>"  # noqa: E704
-
-emojis.failmail="<:failmail:633660039931887616>"
-
-emojis.incident_actioned="<:incident_actioned:714221559279255583>"
-emojis.incident_investigating="<:incident_investigating:714224190928191551>"
-emojis.incident_unactioned="<:incident_unactioned:714223099645526026>"
-
-emojis.status_dnd="<:status_dnd:470326272082313216>"
-emojis.status_idle="<:status_idle:470326266625785866>"
-emojis.status_offline="<:status_offline:470326266537705472>"
-emojis.status_online="<:status_online:470326272351010816>"
-
-emojis.ducky_dave="<:ducky_dave:742058418692423772>"
-
-emojis.trashcan="<:trashcan:637136429717389331>"
-
-emojis.bullet="\u2022"
-emojis.check_mark="\u2705"
-emojis.cross_mark="\u274C"
-emojis.new="\U0001F195"
-emojis.pencil="\u270F"
-
-emojis.ok_hand=":ok_hand:"
+emojis_badge_bug_hunter="<:bug_hunter_lvl1:743882896372269137>"
+emojis_badge_bug_hunter_level_2="<:bug_hunter_lvl2:743882896611344505>"
+emojis_badge_early_supporter="<:early_supporter:743882896909140058>"
+emojis_badge_hypesquad="<:hypesquad_events:743882896892362873>"
+emojis_badge_hypesquad_balance="<:hypesquad_balance:743882896460480625>"
+emojis_badge_hypesquad_bravery="<:hypesquad_bravery:743882896745693335>"
+emojis_badge_hypesquad_brilliance="<:hypesquad_brilliance:743882896938631248>"
+emojis_badge_partner="<:partner:748666453242413136>"
+emojis_badge_staff="<:discord_staff:743882896498098226>"
+emojis_badge_verified_bot_developer="<:verified_bot_dev:743882897299210310>"
+emojis_verified_bot="<:verified_bot:811645219220750347>"
+emojis_bot="<:bot:812712599464443914>"
+
+emojis_defcon_shutdown="<:defcondisabled:470326273952972810>"  # noqa: E704
+emojis_defcon_unshutdown="<:defconenabled:470326274213150730>"  # noqa: E704
+emojis_defcon_update="<:defconsettingsupdated:470326274082996224>"  # noqa: E704
+
+emojis_failmail="<:failmail:633660039931887616>"
+
+emojis_incident_actioned="<:incident_actioned:714221559279255583>"
+emojis_incident_investigating="<:incident_investigating:714224190928191551>"
+emojis_incident_unactioned="<:incident_unactioned:714223099645526026>"
+
+emojis_status_dnd="<:status_dnd:470326272082313216>"
+emojis_status_idle="<:status_idle:470326266625785866>"
+emojis_status_offline="<:status_offline:470326266537705472>"
+emojis_status_online="<:status_online:470326272351010816>"
+
+emojis_ducky_dave="<:ducky_dave:742058418692423772>"
+
+emojis_trashcan="<:trashcan:637136429717389331>"
+
+emojis_bullet="\u2022"
+emojis_check_mark="\u2705"
+emojis_cross_mark="\u274C"
+emojis_new="\U0001F195"
+emojis_pencil="\u270F"
+
+emojis_ok_hand=":ok_hand:"
 
 # Icons configuration
 
-icons.crown_blurple="https://cdn.discordapp.com/emojis/469964153289965568.png"
-icons.crown_green="https://cdn.discordapp.com/emojis/469964154719961088.png"
-icons.crown_red="https://cdn.discordapp.com/emojis/469964154879344640.png"
+icons_crown_blurple="https://cdn.discordapp.com/emojis/469964153289965568.png"
+icons_crown_green="https://cdn.discordapp.com/emojis/469964154719961088.png"
+icons_crown_red="https://cdn.discordapp.com/emojis/469964154879344640.png"
 
-icons.defcon_denied="https://cdn.discordapp.com/emojis/472475292078964738.png"
-icons.defcon_shutdown="https://cdn.discordapp.com/emojis/470326273952972810.png"
-icons.defcon_unshutdown="https://cdn.discordapp.com/emojis/470326274213150730.png"
-icons.defcon_update="https://cdn.discordapp.com/emojis/472472638342561793.png"
+icons_defcon_denied="https://cdn.discordapp.com/emojis/472475292078964738.png"
+icons_defcon_shutdown="https://cdn.discordapp.com/emojis/470326273952972810.png"
+icons_defcon_unshutdown="https://cdn.discordapp.com/emojis/470326274213150730.png"
+icons_defcon_update="https://cdn.discordapp.com/emojis/472472638342561793.png"
 
-icons.filtering="https://cdn.discordapp.com/emojis/472472638594482195.png"
+icons_filtering="https://cdn.discordapp.com/emojis/472472638594482195.png"
 
-icons.green_checkmark="https://raw.githubusercontent.com/python-discord/branding/main/icons/checkmark/green-checkmark-dist.png"
-icons.green_questionmark="https://raw.githubusercontent.com/python-discord/branding/main/icons/checkmark/green-question-mark-dist.png"
+icons_green_checkmark="https://raw.githubusercontent.com/python-discord/branding/main/icons/checkmark/green-checkmark-dist.png"
+icons_green_questionmark="https://raw.githubusercontent.com/python-discord/branding/main/icons/checkmark/green-question-mark-dist.png"
 
-icons.guild_update="https://cdn.discordapp.com/emojis/469954765141442561.png"
+icons_guild_update="https://cdn.discordapp.com/emojis/469954765141442561.png"
 
-icons.hash_blurple="https://cdn.discordapp.com/emojis/469950142942806017.png"
-icons.hash_green="https://cdn.discordapp.com/emojis/469950144918585344.png"
-icons.hash_red="https://cdn.discordapp.com/emojis/469950145413251072.png"
+icons_hash_blurple="https://cdn.discordapp.com/emojis/469950142942806017.png"
+icons_hash_green="https://cdn.discordapp.com/emojis/469950144918585344.png"
+icons_hash_red="https://cdn.discordapp.com/emojis/469950145413251072.png"
 
-icons.message_bulk_delete="https://cdn.discordapp.com/emojis/469952898994929668.png"
-icons.message_delete="https://cdn.discordapp.com/emojis/472472641320648704.png"
-icons.message_edit="https://cdn.discordapp.com/emojis/472472638976163870.png"
+icons_message_bulk_delete="https://cdn.discordapp.com/emojis/469952898994929668.png"
+icons_message_delete="https://cdn.discordapp.com/emojis/472472641320648704.png"
+icons_message_edit="https://cdn.discordapp.com/emojis/472472638976163870.png"
 
-icons.pencil="https://cdn.discordapp.com/emojis/470326272401211415.png"
+icons_pencil="https://cdn.discordapp.com/emojis/470326272401211415.png"
 
-icons.questionmark="https://cdn.discordapp.com/emojis/512367613339369475.png"
+icons_questionmark="https://cdn.discordapp.com/emojis/512367613339369475.png"
 
-icons.remind_blurple="https://cdn.discordapp.com/emojis/477907609215827968.png"
-icons.remind_green="https://cdn.discordapp.com/emojis/477907607785570310.png"
-icons.remind_red="https://cdn.discordapp.com/emojis/477907608057937930.png"
+icons_remind_blurple="https://cdn.discordapp.com/emojis/477907609215827968.png"
+icons_remind_green="https://cdn.discordapp.com/emojis/477907607785570310.png"
+icons_remind_red="https://cdn.discordapp.com/emojis/477907608057937930.png"
 
-icons.sign_in="https://cdn.discordapp.com/emojis/469952898181234698.png"
-icons.sign_out="https://cdn.discordapp.com/emojis/469952898089091082.png"
+icons_sign_in="https://cdn.discordapp.com/emojis/469952898181234698.png"
+icons_sign_out="https://cdn.discordapp.com/emojis/469952898089091082.png"
 
-icons.superstarify="https://cdn.discordapp.com/emojis/636288153044516874.png"
-icons.unsuperstarify="https://cdn.discordapp.com/emojis/636288201258172446.png"
+icons_superstarify="https://cdn.discordapp.com/emojis/636288153044516874.png"
+icons_unsuperstarify="https://cdn.discordapp.com/emojis/636288201258172446.png"
 
-icons.token_removed="https://cdn.discordapp.com/emojis/470326273298792469.png"
+icons_token_removed="https://cdn.discordapp.com/emojis/470326273298792469.png"
 
-icons.user_ban="https://cdn.discordapp.com/emojis/469952898026045441.png"
-icons.user_mute="https://cdn.discordapp.com/emojis/472472640100106250.png"
-icons.user_unban="https://cdn.discordapp.com/emojis/469952898692808704.png"
-icons.user_unmute="https://cdn.discordapp.com/emojis/472472639206719508.png"
-icons.user_update="https://cdn.discordapp.com/emojis/469952898684551168.png"
-icons.user_verified="https://cdn.discordapp.com/emojis/470326274519334936.png"
-icons.user_warn="https://cdn.discordapp.com/emojis/470326274238447633.png"
+icons_user_ban="https://cdn.discordapp.com/emojis/469952898026045441.png"
+icons_user_mute="https://cdn.discordapp.com/emojis/472472640100106250.png"
+icons_user_unban="https://cdn.discordapp.com/emojis/469952898692808704.png"
+icons_user_unmute="https://cdn.discordapp.com/emojis/472472639206719508.png"
+icons_user_update="https://cdn.discordapp.com/emojis/469952898684551168.png"
+icons_user_verified="https://cdn.discordapp.com/emojis/470326274519334936.png"
+icons_user_warn="https://cdn.discordapp.com/emojis/470326274238447633.png"
 
-icons.voice_state_blue="https://cdn.discordapp.com/emojis/656899769662439456.png"
-icons.voice_state_green="https://cdn.discordapp.com/emojis/656899770094452754.png"
-icons.voice_state_red="https://cdn.discordapp.com/emojis/656899769905709076.png"
+icons_voice_state_blue="https://cdn.discordapp.com/emojis/656899769662439456.png"
+icons_voice_state_green="https://cdn.discordapp.com/emojis/656899770094452754.png"
+icons_voice_state_red="https://cdn.discordapp.com/emojis/656899769905709076.png"
 
 ##### << Optional - If you don't care about the filtering, help channel and py-news cogs, ignore the rest of this file >> #####
 
 # Filters configuration
-filters.filter_domains=true
-filters.filter_everyone_ping=true
-filters.filter_invites=true
-filters.filter_zalgo=false
-filters.watch_regex=true
-filters.watch_rich_embeds=true
+filters_filter_domains=true
+filters_filter_everyone_ping=true
+filters_filter_invites=true
+filters_filter_zalgo=false
+filters_watch_regex=true
+filters_watch_rich_embeds=true
 
 ### Notifications are not expected for "watchlist" type filters
 
-filters.notify_user_domains=false
-filters.notify_user_everyone_ping=true
-filters.notify_user_invites=true
-filters.notify_user_zalgo=false
+filters_notify_user_domains=false
+filters_notify_user_everyone_ping=true
+filters_notify_user_invites=true
+filters_notify_user_zalgo=false
 
-filters.offensive_msg_delete_days=7
-filters.ping_everyone=true
+filters_offensive_msg_delete_days=7
+filters_ping_everyone=true
 
   
   
@@ -573,17 +573,17 @@ filters.ping_everyone=true If you don't wish to use the provided `env.server` above, the main values that need overriding are **all** the ones prefixed with: -* `guild.` -* `categories.` -* `channels.` -* `roles.` -* `webhooks.` -* `emojis.` +* `guild_` +* `categories_` +* `channels_` +* `roles_` +* `webhooks_` +* `emojis_` Additionally: -* At this stage, set `redis.use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). -* Set `urls.site_schema` and `urls.site_api_schema` to `"http://"`. +* At this stage, set `redis_use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). +* Set `urls_site_schema` and `urls_site_api_schema` to `"http://"`. We understand this is tedious which is why we **recommend** using the [automatic configuration setup](#automatic-configuration) @@ -606,7 +606,7 @@ We understand this is tedious which is why we **recommend** using the [automatic ##### .env The second file you need to create is the one containing the environment variables, and needs to be named `.env`. -Inside, add the line `BOT.TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token. +Inside, add the line `BOT_TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token. **Note**: The `.env` is and should remain ignored by git, otherwise you risk pushing sensitive information. @@ -627,7 +627,7 @@ Once the previous steps are done, all that is left is to: 1. Create a new channel 2. Choose the `Forum` type 3. [Copy its ID](../obtaining-discord-ids#channel-id) -4. Add the following line to the `.env.server` file: `channels.python_help={newly_created_forum_channel_id}` +4. Add the following line to the `.env.server` file: `channels_python_help={newly_created_forum_channel_id}` ### Run it! @@ -656,10 +656,10 @@ You are now almost ready to run the Python bot. The simplest way to do so is wit In your `.env.server` file: -* Set `urls.site` to `"web:8000"`. +* Set `urls_site` to `"web:8000"`. * If you wish to work with snekbox set the following: - * `urls.snekbox_eval_api` to `"http://snekbox:8060/eval"` - * `urls.snekbox_311_eval_api` to `"http://snekbox-311:8060/eval"`. + * `urls_snekbox_eval_api` to `"http://snekbox:8060/eval"` + * `urls_snekbox_311_eval_api` to `"http://snekbox-311:8060/eval"`. Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker-compose up`. @@ -672,9 +672,9 @@ Your bot is now running, but this method makes debugging with an IDE a fairly in #### With the Bot Running Locally The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. -* Append the following line to your `.env` file: `API_KEYS.SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `.env.server` file, set `urls.site` to `"localhost:8000"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. -* To work with snekbox, set `urls.snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls.snekbox_311_eval_api` to `"http://localhost:8065/eval"` +* Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. +* In your `.env.server` file, set `urls_site` to `"localhost:8000"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* To work with snekbox, set `urls_snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls_snekbox_311_eval_api` to `"http://localhost:8065/eval"` You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: @@ -760,15 +760,15 @@ We are always open to more statistics so add as many as you can! --- ### Optional: Working with Redis -In [Configure the Bot](#envserver) you were asked to set `redis.use_fakeredis` to `true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. +In [Configure the Bot](#envserver) you were asked to set `redis_use_fakeredis` to `true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. If you are working on a feature that relies on Redis, you will need to enable Redis to make sure persistency is achieved for the feature across restarts. The first step towards that is going to `.env.server` and setting `redis.use_fakeredis` to `false`. #### Starting Redis in Docker (Recommended) -If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis.host` to `redis`, and if you're running it on the host set it to `localhost`. Set `bot.redis.password` to `""`. +If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis_host` to `redis`, and if you're running it on the host set it to `localhost`. Set `redis_password` to `""`. #### Starting Redis Using Other Methods -You can run your own instance of Redis, but in that case you will need to correctly set `redis.host` and `redis.port`, and the `redis.password` value in `constants.py` should not be overridden. Then, enter the `.env` file, and set `REDIS.PASSWORD` to whatever password you set. +You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port`, and the `redis_password` value in `constants.py` should not be overridden. Then, enter the `.env` file, and set `REDIS_PASSWORD` to whatever password you set. --- @@ -806,17 +806,17 @@ The following is a list of all available environment variables used by the bot: | Variable | Required | Description | |----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `BOT.TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | -| `GUILD.ID` | When using the bootstrapping script | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | -| `API_KEYS.SITE_API` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | -| `BOT.SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | -| `BOT.TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | +| `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | +| `GUILD_ID` | When using the bootstrapping script | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | +| `API_KEYS_SITE_API` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | +| `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | +| `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | | `DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. | -| `REDIS.PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | +| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | | `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | -| `API_KEYS.GITHUB` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. | -| `METABASE.USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | -| `METABASE.PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. | +| `API_KEYS_GITHUB` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. | +| `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | +| `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. | --- -- cgit v1.2.3 From b804ef7f47a87ee3a80a7471e3d60107f5bda8fd Mon Sep 17 00:00:00 2001 From: shtlrs Date: Wed, 8 Mar 2023 12:39:42 +0100 Subject: make GUILD_ID always required --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 07881543..38f87c91 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -807,7 +807,7 @@ The following is a list of all available environment variables used by the bot: | Variable | Required | Description | |----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | -| `GUILD_ID` | When using the bootstrapping script | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | +| `GUILD_ID` | Always | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | | `API_KEYS_SITE_API` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | | `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | | `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | -- cgit v1.2.3 From 21ed6cdfbde922b4340e78ac1c55e3dbf4f6aa85 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Wed, 8 Mar 2023 12:48:14 +0100 Subject: clarify where redis values should be overriden --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 38f87c91..e8d09a09 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -768,7 +768,8 @@ If you are working on a feature that relies on Redis, you will need to enable Re If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis_host` to `redis`, and if you're running it on the host set it to `localhost`. Set `redis_password` to `""`. #### Starting Redis Using Other Methods -You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port`, and the `redis_password` value in `constants.py` should not be overridden. Then, enter the `.env` file, and set `REDIS_PASSWORD` to whatever password you set. +You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port` in your `.env.server` file and the `REDIS_PASSWORD` in the `.env` file. +**Note**: The previously mentioned variables **SHOULD NOT** be overriden or changed in `constants.py` --- -- cgit v1.2.3 From 781450f8bb76bc7a302a4473f646b2b06a207054 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Thu, 9 Mar 2023 16:33:34 +0100 Subject: update url of site_api --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index e8d09a09..df29e542 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -673,7 +673,7 @@ Your bot is now running, but this method makes debugging with an IDE a fairly in The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. * Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `.env.server` file, set `urls_site` to `"localhost:8000"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* In your `.env.server` file, set `urls_site_api` to `"localhost:8000/api"`. If you wish to keep using `web:8000`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. * To work with snekbox, set `urls_snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls_snekbox_311_eval_api` to `"http://localhost:8065/eval"` You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: -- cgit v1.2.3 From 57c2cbdcd9b5a31b37a6b469f169b223c283919f Mon Sep 17 00:00:00 2001 From: shtlrs Date: Fri, 10 Mar 2023 10:23:55 +0100 Subject: apply Zig's suggestions --- .../guides/pydis-guides/contributing/bot.md | 81 +++++++++++----------- 1 file changed, 42 insertions(+), 39 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index df29e542..da9e1be5 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -16,7 +16,7 @@ The Python bot is tightly coupled with the Python Discord server, so to have a f It's possible to set the bot to use a single channel for all cogs, but that will cause extreme spam and will be difficult to work with. You can start your own server and set up channels as you see fit, but for your convenience we have a template for a development server you can use: [https://discord.new/zmHtscpYN9E3](https://discord.new/zmHtscpYN9E3). -Keep in mind that this is not an exact mirror of the Python server, but a reduced version for testing purposes. +The server will only contain the channels that are needed by the bot. --- ### Set Up a Bot Account @@ -35,18 +35,20 @@ If your bot fails to start with a `PrivilegedIntentsRequired` exception, this in --- ### Configure the Bot -You now have both the bot's code and a server to run it on. It's time you to connect the two by changing the bot's configurations. +You now have both the bot's code and a server to run it on. It's time for you to connect the two by changing the bot's configurations. This can be done either automatically or manually, and we'll be detailing the steps for both. +**Note**: Skip this step if you would like to configure the bot manually, but that will require more work. + #### Automatic configuration -To make setup much easier, there is a file called `botstrap.py` that represents a script to bootstrap the configuration for you and help you get started immediately -without having to spend much time copying ids from your newly created server into your configuration file. +To make setup much easier, the script in `botstrap.py` bootstraps the configuration for you and helps you get started immediately, +without having to spend much time copying IDs from your newly created server into your configuration file. -**Note**: This phase can be skipped and done manually, but would require extra manual work. +**Note**: The script will also work on existing servers as long as the channel names are the same as the one in Python Discord. ##### 1. Script setup ##### 1.1. Environment variables -You will need to create a file called `.env` which will contain two required values for the script to work: `BOT_TOKEN` and `GUILD_ID` +You will need to create a file called `.env`, which will contain two required values: `BOT_TOKEN` and `GUILD_ID`. Inside, add the following two lines: @@ -54,37 +56,37 @@ Inside, add the following two lines: BOT_TOKEN=YourDiscordBotTokenHere GUILD_ID=YourDiscordTestServerIdHere ``` -See [here](../creating-bot-account) for help with obtaining the bot token and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's id +See [here](../creating-bot-account) for help with obtaining the bot token, and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's ID. **Note**: The `.env` is and should remain ignored by git, otherwise you risk pushing sensitive information. ##### 1.2 Setting up the script environment The bootstrapping script is a Python program so you will need a compatible Python version and the necessary dependencies installed, which are all detailed here: -1. Make sure you follow steps `1` and `2` [here](#setting-up-a-development-environment) -2. [Install the `config-bootstrap` dependency group](../installing-project-dependencies#installing-specific-dependency-groups). +1. Make sure you have [Python 3.10](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. +2. [Install Poetry](https://github.com/python-poetry/poetry#installation). +3. [Install the dependencies](../installing-project-dependencies). #### 2. Running the script Once the script setup phase is complete, all that is left is to run it. -To do this, you'll simply need to run the `configure` poetry task like this +To do this, you'll simply need to run the `configure` poetry task: ```shell $ poetry run task configure ``` -or, without poetry and from the root directory +Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory. +This file will contain the extracted IDs from your server which are necessary for your bot to run. -```shell -python3 -m botstrap -``` +**Congratulations**, you have finished the configuration and can now [run your bot](#run-it). -Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory. -This file will contain the extracted ids from your newly created server which are necessary for your bot to run. -**Congratulations**, you have finished the configuration & can now start [running your bot](#run-it) #### Manual configuration + +**Note**: Skip this part if you used the automatic configuration. + ##### .env.server All server configuration values are saved in a file called `.env.server`, which needs to be at the root directory of the cloned code. This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. @@ -96,8 +98,7 @@ otherwise you'll need to create it manually. If you decide to set the configuration values manually, you will **only** need to set the values for the channels, roles, categories, etc. that are used by the component you are developing. - -Let's take an example where we suppose we'll only be testing a feature that needs the `announcements` channel. +For example, if we're testing a feature that only needs the `announcements` channel: `constants.py` @@ -571,7 +572,7 @@ filters_ping_everyone=true
-If you don't wish to use the provided `env.server` above, the main values that need overriding are **all** the ones prefixed with: +If you wish to set all values in your `env.server` for your testing server, you need to set **all** the ones prefixed with: * `guild_` * `categories_` @@ -585,7 +586,7 @@ Additionally: * At this stage, set `redis_use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). * Set `urls_site_schema` and `urls_site_api_schema` to `"http://"`. -We understand this is tedious which is why we **recommend** using the [automatic configuration setup](#automatic-configuration) +We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](#automatic-configuration)
-
-
- - If you wish to set all values in your `env.server` for your testing server, you need to set **all** the ones prefixed with: * `guild_` -- cgit v1.2.3 From e207147d0d58af2ef6f75586f837ee3c96b8b7a4 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Fri, 10 Mar 2023 22:50:49 +0100 Subject: define .env & .env.server then display their usage --- .../guides/pydis-guides/contributing/bot.md | 37 ++++++++++++++-------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 60e5f9b1..3fbec090 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -39,7 +39,23 @@ If your bot fails to start with a `PrivilegedIntentsRequired` exception, this in You now have both the bot's code and a server to run it on. It's time for you to connect the two by changing the bot's configurations. This can be done either automatically or manually, and we'll be detailing the steps for both. -**Note**: Skip this step if you would like to configure the bot manually, but that will require more work. +One thing to know is that the bot relies on precisely **two** configuration files to work + +#### .env.server +All server configuration values are saved in this file, which needs to be at the root directory of the cloned code. +This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. +It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify. + +This file will be created for you automatically if you decide to go with [automatic configuration](#automatic-configuration), +otherwise a lot of it has to be done by hand which will be detailed in the [manual configuration](#manual-configuration) section. + +#### .env +This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`, and other configurations related to external services that the bot might use, +such as: `USE_METRICITY`, etc. which are all not necessarily coupled to things that can be fetched from your server, with the only exception to `GUILD_ID`. + +**Notes**: +* Both `.env` and `.env.server` are and should remain ignored by git, otherwise you risk pushing sensitive information. +* Skip the following step if you would like to configure the bot manually, but that will require more work. #### Automatic configuration To make setup much easier, the script in `botstrap.py` bootstraps the configuration for you and helps you get started immediately, @@ -59,7 +75,7 @@ GUILD_ID=YourDiscordTestServerIdHere ``` See [here](../creating-bot-account) for help with obtaining the bot token, and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's ID. -**Note**: The `.env` is and should remain ignored by git, otherwise you risk pushing sensitive information. + ##### 1.2 Setting up the script environment The bootstrapping script is a Python program so you will need a compatible Python version and the necessary dependencies installed, which are all detailed here: @@ -83,20 +99,15 @@ This file will contain the extracted IDs from your server which are necessary fo **Congratulations**, you have finished the configuration and can now [run your bot](#run-it). - #### Manual configuration **Note**: Skip this part if you used the automatic configuration. ##### .env.server -All server configuration values are saved in a file called `.env.server`, which needs to be at the root directory of the cloned code. -This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. -It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify. +Reading this means that you're ready for a bit of manual labour. +If for some reason you've missed the automatic server setup section, you can read about it [here](#automatic-configuration) -If you decided to use the bootstrapping script, you'll find that this file has already been created (which we recommend), -otherwise you'll need to create it manually. - -If you decide to set the configuration values manually, you will **only** need to set the values for the channels, roles, categories, etc. +To configure the bot manually, you will **only** need to set the values for the channels, roles, categories, etc. that are used by the component you are developing. For example, if we're testing a feature that only needs the `announcements` channel: @@ -120,9 +131,11 @@ class _Channels(EnvConfig): Channels = _Channels() ``` -`.env.server` file +`.env.server` file: ```text +# .env.server + channels_announcements=1077875228002234398 ``` @@ -181,8 +194,6 @@ We understand this is tedious which is why we **heavily recommend** using the [a The second file you need to create is the one containing the environment variables, and needs to be named `.env`. Inside, add the line `BOT_TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token. -**Note**: The `.env` is and should remain ignored by git, otherwise you risk pushing sensitive information. - --- -- cgit v1.2.3 From becd1d6357abb35963898e2f78e55225da2e64fc Mon Sep 17 00:00:00 2001 From: shtlrs Date: Fri, 10 Mar 2023 22:55:11 +0100 Subject: appease linter --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 3fbec090..ccf94046 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -53,7 +53,7 @@ otherwise a lot of it has to be done by hand which will be detailed in the [manu This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`, and other configurations related to external services that the bot might use, such as: `USE_METRICITY`, etc. which are all not necessarily coupled to things that can be fetched from your server, with the only exception to `GUILD_ID`. -**Notes**: +**Notes**: * Both `.env` and `.env.server` are and should remain ignored by git, otherwise you risk pushing sensitive information. * Skip the following step if you would like to configure the bot manually, but that will require more work. -- cgit v1.2.3 From ab5f1d522455a4c2d0d0f080dd1ecc47a9c68ef2 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sat, 11 Mar 2023 09:33:44 +0100 Subject: update site urls one last time --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index ccf94046..18797ab5 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -50,8 +50,8 @@ This file will be created for you automatically if you decide to go with [automa otherwise a lot of it has to be done by hand which will be detailed in the [manual configuration](#manual-configuration) section. #### .env -This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`, and other configurations related to external services that the bot might use, -such as: `USE_METRICITY`, etc. which are all not necessarily coupled to things that can be fetched from your server, with the only exception to `GUILD_ID`. +This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`. +It will also contain configurations related to external services the bot might use such as `USE_METRICITY`, which are unrelated your server, with the only exception being `GUILD_ID`. **Notes**: * Both `.env` and `.env.server` are and should remain ignored by git, otherwise you risk pushing sensitive information. @@ -240,7 +240,7 @@ Your bot is now running, but this method makes debugging with an IDE a fairly in The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. * Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `.env.server` file, set `urls_site` to `"localhost:8000"` and `urls_site_api` to `"localhost:8000/api"`. If you wish to keep using `web:8000/api` and `web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* In your `.env.server` file, set `urls_site` to `"localhost:8000"` and `urls_site_api` to `"localhost:8000/api"`. If you wish to keep using `web:8000` and `web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. * To work with snekbox, set `urls_snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls_snekbox_311_eval_api` to `"http://localhost:8065/eval"` You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: -- cgit v1.2.3 From 22a66ebe50f8e52d5108ea629a34415fdc20cb6b Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sat, 11 Mar 2023 22:27:05 +0100 Subject: delete dependency group orphan guide --- .../installing-project-dependencies.md | 24 ---------------------- 1 file changed, 24 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md index 9ad24034..26d6de30 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/installing-project-dependencies.md @@ -39,27 +39,3 @@ $ poetry run task precommit ![PyCharm Poetry Environment](/static/images/content/contributing/pycharm_poetry.png)
6. PyCharm will automatically install the packages required into a virtual environment.
![PyCharm Project Interpreter](/static/images/content/contributing/pycharm_poetry_success.png) - - -## Installing specific dependency groups - -In some cases, like when you'll be using the configuration bootstrapping script, you might need to install extra dependencies that are -not necessary for the bot project to function. -These dependencies are generally put in a separate optional group likewise: - -```text -[tool.poetry.group.group-name] -... -[tool.poetry.group.group-name.dependencies] -pytest = "^6.0.0" -pytest-mock = "*" -``` - -To install them, you simply need to run the following command ---- - -```shell -$ poetry install --only {{group-name}} -``` - ---- -- cgit v1.2.3 From 2ce0b6936e93271e1de7f772686fb5adff7bb770 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Mon, 13 Mar 2023 12:36:39 +0100 Subject: mention `BOT_PREFIX` in the appendix --- .../guides/pydis-guides/contributing/bot.md | 30 ++++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 18797ab5..795bf58f 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -51,9 +51,10 @@ otherwise a lot of it has to be done by hand which will be detailed in the [manu #### .env This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`. -It will also contain configurations related to external services the bot might use such as `USE_METRICITY`, which are unrelated your server, with the only exception being `GUILD_ID`. +It will also contain configurations related to external services the bot might use such as `USE_METRICITY`, which are unrelated to your server, with the only exception being `GUILD_ID`. **Notes**: + * Both `.env` and `.env.server` are and should remain ignored by git, otherwise you risk pushing sensitive information. * Skip the following step if you would like to configure the bot manually, but that will require more work. @@ -391,19 +392,20 @@ If you find any bugs in the bot or would like to request a feature, feel free to ### Appendix: Full ENV File Options The following is a list of all available environment variables used by the bot: -| Variable | Required | Description | -|----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | -| `GUILD_ID` | Always | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | -| `API_KEYS_SITE_API` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | -| `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | -| `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | -| `DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. | -| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | -| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | -| `API_KEYS_GITHUB` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. | -| `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | -| `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. | +| Variable | Required | Description | +|----------------------|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `BOT_TOKEN` | Always | Your Discord bot account's token (see [Set Up a Bot Account](#set-up-a-bot-account)). | +| `GUILD_ID` | Always | Your Discord test server's id (see [Set Up a Test Server](#set-up-a-test-server)). | +| `BOT_PREFIX` | When you wish to use a prefix different than "!" | Your Discord bot command's prefix. | +| `API_KEYS_SITE_API` | When running bot without Docker | Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below. | +| `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | +| `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | +| `DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. | +| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | +| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | +| `API_KEYS_GITHUB` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. | +| `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | +| `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. | --- -- cgit v1.2.3 From 204f7c10ba950ef3758b0eb1b855ae36631c6002 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Mon, 13 Mar 2023 13:18:39 +0100 Subject: add hyperlink to open an issue --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 795bf58f..04b78f1c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -385,7 +385,7 @@ If you want to run the bot locally, you can run `docker-compose up metricity` in ### Issues? If you have any issues with setting up the bot, come discuss it with us on the [#dev-contrib](https://discord.gg/2h3qBv8Xaa) channel on our server. -If you find any bugs in the bot or would like to request a feature, feel free to open an issue on the repository. +If you find any bugs in the bot or would like to request a feature, feel free to [open an issue](https://github.com/python-discord/bot/issues/new/choose) on the repository. --- -- cgit v1.2.3 From 799efdfd58f028f4e3eb85649609acacd5ce6e51 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Tue, 21 Mar 2023 17:55:32 +0100 Subject: Update docs for upstream documentation change (#905) Fixes #900. --- .../guides/pydis-guides/contributing/creating-bot-account.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/creating-bot-account.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/creating-bot-account.md index ee38baa3..51da3f34 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/creating-bot-account.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/creating-bot-account.md @@ -9,9 +9,9 @@ icon: fab fa-discord 4. Change your bot's `Public Bot` setting off so only you can invite it, save, and then get your **Bot Token** with the `Copy` button. > **Note:** **DO NOT** post your bot token anywhere public. If you do it can and will be compromised. 5. Save your **Bot Token** somewhere safe to use in the project settings later. -6. In the `General Information` tab, grab the **Client ID**. -7. Replace `` in the following URL and visit it in the browser to invite your bot to your new test server. +6. In the `General Information` tab, grab the **Application ID**. +7. Replace `` in the following URL and visit it in the browser to invite your bot to your new test server. ```plaintext -https://discordapp.com/api/oauth2/authorize?client_id=&permissions=8&scope=bot +https://discordapp.com/api/oauth2/authorize?client_id=&permissions=8&scope=bot ``` Optionally, you can generate your own invite url in the `OAuth` tab, after selecting `bot` as the scope. -- cgit v1.2.3 From 2ce0a634254f697190bca782ef641a32deb19c03 Mon Sep 17 00:00:00 2001 From: Diabolical5777 <84365102+Diabolical5777@users.noreply.github.com> Date: Wed, 22 Mar 2023 00:53:17 +0400 Subject: Subclassing context.md (#703) Co-authored-by: Johannes Christ Co-authored-by: Amrou Bellalouna Co-authored-by: Bluenix Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> Co-authored-by: wookie184 --- .../python-guides/discordpy-subclassing-context.md | 129 +++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md b/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md new file mode 100644 index 00000000..b77cb0f9 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md @@ -0,0 +1,129 @@ +--- +title: Subclassing Context in discord.py +description: "Subclassing the default `commands.Context` class to add more functionability and customizability." +--- + +Start by reading the guide on [subclassing the `Bot` class](./subclassing_bot.md). A subclass of Bot has to be used to +inject your custom context subclass into discord.py. + +## Overview + +The way this works is by creating a subclass of discord.py's [`Context` class](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) +adding whatever functionality you wish. Usually this is done by adding custom methods or properties, so that you don't need to +copy it around or awkwardly import it elsewhere. + +This guide will show you how to add a `prompt()` method to the context and how to use it in a command. + +## Example subclass and code + +The first part - of course - is creating the actual context subclass. This is done similarly to creating a bot +subclass, it will look like this: + +```python +import asyncio +from typing import Optional + +from discord import RawReactionActionEvent +from discord.ext import commands + + +class CustomContext(commands.Context): + async def prompt( + self, + message: str, + *, + timeout=30.0, + delete_after=True + ) -> Optional[bool]: + """Prompt the author with an interactive confirmation message. + + This method will send the `message` content, and wait for max `timeout` seconds + (default is `30`) for the author to react to the message. + + If `delete_after` is `True`, the message will be deleted before returning a + True, False, or None indicating whether the author confirmed, denied, + or didn't interact with the message. + """ + msg = await self.send(message) + + for reaction in ('✅', '❌'): + await msg.add_reaction(reaction) + + confirmation = None + + # This function is a closure because it is defined inside of another + # function. This allows the function to access the self and msg + # variables defined above. + + def check(payload: RawReactionActionEvent): + # 'nonlocal' works almost like 'global' except for functions inside of + # functions. This means that when 'confirmation' is changed, that will + # apply to the variable above + nonlocal confirmation + + if payload.message_id != msg.id or payload.user_id != self.author.id: + return False + + emoji = str(payload.emoji) + + if emoji == '✅': + confirmation = True + return True + + elif emoji == '❌': + confirmation = False + return True + + # This means that it was neither of the two emojis added, so the author + # added some other unrelated reaction. + return False + + try: + await self.bot.wait_for('raw_reaction_add', check=check, timeout=timeout) + except asyncio.TimeoutError: + # The 'confirmation' variable is still None in this case + pass + + if delete_after: + await msg.delete() + + return confirmation +``` + +After creating your context subclass, you need to override the `get_context()` method on your +Bot class and change the default of the `cls` parameter to this subclass: + +```python +from discord.ext import commands + + +class CustomBot(commands.Bot): + async def get_context(self, message, *, cls=CustomContext): # From the above codeblock + return await super().get_context(message, cls=cls) +``` + +Now that discord.py is using your custom context, you can use it in a command. For example: + +```python +import discord +from discord.ext import commands + +# Enable the message intent so that we get message content. This is needed for +# the commands we define below +intents = discord.Intents.default() +intents.message_content = True + + +# Replace '...' with any additional arguments for the bot +bot = CustomBot(intents=intents, ...) + + +@bot.command() +async def massban(ctx: CustomContext, members: commands.Greedy[discord.Member]): + prompt = await ctx.prompt(f"Are you sure you want to ban {len(members)} members?") + if not prompt: + # Return if the author cancelled, or didn't react in time + return + + ... # Perform the mass-ban, knowing the author has confirmed this action +``` -- cgit v1.2.3 From d502ec4296e364dcbec86e2ab79c8980d35149a1 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sat, 1 Apr 2023 21:20:37 +0200 Subject: lose all references to site and replace with the suitable changes --- .../resources/guides/pydis-guides/contributing/bot.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 04b78f1c..6f2c7e74 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -170,7 +170,6 @@ If you wish to set all values in your `env.server` for your testing server, you Additionally: * At this stage, set `redis_use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). -* Set `urls_site_schema` and `urls_site_api_schema` to `"http://"`. We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](#automatic-configuration) @@ -224,11 +223,12 @@ You are now almost ready to run the Python bot. The simplest way to do so is wit In your `.env.server` file: -* Set `urls_site` to `"web:8000"` and `urls_site_api` to `"web:8000/api"`. -* If you wish to work with snekbox set the following: +* If you wish to work with snekbox, set the following: * `urls_snekbox_eval_api` to `"http://snekbox:8060/eval"` * `urls_snekbox_311_eval_api` to `"http://snekbox-311:8060/eval"`. + + Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker-compose up`. If working with snekbox you can run `docker-compose --profile 3.10 up` to also start up a 3.10 snekbox container, in addition to the default 3.11 container! @@ -241,9 +241,10 @@ Your bot is now running, but this method makes debugging with an IDE a fairly in The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. * Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `.env.server` file, set `urls_site` to `"localhost:8000"` and `urls_site_api` to `"localhost:8000/api"`. If you wish to keep using `web:8000` and `web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* In your `.env.server` file, set `urls_site_api` to `"http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. * To work with snekbox, set `urls_snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls_snekbox_311_eval_api` to `"http://localhost:8065/eval"` + You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: * `docker-compose up web` to start the site container. This is required. @@ -328,6 +329,9 @@ We are always open to more statistics so add as many as you can! --- ### Optional: Working with the help forum + +**Note**: This is only required when you're not configuring the bot [automatically](#automatic-configuration) + If you will be working on a feature that includes the python help forum, you will need to use `Forum Channels`. Forum channels cannot be included in a template, which is why this needs to be done by hand for the time being. @@ -382,6 +386,12 @@ If you want to run the bot locally, you can run `docker-compose up metricity` in --- +### Optional: Working with bot moderation logs +To be able to view moderation-related logs published by the bot to site, you will need to set `urls_site_logs_view` to `http://localhost:8000/staff/bot/logs` in your `.env.server`. +This will work in both Docker and locally. + +--- + ### Issues? If you have any issues with setting up the bot, come discuss it with us on the [#dev-contrib](https://discord.gg/2h3qBv8Xaa) channel on our server. -- cgit v1.2.3 From 0aea52cc5f1e480424d0056c7825f914f7baaa71 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sat, 1 Apr 2023 21:30:41 +0200 Subject: apply wookie's suggestion to setting variables apply wookie's suggestion to setting variables --- .../resources/guides/pydis-guides/contributing/bot.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 6f2c7e74..009354d2 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -169,7 +169,7 @@ If you wish to set all values in your `env.server` for your testing server, you Additionally: -* At this stage, set `redis_use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). +* At this stage, set `redis_use_fakeredis=true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](#automatic-configuration) @@ -241,8 +241,8 @@ Your bot is now running, but this method makes debugging with an IDE a fairly in The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. * Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `.env.server` file, set `urls_site_api` to `"http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. -* To work with snekbox, set `urls_snekbox_eval_api` to `"http://localhost:8060/eval"` and `urls_snekbox_311_eval_api` to `"http://localhost:8065/eval"` +* In your `.env.server` file, set `urls_site_api="http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* To work with snekbox, set `urls_snekbox_eval_api="http://localhost:8060/eval"` and `urls_snekbox_311_eval_api="http://localhost:8065/eval"` You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: @@ -351,12 +351,12 @@ Once the previous steps are done, all that is left is to: --- ### Optional: Working with Redis -In [Configure the Bot](#envserver) you were asked to set `redis_use_fakeredis` to `true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. +In [Configure the Bot](#envserver) you were asked to set `redis_use_fakeredis=true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. If you are working on a feature that relies on Redis, you will need to enable Redis to make sure persistency is achieved for the feature across restarts. The first step towards that is going to `.env.server` and setting `redis.use_fakeredis` to `false`. #### Starting Redis in Docker (Recommended) -If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis_host` to `redis`, and if you're running it on the host set it to `localhost`. Set `redis_password` to `""`. +If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis_host=redis`, and if you're running it on the host set it to `localhost`. Set `redis_password=""`. #### Starting Redis Using Other Methods You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port` in your `.env.server` file and the `REDIS_PASSWORD` in the `.env` file. @@ -387,11 +387,16 @@ If you want to run the bot locally, you can run `docker-compose up metricity` in --- ### Optional: Working with bot moderation logs -To be able to view moderation-related logs published by the bot to site, you will need to set `urls_site_logs_view` to `http://localhost:8000/staff/bot/logs` in your `.env.server`. +To be able to view moderation-related logs published by the bot to site, you will need to set `urls_site_logs_view=http://localhost:8000/staff/bot/logs` in your `.env.server`. This will work in both Docker and locally. --- +### Optional: Changing your command prefix +If you would like a prefix other than the default `!`, set `BOT_PREFIX={{your_prefix}}` in `.env.server`. + +--- + ### Issues? If you have any issues with setting up the bot, come discuss it with us on the [#dev-contrib](https://discord.gg/2h3qBv8Xaa) channel on our server. -- cgit v1.2.3 From 493ab3c7381ba89f640b7b53d2d0d96bf8944dbf Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sat, 1 Apr 2023 21:36:50 +0200 Subject: replace docker-compose with docker compose --- .../guides/pydis-guides/contributing/bot.md | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 009354d2..02564c0c 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -16,6 +16,7 @@ The Python bot is tightly coupled with the Python Discord server, so to have a f It's possible to set the bot to use a single channel for all cogs, but that will cause extreme spam and will be difficult to work with. You can start your own server and set up channels as you see fit, but for your convenience we have a template for a development server you can use: [https://discord.new/zmHtscpYN9E3](https://discord.new/zmHtscpYN9E3). + Keep in mind that this is not an exact mirror of the Python server, but a reduced version for testing purposes. The channels there are mostly the ones needed by the bot. --- @@ -229,11 +230,11 @@ In your `.env.server` file: -Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker-compose up`. +Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker compose up`. -If working with snekbox you can run `docker-compose --profile 3.10 up` to also start up a 3.10 snekbox container, in addition to the default 3.11 container! +If working with snekbox you can run `docker compose --profile 3.10 up` to also start up a 3.10 snekbox container, in addition to the default 3.11 container! -After pulling the images and building the containers, your bot will start. Enter your server and type `!help` (or whatever prefix you chose instead of `!`). +After pulling the images and building the containers, your bot will start. Enter your server and type `!help` (or whatever prefix you [chose](#optional--changing-your-command-prefix) instead of `!`). Your bot is now running, but this method makes debugging with an IDE a fairly involved process. For additional running methods, continue reading the following sections. @@ -247,17 +248,17 @@ The advantage of this method is that you can run the bot's code in your preferre You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: -* `docker-compose up web` to start the site container. This is required. -* `docker-compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. -* `docker-compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. -* `docker-compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). +* `docker compose up web` to start the site container. This is required. +* `docker compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. +* `docker compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. +* `docker compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). -You can start several services together: `docker-compose up web snekbox redis`. +You can start several services together: `docker compose up web snekbox redis`. ##### Setting Up a Development Environment The bot's code is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: -1. Make sure you have [Python 3.10](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. +1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. 2. [Install Poetry](https://github.com/python-poetry/poetry#installation). 3. [Install the dependencies](../installing-project-dependencies). @@ -380,9 +381,9 @@ guild_id = replace_with_your_guild_id ``` To properly replicate production behavior, set the `staff_role_id`, `staff_categories`, and `ignore_categories` fields as well. -Now, `docker-compose up` will also start Metricity. +Now, `docker compose up` will also start Metricity. -If you want to run the bot locally, you can run `docker-compose up metricity` instead. +If you want to run the bot locally, you can run `docker compose up metricity` instead. --- -- cgit v1.2.3 From 4eedb972d4712082b9a2e381ea728a4fd59ed445 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Thu, 6 Apr 2023 23:59:53 +0200 Subject: remove redundant talk about .env --- .../guides/pydis-guides/contributing/bot.md | 42 +++++++++------------- 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 02564c0c..00d70c0e 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -40,7 +40,21 @@ If your bot fails to start with a `PrivilegedIntentsRequired` exception, this in You now have both the bot's code and a server to run it on. It's time for you to connect the two by changing the bot's configurations. This can be done either automatically or manually, and we'll be detailing the steps for both. -One thing to know is that the bot relies on precisely **two** configuration files to work +One thing to know is that the bot relies on precisely **two** configuration files to work. + + +#### .env +This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`. +It will also contain configurations related to external services the bot might use such as `USE_METRICITY`, which are unrelated to your server, with the only exception being `GUILD_ID`. + +This file will **always** need to have `BOT_TOKEN` and `GUILD_ID` values set: + +```text +BOT_TOKEN=YourDiscordBotTokenHere +GUILD_ID=YourDiscordTestServerIdHere +``` +See [here](../creating-bot-account) for help with obtaining the bot token, and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's ID. + #### .env.server All server configuration values are saved in this file, which needs to be at the root directory of the cloned code. @@ -50,9 +64,6 @@ It also contains configurations such as how long it takes for a help channel to This file will be created for you automatically if you decide to go with [automatic configuration](#automatic-configuration), otherwise a lot of it has to be done by hand which will be detailed in the [manual configuration](#manual-configuration) section. -#### .env -This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`. -It will also contain configurations related to external services the bot might use such as `USE_METRICITY`, which are unrelated to your server, with the only exception being `GUILD_ID`. **Notes**: @@ -66,19 +77,6 @@ without having to spend much time copying IDs from your server into your configu **Note**: The script will also work on existing servers as long as the channel names are the same as the one in Python Discord. ##### 1. Script setup -##### 1.1. Environment variables -You will need to create a file called `.env`, which will contain two required values: `BOT_TOKEN` and `GUILD_ID`. - -Inside, add the following two lines: - -```text -BOT_TOKEN=YourDiscordBotTokenHere -GUILD_ID=YourDiscordTestServerIdHere -``` -See [here](../creating-bot-account) for help with obtaining the bot token, and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's ID. - - -##### 1.2 Setting up the script environment The bootstrapping script is a Python program so you will need a compatible Python version and the necessary dependencies installed, which are all detailed here: @@ -86,7 +84,7 @@ which are all detailed here: 2. [Install Poetry](https://github.com/python-poetry/poetry#installation). 3. [Install the dependencies](../installing-project-dependencies). -#### 2. Running the script +##### 2. Running the script Once the script setup phase is complete, all that is left is to run it. To do this, you'll simply need to run the `configure` poetry task: @@ -105,12 +103,11 @@ This file will contain the extracted IDs from your server which are necessary fo **Note**: Skip this part if you used the automatic configuration. -##### .env.server Reading this means that you're ready for a bit of manual labour. If for some reason you've missed the automatic server setup section, you can read about it [here](#automatic-configuration) To configure the bot manually, you will **only** need to set the values for the channels, roles, categories, etc. -that are used by the component you are developing. +that are used by the component you are developing inside the `.env.server` file. For example, if we're testing a feature that only needs the `announcements` channel: @@ -191,11 +188,6 @@ We understand this is tedious which is why we **heavily recommend** using the [a
-##### .env -The second file you need to create is the one containing the environment variables, and needs to be named `.env`. -Inside, add the line `BOT_TOKEN=YourDiscordBotTokenHere`. See [here](../creating-bot-account) for help with obtaining the bot token. - ---- ### Run it! -- cgit v1.2.3 From 42e7a8914be9cf8d4a10f17ebe4ace49c5046c25 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Fri, 7 Apr 2023 00:42:32 +0200 Subject: improve wording of a couple sections --- .../content/resources/guides/pydis-guides/contributing/bot.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 00d70c0e..769ea838 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -80,7 +80,7 @@ without having to spend much time copying IDs from your server into your configu The bootstrapping script is a Python program so you will need a compatible Python version and the necessary dependencies installed, which are all detailed here: -1. Make sure you have [Python 3.10](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. +1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. 2. [Install Poetry](https://github.com/python-poetry/poetry#installation). 3. [Install the dependencies](../installing-project-dependencies). @@ -106,8 +106,8 @@ This file will contain the extracted IDs from your server which are necessary fo Reading this means that you're ready for a bit of manual labour. If for some reason you've missed the automatic server setup section, you can read about it [here](#automatic-configuration) -To configure the bot manually, you will **only** need to set the values for the channels, roles, categories, etc. -that are used by the component you are developing inside the `.env.server` file. +To configure the bot manually, you will **only** need to set inside the `.env.server` file the values for the channels, roles, categories, etc. +that are used by the component you are developing. For example, if we're testing a feature that only needs the `announcements` channel: @@ -165,9 +165,6 @@ If you wish to set all values in your `env.server` for your testing server, you * `webhooks_` * `emojis_` -Additionally: - -* At this stage, set `redis_use_fakeredis=true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](#automatic-configuration) @@ -220,6 +217,7 @@ In your `.env.server` file: * `urls_snekbox_eval_api` to `"http://snekbox:8060/eval"` * `urls_snekbox_311_eval_api` to `"http://snekbox-311:8060/eval"`. +* At this stage, set `redis_use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker compose up`. -- cgit v1.2.3 From facb030041d916713c9fdacf18c57420d43bc433 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Fri, 14 Apr 2023 21:50:34 +0100 Subject: Seperate manual configuration out of the main bot contributing guide Also update the guide to be far simpler, and less words to read for our contributors to get setup. --- .../bot-extended-configuration-options.md | 192 +++++++++++ .../guides/pydis-guides/contributing/bot.md | 353 ++++----------------- 2 files changed, 257 insertions(+), 288 deletions(-) create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md new file mode 100644 index 00000000..b031a668 --- /dev/null +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md @@ -0,0 +1,192 @@ +--- +title: Extended options for configuring Bot +description: A guide that lists all extended/optional options to configure the bot further. +icon: fab fa-github +toc: 3 +--- + +## Manual constants configuration + +Reading this means that you're ready for a bit of manual labour. +If for some reason you've missed the automatic server setup section, you can read about it in the bot contributing guide [here](../bot.md#envserver) + +To configure the bot manually, you will **only** need to set inside the `.env.server` file the values for the channels, roles, categories, etc. +that are used by the component you are developing. + +For example, if we're testing a feature that only needs the `announcements` channel: + +`constants.py` + +```py + +class EnvConfig: + # Defines from where & how Pydantic will be looking for env variables + ... + +class _Channels(EnvConfig): + + EnvConfig.Config.env_prefix = "channels_" + + announcements = 1079790565794779156 + changelog = 1077877318564991006 + +# Instantiate the class & load the configuration +Channels = _Channels() +``` + +`.env.server` file: + +```text +# .env.server + +channels_announcements=1077875228002234398 +``` + +When you launch your bot, `pydantic` will load up the server constants from the `.env.server` file if they exist. + +Each constants class will define its own prefix, which will make `pydantic` look for variables that will look like `{{env_prefix}}{{attribute_name}}` in the environment files + +In our example, this will imply that pydantic will look for both `channels_announcements` and `channels_changelog` in the `.env.server` file. + +As you can see here, only `channels_announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic` +to use the value **1077875228002234398** for the `announcements` attribute instead of the default **1079790565794779156**, and use the default value for the `changelog` attribute + +```python +>>> Channels.announcements +1077875228002234398 +>>> Channels.changelong +1077877318564991006 +``` + +See [here](../obtaining-discord-ids) for help with obtaining Discord IDs. + +If you wish to set all values in your `env.server` for your testing server, you need to set **all** the ones prefixed with: + +* `guild_` +* `categories_` +* `channels_` +* `roles_` +* `webhooks_` +* `emojis_` + +## Working with the help forum + +**Note**: This is only required when you're not configuring the bot [automatically](#automatic-configuration) + +If you will be working on a feature that includes the python help forum, you will need to use `Forum Channels`. + +Forum channels cannot be included in a template, which is why this needs to be done by hand for the time being. + +To activate forum channels, your Discord server needs to have the community feature. +If that's not the case already, here are the steps required to do it: + +1. Go to server settings +2. Scroll down to the `COMMUNITY` section and click on `Enable Community` +3. Click on `Get Started` and fill out the necessary info + +Once the previous steps are done, all that is left is to: + +1. Create a new channel +2. Choose the `Forum` type +3. [Copy its ID](../obtaining-discord-ids#channel-id) +4. Add the following line to the `.env.server` file: `channels_python_help={newly_created_forum_channel_id}` + +--- + +We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](../bot.md#automatic-configuration) + +--- + +## Reloading parts of the bot +If you make changes to an extension, you might not need to restart the entire bot for the changes to take effect. The command `!ext reload ` re-imports the files associated with the extension. +Invoke `!ext list` for a full list of the available extensions. In this bot in particular, cogs are defined inside extensions. + +Note that if you changed code that is not associated with a particular extension, such as utilities, converters, and constants, you will need to restart the bot. + +## Adding new statistics + +Details on how to add new statistics can be found on the [statistic infrastructure page](https://blog.pythondiscord.com/statistics-infrastructure). +We are always open to more statistics so add as many as you can! + +--- + +## With the Bot Running Locally +The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. + +* Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. +* In your `.env.server` file, set `urls_site_api="http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. +* To work with snekbox, set `urls_snekbox_eval_api="http://localhost:8060/eval"` and `urls_snekbox_311_eval_api="http://localhost:8065/eval"` + + +You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: + +* `docker compose up web` to start the site container. This is required. +* `docker compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. +* `docker compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. +* `docker compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). + +You can start several services together: `docker compose up web snekbox redis`. + +### Setting Up a Development Environment + +With at least the site running in Docker already (see the previous section on how to start services separately), you can now start the bot locally through the command line, or through your preferred IDE. +
+ + +
+
+ +### With More Things Running Locally +You can run additional services on the host, but this guide won't go over how to install and start them in this way. +If possible, prefer to start the services through Docker to replicate the production environment as much as possible. + +The site, however, is a mandatory service for the bot. +Refer to the [previous section](#with-the-bot-running-locally) and the [site contributing guide](../site) to learn how to start it on the host, in which case you will need to change `urls.site` in `.env.server` to wherever the site is being hosted. + +--- + +### Starting Redis Using Other Methods +You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port` in your `.env.server` file and the `REDIS_PASSWORD` in the `.env` file. +**Note**: The previously mentioned variables **SHOULD NOT** be overriden or changed in `constants.py` + +--- + +## Working with Metricity +[Metricity](https://github.com/python-discord/metricity) is our home-grown bot for collecting metrics on activity within the server, such as what users are present, and IDs of the messages they've sent. +Certain features in the Python bot rely on querying the Metricity database for information such as the number of messages a user has sent, most notably the voice verification system. + +If you wish to work on a feature that relies on Metricity, for your convenience we've made the process of using it relatively painless with Docker: Enter the `.env` file you've written for the Python bot, and append the line `USE_METRICITY=true`. +Note that if you don't need Metricity, there's no reason to have it enabled as it is just unnecessary overhead. + +To make the Metricity bot work with your test server, you will need to override its configurations similarly to the Python bot. +You can see the various configurations in [the Metricity repo](https://github.com/python-discord/metricity), but the bare minimum is the guild ID setting. +In your local version of the Python bot repo, create a file called `metricity-config.toml` and insert the following lines: +```yaml +[bot] +guild_id = replace_with_your_guild_id +``` +To properly replicate production behavior, set the `staff_role_id`, `staff_categories`, and `ignore_categories` fields as well. + +Now, `docker compose up` will also start Metricity. + +If you want to run the bot locally, you can run `docker compose up metricity` instead. + +--- + +## Working with bot moderation logs +To be able to view moderation-related logs published by the bot to site, you will need to set `urls_site_logs_view=http://localhost:8000/staff/bot/logs` in your `.env.server`. +This will work in both Docker and locally. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 769ea838..6639d92d 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -10,6 +10,35 @@ You should have already forked the repository and cloned it to your local machin This page will focus on the quickest steps one can take, with mentions of alternatives afterwards. --- +## Setting up the project + +### Setup Project Dependencies +Below are the dependencies you **must** have installed to get started with the bot. + +1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. +1. [Install Poetry](https://github.com/python-poetry/poetry#installation). +1. [Install the project's dependencies](../installing-project-dependencies). +1. Docker. + +
+ + +
+
### Set Up a Test Server The Python bot is tightly coupled with the Python Discord server, so to have a functional version of the bot you need a server with channels it can use. @@ -37,137 +66,45 @@ If your bot fails to start with a `PrivilegedIntentsRequired` exception, this in --- ### Configure the Bot -You now have both the bot's code and a server to run it on. It's time for you to connect the two by changing the bot's configurations. -This can be done either automatically or manually, and we'll be detailing the steps for both. - -One thing to know is that the bot relies on precisely **two** configuration files to work. +You now have both the bot's code and a server to run it on. It's time for you to connect the two by setting the bot's configuration. +Both `.env` and `.env.server` files we talk about below are ignored by git, so they do not get accidentally commit to the repository. #### .env -This file will mostly contain sensitive information such as your `BOT_TOKEN` and your `REDIS_PASSWORD`. -It will also contain configurations related to external services the bot might use such as `USE_METRICITY`, which are unrelated to your server, with the only exception being `GUILD_ID`. +This file will contain sensitive information such as your bot's token, do not share it with anybody! -This file will **always** need to have `BOT_TOKEN` and `GUILD_ID` values set: +To start, create a `.env` file in the project root with the below content. ```text BOT_TOKEN=YourDiscordBotTokenHere GUILD_ID=YourDiscordTestServerIdHere +BOT_PREFIX=YourDesiredPrefixHere ``` See [here](../creating-bot-account) for help with obtaining the bot token, and [here](../obtaining-discord-ids#guild-id) for help with obtaining the guild's ID. +Other values will be added to your `.env` over time as you need to interact with other parts of the bot, but those are not needed for a basic setup. For a full list of support values see the ENV file option [appendix](#appendix-full-env-file-options) #### .env.server -All server configuration values are saved in this file, which needs to be at the root directory of the cloned code. -This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. -It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify. - -This file will be created for you automatically if you decide to go with [automatic configuration](#automatic-configuration), -otherwise a lot of it has to be done by hand which will be detailed in the [manual configuration](#manual-configuration) section. - - -**Notes**: - -* Both `.env` and `.env.server` are and should remain ignored by git, otherwise you risk pushing sensitive information. -* Skip the following step if you would like to configure the bot manually, but that will require more work. - -#### Automatic configuration -To make setup much easier, the script in `botstrap.py` bootstraps the configuration for you and helps you get started immediately, -without having to spend much time copying IDs from your server into your configuration file. - -**Note**: The script will also work on existing servers as long as the channel names are the same as the one in Python Discord. +All server related configuration values are saved in this file, which also needs to be at the root directory of the project. -##### 1. Script setup -The bootstrapping script is a Python program so you will need a compatible Python version and the necessary dependencies installed, -which are all detailed here: +We provide a script to automatically generate a server config. +**Note**: The script **only** works with servers created with the template mentioned above. -1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. -2. [Install Poetry](https://github.com/python-poetry/poetry#installation). -3. [Install the dependencies](../installing-project-dependencies). - -##### 2. Running the script +If you want to setup the bot from an existing guild read out [manual configuration guide](../bot-extended-configuration-options#manual-constants-configuration). This is far more complicated and time consuming. -Once the script setup phase is complete, all that is left is to run it. -To do this, you'll simply need to run the `configure` poetry task: +Running the below command will use the `BOT_TOKEN` and `GUILD_ID` from the `.env` file you created above to download all of the relevant IDs from the template guild into your `.env.server` +**Note**: This script will overwrite the `.env.server` file. We suggest you put any configuration not generated by this script in to `.env` instead ```shell $ poetry run task configure ``` -Once the script has finished running, you'll notice the creation of a new file called [`.env.server`](#envserver) at your project's root directory. +Once the script has finished running, you'll notice the creation of a new file called `.env.server` at your project's root directory. This file will contain the extracted IDs from your server which are necessary for your bot to run. **Congratulations**, you have finished the configuration and can now [run your bot](#run-it). -#### Manual configuration - -**Note**: Skip this part if you used the automatic configuration. - -Reading this means that you're ready for a bit of manual labour. -If for some reason you've missed the automatic server setup section, you can read about it [here](#automatic-configuration) - -To configure the bot manually, you will **only** need to set inside the `.env.server` file the values for the channels, roles, categories, etc. -that are used by the component you are developing. - -For example, if we're testing a feature that only needs the `announcements` channel: - -`constants.py` - -```py - -class EnvConfig: - # Defines from where & how Pydantic will be looking for env variables - ... - -class _Channels(EnvConfig): - - EnvConfig.Config.env_prefix = "channels_" - - announcements = 1079790565794779156 - changelog = 1077877318564991006 - -# Instantiate the class & load the configuration -Channels = _Channels() -``` - -`.env.server` file: - -```text -# .env.server - -channels_announcements=1077875228002234398 -``` - -When you launch your bot, `pydantic` will load up the server constants from the `.env.server` file if they exist. - -Each constants class will define its own prefix, which will make `pydantic` look for variables that will look like `{{env_prefix}}{{attribute_name}}` in the environment files - -In our example, this will imply that pydantic will look for both `channels_announcements` and `channels_changelog` in the `.env.server` file. - -As you can see here, only `channels_announcements` has been defined in the `.env.server` file since it's the only one needed, which will tell `pydantic` -to use the value **1077875228002234398** for the `announcements` attribute instead of the default **1079790565794779156**, and use the default value for the `changelog` attribute - -```python ->>> Channels.announcements -1077875228002234398 ->>> Channels.changelong -1077877318564991006 -``` - -See [here](../obtaining-discord-ids) for help with obtaining Discord IDs. - -If you wish to set all values in your `env.server` for your testing server, you need to set **all** the ones prefixed with: - -* `guild_` -* `categories_` -* `channels_` -* `roles_` -* `webhooks_` -* `emojis_` - - -We understand this is tedious which is why we **heavily recommend** using the [automatic configuration setup](#automatic-configuration) -
- -
-
- -In your `.env.server` file: - -* If you wish to work with snekbox, set the following: - * `urls_snekbox_eval_api` to `"http://snekbox:8060/eval"` - * `urls_snekbox_311_eval_api` to `"http://snekbox-311:8060/eval"`. - -* At this stage, set `redis_use_fakeredis` to `true`. If you're looking for instructions for working with Redis, see [Working with Redis](#optional-working-with-redis). - - -Assuming you have Docker installed **and running**, enter the cloned repo in the command line and type `docker compose up`. - -If working with snekbox you can run `docker compose --profile 3.10 up` to also start up a 3.10 snekbox container, in addition to the default 3.11 container! - -After pulling the images and building the containers, your bot will start. Enter your server and type `!help` (or whatever prefix you [chose](#optional--changing-your-command-prefix) instead of `!`). - -Your bot is now running, but this method makes debugging with an IDE a fairly involved process. For additional running methods, continue reading the following sections. -#### With the Bot Running Locally -The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker. +With all of the above setup, you can run The projec with `docker compose up`. This will start the bot an all required services! Enter your server and type `!help` (or whatever prefix you chose instead of `!`) to see the bot in action! -* Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. -* In your `.env.server` file, set `urls_site_api="http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. -* To work with snekbox, set `urls_snekbox_eval_api="http://localhost:8060/eval"` and `urls_snekbox_311_eval_api="http://localhost:8065/eval"` +Some other useful docker commands are as follows: +1. `docker compose pull` this pulls updates for all non-bot services, such as psotgres, redis and our [site](../site) project! +1. `docker compose build` this rebuilds the bot's docker image, this is only needed if you need to make changes to the bot's dependencies, or the Dockerfile itself. +1. `docker compose --profile 3.10 up` this starts a 3.10 snekbox container, in addition to the default 3.11 container! -You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: - -* `docker compose up web` to start the site container. This is required. -* `docker compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. -* `docker compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. -* `docker compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). - -You can start several services together: `docker compose up web snekbox redis`. - -##### Setting Up a Development Environment -The bot's code is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed: - -1. Make sure you have [Python 3.11](https://www.python.org/downloads/) installed. It helps if it is your system's default Python version. -2. [Install Poetry](https://github.com/python-poetry/poetry#installation). -3. [Install the dependencies](../installing-project-dependencies). - -With at least the site running in Docker already (see the previous section on how to start services separately), you can now start the bot locally through the command line, or through your preferred IDE. -
- - -
-
- -#### With More Things Running Locally -You can run additional services on the host, but this guide won't go over how to install and start them in this way. -If possible, prefer to start the services through Docker to replicate the production environment as much as possible. +Your bot is now running, all inside Docker. -The site, however, is a mandatory service for the bot. -Refer to the [previous section](#with-the-bot-running-locally) and the [site contributing guide](../site) to learn how to start it on the host, in which case you will need to change `urls.site` in `.env.server` to wherever the site is being hosted. +**Note**: If you want to read about how to make debugging with an IDE a easier, or for additional running methods, check out our [extended configuration guide](../bot-extended-configuration-options). --- -### Development Tips + +## Development Tips Now that you have everything setup, it is finally time to make changes to the bot! -#### Working with Git +### Working with Git Version control of our projects is done using Git and Github. It can be intimidating at first, so feel free to ask for any help in the server. [**Click here to see the basic Git workflow when contributing to one of our projects.**](../working-with-git/) -#### Running tests +### Running tests [This section](https://github.com/python-discord/bot/blob/main/tests/README.md#tools) of the README in the `tests` repository will explain how to run tests. The whole document explains how unittesting works, and how it fits in the context of our project. Make sure to run tests *before* pushing code. -Even if you run the bot through Docker, you might want to [setup a development environment](#setting-up-a-development-environment) in order to run the tests locally. +Even if you run the bot through Docker, you might want to [setup a development environment](../bot-extended-configuration-options#setting-up-a-development-environment) in order to run the tests locally. -#### Lint before you push +### Lint before you push As mentioned in the [contributing guidelines](../contributing-guidelines), you should make sure your code passes linting for each commit you make. For ease of development, you can install the pre-commit hook with `poetry run task precommit`, which will check your code every time you try to commit it. -For that purpose, even if you run the bot through Docker, you might want to [setup a development environment](#setting-up-a-development-environment), as otherwise the hook installation will fail. - -#### Reloading parts of the bot -If you make changes to an extension, you might not need to restart the entire bot for the changes to take effect. The command `!ext reload ` re-imports the files associated with the extension. -Invoke `!ext list` for a full list of the available extensions. In this bot in particular, cogs are defined inside extensions. - -Note that if you changed code that is not associated with a particular extension, such as utilities, converters, and constants, you will need to restart the bot. - -#### Adding new statistics - -Details on how to add new statistics can be found on the [statistic infrastructure page](https://blog.pythondiscord.com/statistics-infrastructure). -We are always open to more statistics so add as many as you can! - ---- - -### Optional: Working with the help forum - -**Note**: This is only required when you're not configuring the bot [automatically](#automatic-configuration) +For that purpose, even if you run the bot through Docker, you might want to [setup a development environment](../bot-extended-configuration-options#setting-up-a-development-environment), as otherwise the hook installation will fail. -If you will be working on a feature that includes the python help forum, you will need to use `Forum Channels`. - -Forum channels cannot be included in a template, which is why this needs to be done by hand for the time being. - -To activate forum channels, your Discord server needs to have the community feature. -If that's not the case already, here are the steps required to do it: -1. Go to server settings -2. Scroll down to the `COMMUNITY` section and click on `Enable Community` -3. Click on `Get Started` and fill out the necessary info - -Once the previous steps are done, all that is left is to: -1. Create a new channel -2. Choose the `Forum` type -3. [Copy its ID](../obtaining-discord-ids#channel-id) -4. Add the following line to the `.env.server` file: `channels_python_help={newly_created_forum_channel_id}` - ---- - -### Optional: Working with Redis -In [Configure the Bot](#envserver) you were asked to set `redis_use_fakeredis=true`. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information. - -If you are working on a feature that relies on Redis, you will need to enable Redis to make sure persistency is achieved for the feature across restarts. The first step towards that is going to `.env.server` and setting `redis.use_fakeredis` to `false`. - -#### Starting Redis in Docker (Recommended) -If you're using the Docker image provided in the project's Docker Compose, open your `.env.server` file. If you're running the bot in Docker, set `redis_host=redis`, and if you're running it on the host set it to `localhost`. Set `redis_password=""`. - -#### Starting Redis Using Other Methods -You can run your own instance of Redis, but in that case you will need to correctly set `redis_host` and `redis_port` in your `.env.server` file and the `REDIS_PASSWORD` in the `.env` file. -**Note**: The previously mentioned variables **SHOULD NOT** be overriden or changed in `constants.py` - ---- - -### Optional: Working with Metricity -[Metricity](https://github.com/python-discord/metricity) is our home-grown bot for collecting metrics on activity within the server, such as what users are present, and IDs of the messages they've sent. -Certain features in the Python bot rely on querying the Metricity database for information such as the number of messages a user has sent, most notably the voice verification system. - -If you wish to work on a feature that relies on Metricity, for your convenience we've made the process of using it relatively painless with Docker: Enter the `.env` file you've written for the Python bot, and append the line `USE_METRICITY=true`. -Note that if you don't need Metricity, there's no reason to have it enabled as it is just unnecessary overhead. - -To make the Metricity bot work with your test server, you will need to override its configurations similarly to the Python bot. -You can see the various configurations in [the Metricity repo](https://github.com/python-discord/metricity), but the bare minimum is the guild ID setting. -In your local version of the Python bot repo, create a file called `metricity-config.toml` and insert the following lines: -```yaml -[bot] -guild_id = replace_with_your_guild_id -``` -To properly replicate production behavior, set the `staff_role_id`, `staff_categories`, and `ignore_categories` fields as well. - -Now, `docker compose up` will also start Metricity. - -If you want to run the bot locally, you can run `docker compose up metricity` instead. - ---- - -### Optional: Working with bot moderation logs -To be able to view moderation-related logs published by the bot to site, you will need to set `urls_site_logs_view=http://localhost:8000/staff/bot/logs` in your `.env.server`. -This will work in both Docker and locally. - ---- +### Issues? +If you have any issues with setting up the bot, come discuss it with us on the [#dev-contrib](https://discord.gg/2h3qBv8Xaa) channel on our server. -### Optional: Changing your command prefix -If you would like a prefix other than the default `!`, set `BOT_PREFIX={{your_prefix}}` in `.env.server`. +If you find any bugs in the bot or would like to request a feature, feel free to [open an issue](https://github.com/python-discord/bot/issues/new/choose) on the repository. --- -### Issues? -If you have any issues with setting up the bot, come discuss it with us on the [#dev-contrib](https://discord.gg/2h3qBv8Xaa) channel on our server. +# Next steps +Now that you have everything setup, it is finally time to make changes to the bot! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. -If you find any bugs in the bot or would like to request a feature, feel free to [open an issue](https://github.com/python-discord/bot/issues/new/choose) on the repository. +Have fun! --- -### Appendix: Full ENV File Options +# Appendix: Full ENV File Options The following is a list of all available environment variables used by the bot: | Variable | Required | Description | @@ -407,17 +193,8 @@ The following is a list of all available environment variables used by the bot: | `BOT_SENTRY_DSN` | When connecting the bot to sentry | The DSN of the sentry monitor. | | `BOT_TRACE_LOGGERS ` | When you wish to see specific or all trace logs | Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level. | | `DEBUG` | In production | `true` or `false`, depending on whether to enable debug mode, affecting the behavior of certain features. `true` by default. | -| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Optional: Working with Redis](#optional-working-with-redis)). | -| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Optional: Working with Metricity](#optional-working-with-metricity)). `false` by default. | +| `REDIS_PASSWORD` | When not using FakeRedis | The password to connect to the Redis database (see [Staring Redis with other methods](../bot-extended-configuration-options#starting-redis-using-other-methods)). | +| `USE_METRICITY` | When using Metricity | `true` or `false`, depending on whether to enable metrics collection using Metricity (see [Working with Metricity](../bot-extended-configuration-options#working-with-metricity)). `false` by default. | | `API_KEYS_GITHUB` | When you wish to interact with GitHub | The API key to interact with GitHub, for example to download files for the branding manager. | | `METABASE_USERNAME` | When you wish to interact with Metabase | The username for a Metabase admin account. | | `METABASE_PASSWORD` | When you wish to interact with Metabase | The password for a Metabase admin account. | - ---- - -# Next steps -Now that you have everything setup, it is finally time to make changes to the bot! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. - -If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project) is for you. - -Have fun! -- cgit v1.2.3 From fb954b18754b139a27f05aab0f11266a6766a497 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sat, 6 May 2023 13:12:22 +0100 Subject: update all env var names --- .../pydis-guides/contributing/sir-lancebot.md | 22 +++--- .../contributing/sir-lancebot/env-var-reference.md | 92 ++++++++++------------ 2 files changed, 52 insertions(+), 62 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index edfd7ac1..f4a6dd37 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -72,17 +72,17 @@ You will have to setup environment variables: The following variables are needed for running Sir Lancebot: -| Environment Variable | Description | -| -------- | -------- | -| `BOT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | -| `BOT_GUILD` | ID of the Discord Server | -| `BOT_ADMIN_ROLE_ID` | ID of the role `@Admins` | -| `ROLE_HELPERS` | ID of the role `@Helpers` | -| `CHANNEL_ANNOUNCEMENTS` | ID of the `#announcements` channel | -| `CHANNEL_DEVLOG` | ID of the `#dev-log` channel | -| `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the `#sir-lancebot-commands` channel | - -[**Full environment variable reference for this project.**](./env-var-reference) +| Environment Variable | Description | +|--------------------------------|--------------------------------------------------------------------------------------------| +| `CLIENT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | +| `CLIENT_GUILD` | ID of the Discord Server | +| `ROLES_ADMIN` | ID of the role `@Admins` | +| `ROLES_HELPERS` | ID of the role `@Helpers` | +| `CHANNELS_ANNOUNCEMENTS` | ID of the `#announcements` channel | +| `CHANNELS_DEVLOG` | ID of the `#dev-log` channel | +| `CHANNEL_SIR_LANCEBOT_PLAYGROUND` | ID of the `#sir-lancebot-playground` channel | + +[**Full environment variable reference for this project.**](../sir-lancebot/env-var-reference) --- diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md index 3862fb2e..7e321241 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md @@ -6,69 +6,59 @@ toc: 2 ## General Variables The following variables are needed for running Sir Lancebot: -| Environment Variable | Description | -| -------- | -------- | -| `BOT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | -| `BOT_GUILD` | ID of the Discord Server | -| `BOT_ADMIN_ROLE_ID` | ID of the role `@Admins` | -| `ROLE_HELPERS` | ID of the role `@Helpers` | -| `CHANNEL_ANNOUNCEMENTS` | ID of the `#announcements` channel | -| `CHANNEL_DEVLOG` | ID of the `#dev-log` channel | -| `CHANNEL_COMMUNITY_BOT_COMMANDS` | ID of the `#sir-lancebot-commands` channel | -| `CHANNEL_REDDIT` | ID of the `#reddit` channel | +| Environment Variable | Description | +|------------------------------------|--------------------------------------------------------------------------------------------| +| `CLIENT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | +| `CLIENT_GUILD` | ID of the Discord Server | +| `ROLES_ADMINS` | ID of the role `@Admins` | +| `ROLES_HELPERS` | ID of the role `@Helpers` | +| `CHANNELS_ANNOUNCEMENTS` | ID of the `#announcements` channel | +| `CHANNELS_DEVLOG` | ID of the `#dev-log` channel | +| `CHANNELS_SIR_LANCEBOT_PLAYGROUND` | ID of the `#sir-lancebot-commands` channel | +| `CHANNELS_REDDIT` | ID of the `#reddit` channel | --- ## Debug Variables Additionally, you may find the following environment variables useful during development: -| Environment Variable | Description | -| -------- | -------- | -| `BOT_DEBUG` | Debug mode of the bot | False | -| `PREFIX` | The bot's invocation prefix | `.` | -| `CYCLE_FREQUENCY` | Amount of days between cycling server icon | 3 | -| `MONTH_OVERRIDE` | Integer in range `[0, 12]`, overrides current month w.r.t. seasonal decorators | -| `REDIS_HOST` | The address to connect to for the Redis database. | -| `REDIS_PORT` | | -| `REDIS_PASSWORD` | | -| `USE_FAKEREDIS` | If the FakeRedis module should be used. Set this to true if you don't have a Redis database setup. | -| `BOT_SENTRY_DSN` | The DSN of the sentry monitor. | -| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of sending `\:emoji:` on discord. | +| Environment Variable | Description | +|----------------------------|------------------------------------------------------------------------------------------------------------| +| `CLIENT_DEBUG` | Debug mode of the bot | False | +| `CLIENT_PREFIX` | The bot's invocation prefix | `.` | +| `BRANDING_CYCLE_FREQUENCY` | Amount of days between cycling server icon | 3 | +| `CLIENT_MONTH_OVERRIDE` | Integer in range `[0, 12]`, overrides current month w.r.t. seasonal decorators | +| `REDIS_HOST` | The address to connect to for the Redis database. | +| `REDIS_PORT` | The port on which the Redis database is exposed. | +| `REDIS_PASSWORD` | The password to connect to the Redis database. | +| `REDIS_USE_FAKEREDIS` | If the FakeRedis module should be used. Set this to true if you don't have a Redis database setup. | +| `BOT_SENTRY_DSN` | The DSN of the sentry monitor. | +| `TRASHCAN_EMOJI` | The full emoji to use for the trashcan. Format should be like the output of sending `\:emoji:` on discord. | --- ## Tokens/APIs If you will be working with an external service, you might have to set one of these tokens: -| Token | Description | -| -------- | -------- | -| `GITHUB_TOKEN` | Personal access token for GitHub, raises rate limits from 60 to 5000 requests per hour. | -| `GIPHY_TOKEN` | Required for API access. [Docs](https://developers.giphy.com/docs/api) | -| `OMDB_API_KEY` | Required for API access. [Docs](https://www.omdbapi.com/) | -| `REDDIT_CLIENT_ID` | OAuth2 client ID for authenticating with the [reddit API](https://github.com/reddit-archive/reddit/wiki/OAuth2). | -| `REDDIT_SECRET` | OAuth2 secret for authenticating with the reddit API. *Leave empty if you're not using the reddit API.* | -| `REDDIT_WEBHOOK` | Webhook ID for Reddit channel | -| `YOUTUBE_API_KEY` | An OAuth Key or Token are required for API access. [Docs](https://developers.google.com/youtube/v3/docs#calling-the-api) | -| `TMDB_API_KEY` | Required for API access. [Docs](https://developers.themoviedb.org/3/getting-started/introduction) | -| `NASA_API_KEY` | Required for API access. [Docs](https://api.nasa.gov/) | -| `WOLFRAM_API_KEY` | | -| `UNSPLASH_KEY` | Required for API access. Use the `access_token` given by Unsplash. [Docs](https://unsplash.com/documentation) | -| `IGDB_CLIENT_ID` | OAuth2 client ID for authenticating with the [IGDB API](https://api-docs.igdb.com/) | -| `IGDB_CLIENT_SECRET` | OAuth2 secret for authenticating with the IGDB API. *Leave empty if you're not using the IGDB API.* | +| Token | Description | +|-----------------------------|--------------------------------------------------------------------------------------------------------------------------| +| `TOKENS_GITHUB` | Personal access token for GitHub, raises rate limits from 60 to 5000 requests per hour. | +| `TOKENS_GIPHY` | Required for API access. [Docs](https://developers.giphy.com/docs/api) | +| `REDDIT_CLIENT_ID` | OAuth2 client ID for authenticating with the [reddit API](https://github.com/reddit-archive/reddit/wiki/OAuth2). | +| `REDDIT_SECRET` | OAuth2 secret for authenticating with the reddit API. *Leave empty if you're not using the reddit API.* | +| `REDDIT_WEBHOOK` | Webhook ID for Reddit channel | +| `TOKENS_YOUTUBE` | An OAuth Key or Token are required for API access. [Docs](https://developers.google.com/youtube/v3/docs#calling-the-api) | +| `TOKENS_TMDB` | Required for API access. [Docs](https://developers.themoviedb.org/3/getting-started/introduction) | +| `TOKENS_NASA` | Required for API access. [Docs](https://api.nasa.gov/) | +| `WOLFRAM_KEY` | Required for API access. [Docs](https://products.wolframalpha.com/simple-api/documentation) | +| `TOKENS_UNSPLASH` | Required for API access. Use the `access_token` given by Unsplash. [Docs](https://unsplash.com/documentation) | +| `TOKENS_IGDB_CLIENT_ID` | OAuth2 client ID for authenticating with the [IGDB API](https://api-docs.igdb.com/) | +| `TOKENS_IGDB_CLIENT_SECRET` | OAuth2 secret for authenticating with the IGDB API. *Leave empty if you're not using the IGDB API.* | --- ## Seasonal Cogs These variables might come in handy while working on certain cogs: -| Cog | Environment Variable | Description | -| -------- | -------- | -------- | -| Advent of Code | `AOC_LEADERBOARDS` | List of leaderboards separated by `::`. Each entry should have an `id,session cookie,join code` separated by commas in that order. | -| Advent of Code | `AOC_STAFF_LEADERBOARD_ID` | Integer ID of the staff leaderboard. | -| Advent of Code | `AOC_ROLE_ID` | ID of the advent of code role. -| Advent of Code | `AOC_IGNORED_DAYS` | Comma separated list of days to ignore while calculating score. | -| Advent of Code | `AOC_YEAR` | Debug variable to change the year used for AoC. | -| Advent of Code | `AOC_CHANNEL_ID` | The ID of the `#advent-of-code` channel | -| Advent of Code | `AOC_COMMANDS_CHANNEL_ID` | The ID of the `#advent-of-code-commands` channel | -| Advent of Code | `AOC_FALLBACK_SESSION` | | -| Advent of Code | `AOC_SESSION_COOKIE` | | -| Valentines | `LOVEFEST_ROLE_ID` | | -| Wolfram | `WOLFRAM_USER_LIMIT_DAY` | | -| Wolfram | `WOLFRAM_GUILD_LIMIT_DAY` | | +| Cog | Environment Variable | Description | +|------------|---------------------------|-----------------------------------------------------------------| +| Valentines | `ROLES_LOVEFEST` | ID of the role `@Lovefest` | +| Wolfram | `WOLFRAM_USER_LIMIT_DAY` | The amount of requests a user can make per day | +| Wolfram | `WOLFRAM_GUILD_LIMIT_DAY` | The amount of requests that can come from the say guild per day | -- cgit v1.2.3 From 88c52b4f7b4bc8242905e2d1818f5483494aa5ee Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sun, 7 May 2023 10:39:19 +0100 Subject: remove defaults column fix sir lancebot pg env var name --- .../guides/pydis-guides/contributing/sir-lancebot.md | 18 +++++++++--------- .../contributing/sir-lancebot/env-var-reference.md | 16 ++++++++-------- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index f4a6dd37..b88f2810 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -72,15 +72,15 @@ You will have to setup environment variables: The following variables are needed for running Sir Lancebot: -| Environment Variable | Description | -|--------------------------------|--------------------------------------------------------------------------------------------| -| `CLIENT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | -| `CLIENT_GUILD` | ID of the Discord Server | -| `ROLES_ADMIN` | ID of the role `@Admins` | -| `ROLES_HELPERS` | ID of the role `@Helpers` | -| `CHANNELS_ANNOUNCEMENTS` | ID of the `#announcements` channel | -| `CHANNELS_DEVLOG` | ID of the `#dev-log` channel | -| `CHANNEL_SIR_LANCEBOT_PLAYGROUND` | ID of the `#sir-lancebot-playground` channel | +| Environment Variable | Description | +|------------------------------------|--------------------------------------------------------------------------------------------| +| `CLIENT_TOKEN` | Bot Token from the [Discord developer portal](https://discord.com/developers/applications) | +| `CLIENT_GUILD` | ID of the Discord Server | +| `ROLES_ADMIN` | ID of the role `@Admins` | +| `ROLES_HELPERS` | ID of the role `@Helpers` | +| `CHANNELS_ANNOUNCEMENTS` | ID of the `#announcements` channel | +| `CHANNELS_DEVLOG` | ID of the `#dev-log` channel | +| `CHANNELS_SIR_LANCEBOT_PLAYGROUND` | ID of the `#sir-lancebot-playground` channel | [**Full environment variable reference for this project.**](../sir-lancebot/env-var-reference) diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md index 7e321241..629394d5 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md @@ -23,9 +23,9 @@ Additionally, you may find the following environment variables useful during dev | Environment Variable | Description | |----------------------------|------------------------------------------------------------------------------------------------------------| -| `CLIENT_DEBUG` | Debug mode of the bot | False | -| `CLIENT_PREFIX` | The bot's invocation prefix | `.` | -| `BRANDING_CYCLE_FREQUENCY` | Amount of days between cycling server icon | 3 | +| `CLIENT_DEBUG` | Debug mode of the bot | +| `CLIENT_PREFIX` | The bot's invocation prefix | +| `BRANDING_CYCLE_FREQUENCY` | Amount of days between cycling server icon | | `CLIENT_MONTH_OVERRIDE` | Integer in range `[0, 12]`, overrides current month w.r.t. seasonal decorators | | `REDIS_HOST` | The address to connect to for the Redis database. | | `REDIS_PORT` | The port on which the Redis database is exposed. | @@ -57,8 +57,8 @@ If you will be working with an external service, you might have to set one of th ## Seasonal Cogs These variables might come in handy while working on certain cogs: -| Cog | Environment Variable | Description | -|------------|---------------------------|-----------------------------------------------------------------| -| Valentines | `ROLES_LOVEFEST` | ID of the role `@Lovefest` | -| Wolfram | `WOLFRAM_USER_LIMIT_DAY` | The amount of requests a user can make per day | -| Wolfram | `WOLFRAM_GUILD_LIMIT_DAY` | The amount of requests that can come from the say guild per day | +| Cog | Environment Variable | Description | +|------------|---------------------------|------------------------------------------------------------------| +| Valentines | `ROLES_LOVEFEST` | ID of the role `@Lovefest` | +| Wolfram | `WOLFRAM_USER_LIMIT_DAY` | The amount of requests a user can make per day | +| Wolfram | `WOLFRAM_GUILD_LIMIT_DAY` | The amount of requests that can come from the same guild per day | -- cgit v1.2.3 From 1e99244f06b710e5e53da2336527fcd1cc80786a Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sun, 7 May 2023 10:42:19 +0100 Subject: remove unused cycle_frequency env var --- .../guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md | 1 - 1 file changed, 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md index 629394d5..342da12b 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot/env-var-reference.md @@ -25,7 +25,6 @@ Additionally, you may find the following environment variables useful during dev |----------------------------|------------------------------------------------------------------------------------------------------------| | `CLIENT_DEBUG` | Debug mode of the bot | | `CLIENT_PREFIX` | The bot's invocation prefix | -| `BRANDING_CYCLE_FREQUENCY` | Amount of days between cycling server icon | | `CLIENT_MONTH_OVERRIDE` | Integer in range `[0, 12]`, overrides current month w.r.t. seasonal decorators | | `REDIS_HOST` | The address to connect to for the Redis database. | | `REDIS_PORT` | The port on which the Redis database is exposed. | -- cgit v1.2.3 From dda44dde4c61ee010de0433fb020edb2e87c35d7 Mon Sep 17 00:00:00 2001 From: shtlrs Date: Sun, 7 May 2023 15:59:34 +0100 Subject: update forgotten mentions of sir-lancebot-commands channel This also updates: - docker compose commands - use fake redis env var --- .../resources/guides/pydis-guides/contributing/sir-lancebot.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index b88f2810..7861c3d9 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -57,9 +57,10 @@ You will need your own test server and bot account on Discord to test your chang 3. Create the following text channels: * `#announcements` * `#dev-log` - * `#sir-lancebot-commands` + * `#sir-lancebot-playground` 4. Create the following roles: * `@Admins` + * `@Helpers` 5. Note down the IDs for your server, as well as any channels and roles created. * [**Learn how to obtain the ID of a server, channel or role here.**](../setting-test-server-and-bot-account#obtain-the-ids) @@ -86,7 +87,7 @@ The following variables are needed for running Sir Lancebot: --- -While not required, we advise you set `USE_FAKEREDIS` to `true` in development to avoid the need of setting up a Redis server. +While not required, we advise you set `REDIS_USE_FAKEREDIS` to `true` in development to avoid the need of setting up a Redis server. It does mean you may lose persistent data on restart but this is non-critical. Otherwise, please see the below linked guide for Redis related variables. {: .notification .is-warning } @@ -96,11 +97,11 @@ Otherwise, please see the below linked guide for Redis related variables. The sections below describe the two ways you can run this project. We recommend Docker as it requires less setup. ## Run with Docker -Make sure to have Docker running, then use the Docker command `docker-compose up` in the project root. +Make sure to have Docker running, then use the Docker command `docker compose up` in the project root. The first time you run this command, it may take a few minutes while Docker downloads and installs Sir Lancebot's dependencies. ```shell -$ docker-compose up +$ docker compose up ``` If you get any Docker related errors, reference the [Possible Issues](../docker#possible-issues) section of the Docker page. -- cgit v1.2.3 From 07855963a1eedd80c410ab2dd51fcae1200c9cee Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Wed, 10 May 2023 12:30:57 +0200 Subject: Switch to ruff for linting --- .github/workflows/lint-test.yaml | 17 +- .pre-commit-config.yaml | 12 +- poetry.lock | 700 ++++++--------------- pydis_site/apps/api/admin.py | 29 +- pydis_site/apps/api/github_utils.py | 13 +- pydis_site/apps/api/models/bot/message.py | 7 +- pydis_site/apps/api/models/bot/metricity.py | 19 +- pydis_site/apps/api/tests/base.py | 3 +- pydis_site/apps/api/tests/test_bumped_threads.py | 2 +- pydis_site/apps/api/tests/test_deleted_messages.py | 11 +- .../apps/api/tests/test_documentation_links.py | 2 +- pydis_site/apps/api/tests/test_filters.py | 12 +- pydis_site/apps/api/tests/test_github_utils.py | 41 +- pydis_site/apps/api/tests/test_infractions.py | 110 ++-- pydis_site/apps/api/tests/test_models.py | 4 +- pydis_site/apps/api/tests/test_nominations.py | 2 +- .../apps/api/tests/test_off_topic_channel_names.py | 2 +- .../apps/api/tests/test_offensive_message.py | 10 +- pydis_site/apps/api/tests/test_reminders.py | 4 +- pydis_site/apps/api/tests/test_roles.py | 2 +- pydis_site/apps/api/tests/test_rules.py | 2 +- pydis_site/apps/api/tests/test_users.py | 29 +- pydis_site/apps/api/tests/test_validators.py | 4 +- pydis_site/apps/api/views.py | 4 +- pydis_site/apps/api/viewsets/bot/filters.py | 4 +- .../api/viewsets/bot/off_topic_channel_name.py | 7 +- pydis_site/apps/api/viewsets/bot/user.py | 5 +- pydis_site/apps/content/models/tag.py | 3 +- .../guides/pydis-guides/contributing/linting.md | 2 +- pydis_site/apps/content/tests/helpers.py | 20 +- pydis_site/apps/content/urls.py | 2 +- pydis_site/apps/content/utils.py | 16 +- pydis_site/apps/content/views/tags.py | 3 +- pydis_site/apps/events/urls.py | 2 +- pydis_site/apps/events/views/page.py | 3 +- .../apps/home/tests/test_repodata_helpers.py | 2 +- pydis_site/apps/home/views.py | 13 +- pydis_site/apps/redirect/urls.py | 25 +- pydis_site/apps/redirect/views.py | 3 +- pydis_site/apps/resources/views.py | 7 +- .../staff/templatetags/deletedmessage_filters.py | 3 +- .../staff/tests/test_deletedmessage_filters.py | 2 +- pyproject.toml | 39 +- static-builds/netlify_build.py | 6 +- 44 files changed, 445 insertions(+), 763 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/.github/workflows/lint-test.yaml b/.github/workflows/lint-test.yaml index 1c744470..a12fb650 100644 --- a/.github/workflows/lint-test.yaml +++ b/.github/workflows/lint-test.yaml @@ -24,20 +24,11 @@ jobs: # We will not run `flake8` here, as we will use a separate flake8 # action. - name: Run pre-commit hooks - run: SKIP=flake8 pre-commit run --all-files + run: SKIP=ruff pre-commit run --all-files - # Run flake8 and have it format the linting errors in the format of - # the GitHub Workflow command to register error annotations. This - # means that our flake8 output is automatically added as an error - # annotation to both the run result and in the "Files" tab of a - # pull request. - # - # Format used: - # ::error file={filename},line={line},col={col}::{message} - - name: Run flake8 - run: "flake8 \ - --format='::error file=%(path)s,line=%(row)d,col=%(col)d::\ - [flake8] %(code)s: %(text)s'" + # Run `ruff` using github formatting to enable automatic inline annotations. + - name: Run ruff + run: "ruff check --format=github ." - name: Migrations and run tests with coverage.py run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b2a03559..700dd0a0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,15 +10,11 @@ repos: args: [--fix=lf] - id: trailing-whitespace args: [--markdown-linebreak-ext=md] - - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.5.1 - hooks: - - id: python-check-blanket-noqa - repo: local hooks: - - id: flake8 - name: Flake8 - description: This hook runs flake8 within our project's environment. - entry: poetry run flake8 + - id: ruff + name: ruff + description: This hook runs ruff within our project's environment. + entry: poetry run ruff language: system types: [python] diff --git a/poetry.lock b/poetry.lock index d6e09cbe..4d9a87de 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "anyio" @@ -36,58 +36,16 @@ files = [ [package.extras] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] - -[[package]] -name = "bandit" -version = "1.7.4" -description = "Security oriented static analyser for python code." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, - {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} -GitPython = ">=1.0.1" -PyYAML = ">=5.3.1" -stevedore = ">=1.20.0" - -[package.extras] -test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml"] -toml = ["toml"] -yaml = ["PyYAML"] - [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, + {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, + {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, ] [[package]] @@ -181,100 +139,87 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.0.1" +version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false -python-versions = "*" -files = [ - {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"}, - {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"}, +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, ] [[package]] @@ -355,35 +300,31 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "39.0.1" +version = "40.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:6687ef6d0a6497e2b58e7c5b852b53f62142cfa7cd1555795758934da363a965"}, - {file = "cryptography-39.0.1-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:706843b48f9a3f9b9911979761c91541e3d90db1ca905fd63fee540a217698bc"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5d2d8b87a490bfcd407ed9d49093793d0f75198a35e6eb1a923ce1ee86c62b41"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e17b26de248c33f3acffb922748151d71827d6021d98c70e6c1a25ddd78505"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e124352fd3db36a9d4a21c1aa27fd5d051e621845cb87fb851c08f4f75ce8be6"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:5aa67414fcdfa22cf052e640cb5ddc461924a045cacf325cd164e65312d99502"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:35f7c7d015d474f4011e859e93e789c87d21f6f4880ebdc29896a60403328f1f"}, - {file = "cryptography-39.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f24077a3b5298a5a06a8e0536e3ea9ec60e4c7ac486755e5fb6e6ea9b3500106"}, - {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f0c64d1bd842ca2633e74a1a28033d139368ad959872533b1bab8c80e8240a0c"}, - {file = "cryptography-39.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0f8da300b5c8af9f98111ffd512910bc792b4c77392a9523624680f7956a99d4"}, - {file = "cryptography-39.0.1-cp36-abi3-win32.whl", hash = "sha256:fe913f20024eb2cb2f323e42a64bdf2911bb9738a15dba7d3cce48151034e3a8"}, - {file = "cryptography-39.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:ced4e447ae29ca194449a3f1ce132ded8fcab06971ef5f618605aacaa612beac"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:807ce09d4434881ca3a7594733669bd834f5b2c6d5c7e36f8c00f691887042ad"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c5caeb8188c24888c90b5108a441c106f7faa4c4c075a2bcae438c6e8ca73cef"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4789d1e3e257965e960232345002262ede4d094d1a19f4d3b52e48d4d8f3b885"}, - {file = "cryptography-39.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:96f1157a7c08b5b189b16b47bc9db2332269d6680a196341bf30046330d15388"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e422abdec8b5fa8462aa016786680720d78bdce7a30c652b7fadf83a4ba35336"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:b0afd054cd42f3d213bf82c629efb1ee5f22eba35bf0eec88ea9ea7304f511a2"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:6f8ba7f0328b79f08bdacc3e4e66fb4d7aab0c3584e0bd41328dce5262e26b2e"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ef8b72fa70b348724ff1218267e7f7375b8de4e8194d1636ee60510aae104cd0"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:aec5a6c9864be7df2240c382740fcf3b96928c46604eaa7f3091f58b878c0bb6"}, - {file = "cryptography-39.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdd188c8a6ef8769f148f88f859884507b954cc64db6b52f66ef199bb9ad660a"}, - {file = "cryptography-39.0.1.tar.gz", hash = "sha256:d1f6198ee6d9148405e49887803907fe8962a23e6c6f83ea7d98f1c0de375695"}, + {file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:8f79b5ff5ad9d3218afb1e7e20ea74da5f76943ee5edb7f76e56ec5161ec782b"}, + {file = "cryptography-40.0.2-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:05dc219433b14046c476f6f09d7636b92a1c3e5808b9a6536adf4932b3b2c440"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4df2af28d7bedc84fe45bd49bc35d710aede676e2a4cb7fc6d103a2adc8afe4d"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dcca15d3a19a66e63662dc8d30f8036b07be851a8680eda92d079868f106288"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a04386fb7bc85fab9cd51b6308633a3c271e3d0d3eae917eebab2fac6219b6d2"}, + {file = "cryptography-40.0.2-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:adc0d980fd2760c9e5de537c28935cc32b9353baaf28e0814df417619c6c8c3b"}, + {file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d5a1bd0e9e2031465761dfa920c16b0065ad77321d8a8c1f5ee331021fda65e9"}, + {file = "cryptography-40.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a95f4802d49faa6a674242e25bfeea6fc2acd915b5e5e29ac90a32b1139cae1c"}, + {file = "cryptography-40.0.2-cp36-abi3-win32.whl", hash = "sha256:aecbb1592b0188e030cb01f82d12556cf72e218280f621deed7d806afd2113f9"}, + {file = "cryptography-40.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:b12794f01d4cacfbd3177b9042198f3af1c856eedd0a98f10f141385c809a14b"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:142bae539ef28a1c76794cca7f49729e7c54423f615cfd9b0b1fa90ebe53244b"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:956ba8701b4ffe91ba59665ed170a2ebbdc6fc0e40de5f6059195d9f2b33ca0e"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f01c9863da784558165f5d4d916093737a75203a5c5286fde60e503e4276c7a"}, + {file = "cryptography-40.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3daf9b114213f8ba460b829a02896789751626a2a4e7a43a28ee77c04b5e4958"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48f388d0d153350f378c7f7b41497a54ff1513c816bcbbcafe5b829e59b9ce5b"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c0764e72b36a3dc065c155e5b22f93df465da9c39af65516fe04ed3c68c92636"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:cbaba590180cba88cb99a5f76f90808a624f18b169b90a4abb40c1fd8c19420e"}, + {file = "cryptography-40.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7a38250f433cd41df7fcb763caa3ee9362777fdb4dc642b9a349721d2bf47404"}, + {file = "cryptography-40.0.2.tar.gz", hash = "sha256:c33c0d32b8594fa647d2e01dbccc303478e16fdd7cf98652d5b3ed11aa5e5c99"}, ] [package.dependencies] @@ -392,10 +333,10 @@ cffi = ">=1.12" [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -pep8test = ["black", "check-manifest", "mypy", "ruff", "types-pytz", "types-requests"] +pep8test = ["black", "check-manifest", "mypy", "ruff"] sdist = ["setuptools-rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist", "pytz"] +test = ["iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist"] test-randomorder = ["pytest-randomly"] tox = ["tox"] @@ -536,193 +477,19 @@ pytz = "*" [[package]] name = "filelock" -version = "3.9.0" +version = "3.12.0" description = "A platform independent file lock." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "filelock-3.9.0-py3-none-any.whl", hash = "sha256:f58d535af89bb9ad5cd4df046f741f8553a418c01a7856bf0d173bbc9f6bd16d"}, - {file = "filelock-3.9.0.tar.gz", hash = "sha256:7b319f24340b51f55a2bf7a12ac0755a9b03e718311dac567a0f4f7fabd2f5de"}, + {file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"}, + {file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -testing = ["covdefaults (>=2.2.2)", "coverage (>=7.0.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] - -[[package]] -name = "flake8" -version = "6.0.0" -description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"}, - {file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.10.0,<2.11.0" -pyflakes = ">=3.0.0,<3.1.0" - -[[package]] -name = "flake8-annotations" -version = "3.0.1" -description = "Flake8 Type Annotation Checks" -category = "dev" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8_annotations-3.0.1-py3-none-any.whl", hash = "sha256:af78e3216ad800d7e144745ece6df706c81b3255290cbf870e54879d495e8ade"}, - {file = "flake8_annotations-3.0.1.tar.gz", hash = "sha256:ff37375e71e3b83f2a5a04d443c41e2c407de557a884f3300a7fa32f3c41cb0a"}, -] - -[package.dependencies] -attrs = ">=21.4" -flake8 = ">=5.0" - -[[package]] -name = "flake8-bandit" -version = "4.1.1" -description = "Automated security testing with bandit and flake8." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8_bandit-4.1.1-py3-none-any.whl", hash = "sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d"}, - {file = "flake8_bandit-4.1.1.tar.gz", hash = "sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e"}, -] - -[package.dependencies] -bandit = ">=1.7.3" -flake8 = ">=5.0.0" - -[[package]] -name = "flake8-bugbear" -version = "23.5.9" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -category = "dev" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8-bugbear-23.5.9.tar.gz", hash = "sha256:695c84a5d7da54eb35d79a7354dbaf3aaba80de32250608868aa1c85534b2a86"}, - {file = "flake8_bugbear-23.5.9-py3-none-any.whl", hash = "sha256:631fa927fbc799e8ca636b849dd7dfc304812287137b6ecb3277821f028bee40"}, -] - -[package.dependencies] -attrs = ">=19.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "flake8-docstrings" -version = "1.7.0" -description = "Extension for flake8 which uses pydocstyle to check docstrings" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, - {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, -] - -[package.dependencies] -flake8 = ">=3" -pydocstyle = ">=2.1" - -[[package]] -name = "flake8-import-order" -version = "0.18.2" -description = "Flake8 and pylama plugin that checks the ordering of import statements." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "flake8-import-order-0.18.2.tar.gz", hash = "sha256:e23941f892da3e0c09d711babbb0c73bc735242e9b216b726616758a920d900e"}, - {file = "flake8_import_order-0.18.2-py2.py3-none-any.whl", hash = "sha256:82ed59f1083b629b030ee9d3928d9e06b6213eb196fe745b3a7d4af2168130df"}, -] - -[package.dependencies] -pycodestyle = "*" -setuptools = "*" - -[[package]] -name = "flake8-string-format" -version = "0.3.0" -description = "string format checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, - {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, -] - -[package.dependencies] -flake8 = "*" - -[[package]] -name = "flake8-tidy-imports" -version = "4.8.0" -description = "A flake8 plugin that helps you write tidier imports." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-tidy-imports-4.8.0.tar.gz", hash = "sha256:df44f9c841b5dfb3a7a1f0da8546b319d772c2a816a1afefcce43e167a593d83"}, - {file = "flake8_tidy_imports-4.8.0-py3-none-any.whl", hash = "sha256:25bd9799358edefa0e010ce2c587b093c3aba942e96aeaa99b6d0500ae1bf09c"}, -] - -[package.dependencies] -flake8 = ">=3.8.0" - -[[package]] -name = "flake8-todo" -version = "0.7" -description = "TODO notes checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "flake8-todo-0.7.tar.gz", hash = "sha256:6e4c5491ff838c06fe5a771b0e95ee15fc005ca57196011011280fc834a85915"}, -] - -[package.dependencies] -pycodestyle = ">=2.0.0,<3.0.0" - -[[package]] -name = "gitdb" -version = "4.0.10" -description = "Git Object Database" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, - {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.31" -description = "GitPython is a Python library used to interact with Git repositories" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "GitPython-3.1.31-py3-none-any.whl", hash = "sha256:f04893614f6aa713a60cbbe1e6a97403ef633103cdd0ef5eb6efe0deb98dbe8d"}, - {file = "GitPython-3.1.31.tar.gz", hash = "sha256:8ce3bcf69adfdf7c7d503e78fd3b1c492af782d58893b650adb2ac8912ddd573"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" +docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] [[package]] name = "gunicorn" @@ -759,14 +526,14 @@ files = [ [[package]] name = "httpcore" -version = "0.16.3" +version = "0.17.0" description = "A minimal low-level HTTP client." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, - {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, + {file = "httpcore-0.17.0-py3-none-any.whl", hash = "sha256:0fdfea45e94f0c9fd96eab9286077f9ff788dd186635ae61b312693e4d943599"}, + {file = "httpcore-0.17.0.tar.gz", hash = "sha256:cc045a3241afbf60ce056202301b4d8b6af08845e3294055eb26b09913ef903c"}, ] [package.dependencies] @@ -805,14 +572,14 @@ socks = ["socksio (>=1.0.0,<2.0.0)"] [[package]] name = "identify" -version = "2.5.18" +version = "2.5.24" description = "File identification library for Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "identify-2.5.18-py2.py3-none-any.whl", hash = "sha256:93aac7ecf2f6abf879b8f29a8002d3c6de7086b8c28d88e1ad15045a15ab63f9"}, - {file = "identify-2.5.18.tar.gz", hash = "sha256:89e144fa560cc4cffb6ef2ab5e9fb18ed9f9b3cb054384bab4b95c12f6c309fe"}, + {file = "identify-2.5.24-py2.py3-none-any.whl", hash = "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d"}, + {file = "identify-2.5.24.tar.gz", hash = "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4"}, ] [package.extras] @@ -860,18 +627,6 @@ files = [ [package.extras] testing = ["coverage", "pyyaml"] -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - [[package]] name = "mslex" version = "0.3.0" @@ -899,48 +654,21 @@ files = [ [package.dependencies] setuptools = "*" -[[package]] -name = "pbr" -version = "5.11.1" -description = "Python Build Reasonableness" -category = "dev" -optional = false -python-versions = ">=2.6" -files = [ - {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, - {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, -] - -[[package]] -name = "pep8-naming" -version = "0.13.3" -description = "Check PEP-8 naming conventions, plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, - {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, -] - -[package.dependencies] -flake8 = ">=5.0.0" - [[package]] name = "platformdirs" -version = "3.0.0" +version = "3.5.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.0.0-py3-none-any.whl", hash = "sha256:b1d5eb14f221506f50d6604a561f4c5786d9e80355219694a1b244bcd96f4567"}, - {file = "platformdirs-3.0.0.tar.gz", hash = "sha256:8a1228abb1ef82d788f74139988b137e78692984ec7b08eaa6c65f1723af28f9"}, + {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, + {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pre-commit" @@ -978,26 +706,26 @@ twisted = ["twisted"] [[package]] name = "psutil" -version = "5.9.4" +version = "5.9.5" description = "Cross-platform lib for process and system monitoring in Python." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ - {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, - {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, - {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"}, - {file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"}, - {file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"}, - {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"}, - {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"}, - {file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"}, - {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"}, - {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"}, - {file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"}, - {file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"}, - {file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"}, - {file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"}, + {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, + {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, + {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, + {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, + {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, + {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, + {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, + {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, ] [package.extras] @@ -1075,18 +803,6 @@ files = [ {file = "psycopg2_binary-2.9.6-cp39-cp39-win_amd64.whl", hash = "sha256:f6a88f384335bb27812293fdb11ac6aee2ca3f51d3c7820fe03de0a304ab6249"}, ] -[[package]] -name = "pycodestyle" -version = "2.10.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, - {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, -] - [[package]] name = "pycparser" version = "2.21" @@ -1099,36 +815,6 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -[[package]] -name = "pydocstyle" -version = "6.3.0" -description = "Python docstring style checker" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, - {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, -] - -[package.dependencies] -snowballstemmer = ">=2.2.0" - -[package.extras] -toml = ["tomli (>=1.2.3)"] - -[[package]] -name = "pyflakes" -version = "3.0.1" -description = "passive checker of Python programs" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"}, - {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"}, -] - [[package]] name = "pyjwt" version = "2.7.0" @@ -1202,14 +888,14 @@ test = ["pyaml", "pytest", "toml"] [[package]] name = "pytz" -version = "2022.7.1" +version = "2023.3" description = "World timezone definitions, modern and historical" category = "main" optional = false python-versions = "*" files = [ - {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"}, - {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"}, + {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, + {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, ] [[package]] @@ -1264,26 +950,53 @@ files = [ [[package]] name = "requests" -version = "2.28.2" +version = "2.30.0" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" files = [ - {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, - {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, + {file = "requests-2.30.0-py3-none-any.whl", hash = "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294"}, + {file = "requests-2.30.0.tar.gz", hash = "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"}, ] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "ruff" +version = "0.0.265" +description = "An extremely fast Python linter, written in Rust." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.265-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:30ddfe22de6ce4eb1260408f4480bbbce998f954dbf470228a21a9b2c45955e4"}, + {file = "ruff-0.0.265-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:a11bd0889e88d3342e7bc514554bb4461bf6cc30ec115821c2425cfaac0b1b6a"}, + {file = "ruff-0.0.265-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a9b38bdb40a998cbc677db55b6225a6c4fadcf8819eb30695e1b8470942426b"}, + {file = "ruff-0.0.265-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8b44a245b60512403a6a03a5b5212da274d33862225c5eed3bcf12037eb19bb"}, + {file = "ruff-0.0.265-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b279fa55ea175ef953208a6d8bfbcdcffac1c39b38cdb8c2bfafe9222add70bb"}, + {file = "ruff-0.0.265-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5028950f7af9b119d43d91b215d5044976e43b96a0d1458d193ef0dd3c587bf8"}, + {file = "ruff-0.0.265-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4057eb539a1d88eb84e9f6a36e0a999e0f261ed850ae5d5817e68968e7b89ed9"}, + {file = "ruff-0.0.265-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d586e69ab5cbf521a1910b733412a5735936f6a610d805b89d35b6647e2a66aa"}, + {file = "ruff-0.0.265-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa17b13cd3f29fc57d06bf34c31f21d043735cc9a681203d634549b0e41047d1"}, + {file = "ruff-0.0.265-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9ac13b11d9ad3001de9d637974ec5402a67cefdf9fffc3929ab44c2fcbb850a1"}, + {file = "ruff-0.0.265-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:62a9578b48cfd292c64ea3d28681dc16b1aa7445b7a7709a2884510fc0822118"}, + {file = "ruff-0.0.265-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d0f9967f84da42d28e3d9d9354cc1575f96ed69e6e40a7d4b780a7a0418d9409"}, + {file = "ruff-0.0.265-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1d5a8de2fbaf91ea5699451a06f4074e7a312accfa774ad9327cde3e4fda2081"}, + {file = "ruff-0.0.265-py3-none-win32.whl", hash = "sha256:9e9db5ccb810742d621f93272e3cc23b5f277d8d00c4a79668835d26ccbe48dd"}, + {file = "ruff-0.0.265-py3-none-win_amd64.whl", hash = "sha256:f54facf286103006171a00ce20388d88ed1d6732db3b49c11feb9bf3d46f90e9"}, + {file = "ruff-0.0.265-py3-none-win_arm64.whl", hash = "sha256:c78470656e33d32ddc54e8482b1b0fc6de58f1195586731e5ff1405d74421499"}, + {file = "ruff-0.0.265.tar.gz", hash = "sha256:53c17f0dab19ddc22b254b087d1381b601b155acfa8feed514f0d6a413d0ab3a"}, +] + [[package]] name = "sentry-sdk" version = "1.22.2" @@ -1328,14 +1041,14 @@ tornado = ["tornado (>=5)"] [[package]] name = "setuptools" -version = "67.4.0" +version = "67.7.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "setuptools-67.4.0-py3-none-any.whl", hash = "sha256:f106dee1b506dee5102cc3f3e9e68137bbad6d47b616be7991714b0c62204251"}, - {file = "setuptools-67.4.0.tar.gz", hash = "sha256:e5fd0a713141a4a105412233c63dc4e17ba0090c8e8334594ac790ec97792330"}, + {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"}, + {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"}, ] [package.extras] @@ -1343,18 +1056,6 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-g testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] -[[package]] -name = "smmap" -version = "5.0.0" -description = "A pure Python implementation of a sliding window memory map manager" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"}, - {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, -] - [[package]] name = "sniffio" version = "1.3.0" @@ -1367,18 +1068,6 @@ files = [ {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, ] -[[package]] -name = "snowballstemmer" -version = "2.2.0" -description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, - {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, -] - [[package]] name = "sqlparse" version = "0.4.4" @@ -1396,21 +1085,6 @@ dev = ["build", "flake8"] doc = ["sphinx"] test = ["pytest", "pytest-cov"] -[[package]] -name = "stevedore" -version = "5.0.0" -description = "Manage dynamic plugins for Python applications" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "stevedore-5.0.0-py3-none-any.whl", hash = "sha256:bd5a71ff5e5e5f5ea983880e4a1dd1bb47f8feebbb3d95b592398e2f02194771"}, - {file = "stevedore-5.0.0.tar.gz", hash = "sha256:2c428d2338976279e8eb2196f7a94910960d9f7ba2f41f3988511e95ca447021"}, -] - -[package.dependencies] -pbr = ">=2.0.0,<2.1.0 || >2.1.0" - [[package]] name = "taskipy" version = "1.10.4" @@ -1443,26 +1117,26 @@ files = [ [[package]] name = "tzdata" -version = "2022.7" +version = "2023.3" description = "Provider of IANA time zone data" category = "main" optional = false python-versions = ">=2" files = [ - {file = "tzdata-2022.7-py2.py3-none-any.whl", hash = "sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d"}, - {file = "tzdata-2022.7.tar.gz", hash = "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"}, + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, ] [[package]] name = "urllib3" -version = "1.26.14" +version = "1.26.15" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"}, - {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"}, + {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, + {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, ] [package.extras] @@ -1472,24 +1146,24 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.19.0" +version = "20.23.0" description = "Virtual Python Environment builder" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.19.0-py3-none-any.whl", hash = "sha256:54eb59e7352b573aa04d53f80fc9736ed0ad5143af445a1e539aada6eb947dd1"}, - {file = "virtualenv-20.19.0.tar.gz", hash = "sha256:37a640ba82ed40b226599c522d411e4be5edb339a0c0de030c0dc7b646d61590"}, + {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"}, + {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"}, ] [package.dependencies] distlib = ">=0.3.6,<1" -filelock = ">=3.4.1,<4" -platformdirs = ">=2.4,<4" +filelock = ">=3.11,<4" +platformdirs = ">=3.2,<4" [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] -test = ["covdefaults (>=2.2.2)", "coverage (>=7.1)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23)", "pytest (>=7.2.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"] [[package]] name = "whitenoise" @@ -1509,4 +1183,4 @@ brotli = ["Brotli"] [metadata] lock-version = "2.0" python-versions = "3.10.*" -content-hash = "a89b60823f9d7717b78c1071654c0c1f237768669a8e37e76175730de209e804" +content-hash = "f9076a1d72b610e77d0c389a4992c814a4c81028232a1ec4f060f77f2cb9125c" diff --git a/pydis_site/apps/api/admin.py b/pydis_site/apps/api/admin.py index e123d150..f3cc0405 100644 --- a/pydis_site/apps/api/admin.py +++ b/pydis_site/apps/api/admin.py @@ -1,7 +1,7 @@ from __future__ import annotations import json -from typing import Iterable, Optional, Tuple +from collections.abc import Iterable from django import urls from django.contrib import admin @@ -62,16 +62,16 @@ class InfractionActorFilter(admin.SimpleListFilter): title = "Actor" parameter_name = "actor" - def lookups(self, request: HttpRequest, model: NominationAdmin) -> Iterable[Tuple[int, str]]: + def lookups(self, request: HttpRequest, model: NominationAdmin) -> Iterable[tuple[int, str]]: """Selectable values for viewer to filter by.""" actor_ids = Infraction.objects.order_by().values_list("actor").distinct() actors = User.objects.filter(id__in=actor_ids) return ((a.id, a.username) for a in actors) - def queryset(self, request: HttpRequest, queryset: QuerySet) -> Optional[QuerySet]: + def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet | None: """Query to filter the list of Users against.""" if not self.value(): - return + return None return queryset.filter(actor__id=self.value()) @@ -149,7 +149,7 @@ class DeletedMessageAdmin(admin.ModelAdmin): list_display = ("id", "author", "channel_id") - def embed_data(self, message: DeletedMessage) -> Optional[str]: + def embed_data(self, message: DeletedMessage) -> str | None: """Format embed data in a code block for better readability.""" if message.embeds: return format_html( @@ -157,6 +157,7 @@ class DeletedMessageAdmin(admin.ModelAdmin): "{0}", json.dumps(message.embeds, indent=4) ) + return None embed_data.short_description = "Embeds" @@ -229,16 +230,16 @@ class NominationActorFilter(admin.SimpleListFilter): title = "Actor" parameter_name = "actor" - def lookups(self, request: HttpRequest, model: NominationAdmin) -> Iterable[Tuple[int, str]]: + def lookups(self, request: HttpRequest, model: NominationAdmin) -> Iterable[tuple[int, str]]: """Selectable values for viewer to filter by.""" actor_ids = NominationEntry.objects.order_by().values_list("actor").distinct() actors = User.objects.filter(id__in=actor_ids) return ((a.id, a.username) for a in actors) - def queryset(self, request: HttpRequest, queryset: QuerySet) -> Optional[QuerySet]: + def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet | None: """Query to filter the list of Users against.""" if not self.value(): - return + return None nomination_ids = NominationEntry.objects.filter( actor__id=self.value() ).values_list("nomination_id").distinct() @@ -292,16 +293,16 @@ class NominationEntryActorFilter(admin.SimpleListFilter): title = "Actor" parameter_name = "actor" - def lookups(self, request: HttpRequest, model: NominationAdmin) -> Iterable[Tuple[int, str]]: + def lookups(self, request: HttpRequest, model: NominationAdmin) -> Iterable[tuple[int, str]]: """Selectable values for viewer to filter by.""" actor_ids = NominationEntry.objects.order_by().values_list("actor").distinct() actors = User.objects.filter(id__in=actor_ids) return ((a.id, a.username) for a in actors) - def queryset(self, request: HttpRequest, queryset: QuerySet) -> Optional[QuerySet]: + def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet | None: """Query to filter the list of Users against.""" if not self.value(): - return + return None return queryset.filter(actor__id=self.value()) @@ -425,15 +426,15 @@ class UserRoleFilter(admin.SimpleListFilter): title = "Role" parameter_name = "role" - def lookups(self, request: HttpRequest, model: UserAdmin) -> Iterable[Tuple[str, str]]: + def lookups(self, request: HttpRequest, model: UserAdmin) -> Iterable[tuple[str, str]]: """Selectable values for viewer to filter by.""" roles = Role.objects.all() return ((r.name, r.name) for r in roles) - def queryset(self, request: HttpRequest, queryset: QuerySet) -> Optional[QuerySet]: + def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet | None: """Query to filter the list of Users against.""" if not self.value(): - return + return None role = Role.objects.get(name=self.value()) return queryset.filter(roles__contains=[role.id]) diff --git a/pydis_site/apps/api/github_utils.py b/pydis_site/apps/api/github_utils.py index 44c571c3..af659195 100644 --- a/pydis_site/apps/api/github_utils.py +++ b/pydis_site/apps/api/github_utils.py @@ -82,7 +82,7 @@ def generate_token() -> str: Refer to: https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#authenticating-as-a-github-app """ - now = datetime.datetime.now() + now = datetime.datetime.now(tz=datetime.timezone.utc) return jwt.encode( { "iat": math.floor((now - datetime.timedelta(seconds=60)).timestamp()), # Issued at @@ -145,8 +145,12 @@ def authorize(owner: str, repo: str) -> httpx.Client: def check_run_status(run: WorkflowRun) -> str: """Check if the provided run has been completed, otherwise raise an exception.""" - created_at = datetime.datetime.strptime(run.created_at, settings.GITHUB_TIMESTAMP_FORMAT) - run_time = datetime.datetime.utcnow() - created_at + created_at = ( + datetime.datetime + .strptime(run.created_at, settings.GITHUB_TIMESTAMP_FORMAT) + .replace(tzinfo=datetime.timezone.utc) + ) + run_time = datetime.datetime.now(tz=datetime.timezone.utc) - created_at if run.status != "completed": if run_time <= MAX_RUN_TIME: @@ -154,8 +158,7 @@ def check_run_status(run: WorkflowRun) -> str: f"The requested run is still pending. It was created " f"{run_time.seconds // 60}:{run_time.seconds % 60 :>02} minutes ago." ) - else: - raise RunTimeoutError("The requested workflow was not ready in time.") + raise RunTimeoutError("The requested workflow was not ready in time.") if run.conclusion != "success": # The action failed, or did not run diff --git a/pydis_site/apps/api/models/bot/message.py b/pydis_site/apps/api/models/bot/message.py index 89ae27e4..d8147cd4 100644 --- a/pydis_site/apps/api/models/bot/message.py +++ b/pydis_site/apps/api/models/bot/message.py @@ -61,9 +61,10 @@ class Message(ModelReprMixin, models.Model): @property def timestamp(self) -> datetime.datetime: """Attribute that represents the message timestamp as derived from the snowflake id.""" - return datetime.datetime.utcfromtimestamp( - ((self.id >> 22) + 1420070400000) / 1000 - ).replace(tzinfo=datetime.timezone.utc) + return datetime.datetime.fromtimestamp( + ((self.id >> 22) + 1420070400000) / 1000, + tz=datetime.timezone.utc, + ) class Meta: """Metadata provided for Django's ORM.""" diff --git a/pydis_site/apps/api/models/bot/metricity.py b/pydis_site/apps/api/models/bot/metricity.py index f53dd33c..a55f5e5b 100644 --- a/pydis_site/apps/api/models/bot/metricity.py +++ b/pydis_site/apps/api/models/bot/metricity.py @@ -1,4 +1,3 @@ -from typing import List, Tuple from django.db import connections @@ -10,10 +9,9 @@ EXCLUDE_CHANNELS = ( ) -class NotFoundError(Exception): # noqa: N818 +class NotFoundError(Exception): """Raised when an entity cannot be found.""" - pass class Metricity: @@ -31,15 +29,14 @@ class Metricity: def user(self, user_id: str) -> dict: """Query a user's data.""" # TODO: Swap this back to some sort of verified at date - columns = ["joined_at"] - query = f"SELECT {','.join(columns)} FROM users WHERE id = '%s'" + query = "SELECT joined_at FROM users WHERE id = '%s'" self.cursor.execute(query, [user_id]) values = self.cursor.fetchone() if not values: - raise NotFoundError() + raise NotFoundError - return dict(zip(columns, values)) + return {'joined_at': values[0]} def total_messages(self, user_id: str) -> int: """Query total number of messages for a user.""" @@ -58,7 +55,7 @@ class Metricity: values = self.cursor.fetchone() if not values: - raise NotFoundError() + raise NotFoundError return values[0] @@ -88,11 +85,11 @@ class Metricity: values = self.cursor.fetchone() if not values: - raise NotFoundError() + raise NotFoundError return values[0] - def top_channel_activity(self, user_id: str) -> List[Tuple[str, int]]: + def top_channel_activity(self, user_id: str) -> list[tuple[str, int]]: """ Query the top three channels in which the user is most active. @@ -127,7 +124,7 @@ class Metricity: values = self.cursor.fetchall() if not values: - raise NotFoundError() + raise NotFoundError return values diff --git a/pydis_site/apps/api/tests/base.py b/pydis_site/apps/api/tests/base.py index c9f3cb7e..704b22cf 100644 --- a/pydis_site/apps/api/tests/base.py +++ b/pydis_site/apps/api/tests/base.py @@ -61,6 +61,7 @@ class AuthenticatedAPITestCase(APITestCase): ... self.assertEqual(response.status_code, 200) """ - def setUp(self): + def setUp(self) -> None: + """Bootstrap the user and authenticate it.""" super().setUp() self.client.force_authenticate(test_user) diff --git a/pydis_site/apps/api/tests/test_bumped_threads.py b/pydis_site/apps/api/tests/test_bumped_threads.py index 316e3f0b..2e3892c7 100644 --- a/pydis_site/apps/api/tests/test_bumped_threads.py +++ b/pydis_site/apps/api/tests/test_bumped_threads.py @@ -1,7 +1,7 @@ from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import BumpedThread +from pydis_site.apps.api.models import BumpedThread class UnauthedBumpedThreadAPITests(AuthenticatedAPITestCase): diff --git a/pydis_site/apps/api/tests/test_deleted_messages.py b/pydis_site/apps/api/tests/test_deleted_messages.py index 1eb535d8..62d17e58 100644 --- a/pydis_site/apps/api/tests/test_deleted_messages.py +++ b/pydis_site/apps/api/tests/test_deleted_messages.py @@ -1,10 +1,9 @@ -from datetime import datetime +from datetime import datetime, timezone from django.urls import reverse -from django.utils import timezone from .base import AuthenticatedAPITestCase -from ..models import MessageDeletionContext, User +from pydis_site.apps.api.models import MessageDeletionContext, User class DeletedMessagesWithoutActorTests(AuthenticatedAPITestCase): @@ -18,7 +17,7 @@ class DeletedMessagesWithoutActorTests(AuthenticatedAPITestCase): cls.data = { 'actor': None, - 'creation': datetime.utcnow().isoformat(), + 'creation': datetime.now(tz=timezone.utc).isoformat(), 'deletedmessage_set': [ { 'author': cls.author.id, @@ -58,7 +57,7 @@ class DeletedMessagesWithActorTests(AuthenticatedAPITestCase): cls.data = { 'actor': cls.actor.id, - 'creation': datetime.utcnow().isoformat(), + 'creation': datetime.now(tz=timezone.utc).isoformat(), 'deletedmessage_set': [ { 'author': cls.author.id, @@ -90,7 +89,7 @@ class DeletedMessagesLogURLTests(AuthenticatedAPITestCase): cls.deletion_context = MessageDeletionContext.objects.create( actor=cls.actor, - creation=timezone.now() + creation=datetime.now(tz=timezone.utc), ) def test_valid_log_url(self): diff --git a/pydis_site/apps/api/tests/test_documentation_links.py b/pydis_site/apps/api/tests/test_documentation_links.py index 4e238cbb..f4a332cb 100644 --- a/pydis_site/apps/api/tests/test_documentation_links.py +++ b/pydis_site/apps/api/tests/test_documentation_links.py @@ -1,7 +1,7 @@ from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import DocumentationLink +from pydis_site.apps.api.models import DocumentationLink class UnauthedDocumentationLinkAPITests(AuthenticatedAPITestCase): diff --git a/pydis_site/apps/api/tests/test_filters.py b/pydis_site/apps/api/tests/test_filters.py index 5059d651..4cef1c8f 100644 --- a/pydis_site/apps/api/tests/test_filters.py +++ b/pydis_site/apps/api/tests/test_filters.py @@ -1,7 +1,7 @@ import contextlib from dataclasses import dataclass from datetime import timedelta -from typing import Any, Dict, Tuple, Type +from typing import Any from django.db.models import Model from django.urls import reverse @@ -12,22 +12,22 @@ from pydis_site.apps.api.tests.base import AuthenticatedAPITestCase @dataclass() class TestSequence: - model: Type[Model] + model: type[Model] route: str - object: Dict[str, Any] - ignored_fields: Tuple[str, ...] = () + object: dict[str, Any] + ignored_fields: tuple[str, ...] = () def url(self, detail: bool = False) -> str: return reverse(f'api:bot:{self.route}-{"detail" if detail else "list"}') -FK_FIELDS: Dict[Type[Model], Tuple[str, ...]] = { +FK_FIELDS: dict[type[Model], tuple[str, ...]] = { FilterList: (), Filter: ("filter_list",), } -def get_test_sequences() -> Dict[str, TestSequence]: +def get_test_sequences() -> dict[str, TestSequence]: filter_list1_deny_dict = { "name": "testname", "list_type": 0, diff --git a/pydis_site/apps/api/tests/test_github_utils.py b/pydis_site/apps/api/tests/test_github_utils.py index 95bafec0..34fae875 100644 --- a/pydis_site/apps/api/tests/test_github_utils.py +++ b/pydis_site/apps/api/tests/test_github_utils.py @@ -12,7 +12,7 @@ import rest_framework.test from django.urls import reverse from pydis_site import settings -from .. import github_utils +from pydis_site.apps.api import github_utils class GeneralUtilityTests(unittest.TestCase): @@ -39,7 +39,8 @@ class GeneralUtilityTests(unittest.TestCase): delta = datetime.timedelta(minutes=10) self.assertAlmostEqual(decoded["exp"] - decoded["iat"], delta.total_seconds()) - self.assertLess(decoded["exp"], (datetime.datetime.now() + delta).timestamp()) + then = datetime.datetime.now(tz=datetime.timezone.utc) + delta + self.assertLess(decoded["exp"], then.timestamp()) class CheckRunTests(unittest.TestCase): @@ -50,7 +51,7 @@ class CheckRunTests(unittest.TestCase): "head_sha": "sha", "status": "completed", "conclusion": "success", - "created_at": datetime.datetime.utcnow().strftime(settings.GITHUB_TIMESTAMP_FORMAT), + "created_at": datetime.datetime.now(tz=datetime.timezone.utc).strftime(settings.GITHUB_TIMESTAMP_FORMAT), "artifacts_url": "url", } @@ -74,7 +75,8 @@ class CheckRunTests(unittest.TestCase): # Set the creation time to well before the MAX_RUN_TIME # to guarantee the right conclusion kwargs["created_at"] = ( - datetime.datetime.utcnow() - github_utils.MAX_RUN_TIME - datetime.timedelta(minutes=10) + datetime.datetime.now(tz=datetime.timezone.utc) + - github_utils.MAX_RUN_TIME - datetime.timedelta(minutes=10) ).strftime(settings.GITHUB_TIMESTAMP_FORMAT) with self.assertRaises(github_utils.RunTimeoutError): @@ -103,29 +105,26 @@ def get_response_authorize(_: httpx.Client, request: httpx.Request, **__) -> htt "account": {"login": "VALID_OWNER"}, "access_tokens_url": "https://example.com/ACCESS_TOKEN_URL" }]) - else: - return httpx.Response( - 401, json={"error": "auth app/installations"}, request=request - ) + return httpx.Response( + 401, json={"error": "auth app/installations"}, request=request + ) - elif path == "/installation/repositories": + elif path == "/installation/repositories": # noqa: RET505 if auth == "bearer app access token": return httpx.Response(200, request=request, json={ "repositories": [{ "name": "VALID_REPO" }] }) - else: # pragma: no cover - return httpx.Response( - 401, json={"error": "auth installation/repositories"}, request=request - ) + return httpx.Response( # pragma: no cover + 401, json={"error": "auth installation/repositories"}, request=request + ) - elif request.method == "POST": + elif request.method == "POST": # noqa: RET505 if path == "/ACCESS_TOKEN_URL": if auth == "bearer JWT initial token": return httpx.Response(200, request=request, json={"token": "app access token"}) - else: # pragma: no cover - return httpx.Response(401, json={"error": "auth access_token"}, request=request) + return httpx.Response(401, json={"error": "auth access_token"}, request=request) # pragma: no cover # Reaching this point means something has gone wrong return httpx.Response(500, request=request) # pragma: no cover @@ -138,7 +137,7 @@ class AuthorizeTests(unittest.TestCase): def test_invalid_apps_auth(self): """Test that an exception is raised if authorization was attempted with an invalid token.""" - with mock.patch.object(github_utils, "generate_token", return_value="Invalid token"): + with mock.patch.object(github_utils, "generate_token", return_value="Invalid token"): # noqa: SIM117 with self.assertRaises(httpx.HTTPStatusError) as error: github_utils.authorize("VALID_OWNER", "VALID_REPO") @@ -179,7 +178,11 @@ class ArtifactFetcherTests(unittest.TestCase): run = github_utils.WorkflowRun( name="action_name", head_sha="action_sha", - created_at=datetime.datetime.now().strftime(settings.GITHUB_TIMESTAMP_FORMAT), + created_at=( + datetime.datetime + .now(tz=datetime.timezone.utc) + .strftime(settings.GITHUB_TIMESTAMP_FORMAT) + ), status="completed", conclusion="success", artifacts_url="artifacts_url" @@ -187,7 +190,7 @@ class ArtifactFetcherTests(unittest.TestCase): return httpx.Response( 200, request=request, json={"workflow_runs": [dataclasses.asdict(run)]} ) - elif path == "/artifact_url": + elif path == "/artifact_url": # noqa: RET505 return httpx.Response( 200, request=request, json={"artifacts": [{ "name": "artifact_name", diff --git a/pydis_site/apps/api/tests/test_infractions.py b/pydis_site/apps/api/tests/test_infractions.py index ceb5591b..71611ee9 100644 --- a/pydis_site/apps/api/tests/test_infractions.py +++ b/pydis_site/apps/api/tests/test_infractions.py @@ -8,8 +8,8 @@ from django.db.utils import IntegrityError from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import Infraction, User -from ..serializers import InfractionSerializer +from pydis_site.apps.api.models import Infraction, User +from pydis_site.apps.api.serializers import InfractionSerializer class UnauthenticatedTests(AuthenticatedAPITestCase): @@ -152,8 +152,8 @@ class InfractionTests(AuthenticatedAPITestCase): def test_filter_after(self): url = reverse('api:bot:infraction-list') - target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=5) - response = self.client.get(f'{url}?type=superstar&expires_after={target_time.isoformat()}') + target_time = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=5) + response = self.client.get(url, {'type': 'superstar', 'expires_after': target_time.isoformat()}) self.assertEqual(response.status_code, 200) infractions = response.json() @@ -161,8 +161,8 @@ class InfractionTests(AuthenticatedAPITestCase): def test_filter_before(self): url = reverse('api:bot:infraction-list') - target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=5) - response = self.client.get(f'{url}?type=superstar&expires_before={target_time.isoformat()}') + target_time = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=5) + response = self.client.get(url, {'type': 'superstar', 'expires_before': target_time.isoformat()}) self.assertEqual(response.status_code, 200) infractions = response.json() @@ -185,11 +185,12 @@ class InfractionTests(AuthenticatedAPITestCase): def test_after_before_before(self): url = reverse('api:bot:infraction-list') - target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=4) - target_time_late = datetime.datetime.utcnow() + datetime.timedelta(hours=6) + target_time = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=4) + target_time_late = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=6) response = self.client.get( - f'{url}?expires_before={target_time_late.isoformat()}' - f'&expires_after={target_time.isoformat()}' + url, + {'expires_before': target_time_late.isoformat(), + 'expires_after': target_time.isoformat()}, ) self.assertEqual(response.status_code, 200) @@ -198,11 +199,12 @@ class InfractionTests(AuthenticatedAPITestCase): def test_after_after_before_invalid(self): url = reverse('api:bot:infraction-list') - target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=5) - target_time_late = datetime.datetime.utcnow() + datetime.timedelta(hours=9) + target_time = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=5) + target_time_late = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=9) response = self.client.get( - f'{url}?expires_before={target_time.isoformat()}' - f'&expires_after={target_time_late.isoformat()}' + url, + {'expires_before': target_time.isoformat(), + 'expires_after': target_time_late.isoformat()}, ) self.assertEqual(response.status_code, 400) @@ -212,8 +214,11 @@ class InfractionTests(AuthenticatedAPITestCase): def test_permanent_after_invalid(self): url = reverse('api:bot:infraction-list') - target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=5) - response = self.client.get(f'{url}?permanent=true&expires_after={target_time.isoformat()}') + target_time = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=5) + response = self.client.get( + url, + {'permanent': 'true', 'expires_after': target_time.isoformat()}, + ) self.assertEqual(response.status_code, 400) errors = list(response.json()) @@ -221,8 +226,11 @@ class InfractionTests(AuthenticatedAPITestCase): def test_permanent_before_invalid(self): url = reverse('api:bot:infraction-list') - target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=5) - response = self.client.get(f'{url}?permanent=true&expires_before={target_time.isoformat()}') + target_time = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=5) + response = self.client.get( + url, + {'permanent': 'true', 'expires_before': target_time.isoformat()}, + ) self.assertEqual(response.status_code, 400) errors = list(response.json()) @@ -230,9 +238,10 @@ class InfractionTests(AuthenticatedAPITestCase): def test_nonpermanent_before(self): url = reverse('api:bot:infraction-list') - target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=6) + target_time = datetime.datetime.now(tz=timezone.utc) + datetime.timedelta(hours=6) response = self.client.get( - f'{url}?permanent=false&expires_before={target_time.isoformat()}' + url, + {'permanent': 'false', 'expires_before': target_time.isoformat()}, ) self.assertEqual(response.status_code, 200) @@ -522,39 +531,38 @@ class CreationTests(AuthenticatedAPITestCase): active_infraction_types = ('timeout', 'ban', 'superstar') for infraction_type in active_infraction_types: - with self.subTest(infraction_type=infraction_type): - with transaction.atomic(): - first_active_infraction = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': infraction_type, - 'reason': 'Take me on!', - 'active': True, - 'expires_at': '2019-10-04T12:52:00+00:00' - } + with self.subTest(infraction_type=infraction_type), transaction.atomic(): + first_active_infraction = { + 'user': self.user.id, + 'actor': self.user.id, + 'type': infraction_type, + 'reason': 'Take me on!', + 'active': True, + 'expires_at': '2019-10-04T12:52:00+00:00' + } + + # Post the first active infraction of a type and confirm it's accepted. + first_response = self.client.post(url, data=first_active_infraction) + self.assertEqual(first_response.status_code, 201) - # Post the first active infraction of a type and confirm it's accepted. - first_response = self.client.post(url, data=first_active_infraction) - self.assertEqual(first_response.status_code, 201) - - second_active_infraction = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': infraction_type, - 'reason': 'Take on me!', - 'active': True, - 'expires_at': '2019-10-04T12:52:00+00:00' + second_active_infraction = { + 'user': self.user.id, + 'actor': self.user.id, + 'type': infraction_type, + 'reason': 'Take on me!', + 'active': True, + 'expires_at': '2019-10-04T12:52:00+00:00' + } + second_response = self.client.post(url, data=second_active_infraction) + self.assertEqual(second_response.status_code, 400) + self.assertEqual( + second_response.json(), + { + 'non_field_errors': [ + 'This user already has an active infraction of this type.' + ] } - second_response = self.client.post(url, data=second_active_infraction) - self.assertEqual(second_response.status_code, 400) - self.assertEqual( - second_response.json(), - { - 'non_field_errors': [ - 'This user already has an active infraction of this type.' - ] - } - ) + ) def test_returns_201_for_second_active_infraction_of_different_type(self): """Test if the API accepts a second active infraction of a different type than the first.""" diff --git a/pydis_site/apps/api/tests/test_models.py b/pydis_site/apps/api/tests/test_models.py index d3341b35..1cca133d 100644 --- a/pydis_site/apps/api/tests/test_models.py +++ b/pydis_site/apps/api/tests/test_models.py @@ -118,7 +118,7 @@ class StringDunderMethodTests(SimpleTestCase): OffensiveMessage( id=602951077675139072, channel_id=291284109232308226, - delete_date=dt(3000, 1, 1) + delete_date=dt(3000, 1, 1, tzinfo=timezone.utc) ), OffTopicChannelName(name='bob-the-builders-playground'), Role( @@ -132,7 +132,7 @@ class StringDunderMethodTests(SimpleTestCase): name='shawn', discriminator=555, ), - creation=dt.utcnow() + creation=dt.now(tz=timezone.utc) ), User( id=5, diff --git a/pydis_site/apps/api/tests/test_nominations.py b/pydis_site/apps/api/tests/test_nominations.py index b3742cdd..ee6b1fbd 100644 --- a/pydis_site/apps/api/tests/test_nominations.py +++ b/pydis_site/apps/api/tests/test_nominations.py @@ -3,7 +3,7 @@ from datetime import datetime as dt, timedelta, timezone from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import Nomination, NominationEntry, User +from pydis_site.apps.api.models import Nomination, NominationEntry, User class CreationTests(AuthenticatedAPITestCase): diff --git a/pydis_site/apps/api/tests/test_off_topic_channel_names.py b/pydis_site/apps/api/tests/test_off_topic_channel_names.py index 34098c92..315f707d 100644 --- a/pydis_site/apps/api/tests/test_off_topic_channel_names.py +++ b/pydis_site/apps/api/tests/test_off_topic_channel_names.py @@ -1,7 +1,7 @@ from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import OffTopicChannelName +from pydis_site.apps.api.models import OffTopicChannelName class UnauthenticatedTests(AuthenticatedAPITestCase): diff --git a/pydis_site/apps/api/tests/test_offensive_message.py b/pydis_site/apps/api/tests/test_offensive_message.py index 3cf95b75..53f9cb48 100644 --- a/pydis_site/apps/api/tests/test_offensive_message.py +++ b/pydis_site/apps/api/tests/test_offensive_message.py @@ -3,13 +3,13 @@ import datetime from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import OffensiveMessage +from pydis_site.apps.api.models import OffensiveMessage class CreationTests(AuthenticatedAPITestCase): def test_accept_valid_data(self): url = reverse('api:bot:offensivemessage-list') - delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + delete_at = datetime.datetime.now() + datetime.timedelta(days=1) # noqa: DTZ005 data = { 'id': '602951077675139072', 'channel_id': '291284109232308226', @@ -32,7 +32,7 @@ class CreationTests(AuthenticatedAPITestCase): def test_returns_400_on_non_future_date(self): url = reverse('api:bot:offensivemessage-list') - delete_at = datetime.datetime.now() - datetime.timedelta(days=1) + delete_at = datetime.datetime.now() - datetime.timedelta(days=1) # noqa: DTZ005 data = { 'id': '602951077675139072', 'channel_id': '291284109232308226', @@ -46,7 +46,7 @@ class CreationTests(AuthenticatedAPITestCase): def test_returns_400_on_negative_id_or_channel_id(self): url = reverse('api:bot:offensivemessage-list') - delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + delete_at = datetime.datetime.now() + datetime.timedelta(days=1) # noqa: DTZ005 data = { 'id': '602951077675139072', 'channel_id': '291284109232308226', @@ -72,7 +72,7 @@ class CreationTests(AuthenticatedAPITestCase): class ListTests(AuthenticatedAPITestCase): @classmethod def setUpTestData(cls): - delete_at = datetime.datetime.now() + datetime.timedelta(days=1) + delete_at = datetime.datetime.now() + datetime.timedelta(days=1) # noqa: DTZ005 aware_delete_at = delete_at.replace(tzinfo=datetime.timezone.utc) cls.messages = [ diff --git a/pydis_site/apps/api/tests/test_reminders.py b/pydis_site/apps/api/tests/test_reminders.py index e17569f0..9bb5fe4d 100644 --- a/pydis_site/apps/api/tests/test_reminders.py +++ b/pydis_site/apps/api/tests/test_reminders.py @@ -4,7 +4,7 @@ from django.forms.models import model_to_dict from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import Reminder, User +from pydis_site.apps.api.models import Reminder, User class UnauthedReminderAPITests(AuthenticatedAPITestCase): @@ -59,7 +59,7 @@ class ReminderCreationTests(AuthenticatedAPITestCase): data = { 'author': self.author.id, 'content': 'Remember to...wait what was it again?', - 'expiration': datetime.utcnow().isoformat(), + 'expiration': datetime.now(tz=timezone.utc).isoformat(), 'jump_url': "https://www.google.com", 'channel_id': 123, 'mentions': [8888, 9999], diff --git a/pydis_site/apps/api/tests/test_roles.py b/pydis_site/apps/api/tests/test_roles.py index 73c80c77..d3031990 100644 --- a/pydis_site/apps/api/tests/test_roles.py +++ b/pydis_site/apps/api/tests/test_roles.py @@ -1,7 +1,7 @@ from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import Role, User +from pydis_site.apps.api.models import Role, User class CreationTests(AuthenticatedAPITestCase): diff --git a/pydis_site/apps/api/tests/test_rules.py b/pydis_site/apps/api/tests/test_rules.py index 3ee2d4e0..662fb8e9 100644 --- a/pydis_site/apps/api/tests/test_rules.py +++ b/pydis_site/apps/api/tests/test_rules.py @@ -5,7 +5,7 @@ from pathlib import Path from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..views import RulesView +from pydis_site.apps.api.views import RulesView class RuleAPITests(AuthenticatedAPITestCase): diff --git a/pydis_site/apps/api/tests/test_users.py b/pydis_site/apps/api/tests/test_users.py index d86e80bb..cff4a825 100644 --- a/pydis_site/apps/api/tests/test_users.py +++ b/pydis_site/apps/api/tests/test_users.py @@ -4,9 +4,9 @@ from unittest.mock import Mock, patch from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import Infraction, Role, User -from ..models.bot.metricity import NotFoundError -from ..viewsets.bot.user import UserListPagination +from pydis_site.apps.api.models import Infraction, Role, User +from pydis_site.apps.api.models.bot.metricity import NotFoundError +from pydis_site.apps.api.viewsets.bot.user import UserListPagination class UnauthedUserAPITests(AuthenticatedAPITestCase): @@ -469,18 +469,17 @@ class UserMetricityTests(AuthenticatedAPITestCase): with self.subTest( voice_infractions=case['voice_infractions'], voice_gate_blocked=case['voice_gate_blocked'] - ): - with patch("pydis_site.apps.api.viewsets.bot.user.Infraction.objects.filter") as p: - p.return_value = case['voice_infractions'] - - url = reverse('api:bot:user-metricity-data', args=[0]) - response = self.client.get(url) - - self.assertEqual(response.status_code, 200) - self.assertEqual( - response.json()["voice_gate_blocked"], - case["voice_gate_blocked"] - ) + ), patch("pydis_site.apps.api.viewsets.bot.user.Infraction.objects.filter") as p: + p.return_value = case['voice_infractions'] + + url = reverse('api:bot:user-metricity-data', args=[0]) + response = self.client.get(url) + + self.assertEqual(response.status_code, 200) + self.assertEqual( + response.json()["voice_gate_blocked"], + case["voice_gate_blocked"] + ) def test_metricity_review_data(self): # Given diff --git a/pydis_site/apps/api/tests/test_validators.py b/pydis_site/apps/api/tests/test_validators.py index 8c46fcbc..a7ec6e38 100644 --- a/pydis_site/apps/api/tests/test_validators.py +++ b/pydis_site/apps/api/tests/test_validators.py @@ -3,8 +3,8 @@ from datetime import datetime, timezone from django.core.exceptions import ValidationError from django.test import TestCase -from ..models.bot.bot_setting import validate_bot_setting_name -from ..models.bot.offensive_message import future_date_validator +from pydis_site.apps.api.models.bot.bot_setting import validate_bot_setting_name +from pydis_site.apps.api.models.bot.offensive_message import future_date_validator REQUIRED_KEYS = ( diff --git a/pydis_site/apps/api/views.py b/pydis_site/apps/api/views.py index b1b7dc0f..32f41667 100644 --- a/pydis_site/apps/api/views.py +++ b/pydis_site/apps/api/views.py @@ -93,7 +93,7 @@ class RulesView(APIView): """ if target == 'html': return f'{description}' - elif target == 'md': + elif target == 'md': # noqa: RET505 return f'[{description}]({link})' else: raise ValueError( @@ -101,7 +101,7 @@ class RulesView(APIView): ) # `format` here is the result format, we have a link format here instead. - def get(self, request, format=None): # noqa: D102,ANN001,ANN201 + def get(self, request, format=None): # noqa: ANN001, ANN201 """ Returns a list of our community rules coupled with their keywords. diff --git a/pydis_site/apps/api/viewsets/bot/filters.py b/pydis_site/apps/api/viewsets/bot/filters.py index d6c2d18c..9c9e8338 100644 --- a/pydis_site/apps/api/viewsets/bot/filters.py +++ b/pydis_site/apps/api/viewsets/bot/filters.py @@ -1,10 +1,10 @@ from rest_framework.viewsets import ModelViewSet -from pydis_site.apps.api.models.bot.filters import ( # noqa: I101 - Preserving the filter order +from pydis_site.apps.api.models.bot.filters import ( # - Preserving the filter order FilterList, Filter ) -from pydis_site.apps.api.serializers import ( # noqa: I101 - Preserving the filter order +from pydis_site.apps.api.serializers import ( # - Preserving the filter order FilterListSerializer, FilterSerializer, ) diff --git a/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py b/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py index d0519e86..1774004c 100644 --- a/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py +++ b/pydis_site/apps/api/viewsets/bot/off_topic_channel_name.py @@ -85,10 +85,9 @@ class OffTopicChannelNameViewSet(ModelViewSet): serializer.save() return Response(create_data, status=HTTP_201_CREATED) - else: - raise ParseError(detail={ - 'name': ["This query parameter is required."] - }) + raise ParseError(detail={ + 'name': ["This query parameter is required."] + }) def list(self, request: Request, *args, **kwargs) -> Response: """ diff --git a/pydis_site/apps/api/viewsets/bot/user.py b/pydis_site/apps/api/viewsets/bot/user.py index db73a83c..88fa3415 100644 --- a/pydis_site/apps/api/viewsets/bot/user.py +++ b/pydis_site/apps/api/viewsets/bot/user.py @@ -1,4 +1,3 @@ -import typing from collections import OrderedDict from django.db.models import Q @@ -24,14 +23,14 @@ class UserListPagination(PageNumberPagination): page_size = 2500 page_size_query_param = "page_size" - def get_next_page_number(self) -> typing.Optional[int]: + def get_next_page_number(self) -> int | None: """Get the next page number.""" if not self.page.has_next(): return None page_number = self.page.next_page_number() return page_number - def get_previous_page_number(self) -> typing.Optional[int]: + def get_previous_page_number(self) -> int | None: """Get the previous page number.""" if not self.page.has_previous(): return None diff --git a/pydis_site/apps/content/models/tag.py b/pydis_site/apps/content/models/tag.py index 1a20d775..7c49902f 100644 --- a/pydis_site/apps/content/models/tag.py +++ b/pydis_site/apps/content/models/tag.py @@ -30,8 +30,7 @@ class Commit(models.Model): def lines(self) -> collections.abc.Iterable[str]: """Return each line in the commit message.""" - for line in self.message.split("\n"): - yield line + yield from self.message.split("\n") def format_authors(self) -> collections.abc.Iterable[str]: """Return a nice representation of the author(s)' name and email.""" diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md index f6f8a5f2..b634f513 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/linting.md @@ -4,7 +4,7 @@ description: A guide for linting and setting up pre-commit. --- Your commit will be rejected by the build server if it fails to lint. -On most of our projects, we use `flake8` and `pre-commit` to ensure that the code style is consistent across the code base. +On most of our projects, we use `ruff` and `pre-commit` to ensure that the code style is consistent across the code base. `pre-commit` is a powerful tool that helps you automatically lint before you commit. If the linter complains, the commit is aborted so that you can fix the linting errors before committing again. diff --git a/pydis_site/apps/content/tests/helpers.py b/pydis_site/apps/content/tests/helpers.py index fad91050..0e7562e8 100644 --- a/pydis_site/apps/content/tests/helpers.py +++ b/pydis_site/apps/content/tests/helpers.py @@ -62,19 +62,19 @@ class MockPagesTestCase(TestCase): ├── not_a_page.md ├── tmp.md ├── tmp - |   ├── _info.yml - |   └── category - |    ├── _info.yml - |      └── subcategory_without_info + | ├── _info.yml + | └── category + | ├── _info.yml + | └── subcategory_without_info └── category -    ├── _info.yml -    ├── with_metadata.md -    └── subcategory -    ├── with_metadata.md -       └── without_metadata.md + ├── _info.yml + ├── with_metadata.md + └── subcategory + ├── with_metadata.md + └── without_metadata.md """ - def setUp(self): + def setUp(self) -> None: """Create the fake filesystem.""" Path(f"{BASE_PATH}/_info.yml").write_text(CATEGORY_INFO) Path(f"{BASE_PATH}/root.md").write_text(MARKDOWN_WITH_METADATA) diff --git a/pydis_site/apps/content/urls.py b/pydis_site/apps/content/urls.py index a7695a27..baae154d 100644 --- a/pydis_site/apps/content/urls.py +++ b/pydis_site/apps/content/urls.py @@ -8,7 +8,7 @@ from . import utils, views app_name = "content" -def __get_all_files(root: Path, folder: typing.Optional[Path] = None) -> list[str]: +def __get_all_files(root: Path, folder: Path | None = None) -> list[str]: """Find all folders and markdown files recursively starting from `root`.""" if not folder: folder = root diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py index c12893ef..347640dd 100644 --- a/pydis_site/apps/content/utils.py +++ b/pydis_site/apps/content/utils.py @@ -151,8 +151,11 @@ def set_tag_commit(tag: Tag) -> None: commit = data["commit"] author, committer = commit["author"], commit["committer"] - date = datetime.datetime.strptime(committer["date"], settings.GITHUB_TIMESTAMP_FORMAT) - date = date.replace(tzinfo=datetime.timezone.utc) + date = ( + datetime.datetime + .strptime(committer["date"], settings.GITHUB_TIMESTAMP_FORMAT) + .replace(tzinfo=datetime.timezone.utc) + ) if author["email"] == committer["email"]: authors = [author] @@ -212,9 +215,8 @@ def get_tags() -> list[Tag]: record_tags(tags) return tags - else: - # Get tags from database - return list(Tag.objects.all()) + + return list(Tag.objects.all()) def get_tag(path: str, *, skip_sync: bool = False) -> Tag | list[Tag]: @@ -242,13 +244,13 @@ def get_tag(path: str, *, skip_sync: bool = False) -> Tag | list[Tag]: if tag.last_commit is None and not skip_sync: set_tag_commit(tag) return tag - elif tag.group == name and group is None: + elif tag.group == name and group is None: # noqa: RET505 matches.append(tag) if matches: return matches - raise Tag.DoesNotExist() + raise Tag.DoesNotExist def get_tag_category(tags: list[Tag] | None = None, *, collapse_groups: bool) -> dict[str, dict]: diff --git a/pydis_site/apps/content/views/tags.py b/pydis_site/apps/content/views/tags.py index 4f4bb5a2..8d3e3321 100644 --- a/pydis_site/apps/content/views/tags.py +++ b/pydis_site/apps/content/views/tags.py @@ -1,5 +1,4 @@ import re -import typing import frontmatter import markdown @@ -22,7 +21,7 @@ COMMAND_REGEX = re.compile(r"`*!tags? (?P[\w-]+)(?P [\w-]+)?`*") class TagView(TemplateView): """Handles tag pages.""" - tag: typing.Union[Tag, list[Tag]] + tag: Tag | list[Tag] is_group: bool def setup(self, *args, **kwargs) -> None: diff --git a/pydis_site/apps/events/urls.py b/pydis_site/apps/events/urls.py index 7ea65a31..6121d264 100644 --- a/pydis_site/apps/events/urls.py +++ b/pydis_site/apps/events/urls.py @@ -8,7 +8,7 @@ from pydis_site.apps.events.views import IndexView, PageView app_name = "events" -def __get_all_files(root: Path, folder: typing.Optional[Path] = None) -> list[str]: +def __get_all_files(root: Path, folder: Path | None = None) -> list[str]: """Find all folders and HTML files recursively starting from `root`.""" if not folder: folder = root diff --git a/pydis_site/apps/events/views/page.py b/pydis_site/apps/events/views/page.py index 1622ad70..adf9e952 100644 --- a/pydis_site/apps/events/views/page.py +++ b/pydis_site/apps/events/views/page.py @@ -1,4 +1,3 @@ -from typing import List from django.conf import settings from django.http import Http404 @@ -8,7 +7,7 @@ from django.views.generic import TemplateView class PageView(TemplateView): """Handles event pages showing.""" - def get_template_names(self) -> List[str]: + def get_template_names(self) -> list[str]: """Get specific template names.""" path: str = self.kwargs['path'] page_path = settings.EVENTS_PAGES_PATH / path diff --git a/pydis_site/apps/home/tests/test_repodata_helpers.py b/pydis_site/apps/home/tests/test_repodata_helpers.py index a963f733..acf4a817 100644 --- a/pydis_site/apps/home/tests/test_repodata_helpers.py +++ b/pydis_site/apps/home/tests/test_repodata_helpers.py @@ -22,7 +22,7 @@ def mocked_requests_get(*args, **kwargs) -> "MockResponse": # noqa: F821 if args[0] == HomeView.github_api: json_path = Path(__file__).resolve().parent / "mock_github_api_response.json" - with open(json_path, 'r') as json_file: + with open(json_path) as json_file: mock_data = json.load(json_file) return MockResponse(mock_data, 200) diff --git a/pydis_site/apps/home/views.py b/pydis_site/apps/home/views.py index 8a165682..bfa9e02d 100644 --- a/pydis_site/apps/home/views.py +++ b/pydis_site/apps/home/views.py @@ -1,5 +1,4 @@ import logging -from typing import Dict, List import httpx from django.core.handlers.wsgi import WSGIRequest @@ -45,7 +44,7 @@ class HomeView(View): else: self.headers = {} - def _get_api_data(self) -> Dict[str, Dict[str, str]]: + def _get_api_data(self) -> dict[str, dict[str, str]]: """ Call the GitHub API and get information about our repos. @@ -54,7 +53,7 @@ class HomeView(View): repo_dict = {} try: # Fetch the data from the GitHub API - api_data: List[dict] = httpx.get( + api_data: list[dict] = httpx.get( self.github_api, headers=self.headers, timeout=settings.TIMEOUT_PERIOD @@ -89,7 +88,7 @@ class HomeView(View): return repo_dict - def _get_repo_data(self) -> List[RepositoryMetadata]: + def _get_repo_data(self) -> list[RepositoryMetadata]: """Build a list of RepositoryMetadata objects that we can use to populate the front page.""" # First off, load the timestamp of the least recently updated entry. if settings.STATIC_BUILD: @@ -121,8 +120,7 @@ class HomeView(View): if settings.STATIC_BUILD: return data - else: - return RepositoryMetadata.objects.bulk_create(data) + return RepositoryMetadata.objects.bulk_create(data) # If the data is stale, we should refresh it. if (timezone.now() - last_update).seconds > self.repository_cache_ttl: @@ -149,8 +147,7 @@ class HomeView(View): return database_repositories # Otherwise, if the data is fresher than 2 minutes old, we should just return it. - else: - return RepositoryMetadata.objects.all() + return RepositoryMetadata.objects.all() def get(self, request: WSGIRequest) -> HttpResponse: """Collect repo data and render the homepage view.""" diff --git a/pydis_site/apps/redirect/urls.py b/pydis_site/apps/redirect/urls.py index 067cccc3..a221ea12 100644 --- a/pydis_site/apps/redirect/urls.py +++ b/pydis_site/apps/redirect/urls.py @@ -83,22 +83,21 @@ def map_redirect(name: str, data: Redirect) -> list[URLPattern]: return paths + redirect_path_name = "pages" if new_app_name == "content" else new_app_name + if len(data.redirect_arguments) > 0: + redirect_arg = data.redirect_arguments[0] else: - redirect_path_name = "pages" if new_app_name == "content" else new_app_name - if len(data.redirect_arguments) > 0: - redirect_arg = data.redirect_arguments[0] - else: - redirect_arg = "resources/" - new_redirect = f"/{redirect_path_name}/{redirect_arg}" + redirect_arg = "resources/" + new_redirect = f"/{redirect_path_name}/{redirect_arg}" - if new_redirect == "/resources/resources/": - new_redirect = "/resources/" + if new_redirect == "/resources/resources/": + new_redirect = "/resources/" - return [distill_path( - data.original_path, - lambda *args: HttpResponse(REDIRECT_TEMPLATE.format(url=new_redirect)), - name=name, - )] + return [distill_path( + data.original_path, + lambda *args: HttpResponse(REDIRECT_TEMPLATE.format(url=new_redirect)), + name=name, + )] urlpatterns = [] diff --git a/pydis_site/apps/redirect/views.py b/pydis_site/apps/redirect/views.py index 21180cdf..374daf2b 100644 --- a/pydis_site/apps/redirect/views.py +++ b/pydis_site/apps/redirect/views.py @@ -1,4 +1,3 @@ -import typing as t from django.views.generic import RedirectView @@ -15,7 +14,7 @@ class CustomRedirectView(RedirectView): """Overwrites original as_view to add static args.""" return super().as_view(**initkwargs) - def get_redirect_url(self, *args, **kwargs) -> t.Optional[str]: + def get_redirect_url(self, *args, **kwargs) -> str | None: """Extends default behaviour to use static args.""" args = self.static_args + args + tuple(kwargs.values()) if self.prefix_redirect: diff --git a/pydis_site/apps/resources/views.py b/pydis_site/apps/resources/views.py index 2375f722..a2cd8d0c 100644 --- a/pydis_site/apps/resources/views.py +++ b/pydis_site/apps/resources/views.py @@ -1,5 +1,4 @@ import json -import typing as t from pathlib import Path import yaml @@ -22,7 +21,7 @@ class ResourceView(View): """Sort a tuple by its key alphabetically, disregarding 'the' as a prefix.""" name, resource = tuple_ name = name.casefold() - if name.startswith("the ") or name.startswith("the_"): + if name.startswith(("the ", "the_")): return name[4:] return name @@ -48,7 +47,7 @@ class ResourceView(View): } for resource_name, resource in self.resources.items(): css_classes = [] - for tag_type in resource_tags.keys(): + for tag_type in resource_tags: # Store the tags into `resource_tags` tags = resource.get("tags", {}).get(tag_type, []) for tag in tags: @@ -102,7 +101,7 @@ class ResourceView(View): "difficulty": [to_kebabcase(tier) for tier in self.filters["Difficulty"]["filters"]], } - def get(self, request: WSGIRequest, resource_type: t.Optional[str] = None) -> HttpResponse: + def get(self, request: WSGIRequest, resource_type: str | None = None) -> HttpResponse: """List out all the resources, and any filtering options from the URL.""" # Add type filtering if the request is made to somewhere like /resources/video. # We also convert all spaces to dashes, so they'll correspond with the filters. diff --git a/pydis_site/apps/staff/templatetags/deletedmessage_filters.py b/pydis_site/apps/staff/templatetags/deletedmessage_filters.py index 9d8f1819..c6638a3b 100644 --- a/pydis_site/apps/staff/templatetags/deletedmessage_filters.py +++ b/pydis_site/apps/staff/templatetags/deletedmessage_filters.py @@ -1,5 +1,4 @@ from datetime import datetime -from typing import Union from django import template @@ -7,7 +6,7 @@ register = template.Library() @register.filter -def hex_colour(colour: Union[str, int]) -> str: +def hex_colour(colour: str | int) -> str: """ Converts the given representation of a colour to its RGB hex string. diff --git a/pydis_site/apps/staff/tests/test_deletedmessage_filters.py b/pydis_site/apps/staff/tests/test_deletedmessage_filters.py index 31215784..5e49f103 100644 --- a/pydis_site/apps/staff/tests/test_deletedmessage_filters.py +++ b/pydis_site/apps/staff/tests/test_deletedmessage_filters.py @@ -3,7 +3,7 @@ import enum from django.test import TestCase from django.utils import timezone -from ..templatetags import deletedmessage_filters +from pydis_site.apps.staff.templatetags import deletedmessage_filters class Colour(enum.IntEnum): diff --git a/pyproject.toml b/pyproject.toml index 40461f0b..9019efb0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,18 +29,9 @@ whitenoise = "6.4.0" [tool.poetry.group.dev.dependencies] python-dotenv = "1.0.0" taskipy = "1.10.4" +ruff = "^0.0.265" [tool.poetry.group.lint.dependencies] -flake8 = "6.0.0" -flake8-annotations = "3.0.1" -flake8-bandit = "4.1.1" -flake8-bugbear = "23.5.9" -flake8-docstrings = "1.7.0" -flake8-import-order = "0.18.2" -flake8-tidy-imports = "4.8.0" -flake8-string-format = "0.3.0" -flake8-todo = "0.7" -pep8-naming = "0.13.3" pre-commit = "3.3.1" [tool.poetry.group.test.dependencies] @@ -50,6 +41,34 @@ coverage = "7.2.5" requires = ["poetry-core>=1.2.0"] build-backend = "poetry.core.masonry.api" +[tool.ruff] +target-version = "py310" +extend-exclude = [".cache"] +ignore = [ + "ANN002", "ANN003", "ANN101", "ANN102", "ANN204", "ANN206", "ANN401", + "B904", + "C401", "C408", + "D100", "D104", "D105", "D107", "D203", "D212", "D214", "D215", "D301", + "D400", "D401", "D402", "D404", "D405", "D406", "D407", "D408", "D409", "D410", "D411", "D412", "D413", "D414", "D416", "D417", + "E731", + "RET504", + "RUF005", + "S311", + "SIM102", "SIM108", +] +line-length = 120 +select = ["ANN", "B", "C4", "D", "DTZ", "E", "F", "ISC", "INT", "N", "PGH", "PIE", "RET", "RSE", "RUF", "S", "SIM", "T20", "TID", "UP", "W"] + +[tool.ruff.per-file-ignores] +"pydis_site/apps/**/migrations/*.py" = ["ALL"] +"manage.py" = ["T201"] +"pydis_site/apps/api/tests/base.py" = ["S106"] +"pydis_site/apps/**/tests/test_*.py" = ["ANN", "D"] +"static-builds/netlify_build.py" = ["T201"] +"pydis_site/apps/api/tests/test_off_topic_channel_names.py" = ["RUF001"] +"gunicorn.conf.py" = ["ANN", "D"] +"pydis_site/apps/api/models/bot/off_topic_channel_name.py" = ["RUF001"] + [tool.taskipy.tasks] start = "python manage.py run --debug" makemigrations = "python manage.py makemigrations" diff --git a/static-builds/netlify_build.py b/static-builds/netlify_build.py index 36520c28..2d311a11 100644 --- a/static-builds/netlify_build.py +++ b/static-builds/netlify_build.py @@ -14,15 +14,15 @@ from pathlib import Path from urllib import parse import httpx +import contextlib def raise_response(response: httpx.Response) -> None: """Raise an exception from a response if necessary.""" if response.status_code // 100 != 2: - try: + with contextlib.suppress(json.JSONDecodeError): print(response.json()) - except json.JSONDecodeError: - pass + response.raise_for_status() -- cgit v1.2.3 From 548a81e0e3060483b693079f994fcb70e01084e7 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Tue, 16 May 2023 23:04:04 +0530 Subject: condesed the 2 examples in 1 and added additional comments for reference. --- .../guides/python-guides/subclassing_bot.md | 70 +++++++++++----------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 91df2199..2562d606 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -4,55 +4,55 @@ description: "Subclassing the discord.py Bot class to add more functionality and --- ## Basic Subclassing -First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [`Bot`](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. +First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [`Bot`](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. ## The benefits of subclassing bot Subclassing Bot can be very beneficial as it provides you with more control and customisability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be overriden to add more functionality. -There are two ways to subclass `commands.Bot`, as shown below: +You can subclass `commands.Bot` as shown below: ```python class CustomBot(commands.Bot): - def __init__(self): - super().__init__( - command_prefix= # Your prefix here as a string - intents= # Your intents here - # Other kwargs can be put here - ) - # custom bot attributes can be set here, for example: + def __init__(self, *args, **kwargs) -> None: + # Forward all arguments, and keyword-only arguments to commands.Bot + super().__init__(*args, **kwargs) + + # Custom bot attributes can be set here. self.launch_time = datetime.datetime.utcnow() self.example_integer = 5 - - async def start(self, *args, **kwargs): - # here you are overriding the default start method. You can do some code here for example establish a database connection - # as shown in this example below - self.db = await aiosqlite.connect('database file name.db') + # Here you are overriding the default start method and write your own code. + async def start(self, *args, **kwargs) -> None: + """Establish a database connection.""" + self.db = await aiosqlite.connect('sqlite.db') await super().start(*args, **kwargs) + # Example of a custom bot method + def status(self) -> str: + """Get bot launch time in UTC and status.""" + return f"Bot started at {self.launch_time}, running." -bot = CustomBot() -token = YOUR_TOKEN_HERE -bot.run(token) -``` -Or -```python -class CustomBot(commands.Bot): - def __init__(self, *args, **kwargs): # the key-word arguments are not specified here, unlike the example above +# All arguments as passed to commands.Bot can be passed here. +bot = CustomBot( + command_prefix="!", # Prefix can be set to any string. + # Discord intents, refer to https://discordpy.readthedocs.io/en/stable/intents.html + intents=discord.Intents.default() +) - super().__init__(*args, **kwargs) - # custom bot attributes can be set here, for example: - self.example_string = 'This is an example!' - # You can add a custom bot method, anyhting can be done in this function. This is an example: - def hello(self): - return 'Hello World' +# Example bot command +@bot.command() +async def ping(ctx): + """ + Creates a command with the name `ping`. -# Here you set the *args and **kwargs -bot = CustomBot(command_prefix="!", intents=discord.Intents.default()) + When invoked, sends `pong`. + """ + await ctx.send("pong") -@bot.command() -async def example(ctx): - print(bot.hello()) - # In this case, this will print Hello World! + +# Having the token as an environment variable is recommended. +# Refer to https://www.pythondiscord.com/pages/guides/python-guides/keeping-tokens-safe/ +token = YOUR_TOKEN_HERE +bot.run(token) ``` -With either of the above examples, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. +With the above example, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. -- cgit v1.2.3 From e3576f83993109b49711a2c7c705b2a833107832 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 00:47:24 +0530 Subject: use launch_time attribute in the example method and command --- .../guides/python-guides/subclassing_bot.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 2562d606..47186e3d 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -1,13 +1,13 @@ --- title: Subclassing Bot -description: "Subclassing the discord.py Bot class to add more functionality and customisability." +description: "Subclassing the discord.py Bot class to add more functionality and customizability." --- ## Basic Subclassing First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [`Bot`](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. -## The benefits of subclassing bot -Subclassing Bot can be very beneficial as it provides you with more control and customisability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be overriden to add more functionality. +## The Benefits of Subclassing Bot +Subclassing `Bot` can be very beneficial as it provides you with more control and customizability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be overridden to add more functionality. You can subclass `commands.Bot` as shown below: ```python @@ -27,9 +27,9 @@ class CustomBot(commands.Bot): await super().start(*args, **kwargs) # Example of a custom bot method - def status(self) -> str: - """Get bot launch time in UTC and status.""" - return f"Bot started at {self.launch_time}, running." + def get_launch_time_str(self) -> datetime.datetime: + """Get bot launch datetime without milliseconds in UTC and status.""" + return f"Bot started at: {self.launch_time.strftime('%F %T')} UTC." # All arguments as passed to commands.Bot can be passed here. bot = CustomBot( @@ -41,13 +41,13 @@ bot = CustomBot( # Example bot command @bot.command() -async def ping(ctx): +async def start_time(ctx): """ - Creates a command with the name `ping`. + Creates a command with the name `start_time`. - When invoked, sends `pong`. + When invoked, sends the output of the custom method `get_launch_time_str`. """ - await ctx.send("pong") + await ctx.send(bot.get_launch_time_str()) # Having the token as an environment variable is recommended. -- cgit v1.2.3 From 9b0e2711f15ed2e1aa5c080a716b0e9f1691dbd6 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 00:58:11 +0530 Subject: correct return type annotation for get_launch_time_str function --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 47186e3d..1be6e485 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -27,7 +27,7 @@ class CustomBot(commands.Bot): await super().start(*args, **kwargs) # Example of a custom bot method - def get_launch_time_str(self) -> datetime.datetime: + def get_launch_time_str(self) -> str: """Get bot launch datetime without milliseconds in UTC and status.""" return f"Bot started at: {self.launch_time.strftime('%F %T')} UTC." @@ -56,3 +56,4 @@ token = YOUR_TOKEN_HERE bot.run(token) ``` With the above example, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. +ty \ No newline at end of file -- cgit v1.2.3 From 16e23cd5f817908a5f2bdba3c2dea76c012172de Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 01:00:43 +0530 Subject: highlight 'Bot' in the description with backticks. --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 1be6e485..da71fdba 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -1,6 +1,6 @@ --- title: Subclassing Bot -description: "Subclassing the discord.py Bot class to add more functionality and customizability." +description: "Subclassing the discord.py `Bot` class to add more functionality and customizability." --- ## Basic Subclassing -- cgit v1.2.3 From 01c5c6614ca65216db13e9c420b139bda2c29757 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 01:02:14 +0530 Subject: remove typo --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index da71fdba..f2b70e33 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -55,5 +55,4 @@ async def start_time(ctx): token = YOUR_TOKEN_HERE bot.run(token) ``` -With the above example, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. -ty \ No newline at end of file +With the above example, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. \ No newline at end of file -- cgit v1.2.3 From c62158ed52e3e593624ec2f944653277b758d70a Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 12:06:12 +0530 Subject: give a simple introduction to cogs and example links --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index f2b70e33..cbb2ad83 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -55,4 +55,4 @@ async def start_time(ctx): token = YOUR_TOKEN_HERE bot.run(token) ``` -With the above example, you are not required to change any of the existing or future code, it is identical to code done without subclassing bot. \ No newline at end of file +The next step would be to look into discord.py cogs as they help in organizing of collection of commands into various files and folders. Refer to https://discordpy.readthedocs.io/en/stable/ext/commands/cogs.html for more on cogs. Here is an example of cogs https://gist.github.com/EvieePy/d78c061a4798ae81be9825468fe146be (*Credit to EvieePy*). \ No newline at end of file -- cgit v1.2.3 From b4f764fdb285be44b017f7cc6c5816455bbe0b53 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 12:16:18 +0530 Subject: satisfy linter --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index cbb2ad83..7a5a3529 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -55,4 +55,4 @@ async def start_time(ctx): token = YOUR_TOKEN_HERE bot.run(token) ``` -The next step would be to look into discord.py cogs as they help in organizing of collection of commands into various files and folders. Refer to https://discordpy.readthedocs.io/en/stable/ext/commands/cogs.html for more on cogs. Here is an example of cogs https://gist.github.com/EvieePy/d78c061a4798ae81be9825468fe146be (*Credit to EvieePy*). \ No newline at end of file +The next step would be to look into discord.py cogs as they help in organizing of collection of commands into various files and folders. Refer to https://discordpy.readthedocs.io/en/stable/ext/commands/cogs.html for more on cogs. Here is an example of cogs https://gist.github.com/EvieePy/d78c061a4798ae81be9825468fe146be (*Credit to EvieePy*). -- cgit v1.2.3 From b33330fb11b8ac9c63e29ea56ed76aeabfe17d24 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 17:45:35 +0530 Subject: remove redundant info --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 7a5a3529..1cdf9c14 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -55,4 +55,4 @@ async def start_time(ctx): token = YOUR_TOKEN_HERE bot.run(token) ``` -The next step would be to look into discord.py cogs as they help in organizing of collection of commands into various files and folders. Refer to https://discordpy.readthedocs.io/en/stable/ext/commands/cogs.html for more on cogs. Here is an example of cogs https://gist.github.com/EvieePy/d78c061a4798ae81be9825468fe146be (*Credit to EvieePy*). +The next step would be to look into discord.py cogs as they help in organizing collections of commands into various files and folders. Refer to [the official docs](https://discordpy.readthedocs.io/en/stable/ext/commands/cogs.html) for more on them. -- cgit v1.2.3 From 5a2c346cb07eb746e3d3532cf38dadcfa983e13e Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 20:16:11 +0530 Subject: add reference link for overriding context and fix link for subclassing bot --- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 1cdf9c14..6a79190f 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -7,7 +7,7 @@ description: "Subclassing the discord.py `Bot` class to add more functionality a First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [`Bot`](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. ## The Benefits of Subclassing Bot -Subclassing `Bot` can be very beneficial as it provides you with more control and customizability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be overridden to add more functionality. +Subclassing `Bot` can be very beneficial as it provides you with more control and customizability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be [overridden](../discordpy-subclassing-context.md) to add more functionality. You can subclass `commands.Bot` as shown below: ```python -- cgit v1.2.3 From cc54cb8890813f4dd781f510d1b44d155d0e8b0d Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 20:16:18 +0530 Subject: add reference link for overriding context and fix link for subclassing bot --- .../resources/guides/python-guides/discordpy-subclassing-context.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md b/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md index b77cb0f9..7f43c50f 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md @@ -3,7 +3,7 @@ title: Subclassing Context in discord.py description: "Subclassing the default `commands.Context` class to add more functionability and customizability." --- -Start by reading the guide on [subclassing the `Bot` class](./subclassing_bot.md). A subclass of Bot has to be used to +Start by reading the guide on [subclassing the `Bot` class](../subclassing_bot.md). A subclass of Bot has to be used to inject your custom context subclass into discord.py. ## Overview -- cgit v1.2.3 From a1da70faf493d66c714903328bf79986e7b1dd89 Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 17 May 2023 20:36:48 +0530 Subject: remove .md for hyperlinks --- .../resources/guides/python-guides/discordpy-subclassing-context.md | 2 +- .../apps/content/resources/guides/python-guides/subclassing_bot.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md b/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md index 7f43c50f..5e5f05c1 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md +++ b/pydis_site/apps/content/resources/guides/python-guides/discordpy-subclassing-context.md @@ -3,7 +3,7 @@ title: Subclassing Context in discord.py description: "Subclassing the default `commands.Context` class to add more functionability and customizability." --- -Start by reading the guide on [subclassing the `Bot` class](../subclassing_bot.md). A subclass of Bot has to be used to +Start by reading the guide on [subclassing the `Bot` class](../subclassing_bot). A subclass of Bot has to be used to inject your custom context subclass into discord.py. ## Overview diff --git a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md index 6a79190f..8982a4f6 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md +++ b/pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md @@ -7,7 +7,7 @@ description: "Subclassing the discord.py `Bot` class to add more functionality a First, a [basic article](https://www.codesdope.com/course/python-subclass-of-a-class/) on subclassing will provide some fundamental knowledge, which is highly suggested before moving on to this topic, as subclassing [`Bot`](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Bot) can ultimately be a complicated task. ## The Benefits of Subclassing Bot -Subclassing `Bot` can be very beneficial as it provides you with more control and customizability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be [overridden](../discordpy-subclassing-context.md) to add more functionality. +Subclassing `Bot` can be very beneficial as it provides you with more control and customizability of how your bot functions, also allowing you to add extra features, such as custom bot attributes or methods. For example, the default [Context](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.Context) can be [overridden](../discordpy-subclassing-context) to add more functionality. You can subclass `commands.Bot` as shown below: ```python -- cgit v1.2.3 From 6fcf0c5caa341f23c73dfe4934dcc93971c389c3 Mon Sep 17 00:00:00 2001 From: ChrisJL Date: Tue, 30 May 2023 12:11:36 +0100 Subject: Remove mentions of there being multiple snekbox containers (#988) With https://github.com/python-discord/bot/pull/2618 there will only be 1 snekbox container, that runs the latest verison of snekbox. Supporting multiple versions of snekbox will be covered by https://github.com/python-discord/snekbox/issues/158 where a single instance of snekbox will nativly support multiple Python verisons. --- .../pydis-guides/contributing/bot-extended-configuration-options.md | 3 +-- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md index b031a668..a35d79a9 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md @@ -115,14 +115,13 @@ The advantage of this method is that you can run the bot's code in your preferre * Append the following line to your `.env` file: `API_KEYS_SITE_API=badbot13m0n8f570f942013fc818f234916ca531`. * In your `.env.server` file, set `urls_site_api="http://localhost:8000/api"`. If you wish to keep using `http://web:8000/api`, then [COMPOSE_PROJECT_NAME](../docker/#compose-project-names) has to be set. -* To work with snekbox, set `urls_snekbox_eval_api="http://localhost:8060/eval"` and `urls_snekbox_311_eval_api="http://localhost:8065/eval"` +* To work with snekbox, set `urls_snekbox_eval_api="http://localhost:8060/eval"`. You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple: * `docker compose up web` to start the site container. This is required. * `docker compose up snekbox` to start the snekbox container. You only need this if you're planning on working on the snekbox cog. -* `docker compose up snekbox-311` to start the snekbox 3.11 container. You only need this if you're planning on working on the snekbox cog. * `docker compose up redis` to start the Redis container. You only need this if you're not using fakeredis. For more info refer to [Working with Redis](#optional-working-with-redis). You can start several services together: `docker compose up web snekbox redis`. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index 6639d92d..b5e11a97 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -134,7 +134,6 @@ Some other useful docker commands are as follows: 1. `docker compose pull` this pulls updates for all non-bot services, such as psotgres, redis and our [site](../site) project! 1. `docker compose build` this rebuilds the bot's docker image, this is only needed if you need to make changes to the bot's dependencies, or the Dockerfile itself. -1. `docker compose --profile 3.10 up` this starts a 3.10 snekbox container, in addition to the default 3.11 container! Your bot is now running, all inside Docker. -- cgit v1.2.3 From 932f5aab053f634877b77b97224b42ee893456e6 Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Thu, 22 Jun 2023 15:21:40 +0530 Subject: Fix broken links in the contributing guide. (#1002) --- pydis_site/apps/content/resources/guides/pydis-guides/contributing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md index 07e9a7bd..b36c0afd 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing.md @@ -82,7 +82,7 @@ Our projects on Python Discord are open source and [available on GitHub](https:/ # How do I start contributing? Unsure of what contributing to open source projects involves? Have questions about how to use GitHub? Just need to know about our contribution etiquette? Completing these steps will have you ready to make your first contribution no matter your starting point. -Feel free to skip any steps you're already familiar with, but please make sure not to miss the [Contributing Guidelines](#5-read-our-contributing-guidelines). +Feel free to skip any steps you're already familiar with, but please make sure not to miss the [Contributing Guidelines](#3-read-our-contributing-guidelines). If you are here looking for the answer to a specific question, check out the sub-articles in the top right of the page to see a list of our guides. @@ -129,7 +129,7 @@ Don't move forward until your issue is approved by a Core Developer. Issues are ### 5. Make changes Now it is time to make the changes to fulfill your approved issue. You should create a new Git branch for your feature; that way you can keep your main branch up to date with ours and even work on multiple features at once in separate branches. -This is a good time to review [how to write good commit messages](./contributing-guidelines/commit-messages) if you haven't already. +This is a good time to review [how to write good commit messages](./commit-messages) if you haven't already. ### 6. Open a pull request After your issue has been approved and you've written your code and tested it, it's time to open a pull request. Pull requests are a feature in GitHub; you can think of them as asking the project maintainers to accept your changes. This gives other contributors a chance to review your code and make any needed changes before it's merged into the main branch of the project. -- cgit v1.2.3 From c95e2a2470442b1e83b2c9c1c928afb7730df763 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Sun, 9 Jul 2023 22:32:51 +0200 Subject: Fix "PostegreSQL" typo --- .../apps/content/resources/guides/pydis-guides/contributing/site.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 9786698b..b6da5ba3 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -73,7 +73,7 @@ detailed information about these settings. #### Notes regarding `DATABASE_URL` - If the database is hosted locally i.e. on the same machine as the webserver, then use `localhost` for the host. Windows and macOS users may need to use the [Docker host IP](https://stackoverflow.com/questions/22944631/how-to-get-the-ip-address-of-the-docker-host-from-inside-a-docker-container) instead. -- If the database is running in Docker, use port `7777`. Otherwise, use `5432` as that is the default port used by PostegreSQL. +- If the database is running in Docker, use port `7777`. Otherwise, use `5432` as that is the default port used by PostgreSQL. - If you configured PostgreSQL in a different manner or you are not hosting it locally, then you will need to determine the correct host and port yourself. The user, password, and database name should all still be `pysite` unless you deviated from the setup instructions in the previous section. -- cgit v1.2.3 From 3c0e58bb70fbfff4c4316c3d7eaa47cd442aa0aa Mon Sep 17 00:00:00 2001 From: jchristgit Date: Tue, 11 Jul 2023 16:44:20 +0200 Subject: Drop redirect usage from URL references (#1016) Just one separate, and present beforehand, broken link remains: $ httrack -E --robots=0 --spider http://127.0.0.1:8000 -v | grep 404 20:18:51 Error: "Not Found" (404) at link 127.0.0.1:8000/events/game-jam-2020/technical-requirements/ (from 127.0.0.1:8000/events/game-jams/2020/judging/) Closes #681. --- README.md | 2 +- .../resources/guides/pydis-guides/contributing/hosts-file.md | 2 +- .../resources/guides/pydis-guides/contributing/site.md | 2 +- .../guides/pydis-guides/how-to-contribute-a-page.md | 12 ++++++------ pydis_site/apps/content/resources/server-info/roles.md | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/README.md b/README.md index ef70697d..a37a46b7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you're looking to contribute or play around with the code, take a look at [th [7]: https://coveralls.io/repos/github/python-discord/site/badge.svg?branch=main [8]: https://coveralls.io/github/python-discord/site?branch=main [9]: https://pythondiscord.com -[10]: https://pythondiscord.com/pages/contributing/site/ +[10]: https://pythondiscord.com/pages/guides/pydis-guides/contributing/site/ [11]: https://github.com/python-discord/site/issues [12]: https://raw.githubusercontent.com/python-discord/branding/main/logos/badge/badge_github.svg [13]: https://discord.gg/python diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/hosts-file.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/hosts-file.md index bba5722d..2da88b61 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/hosts-file.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/hosts-file.md @@ -8,7 +8,7 @@ toc: 3 # What's a hosts file? The hosts file maps a hostname/domain to an IP address, allowing you to visit a given domain on your browser and have it resolve by your system to the given IP address, even if it's pointed back to your own system or network. -When staging a local [Site](https://pythondiscord.com/pages/contributing/site/) project, you may want to add an entries to your hosts file so you can visit the site with the domain `http://pythondiscord.local`. This is purely for convenience, and you can use `localhost` or `127.0.0.1` instead if you prefer. +When staging a local [Site](https://pythondiscord.com/pages/guides/pydis-guides/contributing/site/) project, you may want to add an entries to your hosts file so you can visit the site with the domain `http://pythondiscord.local`. This is purely for convenience, and you can use `localhost` or `127.0.0.1` instead if you prefer. # What to add You would add the following entry to your hosts file. diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index b6da5ba3..9eef8d23 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -92,7 +92,7 @@ docker-compose up The `-d` option can be appended to the command to run in detached mode. This runs the containers in the background so the current terminal session is available for use with other things. -If you get any Docker related errors, reference the [Possible Issues](https://pythondiscord.com/pages/contributing/docker/#possible-issues") section of the Docker page. +If you get any Docker related errors, reference the [Possible Issues](https://pythondiscord.com/pages/guides/pydis-guides/contributing/docker/#possible-issues") section of the Docker page. {: .notification .is-warning } ## Run on the host diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md index 0d14ef41..65a402fd 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md @@ -3,8 +3,8 @@ title: How to Contribute a Page description: Learn how to write and publish a page to this website. icon: fas fa-info relevant_links: - Contributing to Site: https://pythondiscord.com/pages/contributing/site/ - Using Git: https://pythondiscord.com/pages/contributing/working-with-git/ + Contributing to Site: https://pythondiscord.com/pages/guides/pydis-guides/contributing/site/ + Using Git: https://pythondiscord.com/pages/guides/pydis-guides/contributing/working-with-git/ toc: 4 --- @@ -14,8 +14,8 @@ If you are interested in writing or modifying pages seen here on the site, follo For further assistance and help with contributing pages, send a message to the `#dev-contrib` channel in the Discord server! ## Prerequisites -Before working on a new page, you have to [setup the site project locally](https://pythondiscord.com/pages/contributing/site/). -It is also a good idea to familiarize yourself with the [git workflow](https://pythondiscord.com/pages/contributing/working-with-git/), as it is part of the contribution workflow. +Before working on a new page, you have to [setup the site project locally](https://pythondiscord.com/pages/guides/pydis-guides/contributing/site/). +It is also a good idea to familiarize yourself with the [git workflow](https://pythondiscord.com/pages/guides/pydis-guides/contributing/working-with-git/), as it is part of the contribution workflow. Additionally, please submit your proposed page or modification to a page as an [issue in the site repository](https://github.com/python-discord/site/issues), or discuss it in the `#dev-contrib` channel in the server. As website changes require staff approval, discussing the page content beforehand helps with accelerating the contribution process, and avoids wasted work in the event the proposed page is not accepted. @@ -68,8 +68,8 @@ title: How to Contribute a Page description: Learn how to write and publish a page to this website. icon: fas fa-info relevant_links: - Contributing to Site: https://pythondiscord.com/pages/contributing/site/ - Using Git: https://pythondiscord.com/pages/contributing/working-with-git/ + Contributing to Site: https://pythondiscord.com/pages/guides/pydis-guides/contributing/site/ + Using Git: https://pythondiscord.com/pages/guides/pydis-guides/contributing/working-with-git/ --- Pages, which include guides, articles, and other static content,... diff --git a/pydis_site/apps/content/resources/server-info/roles.md b/pydis_site/apps/content/resources/server-info/roles.md index dc4240d6..4dadf6b8 100644 --- a/pydis_site/apps/content/resources/server-info/roles.md +++ b/pydis_site/apps/content/resources/server-info/roles.md @@ -33,7 +33,7 @@ It’s difficult to precisely quantify contributions, but we’ve come up with t - The member has made several significant contributions to our projects. - The member has a positive influence in our contributors subcommunity. -The role will be assigned at the discretion of the Admin Team in consultation with the Core Developers Team. Check out our [walkthrough](/pages/contributing/) to get started contributing. +The role will be assigned at the discretion of the Admin Team in consultation with the Core Developers Team. Check out our [walkthrough](/pages/guides/pydis-guides/contributing/) to get started contributing. --- -- cgit v1.2.3 From 80959ab7af347142203d5d4dbd0ce3c471dfe787 Mon Sep 17 00:00:00 2001 From: NipaDev <60810623+Nipa-Code@users.noreply.github.com> Date: Mon, 31 Jul 2023 20:25:54 +0300 Subject: Fix a typo in bot.md (#1058) Fix a typo in bot.md file. Correct the typo "psotgres" to "postgres". --- .../apps/content/resources/guides/pydis-guides/contributing/bot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md index b5e11a97..f54ee664 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot.md @@ -132,7 +132,7 @@ With all of the above setup, you can run The projec with `docker compose up`. Th Some other useful docker commands are as follows: -1. `docker compose pull` this pulls updates for all non-bot services, such as psotgres, redis and our [site](../site) project! +1. `docker compose pull` this pulls updates for all non-bot services, such as postgres, redis and our [site](../site) project! 1. `docker compose build` this rebuilds the bot's docker image, this is only needed if you need to make changes to the bot's dependencies, or the Dockerfile itself. Your bot is now running, all inside Docker. -- cgit v1.2.3 From 45855fe2e3906614490f3577cb50e530423c35b7 Mon Sep 17 00:00:00 2001 From: jchristgit Date: Wed, 2 Aug 2023 11:06:02 +0200 Subject: Capitalize Python outside of tags (#1046) Related to #1044. Co-authored-by: Xithrius <15021300+Xithrius@users.noreply.github.com> --- .../pydis-guides/contributing/bot-extended-configuration-options.md | 2 +- .../content/resources/guides/python-guides/docker-hosting-guide.md | 2 +- pydis_site/templates/events/pages/code-jams/8/_index.html | 4 ++-- pydis_site/templates/events/pages/code-jams/8/frameworks.html | 2 +- pydis_site/templates/events/pages/code-jams/9/_index.html | 2 +- static-builds/README.md | 2 +- static-builds/netlify_build.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md index a35d79a9..f5425d88 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/bot-extended-configuration-options.md @@ -73,7 +73,7 @@ If you wish to set all values in your `env.server` for your testing server, you **Note**: This is only required when you're not configuring the bot [automatically](#automatic-configuration) -If you will be working on a feature that includes the python help forum, you will need to use `Forum Channels`. +If you will be working on a feature that includes the Python help forum, you will need to use `Forum Channels`. Forum channels cannot be included in a template, which is why this needs to be done by hand for the time being. diff --git a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md index 57d86e99..7af6a0bb 100644 --- a/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md +++ b/pydis_site/apps/content/resources/guides/python-guides/docker-hosting-guide.md @@ -26,7 +26,7 @@ description: This guide shows how to host a bot with Docker and GitHub Actions o ## Introduction -Let's say you have got a nice discord bot written in python and you have a VPS to host it on. Now the only question is +Let's say you have got a nice discord bot written in Python and you have a VPS to host it on. Now the only question is how to run it 24/7. You might have been suggested to use *screen multiplexer*, but it has some disadvantages: 1. Every time you update the bot you have to SSH to your server, attach to screen, shutdown the bot, run `git pull` and diff --git a/pydis_site/templates/events/pages/code-jams/8/_index.html b/pydis_site/templates/events/pages/code-jams/8/_index.html index 628a2c22..74e0ad4a 100644 --- a/pydis_site/templates/events/pages/code-jams/8/_index.html +++ b/pydis_site/templates/events/pages/code-jams/8/_index.html @@ -26,7 +26,7 @@

Perceptive Porcupines: WTPython!?

VV, Poppinawhile, ethansocal, Jeff Z, Cohan, ¯\_(ツ)_/¯

- What the Python (wtpython) is a simple terminal user interface that allows you to explore relevant answers on Stackoverflow without leaving your terminal or IDE. When you get an error, all you have to do is swap python for wtpython. When your code hits an error, you'll see a textual interface for exploring relevant answers allowing you to stay focused and ship faster! + What the Python (wtpython) is a simple terminal user interface that allows you to explore relevant answers on Stackoverflow without leaving your terminal or IDE. When you get an error, all you have to do is swap Python for wtpython. When your code hits an error, you'll see a textual interface for exploring relevant answers allowing you to stay focused and ship faster!

Demo video @@ -89,7 +89,7 @@

The Qualifier

The qualifier is a coding challenge that you are required to complete before registering for the code jam. - This is meant as a basic assessment of your skills to ensure you have enough python knowledge to effectively contribute in a team environment. + This is meant as a basic assessment of your skills to ensure you have enough Python knowledge to effectively contribute in a team environment.

View the Qualifier

diff --git a/pydis_site/templates/events/pages/code-jams/8/frameworks.html b/pydis_site/templates/events/pages/code-jams/8/frameworks.html index 1c02e38a..d8fbe96f 100644 --- a/pydis_site/templates/events/pages/code-jams/8/frameworks.html +++ b/pydis_site/templates/events/pages/code-jams/8/frameworks.html @@ -103,7 +103,7 @@

  • Documentation Link
  • Supports: Linux, Mac, and Windows
  • -
  • Pure python library
  • +
  • Pure Python library
diff --git a/pydis_site/templates/events/pages/code-jams/9/_index.html b/pydis_site/templates/events/pages/code-jams/9/_index.html index 3e60c387..5c094b22 100644 --- a/pydis_site/templates/events/pages/code-jams/9/_index.html +++ b/pydis_site/templates/events/pages/code-jams/9/_index.html @@ -75,7 +75,7 @@

The Qualifier

The qualifier is a coding challenge that you are required to complete before registering for the code jam. - This is meant as a basic assessment of your skills to ensure you have enough python knowledge to effectively contribute in a team environment. + This is meant as a basic assessment of your skills to ensure you have enough Python knowledge to effectively contribute in a team environment.

View the Qualifier

diff --git a/static-builds/README.md b/static-builds/README.md index a3c7962b..afd34bb0 100644 --- a/static-builds/README.md +++ b/static-builds/README.md @@ -42,7 +42,7 @@ Publish Directory: | Name | Value | Description | |----------------|--------------------------------|-------------------------------------------------------------------------------------------| -| PYTHON_VERSION | 3.8 | The python version. Supported options are defined by netlify [here][netlify build image]. | +| PYTHON_VERSION | 3.8 | The Python version. Supported options are defined by netlify [here][netlify build image]. | | API_URL | https://pythondiscord.com/ | The link to the API, which will be used to fetch the build artifacts. | | ACTION_NAME | Build & Publish Static Preview | The name of the workflow which will be used to find the artifact. | | ARTIFACT_NAME | static-build | The name of the artifact to download. | diff --git a/static-builds/netlify_build.py b/static-builds/netlify_build.py index 2d311a11..4d4a613d 100644 --- a/static-builds/netlify_build.py +++ b/static-builds/netlify_build.py @@ -1,6 +1,6 @@ """Build script to deploy project on netlify.""" -# WARNING: This file must remain compatible with python 3.8 +# WARNING: This file must remain compatible with Python 3.8 # This script performs all the actions required to build and deploy our project on netlify # It depends on the following packages, which are set in the netlify UI: -- cgit v1.2.3 From 0e389069035af8bbbc6450341373ad18b53e575a Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Thu, 31 Aug 2023 09:18:10 +0200 Subject: Document Netlify static previews Closes #677. --- .../content/resources/guides/pydis-guides/contributing/site.md | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 9eef8d23..13021e65 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -128,6 +128,14 @@ Unless you are editing the Dockerfile or docker-compose.yml, you shouldn't need [**Click here to see the basic Git workflow when contributing to one of our projects.**](../working-with-git/) +--- +# Deploy previews + +When you open a pull request, the `netlify` bot will build and publish a static +preview of your changes, which is very valuable if you made any changes to the +content or styling of the website. An example deploy preview can be found on +[pull request #773](https://github.com/python-discord/site/pull/773#issuecomment-1257224147). + --- # Django admin site -- cgit v1.2.3 From fd3c75be589f9d622a222ebbd017da503df6ffe2 Mon Sep 17 00:00:00 2001 From: jchristgit Date: Mon, 18 Sep 2023 11:54:15 +0200 Subject: Link guide to contributing a page in site guide (#1105) --- .../apps/content/resources/guides/pydis-guides/contributing/site.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 13021e65..b1ed54b8 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -181,6 +181,6 @@ The website is configured through the following environment variables: # Next steps Now that you have everything setup, it is finally time to make changes to the site! If you have not yet read the [contributing guidelines](../contributing-guidelines.md), now is a good time. Contributions that do not adhere to the guidelines may be rejected. -If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project) is for you. +If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project), or the [guide on contributing a page](../../how-to-contribute-a-page) is for you. Have fun! -- cgit v1.2.3 From 83fd70647cebdccf23e892c3d462c613e3674784 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Mon, 4 Dec 2023 10:26:23 +0100 Subject: Update required Python version Include a note to update the contributor guide in the Dockerfile instruction pinning the Python version as well. --- Dockerfile | 4 ++++ .../apps/content/resources/guides/pydis-guides/contributing/site.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/Dockerfile b/Dockerfile index 448d81cf..5aea6dbf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,7 @@ +# When updating the Python version here, please make sure to also +# update the contributor guide, which can be found at +# pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +# Thank you! FROM ghcr.io/owl-corp/python-poetry-base:3.11-slim # Allow service to handle stops gracefully diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index b1ed54b8..2515d07f 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -9,7 +9,7 @@ You should have already forked the [`site`](https://github.com/python-discord/si ### Requirements -- [Python 3.10](https://www.python.org/downloads/) +- [Python 3.11](https://www.python.org/downloads/) - [Poetry](https://python-poetry.org/docs/#installation) - `pip install poetry` - [Git](https://git-scm.com/downloads) -- cgit v1.2.3 From dcb3e14ab19a20fd10eeea0e5ff1736e2c616e61 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Mon, 4 Dec 2023 16:26:45 +0100 Subject: Fix typo in psql quit command --- .../apps/content/resources/guides/pydis-guides/contributing/site.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 2515d07f..404ff429 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -53,7 +53,7 @@ CREATE DATABASE pysite WITH OWNER pysite; CREATE DATABASE metricity WITH OWNER pysite; ``` -Finally, enter `/q` to exit psql. +Finally, enter `\q` to exit psql. ### 2. Environment variables -- cgit v1.2.3 From f33d3535be5eb1bad6df1d765872b6db05b5fff3 Mon Sep 17 00:00:00 2001 From: jchristgit Date: Mon, 11 Dec 2023 14:00:08 +0100 Subject: Mention READMEs for app dirs in contributing guide (#1168) Allow people to figure out our repository structure easily after settnig up the project. Part of #673. --- .../apps/content/resources/guides/pydis-guides/contributing/site.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'pydis_site/apps/content/resources/guides') diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md index 404ff429..1927f449 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/site.md @@ -183,4 +183,9 @@ Now that you have everything setup, it is finally time to make changes to the si If you're not sure where to go from here, our [detailed walkthrough](../#2-set-up-the-project), or the [guide on contributing a page](../../how-to-contribute-a-page) is for you. +The site repository also contains `README.md` files in all major directories of +interest, which explain where which functionality of the site is located. For +example, see the [API app's +README](https://github.com/python-discord/site/tree/main/pydis_site/apps/api). + Have fun! -- cgit v1.2.3