diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..1ac1f10 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,27 @@ +## Functionality Examples +This directory contains multiple examples demonstrating how to use different +features of the **[matrix.py]** library. Each example is self-contained and can be +run independently. + +### How to Run the Examples +- You will first need to update the environment variables in the [config.yaml](config.yaml) +file with your Matrix credentials and desired settings. + +- To run any of the examples, navigate to the `examples` directory from your +command line and execute the desired Python file using the command line. +For instance: + +```bash +python3 error_handling.py +``` + +Make sure you have all the necessary dependencies installed and configured +before running the examples as instructed in the root [README file](../README.md). + +### Available Examples +- [error_handling.py](error_handling.py): Demonstrates how to handle errors in commands. +- [cooldown.py](cooldown.py): Shows how to implement cooldowns for commands. +- [ping.py](ping.py): A simple ping command example. +- [reaction.py](reaction.py): Example of handling reactions to messages. +- [checks.py](checks.py): Demonstrates how to use checks for command execution. +- [scheduler.py](scheduler.py): Shows how to schedule tasks. diff --git a/examples/checks.py b/examples/checks.py index 24ab944..58bf128 100644 --- a/examples/checks.py +++ b/examples/checks.py @@ -1,12 +1,13 @@ from matrix import Bot, Context +from matrix.errors import CheckError -bot = Bot("examples/config.yaml") +bot = Bot(config="config.yaml") allowed_users = {"@alice:matrix.org", "@bob:matrix.org"} -@bot.command("secret") -async def secret_command(ctx: Context): +@bot.command(name="secret") +async def secret_command(ctx: Context) -> None: await ctx.reply("🎉 Welcome to the secret club!") @@ -14,8 +15,12 @@ async def secret_command(ctx: Context): async def is_allowed_user(ctx: Context) -> bool: if ctx.sender in allowed_users: return True - await ctx.reply("You do not have permission to use this command.") return False +@secret_command.error(CheckError) +async def permission_error_handler(ctx: Context, error: CheckError) -> None: + await ctx.reply(f"Access denied: {error}") + + bot.start() diff --git a/examples/cooldown.py b/examples/cooldown.py index a04638a..8450840 100644 --- a/examples/cooldown.py +++ b/examples/cooldown.py @@ -1,30 +1,29 @@ from matrix import Bot, Context, cooldown from matrix.errors import CooldownError -bot = Bot("examples/config.yaml") +bot = Bot(config="config.yaml") -@bot.command(cooldown=(2, 15)) -async def cooldown_command(ctx): - await ctx.reply("This is limited to 2 uses per 15s per user.") +# Invoke by using !hello +@cooldown(rate=2, period=10) +@bot.command("hello") +async def hello_command(ctx: Context) -> None: + await ctx.reply("Hello World.") -@cooldown_command.error(CooldownError) -async def cooldown_error(ctx, error): - print(f"CooldownError invoked: Try again in {error.retry:.1f} seconds.") +@hello_command.error(CooldownError) +async def hello_command_error_handler(ctx: Context, error: CooldownError) -> None: await ctx.reply(f"⏳ Try again in {error.retry:.1f}s") -@cooldown(2, 10) -@bot.command("hi") -async def hello(ctx: Context): - print(f"{ctx.sender} invoked {ctx.body} in room {ctx.room_name}.") - await ctx.reply("Hello World.") +# Invoke by using !cooldown_command +@bot.command(cooldown=(1, 10)) +async def cooldown_command(ctx: Context) -> None: + await ctx.reply("This is limited to 1 uses per 10s per user.") -@hello.error(CooldownError) -async def hello_error(ctx, error): - print(f"CooldownError invoked: Try again in {error.retry:.1f} seconds.") +@cooldown_command.error(CooldownError) +async def cooldown_function(ctx: Context, error: CooldownError) -> None: await ctx.reply(f"⏳ Try again in {error.retry:.1f}s") diff --git a/examples/error.py b/examples/error.py deleted file mode 100644 index e358f73..0000000 --- a/examples/error.py +++ /dev/null @@ -1,36 +0,0 @@ -from matrix import Bot, Context -from matrix.errors import CommandNotFoundError, MissingArgumentError - -bot = Bot("examples/config.yaml") - - -@bot.error(CommandNotFoundError) -async def global_error(error): - print(f"Glable error handler {error}.") - - -@bot.command("div") -async def division(ctx: Context, a: int, b: int): - c = a / b - await ctx.reply(c) - - -@division.error(ZeroDivisionError) -async def div_error(ctx, error): - print(f"Operation Not Allowed: {error}") - await ctx.reply(f"Operation not allowed: {error}") - - -@division.error(ValueError) -async def val_error(ctx, error): - print(f"ValueError: {error}") - await ctx.reply(f"ValueError: {error}") - - -@division.error(MissingArgumentError) -async def command_error(ctx, error): - print(error) - await ctx.reply(error) - - -bot.start() diff --git a/examples/error_handling.py b/examples/error_handling.py new file mode 100644 index 0000000..88b7c25 --- /dev/null +++ b/examples/error_handling.py @@ -0,0 +1,33 @@ +from matrix import Bot, Context +from matrix.errors import CommandNotFoundError, MissingArgumentError + +bot = Bot(config="config.yaml") + + +@bot.error(CommandNotFoundError) +async def global_error(error: CommandNotFoundError) -> None: + print(f"Global error handler {error}.") + + +@bot.command("div") +async def division(ctx: Context, a: int, b: int) -> None: + c = a / b + await ctx.reply(f"{a} / {b} = {c}") + + +@division.error(ZeroDivisionError) +async def div_error(ctx: Context, error: ZeroDivisionError) -> None: + await ctx.reply(f"Operation not allowed: {error}") + + +@division.error(ValueError) +async def val_error(ctx: Context, error: ValueError) -> None: + await ctx.reply(f"ValueError: {error}") + + +@division.error(MissingArgumentError) +async def command_error(ctx: Context, error: MissingArgumentError) -> None: + await ctx.reply(f"{error}") + + +bot.start() diff --git a/examples/ping.py b/examples/ping.py index a8e7735..58d6f39 100644 --- a/examples/ping.py +++ b/examples/ping.py @@ -1,11 +1,10 @@ from matrix import Bot, Context -bot = Bot("examples/config.yaml") +bot = Bot(config="config.yaml") @bot.command("ping") -async def ping(ctx: Context): - print(f"{ctx.sender} invoked {ctx.body} in room {ctx.room_name}.") +async def ping(ctx: Context) -> None: await ctx.reply("Pong!") diff --git a/examples/reaction.py b/examples/reaction.py index d9c585c..204bcd1 100644 --- a/examples/reaction.py +++ b/examples/reaction.py @@ -1,10 +1,11 @@ -from matrix import Bot +from asyncio import Event +from matrix import Bot, Room -bot = Bot("examples/config.yaml") +bot = Bot(config="config.yaml") @bot.event -async def on_message(room, event): +async def on_message(room: Room, event: Event) -> None: """ This function listens for new messages in a room and reacts based on the message content. @@ -22,7 +23,7 @@ async def on_message(room, event): @bot.event -async def on_react(room, event): +async def on_react(room: Room, event: Event) -> None: """ This function listens for new member reaction to messages in a room, and reacts based on the reaction emoji. diff --git a/examples/scheduler.py b/examples/scheduler.py index bcb7266..955535a 100644 --- a/examples/scheduler.py +++ b/examples/scheduler.py @@ -1,6 +1,6 @@ from matrix import Bot, Context -bot = Bot("examples/config.yaml") +bot = Bot(config="config.yaml") room_id = "!your_room_id:matrix.org" # Replace with your room ID @@ -8,26 +8,25 @@ @bot.command("ping") -async def ping(ctx: Context): - print(f"{ctx.sender} invoked {ctx.body} in room {ctx.room_name}.") +async def ping(ctx: Context) -> None: await ctx.reply("Pong!") @bot.schedule("* * * * *") -async def scheduled_task(): - print("This task runs every minute.") +async def scheduled_task() -> None: + # This task runs every minute. await room.send(message="Scheduled ping!") @bot.schedule("0 * * * *") -async def hourly_task(): - print("This task runs every hour.") +async def hourly_task() -> None: + # This task runs every hour. await room.send(message="This is your hourly update!") @bot.schedule("0 9 * * 1-5") -async def weekday_morning_task(): - print("This task runs every weekday at 9 AM.") +async def weekday_morning_task() -> None: + # This task runs every weekday at 9 AM. await room.send(message="Good morning! Here's your weekday update!") diff --git a/matrix/__init__.py b/matrix/__init__.py index 86d366c..e5a749d 100644 --- a/matrix/__init__.py +++ b/matrix/__init__.py @@ -9,6 +9,7 @@ from .command import Command from .help import HelpCommand from .checks import cooldown +from .room import Room __all__ = [ "Bot", @@ -18,4 +19,5 @@ "Context", "HelpCommand", "cooldown", + "Room", ] diff --git a/matrix/errors.py b/matrix/errors.py index 4b64377..18f3890 100644 --- a/matrix/errors.py +++ b/matrix/errors.py @@ -3,7 +3,6 @@ if TYPE_CHECKING: from .command import Command # pragma: no cover - from .error import Error # pragam: no cover from .group import Group # pragma: no cover Callback = Callable[..., Coroutine[Any, Any, Any]] diff --git a/tests/test_help.py b/tests/test_help.py deleted file mode 100644 index e69de29..0000000