Русский
Русский
English
Статистика
Реклама

Пишем Telegram Bota для оповещения о коммите в git репозитарий на базе Gitea и разворачиваем его в Google Cloud Platform

Здравствуйте как и обещал в продолжение моей статьи о Автоматической публикации приложения в Google Play , рассмотрю в деталях процесс написания Telegram Bot`a для оповещения команды тестировщиков о выпуске новой версии.

Регистрация Bota в Telegram и получение ID

Просто напишите пользователю@BotFatherиследуйте его инструкциям.

Выполните последовательно следующий команды

/start/newbotbot_name
В итоге вы должны получить сообщение

Из этого сообщение нам понадобятся собственно

  • t.me/bot_name - Имя бота по которому мы будем добавлять его в каналы или писать в ЛС

  • token - это наш ключ для доступа к API

Подготовка проекта и подключение необходимых библиотек

Наш бот будет написан на Java и будет представлять из себя Spring Boot Web приложение, в качестве системы сборки будет использоваться maven

1) Создайте обычный Spring Boot проект, проще всего это сделать через встроенный конфигуратор в IntelliJ IDEA , либо используя Spring Initializr.

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

pom.xml
    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.1.6.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <dependency>            <groupId>org.telegram</groupId>            <artifactId>telegrambots</artifactId>            <version>5.0.0</version>        </dependency>        <dependency>            <groupId>com.google.code.gson</groupId>            <artifactId>gson</artifactId>            <version>2.8.6</version>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-configuration-processor</artifactId>            <optional>true</optional>        </dependency>        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build>
Минимальный проект будет иметь примерно такую структуру :

А теперь детальней по каждому классу :

BotConfig - Конфигурация подтягивающая настройки бота из application.properties
@Configuration@Data@PropertySource("classpath:application.properties")public class BotConfig {    // Имя бота заданное при регистрации    @Value("${botUserName}")    String botUserName;    // Токен полученный при регистрации    @Value("${token}")    String token;}
BotInitializer - Component регистрации/инициализации бота в системе Telegram
@Component@Slf4jpublic class BotInitializer {    @Autowired    Bot bot;    @EventListener({ContextRefreshedEvent.class})    public void Init() throws TelegramApiException {        TelegramBotsApi telegramBotsApi = new TelegramBotsApi(DefaultBotSession.class);        try {            telegramBotsApi.registerBot(bot);        } catch (TelegramApiRequestException e) {            log.error(exceptionStackTraceToString(e));        }    }}

Телеграм API должно быть зарегистрировано в системе и делать это нужно уже после поднятия контекста Spring, по этому вешаем слушатель на ContextRefreshedEvent

Bot - Сервис инкапсулирующий в себе реализацию TelegramLongPollingBot,
@Component@Slf4j/** * Касс является основным пулом взаимодействия с Telegram * получение, обработка, отправка сообщений */public class Bot extends TelegramLongPollingBot {    final    BotConfig config;    public Bot(BotConfig config) {        this.config = config;    }    public void onUpdateReceived(Update update) {        update.getUpdateId();        SendMessage.SendMessageBuilder builder =SendMessage.builder();        String messageText;        String chatId;        if (update.getMessage() != null) {            chatId = update.getMessage().getChatId().toString();            builder.chatId(chatId);            messageText = update.getMessage().getText();        } else {            chatId = update.getChannelPost().getChatId().toString();            builder.chatId(chatId);            messageText = update.getChannelPost().getText();        }        if (messageText.contains("/hello")) {            builder.text("Привет");            try {                execute(builder.build());            } catch (TelegramApiException e) {                log.debug(e.toString());            }        }        if (messageText.contains("/chartId")) {            builder.text("ID Канала : " + chatId);            try {                execute(builder.build());            } catch (TelegramApiException e) {                log.debug(e.toString());            }        }    }    public String getBotUsername() {        return config.getBotUserName();    }    public String getBotToken() {        return config.getToken();    }}

Данный класс представляет из себя основной функционал для взаимодействия с Telegram

  • метод onUpdateReceived принимает и обрабатывает сообщения пришедшие в личку или в канал где бот администратор

WebHook - RestController обслуживающий API для реакции на события WebHook Gitea
@Slf4j@RestController@RequestMapping("/api/public/gitea")@RequiredArgsConstructor@PropertySource("classpath:application.properties")public class WebHook {    Bot bot;    // Канал в который будем слать уведомления    @Value("${chartId}")    String chartId;    // Секретный ключ который придёт в нутри JSON от Gitea,    // что бы левые люди не имели доступа к боту т.к. API публичное без авторизации    @Value("${secret}")    String secret;    @Autowired    public WebHook(Bot bot) {        this.bot = bot;    }    @PostMapping(value = "/webhook")    public ResponseEntity<?> webhook(@RequestBody String json){        Gson gson = new Gson();        GiteaWebHook giteaWebHook = null;        try {            giteaWebHook = gson.fromJson(json, GiteaWebHook.class);        } catch (JsonSyntaxException e) {            log.error(Utils.exceptionStackTraceToString(e));            return new ResponseEntity<>(Utils.exceptionStackTraceToString(e), HttpStatus.BAD_REQUEST);        }        if (validationWebHookContent(giteaWebHook)) {            SendMessage.SendMessageBuilder messageBuilder =SendMessage.builder();            messageBuilder.chatId(chartId);            messageBuilder.parseMode(ParseMode.HTML);            StringBuilder builder = new StringBuilder();            builder.append("<b>Проект</b> : " + giteaWebHook.getRepository().getName()+"\n");            for (Commit commit : giteaWebHook.getCommits()) {             builder.append("<b>Автор</b> : " + commit.getAuthor().getName()+"\n");             builder.append("<b>Комментарий</b> : " + commit.getMessage()+"\n");            }            builder.append("<a href=\"https://play.google.com/store/apps/details?id=URL_ВАШЕГО_ПРИЛАЖЕНИЯ\">Обновление будет доступно в Play Market через пару минут</a>\n");            messageBuilder.text(buildToCorrectString(builder));            try {                bot.execute(messageBuilder.build());            } catch (TelegramApiException e) {                log.error(Utils.exceptionStackTraceToString(e));                return new ResponseEntity<>(Utils.exceptionStackTraceToString(e), HttpStatus.INTERNAL_SERVER_ERROR);            }        } else return new ResponseEntity<>(HttpStatus.BAD_REQUEST);        HttpHeaders headers = new HttpHeaders();        headers.add("Content-Type", "application/json; charset=utf-8");        return new ResponseEntity<>(headers, HttpStatus.OK);    }    /**     * Проверка пришедших JSON данных на валидность     * @param giteaWebHook - GiteaWebHook     * @return true - если не null, PUSH в master, совпал секретный ключ     */    private boolean validationWebHookContent(GiteaWebHook giteaWebHook){        return giteaWebHook != null && // Если вообще что то есть               giteaWebHook.getRef().contains(giteaWebHook.getRepository().getDefaultBranch()) && // Есть был PUSH в /master               giteaWebHook.getSecret().equals(secret); // Если совпал секретный ключ    }    private String buildToCorrectString(StringBuilder builder){        return builder.toString()                .replace("_", "\\_")                .replace("*", "\\*")                .replace("[", "\\[")                .replace("`", "\\`")                .replace("&nbsp;", " ")                .replace("&frac", " ")                .replaceAll(" \\u003c","");    }}

Данный RestController обслуживает RestAPI с точкой входа http://you_ip:port/api/public/gitea/webhook , сюда наша система контроля версий Gitea будет делать PUSH запрос с JSON данными WebHook возникающего при различных событиях происходящих с вашим репозитарием.

TelegramBotGiteaApplication - Стартовый метод нашего Spring Boot проекта
@SpringBootApplication@AutoConfigurationPackagepublic class TelegramBotGiteaApplication extends SpringBootServletInitializer {    public static void main(String[] args) {        new SpringApplicationBuilder(TelegramBotGiteaApplication.class)                .run(args);    }}

Все те классы что вы наблюдаете в пакете Model , представляют сгенерированную модель GiteaWebHook по JSON-Schema взятому из оф документации по GiteaWebHookApi , удобнее всего это делать при помощи http://www.jsonschema2pojo.org/

Полный исходный код вы можете взять ЗДЕСЬ

Настройка Gitea для выполнения WebHook к нашему боту

Данная статья рассматривает вариант обслуживания API предоставляемое системой контроля версий Gitea но это не значит что вы не сможете сделать оповещение и без неё. Проявив некую долю усердия всё те-же WebHook можно реализовать через .git\hooks\post-update и curl , или некое API GitHub но эти реализации я доверяю вам, и здесь мы рассмотрим лишь вариант с Gitea

1) И так, перейдите в репозитарий вашего проекта и войдите в его Настройки в раздел Автоматическое обновление . Нажмите на кнопку Добавить Webhook , выберете вариант Gitea

2) В качестве URL обработчика укажите URL на котором у нас висит RestController http://you_ip:port/api/public/gitea/webhook

3) Тип содержимого - application/json

3) Секретный ключ - любой набор символов который мы в последующем внесём в наш application.properties

4) На какие события этот webhook должен срабатывать? - выберите PUSH

5) Галочку Активности оставьте включённой.

Всё это хорошо бот написан, Gitea настроена но нашему боту нужно где-то жить.

Публикация нашего бота в Google Cloud Platform, бесплатно

New customers get $300 in free credits to spend on Google Cloud. All customers get free usage of 20+ products.See offer details.

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

И так приступим, авторизуйтесь в Google Cloud Platform

1) В боковом меню перейдите в раздел Сompute Engine, и дождитесь его инициализации

2) В разделе Экземпляры ВМ, нажмите создать

Выберете конфигурацию инстанса к примеру вот такую, это будет оптимальным решением для нашего не требовательного приложения

Давайте зададим сразу правило Брандмауэра разрешающего трафик по порту 8080

Зайдите Cеть VPS - Брандмауэр

Создайте правило для порта 8080 по аналогии с 80 портом

Подключитесь к VM через SSH , непосредственно через браузер

Теперь мы может перейти к настройке нашей виртуальной машины

Для обновления информации об новейших версиях пакетов вводим

sudo apt update

Установим Java

sudo apt install default-jdk

Проверьте это выполнив

java - version

Если всё прошло хорошо вы должны наблюдать версию Java в консоли SSH

Теперь установим maven

sudo apt install maven

Сделаем clone репозитария с нашим ботом заготовкой

git clone https://legan.by/gitea/leganas/TelegramBotGiteaLesson.git

Сделайте необходимые манипуляции по настройке appliation.properties , укажите валидный bot_name и token

nano ./TelegramBotGiteaLesson/src/main/resources/application.properties

Зайдём в папку с нашим ботом и соберём его при помощи maven

cd TelegramBotGiteaLesson/mvn package

После того как maven соберёт наш проект

Бот полностью готов к запуску, выполните команду

java -jar ./target/telegrambotgitea-0.0.1-SNAPSHOT.jar

Используя внешний IP указанный в web консоли управления виртуальными машинами, проверьте его работоспособность открыв в браузере страницу http://YOU_IP:8080/

Если наш бот успешно подключился к Telegram мы можем написать ему проверочное сообщение в ЛС /hello , на что он должен ответить нам Привет

И так теперь у нас всё готово для того что бы добавить нашего бота в Telegram канал, дать ему права администратора (что бы он мог читать сообщения) и протестировать оповещение !

Добавил бота в канал и дав ему права , вы можете написать

/chartId

Теперь это ID можно добавить в application.properties и либо пересобрать проект , либо подкинуть этот файл рядом с jar. Внесите необходимые правки IP адреса в WebHook в настройках Gitea и опробуйте вашего бота.

У кого получилось вот так , тот молодец, о том как сделать jar сервисом писать уже не буду, уж очень много про это написано на хабре, а если не найдёте пишите в личку.

Надеюсь моё повествование было достаточно подробным что бы любой смог запустить свою зверушку. :)

Источник: habr.com
К списку статей
Опубликовано: 27.01.2021 20:23:33
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Java

Git

Devops

Telegram

Google cloud platform

Gtea

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru