Compare commits

...

34 Commits

Author SHA1 Message Date
00cf2705fd
Переработка под новую версию godfather
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-15 16:37:24 +03:00
ff2d302db5
Добавил идентификатор сообщения в ButtonClickAttachment 2022-12-21 19:28:55 +03:00
57694fd40a [maven-release-plugin] prepare for next development iteration 2022-12-18 17:42:55 +03:00
4085ae39f9 [maven-release-plugin] prepare release v.0.0.47 2022-12-18 17:42:54 +03:00
c358c771f6 [maven-release-plugin] prepare for next development iteration 2022-12-18 17:41:08 +03:00
b22393453b [maven-release-plugin] prepare release v.0.0.46 2022-12-18 17:41:08 +03:00
c978736b4f Настройка cicd с помощью drone 2022-12-18 17:40:06 +03:00
4382d8e10d [maven-release-plugin] prepare for next development iteration 2022-12-18 17:36:05 +03:00
6f63613b50 [maven-release-plugin] prepare release v.0.0.45 2022-12-18 17:36:05 +03:00
7dfd315512 Настройка cicd с помощью drone 2022-12-18 17:33:47 +03:00
f62bed7d13 v.0.0.44 2022-12-16 16:22:08 +03:00
2f6b46e5b2 Переключил уровень логирования debug 2022-12-16 16:20:18 +03:00
b25f085727 godfather up to 0.0.32 2022-12-13 22:03:48 +03:00
7fda16b63c Добавил настройку прокси для telegram 2022-12-13 18:34:42 +03:00
4b2175b0df v.0.0.41 2022-12-12 14:06:12 +03:00
eb975568a7 v.0.0.40 2022-12-12 10:27:59 +03:00
3ec635eb77 Рефакторгин пре-процессинга перед отправкой сообщения 2022-12-12 10:25:13 +03:00
78cc771852 Исправил SenderStorageService на SenderRepository 2022-12-09 22:06:59 +03:00
375ee3255b Поправил преобразование ссылки из сообщения в LinkAttachment 2022-12-07 12:20:45 +03:00
3a46f953ee Переход на string вместо long для telegramId 2022-12-04 11:46:36 +03:00
0ac055b488 release-0.0.34 2022-09-19 20:21:31 +03:00
6e4837a8e7 Добавил реактивную версию для Quarkus 2022-08-07 07:09:04 +03:00
95a8084cae Разделение на модули 2022-08-02 21:56:19 +03:00
98bed43267 Добавил поддержку команд 2022-07-30 10:31:31 +03:00
54e1fad49b Добавил новый тип вложения - ссылка 2022-07-26 09:31:39 +03:00
83b9de8b8b Актуализировал версию godfather 2022-07-21 00:50:57 +03:00
e463aa0731 Исправил срабатывание бота на уведомления в групповых чатах 2022-07-19 21:51:21 +03:00
35167a00d2 Исправил срабатывание бота на уведомления в групповых чатах 2022-07-19 20:53:59 +03:00
bf8ba844cf Доработки для загрузки фото 2022-07-19 20:37:29 +03:00
fb240a7b36 Добавил новый тип получения файлов ByteContainer. [ci skip] 2022-07-18 19:51:03 +03:00
1c43f1d797 Добавил два eventproviders для подписки и отписки 2022-07-15 17:48:49 +03:00
3e8989b64e Актуализировал версию godfather 2022-07-15 10:30:40 +03:00
a95db60945 Актуализировал версию godfather 2022-07-13 20:40:25 +03:00
1a6c801e9c Актуализировал с godfatherbot 2022-07-10 00:31:29 +03:00
83 changed files with 3736 additions and 619 deletions

68
.drone.yml Normal file
View File

@ -0,0 +1,68 @@
---
kind: pipeline
type: docker
name: snapshot-publish
trigger:
branch:
- develop
volumes:
- name: m2
host:
path: /drone/volume/m2
steps:
- name: publish
image: maven:3.8.5-openjdk-17
privileged: true
volumes:
- name: m2
path: /root/.m2/repository
environment:
MAVEN_SETTINGS:
from_secret: MAVEN_SETTINGS
commands:
- echo "$MAVEN_SETTINGS" >> maven-settings.xml
- mvn --settings maven-settings.xml -U -P snapshot clean deploy
---
kind: pipeline
type: docker
name: release-publish
trigger:
ref:
- refs/tags/v.*.*.*
volumes:
- name: m2
host:
path: /drone/volume/m2
steps:
- name: publish maven central
image: maven:3.8.5-openjdk-17
privileged: true
volumes:
- name: m2
path: /root/.m2/repository
environment:
GPG_PRIVATE_KEY:
from_secret: GPG_PRIVATE_KEY
MAVEN_SETTINGS:
from_secret: MAVEN_SETTINGS
GPG_PASSPHRASE:
from_secret: GPG_PASSPHRASE
commands:
- echo "$GPG_PRIVATE_KEY" >> gpg.key
- echo "$MAVEN_SETTINGS" >> maven-settings.xml
- gpg --pinentry-mode loopback --passphrase $GPG_PASSPHRASE --import gpg.key
- mvn --settings maven-settings.xml -U -P ossrh,release clean deploy
---
kind: signature
hmac: b723bf6653b2825acdb1de24d88acc510d58c7336f642e71ed0ba0489a7066eb
...

View File

@ -1,17 +0,0 @@
image: maven:3.8.5-openjdk-17
variables:
MAVEN_OPTS: "-Dmaven.repo.local=./.m2/repository"
stages:
- deploy
deploy:
stage: deploy
only:
- /^v.*$/
except:
- branches
before_script:
- gpg --pinentry-mode loopback --passphrase $GPG_PASSPHRASE --import $GPG_PRIVATE_KEY
script:
- 'mvn --settings $MAVEN_SETTINGS -U -P ossrh,release clean deploy'

View File

@ -1,20 +0,0 @@
postgres:
image: 192.168.235.157:8182/postgres:13.1-alpine
container_name: theater-postgres
hostname: postgres
restart: on-failure
networks:
- network
ports:
- 5433:5432
volumes:
- ./volume/db/01-init.sh:/docker-entrypoint-initdb.d/01-init.sh
- ./volume/db/storage:/var/lib/postgresql/data:z
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- APP_DB_USER=${DATASOURCE_USERNAME}
- APP_DB_PASS=${DATASOURCE_PASSWORD}
volumes:
gitlab-notify:

259
pom.xml
View File

@ -3,13 +3,18 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.struchkov.godfather</groupId>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-bot</artifactId>
<version>0.0.10</version>
<version>0.0.48-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>telegram-core</module>
<module>telegram-sender</module>
<module>telegram-domain</module>
<module>telegram-consumer</module>
<module>telegram-context</module>
<module>telegram-simple</module>
</modules>
<name>Telegram Bot</name>
@ -33,29 +38,174 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<godfather.core.ver>0.0.8</godfather.core.ver>
<telegrambots.ver>6.1.0</telegrambots.ver>
<godfather.core.ver>0.0.42-SNAPSHOT</godfather.core.ver>
<telegrambots.ver>6.3.0</telegrambots.ver>
<haiti.version>2.0.0</haiti.version>
<plugin.maven.compiler.ver>3.10.1</plugin.maven.compiler.ver>
<plugin.nexus.staging.ver>1.6.13</plugin.nexus.staging.ver>
<plugin.maven.source.ver>3.2.1</plugin.maven.source.ver>
<plugin.maven.javadoc.ver>3.4.0</plugin.maven.javadoc.ver>
<plugin.maven.gpg.ver>3.0.1</plugin.maven.gpg.ver>
<plugin.maven.release.ver>3.0.0-M7</plugin.maven.release.ver>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-domain</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-main</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-simple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-quarkus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-main</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-simple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-quarkus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer-main</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer-simple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer-quarkus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender-main</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender-simple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender-quarkus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-quarkus-reactive-sender</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-simple-sender</artifactId>
<version>${project.version}</version>
</dependency>
<!--godfather-->
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-core</artifactId>
<artifactId>bot-domain-main</artifactId>
<version>${godfather.core.ver}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context-main</artifactId>
<version>${godfather.core.ver}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context-simple</artifactId>
<version>${godfather.core.ver}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context-quarkus</artifactId>
<version>${godfather.core.ver}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-core-main</artifactId>
<version>${godfather.core.ver}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-core-simple</artifactId>
<version>${godfather.core.ver}</version>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-core-quarkus</artifactId>
<version>${godfather.core.ver}</version>
</dependency>
<!--/godfather-->
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-utils</artifactId>
<version>${haiti.version}</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
<version>${telegrambots.ver}</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId>
<version>${telegrambots.ver}</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
@ -79,11 +229,6 @@
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>${plugin.nexus.staging.ver}</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -134,6 +279,19 @@
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>${plugin.maven.release.ver}</version>
<configuration>
<preparationGoals>clean compile</preparationGoals>
<goal>install</goal>
<tagNameFormat>v.@{project.version}</tagNameFormat>
<autoVersionSubmodules>true</autoVersionSubmodules>
<pushChanges>false</pushChanges>
<localCheckout>true</localCheckout>
</configuration>
</plugin>
</plugins>
</pluginManagement>
@ -150,6 +308,10 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
</plugin>
</plugins>
</build>
@ -161,6 +323,11 @@
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -177,27 +344,83 @@
</plugins>
</build>
</profile>
<profile>
<id>snapshot</id>
<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<configuration>
<serverId>struchkov-nexus</serverId>
<nexusUrl>https://nexus.struchkov.dev/nexus/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<scm>
<connection>scm:git:https://github.com/Godfather-Bots/telegram-bot.git</connection>
<url>https://github.com/Godfather-Bots/telegram-bot</url>
<developerConnection>scm:git:https://github.com/Godfather-Bots/telegram-bot.git</developerConnection>
</scm>
<repositories>
<repository>
<id>struchkov-nexus-release</id>
<url>https://nexus.struchkov.dev/repository/maven-releases/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>struchkov-nexus-snapshot</id>
<url>https://nexus.struchkov.dev/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>struchkov-nexus-release</id>
<url>https://nexus.struchkov.dev/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
<id>struchkov-nexus-snapshot</id>
<url>https://nexus.struchkov.dev/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
<scm>
<connection>scm:git:https://git.struchkov.dev/Godfather-Bots/telegram-bot.git</connection>
<url>https://git.struchkov.dev/Godfather-Bots/telegram-bot</url>
<developerConnection>scm:git:https://git.struchkov.dev/Godfather-Bots/telegram-bot.git</developerConnection>
<tag>HEAD</tag>
</scm>
<developers>
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>mark@struchkov.dev</email>
<url>https://struchkov.dev</url>
<url>https://mark.struchkov.dev</url>
</developer>
</developers>

23
telegram-consumer/pom.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>telegram-bot</artifactId>
<groupId>dev.struchkov.godfather.telegram</groupId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-consumer</artifactId>
<packaging>pom</packaging>
<modules>
<module>telegram-consumer-main</module>
<module>telegram-consumer-simple</module>
<module>telegram-consumer-quarkus</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-consumer-main</artifactId>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-domain</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,50 @@
package dev.struchkov.godfather.telegram.main.consumer;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.telegram.domain.attachment.ButtonClickAttachment;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.User;
import java.time.LocalDateTime;
/**
* TODO: Добавить описание класса.
*
* @author upagge [02.02.2020]
*/
public class CallbackQueryConvert {
public static Mail apply(CallbackQuery callbackQuery) {
final String callbackData = callbackQuery.getData();
final Mail mail = new Mail();
mail.setCreateDate(LocalDateTime.now());
mail.setText(callbackData);
mail.addAttachment(convertToButtonClick(callbackData, callbackQuery.getMessage().getMessageId()));
final Long chatId = callbackQuery.getMessage().getChatId();
mail.setPersonId(chatId != null ? chatId.toString() : null);
final User user = callbackQuery.getFrom();
mail.setFirstName(user.getFirstName());
mail.setLastName(user.getLastName());
return mail;
}
private static ButtonClickAttachment convertToButtonClick(String callbackData, Integer messageId) {
final ButtonClickAttachment buttonClickAttachment = new ButtonClickAttachment();
buttonClickAttachment.setRawCallBackData(callbackData);
buttonClickAttachment.setMessageId(messageId);
if (callbackData.charAt(0) == '[' && callbackData.charAt(callbackData.length() - 1) == ']') {
final String[] args = callbackData.substring(1, callbackData.length() - 1).split(";");
for (String arg : args) {
final String[] oneArg = arg.split(":");
final String key = oneArg[0];
final String value = oneArg[1];
buttonClickAttachment.addClickArg(key, value);
}
}
return buttonClickAttachment;
}
}

View File

