Init commit
commit
bd5a14da19
|
@ -0,0 +1,5 @@
|
|||
### Intellij Idea ###
|
||||
.idea
|
||||
|
||||
### Maven ###
|
||||
target
|
|
@ -0,0 +1,11 @@
|
|||
# Build stage
|
||||
FROM maven:3.6.0-jdk-11-slim AS build
|
||||
COPY src /home/app/src
|
||||
COPY pom.xml /home/app
|
||||
RUN mvn -f /home/app/pom.xml clean package
|
||||
|
||||
# Package stage
|
||||
FROM openjdk:11-jre-slim
|
||||
COPY --from=build /home/app/target/downloader-bot-1.0-SNAPSHOT.jar /usr/local/lib/downloader-bot-1.0-SNAPSHOT.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java","-jar","/usr/local/lib/downloader-bot-1.0-SNAPSHOT.jar"]
|
|
@ -0,0 +1,22 @@
|
|||
version: '3.8'
|
||||
services:
|
||||
app:
|
||||
image: 'docker-spring-boot-postgres:latest'
|
||||
build:
|
||||
context: .
|
||||
container_name: app
|
||||
depends_on:
|
||||
- db
|
||||
environment:
|
||||
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/postgres
|
||||
- SPRING_DATASOURCE_USERNAME=postgres
|
||||
- SPRING_DATASOURCE_PASSWORD=zPAwQpsFZC
|
||||
|
||||
db:
|
||||
image: postgres:14.1-alpine
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=zPAwQpsFZC
|
||||
ports:
|
||||
- '5432:5432'
|
|
@ -0,0 +1,65 @@
|
|||
<?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>
|
||||
|
||||
<groupId>ru.mike.downloaderbot</groupId>
|
||||
<artifactId>downloader-bot</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.5.0</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.pengrad</groupId>
|
||||
<artifactId>java-telegram-bot-api</artifactId>
|
||||
<version>6.7.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.28</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.liquibase</groupId>
|
||||
<artifactId>liquibase-core</artifactId>
|
||||
<version>4.22.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,21 @@
|
|||
package ru.mike.downloaderbot;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DownloaderBotApplication implements CommandLineRunner {
|
||||
@Autowired
|
||||
private UpdateProcessor updateProcessor;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DownloaderBotApplication.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
updateProcessor.processUpdates();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package ru.mike.downloaderbot;
|
||||
|
||||
import com.pengrad.telegrambot.TelegramBot;
|
||||
import com.pengrad.telegrambot.UpdatesListener;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.mike.downloaderbot.processor.updatetype.UpdateTypeProcessor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UpdateProcessor {
|
||||
@Autowired
|
||||
private TelegramBot telegramBot;
|
||||
|
||||
@Autowired
|
||||
private List<UpdateTypeProcessor> updateTypeProcessors;
|
||||
|
||||
public void processUpdates() {
|
||||
telegramBot.setUpdatesListener(updates -> {
|
||||
|
||||
for (Update update : updates) {
|
||||
Optional<UpdateTypeProcessor> updateTypeProcessorOpt = updateTypeProcessors.stream()
|
||||
.filter(p -> p.isSuitableProcessor(update))
|
||||
.findFirst();
|
||||
|
||||
if (updateTypeProcessorOpt.isPresent()) {
|
||||
updateTypeProcessorOpt.get().process(update);
|
||||
} else {
|
||||
log.warn("Unable to find suitable updateTypeProcessor. Update:{}", update);
|
||||
}
|
||||
}
|
||||
|
||||
return UpdatesListener.CONFIRMED_UPDATES_ALL;
|
||||
}, e -> {
|
||||
if (e.response() != null) {
|
||||
// Ошибка из Телеграма
|
||||
e.response().errorCode();
|
||||
e.response().description();
|
||||
} else {
|
||||
// Как видно проблема сети
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package ru.mike.downloaderbot.config;
|
||||
|
||||
import com.pengrad.telegrambot.TelegramBot;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class BotConfig {
|
||||
|
||||
@Bean
|
||||
public TelegramBot telegramBot() {
|
||||
return new TelegramBot("6181387751:AAFha962O3-tK31DghfEIhW_wTfSF-JJBlk");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package ru.mike.downloaderbot.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "channel")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Getter
|
||||
public class Channel {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private UUID id;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "link")
|
||||
private String link;
|
||||
|
||||
@Column(name = "telegram_channel_id")
|
||||
private Long telegramChannelId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "channel_id")
|
||||
private Rule rule;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package ru.mike.downloaderbot.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "link_data")
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class LinkData {
|
||||
@Id
|
||||
private UUID id;
|
||||
|
||||
@Column(name = "resource_link")
|
||||
private String resourceLink;
|
||||
|
||||
@Column(name = "bot_link")
|
||||
private String botLink;
|
||||
|
||||
/**
|
||||
* Имя канала, с которого пришел пользователь по ссылке {@link LinkData#botLink}
|
||||
*/
|
||||
@Column(name = "channel_name")
|
||||
private String channelName;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package ru.mike.downloaderbot.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Entity
|
||||
@Table(name = "rule")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Getter
|
||||
@Setter
|
||||
public class Rule {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private UUID id;
|
||||
|
||||
@Column(name = "channel_name", unique = true)
|
||||
private String channelName;
|
||||
|
||||
@OneToMany(mappedBy = "rule", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
private Set<Channel> channels = new HashSet<>();
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package ru.mike.downloaderbot.processor.command;
|
||||
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
|
||||
public interface CommandProcessor {
|
||||
|
||||
boolean isSuitableCommand(String command);
|
||||
|
||||
void process(Update update);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package ru.mike.downloaderbot.processor.command;
|
||||
|
||||
import com.pengrad.telegrambot.TelegramBot;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.mike.downloaderbot.domain.LinkData;
|
||||
import ru.mike.downloaderbot.service.LinkDataService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class LinkCommandProcessor implements CommandProcessor {
|
||||
@Autowired
|
||||
private TelegramBot telegramBot;
|
||||
|
||||
@Autowired
|
||||
private LinkDataService linkDataService;
|
||||
|
||||
@Override
|
||||
public boolean isSuitableCommand(String command) {
|
||||
return command.startsWith("/link");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Update update) {
|
||||
List<Long> adminsIds = List.of(283573433L, 421233011L);
|
||||
|
||||
Long currentUserId = update.message().from().id();
|
||||
Long currentChatId = update.message().chat().id();
|
||||
String text = update.message().text();
|
||||
|
||||
if (!adminsIds.contains(currentUserId)) {
|
||||
log.warn("User:'{}' trying to send link:{}, but it's not admin", currentUserId, text);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] splitText = text.split(" ");
|
||||
|
||||
if (splitText.length != 3) {
|
||||
SendMessage wrongFormatMessage = new SendMessage(currentChatId, "Неверный формат команды для генерации ссылки. " +
|
||||
"Формат команды:/link <ссылка> <тег канала>");
|
||||
telegramBot.execute(wrongFormatMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
String linkText = splitText[1];
|
||||
String channelName = splitText[2];
|
||||
|
||||
LinkData createdLinkData = linkDataService.createLinkData(linkText, channelName);
|
||||
|
||||
SendMessage generatedLinkMessage = new SendMessage(currentChatId,
|
||||
"Сгенерированная ссылка:" + createdLinkData.getBotLink());
|
||||
|
||||
telegramBot.execute(generatedLinkMessage);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package ru.mike.downloaderbot.processor.command;
|
||||
|
||||
import com.pengrad.telegrambot.TelegramBot;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.mike.downloaderbot.domain.Rule;
|
||||
import ru.mike.downloaderbot.service.RuleChannelService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RuleCommandProcessor implements CommandProcessor {
|
||||
@Autowired
|
||||
private TelegramBot telegramBot;
|
||||
|
||||
@Autowired
|
||||
private RuleChannelService ruleChannelService;
|
||||
|
||||
@Override
|
||||
public boolean isSuitableCommand(String command) {
|
||||
return command.startsWith("/rule");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Update update) {
|
||||
Long currentChatId = update.message().chat().id();
|
||||
String text = update.message().text();
|
||||
|
||||
String[] splitText = text.split(" ");
|
||||
|
||||
String wrongRuleCommandFormatText = "Неверный формат команды для установки правила. " +
|
||||
"Формат команды:/rule c1 c2 c3\n" +
|
||||
"Где \n" +
|
||||
"c1 - имя канала, для которого применяется правило подписки" +
|
||||
"c2 - <имя канала, на который нужно подписаться>\n" +
|
||||
"c3 - <id канала, на который нужно подписаться>\n" +
|
||||
"c2 каналов может быть много, например \"/rule c1 c2 c2 c2";
|
||||
|
||||
if (splitText.length <= 3) {
|
||||
sendCommandParseErrorMessage(currentChatId, text, wrongRuleCommandFormatText);
|
||||
return;
|
||||
}
|
||||
|
||||
String ruleBaseChannelName = splitText[1];
|
||||
|
||||
String[] ruleSubscribeChannelsNames = Arrays.copyOfRange(splitText, 2, splitText.length);
|
||||
|
||||
if (ruleSubscribeChannelsNames.length % 2 != 0) {
|
||||
sendCommandParseErrorMessage(currentChatId, text, wrongRuleCommandFormatText);
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> channelsNames = new ArrayList<>();
|
||||
List<Long> channelsIds = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < ruleSubscribeChannelsNames.length; i++) {
|
||||
String commandPart = ruleSubscribeChannelsNames[i];
|
||||
|
||||
if (i % 2 == 0) {
|
||||
channelsNames.add(commandPart);
|
||||
} else {
|
||||
try {
|
||||
channelsIds.add(Long.parseLong(commandPart));
|
||||
} catch (NumberFormatException e) {
|
||||
sendCommandParseErrorMessage(currentChatId, text, wrongRuleCommandFormatText);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rule createdRule = ruleChannelService.createRuleAndChannels(ruleBaseChannelName, channelsNames, channelsIds);
|
||||
|
||||
SendMessage successCreateRuleMessage = new SendMessage(currentChatId,
|
||||
createSuccessCreateRuleMessage(createdRule)
|
||||
);
|
||||
telegramBot.execute(successCreateRuleMessage);
|
||||
}
|
||||
|
||||
private void sendCommandParseErrorMessage(Long currentChatId, String text, String wrongRuleCommandFormatText) {
|
||||
log.warn("Unable to parse /rule command:'{}'", text);
|
||||
|
||||
SendMessage wrongFormatMessage = new SendMessage(currentChatId, wrongRuleCommandFormatText);
|
||||
telegramBot.execute(wrongFormatMessage);
|
||||
}
|
||||
|
||||
private String createSuccessCreateRuleMessage(Rule createdRule) {
|
||||
String ruleChannelName = createdRule.getChannelName();
|
||||
String channelsStr = createdRule.getChannels().stream()
|
||||
.map(c -> "Имя: " + c.getName() + ", ссылка: " + c.getLink())
|
||||
.collect(Collectors.joining("\n"));
|
||||
|
||||
return "Правило создано успешно\n" +
|
||||
"Имя канала правила:" + ruleChannelName +
|
||||
"\nКаналы для подписки:\n" +
|
||||
channelsStr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
package ru.mike.downloaderbot.processor.command;
|
||||
|
||||
import com.pengrad.telegrambot.TelegramBot;
|
||||
import com.pengrad.telegrambot.model.ChatMember;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import com.pengrad.telegrambot.request.GetChatMember;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import com.pengrad.telegrambot.response.GetChatMemberResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.mike.downloaderbot.domain.Channel;
|
||||
import ru.mike.downloaderbot.domain.LinkData;
|
||||
import ru.mike.downloaderbot.service.LinkDataService;
|
||||
import ru.mike.downloaderbot.service.RuleChannelService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class StartCommandProcessor implements CommandProcessor {
|
||||
@Autowired
|
||||
private TelegramBot telegramBot;
|
||||
|
||||
@Autowired
|
||||
private LinkDataService linkDataService;
|
||||
|
||||
@Autowired
|
||||
private RuleChannelService ruleChannelService;
|
||||
|
||||
@Override
|
||||
public boolean isSuitableCommand(String command) {
|
||||
return command.startsWith("/start ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Update update) {
|
||||
Long currentChatId = update.message().chat().id();
|
||||
Long currentUserId = update.message().from().id();
|
||||
String text = update.message().text();
|
||||
|
||||
String[] splitText = text.split(" ");
|
||||
|
||||
if (splitText.length != 2) {
|
||||
log.warn("Unable to parse /start command:'{}'", text);
|
||||
|
||||
SendMessage wrongFormatMessage = new SendMessage(currentChatId,
|
||||
"Ой, что-то пошло не так! Попробуйте еще раз!");
|
||||
telegramBot.execute(wrongFormatMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
String linkIdStr = splitText[1];
|
||||
UUID linkId;
|
||||
|
||||
try {
|
||||
linkId = UUID.fromString(linkIdStr);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.warn("Unable to parse link id. Command:'{}', id='{}'", text, linkIdStr);
|
||||
|
||||
SendMessage wrongFormatMessage = new SendMessage(currentChatId,
|
||||
"Ой, что-то пошло не так! Попробуйте еще раз!");
|
||||
telegramBot.execute(wrongFormatMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<LinkData> linkDataOptional = linkDataService.findById(linkId);
|
||||
|
||||
if (linkDataOptional.isEmpty()) {
|
||||
SendMessage linkNotFoundMessage = new SendMessage(currentChatId,
|
||||
"Не нашли ссылку на ресурс... Попробуйте другой!");
|
||||
telegramBot.execute(linkNotFoundMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
LinkData linkData = linkDataOptional.get();
|
||||
|
||||
String channelName = linkData.getChannelName();
|
||||
|
||||
List<Channel> channels = ruleChannelService.findChannelsByRuleChannelName(channelName);
|
||||
|
||||
List<Long> channelsTgIds = channels.stream()
|
||||
.map(Channel::getTelegramChannelId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
if (isAnyChannelNotSubscribed(currentUserId, channelsTgIds)) {
|
||||
String subscribeLinks = channels.stream()
|
||||
.map(Channel::getLink)
|
||||
.collect(Collectors.joining("\n"));
|
||||
|
||||
String subscribeMessage = "Подпишись на каналы:\n" + subscribeLinks;
|
||||
|
||||
telegramBot.execute(new SendMessage(currentChatId, subscribeMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
SendMessage linkMessage = new SendMessage(currentChatId,
|
||||
"Ссылка на ресурс: " + linkData.getResourceLink());
|
||||
telegramBot.execute(linkMessage);
|
||||
}
|
||||
|
||||
private boolean isAnyChannelNotSubscribed(Long currentUserId, List<Long> channelsTgIds) {
|
||||
for (Long channelId : channelsTgIds) {
|
||||
GetChatMember chatMember = new GetChatMember(channelId, currentUserId);
|
||||
GetChatMemberResponse chatMemberResponse = telegramBot.execute(chatMember);
|
||||
|
||||
if (Objects.isNull(chatMemberResponse) || Objects.isNull(chatMemberResponse.chatMember()) ||
|
||||
chatMemberResponse.chatMember().status().equals(ChatMember.Status.left)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package ru.mike.downloaderbot.processor.updatetype;
|
||||
|
||||
import com.pengrad.telegrambot.TelegramBot;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.mike.downloaderbot.processor.command.CommandProcessor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class MessageUpdateTypeProcessor implements UpdateTypeProcessor {
|
||||
@Autowired
|
||||
private TelegramBot telegramBot;
|
||||
|
||||
@Autowired
|
||||
private List<CommandProcessor> commandProcessors;
|
||||
|
||||
@Override
|
||||
public boolean isSuitableProcessor(Update update) {
|
||||
return Objects.nonNull(update.message());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Update update) {
|
||||
String text = update.message().text();
|
||||
Optional<CommandProcessor> commandProcessorOptional = commandProcessors.stream()
|
||||
.filter(cp -> cp.isSuitableCommand(text))
|
||||
.findFirst();
|
||||
|
||||
if (commandProcessorOptional.isPresent()) {
|
||||
commandProcessorOptional.get().process(update);
|
||||
} else {
|
||||
SendMessage sendMessage = new SendMessage(
|
||||
update.message().chat().id(),
|
||||
"Я не понимаю тебя, попробуй другую команду!"
|
||||
);
|
||||
|
||||
telegramBot.execute(sendMessage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package ru.mike.downloaderbot.processor.updatetype;
|
||||
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
|
||||
public interface UpdateTypeProcessor {
|
||||
|
||||
boolean isSuitableProcessor(Update update);
|
||||
|
||||
void process(Update update);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package ru.mike.downloaderbot.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import ru.mike.downloaderbot.domain.Channel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ChannelRepository extends JpaRepository<Channel, UUID> {
|
||||
|
||||
void deleteAllByRuleId(UUID id);
|
||||
|
||||
List<Channel> findAllByRuleId(UUID id);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package ru.mike.downloaderbot.repository;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import ru.mike.downloaderbot.domain.LinkData;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface LinkDataRepository extends CrudRepository<LinkData, UUID> {
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package ru.mike.downloaderbot.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import ru.mike.downloaderbot.domain.Rule;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface RuleRepository extends JpaRepository<Rule, UUID> {
|
||||
|
||||
Optional<Rule> findByChannelName(String name);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package ru.mike.downloaderbot.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.mike.downloaderbot.domain.Channel;
|
||||
import ru.mike.downloaderbot.repository.ChannelRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class ChannelService {
|
||||
@Autowired
|
||||
private ChannelRepository channelRepository;
|
||||
|
||||
@Transactional
|
||||
public void deleteAllByRuleId(UUID id) {
|
||||
channelRepository.deleteAllByRuleId(id);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Channel> findAllByRuleId(UUID id) {
|
||||
return channelRepository.findAllByRuleId(id);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package ru.mike.downloaderbot.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.mike.downloaderbot.domain.LinkData;
|
||||
import ru.mike.downloaderbot.repository.LinkDataRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class LinkDataService {
|
||||
public static final String BOT_LINK_PREFIX = "https://t.me/new_downloaderx_bot";
|
||||
@Autowired
|
||||
private LinkDataRepository linkDataRepository;
|
||||
|
||||
@Transactional
|
||||
public LinkData createLinkData(String linkText, String channelName) {
|
||||
UUID linkId = UUID.randomUUID();
|
||||
LinkData linkData = LinkData.builder()
|
||||
.id(linkId)
|
||||
.resourceLink(linkText)
|
||||
.botLink(BOT_LINK_PREFIX + "?start=" + linkId)
|
||||
.channelName(channelName)
|
||||
.build();
|
||||
|
||||
return linkDataRepository.save(linkData);
|
||||
}
|
||||
|
||||
public Optional<LinkData> findById(UUID linkId) {
|
||||
return linkDataRepository.findById(linkId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package ru.mike.downloaderbot.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.mike.downloaderbot.domain.Channel;
|
||||
import ru.mike.downloaderbot.domain.Rule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class RuleChannelService {
|
||||
public static final String TELEGRAM_CHANNEL_URL_PREFIX = "https://t.me/";
|
||||
@Autowired
|
||||
private RuleService ruleService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Transactional
|
||||
public Rule createRuleAndChannels(
|
||||
String ruleBaseChannelName,
|
||||
List<String> channelsNames,
|
||||
List<Long> channelsIds
|
||||
) {
|
||||
Optional<Rule> ruleOptional = ruleService.findByChannelName(ruleBaseChannelName);
|
||||
Rule rule;
|
||||
|
||||
if (ruleOptional.isEmpty()) {
|
||||
rule = Rule.builder()
|
||||
.channelName(ruleBaseChannelName)
|
||||
.build();
|
||||
} else {
|
||||
rule = ruleOptional.get();
|
||||
}
|
||||
|
||||
Set<Channel> channels = createChannels(rule, channelsNames, channelsIds);
|
||||
channelService.deleteAllByRuleId(rule.getId());
|
||||
|
||||
rule.setChannels(channels);
|
||||
|
||||
return ruleService.save(rule);
|
||||
}
|
||||
|
||||
public List<Channel> findChannelsByRuleChannelName(String name) {
|
||||
Optional<Rule> ruleOptional = ruleService.findByChannelName(name);
|
||||
|
||||
if (ruleOptional.isEmpty()) {
|
||||
log.warn("Unable to find rule by name:{}", name);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
UUID ruleId = ruleOptional.get().getId();
|
||||
List<Channel> channels = channelService.findAllByRuleId(ruleId);
|
||||
|
||||
if (channels.isEmpty()) {
|
||||
log.info("Channels by rule id:'{}' not found", ruleId);
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
private Set<Channel> createChannels(Rule rule, List<String> channelsNames, List<Long> channelsIds) {
|
||||
Set<Channel> channels = new HashSet<>();
|
||||
|
||||
for (int i = 0; i < channelsNames.size(); i++) {
|
||||
String channelName = channelsNames.get(i);
|
||||
|
||||
Channel channel = Channel.builder()
|
||||
.name(channelName)
|
||||
.link(TELEGRAM_CHANNEL_URL_PREFIX + channelName)
|
||||
.rule(rule)
|
||||
.telegramChannelId(channelsIds.get(i))
|
||||
.build();
|
||||
|
||||
channels.add(channel);
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package ru.mike.downloaderbot.service;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.mike.downloaderbot.domain.Rule;
|
||||
import ru.mike.downloaderbot.repository.RuleRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class RuleService {
|
||||
@Autowired
|
||||
private RuleRepository ruleRepository;
|
||||
|
||||
|
||||
public Optional<Rule> findByChannelName(String channelName) {
|
||||
return ruleRepository.findByChannelName(channelName);
|
||||
}
|
||||
|
||||
public Rule save(Rule rule) {
|
||||
return ruleRepository.save(rule);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
spring:
|
||||
datasource:
|
||||
username: postgres
|
||||
password: zPAwQpsFZC
|
||||
driver-class-name: org.postgresql.Driver
|
||||
url: jdbc:postgresql://localhost:5432/postgres
|
||||
jpa:
|
||||
database-platform: org.hibernate.dialect.PostgreSQLDialect
|
||||
hibernate:
|
||||
ddl-auto: validate
|
||||
open-in-view: false
|
||||
liquibase:
|
||||
change-log: classpath:db/migration/master/db.changelog-master.xml
|
||||
enabled: true
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.22.xsd">
|
||||
|
||||
<changeSet id="2023-06-24-init-schema" author="mgrunin">
|
||||
<createTable tableName="link_data">
|
||||
<column name="id" type="uuid">
|
||||
<constraints primaryKey="true"/>
|
||||
</column>
|
||||
<column name="resource_link" type="varchar"></column>
|
||||
<column name="bot_link" type="varchar"></column>
|
||||
<column name="channel_name" type="varchar"></column>
|
||||
</createTable>
|
||||
|
||||
<createTable tableName="rule">
|
||||
<column name="id" type="uuid">
|
||||
<constraints primaryKey="true"/>
|
||||
</column>
|
||||
<column name="channel_name" type="varchar">
|
||||
<constraints unique="true"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
<createTable tableName="channel">
|
||||
<column name="id" type="uuid">
|
||||
<constraints primaryKey="true"/>
|
||||
</column>
|
||||
<column name="link" type="varchar"></column>
|
||||
<column name="name" type="varchar"></column>
|
||||
<column name="telegram_channel_id" type="bigint"></column>
|
||||
<column name="channel_id" type="uuid"></column>
|
||||
</createTable>
|
||||
|
||||
<addForeignKeyConstraint baseTableName="channel"
|
||||
baseColumnNames="channel_id"
|
||||
constraintName="fk_channel_id_rule"
|
||||
referencedTableName="rule"
|
||||
referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.6.xsd">
|
||||
|
||||
<include file="db/migration/2023-06-24-init-schema.xml"/>
|
||||
|
||||
</databaseChangeLog>
|
Loading…
Reference in New Issue