Compare commits
166 Commits
7e4264a9e6
...
f21964eee2
Author | SHA1 | Date | |
---|---|---|---|
f21964eee2 | |||
02fd8a016d | |||
fb1822a0ac | |||
2311cd33ab | |||
d41bfae7ff | |||
408bc6022b | |||
c5950f7d81 | |||
3359314848 | |||
22a5d50ea8 | |||
f9ae7b187d | |||
8e1090c608 | |||
3637599e0c | |||
7df4c093ba | |||
3845d3e0db | |||
e1ddbf8a8f | |||
b03ffed637 | |||
a2bcb31085 | |||
b0b454ff00 | |||
52d70a1dd4 | |||
933f1182df | |||
445c67a9de | |||
f09dd42574 | |||
fc2d478d1d | |||
aa8aef7d04 | |||
820c27fa4c | |||
568f6afbf9 | |||
d1e8ca88e8 | |||
f22b8e6941 | |||
284b9a2bc7 | |||
80aa674ed3 | |||
9ccc7688d5 | |||
29bd34ebda | |||
e08fd0e135 | |||
402f8cbd7e | |||
5c9f1fb72a | |||
04b9fc7473 | |||
e26ae25712 | |||
0b7e235774 | |||
99e1875d26 | |||
7a8044f4ca | |||
028938f00b | |||
8a0153d5b0 | |||
8fdfad675e | |||
19ac9030d4 | |||
09475f57e4 | |||
19f678442d | |||
88f38b0fac | |||
647033859c | |||
7d9b9d7bfd | |||
b16ef5ce73 | |||
7f65ec0ed3 | |||
a8a7a6130f | |||
adb7191cfe | |||
fab62dfa55 | |||
e97e33282d | |||
1785a5d819 | |||
26d3416f4f | |||
126160e331 | |||
10a07b322a | |||
a92893e63f | |||
be2332d370 | |||
e652b12f90 | |||
c795ff30cc | |||
ff56a9441d | |||
d43e2150d8 | |||
cc79b67b9b | |||
6648bc1dc6 | |||
bee956c7d7 | |||
1c792e488f | |||
1c1ab65a80 | |||
5300bc5ecb | |||
bef853a3ab | |||
ee7e178f03 | |||
90f4659beb | |||
d608b6ffd3 | |||
ee3e25993a | |||
2464251311 | |||
9bc76f0d94 | |||
b8edee1cc6 | |||
bf9404fb35 | |||
c6338635cf | |||
e081e9af4c | |||
34b3515c37 | |||
f4399bc0af | |||
bf0e5a3c11 | |||
d780aba701 | |||
cc6b588ab8 | |||
3c87887b59 | |||
65e1ef0bf3 | |||
a4b8dbf77d | |||
7c3c100447 | |||
b269d2295b | |||
93b4944929 | |||
ca25e8dfe8 | |||
4b7ce5f649 | |||
32af3a68be | |||
b25a8dc132 | |||
7a968205ea | |||
3c987a9c72 | |||
18407b6366 | |||
4c26875261 | |||
b2a32d99bd | |||
7b5811e0cf | |||
a8d9a03bc2 | |||
37302905d0 | |||
f4b4d81b10 | |||
a44a2f3535 | |||
b2f0f0f33a | |||
da4b053d35 | |||
d1168e0833 | |||
d54ef69aff | |||
2ddbd505a5 | |||
19fbd941a4 | |||
a4767439aa | |||
460772367e | |||
a509e4bc0f | |||
c00c8f90a0 | |||
41570759f6 | |||
5d3206fdb4 | |||
0318a08b78 | |||
b0c1123225 | |||
d951c45049 | |||
3d59cb8989 | |||
7710e2b274 | |||
104d59dde6 | |||
bdb7be787c | |||
ebca79abb9 | |||
3b19ec130a | |||
4a58750325 | |||
061536b663 | |||
3b588ad0ca | |||
cad7dc9cef | |||
61e98c75b2 | |||
154d1e792b | |||
e59777f65d | |||
49484342b6 | |||
7cb3a0a059 | |||
bc66a0164d | |||
eb403f96d6 | |||
04c0a58f22 | |||
333edfb8e5 | |||
edbd20163f | |||
f71ed56e1b | |||
b3f63e6b3c | |||
6f64494504 | |||
ad69ea3702 | |||
cb3557fe9b | |||
e7bf89c24d | |||
b2046cc977 | |||
eaaca3be6c | |||
eb2e7ba012 | |||
7c3711ab90 | |||
1a2d2d4602 | |||
dd6b166506 | |||
d2cf3ed645 | |||
d4f6a672ef | |||
0bbdcaae07 | |||
eaeb220515 | |||
87c565f4d2 | |||
9192b7cd97 | |||
fc3f9563e2 | |||
6d9454fd03 | |||
2a9413ab46 | |||
29145fe093 | |||
996194264e | |||
78b2dda570 |
69
.drone.yml
Normal file
69
.drone.yml
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: snapshot-publish
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- develop
|
||||
|
||||
volumes:
|
||||
- name: m2
|
||||
host:
|
||||
path: /drone/volume/m2
|
||||
|
||||
steps:
|
||||
|
||||
- name: publish
|
||||
image: maven:3.8.5-openjdk-17
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: m2
|
||||
path: /root/.m2/repository
|
||||
environment:
|
||||
MAVEN_SETTINGS:
|
||||
from_secret: MAVEN_SETTINGS
|
||||
commands:
|
||||
- echo "$MAVEN_SETTINGS" >> maven-settings.xml
|
||||
- mvn --settings maven-settings.xml -U -P snapshot clean deploy
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: release-publish
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- refs/tags/v.*.*.*
|
||||
|
||||
volumes:
|
||||
- name: m2
|
||||
host:
|
||||
path: /drone/volume/m2
|
||||
|
||||
steps:
|
||||
|
||||
- name: publish maven central
|
||||
image: maven:3.8.5-openjdk-17
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: m2
|
||||
path: /root/.m2/repository
|
||||
environment:
|
||||
GPG_PRIVATE_KEY:
|
||||
from_secret: GPG_PRIVATE_KEY
|
||||
MAVEN_SETTINGS:
|
||||
from_secret: MAVEN_SETTINGS
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: GPG_PASSPHRASE
|
||||
commands:
|
||||
- echo "$GPG_PRIVATE_KEY" >> gpg.key
|
||||
- echo "$MAVEN_SETTINGS" >> maven-settings.xml
|
||||
- gpg --pinentry-mode loopback --passphrase $GPG_PASSPHRASE --import gpg.key
|
||||
- mvn --settings maven-settings.xml -U -P ossrh,release clean deploy
|
||||
|
||||
---
|
||||
kind: signature
|
||||
hmac: d30cbf3dfe171a8912b3171a0b7e5345f0cd80b65c1386d3207bffc06b56c3db
|
||||
|
||||
...
|
50
.drone.yml.back
Normal file
50
.drone.yml.back
Normal file
@ -0,0 +1,50 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: haiti-framework
|
||||
|
||||
steps:
|
||||
|
||||
- name: publish maven central
|
||||
image: maven:3.8.5-openjdk-17
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: m2
|
||||
path: /root/.m2/repository
|
||||
environment:
|
||||
GPG_PRIVATE_KEY:
|
||||
from_secret: GPG_PRIVATE_KEY
|
||||
MAVEN_SETTINGS:
|
||||
from_secret: MAVEN_SETTINGS
|
||||
GPG_PASSPHRASE:
|
||||
from_secret: GPG_PASSPHRASE
|
||||
SSH_KEY:
|
||||
from_secret: SSH_KEY
|
||||
commands:
|
||||
- eval $(ssh-agent -s)
|
||||
- mkdir -p ~/.ssh
|
||||
- chmod 700 ~/.ssh
|
||||
- echo "$SSH_KEY" | ssh-add -
|
||||
- ssh-keyscan -p 222 git.struchkov.dev >> ~/.ssh/known_hosts
|
||||
- git branch -a
|
||||
# - echo "test" >> test.txt
|
||||
# - git add --all
|
||||
# - git commit -m test
|
||||
# - git remote add deploy ssh://git@git.struchkov.dev:222/Godfather-Bots/godfather.git
|
||||
# - git remote -v
|
||||
# - git push deploy HEAD:master
|
||||
|
||||
# - ssh-keyscan -t rsa git.struchkov.dev >> ~/.ssh/known_hosts
|
||||
# - chmod 644 ~/.ssh/known_hosts
|
||||
# - echo "$GPG_PRIVATE_KEY" >> gpg.key
|
||||
# - echo "$MAVEN_SETTINGS" >> maven-settings.xml
|
||||
# - gpg --pinentry-mode loopback --passphrase $GPG_PASSPHRASE --import gpg.key
|
||||
# - mvn --settings maven-settings.xml -T 1C -U release:clean release:prepare release:perform --batch-mode
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
|
||||
volumes:
|
||||
- name: m2
|
||||
host:
|
||||
path: /drone/volume/m2
|
@ -1,17 +0,0 @@
|
||||
image: maven:3.8.5-openjdk-17
|
||||
variables:
|
||||
MAVEN_OPTS: "-Dmaven.repo.local=./.m2/repository"
|
||||
|
||||
stages:
|
||||
- deploy
|
||||
|
||||
deploy:
|
||||
stage: deploy
|
||||
only:
|
||||
- /^v.*$/
|
||||
except:
|
||||
- branches
|
||||
before_script:
|
||||
- gpg --pinentry-mode loopback --passphrase $GPG_PASSPHRASE --import $GPG_PRIVATE_KEY
|
||||
script:
|
||||
- 'mvn --settings $MAVEN_SETTINGS -U -P ossrh,release clean deploy'
|
35
bot-context/bot-context-main/pom.xml
Normal file
35
bot-context/bot-context-main/pom.xml
Normal file
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-context</artifactId>
|
||||
<version>0.0.42-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bot-context-main</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-domain-main</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.haiti</groupId>
|
||||
<artifactId>haiti-utils</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,8 +1,8 @@
|
||||
package dev.struchkov.godfather.context.utils;
|
||||
package dev.struchkov.godfather.main.context.utils;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.keyboard.button.SimpleButton;
|
||||
import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoard;
|
||||
import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoardLine;
|
||||
import dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton;
|
||||
import dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoard;
|
||||
import dev.struchkov.godfather.main.domain.keyboard.simple.SimpleKeyBoardLine;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
30
bot-context/bot-context-quarkus/pom.xml
Normal file
30
bot-context/bot-context-quarkus/pom.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?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>bot-context</artifactId>
|
||||
<version>0.0.42-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bot-context-quarkus</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-domain-main</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.smallrye.reactive</groupId>
|
||||
<artifactId>smallrye-mutiny-vertx-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,10 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface Accessibility {
|
||||
|
||||
Uni<Void> check(Message message);
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
/**
|
||||
* Используется для перехвата исключений, которые возникают при обработке юнитов.
|
||||
*/
|
||||
public interface ErrorHandler {
|
||||
|
||||
/**
|
||||
* Метод, который должен как-то обработать исключение.
|
||||
*
|
||||
* @param message Сообщение, после которого возникло исключение.
|
||||
* @param e Объект исключения.
|
||||
*/
|
||||
Uni<Void> handle(Message message, Throwable e);
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.event.Event;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public interface EventHandler<T extends Event> {
|
||||
|
||||
Uni<Void> handle(T event);
|
||||
|
||||
String getEventType();
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Интерфес для изменения запроса пользователя перед тем, как он попадет в подсистему обработки.
|
||||
* Например можно исправить опечатки, перевести сообщение на другой язык и так далее.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Modifiable<T extends Message> {
|
||||
|
||||
Uni<Void> change(@NotNull T content);
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface PersonSettingService {
|
||||
|
||||
Uni<Set<String>> getAllPersonIdDisableMessages(@NotNull Set<String> personIds);
|
||||
|
||||
Uni<Boolean> getStateProcessingByPersonId(@NotNull String personId);
|
||||
|
||||
Uni<Void> disableMessageProcessing(@NotNull String personId);
|
||||
|
||||
Uni<Void> enableMessageProcessing(@NotNull String personId);
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PreSendProcessing {
|
||||
|
||||
Uni<BoxAnswer> pretreatment(BoxAnswer boxAnswer);
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание класса.
|
||||
*
|
||||
* @author upagge [13/07/2019]
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Pusher<D> {
|
||||
|
||||
Uni<Void> push(String personId, Map<String, D> saveElement);
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.SendType;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Интерфейс для отправки ответов пользователю.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public interface Sending {
|
||||
|
||||
/**
|
||||
* Отправляет сообщение пользователю
|
||||
*
|
||||
* @param boxAnswer Объект с данными, которые необходимо отправить
|
||||
*/
|
||||
Uni<Void> send(@NotNull BoxAnswer boxAnswer);
|
||||
|
||||
void addPreSendProcess(@NotNull PreSendProcessing processing);
|
||||
|
||||
/**
|
||||
* Возвращает тип объекта отправляющего ответ пользователя. В зависимости от типа ответ будет отправлен с помощью
|
||||
* разных методов.
|
||||
*/
|
||||
SendType getType();
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package dev.struchkov.godfather.quarkus.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.UnitPointer;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Сервис для взаимодействия с сущностью {@link UnitPointer}.
|
||||
*
|
||||
* @author upagge [07/07/2019]
|
||||
*/
|
||||
public interface UnitPointerService {
|
||||
|
||||
Uni<UnitPointer> save(@NotNull UnitPointer unitPointer);
|
||||
|
||||
Uni<String> getUnitNameByPersonId(@NotNull String personId);
|
||||
|
||||
Uni<Void> removeByPersonId(@NotNull String personId);
|
||||
|
||||
}
|
25
bot-context/bot-context-simple/pom.xml
Normal file
25
bot-context/bot-context-simple/pom.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-context</artifactId>
|
||||
<version>0.0.42-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bot-context-simple</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-domain-main</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
|
||||
public interface Accessibility {
|
||||
|
||||
boolean check(Message message);
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
|
||||
/**
|
||||
* Используется для перехвата исключений, которые возникают при обработке юнитов.
|
||||
*/
|
||||
public interface ErrorHandler {
|
||||
|
||||
/**
|
||||
* Метод, который должен как-то обработать исключение.
|
||||
*
|
||||
* @param message Сообщение, после которого возникло исключение.
|
||||
* @param e Объект исключения.
|
||||
*/
|
||||
void handle(Message message, Exception e);
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.event.Event;
|
||||
|
||||
public interface EventHandler<T extends Event> {
|
||||
|
||||
void handle(T event);
|
||||
|
||||
String getEventType();
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package dev.struchkov.godfather.context.service;
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
@ -0,0 +1,18 @@
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public interface PersonSettingService {
|
||||
|
||||
Set<String> getAllPersonIdDisableMessages(@NotNull Set<String> personIds);
|
||||
|
||||
Optional<Boolean> getStateProcessingByPersonId(@NotNull String personId);
|
||||
|
||||
void disableMessageProcessing(@NotNull String personId);
|
||||
|
||||
void enableMessageProcessing(@NotNull String personId);
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PreSendProcessing {
|
||||
|
||||
BoxAnswer pretreatment(BoxAnswer boxAnswer);
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package dev.struchkov.godfather.core.service.save.push;
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ -10,6 +10,6 @@ import java.util.Map;
|
||||
@FunctionalInterface
|
||||
public interface Pusher<D> {
|
||||
|
||||
void push(Map<String, D> saveElement);
|
||||
void push(String personId, Map<String, D> saveElement);
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package dev.struchkov.godfather.context.service.sender;
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.SendType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -11,12 +12,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
public interface Sending {
|
||||
|
||||
/**
|
||||
* Отрпавляет ответ пользователю
|
||||
* Отравляет сообщение пользователю.
|
||||
*
|
||||
* @param personId Идентификатор пользователя
|
||||
* @param boxAnswer Объект с данными, которые необходимо отправить
|
||||
*/
|
||||
void send(@NotNull Long personId, @NotNull BoxAnswer boxAnswer);
|
||||
void send(@NotNull BoxAnswer boxAnswer);
|
||||
|
||||
void addPreSendProcess(@NotNull PreSendProcessing processing);
|
||||
|
||||
/**
|
||||
* Возвращает тип объекта отправляющего ответ пользователя. В зависимости от типа ответ будет отправлен с помощью
|
@ -1,6 +1,6 @@
|
||||
package dev.struchkov.godfather.context.service;
|
||||
package dev.struchkov.godfather.simple.context.service;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.UnitPointer;
|
||||
import dev.struchkov.godfather.main.domain.UnitPointer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
@ -14,8 +14,8 @@ public interface UnitPointerService {
|
||||
|
||||
UnitPointer save(@NotNull UnitPointer unitPointer);
|
||||
|
||||
Optional<String> getUnitNameByPersonId(@NotNull Long personId);
|
||||
Optional<String> getUnitNameByPersonId(@NotNull String personId);
|
||||
|
||||
void removeByPersonId(@NotNull Long personId);
|
||||
void removeByPersonId(@NotNull String personId);
|
||||
|
||||
}
|
@ -1,20 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<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.7</version>
|
||||
<version>0.0.42-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bot-context</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>bot-context-main</module>
|
||||
<module>bot-context-simple</module>
|
||||
<module>bot-context-quarkus</module>
|
||||
</modules>
|
||||
|
||||
|
||||
<name>Bot Context</name>
|
||||
<description>Доменные сущности, интерфейсы, для библиотеки Godfather</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov</groupId>
|
||||
<artifactId>autoresponder</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.haiti</groupId>
|
||||
<artifactId>haiti-utils</artifactId>
|
||||
|
@ -1,27 +0,0 @@
|
||||
package dev.struchkov.godfather.context.domain;
|
||||
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
/**
|
||||
* Основная сущность для сокрытия id у других сущностей.
|
||||
*
|
||||
* @author upagge [28/07/2019]
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public class BasicEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
protected Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
package dev.struchkov.godfather.context.domain.content;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.BasicEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Абстрактная сущность - Сообщение от пользователя.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class Message extends BasicEntity {
|
||||
|
||||
/**
|
||||
* Тип сообщения.
|
||||
*/
|
||||
@Column(name = "type")
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
protected ContentType type;
|
||||
|
||||
/**
|
||||
* Дата создания.
|
||||
*/
|
||||
@NotNull
|
||||
@Column(name = "create_date")
|
||||
private LocalDateTime createDate;
|
||||
|
||||
/**
|
||||
* Дата добавления в базу.
|
||||
*/
|
||||
@Column(name = "add_date")
|
||||
private LocalDateTime addDate;
|
||||
|
||||
/**
|
||||
* Идентификатор пользователя, отправившего сообщение.
|
||||
*/
|
||||
@NotNull
|
||||
@Column(name = "person_id")
|
||||
private Long personId;
|
||||
|
||||
/**
|
||||
* Текстовое сообщение.
|
||||
*/
|
||||
@Column(name = "text")
|
||||
private String text;
|
||||
|
||||
public Message(Message source) {
|
||||
this.personId = source.getPersonId();
|
||||
this.text = source.getText();
|
||||
this.createDate = source.getCreateDate();
|
||||
this.id = source.getPersonId();
|
||||
this.type = source.getType();
|
||||
}
|
||||
|
||||
public Message() {
|
||||
}
|
||||
|
||||
public ContentType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(ContentType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreateDate() {
|
||||
return createDate;
|
||||
}
|
||||
|
||||
public void setCreateDate(LocalDateTime createDate) {
|
||||
this.createDate = createDate;
|
||||
}
|
||||
|
||||
public LocalDateTime getAddDate() {
|
||||
return addDate;
|
||||
}
|
||||
|
||||
public void setAddDate(LocalDateTime addDate) {
|
||||
this.addDate = addDate;
|
||||
}
|
||||
|
||||
public Long getPersonId() {
|
||||
return personId;
|
||||
}
|
||||
|
||||
public void setPersonId(Long personId) {
|
||||
this.personId = personId;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Message message = (Message) o;
|
||||
return type == message.type && Objects.equals(createDate, message.createDate) && Objects.equals(addDate, message.addDate) && Objects.equals(personId, message.personId) && Objects.equals(text, message.text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, createDate, addDate, personId, text);
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Абстрактная сущность, для всех вложений к сообщениям от пользователей.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
@Entity
|
||||
public abstract class Attachment extends BasicEntity {
|
||||
|
||||
/**
|
||||
* Тип сущности.
|
||||
*/
|
||||
@Column(name = "type")
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
protected AttachmentType type;
|
||||
|
||||
public AttachmentType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package dev.struchkov.godfather.context.exception;
|
||||
|
||||
/**
|
||||
* Ошибка таймера.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public class TimerSettingException extends AppBotException {
|
||||
|
||||
public TimerSettingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package dev.struchkov.godfather.context.repository;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Интерфейс взаимодействия со всеми наследниками текстовых запросов пользователей.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public interface ContentRepository<T extends Message> {
|
||||
|
||||
/**
|
||||
* Добавить сообщение в хранилище
|
||||
*
|
||||
* @param content Объект сообщени
|
||||
* @return Идентификатор сообщения в хранилище
|
||||
*/
|
||||
T add(@NotNull T content);
|
||||
|
||||
/**
|
||||
* Получить все сообщения за определенный временной диапазон
|
||||
*
|
||||
* @param dateFrom Начало временного диапазона
|
||||
* @param dateTo Конец диапазона
|
||||
* @return Список сообщений
|
||||
*/
|
||||
List<T> betweenByCreateDateTime(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo);
|
||||
|
||||
List<T> betweenByAddDateTime(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo);
|
||||
|
||||
/**
|
||||
* Удаляет данные за указанный период
|
||||
*
|
||||
* @param dateFrom Дата начала
|
||||
* @param dateTo Дата окончания
|
||||
*/
|
||||
void deleteAllByAddDateBetween(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo);
|
||||
|
||||
void deleteAllByAddDateBefore(@NotNull LocalDateTime date);
|
||||
|
||||
void deleteAllByAddDateAfter(@NotNull LocalDateTime date);
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package dev.struchkov.godfather.context.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public interface PersonSettingRepository {
|
||||
|
||||
Set<Long> findAllByAllowedProcessing(Set<Long> personIds);
|
||||
|
||||
void disableMessageProcessing(Long personId);
|
||||
|
||||
void enableMessageProcessing(Long personId);
|
||||
|
||||
Optional<Boolean> findStateByPersonId(Long personId);
|
||||
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package dev.struchkov.godfather.context.repository.impl.local;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Mail;
|
||||
import dev.struchkov.godfather.context.repository.ContentRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Локальная реализация репозитория на основе {@link ArrayList} для взаимодействия с сущностью {@link Mail}.
|
||||
*
|
||||
* @author upagge [27/07/2019]
|
||||
*/
|
||||
public class MailRepositoryList implements ContentRepository<Mail> {
|
||||
|
||||
private final List<Mail> mails = new ArrayList<>();
|
||||
private Long count = 0L;
|
||||
|
||||
@Override
|
||||
public Mail add(Mail mail) {
|
||||
mail.setId(count++);
|
||||
mails.add(mail);
|
||||
return mail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mail> betweenByCreateDateTime(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo) {
|
||||
ArrayList<Mail> rezultMails = new ArrayList<>();
|
||||
for (int i = mails.size() - 1; i >= 0; i--) {
|
||||
Mail mail = mails.get(i);
|
||||
if (isTimePeriod(dateFrom, dateTo, mail.getAddDate())) {
|
||||
rezultMails.add(mail);
|
||||
} else if (mail.getCreateDate().isBefore(dateFrom)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rezultMails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mail> betweenByAddDateTime(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo) {
|
||||
ArrayList<Mail> rezultMails = new ArrayList<>();
|
||||
for (int i = mails.size() - 1; i >= 0; i--) {
|
||||
Mail mail = mails.get(i);
|
||||
LocalDateTime addDate = mail.getAddDate();
|
||||
if (isTimePeriod(dateFrom, dateTo, addDate)) {
|
||||
rezultMails.add(mail);
|
||||
} else if (addDate.isBefore(dateFrom)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rezultMails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAllByAddDateBetween(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo) {
|
||||
mails.removeIf(mail -> dateFrom.isBefore(mail.getAddDate()) && dateTo.isAfter(mail.getAddDate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAllByAddDateBefore(@NotNull LocalDateTime date) {
|
||||
mails.removeIf(mail -> date.isBefore(mail.getAddDate()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAllByAddDateAfter(@NotNull LocalDateTime date) {
|
||||
mails.removeIf(mail -> date.isAfter(mail.getAddDate()));
|
||||
}
|
||||
|
||||
private boolean isTimePeriod(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo, @NotNull LocalDateTime dateTime) {
|
||||
return dateFrom.isBefore(dateTime) && dateTo.isAfter(dateTime);
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
|
||||
public interface EventProvider<M extends Message> {
|
||||
|
||||
void sendEvent(M message);
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Mail;
|
||||
|
||||
/**
|
||||
* Интерфейс для взаимодействия с личными сообщениями.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public interface MailService extends MessageService<Mail> {
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Интерфейс взаимодйствия с наследниками текстовых сообщений пользователей.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public interface MessageService<T extends Message> {
|
||||
|
||||
void add(@NotNull T event);
|
||||
|
||||
/**
|
||||
* Получить список сообщений за заданный временной интервал
|
||||
*
|
||||
* @param dateFrom Начало интервала
|
||||
* @param dateTo Конец интервала
|
||||
* @return Список сообщений
|
||||
*/
|
||||
List<T> getByAddDateTime(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo);
|
||||
|
||||
/**
|
||||
* Получить список ПОСЛЕДНИХ сообщений для каждого пользователя за заданных временной интервал
|
||||
*
|
||||
* @param dateFrom Начало интервала
|
||||
* @param dateTo Конец интервала
|
||||
* @return Список сообщений
|
||||
*/
|
||||
List<T> getLastEventByCreateDateTime(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo);
|
||||
|
||||
List<T> getLastEventByAddDateTime(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo);
|
||||
|
||||
/**
|
||||
* Возвращает новые сообщения от последнего запроса.
|
||||
*/
|
||||
List<T> getNewMessage();
|
||||
|
||||
void deleteAllByAddDateBetween(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo);
|
||||
|
||||
void deleteAllByAddDateBefore(@NotNull LocalDateTime date);
|
||||
|
||||
void deleteAllByAddDateAfter(@NotNull LocalDateTime date);
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public interface PersonSettingService {
|
||||
|
||||
Set<Long> getAllPersonIdDisableMessages(@NotNull Set<Long> personIds);
|
||||
|
||||
Optional<Boolean> getStateProcessingByPersonId(@NotNull Long personId);
|
||||
|
||||
void disableMessageProcessing(@NotNull Long personId);
|
||||
|
||||
void enableMessageProcessing(@NotNull Long personId);
|
||||
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service.impl;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Mail;
|
||||
import dev.struchkov.godfather.context.repository.ContentRepository;
|
||||
import dev.struchkov.godfather.context.service.MailService;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class MailServiceImpl implements MailService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MailServiceImpl.class);
|
||||
|
||||
private final ContentRepository<Mail> mailRepository;
|
||||
private boolean newMessage = false;
|
||||
private LocalDateTime oldDateTime = LocalDateTime.now(Clock.tickSeconds(ZoneId.systemDefault()));
|
||||
|
||||
public MailServiceImpl(ContentRepository<Mail> mailRepository) {
|
||||
this.mailRepository = mailRepository;
|
||||
}
|
||||
|
||||
//TODO [13.04.2022]: Подобная реализация с newMessage вызовет проблемы с несколькими инстансами.
|
||||
@Override
|
||||
public void add(Mail mail) {
|
||||
mailRepository.add(mail);
|
||||
newMessage = true;
|
||||
log.trace("Сообщение добавлено в репозиторий | {}", mail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mail> getByAddDateTime(LocalDateTime timeFrom, LocalDateTime timeTo) {
|
||||
log.trace("Запрошены все сообщения {} - {} ", timeFrom, timeTo);
|
||||
return mailRepository.betweenByAddDateTime(timeFrom, timeTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mail> getLastEventByCreateDateTime(LocalDateTime timeFrom, LocalDateTime timeTo) {
|
||||
log.trace("Запрошены последние сообщения {} - {} ", timeFrom, timeTo);
|
||||
final List<Mail> mails = mailRepository.betweenByCreateDateTime(timeFrom, timeTo);
|
||||
if (mails != null && !mails.isEmpty()) {
|
||||
return findLastMailEachUser(mails);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mail> getLastEventByAddDateTime(LocalDateTime timeFrom, LocalDateTime timeTo) {
|
||||
log.trace("Запрошены последние сообщения {} - {} ", timeFrom, timeTo);
|
||||
final List<Mail> mails = mailRepository.betweenByAddDateTime(timeFrom, timeTo);
|
||||
if (mails != null && !mails.isEmpty()) {
|
||||
return findLastMailEachUser(mails);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mail> getNewMessage() {
|
||||
final LocalDateTime newData = LocalDateTime.now(Clock.tickSeconds(ZoneId.systemDefault())).plusNanos(999999999);
|
||||
if (newMessage) {
|
||||
final List<Mail> lastEventByAddDateTime = getLastEventByAddDateTime(oldDateTime, newData);
|
||||
newMessage = false;
|
||||
oldDateTime = newData;
|
||||
return lastEventByAddDateTime;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAllByAddDateBetween(@NotNull LocalDateTime dateFrom, @NotNull LocalDateTime dateTo) {
|
||||
mailRepository.deleteAllByAddDateBetween(dateFrom, dateTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAllByAddDateBefore(@NotNull LocalDateTime date) {
|
||||
mailRepository.deleteAllByAddDateBefore(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteAllByAddDateAfter(@NotNull LocalDateTime date) {
|
||||
mailRepository.deleteAllByAddDateAfter(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает только последнее сообщение каждого пользователя переданного из списка.
|
||||
*/
|
||||
private List<Mail> findLastMailEachUser(List<Mail> mails) {
|
||||
final Set<Long> people = new HashSet<>();
|
||||
final List<Mail> returnMails = new ArrayList<>();
|
||||
for (int i = mails.size() - 1; i >= 0; i--) {
|
||||
if (!people.contains(mails.get(i).getPersonId())) {
|
||||
returnMails.add(mails.get(i));
|
||||
people.add(mails.get(i).getPersonId());
|
||||
}
|
||||
}
|
||||
if (!returnMails.isEmpty()) {
|
||||
return returnMails;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service.usercode;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CheckData<C extends Message> {
|
||||
|
||||
boolean checked(C content);
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service.usercode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Insert {
|
||||
|
||||
List<String> insert(Long personId);
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package dev.struchkov.godfather.context.service.usercode;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
|
||||
public interface MessageFunction<M extends Message> {
|
||||
|
||||
void build(M message, BoxAnswer.Builder builder);
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package dev.struchkov.godfather.context.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);
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package dev.struchkov.godfather.context.utils;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.content.EmptyMessage;
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
|
||||
/**
|
||||
* Класс для хранения объекта заглушки для {@link Message}.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public class MessageUtils {
|
||||
|
||||
public static final EmptyMessage EMPTY_MESSAGE = new EmptyMessage();
|
||||
|
||||
private MessageUtils() {
|
||||
throw new IllegalStateException(Messages.UTILITY_CLASS);
|
||||
}
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package dev.struchkov.godfather.context.utils;
|
||||
|
||||
/**
|
||||
* Класс утилита, содержащий сообщения об ошибках, и сообщения логирования.
|
||||
*
|
||||
* @author upagge [15/08/2019]
|
||||
*/
|
||||
public class Messages {
|
||||
|
||||
public static final String UTILITY_CLASS = "Класс утилита";
|
||||
|
||||
private Messages() {
|
||||
throw new IllegalStateException(UTILITY_CLASS);
|
||||
}
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package dev.struchkov.godfather.context.utils;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.context.domain.content.Message;
|
||||
import dev.struchkov.godfather.context.service.sender.Sending;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
|
||||
|
||||
/**
|
||||
* Используется для отправки сообщений определенного типа.
|
||||
*
|
||||
* @author upagge
|
||||
*/
|
||||
public class Sender {
|
||||
|
||||
private Sender() {
|
||||
utilityClass();
|
||||
}
|
||||
|
||||
public static void sends(Message message, BoxAnswer boxAnswer, Sending sending) {
|
||||
switch (sending.getType()) {
|
||||
case PUBLIC:
|
||||
break;
|
||||
case PRIVATE:
|
||||
privateSend(message, boxAnswer, sending);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void privateSend(Message message, BoxAnswer boxAnswer, Sending sending) {
|
||||
sending.send(message.getPersonId(), boxAnswer);
|
||||
}
|
||||
|
||||
}
|
25
bot-core/bot-core-main/pom.xml
Normal file
25
bot-core/bot-core-main/pom.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-core</artifactId>
|
||||
<version>0.0.42-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bot-core-main</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-domain-main</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,4 +1,6 @@
|
||||
package dev.struchkov.godfather.core.utils;
|
||||
package dev.struchkov.godfather.main.core.unit;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
|
||||
|
||||
/**
|
||||
* Тип Unit-а. Обределяет способ обработки.
|
||||
@ -9,14 +11,14 @@ 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 REPLACE_CMD = "REPLACE_CMD";
|
||||
|
||||
private TypeUnit() {
|
||||
throw new IllegalStateException("Утилитарный класс");
|
||||
utilityClass();
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package dev.struchkov.godfather.core.domain.unit;
|
||||
package dev.struchkov.godfather.main.core.unit;
|
||||
|
||||
/**
|
||||
* Тип активации Unit-а. Определяет порядок обработки Unit.
|
@ -1,4 +1,4 @@
|
||||
package dev.struchkov.godfather.context.utils;
|
||||
package dev.struchkov.godfather.main.core.utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -0,0 +1,21 @@
|
||||
package dev.struchkov.godfather.main.core.utils;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.EmptyMessage;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Exceptions.utilityClass;
|
||||
|
||||
/**
|
||||
* Класс для хранения объекта заглушки для {@link Message}.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public final class MessageUtils {
|
||||
|
||||
public static final EmptyMessage EMPTY_MESSAGE = new EmptyMessage();
|
||||
|
||||
private MessageUtils() {
|
||||
utilityClass();
|
||||
}
|
||||
|
||||
}
|
39
bot-core/bot-core-quarkus/pom.xml
Normal file
39
bot-core/bot-core-quarkus/pom.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<?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>bot-core</artifactId>
|
||||
<version>0.0.42-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bot-core-quarkus</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-core-main</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-context-quarkus</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-data-quarkus</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.smallrye.reactive</groupId>
|
||||
<artifactId>smallrye-mutiny-vertx-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,208 @@
|
||||
package dev.struchkov.godfather.quarkus.core;
|
||||
|
||||
import dev.struchkov.autoresponder.Responder;
|
||||
import dev.struchkov.godfather.exception.ConfigAppException;
|
||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.ErrorHandler;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Modifiable;
|
||||
import dev.struchkov.godfather.quarkus.context.service.PersonSettingService;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Sending;
|
||||
import dev.struchkov.godfather.quarkus.core.action.ActionUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.action.AnswerCheckAction;
|
||||
import dev.struchkov.godfather.quarkus.core.action.AnswerSaveAction;
|
||||
import dev.struchkov.godfather.quarkus.core.action.AnswerTextAction;
|
||||
import dev.struchkov.godfather.quarkus.core.action.cmd.ReplaceCmdAction;
|
||||
import dev.struchkov.godfather.quarkus.core.service.StorylineService;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.UnitRequest;
|
||||
import dev.struchkov.haiti.context.exception.NotFoundException;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkEmpty;
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
public class GeneralAutoResponder<M extends Message> {
|
||||
|
||||
private final PersonSettingService personSettingService;
|
||||
private final StorylineService<M> storyLineService;
|
||||
protected Map<String, ActionUnit> actionUnitMap = new HashMap<>();
|
||||
protected List<Modifiable<M>> modifiable;
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
protected GeneralAutoResponder(
|
||||
Sending sending,
|
||||
PersonSettingService personSettingService,
|
||||
StorylineService<M> storyLineService
|
||||
) {
|
||||
this.personSettingService = personSettingService;
|
||||
this.storyLineService = storyLineService;
|
||||
init(sending);
|
||||
}
|
||||
|
||||
private void init(Sending sending) {
|
||||
actionUnitMap.put(TypeUnit.CHECK, new AnswerCheckAction<>(sending));
|
||||
actionUnitMap.put(TypeUnit.TEXT, new AnswerTextAction(sending));
|
||||
actionUnitMap.put(TypeUnit.REPLACE_CMD, new ReplaceCmdAction());
|
||||
}
|
||||
|
||||
public void initModifiable(List<Modifiable<M>> modifiable) {
|
||||
this.modifiable = modifiable;
|
||||
}
|
||||
|
||||
public void initActionUnit(String typeUnit, ActionUnit<? extends MainUnit<M>, M> actionUnit) {
|
||||
if (!actionUnitMap.containsKey(typeUnit)) {
|
||||
actionUnitMap.put(typeUnit, actionUnit);
|
||||
} else {
|
||||
throw new ConfigAppException("Обработка такого типа юнита уже зарегистрирована");
|
||||
}
|
||||
}
|
||||
|
||||
public void initSaveAction(AnswerSaveAction<M, ?> answerSaveAction) {
|
||||
actionUnitMap.put(TypeUnit.SAVE, answerSaveAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет установить перехватчик и обработчик исключений, возникающих при обработке юнитов.
|
||||
*/
|
||||
public void setErrorHandler(ErrorHandler errorHandler) {
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public void setDefaultUnit(String unitName) {
|
||||
storyLineService.setDefaultUnit(unitName);
|
||||
}
|
||||
|
||||
public Uni<Void> processingNewMessage(M newMessage) {
|
||||
return Uni.createFrom().item(newMessage)
|
||||
.onItem().ifNotNull().transformToUni(
|
||||
message -> personSettingService.getStateProcessingByPersonId(newMessage.getPersonId())
|
||||
.replaceIfNullWith(TRUE)
|
||||
.chain(
|
||||
state -> {
|
||||
if (TRUE.equals(state)) {
|
||||
return processing(newMessage);
|
||||
}
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
)
|
||||
).replaceWithVoid();
|
||||
|
||||
}
|
||||
|
||||
public Uni<Void> processingNewMessages(List<M> newMessages) {
|
||||
return Uni.createFrom().item(newMessages)
|
||||
.onItem().ifNotNull().transformToUni(
|
||||
messages -> {
|
||||
if (checkEmpty(newMessages)) return Uni.createFrom().voidItem();
|
||||
|
||||
final Set<String> personIds = newMessages.stream()
|
||||
.map(Message::getPersonId)
|
||||
.collect(Collectors.toSet());
|
||||
return personSettingService.getAllPersonIdDisableMessages(personIds)
|
||||
.replaceIfNullWith(emptySet())
|
||||
.onItem().transformToMulti(
|
||||
disableIds -> {
|
||||
final List<M> allowedMessages = newMessages.stream()
|
||||
.filter(message -> !disableIds.contains(message.getPersonId()))
|
||||
.toList();
|
||||
return Multi.createFrom().iterable(allowedMessages);
|
||||
}
|
||||
)
|
||||
.onItem().transform(this::processing)
|
||||
.toUni().replaceWithVoid();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private Uni<Void> processing(M message) {
|
||||
return Uni.createFrom().item(message)
|
||||
.onItem().ifNotNull().transform(m -> modifiable)
|
||||
.replaceIfNullWith(emptyList())
|
||||
.onItem().transformToMulti(modifiables -> Multi.createFrom().iterable(modifiables))
|
||||
.onItem().transformToUni(mModifiable -> mModifiable.change(message))
|
||||
.concatenate().toUni().replaceWith(
|
||||
storyLineService.getNextUnitByPersonId(message.getPersonId())
|
||||
.onItem().ifNotNull().transformToUni(
|
||||
nextUnits -> Uni.createFrom().optional(
|
||||
Responder.nextUnit(message, nextUnits).or(storyLineService::getDefaultUnit)
|
||||
)
|
||||
).onItem().ifNotNull().transformToUni(answerUnit -> answer(UnitRequest.of(answerUnit, message)))
|
||||
);
|
||||
}
|
||||
|
||||
public Uni<Void> answer(UnitRequest<MainUnit, M> unitRequest) {
|
||||
return getAction(unitRequest)
|
||||
.chain(request -> activeUnitAfter(unitRequest))
|
||||
.onFailure().call(
|
||||
throwable -> {
|
||||
if (checkNotNull(errorHandler)) {
|
||||
return errorHandler.handle(unitRequest.getMessage(), throwable);
|
||||
}
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
)
|
||||
.replaceWithVoid();
|
||||
}
|
||||
|
||||
private Uni<UnitRequest<MainUnit, M>> activeUnitAfter(UnitRequest<MainUnit, M> unitRequest) {
|
||||
final Set<MainUnit<M>> nextUnits = unitRequest.getUnit().getNextUnits();
|
||||
if (checkNotNull(nextUnits)) {
|
||||
Optional<MainUnit<M>> first = nextUnits.stream()
|
||||
.filter(unit -> UnitActiveType.AFTER.equals(unit.getActiveType()))
|
||||
.findFirst();
|
||||
if (first.isPresent()) {
|
||||
return Uni.createFrom().voidItem().onItem().transformToUni(
|
||||
v -> getAction(UnitRequest.of(first.get(), unitRequest.getMessage()))
|
||||
)
|
||||
.onItem().transformToUni(
|
||||
uR -> activeUnitAfter(UnitRequest.of(first.get(), unitRequest.getMessage()))
|
||||
);
|
||||
}
|
||||
}
|
||||
return Uni.createFrom().item(unitRequest);
|
||||
}
|
||||
|
||||
private Uni<UnitRequest<MainUnit, M>> getAction(UnitRequest<MainUnit, M> unitRequest) {
|
||||
final MainUnit<M> unit = unitRequest.getUnit();
|
||||
final M message = unitRequest.getMessage();
|
||||
final String typeUnit = unit.getType();
|
||||
if (actionUnitMap.containsKey(typeUnit)) {
|
||||
ActionUnit<MainUnit, M> actionUnit = actionUnitMap.get(typeUnit);
|
||||
return actionUnit.action(unitRequest)
|
||||
.onItem().transformToUni(
|
||||
newUnitRequest -> {
|
||||
final Optional<MainUnit<M>> optDefaultUnit = storyLineService.getDefaultUnit();
|
||||
if (!unit.isNotSaveHistory() && (optDefaultUnit.isEmpty() || !optDefaultUnit.get().equals(unit))) {
|
||||
return Uni.combine().all().unis(
|
||||
Uni.createFrom().item(newUnitRequest),
|
||||
storyLineService.save(message.getPersonId(), unit.getName(), message)
|
||||
).asTuple();
|
||||
}
|
||||
return Uni.combine().all().unis(Uni.createFrom().item(newUnitRequest), Uni.createFrom().voidItem()).asTuple();
|
||||
}
|
||||
).onItem().transformToUni(
|
||||
t -> {
|
||||
final UnitRequest<MainUnit, M> newUnitRequest = t.getItem1();
|
||||
final MainUnit<M> newUnit = newUnitRequest.getUnit();
|
||||
return !unit.equals(newUnit) ? getAction(newUnitRequest) : Uni.createFrom().item(unitRequest);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
throw new NotFoundException("ActionUnit для типа {0} не зарегистрирован", unit.getType());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package dev.struchkov.godfather.quarkus.core;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNull;
|
||||
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
|
||||
|
||||
public class Storyline<M extends Message> {
|
||||
|
||||
private final Set<MainUnit<M>> startingUnits = new HashSet<>();
|
||||
private final Set<MainUnit<M>> globalUnits = new HashSet<>();
|
||||
private final Map<String, MainUnit<M>> units = new HashMap<>();
|
||||
|
||||
public Storyline(Set<MainUnit<M>> startingUnits, Map<String, MainUnit<M>> units) {
|
||||
this.startingUnits.addAll(startingUnits);
|
||||
this.units.putAll(units);
|
||||
}
|
||||
|
||||
public void addGlobalUnits(Set<MainUnit<M>> globalUnits) {
|
||||
this.globalUnits.addAll(globalUnits);
|
||||
}
|
||||
|
||||
public Set<MainUnit<M>> getGlobalUnits() {
|
||||
return globalUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить юнит по названию.
|
||||
*
|
||||
* @param unitName Название юнита.
|
||||
*/
|
||||
public Optional<MainUnit<M>> getUnit(String unitName) {
|
||||
isNotNull(unitName);
|
||||
return Optional.ofNullable(units.get(unitName));
|
||||
}
|
||||
|
||||
public Set<MainUnit<M>> getStartingUnits() {
|
||||
return startingUnits;
|
||||
}
|
||||
|
||||
//TODO [22.06.2022]: Временное решение ленивой связки юнитов, пока не будет реализован нормальный механизм.
|
||||
public void link(@NotNull String firstName, @NotNull String secondName) {
|
||||
isNotNull(firstName, secondName);
|
||||
final MainUnit<M> firstUnit = units.get(firstName);
|
||||
final MainUnit<M> secondUnit = units.get(secondName);
|
||||
isNotNull(firstUnit, secondUnit);
|
||||
if (checkNull(firstUnit.getNextUnits())) {
|
||||
firstUnit.setNextUnits(new HashSet<>());
|
||||
}
|
||||
firstUnit.getNextUnits().add(secondUnit);
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package dev.struchkov.godfather.core;
|
||||
package dev.struchkov.godfather.quarkus.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.exception.UnitConfigException;
|
||||
import dev.struchkov.godfather.main.domain.UnitDefinition;
|
||||
import dev.struchkov.godfather.main.domain.annotation.Unit;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.haiti.utils.Inspector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -21,20 +21,21 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.struchkov.godfather.context.exception.UnitConfigException.unitConfigException;
|
||||
import static dev.struchkov.godfather.exception.UnitConfigException.unitConfigException;
|
||||
|
||||
public class StorylineMaker {
|
||||
public class StorylineFactory<M extends Message> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(StorylineMaker.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(StorylineFactory.class);
|
||||
|
||||
private final List<Object> configurations = new ArrayList<>();
|
||||
|
||||
private final Map<String, UnitDefinition> unitDefinitions = new HashMap<>();
|
||||
private final Map<String, MainUnit> unitMap = new HashMap<>();
|
||||
private final Set<String> lazyUnits = new HashSet<>();
|
||||
private final Set<String> mainUnits = new HashSet<>();
|
||||
private final Map<String, MainUnit<M>> unitMap = new HashMap<>();
|
||||
|
||||
public StorylineMaker(List<Object> unitConfigurations) {
|
||||
private final Set<String> mainUnits = new HashSet<>();
|
||||
private final Set<String> globalUnits = new HashSet<>();
|
||||
|
||||
public StorylineFactory(List<Object> unitConfigurations) {
|
||||
this.configurations.addAll(unitConfigurations);
|
||||
}
|
||||
|
||||
@ -42,45 +43,36 @@ public class StorylineMaker {
|
||||
return unitDefinitions;
|
||||
}
|
||||
|
||||
public Map<String, MainUnit> getUnitMap() {
|
||||
public Map<String, MainUnit<M>> getUnitMap() {
|
||||
return unitMap;
|
||||
}
|
||||
|
||||
public StoryLine createStoryLine() {
|
||||
public Storyline<M> createStoryLine() {
|
||||
generateUnitDefinitions();
|
||||
try {
|
||||
createUnitMap();
|
||||
createLazy();
|
||||
final Set<MainUnit> mainUnit = getMainUnit();
|
||||
return new StoryLine(mainUnit, unitMap);
|
||||
final Set<MainUnit<M>> mainUnit = getMainUnit();
|
||||
final Set<MainUnit<M>> globalUnit = getGlobalUnit();
|
||||
final Storyline<M> storyline = new Storyline<>(mainUnit, unitMap);
|
||||
storyline.addGlobalUnits(globalUnit);
|
||||
return storyline;
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
throw new UnitConfigException("Ошибка построения StoryLine");
|
||||
}
|
||||
|
||||
private Set<MainUnit> getMainUnit() {
|
||||
private Set<MainUnit<M>> getMainUnit() {
|
||||
Inspector.isNotEmpty(mainUnits, unitConfigException("Не задан ни один mainUnit. Установите хотя бы для одного Unit флаг mainUnit"));
|
||||
return mainUnits.stream()
|
||||
.map(unitMap::get)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void createLazy() throws IllegalAccessException, InvocationTargetException {
|
||||
final List<UnitDefinition> lazyDefinitions = unitDefinitions.values().stream()
|
||||
.filter(UnitDefinition::isLazy)
|
||||
.toList();
|
||||
for (UnitDefinition lazyDefinition : lazyDefinitions) {
|
||||
final MainUnit lazyUnit = createUnit(lazyDefinition);
|
||||
unitMap.put(lazyDefinition.getName(), lazyUnit);
|
||||
for (String dependentUnit : lazyDefinition.getDependentUnits()) {
|
||||
final MainUnit mainUnit = unitMap.get(dependentUnit);
|
||||
final Set<MainUnit> nextUnits = mainUnit.getNextUnits();
|
||||
if (nextUnits != null) {
|
||||
nextUnits.add(lazyUnit);
|
||||
}
|
||||
}
|
||||
}
|
||||
private Set<MainUnit<M>> getGlobalUnit() {
|
||||
return globalUnits.stream()
|
||||
.map(unitMap::get)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void createUnitMap() throws IllegalAccessException, InvocationTargetException {
|
||||
@ -89,20 +81,12 @@ public class StorylineMaker {
|
||||
final Set<String> nextUnitNames = unitDefinition.getNextUnitNames();
|
||||
if (nextUnitNames.isEmpty() || unitMap.keySet().containsAll(nextUnitNames)) {
|
||||
createUnit(unitDefinition);
|
||||
} else if (unitDefinition.isLazy()) {
|
||||
createLazyUnit(unitDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createLazyUnit(UnitDefinition unitDefinition) {
|
||||
final String unitName = unitDefinition.getName();
|
||||
unitMap.put(unitName, LazyUnit.create(unitName, unitDefinition));
|
||||
}
|
||||
|
||||
private MainUnit createUnit(UnitDefinition unitDefinition) throws IllegalAccessException, InvocationTargetException {
|
||||
|
||||
private MainUnit<M> createUnit(UnitDefinition unitDefinition) throws IllegalAccessException, InvocationTargetException {
|
||||
final Object objectConfig = unitDefinition.getObjectConfig();
|
||||
final String currentUnitName = unitDefinition.getName();
|
||||
final Method method = unitDefinition.getMethod();
|
||||
@ -112,13 +96,12 @@ public class StorylineMaker {
|
||||
.map(Unit::value)
|
||||
.map(unitMap::get)
|
||||
.toArray();
|
||||
MainUnit newUnit = (MainUnit) method.invoke(objectConfig, nextUnits);
|
||||
MainUnit<M> newUnit = (MainUnit<M>) method.invoke(objectConfig, nextUnits);
|
||||
newUnit.setName(currentUnitName);
|
||||
|
||||
unitMap.put(currentUnitName, newUnit);
|
||||
|
||||
final Set<String> dependentUnitsName = unitDefinition.getDependentUnits();
|
||||
dependentUnitsName.removeAll(lazyUnits);
|
||||
for (String dependentUnitName : dependentUnitsName) {
|
||||
final Set<String> dependentNextUnitNames = unitDefinitions.get(dependentUnitName).getNextUnitNames();
|
||||
if (unitMap.keySet().containsAll(dependentNextUnitNames)) {
|
||||
@ -145,14 +128,13 @@ public class StorylineMaker {
|
||||
unitDefinition.setName(unitName);
|
||||
unitDefinition.setMethod(method);
|
||||
unitDefinition.setObjectConfig(config);
|
||||
unitDefinition.setLazy(unitConfig.lazy());
|
||||
|
||||
if (unitConfig.lazy()) {
|
||||
lazyUnits.add(unitName);
|
||||
}
|
||||
if (unitConfig.mainUnit()) {
|
||||
if (unitConfig.main()) {
|
||||
mainUnits.add(unitName);
|
||||
}
|
||||
if (unitConfig.global()) {
|
||||
globalUnits.add(unitName);
|
||||
}
|
||||
|
||||
final Parameter[] nextUnits = method.getParameters();
|
||||
if (nextUnits.length > 0) {
|
@ -0,0 +1,23 @@
|
||||
package dev.struchkov.godfather.quarkus.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.UnitRequest;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
/**
|
||||
* Интерфейс для обработки Unit-ов.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ActionUnit<U extends MainUnit, M extends Message> {
|
||||
|
||||
/**
|
||||
* Метод обработки Unit-а.
|
||||
*
|
||||
* @return Новый Unit, который может нуждаться в обработке
|
||||
*/
|
||||
Uni<UnitRequest<MainUnit, M>> action(UnitRequest<U, M> unitRequest);
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package dev.struchkov.godfather.quarkus.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Sending;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.AnswerCheck;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.UnitRequest;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||
import static dev.struchkov.haiti.utils.Checker.checkTrue;
|
||||
|
||||
/**
|
||||
* Обработчик Unit-а {@link AnswerCheck}.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
public class AnswerCheckAction<M extends Message> implements ActionUnit<AnswerCheck<M>, M> {
|
||||
|
||||
private final Sending sending;
|
||||
|
||||
public AnswerCheckAction(Sending sending) {
|
||||
this.sending = sending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<UnitRequest<MainUnit, M>> action(UnitRequest<AnswerCheck<M>, M> unitRequest) {
|
||||
final AnswerCheck<M> unit = unitRequest.getUnit();
|
||||
final M message = unitRequest.getMessage();
|
||||
|
||||
return unit.getCheck().checked(message)
|
||||
.onItem().call(checkValue -> {
|
||||
if (checkTrue(checkValue)) {
|
||||
final BoxAnswer answerIfTrue = unit.getIntermediateAnswerIfTrue();
|
||||
if (checkNotNull(answerIfTrue)) {
|
||||
answerIfTrue.setRecipientIfNull(message.getPersonId());
|
||||
return sending.send(answerIfTrue);
|
||||
}
|
||||
} else {
|
||||
final BoxAnswer answerIfFalse = unit.getIntermediateAnswerIfFalse();
|
||||
if (checkNotNull(answerIfFalse)) {
|
||||
answerIfFalse.setRecipientIfNull(message.getPersonId());
|
||||
return sending.send(answerIfFalse);
|
||||
}
|
||||
}
|
||||
return Uni.createFrom().voidItem();
|
||||
})
|
||||
.onItem().transform(
|
||||
checkValue -> {
|
||||
if (checkTrue(checkValue)) {
|
||||
return UnitRequest.of(Objects.requireNonNullElse(unit.getUnitTrue(), unit), message);
|
||||
} else {
|
||||
return UnitRequest.of(Objects.requireNonNullElse(unit.getUnitFalse(), unit), message);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package dev.struchkov.godfather.quarkus.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Pusher;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.AnswerSave;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.UnitRequest;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.func.CheckSave;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.func.PreservableData;
|
||||
import dev.struchkov.godfather.quarkus.data.preser.AnswerSavePreservable;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||
|
||||
/**
|
||||
* Обработчик Unit-а {@link AnswerSave}.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
public class AnswerSaveAction<M extends Message, D> implements ActionUnit<AnswerSave<M, D>, M> {
|
||||
|
||||
@Override
|
||||
public Uni<UnitRequest<MainUnit, M>> action(UnitRequest<AnswerSave<M, D>, M> unitRequest) {
|
||||
final AnswerSave<M, D> answerSave = unitRequest.getUnit();
|
||||
final M message = unitRequest.getMessage();
|
||||
|
||||
final AnswerSavePreservable<D> preservable = answerSave.getPreservable();
|
||||
final String personId = message.getPersonId();
|
||||
|
||||
final CheckSave<M> checkSave = answerSave.getCheckSave();
|
||||
if (checkNotNull(checkSave)) {
|
||||
return Uni.createFrom().voidItem()
|
||||
.onItem().transformToUni(
|
||||
v -> checkSave.check(message)
|
||||
.onItem().transform(
|
||||
unit -> {
|
||||
if (checkNotNull(unit)) {
|
||||
return UnitRequest.of(unit, message);
|
||||
}
|
||||
return UnitRequest.of(answerSave, message);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final PreservableData<D, M> preservableData = answerSave.getPreservableData();
|
||||
final Pusher<D> pusher = answerSave.getPusher();
|
||||
|
||||
return Uni.createFrom().voidItem()
|
||||
.onItem().transformToUni(
|
||||
v -> {
|
||||
if (checkNotNull(preservableData)) {
|
||||
return preservableData.getData(message);
|
||||
}
|
||||
return Uni.createFrom().nullItem();
|
||||
}
|
||||
).onItem().transformToUni(
|
||||
dataFromSave -> {
|
||||
if (checkNotNull(dataFromSave)) {
|
||||
return preservable.save(personId, answerSave.getKey(), dataFromSave);
|
||||
}
|
||||
return Uni.createFrom().nullItem();
|
||||
}
|
||||
).onItem().transformToUni(
|
||||
v -> {
|
||||
if (checkNotNull(pusher)) {
|
||||
return preservable.push(personId, pusher);
|
||||
}
|
||||
return Uni.createFrom().nullItem();
|
||||
}
|
||||
).onItem().transform(
|
||||
v -> UnitRequest.of(answerSave, message)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package dev.struchkov.godfather.quarkus.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.core.utils.InsertWords;
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Sending;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.AnswerText;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.UnitRequest;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotEmpty;
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||
|
||||
/**
|
||||
* Обработчик Unit-а {@link AnswerText}.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
public class AnswerTextAction implements ActionUnit<AnswerText<Message>, Message> {
|
||||
|
||||
private final Sending sending;
|
||||
|
||||
public AnswerTextAction(Sending sending) {
|
||||
this.sending = sending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<UnitRequest<MainUnit, Message>> action(UnitRequest<AnswerText<Message>, Message> unitRequest) {
|
||||
final Message message = unitRequest.getMessage();
|
||||
final AnswerText<Message> unit = unitRequest.getUnit();
|
||||
return Uni.createFrom().voidItem()
|
||||
.chain(request -> unit.getAnswer().processing(message))
|
||||
.onItem().ifNotNull().transformToUni(boxAnswer -> replaceMarkers(unit, message, boxAnswer))
|
||||
.onItem().ifNotNull().transformToUni(boxAnswer -> {
|
||||
final Sending answerTextSending = unit.getSending();
|
||||
boxAnswer.setRecipientIfNull(message.getPersonId());
|
||||
if (checkNotNull(answerTextSending)) {
|
||||
return answerTextSending.send(boxAnswer);
|
||||
} else {
|
||||
return sending.send(boxAnswer);
|
||||
}
|
||||
}).replaceWith(UnitRequest.of(unit, message));
|
||||
}
|
||||
|
||||
private Uni<BoxAnswer> replaceMarkers(AnswerText<Message> answerText, Message message, BoxAnswer boxAnswer) {
|
||||
return Uni.createFrom().item(answerText.getInsert())
|
||||
.onItem().ifNotNull().transformToUni(insert -> insert.insert(message.getPersonId()))
|
||||
.onItem().ifNotNull().transform(words -> {
|
||||
if (checkNotEmpty(words)) {
|
||||
final String newMessage = InsertWords.insert(boxAnswer.getMessage(), words);
|
||||
boxAnswer.setMessage(newMessage);
|
||||
}
|
||||
return boxAnswer;
|
||||
})
|
||||
.replaceIfNullWith(boxAnswer);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package dev.struchkov.godfather.quarkus.core.action.cmd;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.action.ActionUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.UnitRequest;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.cmd.ReplaceCmd;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public class ReplaceCmdAction implements ActionUnit<ReplaceCmd<Message>, Message> {
|
||||
|
||||
@Override
|
||||
public Uni<UnitRequest<MainUnit, Message>> action(UnitRequest<ReplaceCmd<Message>, Message> unitRequest) {
|
||||
final ReplaceCmd<Message> unit = unitRequest.getUnit();
|
||||
final Message message = unitRequest.getMessage();
|
||||
return Uni.createFrom().item(UnitRequest.of(unit.getThisUnit(), message));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package dev.struchkov.godfather.quarkus.core.action.cmd;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.StorylineHistory;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.action.ActionUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.service.StorylineService;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.UnitRequest;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.cmd.RollBackCmd;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import static dev.struchkov.godfather.exception.RollBackException.rollBackException;
|
||||
|
||||
public class RollBackCmdAction<M extends Message> implements ActionUnit<RollBackCmd<M>, M> {
|
||||
|
||||
private final StorylineService<M> storyLineService;
|
||||
|
||||
public RollBackCmdAction(StorylineService<M> storyLineService) {
|
||||
this.storyLineService = storyLineService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<UnitRequest<MainUnit, M>> action(UnitRequest<RollBackCmd<M>, M> unitRequest) {
|
||||
final RollBackCmd<M> unit = unitRequest.getUnit();
|
||||
final M message = unitRequest.getMessage();
|
||||
|
||||
final int countToBack = unit.getCountBack();
|
||||
final String rollbackUnitName = unit.getRollbackUnitName();
|
||||
|
||||
final Uni<StorylineHistory> uniHistory = (rollbackUnitName != null)
|
||||
? storyLineService.replaceUserToBack(message.getPersonId(), rollbackUnitName).onItem().ifNull().failWith(rollBackException("Юнит для возвращения не был найден"))
|
||||
: storyLineService.replaceUserToBack(message.getPersonId(), countToBack).onItem().ifNull().failWith(rollBackException("Юнит для возвращения не был найден"));
|
||||
|
||||
return uniHistory
|
||||
.onItem().transform(
|
||||
history -> {
|
||||
final String unitName = history.getUnitName();
|
||||
final MainUnit<M> nextUnit = storyLineService.getUnitByName(unitName).orElse(unit);
|
||||
final M oldMessage = (M) history.getMessage();
|
||||
return UnitRequest.of(nextUnit, oldMessage);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package dev.struchkov.godfather.quarkus.core.provider;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||
import dev.struchkov.godfather.quarkus.context.service.EventHandler;
|
||||
import dev.struchkov.godfather.quarkus.core.GeneralAutoResponder;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
public class StoryLineHandler implements EventHandler<Mail> {
|
||||
|
||||
private final GeneralAutoResponder<Mail> generalAutoResponder;
|
||||
|
||||
public StoryLineHandler(GeneralAutoResponder<Mail> generalAutoResponder) {
|
||||
this.generalAutoResponder = generalAutoResponder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Void> handle(Mail message) {
|
||||
return generalAutoResponder.processingNewMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return Mail.TYPE;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package dev.struchkov.godfather.quarkus.core.service;
|
||||
|
||||
import dev.struchkov.godfather.quarkus.context.service.PersonSettingService;
|
||||
import dev.struchkov.godfather.quarkus.data.repository.PersonSettingRepository;
|
||||
import dev.struchkov.haiti.utils.Inspector;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class PersonSettingServiceImpl implements PersonSettingService {
|
||||
|
||||
private final PersonSettingRepository personSettingRepository;
|
||||
|
||||
public PersonSettingServiceImpl(PersonSettingRepository personSettingRepository) {
|
||||
this.personSettingRepository = personSettingRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Set<String>> getAllPersonIdDisableMessages(@NotNull Set<String> personIds) {
|
||||
Inspector.isNotNull(personIds);
|
||||
return personSettingRepository.findAllByAllowedProcessing(personIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Boolean> getStateProcessingByPersonId(@NotNull String personId) {
|
||||
return personSettingRepository.findStateByPersonId(personId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Void> disableMessageProcessing(@NotNull String personId) {
|
||||
Inspector.isNotNull(personId);
|
||||
return personSettingRepository.disableMessageProcessing(personId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Void> enableMessageProcessing(@NotNull String personId) {
|
||||
Inspector.isNotNull(personId);
|
||||
return personSettingRepository.enableMessageProcessing(personId);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package dev.struchkov.godfather.quarkus.core.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.ContextKey;
|
||||
import dev.struchkov.godfather.quarkus.data.StorylineContext;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
|
||||
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
|
||||
|
||||
public class StorylineContextMapImpl implements StorylineContext {
|
||||
|
||||
private final Map<String, Map<String, Object>> map = new HashMap<>();
|
||||
|
||||
public Uni<Void> save(@NotNull String personId, @NotNull ContextKey<?> key, Object objectForSave) {
|
||||
isNotNull(personId, key);
|
||||
map.computeIfAbsent(personId, k -> new HashMap<>()).put(key.getValue(), objectForSave);
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
|
||||
public <T> Uni<T> getByKey(@NotNull String personId, @NotNull ContextKey<T> key) {
|
||||
isNotNull(personId, key);
|
||||
if (map.containsKey(personId)) {
|
||||
final Map<String, Object> storage = map.get(personId);
|
||||
final T object = (T) storage.get(key.getValue());
|
||||
if (object != null && object.getClass().equals(key.getType())) {
|
||||
return Uni.createFrom().item(object);
|
||||
}
|
||||
}
|
||||
return Uni.createFrom().nullItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Uni<T> getByKeyOrThrow(@NotNull String personId, @NotNull ContextKey<T> key) {
|
||||
return getByKey(personId, key)
|
||||
.onItem().ifNull().failWith(notFoundException("Не найдено значение ключа {0}, для пользователя {1}", key.getValue(), personId));
|
||||
}
|
||||
|
||||
public Uni<Map<String, Object>> getAllSaveElement(@NotNull String personId) {
|
||||
isNotNull(personId);
|
||||
return Uni.createFrom().item(map.get(personId));
|
||||
}
|
||||
|
||||
public Uni<Void> removeAll(@NotNull String personId) {
|
||||
isNotNull(personId);
|
||||
map.remove(personId);
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
|
||||
public Uni<Void> removeByKey(@NotNull String personId, @NotNull ContextKey<?> key) {
|
||||
isNotNull(personId, key);
|
||||
map.computeIfAbsent(personId, k -> new HashMap<>()).remove(key.getValue());
|
||||
return Uni.createFrom().voidItem();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
package dev.struchkov.godfather.quarkus.core.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.StorylineHistory;
|
||||
import dev.struchkov.godfather.main.domain.UnitPointer;
|
||||
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||
import dev.struchkov.godfather.quarkus.context.service.UnitPointerService;
|
||||
import dev.struchkov.godfather.quarkus.core.Storyline;
|
||||
import dev.struchkov.godfather.quarkus.core.StorylineFactory;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.quarkus.data.repository.StorylineRepository;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkEmpty;
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotEmpty;
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||
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<Mail> storyLine;
|
||||
private String defaultUnitName;
|
||||
|
||||
public StorylineMailService(
|
||||
UnitPointerService unitPointerService,
|
||||
StorylineRepository storylineRepository,
|
||||
List<Object> unitConfigurations
|
||||
) {
|
||||
this.storyLine = new StorylineFactory<Mail>(unitConfigurations).createStoryLine();
|
||||
this.unitPointerService = unitPointerService;
|
||||
this.storylineRepository = storylineRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Void> save(@NotNull StorylineHistory storylineHistory) {
|
||||
isNotNull(storylineHistory);
|
||||
return storylineRepository.save(storylineHistory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<MainUnit<Mail>> getUnitNameByPersonId(@NotNull String personId) {
|
||||
isNotNull(personId);
|
||||
return unitPointerService.getUnitNameByPersonId(personId)
|
||||
.onItem().transform(
|
||||
unitName -> {
|
||||
if (checkNotNull(unitName)) {
|
||||
return storyLine.getUnit(unitName).orElse(null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Set<MainUnit<Mail>>> getNextUnitByPersonId(@NotNull String personId) {
|
||||
return getUnitNameByPersonId(personId)
|
||||
.flatMap(
|
||||
unit -> {
|
||||
if (checkNotNull(unit) && checkNotEmpty(unit.getNextUnits())) {
|
||||
return Uni.createFrom().item(unit.getNextUnits());
|
||||
} else {
|
||||
return storylineRepository.cleanHistoryByPersonId(personId)
|
||||
.onItem().transform(v -> storyLine.getStartingUnits());
|
||||
}
|
||||
}
|
||||
).map(
|
||||
nextUnits -> {
|
||||
if (checkEmpty(nextUnits)) {
|
||||
return storyLine.getGlobalUnits();
|
||||
} else {
|
||||
nextUnits.addAll(storyLine.getGlobalUnits());
|
||||
return nextUnits;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Void> save(String personId, String unitName, Mail mail) {
|
||||
isNotNull(personId, unitName, mail);
|
||||
return unitPointerService.save(new UnitPointer(personId, unitName))
|
||||
.onItem().transformToUni(u -> {
|
||||
final StorylineHistory storylineHistory = new StorylineHistory();
|
||||
storylineHistory.setPersonId(personId);
|
||||
storylineHistory.setUnitName(unitName);
|
||||
storylineHistory.setMessage(mail);
|
||||
return storylineRepository.save(storylineHistory);
|
||||
}).replaceWithVoid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<StorylineHistory> replaceUserToBack(String personId, int countUnitsToBack) {
|
||||
return storylineRepository.findByCountLast(personId, countUnitsToBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<StorylineHistory> replaceUserToBack(String personId, String unitName) {
|
||||
return storylineRepository.findByCountLast(personId, unitName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MainUnit<Mail>> getDefaultUnit() {
|
||||
if (defaultUnitName == null) return Optional.empty();
|
||||
return storyLine.getUnit(defaultUnitName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultUnit(String defaultUnit) {
|
||||
defaultUnitName = defaultUnit;
|
||||
}
|
||||
|
||||
//TODO [22.06.2022]: Временное решение для ленивой инициализации
|
||||
@Override
|
||||
public void lazyLink(String firstName, String secondName) {
|
||||
storyLine.link(firstName, secondName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MainUnit<Mail>> getUnitByName(String unitName) {
|
||||
return storyLine.getUnit(unitName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package dev.struchkov.godfather.quarkus.core.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.StorylineHistory;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public interface StorylineService<M extends Message> {
|
||||
|
||||
Uni<Void> save(@NotNull StorylineHistory storylineHistory);
|
||||
|
||||
Uni<MainUnit<M>> getUnitNameByPersonId(@NotNull String personId);
|
||||
|
||||
Uni<Set<MainUnit<M>>> getNextUnitByPersonId(@NotNull String personId);
|
||||
|
||||
Uni<Void> save(String personId, String name, M message);
|
||||
|
||||
Uni<StorylineHistory> replaceUserToBack(String personId, int countUnitsToBack);
|
||||
|
||||
Uni<StorylineHistory> replaceUserToBack(String personId, String unitName);
|
||||
|
||||
Optional<MainUnit<M>> getDefaultUnit();
|
||||
|
||||
/**
|
||||
* Ленивая (поздняя) связка юнитов между собой. Осуществляется уже после создания сценария. С помощью данного подхода можно реализовать циклические зависимости юнитов.
|
||||
*/
|
||||
void lazyLink(String firstName, String secondName);
|
||||
|
||||
Optional<MainUnit<M>> getUnitByName(String unitName);
|
||||
|
||||
void setDefaultUnit(String unitName);
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package dev.struchkov.godfather.quarkus.core.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.UnitPointer;
|
||||
import dev.struchkov.godfather.quarkus.context.service.UnitPointerService;
|
||||
import dev.struchkov.godfather.quarkus.data.repository.UnitPointerRepository;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UnitPointerServiceImpl implements UnitPointerService {
|
||||
|
||||
private final UnitPointerRepository unitPointerRepository;
|
||||
|
||||
public UnitPointerServiceImpl(UnitPointerRepository unitPointerRepository) {
|
||||
this.unitPointerRepository = unitPointerRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<UnitPointer> save(@NotNull UnitPointer unitPointer) {
|
||||
return unitPointerRepository.save(unitPointer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<String> getUnitNameByPersonId(@NotNull String personId) {
|
||||
return unitPointerRepository.findUnitNameByPersonId(personId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uni<Void> removeByPersonId(@NotNull String personId) {
|
||||
return unitPointerRepository.removeByPersonId(personId);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,259 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit;
|
||||
|
||||
import dev.struchkov.autoresponder.entity.KeyWord;
|
||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Accessibility;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.func.CheckData;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Обработчик запроса, который реализует конструкцию IF в сценарии.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public class AnswerCheck<M extends Message> extends MainUnit<M> {
|
||||
|
||||
/**
|
||||
* Unit для true.
|
||||
*/
|
||||
private final MainUnit unitTrue;
|
||||
|
||||
/**
|
||||
* Unit для false.
|
||||
*/
|
||||
private final MainUnit unitFalse;
|
||||
|
||||
/**
|
||||
* Временный ответ. Отправляется сразу после проверки условия, если оно true. Предполагается, что после условия следующий Unit может долго обрабатывать какой-то результат. Поэтому можно передать пользователю какое-то сообщение, наподобие: "Подождите идет обработка".
|
||||
*/
|
||||
private final BoxAnswer intermediateAnswerIfTrue;
|
||||
|
||||
/**
|
||||
* Промежуточный ответ. Отправляется сразу после проверки условия, если оно false. Предполагается, что после условия следующий Unit может долго обрабатывать какой-то результат. Поэтому можно передать пользователю какое-то сообщение, наподобие: "Подождите идет обработка".
|
||||
*/
|
||||
private final BoxAnswer intermediateAnswerIfFalse;
|
||||
|
||||
/**
|
||||
* Условие проверки.
|
||||
*/
|
||||
private final CheckData<M> check;
|
||||
|
||||
private AnswerCheck(Builder<M> builder) {
|
||||
super(
|
||||
builder.name,
|
||||
builder.description,
|
||||
builder.triggerWords,
|
||||
builder.triggerPhrases,
|
||||
builder.triggerCheck,
|
||||
builder.triggerPatterns,
|
||||
builder.matchThreshold,
|
||||
builder.priority,
|
||||
new HashSet<>(),
|
||||
builder.activeType,
|
||||
builder.notSaveHistory,
|
||||
builder.accessibility,
|
||||
TypeUnit.CHECK
|
||||
);
|
||||
unitTrue = builder.unitTrue;
|
||||
unitFalse = builder.unitFalse;
|
||||
check = builder.check;
|
||||
intermediateAnswerIfTrue = builder.intermediateAnswerIfTrue;
|
||||
intermediateAnswerIfFalse = builder.intermediateAnswerIfFalse;
|
||||
}
|
||||
|
||||
public static <M extends Message> Builder<M> builder() {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
public MainUnit getUnitTrue() {
|
||||
return unitTrue;
|
||||
}
|
||||
|
||||
public MainUnit getUnitFalse() {
|
||||
return unitFalse;
|
||||
}
|
||||
|
||||
public CheckData<M> getCheck() {
|
||||
return check;
|
||||
}
|
||||
|
||||
public BoxAnswer getIntermediateAnswerIfTrue() {
|
||||
return intermediateAnswerIfTrue;
|
||||
}
|
||||
|
||||
public BoxAnswer getIntermediateAnswerIfFalse() {
|
||||
return intermediateAnswerIfFalse;
|
||||
}
|
||||
|
||||
public static final class Builder<M extends Message> {
|
||||
private String name = UUID.randomUUID().toString();
|
||||
private String description;
|
||||
|
||||
private Set<KeyWord> triggerWords;
|
||||
private Set<String> triggerPhrases;
|
||||
private Predicate<M> triggerCheck;
|
||||
private Set<Pattern> triggerPatterns;
|
||||
private Integer matchThreshold;
|
||||
|
||||
private Integer priority;
|
||||
private UnitActiveType activeType;
|
||||
|
||||
private Accessibility accessibility;
|
||||
private boolean notSaveHistory;
|
||||
|
||||
private MainUnit unitTrue;
|
||||
private MainUnit unitFalse;
|
||||
private CheckData<M> check;
|
||||
private BoxAnswer intermediateAnswerIfFalse;
|
||||
private BoxAnswer intermediateAnswerIfTrue;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder<M> name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWords(Set<KeyWord> val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(KeyWord val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerStringWords(Set<String> val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(String val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(KeyWord.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPhrase(String... val) {
|
||||
if (triggerPhrases == null) {
|
||||
triggerPhrases = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPhrases.add(val[0]);
|
||||
} else {
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
}
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPattern(Pattern... val) {
|
||||
if (triggerPatterns == null) {
|
||||
triggerPatterns = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPatterns.add(val[0]);
|
||||
} else {
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
}
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerCheck(Predicate<M> trigger) {
|
||||
triggerCheck = trigger;
|
||||
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> unitTrue(MainUnit unitTrue) {
|
||||
this.unitTrue = unitTrue;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> unitFalse(MainUnit unitFalse) {
|
||||
this.unitFalse = unitFalse;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> check(CheckData<M> check) {
|
||||
this.check = check;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> accessibility(Accessibility val) {
|
||||
accessibility = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> activeType(UnitActiveType val) {
|
||||
activeType = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> notSaveHistory() {
|
||||
notSaveHistory = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> intermediateAnswer(BoxAnswer val) {
|
||||
intermediateAnswerIfTrue = val;
|
||||
intermediateAnswerIfFalse = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> intermediateAnswerIfTrue(BoxAnswer val) {
|
||||
intermediateAnswerIfTrue = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> intermediateAnswerIfFalse(BoxAnswer val) {
|
||||
intermediateAnswerIfFalse = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnswerCheck<M> build() {
|
||||
// isNotNull(check, unitConfigException("Необходимо установить параметр проверки."));
|
||||
// isAnyNotNull(unitConfigException("Необходимо задать хотя бы один unit результата проверки."));
|
||||
return new AnswerCheck<>(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,284 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit;
|
||||
|
||||
import dev.struchkov.autoresponder.entity.KeyWord;
|
||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Accessibility;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Pusher;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.func.CheckSave;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.func.PreservableData;
|
||||
import dev.struchkov.godfather.quarkus.data.preser.AnswerSavePreservable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNull;
|
||||
|
||||
/**
|
||||
* Обработчик для сохранения ответов пользователя. Так же допускается скрытое сохранение.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public class AnswerSave<M extends Message, D> extends MainUnit<M> {
|
||||
|
||||
/**
|
||||
* Объект отвечающий за сохранение - репозиторий.
|
||||
*/
|
||||
private final AnswerSavePreservable<D> preservable;
|
||||
|
||||
/**
|
||||
* Ключ для данных.
|
||||
*/
|
||||
private final String key;
|
||||
|
||||
/**
|
||||
* Отправка результатов.
|
||||
*/
|
||||
private final Pusher<D> pusher;
|
||||
|
||||
/**
|
||||
* Данные для скрытого сохранения.
|
||||
*/
|
||||
private final PreservableData<D, M> preservableData;
|
||||
|
||||
/**
|
||||
* Скрытое сохранение.
|
||||
*/
|
||||
private final boolean hidden;
|
||||
|
||||
private final CheckSave<M> checkSave;
|
||||
|
||||
private AnswerSave(Builder<M, D> builder) {
|
||||
super(
|
||||
builder.name,
|
||||
builder.description,
|
||||
builder.triggerWords,
|
||||
builder.triggerPhrases,
|
||||
builder.triggerCheck,
|
||||
builder.triggerPatterns,
|
||||
builder.matchThreshold,
|
||||
builder.priority,
|
||||
builder.nextUnits,
|
||||
(builder.hidden) ? UnitActiveType.AFTER : UnitActiveType.DEFAULT,
|
||||
builder.notSaveHistory,
|
||||
builder.accessibility,
|
||||
TypeUnit.SAVE
|
||||
);
|
||||
maintenanceNextUnit(nextUnits);
|
||||
preservable = builder.preservable;
|
||||
key = builder.key;
|
||||
pusher = builder.pusher;
|
||||
preservableData = builder.preservableData;
|
||||
hidden = builder.hidden;
|
||||
checkSave = builder.checkSave;
|
||||
}
|
||||
|
||||
public static <M extends Message, D> Builder<M, D> builder() {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
private void maintenanceNextUnit(Collection<MainUnit<M>> units) {
|
||||
if (units != null) {
|
||||
units.forEach(mainUnit -> mainUnit.setActiveType(UnitActiveType.AFTER));
|
||||
}
|
||||
}
|
||||
|
||||
public AnswerSavePreservable<D> getPreservable() {
|
||||
return preservable;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public Pusher<D> getPusher() {
|
||||
return pusher;
|
||||
}
|
||||
|
||||
public PreservableData<D, M> getPreservableData() {
|
||||
return preservableData;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
public CheckSave<M> getCheckSave() {
|
||||
return checkSave;
|
||||
}
|
||||
|
||||
public static final class Builder<M extends Message, D> {
|
||||
private String name = UUID.randomUUID().toString();
|
||||
private String description;
|
||||
private Set<MainUnit<M>> nextUnits;
|
||||
|
||||
private Set<KeyWord> triggerWords;
|
||||
private Set<String> triggerPhrases;
|
||||
private Set<Pattern> triggerPatterns;
|
||||
private Predicate<M> triggerCheck;
|
||||
|
||||
private Integer matchThreshold;
|
||||
private Integer priority;
|
||||
|
||||
private Accessibility accessibility;
|
||||
private boolean notSaveHistory;
|
||||
|
||||
private AnswerSavePreservable<D> preservable;
|
||||
private String key;
|
||||
private Pusher<D> pusher;
|
||||
private PreservableData<D, M> preservableData;
|
||||
private boolean hidden;
|
||||
private CheckSave<M> checkSave;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder<M, D> name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> triggerWords(Set<KeyWord> val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> triggerWord(KeyWord val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> triggerStringWords(Set<String> val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> triggerWord(String val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(KeyWord.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> triggerPhrase(String... val) {
|
||||
if (checkNull(triggerPhrases)) {
|
||||
triggerPhrases = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPhrases.add(val[0]);
|
||||
} else {
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
}
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> triggerPattern(Pattern... val) {
|
||||
if (checkNull(triggerPatterns)) {
|
||||
triggerPatterns = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPatterns.add(val[0]);
|
||||
} else {
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
}
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> triggerCheck(Predicate<M> trigger) {
|
||||
triggerCheck = trigger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> matchThreshold(Integer val) {
|
||||
matchThreshold = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> priority(Integer val) {
|
||||
priority = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> next(MainUnit<M> val) {
|
||||
if (checkNull(nextUnits)) {
|
||||
nextUnits = new HashSet<>();
|
||||
}
|
||||
nextUnits.add(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> preservable(AnswerSavePreservable<D> val) {
|
||||
this.preservable = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> key(String val) {
|
||||
this.key = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> pusher(Pusher<D> val) {
|
||||
this.pusher = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> preservableData(PreservableData<D, M> val) {
|
||||
this.preservableData = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> hidden(boolean val) {
|
||||
this.hidden = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> checkSave(CheckSave<M> val) {
|
||||
this.checkSave = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> accessibility(Accessibility val) {
|
||||
accessibility = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M, D> notSaveHistory() {
|
||||
notSaveHistory = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnswerSave<M, D> build() {
|
||||
// isNotNull(preservable, "Не указан репозиторий для сохранения формы пользователя");
|
||||
// if (checkNull(pusher)) {
|
||||
// isNotNull(preservableData, "Не указаны данные для сохранения");
|
||||
// Inspector.isNotNull(key, "Не указан ключ для сохранения");
|
||||
// }
|
||||
return new AnswerSave<>(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,261 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit;
|
||||
|
||||
import dev.struchkov.autoresponder.entity.KeyWord;
|
||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Accessibility;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Sending;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.func.Insert;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.func.ProcessingData;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Используется для отправки ответа пользователю.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public class AnswerText<M extends Message> extends MainUnit<M> {
|
||||
|
||||
/**
|
||||
* Объект, который необходимо отправить пользователю.
|
||||
*/
|
||||
private final ProcessingData<M> answer;
|
||||
|
||||
/**
|
||||
* Информация, которую необходимо вставить вместо маркеров в строку ответа.
|
||||
*/
|
||||
private final Insert insert;
|
||||
|
||||
/**
|
||||
* Объект нестандартной отправки ответа.
|
||||
*/
|
||||
private final Sending sender;
|
||||
|
||||
private AnswerText(Builder<M> builder) {
|
||||
super(
|
||||
builder.name,
|
||||
builder.description,
|
||||
builder.triggerWords,
|
||||
builder.triggerPhrases,
|
||||
builder.triggerCheck,
|
||||
builder.triggerPatterns,
|
||||
builder.matchThreshold,
|
||||
builder.priority,
|
||||
builder.nextUnits,
|
||||
builder.activeType,
|
||||
builder.notSaveHistory,
|
||||
builder.accessibility,
|
||||
TypeUnit.TEXT
|
||||
);
|
||||
answer = builder.boxAnswer;
|
||||
insert = builder.insert;
|
||||
sender = builder.sending;
|
||||
}
|
||||
|
||||
public static <M extends Message> AnswerText<M> of(String message) {
|
||||
return AnswerText.<M>builder().answer(BoxAnswer.boxAnswer(message)).build();
|
||||
}
|
||||
|
||||
public static <M extends Message> AnswerText<M> of(BoxAnswer boxAnswer) {
|
||||
return AnswerText.<M>builder().answer(boxAnswer).build();
|
||||
}
|
||||
|
||||
public static <M extends Message> Builder<M> builder() {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
public ProcessingData<M> getAnswer() {
|
||||
return answer;
|
||||
}
|
||||
|
||||
public Insert getInsert() {
|
||||
return insert;
|
||||
}
|
||||
|
||||
public Sending getSending() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public static final class Builder<M extends Message> {
|
||||
private String name = UUID.randomUUID().toString();
|
||||
private String description;
|
||||
private Set<MainUnit<M>> nextUnits;
|
||||
|
||||
private Set<KeyWord> triggerWords;
|
||||
private Set<String> triggerPhrases;
|
||||
private Predicate<M> triggerCheck;
|
||||
private Set<Pattern> triggerPatterns;
|
||||
|
||||
private Integer matchThreshold;
|
||||
private Integer priority;
|
||||
|
||||
private UnitActiveType activeType;
|
||||
private Accessibility accessibility;
|
||||
private boolean notSaveHistory;
|
||||
|
||||
private ProcessingData<M> boxAnswer;
|
||||
private Insert insert;
|
||||
private Sending sending;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder<M> name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> processing(Consumer<M> answer) {
|
||||
this.boxAnswer = message -> {
|
||||
answer.accept(message);
|
||||
return null;
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> answer(Function<M, Uni<BoxAnswer>> answer) {
|
||||
this.boxAnswer = answer::apply;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> answer(BoxAnswer answer) {
|
||||
this.boxAnswer = message -> Uni.createFrom().item(answer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> answer(Supplier<BoxAnswer> answer) {
|
||||
this.boxAnswer = message -> Uni.createFrom().item(answer.get());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> insert(Insert insert) {
|
||||
this.insert = insert;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> sending(Sending sending) {
|
||||
this.sending = sending;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWords(Set<KeyWord> val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(KeyWord val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerStringWords(Set<String> val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(String val) {
|
||||
if (triggerWords == null) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(KeyWord.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPhrase(String... val) {
|
||||
if (triggerPhrases == null) {
|
||||
triggerPhrases = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPhrases.add(val[0]);
|
||||
} else {
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
}
|
||||
triggerPhrases.addAll(List.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPattern(Pattern... val) {
|
||||
if (triggerPatterns == null) {
|
||||
triggerPatterns = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPatterns.add(val[0]);
|
||||
} else {
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
}
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerCheck(Predicate<M> trigger) {
|
||||
triggerCheck = trigger;
|
||||
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> next(MainUnit<M> val) {
|
||||
if (nextUnits == null) {
|
||||
nextUnits = new HashSet<>();
|
||||
}
|
||||
nextUnits.add(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> accessibility(Accessibility val) {
|
||||
accessibility = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> notSaveHistory() {
|
||||
notSaveHistory = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> activeType(UnitActiveType val) {
|
||||
activeType = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnswerText<M> build() {
|
||||
// isNotNull(boxAnswer, UnitConfigException.unitConfigException("BoxAnswer обязательный параметр юнита"));
|
||||
return new AnswerText<>(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit;
|
||||
|
||||
import dev.struchkov.autoresponder.entity.KeyWord;
|
||||
import dev.struchkov.autoresponder.entity.Unit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.context.service.Accessibility;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Главный обработчик {@link Unit}, от него наследуются все остальные Unit-ы.
|
||||
*
|
||||
* @author upagge [08/07/2019]
|
||||
*/
|
||||
public abstract class MainUnit<M extends Message> extends Unit<MainUnit<M>, M> {
|
||||
|
||||
/**
|
||||
* Уникальное имя юнита
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Описание юнита, что он делает. Никак не влияет на работу юнита и не участвует в ней. Возможно отображение этого текста в логах.
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Тип Unit-а.
|
||||
*/
|
||||
protected final String type;
|
||||
|
||||
/**
|
||||
* Режим срабатывания Unit-а.
|
||||
*/
|
||||
protected UnitActiveType activeType;
|
||||
|
||||
/**
|
||||
* Проверка доступа пользователя к юниту.
|
||||
*/
|
||||
private final Accessibility accessibility;
|
||||
|
||||
private final boolean notSaveHistory;
|
||||
|
||||
protected MainUnit(
|
||||
String name,
|
||||
String description,
|
||||
Set<KeyWord> keyWords,
|
||||
Set<String> phrases,
|
||||
Predicate<M> triggerCheck,
|
||||
Set<Pattern> patterns,
|
||||
Integer matchThreshold,
|
||||
Integer priority,
|
||||
Set<MainUnit<M>> nextUnits,
|
||||
UnitActiveType activeType,
|
||||
boolean notSaveHistory,
|
||||
Accessibility accessibility,
|
||||
String type
|
||||
) {
|
||||
super(keyWords, phrases, triggerCheck, patterns, matchThreshold, priority, nextUnits);
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.activeType = Optional.ofNullable(activeType).orElse(UnitActiveType.DEFAULT);
|
||||
this.accessibility = accessibility;
|
||||
this.type = type;
|
||||
this.notSaveHistory = notSaveHistory;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public UnitActiveType getActiveType() {
|
||||
return activeType;
|
||||
}
|
||||
|
||||
public void setActiveType(UnitActiveType activeType) {
|
||||
this.activeType = activeType;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isNotSaveHistory() {
|
||||
return notSaveHistory;
|
||||
}
|
||||
|
||||
public Optional<Accessibility> getAccessibility() {
|
||||
return Optional.ofNullable(accessibility);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MainUnit<?> unit = (MainUnit<?>) o;
|
||||
return name.equals(unit.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
|
||||
/**
|
||||
* Сущность инкапсулирует в себе данные, необходимые для обработки сценария.
|
||||
*
|
||||
* @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>, 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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit.cmd;
|
||||
|
||||
import dev.struchkov.autoresponder.entity.KeyWord;
|
||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import dev.struchkov.haiti.utils.Checker;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ReplaceCmd<M extends Message> extends MainUnit<M> {
|
||||
|
||||
private final MainUnit thisUnit;
|
||||
|
||||
private ReplaceCmd(Builder<M> builder) {
|
||||
super(
|
||||
builder.name,
|
||||
builder.description,
|
||||
builder.triggerWords,
|
||||
builder.triggerPhrases,
|
||||
builder.triggerCheck,
|
||||
builder.triggerPatterns,
|
||||
builder.matchThreshold,
|
||||
builder.priority,
|
||||
new HashSet<>(),
|
||||
builder.activeType,
|
||||
true,
|
||||
null,
|
||||
TypeUnit.REPLACE_CMD
|
||||
);
|
||||
this.thisUnit = builder.thisUnit;
|
||||
}
|
||||
|
||||
public static <M extends Message> Builder<M> builder() {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
public MainUnit getThisUnit() {
|
||||
return thisUnit;
|
||||
}
|
||||
|
||||
public static final class Builder<M extends Message> {
|
||||
private String name = UUID.randomUUID().toString();
|
||||
private String description;
|
||||
|
||||
private Set<String> triggerPhrases;
|
||||
private Predicate<M> triggerCheck;
|
||||
private Set<Pattern> triggerPatterns;
|
||||
private Set<KeyWord> triggerWords;
|
||||
private Integer matchThreshold;
|
||||
|
||||
private Integer priority;
|
||||
private UnitActiveType activeType = UnitActiveType.AFTER;
|
||||
|
||||
private MainUnit thisUnit;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder<M> name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWords(Set<KeyWord> val) {
|
||||
if (Checker.checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(KeyWord val) {
|
||||
if (Checker.checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerStringWords(Set<String> val) {
|
||||
if (Checker.checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(String val) {
|
||||
if (Checker.checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(KeyWord.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPhrase(String... val) {
|
||||
if (Checker.checkNull(triggerPhrases)) {
|
||||
triggerPhrases = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPhrases.add(val[0]);
|
||||
} else {
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPattern(Pattern... val) {
|
||||
if (Checker.checkNull(triggerPatterns)) {
|
||||
triggerPatterns = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPatterns.add(val[0]);
|
||||
} else {
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
}
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerCheck(Predicate<M> trigger) {
|
||||
triggerCheck = trigger;
|
||||
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> activeType(UnitActiveType val) {
|
||||
activeType = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> thisUnit(MainUnit val) {
|
||||
thisUnit = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplaceCmd<M> build() {
|
||||
return new ReplaceCmd<>(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit.cmd;
|
||||
|
||||
import dev.struchkov.autoresponder.entity.KeyWord;
|
||||
import dev.struchkov.godfather.exception.UnitConfigException;
|
||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNull;
|
||||
|
||||
/**
|
||||
* Юнит, который позволяет откатить пользователя на предыдущие юниты в сценарии с сохранением ранее введенной информации в сообщениях.
|
||||
*/
|
||||
public class RollBackCmd<M extends Message> extends MainUnit<M> {
|
||||
|
||||
/**
|
||||
* Количество юнитов, на которые можно откатиться назад.
|
||||
*/
|
||||
private final int countBack;
|
||||
|
||||
/**
|
||||
* Имя юнита, на который нужно вернуть пользователя.
|
||||
*/
|
||||
private final String rollbackUnitName;
|
||||
|
||||
private RollBackCmd(Builder<M> builder) {
|
||||
super(
|
||||
builder.name,
|
||||
builder.description,
|
||||
builder.triggerWords,
|
||||
builder.triggerPhrases,
|
||||
builder.triggerCheck,
|
||||
builder.triggerPatterns,
|
||||
builder.matchThreshold,
|
||||
builder.priority,
|
||||
new HashSet<>(),
|
||||
builder.activeType,
|
||||
true,
|
||||
null,
|
||||
TypeUnit.BACK_CMD
|
||||
);
|
||||
this.countBack = builder.countBack;
|
||||
this.rollbackUnitName = builder.rollbackUnitName;
|
||||
}
|
||||
|
||||
public static <M extends Message> Builder<M> builder() {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
public static <M extends Message> RollBackCmd<M> rollBack(int countToBack) {
|
||||
return RollBackCmd.<M>builder().countBack(countToBack).build();
|
||||
}
|
||||
|
||||
public static <M extends Message> RollBackCmd<M> singleRollBack() {
|
||||
return RollBackCmd.<M>builder().countBack(1).build();
|
||||
}
|
||||
|
||||
public static <M extends Message> RollBackCmd<M> doubleRollBack() {
|
||||
return RollBackCmd.<M>builder().countBack(2).build();
|
||||
}
|
||||
|
||||
public static <M extends Message> RollBackCmd<M> rollBack(String unitName) {
|
||||
return RollBackCmd.<M>builder().rollbackUnitName(unitName).build();
|
||||
}
|
||||
|
||||
public static <M extends Message> RollBackCmd<M> rollBack(String phrase, String unitName) {
|
||||
return RollBackCmd.<M>builder().triggerPhrase(phrase).rollbackUnitName(unitName).build();
|
||||
}
|
||||
|
||||
public int getCountBack() {
|
||||
return countBack;
|
||||
}
|
||||
|
||||
public String getRollbackUnitName() {
|
||||
return rollbackUnitName;
|
||||
}
|
||||
|
||||
public static final class Builder<M extends Message> {
|
||||
private String name = UUID.randomUUID().toString();
|
||||
private String description;
|
||||
|
||||
private Set<String> triggerPhrases;
|
||||
private Predicate<M> triggerCheck;
|
||||
private Set<Pattern> triggerPatterns;
|
||||
private Set<KeyWord> triggerWords;
|
||||
private Integer matchThreshold;
|
||||
|
||||
private Integer priority;
|
||||
private UnitActiveType activeType = UnitActiveType.DEFAULT;
|
||||
|
||||
private int countBack;
|
||||
private String rollbackUnitName;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder<M> name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> description(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWords(Set<KeyWord> val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(KeyWord val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerStringWords(Set<String> val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.addAll(val.stream().map(KeyWord::of).collect(Collectors.toSet()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerWord(String val) {
|
||||
if (checkNull(triggerWords)) {
|
||||
triggerWords = new HashSet<>();
|
||||
}
|
||||
triggerWords.add(KeyWord.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPhrase(String... val) {
|
||||
if (checkNull(triggerPhrases)) {
|
||||
triggerPhrases = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPhrases.add(val[0]);
|
||||
} else {
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
}
|
||||
triggerPhrases.addAll(Set.of(val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerCheck(Predicate<M> trigger) {
|
||||
triggerCheck = trigger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> triggerPattern(Pattern... val) {
|
||||
if (checkNull(triggerPatterns)) {
|
||||
triggerPatterns = new HashSet<>();
|
||||
}
|
||||
if (val.length == 1) {
|
||||
triggerPatterns.add(val[0]);
|
||||
} else {
|
||||
triggerPatterns.addAll(Set.of(val));
|
||||
}
|
||||
triggerPatterns.addAll(Set.of(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> activeType(UnitActiveType val) {
|
||||
activeType = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> countBack(int val) {
|
||||
countBack = val + 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<M> rollbackUnitName(String val) {
|
||||
rollbackUnitName = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RollBackCmd<M> build() {
|
||||
if (rollbackUnitName == null && countBack < 2) {
|
||||
throw new UnitConfigException("Ошибка конфигурирования юнита {0}: Количество юнитов для отката не должно быть меньше 1.", name);
|
||||
}
|
||||
return new RollBackCmd<M>(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit.func;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CheckData<C extends Message> {
|
||||
|
||||
Uni<Boolean> checked(C content);
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit.func;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.quarkus.core.unit.MainUnit;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
/**
|
||||
* TODO: Добавить описание интерфейса.
|
||||
*
|
||||
* @author upagge [04/08/2019]
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface CheckSave<M extends Message> {
|
||||
|
||||
Uni<MainUnit<M>> check(M content);
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit.func;
|
||||
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Insert {
|
||||
|
||||
Uni<List<String>> insert(String personId);
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit.func;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PreservableData<D, M extends Message> {
|
||||
|
||||
Uni<D> getData(M content);
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package dev.struchkov.godfather.quarkus.core.unit.func;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ProcessingData<C> {
|
||||
|
||||
Uni<BoxAnswer> processing(C content);
|
||||
|
||||
}
|
33
bot-core/bot-core-simple/pom.xml
Normal file
33
bot-core/bot-core-simple/pom.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>bot-core</artifactId>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<version>0.0.42-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>bot-core-simple</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-core-main</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-context-simple</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.struchkov.godfather</groupId>
|
||||
<artifactId>bot-data-simple</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,167 @@
|
||||
package dev.struchkov.godfather.simple.core;
|
||||
|
||||
import dev.struchkov.autoresponder.Responder;
|
||||
import dev.struchkov.godfather.exception.ConfigAppException;
|
||||
import dev.struchkov.godfather.main.core.unit.TypeUnit;
|
||||
import dev.struchkov.godfather.main.core.unit.UnitActiveType;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.context.service.Accessibility;
|
||||
import dev.struchkov.godfather.simple.context.service.ErrorHandler;
|
||||
import dev.struchkov.godfather.simple.context.service.Modifiable;
|
||||
import dev.struchkov.godfather.simple.context.service.PersonSettingService;
|
||||
import dev.struchkov.godfather.simple.context.service.Sending;
|
||||
import dev.struchkov.godfather.simple.core.action.ActionUnit;
|
||||
import dev.struchkov.godfather.simple.core.action.AnswerCheckAction;
|
||||
import dev.struchkov.godfather.simple.core.action.AnswerSaveAction;
|
||||
import dev.struchkov.godfather.simple.core.action.AnswerTextAction;
|
||||
import dev.struchkov.godfather.simple.core.action.cmd.ReplaceCmdAction;
|
||||
import dev.struchkov.godfather.simple.core.service.StorylineService;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.UnitRequest;
|
||||
import dev.struchkov.haiti.context.exception.NotFoundException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GeneralAutoResponder<M extends Message> {
|
||||
|
||||
private final PersonSettingService personSettingService;
|
||||
private final StorylineService<M> storyLineService;
|
||||
protected Map<String, ActionUnit> actionUnitMap = new HashMap<>();
|
||||
protected List<Modifiable<M>> modifiable;
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
protected GeneralAutoResponder(
|
||||
Sending sending,
|
||||
PersonSettingService personSettingService,
|
||||
StorylineService<M> storyLineService
|
||||
) {
|
||||
this.personSettingService = personSettingService;
|
||||
this.storyLineService = storyLineService;
|
||||
init(sending);
|
||||
}
|
||||
|
||||
private void init(Sending sending) {
|
||||
actionUnitMap.put(TypeUnit.CHECK, new AnswerCheckAction<>(sending));
|
||||
actionUnitMap.put(TypeUnit.TEXT, new AnswerTextAction(sending));
|
||||
actionUnitMap.put(TypeUnit.REPLACE_CMD, new ReplaceCmdAction());
|
||||
}
|
||||
|
||||
public void initModifiable(List<Modifiable<M>> modifiable) {
|
||||
this.modifiable = modifiable;
|
||||
}
|
||||
|
||||
public void initActionUnit(String typeUnit, ActionUnit<? extends MainUnit<M>, M> actionUnit) {
|
||||
if (!actionUnitMap.containsKey(typeUnit)) {
|
||||
actionUnitMap.put(typeUnit, actionUnit);
|
||||
} else {
|
||||
throw new ConfigAppException("Обработка такого типа юнита уже зарегистрирована");
|
||||
}
|
||||
}
|
||||
|
||||
public void initSaveAction(AnswerSaveAction<M, ?> answerSaveAction) {
|
||||
actionUnitMap.put(TypeUnit.SAVE, answerSaveAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Позволяет установить перехватчик и обработчик исключений, возникающих при обработке юнитов.
|
||||
*/
|
||||
public void setErrorHandler(ErrorHandler errorHandler) {
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public void setDefaultUnit(String unitName) {
|
||||
storyLineService.setDefaultUnit(unitName);
|
||||
}
|
||||
|
||||
public void processingNewMessage(M newMessage) {
|
||||
if (newMessage != null) {
|
||||
final boolean state = personSettingService.getStateProcessingByPersonId(newMessage.getPersonId()).orElse(true);
|
||||
if (state) {
|
||||
processing(newMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void processingNewMessages(List<M> newMessages) {
|
||||
if (newMessages != null && !newMessages.isEmpty()) {
|
||||
final Set<String> personIds = newMessages.stream()
|
||||
.map(Message::getPersonId)
|
||||
.collect(Collectors.toSet());
|
||||
final Set<String> disableIds = personSettingService.getAllPersonIdDisableMessages(personIds);
|
||||
final List<M> allowedMessages = newMessages.stream()
|
||||
.filter(message -> !disableIds.contains(message.getPersonId()))
|
||||
.toList();
|
||||
allowedMessages.parallelStream().forEach(this::processing);
|
||||
}
|
||||
}
|
||||
|
||||
private void processing(M message) {
|
||||
if (modifiable != null) {
|
||||
modifiable.forEach(m -> m.change(message));
|
||||
}
|
||||
final Set<MainUnit<M>> units = storyLineService.getNextUnitByPersonId(message.getPersonId());
|
||||
final Optional<MainUnit<M>> optAnswer = Responder.nextUnit(message, units)
|
||||
.or(storyLineService::getDefaultUnit);
|
||||
if (optAnswer.isPresent()) {
|
||||
final MainUnit<M> answer = optAnswer.get();
|
||||
if (checkPermission(answer.getAccessibility(), message)) {
|
||||
answer(UnitRequest.of(answer, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkPermission(Optional<Accessibility> accessibility, M message) {
|
||||
return accessibility.isEmpty() || accessibility.get().check(message);
|
||||
}
|
||||
|
||||
public void answer(UnitRequest<MainUnit<M>, M> unitRequest) {
|
||||
try {
|
||||
unitRequest = getAction(unitRequest);
|
||||
activeUnitAfter(unitRequest);
|
||||
} catch (Exception e) {
|
||||
if (errorHandler != null) {
|
||||
errorHandler.handle(unitRequest.getMessage(), e);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private UnitRequest<MainUnit<M>, M> activeUnitAfter(UnitRequest<MainUnit<M>, M> unitRequest) {
|
||||
final Set<MainUnit<M>> nextUnits = unitRequest.getUnit().getNextUnits();
|
||||
if (nextUnits != null) {
|
||||
Optional<MainUnit<M>> first = nextUnits.stream()
|
||||
.filter(unit -> UnitActiveType.AFTER.equals(unit.getActiveType()))
|
||||
.findFirst();
|
||||
if (first.isPresent()) {
|
||||
getAction(UnitRequest.of(first.get(), unitRequest.getMessage()));
|
||||
return activeUnitAfter(UnitRequest.of(first.get(), unitRequest.getMessage()));
|
||||
}
|
||||
}
|
||||
return unitRequest;
|
||||
}
|
||||
|
||||
private UnitRequest<MainUnit<M>, M> getAction(UnitRequest<MainUnit<M>, M> unitRequest) {
|
||||
final MainUnit<M> unit = unitRequest.getUnit();
|
||||
final M message = unitRequest.getMessage();
|
||||
final String typeUnit = unit.getType();
|
||||
if (actionUnitMap.containsKey(typeUnit)) {
|
||||
ActionUnit actionUnit = actionUnitMap.get(typeUnit);
|
||||
UnitRequest<MainUnit<M>, M> newUnitRequest = actionUnit.action(unitRequest);
|
||||
final Optional<MainUnit<M>> optDefaultUnit = storyLineService.getDefaultUnit();
|
||||
if (!unit.isNotSaveHistory() && (optDefaultUnit.isEmpty() || !optDefaultUnit.get().equals(unit))) {
|
||||
storyLineService.save(message.getPersonId(), unit.getName(), message);
|
||||
}
|
||||
final MainUnit<M> newUnit = newUnitRequest.getUnit();
|
||||
return !unit.equals(newUnit) ? getAction(newUnitRequest) : unitRequest;
|
||||
} else {
|
||||
throw new NotFoundException("ActionUnit для типа {0} не зарегистрирован", unit.getType());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package dev.struchkov.godfather.simple.core;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.haiti.utils.Inspector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNull;
|
||||
|
||||
public class Storyline<M extends Message> {
|
||||
|
||||
private final Set<MainUnit<M>> startingUnits = new HashSet<>();
|
||||
private final Set<MainUnit<M>> globalUnits = new HashSet<>();
|
||||
private final Map<String, MainUnit<M>> units = new HashMap<>();
|
||||
|
||||
public Storyline(Set<MainUnit<M>> startingUnits, Map<String, MainUnit<M>> units) {
|
||||
this.startingUnits.addAll(startingUnits);
|
||||
this.units.putAll(units);
|
||||
}
|
||||
|
||||
public void addGlobalUnits(Set<MainUnit<M>> globalUnits) {
|
||||
this.globalUnits.addAll(globalUnits);
|
||||
}
|
||||
|
||||
public Set<MainUnit<M>> getGlobalUnits() {
|
||||
return globalUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить юнит по названию.
|
||||
*
|
||||
* @param unitName Название юнита.
|
||||
*/
|
||||
public Optional<MainUnit<M>> getUnit(String unitName) {
|
||||
Inspector.isNotNull(unitName);
|
||||
return Optional.ofNullable(units.get(unitName));
|
||||
}
|
||||
|
||||
public Set<MainUnit<M>> getStartingUnits() {
|
||||
return startingUnits;
|
||||
}
|
||||
|
||||
//TODO [22.06.2022]: Временное решение ленивой связки юнитов, пока не будет реализован нормальный механизм.
|
||||
public void link(@NotNull String firstName, @NotNull String secondName) {
|
||||
Inspector.isNotNull(firstName, secondName);
|
||||
final MainUnit<M> firstUnit = units.get(firstName);
|
||||
final MainUnit<M> secondUnit = units.get(secondName);
|
||||
Inspector.isNotNull(firstUnit, secondUnit);
|
||||
if (checkNull(firstUnit.getNextUnits())) {
|
||||
firstUnit.setNextUnits(new HashSet<>());
|
||||
}
|
||||
firstUnit.getNextUnits().add(secondUnit);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package dev.struchkov.godfather.simple.core;
|
||||
|
||||
import dev.struchkov.godfather.exception.UnitConfigException;
|
||||
import dev.struchkov.godfather.main.domain.UnitDefinition;
|
||||
import dev.struchkov.godfather.main.domain.annotation.Unit;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.haiti.utils.Inspector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.struchkov.godfather.exception.UnitConfigException.unitConfigException;
|
||||
|
||||
public class StorylineFactory<M extends Message> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(StorylineFactory.class);
|
||||
|
||||
private final List<Object> configurations = new ArrayList<>();
|
||||
|
||||
private final Map<String, UnitDefinition> unitDefinitions = new HashMap<>();
|
||||
private final Map<String, MainUnit<M>> unitMap = new HashMap<>();
|
||||
|
||||
private final Set<String> mainUnits = new HashSet<>();
|
||||
private final Set<String> globalUnits = new HashSet<>();
|
||||
|
||||
public StorylineFactory(List<Object> unitConfigurations) {
|
||||
this.configurations.addAll(unitConfigurations);
|
||||
}
|
||||
|
||||
public Map<String, UnitDefinition> getUnitDefinitions() {
|
||||
return unitDefinitions;
|
||||
}
|
||||
|
||||
public Map<String, MainUnit<M>> getUnitMap() {
|
||||
return unitMap;
|
||||
}
|
||||
|
||||
public Storyline<M> createStoryLine() {
|
||||
generateUnitDefinitions();
|
||||
try {
|
||||
createUnitMap();
|
||||
final Set<MainUnit<M>> mainUnit = getMainUnit();
|
||||
final Set<MainUnit<M>> globalUnit = getGlobalUnit();
|
||||
final Storyline<M> storyline = new Storyline<>(mainUnit, unitMap);
|
||||
storyline.addGlobalUnits(globalUnit);
|
||||
return storyline;
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
throw new UnitConfigException("Ошибка построения StoryLine");
|
||||
}
|
||||
|
||||
private Set<MainUnit<M>> getMainUnit() {
|
||||
Inspector.isNotEmpty(mainUnits, unitConfigException("Не задан ни один mainUnit. Установите хотя бы для одного Unit флаг mainUnit"));
|
||||
return mainUnits.stream()
|
||||
.map(unitMap::get)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Set<MainUnit<M>> getGlobalUnit() {
|
||||
return globalUnits.stream()
|
||||
.map(unitMap::get)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void createUnitMap() throws IllegalAccessException, InvocationTargetException {
|
||||
for (UnitDefinition unitDefinition : unitDefinitions.values()) {
|
||||
if (!unitMap.containsKey(unitDefinition.getName())) {
|
||||
final Set<String> nextUnitNames = unitDefinition.getNextUnitNames();
|
||||
if (nextUnitNames.isEmpty() || unitMap.keySet().containsAll(nextUnitNames)) {
|
||||
createUnit(unitDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MainUnit<M> createUnit(UnitDefinition unitDefinition) throws IllegalAccessException, InvocationTargetException {
|
||||
final Object objectConfig = unitDefinition.getObjectConfig();
|
||||
final String currentUnitName = unitDefinition.getName();
|
||||
final Method method = unitDefinition.getMethod();
|
||||
final Object[] nextUnits = Arrays.stream(method.getParameters())
|
||||
.filter(parameter -> parameter.isAnnotationPresent(Unit.class))
|
||||
.map(parameter -> parameter.getAnnotation(Unit.class))
|
||||
.map(Unit::value)
|
||||
.map(unitMap::get)
|
||||
.toArray();
|
||||
MainUnit<M> newUnit = (MainUnit<M>) method.invoke(objectConfig, nextUnits);
|
||||
newUnit.setName(currentUnitName);
|
||||
|
||||
unitMap.put(currentUnitName, newUnit);
|
||||
|
||||
final Set<String> dependentUnitsName = unitDefinition.getDependentUnits();
|
||||
for (String dependentUnitName : dependentUnitsName) {
|
||||
final Set<String> dependentNextUnitNames = unitDefinitions.get(dependentUnitName).getNextUnitNames();
|
||||
if (unitMap.keySet().containsAll(dependentNextUnitNames)) {
|
||||
createUnit(unitDefinitions.get(dependentUnitName));
|
||||
}
|
||||
}
|
||||
|
||||
return newUnit;
|
||||
}
|
||||
|
||||
private void generateUnitDefinitions() {
|
||||
final Map<String, Set<String>> dependentUnits = new HashMap<>();
|
||||
|
||||
for (Object config : configurations) {
|
||||
final Class<?> classUnitConfig = config.getClass();
|
||||
|
||||
for (Method method : classUnitConfig.getDeclaredMethods()) {
|
||||
if (method.isAnnotationPresent(Unit.class)) {
|
||||
final Unit unitConfig = method.getAnnotation(Unit.class);
|
||||
|
||||
final String unitName = unitConfig.value();
|
||||
|
||||
final UnitDefinition unitDefinition = new UnitDefinition();
|
||||
unitDefinition.setName(unitName);
|
||||
unitDefinition.setMethod(method);
|
||||
unitDefinition.setObjectConfig(config);
|
||||
|
||||
if (unitConfig.main()) {
|
||||
mainUnits.add(unitName);
|
||||
}
|
||||
if (unitConfig.global()) {
|
||||
globalUnits.add(unitName);
|
||||
}
|
||||
|
||||
final Parameter[] nextUnits = method.getParameters();
|
||||
if (nextUnits.length > 0) {
|
||||
for (Parameter nextUnit : nextUnits) {
|
||||
if (nextUnit.isAnnotationPresent(Unit.class)) {
|
||||
final Unit nextUnitConfig = nextUnit.getAnnotation(Unit.class);
|
||||
final String nextUnitName = nextUnitConfig.value();
|
||||
unitDefinition.setNextUnitName(nextUnitName);
|
||||
dependentUnits.computeIfAbsent(nextUnitName, k -> new HashSet<>());
|
||||
dependentUnits.get(nextUnitName).add(unitName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unitDefinitions.put(unitDefinition.getName(), unitDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Set<String>> entry : dependentUnits.entrySet()) {
|
||||
final UnitDefinition unitDefinition = unitDefinitions.get(entry.getKey());
|
||||
if (unitDefinition != null) {
|
||||
unitDefinition.setDependentUnits(entry.getValue());
|
||||
} else {
|
||||
throw new UnitConfigException("Ошибка связи юнитов. Проблема с описанием {0} юнита. Возможно вы не указали класс конфигурации для этого юнита.", entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package dev.struchkov.godfather.simple.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.UnitRequest;
|
||||
|
||||
/**
|
||||
* Интерфейс для обработки Unit-ов.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ActionUnit<U extends MainUnit, M extends Message> {
|
||||
|
||||
/**
|
||||
* Метод обработки Unit-а.
|
||||
*
|
||||
* @return Новый Unit, который может нуждаться в обработке
|
||||
*/
|
||||
UnitRequest<MainUnit, M> action(UnitRequest<U, M> unitRequest);
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package dev.struchkov.godfather.simple.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.context.service.Sending;
|
||||
import dev.struchkov.godfather.simple.core.unit.AnswerCheck;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.UnitRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||
|
||||
/**
|
||||
* Обработчик Unit-а {@link AnswerCheck}.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
public class AnswerCheckAction<M extends Message> implements ActionUnit<AnswerCheck<M>, M> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AnswerCheckAction.class);
|
||||
|
||||
private final Sending sending;
|
||||
|
||||
public AnswerCheckAction(Sending sending) {
|
||||
this.sending = sending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnitRequest<MainUnit, M> action(UnitRequest<AnswerCheck<M>, M> unitRequest) {
|
||||
final AnswerCheck<M> unit = unitRequest.getUnit();
|
||||
log.debug("Началась обработка unit: {}.", unit.getName());
|
||||
|
||||
final M message = unitRequest.getMessage();
|
||||
|
||||
MainUnit<M> unitAnswer;
|
||||
if (unit.getCheck().checked(message)) {
|
||||
log.debug("Unit: {}. Проверка пройдена", unit.getName());
|
||||
final BoxAnswer answerIfTrue = unit.getIntermediateAnswerIfTrue();
|
||||
if (checkNotNull(answerIfTrue)) {
|
||||
answerIfTrue.setRecipientIfNull(message.getPersonId());
|
||||
sending.send(answerIfTrue);
|
||||
}
|
||||
unitAnswer = unit.getUnitTrue();
|
||||
} else {
|
||||
log.debug("Unit: {}. Проверка НЕ пройдена", unit.getName());
|
||||
final BoxAnswer answerIfFalse = unit.getIntermediateAnswerIfFalse();
|
||||
if (checkNotNull(answerIfFalse)) {
|
||||
answerIfFalse.setRecipientIfNull(message.getPersonId());
|
||||
sending.send(answerIfFalse);
|
||||
}
|
||||
unitAnswer = unit.getUnitFalse();
|
||||
}
|
||||
log.debug("Завершилась обработка unit: {}.", unit.getName());
|
||||
return UnitRequest.of(Objects.requireNonNullElse(unitAnswer, unit), message);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package dev.struchkov.godfather.simple.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.context.service.Pusher;
|
||||
import dev.struchkov.godfather.simple.core.unit.AnswerSave;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.UnitRequest;
|
||||
import dev.struchkov.godfather.simple.core.unit.func.CheckSave;
|
||||
import dev.struchkov.godfather.simple.core.unit.func.PreservableData;
|
||||
import dev.struchkov.godfather.simple.data.preser.AnswerSavePreservable;
|
||||
|
||||
import static dev.struchkov.haiti.utils.Checker.checkNotNull;
|
||||
|
||||
/**
|
||||
* Обработчик Unit-а {@link AnswerSave}.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
public class AnswerSaveAction<M extends Message, D> implements ActionUnit<AnswerSave<M, D>, M> {
|
||||
|
||||
@Override
|
||||
public UnitRequest<MainUnit, M> action(UnitRequest<AnswerSave<M, D>, M> unitRequest) {
|
||||
final AnswerSave<M, D> answerSave = unitRequest.getUnit();
|
||||
final M message = unitRequest.getMessage();
|
||||
|
||||
final AnswerSavePreservable<D> preservable = answerSave.getPreservable();
|
||||
final String personId = message.getPersonId();
|
||||
|
||||
final CheckSave<M> checkSave = answerSave.getCheckSave();
|
||||
if (checkNotNull(checkSave)) {
|
||||
MainUnit<M> unit = checkSave.check(message);
|
||||
if (checkNotNull(unit)) {
|
||||
return UnitRequest.of(unit, message);
|
||||
}
|
||||
}
|
||||
|
||||
final PreservableData<D, M> preservableData = answerSave.getPreservableData();
|
||||
if (checkNotNull(preservableData)) {
|
||||
D data = preservableData.getData(message);
|
||||
if (checkNotNull(data)) {
|
||||
preservable.save(personId, answerSave.getKey(), data);
|
||||
}
|
||||
}
|
||||
|
||||
final Pusher<D> pusher = answerSave.getPusher();
|
||||
if (checkNotNull(pusher)) {
|
||||
preservable.push(personId, pusher);
|
||||
}
|
||||
return UnitRequest.of(answerSave, message);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package dev.struchkov.godfather.simple.core.action;
|
||||
|
||||
import dev.struchkov.godfather.main.core.utils.InsertWords;
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.context.service.Sending;
|
||||
import dev.struchkov.godfather.simple.core.unit.AnswerText;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.UnitRequest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Обработчик Unit-а {@link AnswerText}.
|
||||
*
|
||||
* @author upagge [11/07/2019]
|
||||
*/
|
||||
public class AnswerTextAction implements ActionUnit<AnswerText<Message>, Message> {
|
||||
|
||||
private final Sending sending;
|
||||
|
||||
public AnswerTextAction(Sending sending) {
|
||||
this.sending = sending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnitRequest<MainUnit, Message> action(UnitRequest<AnswerText<Message>, Message> unitRequest) {
|
||||
final AnswerText<Message> unit = unitRequest.getUnit();
|
||||
final Message message = unitRequest.getMessage();
|
||||
|
||||
final Optional<BoxAnswer> optAnswer = unit.getAnswer().processing(message);
|
||||
if (optAnswer.isPresent()) {
|
||||
final BoxAnswer answer = optAnswer.get();
|
||||
replaceMarkers(unit, message, answer);
|
||||
|
||||
final Sending answerTextSending = unit.getSending();
|
||||
answer.setRecipientIfNull(message.getPersonId());
|
||||
if (answerTextSending != null) {
|
||||
answerTextSending.send(answer);
|
||||
} else {
|
||||
sending.send(answer);
|
||||
}
|
||||
}
|
||||
|
||||
return UnitRequest.of(unit, message);
|
||||
}
|
||||
|
||||
private void replaceMarkers(AnswerText<Message> answerText, Message message, BoxAnswer boxAnswer) {
|
||||
if (answerText.getInsert() != null) {
|
||||
final List<String> words = answerText.getInsert().insert(message.getPersonId());
|
||||
final String newMessage = InsertWords.insert(boxAnswer.getMessage(), words);
|
||||
boxAnswer.setMessage(newMessage);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package dev.struchkov.godfather.simple.core.action.cmd;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.core.action.ActionUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.UnitRequest;
|
||||
import dev.struchkov.godfather.simple.core.unit.cmd.ReplaceCmd;
|
||||
|
||||
public class ReplaceCmdAction implements ActionUnit<ReplaceCmd<Message>, Message> {
|
||||
|
||||
@Override
|
||||
public UnitRequest<MainUnit, Message> action(UnitRequest<ReplaceCmd<Message>, Message> unitRequest) {
|
||||
final ReplaceCmd<Message> unit = unitRequest.getUnit();
|
||||
final Message message = unitRequest.getMessage();
|
||||
return UnitRequest.of(unit.getThisUnit(), message);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package dev.struchkov.godfather.simple.core.action.cmd;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.StorylineHistory;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.core.action.ActionUnit;
|
||||
import dev.struchkov.godfather.simple.core.service.StorylineService;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.core.unit.UnitRequest;
|
||||
import dev.struchkov.godfather.simple.core.unit.cmd.RollBackCmd;
|
||||
|
||||
import static dev.struchkov.godfather.exception.RollBackException.rollBackException;
|
||||
|
||||
public class RollBackCmdAction<M extends Message> implements ActionUnit<RollBackCmd<M>, M> {
|
||||
|
||||
private final StorylineService<M> storyLineService;
|
||||
|
||||
public RollBackCmdAction(StorylineService<M> storyLineService) {
|
||||
this.storyLineService = storyLineService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnitRequest<MainUnit, M> action(UnitRequest<RollBackCmd<M>, M> unitRequest) {
|
||||
final RollBackCmd<M> unit = unitRequest.getUnit();
|
||||
final M message = unitRequest.getMessage();
|
||||
|
||||
final int countToBack = unit.getCountBack();
|
||||
final String rollbackUnitName = unit.getRollbackUnitName();
|
||||
|
||||
StorylineHistory history = rollbackUnitName != null
|
||||
? storyLineService.replaceUserToBack(message.getPersonId(), rollbackUnitName).orElseThrow(rollBackException("Юнит для возвращения не был найден"))
|
||||
: storyLineService.replaceUserToBack(message.getPersonId(), countToBack).orElseThrow(rollBackException("Юнит для возвращения не был найден"));
|
||||
final String unitName = history.getUnitName();
|
||||
final MainUnit<M> nextUnit = storyLineService.getUnitByName(unitName).orElse(unit);
|
||||
final M oldMessage = (M) history.getMessage();
|
||||
return UnitRequest.of(nextUnit, oldMessage);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package dev.struchkov.godfather.simple.core.provider;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||
import dev.struchkov.godfather.simple.context.service.EventHandler;
|
||||
import dev.struchkov.godfather.simple.core.GeneralAutoResponder;
|
||||
|
||||
public class StoryLineHandler implements EventHandler<Mail> {
|
||||
|
||||
private final GeneralAutoResponder<Mail> generalAutoResponder;
|
||||
|
||||
public StoryLineHandler(GeneralAutoResponder<Mail> generalAutoResponder) {
|
||||
this.generalAutoResponder = generalAutoResponder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Mail message) {
|
||||
generalAutoResponder.processingNewMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return Mail.TYPE;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package dev.struchkov.godfather.simple.core.pusher;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.BoxAnswer;
|
||||
import dev.struchkov.godfather.simple.context.service.Pusher;
|
||||
import dev.struchkov.godfather.simple.context.service.Sending;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static dev.struchkov.godfather.main.domain.BoxAnswer.boxAnswer;
|
||||
|
||||
public class UserSanderPusher implements Pusher<String> {
|
||||
|
||||
private final String personId;
|
||||
private final String nameForm;
|
||||
private final Sending sending;
|
||||
|
||||
public UserSanderPusher(String personId, String nameForm, Sending sending) {
|
||||
this.personId = personId;
|
||||
this.nameForm = nameForm;
|
||||
this.sending = sending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(String personId, 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("====================");
|
||||
final BoxAnswer boxAnswer = boxAnswer(stringBuilder.toString());
|
||||
boxAnswer.setRecipientIfNull(this.personId);
|
||||
sending.send(boxAnswer);
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package dev.struchkov.godfather.core.service;
|
||||
package dev.struchkov.godfather.simple.core.service;
|
||||
|
||||
import dev.struchkov.godfather.context.repository.PersonSettingRepository;
|
||||
import dev.struchkov.godfather.context.service.PersonSettingService;
|
||||
import dev.struchkov.godfather.simple.context.service.PersonSettingService;
|
||||
import dev.struchkov.godfather.simple.data.repository.PersonSettingRepository;
|
||||
import dev.struchkov.haiti.utils.Inspector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -17,24 +17,24 @@ public class PersonSettingServiceImpl implements PersonSettingService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getAllPersonIdDisableMessages(@NotNull Set<Long> personIds) {
|
||||
public Set<String> getAllPersonIdDisableMessages(@NotNull Set<String> personIds) {
|
||||
Inspector.isNotNull(personIds);
|
||||
return personSettingRepository.findAllByAllowedProcessing(personIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Boolean> getStateProcessingByPersonId(@NotNull Long personId) {
|
||||
public Optional<Boolean> getStateProcessingByPersonId(@NotNull String personId) {
|
||||
return personSettingRepository.findStateByPersonId(personId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableMessageProcessing(@NotNull Long personId) {
|
||||
public void disableMessageProcessing(@NotNull String personId) {
|
||||
Inspector.isNotNull(personId);
|
||||
personSettingRepository.disableMessageProcessing(personId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableMessageProcessing(@NotNull Long personId) {
|
||||
public void enableMessageProcessing(@NotNull String personId) {
|
||||
Inspector.isNotNull(personId);
|
||||
personSettingRepository.enableMessageProcessing(personId);
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package dev.struchkov.godfather.simple.core.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.ContextKey;
|
||||
import dev.struchkov.godfather.simple.data.StorylineContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static dev.struchkov.haiti.context.exception.NotFoundException.notFoundException;
|
||||
import static dev.struchkov.haiti.utils.Inspector.isNotNull;
|
||||
|
||||
public class StorylineContextMapImpl implements StorylineContext {
|
||||
|
||||
private final Map<String, Map<String, Object>> map = new HashMap<>();
|
||||
|
||||
public void save(@NotNull String personId, @NotNull ContextKey<?> key, Object objectForSave) {
|
||||
isNotNull(personId, key);
|
||||
map.computeIfAbsent(personId, k -> new HashMap<>()).put(key.getValue(), objectForSave);
|
||||
}
|
||||
|
||||
public <T> Optional<T> getByKey(@NotNull String personId, @NotNull ContextKey<T> key) {
|
||||
isNotNull(personId, key);
|
||||
if (map.containsKey(personId)) {
|
||||
final Map<String, Object> storage = map.get(personId);
|
||||
final T object = (T) storage.get(key.getValue());
|
||||
if (object != null && object.getClass().equals(key.getType())) {
|
||||
return Optional.of(object);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getByKeyOrThrow(@NotNull String personId, @NotNull ContextKey<T> key) {
|
||||
return getByKey(personId, key).orElseThrow(notFoundException("Не найдено значение ключа {0}, для пользователя {1}", key.getValue(), personId));
|
||||
}
|
||||
|
||||
public Map<String, Object> getAllSaveElement(@NotNull String personId) {
|
||||
isNotNull(personId);
|
||||
return map.get(personId);
|
||||
}
|
||||
|
||||
public void removeAll(@NotNull String personId) {
|
||||
isNotNull(personId);
|
||||
map.remove(personId);
|
||||
}
|
||||
|
||||
public void removeByKey(@NotNull String personId, @NotNull ContextKey<?> key) {
|
||||
isNotNull(personId, key);
|
||||
map.computeIfAbsent(personId, k -> new HashMap<>()).remove(key.getValue());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package dev.struchkov.godfather.simple.core.service;
|
||||
|
||||
import dev.struchkov.autoresponder.entity.Unit;
|
||||
import dev.struchkov.godfather.main.domain.StorylineHistory;
|
||||
import dev.struchkov.godfather.main.domain.UnitPointer;
|
||||
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||
import dev.struchkov.godfather.simple.context.service.UnitPointerService;
|
||||
import dev.struchkov.godfather.simple.core.Storyline;
|
||||
import dev.struchkov.godfather.simple.core.StorylineFactory;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import dev.struchkov.godfather.simple.data.repository.StorylineRepository;
|
||||
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<Mail> storyLine;
|
||||
private String defaultUnitName;
|
||||
|
||||
public StorylineMailService(
|
||||
UnitPointerService unitPointerService,
|
||||
StorylineRepository storylineRepository,
|
||||
List<Object> unitConfigurations
|
||||
) {
|
||||
this.storyLine = new StorylineFactory<Mail>(unitConfigurations).createStoryLine();
|
||||
this.unitPointerService = unitPointerService;
|
||||
this.storylineRepository = storylineRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(@NotNull StorylineHistory storylineHistory) {
|
||||
isNotNull(storylineHistory);
|
||||
storylineRepository.save(storylineHistory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MainUnit<Mail>> getUnitNameByPersonId(@NotNull String personId) {
|
||||
isNotNull(personId);
|
||||
return unitPointerService.getUnitNameByPersonId(personId)
|
||||
.flatMap(storyLine::getUnit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MainUnit<Mail>> getNextUnitByPersonId(@NotNull String personId) {
|
||||
final Optional<Set<MainUnit<Mail>>> optMainUnits = getUnitNameByPersonId(personId)
|
||||
.map(Unit::getNextUnits)
|
||||
.filter(mainUnits -> !mainUnits.isEmpty());
|
||||
if (optMainUnits.isEmpty()) {
|
||||
storylineRepository.cleanHistoryByPersonId(personId);
|
||||
}
|
||||
final Set<MainUnit<Mail>> nextUnits = optMainUnits.orElse(storyLine.getStartingUnits());
|
||||
nextUnits.addAll(storyLine.getGlobalUnits());
|
||||
return nextUnits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(String personId, String unitName, Mail mail) {
|
||||
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(String personId, int countUnitsToBack) {
|
||||
return storylineRepository.findByCountLast(personId, countUnitsToBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<StorylineHistory> replaceUserToBack(String personId, String unitName) {
|
||||
return storylineRepository.findByCountLast(personId, unitName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MainUnit<Mail>> getDefaultUnit() {
|
||||
if (defaultUnitName == null) return Optional.empty();
|
||||
return storyLine.getUnit(defaultUnitName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultUnit(String defaultUnit) {
|
||||
defaultUnitName = defaultUnit;
|
||||
}
|
||||
|
||||
//TODO [22.06.2022]: Временное решение для ленивой инициализации
|
||||
@Override
|
||||
public void lazyLink(String firstName, String secondName) {
|
||||
storyLine.link(firstName, secondName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MainUnit<Mail>> getUnitByName(String unitName) {
|
||||
return storyLine.getUnit(unitName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package dev.struchkov.godfather.simple.core.service;
|
||||
|
||||
import dev.struchkov.godfather.main.domain.StorylineHistory;
|
||||
import dev.struchkov.godfather.main.domain.content.Message;
|
||||
import dev.struchkov.godfather.simple.core.unit.MainUnit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public interface StorylineService<M extends Message> {
|
||||
|
||||
void save(@NotNull StorylineHistory storylineHistory);
|
||||
|
||||
Optional<MainUnit<M>> getUnitNameByPersonId(@NotNull String personId);
|
||||
|
||||
Set<MainUnit<M>> getNextUnitByPersonId(@NotNull String personId);
|
||||
|
||||
void save(String personId, String name, M message);
|
||||
|
||||
Optional<StorylineHistory> replaceUserToBack(String personId, int countUnitsToBack);
|
||||
|
||||
Optional<StorylineHistory> replaceUserToBack(String personId, String unitName);
|
||||
|
||||
Optional<MainUnit<M>> getDefaultUnit();
|
||||
|
||||
/**
|
||||
* Ленивая (поздняя) связка юнитов между собой. Осуществляется уже после создания сценария. С помощью данного подхода можно реализовать циклические зависимости юнитов.
|
||||
*/
|
||||
void lazyLink(String firstName, String secondName);
|
||||
|
||||
Optional<MainUnit<M>> getUnitByName(String unitName);
|
||||
|
||||
void setDefaultUnit(String unitName);
|
||||
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package dev.struchkov.godfather.core.service;
|
||||
package dev.struchkov.godfather.simple.core.service;
|
||||
|
||||
import dev.struchkov.godfather.context.domain.UnitPointer;
|
||||
import dev.struchkov.godfather.context.repository.UnitPointerRepository;
|
||||
import dev.struchkov.godfather.context.service.UnitPointerService;
|
||||
import dev.struchkov.godfather.main.domain.UnitPointer;
|
||||
import dev.struchkov.godfather.simple.context.service.UnitPointerService;
|
||||
import dev.struchkov.godfather.simple.data.repository.UnitPointerRepository;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
@ -21,12 +21,12 @@ public class UnitPointerServiceImpl implements UnitPointerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getUnitNameByPersonId(@NotNull Long personId) {
|
||||
public Optional<String> getUnitNameByPersonId(@NotNull String personId) {
|
||||
return unitPointerRepository.findUnitNameByPersonId(personId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeByPersonId(@NotNull Long personId) {
|
||||
public void removeByPersonId(@NotNull String personId) {
|
||||
unitPointerRepository.removeByPersonId(personId);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user