natilosir / bot
A simple and flexible PHP package for building Telegram bots, featuring route handling, user state management, logging, path helpers, and an Illuminate-based container.
Requires
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
یک SDK سبک برای ساخت ربات تلگرام با PHP و ساختاری الهامگرفته از Laravel؛ شامل مسیریابی، state پایدار برای مکالمه، مدلهای Eloquent، HTTP Client مبتنی بر Illuminate، container و dependency injection، مسیرهای قابل تنظیم پروژه و لاگر HTML برای دیباگ.
زبان: English · فارسی
این مستندات معماری و رفتار عمومی نسخه فعلی SDK و سورس جدید
natilosir/botمورد استفاده پروژه را توضیح میدهد.
فهرست مطالب
- قابلیتها
- پیشنیازها
- نصب
- ساختار پروژه
- Bootstrap
- تنظیمات
- Helperها و Container
- مسیریابی
- مدیریت State
- Request
- ارسال درخواست از برنامه دیگر به Webhook ربات
- HTTP Client
- HTTP Response
- دیتابیس و مدلهای Eloquent
- Logging و Debugging
- Helperهای Telegram Bot API
- Keyboard Builder
- ارسال و ویرایش عکس
- نکات مهاجرت از README قدیمی
- مجوز
قابلیتها
- Bootstrap برنامه با ساختاری شبیه Laravel.
- استفاده از Illuminate Service Container از طریق
Bootstrap،Containerو helper سراسریapp(). - امکان تنظیم مسیر app، routes، config، storage و log.
- پشتیبانی از config بهصورت یک فایل PHP یا یک پوشه شامل چند فایل config.
- مسیریابی پیامها و callbackها به controller، callable یا کلاس invokable.
- dispatch خودکار routeها در پایان request پس از ثبت routeها.
- مدیریت state پایدار مکالمه با استفاده از
app\Models\User. - تجزیه Webhook تلگرام برای message، callback، inline query، پرداخت، poll و تغییرات chat member.
- پشتیبانی از درخواستهای برنامهای با فیلد اختصاصی
route. - پشتیبانی از multipart/form-data و فایلهای آپلودشده.
- HTTP Client مبتنی بر Illuminate با متدهای fluent و Response wrapper اختصاصی.
- ORM مبتنی بر
illuminate/databaseو Eloquent. - لاگ HTML پیشرفته همراه با محل فراخوانی، backtrace، exception handling و ثبت fatal error.
- helperهای تلگرام برای message، photo، callback، forward، copy، delete، chat action، inline keyboard و reply keyboard.
- مخفیسازی خودکار Bot Token از متن exceptionهایی که در HTTP helper سطح پایین تلگرام ساخته میشوند.
پیشنیازها
سورس فعلی از قابلیتهایی مانند return type نوع never استفاده میکند؛ بنابراین پیشنهاد و نیاز عملی این نسخه:
- PHP 8.1+
- Composer
- افزونه PDO
- افزونه cURL
- در صورت استفاده از Eloquent و State، یک دیتابیس سازگار با PDO؛ تنظیم پیشفرض MySQL است.
- افزونه
mbstringتوصیه میشود، چون caption عکس در کد ازmb_convert_encoding()استفاده میکند.
وابستگیهای PHP لازم از طریق Composer نصب میشوند؛ از جمله natilosir/bot، پکیجهای Illuminate و Verta که در ساختار
فعلی پروژه استفاده میشوند.
معماری پکیج
این repository پکیج application/scaffold با نام natilosir/telegram-bot-sdk است. هسته اصلی Bot از طریق dependency
کامپوزر با نام natilosir/bot تأمین میشود؛ همان هستهای که سورس Bot ارائهشده مربوط به آن است. مخزن Telegram-Bot-SDK
ساختار برنامه شامل app/، Router/، index.php، config و integration مربوط به Verta را در کنار آن هسته فراهم میکند.
نصب
پکیج SDK را از Packagist نصب کنید:
composer require natilosir/telegram-bot-sdk
سپس installer یکباره را اجرا کنید:
php vendor/natilosir/bot/install.php
Installer فایلهای scaffold پروژه را به ریشه پروژه منتقل/منتشر میکند و اطلاعات زیر را از شما میگیرد:
- Telegram Bot API Token
- آدرس host دیتابیس
- نام کاربری دیتابیس
- رمز عبور دیتابیس
- نام دیتابیس
سپس فایل config.php را در ریشه پروژه ایجاد میکند.
رفتار Installer: اگر از قبل در ریشه پروژه فایل
config.phpوجود داشته باشد، installer بدون انجام تنظیم مجدد خارج میشود. فقط زمانی فایل را حذف یا backup کنید که واقعاً قصد دارید installer را دوباره اجرا کنید.
ساختار پروژه
ساختار معمول پروژه پس از نصب:
project/
├── app/
│ ├── Controllers/
│ ├── Models/
│ └── State/
├── Router/
│ ├── route.php
│ └── state.php
├── storage/
├── config.php
├── index.php
├── log.html
└── vendor/
هسته پکیج توسط Composer در مسیر vendor/natilosir/bot قرار میگیرد.
Bootstrap
فایل index.php نقطه ورود اصلی webhook و برنامه است. ابتدا autoload مربوط به Composer را لود کرده و سپس container اصلی
SDK را بسازید:
<?php use natilosir\bot\Bootstrap; require __DIR__ . '/vendor/autoload.php'; $paths = [ 'base_path' => __DIR__, 'app_path' => __DIR__ . '/app', 'route_path' => __DIR__ . '/Router', 'config_path' => __DIR__ . '/config.php', 'storage_path' => __DIR__ . '/storage', 'log_path' => __DIR__ . '/log.html', ]; $app = new Bootstrap($paths);
Bootstrap چه کاری انجام میدهد؟
هنگام ساخت Bootstrap این مراحل انجام میشود:
- instance اصلی Illuminate Container ثبت میشود.
- مسیرهای پروژه resolve و داخل container ثبت میشوند.
- خود Bootstrap با کلیدهای
app،bootstrap،Bootstrap::classوContainer::classbind میشود. - فایل config یا پوشه config مشخصشده لود میشود.
- در صورت وجود
timezone، timezone PHP تنظیم میشود. - فایل
Router/route.phpلود میشود. - HTML logger راهاندازی میشود.
مسیرهای پیشفرض
کلیدهای زیر قابل تنظیم هستند:
| کلید | مقدار نسبی پیشفرض |
|---|---|
base_path |
مسیر پایه پکیج/پروژه |
app_path |
app |
route_path |
Router |
config_path |
config.php |
storage_path |
storage |
log_path |
log.html |
مسیرهای نسبی بر اساس base_path ساخته میشوند و مسیرهای absolute بدون تغییر استفاده میشوند.
API مربوط به مسیرها در Bootstrap
$app->basePath(); $app->appPath('Controllers'); $app->routePath('route.php'); $app->configPath(); $app->storagePath('cache'); $app->logPath(); $app->path('app_path', 'Models/User.php'); $app->paths();
میتوانید در runtime نیز مسیرها را تغییر دهید:
$app->setPath('storage_path', __DIR__ . '/var/storage'); $app->setBasePath(__DIR__);
برای دریافت Bootstrap فعال:
$app = Bootstrap::getInstance();
تنظیمات
نمونه یک فایل config کامل:
<?php return [ 'timezone' => 'Asia/Tehran', 'locale' => 'fa', 'calendar' => 'jalali', 'bot' => [ 'token' => 'YOUR_TELEGRAM_BOT_TOKEN', ], 'database' => [ 'driver' => 'mysql', 'host' => 'localhost', 'port' => 3306, 'database' => 'your_database', 'user' => 'root', 'password' => '', 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, ], ];
خواندن config با dot notation:
$token = paths()->config('bot.token'); $host = paths()->config('database.host', 'localhost');
یا از طریق Bootstrap:
$timezone = $app->config('timezone'); $all = $app->config();
استفاده از پوشه config
config_path میتواند بهجای یک فایل، مسیر یک پوشه باشد. تمام فایلهای *.php داخل آن پوشه با نام فایل بهعنوان key
لود میشوند.
مثال:
config/
├── app.php
├── bot.php
└── database.php
اگر database.php آرایه تنظیمات دیتابیس را برگرداند:
paths()->config('database.host');
Helperها و Container
Composer فایل src/helpers.php را بهصورت سراسری autoload میکند.
app()
دریافت container فعلی:
$container = app();
Resolve کردن یک کلاس یا binding:
$service = app(MyService::class);
ارسال پارامتر هنگام resolve:
$service = app(MyService::class, ['name' => 'example']);
paths()
paths() یک object برمیگرداند که aliasهای مسیر را بهصورت property یا method در اختیار میگذارد:
paths()->base; paths()->app; paths()->route; paths()->router; // alias برای route paths()->config; paths()->storage; paths()->log; paths()->logs; // alias برای log
اضافه کردن یک مسیر نسبی:
paths()->app('Controllers/StartController.php'); paths()->route('state.php'); paths()->storage('cache/data.json');
خواندن config:
paths()->config('bot.token');
Helperهای Debug
lg($value); // ثبت با سطح DEBUG lg($a, $b, $c); // هر مقدار جداگانه لاگ میشود dad($value); // alias برای DEBUG log dd($value); // لاگ و سپس توقف اجرای برنامه
خود PHP از قبل یک تابع ریاضی داخلی با نام
log()دارد. به همین دلیل SDK در runtime نمیتواند با اطمینان یک helper سراسری logger با نامlog()ثبت کند. برای لاگ ازlg()،dad()یاLog::debug()استفاده کنید.
مسیریابی
Routeها معمولاً در Router/route.php تعریف میشوند:
<?php use app\Controllers\StartController; use natilosir\bot\Route; Route::add( ['/start', '🏠 بازگشت', 'انصراف'], [StartController::class, 'hello'] );
پس از ثبت حداقل یک route یا default route، سیستم dispatch خودکار را برای پایان request ثبت میکند. در entry point معمول
پروژه نیازی نیست Route::dispatch() را دستی اجرا کنید.
نمونه Controller
<?php namespace app\Controllers; use natilosir\bot\bot as Bot; use natilosir\bot\Request; class StartController { public function hello(Request $request) { return Bot::sendMessage( $request->chatID, 'Welcome to the bot!' ); } }
Route::add($uri, $action)
پارامتر $uri میتواند string یا آرایهای از stringها باشد:
Route::add('/start', [StartController::class, 'hello']); Route::add(['/start', 'Home'], [StartController::class, 'hello']);
انواع action پشتیبانیشده:
// Controller + method Route::add('/start', [StartController::class, 'hello']); // Callable Route::add('/ping', function (Request $request) { return 'pong'; }); // Invokable class Route::add('/help', HelpController::class);
اگر action بهصورت class string باشد، Router متد __invoke() را اجرا میکند.
نرمالسازی ورودی
کلید route پیش از match شدن نرمال میشود:
- فاصله ابتدا و انتهای متن حذف میشود.
- فاصلههای تکراری به یک فاصله تبدیل میشوند.
يعربی بهیفارسی تبدیل میشود.كعربی بهکفارسی تبدیل میشود.
این رفتار مخصوصاً برای ورودیهای فارسی و دکمههای تلگرام مفید است.
Route پیشفرض
Route::def([FallbackController::class, 'handle']);
اگر route ثبتشدهای match نشود و state فعالی نیز request را handle نکند، default route اجرا میشود.
اتصال Route به State
میتوانید هنگام match شدن یک route، state ذخیره کنید:
Route::add('/phone', [ProfileController::class, 'askPhone']) ->state('phoneNumber');
پیش از اجرای controller، State::set('phoneNumber') فراخوانی میشود.
پاسخ JSON
برای endpointهایی که از طریق Router توسط یک برنامه دیگر فراخوانی میشوند:
Route::response([ 'message' => 'ok', ], 200);
خروجی:
{
"status":200,
"data":{
"message":"ok"
}
}
Route::response() status کد HTTP را تنظیم میکند، Content-Type را JSON میگذارد، پاسخ را چاپ میکند و execution را
متوقف میکند.
مخزن و پکیج
- GitHub: https://github.com/natilosir/Telegram-Bot-SDK
- Packagist: https://packagist.org/packages/natilosir/telegram-bot-sdk
مجوز
این پروژه تحت MIT License منتشر شده است.