JavaRush /Java блог /Random /Telegram-бот в качестве первого проекта и его значимость ...
Pavel Mironov (Miroha)
16 уровень
Москва

Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте

Статья из группы Random
Приветствую всех! Расскажу немного о себе. Мне 24 года, в прошлом году закончил технический ВУЗ и до сих пор не имею опыта работы. Забегая вперед хочу сказать, что изначально в заложенном плане (составленном осенью 2019 года) планировал выход на работу в марте-апреле 2020, но, к сожалению, вмешался карантин, поэтому отложил всё до середины лета и в будущем надеюсь написать свою историю успеха. Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте - 1К программированию меня никогда не тянуло. В университете преподавали программирования достаточно, но вот заинтересовать меня это ремесло тогда не смогло. Были и процедурные языки (C), годичный курс по ООП (Java), базы данных, даже ассемблер и C++. Да чего таить, к учебе в целом я был равнодушен, так как большинство преподаваемых дисциплин казались мне бесполезными, годившимися только для отчетной ведомости (в принципе это так и есть). После окончания ВУЗа необходимо было решаться: каких-то навыков я не приобрел, а работать надо. Пришлось задуматься о самообразовании (ох, как минимум 2 полноценных года я уже упустил, сидев сложа руки) и выбор сам собой пал на Java, так как на курсе ООП в университете кто-то из ребят посоветовал курс javarush, а он, как вы знаете, посвящен именно языку Java. Заинтересовала подача курса. Да, я не любил тогда программировать, так как сразу это дело бросал, когда встречал какую-то сложность, а сложностей в программировании хоть отбавляй. Но в то же время я чувствовал, что хочу писать код, поэтому в конце концов я и решил связать себя с программированием. Вкратце расскажу и про мой опыт на javarush. Начал я в августе 2019, сразу купил подписку на месяц, но на 7 уровне понял, что задачи даются тяжело. Отложил курс, взял в руки Шилдта. Так параллельно и проходил курс в течение 3 месяцев. Дошел до 20 уровня (это мой второй аккаунт), почти полностью прочитал Шилдта, потом устал от здешних задач, в которых я перестал видеть практическую пользу для себя. Заходил на codewars, leetcode, начал смотреть видеокурсы. К слову, за 3 месяца я прошел путь от "О нет, что такое массив? Как с ним работать и почему так страшно"? до детального изучения исходного кода классов коллекций (ArrayList, HashMap и т.д.). Основываясь на личном опыте, новичкам скажу: здесь главное побороть такое чувство, которое возникает, если ничего не понимаешь и не можешь ничего решить. Когда оно возникает, просто хочется всё бросить и кажется, что ты слишком тупой для этого дела. Если перебарывать в себе такие моменты и морально отдыхать, то успех придет. Я думаю, что многие не справляются с этим, поэтому быстро бросают подобные начинания. В итоге, в декабре 2019 задумался о своём проекте. Решил выбрать Telegram-бота, но идеи не было. В это же самое время одному знакомому понадобился функционал для своей группы в телеграмме, который он хотел бы автоматизировать. Он как раз был в курсе, что я углубленно изучаю программирование и предложил мне проект. Мне для опыта и будущего резюме, ему - для развития группы. Я даже позволю себе процитировать его идею: "Недавно софтину хотел у программиста заказать, которая загружала бы в выбранное Облако файлы по прямым ссылкам. Это интересно, так как аналогов нет. И просто очень удобно. Суть: копируешь ссылку, вставляешь в окно и выбираешь нужное Облако (GDrive, Mail, Яндекс Диск и т.п), в своё время софт всё делает на стороне сервера и юзеру ничего не нужно загружать на свою машину (особенно круто, когда у тебя сборка на SSD-накопителях). Думали сделать в web-интерфейсе, чтобы можно было запускать как с телефонов, так и с десктопа... Можно в принципе через приложение реализовать, а не через web-интерфейс. Тебе такое по силам?" Я начал было работать, но в итоге через пару дней понял, что у нас ничего не получится, во многом из-за нехватки знаний. Знакомому нужны были эти самые ссылки на Облако.Mail, а у них до сих пор нет API. Была попытка что-то склепать через GDrive, но реализация хромала, плюс данный облачный сервис не устраивал "заказчика". Хотя изначально он предлагал несколько облаков на выбор, но в итоге отверг всё кроме mail.ru, решения которому так и не нашлось. Да и как-то это накладно всё выходило, нужно было подключать БД, использовать сервер для хранения и т.д. К слову, ему по-прежнему нужно это веб-приложение. Так как у нас не срослось, я решил сделать информационного бота. Он должен был получать ссылки на игру из магазина Google Play, парсить ссылку и сохранять полученную информацию в библиотеку, а затем писать её в json файл. Тем самым при каждом запросе библиотека может расширяться благодаря усилиям пользователей. В дальнейшем получить информацию об игре в удобном виде можно не заходя в Google Play. Вы просто пишите команду /library Тут_название_игры и получаете всё, что нужно. Но есть несколько трудностей, о которых еще расскажу. По началу продвигался медленно, так как параллельно начал проходить два курса по SQL. Банально не мог понять, как вообще работает бот, и как обрабатывать запросы. Встретил товарища, которому тоже было интересно поработать над проектом. Первый вариант бота был готов примерно через месяц, но с товарищем возникли разногласия (с моей стороны). Я занялся частью бота, которая отвечает за парсинг, а он непосредственно работал над запросами к боту и их обработкой. Он зачем-то стал усложнять бота, вводить какие-то авторизации, придумывать админов, добавлять ненужную функциональность, плюс мне не совсем нравился его стиль написания кода. На мой взгляд, это было не нужно в информационном боте. Так я принял решение, что напишу бота с нуля сам с нужным мне функционалом. Теперь расскажу, что собственно делает бот (с примера из кода проекта). Полный код проекта приложу в конце статьи и, к сожалению, полностью прокомментировать его физически не смогу. Любое сообщение пользователя, отправленное боту, - это объект класса Update. Он содержит в себе много информации (id сообщения, id чата, уникальный id юзера и т.д.). Есть несколько типов update: это может быть текстовое сообщение, это может быть ответ от telegram-клавиатуры (callback), фотография, аудио и т.д. Чтобы пользователь особо не баловался, я обрабатываю только текстовые запросы и callback'и от клавиатуры. Если пользователь отправит фотографию, бот его уведомит о том, что делать с ней он ничего не намерен. В главном классе бота, в методе onUpdateReceived бот получает апдейт.

