Search by

hojjatjh / bot-builder

hojjatjh

A PHP tool to scaffold ready-to-run Telegram bots from reusable templates.

Package info

github.com/hojjatjh/bot-builder

pkg:composer/hojjatjh/bot-builder

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 6

Open Issues: 0

v0.1.0 2026-07-20 18:54 UTC

This package is auto-updated.

Last update: 2026-08-21 01:41:21 UTC


README

🤖 BotBuilder

A modern, zero-dependency PHP scaffolding engine that builds ready-to-run projects (like Telegram bots) from reusable templates.

Latest Version Total Downloads PHP Version License

English | فارسی

Table of Contents

Why BotBuilder?

Building many similar projects by hand is repetitive and error-prone. BotBuilder lets you keep a single base template and generate as many customized copies as you want — each one filled with its own values. Perfect for spinning up new Telegram bots, micro-services, or any boilerplate project in seconds, while your original template stays untouched and reusable forever.

Features

  • 🧩 Template-based scaffolding — generate a whole project from a base folder.
  • 🔖 {{PLACEHOLDER}} replacement in both file contents and file/folder names.
  • 🗂 Works on any file — not just config.php. Every file in the template is scanned.
  • 🧵 Multiple files at once — fill config.php, server-key.php, and more in a single build.
  • 🌳 Nested folders supported out of the box (recursive).
  • Required values & defaults with built-in validation.
  • ♻️ Read-only base — the template is never modified and can be reused infinitely.
  • 🪶 Zero dependencies — pure filesystem, fully unit-tested.
  • ⚙️ Configurable delimiters ({{ }} by default).

How It Works

BotBuilder reads a base/template directory, replaces every {{KEY}} token with the values you provide, and writes the result into a new output directory — leaving the original template untouched.

base/telegram-bot/            ->   bots/my-new-bot/
config.php   ({{...}})        ->   config.php   (filled in)
server-key.php ({{...}})      ->   server-key.php (filled in)
bot.php                      ->   bot.php

Requirements

  • PHP >= 8.1
  • ext-json

Installation

composer require hojjatjh/bot-builder

Quick Start

<?php

require 'vendor/autoload.php';

use BotBuilder\BotBuilder;

$builder = new BotBuilder(__DIR__ . '/base/telegram-bot');

$builder
    ->define('BOT_NAME', required: true)
    ->define('BOT_TOKEN', required: true)
    ->define('ADMIN_ID', default: '0');

$files = $builder->build(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME'  => 'MyCoolBot',
    'BOT_TOKEN' => '123456:ABC-DEF',
]);

print_r($files);

Creating a Template

A template is nothing more than a normal folder of files. Wherever you want a value to be filled in later, you write a placeholder like {{BOT_NAME}}. That's the whole idea — there is nothing complicated to learn.

💡 Important: BotBuilder does not care about file names, and it is not limited to config.php. It scans every file in the template, so your placeholders work in any file you like — config.php, server-key.php, .env, README.md, anything.

Step 1 — Put placeholders in your files

Your config file can have any name. Here it is called config.php:

<?php

return [
    'name'  => '{{BOT_NAME}}',
    'token' => '{{BOT_TOKEN}}',
];

Step 2 — Placeholders also work in file & folder names

A file literally named {{BOT_NAME}}.php becomes MyCoolBot.php after building. The same works for folders, e.g. handlers/{{BOT_NAME}}/.

Step 3 — Use as many files as you want (a real example)

A template can hold any number of files. Here it has two: config.php and server-key.php.

config.php

<?php

return [
    'name'  => '{{BOT_NAME}}',
    'token' => '{{BOT_TOKEN}}',
];

server-key.php

<?php

return [
    'secret'      => '{{SERVER_KEY}}',
    'webhook_url' => '{{WEBHOOK_URL}}',
];

A single build() call fills in both files at once:

$builder
    ->define('BOT_NAME', required: true)
    ->define('BOT_TOKEN', required: true)
    ->define('SERVER_KEY', required: true)
    ->define('WEBHOOK_URL', default: '');

$builder->build(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME'    => 'MyCoolBot',
    'BOT_TOKEN'   => '123456:ABC-DEF',
    'SERVER_KEY'  => 's3cr3t',
    'WEBHOOK_URL' => 'https://example.com/hook',
]);

Files without any placeholder are simply copied as-is, so you can freely mix static and templated files (PHP, JSON, .env, Markdown, images — anything).

Usage

Defining config (required & defaults)

$builder
    ->define('BOT_TOKEN', required: true)   // must be provided
    ->define('ADMIN_ID', default: '0');     // optional, falls back to '0'

If a required value is missing, a BotBuilderException is thrown before anything is written to disk — so you never end up with a half-generated project.

Overwriting an existing target

$builder->build($target, $values, overwrite: true);

