Перестройка

This commit is contained in:
Struchkov Mark 2021-11-30 12:33:09 +03:00
parent 0729557202
commit e00d106ccb
102 changed files with 2306 additions and 173 deletions

53
bot-context/pom.xml Normal file
View File

@ -0,0 +1,53 @@
<?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">
<parent>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>godfather-bot</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bot-context</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>javax.mail-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.domain;
package dev.struchkov.godfather.context.domain;
import lombok.Data;
import lombok.ToString;

View File

@ -1,13 +1,13 @@
package org.sadtech.social.core.domain;
package dev.struchkov.godfather.context.domain;
import dev.struchkov.godfather.context.domain.content.attachment.GeoCoordinate;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoard;
import dev.struchkov.godfather.context.utils.Description;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.sadtech.social.core.domain.content.attachment.GeoCoordinate;
import org.sadtech.social.core.domain.keyboard.KeyBoard;
import org.sadtech.social.core.utils.Description;
/**
* Контейнер, которые содержит данные, которые будут отправлены пользователю как ответ на его запрос.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.domain.content;
package dev.struchkov.godfather.context.domain.content;
/**
* Сообщение от пользователя типа "Комментарий к обсуждению группы".

View File

@ -1,9 +1,9 @@
package org.sadtech.social.core.domain.content;
package dev.struchkov.godfather.context.domain.content;
import dev.struchkov.godfather.context.utils.Description;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.sadtech.social.core.utils.Description;
/**
* Абстрактная сущность для сообщений от пользователей с привязкой к какому-то контенту (картинка, видео).

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.domain.content;
package dev.struchkov.godfather.context.domain.content;
/**
* Тип сообщения от пользователя {@link Message}.

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.domain.content;
package dev.struchkov.godfather.context.domain.content;
import dev.struchkov.godfather.context.exception.AppBotException;
import lombok.ToString;
import org.sadtech.social.core.exception.AppBotException;
/**
* Заглушка для сообщения от пользователя.

View File

@ -1,10 +1,10 @@
package org.sadtech.social.core.domain.content;
package dev.struchkov.godfather.context.domain.content;
import dev.struchkov.godfather.context.domain.content.attachment.Attachment;
import dev.struchkov.godfather.context.utils.Description;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.sadtech.social.core.domain.content.attachment.Attachment;
import org.sadtech.social.core.utils.Description;
import javax.persistence.Column;
import javax.persistence.Entity;

View File

@ -1,9 +1,9 @@
package org.sadtech.social.core.domain.content;
package dev.struchkov.godfather.context.domain.content;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.sadtech.social.core.domain.BasicEntity;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.domain.BasicEntity;
import dev.struchkov.godfather.context.utils.Description;
import javax.persistence.Column;
import javax.persistence.EnumType;

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.domain.content.attachment;
package dev.struchkov.godfather.context.domain.content.attachment;
import lombok.EqualsAndHashCode;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.utils.Description;
import javax.persistence.Column;
import javax.persistence.Entity;

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.domain.content.attachment;
package dev.struchkov.godfather.context.domain.content.attachment;
/**
* Тип вложения {@link Attachment} к сообщению.

View File

@ -1,10 +1,10 @@
package org.sadtech.social.core.domain.content.attachment;
package dev.struchkov.godfather.context.domain.content.attachment;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.utils.Description;
import java.net.URL;

View File

@ -1,9 +1,9 @@
package org.sadtech.social.core.domain.content.attachment;
package dev.struchkov.godfather.context.domain.content.attachment;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.utils.Description;
/**
* Вложение типа "Карта".

View File

@ -1,8 +1,8 @@
package org.sadtech.social.core.domain.content.attachment;
package dev.struchkov.godfather.context.domain.content.attachment;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.utils.Description;
/**
* Сущность для хранения географических координат.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.domain.keyboard;
package dev.struchkov.godfather.context.domain.keyboard;
/**
* Цвета кнопок на клавиатуре {@link KeyBoard}.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.domain.keyboard;
package dev.struchkov.godfather.context.domain.keyboard;
/**
* Тип кнопки на клавиатуре {@link KeyBoard}.

View File

@ -1,11 +1,11 @@
package org.sadtech.social.core.domain.keyboard;
package dev.struchkov.godfather.context.domain.keyboard;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import lombok.ToString;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.utils.Description;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,11 +1,11 @@
package org.sadtech.social.core.domain.keyboard;
package dev.struchkov.godfather.context.domain.keyboard;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.utils.Description;
/**
* Абстрактная сущность кнопки для клавиатуры.

View File

@ -1,11 +1,11 @@
package org.sadtech.social.core.domain.keyboard;
package dev.struchkov.godfather.context.domain.keyboard;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import lombok.ToString;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.utils.Description;
import java.util.ArrayList;
import java.util.List;

View File

@ -1,12 +1,12 @@
package org.sadtech.social.core.domain.keyboard.button;
package dev.struchkov.godfather.context.domain.keyboard.button;
import dev.struchkov.godfather.context.domain.keyboard.ButtonType;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.sadtech.social.core.domain.keyboard.ButtonType;
import org.sadtech.social.core.domain.keyboard.KeyBoardButton;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.context.utils.Description;
/**
* Кнопка клавиатуры для оплаты счета.

View File

@ -1,13 +1,13 @@
package org.sadtech.social.core.domain.keyboard.button;
package dev.struchkov.godfather.context.domain.keyboard.button;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.sadtech.social.core.domain.keyboard.ButtonColor;
import org.sadtech.social.core.domain.keyboard.ButtonType;
import org.sadtech.social.core.domain.keyboard.KeyBoardButton;
import org.sadtech.social.core.utils.Description;
import dev.struchkov.godfather.context.domain.keyboard.ButtonColor;
import dev.struchkov.godfather.context.domain.keyboard.ButtonType;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton;
import dev.struchkov.godfather.context.utils.Description;
@Getter
@ToString

View File

@ -1,10 +1,10 @@
package org.sadtech.social.core.domain.money;
package dev.struchkov.godfather.context.domain.money;
import dev.struchkov.godfather.context.utils.Description;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.sadtech.social.core.utils.Description;
import javax.persistence.Column;
import javax.persistence.Entity;

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.domain.money;
package dev.struchkov.godfather.context.domain.money;
/**
* Состояние счета.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.exception;
package dev.struchkov.godfather.context.exception;
/**
* Ошибка доступа к чему-либо.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.exception;
package dev.struchkov.godfather.context.exception;
import java.time.LocalDateTime;

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.exception;
package dev.struchkov.godfather.context.exception;
/**
* Исключения настройки бота.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.exception;
package dev.struchkov.godfather.context.exception;
/**
* Ошибки при отправке сообщений.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.exception;
package dev.struchkov.godfather.context.exception;
/**
* Ошибка, когда что-то не найдено.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.exception;
package dev.struchkov.godfather.context.exception;
/**
* Ошибка оплаты.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.exception;
package dev.struchkov.godfather.context.exception;
/**
* Ошибка таймера.

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.repository;
package dev.struchkov.godfather.context.repository;
import lombok.NonNull;
import org.sadtech.social.core.domain.money.Account;
import dev.struchkov.godfather.context.domain.money.Account;
import java.util.Optional;

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.repository;
package dev.struchkov.godfather.context.repository;
import lombok.NonNull;
import org.sadtech.social.core.domain.content.Message;
import dev.struchkov.godfather.context.domain.content.Message;
import java.time.LocalDateTime;
import java.util.List;

View File

@ -1,10 +1,10 @@
package org.sadtech.social.core.repository.impl.jpa;
package dev.struchkov.godfather.context.repository.impl.jpa;
import dev.struchkov.godfather.context.repository.AccountRepository;
import dev.struchkov.godfather.context.repository.jpa.AccountRepositoryJpa;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.social.core.domain.money.Account;
import org.sadtech.social.core.repository.AccountRepository;
import org.sadtech.social.core.repository.jpa.AccountRepositoryJpa;
import dev.struchkov.godfather.context.domain.money.Account;
import java.util.Optional;

View File

@ -1,10 +1,10 @@
package org.sadtech.social.core.repository.impl.jpa;
package dev.struchkov.godfather.context.repository.impl.jpa;
import dev.struchkov.godfather.context.repository.ContentRepository;
import dev.struchkov.godfather.context.repository.jpa.MailRepositoryJpa;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.social.core.domain.content.Mail;
import org.sadtech.social.core.repository.ContentRepository;
import org.sadtech.social.core.repository.jpa.MailRepositoryJpa;
import dev.struchkov.godfather.context.domain.content.Mail;
import java.time.LocalDateTime;
import java.util.List;

View File

@ -1,8 +1,8 @@
package org.sadtech.social.core.repository.impl.local;
package dev.struchkov.godfather.context.repository.impl.local;
import dev.struchkov.godfather.context.repository.AccountRepository;
import lombok.NonNull;
import org.sadtech.social.core.domain.money.Account;
import org.sadtech.social.core.repository.AccountRepository;
import dev.struchkov.godfather.context.domain.money.Account;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,9 +1,9 @@
package org.sadtech.social.core.repository.impl.local;
package dev.struchkov.godfather.context.repository.impl.local;
import dev.struchkov.godfather.context.repository.ContentRepository;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.sadtech.social.core.domain.content.Mail;
import org.sadtech.social.core.repository.ContentRepository;
import dev.struchkov.godfather.context.domain.content.Mail;
import java.time.LocalDateTime;
import java.util.ArrayList;

View File

@ -1,6 +1,6 @@
package org.sadtech.social.core.repository.jpa;
package dev.struchkov.godfather.context.repository.jpa;
import org.sadtech.social.core.domain.money.Account;
import dev.struchkov.godfather.context.domain.money.Account;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.repository.jpa;
package dev.struchkov.godfather.context.repository.jpa;
import org.sadtech.social.core.domain.content.Mail;
import org.sadtech.social.core.repository.impl.jpa.MailRepositoryJpaImpl;
import dev.struchkov.godfather.context.domain.content.Mail;
import dev.struchkov.godfather.context.repository.impl.jpa.MailRepositoryJpaImpl;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.service;
package dev.struchkov.godfather.context.service;
import lombok.NonNull;
import org.sadtech.social.core.domain.money.Account;
import dev.struchkov.godfather.context.domain.money.Account;
/**
* Интерфейс сервиса по работе с оплатой.

View File

@ -1,6 +1,6 @@
package org.sadtech.social.core.service;
package dev.struchkov.godfather.context.service;
import org.sadtech.social.core.domain.content.Mail;
import dev.struchkov.godfather.context.domain.content.Mail;
/**
* Интерфейс для взаимодействия с личными сообщениями.

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.service;
package dev.struchkov.godfather.context.service;
import lombok.NonNull;
import org.sadtech.social.core.domain.content.Message;
import dev.struchkov.godfather.context.domain.content.Message;
import java.time.LocalDateTime;
import java.util.List;

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.service;
package dev.struchkov.godfather.context.service;
import lombok.NonNull;
import org.sadtech.social.core.domain.content.Message;
import dev.struchkov.godfather.context.domain.content.Message;
/**
* Интерфес для изменения запроса пользователя перед тем, как он попадет в подсистему обработки.

View File

@ -1,14 +1,14 @@
package org.sadtech.social.core.service.impl;
package dev.struchkov.godfather.context.service.impl;
import dev.struchkov.godfather.context.exception.AccessException;
import dev.struchkov.godfather.context.exception.NotFoundException;
import dev.struchkov.godfather.context.repository.AccountRepository;
import dev.struchkov.godfather.context.service.AccountService;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.social.core.domain.money.Account;
import org.sadtech.social.core.domain.money.AccountStatus;
import org.sadtech.social.core.exception.AccessException;
import org.sadtech.social.core.exception.NotFoundException;
import org.sadtech.social.core.exception.PaymentException;
import org.sadtech.social.core.repository.AccountRepository;
import org.sadtech.social.core.service.AccountService;
import dev.struchkov.godfather.context.domain.money.Account;
import dev.struchkov.godfather.context.domain.money.AccountStatus;
import dev.struchkov.godfather.context.exception.PaymentException;
@RequiredArgsConstructor
public class AccountServiceImpl implements AccountService {

View File

@ -1,11 +1,11 @@
package org.sadtech.social.core.service.impl;
package dev.struchkov.godfather.context.service.impl;
import dev.struchkov.godfather.context.repository.ContentRepository;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.sadtech.social.core.domain.content.Mail;
import org.sadtech.social.core.repository.ContentRepository;
import org.sadtech.social.core.service.MailService;
import dev.struchkov.godfather.context.domain.content.Mail;
import dev.struchkov.godfather.context.service.MailService;
import java.time.Clock;
import java.time.LocalDateTime;

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.service.sender;
package dev.struchkov.godfather.context.service.sender;
/**
* Тип объекта отправляющего ответы пользователю.

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.service.sender;
package dev.struchkov.godfather.context.service.sender;
import lombok.NonNull;
import org.sadtech.social.core.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.BoxAnswer;
/**
* Интерфейс для отправки ответов пользователю.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.service.sender.email;
package dev.struchkov.godfather.context.service.sender.email;
import lombok.Getter;

View File

@ -1,12 +1,12 @@
package org.sadtech.social.core.service.sender.email;
package dev.struchkov.godfather.context.service.sender.email;
import dev.struchkov.godfather.context.exception.MailSendException;
import dev.struchkov.godfather.context.service.sender.SendType;
import dev.struchkov.godfather.context.service.sender.Sending;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.exception.MailSendException;
import org.sadtech.social.core.service.sender.SendType;
import org.sadtech.social.core.service.sender.Sending;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import javax.mail.Authenticator;
import javax.mail.Message;

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.utils;
package dev.struchkov.godfather.context.utils;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.utils;
package dev.struchkov.godfather.context.utils;
import lombok.NonNull;

View File

@ -1,10 +1,10 @@
package org.sadtech.social.core.utils;
package dev.struchkov.godfather.context.utils;
import org.sadtech.social.core.domain.keyboard.ButtonColor;
import org.sadtech.social.core.domain.keyboard.KeyBoard;
import org.sadtech.social.core.domain.keyboard.KeyBoardButton;
import org.sadtech.social.core.domain.keyboard.KeyBoardLine;
import org.sadtech.social.core.domain.keyboard.button.KeyBoardButtonText;
import dev.struchkov.godfather.context.domain.keyboard.ButtonColor;
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.KeyBoardButtonText;
import java.util.Arrays;
import java.util.List;

View File

@ -1,7 +1,7 @@
package org.sadtech.social.core.utils;
package dev.struchkov.godfather.context.utils;
import org.sadtech.social.core.domain.content.EmptyMessage;
import org.sadtech.social.core.domain.content.Message;
import dev.struchkov.godfather.context.domain.content.EmptyMessage;
import dev.struchkov.godfather.context.domain.content.Message;
/**
* Класс для хранения объекта заглушки для {@link Message}.

View File

@ -1,4 +1,4 @@
package org.sadtech.social.core.utils;
package dev.struchkov.godfather.context.utils;
/**
* Класс утилита, содержащий сообщения об ошибках, и сообщения логирования.

View File

@ -1,11 +1,9 @@
package org.sadtech.social.core.utils;
package dev.struchkov.godfather.context.utils;
import org.sadtech.social.core.domain.BoxAnswer;
import org.sadtech.social.core.domain.content.Comment;
import org.sadtech.social.core.domain.content.Message;
import org.sadtech.social.core.service.sender.Sending;
import static org.sadtech.social.core.utils.Messages.UTILITY_CLASS;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.context.domain.content.Comment;
/**
* Используется для отправки сообщений определенного типа.
@ -15,7 +13,7 @@ import static org.sadtech.social.core.utils.Messages.UTILITY_CLASS;
public class Sender {
private Sender() {
throw new IllegalStateException(UTILITY_CLASS);
throw new IllegalStateException(Messages.UTILITY_CLASS);
}
public static void sends(Message message, BoxAnswer boxAnswer, Sending sending) {

154
bot-core/pom.xml Normal file
View File

@ -0,0 +1,154 @@
<?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</groupId>
<artifactId>godfather-bot</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>bot-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Bot Core</name>
<description>Реализация основной логики для создания ботов без привязки к конкретным социальным сетям.</description>
<url>https://github.com/uPagge/social-bot</url>
<licenses>
<license>
<name>BSD 3-Clause "New" or "Revised" License</name>
<url>https://github.com/uPagge/social-bot/blob/master/LICENSE</url>
</license>
</licenses>
<scm>
<connection>scm:git:https://github.com/uPagge/social-bot.git</connection>
<url>https://github.com/uPagge/social-bot</url>
<developerConnection>scm:git:https://github.com/uPagge/social-bot.git</developerConnection>
</scm>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context</artifactId>
</dependency>
<dependency>
<groupId>org.sadtech.autoresponder</groupId>
<artifactId>autoresponder</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.7</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.7</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</build>
<developers>
<developer>
<id>uPagge</id>
<name>Struchkov Mark</name>
<email>upagge@mail.ru</email>
<organization>SADTECH</organization>
</developer>
</developers>
</project>

View File

@ -0,0 +1,148 @@
package dev.struchkov.godfather.core;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.exception.ConfigAppException;
import dev.struchkov.godfather.context.exception.NotFoundException;
import dev.struchkov.godfather.context.service.AccountService;
import dev.struchkov.godfather.context.service.MessageService;
import dev.struchkov.godfather.context.service.Modifiable;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.core.domain.unit.UnitActiveType;
import dev.struchkov.godfather.core.service.action.ActionUnit;
import dev.struchkov.godfather.core.service.action.AnswerAccountAction;
import dev.struchkov.godfather.core.service.action.AnswerCheckAction;
import dev.struchkov.godfather.core.service.action.AnswerProcessingAction;
import dev.struchkov.godfather.core.service.action.AnswerSaveAction;
import dev.struchkov.godfather.core.service.action.AnswerTextAction;
import dev.struchkov.godfather.core.service.action.AnswerTimerAction;
import dev.struchkov.godfather.core.service.action.AnswerValidityAction;
import dev.struchkov.godfather.core.service.timer.TimerService;
import dev.struchkov.godfather.core.utils.TypeUnit;
import org.sadtech.autoresponder.AutoResponder;
import org.sadtech.autoresponder.entity.UnitPointer;
import org.sadtech.autoresponder.repository.UnitPointerRepository;
import org.sadtech.autoresponder.service.UnitPointerServiceImpl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
public class GeneralAutoResponder<T extends Message> extends TimerTask {
protected final AutoResponder<MainUnit> autoResponder;
private final MessageService<T> messageService;
protected Map<String, ActionUnit<? extends MainUnit, ? extends Message>> actionUnitMap = new HashMap<>();
protected List<Modifiable<T>> modifiables;
private ExecutorService executorService = Executors.newFixedThreadPool(10);
protected GeneralAutoResponder(Set<MainUnit> menuUnit,
Sending sending,
MessageService<T> messageService,
UnitPointerRepository<MainUnit> unitPointerRepository
) {
this.messageService = messageService;
autoResponder = new AutoResponder<>(new UnitPointerServiceImpl<>(unitPointerRepository), menuUnit);
init(sending);
}
private void init(Sending sending) {
actionUnitMap.put(TypeUnit.CHECK, new AnswerCheckAction());
actionUnitMap.put(TypeUnit.PROCESSING, new AnswerProcessingAction(sending));
actionUnitMap.put(TypeUnit.TEXT, new AnswerTextAction(sending));
actionUnitMap.put(TypeUnit.VALIDITY, new AnswerValidityAction());
}
public void initModifiables(List<Modifiable<T>> modifiables) {
this.modifiables = modifiables;
}
protected void initActionUnit(String typeUnit, ActionUnit<? super MainUnit, T> actionUnit) {
if (!actionUnitMap.containsKey(typeUnit)) {
actionUnitMap.put(typeUnit, actionUnit);
} else {
throw new ConfigAppException("Обработка такого типа юнита уже зарегистрирована");
}
}
public <U extends MainUnit> void initDefaultUnit(U defaultUnit) {
autoResponder.setDefaultUnit(defaultUnit);
}
public void initSaveAction(AnswerSaveAction<?> answerSaveAction) {
actionUnitMap.put(TypeUnit.SAVE, answerSaveAction);
}
public void initTimerAction(TimerService timerService) {
actionUnitMap.put(TypeUnit.TIMER, new AnswerTimerAction(timerService, this));
}
public void initAccountAction(AccountService accountService, TimerService timerService) {
actionUnitMap.put(TypeUnit.ACCOUNT, new AnswerAccountAction(accountService, timerService));
}
public void setDefaultUnit(MainUnit mainUnit) {
autoResponder.setDefaultUnit(mainUnit);
}
public void checkNewMessage() {
List<T> eventByTime = messageService.getNewMessage();
if (eventByTime != null && !eventByTime.isEmpty()) {
executorService.execute(
() -> eventByTime.parallelStream().forEach(processing())
);
}
}
private Consumer<T> processing() {
return event -> {
if (modifiables != null) {
modifiables.forEach(modifiable -> modifiable.change(event));
}
autoResponder.answer(event.getPersonId(), event.getText()).ifPresent(unitAnswer -> answer(event, unitAnswer));
};
}
public void answer(T event, MainUnit unitAnswer) {
unitAnswer = getAction(event, unitAnswer);
unitAnswer = activeUnitAfter(unitAnswer, event);
if (!(autoResponder.getDefaultUnit() != null && autoResponder.getDefaultUnit().equals(unitAnswer))) {
autoResponder.getUnitPointerService().save(new UnitPointer<>(event.getPersonId(), unitAnswer));
}
}
private MainUnit activeUnitAfter(MainUnit mainUnit, T content) {
if (mainUnit.getNextUnits() != null) {
Optional<MainUnit> first = mainUnit.getNextUnits().stream()
.filter(unit -> UnitActiveType.AFTER.equals(unit.getActiveType()))
.findFirst();
if (first.isPresent()) {
getAction(content, first.get());
return activeUnitAfter(first.get(), content);
}
}
return mainUnit;
}
private MainUnit getAction(T event, MainUnit unitAnswer) {
if (actionUnitMap.containsKey(unitAnswer.getType())) {
ActionUnit actionUnit = actionUnitMap.get(unitAnswer.getType());
MainUnit mainUnit = actionUnit.action(unitAnswer, event);
if (!unitAnswer.equals(mainUnit)) return getAction(event, mainUnit);
return mainUnit;
}
throw new NotFoundException("ActionUnit для типа " + unitAnswer.getType() + " не зарегистрирован");
}
@Override
public void run() {
checkNewMessage();
}
}

View File

@ -0,0 +1,33 @@
package dev.struchkov.godfather.core.domain;
import dev.struchkov.godfather.context.domain.money.Account;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
/**
* Объект, для автоматической проверки оплаты счета {@link Account}.
*
* @author upagge [11/07/2019]
*/
@Getter
@EqualsAndHashCode
@ToString
@Builder
public class AccountAutoCheck {
@Description("Unut, который обрабатывается при успешной оплате")
private MainUnit successfulPayment;
@Description("Unit, который обрабатывается при не успешной оплате")
private MainUnit failedPayment;
@Description("Период проверки")
private Integer periodSec;
@Description("Время жизни счета")
private Integer lifeTimeHours;
}