@ -0,0 +1,150 @@
package dev.struchkov.godfather.telegram.main.consumer;
import dev.struchkov.godfather.main.domain.content.Attachment;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.ContactAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.DocumentAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.LinkAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.Picture;
import dev.struchkov.godfather.telegram.domain.attachment.PictureGroupAttachment;
import dev.struchkov.haiti.utils.Checker;
import dev.struchkov.haiti.utils.Strings;
import org.telegram.telegrambots.meta.api.objects.Contact;
import org.telegram.telegrambots.meta.api.objects.Document;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.MessageEntity;
import org.telegram.telegrambots.meta.api.objects.PhotoSize;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
/**
* TODO: Добавить описание класса.
*
* @author upagge [18.08.2019]
*/
public final class MessageMailConvert {
private MessageMailConvert() {
utilityClass();
}
public static Mail apply(Message message) {
final Mail mail = new Mail();
final Long chatId = message.getChatId();
mail.setPersonId(chatId != null ? chatId.toString() : null);
mail.setText(message.getText());
mail.setCreateDate(LocalDateTime.ofInstant(Instant.ofEpochSecond(message.getDate()), ZoneId.systemDefault()));
mail.setFirstName(message.getChat().getFirstName());
mail.setLastName(message.getChat().getLastName());
convertDocument(message.getDocument()).ifPresent(mail::addAttachment);
convertContact(message.getContact()).ifPresent(mail::addAttachment);
convertPhoto(message.getPhoto()).ifPresent(mail::addAttachment);
final List<MessageEntity> entities = message.getEntities();
if (entities != null) {
mail.addAttachments(convertAttachments(message));
}
if (message.getReplyToMessage() != null) {
mail.setForwardMail(Collections.singletonList(apply(message.getReplyToMessage())));
}
return mail;
}
private static Optional<Attachment> convertPhoto(List<PhotoSize> photoSizes) {
if (photoSizes != null && !photoSizes.isEmpty()) {
final PictureGroupAttachment attachment = new PictureGroupAttachment();
final List<Picture> pictures = photoSizes.stream()
.map(photoSize -> {
final Picture picture = new Picture();
picture.setFileSize(photoSize.getFileSize());
picture.setFileId(photoSize.getFileId());
picture.setHeight(photoSize.getHeight());
picture.setWeight(photoSize.getWidth());
picture.setFileUniqueId(photoSize.getFileUniqueId());
return picture;
}).toList();
attachment.setPictureSizes(pictures);
return Optional.of(attachment);
}
return Optional.empty();
}
private static Optional<ContactAttachment> convertContact(Contact contact) {
if (contact != null) {
final ContactAttachment attachment = new ContactAttachment();
attachment.setPhoneNumber(contact.getPhoneNumber());
attachment.setUserId(contact.getUserId());
attachment.setFirstName(contact.getFirstName());
attachment.setLastName(contact.getLastName());
if (contact.getVCard() != null) {
attachment.setOwner(false);
attachment.setVCard(contact.getVCard());
} else {
attachment.setOwner(true);
}
return Optional.of(attachment);
}
return Optional.empty();
}
private static Optional<DocumentAttachment> convertDocument(Document document) {
if (document != null) {
final DocumentAttachment attachment = new DocumentAttachment();
attachment.setFileId(document.getFileId());
attachment.setFileSize(document.getFileSize());
attachment.setFileName(document.getFileName());
attachment.setMimeType(document.getMimeType());
return Optional.of(attachment);
}
return Optional.empty();
}
private static List<Attachment> convertAttachments(Message message) {
final List<MessageEntity> entities = message.getEntities();
if (Checker.checkNotEmpty(entities)) {
return entities.stream()
.map(entity -> convertEntity(message, entity))
.filter(Optional::isPresent)
.map(Optional::get)
.toList();
}
return Collections.emptyList();
}
private static Optional<Attachment> convertEntity(Message message, MessageEntity entity) {
switch (entity.getType()) {
case "text_link" -> {
return Optional.of(new LinkAttachment(entity.getUrl()));
}
case "bot_command" -> {
final String commandValue = entity.getText();
String commandArg = message.getText().replace(commandValue, "");
if (Checker.checkNotEmpty(commandArg)) {
commandArg = commandArg.substring(1);
}
final CommandAttachment commandAttachment = new CommandAttachment();
commandAttachment.setValue(commandValue);
commandAttachment.setCommandType(commandValue.replace("/", ""));
commandAttachment.setArg(Strings.EMPTY.equals(commandArg) ? null : commandArg);
commandAttachment.setRawValue(message.getText());
return Optional.of(commandAttachment);
}
}
return Optional.empty();
}
}

View File

@ -0,0 +1,28 @@
package dev.struchkov.godfather.telegram.main.consumer;
import dev.struchkov.godfather.telegram.domain.event.Subscribe;
import org.telegram.telegrambots.meta.api.objects.Chat;
import org.telegram.telegrambots.meta.api.objects.ChatMemberUpdated;
import java.time.LocalDateTime;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
public final class SubscribeConvert {
private SubscribeConvert() {
utilityClass();
}
public static Subscribe apply(ChatMemberUpdated updated) {
final Chat chat = updated.getChat();
final Subscribe subscribe = new Subscribe();
subscribe.setTelegramId(chat.getId().toString());
subscribe.setLastName(chat.getLastName());
subscribe.setFirstName(chat.getFirstName());
subscribe.setSubscriptionDate(LocalDateTime.now());
return subscribe;
}
}

View File

@ -0,0 +1,28 @@
package dev.struchkov.godfather.telegram.main.consumer;
import dev.struchkov.godfather.telegram.domain.event.Unsubscribe;
import org.telegram.telegrambots.meta.api.objects.Chat;
import org.telegram.telegrambots.meta.api.objects.ChatMemberUpdated;
import java.time.LocalDateTime;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
public final class UnsubscribeConvert {
private UnsubscribeConvert() {
utilityClass();
}
public static Unsubscribe apply(ChatMemberUpdated updated) {
final Chat chat = updated.getChat();
final Unsubscribe unsubscribe = new Unsubscribe();
unsubscribe.setTelegramId(chat.getId().toString());
unsubscribe.setLastName(chat.getLastName());
unsubscribe.setFirstName(chat.getFirstName());
unsubscribe.setSubscriptionDate(LocalDateTime.now());
return unsubscribe;
}
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-consumer-quarkus</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-quarkus</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer-main</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-quarkus</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,126 @@
package dev.struchkov.godfather.telegram.quarkus.consumer;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.quarkus.context.service.EventHandler;
import dev.struchkov.godfather.telegram.domain.event.Subscribe;
import dev.struchkov.godfather.telegram.domain.event.Unsubscribe;
import dev.struchkov.godfather.telegram.main.consumer.CallbackQueryConvert;
import dev.struchkov.godfather.telegram.main.consumer.MessageMailConvert;
import dev.struchkov.godfather.telegram.main.consumer.SubscribeConvert;
import dev.struchkov.godfather.telegram.main.consumer.UnsubscribeConvert;
import dev.struchkov.godfather.telegram.quarkus.context.service.EventDistributor;
import dev.struchkov.godfather.telegram.quarkus.core.TelegramConnectBot;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.ChatMemberUpdated;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.api.objects.User;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
/**
* TODO: Добавить описание класса.
*
* @author upagge [30.01.2020]
*/
public class EventDistributorService implements EventDistributor {
private final Map<String, List<EventHandler>> eventHandlerMap;
public EventDistributorService(TelegramConnectBot telegramConnectBot, List<EventHandler> eventProviders) {
this.eventHandlerMap = eventProviders.stream().collect(Collectors.groupingBy(EventHandler::getEventType));
telegramConnectBot.initEventDistributor(this);
}
@Override
public Uni<Void> processing(@NotNull Update update) {
return Uni.createFrom().voidItem()
.onItem().transformToUni(
v -> {
if (checkNotNull(update.getMessage())) {
final Message message = update.getMessage();
if (!isEvent(message)) {
final Optional<List<EventHandler>> optHandlers = getHandler(Mail.TYPE);
if (optHandlers.isPresent()) {
return Multi.createFrom().iterable(optHandlers.get())
.onItem().transformToUni(
eventHandler -> eventHandler.handle(MessageMailConvert.apply(message))
).concatenate().toUni().replaceWithVoid();
}
return Uni.createFrom().voidItem();
}
}
if (checkNotNull(update.getCallbackQuery())) {
final CallbackQuery callbackQuery = update.getCallbackQuery();
final Optional<List<EventHandler>> optHandlers = getHandler(Mail.TYPE);
if (optHandlers.isPresent()) {
return Multi.createFrom().iterable(optHandlers.get())
.onItem().transformToUni(
eventHandler -> eventHandler.handle(CallbackQueryConvert.apply(callbackQuery))
).concatenate().toUni().replaceWithVoid();
}
return Uni.createFrom().voidItem();
}
if (checkNotNull(update.getMyChatMember())) {
final ChatMemberUpdated chatMember = update.getMyChatMember();
if ("kicked".equals(chatMember.getNewChatMember().getStatus())) {
final Optional<List<EventHandler>> optHandlers = getHandler(Unsubscribe.TYPE);
if (optHandlers.isPresent()) {
return Multi.createFrom().iterable(optHandlers.get())
.onItem().transformToUni(
eventHandler -> eventHandler.handle(UnsubscribeConvert.apply(chatMember))
).concatenate().toUni().replaceWithVoid();
}
return Uni.createFrom().voidItem();
}
if ("member".equals(chatMember.getNewChatMember().getStatus())) {
final Optional<List<EventHandler>> optHandlers = getHandler(Subscribe.TYPE);
if (optHandlers.isPresent()) {
return Multi.createFrom().iterable(optHandlers.get())
.onItem().transformToUni(
eventHandler -> eventHandler.handle(SubscribeConvert.apply(chatMember))
).concatenate().toUni().replaceWithVoid();
}
return Uni.createFrom().voidItem();
}
}
return Uni.createFrom().voidItem();
}
);
}
private boolean isEvent(Message message) {
return message.getChannelChatCreated() != null
|| message.getDeleteChatPhoto() != null
|| isNewChatMember(message.getNewChatMembers())
|| message.getNewChatTitle() != null
|| message.getNewChatPhoto() != null
|| message.getVideoChatEnded() != null
|| message.getVideoChatParticipantsInvited() != null
|| message.getVideoChatScheduled() != null
|| message.getVideoNote() != null
|| message.getVideoChatStarted() != null;
}
private boolean isNewChatMember(List<User> newChatMembers) {
if (newChatMembers == null) {
return true;
} else {
return !newChatMembers.isEmpty();
}
}
private Optional<List<EventHandler>> getHandler(String type) {
return Optional.ofNullable(eventHandlerMap.get(type));
}
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-consumer-simple</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-simple</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer-main</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-simple</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,95 @@
package dev.struchkov.godfather.telegram.simple.consumer;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.simple.context.service.EventHandler;
import dev.struchkov.godfather.telegram.domain.event.Subscribe;
import dev.struchkov.godfather.telegram.domain.event.Unsubscribe;
import dev.struchkov.godfather.telegram.main.consumer.CallbackQueryConvert;
import dev.struchkov.godfather.telegram.main.consumer.MessageMailConvert;
import dev.struchkov.godfather.telegram.main.consumer.SubscribeConvert;
import dev.struchkov.godfather.telegram.main.consumer.UnsubscribeConvert;
import dev.struchkov.godfather.telegram.simple.context.service.EventDistributor;
import dev.struchkov.godfather.telegram.simple.core.TelegramConnectBot;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.ChatMemberUpdated;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.api.objects.User;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* TODO: Добавить описание класса.
*
* @author upagge [30.01.2020]
*/
public class EventDistributorService implements EventDistributor {
private final Map<String, List<EventHandler>> eventProviderMap;
public EventDistributorService(TelegramConnectBot telegramConnectBot, List<EventHandler> eventProviders) {
this.eventProviderMap = eventProviders.stream().collect(Collectors.groupingBy(EventHandler::getEventType));
telegramConnectBot.initEventDistributor(this);
}
@Override
public void processing(@NotNull Update update) {
if (update.getMessage() != null) {
final Message message = update.getMessage();
if (!isEvent(message)) {
getHandler(Mail.TYPE)
.ifPresent(eventProviders -> eventProviders.forEach(eventProvider -> eventProvider.handle(MessageMailConvert.apply(message))));
return;
}
}
if (update.getCallbackQuery() != null) {
final CallbackQuery callbackQuery = update.getCallbackQuery();
getHandler(Mail.TYPE)
.ifPresent(eventProviders -> eventProviders.forEach(eventProvider -> eventProvider.handle(CallbackQueryConvert.apply(callbackQuery))));
return;
}
if (update.getMyChatMember() != null) {
final ChatMemberUpdated chatMember = update.getMyChatMember();
if ("kicked".equals(chatMember.getNewChatMember().getStatus())) {
getHandler(Unsubscribe.TYPE)
.ifPresent(providers -> providers.forEach(provider -> provider.handle(UnsubscribeConvert.apply(chatMember))));
return;
}
if ("member".equals(chatMember.getNewChatMember().getStatus())) {
getHandler(Subscribe.TYPE)
.ifPresent(eventProviders -> eventProviders.forEach(eventProvider -> eventProvider.handle(SubscribeConvert.apply(chatMember))));
return;
}
}
}
private boolean isEvent(Message message) {
return message.getChannelChatCreated() != null
|| message.getDeleteChatPhoto() != null
|| isNewChatMember(message.getNewChatMembers())
|| message.getNewChatTitle() != null
|| message.getNewChatPhoto() != null
|| message.getVideoChatEnded() != null
|| message.getVideoChatParticipantsInvited() != null
|| message.getVideoChatScheduled() != null
|| message.getVideoNote() != null
|| message.getVideoChatStarted() != null;
}
private boolean isNewChatMember(List<User> newChatMembers) {
if (newChatMembers == null) {
return true;
} else {
return !newChatMembers.isEmpty();
}
}
private Optional<List<EventHandler>> getHandler(String type) {
return Optional.ofNullable(eventProviderMap.get(type));
}
}

23
telegram-context/pom.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>telegram-bot</artifactId>
<groupId>dev.struchkov.godfather.telegram</groupId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-context</artifactId>
<packaging>pom</packaging>
<modules>
<module>telegram-context-main</module>
<module>telegram-context-simple</module>
<module>telegram-context-quarkus</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-context-main</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-domain</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,11 @@
package dev.struchkov.godfather.telegram.main.context;
import org.telegram.telegrambots.meta.bots.AbsSender;
public interface TelegramConnect {
AbsSender getAbsSender();
String getToken();
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-context-quarkus</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context-quarkus</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-main</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package dev.struchkov.godfather.telegram.quarkus.context.repository;
import io.smallrye.mutiny.Uni;
public interface SenderRepository {
Uni<Integer> getLastSendMessage(String telegramId);
Uni<Void> saveLastSendMessage(String telegramId, Integer messageId);
Uni<Void> removeLastSendMessage(String telegramId);
}

View File

@ -0,0 +1,13 @@
package dev.struchkov.godfather.telegram.quarkus.context.service;
import io.smallrye.mutiny.Uni;
import org.telegram.telegrambots.meta.api.objects.Update;
import javax.validation.constraints.NotNull;
public interface EventDistributor {
Uni<Void> processing(@NotNull Update update);
}

View File

@ -0,0 +1,18 @@
package dev.struchkov.godfather.telegram.quarkus.context.service;
import org.telegram.telegrambots.meta.bots.AbsSender;
import javax.validation.constraints.NotNull;
/**
* TODO: Добавить описание интерфейса.
*
* @author upagge [12.02.2020]
*/
public interface TelegramBot {
AbsSender getAdsSender();
void initEventDistributor(@NotNull EventDistributor eventDistributor);
}

View File

@ -0,0 +1,13 @@
package dev.struchkov.godfather.telegram.quarkus.context.service;
import dev.struchkov.godfather.main.domain.BoxAnswer;
import dev.struchkov.godfather.main.domain.SentBox;
import dev.struchkov.godfather.quarkus.context.service.SendingService;
import io.smallrye.mutiny.Uni;
import org.jetbrains.annotations.NotNull;
public interface TelegramSending extends SendingService<Integer> {
Uni<SentBox<Integer>> sendNotSave(@NotNull BoxAnswer boxAnswer);
}

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>telegram-context</artifactId>
<groupId>dev.struchkov.godfather.telegram</groupId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-context-simple</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-main</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context-simple</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package dev.struchkov.godfather.telegram.simple.context.repository;
import java.util.Optional;
public interface SenderRepository {
Optional<Integer> getLastSendMessage(String telegramId);
void saveLastSendMessage(String telegramId, Integer messageId);
void removeLastSendMessage(String telegramId);
}

View File

@ -1,8 +1,9 @@
package dev.struchkov.godfather.telegram.listen;
package dev.struchkov.godfather.telegram.simple.context.service;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.meta.api.objects.Update;
import javax.validation.constraints.NotNull;
public interface EventDistributor {
void processing(@NotNull Update update);

View File

@ -0,0 +1,18 @@
package dev.struchkov.godfather.telegram.simple.context.service;
import org.telegram.telegrambots.meta.bots.AbsSender;
import javax.validation.constraints.NotNull;
/**
* TODO: Добавить описание интерфейса.
*
* @author upagge [12.02.2020]
*/
public interface TelegramBot {
AbsSender getAdsSender();
void initEventDistributor(@NotNull EventDistributor eventDistributor);
}

View File

@ -0,0 +1,14 @@
package dev.struchkov.godfather.telegram.simple.context.service;
import dev.struchkov.godfather.main.domain.BoxAnswer;
import dev.struchkov.godfather.main.domain.SentBox;
import dev.struchkov.godfather.simple.context.service.SendingService;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public interface TelegramSending extends SendingService<Integer> {
Optional<SentBox<Integer>> sendNotSave(@NotNull BoxAnswer boxAnswer);
}

View File

@ -1,38 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather</groupId>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-bot</artifactId>
<version>0.0.10</version>
<version>0.0.48-SNAPSHOT</version>
</parent>
<modules>
<module>telegram-core-main</module>
<module>telegram-core-simple</module>
<module>telegram-core-quarkus</module>
</modules>
<artifactId>telegram-core</artifactId>
<packaging>pom</packaging>
<name>Telegram Core</name>
<description>Allows you to create bots for Telegram</description>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-core</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-abilities</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambotsextensions</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,18 +0,0 @@
package dev.struchkov.godfather.telegram;
import dev.struchkov.godfather.telegram.listen.EventDistributorService;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.meta.bots.AbsSender;
/**
* TODO: Добавить описание интерфейса.
*
* @author upagge [12.02.2020]
*/
public interface TelegramBot {
AbsSender getAdsSender();
void initEventDistributor(@NotNull EventDistributorService eventDistributor);
}

View File

@ -1,27 +0,0 @@
package dev.struchkov.godfather.telegram.autoresponder;
import dev.struchkov.godfather.context.domain.content.Mail;
import dev.struchkov.godfather.context.service.PersonSettingService;
import dev.struchkov.godfather.context.service.UnitPointerService;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.core.GeneralAutoResponder;
import java.util.List;
/**
* TODO: Добавить описание класса.
*
* @author upagge [18.08.2019]
*/
public class MessageAutoresponderTelegram extends GeneralAutoResponder<Mail> {
public MessageAutoresponderTelegram(
Sending sending,
PersonSettingService personSettingService,
UnitPointerService unitPointerService,
List<Object> unitConfigurations
) {
super(sending, personSettingService, unitPointerService, unitConfigurations);
}
}

View File

@ -1,28 +0,0 @@
package dev.struchkov.godfather.telegram.convert;
import dev.struchkov.godfather.context.domain.content.Mail;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.User;
import java.time.LocalDateTime;
/**
* TODO: Добавить описание класса.
*
* @author upagge [02.02.2020]
*/
public class CallbackQueryConvert {
public static Mail apply(CallbackQuery callbackQuery) {
final Mail mail = new Mail();
mail.setText(callbackQuery.getData());
mail.setPersonId(callbackQuery.getMessage().getChatId());
mail.setAddDate(LocalDateTime.now());
final User user = callbackQuery.getFrom();
mail.setFirstName(user.getFirstName());
mail.setLastName(user.getLastName());
return mail;
}
}

View File

@ -1,63 +0,0 @@
package dev.struchkov.godfather.telegram.convert;
import dev.struchkov.godfather.context.domain.content.Mail;
import dev.struchkov.godfather.context.domain.content.attachment.Attachment;
import dev.struchkov.godfather.context.domain.content.attachment.Link;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.MessageEntity;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
/**
* TODO: Добавить описание класса.
*
* @author upagge [18.08.2019]
*/
public final class MessageMailConvert {
public MessageMailConvert() {
utilityClass();
}
public static Mail apply(Message message) {
final Mail mail = new Mail();
mail.setPersonId(message.getChatId());
mail.setAddDate(LocalDateTime.now());
mail.setText(message.getText());
mail.setCreateDate(LocalDateTime.ofInstant(Instant.ofEpochSecond(message.getDate()), ZoneId.systemDefault()));
mail.setFirstName(message.getChat().getFirstName());
mail.setLastName(message.getChat().getLastName());
final List<MessageEntity> entities = message.getEntities();
if (entities != null) {
mail.setAttachments(convertAttachments(entities));
}
if (message.getReplyToMessage() != null) {
mail.setForwardMail(Collections.singletonList(apply(message.getReplyToMessage())));
}
return mail;
}
private static List<Attachment> convertAttachments(List<MessageEntity> entities) {
final List<Attachment> attachments = new ArrayList<>();
for (MessageEntity entity : entities) {
String type = entity.getType();
if ("text_link".equals(type)) {
Link link = new Link();
link.setUrl(entity.getUrl());
attachments.add(link);
}
}
return attachments;
}
}

View File

@ -1,33 +0,0 @@
package dev.struchkov.godfather.telegram.domain.keyboard.button;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton;
public class ButtonUrl implements KeyBoardButton {
public static final String TYPE = "URL";
private String label;
private String url;
public ButtonUrl(String label, String url) {
this.label = label;
this.url = url;
}
public static ButtonUrl buttonUrl(String label, String url) {
return new ButtonUrl(label, url);
}
@Override
public String getType() {
return TYPE;
}
public String getLabel() {
return label;
}
public String getUrl() {
return url;
}
}

View File

@ -1,40 +0,0 @@
package dev.struchkov.godfather.telegram.listen;
import dev.struchkov.godfather.context.domain.content.Mail;
import dev.struchkov.godfather.context.service.EventProvider;
import dev.struchkov.godfather.telegram.convert.CallbackQueryConvert;
import dev.struchkov.godfather.telegram.convert.MessageMailConvert;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import java.util.List;
/**
* TODO: Добавить описание класса.
*
* @author upagge [30.01.2020]
*/
public class EventDistributorService implements EventDistributor {
private final List<EventProvider<Mail>> eventProviders;
public EventDistributorService(TelegramConnect telegramConnect, List<EventProvider<Mail>> eventProviders) {
this.eventProviders = eventProviders;
telegramConnect.initEventDistributor(this);
}
@Override
public void processing(@NotNull Update update) {
final Message message = update.getMessage();
final CallbackQuery callbackQuery = update.getCallbackQuery();
if (message != null) {
eventProviders.forEach(provider -> provider.sendEvent(MessageMailConvert.apply(message)));
}
if (callbackQuery != null) {
eventProviders.forEach(provider -> provider.sendEvent(CallbackQueryConvert.apply(callbackQuery)));
}
}
}

View File

@ -1,225 +0,0 @@
package dev.struchkov.godfather.telegram.listen;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoard;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardLine;
import dev.struchkov.godfather.context.domain.keyboard.button.SimpleButton;
import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoard;
import dev.struchkov.godfather.context.service.sender.SendType;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
import dev.struchkov.godfather.telegram.domain.keyboard.MarkupKeyBoard;
import dev.struchkov.godfather.telegram.domain.keyboard.button.ButtonUrl;
import dev.struchkov.godfather.telegram.domain.keyboard.button.ButtonWebApp;
import dev.struchkov.godfather.telegram.service.SendPreProcessing;
import dev.struchkov.haiti.context.exception.ConvertException;
import dev.struchkov.haiti.utils.Inspector;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardButton;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow;
import org.telegram.telegrambots.meta.api.objects.webapp.WebAppInfo;
import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
/**
* TODO: Добавить описание класса.
*
* @author upagge [15/07/2019]
*/
public class TelegramSender implements Sending {
private static final Logger log = LoggerFactory.getLogger(TelegramSender.class);
private static final String ERROR_REPLACE_MESSAGE = "Bad Request: message to edit not found";
private final AbsSender absSender;
private Map<Long, Integer> map = new HashMap<>();
private SendPreProcessing sendPreProcessing;
public TelegramSender(TelegramConnect telegramConnect) {
this.absSender = telegramConnect.getAdsSender();
}
public void setSendPreProcessing(SendPreProcessing sendPreProcessing) {
this.sendPreProcessing = sendPreProcessing;
}
public void send(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) {
isNotNull(telegramId, boxAnswer);
try {
if (boxAnswer.isReplace() && map.containsKey(telegramId)) {
replaceMessage(telegramId, boxAnswer);
} else {
sendMessage(telegramId, boxAnswer);
}
} catch (TelegramApiRequestException e) {
log.error(e.getApiResponse());
if (ERROR_REPLACE_MESSAGE.equals(e.getApiResponse())) {
sendMessage(telegramId, boxAnswer);
}
} catch (TelegramApiException e) {
log.error(e.getMessage());
}
}
private void replaceMessage(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) throws TelegramApiException {
final EditMessageText editMessageText = new EditMessageText();
editMessageText.setChatId(String.valueOf(telegramId));
editMessageText.setMessageId(map.get(telegramId));
editMessageText.enableMarkdown(true);
editMessageText.setText(boxAnswer.getMessage());
editMessageText.setReplyMarkup(convertInlineKeyBoard((InlineKeyBoard) boxAnswer.getKeyBoard()));
absSender.execute(editMessageText);
}
private void sendMessage(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) {
final SendMessage sendMessage = new SendMessage();
sendMessage.enableMarkdown(true);
sendMessage.setChatId(String.valueOf(telegramId));
sendMessage.setText(
sendPreProcessing != null
? sendPreProcessing.pretreatment(boxAnswer.getMessage())
: boxAnswer.getMessage()
);
sendMessage.setReplyMarkup(convertKeyBoard(boxAnswer.getKeyBoard()));
try {
final Message execute = absSender.execute(sendMessage);
map.put(telegramId, execute.getMessageId());
} catch (TelegramApiRequestException e) {
log.error(e.getApiResponse());
} catch (TelegramApiException e) {
log.error(e.getMessage());
}
}
private ReplyKeyboard convertKeyBoard(KeyBoard keyBoard) {
if (keyBoard != null) {
switch (keyBoard.getType()) {
case InlineKeyBoard.TYPE:
return convertInlineKeyBoard((InlineKeyBoard) keyBoard);
case MarkupKeyBoard.TYPE:
return convertMarkupKeyBoard((MarkupKeyBoard) keyBoard);
case SimpleKeyBoard.TYPE:
return convertSimpleKeyBoard((SimpleKeyBoard) keyBoard);
}
}
return null;
}
private ReplyKeyboard convertSimpleKeyBoard(SimpleKeyBoard keyBoard) {
final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup();
keyboardMarkup.setKeyboard(
keyBoard.getLines().stream()
.map(this::convertMarkupLine)
.toList()
);
return keyboardMarkup;
}
private ReplyKeyboard convertMarkupKeyBoard(MarkupKeyBoard keyBoard) {
if (keyBoard != null) {
final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup();
keyboardMarkup.setOneTimeKeyboard(keyBoard.isOneTime());
keyboardMarkup.setInputFieldPlaceholder(keyBoard.getInputFieldPlaceholder());
keyboardMarkup.setResizeKeyboard(keyBoard.isResizeKeyboard());
keyboardMarkup.setKeyboard(
keyBoard.getLines().stream()
.map(this::convertMarkupLine)
.toList()
);
return keyboardMarkup;
}
return null;
}
private InlineKeyboardMarkup convertInlineKeyBoard(InlineKeyBoard keyBoard) {
if (keyBoard != null) {
final InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();
inlineKeyboardMarkup.setKeyboard(
keyBoard.getLines().stream()
.map(this::convertInlineLine)
.toList()
);
return inlineKeyboardMarkup;
}
return null;
}
private List<InlineKeyboardButton> convertInlineLine(KeyBoardLine line) {
return line.getButtons().stream().map(this::convertInlineButton).toList();
}
private KeyboardRow convertMarkupLine(KeyBoardLine line) {
final List<KeyboardButton> buttons = line.getButtons().stream().map(this::convertMarkupButton).toList();
return new KeyboardRow(buttons);
}
private InlineKeyboardButton convertInlineButton(KeyBoardButton keyBoardButton) {
final InlineKeyboardButton button = new InlineKeyboardButton();
switch (keyBoardButton.getType()) {
case SimpleButton.TYPE -> {
final SimpleButton simpleButton = (SimpleButton) keyBoardButton;
final String callbackData = simpleButton.getCallbackData();
final String label = simpleButton.getLabel();
button.setText(label);
button.setCallbackData(callbackData != null ? callbackData : label);
}
case ButtonUrl.TYPE -> {
final ButtonUrl buttonUrl = (ButtonUrl) keyBoardButton;
button.setUrl(buttonUrl.getUrl());
button.setText(buttonUrl.getLabel());
}
case ButtonWebApp.TYPE -> {
final ButtonWebApp buttonWebApp = (ButtonWebApp) keyBoardButton;
final WebAppInfo webAppInfo = WebAppInfo.builder().url(buttonWebApp.getUrl()).build();
button.setWebApp(webAppInfo);
button.setText(buttonWebApp.getLabel());
}
default -> throw new ConvertException("Ошибка преобразования кнопки");
}
return button;
}
private KeyboardButton convertMarkupButton(KeyBoardButton keyBoardButton) {
final KeyboardButton button = new KeyboardButton();
switch (keyBoardButton.getType()) {
case SimpleButton.TYPE -> {
final SimpleButton simpleButton = (SimpleButton) keyBoardButton;
button.setText(simpleButton.getLabel());
Inspector.isNull(simpleButton.getCallbackData(), ConvertException.supplier("CallbackData поддерживает только Inline клавитаура"));
}
case ButtonWebApp.TYPE -> {
final ButtonWebApp buttonWebApp = (ButtonWebApp) keyBoardButton;
final WebAppInfo webAppInfo = WebAppInfo.builder().url(buttonWebApp.getUrl()).build();
button.setText(buttonWebApp.getLabel());
button.setWebApp(webAppInfo);
}
default -> throw new ConvertException("Ошибка преобразования кнопки");
}
return button;
}
public SendType getType() {
return SendType.PRIVATE;
}
}

View File

@ -1,13 +0,0 @@
package dev.struchkov.godfather.telegram.service;
/**
* // TODO: 18.09.2020 Добавить описание.
*
* @author upagge 18.09.2020
*/
@FunctionalInterface
public interface SendPreProcessing {
String pretreatment(String messageText);
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-core-main</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-main</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,83 @@
package dev.struchkov.godfather.telegram.main.core;
import dev.struchkov.godfather.telegram.domain.config.ProxyConfig;
import dev.struchkov.godfather.telegram.domain.config.TelegramConnectConfig;
import dev.struchkov.godfather.telegram.main.context.TelegramConnect;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.bots.DefaultAbsSender;
import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.meta.bots.AbsSender;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
public class TelegramDefaultConnect implements TelegramConnect {
private final String botToken;
private final AbsSender absSender;
public TelegramDefaultConnect(TelegramConnectConfig connectConfig) {
this.botToken = connectConfig.getBotToken();
this.absSender = createAbsSender(connectConfig);
}
@NotNull
private DefaultAbsSender createAbsSender(TelegramConnectConfig connectConfig) {
final DefaultBotOptions botOptions = new DefaultBotOptions();
final ProxyConfig proxyConfig = connectConfig.getProxyConfig();
if (checkNotNull(proxyConfig) && proxyConfig.isEnable()) {
if (checkNotNull(proxyConfig.getPassword())) {
try {
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
proxyConfig.getUser(),
proxyConfig.getPassword().toCharArray()
);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
if (checkNotNull(proxyConfig.getHost())) {
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
// System.setProperty("javax.net.debug", "all");
botOptions.setProxyHost(proxyConfig.getHost());
botOptions.setProxyPort(proxyConfig.getPort());
botOptions.setProxyType(convertProxyType(proxyConfig.getType()));
}
}
return new DefaultAbsSender(botOptions) {
@Override
public String getBotToken() {
return botToken;
}
};
}
private DefaultBotOptions.ProxyType convertProxyType(ProxyConfig.Type type) {
return switch (type) {
case SOCKS5 -> DefaultBotOptions.ProxyType.SOCKS5;
case SOCKS4 -> DefaultBotOptions.ProxyType.SOCKS4;
case HTTP -> DefaultBotOptions.ProxyType.HTTP;
};
}
@Override
public AbsSender getAbsSender() {
return absSender;
}
@Override
public String getToken() {
return botToken;
}
}

View File

@ -0,0 +1,156 @@
package dev.struchkov.godfather.telegram.main.core.util;
import dev.struchkov.godfather.main.domain.content.Attachment;
import dev.struchkov.godfather.telegram.domain.attachment.ButtonClickAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.ContactAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.DocumentAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.LinkAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.Picture;
import dev.struchkov.godfather.telegram.domain.attachment.PictureGroupAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.TelegramAttachmentType;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static dev.struchkov.haiti.utils.Checker.checkNotEmpty;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
public final class Attachments {
private Attachments() {
utilityClass();
}
public static List<LinkAttachment> findAllLinks(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
return attachments.stream()
.filter(Attachments::isLink)
.map(LinkAttachment.class::cast)
.toList();
}
return Collections.emptyList();
}
public static Optional<LinkAttachment> findFirstLink(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
for (Attachment attachment : attachments) {
if (isLink(attachment)) {
return Optional.of((LinkAttachment) attachment);
}
}
}
return Optional.empty();
}
public static Optional<ButtonClickAttachment> findFirstButtonClick(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
for (Attachment attachment : attachments) {
if (isButtonClick(attachment)) {
return Optional.of((ButtonClickAttachment) attachment);
}
}
}
return Optional.empty();
}
public static Optional<PictureGroupAttachment> findFirstPictureGroup(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
for (Attachment attachment : attachments) {
if (isPictureGroup(attachment)) {
return Optional.of((PictureGroupAttachment) attachment);
}
}
}
return Optional.empty();
}
public static Optional<Picture> findFirstLargePicture(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
for (Attachment attachment : attachments) {
if (isPictureGroup(attachment)) {
final PictureGroupAttachment pictureGroup = (PictureGroupAttachment) attachment;
return pictureGroup.getLargePicture();
}
}
}
return Optional.empty();
}
public static Optional<DocumentAttachment> findFirstDocument(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
for (Attachment attachment : attachments) {
if (isDocument(attachment)) {
return Optional.of((DocumentAttachment) attachment);
}
}
}
return Optional.empty();
}
public static Optional<ContactAttachment> findFirstContact(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
for (Attachment attachment : attachments) {
if (isContact(attachment)) {
return Optional.of((ContactAttachment) attachment);
}
}
}
return Optional.empty();
}
public static Optional<CommandAttachment> findFirstCommand(Collection<Attachment> attachments) {
if (checkNotEmpty(attachments)) {
for (Attachment attachment : attachments) {
if (isCommand(attachment)) {
return Optional.of((CommandAttachment) attachment);
}
}
}
return Optional.empty();
}
public static boolean hasDocument(Collection<Attachment> attachments) {
isNotNull(attachments);
for (Attachment attachment : attachments) {
if (isDocument(attachment)) {
return true;
}
}
return false;
}
public static boolean isCommand(Attachment attachment) {
isNotNull(attachment);
return TelegramAttachmentType.COMMAND.name().equals(attachment.getType());
}
public static boolean isDocument(Attachment attachment) {
isNotNull(attachment);
return TelegramAttachmentType.DOCUMENT.name().equals(attachment.getType());
}
private static boolean isContact(Attachment attachment) {
isNotNull(attachment);
return TelegramAttachmentType.CONTACT.name().equals(attachment.getType());
}
private static boolean isPictureGroup(Attachment attachment) {
isNotNull(attachment);
return TelegramAttachmentType.PICTURE.name().equals(attachment.getType());
}
private static boolean isLink(Attachment attachment) {
isNotNull(attachment);
return TelegramAttachmentType.LINK.name().equals(attachment.getType());
}
public static boolean isButtonClick(Attachment attachment) {
isNotNull(attachment);
return TelegramAttachmentType.BUTTON_CLICK.name().equals(attachment.getType());
}
}