Without overwrite: true, building into a directory that already exists throws an exception (this protects you from accidentally clobbering previous work).

Using the lower-level pieces

The BotBuilder facade is optional. You can compose the parts directly:

use BotBuilder\Template;
use BotBuilder\BotGenerator;

$generator = new BotGenerator(new Template(__DIR__ . '/base/telegram-bot'));

$files = $generator->generate(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME' => 'MyCoolBot',
]);

Custom delimiters

use BotBuilder\Template;
use BotBuilder\BotGenerator;
use BotBuilder\PlaceholderReplacer;

$generator = new BotGenerator(
    new Template(__DIR__ . '/base/telegram-bot'),
    new PlaceholderReplacer('%%', '%%'),  // use %%KEY%% instead of {{KEY}}
);

API Reference

BotBuilder (facade)

Method Description
__construct(string $templatePath) Point at the base template folder.
define(string $key, ?string $default = null, bool $required = false): self Register an expected placeholder.
build(string $target, array $values, bool $overwrite = false): array Validate values and generate the project. Returns the generated file paths.

BotGenerator

Method Description
__construct(Template $template, PlaceholderReplacer $replacer = new PlaceholderReplacer()) Build from a template with an optional custom replacer.
generate(string $target, array $values, bool $overwrite = false): array Generate files (content + names) into the target directory.

Template

Method Description
__construct(string $path) Wrap a base directory (must exist).
path(): string The template root path.
files(): array All files as relative paths (recursive).
read(string $relativePath): string Read a single file's content.

Config

Method Description
define(string $key, ?string $default = null, bool $required = false): self Declare an expected placeholder.
resolve(array $values): array Merge given values with defaults and validate required keys.

PlaceholderReplacer

Method Description
__construct(string $open = '{{', string $close = '}}') Configure the delimiters.
replace(string $content, array $values): string Replace known tokens (unknown ones are left untouched).
placeholders(string $content): array List the unique tokens found in a string.

Full Example: Telegram Bot

base/telegram-bot/config.php

<?php

return [
    'name'     => '{{BOT_NAME}}',
    'token'    => '{{BOT_TOKEN}}',
    'admin_id' => {{ADMIN_ID}},
];

base/telegram-bot/bot.php

<?php

$config = require __DIR__ . '/config.php';
$api = 'https://api.telegram.org/bot' . $config['token'] . '/';
$offset = 0;

echo $config['name'] . ' is running...' . PHP_EOL;

while (true) {
    $response = file_get_contents($api . 'getUpdates?timeout=30&offset=' . $offset);
    $updates = json_decode($response, true);

    foreach ($updates['result'] ?? [] as $update) {
        $offset = $update['update_id'] + 1;
        $chatId = $update['message']['chat']['id'] ?? null;
        $text = $update['message']['text'] ?? '';

        if ($chatId !== null) {
            file_get_contents($api . 'sendMessage?' . http_build_query([
                'chat_id' => $chatId,
                'text' => 'You said: ' . $text,
            ]));
        }
    }
}

Generate it:

use BotBuilder\BotBuilder;

$builder = new BotBuilder(__DIR__ . '/base/telegram-bot');

$builder
    ->define('BOT_NAME', required: true)
    ->define('BOT_TOKEN', required: true)
    ->define('ADMIN_ID', default: '0');

$builder->build(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME'  => 'MyCoolBot',
    'BOT_TOKEN' => '123456:ABC-DEF',
    'ADMIN_ID'  => '55555',
]);

Now run your brand-new bot:

php bots/my-new-bot/bot.php

Testing

composer install
./vendor/bin/phpunit

Contributing

Contributions are welcome! Feel free to open an issue or submit a pull request on GitHub.

License

Released under the MIT License. See LICENSE for details.

📖 راهنمای فارسی

BotBuilder یک موتور scaffolding مدرن و بدون هیچ وابستگی برای PHP است که پروژه‌های آماده‌ی اجرا (مثل ربات‌های تلگرام) را از روی قالب‌های قابل‌استفاده‌ی مجدد می‌سازد.

فهرست

  • چرا BotBuilder؟
  • ویژگی‌ها
  • چطور کار می‌کند
  • پیش‌نیازها
  • نصب
  • شروع سریع
  • ساخت یک قالب
  • استفاده
  • مرجع API
  • مثال کامل: ربات تلگرام
  • تست
  • مشارکت
  • لایسنس

چرا BotBuilder؟

ساختن دستیِ چندین پروژه‌ی مشابه، تکراری و مستعد خطاست. با BotBuilder فقط یک قالب پایه (base) نگه می‌داری و هر تعداد که خواستی نسخه‌ی سفارشی‌شده از رویش می‌سازی — هرکدام با مقادیر مخصوص خودش. عالی برای ساختِ ربات‌های تلگرام جدید یا هر پروژه‌ی boilerplate در چند ثانیه، درحالی‌که قالب اصلی‌ات دست‌نخورده و برای همیشه قابل استفاده می‌ماند.

