Editmessagetext Telegram bot пример java

Hello, I’ve been playing with Telegraf for a while and can’t find enough details or examples of how to use editMessageText. I read through the Telegraf and Telegram docs but have not been able to get my issue sorted out.

I am working on a standard messaging bot (bot user) and am sending messages via ctx.reply. I would like to edit those messages later on, but am unable to find the proper context/format. I am already passing the chat and message IDs back from the reply I’m sending.

Can I make a request for a simple example of a bot editing its own message sent via reply?

I am looking for something along these lines:

bot.on(‘message’, (ctx) => < ctx.reply(«hello world»).then((msgInfo) =>< bot.editMessageText(msgInfo.chat.id, msgInfo.message_id, «goodbye»); >);
(Format for that is probably wrong, I have tried several variations/contexts, consider it pseudocode)
In reality I would be passing the message ID and chat ID to a function which processes info, then use it to update the staus of a job for the user

Creating and using a Telegram Bot with Java

Application/context:
I allow users to send links to my bot (ytdl-core stuff) which then downloads the media and does some processing. Currently my bot notifies when it starts downloading, then sends a second message upon completion. This is both noisy, and as the processes are async, a bit confusing matching multiple starts/completions up. My goal is to have a message that reads something like:
Video: Title heren Status: Downloading
Upon completion/processing, edit the message to read:
Video: Title heren Status: Complete

Thanks in advance for input!

Источник: bleepcoder.com

Подтверждение входа с помощью Telegram на Spring Boot

Недавно столкнулся с проблемой: все приложения используют Telegram-бота в качестве подтверждения входа в аккаунт, а мое — нет. Я был настроен серьезно и провёл уйму времени в интернете в поиске туториала, но меня ждало разочарование. Задача сложная и имеет много подводных камней, а туториалов — ноль.

Следующую неделю я потратил на написание своей имплементации данной фичи и готов поделиться успехом.

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

Создание проекта

Spring Initializr Settings

Итак, для начала создадим проект. Для этого я использовал Spring Initializr. Для проекта нам понадобится Spring MVC, Spring Security и Spring WebSocket. В качестве базы данных будем использовать H2. Мои настройки выглядели вот так:

Затем в наш pom.xml добавим дополнительные зависимости: библиотека для работы с Telegram и webjars: bootstrap (для красивого дизайна), stomp-websocket и sockjs-client для работы с Spring WebSocket.

Telegram Bot на Java ООП

В итоге наш pom.xml будет выглядеть вот так.

Зависимости pom.xml

org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity5 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-websocket org.springframework.security spring-security-messaging com.h2database h2 runtime org.telegram telegrambots 4.8.1 org.telegram telegrambotsextensions 4.8.1 org.webjars bootstrap 4.4.1-1 org.webjars stomp-websocket 2.3.3 org.webjars sockjs-client 1.0.2 org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.security spring-security-test test

Настройка базовой авторизации

Перейдём к настройке базовой авторизации. Сейчас наш класс настройки Web Security выглядит так, но позже он сильно измениться:

Вы можете обратить внимание, что мы сказали Spring’у, что он должен разрешать запрос /websocket/** всем. Пока что в этом нет никакого смысла, но в будущем это будет очень важная строка.

Перепись авторизации на JSON формат

Алгоритм авторизации

Наше приложение будет работать по такому алгоритму:

Как вы видите, тут проверка пользователя идёт по порядку: спросили одно и ждём ответа, при получении ответа, если надо, спрашиваем второе. Перенаправлять пользователя со страницы на страницу было бы не очень удобно, а вот технологию AJAX применить можно было бы. Для этого перепишем нашу авторизацию на JSON. Делать мы это будем с помощью AuthenticationSuccessHandler и AuthenticationFailureHandler , но для начала создадим модель, которую будем возвращать в качестве информации об авторизации:

public class AuthenticationInfo < private boolean success; private String redirectUrl; private String errorMessage; private SetrequiredMfas; public enum RequiredMfa < TELEGRAM_MFA >// getters, setters and no args constructor >

Еще по теме:  Где в Самсунге файлы Телеграмм

Как вы видите, тут мы используем Set requiredMfas вместо простого boolean askTelegramMfa . Как вы думаете почему?

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

Теперь напишем RequireTelegramMfaException . Это Exception, который мы будем выбрасывать, если пользователь должен авторизоваться с помощью Telegram. Почему? Пока пользователь не подтвердил авторизацию в Telegram, мы не должны его авторизовать, а значит мы должны выбросить Exception, что бы Spring этого не сделал. Почему мы пишем его сейчас? Далее мы напишем CustomAuthenticationFailureHandler , который будет проверять эту ошибку.

Наш RequireTelegramMfaException обязательно должен наследоваться от AuthenticationException , а выглядеть будет так:

public class RequireTelegramMfaException extends AuthenticationException < public RequireTelegramMfaException(String msg) < super(msg); >>

Теперь перейдём непосредственно к CustomAuthenticationFailureHandler . Наш код будет выглядеть вот так:

Тут всё просто: в начале мы создаем и настраиваем AuthenticationInfo , говорим, что авторизация была не успешна, ошибку берём из Exception и если наш Exception — это RequireTelegramMfaException говорим, что пользователь ещё должен подтвердить авторизацию в Telegram. Затем мы уже просто настраиваем ответ: ставим character encoding = UTF-8, отправляем статус 401 (UNAUTHORIZE) и ставим content type = application/json . Затем просто возвращаем наш AuthenticationInfo .

Наш CustomSuccessHandler будет возвращать AuthenticationInfo с параметром success=true и указывать адрес, на который надо перенаправлять после авторизации (последняя открытая страница). Статус ответа будет 200 (OK). Делается это вот так:

Как вы видите, redirectUrl мы берём из объекта RequestCache , который мы можем взять у объекта HttpSecurity . Наш новый WebSecurityConfig будет выглядеть вот так (в будущем мы будем его редактировать ещё один раз):

После этого наш frontend нужно переписать на систему AJAX. В этом примере я использовал Bootstrap Carousel, а авторизацию переписал вот так (код html и js):

document.addEventListener(‘DOMContentLoaded’, () => < loginForm.addEventListener(‘submit’, e => < e.preventDefault(); $.ajax(< method: ‘POST’, url: ‘/login’, data: $(loginForm).serialize(), error: response => < let data = response.responseJSON; // если требуется подтверждение авторизации в Telegram — // открыть нужный слайд, где будет сообщение об этом if (data.requiredMfas data.requiredMfas.includes(‘TELEGRAM_MFA’)) < $(carousel).carousel(TELEGRAM_SLIDE); >else < // иначе — выводим сообщение ошибки showAlert(data.errorMessage, ‘danger’); loginForm.querySelector(‘input[name=»password»]’).value = »; >> >).done(response => < loginModal.classList.add(‘fullscreen-loading-modal’); // запускаем анимацию загрузки location.href = response.redirectUrl; // перенаправляем пользователя >); >); >

Хотелось бы отметить, почему мы не проверяем параметр success : в своих handler’ах мы указываем нужные статусы ответа (200, если авторизован и 401, если не авторизован). Благодаря этому, jQuery сам направит response в нужный callback: error , если ошибка (в нашем случае, ответ 401) или done , если всё нормально (в нашем случае, ответ 200).

Создание и настройка Telegram бота

Теперь займёмся самим Telegram ботом. В нашем pom.xml должны быть две зависимости: наркотическая и никотиновая org.telegram:telegrambots и org.telegram:telegrambotsextensions . Код нашего бота будет выглядеть вот так:

ConnectAccountCommand

Подтверждение авторизации с помощью Telegram бота

Перейдём к написанию самой авторизации с помощью Telegram. Для начала нам понадобится свой WebAuthenticationDetails . Нам понадобится HttpServletRequest, мы будем с ним работать. Наш CustomWebAuthenticationDetails будет выглядеть вот так:

public class CustomWebAuthenticationDetails extends WebAuthenticationDetails < private final HttpServletRequest request; public CustomWebAuthenticationDetails(HttpServletRequest request) < super(request); this.request = request; >public HttpServletRequest getRequest() < return request; >>

Теперь нам понадобится свой AuthenticationProvider , который будет проверять нужно ли подтверждение с помощью Telegram и если да — отправлять сообщение в Telegram и сообщать об этом пользователю. Мы будем наследоваться от класса DaoAuthenticationProvider . У него есть метод additionalAuthenticationChecks(UserDetails, UsernamePasswordAuthenticationToken) . Он может делать проверку пользователя уже после того, как мы проверили логин и пароль пользователя.

Создадим команду Telegram бота для подтверждения авторизации MfaCommand :

Перепишем if в методе additionalAuthenticationChecks() класса CustomAuthenticationProvider .

if (user.getTelegramChatId() != null)

И обновим метод processNonCommandUpdate(Update) класса TelegramBot :

Теперь обновим WebSecurityConfig где добавим парсер AuthenticationDetais в CustomWebAuthenticationDetails и наш новый CustomAuthenticationProvider .

На этом этапе можете запустить приложение. Если у вас подключён Telegram аккаунт — бот отправит вам сообщение для подтверждения. Если вы нажмёте кнопку «Подтвердить» — вас авторизуют, но вы этого не увидите. Для этого обновите страницу в браузере или, что лучше, перейдите на главную страницу (к странице авторизации доступа у вас уже не будет, так как вы авторизованы).

Еще по теме:  Если мой контакт есть в телефоне в Телеграмме отображается

Отправка сообщение в браузер, об успешной авторизации

Последнее, что осталось сделать — потанцевать с бубном написать уведомление для браузера. Мы уже авторизуем браузер при подтверждении, но браузер об этом не знает. Мы должны вручную обновлять страничку, чтобы увидеть это. От этого будем пытаться избавиться.

Начнём сразу с проблемы, которая у нас встречается: мы можем подключать Spring WebSocket, но как мы будем ему говорить, кому отправлять сообщение? Пользователь подключается ещё до авторизации, так что его логин ещё неизвестен. Если при подключении пользователь не авторизован, в метод simpMessagingTemplate.convertAndSendToUser нужно передавать Session ID в качестве String user параметра: ID подключения. Однако, Session ID , который к нам приходит в HttpServletRequest , отличается от Session ID , который к нам приходит при подключении к WebSocket.

Сделаем свой репозиторий, который будет хранить Session ID подключения WebSocket. Но как мы будем аутентифицировать пользователя? В качестве решения решил использовать CSRF токен. Для подключения WebSocket, нам нужно указать CSRF токен, для запросов — тоже. Перейдём к реализации:

Теперь создадим WebSocketService , который будет отправлять сообщение для бразура. Он будет принимать информацию об авторизации и CSRF токен.

Добавим вызов этого метода в MfaCommand :

public void onCallbackQuery(CallbackQuery callbackQuery) < Message message = callbackQuery.getMessage(); AuthInfo authInfo = connectingUser.remove(message.getChatId()); // . AuthenticationInfo info = new AuthenticationInfo(); if (callbackQuery.getData().equals(CONFIRM_BUTTON)) < // . >// отправляем уведомление для браузера webSocketService.sendLoginStatus(info, authInfo.getCsrf()); try < telegramBot.execute(editMessageText); >catch (TelegramApiException e) < log.error(«Error updating telegram MFA message», e); >>

Создадим WebSocketConfig и WebSocketSecurityConfiguration :

Напоню, что в WebSecurityConfig должно стоять .antMatchers(«/websocket/**»).permitAll() . Это очень важно. Иначе, неавторизованный пользователь не сможет подключиться.

Осталось только переписать frontend, что бы он ловил эти сообщения и делал какие-то действия, в зависимости от содержимого:

let socket = new SockJS(‘/websocket’); let stompClient = Stomp.over(socket); // создаем объект headers, куда кладём все Header’ы, // необходимые для подключения let headers = <>; // кладём CSRF токен // по нему мы и будем авторизовывать нашего пользователя // а без него — WebSecurity запретит подключение let csrfHeader = document.querySelector(‘meta[name=»_csrf_header»]’).content; headers[csrfHeader] = document.querySelector(‘meta[name=»_csrf»]’).content; // подключаемся к WebSocket серверу stompClient.connect(headers, frame => < console.log(frame); // подписываемся на уведомления по авторизации stompClient.subscribe(‘/user/queue/login’, data => < const info = JSON.parse(data.body); // если авторизация успешна — // выводим анимацию загрузки // и открываем нужную страницу if (info.success) < loginModal.classList.add(‘fullscreen-loading-modal’); location.href = info.redirectUrl; >else < // иначе — выводим ошибку // и открываем слайд ввода логина и пароля loginForm.querySelector(‘input[name=»password»]’).value = »; $(carousel).carousel(LOGIN_SLIDE); showAlert(info.errorMessage, ‘danger’); >>); >);

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

Также, в этом приложении мы это не рассматривали, но, для продакшона, вам, скорее всего, понадобится реализовать функцию «Запомнить меня». Дело в том, что если пользователь использует вход с помощью телеграма — приложение не сможет добавить ему remember me cookie . Для исправления этого, вы можете записывать cookie с помощью JavaScript или, к примеру, перенаправлять пользователя на страничку с параметром ?rememberMe=true , а затем, используя Filter , проверять на наличие этого параметра и, если это необходимо, записывать cookie .

  • Информационная безопасность
  • Java

Источник: habr.com

Попытка создать java Framework для телеграм ботов

У меня иногда появлялось желаение делать ботов для телеграм, так мой основной язык Java — выбор не велик и он меня не устраивает. Каждый раз нужно было придумывать какие-то схемы обработки приходящих апдейтов и мучаться с этим всем. Либо был другой выбор — всякие непонятные Abilities / Replies, по которым нет информации нигде, а еще они используют внутри свою странную БД.

По этим причинам у меня в голове давно витает мысль сделать какую-то библиотеку / фреймворк, что бы можно было нормально и без мучений делать ботов. На данный момент уже есть небольшой framework, который работает и решает выше описанные проблемы. Он построен по принципу MVC. Есть контроллер, который обрабатывает данные, затем он передаёт модель во View, который уже отправляет сообщение пользователю, но это не обязательно и контроллер может сам отправить сообщение.Так же он поддерживает сессии и состояния.

Все это построено на Spring и работает как простая зависимость.

Демонстрация

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

Бот будет использовать состояния и сессии, для того что бы их включить нужно добавить следующие параметры в application.properties

Еще по теме:  Как Мейзу скачать Телеграм

#Включить управление состояниями slyrack.enableStateManagement=true #Включить управление сессиями slyrack.enableSessionManagement=true #Задать время жизни сессии slyrack.sessionTtlMillis=600000

Первая команда

  • UpdateType[] value — типы апдейтов, на которые будет реагировать комманда. Это enum, который содержит некоторые типы апдейтов.
  • String[] state — состояния, при которых будет срабатывать комманда.
  • boolean exclusive — значит то что если команд-кандидатов на исполнение будет найдено несколько — будет выполнена только команда которая содержит в данном поле true

Метод-команда может возвращать void / ModelAndView / StatefulModelAndView на выбор. Метод-команда может принимать некоторые параметры на выбор:

  • Update
  • AbsSender
  • Session — если включено управление сессиями, если нет — null
  • Model — если включено управление состояниями и если было предшествующее состояние, в остальных случаях — null
  • Любое кол-во параметров любого типа с аннотацией SessionAtr , если такой не найден — null
  • Любое кол-во параметров любого типа с аннотацией ModelAtr , если не было предшествующего состояние или нету такого атрибута — null

Создадим первую команду, которая будет отвечать на любое сообщение и возвращает некоторое состояние и название view.

Первый view

Метод-view ничего не возвращает, т.е. void Метод-view принимает все те же параметры что и метод-команда с одним отличием — ей приходит модель не от состояния, а с предшествующей команды.

Создадим первый view с названием select-subject-view :

Здесь просто отсылается SendMessage с Inline клавиатурой. Но есть один момент — откуда взялся chat-id ? Пока что ему неоткуда взятся. С этого места мы переходим к последнему из освополагающих компонентов фреймворка.

MiddleHandler

В данном методе мы устанавливаем 2 атрибута в сессию: chat-id и user если сессия существует и эти атрибуты ранее не были установлены. В дальнейшем мы можем их использовать по своему усмотрению.

Добавление функций

Добавим в наш InitController метод обработки нажатий по Inline клавиатуре:

Эта команда будет обрабатывать только те апдейты, которые содержат CallbackQuery, и если пользователь имеет состояние subject-select-state . Возвращает она новое состояние и название view. Так же она сохраняет тему вопроса в модель. (в данном случае лучше это делать в сессию, но сделано так для демонстрации)

Можем еще добавить метод, который будет входящие удалять сообщения пока не была нажата кнопка на Inline клавиаутуре:

Теперь нужно добавить метод в InitViews , который будет обрабатывать новый view:

Что делает данный метод:

  • Отвечает на inline query как этого требует документация telegram bots.
  • Редактирует сообщение с клавиатурой. Новое сообщение будет содержать выбранную тему вопроса.
  • Отправляет новое сообщение с запросом ввести номер телефона.

Теперь нужно добавить метод в контроллер, который будет обрабатывать ввод номера телефона:

Проверка номера телефона здесь выполняется очень простой и некоректной регуляркой. В случае если апдейт содержит текст и он подходит под условие регулярного выражения — добавляется номер телефона в текущую модель и передаётся в новый view. В остальных случаях — состояние и его модель не изменяются, и вызывается view, который говорит о некорректности данных.

Добавим соотвествующие view:

В данный момент бот уже может предложить пользователю выбрать тему вопроса и ввести номер телефона. Осталось добавить иммитацию общения со специалистом. Сделаем новый класс, так как там могла бы быть сложная логика.

И соотвествующий view:

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

Вроде бы все готово, только что если пользователь захочет прервать общение со специалистом, либо передумает еще на этапе заполнения данных ? Нам нужна отмена. И можем её просто сделать. Добавим такой метод в InitController :

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

  • equals
  • equalsIgnoreCase
  • contains
  • startsWith
  • endsWith

Ну и добавим соотвествующий view в InitViews :

Бот готов

Ознакомится с ботом можно по ссылке

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

Заключение

Статья получилась не очень читабельная, прошу прощения. Но мне бы хотелось что бы было что-то подобное для java.

Ссылка на сам framework

Еще нужно добавить что по умолчанию для поддержки сессий и состояний используются in-memory хранилища. Если вы хотите использовать это не только для тестов — вам необходимо реализовать два интерфейса — SessionManager https://temofeev.ru/info/articles/popytka-sozdat-java-framework-dlya-telegram-botov/» target=»_blank»]temofeev.ru[/mask_link]

Рейтинг
( Пока оценок нет )
Загрузка ...