Skip to content

💻 Initial structure and a simple handler

Introduction

The structure of the module was described in the previous section. Now let's move on to its creation!

INFO

First read the PyroTGFork, this only describes the specifics of writing for PBModular

Step 1: Create module directory and configuration

Create a directory for your module (e.g., my_module) inside the main modules/ folder. Inside my_module, create:

  1. init.py: This file makes Python treat the directory as a package. It should import your main module class (see Step 2).
  2. config.yaml: This file defines metadata and settings for your module. It's preferred over the older info.yaml.

Example config.yaml:

python
# config.yaml
info:
  name: MyModule # User-friendly name (single word recommended)
  author: Your Name
  version: 0.1.0
  description: A brief description of what the module does.
  src_url: https://github.com/your/repo # Optional: Link to source code
  python: 3.11 # Optional: Recommended Python version (warns if different)
  auto_load: true # Optional: Whether to load this module automatically (default: true)

# Optional: List of permissions needed (see Module Permissions)
permissions:
  - use_db # Example: requests database access

# Optional: Custom configuration specific to your module
config:
  key: "YOUR_DEFAULT_KEY"
  feature_enabled: true

WARNING

Fallback: If config.yaml is missing, the loader will look for info.yaml (containing only info and permissions keys) for backward compatibility, but using config.yaml is strongly recommended.

Step 2: Create the main module class

Create a Python file (e.g., main.py) in your module directory and define your main class inheriting from BaseModule.

python
# main.py
from base.module import BaseModule, command
from pyrogram import Client
from pyrogram.types import Message

class MyModule(BaseModule):
    # Module logic and handlers go here
    pass

Now, make sure __init__.py imports this class:

python
# __init__.py
from .main import MyModule

Step 3: Writing a command handler

Define an asynchronous method within your MyModule class. The method should accept self, and optionally client (the Pyrogram Client instance) and message (or callback_query, depending on the handler type).

python
# main.py (inside MyModule class)
    async def on_hello(self, client: Client, message: Message):
        """Replies with a friendly greeting.""" # Docstring used for auto-help
        await message.reply("Hello World!")

Step 4: Registering the handler

Use decorators from base.module to register your method as a handler.

  • @command(names, filters=None, fsm_state=None): Registers a command handler.
    • names: A string or list of strings for the command name(s) (e.g., "hello" or ["hi", "hello"]).
    • filters: Optional Pyrogram filter (pyrogram.filters.Filter) to add more specific conditions. Highly recommended for commands beyond simple triggers (e.g., filters.private or filters.regex).
    • fsm_state: Optional State or list of States for FSM control (see FSM documentation).
  • @callback_query(filters=None, fsm_state=None): Registers a callback query handler (for inline buttons).
  • @message(filters=None, fsm_state=None): Registers a general message handler. Using filters here is crucial to avoid conflicts and performance issues.
python
# main.py (inside MyModule class)
    from base.module import command
    from pyrogram import filters

    @command("hello", filters=filters.private) # Only works in private chat
    async def on_hello(self, client: Client, message: Message):
        """Replies with a friendly greeting."""
        await message.reply("Hello World!")

    @command("start", filters.regex(r"/start payload_\w+")) # Example with regex
    async def on_start_with_payload(self, client: Client, message: Message):
        """Handles start command with specific payload"""
        payload = message.text.split('_', 1)[1]
        await message.reply(f"Received start with payload: {payload}")

INFO

The framework automatically handles command registration (command_registry) and permission checks (@allowed_for decorator and /allow_cmd command).