Skip to content

Reference ​

Helpers ​

All helpers are defined in src/helpers.php and available globally when the package is installed.

Context & Buses ​

HelperReturnsDescription
wHook()WebhookCurrent request context (api, update, bot, user)
telegramApi($token, $baseUrl?)ApiCreate a Telegram API client
replyKeyBus()ReplyKeyBusReply keyboard handler registry
callbackQueryBus()CallbackQueryBusInline callback handler registry
stateAnswerBus()StateAnswerBusText input handler registry
inlineQueryBus()InlineQueryBusInline-mode query handler registry
commandBus()CommandBus/command handler registry — see Commands
botEventBus()BotEventBusLifecycle event registry — see Events & Listeners
stateData()StateDataServiceStateData create/merge service
botUserStatus()BotUserStatusBot-user reachability tracker — see Architecture
navState()NavStatePer-message navigation state (page/sort/filter) that outgrows callback_data
exceptionHandler()ExceptionHandlerWebhook exception handler

Encoding ​

HelperDescription
encodeCallback($type, $method, $params = [])Encode inline button callback_data (64-byte limit)
decodeCallback($input)Decode callback_data → ['type', 'method', 'params']
encodeAnswerState($type, $method, $params = [])Encode user state string
decodeAnswerState($input)Decode user state → ['type', 'method', 'params']

Registration ​

HelperDescription
loadCallbackQueries($path)Scan directory and register CallbackQuery subclasses
loadStateAnswers($path)Scan directory and register StateAnswer subclasses
loadReplyKeys($path)Scan directory and register ReplyKey subclasses
loadCommands($path)Scan directory and register Command subclasses
loadInlineQueries($path)Scan directory and register InlineQuery subclasses
addUserReplyKeys(array $rows)Register reply keys from config keyboard array
resolveNamespace($path)Resolve PSR-4 namespace from filesystem path

Since v0.12.0 these run once per worker boot from TelegramBotServiceProvider (app classes in a booted() callback so they win collisions), not per request.

UI Helpers ​

HelperDescription
inlineSorter($buttons, $step?)Arrange inline buttons into rows
smartInlineKeysSorter($buttons, $step?, $limit?)Sort by text length with row width limit
addInlineKeysSorted($keyboard, $keys, $step?)Add sorted rows to a Keyboard
addInlineKeysSmartSorted($keyboard, $keys, $step?, $limit?)Smart-sorted rows
getInputInlineKeyText()Get text of the pressed inline button
inlineConfirmationKey($text, $target, $back, $confirmText?)Create a confirmation button

Access & Guards ​

HelperDescription
hasAccess(?int $power)Check user role against required power level
dependsOn(?bool $condition, ?string $message)Throw FeatureIsDisabled if condition is falsy

Debugging ​

HelperDescription
exceptionReport(Throwable $e)Log + send trace/update to bug report chat
debugMessage(string $message)Log + send debug text to bug report chat
mixedDebugMessage(mixed $data)Log + send JSON-encoded data
adminAlert(string $key, Closure|string $text, ?Bot $bot, ?int $throttle)Tell the bot's owner and admins about something only they can fix, throttled per key (Logging)

Configuration ​

Published to config/tbe-essence.php via php artisan tbe:install.