View File

@ -0,0 +1,14 @@
package dev.struchkov.godfather.core.domain;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import lombok.Builder;
import lombok.Getter;
@Builder
@Getter
public class Clarification {
private BoxAnswer question;
private String value;
}

View File

@ -0,0 +1,44 @@
package dev.struchkov.godfather.core.domain;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.core.service.usercode.CheckData;
import lombok.Builder;
import lombok.Data;
import java.time.LocalDateTime;
/**
* Используется для отложенной активации обработки Unit-ов.
*
* @author upagge [11/07/2019]
*/
@Builder
@Data
public class Timer {
@Description("Идентификатор таймера")
private Integer id;
@Description("Unit, обработка которого откладывается")
private MainUnit unitAnswer;
@Description("Unit, который будет обработан после удаления таймера")
private MainUnit unitDeath;
@Description("Идентификатор пользователя")
private Long personId;
@Description("Время активации таймера")
private LocalDateTime timeActive;
@Description("Время смерти таймера")
private LocalDateTime timeDeath;
@Description("Интервал срабатывания таймера")
private Integer periodSec;
@Description("Условие срабатывания таймера")
private CheckData checkLoop;
}

View File

@ -0,0 +1,29 @@
package dev.struchkov.godfather.core.domain.question;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.utils.Description;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.Singular;
import java.util.List;
/**
* Используется для конфигурации генерации цепочки Unit-ов в виде тестов для прохождения пользователем.
*
* @author upagge [14/07/2019]
*/
@Getter
@Setter
@Builder
public class Question {
@Description("Вопрос")
private BoxAnswer boxAnswer;
@Singular
@Description("Список предполагаемых ответов")
private List<QuestionAnswer> questionAnswers;
}

