Простой инфо-бот с многоуровневым меню на InlineKeyboardButton

Привожу простой пример инфо-бота с практически неограниченной вложенностью. Вывод на экран текстового и медиа (картинка, видео, аудио, документ) сообщения. Многоуровневое меню включено.

Хотел привести пример как отобразить в Телеграм многоуровневое меню, но получился простой в создании информационный бот с вложенностью, ограниченной только возможной длинной значения в параметре callback_data inline-кнопки (1-64 bytes).

Еще интересный момент это - в одном боте можно создать неограниченное количество сценариев, для этого достаточно просто стартовать бота по html-ссылке со специальными параметрами. При обычном старте бота - запускается первый сценарий. Об этом чуть ниже.

Настройки

В настройках бота нужно указать токен бота, id админа бота и заполнить массив с информацией о "шагах".

steps 
   |__
   |__
      |__
      |__
      |__
   |__
      |__
         |__
   |__
 

Каждый шаг имеет простой набор параметров:

[
    "name" => "", // string
    "line" => 0, // int
    "type" => "text|photo|video|audio|document", // string
    "text" => "", // string
    "media" => "" // string | null,
    "steps" => [] // array
]
  1. name* - Название шага, будет отображено на кнопке
  2. line* - уровень ряда в наборе кнопок
  3. type*- тип сообщения (text|photo|video|audio|document)
  4. text - текстовое сообщение, обязательно для type="text"
  5. media - ссылка или file_id медиа файла, при type="text" должно быть значение null
  6. steps - это массив вложенных шагов,

---
* - обязательный параметр

Для ускорения отрисовки экранов желательно в параметре media указывать file_id файла, он для каждого бота уникальный, поэтому из моего примера медиа у вас не будут подгружаться - их надо будет заменить.

Чтобы вам получить file_id я добавил небольшой функционал (только если указана настройка bot_admin), нужно просто отправить в бот файл: документ, картинку, видео или аудио файлы.

В ответ бот пришлет строку - она же и будет file_id, просто скопируйте ее и подставьте в параметр media в нужном шаге (массива $steps).


* * *

Что из интересного?

Весь контент бота упакован в массив steps он же $content. Важным моментом является конечно же валидность массива.

При старте бота настроен выбор сценария под индексом 0 массива (можно указать любой).

/**
 1 параметр это индекс элемента массива
 2 параметр это индексы родительских элементов массива steps, разделены тире (-), если null то выводим из верхнего уровня вложенности
 3 параметр это id чата пользователя
*/
$printUpdate(0, null, $chat_id);

Если старт по HTML-ссылке то сценарий будет выбран из параметров ссылки

tg://resolve?domain=iMakeBot&start=s_3_0-1

где, 
domain - это username вашего бота
start - это значение для выбора сценария

Параметр start имеет 3 вложенных параметра разделенных знаком нижнего подчеркивания (_), где
1 подпараметр - это action, он всегда будет s
2 подпараметр - это индекс элемента массива steps
3 подпараметр - это индексы родительских элементов массива steps, разделены тире (-)

3 подпараметр может быть пустым, то есть можно передать только первые 2 подпараметра (s_0 или s_3)

Если разбирать приведенный в ссылке пример параметра start (s_3_0-1) то это будет означать, что на экран по ссылке выведется элемент массива steps 

$content['steps'][0]['steps'][1]['steps'][3];
// в раскрытом виде
$content = [
    'steps' => [
        [
            'name' => 'Название элемента 0',
            // ... 
            'steps' => [
                [
                    'name' => 'Название элемента 0-0'
                    // ...
                ],
                [
                    'name' => 'Название элемента 0-1',
                    // ...
                    'steps' => [
                        [
                            'name' => 'Название элемента 0-1-0'
                            // ...
                        ],
                        [
                            'name' => 'Название элемента 0-1-1'
                            // ...
                        ],
                        [
                            'name' => 'Название элемента 0-1-2'
                            // ...
                        ],
                        [
                            'name' => 'Название элемента 0-1-3'
                            // ... Вот этот элемент будет отработан для вывода на экран
                        ],
                    ]
                ]
            ]
        ]
    ]
]

