-
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.
Update README & refactor examples (#44)
Co-authored-by: Ayden <jaholaayden@gmail.com>
- Loading branch information
1 parent
c3b04f8
commit 65d1d95
Showing
10 changed files
with
196 additions
and
143 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 |
---|---|---|
@@ -0,0 +1 @@ | ||
TOKEN= |
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,53 +1,8 @@ | ||
# Blockbot | ||
|
||
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. | ||
Blockbot is a Discord bot, written in Python, that is maintained by the [Redbrick Webgroup](https://docs.redbrick.dcu.ie/webgroup/). | ||
|
||
## Resources | ||
## Documentation | ||
|
||
- [`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) | ||
Development documentation is hosted on the [Redbrick docs](https://docs.redbrick.dcu.ie/webgroup/blockbot/). | ||
|
||
## File Structure | ||
|
||
- `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 | ||
|
||
### 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 @@ | ||
hikari==2.0.0.dev122 | ||
hikari-arc==1.1.0 | ||
ruff==0.2.0 | ||
pre-commit==3.6.0 | ||
hikari==2.1.0 | ||
hikari-arc==1.3.4 | ||
hikari-miru==4.1.1 | ||
python-dotenv==1.0.1 | ||
pyfiglet==1.0.2 | ||
fortune-python==1.1.1 |
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,2 @@ | ||
ruff==0.6.9 | ||
pre-commit==4.0.0 |
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,35 @@ | ||
import arc | ||
|
||
plugin = arc.GatewayPlugin(name="Example Commands") | ||
|
||
|
||
@plugin.include | ||
@arc.slash_command("hello", "Say hello!") | ||
async def hello(ctx: arc.GatewayContext) -> None: | ||
"""An individual command, invoked by `/hello`.""" | ||
await ctx.respond("Hello from hikari and hikari-arc!") | ||
|
||
|
||
group = plugin.include_slash_group("base_group", "A base command group, with sub groups and sub commands.") | ||
|
||
|
||
@group.include | ||
@arc.slash_subcommand("sub_command", "A sub command") | ||
async def sub_command(ctx: arc.GatewayContext) -> None: | ||
"""A subcommand, invoked by `/base_command sub_command`.""" | ||
await ctx.respond("Hello, world! This is a sub command") | ||
|
||
|
||
sub_group = group.include_subgroup("sub_group", "A subgroup to add commands to.") | ||
|
||
|
||
@sub_group.include | ||
@arc.slash_subcommand("sub_command", "A subgroup subcommand.") | ||
async def sub_group_sub_command(ctx: arc.GatewayContext) -> None: | ||
"""A subcommand belonging to a subgroup, invoked by `/base_group sub_group sub_command`.""" | ||
await ctx.respond("This is a subgroup subcommand.") | ||
|
||
|
||
@arc.loader | ||
def loader(client: arc.GatewayClient) -> None: | ||
client.add_plugin(plugin) |
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,67 @@ | ||
import arc | ||
import hikari | ||
import miru | ||
|
||
plugin = arc.GatewayPlugin("Example Components") | ||
|
||
|
||
class View(miru.View): | ||
def __init__(self, user_id: int) -> None: | ||
self.user_id = user_id | ||
|
||
super().__init__(timeout=60) | ||
|
||
@miru.button("Click me!", custom_id="click_me") | ||
async def click_button(self, ctx: miru.ViewContext, button: miru.Button) -> None: | ||
await ctx.respond(f"{ctx.user.mention}, you clicked me!") | ||
|
||
# Defining select menus: https://miru.hypergonial.com/guides/selects/ | ||
@miru.text_select( | ||
custom_id="select_me", | ||
placeholder="Choose your favourite colours...", | ||
min_values=1, | ||
max_values=3, | ||
options=[ | ||
miru.SelectOption(label=colour) | ||
for colour in ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"] | ||
], | ||
) | ||
async def colour_select(self, ctx: miru.ViewContext, select: miru.TextSelect) -> None: | ||
await ctx.respond(f"Your favourite colours are: {', '.join(select.values)}!") | ||
|
||
# Defining a custom view check: https://miru.hypergonial.com/guides/checks_timeout/#checks | ||
async def view_check(self, ctx: miru.ViewContext) -> bool: | ||
# This view will only handle interactions that belong to the | ||
# user who originally ran the command. | ||
# For every other user they will receive an error message. | ||
if ctx.user.id != self.user_id: | ||
await ctx.respond("You can't press this!", flags=hikari.MessageFlag.EPHEMERAL) | ||
return False | ||
|
||
return True | ||
|
||
# Handling view timeouts: https://miru.hypergonial.com/guides/checks_timeout/#timeout | ||
# Editing view items: https://miru.hypergonial.com/guides/editing_items/ | ||
async def on_timeout(self) -> None: | ||
message = self.message | ||
assert message # Since the view is bound to a message, we can assert it's not None | ||
|
||
for item in self.children: | ||
item.disabled = True | ||
|
||
await message.edit(components=self) | ||
self.stop() | ||
|
||
|
||
@plugin.include | ||
@arc.slash_command("components", "A command with components.") | ||
async def components_cmd(ctx: arc.GatewayContext, miru_client: miru.Client = arc.inject()) -> None: | ||
view = View(ctx.user.id) | ||
response = await ctx.respond("Here are some components...", components=view) | ||
|
||
miru_client.start_view(view, bind_to=await response.retrieve_message()) | ||
|
||
|
||
@arc.loader | ||
def loader(client: arc.GatewayClient) -> None: | ||
client.add_plugin(plugin) |
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,45 @@ | ||
import arc | ||
import hikari | ||
import miru | ||
|
||
plugin = arc.GatewayPlugin("Example Modal") | ||
|
||
|
||
# Modals Guide: https://miru.hypergonial.com/guides/modals/ | ||
class MyModal(miru.Modal, title="Tell us about yourself!"): | ||
name = miru.TextInput( | ||
label="Name", | ||
placeholder="Enter your name!", | ||
required=True, | ||
) | ||
|
||
bio = miru.TextInput( | ||
label="Biography", | ||
value="Age: \nHobbies:", # pre-filled content | ||
style=hikari.TextInputStyle.PARAGRAPH, | ||
required=False, | ||
) | ||
|
||
# The callback function is called after the user hits 'Submit' | ||
async def callback(self, ctx: miru.ModalContext) -> None: | ||
# values can also be accessed using ctx.values, | ||
# Modal.values, or with ctx.get_value_by_id() | ||
embed = hikari.Embed(title=self.name.value, description=self.bio.value) | ||
await ctx.respond(embed=embed) | ||
|
||
|
||
@plugin.include | ||
@arc.slash_command("modal", "A command with a modal response.") | ||
async def modal_command(ctx: arc.GatewayContext, miru_client: miru.Client = arc.inject()) -> None: | ||
modal = MyModal() | ||
builder = modal.build_response(miru_client) | ||
|
||
# arc has a built-in way to respond with a builder | ||
await ctx.respond_with_builder(builder) | ||
|
||
miru_client.start_modal(modal) | ||
|
||
|
||
@arc.loader | ||
def loader(client: arc.GatewayClient) -> None: | ||
client.add_plugin(plugin) |
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,32 @@ | ||
import arc | ||
import hikari | ||
|
||
plugin = arc.GatewayPlugin("Example Options") | ||
|
||
|
||
# Options Guide: https://arc.hypergonial.com/guides/options/ | ||
@plugin.include | ||
@arc.slash_command("options", "A command with options") | ||
async def options( | ||
ctx: arc.GatewayContext, | ||
str_option: arc.Option[str, arc.StrParams("A string option.", name="string")], | ||
int_option: arc.Option[int, arc.IntParams("An integer option.", name="integer", min=5, max=150)], | ||
attachment_option: arc.Option[hikari.Attachment, arc.AttachmentParams("An attachment option.", name="attachment")], | ||
channel_option: arc.Option[ | ||
hikari.TextableChannel | None, arc.ChannelParams("A textable channel option.", name="channel") | ||
] = None, | ||
) -> None: | ||
"""A command with lots of options.""" | ||
embed = hikari.Embed(title="There are a lot of options here", description="Maybe too many...", colour=0x5865F2) | ||
embed.set_image(attachment_option) | ||
|
||
embed.add_field("String option", str_option, inline=True) | ||
embed.add_field("Integer option", str(int_option), inline=True) | ||
embed.add_field("Channel option", f"<#{channel_option.id}>" if channel_option else "Not supplied", inline=True) | ||
|
||
await ctx.respond(embed=embed) | ||
|
||
|
||
@arc.loader | ||
def loader(client: arc.GatewayClient) -> None: | ||
client.add_plugin(plugin) |
This file was deleted.
Oops, something went wrong.