Working With the Plugin System#

The plugin system is so great, such that you can just delete all of my plugins under the hbot/plugins/* folder, put your own plugins there. The bot will work fine provided that you did not mess up the plugins, but if it ever crash, it is guaranteed to not be caused by the core of the bot, but rather your plugins.

How does the plugin system work?#

The plugin system is meant to be modular and simple enough for quick setup. Your custom module must have a class that inherit from hbot.core.base_plugins.BasePlugin (In other word, the class must be a subclass of hbot.core.base_plugins.BasePlugin). The class must also define a method called register_handlers(self), which can either be a normal method, or async method. The loader is capable of calling async version properly.

With this approach, you are free to have as many class as you want in your plugin, as the loader will only look for the class that inherit hbot.core.base_plugins.BasePlugin.

Take a look at the Sample Plugin.

Sample Plugin#

import logging
from typing import override

from pyrogram import filters
from pyrogram.client import Client
from pyrogram.handlers.handler import Handler
from pyrogram.handlers.message_handler import MessageHandler
from pyrogram.types.messages_and_media import Message

from hbot.base_plugin import BasePlugin, RegisterHandlerResult

logger = logging.getLogger(__name__)


class MyPlugin(BasePlugin):
    name: str = "Example Plugin"
    description: str = "This is the description of your plugin."

    def __init__(self, app: Client) -> None:
        self.app: Client = app

    async def ping(self, app: Client, message: Message) -> None:
        logger.debug("ping, pong!")
        await message.edit_text("Pong!")

    @override
    def register_handlers(self) -> RegisterHandlerResult:  # Note that this can be async if desired
        return RegisterHandlerResult(
            # This group set to 0 by default, you don't really need to specify this unless you
            # have an advanced use case that requires a different value for this
            group=0,
            handlers=[
                MessageHandler(
                    self.ping,
                    filters.command("ping", prefixes=self.prefixes) & filters.me,
                )
            ],
        )

It may look intimidating at first, but if you remove the type annotations and the import for it, they will look very simple.