# 📖 Master Guide: Telegram Bot Making on Free Bot Host (`botmakingdocs.md`)

Welcome to the comprehensive development guide for building high-performance Telegram bots on **Free Bot Host**. This guide covers everything from beginner setup to advanced architectures, including our modern **Inline and Reply Keyboard Button Color Styling (`primary`, `success`, `danger`)**, SQLite database integration, cron automations, and best practices.

---

## 📌 Table of Contents
1. [Architecture & Folder Structure](#1-architecture--folder-structure)
2. [Environment Variables & Credentials (.env)](#2-environment-variables--credentials-env)
3. [Incoming Updates & Telegram Bot API Handler](#3-incoming-updates--telegram-bot-api-handler)
4. [🎨 Keyboard Menus & Button Color Styling (`primary`, `success`, `danger`)](#4--keyboard-menus--button-color-styling)
   - [Inline Keyboard with Button Colors](#inline-keyboard-with-button-colors)
   - [Reply Keyboard with Button Colors](#reply-keyboard-with-button-colors)
   - [Combined Interactive Menu Grid](#combined-interactive-menu-grid)
5. [Callback Queries & Interactive Navigation](#5-callback-queries--interactive-navigation)
6. [SQLite Database Integration (`storage/database.db`)](#6-sqlite-database-integration-storagedatabasedb)
7. [Automated Background Cron Jobs (`cron.php`)](#7-automated-background-cron-jobs-cronphp)
8. [Broadcast & User Tracking](#8-broadcast--user-tracking)
9. [Error Handling & Debugging](#9-error-handling--debugging)
10. [🚀 Full Production Ready Boilerplates](#10--full-production-ready-boilerplates)
    - [Boilerplate 1: Modern Styled Keyboard Bot](#boilerplate-1-modern-styled-keyboard-bot)
    - [Boilerplate 2: Full SQLite Database Bot](#boilerplate-2-full-sqlite-database-bot)
11. [✨ Custom Animated & Static Emojis (`<tg-emoji>` & MarkdownV2)](#11--custom-animated--static-emojis-tg-emoji--markdownv2)
12. [⭐ Telegram Stars Payments System (`currency: XTR`)](#12--telegram-stars-payments-system-currency-xtr)
13. [🧠 AI Chat & Auto-Reply Integration (Gemini, OpenAI, Claude, OpenRouter)](#13--ai-chat--auto-reply-integration-gemini-openai-claude-openrouter)
14. [📱 Telegram Mini Apps (WebApp Buttons) & Media Handlers](#14--telegram-mini-apps-webapp-buttons--media-handlers)
15. [🚀 Complete Boilerplate 3: Telegram Stars Digital Store Bot](#15--complete-boilerplate-3-telegram-stars-digital-store-bot)
16. [🚀 Complete Boilerplate 4: AI Intelligent Chatbot with SQLite Memory](#16--complete-boilerplate-4-ai-intelligent-chatbot-with-sqlite-memory)
17. [💥 Message Reactions & Emoji Reacts (`setMessageReaction`)](#17--message-reactions--emoji-reacts-setmessagereaction)
18. [🔒 Paid Media with Telegram Stars (`sendPaidMedia`)](#18--paid-media-with-telegram-stars-sendpaidmedia)
19. [💼 Telegram Business Integration (`business_connection`, `business_message`)](#19--telegram-business-integration-business_connection-business_message)
20. [🎁 Telegram Star Gifts System (`sendGift`)](#20--telegram-star-gifts-system-sendgift)
21. [🏛️ Forum Topics Management (`createForumTopic`, `message_thread_id`)](#21--forum-topics-management-createforumtopic-message_thread_id)
22. [👥 Chat Join Requests & Auto-Approvals (`approveChatJoinRequest`)](#22--chat-join-requests--auto-approvals-approvechatjoinrequest)
23. [⚡ Inline Mode Queries & Instant Results (`answerInlineQuery`)](#23--inline-mode-queries--instant-results-answerinlinequery)
24. [🎲 Interactive Entertainment: Polls, Quizzes & Animated Dice (`sendDice`, `sendPoll`)](#24--interactive-entertainment-polls-quizzes--animated-dice-senddice-sendpoll)
25. [🛡️ Production Webhook Security & Dropping Pending Updates](#25--production-webhook-security--dropping-pending-updates)
26. [🔘 Bot Commands, Scopes & Menu Button (`setMyCommands`, `setChatMenuButton`)](#26--bot-commands-scopes--menu-button-setmycommands-setchatmenubutton)
27. [📝 Bot Profile, Descriptions & Multilingual Onboarding (`setMyDescription`, `setMyName`)](#27--bot-profile-descriptions--multilingual-onboarding-setmydescription-setmyname)
28. [👥 Chat Member & Admin Rights Management (`banChatMember`, `restrictChatMember`, `promoteChatMember`)](#28--chat-member--admin-rights-management-banchatmember-restrictchatmember-promotechatmember)
29. [📌 Chat Settings, Pinned Messages & Batch Deletions (`deleteMessages`, `pinChatMessage`, `copyMessages`)](#29--chat-settings-pinned-messages--batch-deletions-deletemessages-pinchatmessage-copymessages)
30. [🚀 Channel Boosts & User Boost Detection (`getUserChatBoosts`, `chat_boost`)](#30--channel-boosts--user-boost-detection-getuserchatboosts-chat_boost)
31. [🖼️ Media Albums & Groups (`sendMediaGroup`)](#31--media-albums--groups-sendmediagroup)
32. [📍 Geolocation, Live Location & Venues (`sendLocation`, `editMessageLiveLocation`)](#32--geolocation-live-location--venues-sendlocation-editmessagelivelocation)
33. [📱 Contacts, Phone Verification & VCards (`request_contact`, `sendContact`)](#33--contacts-phone-verification--vcards-request_contact-sendcontact)
34. [🎨 Custom Sticker Packs & Stickers (`createNewStickerSet`, `sendSticker`)](#34--custom-sticker-packs--stickers-createnewstickerset-sendsticker)
35. [🎙️ Voice Notes, Audio & Circular Video Notes (`sendVoice`, `sendVideoNote`, `sendAudio`)](#35--voice-notes-audio--circular-video-notes-sendvoice-sendvideonote-sendaudio)

---

## 1. Architecture & Folder Structure

Every bot on Free Bot Host operates in its own isolated workspace with dedicated compute, storage quotas, and a sandboxed SQLite database:

```text
/storage/users/{chat_id}/bots/{bot_username}/
├── index.php             # Main webhook execution entrypoint
├── .env                  # Protected credentials and custom environment variables
├── storage/
│   └── database.db       # Bot-isolated SQLite database
├── cron.php              # (Optional) Automated periodic cron script
├── handlers/             # (Optional) Modular PHP action handlers
└── error.log             # Auto-generated runtime error log
```

When a user interacts with your bot on Telegram, Telegram delivers an HTTP `POST` JSON payload directly to your bot's `index.php`.

---

## 2. Environment Variables & Credentials (.env)

Your bot's `.env` file is generated automatically when you deploy. It securely holds your bot token and configuration without exposing them in public repositories:

```ini
BOT_TOKEN="1234567890:AAHxyz..."
BOT_USERNAME="MyAwesomeBot"
BOT_ID="1234567890"
ADMIN_CHAT_ID="987654321"
OWNER_CHAT_ID="987654321"
CREATED_AT="1726000000"
```

### Loading `.env` in PHP:
```php
$envFile = __DIR__ . '/.env';
$ENV = [];
if (is_file($envFile)) {
    foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
        $line = trim($line);
        if ($line === '' || str_starts_with($line, '#') || !str_contains($line, '=')) continue;
        [$k, $v] = explode('=', $line, 2);
        $ENV[trim($k)] = trim(trim($v), '"\'');
    }
}

define('BOT_TOKEN', $ENV['BOT_TOKEN'] ?? '');
define('ADMIN_ID', $ENV['ADMIN_CHAT_ID'] ?? '');
```

---

## 3. Incoming Updates & Telegram Bot API Handler

### Handling the Webhook:
```php
<?php
declare(strict_types=1);

// Capture Telegram's incoming JSON update
$rawUpdate = file_get_contents('php://input');
$update = json_decode((string)$rawUpdate, true);

if (!$update) {
    echo "Bot is online and waiting for Telegram updates.";
    exit;
}

// Extract message or callback query
$message = $update['message'] ?? null;
$callback = $update['callback_query'] ?? null;
```

### Clean API Request Helper (`bot()`):
```php
function bot(string $method, array $params = []): array {
    $url = 'https://api.telegram.org/bot' . BOT_TOKEN . '/' . $method;
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($params),
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_TIMEOUT        => 20,
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode((string)$res, true) ?: ['ok' => false];
}

// Convenient shortcut for sendMessage
function sendMessage($chatId, string $text, array $extra = []): array {
    return bot('sendMessage', array_merge([
        'chat_id'    => $chatId,
        'text'       => $text,
        'parse_mode' => 'HTML'
    ], $extra));
}
```

---

## 4. 🎨 Keyboard Menus & Button Color Styling

Free Bot Host supports button color styling for both **Inline Keyboards** and **Reply Keyboards**.

### 🎨 Style to Color Mapping:
| Style Attribute | Rendered Button Color | Best Use Cases |
|---|---|---|
| `'style' => 'primary'` | 🔵 **Blue** | Main call-to-action, Confirm, Open, Start, Next |
| `'style' => 'success'` | 🟢 **Green** | Buy, Deposit, Approve, Completed, Accept, Add |
| `'style' => 'danger'`  | 🔴 **Red** | Delete, Cancel, Reject, Withdraw, Ban, Clear |
| (omitted / default)    | ⚪ **Standard/Gray** | Back, Settings, Info, Navigation |

---

### Inline Keyboard with Button Colors

Inline keyboards appear directly attached to the message. You can specify `'style'` for any button:

```php
$inlineKeyboard = [
    'inline_keyboard' => [
        [
            [
                'text' => '🚀 Launch App',
                'callback_data' => 'action_launch',
                'style' => 'primary' // 🔵 Blue
            ],
            [
                'text' => '💳 Deposit USDT',
                'callback_data' => 'action_deposit',
                'style' => 'success' // 🟢 Green
            ]
        ],
        [
            [
                'text' => '🗑️ Delete Project',
                'callback_data' => 'action_delete',
                'style' => 'danger' // 🔴 Red
            ]
        ]
    ]
];

$reply_markup = json_encode($inlineKeyboard);

sendMessage($chatId, "<b>Welcome to Bot Dashboard!</b>\nPlease choose an option:", [
    'reply_markup' => $reply_markup
]);
```

---

### Reply Keyboard with Button Colors

Reply keyboards stay fixed at the bottom of the user's chat screen:

```php
$replyKeyboard = [
    'keyboard' => [
        [
            [
                'text' => '🟢 Activate VIP Plan',
                'style' => 'success' // 🟢 Green
            ],
            [
                'text' => '🔵 My Wallet & Stats',
                'style' => 'primary' // 🔵 Blue
            ]
        ],
        [
            [
                'text' => '🔴 Cancel Order',
                'style' => 'danger' // 🔴 Red
            ],
            [
                'text' => '⚙️ Settings' // ⚪ Standard
            ]
        ]
    ],
    'resize_keyboard' => true,
    'one_time_keyboard' => false
];

$reply_markup = json_encode($replyKeyboard);

sendMessage($chatId, "Main menu loaded with colored buttons:", [
    'reply_markup' => $reply_markup
]);
```

---

### Combined Interactive Menu Grid

Here is a full pattern for an interactive confirmation prompt:

```php
$confirmMenu = [
    'inline_keyboard' => [
        [
            [
                'text' => '✅ Confirm & Proceed',
                'callback_data' => 'confirm_yes',
                'style' => 'success' // 🟢 Green
            ],
            [
                'text' => '❌ Cancel & Abort',
                'callback_data' => 'confirm_no',
                'style' => 'danger' // 🔴 Red
            ]
        ],
        [
            [
                'text' => 'ℹ️ View Documentation',
                'url' => 'https://t.me/your_channel',
                'style' => 'primary' // 🔵 Blue
            ]
        ]
    ]
];
```

---

## 5. Callback Queries & Interactive Navigation

When users click an inline button, Telegram sends a `callback_query`. Always respond using `answerCallbackQuery` so the button stops loading:

```php
if ($callback) {
    $callbackId = $callback['id'];
    $data = $callback['data'] ?? '';
    $chatId = $callback['message']['chat']['id'] ?? 0;
    $messageId = $callback['message']['message_id'] ?? 0;

    // 1. Acknowledge the click immediately
    bot('answerCallbackQuery', [
        'callback_query_id' => $callbackId,
        'text'              => 'Loading…',
        'show_alert'        => false
    ]);

    // 2. Handle actions
    if ($data === 'action_deposit') {
        bot('editMessageText', [
            'chat_id'    => $chatId,
            'message_id' => $messageId,
            'text'       => "<b>Deposit Funds</b>\nSend USDT (TRC20) to your balance.",
            'parse_mode' => 'HTML',
            'reply_markup' => json_encode([
                'inline_keyboard' => [
                    [['text' => '⬅️ Back to Menu', 'callback_data' => 'main_menu', 'style' => 'primary']]
                ]
            ])
        ]);
    }
}
```

---

## 6. SQLite Database Integration (`storage/database.db`)

Each bot has access to its own ultra-fast, local SQLite database file in `storage/database.db`:

```php
$dbFile = __DIR__ . '/storage/database.db';
if (!is_dir(__DIR__ . '/storage')) {
    mkdir(__DIR__ . '/storage', 0755, true);
}

$db = new PDO('sqlite:' . $dbFile, null, null, [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);

// Initialize tables
$db->exec("CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id TEXT UNIQUE,
    username TEXT,
    first_name TEXT,
    balance REAL DEFAULT 0.00,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    last_active DATETIME DEFAULT CURRENT_TIMESTAMP
)");
```

### User Registration & Balance Tracking:
```php
function registerUser(PDO $db, array $from): array {
    $chatId = (string) $from['id'];
    $username = $from['username'] ?? '';
    $firstName = $from['first_name'] ?? 'User';

    $stmt = $db->prepare("INSERT INTO users (chat_id, username, first_name, last_active)
        VALUES (?, ?, ?, datetime('now'))
        ON CONFLICT(chat_id) DO UPDATE SET
            username = excluded.username,
            first_name = excluded.first_name,
            last_active = datetime('now')");
    $stmt->execute([$chatId, $username, $firstName]);

    $getUser = $db->prepare("SELECT * FROM users WHERE chat_id = ?");
    $getUser->execute([$chatId]);
    return $getUser->fetch() ?: [];
}
```

---

## 7. Automated Background Cron Jobs (`cron.php`)

To perform automated background tasks (daily reports, subscription renewals, database cleanups):

1. Create a `cron.php` file in your bot root folder:
```php
<?php
declare(strict_types=1);

require_once __DIR__ . '/index.php'; // Or load your bot functions

// Connect to bot DB
$db = new PDO('sqlite:' . __DIR__ . '/storage/database.db');

// Example: Send automated reminder to users inactive for 3 days
$stmt = $db->query("SELECT chat_id FROM users WHERE last_active < datetime('now', '-3 days') LIMIT 50");
$users = $stmt->fetchAll(PDO::FETCH_COLUMN);

foreach ($users as $chatId) {
    sendMessage($chatId, "👋 We missed you! Check out our new features today.", [
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => '🚀 Open Dashboard', 'callback_data' => 'main_menu', 'style' => 'primary']]
            ]
        ])
    ]);
    usleep(50000); // 50ms throttle
}

echo "Cron finished successfully at " . date('Y-m-d H:i:s');
```

2. Schedule the cron job in your Mini App under **Variables & Cron** -> **+ New Cron Task**, or through the Developer API / MCP!

---

## 8. Broadcast & User Tracking

Send mass notifications safely with rate-limiting:

```php
function broadcastMessage(PDO $db, string $text, ?string $replyMarkup = null): array {
    $stmt = $db->query("SELECT chat_id FROM users");
    $total = 0; $sent = 0; $failed = 0;

    while ($chatId = $stmt->fetchColumn()) {
        $total++;
        $extra = [];
        if ($replyMarkup) $extra['reply_markup'] = $replyMarkup;
        $res = sendMessage($chatId, $text, $extra);

        if (!empty($res['ok'])) {
            $sent++;
        } else {
            $failed++;
        }
        usleep(35000); // Sleep 35ms (Telegram limit: ~30 msg/sec)
    }

    return ['total' => $total, 'sent' => $sent, 'failed' => $failed];
}
```

---

## 9. Error Handling & Debugging

Always wrap your main logic in a `try...catch` block to log exceptions and prevent Telegram retry storms:

```php
try {
    // Your bot code here
} catch (Throwable $e) {
    $errorMsg = "[" . date('Y-m-d H:i:s') . "] " . $e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine() . "\n";
    @file_put_contents(__DIR__ . '/error.log', $errorMsg, FILE_APPEND);

    // Notify bot admin if configured
    if (defined('ADMIN_ID') && ADMIN_ID !== '') {
        sendMessage(ADMIN_ID, "⚠️ <b>Bot Exception:</b>\n<code>" . htmlspecialchars($e->getMessage()) . "</code>");
    }
}
```

---

## 10. 🚀 Full Production Ready Boilerplates

### Boilerplate 1: Modern Styled Keyboard Bot
Save as `index.php`:

```php
<?php
declare(strict_types=1);

// 1. Load Credentials
$envFile = __DIR__ . '/.env';
$ENV = [];
if (is_file($envFile)) {
    foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $l) {
        if ($l && $l[0] !== '#' && str_contains($l, '=')) {
            [$k, $v] = explode('=', $l, 2);
            $ENV[trim($k)] = trim(trim($v), '"\'');
        }
    }
}

define('BOT_TOKEN', $ENV['BOT_TOKEN'] ?? '');
if (BOT_TOKEN === '') exit('No BOT_TOKEN');

// 2. Telegram Helper
function bot(string $method, array $params = []): array {
    $ch = curl_init('https://api.telegram.org/bot' . BOT_TOKEN . '/' . $method);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($params),
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_TIMEOUT        => 15
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode((string)$res, true) ?: [];
}

// 3. Handle Updates
$update = json_decode((string)file_get_contents('php://input'), true);
if (!$update) exit('Bot is active');

$msg = $update['message'] ?? null;
$cb  = $update['callback_query'] ?? null;

if ($msg && isset($msg['text'])) {
    $chatId = $msg['chat']['id'];
    $text = trim($msg['text']);

    if ($text === '/start') {
        // Styled Inline Menu
        $inlineMenu = [
            'inline_keyboard' => [
                [
                    ['text' => '🚀 Launch Portal', 'callback_data' => 'launch', 'style' => 'primary'],
                    ['text' => '💎 Upgrade VIP', 'callback_data' => 'upgrade', 'style' => 'success']
                ],
                [
                    ['text' => '🛑 Stop Service', 'callback_data' => 'stop', 'style' => 'danger']
                ]
            ]
        ];

        // Styled Reply Keyboard
        $replyMenu = [
            'keyboard' => [
                [
                    ['text' => '🟢 Deposit Funds', 'style' => 'success'],
                    ['text' => '🔵 My Profile', 'style' => 'primary']
                ],
                [
                    ['text' => '🔴 Close Menu', 'style' => 'danger']
                ]
            ],
            'resize_keyboard' => true
        ];

        bot('sendMessage', [
            'chat_id'      => $chatId,
            'text'         => "👋 <b>Welcome!</b>\nEnjoy our modern styled keyboards:",
            'parse_mode'   => 'HTML',
            'reply_markup' => json_encode($inlineMenu)
        ]);
    }
}

if ($cb) {
    $cbId = $cb['id'];
    $data = $cb['data'] ?? '';
    $chatId = $cb['message']['chat']['id'];
    $msgId  = $cb['message']['message_id'];

    bot('answerCallbackQuery', ['callback_query_id' => $cbId, 'text' => "Selected: {$data}"]);

    if ($data === 'launch') {
        bot('editMessageText', [
            'chat_id'      => $chatId,
            'message_id'   => $msgId,
            'text'         => "🚀 <b>Portal Active</b>\nChoose an action below:",
            'parse_mode'   => 'HTML',
            'reply_markup' => json_encode([
                'inline_keyboard' => [
                    [['text' => '⬅️ Back', 'callback_data' => 'back', 'style' => 'primary']]
                ]
            ])
        ]);
    }
}
```

---

### Boilerplate 2: Full SQLite Database Bot
Save as `index.php`:

```php
<?php
declare(strict_types=1);

// 1. Load Env
$envFile = __DIR__ . '/.env';
$ENV = [];
if (is_file($envFile)) {
    foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $l) {
        if ($l && $l[0] !== '#' && str_contains($l, '=')) {
            [$k, $v] = explode('=', $l, 2);
            $ENV[trim($k)] = trim(trim($v), '"\'');
        }
    }
}
define('BOT_TOKEN', $ENV['BOT_TOKEN'] ?? '');
if (BOT_TOKEN === '') exit('No token');

// 2. Database Connection
$db = new PDO('sqlite:' . __DIR__ . '/storage/database.db');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec("CREATE TABLE IF NOT EXISTS users (
    chat_id TEXT PRIMARY KEY,
    username TEXT,
    balance REAL DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)");

// 3. Telegram API Helper
function bot(string $method, array $params = []): array {
    $ch = curl_init('https://api.telegram.org/bot' . BOT_TOKEN . '/' . $method);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($params),
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_TIMEOUT        => 15
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode((string)$res, true) ?: [];
}

// 4. Update Processing
$update = json_decode((string)file_get_contents('php://input'), true);
if (!$update) exit('Online');

$msg = $update['message'] ?? null;
if ($msg && isset($msg['text'])) {
    $chatId = (string) $msg['chat']['id'];
    $text = trim($msg['text']);
    $user = $msg['from'] ?? [];

    // Register user
    $st = $db->prepare("INSERT OR IGNORE INTO users (chat_id, username) VALUES (?, ?)");
    $st->execute([$chatId, $user['username'] ?? '']);

    if ($text === '/start') {
        $st = $db->prepare("SELECT balance FROM users WHERE chat_id = ?");
        $st->execute([$chatId]);
        $balance = (float)$st->fetchColumn();

        $menu = [
            'inline_keyboard' => [
                [
                    ['text' => '➕ Deposit 5 USDT', 'callback_data' => 'add_funds', 'style' => 'success'],
                    ['text' => '📊 Account Stats', 'callback_data' => 'stats', 'style' => 'primary']
                ],
                [
                    ['text' => '❌ Reset Account', 'callback_data' => 'reset', 'style' => 'danger']
                ]
            ]
        ];

        bot('sendMessage', [
            'chat_id'      => $chatId,
            'text'         => "👋 <b>Welcome!</b>\n💰 Your Balance: <b>{$balance} USDT</b>",
            'parse_mode'   => 'HTML',
            'reply_markup' => json_encode($menu)
        ]);
    }
}

$cb = $update['callback_query'] ?? null;
if ($cb) {
    $chatId = (string)$cb['message']['chat']['id'];
    $msgId  = $cb['message']['message_id'];
    $data   = $cb['data'] ?? '';

    if ($data === 'add_funds') {
        $db->prepare("UPDATE users SET balance = balance + 5 WHERE chat_id = ?")->execute([$chatId]);
        bot('answerCallbackQuery', ['callback_query_id' => $cb['id'], 'text' => '+5 USDT Added!']);
        
        $st = $db->prepare("SELECT balance FROM users WHERE chat_id = ?");
        $st->execute([$chatId]);
        $newBal = (float)$st->fetchColumn();

        bot('editMessageText', [
            'chat_id'    => $chatId,
            'message_id' => $msgId,
            'text'       => "✅ <b>Deposit Successful!</b>\nNew Balance: <b>{$newBal} USDT</b>",
            'parse_mode' => 'HTML',
            'reply_markup' => json_encode([
                'inline_keyboard' => [
                    [['text' => '⬅️ Back to Menu', 'callback_data' => 'back', 'style' => 'primary']]
                ]
            ])
        ]);
    }
}
```

---

## 11. ✨ Custom Animated & Static Emojis (`<tg-emoji>` & MarkdownV2)

Telegram Bot API supports custom emojis across messages, captions, and notifications. Custom emojis render as animated or styled stickers directly inline with text.

### 📌 Formatting Specifications:

#### 1. HTML Formatting (`parse_mode: 'HTML'`):
Wrap the fallback standard emoji inside the `<tg-emoji>` tag with the `emoji-id` attribute:
```html
Welcome to our bot! <tg-emoji emoji-id="5368324170671202286">🔥</tg-emoji>
Congratulations, you unlocked VIP <tg-emoji emoji-id="5449987823521096781">⭐</tg-emoji>
```

> [!IMPORTANT]
> **Fallback Emoji Requirement**: The tag must wrap a standard Unicode emoji (like `🔥` or `⭐`). Clients that cannot render custom emojis (or web clients without Premium) will gracefully fall back to this character.

#### 2. MarkdownV2 Formatting (`parse_mode: 'MarkdownV2'`):
```markdown
Welcome to our bot\! \![🔥](tg://emoji?id=5368324170671202286)
Congratulations, you unlocked VIP \![⭐](tg://emoji?id=5449987823521096781)
```

### 🔍 How to Find Custom Emoji IDs:
1. **Telegram Web Inspector**: Open Telegram Web (A or K version), right-click on an emoji from a sticker pack, and inspect element to find `data-custom-emoji-id` or `custom_emoji_id`.
2. **Bot Message Echo**: Send the custom emoji to your bot in Telegram and print `$update['message']['entities']`. Look for an entity where `'type' === 'custom_emoji'` and read `'custom_emoji_id'`.

### 💡 PHP Helper Function for Custom Emojis:
```php
function tg_emoji(string $emojiId, string $fallback = '⭐'): string {
    return "<tg-emoji emoji-id=\"{$emojiId}\">{$fallback}</tg-emoji>";
}

// Usage in messages:
$star = tg_emoji('5449987823521096781', '⭐');
$fire = tg_emoji('5368324170671202286', '🔥');

bot('sendMessage', [
    'chat_id'    => $chatId,
    'text'       => "{$star} <b>Premium Store Active</b> {$fire}\n\nUpgrade your account today!",
    'parse_mode' => 'HTML'
]);
```

---

## 12. ⭐ Telegram Stars Payments System (`currency: XTR`)

**Telegram Stars (`XTR`)** is the official digital currency for purchasing digital goods, subscriptions, and services inside Telegram bots and Mini Apps.

### ⚠️ Critical Telegram Stars Rules:
1. **Currency**: Must be strictly set to `"XTR"`.
2. **`provider_token`**: **MUST BE COMPLETELY OMITTED!** Do not set it to an empty string, null, or false. Delete the key entirely from the `sendInvoice` payload.
3. **Prices Amount**: Integer amount of Stars (e.g., `50` means 50 Stars; no cents or decimal multiplication).
4. **Pre-Checkout Timeout**: You **must** answer `pre_checkout_query` within **10 seconds** via `answerPreCheckoutQuery`, or Telegram will cancel the order.

### 🔄 The 3-Step Stars Payment Lifecycle:

```
[User clicks Buy Button] 
       │
       ▼
1. Bot calls sendInvoice (currency: "XTR", NO provider_token)
       │
       ▼
[Telegram displays native Star payment modal & user confirms]
       │
       ▼
2. Telegram sends update: pre_checkout_query
   Bot immediately answers with: answerPreCheckoutQuery (ok: true)
       │
       ▼
3. Telegram processes payment and sends update: successful_payment
   Bot delivers digital item / activates VIP in database & notifies user
```

### 1. Sending a Stars Invoice (`sendInvoice`):
```php
function send_stars_invoice(string $chatId, string $title, string $description, int $starsAmount, string $payload): array {
    return bot('sendInvoice', [
        'chat_id'      => $chatId,
        'title'        => $title,
        'description'  => $description,
        'payload'      => $payload,
        'currency'     => 'XTR', // Official Stars Currency
        // CRITICAL: provider_token is omitted entirely!
        'prices'       => [
            ['label' => $title, 'amount' => $starsAmount]
        ]
    ]);
}
```

### 2. Handling `pre_checkout_query`:
```php
$preCheckout = $update['pre_checkout_query'] ?? null;
if ($preCheckout) {
    $queryId = $preCheckout['id'];
    $stars   = (int) $preCheckout['total_amount'];
    $payload = $preCheckout['invoice_payload'];

    // Verify inventory or conditions here
    $inStock = true;

    if ($inStock) {
        bot('answerPreCheckoutQuery', [
            'pre_checkout_query_id' => $queryId,
            'ok'                    => true
        ]);
    } else {
        bot('answerPreCheckoutQuery', [
            'pre_checkout_query_id' => $queryId,
            'ok'                    => false,
            'error_message'         => 'Sorry, this digital product is currently out of stock.'
        ]);
    }
    exit;
}
```

### 3. Handling `successful_payment`:
```php
$msg = $update['message'] ?? null;
if ($msg && isset($msg['successful_payment'])) {
    $pay       = $msg['successful_payment'];
    $chatId    = (string) $msg['chat']['id'];
    $starsPaid = (int) $pay['total_amount'];
    $payload   = (string) $pay['invoice_payload'];
    $chargeId  = (string) $pay['telegram_payment_charge_id'];

    // Deliver product & update database
    $st = $db->prepare("INSERT INTO transactions (chat_id, stars_amount, charge_id, payload) VALUES (?, ?, ?, ?)");
    $st->execute([$chatId, $starsPaid, $chargeId, $payload]);

    bot('sendMessage', [
        'chat_id'    => $chatId,
        'text'       => "🎉 <b>Payment Successful!</b>\n\n⭐ Stars Paid: <b>{$starsPaid} XTR</b>\n🧾 Charge ID: <code>{$chargeId}</code>\n\nYour digital service has been activated immediately!",
        'parse_mode' => 'HTML'
    ]);
}
```

---

## 13. 🧠 AI Chat & Auto-Reply Integration (Gemini, OpenAI, Claude, OpenRouter)

Integrate state-of-the-art AI models to turn your bot into a 24/7 intelligent assistant, customer support agent, or creative writer.

### ⚡ Key Architectural Considerations for PHP Webhooks:
1. **Synchronous Execution**: Use direct HTTP requests (cURL with 15-25s timeout) inside webhook execution.
2. **User Feedback (`sendChatAction: typing`)**: Always send typing action immediately before calling the AI API so the user sees Telegram's native "typing..." bubble.
3. **HTML Sanitization**: Always wrap user and AI text with `htmlspecialchars()` if outputting in `parse_mode: 'HTML'` to prevent malformed tag crashes.
4. **Context Memory**: Store recent conversation history in the bot's SQLite database (`storage/database.db`) so the AI remembers context across turns.

### 🌐 Universal AI Caller Function (OpenAI / OpenRouter / Gemini Compatible):
```php
function ai_generate_reply(string $userPrompt, array $history = [], string $systemPrompt = ''): string {
    // Option A: OpenRouter / OpenAI API
    $apiKey = getenv('OPENAI_API_KEY') ?: getenv('AI_API_KEY');
    $endpoint = 'https://openrouter.ai/api/v1/chat/completions'; // Or https://api.openai.com/v1/chat/completions
    $model = 'google/gemini-2.0-flash-exp:free'; // Or gpt-4o-mini

    if (!$apiKey) {
        return "⚠️ AI API key is not configured. Please add AI_API_KEY in your .env file.";
    }

    $messages = [];
    if ($systemPrompt !== '') {
        $messages[] = ['role' => 'system', 'content' => $systemPrompt];
    }
    foreach ($history as $h) {
        $messages[] = ['role' => $h['role'], 'content' => $h['content']];
    }
    $messages[] = ['role' => 'user', 'content' => $userPrompt];

    $ch = curl_init($endpoint);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode([
            'model'       => $model,
            'messages'    => $messages,
            'temperature' => 0.7,
            'max_tokens'  => 1000
        ]),
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $apiKey
        ],
        CURLOPT_TIMEOUT => 25
    ]);
    $raw = curl_exec($ch);
    curl_close($ch);

    $json = json_decode((string)$raw, true);
    return $json['choices'][0]['message']['content'] ?? '⚠️ Sorry, I could not generate a response at this moment.';
}
```

### 🗄️ Multi-Turn Chat History Table in SQLite:
```sql
CREATE TABLE IF NOT EXISTS chat_history (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id TEXT NOT NULL,
    role TEXT NOT NULL, -- 'user' or 'assistant'
    content TEXT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_chat_history_id ON chat_history(chat_id);
```

---

## 14. 📱 Telegram Mini Apps (WebApp Buttons) & Media Handlers

### 1. Launching a Telegram Mini App from Inline Buttons:
```php
$webAppKeyboard = [
    'inline_keyboard' => [
        [
            [
                'text'    => '🚀 Open Web App',
                'web_app' => ['url' => 'https://yourdomain.com/miniapp.php'],
                'style'   => 'primary' // 🔵 Blue
            ]
        ],
        [
            [
                'text'          => '🛍️ Star Shop',
                'callback_data' => 'open_stars_shop',
                'style'         => 'success' // 🟢 Green
            ]
        ]
    ]
];

bot('sendMessage', [
    'chat_id'      => $chatId,
    'text'         => "✨ <b>Welcome to the Next-Gen Bot Studio!</b>\nLaunch the full Mini App below:",
    'parse_mode'   => 'HTML',
    'reply_markup' => json_encode($webAppKeyboard)
]);
```

### 2. Sending Photos, Audios, and Media with Styled Buttons:
```php
bot('sendPhoto', [
    'chat_id'      => $chatId,
    'photo'        => 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe',
    'caption'      => "🌌 <b>Digital Art NFT #104</b>\nPrice: <b>25 Stars (XTR)</b>",
    'parse_mode'   => 'HTML',
    'reply_markup' => json_encode([
        'inline_keyboard' => [
            [['text' => '⭐ Buy with Stars (25 XTR)', 'callback_data' => 'buy_art_104', 'style' => 'success']]
        ]
    ])
]);
```

---

## 15. 🚀 Complete Boilerplate 3: Telegram Stars Digital Store Bot

Save this as your bot's `index.php` for a complete Telegram Stars e-commerce solution:

```php
<?php
/**
 * Telegram Stars Digital Store Bot
 * Supports: Catalog, Invoices (XTR), pre_checkout_query, successful_payment, and delivery
 */
declare(strict_types=1);

@ini_set('log_errors', '1');
@ini_set('error_log', __DIR__ . '/error.log');

// 1. Load Credentials
$envFile = __DIR__ . '/.env';
$ENV = [];
if (is_file($envFile)) {
    foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $l) {
        if ($l && $l[0] !== '#' && str_contains($l, '=')) {
            [$k, $v] = explode('=', $l, 2);
            $ENV[trim($k)] = trim(trim($v), '"\'');
        }
    }
}
define('BOT_TOKEN', $ENV['BOT_TOKEN'] ?? '');
if (BOT_TOKEN === '') exit('No BOT_TOKEN');

// 2. Database
if (!is_dir(__DIR__ . '/storage')) mkdir(__DIR__ . '/storage', 0755, true);
$db = new PDO('sqlite:' . __DIR__ . '/storage/database.db', null, null, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
$db->exec("CREATE TABLE IF NOT EXISTS orders (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id TEXT,
    product_name TEXT,
    stars_amount INTEGER,
    charge_id TEXT,
    status TEXT DEFAULT 'completed',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)");

// 3. Telegram API Helper
function bot(string $method, array $params = []): array {
    $ch = curl_init('https://api.telegram.org/bot' . BOT_TOKEN . '/' . $method);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($params),
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_TIMEOUT        => 20
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode((string)$res, true) ?: [];
}

// 4. Update Processing
$raw = file_get_contents('php://input');
$update = json_decode((string)$raw, true);
if (!$update) exit('Stars Bot Online');

// ── Handle Pre-Checkout Query (Within 10s) ──
if (isset($update['pre_checkout_query'])) {
    $q = $update['pre_checkout_query'];
    bot('answerPreCheckoutQuery', [
        'pre_checkout_query_id' => $q['id'],
        'ok'                    => true
    ]);
    exit;
}

// ── Handle Message & Successful Payment ──
$msg = $update['message'] ?? null;
if ($msg) {
    $chatId = (string) $msg['chat']['id'];

    // Successful Stars Payment Event
    if (isset($msg['successful_payment'])) {
        $pay      = $msg['successful_payment'];
        $stars    = (int) $pay['total_amount'];
        $chargeId = (string) $pay['telegram_payment_charge_id'];
        $payload  = (string) $pay['invoice_payload'];

        $db->prepare("INSERT INTO orders (chat_id, product_name, stars_amount, charge_id) VALUES (?, ?, ?, ?)")
           ->execute([$chatId, $payload, $stars, $chargeId]);

        bot('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => "🎉 <b>Payment Confirmed!</b>\n\n⭐ Amount: <b>{$stars} Stars (XTR)</b>\n📦 Product: <b>" . htmlspecialchars($payload) . "</b>\n🧾 Charge ID: <code>{$chargeId}</code>\n\n🔑 <b>Your License Key:</b> <code>VIP-" . strtoupper(bin2hex(random_bytes(6))) . "</code>",
            'parse_mode' => 'HTML',
            'reply_markup' => json_encode([
                'inline_keyboard' => [
                    [['text' => '🛍️ Browse More Items', 'callback_data' => 'catalog', 'style' => 'primary']]
                ]
            ])
        ]);
        exit;
    }

    $text = trim($msg['text'] ?? '');
    if ($text === '/start' || $text === '/shop') {
        $catalog = [
            'inline_keyboard' => [
                [
                    ['text' => '⭐ VIP Access (50 Stars)', 'callback_data' => 'buy_vip_50', 'style' => 'success']
                ],
                [
                    ['text' => '🚀 Bot Source Code (100 Stars)', 'callback_data' => 'buy_src_100', 'style' => 'primary']
                ]
            ]
        ];

        bot('sendMessage', [
            'chat_id'      => $chatId,
            'text'         => "🌟 <b>Welcome to the Telegram Stars Digital Store!</b>\n\nPurchase digital subscriptions and goods using official Telegram Stars:\n\n• <b>VIP Membership</b>: 50 Stars\n• <b>Full Source Code</b>: 100 Stars",
            'parse_mode'   => 'HTML',
            'reply_markup' => json_encode($catalog)
        ]);
    }
}

// ── Handle Catalog Invoices via Callback Queries ──
$cb = $update['callback_query'] ?? null;
if ($cb) {
    $cbId   = $cb['id'];
    $chatId = (string) $cb['message']['chat']['id'];
    $data   = $cb['data'] ?? '';

    bot('answerCallbackQuery', ['callback_query_id' => $cbId]);

    if ($data === 'buy_vip_50') {
        bot('sendInvoice', [
            'chat_id'     => $chatId,
            'title'       => 'VIP Membership (1 Month)',
            'description' => 'Unlocks all premium features and dedicated 24/7 priority support.',
            'payload'     => 'vip_1_month',
            'currency'    => 'XTR', // Stars
            'prices'      => [
                ['label' => 'VIP 1 Month', 'amount' => 50]
            ]
        ]);
    } elseif ($data === 'buy_src_100') {
        bot('sendInvoice', [
            'chat_id'     => $chatId,
            'title'       => 'Full Bot Source Code Bundle',
            'description' => 'Complete production PHP source code with SQLite and webhook architecture.',
            'payload'     => 'bot_source_code',
            'currency'    => 'XTR', // Stars
            'prices'      => [
                ['label' => 'Source Code Bundle', 'amount' => 100]
            ]
        ]);
    }
}
```

---

## 16. 🚀 Complete Boilerplate 4: AI Intelligent Chatbot with SQLite Memory

Save this as your bot's `index.php` for a complete conversational AI assistant with memory:

```php
<?php
/**
 * Intelligent AI Assistant Bot with SQLite Conversation Memory
 * Compatible with OpenAI, OpenRouter, and Google Gemini
 */
declare(strict_types=1);

@ini_set('log_errors', '1');
@ini_set('error_log', __DIR__ . '/error.log');

// 1. Load Credentials from .env
$envFile = __DIR__ . '/.env';
$ENV = [];
if (is_file($envFile)) {
    foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $l) {
        if ($l && $l[0] !== '#' && str_contains($l, '=')) {
            [$k, $v] = explode('=', $l, 2);
            $ENV[trim($k)] = trim(trim($v), '"\'');
        }
    }
}
define('BOT_TOKEN', $ENV['BOT_TOKEN'] ?? '');
define('AI_API_KEY', $ENV['AI_API_KEY'] ?? ($ENV['OPENAI_API_KEY'] ?? ''));
if (BOT_TOKEN === '') exit('No BOT_TOKEN');

// 2. Database for Chat Context Memory
if (!is_dir(__DIR__ . '/storage')) mkdir(__DIR__ . '/storage', 0755, true);
$db = new PDO('sqlite:' . __DIR__ . '/storage/database.db', null, null, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
$db->exec("CREATE TABLE IF NOT EXISTS conversation_memory (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id TEXT NOT NULL,
    role TEXT NOT NULL,
    content TEXT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)");

// 3. Telegram API Helper
function bot(string $method, array $params = []): array {
    $ch = curl_init('https://api.telegram.org/bot' . BOT_TOKEN . '/' . $method);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($params),
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
        CURLOPT_TIMEOUT        => 20
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode((string)$res, true) ?: [];
}

// 4. AI Completion Helper
function call_ai(string $prompt, array $history): string {
    if (AI_API_KEY === '') {
        return "⚠️ AI API Key is missing! Please configure AI_API_KEY in your bot's .env file.";
    }

    $messages = [
        ['role' => 'system', 'content' => 'You are an intelligent, helpful, concise, and friendly Telegram assistant. Format your replies neatly using bold, bullet points, and code snippets when appropriate.']
    ];
    foreach ($history as $msg) {
        $messages[] = ['role' => $msg['role'], 'content' => $msg['content']];
    }
    $messages[] = ['role' => 'user', 'content' => $prompt];

    $ch = curl_init('https://openrouter.ai/api/v1/chat/completions'); // Or https://api.openai.com/v1/chat/completions
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode([
            'model'       => 'google/gemini-2.0-flash-exp:free', // Fast & powerful
            'messages'    => $messages,
            'temperature' => 0.7,
            'max_tokens'  => 800
        ]),
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . AI_API_KEY
        ],
        CURLOPT_TIMEOUT => 25
    ]);
    $res = curl_exec($ch);
    curl_close($ch);

    $json = json_decode((string)$res, true);
    return $json['choices'][0]['message']['content'] ?? '⚠️ Sorry, I could not generate an answer right now.';
}

// 5. Update Processing
$raw = file_get_contents('php://input');
$update = json_decode((string)$raw, true);
if (!$update) exit('AI Bot Online');

$msg = $update['message'] ?? null;
if ($msg && isset($msg['text'])) {
    $chatId = (string) $msg['chat']['id'];
    $text   = trim($msg['text']);

    if ($text === '/start') {
        $menu = [
            'inline_keyboard' => [
                [
                    ['text' => '🧹 Clear Chat Memory', 'callback_data' => 'clear_memory', 'style' => 'danger'],
                    ['text' => 'ℹ️ About Assistant', 'callback_data' => 'about_ai', 'style' => 'primary']
                ]
            ]
        ];

        bot('sendMessage', [
            'chat_id'      => $chatId,
            'text'         => "🤖 <b>Hello! I am your AI Assistant.</b>\n\nAsk me any question, brainstorm ideas, request code, or chat about anything! I remember our conversation context automatically.",
            'parse_mode'   => 'HTML',
            'reply_markup' => json_encode($menu)
        ]);
        exit;
    }

    if ($text === '/clear') {
        $db->prepare("DELETE FROM conversation_memory WHERE chat_id = ?")->execute([$chatId]);
        bot('sendMessage', ['chat_id' => $chatId, 'text' => '🧹 <b>Conversation memory cleared!</b>', 'parse_mode' => 'HTML']);
        exit;
    }

    // 1. Show Typing Status to User
    bot('sendChatAction', ['chat_id' => $chatId, 'action' => 'typing']);

    // 2. Retrieve Last 6 Conversation Turns for Memory
    $st = $db->prepare("SELECT role, content FROM conversation_memory WHERE chat_id = ? ORDER BY id DESC LIMIT 6");
    $st->execute([$chatId]);
    $history = array_reverse($st->fetchAll());

    // 3. Call AI
    $aiResponse = call_ai($text, $history);

    // 4. Save User Prompt and AI Reply to Memory
    $ins = $db->prepare("INSERT INTO conversation_memory (chat_id, role, content) VALUES (?, ?, ?)");
    $ins->execute([$chatId, 'user', $text]);
    $ins->execute([$chatId, 'assistant', $aiResponse]);

    // 5. Deliver Reply
    bot('sendMessage', [
        'chat_id'    => $chatId,
        'text'       => $aiResponse,
        'reply_markup' => json_encode([
            'inline_keyboard' => [
                [['text' => '🧹 Reset Context', 'callback_data' => 'clear_memory', 'style' => 'danger']]
            ]
        ])
    ]);
}

$cb = $update['callback_query'] ?? null;
if ($cb) {
    $cbId   = $cb['id'];
    $chatId = (string) $cb['message']['chat']['id'];
    $data   = $cb['data'] ?? '';

    if ($data === 'clear_memory') {
        $db->prepare("DELETE FROM conversation_memory WHERE chat_id = ?")->execute([$chatId]);
        bot('answerCallbackQuery', ['callback_query_id' => $cbId, 'text' => 'Context Memory Cleared!']);
        bot('sendMessage', ['chat_id' => $chatId, 'text' => '🧹 <b>Conversation context reset. What would you like to discuss next?</b>', 'parse_mode' => 'HTML']);
    } elseif ($data === 'about_ai') {
        bot('answerCallbackQuery', ['callback_query_id' => $cbId]);
        bot('sendMessage', [
            'chat_id'    => $chatId,
            'text'       => "🧠 <b>AI Assistant Specifications:</b>\n\n• Multi-turn SQLite memory cache\n• Styled inline action buttons\n• Supports OpenAI, OpenRouter, and Google Gemini models",
            'parse_mode' => 'HTML'
        ]);
    }
}
```

---

## 17. 💥 Message Reactions & Emoji Reacts (`setMessageReaction`)

Bots can react to messages with standard Unicode emojis or Custom Emojis, featuring optional full-screen "big" animations!

### 📌 API Method: `setMessageReaction`

#### Parameters:
- `chat_id`: Target chat ID or `@channelusername`
- `message_id`: Message ID to react to
- `reaction`: Array of `ReactionType` objects (up to 1 reaction per bot per message)
- `is_big`: *(Optional)* Boolean (`true` displays full-screen popping animation!)

### 💡 Helper Function for Sending Reactions:
```php
function bot_react(string|int $chatId, int $messageId, string $emoji = '👍', bool $isBig = true): array {
    return bot('setMessageReaction', [
        'chat_id'    => $chatId,
        'message_id' => $messageId,
        'reaction'   => [
            [
                'type'  => 'emoji',
                'emoji' => $emoji
            ]
        ],
        'is_big'     => $isBig
    ]);
}

// React with a Custom Emoji:
function bot_react_custom(string|int $chatId, int $messageId, string $customEmojiId, bool $isBig = true): array {
    return bot('setMessageReaction', [
        'chat_id'    => $chatId,
        'message_id' => $messageId,
        'reaction'   => [
            [
                'type'            => 'custom_emoji',
                'custom_emoji_id' => $customEmojiId
            ]
        ],
        'is_big'     => $isBig
    ]);
}
```

### ⚡ Practical Usage in Webhook Handler:
```php
$msg = $update['message'] ?? null;
if ($msg && isset($msg['text'])) {
    $chatId = $msg['chat']['id'];
    $msgId  = $msg['message_id'];
    $text   = trim($msg['text']);

    // Instantly celebrate when user submits a successful command
    if ($text === '/success' || $text === 'paid') {
        bot_react($chatId, $msgId, '🎉', true); // Big celebration animation!
    } elseif ($text === '/like') {
        bot_react($chatId, $msgId, '🔥', false);
    }
}
```

### 🔄 Handling Incoming Reaction Updates:
Telegram notifies your bot whenever users react to messages via two updates:
```php
// Individual user reaction event
$userReaction = $update['message_reaction'] ?? null;
if ($userReaction) {
    $chatId   = $userReaction['chat']['id'];
    $msgId    = $userReaction['message_id'];
    $user     = $userReaction['user'] ?? [];
    $newReact = $userReaction['new_reaction'] ?? []; // List of newly placed reactions
}

// Aggregate reaction counts (useful for channels)
$reactionCount = $update['message_reaction_count'] ?? null;
if ($reactionCount) {
    $chatId = $reactionCount['chat']['id'];
    $counts = $reactionCount['reactions']; // List of ReactionCount objects
}
```

---

## 18. 🔒 Paid Media with Telegram Stars (`sendPaidMedia`)

Monetize exclusive content (photos, albums, and video courses) by locking them behind Telegram Stars. Users pay Stars directly in chat to unlock and view the media!

### 📌 Method: `sendPaidMedia`
```php
function send_paid_photo(string|int $chatId, int $starCount, string $photoUrl, string $caption): array {
    return bot('sendPaidMedia', [
        'chat_id'    => $chatId,
        'star_count' => $starCount, // Stars required to unlock (1 - 25,000)
        'media'      => [
            [
                'type'  => 'photo',
                'media' => $photoUrl
            ]
        ],
        'caption'    => $caption,
        'parse_mode' => 'HTML'
    ]);
}

// Example: Lock an exclusive digital download
send_paid_photo($chatId, 15, 'https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe', "🔒 <b>Exclusive 4K Wallpaper Pack</b>\nUnlock now for only <b>15 Stars!</b>");
```

---

## 19. 💼 Telegram Business Integration (`business_connection`, `business_message`)

Telegram Business allows regular users and brands to connect your bot to their personal or business accounts to act as a 24/7 AI receptionist, order taker, or CRM auto-responder.

### 🔄 1. Handling Business Connections (`business_connection`):
```php
$bizConn = $update['business_connection'] ?? null;
if ($bizConn) {
    $connId   = $bizConn['id'];
    $userChat = $bizConn['user_chat_id'];
    $rights   = $bizConn['rights'] ?? [];
    $canReply = !empty($rights['can_reply']);

    // Store connection in SQLite
    $st = $db->prepare("INSERT OR REPLACE INTO business_connections (connection_id, user_chat_id, can_reply) VALUES (?, ?, ?)");
    $st->execute([$connId, $userChat, $canReply ? 1 : 0]);
    exit;
}
```

### 💬 2. Answering Messages on Behalf of Business (`business_message`):
```php
$bizMsg = $update['business_message'] ?? null;
if ($bizMsg) {
    $connId = $bizMsg['business_connection_id'];
    $chatId = $bizMsg['chat']['id'];
    $text   = trim($bizMsg['text'] ?? '');

    // Reply seamlessly on behalf of the business account
    bot('sendMessage', [
        'business_connection_id' => $connId,
        'chat_id'                => $chatId,
        'text'                   => "👋 Hello! Thank you for reaching out to our business. How may we assist you today?",
        'parse_mode'             => 'HTML'
    ]);
    exit;
}
```

---

## 20. 🎁 Telegram Star Gifts System (`sendGift`)

Send official Telegram virtual gifts to users or channels directly from your bot's Stars balance.

```php
function send_telegram_gift(int $userId, string $giftId, string $message = '', bool $payUpgrade = false): array {
    return bot('sendGift', [
        'user_id'          => $userId,
        'gift_id'          => $giftId,
        'text'             => $message,
        'pay_for_upgrade'  => $payUpgrade // Bot pays upgrade fee if true
    ]);
}
```

---

## 21. 🏛️ Forum Topics Management (`createForumTopic`, `message_thread_id`)

In supergroups with topics enabled, bots can create, rename, and manage threads, directing communications into dedicated rooms.

### 1. Creating a Forum Topic:
```php
function create_bot_topic(string|int $chatId, string $topicName, string $customEmojiId = ''): array {
    $params = [
        'chat_id' => $chatId,
        'name'    => $topicName
    ];
    if ($customEmojiId !== '') {
        $params['icon_custom_emoji_id'] = $customEmojiId;
    }
    return bot('createForumTopic', $params);
}
```

### 2. Sending Messages Directly to a Topic (`message_thread_id`):
```php
bot('sendMessage', [
    'chat_id'           => $supergroupId,
    'message_thread_id' => $topicId, // Directs message to specific topic
    'text'              => "📢 <b>Support Ticket #492 Opened</b>\nA customer is waiting for assistance.",
    'parse_mode'        => 'HTML'
]);
```

---

## 22. 👥 Chat Join Requests & Auto-Approvals (`approveChatJoinRequest`)

For private channels and VIP groups requiring approval to join, your bot can automatically approve or decline members based on subscription status or payment verification.

```php
$joinReq = $update['chat_join_request'] ?? null;
if ($joinReq) {
    $chatId = $joinReq['chat']['id'];
    $userId = $joinReq['from']['id'];
    $invite = $joinReq['invite_link']['invite_link'] ?? '';

    // Verify condition (e.g. user paid Stars or registered in DB)
    $approved = true;

    if ($approved) {
        bot('approveChatJoinRequest', [
            'chat_id' => $chatId,
            'user_id' => $userId
        ]);

        // Send a private welcome message
        bot('sendMessage', [
            'chat_id'    => $userId,
            'text'       => "🎉 <b>Welcome to the VIP Channel!</b>\nYour membership request has been automatically approved.",
            'parse_mode' => 'HTML'
        ]);
    } else {
        bot('declineChatJoinRequest', [
            'chat_id' => $chatId,
            'user_id' => $userId
        ]);
    }
    exit;
}
```

---

## 23. ⚡ Inline Mode Queries & Instant Results (`answerInlineQuery`)

Allow users to type `@YourBot query` in any private chat, group, or channel to summon interactive results directly.

```php
$inlineQuery = $update['inline_query'] ?? null;
if ($inlineQuery) {
    $queryId = $inlineQuery['id'];
    $query   = trim($inlineQuery['query']);

    $results = [
        [
            'type'        => 'article',
            'id'          => 'result_1',
            'title'       => '🌟 Free Bot Hosting Platform',
            'description' => 'Deploy high-performance PHP Telegram bots in seconds',
            'input_message_content' => [
                'message_text' => "🚀 <b>Free Bot Host</b>\nHost your bots with SQLite, Crons, and Webhooks for free!\nhttps://digibd.store",
                'parse_mode'   => 'HTML'
            ]
        ],
        [
            'type'        => 'article',
            'id'          => 'result_2',
            'title'       => '⭐ Telegram Stars Store',
            'description' => 'Pay with Telegram Stars (XTR)',
            'input_message_content' => [
                'message_text' => "⭐ Check out our official Telegram Stars digital shop!",
                'parse_mode'   => 'HTML'
            ]
        ]
    ];

    bot('answerInlineQuery', [
        'inline_query_id' => $queryId,
        'results'         => json_encode($results),
        'cache_time'      => 300,
        'is_personal'     => true
    ]);
    exit;
}
```

---

## 24. 🎲 Interactive Entertainment: Polls, Quizzes & Animated Dice (`sendDice`, `sendPoll`)

### 1. Animated Physics Dice (`sendDice`):
```php
// Supports: '🎲' (Dice), '🎯' (Darts), '🏀' (Basketball), '⚽' (Football), '🎳' (Bowling), '🎰' (Slot Machine)
bot('sendDice', [
    'chat_id' => $chatId,
    'emoji'   => '🎰'
]);
```

### 2. Quizzes and Polls (`sendPoll`):
```php
bot('sendPoll', [
    'chat_id'               => $chatId,
    'question'              => 'Which currency is used for official Telegram bot payments?',
    'options'               => json_encode(['USD ($)', 'Telegram Stars (XTR)', 'Bitcoin (BTC)']),
    'is_anonymous'          => false,
    'type'                  => 'quiz',
    'correct_option_id'     => 1, // 'Telegram Stars (XTR)'
    'explanation'           => 'Telegram Stars (XTR) is the official in-app currency for digital goods in Telegram bots.',
    'explanation_parse_mode'=> 'HTML'
]);
```

---

## 25. 🛡️ Production Webhook Security & Dropping Pending Updates

### 1. Setting Up Webhook with Secret Token & Clean Slate:
```php
function setup_bot_webhook(string $botToken, string $webhookUrl, string $secretToken): array {
    $url = "https://api.telegram.org/bot{$botToken}/setWebhook";
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode([
            'url'                  => $webhookUrl,
            'secret_token'         => $secretToken, // 1 - 256 characters (a-z, A-Z, 0-9, _, -)
            'drop_pending_updates' => true,         // Ignores stale pending requests on startup
            'allowed_updates'      => [
                'message', 'edited_message', 'callback_query', 'inline_query',
                'pre_checkout_query', 'successful_payment', 'message_reaction',
                'message_reaction_count', 'chat_join_request', 'business_connection',
                'business_message'
            ]
        ]),
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json']
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode((string)$res, true) ?: [];
}
```

### 2. Verifying Secret Token Inside `index.php`:
```php
// Add this at the very top of your index.php for unbreakable webhook verification:
$receivedSecret = $_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] ?? '';
$expectedSecret = $ENV['WEBHOOK_SECRET'] ?? '';

if ($expectedSecret !== '' && !hash_equals($expectedSecret, $receivedSecret)) {
    http_response_code(403);
    exit('Forbidden: Invalid webhook secret token.');
}
```

---

## 26. 🔘 Bot Commands, Scopes & Menu Button (`setMyCommands`, `setChatMenuButton`)

Configure autocomplete slash commands (`/help`, `/settings`) and customize the bottom-left Menu Button to launch your Mini App or show the command sheet.

### 1. Registering Slash Commands with Scopes (`setMyCommands`):
```php
function register_bot_commands(string $languageCode = ''): array {
    return bot('setMyCommands', [
        'commands' => [
            ['command' => 'start',    'description' => '🚀 Launch main interactive menu'],
            ['command' => 'shop',     'description' => '⭐ Browse Telegram Stars marketplace'],
            ['command' => 'wallet',   'description' => '💰 View balance & deposit USDT/Stars'],
            ['command' => 'clear',    'description' => '🧹 Reset conversational AI memory'],
            ['command' => 'support',  'description' => '💬 Open 24/7 VIP help ticket']
        ],
        // Scopes: BotCommandScopeDefault, BotCommandScopeAllPrivateChats, BotCommandScopeAllChatAdministrators
        'scope'         => json_encode(['type' => 'default']),
        'language_code' => $languageCode // Leave blank for global default, or 'en', 'bn'
    ]);
}
```

### 2. Customizing the Bottom-Left Menu Button (`setChatMenuButton`):
Change the menu button to immediately open a Telegram Mini App:
```php
function set_webapp_menu_button(string $chatId, string $webAppUrl): array {
    return bot('setChatMenuButton', [
        'chat_id'     => $chatId,
        'menu_button' => [
            'type'    => 'web_app',
            'text'    => '🚀 Open App',
            'web_app' => ['url' => $webAppUrl]
        ]
    ]);
}
```

---

## 27. 📝 Bot Profile, Descriptions & Multilingual Onboarding (`setMyDescription`, `setMyName`)

Automate how your bot appears across Telegram search results, profile dialogs, and empty chat screens.

```php
// 1. Set Chat Placeholder Description (0 - 512 chars, shown before user taps /start)
bot('setMyDescription', [
    'description'   => "🤖 Welcome to the Official Free Bot Host Assistant!\n\nBuild, host, and scale Telegram bots with integrated SQLite, Cron jobs, Telegram Stars payments, and AI intelligence.",
    'language_code' => ''
]);

// 2. Set Short Description (0 - 120 chars, displayed on bot profile page and shared links)
bot('setMyShortDescription', [
    'short_description' => 'Deploy Telegram bots with SQLite, Stars Pay, and AI.',
    'language_code'     => ''
]);

// 3. Set Bot Name in Title Bar
bot('setMyName', [
    'name'          => 'Smart Bot Studio 🚀',
    'language_code' => ''
]);
```

---

## 28. 👥 Chat Member & Admin Rights Management (`banChatMember`, `restrictChatMember`, `promoteChatMember`)

Automate community moderation, gatekeep channels, and restrict disruptive users.

### 1. Banning / Kicking Members (`banChatMember`):
```php
function ban_user(string|int $chatId, int $userId, int $banDurationSeconds = 0): array {
    return bot('banChatMember', [
        'chat_id'         => $chatId,
        'user_id'         => $userId,
        'until_date'      => $banDurationSeconds > 0 ? time() + $banDurationSeconds : 0, // 0 = permanent
        'revoke_messages' => true // Deletes recent messages from the banned user
    ]);
}

// Unban / un-mute:
bot('unbanChatMember', ['chat_id' => $chatId, 'user_id' => $userId, 'only_if_banned' => true]);
```

### 2. Restricting Permissions (`restrictChatMember` - Muting):
```php
function mute_user(string|int $chatId, int $userId, int $muteSeconds = 3600): array {
    return bot('restrictChatMember', [
        'chat_id'     => $chatId,
        'user_id'     => $userId,
        'until_date'  => time() + $muteSeconds,
        'permissions' => [
            'can_send_messages'         => false,
            'can_send_media_messages'   => false,
            'can_send_polls'            => false,
            'can_send_other_messages'   => false,
            'can_add_web_page_previews' => false
        ]
    ]);
}
```

### 3. Promoting Members & Setting Custom Admin Titles:
```php
bot('promoteChatMember', [
    'chat_id'              => $chatId,
    'user_id'              => $userId,
    'can_manage_chat'      => true,
    'can_delete_messages'  => true,
    'can_invite_users'     => true,
    'can_pin_messages'     => true,
    'can_manage_topics'    => true
]);

// Set Custom Title Badge (e.g. "👑 Co-Founder" or "🛡️ Moderator")
bot('setChatAdministratorCustomTitle', [
    'chat_id'      => $chatId,
    'user_id'      => $userId,
    'custom_title' => '🛡️ Senior Mod'
]);
```

---

## 29. 📌 Chat Settings, Pinned Messages & Batch Deletions (`deleteMessages`, `pinChatMessage`, `copyMessages`)

### 1. Batch Deleting Messages (`deleteMessages`):
Delete up to 100 messages simultaneously in a single API roundtrip:
```php
function batch_delete_messages(string|int $chatId, array $messageIds): array {
    return bot('deleteMessages', [
        'chat_id'     => $chatId,
        'message_ids' => $messageIds // Array of integers [101, 102, 103, ...]
    ]);
}
```

### 2. Batch Copying & Forwarding Messages (`copyMessages`, `forwardMessages`):
Replicate content across chats without forwarding link headers:
```php
bot('copyMessages', [
    'chat_id'      => $destinationChatId,
    'from_chat_id' => $sourceChatId,
    'message_ids'  => [201, 202, 203]
]);
```

### 3. Pinning and Unpinning Messages:
```php
// Pin message silently or with notification
bot('pinChatMessage', [
    'chat_id'              => $chatId,
    'message_id'           => $messageId,
    'disable_notification' => false
]);

// Unpin all messages
bot('unpinAllChatMessages', ['chat_id' => $chatId]);
```

---

## 30. 🚀 Channel Boosts & User Boost Detection (`getUserChatBoosts`, `chat_boost`)

Reward users who boost your Telegram Channel or Supergroup with automatic VIP membership and exclusive perks!

### 1. Checking If a User Boosted Your Channel:
```php
function check_user_boosts(string|int $channelChatId, int $userId): array {
    $res = bot('getUserChatBoosts', [
        'chat_id' => $channelChatId,
        'user_id' => $userId
    ]);

    $boosts = $res['result']['boosts'] ?? [];
    return [
        'is_booster'  => count($boosts) > 0,
        'boost_count' => count($boosts),
        'boosts'      => $boosts
    ];
}
```

### 2. Real-Time Boost Event Handlers:
```php
// User added a boost
$boostEvent = $update['chat_boost'] ?? null;
if ($boostEvent) {
    $chatId = $boostEvent['chat']['id'];
    $user   = $boostEvent['boost']['source']['user'] ?? [];
    $userId = $user['id'] ?? 0;

    // Credit VIP reward in SQLite
    $db->prepare("UPDATE users SET is_vip = 1 WHERE chat_id = ?")->execute([$userId]);
}

// User removed a boost
$removedBoost = $update['removed_chat_boost'] ?? null;
if ($removedBoost) {
    $userId = $removedBoost['source']['user']['id'] ?? 0;
    // Downgrade status if desired
}
```

---

## 31. 🖼️ Media Albums & Groups (`sendMediaGroup`)

Deliver between 2 and 10 photos or videos together in an aesthetically cohesive album grid:

```php
function send_product_album(string|int $chatId, array $photoUrls, string $caption): array {
    $media = [];
    foreach ($photoUrls as $idx => $url) {
        $item = [
            'type'  => 'photo',
            'media' => $url
        ];
        if ($idx === 0) {
            $item['caption']    = $caption;
            $item['parse_mode'] = 'HTML';
        }
        $media[] = $item;
    }

    return bot('sendMediaGroup', [
        'chat_id' => $chatId,
        'media'   => json_encode($media)
    ]);
}

// Example usage:
send_product_album($chatId, [
    'https://images.unsplash.com/photo-1550745165-9bc0b252726f',
    'https://images.unsplash.com/photo-1518770660439-4636190af475'
], "📸 <b>Hardware Showcase Album</b>\nExplore our latest server infrastructure.");
```

---

## 32. 📍 Geolocation, Live Location & Venues (`sendLocation`, `editMessageLiveLocation`)

Build delivery trackers, event guides, and location-based check-ins.

### 1. Static Location Pin:
```php
bot('sendLocation', [
    'chat_id'   => $chatId,
    'latitude'  => 23.8103, // Latitude
    'longitude' => 90.4125  // Longitude
]);
```

### 2. Live Location Sharing (Real-Time Driver / Delivery Tracking):
```php
// Initiate Live Location (updates for up to 24 hours / 86400s)
$liveMsg = bot('sendLocation', [
    'chat_id'     => $chatId,
    'latitude'    => 23.8103,
    'longitude'   => 90.4125,
    'live_period' => 3600 // Active for 1 hour
]);
$msgId = $liveMsg['result']['message_id'] ?? 0;

// Dynamically update coordinates as user moves:
bot('editMessageLiveLocation', [
    'chat_id'    => $chatId,
    'message_id' => $msgId,
    'latitude'   => 23.8150,
    'longitude'  => 90.4200
]);

// Stop live tracking when order delivered:
bot('stopMessageLiveLocation', ['chat_id' => $chatId, 'message_id' => $msgId]);
```

---

## 33. 📱 Contacts, Phone Verification & VCards (`request_contact`, `sendContact`)

Securely verify genuine user identities and cell phone numbers using Telegram's native contact prompt:

```php
// 1. Prompt User to Share Verified Phone Number
$keyboard = [
    'keyboard' => [
        [
            ['text' => '📱 Share Verified Phone Number', 'request_contact' => true]
        ]
    ],
    'resize_keyboard'  => true,
    'one_time_keyboard'=> true
];

bot('sendMessage', [
    'chat_id'      => $chatId,
    'text'         => "🔐 <b>Account Verification Required</b>\nPlease tap the button below to share your verified Telegram phone number:",
    'parse_mode'   => 'HTML',
    'reply_markup' => json_encode($keyboard)
]);

// 2. Intercept Verified Contact in Webhook Handler:
$contact = $update['message']['contact'] ?? null;
if ($contact) {
    $phoneNumber = $contact['phone_number'];
    $userId      = $contact['user_id'];

    // Verify user didn't spoof another person's vCard
    if ((string)$userId === (string)$update['message']['from']['id']) {
        // Save verified number in SQLite
        $db->prepare("UPDATE users SET phone = ?, is_verified = 1 WHERE chat_id = ?")->execute([$phoneNumber, $userId]);
        
        bot('sendMessage', [
            'chat_id'      => $userId,
            'text'         => "✅ <b>Phone Verified!</b>\nNumber: <code>{$phoneNumber}</code>\nYour account is now fully unlocked.",
            'parse_mode'   => 'HTML',
            'reply_markup' => json_encode(['remove_keyboard' => true])
        ]);
    }
}
```

---

## 34. 🎨 Custom Sticker Packs & Stickers (`createNewStickerSet`, `sendSticker`)

Deploy branded sticker collections and send stickers in response to user milestones:

```php
// 1. Send an animated or static sticker
bot('sendSticker', [
    'chat_id' => $chatId,
    'sticker' => 'CAACAgIAAxkBAAE...sticker_file_id'
]);

// 2. Programmatically Create a Bot Sticker Set:
bot('createNewStickerSet', [
    'user_id'        => $ownerUserId,
    'name'           => 'my_bot_pack_by_' . BOT_USERNAME, // Must end in _by_<bot_username>
    'title'          => 'VIP Community Pack',
    'sticker_format' => 'static', // 'static' (PNG/WEBP), 'animated' (TGS), 'video' (WEBM)
    'stickers'       => [
        [
            'sticker'    => 'https://example.com/sticker1.png',
            'emoji_list' => ['🚀', '⭐'],
            'format'     => 'static'
        ]
    ]
]);
```

---

## 35. 🎙️ Voice Notes, Audio & Circular Video Notes (`sendVoice`, `sendVideoNote`, `sendAudio`)

Deliver rich auditory and circular video experiences:

```php
// 1. Send Circular Video Note (Telescope message)
bot('sendVideoNote', [
    'chat_id'    => $chatId,
    'video_note' => 'https://example.com/camera_bubble.mp4',
    'length'     => 360 // Diameter in pixels
]);

// 2. Send Voice Memo with Caption & Waveform
bot('sendVoice', [
    'chat_id'  => $chatId,
    'voice'    => 'https://example.com/audio_memo.ogg',
    'caption'  => '🎙️ <b>Daily Podcast Briefing</b>',
    'parse_mode' => 'HTML',
    'duration' => 45
]);

// 3. Send MP3 Audio File with Artist & Title metadata:
bot('sendAudio', [
    'chat_id'   => $chatId,
    'audio'     => 'https://example.com/track.mp3',
    'performer' => 'Smart Host Audio',
    'title'     => 'Welcome Jingle',
    'duration'  => 120
]);
```