View File

@ -1,24 +1,24 @@
package dev.struchkov.godfather.telegram.utils;
package dev.struchkov.godfather.telegram.main.core.util;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.context.domain.keyboard.button.SimpleButton;
import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoard;
import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoardLine;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton;
import dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoard;
import dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine;
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
import java.util.Arrays;
import java.util.List;
import static dev.struchkov.godfather.context.domain.keyboard.button.SimpleButton.simpleButton;
import static dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
public final class InlineKeyBoards {
public static final SimpleButton YES_BUTTON = simpleButton("Да", "{\"button\": \"yes\"}");
public static final SimpleButton NO_BUTTON = simpleButton("Нет", "{\"button\": \"no\"}");
public static final SimpleButton YES_BUTTON = simpleButton("Да", "Да");
public static final SimpleButton NO_BUTTON = simpleButton("Нет", "Нет");
public InlineKeyBoards() {
private InlineKeyBoards() {
utilityClass();
}
@ -27,10 +27,8 @@ public final class InlineKeyBoards {
*
* @return {@link SimpleKeyBoard}
*/
public static InlineKeyBoard keyBoardYesNo() {
return InlineKeyBoard.inlineKeyBoard(
SimpleKeyBoardLine.builder().button(YES_BUTTON).button(NO_BUTTON).build()
);
public static SimpleKeyBoardLine lineYesOrNo() {
return simpleLine(YES_BUTTON, NO_BUTTON);
}
/**
@ -95,34 +93,42 @@ public final class InlineKeyBoards {
return keyBoard.build();
}
public static InlineKeyBoard verticalDuoMenu(KeyBoardButton... buttons) {
final InlineKeyBoard.Builder keyBoard = InlineKeyBoard.builder();
public static void verticalDuoMenu(InlineKeyBoard.Builder builder, List<? extends KeyBoardButton> buttons) {
boolean flag = true;
SimpleKeyBoardLine.Builder keyBoardLine = SimpleKeyBoardLine.builder();
for (int i = 0; i <= buttons.length - 1; i++) {
keyBoardLine.button(buttons[i]);
for (int i = 0; i <= buttons.size() - 1; i++) {
keyBoardLine.button(buttons.get(i));
if (flag) {
if (i == buttons.length - 1) {
keyBoard.line(keyBoardLine.build());
if (i == buttons.size() - 1) {
builder.line(keyBoardLine.build());
} else {
flag = false;
}
} else {
keyBoard.line(keyBoardLine.build());
builder.line(keyBoardLine.build());
keyBoardLine = SimpleKeyBoardLine.builder();
flag = true;
}
}
}
public static InlineKeyBoard verticalDuoMenu(List<? extends KeyBoardButton> buttons) {
final InlineKeyBoard.Builder keyBoard = InlineKeyBoard.builder();
verticalDuoMenu(keyBoard, buttons);
return keyBoard.build();
}
public static InlineKeyBoard verticalDuoMenu(KeyBoardButton... buttons) {
return verticalDuoMenu(Arrays.stream(buttons).toList());
}
/**
* Возвращает клавиатуру формата 1xN сформированную из списка кнопок, где N - количество кнопок в списке
*
* @param buttons Список кнопок
* @return {@link SimpleKeyBoard}
*/
public static InlineKeyBoard verticalMenuButton(List<KeyBoardButton> buttons) {
public static InlineKeyBoard verticalMenuButton(KeyBoardButton... buttons) {
final InlineKeyBoard.Builder keyBoard = InlineKeyBoard.builder();
for (KeyBoardButton simpleButton : buttons) {
keyBoard.line(simpleLine(simpleButton));

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>telegram-core</artifactId>
<groupId>dev.struchkov.godfather.telegram</groupId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-core-quarkus</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-quarkus</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-main</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-core-quarkus</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,24 @@
package dev.struchkov.godfather.telegram.quarkus.core;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.quarkus.context.service.PersonSettingService;
import dev.struchkov.godfather.quarkus.core.GeneralAutoResponder;
import dev.struchkov.godfather.quarkus.core.service.StorylineService;
import dev.struchkov.godfather.telegram.quarkus.context.service.TelegramSending;
/**
* TODO: Добавить описание класса.
*
* @author upagge [18.08.2019]
*/
public class MailAutoresponderTelegram extends GeneralAutoResponder<Mail> {
public MailAutoresponderTelegram(
TelegramSending sending,
PersonSettingService personSettingService,
StorylineService<Mail> storyLineService
) {
super(sending, personSettingService, storyLineService);
}
}

View File

@ -1,9 +1,11 @@
package dev.struchkov.godfather.telegram.listen;
package dev.struchkov.godfather.telegram.quarkus.core;
import dev.struchkov.godfather.telegram.ProxyConfig;
import dev.struchkov.godfather.telegram.TelegramBot;
import dev.struchkov.godfather.telegram.TelegramPollingBot;
import dev.struchkov.godfather.telegram.config.TelegramPollingConfig;
import dev.struchkov.godfather.telegram.domain.config.ProxyConfig;
import dev.struchkov.godfather.telegram.domain.config.ProxyConfig.Type;
import dev.struchkov.godfather.telegram.domain.config.TelegramConnectConfig;
import dev.struchkov.godfather.telegram.main.context.TelegramConnect;
import dev.struchkov.godfather.telegram.quarkus.context.service.EventDistributor;
import dev.struchkov.godfather.telegram.quarkus.context.service.TelegramBot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.telegram.telegrambots.bots.DefaultBotOptions;
@ -15,19 +17,23 @@ import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
/**
* TODO: Добавить описание класса.
*
* @author upagge [30.01.2020]
*/
public class TelegramConnect {
public class TelegramConnectBot implements TelegramConnect {
private static final Logger log = LoggerFactory.getLogger(TelegramConnect.class);
private static final Logger log = LoggerFactory.getLogger(TelegramConnectBot.class);
private TelegramBot telegramBot;
private final TelegramConnectConfig telegramConnectConfig;
public TelegramConnect(TelegramPollingConfig telegramPollingConfig) {
initLongPolling(telegramPollingConfig);
public TelegramConnectBot(TelegramConnectConfig telegramConnectConfig) {
this.telegramConnectConfig = telegramConnectConfig;
initLongPolling(telegramConnectConfig);
}
// public TelegramConnect(TelegramWebHookConfig telegramWebHookConfig) {
@ -45,9 +51,10 @@ public class TelegramConnect {
// }
// }
private void initLongPolling(TelegramPollingConfig telegramPollingConfig) {
final ProxyConfig proxyConfig = telegramPollingConfig.getProxyConfig();
if (proxyConfig != null && proxyConfig.getPassword() != null) {
private void initLongPolling(TelegramConnectConfig telegramConnectConfig) {
final ProxyConfig proxyConfig = telegramConnectConfig.getProxyConfig();
if (checkNotNull(proxyConfig) && proxyConfig.isEnable() && checkNotNull(proxyConfig.getPassword()) && !"".equals(proxyConfig.getPassword())) {
try {
Authenticator.setDefault(new Authenticator() {
@Override
@ -65,9 +72,9 @@ public class TelegramConnect {
final TelegramBotsApi botapi;
try {
if (proxyConfig != null && proxyConfig.getHost() != null) {
if (checkNotNull(proxyConfig) && proxyConfig.isEnable() && checkNotNull(proxyConfig.getHost()) && !"".equals(proxyConfig.getHost())) {
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
System.setProperty("javax.net.debug", "all");
// System.setProperty("javax.net.debug", "all");
log.info(System.getProperty("https.protocols"));
DefaultBotOptions botOptions = new DefaultBotOptions();
botOptions.setProxyHost(proxyConfig.getHost());
@ -75,14 +82,13 @@ public class TelegramConnect {
botOptions.setProxyType(convertProxyType(proxyConfig.getType()));
final TelegramPollingBot bot = new TelegramPollingBot(telegramPollingConfig, botOptions);
final TelegramPollingBot bot = new TelegramPollingBot(telegramConnectConfig, botOptions);
botapi = new TelegramBotsApi(DefaultBotSession.class);
botapi.registerBot(bot);
this.telegramBot = bot;
} else {
final TelegramPollingBot bot = new TelegramPollingBot(telegramPollingConfig);
final TelegramPollingBot bot = new TelegramPollingBot(telegramConnectConfig);
botapi = new TelegramBotsApi(DefaultBotSession.class);
botapi.registerBot(bot);
this.telegramBot = bot;
@ -92,25 +98,25 @@ public class TelegramConnect {
}
}
private DefaultBotOptions.ProxyType convertProxyType(ProxyConfig.Type type) {
switch (type) {
case SOCKS5:
return DefaultBotOptions.ProxyType.SOCKS5;
case SOCKS4:
return DefaultBotOptions.ProxyType.SOCKS4;
case HTTP:
return DefaultBotOptions.ProxyType.HTTP;
default:
return DefaultBotOptions.ProxyType.NO_PROXY;
}
private DefaultBotOptions.ProxyType convertProxyType(Type type) {
return switch (type) {
case SOCKS5 -> DefaultBotOptions.ProxyType.SOCKS5;
case SOCKS4 -> DefaultBotOptions.ProxyType.SOCKS4;
case HTTP -> DefaultBotOptions.ProxyType.HTTP;
};
}
AbsSender getAdsSender() {
return telegramBot.getAdsSender();
}
void initEventDistributor(EventDistributorService eventDistributor) {
public void initEventDistributor(EventDistributor eventDistributor) {
telegramBot.initEventDistributor(eventDistributor);
}
public String getToken() {
return telegramConnectConfig.getBotToken();
}
@Override
public AbsSender getAbsSender() {
return telegramBot.getAdsSender();
}
}

View File

@ -0,0 +1,59 @@
package dev.struchkov.godfather.telegram.quarkus.core;
import dev.struchkov.godfather.telegram.domain.config.TelegramConnectConfig;
import dev.struchkov.godfather.telegram.quarkus.context.service.EventDistributor;
import dev.struchkov.godfather.telegram.quarkus.context.service.TelegramBot;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.bots.AbsSender;
/**
* TODO: Добавить описание класса.
*
* @author upagge [15/07/2019]
*/
public class TelegramPollingBot extends TelegramLongPollingBot implements TelegramBot {
private final TelegramConnectConfig telegramConnectConfig;
private EventDistributor eventDistributor;
public TelegramPollingBot(TelegramConnectConfig telegramConnectConfig, DefaultBotOptions defaultBotOptions) {
super(defaultBotOptions);
this.telegramConnectConfig = telegramConnectConfig;
}
public TelegramPollingBot(TelegramConnectConfig telegramConnectConfig) {
this.telegramConnectConfig = telegramConnectConfig;
}
@Override
public void onUpdateReceived(Update update) {
if (update != null && eventDistributor != null) {
eventDistributor.processing(update)
.subscribe().asCompletionStage();
}
}
@Override
public String getBotUsername() {
return telegramConnectConfig.getBotUsername();
}
@Override
public String getBotToken() {
return telegramConnectConfig.getBotToken();
}
@Override
public AbsSender getAdsSender() {
return this;
}
@Override
public void initEventDistributor(@NotNull EventDistributor eventDistributor) {
this.eventDistributor = eventDistributor;
}
}

View File

@ -0,0 +1,128 @@
package dev.struchkov.godfather.telegram.quarkus.core.service;
import dev.struchkov.godfather.telegram.domain.attachment.DocumentAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.Picture;
import dev.struchkov.godfather.telegram.domain.files.ByteContainer;
import dev.struchkov.godfather.telegram.domain.files.FileContainer;
import dev.struchkov.godfather.telegram.main.context.TelegramConnect;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.telegram.telegrambots.meta.api.methods.GetFile;
import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.stream.Stream;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
public class AttachmentServiceImpl {
private static final Logger log = LoggerFactory.getLogger(AttachmentServiceImpl.class);
private final AbsSender absSender;
private final String botToken;
private String folderPathForFiles;
public AttachmentServiceImpl(TelegramConnect telegramConnect) {
this.absSender = telegramConnect.getAbsSender();
this.botToken = telegramConnect.getToken();
}
public void setFolderPathForFiles(String folderPathForFiles) {
if (folderPathForFiles != null) {
this.folderPathForFiles = folderPathForFiles + "/";
try (final Stream<Path> pathStream = Files.list(Path.of(folderPathForFiles))) {
pathStream.forEach(path -> {
try {
Files.delete(path);
} catch (IOException e) {
log.error(e.getMessage());
}
});
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
public FileContainer uploadFile(@NotNull DocumentAttachment documentAttachment) {
isNotNull(documentAttachment);
try {
final File file = downloadFile(documentAttachment);
return new FileContainer(documentAttachment.getFileName(), documentAttachment.getMimeType(), file);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return FileContainer.empty();
}
public ByteContainer uploadBytes(@NotNull DocumentAttachment documentAttachment) {
isNotNull(documentAttachment);
try {
final byte[] bytes = downloadBytes(documentAttachment);
return new ByteContainer(documentAttachment.getFileName(), documentAttachment.getMimeType(), bytes);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return ByteContainer.empty();
}
public ByteContainer uploadBytes(@NotNull Picture picture) {
isNotNull(picture);
try {
final byte[] bytes = downloadBytes(picture);
return new ByteContainer(null, "image/jpeg", bytes);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return ByteContainer.empty();
}
private byte[] downloadBytes(Picture picture) throws TelegramApiException, IOException {
return telegramDownloadBytes(picture.getFileId());
}
private byte[] downloadBytes(DocumentAttachment documentAttachment) throws TelegramApiException, IOException {
return telegramDownloadBytes(documentAttachment.getFileId());
}
private byte[] telegramDownloadBytes(String fileId) throws TelegramApiException, IOException {
final String fileUrl = getFileUrl(fileId);
return IOUtils.toByteArray(new URL(fileUrl));
}
private File downloadFile(DocumentAttachment documentAttachment) throws IOException, TelegramApiException {
final String fileUrl = getFileUrl(documentAttachment.getFileId());
final StringBuilder filePath = new StringBuilder();
if (folderPathForFiles != null) {
filePath.append(folderPathForFiles);
}
filePath.append(UUID.randomUUID());
filePath.append("_");
filePath.append(documentAttachment.getFileName());
final File localFile = new File(filePath.toString());
final InputStream is = new URL(fileUrl).openStream();
FileUtils.copyInputStreamToFile(is, localFile);
return localFile;
}
private String getFileUrl(String fileId) throws TelegramApiException {
final GetFile getFile = new GetFile();
getFile.setFileId(fileId);
return absSender.execute(getFile).getFileUrl(botToken);
}
}

View File

@ -0,0 +1,34 @@
package dev.struchkov.godfather.telegram.quarkus.core.service;
import dev.struchkov.godfather.telegram.quarkus.context.repository.SenderRepository;
import io.smallrye.mutiny.Uni;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
public class SenderMapRepository implements SenderRepository {
private final Map<String, Integer> lastMessageId = new HashMap<>();
@Override
public Uni<Integer> getLastSendMessage(String telegramId) {
return Uni.createFrom().item(lastMessageId.get(telegramId));
}
@Override
public Uni<Void> saveLastSendMessage(@NotNull String telegramId, @NotNull Integer messageId) {
isNotNull(telegramId);
lastMessageId.put(telegramId, messageId);
return Uni.createFrom().voidItem();
}
@Override
public Uni<Void> removeLastSendMessage(String telegramId) {
lastMessageId.remove(telegramId);
return Uni.createFrom().voidItem();
}
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-core-simple</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-simple</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-main</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-core-simple</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,24 @@
package dev.struchkov.godfather.telegram.simple.core;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.simple.context.service.PersonSettingService;
import dev.struchkov.godfather.simple.core.GeneralAutoResponder;
import dev.struchkov.godfather.simple.core.service.StorylineService;
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
/**
* TODO: Добавить описание класса.
*
* @author upagge [18.08.2019]
*/
public class MailAutoresponderTelegram extends GeneralAutoResponder<Mail> {
public MailAutoresponderTelegram(
TelegramSending sending,
PersonSettingService personSettingService,
StorylineService<Mail> storyLineService
) {
super(sending, personSettingService, storyLineService);
}
}

View File

@ -0,0 +1,105 @@
package dev.struchkov.godfather.telegram.simple.core;
import dev.struchkov.godfather.telegram.domain.config.ProxyConfig;
import dev.struchkov.godfather.telegram.domain.config.ProxyConfig.Type;
import dev.struchkov.godfather.telegram.domain.config.TelegramConnectConfig;
import dev.struchkov.godfather.telegram.main.context.TelegramConnect;
import dev.struchkov.godfather.telegram.simple.context.service.EventDistributor;
import dev.struchkov.godfather.telegram.simple.context.service.TelegramBot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
/**
* TODO: Добавить описание класса.
*
* @author upagge [30.01.2020]
*/
public class TelegramConnectBot implements TelegramConnect {
private static final Logger log = LoggerFactory.getLogger(TelegramConnectBot.class);
private TelegramBot telegramBot;
private final TelegramConnectConfig telegramConnectConfig;
public TelegramConnectBot(TelegramConnectConfig telegramConnectConfig) {
this.telegramConnectConfig = telegramConnectConfig;
initLongPolling(telegramConnectConfig);
}
private void initLongPolling(TelegramConnectConfig telegramConnectConfig) {
final ProxyConfig proxyConfig = telegramConnectConfig.getProxyConfig();
if (checkNotNull(proxyConfig) && checkNotNull(proxyConfig.getPassword()) && !"".equals(proxyConfig.getPassword())) {
try {
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
proxyConfig.getUser(),
proxyConfig.getPassword().toCharArray()
);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
final TelegramBotsApi botapi;
try {
if (checkNotNull(proxyConfig) && proxyConfig.isEnable() && checkNotNull(proxyConfig.getHost()) && !"".equals(proxyConfig.getHost())) {
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
// System.setProperty("javax.net.debug", "all");
log.info(System.getProperty("https.protocols"));
DefaultBotOptions botOptions = new DefaultBotOptions();
botOptions.setProxyHost(proxyConfig.getHost());
botOptions.setProxyPort(proxyConfig.getPort());
botOptions.setProxyType(convertProxyType(proxyConfig.getType()));
final TelegramPollingBot bot = new TelegramPollingBot(telegramConnectConfig, botOptions);
botapi = new TelegramBotsApi(DefaultBotSession.class);
botapi.registerBot(bot);
this.telegramBot = bot;
} else {
final TelegramPollingBot bot = new TelegramPollingBot(telegramConnectConfig);
botapi = new TelegramBotsApi(DefaultBotSession.class);
botapi.registerBot(bot);
this.telegramBot = bot;
}
} catch (TelegramApiException e) {
log.error(e.getMessage());
}
}
private DefaultBotOptions.ProxyType convertProxyType(Type type) {
return switch (type) {
case SOCKS5 -> DefaultBotOptions.ProxyType.SOCKS5;
case SOCKS4 -> DefaultBotOptions.ProxyType.SOCKS4;
case HTTP -> DefaultBotOptions.ProxyType.HTTP;
};
}
public void initEventDistributor(EventDistributor eventDistributor) {
telegramBot.initEventDistributor(eventDistributor);
}
public String getToken() {
return telegramConnectConfig.getBotToken();
}
@Override
public AbsSender getAbsSender() {
return telegramBot.getAdsSender();
}
}

View File

@ -1,8 +1,8 @@
package dev.struchkov.godfather.telegram;
package dev.struchkov.godfather.telegram.simple.core;
import dev.struchkov.godfather.telegram.config.TelegramPollingConfig;
import dev.struchkov.godfather.telegram.listen.EventDistributor;
import dev.struchkov.godfather.telegram.listen.EventDistributorService;
import dev.struchkov.godfather.telegram.domain.config.TelegramConnectConfig;
import dev.struchkov.godfather.telegram.simple.context.service.EventDistributor;
import dev.struchkov.godfather.telegram.simple.context.service.TelegramBot;
import org.jetbrains.annotations.NotNull;
import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
@ -16,16 +16,16 @@ import org.telegram.telegrambots.meta.bots.AbsSender;
*/
public class TelegramPollingBot extends TelegramLongPollingBot implements TelegramBot {
private final TelegramPollingConfig telegramPollingConfig;
private final TelegramConnectConfig telegramConnectConfig;
private EventDistributor eventDistributor;
public TelegramPollingBot(TelegramPollingConfig telegramPollingConfig, DefaultBotOptions defaultBotOptions) {
public TelegramPollingBot(TelegramConnectConfig telegramConnectConfig, DefaultBotOptions defaultBotOptions) {
super(defaultBotOptions);
this.telegramPollingConfig = telegramPollingConfig;
this.telegramConnectConfig = telegramConnectConfig;
}
public TelegramPollingBot(TelegramPollingConfig telegramPollingConfig) {
this.telegramPollingConfig = telegramPollingConfig;
public TelegramPollingBot(TelegramConnectConfig telegramConnectConfig) {
this.telegramConnectConfig = telegramConnectConfig;
}
@Override
@ -37,12 +37,12 @@ public class TelegramPollingBot extends TelegramLongPollingBot implements Telegr
@Override
public String getBotUsername() {
return telegramPollingConfig.getBotUsername();
return telegramConnectConfig.getBotUsername();
}
@Override
public String getBotToken() {
return telegramPollingConfig.getBotToken();
return telegramConnectConfig.getBotToken();
}
@Override
@ -51,7 +51,7 @@ public class TelegramPollingBot extends TelegramLongPollingBot implements Telegr
}
@Override
public void initEventDistributor(@NotNull EventDistributorService eventDistributor) {
public void initEventDistributor(@NotNull EventDistributor eventDistributor) {
this.eventDistributor = eventDistributor;
}

View File

@ -0,0 +1,128 @@
package dev.struchkov.godfather.telegram.simple.core.service;
import dev.struchkov.godfather.telegram.domain.attachment.DocumentAttachment;
import dev.struchkov.godfather.telegram.domain.attachment.Picture;
import dev.struchkov.godfather.telegram.domain.files.ByteContainer;
import dev.struchkov.godfather.telegram.domain.files.FileContainer;
import dev.struchkov.godfather.telegram.main.context.TelegramConnect;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.telegram.telegrambots.meta.api.methods.GetFile;
import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.stream.Stream;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
public class AttachmentServiceImpl {
private static final Logger log = LoggerFactory.getLogger(AttachmentServiceImpl.class);
private final AbsSender absSender;
private final String botToken;
private String folderPathForFiles;
public AttachmentServiceImpl(TelegramConnect telegramConnect) {
this.absSender = telegramConnect.getAbsSender();
this.botToken = telegramConnect.getToken();
}
public void setFolderPathForFiles(String folderPathForFiles) {
if (folderPathForFiles != null) {
this.folderPathForFiles = folderPathForFiles + "/";
try (final Stream<Path> pathStream = Files.list(Path.of(folderPathForFiles))) {
pathStream.forEach(path -> {
try {
Files.delete(path);
} catch (IOException e) {
log.error(e.getMessage());
}
});
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
public FileContainer uploadFile(@NotNull DocumentAttachment documentAttachment) {
isNotNull(documentAttachment);
try {
final File file = downloadFile(documentAttachment);
return new FileContainer(documentAttachment.getFileName(), documentAttachment.getMimeType(), file);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return FileContainer.empty();
}
public ByteContainer uploadBytes(@NotNull DocumentAttachment documentAttachment) {
isNotNull(documentAttachment);
try {
final byte[] bytes = downloadBytes(documentAttachment);
return new ByteContainer(documentAttachment.getFileName(), documentAttachment.getMimeType(), bytes);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return ByteContainer.empty();
}
public ByteContainer uploadBytes(@NotNull Picture picture) {
isNotNull(picture);
try {
final byte[] bytes = downloadBytes(picture);
return new ByteContainer(null, "image/jpeg", bytes);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return ByteContainer.empty();
}
private byte[] downloadBytes(Picture picture) throws TelegramApiException, IOException {
return telegramDownloadBytes(picture.getFileId());
}
private byte[] downloadBytes(DocumentAttachment documentAttachment) throws TelegramApiException, IOException {
return telegramDownloadBytes(documentAttachment.getFileId());
}
private byte[] telegramDownloadBytes(String fileId) throws TelegramApiException, IOException {
final String fileUrl = getFileUrl(fileId);
return IOUtils.toByteArray(new URL(fileUrl));
}
private File downloadFile(DocumentAttachment documentAttachment) throws IOException, TelegramApiException {
final String fileUrl = getFileUrl(documentAttachment.getFileId());
final StringBuilder filePath = new StringBuilder();
if (folderPathForFiles != null) {
filePath.append(folderPathForFiles);
}
filePath.append(UUID.randomUUID());
filePath.append("_");
filePath.append(documentAttachment.getFileName());
final File localFile = new File(filePath.toString());
final InputStream is = new URL(fileUrl).openStream();
FileUtils.copyInputStreamToFile(is, localFile);
return localFile;
}
private String getFileUrl(String fileId) throws TelegramApiException {
final GetFile getFile = new GetFile();
getFile.setFileId(fileId);
return absSender.execute(getFile).getFileUrl(botToken);
}
}

View File

@ -0,0 +1,32 @@
package dev.struchkov.godfather.telegram.simple.core.service;
import dev.struchkov.godfather.telegram.simple.context.repository.SenderRepository;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
public class SenderMapRepository implements SenderRepository {
private final Map<String, Integer> lastMessageId = new HashMap<>();
@Override
public Optional<Integer> getLastSendMessage(String telegramId) {
return Optional.ofNullable(lastMessageId.get(telegramId));
}
@Override
public void saveLastSendMessage(@NotNull String telegramId, @NotNull Integer messageId) {
isNotNull(telegramId);
lastMessageId.put(telegramId, messageId);
}
@Override
public void removeLastSendMessage(String telegramId) {
lastMessageId.remove(telegramId);
}
}

View File

@ -0,0 +1,30 @@
package dev.struchkov.godfather.telegram.simple.core.util;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.telegram.domain.attachment.ButtonClickAttachment;
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
import java.util.Optional;
import java.util.function.Predicate;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
public class TriggerChecks {
private TriggerChecks() {
utilityClass();
}
public static Predicate<Mail> clickButtonRaw(String rawCallBackData) {
return mail -> {
final Optional<ButtonClickAttachment> optButtonClick = Attachments.findFirstButtonClick(mail.getAttachments());
if (optButtonClick.isPresent()) {
final ButtonClickAttachment buttonClick = optButtonClick.get();
final String rawData = buttonClick.getRawCallBackData();
return rawData.equals(rawCallBackData);
}
return false;
};
}
}

29
telegram-domain/pom.xml Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-bot</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-domain</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context-main</artifactId>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,147 @@
package dev.struchkov.godfather.telegram.domain;
import dev.struchkov.godfather.main.domain.BoxAnswer;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardLine;
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
import dev.struchkov.haiti.utils.Inspector;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
import static dev.struchkov.godfather.telegram.domain.UnitPaginationUtil.navigableLine;
public class UnitPage<T> {
/**
* Дополнительные линии клавиатуры. Выводятся после кнопок навигации.
*/
private final List<KeyBoardLine> additionalLines = new ArrayList<>();
/**
* Элементы, которые будут выводиться.
*/
private List<T> elements;
/**
* Номер текущей страницы.
*/
private Integer currentOffset;
/**
* Общее количество элементов на всех страницах.
*/
private Integer countAllElements;
/**
* Функция преобразования элементов с линии.
*/
private Function<T, KeyBoardLine> function;
/**
* Сообщение, которое выводится над результатами
*/
private String message;
/**
* Флаг, определяющий нужно ли заменить старое сообщение или вывести новое (по умолчанию заменять)
*/
private boolean replace;
/**
* Флаг, исключающий добавление строки с навигацией
*/
private boolean removeDefaultNavigableLine;
/**
* Сообщение, которое будет отправлено, если коллекция элементов пустая.
*/
private BoxAnswer emptyElements;
public static <T> UnitPage<T> builder() {
return new UnitPage<>();
}
public UnitPage<T> elements(List<T> elements) {
this.elements = elements;
return this;
}
public UnitPage<T> countAllElements(Integer countAllElements) {
this.countAllElements = countAllElements;
return this;
}
public UnitPage<T> currentOffset(Integer currentOffset) {
this.currentOffset = currentOffset;
return this;
}
public UnitPage<T> additionLine(KeyBoardLine line) {
additionalLines.add(line);
return this;
}
public UnitPage<T> additionLine(KeyBoardButton button) {
additionalLines.add(simpleLine(button));
return this;
}
public UnitPage<T> mapper(Function<T, KeyBoardLine> function) {
this.function = function;
return this;
}
public UnitPage<T> message(String message) {
this.message = message;
return this;
}
public UnitPage<T> replace(boolean replace) {
this.replace = replace;
return this;
}
public UnitPage<T> emptyElements(BoxAnswer boxAnswer) {
this.emptyElements = boxAnswer;
return this;
}
public UnitPage<T> removeDefaultNavigableLine() {
this.removeDefaultNavigableLine = true;
return this;
}
public BoxAnswer build() {
Inspector.isNotNull(currentOffset, countAllElements, function);
if (elements.isEmpty()) {
return emptyElements != null ? emptyElements : BoxAnswer.boxAnswer("Данные не найдены.");
} else {
final List<KeyBoardLine> lines = elements.stream()
.map(function)
.toList();
final InlineKeyBoard.Builder builder = InlineKeyBoard.builder();
lines.forEach(builder::line);
if (!removeDefaultNavigableLine) {
navigableLine(currentOffset, countAllElements).ifPresent(builder::line);
}
additionalLines.forEach(builder::line);
final InlineKeyBoard keyBoard = builder.build();
final BoxAnswer.Builder boxAnswer = BoxAnswer.builder()
.keyBoard(keyBoard)
.replace(true);
if (message != null) {
boxAnswer.message(message);
}
boxAnswer.replace(replace);
return boxAnswer.build();
}
}
}

View File

@ -0,0 +1,88 @@
package dev.struchkov.godfather.telegram.domain;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardLine;
import dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton.simpleButton;
public final class UnitPaginationUtil {
public static final String PAGE_REGEX = "^page\\s\\d*$";
private static final String PAGINATION_SCHEMA = "page %s";
private static final Pattern PATTERN_FOR_SEARCH_OFFSET = Pattern.compile("\\d++$");
/**
* Создание строки пагинации для передачи ее в payload кнопки
*/
public static String getStringForOffset(Integer offset) {
return PAGINATION_SCHEMA.formatted(offset);
}
/**
* Разбор передаваемой строки пагинации
*/
public static Optional<Integer> getOffsetFromString(String offsetString) {
if (!Pattern.matches(PAGE_REGEX, offsetString)) {
return Optional.empty();
}
final Matcher matcher = PATTERN_FOR_SEARCH_OFFSET.matcher(offsetString);
if (matcher.find()) {
final String offsetNumber = offsetString.substring(matcher.start(), matcher.end());
return Optional.of(Integer.valueOf(offsetNumber));
} else {
return Optional.empty();
}
}
/**
* Получение строки для клавиатуры, в которой содержатся кнопки навигации.
*
* @param currentOffset - текущее смещение, используемое для запроса
* @param countElements - общее количество элементов которое может вернуть запрос
*/
public static Optional<KeyBoardLine> navigableLine(Integer currentOffset, Integer countElements) {
final SimpleKeyBoardLine.Builder lineBuilder = SimpleKeyBoardLine.builder();
final Optional<KeyBoardButton> optPrevButton = getPrevPageButton(currentOffset);
final Optional<KeyBoardButton> optNextButton = getNextPageButton(currentOffset, countElements);
if (optPrevButton.isPresent() || optNextButton.isPresent()) {
optPrevButton.ifPresent(lineBuilder::button);
optNextButton.ifPresent(lineBuilder::button);
return Optional.of(lineBuilder.build());
}
return Optional.empty();
}
/**
* Получение кнопки навигации на прошлую страницу, т.к. пользователь находится на самой первой странице, то
* кнопки перехода на предыдущую страницу может и не быть
*/
private static Optional<KeyBoardButton> getPrevPageButton(Integer currentOffset) {
if (!currentOffset.equals(0)) {
int prevOffset = currentOffset < 5 ? 0 : currentOffset - 5;
return Optional.of(simpleButton("", getStringForOffset(prevOffset)));
}
return Optional.empty();
}
/**
* Получение кнопки навигации на следующую страницу, т.к. пользователь может находиться на последней странице,
* то кнопки навигации вперед может и не быть
*/
private static Optional<KeyBoardButton> getNextPageButton(Integer currentOffset, Integer countElements) {
final Integer nextOffset = currentOffset + 5;
if (nextOffset.compareTo(countElements) < 0) {
return Optional.of(simpleButton("", getStringForOffset(nextOffset)));
}
return Optional.empty();
}
}

View File

@ -0,0 +1,85 @@
package dev.struchkov.godfather.telegram.domain.attachment;
import dev.struchkov.godfather.main.domain.content.Attachment;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
public class ButtonClickAttachment extends Attachment {
/**
* Идентификатор сообщения, под которым пользователь нажал кнопку.
*/
private Integer messageId;
private String rawCallBackData;
private final Map<String, Arg> args = new HashMap<>();
public String getRawCallBackData() {
return rawCallBackData;
}
public void setRawCallBackData(String rawCallBackData) {
this.rawCallBackData = rawCallBackData;
}
public void addClickArg(String type, String value) {
isNotNull(type, value);
args.put(type, new Arg(type, value));
}
public Optional<Arg> getArgByType(String type) {
isNotNull(type);
return Optional.ofNullable(args.get(type));
}
public Arg getArgByTypeOrThrow(String type) {
isNotNull(type);
return Optional.of(args.get(type)).orElseThrow(notFoundException("Аргумент типа {0} не найден.", type));
}
public Collection<Arg> getClickArgs() {
return args.values();
}
public Integer getMessageId() {
return messageId;
}
public void setMessageId(Integer messageId) {
this.messageId = messageId;
}
public Map<String, Arg> getArgs() {
return args;
}
@Override
public String getType() {
return TelegramAttachmentType.BUTTON_CLICK.name();
}
public static class Arg {
private final String type;
private final String value;
private Arg(String type, String value) {
this.type = type;
this.value = value;
}
public String getType() {
return type;
}
public String getValue() {
return value;
}
}
}

View File

@ -0,0 +1,59 @@
package dev.struchkov.godfather.telegram.domain.attachment;
import dev.struchkov.godfather.main.domain.content.Attachment;
import java.util.Optional;
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
public class CommandAttachment extends Attachment {
private String value;
private String commandType;
private String arg;
private String rawValue;
public void setValue(String value) {
this.value = value;
}
public void setCommandType(String commandType) {
this.commandType = commandType;
}
public void setArg(String arg) {
this.arg = arg;
}
public void setRawValue(String rawValue) {
this.rawValue = rawValue;
}
public String getValue() {
return value;
}
public Optional<String> getArg() {
return Optional.ofNullable(arg);
}
public String getCommandType() {
return commandType;
}
public boolean isCommandType(String type) {
if (checkNotNull(type)) {
return type.equals(commandType);
}
return false;
}
public String getRawValue() {
return rawValue;
}
@Override
public String getType() {
return TelegramAttachmentType.COMMAND.name();
}
}

View File

@ -0,0 +1,71 @@
package dev.struchkov.godfather.telegram.domain.attachment;
import dev.struchkov.godfather.main.domain.content.Attachment;
public class ContactAttachment extends Attachment {
private String phoneNumber;
private String firstName;
private String lastName;
private Long userId;
private String vCard;
/**
* если true, то контакт принадлежит отправившему телеграм аккаунту.
*/
private boolean owner;
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public boolean isOwner() {
return owner;
}
public void setOwner(boolean owner) {
this.owner = owner;
}
public String getVCard() {
return vCard;
}
public void setVCard(String vCard) {
this.vCard = vCard;
}
@Override
public String getType() {
return TelegramAttachmentType.CONTACT.name();
}
}

View File

@ -0,0 +1,49 @@
package dev.struchkov.godfather.telegram.domain.attachment;
import dev.struchkov.godfather.main.domain.content.Attachment;
public class DocumentAttachment extends Attachment {
private String fileId;
private Long fileSize;
private String fileName;
private String mimeType;
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
public Long getFileSize() {
return fileSize;
}
public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
@Override
public String getType() {
return TelegramAttachmentType.DOCUMENT.name();
}
}

View File

@ -0,0 +1,32 @@
package dev.struchkov.godfather.telegram.domain.attachment;
import dev.struchkov.godfather.main.domain.content.Attachment;
import dev.struchkov.haiti.utils.Parser;
import dev.struchkov.haiti.utils.domain.CompositeUrl;
public class LinkAttachment extends Attachment {
private String url;
public LinkAttachment(String url) {
this.url = url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUrl() {
return url;
}
@Override
public String getType() {
return TelegramAttachmentType.LINK.name();
}
public CompositeUrl split() {
return Parser.url(url);
}
}

View File

@ -0,0 +1,51 @@
package dev.struchkov.godfather.telegram.domain.attachment;
public class Picture {
private String fileId;
private String fileUniqueId;
private Integer fileSize;
private Integer weight;
private Integer height;
public String getFileId() {
return fileId;
}
public void setFileId(String fileId) {
this.fileId = fileId;
}
public String getFileUniqueId() {
return fileUniqueId;
}
public void setFileUniqueId(String fileUniqueId) {
this.fileUniqueId = fileUniqueId;
}
public Integer getFileSize() {
return fileSize;
}
public void setFileSize(Integer fileSize) {
this.fileSize = fileSize;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
}

View File

@ -0,0 +1,31 @@
package dev.struchkov.godfather.telegram.domain.attachment;
import dev.struchkov.godfather.main.domain.content.Attachment;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class PictureGroupAttachment extends Attachment {
private List<Picture> pictures;
public void setPictureSizes(List<Picture> pictures) {
this.pictures = pictures;
}
public List<Picture> getPictureSizes() {
return pictures;
}
public Optional<Picture> getLargePicture() {
return pictures.stream()
.max(Comparator.comparingInt(Picture::getFileSize));
}
@Override
public String getType() {
return TelegramAttachmentType.PICTURE.name();
}
}

View File

@ -0,0 +1,12 @@
package dev.struchkov.godfather.telegram.domain.attachment;
public enum TelegramAttachmentType {
DOCUMENT,
CONTACT,
PICTURE,
LINK,
COMMAND,
BUTTON_CLICK
}

View File

@ -1,4 +1,4 @@
package dev.struchkov.godfather.telegram;
package dev.struchkov.godfather.telegram.domain.config;
/**
* TODO: Добавить описание класса.
@ -7,6 +7,7 @@ package dev.struchkov.godfather.telegram;
*/
public class ProxyConfig {
private boolean enable = true;
private String host;
private Integer port;
private String user;
@ -53,7 +54,16 @@ public class ProxyConfig {
this.type = type;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public enum Type {
SOCKS5, SOCKS4, HTTP
}
}

View File

@ -1,25 +1,23 @@
package dev.struchkov.godfather.telegram.config;
import dev.struchkov.godfather.telegram.ProxyConfig;
package dev.struchkov.godfather.telegram.domain.config;
/**
* TODO: Добавить описание класса.
*
* @author upagge [18.08.2019]
*/
public class TelegramPollingConfig {
public class TelegramConnectConfig {
private String botUsername;
private String botToken;
private ProxyConfig proxyConfig;
public TelegramPollingConfig(String botUsername, String botToken) {
public TelegramConnectConfig(String botUsername, String botToken) {
this.botUsername = botUsername;
this.botToken = botToken;
}
public TelegramPollingConfig() {
public TelegramConnectConfig() {
}
public void setBotUsername(String botUsername) {

View File

@ -0,0 +1,53 @@
package dev.struchkov.godfather.telegram.domain.event;
import dev.struchkov.godfather.main.domain.event.Event;
import java.time.LocalDateTime;
public class Subscribe implements Event {
public static final String TYPE = "SUBSCRIBE";
private String telegramId;
private String firstName;
private String lastName;
private LocalDateTime subscriptionDate;
public String getTelegramId() {
return telegramId;
}
public void setTelegramId(String telegramId) {
this.telegramId = telegramId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDateTime getSubscriptionDate() {
return subscriptionDate;
}
public void setSubscriptionDate(LocalDateTime subscriptionDate) {
this.subscriptionDate = subscriptionDate;
}
@Override
public String getEventType() {
return TYPE;
}
}

View File

@ -0,0 +1,53 @@
package dev.struchkov.godfather.telegram.domain.event;
import dev.struchkov.godfather.main.domain.event.Event;
import java.time.LocalDateTime;
public class Unsubscribe implements Event {
public static final String TYPE = "UNSUBSCRIBE";
private String telegramId;
private String firstName;
private String lastName;
private LocalDateTime subscriptionDate;
public String getTelegramId() {
return telegramId;
}
public void setTelegramId(String telegramId) {
this.telegramId = telegramId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDateTime getSubscriptionDate() {
return subscriptionDate;
}
public void setSubscriptionDate(LocalDateTime subscriptionDate) {
this.subscriptionDate = subscriptionDate;
}
@Override
public String getEventType() {
return TYPE;
}
}

View File

@ -0,0 +1,37 @@
package dev.struchkov.godfather.telegram.domain.files;
public class ByteContainer {
public static final ByteContainer EMPTY = new ByteContainer(null, null, null);
private final String fileName;
private final String mimeType;
private final byte[] bytes;
public ByteContainer(String fileName, String mimeType, byte[] bytes) {
this.fileName = fileName;
this.mimeType = mimeType;
this.bytes = bytes;
}
public static ByteContainer empty() {
return EMPTY;
}
public String getFileName() {
return fileName;
}
public byte[] getBytes() {
return bytes;
}
public String getMimeType() {
return mimeType;
}
public boolean isNotEmpty() {
return bytes != null && bytes.length > 0;
}
}

View File

@ -0,0 +1,54 @@
package dev.struchkov.godfather.telegram.domain.files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class FileContainer {
public static final FileContainer EMPTY = new FileContainer(null, null, null);
private static final Logger log = LoggerFactory.getLogger(FileContainer.class);
private final String fileName;
private final File file;
private final String mimeType;
public FileContainer(String fileName, String mimeType, File file) {
this.fileName = fileName;
this.file = file;
this.mimeType = mimeType;
}
public static FileContainer empty() {
return EMPTY;
}
public String getFileName() {
return fileName;
}
public File getFile() {
return file;
}
public String getMimeType() {
return mimeType;
}
public boolean isNotEmpty() {
return file != null;
}
public void delete() {
try {
Files.deleteIfExists(file.toPath());
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}

View File

@ -1,15 +1,19 @@
package dev.struchkov.godfather.telegram.domain.keyboard;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoard;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardLine;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoard;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardLine;
import java.util.ArrayList;
import java.util.List;
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
public class InlineKeyBoard implements KeyBoard {
public static final String TYPE = "INLINE";
protected List<KeyBoardLine> lines = new ArrayList<>();
protected List<KeyBoardLine> lines;
public InlineKeyBoard(List<KeyBoardLine> lines) {
this.lines = lines;
@ -23,8 +27,16 @@ public class InlineKeyBoard implements KeyBoard {
return new Builder();
}
public static InlineKeyBoard inlineKeyBoard(KeyBoardLine keyBoardLine) {
return builder().line(keyBoardLine).build();
public static InlineKeyBoard inlineKeyBoard(KeyBoardLine... keyBoardLine) {
final Builder builder = builder();
for (KeyBoardLine boardLine : keyBoardLine) {
builder.line(boardLine);
}
return builder.build();
}
public static InlineKeyBoard inlineKeyBoard(KeyBoardButton... buttons) {
return builder().line(simpleLine(buttons)).build();
}
public List<KeyBoardLine> getLines() {

View File

@ -1,19 +1,23 @@
package dev.struchkov.godfather.telegram.domain.keyboard;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardLine;
import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoard;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardLine;
import dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoard;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine;
public class MarkupKeyBoard extends SimpleKeyBoard {
public static final String TYPE = "MARKUP";
private static final MarkupKeyBoard EMPTY = new MarkupKeyBoard();
/**
* Скрыть меню после ответа или нет.
*/
private boolean oneTime = true;
private boolean oneTime;
/**
* Изменяет размер клавиатуры по вертикали для оптимального соответствия (например, сделать клавиатуру меньше, если есть только два ряда кнопок).
@ -22,6 +26,10 @@ public class MarkupKeyBoard extends SimpleKeyBoard {
private String inputFieldPlaceholder;
public MarkupKeyBoard() {
super(Collections.emptyList());
}
private MarkupKeyBoard(Builder builder) {
super(builder.lines);
oneTime = builder.oneTime;
@ -29,10 +37,30 @@ public class MarkupKeyBoard extends SimpleKeyBoard {
inputFieldPlaceholder = builder.inputFieldPlaceholder;
}
public static Builder newBuilder() {
public static MarkupKeyBoard markupKeyBoard(KeyBoardLine... lines) {
final Builder builder = new Builder();
for (KeyBoardLine line : lines) {
builder.line(line);
}
return builder.build();
}
public static MarkupKeyBoard markupKeyBoard(KeyBoardButton... buttons) {
final Builder builder = new Builder();
for (KeyBoardButton button : buttons) {
builder.line(simpleLine(button));
}
return builder.build();
}
public static Builder markupBuilder() {
return new Builder();
}
public static MarkupKeyBoard empty() {
return EMPTY;
}
public boolean isResizeKeyboard() {
return resizeKeyboard;
}
@ -50,6 +78,14 @@ public class MarkupKeyBoard extends SimpleKeyBoard {
return TYPE;
}
public boolean isEmpty() {
return lines.isEmpty();
}
public boolean isNotEmpty() {
return !lines.isEmpty();
}
public static final class Builder {
private List<KeyBoardLine> lines = new ArrayList<>();
private boolean oneTime = true;

View File

@ -0,0 +1,32 @@
package dev.struchkov.godfather.telegram.domain.keyboard.button;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import org.jetbrains.annotations.NotNull;
/**
* Запрашивает у пользователя его контактный номер.
*/
public class ContactButton implements KeyBoardButton {
public static final String TYPE = "CONTACT";
private final String label;
private ContactButton(String label) {
this.label = label;
}
public static ContactButton contactButton(@NotNull String label) {
return new ContactButton(label);
}
public String getLabel() {
return label;
}
@Override
public String getType() {
return TYPE;
}
}

View File

@ -0,0 +1,34 @@
package dev.struchkov.godfather.telegram.domain.keyboard.button;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import org.jetbrains.annotations.NotNull;
public class UrlButton implements KeyBoardButton {
public static final String TYPE = "URL";
private final String label;
private final String url;
public UrlButton(String label, String url) {
this.label = label;
this.url = url;
}
public static UrlButton urlButton(@NotNull String label, @NotNull String url) {
return new UrlButton(label, url);
}
@Override
public String getType() {
return TYPE;
}
public String getLabel() {
return label;
}
public String getUrl() {
return url;
}
}

View File

@ -1,21 +1,22 @@
package dev.struchkov.godfather.telegram.domain.keyboard.button;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import org.jetbrains.annotations.NotNull;
public class ButtonWebApp implements KeyBoardButton {
public class WebAppButton implements KeyBoardButton {
public static final String TYPE = "WEB_APP";
private final String label;
private final String url;
public ButtonWebApp(String label, String url) {
private WebAppButton(String label, String url) {
this.label = label;
this.url = url;
}
public static ButtonWebApp buttonWebApp(String label, String url) {
return new ButtonWebApp(label, url);
public static WebAppButton webAppButton(@NotNull String label, @NotNull String url) {
return new WebAppButton(label, url);
}
public String getUrl() {

23
telegram-sender/pom.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-bot</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-sender</artifactId>
<packaging>pom</packaging>
<modules>
<module>telegram-sender-main</module>
<module>telegram-sender-simple</module>
<module>telegram-sender-quarkus</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-sender-main</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-domain</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,152 @@
package dev.struchkov.godfather.telegram.main.sender.util;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoard;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.main.domain.keyboard.KeyBoardLine;
import dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton;
import dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoard;
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
import dev.struchkov.godfather.telegram.domain.keyboard.MarkupKeyBoard;
import dev.struchkov.godfather.telegram.domain.keyboard.button.ContactButton;
import dev.struchkov.godfather.telegram.domain.keyboard.button.UrlButton;
import dev.struchkov.godfather.telegram.domain.keyboard.button.WebAppButton;
import dev.struchkov.haiti.context.exception.ConvertException;
import dev.struchkov.haiti.utils.Exceptions;
import dev.struchkov.haiti.utils.Inspector;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardRemove;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardButton;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow;
import org.telegram.telegrambots.meta.api.objects.webapp.WebAppInfo;
import java.util.List;
public final class KeyBoardConvert {
private KeyBoardConvert() {
Exceptions.utilityClass();
}
public static ReplyKeyboard convertKeyBoard(KeyBoard keyBoard) {
if (keyBoard != null) {
switch (keyBoard.getType()) {
case InlineKeyBoard.TYPE:
return convertInlineKeyBoard((InlineKeyBoard) keyBoard);
case MarkupKeyBoard.TYPE:
return convertMarkupKeyBoard((MarkupKeyBoard) keyBoard);
case SimpleKeyBoard.TYPE:
return convertSimpleKeyBoard((SimpleKeyBoard) keyBoard);
}
}
return null;
}
public static ReplyKeyboard convertSimpleKeyBoard(SimpleKeyBoard keyBoard) {
final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup();
keyboardMarkup.setKeyboard(
keyBoard.getLines().stream()
.map(KeyBoardConvert::convertMarkupLine)
.toList()
);
return keyboardMarkup;
}
public static ReplyKeyboard convertMarkupKeyBoard(MarkupKeyBoard keyBoard) {
if (keyBoard != null) {
if (keyBoard.isNotEmpty()) {
final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup();
keyboardMarkup.setOneTimeKeyboard(keyBoard.isOneTime());
keyboardMarkup.setInputFieldPlaceholder(keyBoard.getInputFieldPlaceholder());
keyboardMarkup.setResizeKeyboard(keyBoard.isResizeKeyboard());
keyboardMarkup.setKeyboard(
keyBoard.getLines().stream()
.map(KeyBoardConvert::convertMarkupLine)
.toList()
);
return keyboardMarkup;
} else {
final ReplyKeyboardRemove replyKeyboardRemove = new ReplyKeyboardRemove();
replyKeyboardRemove.setRemoveKeyboard(true);
return replyKeyboardRemove;
}
}
return null;
}
public static InlineKeyboardMarkup convertInlineKeyBoard(InlineKeyBoard keyBoard) {
if (keyBoard != null) {
final InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();
inlineKeyboardMarkup.setKeyboard(
keyBoard.getLines().stream()
.map(KeyBoardConvert::convertInlineLine)
.toList()
);
return inlineKeyboardMarkup;
}
return null;
}
private static List<InlineKeyboardButton> convertInlineLine(KeyBoardLine line) {
return line.getButtons().stream().map(KeyBoardConvert::convertInlineButton).toList();
}
private static KeyboardRow convertMarkupLine(KeyBoardLine line) {
final List<KeyboardButton> buttons = line.getButtons().stream().map(KeyBoardConvert::convertMarkupButton).toList();
return new KeyboardRow(buttons);
}
private static InlineKeyboardButton convertInlineButton(KeyBoardButton keyBoardButton) {
final InlineKeyboardButton button = new InlineKeyboardButton();
switch (keyBoardButton.getType()) {
case SimpleButton.TYPE -> {
final SimpleButton simpleButton = (SimpleButton) keyBoardButton;
final String callbackData = simpleButton.getCallbackData();
final String label = simpleButton.getLabel();
button.setText(label);
button.setCallbackData(callbackData != null ? callbackData : label);
}
case UrlButton.TYPE -> {
final UrlButton urlButton = (UrlButton) keyBoardButton;
button.setUrl(urlButton.getUrl());
button.setText(urlButton.getLabel());
}
case WebAppButton.TYPE -> {
final WebAppButton webAppButton = (WebAppButton) keyBoardButton;
final WebAppInfo webAppInfo = WebAppInfo.builder().url(webAppButton.getUrl()).build();
button.setWebApp(webAppInfo);
button.setText(webAppButton.getLabel());
}
default -> throw new ConvertException("Ошибка преобразования кнопки");
}
return button;
}
private static KeyboardButton convertMarkupButton(KeyBoardButton keyBoardButton) {
final KeyboardButton button = new KeyboardButton();
switch (keyBoardButton.getType()) {
case SimpleButton.TYPE -> {
final SimpleButton simpleButton = (SimpleButton) keyBoardButton;
button.setText(simpleButton.getLabel());
Inspector.isNull(simpleButton.getCallbackData(), ConvertException.convertException("CallbackData поддерживает только Inline клавитаура"));
}
case WebAppButton.TYPE -> {
final WebAppButton webAppButton = (WebAppButton) keyBoardButton;
final WebAppInfo webAppInfo = WebAppInfo.builder().url(webAppButton.getUrl()).build();
button.setText(webAppButton.getLabel());
button.setWebApp(webAppInfo);
}
case ContactButton.TYPE -> {
final ContactButton contactButton = (ContactButton) keyBoardButton;
button.setText(contactButton.getLabel());
button.setRequestContact(true);
}
default -> throw new ConvertException("Ошибка преобразования кнопки");
}
return button;
}
}

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-sender-quarkus</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-quarkus</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender-main</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,170 @@
package dev.struchkov.godfather.telegram.quarkus.sender;
import dev.struchkov.godfather.main.domain.BoxAnswer;
import dev.struchkov.godfather.main.domain.SendType;
import dev.struchkov.godfather.main.domain.SentBox;
import dev.struchkov.godfather.quarkus.context.service.PreSendProcessing;
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
import dev.struchkov.godfather.telegram.main.context.TelegramConnect;
import dev.struchkov.godfather.telegram.main.sender.util.KeyBoardConvert;
import dev.struchkov.godfather.telegram.quarkus.context.repository.SenderRepository;
import dev.struchkov.godfather.telegram.quarkus.context.service.TelegramSending;
import io.smallrye.mutiny.Uni;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.methods.updatingmessages.DeleteMessage;
import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText;
import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import java.util.List;
import static dev.struchkov.godfather.telegram.main.sender.util.KeyBoardConvert.convertInlineKeyBoard;
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
public class TelegramSender implements TelegramSending {
private static final Logger log = LoggerFactory.getLogger(TelegramSender.class);
private static final String ERROR_REPLACE_MESSAGE = "Bad Request: message to edit not found";
private final AbsSender absSender;
//TODO [09.12.2022|uPagge]: Доработать использование preSendProcessors
private List<PreSendProcessing> preSendProcessors;
private SenderRepository senderRepository;
public TelegramSender(TelegramConnect telegramConnect) {
this.absSender = telegramConnect.getAbsSender();
}
public TelegramSender(TelegramConnect telegramConnect, SenderRepository senderRepository) {
this.absSender = telegramConnect.getAbsSender();
this.senderRepository = senderRepository;
}
public void setSenderRepository(SenderRepository senderRepository) {
this.senderRepository = senderRepository;
}
@Override
public Uni<SentBox<Integer>> send(@NotNull BoxAnswer boxAnswer) {
return sendBoxAnswer(boxAnswer, true);
}
@Override
public void addPreSendProcess(@NotNull PreSendProcessing processing) {
preSendProcessors.add(processing);
}
@Override
public Uni<Void> deleteMessage(@NotNull String personId, @NotNull Integer messageId) {
final DeleteMessage deleteMessage = new DeleteMessage();
deleteMessage.setChatId(personId);
deleteMessage.setMessageId(messageId);
try {
absSender.execute(deleteMessage);
} catch (TelegramApiException e) {
log.error(e.getMessage(), e);
}
return Uni.createFrom().voidItem();
}
@Override
public Uni<SentBox<Integer>> replaceMessage(@NotNull String personId, @NotNull Integer messageId, @NotNull BoxAnswer newAnswer) {
return replace(personId, messageId, newAnswer, true);
}
@Override
public Uni<SentBox<Integer>> sendNotSave(@NotNull BoxAnswer boxAnswer) {
return sendBoxAnswer(boxAnswer, false);
}
private Uni<SentBox<Integer>> sendBoxAnswer(@NotNull BoxAnswer boxAnswer, boolean saveMessageId) {
return Uni.createFrom().voidItem()
.onItem().transformToUni(
v -> {
final String recipientTelegramId = boxAnswer.getRecipientPersonId();
if (boxAnswer.isReplace() && checkNotNull(senderRepository)) {
return senderRepository.getLastSendMessage(recipientTelegramId)
.onItem().transformToUni(
lastId -> {
if (checkNotNull(lastId)) {
return replace(recipientTelegramId, lastId, boxAnswer, saveMessageId);
} else {
return sendMessage(recipientTelegramId, boxAnswer, saveMessageId);
}
}
);
} else {
return sendMessage(recipientTelegramId, boxAnswer, saveMessageId);
}
}
);
}
private Uni<SentBox<Integer>> replace(@NotNull String telegramId, @NotNull Integer lastMessageId, @NotNull BoxAnswer boxAnswer, boolean saveMessageId) {
return Uni.createFrom().voidItem()
.onItem().transformToUni(
v -> {
final EditMessageText editMessageText = new EditMessageText();
editMessageText.setChatId(telegramId);
editMessageText.setMessageId(lastMessageId);
editMessageText.enableMarkdown(true);
editMessageText.setText(boxAnswer.getMessage());
editMessageText.setReplyMarkup(convertInlineKeyBoard((InlineKeyBoard) boxAnswer.getKeyBoard()));
try {
absSender.execute(editMessageText);
return Uni.createFrom().optional(SentBox.optional(lastMessageId, boxAnswer, boxAnswer));
} catch (TelegramApiRequestException e) {
log.error(e.getApiResponse());
if (ERROR_REPLACE_MESSAGE.equals(e.getApiResponse())) {
return sendMessage(telegramId, boxAnswer, saveMessageId);
}
} catch (TelegramApiException e) {
log.error(e.getMessage(), e);
}
return Uni.createFrom().nullItem();
}
);
}
private Uni<SentBox<Integer>> sendMessage(@NotNull String telegramId, @NotNull BoxAnswer boxAnswer, boolean saveMessageId) {
return Uni.createFrom().voidItem()
.onItem().transform(
v -> {
final SendMessage sendMessage = new SendMessage();
sendMessage.enableMarkdown(true);
sendMessage.setChatId(telegramId);
sendMessage.setText(boxAnswer.getMessage());
sendMessage.setReplyMarkup(KeyBoardConvert.convertKeyBoard(boxAnswer.getKeyBoard()));
try {
return absSender.execute(sendMessage);
} catch (TelegramApiRequestException e) {
log.error(e.getApiResponse());
} catch (TelegramApiException e) {
log.error(e.getMessage());
}
return null;
}
).onItem().ifNotNull().call(answerMessage -> {
if (checkNotNull(senderRepository) && saveMessageId) {
return senderRepository.saveLastSendMessage(telegramId, answerMessage.getMessageId());
}
return null;
})
.onItem().ifNotNull().transformToUni(
answerMessage -> Uni.createFrom().optional(SentBox.optional(answerMessage.getMessageId(), boxAnswer, boxAnswer))
);
}
@Override
public SendType getType() {
return SendType.PRIVATE;
}
}

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-sender-simple</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender-main</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-context-simple</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,154 @@
package dev.struchkov.godfather.telegram.simple.sender;
import dev.struchkov.godfather.main.domain.BoxAnswer;
import dev.struchkov.godfather.main.domain.SendType;
import dev.struchkov.godfather.main.domain.SentBox;
import dev.struchkov.godfather.simple.context.service.PreSendProcessing;
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
import dev.struchkov.godfather.telegram.main.context.TelegramConnect;
import dev.struchkov.godfather.telegram.main.sender.util.KeyBoardConvert;
import dev.struchkov.godfather.telegram.simple.context.repository.SenderRepository;
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.methods.updatingmessages.DeleteMessage;
import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.bots.AbsSender;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
public class TelegramSender implements TelegramSending {
private static final Logger log = LoggerFactory.getLogger(TelegramSender.class);
private static final String ERROR_REPLACE_MESSAGE = "Bad Request: message to edit not found";
private final AbsSender absSender;
private final List<PreSendProcessing> preSendProcessors = new ArrayList<>();
private SenderRepository senderRepository;
public TelegramSender(TelegramConnect telegramConnect) {
this.absSender = telegramConnect.getAbsSender();
}
public TelegramSender(TelegramConnect telegramConnect, SenderRepository senderRepository) {
this.absSender = telegramConnect.getAbsSender();
this.senderRepository = senderRepository;
}
public void setSenderRepository(SenderRepository senderRepository) {
this.senderRepository = senderRepository;
}
@Override
public void addPreSendProcess(@NotNull PreSendProcessing processing) {
preSendProcessors.add(processing);
}
@Override
public void deleteMessage(@NotNull String personId, @NotNull Integer messageId) {
final DeleteMessage deleteMessage = new DeleteMessage();
deleteMessage.setChatId(personId);
deleteMessage.setMessageId(messageId);
try {
absSender.execute(deleteMessage);
} catch (TelegramApiException e) {
log.error(e.getMessage(), e);
}
}
@Override
public Optional<SentBox<Integer>> replaceMessage(@NotNull String personId, @NotNull Integer messageId, @NotNull BoxAnswer newAnswer) {
return replace(personId, messageId, newAnswer, newAnswer, true);
}
@Override
public Optional<SentBox<Integer>> send(@NotNull BoxAnswer boxAnswer) {
isNotNull(boxAnswer.getRecipientPersonId());
return sendBoxAnswer(boxAnswer, true);
}
@Override
public Optional<SentBox<Integer>> sendNotSave(@NotNull BoxAnswer boxAnswer) {
return sendBoxAnswer(boxAnswer, false);
}
private Optional<SentBox<Integer>> sendBoxAnswer(BoxAnswer boxAnswer, boolean saveMessageId) {
final String recipientTelegramId = boxAnswer.getRecipientPersonId();
isNotNull(recipientTelegramId);
BoxAnswer preparedAnswer = boxAnswer;
for (PreSendProcessing preSendProcessor : preSendProcessors) {
preparedAnswer = preSendProcessor.pretreatment(boxAnswer);
}
if (preparedAnswer.isReplace() && checkNotNull(senderRepository)) {
final Optional<Integer> optLastId = senderRepository.getLastSendMessage(recipientTelegramId);
if (optLastId.isPresent()) {
return replace(recipientTelegramId, optLastId.get(), boxAnswer, preparedAnswer, saveMessageId);
} else {
return sendMessage(recipientTelegramId, boxAnswer, preparedAnswer, saveMessageId);
}
} else {
return sendMessage(recipientTelegramId, boxAnswer, preparedAnswer, saveMessageId);
}
}
private Optional<SentBox<Integer>> replace(@NotNull String telegramId, @NotNull Integer lastMessageId, @NotNull BoxAnswer boxAnswer, BoxAnswer preparedAnswer, boolean saveMessageId) {
final EditMessageText editMessageText = new EditMessageText();
editMessageText.setChatId(telegramId);
editMessageText.setMessageId(lastMessageId);
editMessageText.enableMarkdown(true);
editMessageText.setText(boxAnswer.getMessage());
editMessageText.setReplyMarkup(KeyBoardConvert.convertInlineKeyBoard((InlineKeyBoard) boxAnswer.getKeyBoard()));
try {
absSender.execute(editMessageText);
return SentBox.optional(lastMessageId, preparedAnswer, boxAnswer);
} catch (TelegramApiRequestException e) {
log.error(e.getApiResponse());
if (ERROR_REPLACE_MESSAGE.equals(e.getApiResponse())) {
return sendMessage(telegramId, preparedAnswer, preparedAnswer, saveMessageId);
}
} catch (TelegramApiException e) {
log.error(e.getMessage(), e);
}
return Optional.empty();
}
private Optional<SentBox<Integer>> sendMessage(@NotNull String telegramId, @NotNull BoxAnswer boxAnswer, BoxAnswer preparedAnswer, boolean saveMessageId) {
final SendMessage sendMessage = new SendMessage();
sendMessage.enableMarkdown(true);
sendMessage.setChatId(telegramId);
sendMessage.setText(boxAnswer.getMessage());
sendMessage.setReplyMarkup(KeyBoardConvert.convertKeyBoard(boxAnswer.getKeyBoard()));
try {
final Message execute = absSender.execute(sendMessage);
if (checkNotNull(senderRepository) && saveMessageId) {
senderRepository.saveLastSendMessage(telegramId, execute.getMessageId());
}
return SentBox.optional(execute.getMessageId(), preparedAnswer, boxAnswer);
} catch (TelegramApiRequestException e) {
log.error(e.getApiResponse());
} catch (TelegramApiException e) {
log.error(e.getMessage());
}
return Optional.empty();
}
@Override
public SendType getType() {
return SendType.PRIVATE;
}
}

32
telegram-simple/pom.xml Normal file
View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-bot</artifactId>
<version>0.0.48-SNAPSHOT</version>
</parent>
<artifactId>telegram-simple</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-core-simple</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-consumer-simple</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.godfather.telegram</groupId>
<artifactId>telegram-sender-simple</artifactId>
</dependency>
</dependencies>
</project>