-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into 27-uptime--koyakonsta
- Loading branch information
Showing
9 changed files
with
205 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,53 @@ | ||
# Blockbot | ||
|
||
This Discord bot uses the `interactions.py` module to interface with the Discord API. | ||
Blockbot is a Discord bot, written in Python, that is maintained by the Redbrick Webgroup. This project uses [`hikari`](https://github.com/hikari-py/hikari/), an opinionated microframework, to interface with the Discord API. [`hikari-arc`](https://github.com/hypergonial/hikari-arc) is the command handler of choice. | ||
|
||
For help with using the module, check out the [documentation](https://interactions-py.github.io/interactions.py/Guides/). | ||
## Resources | ||
|
||
## Overview | ||
- [`hikari` Documentation](https://docs.hikari-py.dev/en/latest/) | ||
- [`hikari-arc` Documentation](https://arc.hypergonial.com/) | ||
- [Examples](https://github.com/hypergonial/hikari-arc/tree/main/examples/gateway) | ||
|
||
> `main.py:` | ||
- A custom, dynamic extension (command) loader. Write an extension in the `extensions/` directory, and it will automatically be loaded when the bot boots. | ||
## File Structure | ||
|
||
> `extensions/`: | ||
- This directory is home to the custom extensions (known as cogs in `discord.py`, or command groups) that are loaded when the bot is started. Extensions are classes that encapsulate command logic and can be dynamically loaded/unloaded. | ||
|
||
> `config.py:` | ||
- This module houses the bot configuration. The values are loaded from environment variables, so you can set them in your shell or in a `.env` file. | ||
- `bot.py` | ||
- This is the file that contains the bot configuration and instantiation, while also being responsible for loading the bot extensions. | ||
- `extensions/` | ||
- This directory is home to the custom extensions (known as cogs in `discord.py`, or command groups) that are loaded when the bot is started. Extensions are classes that encapsulate command logic and can be dynamically loaded/unloaded. In `hikari-arc`, an intuitive [plugin system](https://arc.hypergonial.com/guides/plugins_extensions/) is used. | ||
- `config.py` | ||
- Configuration secrets and important constants (such as identifiers) are stored here. The secrets are loaded from environment variables, so you can set them in your shell or in a `.env` file. | ||
- `utils.py` | ||
- Simple utility functions are stored here, that can be reused across the codebase. | ||
|
||
## Installation | ||
|
||
> 1. Clone this repository. To switch to a different version, `cd` into this cloned repository and run `git checkout [branch name/version here]` | ||
> 2. It's generally advised to work in a Python virtual environment. Here are steps to create one *(the `discord-py-interactions` library requires Python 3.10.0 or later)*: | ||
> > - `$` `python3 -m venv env` | ||
> > - `$` `source env/bin/activate` | ||
> 3. Create a Discord bot token from [here](https://discord.com/developers/applications/) | ||
> **Register it for slash commands:** | ||
> - Under *OAuth2 > General*, set the Authorization Method to "In-app Authorization" | ||
> - Tick `bot` and `applications.commands` | ||
> - Go to *OAuth2 > URL Generator*, tick `bot` and `applications.commands` | ||
> - Copy the generated URL at the bottom of the page to invite it to desired servers | ||
> 4. Make a new file called `.env` inside the repo folder and paste the below code block in the file | ||
> ``` | ||
> TOKEN=<paste Discord bot token here> | ||
> ``` | ||
> 5. Run `pip install -r requirements.txt` to install packages. You'll need Python 3.10 or later | ||
> 6. Once that's done, run the bot by executing `python3 main.py` in the terminal | ||
*If you aren't sure how to obtain your server ID, check out [this article](https://www.alphr.com/discord-find-server-id/)* | ||
*If you get errors related to missing token environment variables, run `source .env`* | ||
### Discord Developer Portal | ||
|
||
As a prerequisite, you need to have a bot application registered on the Discord developer portal. | ||
|
||
1. Create a Discord bot application [here](https://discord.com/developers/applications/). | ||
2. When you have a bot application, register it for slash commands: | ||
3. Go to *"OAuth2 > URL Generator"* on the left sidebar, select the `bot` and `applications.commands` scopes, scroll down & select the bot permissions you need (for development, you can select `Administator`). | ||
4. Copy and visit the generated URL at the bottom of the page to invite it to the desired server. | ||
|
||
#### Bot Token | ||
|
||
- Go to the Discord developer portal and under *"Bot"* on the left sidebar, click `Reset Token`. Copy the generated token. | ||
|
||
### Source Code | ||
1. `git clone` and `cd` into this repository. | ||
2. It's generally advised to work in a Python [virtual environment](https://docs.python.org/3/library/venv.html): | ||
```sh | ||
python3 -m venv .venv | ||
source .venv/bin/activate | ||
``` | ||
3. Create a new file called `.env` inside the repo folder and paste your bot token into the file as such: | ||
``` | ||
TOKEN=<Discord bot token here> | ||
``` | ||
4. Run `pip install -r requirements.txt` to install the required packages. | ||
5. Once that's done, start the bot by running `python3 -m src`. | ||
|
||
## FAQ | ||
|
||
- If you get errors related to missing token environment variables, run `source .env`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
"""Entrypoint script to load extensions and start the client.""" | ||
import hikari | ||
from hikari import Activity, ActivityType | ||
|
||
from src.bot import bot | ||
|
||
if __name__ == "__main__": | ||
bot.run(activity=hikari.Activity(name="Webgroup issues", type=hikari.ActivityType.WATCHING)) | ||
bot.run(activity=Activity(name="Webgroup issues", type=ActivityType.WATCHING)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import arc | ||
import hikari | ||
|
||
from src.utils import role_mention | ||
|
||
plugin = arc.GatewayPlugin(name="User Roles") | ||
|
||
role = plugin.include_slash_group("role", "Get/remove assignable roles.") | ||
|
||
role_choices = [ | ||
hikari.CommandChoice(name="Webgroup", value="1166751688598761583"), | ||
hikari.CommandChoice(name="Gamez", value="1089204642241581139"), | ||
hikari.CommandChoice(name="Croomer", value="1172696659097047050"), | ||
] | ||
|
||
@role.include | ||
@arc.slash_subcommand("add", "Add an assignable role.") | ||
async def add_role( | ||
ctx: arc.GatewayContext, | ||
role: arc.Option[str, arc.StrParams("The role to add.", choices=role_choices)] | ||
) -> None: | ||
assert ctx.guild_id | ||
assert ctx.member | ||
|
||
if int(role) in ctx.member.role_ids: | ||
return await ctx.respond( | ||
f"You already have the {role_mention(role)} role.", | ||
flags=hikari.MessageFlag.EPHEMERAL | ||
) | ||
|
||
await ctx.client.rest.add_role_to_member( | ||
ctx.guild_id, ctx.author, int(role), reason="Self-service role." | ||
) | ||
await ctx.respond( | ||
f"Done! Added {role_mention(role)} to your roles.", | ||
flags=hikari.MessageFlag.EPHEMERAL | ||
) | ||
|
||
@role.include | ||
@arc.slash_subcommand("remove", "Remove an assignable role.") | ||
async def remove_role( | ||
ctx: arc.GatewayContext, | ||
role: arc.Option[str, arc.StrParams("The role to remove.", choices=role_choices)] | ||
) -> None: | ||
assert ctx.guild_id | ||
assert ctx.member | ||
|
||
if int(role) not in ctx.member.role_ids: | ||
return await ctx.respond( | ||
f"You don't have the {role_mention(role)} role.", | ||
flags=hikari.MessageFlag.EPHEMERAL | ||
) | ||
|
||
await ctx.client.rest.remove_role_from_member( | ||
ctx.guild_id, ctx.author, int(role), reason=f"{ctx.author} removed role." | ||
) | ||
await ctx.respond( | ||
f"Done! Removed {role_mention(role)} from your roles.", | ||
flags=hikari.MessageFlag.EPHEMERAL | ||
) | ||
|
||
@role.set_error_handler | ||
async def role_error_handler(ctx: arc.GatewayContext, exc: Exception) -> None: | ||
role = ctx.get_option("role", arc.OptionType.STRING) | ||
assert role is not None | ||
|
||
if isinstance(exc, hikari.ForbiddenError): | ||
return await ctx.respond( | ||
f"❌ Blockbot is not permitted to self-service the {role_mention(role)} role.", | ||
flags=hikari.MessageFlag.EPHEMERAL | ||
) | ||
|
||
if isinstance(exc, hikari.NotFoundError): | ||
return await ctx.respond( | ||
f"❌ Blockbot can't find that role.", | ||
flags=hikari.MessageFlag.EPHEMERAL | ||
) | ||
|
||
raise exc | ||
|
||
@arc.loader | ||
def loader(client: arc.GatewayClient) -> None: | ||
client.add_plugin(plugin) |
Oops, something went wrong.