ویژگی‌ها

  • 🧩 scaffolding مبتنی بر قالب — کل پروژه از روی یک پوشه‌ی base ساخته می‌شود.
  • 🔖 جای‌گزینی {{PLACEHOLDER}} هم در محتوای فایل‌ها و هم در نام فایل/پوشه‌ها.
  • 🗂 روی هر فایلی کار می‌کند — فقط config.php نیست؛ همه‌ی فایل‌های قالب اسکن می‌شوند.
  • 🧵 چند فایل هم‌زمان — در یک build هم config.php و هم server-key.php و بیشتر را پر می‌کند.
  • 🌳 پوشه‌های تودرتو به‌صورت بازگشتی پشتیبانی می‌شوند.
  • مقادیر اجباری و پیش‌فرض با اعتبارسنجی داخلی.
  • ♻️ قالب فقط‌خواندنی — قالب هیچ‌وقت تغییر نمی‌کند و بی‌نهایت بار قابل استفاده است.
  • 🪶 بدون هیچ وابستگی — فقط فایل‌سیستم، کاملاً تست‌شده.
  • ⚙️ جداکننده‌های قابل تنظیم (پیش‌فرض {{ }}).

چطور کار می‌کند

BotBuilder یک پوشه‌ی قالب را می‌خواند، همه‌ی {{KEY}}ها را با مقادیر تو جایگزین می‌کند و نتیجه را در یک پوشه‌ی خروجی جدید می‌نویسد — بدون اینکه به قالب اصلی دست بزند.

base/telegram-bot/            ->   bots/my-new-bot/
config.php   ({{...}})        ->   config.php   (filled in)
server-key.php ({{...}})      ->   server-key.php (filled in)
bot.php                      ->   bot.php

پیش‌نیازها

  • PHP نسخه‌ی 8.1 یا بالاتر
  • افزونه‌ی ext-json

نصب

composer require hojjatjh/bot-builder

شروع سریع

<?php

require 'vendor/autoload.php';

use BotBuilder\BotBuilder;

$builder = new BotBuilder(__DIR__ . '/base/telegram-bot');

$builder
    ->define('BOT_NAME', required: true)
    ->define('BOT_TOKEN', required: true)
    ->define('ADMIN_ID', default: '0');

$files = $builder->build(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME'  => 'MyCoolBot',
    'BOT_TOKEN' => '123456:ABC-DEF',
]);

print_r($files);

ساخت یک قالب

یک قالب چیزی نیست جز یک پوشه‌ی معمولی از فایل‌ها. هر جا خواستی بعداً یک مقدار جایگزین شود، یک placeholder مثل {{BOT_NAME}} می‌نویسی. کل ایده همین است — هیچ چیز پیچیده‌ای برای یادگرفتن نیست.

💡 مهم: BotBuilder به اسم فایل‌ها کاری ندارد و فقط محدود به config.php نیست. همه‌ی فایل‌های قالب را می‌خواند، پس placeholderهایت در هر فایلی کار می‌کنند — config.php، server-key.php، .env یا هر چیزی.

قدم ۱ — placeholder در فایل‌هایت بگذار

فایل کانفیگت می‌تواند هر اسمی داشته باشد. اینجا اسمش config.php است:

<?php

return [
    'name'  => '{{BOT_NAME}}',
    'token' => '{{BOT_TOKEN}}',
];

قدم ۲ — placeholder در نام فایل و پوشه هم کار می‌کند

فایلی به اسمِ {{BOT_NAME}}.php بعد از ساخت می‌شود MyCoolBot.php. برای پوشه‌ها هم همین‌طور، مثل handlers/{{BOT_NAME}}/.

قدم ۳ — هر تعداد فایل که خواستی (یک مثال واقعی)

یک قالب می‌تواند هر تعداد فایل داشته باشد. اینجا دو فایل دارد: config.php و server-key.php.

فایل config.php:

<?php

return [
    'name'  => '{{BOT_NAME}}',
    'token' => '{{BOT_TOKEN}}',
];

فایل server-key.php:

<?php

return [
    'secret'      => '{{SERVER_KEY}}',
    'webhook_url' => '{{WEBHOOK_URL}}',
];

فقط یک فراخوانی build() هر دو فایل را یکجا پر می‌کند:

$builder
    ->define('BOT_NAME', required: true)
    ->define('BOT_TOKEN', required: true)
    ->define('SERVER_KEY', required: true)
    ->define('WEBHOOK_URL', default: '');

$builder->build(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME'    => 'MyCoolBot',
    'BOT_TOKEN'   => '123456:ABC-DEF',
    'SERVER_KEY'  => 's3cr3t',
    'WEBHOOK_URL' => 'https://example.com/hook',
]);