View File

@ -0,0 +1,32 @@
package dev.struchkov.godfather.core.domain.question;
import dev.struchkov.godfather.context.utils.Description;
import lombok.Getter;
import lombok.Setter;
/**
* Используется для конфигурации генерации цепочки Unit-ов в виде тестов для прохождения пользователем.
* Отвечает за варианты ответов.
*
* @author upagge [14/07/2019]
*/
@Getter
@Setter
public class QuestionAnswer {
@Description("Текстовый ответ")
private String text;
@Description("Количество балов за ответ")
private int points;
public QuestionAnswer(String text, Integer points) {
this.text = text;
this.points = points;
}
public QuestionAnswer(String text) {
this.text = text;
}
}

View File

@ -0,0 +1,27 @@
package dev.struchkov.godfather.core.domain.question;
import dev.struchkov.godfather.context.utils.Description;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
/**
* Используется для сохранения результатов ответов на вопросы.
*
* @author upagge [14/07/2019]
*/
@Getter
@Setter
@AllArgsConstructor
public class QuestionResult {
@Description("Вопрос")
private String question;
@Description("Ответ")
private String answer;
@Description("Количество баллов за ответ")
private Integer points;
}

View File

@ -0,0 +1,60 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.domain.AccountAutoCheck;
import dev.struchkov.godfather.core.utils.TypeUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Юнит для обработки платежей.
*
* @author upagge [08/07/2019]
*/
@Getter
@EqualsAndHashCode(callSuper = true)
public class AnswerAccount extends MainUnit {
@Description("Сумма к оплате")
private final Integer totalSum;
@Description("Время жизни счета")
private final Integer timeHours;
@Description("Настройки для автоматической проверки оплаты")
private final AccountAutoCheck autoCheck;
@Builder
private AnswerAccount(
@Singular Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
@Singular Set<MainUnit> nextUnits,
UnitActiveType activeType,
Integer totalSum,
Integer timeHours,
AccountAutoCheck autoCheck
) {
super(
keyWords,
phrase,
pattern,
matchThreshold,
priority,
nextUnits,
(activeType == null) ? UnitActiveType.AFTER : activeType,
TypeUnit.ACCOUNT
);
this.totalSum = totalSum;
this.timeHours = timeHours;
this.autoCheck = autoCheck;
}
}