php
return [
    // Reply keyboard layout per role
    'keyboard' => [
        'admin'  => [[AdminPanelKey::class], ...],
        'member' => [[MainMenuKey::class], ...],
    ],

    // Commands registered on Telegram's own command menu via tbe:set-webhook
    'commands' => [
        HelpCommand::class,
    ],

    // Bot management API token
    'bot_access' => [
        'token' => env('BOT_MANAGEMENT_ACCESS_TOKEN'),
    ],

    // Single-bot mode defaults
    'main' => [
        'unique_id'          => env('MAIN_UNIQUE_ID', 'main'),
        'telegram_bot_token' => env('MAIN_TELEGRAM_BOT_TOKEN'),
        'admin_chat_id'      => env('MAIN_ADMIN_CHAT_ID'),
        'currency'           => env('MAIN_CURRENCY', 'USD'),
    ],

    // Telegram API base URL
    'base_bot_url' => env('TELEGRAM_BOT_BASE_URL', 'https://api.telegram.org/bot'),

    // Error reporting destination
    'bug_report' => [
        'telegram_chat_id' => env('BUG_REPORT_TELEGRAM_CHAT_ID'),
    ],

    // Log channels + Telegram notification for tbeLog()
    'logging' => [
        'channel' => env('TBE_LOG_CHANNEL'),
        'channels' => [],                       // per-package overrides
        'audit_channel' => env('TBE_LOG_AUDIT_CHANNEL'),
        'telegram_notify' => env('TBE_LOG_TELEGRAM_NOTIFY', true),
    ],

    // adminAlert() throttle window, seconds
    'admin_alerts' => [
        'throttle' => env('TBE_ADMIN_ALERT_THROTTLE', 21600),
    ],

    // Developer override for hasAccess()
    'developer' => [
        'peer_id' => env('DEVELOPER_PEER_ID'),
    ],

    // translations:stats / translations:check command config
    'translation_stats' => [
        'base_locale' => 'en',
        'cache_key' => 'tbe.translation_stats',
        'ttl' => 86400,
    ],

    // Retention windows for model:prune (StateData, InlineConfirmation,
    // MessageMeta). essence schedules `model:prune` hourly for all three in
    // routes/console.php — no host-app scheduler setup needed.
    'pruning' => [
        'state_data_days' => env('TBE_PRUNE_STATE_DATA_DAYS', 7),
        'message_metas_days' => env('TBE_PRUNE_MESSAGE_METAS_DAYS', 7),
        'inline_confirmations_hours' => env('TBE_PRUNE_INLINE_CONFIRMATIONS_HOURS', 6),
    ],

    // Opt out of essence's own routes, or move them off the default prefixes
    'routes' => [
        'enabled' => env('TBE_ROUTES_ENABLED', true),
        'api_prefix' => env('TBE_ROUTES_API_PREFIX', 'api'),
        'web_prefix' => env('TBE_ROUTES_WEB_PREFIX', ''),
    ],

    // update_id dedup claim TTL — needs an atomic cache driver (redis/memcached),
    // not array/file
    'update_dedup' => [
        'ttl_seconds' => env('TBE_UPDATE_DEDUP_TTL_SECONDS', 300),
    ],
];

telegram.php ​

Merged from the package but typically overridden by the host app. Configures the telegram-bot-sdk BotsManager and HTTP client handler (LaravelHttpClient).

Database ​

Tables ​

TableModelDescription
botsBotBot tenant (token, owner, activation)
telegram_usersTelegramUserGlobal Telegram user profiles
bot_usersBotUserPer-bot user (power, state, menu)
message_metasMessageMetaTracked messages for lock/revert
state_dataStateDataJSON payload storage
inline_confirmationsInlineConfirmationConfirmation dialog state

bot_users columns ​

ColumnTypeDescription
bot_idFKTenant bot
telegram_user_peer_idFKTelegram user
powerintRole level (see Roles enum)
statestring, nullableEncoded active input flow
menuenummain or admin — controls keyboard
statusstringactive / blocked / unreachable — reachability, added in v0.12.0 (see Architecture)
suspended_attimestampSuspension flag
last_interactiontimestampLast activity

telegram_users.deactivated_at (nullable timestamp) holds the fourth, peer-global reachability state — the Telegram account itself is gone.

state_data columns ​

ColumnTypeDescription
idbigintPrimary key
datajson, nullableArbitrary payload
created_at / updated_attimestampAdded in v0.12.0 so model:prune can age rows out

BotUser methods ​

php
$botUser->changeState(?string $state);     // set or clear active state
$botUser->addParamToState(array $params);  // merge params into current state
$botUser->getKeyboard();                   // build reply keyboard for current context
$botUser->interact();                      // update last_interaction timestamp