Чтобы получить из массива нужный элемент, пропускаем запрос через рекурсивную (самовызывающуюся) функцию

/** Получаем контент
 * @param $step_idx
 * @param $parents
 * @param $data
 * @return array
 */
$getContent = function ($step_idx, $parents, $data) use (&$getContent) {
    // определим результат по умолчанию
    $result = null;
    // проверим родительские элементы
    if (!is_null($parents)) {
        // получим первого по списку родителя
        $parent = array_shift($parents);
        // проверим наличие родителя в массиве
        if (isset($data['steps'][$parent])) {
            // проверим путь - если еще остались в списке 
            if (count($parents)) {
                // отправим на рекурсию - подставив новые параметры
                $result = $getContent($step_idx, $parents, $data['steps'][$parent]);
            } else {
                // определим результат
                $result = $data['steps'][$parent]['steps'][$step_idx];
            }
        }
    } else {
        // определим результат
        $result = $data["steps"][$step_idx];
    }
    // вернем результат
    return $result;
};

* * *

Отрисовка экрана

/** Выводим сообщение по запросу
 * @param $step_idx
 * @param $parents
 * @param $chat_id
 * @param null $cbq_id
 * @param null $message_id
 */
$printUpdate = function ($step_idx, $parents, $chat_id, $cbq_id = null, $message_id = null) use ($getContent, $query, $notice, $content) {
    // переопределим вложенность
    $parents = !is_null($parents) ? explode("-", $parents) : null;
    // получаем шаг
    $step = $getContent($step_idx, $parents, $content);
    // проверим
    if (!is_null($step)) {
        // готовим данные
        $data = [
            "chat_id" => $chat_id,
        ];
        // если это нажатие по кнопке то удалим текущее сообщение
        if (!is_null($cbq_id)) {
            // гасим запрос
            $notice($cbq_id);
            // удаляем текущее сообщение
            $query("deleteMessage", array_merge($data, ["message_id" => $message_id]));
        }
        // дополним данные
        $data["parse_mode"] = "html";
        // определим кнопки если они есть
        $buttons = [];
        // проверим
        if (count($step['steps'])) {
            // определим путь
            $parents_ = !is_null($parents) ? implode("-", array_merge($parents, [$step_idx])) : $step_idx;
            // переберем
            foreach ($step['steps'] as $key => $next) {
                // добавим кнопку
                $buttons[$next['line']][] = [
                    "text" => $next['name'],
                    "callback_data" => "s_" . $key . "_" . $parents_
                ];
            }
        }
        // кнопка вернуться
        if (!is_null($parents)) {
            // получим первого
            $parent = array_pop($parents);
            // добавим кнопку последним рядом
            $buttons[count($buttons)][] = [
                "text" => "Вернуться",
                "callback_data" => "s_" . $parent . "_" . implode("-", $parents)
            ];
        }
        // проверим добавление кнопок
        if (count($buttons)) {
            // добавим кнопки
            $data["reply_markup"] = json_encode(['inline_keyboard' => array_values($buttons)]);
        }
        // поддерживаемые типы
        if (!is_null($step['media']) && in_array($step['type'], ['photo', 'video', 'audio', 'document'])) {
            // проверим описание
            if (!empty($step['text'])) {
                // добавим описание
                $data['caption'] = $step['text'];
            }
            // добавим медиа
            $data[$step['type']] = $step['media'];
            // отправим сообщение
            $query("send" . ucfirst($step['type']), $data);
        } elseif ($step['type'] === "text" && !empty($step['text'])) {
            // добавим текст
            $data['text'] = $step['text'];
            // отправим сообщение
            $query("sendMessage", $data);
        } else {
            // выведем ошибку о не поддерживаемом методе
            $query("sendMessage", array_merge($data, ["text" => "Sorry, error 405"]));
        }
    } else {
        // проверим на нажатие кнопки
        if (!is_null($cbq_id)) {
            // выведем уведомление
            $notice($cbq_id, "Error 404 STEP");
        }
    }
};

* * *

