Skip to content

Commit

Permalink
♻️✨refactor | feature: add precommit hooks for black and ruff
Browse files Browse the repository at this point in the history
  • Loading branch information
ScuffedNewt committed Feb 2, 2024
1 parent 3229316 commit dff692a
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 38 deletions.
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
repos:
- repo: https://github.com/psf/black
rev: 24.1.1
hooks:
- id: black
language_version: python3
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
61 changes: 58 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,58 @@
hikari==2.0.0.dev122
hikari-arc==1.1.0
python-dotenv==1.0.1
aiohttp==3.9.3
aiosignal==1.3.1
alluka==0.1.4
async-timeout==4.0.3
attrs==23.2.0
black==24.1.1
blinker==1.4
cfgv==3.4.0
click==8.1.7
colorlog==6.8.2
command-not-found==0.3
cryptography==3.4.8
dbus-python==1.2.18
distlib==0.3.8
distro==1.7.0
distro-info==1.1+ubuntu0.1
filelock==3.13.1
frozenlist==1.4.1
hikari==2.0.0.dev122
hikari-arc==1.1.0
httplib2==0.20.2
identify==2.5.33
idna==3.6
importlib-metadata==4.6.4
jeepney==0.7.1
keyring==23.5.0
launchpadlib==1.10.16
lazr.restfulclient==0.14.4
lazr.uri==1.0.6
more-itertools==8.10.0
multidict==6.0.5
mypy-extensions==1.0.0
netifaces==0.11.0
nodeenv==1.8.0
oauthlib==3.2.0
packaging==23.2
pathspec==0.12.1
platformdirs==4.2.0
pre-commit==3.6.0
PyGObject==3.42.1
PyJWT==2.3.0
pyparsing==2.4.7
python-apt==2.4.0+ubuntu2
python-dotenv==1.0.1
PyYAML==5.4.1
ruff==0.2.0
SecretStorage==3.3.1
six==1.16.0
systemd-python==234
tomli==2.0.1
typing_extensions==4.9.0
ubuntu-advantage-tools==8001
ufw==0.36.1
unattended-upgrades==0.1
virtualenv==20.25.0
wadllib==1.3.6
yarl==1.9.4
zipp==1.0.0
1 change: 1 addition & 0 deletions src/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
client = arc.GatewayClient(bot, is_dm_enabled=False)
client.load_extensions_from("./src/extensions/")


@client.set_error_handler
async def error_handler(ctx: arc.GatewayContext, exc: Exception) -> None:
if DEBUG:
Expand Down
6 changes: 2 additions & 4 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

load_dotenv()

TOKEN = os.environ.get("TOKEN") # required
TOKEN = os.environ.get("TOKEN") # required
DEBUG = os.environ.get("DEBUG", False)

CHANNEL_IDS = {
"lobby": "627542044390457350"
}
CHANNEL_IDS = {"lobby": "627542044390457350"}
14 changes: 9 additions & 5 deletions src/extensions/boosts.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,40 @@
hikari.MessageType.USER_PREMIUM_GUILD_SUBSCRIPTION,
]


def build_boost_message(
message_type: hikari.MessageType | int,
number_of_boosts: str | None,
booster_user: hikari.Member,
guild: hikari.Guild
guild: hikari.Guild,
) -> str:
assert message_type in BOOST_MESSAGE_TYPES

base_message = f"{booster_user.display_name} just boosted the server"
multiple_boosts_message = f" **{number_of_boosts}** times" if number_of_boosts else ""
multiple_boosts_message = (
f" **{number_of_boosts}** times" if number_of_boosts else ""
)

message = base_message + multiple_boosts_message + "!"

if (message_type in BOOST_TIERS):
if message_type in BOOST_TIERS:
count = BOOST_TIERS.index(message_type) + 1
message += f"\n{guild.name} has reached **Level {count}!**"

return message


@plugin.listen()
async def on_message(event: hikari.GuildMessageCreateEvent):
if not event.message.type in BOOST_MESSAGE_TYPES:
if event.message.type not in BOOST_MESSAGE_TYPES:
return

assert event.member is not None
message = build_boost_message(
event.message.type,
number_of_boosts=event.content,
booster_user=event.member,
guild=await get_guild(plugin.client, event)
guild=await get_guild(plugin.client, event),
)

await plugin.client.rest.create_message(CHANNEL_IDS["lobby"], content=message)
Expand Down
25 changes: 16 additions & 9 deletions src/extensions/hello_world.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,59 @@
"""
Example extension with simple commands
"""

import arc
import hikari

plugin = arc.GatewayPlugin(name="Hello World")