$botUser->reachability();   // 'active' | 'blocked' | 'unreachable' | 'deactivated'
$botUser->isReachable();    // bool — reachability() === 'active'

BotUser::reachable();       // scope: status 'active' AND not deactivated
BotUser::withStatus($s);    // scope: whereIn('status', (array) $s)
BotUser::deactivated();     // scope: telegram account gone
BotUser::notSuspended();    // scope: suspended_at is null

StateDataService methods ​

php
stateData()->store(array $data = []): StateData;
stateData()->addData(StateData $row, array $data): void;

Artisan Commands ​

CommandDescription
tbe:installPublish config and translations
tbe:publish [--force](Re)publish package files
tbe:singlebot:init [--force]Create bot from tbe-essence.main config (--force reinitializes an existing bot)
tbe:set-webhook [--unique-id=] [--endpoint=] [--all]Set Telegram webhook + rotate secret token; --all rotates every bot
tbe:bot-management-tokenGenerate bot management API token
translations:stats [--base=] [--no-cache]Report translation-key coverage per locale
translations:check [--base=]List translation keys missing from non-base locales
tbe:make:callback-query {name} [--admin] [--all] [-f|-r|-s]Generate CallbackQuery class (+ siblings)
tbe:make:state-answer {name} [--admin] [--all] [-f|-c|-r]Generate StateAnswer class (+ siblings)
tbe:make:reply-key {name} [--admin] [--all] [-f|-c|-s]Generate ReplyKey class (+ siblings)
tbe:make:feature {name} [--admin] [--all] [-c|-r|-s]Generate Feature class (+ siblings)
tbe:make:inline-query {name}Generate InlineQuery class
tbe:make:command {name} [--admin] [--command-name=] [-d|--description=]Generate Telegram Command class — see Commands

tbe:set-webhook options ​

bash
php artisan tbe:set-webhook --unique-id=main
php artisan tbe:set-webhook --endpoint="/api/{unique_id}/telegram/bot/webhook"
php artisan tbe:set-webhook --all

Generates a new secret_token, hashes it on the bot record, and registers the webhook URL with Telegram. It also (re)builds each bot's Telegram command menu from config('tbe-essence.commands') — resolving each bot's locale through ResolvesBotLocale first, so the menu is translated per bot rather than in whatever locale the console process happens to be in.

Enums ​

Roles (src/Enums/Roles.php) ​

php
Roles::ADMIN->value      // 100
Roles::MODERATOR->value  // 10
Roles::MEMBER->value     // 0

AllowableFields (src/Enums/AllowableFields.php) ​

Used in StateAnswer $allowedFields:

php
AllowableFields::TEXT->value      // 'text'
AllowableFields::PHOTO->value     // 'photo'
AllowableFields::DOCUMENT->value  // 'document'

Routes ​

Defined in routes/api.php:

MethodPathHandler
GET/POST/PUT/PATCH/DELETE/api/botsBot CRUD (management API)
GET/api/{bot}/telegram/bot/webhookHealth check
POST/api/{bot}/telegram/bot/webhookWebhook handler

Webhook POST requires header X-Telegram-Bot-Api-Secret-Token matching the bot's stored secret.

TelegramResponse API ​

php
$response = new TelegramResponse(
    text: 'Hello',
    replyMarkup: $keyboard,
    parseMode: 'HTML',
);

$response->answer('Done!');           // callback toast text
$response->softAnswer('Saved');       // silent callback answer
$response->photo($inputFile);         // send as photo with caption
$response->messageMetaModel($model);  // attach MessageMeta on send

$response->send($chatId);             // new message
$response->update($chatId, $messageId); // edit existing message

When called from a CallbackQuery handler without arguments, update() edits the message that contained the pressed button.

Webhook Context Export (for Jobs) ​

php
$context = wHook()->exportContext();

// In job:
wHook()->importContext($context);
wHook()->api()->sendMessage([...]);

Useful for sending Telegram messages from queued jobs while preserving bot/user context.