Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Appto Telegram Bot

Multi-bot Telegram framework for Laravel: declarative routing (commands, callback patterns, text triggers, arbitrary update types), a dialog engine with step-by-step conversations, webhook and long-polling delivery, out of the box.

Installation

composer require appto/telegram-bot
php artisan vendor:publish --tag=telegram-bot-config
php artisan migrate

Quick start

final class ShopBot extends Bot
{
    protected function register(): void
    {
        $this->onCommand('start', RegistrationDialog::class);
        $this->onCommand('help', HelpCommand::class);
        $this->onCallback('order:confirm {id}', OrderConfirmHandler::class);

        $this->onText('hello', HelloHandler::class);
        $this->onText('send me photo',
            fn (UpdateContext $context) => $context->replyPhoto(
                FileInput::fromFile(storage_path('your_file.jpg')),
                caption: 'It\'s me'
            )
        );
    }
}
php artisan telegram:poll test

Dialogs (RegistrationDialog above) implement the same UpdateHandler contract as any other handler — no separate registration API, they're wired through onCommand()/onText()/ onCallback() just like the rest.

Authorization

Any command, callback handler, or dialog can opt in to access control by implementing RequiresPermission:

final class AdminPanel implements CommandHandler, RequiresPermission
{
    public function authorize(UpdateContext $context): bool
    {
        return $context->userId() === 123456;
    }
}

The framework calls authorize() before handle() — no wiring required. When it returns false, the request is rejected silently by default. To customize the rejection message, implement HasUnauthorizedMessage alongside it:

public function unauthorizedMessage(UpdateContext $context): ?string
{
    return 'This command is for admins only.';
}

For callback_query updates the message is delivered via answerCallbackQuery (as an alert by default); for everything else, as a regular reply. A global fallback message can be set in config('telegram-bot.unauthorized.message').

Built-in /help command

An opt-in HelpCommand lists every registered command that implements HasDescription:

final class StartCommand implements CommandHandler, HasDescription
{
    public static function description(): string
    {
        return __('telegram-bot::help.start_command');
    }
}
$this->onCommand('help', HelpCommand::class);

Only commands the requesting user is authorized for (per RequiresPermission, if implemented) show up in their /help output. Package strings (title, empty-list message) are translatable — see Translations below.

Long polling (telegram:poll)

An alternative to webhooks for local development or environments without a public HTTPS URL: the command repeatedly calls getUpdates and dispatches every update through the same pipeline a webhook request would use (Bot::dispatch()).

php artisan telegram:poll shop

Run without an argument to pick a bot interactively from the list of registered bots:

php artisan telegram:poll

Webhook conflict is handled automatically

Telegram allows only one delivery method per bot — before polling starts, the command checks whether a webhook is set and, if so, prompts you to remove it. There's no need to run telegram:delete-webhook manually first.

Options

Option Description
--timeout=30 Long-poll timeout in seconds passed to getUpdates
-o, --show-outgoing Also print the bot's outgoing API calls to the console, not just incoming updates
--only=* Only show/dispatch these update types, e.g. --only=message --only=callback_query
--user=* Only show/dispatch updates from these Telegram user IDs
--dry-run Receive and display updates without dispatching them to the bot — inspect traffic without triggering handlers
-l, --log-traffic Log raw incoming/outgoing payloads to storage/logs/telegram-traffic.log
# watch only callback_query updates from a specific user, without running any handlers
php artisan telegram:poll shop --only=callback_query --user=123456789 --dry-run

Errors during polling don't stop the command — a failed getUpdates call backs off exponentially (5s, 10s, 20s... capped at 60s) and retries; an exception thrown by a specific update's handler is reported and logged without interrupting the loop for subsequent updates.

Not for production

Long polling holds an open foreground process — it's meant for local development, not for running behind a process manager in production. Use a webhook (telegram:set-webhook) for anything deployed.

Inspecting routes

php artisan telegram:routes                # all bots
php artisan telegram:routes shop            # a single bot
php artisan telegram:routes shop --type=commands

Lists every registered command, callback pattern, and text trigger per bot, and flags which ones require authorization.

Publishing

php artisan vendor:publish --tag=telegram-bot-config       # config only
php artisan vendor:publish --tag=telegram-bot-migrations   # migrations only
php artisan vendor:publish --tag=telegram-bot-lang         # translations only
php artisan vendor:publish --provider="Appto\TelegramBot\TelegramBotServiceProvider"  # everything

Translations

Package strings are published under telegram-bot:: and can be overridden per locale by publishing them into lang/vendor/telegram-bot/{locale}:

php artisan vendor:publish --tag=telegram-bot-lang

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages