v0.3.x · pyrogram_patch

Middleware

Middleware functions intercept every update before or after handlers run. Three kinds: before, after, and around.

Before Middleware

Runs before every handler. Receives update, client, and patch_helper by parameter name (positional sniffing).

async def logging_middleware(update, client, patch_helper):
    user_id = getattr(update.from_user, "id", "?")
    print(f"[{user_id}] update received")

# Register after app.start()
await manager.add_middleware(logging_middleware, kind="before")

After Middleware

async def analytics_middleware(update, client):
    await track_event("update_handled", user=update.from_user.id)

await manager.add_middleware(analytics_middleware, kind="after")

Around Middleware

Wraps the handler call — useful for timing, transactions, or catching errors. Must accept and call next_handler.

async def timing_middleware(next_handler, update):
    import time
    start = time.monotonic()
    result = await next_handler(update)
    elapsed = time.monotonic() - start
    print(f"Handler took {elapsed:.3f}s")
    return result

await manager.add_middleware(timing_middleware, kind="around")

Priority

Higher-priority middleware runs first. Default is 0.

# Runs first (highest priority)
await manager.add_middleware(auth_check, kind="before", priority=100)

# Runs second
await manager.add_middleware(logging_mw, kind="before", priority=0)

# Runs last
await manager.add_middleware(cleanup_mw, kind="after", priority=-10)

PatchHelper in Middleware

The patch_helper parameter gives access to the FSM context and stored data for the current update's user.

async def session_middleware(update, client, patch_helper):
    state = await patch_helper.state
    data  = await patch_helper.get_data()

    if state == "banned":
        return   # short-circuit — do not call next handler