View File

@ -0,0 +1,52 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.service.usercode.CheckData;
import dev.struchkov.godfather.core.utils.TypeUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Обработчик запроса, который реализует конструкцию IF в сценарии.
*
* @author upagge [08/07/2019]
*/
@Getter
@EqualsAndHashCode(callSuper = true)
public class AnswerCheck extends MainUnit {
@Description("Unit для true")
private final MainUnit unitTrue;
@Description("Unit для false")
private final MainUnit unitFalse;
@Description("Условие проверки")
private final CheckData<Message> check;
@Builder
protected AnswerCheck(
@Singular Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
@Singular Set<MainUnit> nextUnits,
UnitActiveType activeType,
MainUnit unitTrue,
MainUnit unitFalse,
CheckData<Message> check
) {
super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits, activeType, TypeUnit.CHECK);
this.unitTrue = unitTrue;
this.unitFalse = unitFalse;
this.check = check;
}
}

View File

@ -0,0 +1,46 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.service.usercode.ProcessingData;
import dev.struchkov.godfather.core.utils.TypeUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Обработчик для кастомных реализаций.
*
* @author upagge [08/07/2019]
*/
@Getter
@EqualsAndHashCode(callSuper = true)
public class AnswerProcessing<M extends Message> extends MainUnit {
@Description("Кастомная обработка")
private final ProcessingData<M> processingData;
@Description("Объект для сквозной отправки ответа")
private final Sending sending;
@Builder
private AnswerProcessing(@Singular Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
@Singular Set<MainUnit> nextUnits,
UnitActiveType activeType,
ProcessingData<M> processingData,
Sending sending) {
super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits, activeType, TypeUnit.PROCESSING);
this.processingData = processingData;
this.sending = sending;
}
}

View File

@ -0,0 +1,75 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.service.save.CheckSave;
import dev.struchkov.godfather.core.service.save.Preservable;
import dev.struchkov.godfather.core.service.save.data.PreservableData;
import dev.struchkov.godfather.core.service.save.push.Pusher;
import dev.struchkov.godfather.core.utils.TypeUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Обработчик для сохранения ответов пользователя. Так же допускается скрытое сохранение.
*
* @author upagge [08/07/2019]
*/
@Getter
@EqualsAndHashCode(callSuper = true)
public class AnswerSave<D> extends MainUnit {
@Description("Объект отвечающий за сохранение - репозиторий")
private final Preservable<D> preservable;
@Description("Ключ для данных")
private final String key;
@Description("Отправка результатов")
private final Pusher<D> pusher;
@Description("Данные для скрытого сохранения")
private final PreservableData<D, ? super Message> preservableData;
@Description("Скрытое сохранение")
private final boolean hidden;
private final CheckSave<? super Message> checkSave;
@Builder
private AnswerSave(@Singular Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
@Singular Set<MainUnit> nextUnits,
Preservable<D> preservable,
String key,
Pusher<D> pusher,
PreservableData<D, ? super Message> preservableData,
CheckSave<? super Message> checkSave,
boolean hidden) {
super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits, (hidden) ? UnitActiveType.AFTER : UnitActiveType.DEFAULT, TypeUnit.SAVE);
this.key = key;
this.pusher = pusher;
maintenanceNextUnit(nextUnits);
this.preservable = preservable;
this.preservableData = preservableData;
this.hidden = Optional.of(hidden).orElse(false);
this.checkSave = checkSave;
}
private void maintenanceNextUnit(Collection<MainUnit> units) {
if (units != null) {
units.forEach(mainUnit -> mainUnit.setActiveType(UnitActiveType.AFTER));
}
}
}

View File

@ -0,0 +1,55 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.service.usercode.Insert;
import dev.struchkov.godfather.core.utils.TypeUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Используется для отправки ответа пользователю.
*
* @author upagge [08/07/2019]
*/
@Getter
@EqualsAndHashCode(callSuper = true)
public class AnswerText extends MainUnit {
@Description("Объект, который необходимо отправить пользователю")
private final BoxAnswer boxAnswer;
@Description("Информация, которую необходимо вставить вместо маркеров в строку ответа")
private final Insert insert;
@Description("Объект нестандартной отправки ответа")
private final Sending sending;
@Builder(toBuilder = true)
private AnswerText(@Singular Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
@Singular Set<MainUnit> nextUnits,
UnitActiveType activeType,
BoxAnswer boxAnswer,
Insert insert,
Sending sending) {
super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits, activeType, TypeUnit.TEXT);
this.boxAnswer = boxAnswer;
this.insert = insert;
this.sending = sending;
}
public static AnswerText of(String message) {
return AnswerText.builder().boxAnswer(BoxAnswer.of(message)).build();
}
}

View File

@ -0,0 +1,56 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.service.usercode.CheckData;
import dev.struchkov.godfather.core.utils.TypeUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import lombok.ToString;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Обработчик таймер, позволяющий отложить обработку других Unit-ов.
*
* @author upagge [08/07/2019]
*/
@Getter
@ToString
@EqualsAndHashCode(callSuper = true)
public class AnswerTimer extends MainUnit {
@Description("Unit обработку которого необходимо отложить")
private final MainUnit unitAnswer;
@Description("Задержка обработки в секундах")
private final Integer timeDelaySec;
@Description("Время, через которое таймер будет удален в секундах")
private final Integer timeDeathSec;
@Description("Условие срабатывания отложенного Unit")
private final CheckData checkLoop;
@Builder
private AnswerTimer(@Singular Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
@Singular Set<MainUnit> nextUnits,
UnitActiveType activeType,
MainUnit unitAnswer,
Integer timeDelaySec,
Integer timeDeathSec,
CheckData checkLoop) {
super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits, (activeType == null) ? UnitActiveType.AFTER : activeType, TypeUnit.TIMER);
this.unitAnswer = unitAnswer;
this.timeDelaySec = timeDelaySec;
this.timeDeathSec = timeDeathSec;
this.checkLoop = checkLoop;
}
}

