Skip to content

Commit

Permalink
[FEATURE]: add parsing scenario from config file
Browse files Browse the repository at this point in the history
  • Loading branch information
Drednote committed Dec 7, 2024
1 parent 2a6f1f3 commit 6938c11
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 18 deletions.
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,9 +480,6 @@ handle this, there is a component called **Response Processing**, which follows
- You can create any implementation of `TelegramResponse` for sending response
- Any custom code can be written in `TelegramResponse`, but I strongly recommend using this
interface only for sending a response to **Telegram**
- If you pass {@link BotApiMethod} or {@link SendMediaBotMethod} in the constructor of this class,
the 'chatId' property will be automatically set (only if it is null). If you manually
set 'chatId', nothing happens

### Exception Handling

Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
api 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.6.0'
api 'com.github.ben-manes.caffeine:caffeine'
api 'org.apache.httpcomponents.client5:httpclient5'
api 'io.github.resilience4j:resilience4j-spring-boot2:2.2.0'

// data
compileOnly 'org.springframework.boot:spring-boot-starter-webflux'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,30 @@ public static class Scenario {
private TransitionType type = TransitionType.External;
private String source;
private String target;
private List<Node> graph = new ArrayList<>();
/**
* Only if type == Rollback.
*/
@Nullable
private Rollback rollback;

private Map<String, Object> props = new HashMap<>();
private List<Scenario> children = new ArrayList<>();
private Map<String, Scenario> steps = new HashMap<>();

public enum TransitionType {
Rollback, ResponseMessageProcessing, External
}
}

@Getter
@Setter
public static class Node {

private String id;
private List<Node> children = new ArrayList<>();

}

@Getter
@Setter
public static class Request {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.github.drednote.telegram.core.request.TelegramRequest;
import io.github.drednote.telegram.core.request.TelegramRequestImpl;
import io.github.drednote.telegram.handler.scenario.Action;
import io.github.drednote.telegram.handler.scenario.property.ScenarioProperties.Node;
import io.github.drednote.telegram.handler.scenario.property.ScenarioProperties.Request;
import io.github.drednote.telegram.handler.scenario.property.ScenarioProperties.Rollback;
import io.github.drednote.telegram.handler.scenario.property.ScenarioProperties.Scenario;
Expand Down Expand Up @@ -46,18 +47,24 @@ public <S> void configure(ScenarioBuilder<S> scenarioBuilder) {
throw new IllegalArgumentException("First transition cannot be of 'Rollback' type");
}
TransitionData<S> transitionData = configureTransition(scenarioBuilder, scenario, null);
for (Scenario child : scenario.getChildren()) {
doConfigure(scenarioBuilder, transitionData, child);
}
scenario.getGraph().forEach(node -> {
doConfigure(scenarioBuilder, transitionData, scenario, node);
});
});
}
}

public <S> void doConfigure(ScenarioBuilder<S> scenarioBuilder, TransitionData<S> parent, Scenario scenario) {
TransitionData<S> transitionData = configureTransition(scenarioBuilder, scenario, parent);
for (Scenario child : scenario.getChildren()) {
doConfigure(scenarioBuilder, transitionData, child);
private <S> void doConfigure(
ScenarioBuilder<S> scenarioBuilder, TransitionData<S> parent, Scenario scenario, Node node
) {
Scenario child = scenario.getSteps().get(node.getId());
if (child == null) {
throw new IllegalArgumentException("Step '" + node.getId() + "' does not exist");
}
TransitionData<S> transitionData = configureTransition(scenarioBuilder, child, parent);
node.getChildren().forEach(childNode -> {
doConfigure(scenarioBuilder, transitionData, scenario, childNode);
});
}

@NotNull
Expand All @@ -67,7 +74,7 @@ private <S> TransitionData<S> configureTransition(
Request request = scenario.getRequest();
Set<String> actionClassName = scenario.getActionReferences();
String target = scenario.getTarget();
Object source = parent != null ? scenario.getSource(): scenarioBuilder.getInitial();
Object source = parent != null ? scenario.getSource() : scenarioBuilder.getInitial();

Assert.required(target, "Target state");
Assert.required(source, "Source state");
Expand Down Expand Up @@ -109,7 +116,8 @@ private List<Action<Object>> createAction(@Nullable Set<String> actionReference)
if (handlerMethod == null) {
throw new IllegalArgumentException("Action class name" + name + " not found");
}
InvocableHandlerMethod invocableHandlerMethod = new InvocableHandlerMethod(handlerMethod, "ScenarioFactory");
InvocableHandlerMethod invocableHandlerMethod = new InvocableHandlerMethod(handlerMethod,
"ScenarioFactory");
response.add(invocableHandlerMethod::invoke);
}
return response;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ void shouldCorrectCreateTransitionsFromProperties() {
ScenarioBuilder<Object> scenarioBuilder = new ScenarioBuilder<>();
scenarioBuilder.setInitial(StateEnum.INITIAL);
configurer.configure(scenarioBuilder);

ScenarioData<Object> build = scenarioBuilder.build();
assertThat(build).isNotNull();
assertThat(build.states()).hasSize(3);
assertThat(build.states()).hasSize(4);
for (Entry<State<Object>, List<Transition<Object>>> entry : build.states().entrySet()) {
if (entry.getKey().getId().equals(StateEnum.INITIAL)) {
assertThat(entry.getValue()).hasSize(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ void setUp() {
filterProperties.setUserRateLimitUnit(ChronoUnit.MILLIS);
}

@RepeatedTest(20)
@Timeout(value = 10, threadMode = ThreadMode.SEPARATE_THREAD)
@RepeatedTest(5)
@Timeout(value = 2, threadMode = ThreadMode.SEPARATE_THREAD)
void shouldWaitIfMaxQueueSizeExceed() throws InterruptedException {
sessionProperties.setCacheLiveDuration(100);
session = new DefaultTelegramUpdateProcessor(sessionProperties, filterProperties,
Expand Down
29 changes: 27 additions & 2 deletions src/test/resources/application-scenarioproperties.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ drednote:
value: telegram-settings_get
- - text: change
value: telegram-settings_change
children:
- type: Rollback
graph:
- id: get
children:
- id: test
steps:
get:
type: Rollback
request:
patterns: [telegram-settings_get]
requestTypes: [CALLBACK_QUERY]
Expand All @@ -39,3 +44,23 @@ drednote:
keyboard:
- - text: back
value: rollback
test:
type: Rollback
request:
patterns: [ telegram-settings_test ]
requestTypes: [ CALLBACK_QUERY ]
action-references:
- "TestScenarioFactory#name3"
source: GET_TELEGRAM_SETTINGS
target: TEST_TELEGRAM_SETTINGS
rollback:
action-references:
- "test_name"
request:
patterns: [ rollback ]
requestTypes: [ CALLBACK_QUERY ]
props:
text: 'settings:'
keyboard:
- - text: back
value: rollback

0 comments on commit 6938c11

Please sign in to comment.