Простой инфо-бот с многоуровневым меню на 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
52 комментария
Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте бот @iMakeBot, нажмите кнопку Старт/Start. Следуйте инструкциям бота.

  • ᴏɴᴇ ᴍᴇᴅɪᴀ [3 месяца назад]

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

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

  • iMakeBots [3 месяца назад → ᴏɴᴇ ᴍᴇᴅɪᴀ]

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

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

  • S.К [3 месяца назад]

    Хороший бот)

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

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

  • iMakeBots [3 месяца назад → 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 [3 месяца назад]

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

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

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

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

  • iMakeBots [3 месяца назад → EXID]

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

  • EXID [3 месяца назад → iMakeBots]

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

  • iMakeBots [3 месяца назад → EXID]

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

  • EXID [3 месяца назад → iMakeBots]

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

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

  • iMakeBots [3 месяца назад → 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 [3 месяца назад]

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

  • iMakeBots [3 месяца назад → EXID]

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

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

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

  • iMakeBots [3 месяца назад → EXID]

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

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

    [
        // ...
    
        "type" => "location", 
        "latitude" => "00.000000",
        "longitude" => "00.000000",
    
        // ...
    ]
  • EXID [3 месяца назад → 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;
    }
  • Аккаунт [3 недели назад]

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

  • iMakeBots [3 недели назад → Аккаунт]

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