phenogram / bindings
Low level type-safe PHP bindings for the Telegram Bot API
Requires
- php: ^8.2
Requires (Dev)
- monolog/monolog: ^3.4
- phpunit/phpunit: ^11
- symfony/var-dumper: ^7
- vlucas/phpdotenv: ^5.5
README
π¬π§ ENGLISH | π·πΊ Π Π£Π‘Π‘ΠΠΠ
PHP ΡΠΈΠΏΡ Π΄Π»Ρ Telegram Bot API
Π‘ΡΡΠΎΠ³ΠΎ ΡΠΈΠΏΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ PHP ΠΊΠ»Π°ΡΡΡ Π΄Π»Ρ Telegram Bot API, ΠΎΡΠ½ΠΎΠ²Π°Π½Π½ΡΠ΅ Π½Π° ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΠΎΠΉ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π² Π€ΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠ΅ Phenogram
Π ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΌ ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°Π½Ρ Ρ ΠΏΠΎΠΌΠΎΡΡΡ scrapper
Π Π°Π±ΠΎΡΠ° Π²ΡΡ Π΅ΡΡ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅, ΠΈ Π½Π΅ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΊΠ»Π°ΡΡ ΠΏΡΠΎΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΡΡ. ΠΡΠ»ΠΈ Π²Ρ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΡΠ΅ ΠΊΠ°ΠΊΠΈΠ΅-Π»ΠΈΠ±ΠΎ Π½Π΅ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΈΡ Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠ΅ΠΉ, Π½Π΅ ΡΡΠ΅ΡΠ½ΡΠΉΡΠ΅ΡΡ ΡΠΎΠ·Π΄Π°ΡΡ ΠΈΡΡΡ. ΠΡΡ, ΡΡΠΎ Π½Π΅ ΠΎΠΏΠΈΡΠ°Π½ΠΎ Π² Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, Π²ΡΡ ΠΎΠ΄ΠΈΡ Π·Π° ΡΠ°ΠΌΠΊΠΈ ΡΡΠΎΠ³ΠΎ ΠΏΡΠΎΠ΅ΠΊΡΠ°.
Π’Π΅ΠΊΡΡΠ°Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΠΌΠ°Ρ Π²Π΅ΡΡΠΈΡ Telegram bot API - v7.10
Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°
composer require phenogram/bindings
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅
Π‘Π΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΎΡ
ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²ΠΈΠ΄Π΅ΡΡ Π² ΠΊΠ»Π°ΡΡΠ΅ Api.
ΠΠΎ Π²ΠΎΡ ΠΏΡΠΎΡΡΠΎΠΉ ΠΏΡΠΈΠΌΠ΅Ρ:
use Phenogram\Bindings\Serializer; $serializer = new Serializer(); $inlineKeyboardMarkup = new InlineKeyboardMarkup( inlineKeyboard: [[ new InlineKeyboardButton(text: 'ΠΠ½ΠΎΠΏΠΊΠ° 1', callbackData: 'data1') ]], ); $json = $serializer->serialize([ 'reply_markup' => $inlineKeyboardMarkup, ]); $arrayKeyboard = [ 'reply_markup' => [ 'inline_keyboard' => [[ ['text' => 'ΠΠ½ΠΎΠΏΠΊΠ° 1', 'callback_data' => 'data1'] ]], ], ]; $jsonFromArray = json_encode($arrayKeyboard); assert($jsonFromArray === $json);
ΠΠ³ΠΎ ΡΠ°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΄Π»Ρ Π΄Π΅ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ² Telegram Π² ΡΠΈΠΏΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ PHP-ΠΊΠ»Π°ΡΡΡ.
ΠΠ΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΠΎΠ΅ Π½Π΅ ΡΠΎΠ²ΡΠ΅ΠΌ ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎΠ΅ - Π²Π°ΠΌ Π½ΡΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ JSON-Π·Π°ΠΊΠΎΠ΄ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΡΡΡΠΎΠΊΡ
ΠΈΠ· ΠΏΠΎΠ»Ρ result
Π·Π°ΠΏΡΠΎΡΠ° Telegram, Π° Π½Π΅ Π²Π΅ΡΡ Π·Π°ΠΏΡΠΎΡ.
use Phenogram\Bindings\Serializer; use Phenogram\Bindings\Types\Update; use Phenogram\Bindings\Types\Message; use Phenogram\Bindings\Types\Chat; $updatesData = [[ 'update_id' => 1, 'message' => [ 'message_id' => 54321, 'chat' => [ 'id' => 11223344, 'type' => 'private', ], 'date' => 1600000000, ], ]]; $serializer = new Serializer(); $updates = $serializer->deserialize( data: json_encode($updatesData), type: Update::class, isArray: true, ); assert($updates[0] instanceof Update::class); assert($updates[0]->message instanceof Message::class); assert($updates[0]->message->chat instanceof Chat::class);
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ API
ΠΠ»ΠΈΠ΅Π½Ρ
Π§ΡΠΎΠ±Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ API, Π²Π°ΠΌ ΡΠ½Π°ΡΠ°Π»Π° Π½ΡΠΆΠ½ΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ClientInterface,
Π² ΠΊΠΎΡΠΎΡΠΎΠΌ Π΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΌΠ΅ΡΠΎΠ΄ - sendRequest
.
ΠΠ°ΡΠ΅ΠΌ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ»Π°ΡΡ Api
Π΄Π»Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΊ API Telegram.
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° Π²ΡΡ ΠΎΠ΄ΠΈΡ Π·Π° ΡΠ°ΠΌΠΊΠΈ ΡΡΠΎΠ³ΠΎ ΠΏΡΠΎΠ΅ΠΊΡΠ°, Π½ΠΎ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ ΠΏΡΠΈΠΌΠ΅Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Ρ amphp/http-client Π² Π€ΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠ΅ Phenogram
Π‘Π°ΠΌΠ°Ρ Π±Π°Π·ΠΎΠ²Π°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ext-curl ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΡΠ°ΠΊ:
use Phenogram\Bindings\ClientInterface; use Phenogram\Bindings\Types; final readonly class TelegramBotApiClient implements ClientInterface { public function __construct( private string $token, private string $apiUrl = 'https://api.telegram.org', ) { } public function sendRequest(string $method, string $json): Types\Response { $ch = curl_init("{$this->apiUrl}/bot{$this->token}/{$method}"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); if (curl_errno($ch)) { throw new \RuntimeException('ΠΡΠΈΠ±ΠΊΠ° Π·Π°ΠΏΡΠΎΡΠ°: ' . curl_error($ch)); } curl_close($ch); $responseData = json_decode($response, true); if (!isset($responseData['ok']) || !isset($responseData['result'])) { return new Types\Response( ok: false, result: null, errorCode: $responseData['error_code'] ?? null, description: $responseData['description'] ?? null, parameters: isset($responseData['parameters']) ? new Types\ResponseParameters( migrateToChatId: $responseData['parameters']['migrate_to_chat_id'] ?? null, retryAfter: $responseData['parameters']['retry_after'] ?? null, ) : null, ); } return new Types\Response( ok: $responseData['ok'], result: json_encode($responseData['result']), errorCode: $responseData['error_code'] ?? null, description: $responseData['description'] ?? null, parameters: isset($responseData['parameters']) ? new Types\ResponseParameters( migrateToChatId: $responseData['parameters']['migrate_to_chat_id'] ?? null, retryAfter: $responseData['parameters']['retry_after'] ?? null, ) : null, ); } }
ΠΠΎ Ρ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ, ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΊΡΡ-Π½ΠΈΠ±ΡΠ΄Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ Guzzle ΠΈΠ»ΠΈ amphp/http-client.
ΠΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π·Π°ΠΏΡΠΎΡΠΎΠ²
$api = new Api( client: new TelegramBotApiClient($token), serializer: new Serializer(), ); $me = $api->getMe(); assert($me instanceof User::class);
ΠΡΡ Π΅ΡΡ work in progress
ΠΡΠ½ΠΎΠ²Π½Π°Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π½Π° Π΄Π°Π½Π½ΡΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ - ΡΡΠΎ Π·Π°Π³ΡΡΠ·ΠΊΠ° ΡΠ°ΠΉΠ»ΠΎΠ² Ρ MultiPart-Π·Π°ΠΏΡΠΎΡΠ°ΠΌΠΈ, Π½ΠΎ Ρ Π΄ΡΠΌΠ°Ρ ΠΎΠ± ΡΡΠΎΠΌ.
Π’Π°ΠΊΠΆΠ΅ ΠΌΠ½Π΅ Π½ΡΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ ΠΏΡΠΈΠ΄ΡΠΌΠ°ΡΡ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΡΠΉ ΠΈΠ· Api::doRequest ΡΠΈΠΏ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠ°Π±Π»ΠΎΠ½ΠΎΠ², Π½ΠΎ ΠΏΠΎΠΊΠ° Π½Π΅ ΡΠ²Π΅ΡΠ΅Π½, ΠΊΠ°ΠΊ ΡΡΠΎ ΡΠ΄Π΅Π»Π°ΡΡ, phpstan ΠΏΠΎΠ±Π΅ΠΆΠ΄Π°Π΅Ρ.
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
ΠΡΠΎ ΠΏΡΠΎΡΡΠΎ SDK Π΄Π»Ρ Π²Π°ΡΠ΅Π³ΠΎ Telegram-Π±ΠΎΡΠ°, Π° Π½Π΅ ΠΏΠΎΠ»Π½ΠΎΡΠ΅Π½Π½ΡΠΉ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ, Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΅Π³ΠΎ ΠΊΠ°ΠΊ Π΅ΡΡΡ ΠΈΠ»ΠΈ ΡΠ°ΡΡΠΈΡΠΈΡΡ Π΄Π»Ρ ΡΠ²ΠΎΠΈΡ Π½ΡΠΆΠ΄.
ΠΡΠ»ΠΈ Π²Π°ΠΌ Π½ΡΠΆΠ΅Π½ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ, ΠΏΠΎΡΠΌΠΎΡΡΠΈΡΠ΅ Π½Π° Phenogram