Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Telegram Bot Bundle Laravel Package

morfeditorial/telegram-bot-bundle

morfeditorial/telegram-bot-bundle is a Symfony bundle for integrating Telegram bots into PHP applications. It provides configuration and services to connect your app with the Telegram Bot API and handle bot updates within a Symfony project.

View on GitHub
Deep Wiki
Context7

Getting Started

Because telegram-bot-bundle is a Symfony bundle, a Laravel developer cannot rely on the usual php artisan vendor:publish / package-discovery conveniences. Treat it as a standalone OOP Telegram toolkit that you wire into Laravel manually.

  1. Install and inspect the README first.

    composer require morfeditorial/telegram-bot-bundle
    

    The README is the only real source of truth right now — read the sections on Screens, Payload Routing (domain:action:args), and State Management before writing any code.

  2. Confirm it boots outside Symfony. The v1.0.0 notes advertise DI autowiring and Symfony event dispatching "out of the box" — none of that exists in Laravel. Check composer.json for hard symfony/* requirements; you may pull in a large dependency tree even if you only use the Screen classes.

  3. First use case — a single webhook endpoint. The fastest meaningful integration is a route that receives Telegram updates and hands them to the bundle's bot/kernel class:

    // routes/api.php
    Route::post('/telegram/webhook', TelegramWebhookController::class);
    
  4. Bridge the transport layer yourself. The bundle's Long Polling / Webhook support is Symfony-flavoured. In Laravel you will typically:

    • Use your own controller for webhooks (disable the bundle's routing).
    • Use a queued job or an Artisan command with a loop for long polling.
  5. Start with one Screen. Build a /start screen that replies with an inline keyboard, then iterate. Do not attempt stateful wizards until the basic dispatch loop works end-to-end.

Implementation Patterns

Screen classes as the unit of work. Extend the bundle's Screen, implement supports() to declare which updates/payloads it claims, and handle() to act. Keep each screen small and single-purpose — the release notes explicitly position this as the replacement for legacy monolithic handlers.

final class StartScreen extends Screen
{
    public function supports(Update $update): bool
    {
        return $update->message?->text === '/start';
    }

    public function handle(Update $update): void
    {
        $this->reply($update, 'Pick one:', $this->keyboard([
            'orders:list' => 'My orders',
            'profile:edit' => 'Edit profile',
        ]));
    }
}

Payload routing (domain:action:args) as your callback contract. Stick to the colon-delimited format. Map it to a screen per domain, and branch on action inside handle() rather than creating a screen per button:

  • orders:list → OrdersScreen
  • orders:show:42 → same screen, parse 42 from args
  • profile:edit → ProfileScreen

Keep args scalar and short (see Gotchas on the 64-byte limit).

State via Laravel's persistence layer. The bundle deliberately does not prescribe storage. Back it with cache()->store('redis'), a telegram_states table, or a dedicated Eloquent model keyed by chat_id:

Cache::put("tg:state:{$chatId}", ['screen' => 'checkout', 'step' => 2], now()->addHour());

Webhook controller pattern. Validate the Telegram secret token, resolve the bot from the container (bind it in an AppServiceProvider), dispatch the update through the bundle's router, and return 200 immediately:

public function __invoke(Request $request)
{
    abort_unless($request->header('X-Telegram-Bot-Api-Secret-Token') === config('services.telegram.secret'), 403);

    app(BotKernel::class)->handle(Update::fromArray($request->all()));

    return response()->noContent();
}

Long polling as an Artisan command. Wrap the bundle's poller in a php artisan telegram:poll command. Use --once for tests and a supervisor for production. Do not run long polling inside a FPM request.

Event bridging. If the bundle dispatches Symfony events, register a small subscriber class (implements EventSubscriberInterface) that re-dispatches Laravel events, or register the bundle's dispatcher in your container pointing at Laravel's EventDispatcher. This keeps your listeners framework-native.

Config in config/services.php. Token, webhook secret, and allowed update types go here. There is no config/telegram-bot-bundle.php to publish.

Gotchas and Tips

  • This is not a Laravel package. No ServiceProvider, no Facade, no auto-discovery, no publishable config. Expect to write an adapter layer (~50–100 lines) the first time.
  • Symfony DI will not autowire into your app. You must instantiate the bot kernel, screens, and router in a Laravel service provider and pass dependencies explicitly. If the bundle's classes rely on ContainerInterface, provide Laravel's container via a thin adapter.
  • Callback data is capped at 64 bytes by Telegram. domain:action:args burns fast. Keep domains/actions to short slugs and use IDs rather than serialized payloads.
  • State management is entirely yours. There is no default store, no migration, no cleanup. Decide retention and prune stale states — otherwise your cache/table grows unbounded on inactive chats.
  • Webhook correctness matters more than with a framework-integrated package. Set the secret token, verify it on every request, register the URL with setWebhook, and ensure your route is excluded from CSRF and rate limiting.
  • Async / ReactPHP claims need a compatible runtime. "Non-blocking architectures in mind" is accurate, but you cannot block on Eloquent or the cache within an event loop without a driver that supports it. For most Laravel apps, stick to the synchronous webhook path.
  • Licence is unusual. CSSM Unlimited License v2.0 is not a common OSI-style licence. Read it before commercial use — "Unlimited" naming should not be assumed to mean "MIT-like".
  • Debugging tips. Log raw update JSON before dispatch; log the resolved screen name and payload in supports(); on "no screen handled", dump your registered screen list — silent no-ops are the most common failure mode when supports() returns false everywhere.
  • Extension points. Where the bundle is thin (transport, state, config), prefer wrapping it in your own service classes rather than forking. The Screen architecture was explicitly designed for extension; the framework glue was not.
  • Versioning. v1.0.0 establishes the architecture but is the first stable cut — pin the version and watch for minor releases; the Screen API is the most likely to shift as Symfony conventions evolve.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package