View File

@ -0,0 +1,59 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.utils.Description;
import dev.struchkov.godfather.core.service.save.LocalPreservable;
import dev.struchkov.godfather.core.service.save.Preservable;
import dev.struchkov.godfather.core.service.usercode.ClarificationQuestion;
import dev.struchkov.godfather.core.utils.TypeUnit;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Singular;
import lombok.ToString;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Обработка данных со страницы пользователя.
*
* @author upagge [11/07/2019]
*/
@Getter
@ToString
@EqualsAndHashCode(callSuper = true)
public class AnswerValidity extends MainUnit {
@Description("Unit обрабатывается, если пользователь подтверждает данные")
private final MainUnit unitYes;
@Description("Unit обрабатывается, если пользователь отклоняет данные")
private final MainUnit unitNo;
@Description("Unit обрабатывается, если данные не найдены")
private final MainUnit unitNull;
private final Preservable<String> tempSave = new LocalPreservable<>();
private final ClarificationQuestion clarificationQuestion;
@Builder(toBuilder = true)
private AnswerValidity(@Singular Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
@Singular Set<MainUnit> nextUnits,
UnitActiveType activeType,
MainUnit unitYes,
MainUnit unitNo,
MainUnit unitNull,
ClarificationQuestion clarificationQuestion) {
super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits, UnitActiveType.DEFAULT, TypeUnit.VALIDITY);
this.unitYes = unitYes;
this.unitNo = unitNo;
this.unitNull = unitNull;
this.clarificationQuestion = clarificationQuestion;
}
}

View File

@ -0,0 +1,49 @@
package dev.struchkov.godfather.core.domain.unit;
import dev.struchkov.godfather.context.utils.Description;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.sadtech.autoresponder.entity.Unit;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
/**
* Главный обработчик {@link Unit}, от него наследуются все остальные Unit-ы.
*
* @author upagge [08/07/2019]
*/
@ToString
@EqualsAndHashCode(callSuper = true)
public abstract class MainUnit extends Unit<MainUnit> {
@Getter
@Description("Тип Unit-а")
protected final String type;
@Getter
@Setter
@Description("Режим срабатывания Unit-а")
protected UnitActiveType activeType;
@Getter
private String uuid = UUID.randomUUID().toString();
protected MainUnit(Set<String> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,
Integer priority,
Set<MainUnit> nextUnits,
UnitActiveType activeType,
String type) {
super(keyWords, phrase, pattern, matchThreshold, priority, nextUnits);
this.activeType = Optional.ofNullable(activeType).orElse(UnitActiveType.DEFAULT);
this.type = type;
}
}

View File

@ -0,0 +1,13 @@
package dev.struchkov.godfather.core.domain.unit;
/**
* Тип активации Unit-а. Определяет порядок обработки Unit.
*
* @author upagge [11/07/2019]
*/
public enum UnitActiveType {
DEFAULT,
AFTER
}

View File

@ -0,0 +1,29 @@
package dev.struchkov.godfather.core.repository;
import dev.struchkov.godfather.core.domain.Timer;
import java.time.LocalDateTime;
import java.util.Collection;
/**
* Репозиторий для работы с хранилищем таймеров {@link Timer}.
*
* @author upagge [11/07/2019]
*/
public interface TimerRepository {
Integer add(Timer timer);
/**
* Получить все таймеры, время активации которых меньше, чем переданное время
*
* @param time Время
* @return Коллекция таймеров
*/
Collection<Timer> getTimerActive(LocalDateTime time);
void remove(Integer id);
void edit(Timer timer);
}

View File

@ -0,0 +1,42 @@
package dev.struchkov.godfather.core.repository;
import dev.struchkov.godfather.core.domain.Timer;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Локальная реализация репозитория {@link TimerRepository} на основе HashMap.
*
* @author upagge [11/07/2019]
*/
public class TimerRepositoryMap implements TimerRepository {
private final Map<Integer, Timer> map = new HashMap<>();
private Integer count = 0;
public Integer add(Timer timer) {
timer.setId(count);
map.put(count, timer);
return count++;
}
@Override
public Collection<Timer> getTimerActive(LocalDateTime time) {
return map.values().parallelStream().filter(timer -> time.isAfter(timer.getTimeActive())).collect(Collectors.toSet());
}
@Override
public void remove(Integer id) {
map.remove(id);
}
@Override
public void edit(Timer timer) {
map.put(timer.getId(), timer);
}
}

View File

@ -0,0 +1,23 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
/**
* Интерфейс для обработки Unit-ов.
*
* @author upagge [11/07/2019]
*/
@FunctionalInterface
public interface ActionUnit<M extends MainUnit, C extends Message> {
/**
* Метод обработки Unit-а.
*
* @param unit Unit, который необходимо обработать
* @param content Запрос пользователя
* @return Новый Unit, который может нуждаться в обработке
*/
MainUnit action(M unit, C content);
}

View File

@ -0,0 +1,81 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.content.Mail;
import dev.struchkov.godfather.context.domain.keyboard.button.KeyBoardButtonAccount;
import dev.struchkov.godfather.context.domain.money.Account;
import dev.struchkov.godfather.context.service.AccountService;
import dev.struchkov.godfather.context.utils.KeyBoards;
import dev.struchkov.godfather.core.domain.AccountAutoCheck;
import dev.struchkov.godfather.core.domain.Timer;
import dev.struchkov.godfather.core.domain.unit.AnswerAccount;
import dev.struchkov.godfather.core.domain.unit.AnswerText;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.core.service.timer.TimerService;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneId;
/**
* Обработчик Unit-а {@link AnswerAccount}.
*
* @author upagge [11/07/2019]
*/
public class AnswerAccountAction implements ActionUnit<AnswerAccount, Mail> {
private final AccountService accountService;
private TimerService timerService;
public AnswerAccountAction(AccountService accountService, TimerService timerService) {
this.accountService = accountService;
this.timerService = timerService;
}
public AnswerAccountAction(AccountService accountService) {
this.accountService = accountService;
}
@Override
public MainUnit action(AnswerAccount answerAccount, Mail mail) {
final Account account = new Account();
account.setBelongsPersonId(mail.getPersonId());
account.setTotalSum(answerAccount.getTotalSum());
final Integer accountId = accountService.add(account).getId();
settingCheckTimer(answerAccount, mail, accountId);
KeyBoardButtonAccount buttonAccount = KeyBoardButtonAccount.builder()
.accountId(accountId)
.amount(answerAccount.getTotalSum()).build();
BoxAnswer boxAnswer = BoxAnswer.builder()
.message("Для оплаты укажите номер счета " + accountId + "\nСумма к оплате: "
+ answerAccount.getTotalSum())
.keyBoard(KeyBoards.singelton(buttonAccount))
.build();
return AnswerText.builder().boxAnswer(boxAnswer).build();
}
private void settingCheckTimer(AnswerAccount answerAccount, Mail mail, Integer accountId) {
AccountAutoCheck autoCheck = answerAccount.getAutoCheck();
if (autoCheck != null && timerService != null) {
Timer timer = Timer.builder()
.personId(mail.getPersonId())
.unitAnswer(autoCheck.getSuccessfulPayment())
.unitDeath(autoCheck.getFailedPayment())
.checkLoop(content1 -> accountService.paymentVerification(accountId))
.periodSec(autoCheck.getPeriodSec())
.timeActive(LocalDateTime
.now(Clock.tickSeconds(ZoneId.systemDefault()))
.plusSeconds(autoCheck.getPeriodSec()))
.timeDeath(LocalDateTime
.now(Clock.tickSeconds(ZoneId.systemDefault()))
.plusHours(autoCheck.getLifeTimeHours()))
.build();
timerService.add(timer);
}
}
}

View File

@ -0,0 +1,31 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.unit.AnswerCheck;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import lombok.extern.slf4j.Slf4j;
import java.util.Optional;
/**
* Обработчик Unit-а {@link AnswerCheck}.
*
* @author upagge [11/07/2019]
*/
@Slf4j
public class AnswerCheckAction implements ActionUnit<AnswerCheck, Message> {
@Override
public MainUnit action(AnswerCheck answerCheck, Message mail) {
MainUnit unitAnswer;
if (answerCheck.getCheck().checked(mail)) {
log.info("Проверка пройдена");
unitAnswer = answerCheck.getUnitTrue();
} else {
log.info("Проверка не пройдена");
unitAnswer = answerCheck.getUnitFalse();
}
return Optional.ofNullable(unitAnswer).orElse(answerCheck);
}
}