Простой роутер для бота

/**
 * Простой роутер бота
 */
if (isset($data->message)) {
    // получим id чата
    $chat_id = $data->message->from->id;
    // если это текстовое сообщение
    if (isset($data->message->text)) {
        // проверим что это старт бота
        if ($data->message->text == "/start") {
            // выводим сообщение
            $printUpdate(0, null, $chat_id);
        }
        // если это старт по ссылке
        elseif (preg_match("~\/start s_([\d]+)_?([\d-]*)~", $data->message->text, $matches)) {
            // выведем сообщение по ссылке
            $printUpdate($matches[1], $matches[2], $chat_id);
        }
    }
    // другие типы сообщений
    else {
        // если это админ бота направляет сообщение
        if ($chat_id === $bot_admin) {
            // по умолчанию
            $file_id = null;
            // если это картинка
            if (isset($data->message->photo)) {
                // file_id последней картикни
                $file_id = end($data->message->photo)->file_id;
            } 
            // если это видео-файл
            elseif (isset($data->message->video)) {
                // file_id видео-файла
                $file_id = $data->message->video->file_id;
            } 
            // если это аудио-файл
            elseif (isset($data->message->audio)) {
                // file_id аудио-файла
                $file_id = $data->message->audio->file_id;
            } 
            // если это документ
            elseif (isset($data->message->document)) {
                // file_id документа
                $file_id = $data->message->document->file_id;
            }
            // проверим необходимость отправки
            if (!is_null($file_id)) {
                // отправим file_id
                $query("sendMessage", [
                    "chat_id" => $chat_id,
                    "text" => $file_id
                ]);
            }
        }
    }
// если это нажатие по кнопке
} elseif (isset($data->callback_query)) {
    // получим id чата
    $chat_id = $data->callback_query->from->id;
    // получим callBackQuery_id
    $cbq_id = $data->callback_query->id;
    // получим переданное значение в кнопке
    $c_data = $data->callback_query->data;
    // спарсим значения
    $params = explode("_", $c_data);
    // если это переход по шагам
    if ($params[0] == "s") {
        // выводим сообщение
        $printUpdate(
            $params[1],
            ($params[2] !== "")
                ? $params[2]
                : null,
            $chat_id,
            $cbq_id,
            $data->callback_query->message->message_id
        );
    }
    // если это другие кнопки
    else {
        // заглушим просто запрос
        $notice($cbq_id, "This is notice for bot");
    }
}

* * *

Исходный код бота

Бот настроен под работу с Webhook 