فایل‌های بدون placeholder همان‌طور که هستند کپی می‌شوند، پس می‌توانی فایل‌های ثابت و قالبی را آزادانه کنار هم بگذاری (PHP، JSON، .env، Markdown، تصویر و هر چیز دیگر).

استفاده

تعریف مقادیر (اجباری و پیش‌فرض):

$builder
    ->define('BOT_TOKEN', required: true)   // must be provided
    ->define('ADMIN_ID', default: '0');     // optional, falls back to '0'

اگر یک مقدار اجباری داده نشود، پیش از نوشتن هر فایلی یک BotBuilderException پرتاب می‌شود — پس هیچ‌وقت پروژه‌ی نصفه‌کاره تولید نمی‌شود.

بازنویسی مقصد موجود:

$builder->build($target, $values, overwrite: true);

بدون overwrite: true، ساختن در پوشه‌ای که از قبل وجود دارد خطا می‌دهد (این جلوی خراب‌کردن کارِ قبلی‌ات را می‌گیرد).

استفاده از اجزای سطح‌پایین: نمای BotBuilder اختیاری است؛ می‌توانی مستقیم از اجزا استفاده کنی:

use BotBuilder\Template;
use BotBuilder\BotGenerator;

$generator = new BotGenerator(new Template(__DIR__ . '/base/telegram-bot'));

$files = $generator->generate(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME' => 'MyCoolBot',
]);

جداکننده‌های سفارشی:

use BotBuilder\Template;
use BotBuilder\BotGenerator;
use BotBuilder\PlaceholderReplacer;

$generator = new BotGenerator(
    new Template(__DIR__ . '/base/telegram-bot'),
    new PlaceholderReplacer('%%', '%%'),  // use %%KEY%% instead of {{KEY}}
);

مرجع API

BotBuilder (facade)

Method Description
__construct(string $templatePath) Point at the base template folder.
define(string $key, ?string $default = null, bool $required = false): self Register an expected placeholder.
build(string $target, array $values, bool $overwrite = false): array Validate values and generate the project. Returns the generated file paths.

BotGenerator

Method Description
generate(string $target, array $values, bool $overwrite = false): array Generate files (content + names) into the target directory.

Template

Method Description
path(): string The template root path.
files(): array All files as relative paths (recursive).
read(string $relativePath): string Read a single file's content.

Config

Method Description
define(string $key, ?string $default = null, bool $required = false): self Declare an expected placeholder.
resolve(array $values): array Merge given values with defaults and validate required keys.

PlaceholderReplacer

Method Description
replace(string $content, array $values): string Replace known tokens (unknown ones are left untouched).
placeholders(string $content): array List the unique tokens found in a string.

مثال کامل: ربات تلگرام

فایل base/telegram-bot/config.php

<?php

return [
    'name'     => '{{BOT_NAME}}',
    'token'    => '{{BOT_TOKEN}}',
    'admin_id' => {{ADMIN_ID}},
];

فایل base/telegram-bot/bot.php

<?php

$config = require __DIR__ . '/config.php';
$api = 'https://api.telegram.org/bot' . $config['token'] . '/';
$offset = 0;

echo $config['name'] . ' is running...' . PHP_EOL;

while (true) {
    $response = file_get_contents($api . 'getUpdates?timeout=30&offset=' . $offset);
    $updates = json_decode($response, true);

    foreach ($updates['result'] ?? [] as $update) {
        $offset = $update['update_id'] + 1;
        $chatId = $update['message']['chat']['id'] ?? null;
        $text = $update['message']['text'] ?? '';

        if ($chatId !== null) {
            file_get_contents($api . 'sendMessage?' . http_build_query([
                'chat_id' => $chatId,
                'text' => 'You said: ' . $text,
            ]));
        }
    }
}

ساختنش:

use BotBuilder\BotBuilder;

$builder = new BotBuilder(__DIR__ . '/base/telegram-bot');

$builder
    ->define('BOT_NAME', required: true)
    ->define('BOT_TOKEN', required: true)
    ->define('ADMIN_ID', default: '0');

$builder->build(__DIR__ . '/bots/my-new-bot', [
    'BOT_NAME'  => 'MyCoolBot',
    'BOT_TOKEN' => '123456:ABC-DEF',
    'ADMIN_ID'  => '55555',
]);

حالا رباتِ تازه‌ساخته‌شده‌ات را اجرا کن:

php bots/my-new-bot/bot.php

تست

composer install
./vendor/bin/phpunit

مشارکت

از مشارکت استقبال می‌شود! توی گیت‌هاب به‌راحتی issue باز کن یا pull request بفرست.

لایسنس

تحت لایسنس MIT منتشر شده است. برای جزئیات فایل LICENSE را ببین.

Made with ❤️ by hojjatjh