@Override
    public void onUpdateReceived(Update update) {
        UpdatesReceiver.handleUpdates(update);
    }
который я передаю обработчику (собственный класс UpdatesReceiver):

public static void handleUpdates(Update update) {
        ...
        if (update.hasMessage() && update.getMessage().hasText()){
            log.info("[Update (id {}) типа \"Текстовое сообщение\"]", update.getUpdateId());
            new TextMessageHandler(update, replyGenerator).handleTextMessage();
        }
        else if (update.hasCallbackQuery()) {
            //логгирование
            new CallbackQueryHandler(update, replyGenerator).handleCallBackQuery();
        }
        else {
           //логгирование
            replyGenerator.sendTextMessage(update.getMessage().getChatId(), "Я могу принимать только текстовые сообщения!");
        }
    }
UpdatesReceiver - это центральный обработчик, который в зависимости от типа апдейта передает управление в другой специализированный обработчик: TextMessageHandler или CallbackQueryHandler, в конструкторы которым я дальше по цепочке передаю update. Update - это самое важное при работе с ботом и его нельзя терять, так как с помощью информации, хранящейся в апдейте, мы узнаем какому юзеру и в какой чат необходимо отсылать ответ. Для генерирования ответов пользователю написал отдельный класс. Он может отправлять обычное текстовое сообщение, сообщение с inline клавиатурой, сообщение с картинкой и сообщение с reply клавиатурой. Inline-клавиатура выглядит так: Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте - 1Она задает кнопки, нажав на которые, пользователь отправляет callback'и серверу, которые можно обрабатывать почти таким же образом, что и обычные сообщения. Для её "поддержания" нужен свой обработчик. Мы задаем для каждой кнопки некое действие, которое затем записывается в объект Update. Т.е. для кнопки "Стоимость" мы задали описание "/price" для callback'а, которое в дальнейшем мы можем получить из апдейта. Далее в отдельном классе, я уже могу обработать данный callback:

public void handleCallBackQuery() {
  String call_data = update.getCallbackQuery().getData();
  long message_id = update.getCallbackQuery().getMessage().getMessageId();
  long chat_id = update.getCallbackQuery().getMessage().getChatId();
    switch (call_date){
      case "/price" :
        //тут что-то сделать
        break;
...
Reply-клавиатура выглядит так: Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте - 2И по сути она заменяет пользователю набор текста. Нажав на кнопку "Библиотека", вы быстро отправите сообщение "Библиотека" боту. Для каждого типа клавиатуры я написал свой класс, реализовав паттерн "Строитель" (Builder): inline и reply. В итоге, можно по сути "нарисовать" нужную клавиатуру в зависимости от требований. Это жутко удобно, так как клавиатуры могут быть разными, а принцип остается тем же. Вот интуитивно понятный метод для отправки сообщения с inline-клавиатурой:

public synchronized void sendInlineKeyboardMessage(long chat_id, String gameTitle) {
        SendMessage keyboard = InlineKeyboardMarkupBuilder.create(chat_id)
                .setText("Вы может узнать следующую информацию об игре " + gameTitle)
                .row()
                .button("Стоимость " + "\uD83D\uDCB0", "/price " + gameTitle)
                .button("Обновлено " + "\uD83D\uDDD3", "/updated " + gameTitle)
                .button("Версия " + "\uD83D\uDEE0", "/version " + gameTitle)
                .endRow()
                .row()
                .button("Требования " + "\uD83D\uDCF5", "/requirements " + gameTitle)
                .button("Покупки " + "\uD83D\uDED2", "/iap " + gameTitle)
                .button("Размер " + "\uD83D\uDD0E", "/size " + gameTitle)
                .endRow()
                .row()
                .button("Получить всю информацию об игре" + "\uD83D\uDD79", "/all " + gameTitle)
                .endRow()
                .row()
                .button("Скрыть клавиатуру", "close")
                .endRow()
                .build();
        try {
            execute(keyboard);
        } catch (TelegramApiException e) {
            log.error("[Не удалось отправить сообщение с -inline- клавиатурой]: {}", e.getMessage());
        }
    }
Для придания боту строгого функционала, были придуманы специальные команды через символ слэша: /library, /help, /game и т.д. Иначе пришлось бы обрабатывать всякий мусор, который мог написать пользователь. Собственно, для этого был написан MessageHandler:

if (message.equals(ChatCommands.START.getDescription())) {
     replyGenerator.sendTextMessage(chat_id, new StartMessageHandler().reply());
     replyGenerator.sendReplyKeyboardMessage(chat_id);
}
else if (message.equals(ChatCommands.HELP.getDescription())
             || message.equalsIgnoreCase("Помощь")) {
      replyGenerator.sendTextMessage(chat_id, new HelpMessageHandler().reply());
}
 ...
Таким образом, в зависимости от того, какую команду вы отправите боту, в работу будет включаться специальный обработчик. Идем далее и рассмотрим работу парсера и библиотеки. Если отправить боту ссылку на игру в магазине Google Play, то автоматически сработает специальный handler. В ответ пользователь получит информацию об игре в следующем виде: Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте - 3Вместе с этим, будет вызван метод, который попробует добавить игру в библиотеку бота (сначала в локальную мапу, затем в -> json файл). Если игра уже есть в библиотеке, то будет осуществлена проверка (как в обычной хешмапе), и если данные полей (например, номер версии изменился), то игра в библиотеке будет перезаписана. Если же изменений не будет обнаружено, то никаких записей осуществляться не будет. Если игры в библиотеке вообще не было, то она сначала записывается в локальную мапу (объект вида тык), а затем пишется в json файл, так как при непредвиденном закрытии приложения на сервере данные будут утеряны, а с помощью файла их всегда можно будет прочитать. Собственно, библиотека при старте программы всегда в первый раз загружается из файла из static блока:

static {
        TypeFactory typeFactory = mapper.getTypeFactory();
        MapType mapType = typeFactory.constructMapType(ConcurrentSkipListMap.class, String.class, GooglePlayGame.class);

        try {
            Path path = Paths.get(LIBRARY_PATH);
            if (!Files.exists(path)) {
                Files.createDirectories(path.getParent());
                Files.createFile(path);
                log.info("[Файл библиотеки создан]");
            }
            else {
                ConcurrentMap<string, googleplaygame=""> temporary = mapper.readValue(new File(LIBRARY_PATH), mapType);
                games.putAll(temporary);
                log.info("[Количество игр в загруженной библиотеке] = " + games.size());
            }
        }
        catch (IOException e) {
            log.error("[Ошибка при чтении/записи файла] {}", e.getMessage());
        }
    }
Тут дополнительно приходится читать данные из файла во временную мапу, которую потом "копировать" в полноценную, дабы сохранить нечувствительность к регистру при поиске игры в файле (написав tITan QuEST, бот все равно найдет игру Titan Quest в библиотеке). Другого решения найти не удалось, таковы особенности десериализации с использованием Jackson. Итак, при каждом запросе по ссылке игра по возможности добавляется в библиотеку, и библиотека тем самым расширяется. Далее информацию о конкретной игре можно достать по команде /library Название_Игры. Можно узнать как определенный параметр (например, текущую версию), так и все параметры сразу. Это реализовано с помощью inline-клавиатуры, которая была рассмотрена ранее. В ходе работы применял и навыки, полученные здесь в ходе решения задач. Например, список названий случайных игр, находящихся в библиотеке (опция доступна по команде /library):

private String getRandomTitles(){
        if (LibraryService.getLibrary().size() < 10){
            return String.join("\n", LibraryService.getLibrary().keySet());
        }
        List<string> keys = new ArrayList<>(LibraryService.getLibrary().keySet());
        Collections.shuffle(keys);
        List<string> randomKeys = keys.subList(0, 10);
        return String.join("\n", randomKeys);
    }

Как бот обрабатывает ссылки? Он проверяет их на принадлежность к Google Play (хост, протокол, порт):

private static class GooglePlayCorrectURL {

        private static final String VALID_HOST = "play.google.com";

        private static final String VALID_PROTOCOL = "https";

        private static final int VALID_PORT = -1;

        private static boolean isLinkValid(URI link) {
            return (isHostExist(link) && isProtocolExist(link) && link.getPort() == VALID_PORT);
        }

        private static boolean isProtocolExist(URI link) {
            if (link.getScheme() != null) {
                return link.getScheme().equals(VALID_PROTOCOL);
            }
            else {
                return false;
            }
        }

        private static boolean isHostExist(URI link) {
            if (link.getHost() != null) {
                return link.getHost().equals(VALID_HOST);
            }
            else {
                return false;
            }
        }
Если всё в порядке, то бот подключается по ссылке с помощью библиотеки Jsoup, которая позволяет достать HTML-код странички, подлежащий дальнейшему анализу и парсингу. Обмануть бота неправильной или вредной ссылкой не получится.

if (GooglePlayCorrectURL.isLinkValid(link)){
     if (!link.getPath().contains("apps")){
         throw new InvalidGooglePlayLinkException("К сожалению, бот работает исключительно с играми. Введите другую ссылку.");
     }
     URL = forceToRusLocalization(URL);
     document = Jsoup.connect(URL).get();
 }
     else {
         throw new NotGooglePlayLinkException();
      }
...
Здесь пришлось решать проблему с региональными настройками. Бот подключается к магазину Google Play из сервера, который находится в Европе, поэтому и страничка в магазине Google Play открывается на соответствующем языке. Пришлось писать костыль, который принудительно осуществляет "редирект" на российскую версию странички (проект все-таки нацелен был на нашу аудиторию). Для этого в конце ссылки нужно аккуратно дописать в GET запросе к серверу Google Play параметр hl: &hl=ru.

private String forceToRusLocalization(String URL) {
        if (URL.endsWith("&hl=ru")){
            return URL;
        }
        else {
            if (URL.contains("&hl=")){
                URL = URL.replace(
                        URL.substring(URL.length()-"&hl=ru".length()), "&hl=ru");
            }
            else {
                URL += "&hl=ru";
            }
        }
        return URL;
    }
После удачного подключения мы получаем HTML-документ, готовый для анализа и парсинга, но это уже выходит за рамки этой статьи. Код парсера тут. Собственно парсер достает нужную информацию и создает объект с игрой, который в дальнейшем в случае необходимости добавляется в библиотеку. <h2>Подытожу</h2>Бот поддерживает несколько команд, в которых заложена определенная функциональность. Он получает сообщение от пользователя и сопоставляет их со своими командами. Если это ссылка или команда /game + ссылка, он проверяет эту ссылку на принадлежность к Google Play. Если ссылка корректная, он осуществляет подключение посредством Jsoup и получает HTML-документ. Данный документ анализируется на основе написанного парсера. Из документа вытаскивается нужная информация об игре, и далее объект с игрой заполняется этими данными. Далее объект с игрой помещается в локальное хранилище (если игры там еще нет) и тут же записывается в файл для избежания потерь данных. Записанную в библиотеку игру (название игры - ключ для мапы, объект с игрой - значение для мапы), можно получить по команде /library Название_игры. Если указанная игра будет найдена в библиотеке бота, то пользователю вернется inline-клавиатура, с помощью которой он может получить информацию об игре. Если игры найдено не будет, необходимо либо убедиться в правильности написания названия (оно должно целиком соответствовать названию игры в магазине Google Play за исключением регистра), либо добавить игру в библиотеку, отправив боту ссылку на игру. Деплой бота я осуществлял на heroku и для тех, кто в будущем планирует написать своего бота и разместить его бесплатно на heroku, дам парочку рекомендаций для решения трудностей, с которыми вы можете столкнуться (т.к. с ними я столкнулся сам). К сожалению, из-за особенностей heroku, библиотека бота постоянно "обнуляется" раз в 24 часа. Мой тариф не поддерживает хранение файлов на серверах heroku, поэтому он просто подтягивает мой файл с играми с гитхаба. Решений было несколько: использовать БД, либо искать другой сервер, который хранил бы этот файл с игрой. Я пока решил ничего не предпринимать, так как по сути бот не такой уж и полезный. Он мне был необходим скорее для получения полноценного опыта, чего я в принципе и добился. Итак, рекомендации по heroku:
  1. Регистрироваться на heroku скорее всего придется с помощью VPN, если вы живете в России.

  2. В корень проекта необходимо положить файл без расширения под названием Procfile. Его содержимое должно быть таким: https://github.com/miroha/Telegram-Bot/blob/master/Procfile

  3. В pom.xml добавить следующие строчки по образцу, где в теге mainClass указать путь к классу, который содержит main метод: bot.BotApplication (если класс BotApplication лежит в папке bot).

  4. Не осуществлять каких-то сборок проекта с помощью команд mvn package и т.д., heroku все соберет за вас сам.

  5. Желательно добавить в проект gitignore, например такой:

    
    # Log file
    *.log
    
    # Compiled resources
    target
    
    # Tests
    test
    
    # IDEA files
    .idea
    *.iml
    
  6. Собственно загрузить проект на github, а далее подключить репозиторий в heroku (либо используйте другие способы, там их 3, если не ошибаюсь).

  7. Если загрузка прошла успешно ("Build succeeded"), обязательно зайдите в Configure Dynos:

    Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте - 4

    и переключите ползунок, а затем убедитесь, что он в положении ON (из-за того, что я это не сделал, мой бот не работал и я пару дней ломал голову и сделал очень много лишних телодвижений).

  8. Прячьте токен бота на гитхабе. Для этого необходимо получать токен из переменной окружения:

    
    public class Bot extends TelegramLongPollingBot {
    
        private static final String BOT_TOKEN = System.getenv("TOKEN");
    
        @Override
        public String getBotToken() {
            return BOT_TOKEN;
        }
    ...
    }
    

    А затем после деплоя бота, задать эту переменную в dashboard'e heroku во вкладке Settings (справа от TOKEN будет поле VALUE, туда и копируйте токен вашего бота):

    Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте - 5
Итого, за 2 месяца работы над собственным проектом я:
  • получил полностью рабочий проект, написанный на Java;
  • научился работать со сторонним API (Telegram Bot API);
  • на практике углубился в сериализацию, много поработал с JSON и библиотекой Jackson (изначально использовал GSON, но с ней были проблемы);
  • укрепил свои навыки при работе с файлами, познакомился с Java NIO;
  • научился работать с конфигурационными .xml файлами и приучил себя к логгированию;
  • улучшил владение средой разработки (IDEA);
  • научился работать с git и познал ценность gitignore;
  • получил навыки в парсинге веб-страничек (библиотека Jsoup);
  • изучил и использовал несколько паттернов проектирования;
  • развил в себе чувство и желание улучшать код (рефакторинг);
  • научился находить решения в сети и не стесняться задавать вопросы, на которые не удалось найти ответа.
Telegram-бот в качестве первого проекта и его значимость для профессионального роста на личном опыте - 7Я не знаю, насколько полезным или бесполезным получился бот, насколько красивый/некрасивый код, но опыт, который я получил, определенно того стоил. У меня возникло чувство ответственности за свой проект. Его то и дело хочется улучшать, добавлять что-то новое. Когда я смог его запустить и убедиться в том, что всё работает так, как я и хотел, я испытал настоящий кайф. Разве это не главное? Получать удовольствие от того, чем ты занимаешься и радоваться каждой работающей строчке кода, как последней шоколадке. Поэтому если вы осваиваете программирование, то мой вам совет: не засиживайтесь здесь до 40 уровня, а приступайте к собственному проекту как можно раньше. Если кому интересно, исходный код проекта находится тут (переписан под Spring): https://github.com/miroha/GooglePlayGames-TelegramBot Последние месяца два я почти не изучаю новый материал, так как мне кажется достиг тупика. Без работы уже не вижу куда развиваться, разве что учить Spring Framework, чем я и планирую заняться в ближайший месяц. А потом попробую "переписать" бота с использованием этого фреймворка. Готов ответить на любые вопросы. :) Всем успехов! UPDATE от 07.07.2020 Репозиторий с ботом на чистой Java был утерян (я его удалял, копия осталась на другой локальной машине), но загрузил переписанного бота под Spring Boot: https://github.com/miroha/GooglePlayGames-TelegramBot
Комментарии (46)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Dencik1337 Уровень 20
21 октября 2020
А что именно возвращает callbackdata? также как и Reply кнопка отправляет сообщение боту, только скрытое от пользователя? Например у меня есть обработка конкретного сообщения , что нужно указать в SetCallBackData чтобы включился обработчик моего сообщения ?
ak Уровень 22
16 сентября 2020
P.S. код кривой, но пока не до этого. Хочу сначала разобраться в логике работы бота
ak Уровень 22
16 сентября 2020
это метод для кнопки "Пол" public static SendMessage sendInlineKeyBoardGender(long charId){ InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup(); List<InlineKeyboardButton> keyboardButtonsRow1 = new ArrayList<>(); keyboardButtonsRow1.add(new InlineKeyboardButton().setText("М"). setCallbackData("1")); keyboardButtonsRow1.add(new InlineKeyboardButton().setText("Ж"). setCallbackData("2")); List<List<InlineKeyboardButton>> rowList = new ArrayList<>(); rowList.add(keyboardButtonsRow1); inlineKeyboardMarkup.setKeyboard(rowList); return new SendMessage().setChatId(charId).setText("Выберите пол"). setReplyMarkup(inlineKeyboardMarkup); }
ak Уровень 22
16 сентября 2020
это метод с update public void onUpdateReceived(Update update) { Message message = update.getMessage(); if(message != null && message.hasText()){ switch (message.getText()){ case "привет": sendMsg(message, "Привет! Меня зовут бот Вася. Чем могу помочь?"); break; case "Помощь": sendMsg(message, "Привет! Я примитивный бот Вася, умеющий две вещи:" + " шерстить базу и принимать анкеты."+ "\n"+ " Можно найти человека по виду деятельности, хобби, по полу и возрасту." + '\n' +'\n' + "Чтобы начать поиск, нажмите кнопку ПОИСК." +'\n' + "Чтобы внести свои данные в базу, нажмите кнопку АНКЕТА"); break; case "Поиск": sendMsg(message, "Что будем искать?"); try { execute(sendInlineKeyBoardMessage(update.getMessage().getChatId())); } catch (TelegramApiException e) { e.printStackTrace(); } break; case "Пол": sendMsg(message, "Пол, пол..."); try { execute(sendInlineKeyBoardGender(update.getMessage().getChatId())); } catch (TelegramApiException e) { e.printStackTrace(); } break; case "Анкета": sendMsg(message, "Напишите о себе..."); break; default: } }
ak Уровень 22
15 сентября 2020
Вопрос про клавиатуру которая не появляется пока не напишу хотя бы одно слово из swich. Почему? Я сделал базовую раскладку клавиатуры в три кнопки: Помощь, Настройки, Поиск. Когда захожу первый раз к боту есть кнопка "Запустить" (это не моя кнопка, она от API). Нажимаю запустить и все. Тишина. Мои кнопки не появляются пока не напишу руками слово Помощь или Поиск или Настройки. Это происходит изза того что бот запускается с компа или в чем проблема? по-идее, кнопки должны появляться сразу после Запустить или /start
Pavel Mironov (Miroha) Уровень 16
3 июля 2020
Переписал своего бота на Spring Boot: Ссылка: https://github.com/miroha/GooglePlayGames-TelegramBot
Pavel Mironov (Miroha) Уровень 16
24 июня 2020
Для тех, кто уже прочитал или прочитает в будущем эту статью, будет ли вам интересно прочитать про написание этого же бота, но уже с использованием Spring Framework (Boot, Data) + MongoDB + Gradle? И вообще, где можно выложить "небольшую книгу" по созданию бота? С многими проблемами столкнулся, с которыми будут сталкиваться новички, хотел бы сэкономить им время в этих делах.
Pavel Mironov (Miroha) Уровень 16
9 июня 2020
Уже начал переделывать бота с использованием Spring Boot с подключением БД.
A.L.F. Уровень 4
3 июня 2020
В JR далее разбираются подобные задачи (написать бота)? Тема актуальная, начальник вечно хочет какого то бота подружить с 1С, но хочет на питоне. Но если смогу делать ботов лучше на джаве, то думаю ему будет фиолетово. Ну и есть моб игра, там альянс, даже скорее семейство альянсов, все сидим в телеге, хочу некоего бота для альянса запилить, а то плодить отдельные чаты для голосования или для найма в альянс не комильфо.
Dmitry Уровень 27
3 июня 2020
Тоже хочу написать телеграм бот. Только простой. Ты ему номер автобуса , он тебя спрашивает в какую сторону и какая остановка. Потом выдает пару ближайших рейсов автобуса. + доп кнопка "показать всё расписание". Пока на стадии задумки, но обязательно доберусь)