SimpleBot.zip
3.3
62 комментария
Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте по ссылке или QR бот @iMakeBot, нажмите кнопку Старт/Start.
Следуйте инструкциям бота.

  • ᴏɴᴇ ᴍᴇᴅɪᴀ [2 года назад]

    либо у меня руки кривые либо в архиве что то не хватает

    указал токин поставил вебхук бот не отвечает на старт

  • iMakeBots [2 года назад → ᴏɴᴇ ᴍᴇᴅɪᴀ]

    В архиве должен быть один файл. 

    Посмотрите в логах сервера, были ли запросы от Телеграм. И еще посмотрите getWebHookInfo 

  • 🜲 s.ᴋ. [2 года назад]

    Хороший бот)

    А как в этот код можно добавить кнопку с ссылкой  помимо кнопок для перехода по меню бота 

    Подскажите пожалуйста 😫🙏🙏💓

  • iMakeBots [2 года назад → 🜲 s.ᴋ.]

    Спасибо.

    Достаточно расширить настройки шага, например добавить параметры: 

    [
        // ...
    
        // true в случае если это вложенность
        "callback_data" => false, 
        // null в случае если "callback_data" => true
        "url" => "https://imakebots.ru" 
    
        // ...
    ]

    И в отрисовке экрана исправить:

    // .......
    foreach ($step['steps'] as $key => $next) {
        // наполним кнопку
        $btn_data = [
            "text" => $next['name']
        ];
        // проверим что на кнопке должно быть
        if($next['callback_data']) {
            $btn_data['callback_data'] = "s_" . $key . "_" . $parents_;
        } else {
            $btn_data['url'] = $next['url'];
        }
        // добавим кнопку
        $buttons[$next['line']][] = $btn_data;
    }
    // ......
  • Аккаунт [2 года назад → iMakeBots]

    Здравствуйте! А вы можете в коде бота добавить эти исправления?
    Что то пробую заменить код на ваш, но бот молчит

  • iMakeBots [2 года назад → Аккаунт]
    /**
     * Контент
     */
    $content = [
        "steps" => [
            [
                "name" => "start",
                "line" => 0,
                "type" => "text",
                "text" => "Старт бота!",
                "callback_data" => true,
                "url" => null, 
                "media" => null,
                "steps" => [
                    [
                        "name" => "Действие 1",
                        "line" => 0,
                        "type" => "photo",
                        "text" => "Проверка действия 1",
                	    "callback_data" => true,
                	    "url" => null,
                        "media" => "AgACAgIAAxkBAAIBN2ND243nv5Lnovr5m2QZ1JhihXojAAKNvjEbY-0hSjEnObocgoFPAQADAgADeAADKgQ",
                        "steps" => []
                    ],
                    [
                        "name" => "Проверка ссылки",
                        "line" => 0,
                        "type" => null,
                        "text" => null,
                	    "callback_data" => false,
                	    "url" => "https://imakebots.ru",
                        "media" => null,
                        "steps" => []
                    ],
                ]
            ]
        ]
    ];
    /** Выводим сообщение по запросу
     * @param $step_idx
     * @param $parents
     * @param $chat_id
     * @param null $cbq_id
     * @param null $message_id
     */
    $printUpdate = function ($step_idx, $parents, $chat_id, $cbq_id = null, $message_id = null) use ($getContent, $query, $notice, $content) {
        // переопределим вложенность
        $parents = !is_null($parents) ? explode("-", $parents) : null;
        // получаем шаг
        $step = $getContent($step_idx, $parents, $content);
        // проверим
        if (!is_null($step)) {
            // готовим данные
            $data = [
                "chat_id" => $chat_id,
            ];
            // если это нажатие по кнопке то удалим текущее сообщение
            if (!is_null($cbq_id)) {
                // гасим запрос
                $notice($cbq_id);
                // удаляем сообщение
                $query("deleteMessage", array_merge($data, ["message_id" => $message_id]));
            }
            // дополним данные
            $data["parse_mode"] = "html";
            // определим кнопки если они есть
            $buttons = [];
            // проверим
            if (count($step['steps'])) {
                // определим путь
                $parents_ = !is_null($parents) ? implode("-", array_merge($parents, [$step_idx])) : $step_idx;
                // переберем
                foreach ($step['steps'] as $key => $next) {
                    // наполним кнопку
                    $btn_data = [
                        "text" => $next['name']
                    ];
                    // проверим что на кнопке должно быть
                    if($next['callback_data']) {
                        $btn_data['callback_data'] = "s_" . $key . "_" . $parents_;
                    } else {
                        $btn_data['url'] = $next['url'];
                    }
                    // добавим кнопку
                    $buttons[$next['line']][] = $btn_data;
                }
            }
            // кнопка вернуться
            if (!is_null($parents)) {
                // получим первого
                $parent = array_pop($parents);
                // добавим кнопку последним рядом
                $buttons[count($buttons)][] = [
                    "text" => "Вернуться",
                    "callback_data" => "s_" . $parent . "_" . implode("-", $parents)
                ];
            }
            // проверим добавление кнопок
            if (count($buttons)) {
                // добавим кнопки
                $data["reply_markup"] = json_encode(['inline_keyboard' => array_values($buttons)]);
            }
            // поддерживаемые типы
            if (!is_null($step['media']) && in_array($step['type'], ['photo', 'video', 'audio', 'document'])) {
                // проверим описание
                if (!empty($step['text'])) {
                    $data['caption'] = $step['text'];
                }
                // добавим медиа
                $data[$step['type']] = $step['media'];
                // отправим сообщение
                $query("send" . ucfirst($step['type']), $data);
            } elseif ($step['type'] === "text" && !empty($step['text'])) {
                // добавим текст
                $data['text'] = $step['text'];
                // отправим сообщение
                $query("sendMessage", $data);
            } else {
                // выведем ошибку о не поддерживаемом методе
                $query("sendMessage", array_merge($data, ["text" => "Sorry, error 405"]));
            }
        } else {
            // проверим на нажатие кнопки
            if (!is_null($cbq_id)) {
                // выведем уведомление
                $notice($cbq_id, "Error 404 STEP");
            }
        }
    };
  • Аккаунт [2 года назад → iMakeBots]

    Спасибо большое!
    Один момент ещё, а для чего нужен параметр "text" если у ссылки есть имя "name"?

    [
      "name" => "Действие 1",
      "line" => 0,
      "type" => null,
      "text" => "Проверка ссылки",
      "callback_data" => false,
      "url" => "https://imakebots.ru",
      "media" => null,
      "steps" => []
    ]
  • iMakeBots [2 года назад → Аккаунт]

    Торопился )) не усмотрел и ошибся, хотел вот так:

    [
      "name" => "Проверка ссылки",
      "line" => 0,
      "type" => null,
      "text" => null,
      "callback_data" => false,
      "url" => "https://imakebots.ru",
      "media" => null,
      "steps" => []
    ]
  • Аккаунт [2 года назад → iMakeBots]

    Отлично! Теперь подскажите как в вашем коде ссылки вывести в веб меню, по типу:

    [ 
        'text' => "Поделиться", 
        'switch_inline_query' => "" 
    ]
  • iMakeBots [2 года назад → Аккаунт]

    По тому же принципу как и url, добавляете параметры в настройки, в отрисовке делаете проверку и выводите нужный функционал на экран бота.

  • Аккаунт [2 года назад → iMakeBots]

    Добавил, но что то по ходу накосячил. Можете подправить пожалуйста если что не так?

    [
      "name" => "Проверка ссылки",
      "line" => 0,
      "type" => null,
      "text" => null,
      "callback_data" => false,
      "url" => "https://imakebots.ru",
      "switch_inline_query" => "",
      "media" => null,
      "steps" => []
    ]
    if ( $next[ 'callback_data' ] ) {
      $btn_data[ 'callback_data' ] = "s_" . $key . "_" . $parents_;
    } else {
      $btn_data[ 'url' ] = $next[ 'url' ];
    },
    elseif {
      $btn_data[ 'switch_inline_query' ] = $next[ 'switch_inline_query' ];
    }
  • iMakeBots [2 года назад → Аккаунт]

    Конструкция точно не правильно:

    if() {
    } elseif() {
    } else {
    }
  • Аккаунт [2 года назад → iMakeBots]

    Чёт снова не так:

    // проверим что на кнопке должно быть
    if ( $next[ 'callback_data' ] ) {
      $btn_data[ 'callback_data' ] = "s_" . $key . "_" . $parents_;
    } elseif ( $btn_data[ 'callback_data' ] === "switch_inline_query" ){
      $btn_data[ 'switch_inline_query' ] = $next[ 'switch_inline_query' ];
    } else {
      $btn_data[ 'url' ] = $next[ 'url' ];
    }
  • iMakeBots [2 года назад → Аккаунт]
    elseif ( $btn_data[
    elseif ( $next[
  • Аккаунт [2 года назад → iMakeBots]

    Ничего не поменялось:

    if ( $next[ 'callback_data' ] ) {
      $btn_data[ 'callback_data' ] = "s_" . $key . "_" . $parents_;
    } elseif ( $btn_data[ 'callback_data' ] === "switch_inline_query" ) {
      $btn_data[ 'switch_inline_query' ] = $next[ 'switch_inline_query' ];
    } elseif ( $next[ 'callback_data' ] === "switch_inline_query" ) {
      $btn_data[ 'switch_inline_query' ] = $next[ 'switch_inline_query' ];
    } else {
      $btn_data[ 'url' ] = $next[ 'url' ];
    }
  • iMakeBots [2 года назад → Аккаунт]

    У вас бот переключен в режим inline?

    [
      ...
      "switch_inline_query" => true,
      "switch_inline_query_param" => "switch_inline_query",
      ...
    ]
    if ($next['callback_data']) {
      $btn_data['callback_data'] = "s_" . $key . "_" . $parents_;
    } elseif ($next['switch_inline_query']) {
      $btn_data['switch_inline_query'] = $next['switch_inline_query_param'];
    } else {
      $btn_data['url'] = $next['url'];
    }
  • Аккаунт [2 года назад → iMakeBots]

    Вы сделали кнопку типа поделиться, а мне нужно открыть по ссылке веб меню (webview или как оно там называется)

  • iMakeBots [2 года назад → Аккаунт]

    )) это было ваша просьба прикрутить switch_inline_query, вам необходимо web_app?

  • Аккаунт [2 года назад → iMakeBots]

    Ну я же там сразу написал что нужно вывести в веб меню (web_app)

  • Аккаунт [2 года назад → iMakeBots]

    При нажатии на switch кнопку должна всплывать web_app страница

  • iMakeBots [2 года назад → Аккаунт]

    Что за switch кнопка? 

    web_app можно вывести несколькими способами:

    1. через inline кнопку
    2. через кнопку клавиатуры
    3. через кнопку меню (настройки бота в @BotFather)
    4. через прикрепленную ссылку в меню 

  • Аккаунт [2 года назад → iMakeBots]

    Как здесь: @asmico_attach_bot через inline кнопку

  • Аккаунт [2 года назад → iMakeBots]

    таким образом я могу вывести

    [ 'text' => "Ссылка", 'web_app' => [ 'url' => 'https://link.ru' ] ],

    а как в вашем боте не понял, поэтому и попросил помочь.
    Видимо выше не так указал код

  • iMakeBots [2 года назад → Аккаунт]

    switch_inline_query и web_app - это совершенно разные типы кнопок:

    switch_inline_query - это кнопка позволяет выбрать чат, в который необходимо направить inline запрос для бота с выводом в этот чат answerInlineQuery 

    web_app - это возможность в специальном интерфейсе Телеграм клиента выводить web-ресурс

    Если у вас все таки есть необходимость работы с switch_inline_query то этот пример бота в представленном виде не поддерживает inline запросы

    Если вы имеете в виду web_app - то тут проще:

    [
      ...
      "web_app" => "https://link.ru", // в остальных случаях где не нужно то указывать false
      ...
    ]
    if ($next['callback_data']) {
      $btn_data['callback_data'] = "s_" . $key . "_" . $parents_;
    } elseif ($next['web_app']) {
      $btn_data['web_app'] = ["url" => $next['web_app']];
    } else {
      $btn_data['url'] = $next['url'];
    }
  • EXID [2 года назад]

    Здравствуйте! Для небольшого бота годится.

    А если я к примеру хочу выводить каталог продуктов с сайта, где их количество больше 100?

    В одном файле прописывать запросы не очень как то.

    Что посоветуете?

  • iMakeBots [2 года назад → EXID]

    Здравствуйте, как пример: вы можете подтягивать из бд данные формировать их в json-файл, json-файл подключать - конвертировать в данные массив или сразу формировать массив из данных в бд -  использовать этот бот.

  • EXID [2 года назад → iMakeBots]

    Подскажите как вставить фото и др. файлы с сайта вместо id файлов.

  • iMakeBots [2 года назад → EXID]

    Укажите url файла http….

  • EXID [2 года назад → iMakeBots]

    Спасибо, получилось.

    А какие ограничения на размер файлов, если брать файлы с сервера?

  • iMakeBots [2 года назад → EXID]

    При методе query(), который в примере, то 5 мб для картинок и 20 мб для других типов, если отправлять через multipart/form-data то 10 мб и 50 мб соответственно.

    1. If the file is already stored somewhere on the Telegram servers, you don't need to reupload it: each file object has a file_id field, simply pass this file_id as a parameter instead of uploading. There are no limits for files sent this way.

    2. Provide Telegram with an HTTP URL for the file to be sent. Telegram will download and send the file. 5 MB max size for photos and 20 MB max for other types of content.

    3. Post the file using multipart/form-data in the usual way that files are uploaded via the browser. 10 MB max size for photos, 50 MB for other files.

    https://core.telegram.org/bots/api#inputfile

  • EXID [2 года назад]

    Может ли бот так же как и фото, видео прислать геолокацию с указанной точкой на карте?

  • iMakeBots [2 года назад → EXID]

    Может конечно, в API для этого есть метод sendLocalion(). Нужно также передать ему в качестве обязательных параметров широту и долготу [latitude, longitude].

    } elseif ($step['type'] === "location") {
        // добавим latitude
        $data['latitude'] = $step['latitude'];
        // добавим longitude
        $data['longitude'] = $step['longitude'];
        // отправим сообщение
        $query("sendLocation", $data);
    }
  • EXID [2 года назад → iMakeBots]

    Широту и долготу как передать? Через запятую, в кавычках или как?

  • iMakeBots [2 года назад → EXID]

    Посмотрите я привел пример для этого бота - добавьте это условие в логику.

    И в настройки шага: 

    [
        // ...
    
        "type" => "location", 
        "latitude" => "00.000000",
        "longitude" => "00.000000",
    
        // ...
    ]
  • EXID [2 года назад → iMakeBots]

    Спасибо. Поизучаю

  • Аккаунт [2 года назад]

    Покажите пожалуйста как добавить в данного бота список, что бы при вводе @mybot запрос открывался всплывающий список с массивом данных

  • iMakeBots [2 года назад → Аккаунт]

    1. Нужно у бота включить inline режим
    2. В методе route() добавить инструкцию на проверку inline_query
    3. Создать массив даных для ответа
    4. Настроить логику для вывода ответов

    Не думал, что бот будет настолько популярен)) прикольно. Уже с учетом правок через бот обратной связи и через комментарии в статье - превращаем бота в более универсального)

  • Аккаунт [2 года назад → iMakeBots]

    Всё это хорошо конечно, но на примере действующего кода ориентироваться более понятно, что бы в дальнейшем и в комментах лишний раз не мусорить.
    Сможете помочь работающим примером?

  • iMakeBots [2 года назад → Аккаунт]

    Лучше запланировать тогда вторую статью с учетом всех пожеланий )

  • Аккаунт [2 года назад → iMakeBots]

    Ну или так. Давайте тогда вторую статью, но только что бы вся логика этого бота сохранилась. Когда сможете?

  • iMakeBots [2 года назад → Аккаунт]

    В план поставил, но по срокам и формату не смогу сориентировать.

    Есть мысли дополнить формат подачи информации на сайте. Над этим сейчас работаю.

  • Аккаунт [2 года назад → iMakeBots]

    Вы пробовали отправлять скрытый текст?

    Посмотрел по коду, там координаты задаются то есть: Номер символа считая от самого начала и количество символов в слове. Всё это оборачивается в единый блок. Сможете пример написать?

    "text": "\u042d\u0442\u043e \u0441\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f",
            "entities": [
                {
                    "offset": 4,
                    "length": 7,
                    "type": "spoiler"
                },
                {
                    "offset": 18,
                    "length": 9,
                    "type": "spoiler"
                }
            ]
  • iMakeBots [2 года назад → Аккаунт]

    Попробуйте использовать html разметку

    [
      // ...
      "text" => "<tg-spoiler>Скрытый текст</tg-spoiler>"
      // ...
    ]
  • Аккаунт [2 года назад → iMakeBots]

    Вот блин, оказывается ещё проще! Спасибо!

  • Аккаунт [2 года назад → iMakeBots]

    Приветствую! Когда сделаете продолжение функционала данного бота с вышеописанными хотелками?

    Странная подача информации. Публикации в вашем телеграм канале появляются через месяц после публикации на сайте. Почему не в одно и тоже время? По одной статье в месяц?

  • iMakeBots [2 года назад → Аккаунт]

    Добрый. Сейчас занят - пишу игру.

    Когда было время написал сразу много статей. Выложил чтобы индексировались. В канал публикую с переодичностью, чтобы не спамить людей уведомлениями. 

  • Аккаунт [2 года назад]

    Подскажите пожалуйста как вывести Имя пользователя, да и вообще информацию о нём

  • iMakeBots [2 года назад → Аккаунт]
  • Аккаунт [2 года назад → iMakeBots]

    Код по вашей ссылке весь просто добавить в текущего бота или что то править надо? Потому что есть одинаковые строки с некоторыми изменениями.

  • iMakeBots [2 года назад → Аккаунт]

    Нужно посмотреть - понять как и что делается, и применить в том месте где вам необходимо.

    Вы заранее определяете какие алиасы бы будете использовать для подмены значений. Создаете например массив, где ключ это алиас - значение это необходимый вам текст для замены.

    В настройках шага вы в тексте подставляете нужный вам алиас.

    В отрисовке делаете подмену, так как вы не знаете что и когда (в отрисовке) нужно будет подставлять - прогоняйте весь массив алиасов. Обнаруженный заменится.

    Примеры (не тестировал)

    // значения динамически подставите например через функцию
    function getAliases($data) {
      return [
        "first_name" => $data->message->from->first_name,
        "last_name" => $data->message->from->last_name
      ];
    }
    
    // примерная функция подмены
    function replace_text($text, $data) {
      foreach(getAliases($data) as $key => $alias) {
        $text = str_replace("{%".$key."%}", $alias, $text);
      }
      return $text;
    }
  • Аккаунт [1 год назад]

    Здравствуйте! Уже 2023 год. Вы Обещали продолжение развития данной темы.

  • iMakeBots [1 год назад → Аккаунт]

    Доброе утро. В плане обещанное, по срокам не подскажу. 

  • [1 год назад]

    Здравствуйте, прежде всего - Спасибо Вам. 
    Не могли бы Вы подсказать, как можно в этот скрипт интегрировать один из Ваших предыдущих, а именно: Делаем бот для обратной связи в Telegram (imakebots.ru)
    Типа обратная связь из бота в этой статье, по кнопке или команде - без разницы. 
    Спасибо! 

  • Vor Vor [1 год назад]

    Здравствуйте я не понял как запустить бота вроде ссылку поменял как надо ну  наверное, помогите пожалуйста с запуском.

  • Аккаунт [1 год назад]

    Здравствуйте! Год прошёл, но тема так и не получила развития...
    Может уже допишете бота что бы он стал более функциональным?

  • iMakeBots [1 год назад → Аккаунт]

    Здравствуйте! Как у вас успехи? Сделали форк бота? Или ждете готовых решений? ))

    Есть планы на продолжение, но это надо чтобы было желание им заниматься, пока желания нет. 

  • Аккаунт [1 год назад → iMakeBots]

    Бота сделал, но с интеграцией в CMS возникли сложности. Почему то не хочет запрос выводиться в блоке PHP кода, а мне именно запросы там и нужны были для создания массива. Пока разбираюсь.

  • Аккаунт [1 год назад → iMakeBots]

    Подскажите пожалуйста где ошибка? Почему то на этом месте бот замолчал, надо что бы грузился файл:

    [
    "name" => "Документ",
    "line" => 0,
    "type" => "document",
    "text" => "Подпись документа",
    "callback_data" => true,
    "url" => null,
    "media" => "https://site.ru/uploads/prices/price.xlsx",
    "steps" => []
    ]
  • Аккаунт [1 год назад → iMakeBots]

    Здравствуйте! Посмотрите в чём дело? Почему то по ссылке не выдаёт файл. Файл весит около 1мб где то. Если скормить файл боту и вставить его id то работает.

  • iMakeBots [1 год назад → Аккаунт]

    Смотрели какой возвращается ответ при запросе?

  • Аккаунт [1 год назад → iMakeBots]

    никакого ответа

  • iMakeBots [1 год назад → Аккаунт]

    Если ответа никакого нет, тогда запрос до Телеграм не доходит - зависает. Телеграм всегда отвечает на запрос, даже если он долгий. 

    Запишите то что вернет запрос $query() в файл