SimpleEventHandler
SimpleEventHandler extends EventHandler to provide a more streamlined API with built-in support for filters and scheduled tasks.
Overview
By extending SimpleEventHandler, you can:
- Use attribute-based filters for fine-grained update handling
- Schedule periodic tasks with the
#[Cron] attribute
- Write cleaner, more declarative code
- Handle updates with automatic filtering
Basic Usage
use danog\MadelineProto\SimpleEventHandler;
use danog\MadelineProto\EventHandler\Message;
use danog\MadelineProto\EventHandler\Attributes\Handler;
use danog\MadelineProto\EventHandler\SimpleFilter\Incoming;
class MyBot extends SimpleEventHandler
{
#[Handler]
#[Incoming]
public function handleMessage(Message $message): void
{
// Only handles incoming messages
$message->reply("You said: {$message->message}");
}
}
MyBot::startAndLoopBot('bot.madeline', 'YOUR_BOT_TOKEN');
Filter System
Filters allow you to specify which updates a handler should process using PHP attributes.
Available Filters
SimpleEventHandler supports various filters from the SimpleFilter namespace:
Incoming
Only process incoming messages.
use danog\MadelineProto\EventHandler\SimpleFilter\Incoming;
#[Incoming]
public function onIncoming(Message $message): void
{
// Only incoming messages
}
Outgoing
Only process outgoing messages.
use danog\MadelineProto\EventHandler\SimpleFilter\Outgoing;
#[Outgoing]
public function onOutgoing(Message $message): void
{
// Only outgoing messages
}
FromAdmin
Only process messages from administrators.
use danog\MadelineProto\EventHandler\SimpleFilter\FromAdmin;
#[FromAdmin]
public function onAdminMessage(Message $message): void
{
// Only messages from admins
}
Only process messages containing media.
use danog\MadelineProto\EventHandler\SimpleFilter\HasMedia;
#[HasMedia]
public function onMediaMessage(Message $message): void
{
// Only messages with media
$this->logger("Received media: " . get_class($message->media));
}
Combining Filters
Multiple filters can be combined on a single handler:
use danog\MadelineProto\EventHandler\SimpleFilter\Incoming;
use danog\MadelineProto\EventHandler\SimpleFilter\FromAdmin;
#[Incoming]
#[FromAdmin]
public function onAdminIncoming(Message $message): void
{
// Only incoming messages from admins
}
Regular Expression Filters
Filter messages by regex patterns:
use danog\MadelineProto\EventHandler\Filter\FilterRegex;
#[FilterRegex('/^\/start/')]
public function onStart(Message $message): void
{
// Matches /start command
$message->reply("Welcome!");
}
#[FilterRegex('/hello/i')]
public function onHello(Message $message): void
{
// Matches messages containing "hello" (case-insensitive)
$message->reply("Hi there!");
}
Access regex matches via the $matches property:
#[FilterRegex('/\/echo (.+)/')]
public function onEcho(Message $message): void
{
// Extract text after /echo command
$text = $message->matches[1] ?? '';
$message->reply($text);
}
Cron Tasks
Schedule periodic tasks using the #[Cron] attribute.
Basic Cron
use danog\MadelineProto\EventHandler\Attributes\Cron;
use danog\Loop\PeriodicLoop;
#[Cron(period: 60.0)] // Run every 60 seconds
public function checkStatus(PeriodicLoop $loop): void
{
$this->logger("Status check running...");
// Return true to stop the loop
// return true;
}
Cron Parameters
Interval in seconds between executions
Controlling Cron Loops
You can control cron loops programmatically:
use danog\MadelineProto\EventHandler\Attributes\Cron;
use danog\Loop\PeriodicLoop;
class MyBot extends SimpleEventHandler
{
#[Cron(period: 30.0)]
public function periodicTask(PeriodicLoop $loop): bool
{
$this->logger("Running periodic task");
// Return true to stop the loop
if ($this->shouldStop) {
return true;
}
return false;
}
public function stopPeriodicTask(): void
{
$loop = $this->getPeriodicLoop('periodicTask');
if ($loop) {
$loop->stop();
}
}
}
Type-Based Filtering
Handlers automatically filter by parameter type:
use danog\MadelineProto\EventHandler\Message;
use danog\MadelineProto\EventHandler\InlineQuery;
use danog\MadelineProto\EventHandler\CallbackQuery;
use danog\MadelineProto\EventHandler\Attributes\Handler;
#[Handler]
public function onMessage(Message $message): void
{
// Only messages
}
#[Handler]
public function onInlineQuery(InlineQuery $query): void
{
// Only inline queries
}
#[Handler]
public function onCallback(CallbackQuery $query): void
{
// Only callback queries
}
Complete Example
use danog\MadelineProto\SimpleEventHandler;
use danog\MadelineProto\EventHandler\Message;
use danog\MadelineProto\EventHandler\InlineQuery;
use danog\MadelineProto\EventHandler\Attributes\{Handler, Cron};
use danog\MadelineProto\EventHandler\SimpleFilter\{Incoming, FromAdmin};
use danog\MadelineProto\EventHandler\Filter\FilterRegex;
use danog\Loop\PeriodicLoop;
class AdvancedBot extends SimpleEventHandler
{
private int $messageCount = 0;
public function onStart(): void
{
$this->logger("Advanced bot started!");
}
#[FilterRegex('/^\/start/')]
#[Incoming]
public function handleStart(Message $message): void
{
$message->reply(
"Welcome! Available commands:\n" .
"/help - Show help\n" .
"/stats - Show statistics\n" .
"/admin - Admin panel (admins only)"
);
}
#[FilterRegex('/^\/stats/')]
public function handleStats(Message $message): void
{
$message->reply("Total messages processed: {$this->messageCount}");
}
#[FilterRegex('/^\/admin/')]
#[FromAdmin]
public function handleAdmin(Message $message): void
{
$message->reply("Admin panel access granted.");
}
#[Handler]
#[Incoming]
public function countMessages(Message $message): void
{
$this->messageCount++;
}
#[Handler]
public function handleInlineQuery(InlineQuery $query): void
{
// Handle inline queries
$this->logger("Inline query: {$query->query}");
}
#[Cron(period: 300.0)] // Every 5 minutes
public function saveStats(PeriodicLoop $loop): void
{
$this->logger("Saving statistics: {$this->messageCount} messages");
$this->internalSaveDbProperties();
}
public function getReportPeers(): string
{
return '@admin';
}
}
AdvancedBot::startAndLoopBot('bot.madeline', 'YOUR_BOT_TOKEN');
Advantages Over EventHandler
- Declarative Filters: Use attributes instead of manual if-checks
- Type Safety: Automatic filtering by parameter types
- Scheduled Tasks: Built-in cron support
- Cleaner Code: Less boilerplate, more focused on logic
- Regex Matching: Easy pattern matching with automatic match extraction
Requirements
To use filters and cron tasks, you must extend SimpleEventHandler instead of the base EventHandler class.
// ✅ Correct
class MyBot extends SimpleEventHandler { }
// ❌ Will throw AssertionError
class MyBot extends EventHandler {
#[Cron(period: 60.0)]
public function task(): void { } // Error: extend SimpleEventHandler
}
See Also