This commit is contained in:
parent
f64c5f8cf7
commit
daab0bb6b7
@ -0,0 +1,62 @@
|
|||||||
|
package dev.struchkov.example.bot.conf;
|
||||||
|
|
||||||
|
import dev.struchkov.godfather.main.domain.EventContainer;
|
||||||
|
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||||
|
import dev.struchkov.godfather.simple.context.service.EventDispatching;
|
||||||
|
import dev.struchkov.godfather.simple.context.service.EventHandler;
|
||||||
|
import dev.struchkov.godfather.simple.core.EventDispatchingImpl;
|
||||||
|
import dev.struchkov.godfather.simple.domain.BoxAnswer;
|
||||||
|
import dev.struchkov.godfather.telegram.main.context.MailPayload;
|
||||||
|
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static dev.struchkov.godfather.telegram.main.context.BoxAnswerPayload.ENABLE_MARKDOWN;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CustomEventDispatching extends EventDispatchingImpl implements EventDispatching {
|
||||||
|
|
||||||
|
private final TelegramSending telegramSending;
|
||||||
|
private final AppProperty appProperty;
|
||||||
|
|
||||||
|
public CustomEventDispatching(List<EventHandler> eventProviders, TelegramSending telegramSending, AppProperty appProperty) {
|
||||||
|
super(eventProviders);
|
||||||
|
this.telegramSending = telegramSending;
|
||||||
|
this.appProperty = appProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispatch(EventContainer event) {
|
||||||
|
if (Mail.class.equals(event.getType())) {
|
||||||
|
final Mail mail = (Mail) event.getObject();
|
||||||
|
final String fromPersonId = mail.getFromPersonId();
|
||||||
|
if (appProperty.getTelegramIds().contains(fromPersonId)) {
|
||||||
|
super.dispatch(event);
|
||||||
|
} else {
|
||||||
|
final StringBuilder messageText = new StringBuilder("\uD83D\uDEA8 *Attempted unauthorized access to the bot*")
|
||||||
|
.append("\n-- -- -- -- --\n");
|
||||||
|
|
||||||
|
mail.getPayLoad(MailPayload.USERNAME)
|
||||||
|
.ifPresent(username -> messageText.append("\uD83E\uDDB9\u200D♂️: @").append(username));
|
||||||
|
|
||||||
|
messageText.append("\n")
|
||||||
|
.append("\uD83D\uDCAC: ").append(mail.getText());
|
||||||
|
|
||||||
|
for (String adminTelegramId : appProperty.getAdminTelegramIds()) {
|
||||||
|
telegramSending.send(
|
||||||
|
BoxAnswer.builder()
|
||||||
|
.recipientPersonId(adminTelegramId)
|
||||||
|
.message(messageText.toString())
|
||||||
|
.payload(ENABLE_MARKDOWN)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.dispatch(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,21 +1,32 @@
|
|||||||
package dev.struchkov.example.bot.service;
|
package dev.struchkov.example.bot.service;
|
||||||
|
|
||||||
import dev.struchkov.example.bot.conf.AppProperty;
|
import dev.struchkov.example.bot.conf.AppProperty;
|
||||||
|
import dev.struchkov.haiti.context.exception.NotFoundException;
|
||||||
import dev.struchkov.openai.context.ChatGptService;
|
import dev.struchkov.openai.context.ChatGptService;
|
||||||
import dev.struchkov.openai.domain.chat.ChatInfo;
|
import dev.struchkov.openai.domain.chat.ChatInfo;
|
||||||
import dev.struchkov.openai.domain.chat.CreateChat;
|
import dev.struchkov.openai.domain.chat.CreateChat;
|
||||||
import dev.struchkov.openai.domain.chat.UpdateChat;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PersonalChatService {
|
public class PersonalChatService {
|
||||||
|
|
||||||
|
public static final String DEFAULT_CHAT_NAME = "DEFAULT";
|
||||||
|
|
||||||
private final ChatGptService chatGptService;
|
private final ChatGptService chatGptService;
|
||||||
private final Map<String, String> chatDefaultContext = new ConcurrentHashMap<>();
|
|
||||||
private final Map<String, ChatInfo> chatMap = new ConcurrentHashMap<>();
|
// ключ это идентификатор пользователя, значение это название чата
|
||||||
|
private final Map<String, String> currentChatMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
// первый ключ это идентификатор пользователя. второй это название чата
|
||||||
|
private final Map<String, Map<String, ChatInfo>> chatMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public PersonalChatService(
|
public PersonalChatService(
|
||||||
AppProperty appProperty,
|
AppProperty appProperty,
|
||||||
@ -24,39 +35,82 @@ public class PersonalChatService {
|
|||||||
this.chatGptService = chatGptService;
|
this.chatGptService = chatGptService;
|
||||||
appProperty.getTelegramIds().forEach(
|
appProperty.getTelegramIds().forEach(
|
||||||
telegramId -> {
|
telegramId -> {
|
||||||
final ChatInfo newChat = this.chatGptService.createChat(
|
final ChatInfo defaultChat = this.chatGptService.createChat(CreateChat.builder().build());
|
||||||
CreateChat.builder().build()
|
final HashMap<String, ChatInfo> personChats = new HashMap<>();
|
||||||
);
|
personChats.put(DEFAULT_CHAT_NAME, defaultChat);
|
||||||
chatMap.put(telegramId, newChat);
|
chatMap.put(telegramId, personChats);
|
||||||
|
currentChatMap.put(telegramId, DEFAULT_CHAT_NAME);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChatInfo getChatByPersonId(String personId) {
|
public ChatInfo createChat(String personId, String chatName) {
|
||||||
return chatMap.get(personId);
|
if (existChat(personId, chatName)) {
|
||||||
|
closeChat(personId, chatName, DEFAULT_CHAT_NAME);
|
||||||
}
|
}
|
||||||
|
final ChatInfo newChat = chatGptService.createChat(CreateChat.builder().build());
|
||||||
public ChatInfo recreateChat(String personId) {
|
chatMap.get(personId).put(chatName, newChat);
|
||||||
final ChatInfo chatInfo = chatMap.get(personId);
|
|
||||||
chatGptService.closeChat(chatInfo.getChatId());
|
|
||||||
final ChatInfo newChat = chatGptService.createChat(
|
|
||||||
CreateChat.builder()
|
|
||||||
.systemBehavior(chatDefaultContext.get(personId))
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
chatMap.put(personId, newChat);
|
|
||||||
return newChat;
|
return newChat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBehavior(String fromPersonId, String behavior) {
|
public String getCurrentChatName(String personId) {
|
||||||
chatDefaultContext.put(fromPersonId, behavior);
|
return currentChatMap.get(personId);
|
||||||
final ChatInfo chatInfo = chatMap.get(fromPersonId);
|
}
|
||||||
chatGptService.updateChat(
|
|
||||||
UpdateChat.builder()
|
public ChatInfo getCurrentChat(String personId) {
|
||||||
.chatId(chatInfo.getChatId())
|
final String currentChatName = getCurrentChatName(personId);
|
||||||
.systemBehavior(behavior)
|
return chatMap.get(personId).get(currentChatName);
|
||||||
.build()
|
}
|
||||||
);
|
|
||||||
|
public void setBehavior(String personId, String chatName, String behavior) {
|
||||||
|
final ChatInfo chatInfo = getChat(personId, chatName);
|
||||||
|
chatInfo.setSystemBehavior(behavior);
|
||||||
|
chatGptService.updateChat(chatInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatInfo getChat(String personId, String chatName) {
|
||||||
|
return Optional.ofNullable(chatMap.get(personId).get(chatName))
|
||||||
|
.orElseThrow(notFoundException("Chat with this name was not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean existChat(String personId, String chatName) {
|
||||||
|
return chatMap.get(personId).containsKey(chatName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeChat(String personId, String closeChatName, String switchChatName) {
|
||||||
|
if (DEFAULT_CHAT_NAME.equals(closeChatName)) {
|
||||||
|
throw new RuntimeException("You can't close the default chat room");
|
||||||
|
}
|
||||||
|
|
||||||
|
final ChatInfo chat = getChat(personId, closeChatName);
|
||||||
|
final ChatInfo switchChat = getChat(personId, switchChatName);
|
||||||
|
|
||||||
|
currentChatMap.put(personId, switchChatName);
|
||||||
|
chatGptService.closeChat(chat.getChatId());
|
||||||
|
chatMap.get(personId).remove(closeChatName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearContext(String personId, String chatName) {
|
||||||
|
final ChatInfo chat = getChat(personId, chatName);
|
||||||
|
chatGptService.clearContext(chat.getChatId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearBehavior(String personId) {
|
||||||
|
final ChatInfo currentChat = getCurrentChat(personId);
|
||||||
|
currentChat.setSystemBehavior(null);
|
||||||
|
chatGptService.updateChat(currentChat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void switchChat(String personId, String chatName) {
|
||||||
|
if (existChat(personId, chatName)) {
|
||||||
|
currentChatMap.put(personId, chatName);
|
||||||
|
} else {
|
||||||
|
throw new NotFoundException("Chat with the name {0} not found", chatName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getAllChatName(String personId) {
|
||||||
|
return chatMap.get(personId).keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package dev.struchkov.example.bot.unit;
|
package dev.struchkov.example.bot.unit;
|
||||||
|
|
||||||
import dev.struchkov.example.bot.conf.AppProperty;
|
|
||||||
import dev.struchkov.example.bot.service.PersonalChatService;
|
import dev.struchkov.example.bot.service.PersonalChatService;
|
||||||
import dev.struchkov.example.bot.util.Cmd;
|
import dev.struchkov.example.bot.util.Cmd;
|
||||||
import dev.struchkov.example.bot.util.UnitName;
|
import dev.struchkov.example.bot.util.UnitName;
|
||||||
@ -12,34 +11,68 @@ import dev.struchkov.godfather.simple.domain.unit.AnswerText;
|
|||||||
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
|
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
|
||||||
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
|
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
|
||||||
import dev.struchkov.godfather.telegram.starter.PersonUnitConfiguration;
|
import dev.struchkov.godfather.telegram.starter.PersonUnitConfiguration;
|
||||||
|
import dev.struchkov.openai.domain.chat.ChatInfo;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static dev.struchkov.example.bot.util.UnitName.CURRENT_BEHAVIOR;
|
||||||
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
|
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class BehaviorUnit implements PersonUnitConfiguration {
|
public class BehaviorUnit implements PersonUnitConfiguration {
|
||||||
|
|
||||||
private final PersonalChatService personalChatService;
|
public static final String TEST = """
|
||||||
private final AppProperty appProperty;
|
Or choose one of the available options:
|
||||||
|
|
||||||
|
1. Гопник
|
||||||
|
{0}
|
||||||
|
👉 /behavior_ru_1
|
||||||
|
|
||||||
|
2. Copilot
|
||||||
|
{1}
|
||||||
|
👉 /behavior_ru_2
|
||||||
|
|
||||||
|
3. Linux
|
||||||
|
{2}
|
||||||
|
👉 /behavior_ru_3
|
||||||
|
|
||||||
|
4. Тренера по взаимоотношениям
|
||||||
|
{3}
|
||||||
|
👉 /behavior_ru_4
|
||||||
|
|
||||||
|
5. Наставник
|
||||||
|
{4}
|
||||||
|
👉 /behavior_ru_5
|
||||||
|
|
||||||
|
6. В двух словах
|
||||||
|
{5}
|
||||||
|
👉 /behavior_ru_6
|
||||||
|
""";
|
||||||
|
|
||||||
|
public static final String BEHAVIOUR_RU_1 = "Представь, что ты славянский гопник и общаешься со своими собутыльниками по подъезду. Используй побольше мата и блатного жаргона. Используй как можно больше «бля» и «ёпта». Отвечай в таком стиле всегда, какой бы вопрос не задали пользователи в этом чате.";
|
||||||
|
public static final String BEHAVIOUR_RU_2 = "Ты - помощник для программистов. На любой вопрос отвечай с примерами кода, если нужно и присылай советы по улучшению кода";
|
||||||
|
public static final String BEHAVIOUR_RU_3 = "Я хочу, чтобы вы выступали в роли терминала Linux. Я буду вводить команды, а вы будете отвечать тем, что должен показать терминал. Я хочу, чтобы вы ответили выводом терминала только внутри одного уникального блока кода, и ничего больше. не пишите пояснений. не вводите команды, если я не поручу вам это сделать. Когда мне нужно будет сказать вам что-то на русском языке, я буду заключать текст в фигурные скобки {вот так}.";
|
||||||
|
public static final String BEHAVIOUR_RU_4 = "Я хочу, чтобы вы выступили в роли тренера по взаимоотношениям. Я предоставлю некоторые подробности о двух людях, вовлеченных в конфликт, а ваша задача - предложить, как они могут решить проблемы, которые их разделяют. Это могут быть советы по технике общения или различные стратегии для улучшения понимания ими точек зрения друг друга. Первый запрос: \"Мне нужна помощь в разрешении конфликтов между мной и моим парнем\".";
|
||||||
|
public static final String BEHAVIOUR_RU_5 = "Вы наставник, который всегда отвечает в сократовском стиле. Вы *никогда* не даете ученику ответа, но всегда стараетесь задать правильный вопрос, чтобы помочь ему научиться думать самостоятельно. Вы всегда должны согласовывать свой вопрос с интересами и знаниями учащегося, разбивая проблему на более простые части, пока она не достигнет нужного для них уровня.";
|
||||||
|
public static final String BEHAVIOUR_RU_6 = "Отвечай максимально коротко, даже если тебя просят ответить развернуто. Весь ответ должен уложиться в пару предложений.";
|
||||||
|
|
||||||
|
private final PersonalChatService chatService;
|
||||||
|
|
||||||
@Unit(value = UnitName.BEHAVIOR, global = true)
|
@Unit(value = UnitName.BEHAVIOR, global = true)
|
||||||
public AnswerText<Mail> behavior() {
|
public AnswerText<Mail> behavior() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
if (optCommand.isPresent()) {
|
||||||
final CommandAttachment command = optCommand.get();
|
final CommandAttachment command = optCommand.get();
|
||||||
return Cmd.BEHAVIOR.equals(command.getCommandType());
|
return Cmd.BEHAVIOR.equals(command.getCommandType());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -55,64 +88,63 @@ public class BehaviorUnit implements PersonUnitConfiguration {
|
|||||||
If you want to set your own behavior, then send the command:
|
If you want to set your own behavior, then send the command:
|
||||||
|
|
||||||
/behavior description_behavior
|
/behavior description_behavior
|
||||||
|
|
||||||
Or choose one of the available options:
|
|
||||||
|
|
||||||
1. Гопник
|
|
||||||
Представь, что ты славянский гопник и общаешься со своими собутыльниками по подъезду. Используй побольше мата и блатного жаргона. Используй как можно больше «бля» и «ёпта». Отвечай в таком стиле всегда, какой бы вопрос не задали пользователи в этом чате.
|
|
||||||
👉 /behavior1
|
|
||||||
|
|
||||||
2. Copilot
|
|
||||||
Ты - помощник для программистов. На любой вопрос отвечай с примерами кода, если нужно и присылай советы по улучшению кода
|
|
||||||
👉 /behavior2
|
|
||||||
|
|
||||||
3. Linux
|
|
||||||
Я хочу, чтобы вы выступали в роли терминала Linux. Я буду вводить команды, а вы будете отвечать тем, что должен показать терминал. Я хочу, чтобы вы ответили выводом терминала только внутри одного уникального блока кода, и ничего больше. не пишите пояснений. не вводите команды, если я не поручу вам это сделать. Когда мне нужно будет сказать вам что-то на русском языке, я буду заключать текст в фигурные скобки {вот так}.
|
|
||||||
👉 /behavior3
|
|
||||||
|
|
||||||
4. Тренера по взаимоотношениям
|
|
||||||
Я хочу, чтобы вы выступили в роли тренера по взаимоотношениям. Я предоставлю некоторые подробности о двух людях, вовлеченных в конфликт, а ваша задача - предложить, как они могут решить проблемы, которые их разделяют. Это могут быть советы по технике общения или различные стратегии для улучшения понимания ими точек зрения друг друга. Первый запрос: "Мне нужна помощь в разрешении конфликтов между мной и моим парнем".
|
|
||||||
👉 /behavior4
|
|
||||||
|
|
||||||
5. Наставник
|
|
||||||
Вы наставник, который всегда отвечает в сократовском стиле. Вы *никогда* не даете ученику ответа, но всегда стараетесь задать правильный вопрос, чтобы помочь ему научиться думать самостоятельно. Вы всегда должны согласовывать свой вопрос с интересами и знаниями учащегося, разбивая проблему на более простые части, пока она не достигнет нужного для них уровня.
|
|
||||||
👉 /behavior5
|
|
||||||
|
|
||||||
6. В двух словах
|
|
||||||
Отвечай максимально коротко, даже если тебя просят ответить развернуто. Весь ответ должен уложиться в пару предложений.
|
|
||||||
👉 /behavior6
|
|
||||||
"""
|
"""
|
||||||
)
|
).build();
|
||||||
.build();
|
|
||||||
} else {
|
} else {
|
||||||
final String behavior = optArg.get();
|
final String behavior = optArg.get();
|
||||||
personalChatService.setBehavior(mail.getFromPersonId(), behavior);
|
final String personId = mail.getFromPersonId();
|
||||||
|
final String currentChatName = chatService.getCurrentChatName(personId);
|
||||||
|
chatService.setBehavior(personId, currentChatName, behavior);
|
||||||
return boxAnswer("\uD83D\uDC4C");
|
return boxAnswer("\uD83D\uDC4C");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Unit(value = UnitName.BEHAVIOUR, global = true)
|
@Unit(value = UnitName.CLEAR_BEHAVIOR, global = true)
|
||||||
// public AnswerText<Mail> behaviour1() {
|
public AnswerText<Mail> clearBehavior() {
|
||||||
// return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
// .triggerCheck(
|
.triggerCheck(
|
||||||
// mail -> {
|
mail -> {
|
||||||
// if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
// final List<Attachment> attachments = mail.getAttachments();
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
// final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
if (optCommand.isPresent()) {
|
||||||
// if (optCommand.isPresent()) {
|
final CommandAttachment command = optCommand.get();
|
||||||
// final CommandAttachment command = optCommand.get();
|
return Cmd.CLEAR_BEHAVIOR.equals(command.getCommandType());
|
||||||
// return Cmd.BEHAVIOUR_1.equals(command.getCommandType());
|
}
|
||||||
// }
|
return false;
|
||||||
// }
|
}
|
||||||
// return false;
|
)
|
||||||
// }
|
.answer(mail -> {
|
||||||
// )
|
chatService.clearBehavior(mail.getFromPersonId());
|
||||||
// .answer(() -> {
|
return boxAnswer("Behavior successfully cleared");
|
||||||
//
|
})
|
||||||
// })
|
.build();
|
||||||
// .build();
|
}
|
||||||
// }
|
|
||||||
|
@Unit(value = CURRENT_BEHAVIOR, global = true)
|
||||||
|
public AnswerText<Mail> currentBehavior() {
|
||||||
|
return AnswerText.<Mail>builder()
|
||||||
|
.triggerCheck(
|
||||||
|
mail -> {
|
||||||
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
|
if (optCommand.isPresent()) {
|
||||||
|
final CommandAttachment command = optCommand.get();
|
||||||
|
return Cmd.CURRENT_BEHAVIOR.equals(command.getCommandType());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.answer(mail -> {
|
||||||
|
final ChatInfo currentChat = chatService.getCurrentChat(mail.getFromPersonId());
|
||||||
|
final String systemBehavior = currentChat.getSystemBehavior();
|
||||||
|
if (systemBehavior != null && !"".equals(systemBehavior)) {
|
||||||
|
return boxAnswer(systemBehavior);
|
||||||
|
}
|
||||||
|
return boxAnswer("The behavior for this chat is not set");
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
package dev.struchkov.example.bot.unit;
|
||||||
|
|
||||||
|
import dev.struchkov.example.bot.service.PersonalChatService;
|
||||||
|
import dev.struchkov.example.bot.util.Cmd;
|
||||||
|
import dev.struchkov.example.bot.util.UnitName;
|
||||||
|
import dev.struchkov.godfather.main.domain.annotation.Unit;
|
||||||
|
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||||
|
import dev.struchkov.godfather.simple.domain.BoxAnswer;
|
||||||
|
import dev.struchkov.godfather.simple.domain.unit.AnswerText;
|
||||||
|
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
|
||||||
|
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
|
||||||
|
import dev.struchkov.godfather.telegram.starter.PersonUnitConfiguration;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ChatSettingUnit implements PersonUnitConfiguration {
|
||||||
|
|
||||||
|
private final PersonalChatService chatService;
|
||||||
|
|
||||||
|
@Unit(value = UnitName.CHAT, global = true)
|
||||||
|
public AnswerText<Mail> chat() {
|
||||||
|
return AnswerText.<Mail>builder()
|
||||||
|
.triggerCheck(
|
||||||
|
mail -> {
|
||||||
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(mail.getAttachments());
|
||||||
|
return optCommand.filter(commandAttachment -> Cmd.CHAT.equals(commandAttachment.getCommandType())).isPresent();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.answer(
|
||||||
|
mail -> {
|
||||||
|
final String personId = mail.getFromPersonId();
|
||||||
|
final CommandAttachment command = Attachments.findFirstCommand(mail.getAttachments()).orElseThrow();
|
||||||
|
final Optional<String> optArg = command.getArg();
|
||||||
|
if (optArg.isPresent()) {
|
||||||
|
final String chatName = optArg.get();
|
||||||
|
final boolean isExistChat = chatService.existChat(personId, chatName);
|
||||||
|
if (!isExistChat) {
|
||||||
|
chatService.createChat(personId, chatName);
|
||||||
|
}
|
||||||
|
chatService.switchChat(personId, chatName);
|
||||||
|
return boxAnswer("Chat successfully switched");
|
||||||
|
} else {
|
||||||
|
final Set<String> chatNames = chatService.getAllChatName(personId);
|
||||||
|
final String chatList;
|
||||||
|
if (chatNames.size() > 1) {
|
||||||
|
chatList = "\n\nYour chats:\n" + chatNames.stream()
|
||||||
|
.filter(name -> !"DEFAULT".equals(name))
|
||||||
|
.collect(Collectors.joining("\n• ", "• ", ""));
|
||||||
|
} else {
|
||||||
|
chatList = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
final String message = MessageFormat.format(
|
||||||
|
"""
|
||||||
|
Chats allow you to have multiple conversations with different discussion contexts.
|
||||||
|
|
||||||
|
To create a new chat room or switch to an existing one, use the
|
||||||
|
|
||||||
|
/chat chat_name{0}
|
||||||
|
""",
|
||||||
|
chatList
|
||||||
|
);
|
||||||
|
return BoxAnswer.builder()
|
||||||
|
.message(message)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unit(value = UnitName.CURRENT_CHAT, global = true)
|
||||||
|
public AnswerText<Mail> getCurrentChatName() {
|
||||||
|
return AnswerText.<Mail>builder()
|
||||||
|
.triggerCheck(
|
||||||
|
mail -> {
|
||||||
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(mail.getAttachments());
|
||||||
|
return optCommand.filter(commandAttachment -> Cmd.CURRENT_CHAT.equals(commandAttachment.getCommandType())).isPresent();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.answer(
|
||||||
|
mail -> {
|
||||||
|
final String currentChatName = chatService.getCurrentChatName(mail.getFromPersonId());
|
||||||
|
return BoxAnswer.builder()
|
||||||
|
.message("Current chat name: " + currentChatName)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unit(value = UnitName.CLOSE_CHAT, global = true)
|
||||||
|
public AnswerText<Mail> closeChat() {
|
||||||
|
return AnswerText.<Mail>builder()
|
||||||
|
.triggerCheck(
|
||||||
|
mail -> {
|
||||||
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(mail.getAttachments());
|
||||||
|
return optCommand.filter(commandAttachment -> Cmd.CLOSE_CHAT.equals(commandAttachment.getCommandType())).isPresent();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.answer(
|
||||||
|
mail -> {
|
||||||
|
final String personId = mail.getFromPersonId();
|
||||||
|
final CommandAttachment command = Attachments.findFirstCommand(mail.getAttachments()).orElseThrow();
|
||||||
|
final Optional<String> optArg = command.getArg();
|
||||||
|
if (optArg.isPresent()) {
|
||||||
|
final String name = optArg.get();
|
||||||
|
chatService.closeChat(personId, name, PersonalChatService.DEFAULT_CHAT_NAME);
|
||||||
|
return boxAnswer("Chat has been successfully closed. You have returned to the default chat room!");
|
||||||
|
} else {
|
||||||
|
final String currentChatName = chatService.getCurrentChatName(personId);
|
||||||
|
chatService.closeChat(personId, currentChatName, PersonalChatService.DEFAULT_CHAT_NAME);
|
||||||
|
return boxAnswer("Chat has been successfully closed. You have returned to the default chat room!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,7 +16,6 @@ import dev.struchkov.godfather.telegram.domain.ClientBotCommand;
|
|||||||
import dev.struchkov.godfather.telegram.domain.attachment.ButtonClickAttachment;
|
import dev.struchkov.godfather.telegram.domain.attachment.ButtonClickAttachment;
|
||||||
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
|
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
|
||||||
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
|
import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard;
|
||||||
import dev.struchkov.godfather.telegram.main.context.MailPayload;
|
|
||||||
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
|
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
|
||||||
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
|
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
|
||||||
import dev.struchkov.godfather.telegram.simple.context.service.TelegramService;
|
import dev.struchkov.godfather.telegram.simple.context.service.TelegramService;
|
||||||
@ -64,6 +63,21 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
.description("help in use")
|
.description("help in use")
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
|
ClientBotCommand.builder()
|
||||||
|
.key(Cmd.CHAT)
|
||||||
|
.description("Create or toggle a chat room")
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ClientBotCommand.builder()
|
||||||
|
.key(Cmd.CLOSE_CHAT)
|
||||||
|
.description("Close the current chat.")
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ClientBotCommand.builder()
|
||||||
|
.key(Cmd.CURRENT_CHAT)
|
||||||
|
.description("Returns the name of the current chat")
|
||||||
|
.build(),
|
||||||
|
|
||||||
ClientBotCommand.builder()
|
ClientBotCommand.builder()
|
||||||
.key(Cmd.CLEAR_CONTEXT)
|
.key(Cmd.CLEAR_CONTEXT)
|
||||||
.description("Clears the discussion context. Start a conversation from the beginning.")
|
.description("Clears the discussion context. Start a conversation from the beginning.")
|
||||||
@ -79,6 +93,16 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
.description("Allows you to set the initial behavior of ChatGPT.")
|
.description("Allows you to set the initial behavior of ChatGPT.")
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
|
ClientBotCommand.builder()
|
||||||
|
.key(Cmd.CURRENT_BEHAVIOR)
|
||||||
|
.description("Returns the current behavior description for the chat")
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ClientBotCommand.builder()
|
||||||
|
.key(Cmd.CLEAR_BEHAVIOR)
|
||||||
|
.description("Clears the behavior settings for the current chat")
|
||||||
|
.build(),
|
||||||
|
|
||||||
ClientBotCommand.builder()
|
ClientBotCommand.builder()
|
||||||
.key(Cmd.SUPPORT_DEV)
|
.key(Cmd.SUPPORT_DEV)
|
||||||
.description("Support project development.")
|
.description("Support project development.")
|
||||||
@ -86,41 +110,12 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unit(value = UnitName.ACCESS_ERROR, main = true)
|
@Unit(value = GPT_UNIT, main = true, global = true)
|
||||||
public AnswerText<Mail> accessError() {
|
|
||||||
return AnswerText.<Mail>builder()
|
|
||||||
.triggerCheck(mail -> !appProperty.getTelegramIds().contains(mail.getFromPersonId()))
|
|
||||||
.answer(message -> {
|
|
||||||
final StringBuilder messageText = new StringBuilder("\uD83D\uDEA8 *Attempted unauthorized access to the bot*")
|
|
||||||
.append("\n-- -- -- -- --\n");
|
|
||||||
|
|
||||||
message.getPayLoad(MailPayload.USERNAME)
|
|
||||||
.ifPresent(username -> messageText.append("\uD83E\uDDB9\u200D♂️: @").append(username));
|
|
||||||
|
|
||||||
messageText.append("\n")
|
|
||||||
.append("\uD83D\uDCAC: ").append(message.getText());
|
|
||||||
|
|
||||||
return BoxAnswer.builder()
|
|
||||||
.recipientPersonId(appProperty.getAdminTelegramIds().get(0))
|
|
||||||
.message(messageText.toString())
|
|
||||||
.payload(ENABLE_MARKDOWN)
|
|
||||||
.build();
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Unit(value = GPT_UNIT, global = true)
|
|
||||||
public AnswerText<Mail> chatGpt() {
|
public AnswerText<Mail> chatGpt() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(mail -> {
|
.triggerCheck(mail -> Attachments.findFirstCommand(mail.getAttachments()).isEmpty())
|
||||||
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
|
||||||
final Optional<CommandAttachment> firstCommand = Attachments.findFirstCommand(mail.getAttachments());
|
|
||||||
return firstCommand.isEmpty();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
.answer(message -> {
|
.answer(message -> {
|
||||||
final ChatInfo chatInfo = personalChatService.getChatByPersonId(message.getFromPersonId());
|
final ChatInfo chatInfo = personalChatService.getCurrentChat(message.getFromPersonId());
|
||||||
final long countMessages = chatGptService.getCountMessages(chatInfo.getChatId());
|
final long countMessages = chatGptService.getCountMessages(chatInfo.getChatId());
|
||||||
|
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
@ -154,19 +149,15 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
return optCommand.filter(commandAttachment -> Cmd.CLEAR_CONTEXT.equals(commandAttachment.getCommandType())).isPresent();
|
||||||
final CommandAttachment command = optCommand.get();
|
|
||||||
return Cmd.CLEAR_CONTEXT.equals(command.getCommandType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(message -> {
|
.answer(message -> {
|
||||||
personalChatService.recreateChat(message.getFromPersonId());
|
final String personId = message.getFromPersonId();
|
||||||
|
final String currentChatName = personalChatService.getCurrentChatName(personId);
|
||||||
|
personalChatService.clearContext(personId, currentChatName);
|
||||||
return boxAnswer("\uD83E\uDDF9 Discussion context cleared successfully");
|
return boxAnswer("\uD83E\uDDF9 Discussion context cleared successfully");
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
@ -177,15 +168,8 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(mail.getAttachments());
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
return optCommand.filter(commandAttachment -> Cmd.START.equals(commandAttachment.getCommandType())).isPresent();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
|
||||||
if (optCommand.isPresent()) {
|
|
||||||
final CommandAttachment command = optCommand.get();
|
|
||||||
return Cmd.START.equals(command.getCommandType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(message -> {
|
.answer(message -> {
|
||||||
@ -216,15 +200,8 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(mail.getAttachments());
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
return optCommand.filter(commandAttachment -> Cmd.PROMPT.equals(commandAttachment.getCommandType())).isPresent();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
|
||||||
if (optCommand.isPresent()) {
|
|
||||||
final CommandAttachment command = optCommand.get();
|
|
||||||
return Cmd.PROMPT.equals(command.getCommandType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(
|
.answer(
|
||||||
@ -272,19 +249,15 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
if (optCommand.isPresent()) {
|
||||||
final CommandAttachment command = optCommand.get();
|
return Cmd.SUPPORT_DEV.equals(optCommand.get().getCommandType());
|
||||||
return Cmd.SUPPORT_DEV.equals(command.getCommandType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final Optional<ButtonClickAttachment> optClick = Attachments.findFirstButtonClick(attachments);
|
final Optional<ButtonClickAttachment> optClick = Attachments.findFirstButtonClick(attachments);
|
||||||
if (optClick.isPresent()) {
|
if (optClick.isPresent()) {
|
||||||
final ButtonClickAttachment click = optClick.get();
|
return Cmd.SUPPORT_DEV.equals(optClick.get().getRawCallBackData());
|
||||||
return Cmd.SUPPORT_DEV.equals(click.getRawCallBackData());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -320,15 +293,8 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(mail.getAttachments());
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
return optCommand.filter(commandAttachment -> Cmd.HELP.equals(commandAttachment.getCommandType())).isPresent();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
|
||||||
if (optCommand.isPresent()) {
|
|
||||||
final CommandAttachment command = optCommand.get();
|
|
||||||
return Cmd.HELP.equals(command.getCommandType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(() -> boxAnswer("""
|
.answer(() -> boxAnswer("""
|
||||||
|
@ -12,7 +12,14 @@ public class Cmd {
|
|||||||
public static final String START = "start";
|
public static final String START = "start";
|
||||||
public static final String BALANCE = "balance";
|
public static final String BALANCE = "balance";
|
||||||
|
|
||||||
|
public static final String CHAT = "chat";
|
||||||
|
public static final String CURRENT_CHAT = "current_chat";
|
||||||
|
public static final String CLOSE_CHAT = "close_chat";
|
||||||
|
|
||||||
public static final String BEHAVIOR = "behavior";
|
public static final String BEHAVIOR = "behavior";
|
||||||
|
public static final String CLEAR_BEHAVIOR = "clear_behavior";
|
||||||
|
public static final String CURRENT_BEHAVIOR = "current_behavior";
|
||||||
|
|
||||||
public static final String BEHAVIOR_1 = "behavior1";
|
public static final String BEHAVIOR_1 = "behavior1";
|
||||||
public static final String BEHAVIOR_2 = "behavior2";
|
public static final String BEHAVIOR_2 = "behavior2";
|
||||||
public static final String BEHAVIOR_3 = "behavior3";
|
public static final String BEHAVIOR_3 = "behavior3";
|
||||||
@ -20,5 +27,4 @@ public class Cmd {
|
|||||||
public static final String BEHAVIOR_5 = "behavior5";
|
public static final String BEHAVIOR_5 = "behavior5";
|
||||||
public static final String BEHAVIOR_6 = "behavior6";
|
public static final String BEHAVIOR_6 = "behavior6";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,20 @@ import lombok.experimental.UtilityClass;
|
|||||||
public class UnitName {
|
public class UnitName {
|
||||||
|
|
||||||
public static final String GPT_UNIT = "GENERAL_MENU";
|
public static final String GPT_UNIT = "GENERAL_MENU";
|
||||||
public static final String CLEAR_CONTEXT = "CLEAR_CONTEXT";
|
|
||||||
public static final String HELP = "HELP";
|
public static final String HELP = "HELP";
|
||||||
public static final String PROMPT = "PROMPT";
|
public static final String PROMPT = "PROMPT";
|
||||||
public static final String ACCESS_ERROR = "ACCESS_ERROR";
|
public static final String ACCESS_ERROR = "ACCESS_ERROR";
|
||||||
public static final String SUPPORT = "SUPPORT";
|
public static final String SUPPORT = "SUPPORT";
|
||||||
public static final String START = "START";
|
public static final String START = "START";
|
||||||
|
|
||||||
|
public static final String CHAT = "CHAT";
|
||||||
|
public static final String CURRENT_CHAT = "CURRENT_CHAT";
|
||||||
|
public static final String CLOSE_CHAT = "CLOSE_CHAT";
|
||||||
|
public static final String CLEAR_CONTEXT = "CLEAR_CONTEXT";
|
||||||
|
|
||||||
public static final String BEHAVIOR = "BEHAVIOR";
|
public static final String BEHAVIOR = "BEHAVIOR";
|
||||||
|
public static final String CURRENT_BEHAVIOR = "CURRENT_BEHAVIOR";
|
||||||
|
public static final String CLEAR_BEHAVIOR = "CLEAR_BEHAVIOR";
|
||||||
|
|
||||||
public static final String BALANCE = "BALANCE";
|
public static final String BALANCE = "BALANCE";
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
app:
|
app:
|
||||||
admin-telegram-ids: ${ADMIN_TELEGRAM_PERSON_ID}
|
admin-telegram-ids: ${ADMIN_TELEGRAM_PERSON_ID}
|
||||||
telegram-ids: ${TELEGRAM_PERSON_ID}
|
telegram-ids: ${TELEGRAM_PERSON_ID}
|
||||||
version: 0.0.1
|
version: 0.1.0
|
||||||
telegram:
|
telegram:
|
||||||
bot:
|
bot:
|
||||||
username: ${TELEGRAM_BOT_USERNAME}
|
username: ${TELEGRAM_BOT_USERNAME}
|
||||||
|
Loading…
Reference in New Issue
Block a user