View File

@ -0,0 +1,36 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.context.utils.Sender;
import dev.struchkov.godfather.core.domain.unit.AnswerProcessing;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
/**
* Обработчик Unit-а {@link AnswerProcessing}.
*
* @author upagge [11/07/2019]
*/
public class AnswerProcessingAction implements ActionUnit<AnswerProcessing<Message>, Message> {
private final Sending sending;
public AnswerProcessingAction(Sending sending) {
this.sending = sending;
}
@Override
public MainUnit action(AnswerProcessing<Message> answerProcessing, Message message) {
BoxAnswer boxAnswer = answerProcessing.getProcessingData().processing(message);
Sending answerProcessingSending = answerProcessing.getSending();
if (answerProcessingSending != null) {
Sender.sends(message, boxAnswer, answerProcessingSending);
} else {
Sender.sends(message, boxAnswer, this.sending);
}
return answerProcessing;
}
}

View File

@ -0,0 +1,39 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.unit.AnswerSave;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.core.service.save.CheckSave;
import dev.struchkov.godfather.core.service.save.Preservable;
import dev.struchkov.godfather.core.service.save.data.PreservableData;
/**
* Обработчик Unit-а {@link AnswerSave}.
*
* @author upagge [11/07/2019]
*/
public class AnswerSaveAction<D> implements ActionUnit<AnswerSave<D>, Message> {
@Override
public MainUnit action(AnswerSave<D> answerSave, Message mail) {
Preservable<D> preservable = answerSave.getPreservable();
Long personId = mail.getPersonId();
CheckSave<? super Message> checkSave = answerSave.getCheckSave();
if (checkSave != null) {
MainUnit unit = checkSave.check(mail);
if (unit != null) {
return unit;
}
}
PreservableData<D, ? super Message> preservableData = answerSave.getPreservableData();
D data = preservableData.getData(mail);
if (data != null) {
preservable.save(personId, answerSave.getKey(), data);
}
preservable.push(personId, answerSave.getPusher());
return answerSave;
}
}

View File

@ -0,0 +1,46 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.context.utils.InsertWords;
import dev.struchkov.godfather.context.utils.Sender;
import dev.struchkov.godfather.core.domain.unit.AnswerText;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* Обработчик Unit-а {@link AnswerText}.
*
* @author upagge [11/07/2019]
*/
@AllArgsConstructor
@NoArgsConstructor
public class AnswerTextAction implements ActionUnit<AnswerText, Message> {
private Sending sending;
@Override
public MainUnit action(AnswerText answerText, Message message) {
BoxAnswer boxAnswer = answerText.getBoxAnswer().toBuilder().build();
if (answerText.getInsert() != null) {
List<String> words = answerText.getInsert().insert(message.getPersonId());
String newMessage = InsertWords.insert(boxAnswer.getMessage(), words);
boxAnswer.setMessage(newMessage);
}
Sending answerTextSending = answerText.getSending();
if (answerTextSending != null) {
Sender.sends(message, boxAnswer, answerTextSending);
} else {
Sender.sends(message, boxAnswer, this.sending);
}
return answerText;
}
}

View File

@ -0,0 +1,68 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.exception.TimerSettingException;
import dev.struchkov.godfather.core.GeneralAutoResponder;
import dev.struchkov.godfather.core.domain.Timer;
import dev.struchkov.godfather.core.domain.unit.AnswerTimer;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.core.service.timer.TimerActionTask;
import dev.struchkov.godfather.core.service.timer.TimerService;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Optional;
/**
* Обработчик Unit-а {@link AnswerTimer}.
*
* @author upagge [11/07/2019]
*/
public class AnswerTimerAction implements ActionUnit<AnswerTimer, Message> {
private TimerService timerService;
private Long verificationPeriodSec = 15L;
public AnswerTimerAction(TimerService timerService, GeneralAutoResponder generalAutoresponder) {
this.timerService = timerService;
TimerActionTask timerActionTask = new TimerActionTask(timerService, generalAutoresponder);
java.util.Timer timer = new java.util.Timer(true);
timer.schedule(timerActionTask, 0, 1000L * verificationPeriodSec);
}
public Long getVerificationPeriodSec() {
return verificationPeriodSec;
}
public void setVerificationPeriodSec(Long verificationPeriodSec) {
this.verificationPeriodSec = verificationPeriodSec;
}
@Override
public MainUnit action(AnswerTimer answerTimer, Message message) {
LocalDateTime timeActive = LocalDateTime
.now(Clock.tickSeconds(ZoneId.systemDefault()))
.plusSeconds(Optional
.ofNullable(answerTimer.getTimeDelaySec())
.orElseThrow(() -> new TimerSettingException("Не установлена временная задержка таймера")));
Timer.TimerBuilder timer = Timer.builder()
.personId(message.getPersonId())
.unitAnswer(answerTimer.getUnitAnswer())
.timeActive(timeActive)
.periodSec(answerTimer.getTimeDelaySec())
.checkLoop(answerTimer.getCheckLoop());
if (answerTimer.getTimeDeathSec() != null) {
timer.timeDeath(LocalDateTime
.now(Clock.tickSeconds(ZoneId.systemDefault()))
.plusSeconds(answerTimer.getTimeDeathSec()));
} else if (answerTimer.getCheckLoop() == null) {
timer.timeDeath(timeActive);
}
timerService.add(timer.build());
return answerTimer;
}
}

View File

@ -0,0 +1,53 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.Clarification;
import dev.struchkov.godfather.core.domain.unit.AnswerText;
import dev.struchkov.godfather.core.domain.unit.AnswerValidity;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Обработчик Unit-а {@link AnswerValidity}.
*
* @author upagge [11/07/2019]
*/
public class AnswerValidityAction implements ActionUnit<AnswerValidity, Message> {
public static final Set<String> WORDS_YES = Set.of("да", "ага");
public static final Set<String> WORDS_NO = Set.of("нет", "неа");
public static final Set<String> WORDS_YES_NO = Set.of("да", "ага", "нет", "неа");
@Override
public MainUnit action(AnswerValidity unit, Message content) {
String message = content.getText();
Long personId = content.getPersonId();
if (WORDS_YES.contains(message.toLowerCase())) {
unit.getTempSave().getByKey(personId, "temp").ifPresent(content::setText);
return unit.getUnitYes();
} else if (WORDS_NO.contains(message.toLowerCase())) {
unit.getTempSave().getByKey(personId, "temp").ifPresent(content::setText);
return unit.getUnitNo();
} else {
Clarification clarification = unit.getClarificationQuestion().getClarification(content);
final String value = clarification.getValue();
if (value == null) {
return unit.getUnitNull();
} else {
unit.getTempSave().save(personId, "temp", value);
AnswerValidity newValidity = unit.toBuilder()
.clearKeyWords().keyWords(WORDS_YES_NO)
.build();
return AnswerText.builder()
.boxAnswer(clarification.getQuestion())
.nextUnit(newValidity)
.build();
}
}
}
}

View File

@ -0,0 +1,16 @@
package dev.struchkov.godfather.core.service.save;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
/**
* TODO: Добавить описание интерфейса.
*
* @author upagge [04/08/2019]
*/
@FunctionalInterface
public interface CheckSave<D extends Message> {
MainUnit check(D content);
}

View File

@ -0,0 +1,35 @@
package dev.struchkov.godfather.core.service.save;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class LocalPreservable<S> implements Preservable<S> {
private final Map<Long, Map<String, S>> saveMap = new HashMap<>();
@Override
public void save(Long personId, String key, S save) {
if (!saveMap.containsKey(personId)) {
saveMap.put(personId, new HashMap<>());
}
saveMap.get(personId).put(key, save);
}
@Override
public Optional<S> getByKey(Long personId, String key) {
if (saveMap.containsKey(personId)) {
if (saveMap.get(personId).containsKey(key)) {
return Optional.of(saveMap.get(personId).get(key));
}
}
return Optional.empty();
}
@Override
public Map<String, S> getAllSaveElement(Long personId) {
return null;
}
}

View File

