Search by

afaztech / neili

afaztech

Neili is an async-first PHP library built on Amp that streamlines creating robust Telegram bots. It provides a non-blocking HTTP client, wrappers for all Telegram Bot API methods, a long-polling Poller with concurrency control, and a flexible webhook handler. Neili is optimized for both constrained

Package info

github.com/AfazTech/Neili

Homepage

Issues

pkg:composer/afaztech/neili

Statistics

Installs: 131

Dependents: 2

Suggesters: 0

Stars: 5

v3.2.3 2026-10-26 11:37 UTC

README

PHP Version License Amp

Async-first PHP library for building Telegram bots on top of Amp.

Features

  • Non-blocking HTTP client built on amphp/http-client
  • Wrappers for the Telegram Bot API methods
  • Long-polling Poller with exponential backoff + jitter and concurrency control
  • Webhook handler with three delivery modes:
    • Standard webhook — the script replies to Telegram when it finishes
    • Multi-process — each update is forked into a PHP CLI worker via exec()
    • Fast-ack — replies 200 OK immediately and keeps processing (requires FPM / LiteSpeed / FrankenPHP)
  • Fluent KeyboardBuilder for reply and inline keyboards
  • Media helper for local file uploads with automatic attach:// mapping
  • Streaming file downloads via amphp/file (safe for large files)
  • Full exception taxonomy: TransientException, PermanentException, RateLimitException
  • Zero internal logging — errors surface through exceptions and Poller::onError()

Requirements

  • PHP >= 8.1
  • amphp/amp ^3
  • amphp/file ^3.2
  • amphp/http-client ^5.3
  • PHP extensions: fileinfo; posix (optional, recommended)
  • exec() — required only for multi-process webhook mode

Installation

composer require afaztech/neili

Usage

Long polling

use Neili\Client;
use Neili\Poller;
use Neili\Settings;

$settings = (new Settings())->setAccessToken('YOUR_BOT_TOKEN');
$client   = new Client($settings);
$poller   = new Poller($client);

$poller->onMessage(function (array $update) use ($client) {
    $chatId = $update['message']['chat']['id'] ?? null;
    $text   = $update['message']['text'] ?? null;
    if ($chatId && $text) {
        $client->sendMessage($chatId, "Echo: {$text}");
    }
});

$poller->start();

Standard webhook

use Neili\Client;
use Neili\Settings;

$settings = (new Settings())->setAccessToken('YOUR_BOT_TOKEN');
$client   = new Client($settings);

$update = $client->handleUpdate('YOUR_SECRET_TOKEN');

if (isset($update['message']['chat']['id'], $update['message']['text'])) {
    $client->sendMessage(
        $update['message']['chat']['id'],
        'Echo: ' . $update['message']['text']
    )->await();
}

Multi-process webhook

Each update is forked into a separate PHP CLI worker and the parent returns to Telegram immediately.

$settings = (new Settings())
    ->setAccessToken('YOUR_BOT_TOKEN')
    ->setMultiProcess(true)
    ->setPhpBinary('/usr/bin/php');

$client = new Client($settings);
$client->handleUpdate('YOUR_SECRET_TOKEN');

Fast-ack webhook

Replies 200 OK to Telegram as soon as possible and keeps processing in the same request. Mutually exclusive with multi-process mode — enabling both throws RuntimeException.

$settings = (new Settings())
    ->setAccessToken('YOUR_BOT_TOKEN')
    ->setFastAck(true);

$client = new Client($settings);

$update = $client->handleUpdate('YOUR_SECRET_TOKEN');

// Telegram has already received its 200 OK. Slow work continues below.

Detaches the response only on PHP-FPM, LiteSpeed, or FrankenPHP. On other SAPIs it falls back to flushing the output buffer and behaves like a standard webhook.

Documentation

For detailed documentation, see DOCUMENT.md.

Contributing

Contributions are welcome via pull requests. Please keep the codebase stable, tested, and backward-compatible.

License

This project is licensed under the MIT License.