Телеграм бот прогноза погоды на Java Spring |
||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2021-08-19 02:08 Здравствуйте, сегодня мы создадим простого бота для Телеграм, который демонстрирует базовые возможности работы с Telegram API. Работать он будет следующим образом: Регистрация бота в Telegram и получение токена Тут всё довольно просто, необходимо написать @BotFather и следовать его инструкциям, если вы всё сделаете правильно, то получите сообщение такого вида: Это и есть необходимый токен для бота. Регистрация в openweather и получение ключа доступа Заходим на сайт https://openweathermap.org/ и проходим регистрацию, ключ находится в разделе MyAPI keys. По бесплатному тарифу вам доступно до 60 звонков в минуту и до 1 000 000 в месяц. Наш бот будет получать данные по текущей погоде, поэтому шаблон API ссылки будет такой - http://api.openweathermap.org/data/2.5/weather?q={city}&appid={key}&units=metric&lang=ru , где units=metric отвечает за единицу измерения температуры в цельсиях. О других возможностях API можно почитать в документации на сайте сервиса. Подготовка проекта Далее создаем пустой проект Spring Boot с помощью https://start.spring.io/, если вы используете IntelliJ IDEA, то можете использовать встроенный инициализатор Spring Boot проекта. После создания проекта добавляем необходимые зависимости: pom.xml <dependencies> <!--Драйвер для MongoDB--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <!--Аннотации для оптимизации Java кода--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--Библиотека для удобной работы с Telegram API--> <dependency> <groupId>org.telegram</groupId> <artifactId>telegrambots</artifactId> <version>5.2.0</version> </dependency> <!--Библиотека для парсинга эмоджи--> <dependency> <groupId>com.vdurmont</groupId> <artifactId>emoji-java</artifactId> <version>5.1.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> Наш бот будет использовать MongoDB для хранения конфигурации, а также для хранения состояния относительно чатов. Пройдёмся по необходимым сущностям (документам): BotConfig - конфигурация нашего бота (collection = "bot_config") public class BotConfig { @Id private BigInteger id; //имя бота, которое вы указали при регистрации private String name; //токен private String accessToken; //http://api.openweathermap.org/data/2.5/weather?q={city}&appid=ВАШ_КЛЮЧ&units=metric&lang=ru private String nowWeatherApiTemp; //подробнее о данной ссылке ниже //https://api.telegram.org/bot{token}/answerCallbackQuery?callback_query_id={id} private String telegramCallbackAnswerTemp; private List<Command> commands; } public class Command { private String name; // /command private String description; // bla bla bla } ChatConfig - Информация о чатах с пользователями (collection = "chats_config") public class ChatConfig { @Id private BigInteger id; @NonNull private Long chatId;(targetType = FieldType.STRING) private BotState botState; //стандартный город для пользователя private String city; } Также при разработке нам понадобятся три enum: BotState - Состояния бота public enum BotState { DEFAULT,SEARCH_NOW,SEARCH_PREDICT,NOW,PREDICT,SET_CITY } KeyboardType - Группы кнопок в Телеграм чате, в нашем случае понадобится только одна public enum KeyboardType { CITY_CHOOSE } MainCommand - Команды, которые бот будет воспринимать, находясь в состоянии DEFAULT public enum MainCommand { START,HELP,CITY,SETCITY,NOW,CANCEL } Создание компонентов для работы с базой данных и API Openweather Далее необходимо создать репозитории и сервисы для документов BotConfigService - Сервис для работы с конфигурацией бота @Service public class BotConfigService { @Autowired //пустой интерфейс, наследуемый от MongoRepository<BotConfig, BigInteger> private BotConfigRepo botConfigRepo; public String getTelegramCallbackAnswerTemp(){ return this.botConfigRepo.findAll().get(0).getTelegramCallbackAnswerTemp(); } public String getNowApiTemp(){ return this.botConfigRepo.findAll().get(0).getNowWeatherApiTemp(); } public List<Command> getAllCommands(){ return botConfigRepo.findAll().get(0).getCommands(); } public String getBotUsername(){ return botConfigRepo.findAll().get(0).getName(); } public String getBotAccessToken(){ return botConfigRepo.findAll().get(0).getAccessToken(); } } ChatConfigRepo и ChatConfigService public interface ChatConfigRepo extends MongoRepository<ChatConfig, BigInteger> { ChatConfig findAllByChatId(Long chatId); void deleteByChatId(Long chatId); } @Service public class ChatConfigService { @Autowired private ChatConfigRepo chatConfigRepo; public boolean isChatInit(Long chatId){ return chatConfigRepo.findAllByChatId(chatId) != null; } //создание нового чата public void initChat(Long chatId){ chatConfigRepo.save(new ChatConfig(chatId, BotState.DEFAULT)); } public void deleteChat(Long chatId){ chatConfigRepo.deleteByChatId(chatId); } public void setBotState(Long chatId,BotState botState){ ChatConfig chatConfig = chatConfigRepo.findAllByChatId(chatId); chatConfig.setBotState(botState); chatConfigRepo.save(chatConfig); } public BotState getBotState(Long chatId){ return chatConfigRepo.findAllByChatId(chatId).getBotState(); } public void setCity(Long chatId,String city){ ChatConfig chatConfig = chatConfigRepo.findAllByChatId(chatId); chatConfig.setCity(city); chatConfigRepo.save(chatConfig); } public String getCity(Long chatId){ return chatConfigRepo.findAllByChatId(chatId).getCity(); } } Теперь давайте создадим классы для работы с API погоды. При запросе нам приходит ответ вида: current weather json response { "coord": { "lon": 37.6156, "lat": 55.7522 }, "weather": [ { "id": 500, "main": "Rain", "description": "небольшой дождь", "icon": "10n" } ], "base": "stations", "main": { "temp": 13.78, "feels_like": 13.69, "temp_min": 12.37, "temp_max": 14.24, "pressure": 1013, "humidity": 95, "sea_level": 1013, "grnd_level": 995 }, "visibility": 10000, "wind": { "speed": 3.52, "deg": 43, "gust": 9.4 }, "rain": { "1h": 0.22 }, "clouds": { "all": 100 }, "dt": 1623359195, "sys": { "type": 2, "id": 2000314, "country": "RU", "sunrise": 1623372350, "sunset": 1623435164 }, "timezone": 10800, "id": 524901, "name": "Москва", "cod": 200 } Из всего этого огромного количества полей мы будем использовать всего несколько: weather.main, weather.description, main.temp, main.feels_like. Создадим модель для ответа: WeatherNow public class WeatherNow { private List<Weather> weather; private Main main; } public class Weather { private String main; private String description; } public class Main { private Integer temp; @JsonProperty("feels_like") private Integer feelsLike; } Далее создадим класс, методы которого будут делать запросы на API, а также сервис для него WeatherRestMap @Component public class WeatherRestMap { @Autowired private RestTemplate restTemplate; @Autowired private BotConfigService botConfigService; //получение текущей погоды public WeatherNow getNowWeather(String city){ try { return restTemplate.getForObject(botConfigService.getNowApiTemp() .replace("{city}",city), WeatherNow.class); }catch (Exception e){ e.printStackTrace(); return null; } } //проверка существования города public boolean isCity(String city) throws IOException { URL weatherApiUrl = new URL(botConfigService.getNowApiTemp().replace("{city}",city)); HttpURLConnection weatherApiConnection = (HttpURLConnection)weatherApiUrl.openConnection(); weatherApiConnection.setRequestMethod("GET"); weatherApiConnection.connect(); return weatherApiConnection.getResponseCode() == HttpURLConnection.HTTP_OK; } } WeatherService @Service public class WeatherService { @Autowired private WeatherRestMap weatherRestMap; public boolean isCity(String city) throws IOException { return weatherRestMap.isCity(city); } public WeatherNow getCurrentWeather(String city){ return weatherRestMap.getNowWeather(city); } } Создание логики по взаимодействию с Telegram API Для начала создадим основной класс нашего бота, наследуемый от TelegramLongPollingBot из библиотеки для работы с Telegram API Класс WeatherBot @Component public class WeatherBot extends TelegramLongPollingBot { @Autowired private BotConfigService botConfigService; @Autowired private WeatherBotFacade weatherBotFacade; @Override public String getBotUsername() { return botConfigService.getBotUsername(); } @Override public String getBotToken() { return botConfigService.getBotAccessToken(); } @SneakyThrows //отслеживание Exceptions @Override public void onUpdateReceived(Update update) { weatherBotFacade.handleUpdate(update); } } Метод onUpdateReceived получает с Telegram API так называемые апдейты, это может быть как сообщение, поступившее боту, так и какое-либо другое изменение в чате с ботом (изменение сообщения, удаление чата и.т.д.) Также необходимо инициализировать нашего бота после запуска приложения Класс BotInit @Component public class BotInit { @Autowired private WeatherBot weatherBot; //после того, как приложение полностью запущено @EventListener({ApplicationReadyEvent.class}) public void init() throws TelegramApiException { TelegramBotsApi telegramBotsApi = new TelegramBotsApi( DefaultBotSession.class); try { telegramBotsApi.registerBot(weatherBot); } catch (TelegramApiRequestException e) { e.printStackTrace(); } } } Для создания класса WeatherBotFacade, в котором будет реализована основная логика по взаимодействию с Telegram API, необходимо создать несколько вспомогательных классов: Первый - сервис, который будет возвращать строки с сообщениями от бота: MessageGenerator @Service public class MessageGenerator { @Autowired private BotConfigService botConfigService; @Autowired private WeatherService weatherService; private String message; public String generateStartMessage(String name){ return EmojiParser.parseToUnicode("Привет, " + name + " :wave: Чтобы узнать, как мной пользоваться - введите /help"); } public String generateHelpMessage(){ message = ""; message = ":sunny: Вот мои доступные команды :sunny: "; botConfigService.getAllCommands() .forEach(command -> { message = message + command.getName() + " - " + command.getDescription() + " "; }); return EmojiParser.parseToUnicode(message); } public String generateSuccessCancel(){ return EmojiParser.parseToUnicode(":white_check_mark: Активная команда успешно отклонена"); } public String generateSuccessSetCity(String city){ return EmojiParser.parseToUnicode(":white_check_mark: Новый стандартный город - " + city); } public String generateErrorCity(){ return EmojiParser.parseToUnicode(":x: Такого города не существует"); } public String generateSuccessGetCity(String city){ return EmojiParser.parseToUnicode(":cityscape: Стандартный город - " + city); } public String generateErrorGetCity(){ return EmojiParser.parseToUnicode(":x: Стандартный город не назначен"); } public String generateCurrentWeather(String city){ WeatherNow weatherNow = weatherService.getCurrentWeather(city); return EmojiParser.parseToUnicode("Текущая погода " + "В городе " + city + " " + weatherNow.getWeather().get(0).getDescription() + " " + ":thermometer: Температура: " + weatherNow.getMain().getTemp() + "°C, ощущается как " + weatherNow.getMain().getFeelsLike() + "°C"); } } Здесь мы используем библиотеку для парсинга иконок, код вида :icon: для любого эмоджи можно найти на сайте https://emojipedia.org/ Далее создаём класс, который будет создавать кнопки в сообщениях от бота KeyboardService @Service public class KeyboardService { @Autowired private ChatConfigService chatConfigService; private final InlineKeyboardMarkup keyboard = new InlineKeyboardMarkup(); public InlineKeyboardMarkup setChooseCityKeyboard(Long chatId){ List<InlineKeyboardButton> keyboardRow = new ArrayList<>(); InlineKeyboardButton button1 = new InlineKeyboardButton(); //текст на кнопке button1.setText(chatConfigService.getCity(chatId)); //сообщение, которое она возвращает button1.setCallbackData(getCurrentCityNowButton(chatConfigService .getCity(chatId))); InlineKeyboardButton button2 = new InlineKeyboardButton(); button2.setText("Другой"); button2.setCallbackData(getChooseCityNowButtonData()); keyboardRow.add(button1); keyboardRow.add(button2); keyboard.setKeyboard(Arrays.asList(keyboardRow)); return keyboard; } public String getChooseCityNowButtonData(){ return "Введите необходимый город"; } public String getCurrentCityNowButton(String city){ return "Сейчас " + city; } } Кнопки с CallbackData часто используются для перенаправления пользователей на сторонние ресурсы, например для совершения оплаты, в нашем случае они будут просто возвращать сообщение, однако согласно документации Telegram API, необходимо вернуть callbackAnswer, содержащий поле callback_query_id. Подробнее о методе и его полях - https://core.telegram.org/bots/api#answercallbackquery Если не вернуть callbackAnswer, то у кнопки будет состояние загрузки до окончания таймаута (около 15 секунд), что может ввести в заблуждение пользователя Загрузка кнопки Для использования callbackAnswer создадим одноименный класс, в котором будем делать одиночный HTTP запрос на нужный метод - https://api.telegram.org/bot{token}/answerCallbackQuery?callback_query_id={id} Класс CallbackAnswer @Service public class CallbackAnswer { @Autowired private BotConfigService botConfigService; public void callbackAnswer(String callbackId) throws IOException, InterruptedException { HttpClient telegramApiClient = HttpClient.newHttpClient(); HttpRequest telegramCallbackAnswerReq = HttpRequest.newBuilder(URI .create(botConfigService .getTelegramCallbackAnswerTemp() .replace("{token}",botConfigService.getBotAccessToken()) .replace("{id}",callbackId))) .GET().build(); telegramApiClient.send(telegramCallbackAnswerReq, HttpResponse.BodyHandlers .ofString()); } } Теперь же приступим к основному классу WeatherBotFacade Для начала создадим метод для отправки сообщения ботом: void sendMessage private Long setChatIdToMessageBuilder(Update update, SendMessage.SendMessageBuilder messageBuilder){ Long chatId = null; if (update.hasMessage()) { chatId = update.getMessage().getChatId(); messageBuilder.chatId(update.getMessage().getChatId().toString()); } else if (update.hasChannelPost()) { chatId = update.getChannelPost().getChatId(); messageBuilder.chatId(update.getChannelPost().getChatId().toString()); }else if (update.hasCallbackQuery()){ chatId = update.getCallbackQuery().getMessage().getChatId(); messageBuilder.chatId(update.getCallbackQuery().getMessage().getChatId().toString()); } return chatId; } private void sendMessage(Update update,String messageText){ SendMessage.SendMessageBuilder messageBuilder = SendMessage.builder(); Long chatId = setChatIdToMessageBuilder(update,messageBuilder); messageBuilder.text(messageText); try { weatherBot.execute(messageBuilder.build()); }catch (TelegramApiException telegramApiException){ telegramApiException.printStackTrace(); } } private void sendMessage(Update update, String messageText, KeyboardType keyboardType) { SendMessage.SendMessageBuilder messageBuilder = SendMessage.builder(); Long chatId = setChatIdToMessageBuilder(update, messageBuilder); messageBuilder.text(messageText); switch (keyboardType) { case CITY_CHOOSE: { //устанавливаем кнопки, созданные выше messageBuilder.replyMarkup(keyboardService.setChooseCityKeyboard(chatId)); break; } } try { weatherBot.execute(messageBuilder.build()); }catch (TelegramApiException telegramApiException){ telegramApiException.printStackTrace(); } } Далее нам понадобится метод для отслеживания апдейтов, который будет использован в методе onUpdateReceived в классе нашего бота, созданного выше: void handleUpdate public void handleUpdate(Update update) throws IOException, InterruptedException { String messageText; Long chatId; String userFirstName = ""; //если сообщение пришло в лс боту if (update.hasMessage()) { chatId = update.getMessage().getChatId(); messageText = update.getMessage().getText().toUpperCase(Locale.ROOT).replace("/",""); userFirstName = update.getMessage().getChat().getFirstName(); } //если пришло сообщение с кнопок, которые мы создавали выше else if (update.hasCallbackQuery()){ callbackAnswer.callbackAnswer(update.getCallbackQuery().getId()); chatId = update.getCallbackQuery().getMessage().getChatId(); messageText = update.getCallbackQuery().getData().toUpperCase(Locale.ROOT); sendMessage(update,update.getCallbackQuery().getData()); if (messageText.equals(keyboardService.getChooseCityNowButtonData().toUpperCase(Locale.ROOT))){ chatConfigService.setBotState(chatId,BotState.SEARCH_NOW); return; } else if (messageText.equals(keyboardService.getCurrentCityNowButton(chatConfigService.getCity(chatId)).toUpperCase(Locale.ROOT))){ chatConfigService.setBotState(chatId,BotState.NOW); } } //если человек присоединился к чату или покинул его else if (update.hasMyChatMember()) { //удаляем данные о чате из бд, если пользователь покинул чат с ботом if (update.getMyChatMember().getNewChatMember().getStatus().equals("kicked")){ chatConfigService.deleteChat(update.getMyChatMember().getChat().getId()); } return; }else { return; } //создаём запись о чате в бд и возвращаем приветствие if (!chatConfigService.isChatInit(chatId)){ chatConfigService.initChat(chatId); sendMessage(update, messageGenerator.generateStartMessage(userFirstName)); }else{ //отслеживаем состояние бота относительно текущего чата handleBotState(update,chatId,messageText,userFirstName); } } Ну и последний метод, который нам понадобится будет отслеживать состояние бота относительно чата и возвращать нужные сообщения: void handleBotState private void handleBotState(Update update,Long chatId,String messageText,String userFirstName) throws IOException { BotState botState = chatConfigService.getBotState(chatId); // /start - Приветствие if (messageText.equals(MainCommand.START.name())) { chatConfigService.setBotState(chatId,BotState.DEFAULT); sendMessage(update,messageGenerator.generateStartMessage(userFirstName)); return; } // /cancel Возвращение бота в состояние DEFAULT (отмена текущей команды) if (messageText.equals(MainCommand.CANCEL.name())){ if (botState == BotState.DEFAULT){ sendMessage(update,"Нет активной команды для отклонения"); }else { chatConfigService.setBotState(chatId,BotState.DEFAULT); sendMessage(update,messageGenerator.generateSuccessCancel()); return; } } switch (botState) { case DEFAULT: { // /help - Список команд if (messageText.equals(MainCommand.HELP.name())) { sendMessage(update, messageGenerator.generateHelpMessage()); } // /setcity - Установка стандартного города else if (messageText.equals(MainCommand.SETCITY.name())) { chatConfigService.setBotState(chatId, BotState.SET_CITY); sendMessage(update, "Введите новый стандартный город"); } // /city - Текущий стандартный город для чата else if (messageText.equals(MainCommand.CITY.name())) { if (chatConfigService.getCity(chatId) != null && !chatConfigService.getCity(chatId).equals("")) sendMessage(update, messageGenerator.generateSuccessGetCity(chatConfigService.getCity(chatId))); else sendMessage(update, messageGenerator.generateErrorGetCity()); } // /now - Узнать текущую погоду else if (messageText.equals(MainCommand.NOW.name())) { chatConfigService.setBotState(chatId, BotState.NOW); sendMessage(update, "Выберите город", KeyboardType.CITY_CHOOSE); } break; } case SET_CITY: { //проверка - существует ли введенный пользователем город if (weatherService.isCity(messageText.toLowerCase(Locale.ROOT))) { chatConfigService.setCity(chatId, messageText.charAt(0)+messageText.substring(1).toLowerCase(Locale.ROOT)); chatConfigService.setBotState(chatId, BotState.DEFAULT); sendMessage(update, messageGenerator.generateSuccessSetCity(chatConfigService.getCity(chatId))); } else sendMessage(update, messageGenerator.generateErrorCity()); break; } case NOW: { // если выбран не стандартный город if (messageText.equals(keyboardService.getChooseCityNowButtonData().toUpperCase(Locale.ROOT))) { chatConfigService.setBotState(chatId,BotState.SEARCH_NOW); } // погода для стандартного города else { chatConfigService.setBotState(chatId,BotState.DEFAULT); sendMessage(update,messageGenerator.generateCurrentWeather(chatConfigService.getCity(chatId))); } break; } case SEARCH_NOW: { // проверка на существование города if (!weatherService.isCity(messageText)){ sendMessage(update,messageGenerator.generateErrorCity()); } // погода для введенного города else { sendMessage(update,messageGenerator.generateCurrentWeather(messageText.charAt(0) + messageText.substring(1).toLowerCase(Locale.ROOT))); chatConfigService.setBotState(chatId,BotState.DEFAULT); } break; } } } Полный код класса WeatherBotFacade: WeatherBotFacade @Component public class WeatherBotFacade { @Autowired private ChatConfigService chatConfigService; @Autowired private MessageGenerator messageGenerator; @Autowired private WeatherService weatherService; @Autowired private KeyboardService keyboardService; @Autowired private WeatherBot weatherBot; @Autowired private CallbackAnswer callbackAnswer; public void handleUpdate(Update update) throws IOException, InterruptedException { String messageText; Long chatId; String userFirstName = ""; if (update.hasMessage()) { chatId = update.getMessage().getChatId(); messageText = update.getMessage().getText().toUpperCase(Locale.ROOT).replace("/",""); userFirstName = update.getMessage().getChat().getFirstName(); } else if (update.hasChannelPost()){ chatId = update.getChannelPost().getChatId(); messageText = update.getChannelPost().getText().toUpperCase(Locale.ROOT).replace("/",""); userFirstName = update.getChannelPost().getChat().getFirstName(); } else if (update.hasCallbackQuery()){ callbackAnswer.callbackAnswer(update.getCallbackQuery().getId()); chatId = update.getCallbackQuery().getMessage().getChatId(); messageText = update.getCallbackQuery().getData().toUpperCase(Locale.ROOT); sendMessage(update,update.getCallbackQuery().getData()); if (messageText.equals(keyboardService.getChooseCityNowButtonData().toUpperCase(Locale.ROOT))){ chatConfigService.setBotState(chatId,BotState.SEARCH_NOW); return; } else if (messageText.equals(keyboardService.getCurrentCityNowButton(chatConfigService.getCity(chatId)).toUpperCase(Locale.ROOT))){ chatConfigService.setBotState(chatId,BotState.NOW); } } else if (update.hasMyChatMember()) { if (update.getMyChatMember().getNewChatMember().getStatus().equals("kicked")){ chatConfigService.deleteChat(update.getMyChatMember().getChat().getId()); } return; }else { return; } if (!chatConfigService.isChatInit(chatId)){ chatConfigService.initChat(chatId); sendMessage(update, messageGenerator.generateStartMessage(userFirstName)); }else{ handleBotState(update,chatId,messageText,userFirstName); } } private Long setChatIdToMessageBuilder(Update update, SendMessage.SendMessageBuilder messageBuilder){ Long chatId = null; if (update.hasMessage()) { chatId = update.getMessage().getChatId(); messageBuilder.chatId(update.getMessage().getChatId().toString()); } else if (update.hasChannelPost()) { chatId = update.getChannelPost().getChatId(); messageBuilder.chatId(update.getChannelPost().getChatId().toString()); }else if (update.hasCallbackQuery()){ chatId = update.getCallbackQuery().getMessage().getChatId(); messageBuilder.chatId(update.getCallbackQuery().getMessage().getChatId().toString()); } return chatId; } private void sendMessage(Update update,String messageText){ SendMessage.SendMessageBuilder messageBuilder = SendMessage.builder(); Long chatId = setChatIdToMessageBuilder(update,messageBuilder); messageBuilder.text(messageText); try { weatherBot.execute(messageBuilder.build()); }catch (TelegramApiException telegramApiException){ telegramApiException.printStackTrace(); } } private void sendMessage(Update update, String messageText, KeyboardType keyboardType) { SendMessage.SendMessageBuilder messageBuilder = SendMessage.builder(); Long chatId = setChatIdToMessageBuilder(update, messageBuilder); messageBuilder.text(messageText); switch (keyboardType) { case CITY_CHOOSE: { messageBuilder.replyMarkup(keyboardService.setChooseCityKeyboard(chatId)); break; } } try { weatherBot.execute(messageBuilder.build()); }catch (TelegramApiException telegramApiException){ telegramApiException.printStackTrace(); } } private void handleBotState(Update update,Long chatId,String messageText,String userFirstName) throws IOException { BotState botState = chatConfigService.getBotState(chatId); if (messageText.equals(MainCommand.START.name())) { chatConfigService.setBotState(chatId,BotState.DEFAULT); sendMessage(update,messageGenerator.generateStartMessage(userFirstName)); return; } if (messageText.equals(MainCommand.CANCEL.name())){ if (botState == BotState.DEFAULT){ sendMessage(update,"Нет активной команды для отклонения"); }else { chatConfigService.setBotState(chatId,BotState.DEFAULT); sendMessage(update,messageGenerator.generateSuccessCancel()); return; } } switch (botState) { case DEFAULT: { if (messageText.equals(MainCommand.HELP.name())) { sendMessage(update, messageGenerator.generateHelpMessage()); } else if (messageText.equals(MainCommand.SETCITY.name())) { chatConfigService.setBotState(chatId, BotState.SET_CITY); sendMessage(update, "Введите новый стандартный город"); } else if (messageText.equals(MainCommand.CITY.name())) { if (chatConfigService.getCity(chatId) != null && !chatConfigService.getCity(chatId).equals("")) sendMessage(update, messageGenerator.generateSuccessGetCity(chatConfigService.getCity(chatId))); else sendMessage(update, messageGenerator.generateErrorGetCity()); } else if (messageText.equals(MainCommand.NOW.name())) { chatConfigService.setBotState(chatId, BotState.NOW); sendMessage(update, "Выберите город", KeyboardType.CITY_CHOOSE); } break; } case SET_CITY: { if (weatherService.isCity(messageText.toLowerCase(Locale.ROOT))) { chatConfigService.setCity(chatId, messageText.charAt(0)+messageText.substring(1).toLowerCase(Locale.ROOT)); chatConfigService.setBotState(chatId, BotState.DEFAULT); sendMessage(update, messageGenerator.generateSuccessSetCity(chatConfigService.getCity(chatId))); } else sendMessage(update, messageGenerator.generateErrorCity()); break; } case NOW: { if (messageText.equals(keyboardService.getChooseCityNowButtonData().toUpperCase(Locale.ROOT))) { chatConfigService.setBotState(chatId,BotState.SEARCH_NOW); } else { chatConfigService.setBotState(chatId,BotState.DEFAULT); sendMessage(update,messageGenerator.generateCurrentWeather(chatConfigService.getCity(chatId))); } break; } case SEARCH_NOW: { if (!weatherService.isCity(messageText)){ sendMessage(update,messageGenerator.generateErrorCity()); } else { sendMessage(update,messageGenerator.generateCurrentWeather(messageText.charAt(0) + messageText.substring(1).toLowerCase(Locale.ROOT))); chatConfigService.setBotState(chatId,BotState.DEFAULT); } break; } } } } Источник: m.vk.com Комментарии: |
|