@ -0,0 +1,37 @@
package dev.struchkov.godfather.core.service.save;
import dev.struchkov.godfather.core.service.save.push.Pusher;
import java.util.Map;
import java.util.Optional;
/**
* Интерфейс для сохранения и взаимодейтсвия с ответами прав пользователя.
*
* @author upagge [11/07/2019]
*/
public interface Preservable<S> {
/**
* Сохранение данных для пользователя
*
* @param personId Идентификатор пользователя
* @param save Объект данных
*/
void save(Long personId, String key, S save);
Optional<S> getByKey(Long personId, String key);
/**
* Финальное сохранение, можно реализовать как отправку данных куда-то
*
* @param personId Идентификатор пользователя
*/
default void push(Long personId, Pusher<S> pusher) {
Optional.ofNullable(pusher).ifPresent(sPusher -> sPusher.push(getAllSaveElement(personId)));
}
Map<String, S> getAllSaveElement(Long personId);
}

View File

@ -0,0 +1,10 @@
package dev.struchkov.godfather.core.service.save.data;
import dev.struchkov.godfather.context.domain.content.Message;
@FunctionalInterface
public interface PreservableData<E, C extends Message> {
E getData(C content);
}

View File

@ -0,0 +1,23 @@
package dev.struchkov.godfather.core.service.save.data;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.utils.Pair;
/**
* TODO: Добавить описание класса.
*
* @author upagge [13/07/2019]
*/
public class PreservableDataSimple implements PreservableData<Pair<String, String>, Message> {
private final String fieldName;
public PreservableDataSimple(String fieldName) {
this.fieldName = fieldName;
}
@Override
public Pair<String, String> getData(Message content) {
return new Pair<>(fieldName, content.getText());
}
}

View File

@ -0,0 +1,23 @@
package dev.struchkov.godfather.core.service.save.jpa;//package org.sadtech.social.bot.service.save.jpa;
//
//import lombok.RequiredArgsConstructor;
//import org.sadtech.social.bot.service.save.Preservable;
//import org.springframework.data.jpa.repository.JpaRepository;
//
///**
// * TODO: Добавить описание класса.
// *
// * @author upagge [01/08/2019]
// */
//@RequiredArgsConstructor
//public abstract class PreservableJpa<R extends JpaRepository<D, Long>, D extends SaveObjectJpa> implements Preservable<D> {
//
// protected final R jpaRepository;
//
// @Override
// public void save(Long personId, String key, R save) {
// save.setPersonId(personId);
// jpaRepository.save(save);
// }
//
//}

View File

@ -0,0 +1,23 @@
package dev.struchkov.godfather.core.service.save.jpa;
import dev.struchkov.godfather.context.domain.BasicEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
/**
* TODO: Добавить описание класса.
*
* @author upagge [01/08/2019]
*/
@EqualsAndHashCode(callSuper = true)
@MappedSuperclass
@Data
public abstract class SaveObjectJpa extends BasicEntity {
@Column(name = "personId")
private Long personId;
}

View File

@ -0,0 +1,125 @@
package dev.struchkov.godfather.core.service.save.push;
import dev.struchkov.godfather.context.exception.MailSendException;
import dev.struchkov.godfather.context.service.sender.email.EmailConfig;
import lombok.extern.slf4j.Slf4j;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Map;
/**
* Сохранение результатов анкеты на Email.
*
* @author upagge [11/07/2019]
*/
// todo [upagge] [11/07/2019]: Отрефакторить
@Slf4j
public class EmailPusher implements Pusher<String> {
private final EmailConfig emailConfig;
private final String nameForm;
public EmailPusher(EmailConfig emailConfig, String nameForm) {
this.emailConfig = emailConfig;
this.nameForm = nameForm;
}
@Override
public void push(Map<String, String> saveElement) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<table cellspacing=\"0\" cellpadding=\"0\" width=\"600\" bgcolor=\"#FFFFFF\">\n" +
" <tbody>\n" +
" <tr>\n" +
" <td>\n" +
" <table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n" +
" <tbody>\n" +
" <tr>\n" +
" <td width=\"149\" valign=\"top\" bgcolor=\"#476695\" style=\"border-radius: 5px 0px 0px 0px;\">&nbsp;</td>\n" +
" <td width=\"100%\" bgcolor=\"#476695\" valign=\"top\" style=\"border-radius: 0px 5px 0px 0px;\">&nbsp;</td>\n" +
" </tr>\n" +
" </tbody>\n" +
" </table>\n" +
" </td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td>\n" +
" <div style=\"padding:18px 18px 13px 18px;border-left:1px solid #dadee3;border-right:1px solid #dadee3;font-size:12px;color:black;\">\n" +
" <h1 style=\"margin:2px 0px 15px 0;padding:0px 0px 4px;border-bottom:1px solid #D8DFE6;color:#45668E;font-size:100%;\">")
.append(nameForm)
.append("</h1>\n" +
" <div style=\"line-height:160%;\">\n" +
" <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n" +
" <tbody>");
for (Map.Entry<String, String> element : saveElement.entrySet()) {
stringBuilder.append("<tr>\n" +
" <td valign=\"top\" style=\"padding-right:10px;color:#808080\">")
.append(element.getKey())
.append(":\n" +
" </td>\n" +
" <td style=\"padding-bottom:6px\">")
.append(element.getValue())
.append("</td></tr>");
}
stringBuilder.append("</tbody>\n" +
" </table>\n" +
" \n" +
" </div>\n" +
" </div>\n" +
" </td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td>\n" +
" <table cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n" +
" <tbody>\n" +
" <tr>\n" +
" <td width=\"3\">\n" +
" <div style=\"width:0;height:1px;max-height:1px;line-height:1px;font-size:0;border-left:1px solid #e6e7eb;border-right:1px solid #e8ebed;\"></div>\n" +
" <div style=\"width:0;height:1px;max-height:1px;line-height:1px;font-size:0;border-left:1px solid #f5f5f5;border-right:1px solid #e6e7eb;\"></div>\n" +
" </td>\n" +
" <td width=\"100%\" valign=\"bottom\">\n" +
" <div style=\"height:1px;max-height:1px;line-height:0;font-size:0;border-bottom:1px solid #dadee3;\">&nbsp;</div>\n" +
" </td>\n" +
" <td width=\"3\" align=\"right\">\n" +
" <div style=\"width:0;height:1px;max-height:1px;line-height:1px;font-size:0;border-left:1px solid #e8ebed;border-right:1px solid #e6e7eb;\"></div>\n" +
" <div style=\"width:0;height:1px;max-height:1px;line-height:1px;font-size:0;border-left:1px solid #e6e7eb;border-right:1px solid #f5f5f5;\"></div>\n" +
" </td>\n" +
" </tr>\n" +
" </tbody>\n" +
" </table>\n" +
" </td>\n" +
" </tr>\n" +
" <tr>\n" +
" <td bgcolor=\"#ffffff\" align=\"center\" style=\"padding:13px 0 0 0;font-size:12px;color:#888888;\"></td>\n" +
" </tr>\n" +
" </tbody>\n" +
" </table>");
Session session = Session.getDefaultInstance(emailConfig.getProps(), new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(emailConfig.getUsername(), emailConfig.getPassword());
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(emailConfig.getUsername()));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(emailConfig.getUsername()));
message.setSubject(nameForm);
message.setContent(stringBuilder.toString(), "text/html; charset=utf-8");
Transport.send(message);
} catch (MessagingException e) {
log.error(e.getMessage());
throw new MailSendException();
}
}
}

View File

@ -0,0 +1,15 @@
package dev.struchkov.godfather.core.service.save.push;
import java.util.Map;
/**
* TODO: Добавить описание класса.
*
* @author upagge [13/07/2019]
*/
@FunctionalInterface
public interface Pusher<D> {
void push(Map<String, D> saveElement);
}

View File

@ -0,0 +1,29 @@
package dev.struchkov.godfather.core.service.save.push;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.service.sender.Sending;
import java.util.Map;
public class UserSanderPusher implements Pusher<String> {
private final Long personId;
private final String nameForm;
private final Sending sending;
public UserSanderPusher(Long personId, String nameForm, Sending sending) {
this.personId = personId;
this.nameForm = nameForm;
this.sending = sending;
}
@Override
public void push(Map<String, String> saveElement) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("========= ").append(nameForm).append(" =========\n");
saveElement.forEach((key, value) -> stringBuilder.append(key).append(": ").append(value).append("\n"));
stringBuilder.append("====================");
sending.send(this.personId, BoxAnswer.builder().message(stringBuilder.toString()).build());
}
}

