Track chat-member transitions
When to use this
Welcome new joiners, archive leavers, audit promotions — anything that fires when someone's chat membership status changes. The framework exposes my_chat_member
and chat_member
updates with a filter that matches by old/new status pairs.
Solution
Using a pre-built transition
use Gruven\PhpBotGram\Filters\ChatMemberUpdatedFilter;
use Gruven\PhpBotGram\Types\ChatMemberUpdated;
// Pre-built: anyone joining the chat.
$dispatcher->chatMember->register(
static function (ChatMemberUpdated $event): void {
$name = $event->newChatMember->user->firstName ?? 'a user';
$event->bot->sendMessage(
chatId: $event->chat->id,
text: "Welcome, {$name}!",
);
},
filters: [ChatMemberUpdatedFilter::join()],
);
Using a custom transition
use Gruven\PhpBotGram\Filters\ChatMemberUpdatedFilter;
use Gruven\PhpBotGram\Types\ChatMemberUpdated;
// Custom transition: any member becoming an administrator.
$dispatcher->chatMember->register(
static function (ChatMemberUpdated $event): void {
// Audit log…
},
filters: [ChatMemberUpdatedFilter::transition(
from: ChatMemberUpdatedFilter::MEMBER,
to: ChatMemberUpdatedFilter::IS_ADMIN,
)],
);
ChatMemberUpdatedFilter ports aiogram's JOIN_TRANSITION
/LEAVE_TRANSITION
constants as the factory methods join()
, leave()
, promotion()
, demotion()
. transition(from:, to:)
accepts the public status lists (MEMBER
, IS_ADMIN
, IS_MEMBER
, IS_NOT_MEMBER
, etc.).
Pitfalls
- Subscribe to
chat_memberupdates explicitly viaPollingOptions::$allowedUpdates— Telegram strips them by default.my_chat_memberarrives unconditionally. - The
restrictedstatus is collapsed intoIS_MEMBERregardless ofis_member. For finer control, build atransition()manually and post-filter onoldChatMember->isMember. - The bot must be an admin in the chat to receive
chat_memberevents for OTHER users — Telegram restriction, not framework. See Filters for the predicate model.