@plugin.include
@arc.slash_command("hello", "Say hello!")
async def hello(ctx: arc.GatewayContext) -> None:
"""A simple hello world command"""
await ctx.respond("Hello from hikari!")


group = plugin.include_slash_group("base_command", "A base command, to expand on")


@group.include
@arc.slash_subcommand("sub_command", "A sub command, to expand on")
async def sub_command(ctx: arc.GatewayContext) -> None:
"""A simple sub command"""
await ctx.respond("Hello, world! This is a sub command")


@plugin.include
@arc.slash_command("options", "A command with options")
async def options(
ctx: arc.GatewayContext,
option_str: arc.Option[str, arc.StrParams("A string option")],
option_int: arc.Option[int, arc.IntParams("An integer option")],
option_attachment: arc.Option[hikari.Attachment, arc.AttachmentParams("An attachment option")],
option_attachment: arc.Option[
hikari.Attachment, arc.AttachmentParams("An attachment option")
],
) -> None:
"""A command with lots of options"""
embed = hikari.Embed(
title="There are a lot of options here",
description="Maybe too many",
colour=0x5865F2
title="There are a lot of options here",
description="Maybe too many",
colour=0x5865F2,
)
embed.set_image(option_attachment)
embed.add_field("String option", option_str, inline=False)
embed.add_field("Integer option", str(option_int), inline=False)
await ctx.respond(embed=embed)


@plugin.include
@arc.slash_command("components", "A command with components")
async def components(ctx: arc.GatewayContext) -> None:
"""A command with components"""
builder = ctx.client.rest.build_message_action_row()
select_menu = builder.add_text_menu(
"select_me",
placeholder="I wonder what this does",
min_values=1,
max_values=2
"select_me", placeholder="I wonder what this does", min_values=1, max_values=2
)
for opt in ("Select me!", "No, select me!", "Select me too!"):
select_menu.add_option(opt, opt)
Expand All @@ -59,6 +64,7 @@ async def components(ctx: arc.GatewayContext) -> None:

await ctx.respond("Here are some components", components=[builder, button])


@plugin.listen()
async def on_interaction(event: hikari.InteractionCreateEvent) -> None:
interaction = event.interaction
Expand All @@ -71,14 +77,15 @@ async def on_interaction(event: hikari.InteractionCreateEvent) -> None:
if interaction.custom_id == "click_me":
await interaction.create_initial_response(
hikari.ResponseType.MESSAGE_CREATE,
f"{interaction.user.mention}, you clicked me!"
f"{interaction.user.mention}, you clicked me!",
)
elif interaction.custom_id == "select_me":
await interaction.create_initial_response(
hikari.ResponseType.MESSAGE_CREATE,
f"{interaction.user.mention}, you selected {' '.join(interaction.values)}",
)


@arc.loader
def loader(client: arc.GatewayClient) -> None:
client.add_plugin(plugin)
8 changes: 6 additions & 2 deletions src/extensions/uptime.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

plugin = arc.GatewayPlugin("Blockbot Uptime")


@plugin.include
@arc.slash_command("uptime", "Show formatted uptime of Blockbot")
async def uptime(ctx):
Expand All @@ -14,12 +15,15 @@ async def uptime(ctx):
h, ms = divmod(up_time.seconds, 3600)
m, s = divmod(ms, 60)

format = lambda val, str: f"{val} {str}{'s' if val != 1 else ''}"
def format(val, str):
return f"{val} {str}{'s' if val != 1 else ''}"

message_parts = [(d, "day"), (h, "hour"), (m, "minute"), (s, "second")]
formatted_parts = [format(val, str) for val, str in message_parts if val]

await ctx.respond(f"Uptime: **{', '.join(formatted_parts)}**")


@arc.loader
def loader(client):
client.add_plugin(plugin)
33 changes: 18 additions & 15 deletions src/extensions/user_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,71 +13,74 @@
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)]
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
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
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)]
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
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
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
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
"❌ Blockbot can't find that role.", flags=hikari.MessageFlag.EPHEMERAL
)

raise exc


@arc.loader
def loader(client: arc.GatewayClient) -> None:
client.add_plugin(plugin)
2 changes: 2 additions & 0 deletions src/utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import hikari
from arc import GatewayClient


async def get_guild(client: GatewayClient, event: hikari.GuildMessageCreateEvent):
return event.get_guild() or await client.rest.fetch_guild(event.guild_id)


def role_mention(role_id: hikari.Snowflake | int | str):
return f"<@&{role_id}>"

0 comments on commit dff692a

Please sign in to comment.