View File

@ -0,0 +1,84 @@
package dev.struchkov.godfather.core.service.timer;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.utils.MessageUtils;
import dev.struchkov.godfather.core.GeneralAutoResponder;
import dev.struchkov.godfather.core.domain.Timer;
import dev.struchkov.godfather.core.service.usercode.CheckData;
import lombok.extern.slf4j.Slf4j;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.TimerTask;
/**
* Обслуживание таймеров. Отвечает за активацию, удаление, перенастройку таймеров.
*
* @author upagge [11/07/2019]
*/
@Slf4j
public class TimerActionTask extends TimerTask {
private final TimerService timerService;
private final GeneralAutoResponder generalAutoresponder;
public TimerActionTask(TimerService timerService, GeneralAutoResponder generalAutoresponder) {
this.generalAutoresponder = generalAutoresponder;
log.info("Инициализация сервиса по активации таймеров");
this.timerService = timerService;
}
@Override
public void run() {
LocalDateTime nowDate = LocalDateTime.now(Clock.tickSeconds(ZoneId.systemDefault()));
log.info("Сервис таймеров сработал. Время: {}", nowDate);
timerService.getTimerActive()
.parallelStream()
.forEach(timer -> processingTimer(timer, nowDate));
}
private void processingTimer(Timer timer, LocalDateTime nowDate) {
Message emptyMessage = MessageUtils.EMPTY_MESSAGE;
emptyMessage.setPersonId(timer.getPersonId());
CheckData checkLoop = timer.getCheckLoop();
if (!timeDeath(nowDate, timer.getTimeDeath())) {
if (checkLoop != null) {
if (checkLoop.checked(emptyMessage)) {
generalAutoresponder.answer(emptyMessage, timer.getUnitAnswer());
timerService.remove(timer.getId());
} else {
reinstallation(timer);
}
} else {
generalAutoresponder.answer(emptyMessage, timer.getUnitAnswer());
reinstallation(timer);
}
} else {
generalAutoresponder.answer(emptyMessage, timer.getUnitAnswer());
death(timer, emptyMessage);
}
}
private void reinstallation(Timer timer) {
if (timer.getPeriodSec() != null) {
timer.setTimeActive(timer.getTimeActive().plusSeconds(timer.getPeriodSec()));
timerService.edit(timer.getId(), timer);
}
}
private void death(Timer timer, Message emptyMessage) {
if (timer.getUnitDeath() != null) {
generalAutoresponder.answer(emptyMessage, timer.getUnitDeath());
}
timerService.remove(timer.getId());
}
private boolean timeDeath(LocalDateTime nowTime, LocalDateTime timeDeath) {
return timeDeath != null && nowTime.isAfter(timeDeath);
}
}

View File

@ -0,0 +1,17 @@
package dev.struchkov.godfather.core.service.timer;
import dev.struchkov.godfather.core.domain.Timer;
import java.util.List;
public interface TimerService {
List<Timer> getTimerActive();
Integer add(Timer timer);
void remove(Integer id);
void edit(Integer id, Timer timer);
}

View File

@ -0,0 +1,42 @@
package dev.struchkov.godfather.core.service.timer;
import dev.struchkov.godfather.core.domain.Timer;
import dev.struchkov.godfather.core.repository.TimerRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@RequiredArgsConstructor
public class TimerServiceImpl implements TimerService {
private final TimerRepository timerRepository;
public TimerRepository getTimerRepository() {
return timerRepository;
}
@Override
public List<Timer> getTimerActive() {
return new ArrayList<>(timerRepository.getTimerActive(LocalDateTime.now()));
}
public Integer add(Timer timer) {
log.info("Таймер установлен: {}", timer);
return timerRepository.add(timer);
}
public void remove(Integer id) {
log.info("Таймер удален");
timerRepository.remove(id);
}
public void edit(Integer id, Timer timer) {
timer.setId(id);
timerRepository.edit(timer);
}
}

View File

@ -0,0 +1,10 @@
package dev.struchkov.godfather.core.service.usercode;
import dev.struchkov.godfather.context.domain.content.Message;
@FunctionalInterface
public interface CheckData<C extends Message> {
boolean checked(C content);
}

View File

@ -0,0 +1,11 @@
package dev.struchkov.godfather.core.service.usercode;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.Clarification;
@FunctionalInterface
public interface ClarificationQuestion<C extends Message> {
Clarification getClarification(C message);
}

View File

@ -0,0 +1,10 @@
package dev.struchkov.godfather.core.service.usercode;
import java.util.List;
@FunctionalInterface
public interface Insert {
List<String> insert(Long personId);
}

View File

@ -0,0 +1,11 @@
package dev.struchkov.godfather.core.service.usercode;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.content.Message;
@FunctionalInterface
public interface ProcessingData<C extends Message> {
BoxAnswer processing(C content);
}

View File

@ -0,0 +1,17 @@
package dev.struchkov.godfather.core.utils;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@EqualsAndHashCode
@AllArgsConstructor
public class Pair<K, D> {
private K key;
private D value;
}

View File

@ -0,0 +1,95 @@
package dev.struchkov.godfather.core.utils;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.utils.KeyBoards;
import dev.struchkov.godfather.core.domain.question.Question;
import dev.struchkov.godfather.core.domain.question.QuestionAnswer;
import dev.struchkov.godfather.core.domain.question.QuestionResult;
import dev.struchkov.godfather.core.domain.unit.AnswerSave;
import dev.struchkov.godfather.core.domain.unit.AnswerText;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.core.domain.unit.UnitActiveType;
import dev.struchkov.godfather.core.service.save.Preservable;
import dev.struchkov.godfather.core.service.save.push.Pusher;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* Утилита для быстрой генерации цепочки Unit-ов, образующих сценарий "Тестирование".
*
* @author upagge [14/07/2019]
*/
public class QuestionUtils {
private final Preservable<QuestionResult> preservable;
private final List<Question> questions;
private Pusher<QuestionResult> pusher;
private QuestionUtils(List<Question> questions, Preservable<QuestionResult> preservable) {
this.questions = questions;
this.preservable = preservable;
}
private QuestionUtils(List<Question> questions, Preservable<QuestionResult> preservable, Pusher<QuestionResult> pusher) {
this.questions = questions;
this.preservable = preservable;
this.pusher = pusher;
}
public static QuestionUtils builder(Preservable<QuestionResult> preservable, List<Question> questions) {
return new QuestionUtils(questions, preservable);
}
public static QuestionUtils builder(Preservable<QuestionResult> preservable, Pusher<QuestionResult> pusher, List<Question> list) {
return new QuestionUtils(list, preservable, pusher);
}
public MainUnit build(MainUnit finishUnit) {
return generateTest(finishUnit);
}
public MainUnit build() {
return generateTest(null);
}
private MainUnit generateTest(MainUnit finishUnit) {
AnswerText previousUnit = null;
for (int i = questions.size() - 1; i >= 0; i--) {
Question question = this.questions.get(i);
List<String> collectAnswer = question.getQuestionAnswers().stream()
.map(QuestionAnswer::getText)
.collect(Collectors.toList());
BoxAnswer boxAnswer = question.getBoxAnswer().toBuilder()
.keyBoard(KeyBoards.verticalDuoMenuString(collectAnswer)).build();
AnswerText.AnswerTextBuilder answerTextBuilder = AnswerText.builder()
.boxAnswer(boxAnswer);
for (QuestionAnswer questionAnswer : question.getQuestionAnswers()) {
AnswerSave.AnswerSaveBuilder answerSaveBuilder = AnswerSave.<QuestionResult>builder()
.preservable(preservable)
.preservableData(
message -> new QuestionResult(
question.getBoxAnswer().getMessage(),
questionAnswer.getText(),
questionAnswer.getPoints()
)
)
.phrase(questionAnswer.getText());
if (i != this.questions.size() - 1) {
answerSaveBuilder.nextUnit(previousUnit).build();
} else {
answerSaveBuilder.pusher(pusher);
Optional.of(finishUnit).ifPresent(answerSaveBuilder::nextUnit);
}
answerTextBuilder.nextUnit(answerSaveBuilder.build());
}
if (i == 0) answerTextBuilder.activeType(UnitActiveType.AFTER);
previousUnit = answerTextBuilder.build();
}
return previousUnit;
}
}

Some files were not shown because too many files have changed in this diff Show More