Множественные изменения и улучшения:

* Удалил все типы вложений, теперь типы вложений реализуются в библиотеках для каждого конкретного мессенджера.
* Теперь сохраняется история перемещения пользователя по сценарию. Сохраняется сообщение и название юнита. Это позволяет откатывать пользователя назад.
* Реализовал два новых юнита. RollBackCmd позволяет откатить пользователя назад в сценарии на произвольное количество юнитов. TeleportCmd позволяет перенести пользователя в произвольное место сценария.
* Удалил AnswerProcessing, вместо него можно использовать AnswerText.
This commit is contained in:
Struchkov Mark 2022-07-10 00:25:53 +03:00
parent 78b2dda570
commit 996194264e
54 changed files with 890 additions and 564 deletions

View File

@ -6,7 +6,7 @@
<parent>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>godfather-bot</artifactId>
<version>0.0.8</version>
<version>0.0.9</version>
</parent>
<artifactId>bot-context</artifactId>
@ -15,6 +15,10 @@
<description>Доменные сущности, интерфейсы, для библиотеки Godfather</description>
<dependencies>
<dependency>
<groupId>dev.struchkov</groupId>
<artifactId>autoresponder</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov.haiti</groupId>
<artifactId>haiti-utils</artifactId>

View File

@ -1,6 +1,4 @@
package dev.struchkov.godfather.core.domain;
import dev.struchkov.godfather.context.domain.BoxAnswer;
package dev.struchkov.godfather.context.domain;
public class Clarification {

View File

@ -0,0 +1,35 @@
package dev.struchkov.godfather.context.domain;
import dev.struchkov.godfather.context.domain.content.Message;
public class StorylineHistory extends BasicEntity {
private Long personId;
private String unitName;
private Message message;
public Long getPersonId() {
return personId;
}
public void setPersonId(Long personId) {
this.personId = personId;
}
public String getUnitName() {
return unitName;
}
public void setUnitName(String unitName) {
this.unitName = unitName;
}
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
}

View File

@ -1,4 +1,6 @@
package dev.struchkov.godfather.core.utils;
package dev.struchkov.godfather.context.domain;
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
/**
* Тип Unit-а. Обределяет способ обработки.
@ -9,14 +11,15 @@ public class TypeUnit {
public static final String TEXT = "TEXT";
public static final String SAVE = "SAVE";
public static final String PROCESSING = "PROCESSING";
public static final String TIMER = "TIMER";
public static final String CHECK = "CHECK";
public static final String VALIDITY = "VALIDITY";
public static final String ACCOUNT = "ACCOUNT";
public static final String BACK_CMD = "BACK_CMD";
public static final String TELEPORT_CMD = "TELEPORT_CMD";
private TypeUnit() {
throw new IllegalStateException("Утилитарный класс");
utilityClass();
}

View File

@ -0,0 +1,34 @@
package dev.struchkov.godfather.context.domain;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
/**
* Сущность инкапсулирует в себе данные, необходимые для обработки сценария.
*
* @param <U> Тип юнита
* @param <M> Тип сообщения
*/
public class UnitRequest<U extends MainUnit, M extends Message> {
private final U unit;
private final M message;
private UnitRequest(U unit, M message) {
this.unit = unit;
this.message = message;
}
public static <U extends MainUnit, M extends Message> UnitRequest<U, M> of(U mainUnit, M message) {
return new UnitRequest<>(mainUnit, message);
}
public U getUnit() {
return unit;
}
public M getMessage() {
return message;
}
}

View File

@ -7,6 +7,8 @@ import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
@ -33,9 +35,9 @@ public class Mail extends Message {
/**
* Вложения к сообщению.
*/
@OneToMany(fetch = FetchType.EAGER)
@Column(name = "attachment")
private List<Attachment> attachments;
@OneToMany(fetch = FetchType.LAZY)
private List<Attachment> attachments = new ArrayList<>();
/**
* Пересланные сообщения.
@ -68,8 +70,12 @@ public class Mail extends Message {
return attachments;
}
public void setAttachments(List<Attachment> attachments) {
this.attachments = attachments;
public void addAttachment(Attachment attachment) {
this.attachments.add(attachment);
}
public void addAttachments(Collection<Attachment> attachments) {
this.attachments.addAll(attachments);
}
public List<Mail> getForwardMail() {

View File

@ -2,10 +2,7 @@ package dev.struchkov.godfather.context.domain.content.attachment;
import dev.struchkov.godfather.context.domain.BasicEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
/**
* Абстрактная сущность, для всех вложений к сообщениям от пользователей.
@ -15,15 +12,6 @@ import javax.persistence.Enumerated;
@Entity
public abstract class Attachment extends BasicEntity {
/**
* Тип сущности.
*/
@Column(name = "type")
@Enumerated(value = EnumType.STRING)
protected AttachmentType type;
public AttachmentType getType() {
return type;
}
public abstract String getType();
}

View File

@ -1,14 +0,0 @@
package dev.struchkov.godfather.context.domain.content.attachment;
/**
* Тип вложения {@link Attachment} к сообщению.
*
* @author upagge [08/07/2019]
*/
public enum AttachmentType {
AUDIO_MESSAGE,
GEO,
LINK
}

View File

@ -1,25 +0,0 @@
package dev.struchkov.godfather.context.domain.content.attachment;
import java.net.URL;
/**
* Вложение типа "Аудиосообщение".
*
* @author upagge [08/07/2019]
*/
public class AudioMessage extends Attachment {
/**
* Ссылка на аудиозапись в формате odd.
*/
private URL linkOdd;
public AudioMessage() {
type = AttachmentType.AUDIO_MESSAGE;
}
public AudioMessage(URL linkOdd) {
this.linkOdd = linkOdd;
}
}

View File

@ -1,69 +0,0 @@
package dev.struchkov.godfather.context.domain.content.attachment;
/**
* Вложение типа "Карта".
*
* @author upagge [08/07/2019]
*/
public class Geo extends Attachment {
/**
* Географические координаты.
*/
private GeoCoordinate geoCoordinate;
/**
* Название страны.
*/
private String country;
/**
* Название города.
*/
private String city;
private Geo() {
type = AttachmentType.GEO;
}
public static Builder builder() {
return new Geo().new Builder();
}
public GeoCoordinate getGeoCoordinate() {
return geoCoordinate;
}
public String getCountry() {
return country;
}
public String getCity() {
return city;
}
public class Builder {
private Builder() {
}
public Builder coordinate(Float lat, Float aLong) {
Geo.this.geoCoordinate = new GeoCoordinate(lat, aLong);
return this;
}
public Builder country(String countryName) {
Geo.this.country = countryName;
return this;
}
public Builder city(String cityName) {
Geo.this.city = cityName;
return this;
}
public Geo build() {
return Geo.this;
}
}
}

View File

@ -1,41 +0,0 @@
package dev.struchkov.godfather.context.domain.content.attachment;
/**
* Сущность для хранения географических координат.
*
* @author upagge [08/07/2019]
*/
public class GeoCoordinate {
/**
* Широта.
*/
private Float latitude;
/**
* Долгота.
*/
private Float longitude;
public GeoCoordinate(Float latitude, Float longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public Float getLatitude() {
return latitude;
}
public void setLatitude(Float latitude) {
this.latitude = latitude;
}
public Float getLongitude() {
return longitude;
}
public void setLongitude(Float longitude) {
this.longitude = longitude;
}
}

View File

@ -1,19 +0,0 @@
package dev.struchkov.godfather.context.domain.content.attachment;
public class Link extends Attachment {
private String url;
public Link() {
this.type = AttachmentType.LINK;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}

View File

@ -1,13 +1,15 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.service.Accessibility;
import dev.struchkov.godfather.context.service.usercode.CheckData;
import dev.struchkov.godfather.core.service.Accessibility;
import dev.struchkov.godfather.core.utils.TypeUnit;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static dev.struchkov.godfather.context.exception.UnitConfigException.unitConfigException;
import static dev.struchkov.haiti.utils.Inspector.isAnyNotNull;
@ -71,7 +73,7 @@ public class AnswerCheck extends MainUnit {
public static final class Builder {
private String name;
private Set<String> keyWords = new HashSet<>();
private Set<KeyWord> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
@ -90,13 +92,23 @@ public class AnswerCheck extends MainUnit {
return this;
}
public Builder keyWords(Set<String> val) {
keyWords = val;
public Builder keyWords(Set<KeyWord> val) {
keyWords.addAll(val);
return this;
}
public Builder keyWord(KeyWord val) {
keyWords.add(val);
return this;
}
public Builder stringKeyWords(Set<String> val) {
keyWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
return this;
}
public Builder keyWord(String val) {
keyWords.add(val);
keyWords.add(KeyWord.of(val));
return this;
}

View File

@ -1,17 +1,19 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.service.Accessibility;
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 dev.struchkov.godfather.context.service.Accessibility;
import dev.struchkov.godfather.context.service.save.CheckSave;
import dev.struchkov.godfather.context.service.save.Preservable;
import dev.struchkov.godfather.context.service.save.PreservableData;
import dev.struchkov.godfather.context.service.save.Pusher;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
@ -107,7 +109,7 @@ public class AnswerSave<D> extends MainUnit {
public static final class Builder<D> {
private String name;
private Set<String> keyWords = new HashSet<>();
private Set<KeyWord> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
@ -129,13 +131,23 @@ public class AnswerSave<D> extends MainUnit {
return this;
}
public Builder<D> keyWords(Set<String> val) {
keyWords = val;
public Builder<D> keyWords(Set<KeyWord> val) {
keyWords.addAll(val);
return this;
}
public Builder<D> keyWord(KeyWord val) {
keyWords.add(val);
return this;
}
public Builder<D> stringKeyWords(Set<String> val) {
keyWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
return this;
}
public Builder<D> keyWord(String val) {
keyWords.add(val);
keyWords.add(KeyWord.of(val));
return this;
}

View File

@ -1,19 +1,21 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.exception.UnitConfigException;
import dev.struchkov.godfather.context.service.Accessibility;
import dev.struchkov.godfather.context.service.sender.Sending;
import dev.struchkov.godfather.context.service.usercode.Insert;
import dev.struchkov.godfather.context.service.usercode.MessageFunction;
import dev.struchkov.godfather.context.service.usercode.ProcessingData;
import dev.struchkov.godfather.core.service.Accessibility;
import dev.struchkov.godfather.core.utils.TypeUnit;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
@ -82,7 +84,7 @@ public class AnswerText<M extends Message> extends MainUnit {
private ProcessingData<M> boxAnswer;
private Insert insert;
private Sending sending;
private Set<String> keyWords = new HashSet<>();
private Set<KeyWord> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
@ -135,8 +137,23 @@ public class AnswerText<M extends Message> extends MainUnit {
return this;
}
public Builder<M> keyWords(Set<String> val) {
keyWords = val;
public Builder<M> keyWords(Set<KeyWord> val) {
keyWords.addAll(val);
return this;
}
public Builder<M> keyWord(KeyWord val) {
keyWords.add(val);
return this;
}
public Builder<M> stringKeyWords(Set<String> val) {
keyWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
return this;
}
public Builder<M> keyWord(String val) {
keyWords.add(KeyWord.of(val));
return this;
}

View File

@ -1,12 +1,16 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoard;
import dev.struchkov.godfather.context.service.Accessibility;
import dev.struchkov.godfather.context.service.usercode.CheckData;
import dev.struchkov.godfather.core.service.Accessibility;
import dev.struchkov.godfather.core.utils.TypeUnit;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static dev.struchkov.godfather.context.exception.UnitConfigException.unitConfigException;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
@ -83,7 +87,7 @@ public class AnswerTimer<M extends Message> extends MainUnit {
private Integer timeDelaySec;
private Integer timeDeathSec;
private CheckData<M> checkLoop;
private Set<String> keyWords;
private Set<KeyWord> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
@ -119,8 +123,23 @@ public class AnswerTimer<M extends Message> extends MainUnit {
return this;
}
public Builder<M> keyWords(Set<String> val) {
keyWords = val;
public Builder<M> keyWords(Set<KeyWord> val) {
keyWords.addAll(val);
return this;
}
public Builder<M> keyWord(KeyWord val) {
keyWords.add(val);
return this;
}
public Builder<M> stringKeyWords(Set<String> val) {
keyWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
return this;
}
public Builder<M> keyWord(String val) {
keyWords.add(KeyWord.of(val));
return this;
}

View File

@ -1,14 +1,16 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
import dev.struchkov.godfather.core.service.Accessibility;
import dev.struchkov.godfather.core.service.ClarificationQuestion;
import dev.struchkov.godfather.core.service.save.LocalPreservable;
import dev.struchkov.godfather.core.service.save.Preservable;
import dev.struchkov.godfather.core.utils.TypeUnit;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.service.Accessibility;
import dev.struchkov.godfather.context.service.ClarificationQuestion;
import dev.struchkov.godfather.context.service.save.LocalPreservable;
import dev.struchkov.godfather.context.service.save.Preservable;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Обработка данных со страницы пользователя.
@ -85,7 +87,7 @@ public class AnswerValidity extends MainUnit {
private MainUnit unitNo;
private MainUnit unitNull;
private ClarificationQuestion clarificationQuestion;
private Set<String> keyWords;
private Set<KeyWord> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
@ -121,13 +123,23 @@ public class AnswerValidity extends MainUnit {
return this;
}
public Builder keyWords(Set<String> val) {
keyWords = val;
public Builder keyWords(Set<KeyWord> val) {
keyWords.addAll(val);
return this;
}
public Builder keyWord(KeyWord val) {
keyWords.add(val);
return this;
}
public Builder stringKeyWords(Set<String> val) {
keyWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
return this;
}
public Builder keyWord(String val) {
keyWords.add(val);
keyWords.add(KeyWord.of(val));
return this;
}
@ -162,7 +174,7 @@ public class AnswerValidity extends MainUnit {
}
public Builder clearKeyWords() {
nextUnits.clear();
keyWords.clear();
return this;
}

View File

@ -1,7 +1,9 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.UnitDefinition;
import dev.struchkov.godfather.core.service.Accessibility;
import dev.struchkov.godfather.context.domain.keyboard.KeyBoard;
import dev.struchkov.godfather.context.service.Accessibility;
import java.util.Set;
import java.util.regex.Pattern;
@ -12,7 +14,7 @@ public class LazyUnit extends MainUnit {
private LazyUnit(
String name,
Set<String> keyWords,
Set<KeyWord> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,

View File

@ -1,7 +1,8 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.autoresponder.entity.Unit;
import dev.struchkov.godfather.core.service.Accessibility;
import dev.struchkov.godfather.context.service.Accessibility;
import java.util.Objects;
import java.util.Optional;
@ -43,7 +44,7 @@ public abstract class MainUnit extends Unit<MainUnit> {
protected MainUnit(
String name,
Set<String> keyWords,
Set<KeyWord> keyWords,
String phrase,
Pattern pattern,
Integer matchThreshold,

View File

@ -1,4 +1,4 @@
package dev.struchkov.godfather.core.domain.unit;
package dev.struchkov.godfather.context.domain.unit;
/**
* Тип активации Unit-а. Определяет порядок обработки Unit.

View File

@ -0,0 +1,133 @@
package dev.struchkov.godfather.context.domain.unit.cmd;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.UnitActiveType;
import dev.struchkov.godfather.context.exception.UnitConfigException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Юнит, который позволяет откатить пользователя на предыдущие юниты в сценарии с сохранением ранее введенной информации в сообщениях.
*/
public class RollBackCmd extends MainUnit {
/**
* Количество юнитов, на которые можно откатиться назад.
*/
private final int countBack;
private RollBackCmd(Builder builder) {
super(
builder.name,
builder.keyWords,
builder.phrase,
builder.pattern,
builder.matchThreshold,
builder.priority,
new HashSet<>(),
builder.activeType,
null,
TypeUnit.BACK_CMD
);
this.countBack = builder.countBack;
}
public int getCountBack() {
return countBack;
}
public static RollBackCmd.Builder builder() {
return new RollBackCmd.Builder();
}
public static RollBackCmd rollBack(int countToBack) {
return RollBackCmd.builder().countBack(countToBack).build();
}
public static RollBackCmd singleRollBack() {
return RollBackCmd.builder().countBack(1).build();
}
public static final class Builder {
private String name;
private Set<KeyWord> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
private Integer priority;
private UnitActiveType activeType = UnitActiveType.DEFAULT;
private int countBack;
private Builder() {
}
public RollBackCmd.Builder name(String name) {
this.name = name;
return this;
}
public RollBackCmd.Builder keyWords(Set<KeyWord> val) {
keyWords.addAll(val);
return this;
}
public RollBackCmd.Builder keyWord(KeyWord val) {
keyWords.add(val);
return this;
}
public RollBackCmd.Builder stringKeyWords(Set<String> val) {
keyWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
return this;
}
public RollBackCmd.Builder keyWord(String val) {
keyWords.add(KeyWord.of(val));
return this;
}
public RollBackCmd.Builder phrase(String val) {
phrase = val;
return this;
}
public RollBackCmd.Builder pattern(Pattern val) {
pattern = val;
return this;
}
public RollBackCmd.Builder matchThreshold(Integer val) {
matchThreshold = val;
return this;
}
public RollBackCmd.Builder priority(Integer val) {
priority = val;
return this;
}
public RollBackCmd.Builder activeType(UnitActiveType val) {
activeType = val;
return this;
}
public RollBackCmd.Builder countBack(int val) {
countBack = val + 1;
return this;
}
public RollBackCmd build() {
if (countBack < 2) {
throw new UnitConfigException("Ошибка конфигурирования юнита {0}: Количество юнитов для отката не должно быть меньше 1.", name);
}
return new RollBackCmd(this);
}
}
}

View File

@ -0,0 +1,121 @@
package dev.struchkov.godfather.context.domain.unit.cmd;
import dev.struchkov.autoresponder.entity.KeyWord;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.UnitActiveType;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* Позволяет перенести пользователя в произвольное место в сценарии.
*/
public class TeleportCmd extends MainUnit {
/**
* Название юнита, в которое необходимо осуществить перенос.
*/
private String unitNameToTeleport;
private TeleportCmd(Builder builder) {
super(
builder.name,
builder.keyWords,
builder.phrase,
builder.pattern,
builder.matchThreshold,
builder.priority,
new HashSet<>(),
builder.activeType,
null,
TypeUnit.TELEPORT_CMD
);
this.unitNameToTeleport = builder.unitNameToTeleport;
}
public String getUnitNameToTeleport() {
return unitNameToTeleport;
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private String name;
private Set<KeyWord> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
private Integer priority;
private UnitActiveType activeType = UnitActiveType.DEFAULT;
private String unitNameToTeleport;
private Builder() {
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder keyWords(Set<KeyWord> val) {
keyWords.addAll(val);
return this;
}
public Builder keyWord(KeyWord val) {
keyWords.add(val);
return this;
}
public Builder stringKeyWords(Set<String> val) {
keyWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
return this;
}
public Builder keyWord(String val) {
keyWords.add(KeyWord.of(val));
return this;
}
public Builder phrase(String val) {
phrase = val;
return this;
}
public Builder pattern(Pattern val) {
pattern = val;
return this;
}
public Builder matchThreshold(Integer val) {
matchThreshold = val;
return this;
}
public Builder priority(Integer val) {
priority = val;
return this;
}
public Builder activeType(UnitActiveType val) {
activeType = val;
return this;
}
public Builder unitNameToTeleport(String val) {
unitNameToTeleport = val;
return this;
}
public TeleportCmd build() {
return new TeleportCmd(this);
}
}
}

View File

@ -0,0 +1,16 @@
package dev.struchkov.godfather.context.repository;
import dev.struchkov.godfather.context.domain.StorylineHistory;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public interface StorylineRepository {
void save(@NotNull StorylineHistory storylineHistory);
Optional<StorylineHistory> findByCountLast(long personId, int countUnitsToBack);
void cleanHistoryByPersonId(@NotNull Long personId);
}

View File

@ -0,0 +1,47 @@
package dev.struchkov.godfather.context.repository.impl.local;
import dev.struchkov.godfather.context.domain.StorylineHistory;
import dev.struchkov.godfather.context.repository.StorylineRepository;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Stack;
public class StorylineMapRepository implements StorylineRepository {
private final Map<Long, Stack<StorylineHistory>> map = new HashMap<>();
@Override
public void save(@NotNull StorylineHistory history) {
final Long personId = history.getPersonId();
map.computeIfAbsent(personId, k -> new Stack<>()).push(history);
}
@Override
public Optional<StorylineHistory> findByCountLast(long personId, int countUnitsToBack) {
if (map.containsKey(personId)) {
final Stack<StorylineHistory> stack = map.get(personId);
if (stack.size() < countUnitsToBack) {
countUnitsToBack = stack.size();
}
StorylineHistory storylineHistory = null;
for (int i = 0; i < countUnitsToBack; i++) {
storylineHistory = stack.pop();
}
return Optional.ofNullable(storylineHistory);
}
return Optional.empty();
}
@Override
public void cleanHistoryByPersonId(@NotNull Long personId) {
if (map.containsKey(personId)) {
map.get(personId).clear();
} else {
map.put(personId, new Stack<>());
}
}
}

View File

@ -10,7 +10,7 @@ import java.util.Optional;
public class UnitPointLocalRepository implements UnitPointerRepository {
public static final Map<Long, String> map = new HashMap<>();
public final Map<Long, String> map = new HashMap<>();
@Override
public UnitPointer save(@NotNull UnitPointer unitPointer) {

View File

@ -1,4 +1,4 @@
package dev.struchkov.godfather.core.service;
package dev.struchkov.godfather.context.service;
import dev.struchkov.godfather.context.domain.content.Message;

View File

@ -1,7 +1,7 @@
package dev.struchkov.godfather.core.service;
package dev.struchkov.godfather.context.service;
import dev.struchkov.godfather.context.domain.Clarification;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.Clarification;
@FunctionalInterface
public interface ClarificationQuestion<C extends Message> {

View File

@ -0,0 +1,35 @@
package dev.struchkov.godfather.context.service;
import dev.struchkov.godfather.context.domain.StorylineHistory;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.Set;
public interface StorylineService<T extends Message> {
void save(@NotNull StorylineHistory storylineHistory);
Optional<MainUnit> getUnitNameByPersonId(@NotNull Long personId);
Set<MainUnit> getNextUnitByPersonId(@NotNull Long personId);
void save(Long personId, String name, T message);
Optional<StorylineHistory> replaceUserToBack(long personId, int countUnitsToBack);
Optional<MainUnit> getDefaultUnit();
/**
* Ленивая (поздняя) связка юнитов между собой. Осуществляется уже после создания сценария. С помощью данного подхода можно реализовать циклические зависимости юнитов. Либо можно использовать {@link dev.struchkov.godfather.context.domain.unit.cmd.TeleportCmd}
*
* @param firstName
* @param secondName
*/
void lazyLink(String firstName, String secondName);
Optional<MainUnit> getUnitByName(String unitName);
}

View File

@ -1,7 +1,7 @@
package dev.struchkov.godfather.core.service.save;
package dev.struchkov.godfather.context.service.save;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
/**
* TODO: Добавить описание интерфейса.

View File

@ -1,4 +1,6 @@
package dev.struchkov.godfather.core.service.save;
package dev.struchkov.godfather.context.service.save;
import dev.struchkov.godfather.context.service.save.Preservable;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,6 +1,6 @@
package dev.struchkov.godfather.core.service.save;
package dev.struchkov.godfather.context.service.save;
import dev.struchkov.godfather.core.service.save.push.Pusher;
import dev.struchkov.godfather.context.service.save.Pusher;
import java.util.Map;
import java.util.Optional;

View File

@ -1,4 +1,4 @@
package dev.struchkov.godfather.core.service.save.data;
package dev.struchkov.godfather.context.service.save;
import dev.struchkov.godfather.context.domain.content.Message;

View File

@ -1,4 +1,4 @@
package dev.struchkov.godfather.core.service.save.push;
package dev.struchkov.godfather.context.service.save;
import java.util.Map;

View File

@ -6,7 +6,7 @@
<parent>
<groupId>dev.struchkov.godfather</groupId>
<artifactId>godfather-bot</artifactId>
<version>0.0.8</version>
<version>0.0.9</version>
</parent>
<artifactId>bot-core</artifactId>
@ -19,11 +19,6 @@
<groupId>dev.struchkov.godfather</groupId>
<artifactId>bot-context</artifactId>
</dependency>
<dependency>
<groupId>dev.struchkov</groupId>
<artifactId>autoresponder</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,27 +1,25 @@
package dev.struchkov.godfather.core;
import dev.struchkov.autoresponder.Responder;
import dev.struchkov.autoresponder.entity.Unit;
import dev.struchkov.godfather.context.domain.UnitPointer;
import dev.struchkov.godfather.context.domain.TypeUnit;
import dev.struchkov.godfather.context.domain.UnitRequest;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.UnitActiveType;
import dev.struchkov.godfather.context.exception.ConfigAppException;
import dev.struchkov.godfather.context.service.Accessibility;
import dev.struchkov.godfather.context.service.Modifiable;
import dev.struchkov.godfather.context.service.PersonSettingService;
import dev.struchkov.godfather.context.service.UnitPointerService;
import dev.struchkov.godfather.context.service.StorylineService;
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.Accessibility;
import dev.struchkov.godfather.core.service.ErrorHandler;
import dev.struchkov.godfather.core.service.action.ActionUnit;
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 dev.struchkov.haiti.context.exception.NotFoundException;
import java.util.HashMap;
@ -33,10 +31,10 @@ import java.util.stream.Collectors;
public class GeneralAutoResponder<T extends Message> {
private ErrorHandler errorHandler;
private final PersonSettingService personSettingService;
private final UnitPointerService unitPointerService;
private final StoryLine storyLine;
private ErrorHandler errorHandler;
private final StorylineService<T> storyLineService;
protected Map<String, ActionUnit<? extends MainUnit, ? extends Message>> actionUnitMap = new HashMap<>();
protected List<Modifiable<T>> modifiable;
@ -44,18 +42,15 @@ public class GeneralAutoResponder<T extends Message> {
protected GeneralAutoResponder(
Sending sending,
PersonSettingService personSettingService,
UnitPointerService unitPointerService,
List<Object> unitConfigurations
StorylineService<T> storyLineService
) {
this.personSettingService = personSettingService;
this.unitPointerService = unitPointerService;
this.storyLine = new StorylineMaker(unitConfigurations).createStoryLine();
this.storyLineService = storyLineService;
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());
}
@ -64,7 +59,7 @@ public class GeneralAutoResponder<T extends Message> {
this.modifiable = modifiable;
}
public void initActionUnit(String typeUnit, ActionUnit<? super MainUnit, T> actionUnit) {
public void initActionUnit(String typeUnit, ActionUnit<? extends MainUnit, T> actionUnit) {
if (!actionUnitMap.containsKey(typeUnit)) {
actionUnitMap.put(typeUnit, actionUnit);
} else {
@ -113,16 +108,12 @@ public class GeneralAutoResponder<T extends Message> {
if (modifiable != null) {
modifiable.forEach(m -> m.change(message));
}
final Set<MainUnit> units = unitPointerService.getUnitNameByPersonId(message.getPersonId())
.flatMap(storyLine::getUnit)
.map(Unit::getNextUnits)
.filter(mainUnits -> !mainUnits.isEmpty())
.orElse(storyLine.getStartingUnits());
final Set<MainUnit> units = storyLineService.getNextUnitByPersonId(message.getPersonId());
final Optional<MainUnit> optAnswer = Responder.nextUnit(message.getText(), units);
if (optAnswer.isPresent()) {
final MainUnit answer = optAnswer.get();
if (checkPermission(answer.getAccessibility(), message)) {
answer(message, answer);
answer(UnitRequest.of(answer, message));
}
}
}
@ -131,50 +122,51 @@ public class GeneralAutoResponder<T extends Message> {
return accessibility.isEmpty() || accessibility.get().check(message);
}
public void answer(T message, MainUnit unitAnswer) {
public void answer(UnitRequest<MainUnit, T> unitRequest) {
try {
unitAnswer = getAction(message, unitAnswer);
unitAnswer = activeUnitAfter(unitAnswer, message);
unitRequest = getAction(unitRequest);
unitRequest = activeUnitAfter(unitRequest);
final Optional<MainUnit> optDefaultUnit = storyLine.getDefaultUnit();
if (optDefaultUnit.isEmpty() || !optDefaultUnit.get().equals(unitAnswer)) {
unitPointerService.save(new UnitPointer(message.getPersonId(), unitAnswer.getName()));
final Optional<MainUnit> optDefaultUnit = storyLineService.getDefaultUnit();
final MainUnit unit = unitRequest.getUnit();
final T message = unitRequest.getMessage();
if (optDefaultUnit.isEmpty() || !optDefaultUnit.get().equals(unit)) {
storyLineService.save(message.getPersonId(), unit.getName(), message);
}
} catch (Exception e) {
if (errorHandler != null) {
errorHandler.handle(message, e);
errorHandler.handle(unitRequest.getMessage(), e);
} else {
throw e;
}
}
}
private MainUnit activeUnitAfter(MainUnit mainUnit, T content) {
if (mainUnit.getNextUnits() != null) {
Optional<MainUnit> first = mainUnit.getNextUnits().stream()
private UnitRequest<MainUnit, T> activeUnitAfter(UnitRequest<MainUnit, T> unitRequest) {
final Set<MainUnit> nextUnits = unitRequest.getUnit().getNextUnits();
if (nextUnits != null) {
Optional<MainUnit> first = nextUnits.stream()
.filter(unit -> UnitActiveType.AFTER.equals(unit.getActiveType()))
.findFirst();
if (first.isPresent()) {
getAction(content, first.get());
return activeUnitAfter(first.get(), content);
getAction(UnitRequest.of(first.get(), unitRequest.getMessage()));
return activeUnitAfter(UnitRequest.of(first.get(), unitRequest.getMessage()));
}
}
return mainUnit;
return unitRequest;
}
private MainUnit getAction(T event, MainUnit unitAnswer) {
if (actionUnitMap.containsKey(unitAnswer.getType())) {
ActionUnit actionUnit = actionUnitMap.get(unitAnswer.getType());
MainUnit mainUnit = actionUnit.action(unitAnswer, event);
return !unitAnswer.equals(mainUnit) ? getAction(event, mainUnit) : mainUnit;
private UnitRequest<MainUnit, T> getAction(UnitRequest<MainUnit, T> unitRequest) {
final MainUnit unit = unitRequest.getUnit();
final String typeUnit = unit.getType();
if (actionUnitMap.containsKey(typeUnit)) {
ActionUnit actionUnit = actionUnitMap.get(typeUnit);
UnitRequest<MainUnit, T> newUnitRequest = actionUnit.action(unitRequest);
final MainUnit newUnit = newUnitRequest.getUnit();
return !unit.equals(newUnit) ? getAction(newUnitRequest) : unitRequest;
} else {
throw new NotFoundException("ActionUnit для типа {0} не зарегистрирован", unitAnswer.getType());
throw new NotFoundException("ActionUnit для типа {0} не зарегистрирован", unit.getType());
}
}
//TODO [22.06.2022]: Временное решение для ленивой инициализации
public void link(String firstName, String secondName) {
storyLine.link(firstName, secondName);
}
}

View File

@ -1,6 +1,6 @@
package dev.struchkov.godfather.core;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.haiti.utils.Inspector;
import org.jetbrains.annotations.NotNull;
@ -10,13 +10,13 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class StoryLine {
public class Storyline {
private MainUnit defaultUnit;
private final Set<MainUnit> startingUnits = new HashSet<>();
private final Map<String, MainUnit> units = new HashMap<>();
public StoryLine(Set<MainUnit> startingUnits, Map<String, MainUnit> units) {
public Storyline(Set<MainUnit> startingUnits, Map<String, MainUnit> units) {
this.startingUnits.addAll(startingUnits);
this.units.putAll(units);
}

View File

@ -3,8 +3,8 @@ package dev.struchkov.godfather.core;
import dev.struchkov.godfather.context.domain.UnitDefinition;
import dev.struchkov.godfather.context.domain.annotation.Unit;
import dev.struchkov.godfather.context.exception.UnitConfigException;
import dev.struchkov.godfather.core.domain.unit.LazyUnit;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.LazyUnit;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.haiti.utils.Inspector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -46,13 +46,13 @@ public class StorylineMaker {
return unitMap;
}
public StoryLine createStoryLine() {
public Storyline createStoryLine() {
generateUnitDefinitions();
try {
createUnitMap();
createLazy();
final Set<MainUnit> mainUnit = getMainUnit();
return new StoryLine(mainUnit, unitMap);
return new Storyline(mainUnit, unitMap);
} catch (IllegalAccessException | InvocationTargetException e) {
log.error(e.getMessage(), e);
}

View File

@ -1,7 +1,7 @@
package dev.struchkov.godfather.core.domain;
import dev.struchkov.godfather.context.service.usercode.CheckData;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import java.time.LocalDateTime;

View File

@ -1,146 +0,0 @@
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.service.usercode.ProcessingData;
import dev.struchkov.godfather.core.service.Accessibility;
import dev.struchkov.godfather.core.utils.TypeUnit;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Обработчик для кастомных реализаций.
*
* @author upagge [08/07/2019]
*/
public class AnswerProcessing<M extends Message> extends MainUnit {
/**
* Кастомная обработка.
*/
private final ProcessingData<M> processingData;
/**
* Объект для сквозной отправки ответа.
*/
private final Sending sending;
private AnswerProcessing(Builder<M> builder) {
super(
builder.name,
builder.keyWords,
builder.phrase,
builder.pattern,
builder.matchThreshold,
builder.priority,
builder.nextUnits,
builder.activeType,
builder.accessibility,
TypeUnit.PROCESSING
);
processingData = builder.processingData;
sending = builder.sending;
}
public static <M extends Message> Builder<M> builder() {
return new Builder<>();
}
public ProcessingData<M> getProcessingData() {
return processingData;
}
public Sending getSending() {
return sending;
}
public static final class Builder<M extends Message> {
private String name;
private Set<String> keyWords = new HashSet<>();
private String phrase;
private Pattern pattern;
private Integer matchThreshold;
private Integer priority;
private Set<MainUnit> nextUnits = new HashSet<>();
private ProcessingData<M> processingData;
private Sending sending;
private UnitActiveType activeType;
private Accessibility accessibility;
private Builder() {
}
public Builder<M> name(String name) {
this.name = name;
return this;
}
public Builder<M> processingData(ProcessingData<M> val) {
processingData = val;
return this;
}
public Builder<M> sending(Sending val) {
sending = val;
return this;
}
public Builder<M> keyWords(Set<String> val) {
keyWords = val;
return this;
}
public Builder<M> keyWord(String val) {
keyWords.add(val);
return this;
}
public Builder<M> phrase(String val) {
phrase = val;
return this;
}
public Builder<M> pattern(Pattern val) {
pattern = val;
return this;
}
public Builder<M> matchThreshold(Integer val) {
matchThreshold = val;
return this;
}
public Builder<M> priority(Integer val) {
priority = val;
return this;
}
public Builder<M> nextUnits(Set<MainUnit> val) {
nextUnits = val;
return this;
}
public Builder<M> nextUnit(MainUnit val) {
nextUnits.add(val);
return this;
}
public Builder accessibility(Accessibility val) {
accessibility = val;
return this;
}
public Builder<M> activeType(UnitActiveType val) {
activeType = val;
return this;
}
public AnswerProcessing<M> build() {
return new AnswerProcessing<>(this);
}
}
}

View File

@ -0,0 +1,100 @@
package dev.struchkov.godfather.core.service;
import dev.struchkov.autoresponder.entity.Unit;
import dev.struchkov.godfather.context.domain.StorylineHistory;
import dev.struchkov.godfather.context.domain.UnitPointer;
import dev.struchkov.godfather.context.domain.content.Mail;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.context.repository.StorylineRepository;
import dev.struchkov.godfather.context.service.StorylineService;
import dev.struchkov.godfather.context.service.UnitPointerService;
import dev.struchkov.godfather.core.Storyline;
import dev.struchkov.godfather.core.StorylineMaker;
import dev.struchkov.haiti.utils.Inspector;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
/**
* Отвечает за работу со сценарием в личных сообщениях с пользователем.
*/
public class StorylineMailService implements StorylineService<Mail> {
private final UnitPointerService unitPointerService;
private final StorylineRepository storylineRepository;
private final Storyline storyLine;
public StorylineMailService(
UnitPointerService unitPointerService,
StorylineRepository storylineRepository,
List<Object> unitConfigurations
) {
this.storyLine = new StorylineMaker(unitConfigurations).createStoryLine();
this.unitPointerService = unitPointerService;
this.storylineRepository = storylineRepository;
}
@Override
public void save(@NotNull StorylineHistory storylineHistory) {
isNotNull(storylineHistory);
storylineHistory.setId(null);
storylineRepository.save(storylineHistory);
}
@Override
public Optional<MainUnit> getUnitNameByPersonId(@NotNull Long personId) {
Inspector.isNotNull(personId);
return unitPointerService.getUnitNameByPersonId(personId)
.flatMap(storyLine::getUnit);
}
@Override
public Set<MainUnit> getNextUnitByPersonId(@NotNull Long personId) {
final Optional<Set<MainUnit>> optMainUnits = getUnitNameByPersonId(personId)
.map(Unit::getNextUnits)
.filter(mainUnits -> !mainUnits.isEmpty());
if (optMainUnits.isEmpty()) {
storylineRepository.cleanHistoryByPersonId(personId);
}
return optMainUnits
.orElse(storyLine.getStartingUnits());
}
@Override
public void save(Long personId, String unitName, Mail mail) {
Inspector.isNotNull(personId, unitName, mail);
unitPointerService.save(new UnitPointer(personId, unitName));
final StorylineHistory storylineHistory = new StorylineHistory();
storylineHistory.setPersonId(personId);
storylineHistory.setUnitName(unitName);
storylineHistory.setMessage(mail);
storylineRepository.save(storylineHistory);
}
@Override
public Optional<StorylineHistory> replaceUserToBack(long personId, int countUnitsToBack) {
return storylineRepository.findByCountLast(personId, countUnitsToBack);
}
@Override
public Optional<MainUnit> getDefaultUnit() {
return storyLine.getDefaultUnit();
}
//TODO [22.06.2022]: Временное решение для ленивой инициализации
@Override
public void lazyLink(String firstName, String secondName) {
storyLine.link(firstName, secondName);
}
@Override
public Optional<MainUnit> getUnitByName(String unitName) {
return storyLine.getUnit(unitName);
}
}

View File

@ -1,7 +1,8 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.UnitRequest;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.core.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
/**
* Интерфейс для обработки Unit-ов.
@ -14,10 +15,8 @@ public interface ActionUnit<M extends MainUnit, C extends Message> {
/**
* Метод обработки Unit-а.
*
* @param unit Unit, который необходимо обработать
* @param content Запрос пользователя
* @return Новый Unit, который может нуждаться в обработке
*/
MainUnit action(M unit, C content);
UnitRequest<MainUnit, C> action(UnitRequest<M, C> unitRequest);
}

View File

@ -1,11 +1,13 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.UnitRequest;
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 dev.struchkov.godfather.context.domain.unit.AnswerCheck;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.Optional;
/**
@ -18,16 +20,18 @@ public class AnswerCheckAction implements ActionUnit<AnswerCheck, Message> {
private static final Logger log = LoggerFactory.getLogger(AnswerCheckAction.class);
@Override
public MainUnit action(AnswerCheck answerCheck, Message mail) {
public UnitRequest<MainUnit, Message> action(UnitRequest<AnswerCheck, Message> unitRequest) {
final AnswerCheck unit = unitRequest.getUnit();
final Message message = unitRequest.getMessage();
MainUnit unitAnswer;
if (answerCheck.getCheck().checked(mail)) {
if (unit.getCheck().checked(message)) {
log.info("Проверка пройдена");
unitAnswer = answerCheck.getUnitTrue();
unitAnswer = unit.getUnitTrue();
} else {
log.info("Проверка не пройдена");
unitAnswer = answerCheck.getUnitFalse();
unitAnswer = unit.getUnitFalse();
}
return Optional.ofNullable(unitAnswer).orElse(answerCheck);
return UnitRequest.of(Objects.requireNonNullElse(unitAnswer, unit), message);
}
}

View File

@ -1,36 +0,0 @@
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) {
final 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

@ -1,11 +1,12 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.UnitRequest;
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;
import dev.struchkov.godfather.context.domain.unit.AnswerSave;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.context.service.save.CheckSave;
import dev.struchkov.godfather.context.service.save.Preservable;
import dev.struchkov.godfather.context.service.save.PreservableData;
/**
* Обработчик Unit-а {@link AnswerSave}.
@ -15,27 +16,30 @@ import dev.struchkov.godfather.core.service.save.data.PreservableData;
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();
public UnitRequest<MainUnit, Message> action(UnitRequest<AnswerSave<D>, Message> unitRequest) {
final AnswerSave<D> answerSave = unitRequest.getUnit();
final Message message = unitRequest.getMessage();
CheckSave<? super Message> checkSave = answerSave.getCheckSave();
final Preservable<D> preservable = answerSave.getPreservable();
final Long personId = message.getPersonId();
final CheckSave<? super Message> checkSave = answerSave.getCheckSave();
if (checkSave != null) {
MainUnit unit = checkSave.check(mail);
MainUnit unit = checkSave.check(message);
if (unit != null) {
return unit;
return UnitRequest.of(unit, message);
}
}
PreservableData<D, ? super Message> preservableData = answerSave.getPreservableData();
if (preservableData != null) {
D data = preservableData.getData(mail);
D data = preservableData.getData(message);
if (data != null) {
preservable.save(personId, answerSave.getKey(), data);
}
}
preservable.push(personId, answerSave.getPusher());
return answerSave;
return UnitRequest.of(answerSave, message);
}
}

View File

@ -1,12 +1,13 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.domain.UnitRequest;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.domain.unit.AnswerText;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
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 java.util.List;
@ -24,18 +25,21 @@ public class AnswerTextAction implements ActionUnit<AnswerText<Message>, Message
}
@Override
public MainUnit action(AnswerText<Message> answerText, Message message) {
final BoxAnswer boxAnswer = answerText.getBoxAnswer().processing(message);
replaceMarkers(answerText, message, boxAnswer);
public UnitRequest<MainUnit, Message> action(UnitRequest<AnswerText<Message>, Message> unitRequest) {
final AnswerText<Message> unit = unitRequest.getUnit();
final Message message = unitRequest.getMessage();
final Sending answerTextSending = answerText.getSending();
final BoxAnswer boxAnswer = unit.getBoxAnswer().processing(message);
replaceMarkers(unit, message, boxAnswer);
final Sending answerTextSending = unit.getSending();
if (answerTextSending != null) {
Sender.sends(message, boxAnswer, answerTextSending);
} else {
Sender.sends(message, boxAnswer, this.sending);
}
return answerText;
return UnitRequest.of(unit, message);
}
private void replaceMarkers(AnswerText<Message> answerText, Message message, BoxAnswer boxAnswer) {
@ -46,5 +50,4 @@ public class AnswerTextAction implements ActionUnit<AnswerText<Message>, Message
}
}
}

View File

@ -1,11 +1,12 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.UnitRequest;
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.context.domain.unit.AnswerTimer;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.core.service.timer.TimerActionTask;
import dev.struchkov.godfather.core.service.timer.TimerService;
@ -40,29 +41,32 @@ public class AnswerTimerAction implements ActionUnit<AnswerTimer, Message> {
}
@Override
public MainUnit action(AnswerTimer answerTimer, Message message) {
LocalDateTime timeActive = LocalDateTime
public UnitRequest<MainUnit, Message> action(UnitRequest<AnswerTimer, Message> unitRequest) {
final AnswerTimer unit = unitRequest.getUnit();
final Message message = unitRequest.getMessage();
final LocalDateTime timeActive = LocalDateTime
.now(Clock.tickSeconds(ZoneId.systemDefault()))
.plusSeconds(Optional
.ofNullable(answerTimer.getTimeDelaySec())
.ofNullable(unit.getTimeDelaySec())
.orElseThrow(() -> new TimerSettingException("Не установлена временная задержка таймера")));
Timer.Builder timer = Timer.builder()
final Timer.Builder timer = Timer.builder()
.personId(message.getPersonId())
.unitAnswer(answerTimer.getUnitAnswer())
.unitAnswer(unit.getUnitAnswer())
.timeActive(timeActive)
.periodSec(answerTimer.getTimeDelaySec())
.checkLoop(answerTimer.getCheckLoop());
.periodSec(unit.getTimeDelaySec())
.checkLoop(unit.getCheckLoop());
if (answerTimer.getTimeDeathSec() != null) {
if (unit.getTimeDeathSec() != null) {
timer.timeDeath(LocalDateTime
.now(Clock.tickSeconds(ZoneId.systemDefault()))
.plusSeconds(answerTimer.getTimeDeathSec()));
} else if (answerTimer.getCheckLoop() == null) {
.plusSeconds(unit.getTimeDeathSec()));
} else if (unit.getCheckLoop() == null) {
timer.timeDeath(timeActive);
}
timerService.add(timer.build());
return answerTimer;
return UnitRequest.of(unit, message);
}
}

View File

@ -1,10 +1,11 @@
package dev.struchkov.godfather.core.service.action;
import dev.struchkov.godfather.context.domain.Clarification;
import dev.struchkov.godfather.context.domain.UnitRequest;
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 dev.struchkov.godfather.context.domain.unit.AnswerText;
import dev.struchkov.godfather.context.domain.unit.AnswerValidity;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import java.util.Set;
@ -20,31 +21,37 @@ public class AnswerValidityAction implements ActionUnit<AnswerValidity, Message>
public static final Set<String> WORDS_YES_NO = Set.of("да", "ага", "нет", "неа");
@Override
public MainUnit action(AnswerValidity unit, Message content) {
public UnitRequest<MainUnit, Message> action(UnitRequest<AnswerValidity, Message> unitRequest) {
final AnswerValidity unit = unitRequest.getUnit();
final Message content = unitRequest.getMessage();
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();
return UnitRequest.of(unit.getUnitYes(), content);
} else if (WORDS_NO.contains(message.toLowerCase())) {
unit.getTempSave().getByKey(personId, "temp").ifPresent(content::setText);
return unit.getUnitNo();
return UnitRequest.of(unit.getUnitNo(), content);
} else {
Clarification clarification = unit.getClarificationQuestion().getClarification(content);
final String value = clarification.getValue();
if (value == null) {
return unit.getUnitNull();
return UnitRequest.of(unit.getUnitNull(), content);
} else {
unit.getTempSave().save(personId, "temp", value);
AnswerValidity newValidity = unit.builder()
.clearKeyWords().keyWords(WORDS_YES_NO)
.build();
return AnswerText.builder()
.message(mes -> clarification.getQuestion())
.nextUnit(newValidity)
.clearKeyWords()
.stringKeyWords(WORDS_YES_NO)
.build();
return UnitRequest.of(
AnswerText.builder()
.message(mes -> clarification.getQuestion())
.nextUnit(newValidity)
.build(),
content
);
}
}
}
}

View File

@ -0,0 +1,38 @@
package dev.struchkov.godfather.core.service.action.cmd;
import dev.struchkov.godfather.context.domain.StorylineHistory;
import dev.struchkov.godfather.context.domain.UnitRequest;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.domain.unit.cmd.RollBackCmd;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.context.service.StorylineService;
import dev.struchkov.godfather.core.service.action.ActionUnit;
import java.util.Optional;
public class BackCmdAction<T extends Message> implements ActionUnit<RollBackCmd, T> {
private final StorylineService<T> storyLineService;
public BackCmdAction(StorylineService<T> storyLineService) {
this.storyLineService = storyLineService;
}
@Override
public UnitRequest<MainUnit, T> action(UnitRequest<RollBackCmd, T> unitRequest) {
final RollBackCmd unit = unitRequest.getUnit();
final T message = unitRequest.getMessage();
final int countToBack = unit.getCountBack();
final Optional<StorylineHistory> optHistory = storyLineService.replaceUserToBack(message.getPersonId(), countToBack);
if (optHistory.isPresent()) {
final StorylineHistory history = optHistory.get();
final String unitName = history.getUnitName();
final MainUnit nextUnit = storyLineService.getUnitByName(unitName).orElse(unit);
final T oldMessage = (T) history.getMessage();
return UnitRequest.of(nextUnit, oldMessage);
}
return UnitRequest.of(unit, message);
}
}

View File

@ -0,0 +1,30 @@
package dev.struchkov.godfather.core.service.action.cmd;
import dev.struchkov.godfather.context.domain.UnitRequest;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.domain.unit.MainUnit;
import dev.struchkov.godfather.context.domain.unit.cmd.TeleportCmd;
import dev.struchkov.godfather.context.service.StorylineService;
import dev.struchkov.godfather.core.service.action.ActionUnit;
import java.util.Optional;
public class TeleportCmdAction<T extends Message> implements ActionUnit<TeleportCmd, T> {
private final StorylineService<T> storyLineService;
public TeleportCmdAction(StorylineService<T> storyLineService) {
this.storyLineService = storyLineService;
}
@Override
public UnitRequest<MainUnit, T> action(UnitRequest<TeleportCmd, T> unitRequest) {
final TeleportCmd unit = unitRequest.getUnit();
final T message = unitRequest.getMessage();
final Optional<MainUnit> optNextUnit = storyLineService.getUnitByName(unit.getUnitNameToTeleport());
return optNextUnit
.map(mainUnit -> UnitRequest.of(mainUnit, message))
.orElseGet(() -> UnitRequest.of(unit, message));
}
}

View File

@ -1,6 +1,7 @@
package dev.struchkov.godfather.core.service.save.data;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.service.save.PreservableData;
import dev.struchkov.haiti.utils.Pair;
/**

View File

@ -1,6 +1,7 @@
package dev.struchkov.godfather.core.service.save.push;
import dev.struchkov.godfather.context.domain.BoxAnswer;
import dev.struchkov.godfather.context.service.save.Pusher;
import dev.struchkov.godfather.context.service.sender.Sending;
import java.util.Map;

View File

@ -1,5 +1,6 @@
package dev.struchkov.godfather.core.service.timer;
import dev.struchkov.godfather.context.domain.UnitRequest;
import dev.struchkov.godfather.context.domain.content.Message;
import dev.struchkov.godfather.context.service.usercode.CheckData;
import dev.struchkov.godfather.context.utils.MessageUtils;
@ -50,17 +51,17 @@ public class TimerActionTask extends TimerTask {
if (!timeDeath(nowDate, timer.getTimeDeath())) {
if (checkLoop != null) {
if (checkLoop.checked(emptyMessage)) {
generalAutoresponder.answer(emptyMessage, timer.getUnitAnswer());
generalAutoresponder.answer(UnitRequest.of(timer.getUnitAnswer(), emptyMessage));
timerService.remove(timer.getId());
} else {
reinstallation(timer);
}
} else {
generalAutoresponder.answer(emptyMessage, timer.getUnitAnswer());
generalAutoresponder.answer(UnitRequest.of(timer.getUnitAnswer(), emptyMessage));
reinstallation(timer);
}
} else {
generalAutoresponder.answer(emptyMessage, timer.getUnitAnswer());
generalAutoresponder.answer(UnitRequest.of(timer.getUnitAnswer(), emptyMessage));
death(timer, emptyMessage);
}
}
@ -74,7 +75,7 @@ public class TimerActionTask extends TimerTask {
private void death(Timer timer, Message emptyMessage) {
if (timer.getUnitDeath() != null) {
generalAutoresponder.answer(emptyMessage, timer.getUnitDeath());
generalAutoresponder.answer(UnitRequest.of(timer.getUnitDeath(), emptyMessage));
}
timerService.remove(timer.getId());
}

View File

@ -9,8 +9,8 @@
//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 dev.struchkov.godfather.context.service.save.Preservable;
//import dev.struchkov.godfather.context.service.save.Pusher;
//
//import java.util.List;
//import java.util.Optional;

View File

@ -6,7 +6,7 @@
<groupId>dev.struchkov.godfather</groupId>
<artifactId>godfather-bot</artifactId>
<version>0.0.8</version>
<version>0.0.9</version>
<packaging>pom</packaging>
<modules>
@ -32,12 +32,12 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<godfather.ver>0.0.8</godfather.ver>
<godfather.ver>0.0.9</godfather.ver>
<godfather.context.ver>${godfather.ver}</godfather.context.ver>
<godfather.core.ver>${godfather.ver}</godfather.core.ver>
<autoresponder.ver>3.0.0</autoresponder.ver>
<autoresponder.ver>3.1.0</autoresponder.ver>
<haiti.utils>1.0.2</haiti.utils>
<javax.persistence.api.ver>2.2</javax.persistence.api.ver>