Commit aa62787f6ca23d814c166b762bec959e5a53852b
0 parents
Initial commit
Showing
146 changed files
with
9863 additions
and
0 deletions
.gitignore
0 → 100755
| 1 | +++ a/.gitignore | |
| 1 | +*.class | |
| 2 | + | |
| 3 | +# Mobile Tools for Java (J2ME) | |
| 4 | +.mtj.tmp/ | |
| 5 | + | |
| 6 | +# Package Files # | |
| 7 | +*.war | |
| 8 | +*.war.* | |
| 9 | +*.ear | |
| 10 | + | |
| 11 | +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | |
| 12 | +hs_err_pid* | |
| 13 | + | |
| 14 | +# Logfiles | |
| 15 | +**.log | |
| 16 | +**.log.* | |
| 17 | + | |
| 18 | +**/.DS_Store | |
| 19 | +.idea | |
| 20 | +.gradle | |
| 21 | +bht-chatbot.iml | |
| 22 | +target/ | |
| 23 | +build | ... | ... |
README.md
0 → 100755
| 1 | +++ a/README.md | |
| 1 | +# BHT-Chatbot | |
| 2 | +Master-Projekt SS2017 Medieninformatik | |
| 3 | +<!-- MarkdownTOC --> | |
| 4 | + | |
| 5 | +- [Requirements](#requirements) | |
| 6 | +- [Main TechStack](#main-techstack) | |
| 7 | +- [Project documention](#project-documention) | |
| 8 | +- [Run and stop the application](#run-and-stop-the-application) | |
| 9 | +- [Used online sources](#used-online-sources) | |
| 10 | + | |
| 11 | +<!-- /MarkdownTOC --> | |
| 12 | + | |
| 13 | +## Requirements | |
| 14 | +- Java 8 to build the application | |
| 15 | +- a running docker daemon to start application server | |
| 16 | + | |
| 17 | +## Main TechStack | |
| 18 | +- Gradle 3.5 | |
| 19 | +- Docker | |
| 20 | +- WildFly 10 | |
| 21 | + | |
| 22 | +## Project documention | |
| 23 | +You can find the whole project documentation under [project_documentation](docu/project_documentation.md). | |
| 24 | + | |
| 25 | +## Run and stop the application | |
| 26 | +Go to project path and executes the following gradle tasks to start/stop the application: | |
| 27 | + ```bash | |
| 28 | + # Unix based | |
| 29 | + ./gradlew chatbotRun | |
| 30 | + ./gradlew chatbotStop | |
| 31 | + | |
| 32 | + # Windows | |
| 33 | + gradlew.bat chatbotRun | |
| 34 | + gradlew.bat chatbotStop | |
| 35 | + | |
| 36 | + # MacOS | |
| 37 | + # you need to execute the docker commands directly | |
| 38 | + cd docker | |
| 39 | + docker-compose up --build | |
| 40 | + docker-compose down | |
| 41 | + ``` | |
| 42 | + | |
| 43 | +The following ports are mapped to host: | |
| 44 | +- 8080 -> 8080 | |
| 45 | +- 8787 -> 8787 (Remote Debug Port) | |
| 46 | +- 9990 -> 9990 (WildFly Server Manager) | |
| 47 | + | |
| 48 | +If all went well, you should see the application appearing at [localhost:8080/bht-chatbot](http://localhost:8080/bht-chatbot) | |
| 49 | + | |
| 50 | +## Known issues | |
| 51 | +- The usage of `./gradlew chatbotRun` is not working under Mac OSX | |
| 52 | + | |
| 53 | +## Used online sources | |
| 54 | +- [Markdown CheetSheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) | |
| 55 | +- [Docker base image for WildFly application server](https://hub.docker.com/r/jboss/wildfly/) | |
| 56 | +- [Gradle 3.5 User Guide](https://docs.gradle.org/3.5/userguide/userguide.html) | |
| 57 | + | ... | ... |
build.gradle
0 → 100755
| 1 | +++ a/build.gradle | |
| 1 | +/* Plugins | |
| 2 | +---------------------------------*/ | |
| 3 | +apply plugin: 'war' | |
| 4 | + | |
| 5 | + | |
| 6 | +/* Repositories | |
| 7 | +---------------------------------*/ | |
| 8 | + | |
| 9 | + | |
| 10 | +/* Dependencies | |
| 11 | +---------------------------------*/ | |
| 12 | +/*dependencies { | |
| 13 | + | |
| 14 | + compile 'org.jboss.resteasy:resteasy-jaxrs-all:3.1.3.Final' | |
| 15 | + | |
| 16 | + compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.3' | |
| 17 | + compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.3.1' | |
| 18 | + | |
| 19 | + compile "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 20 | + "org.json:json:20160810", | |
| 21 | + "com.github.pengrad:java-telegram-bot-api:3.0.0", | |
| 22 | + "com.mashape.unirest:unirest-java:1.4.9", | |
| 23 | + "org.drools:drools-compiler:7.0.0.Final", | |
| 24 | + "commons-cli:commons-cli:1.3.1", | |
| 25 | + "org.jsoup:jsoup:1.10.2", | |
| 26 | + "net.jodah:expiringmap:0.5.8" | |
| 27 | + | |
| 28 | + providedCompile "org.slf4j:slf4j-api:1.7.25", | |
| 29 | + "org.jboss.resteasy:resteasy-client:3.1.3.Final", | |
| 30 | + "org.infinispan:infinispan-core:8.2.4.Final" | |
| 31 | + | |
| 32 | + testCompile "org.jboss.arquillian.junit:arquillian-junit-container:1.1.13.Final", | |
| 33 | + "junit:junit:4.12" | |
| 34 | + | |
| 35 | + testRuntime "org.wildfly.arquillian:wildfly-arquillian-container-remote:2.0.2.Final", | |
| 36 | + "org.slf4j:slf4j-simple:1.7.25" | |
| 37 | +}*/ | |
| 38 | + | |
| 39 | + | |
| 40 | +/* Configurations | |
| 41 | +---------------------------------*/ | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | +/* Tasks | |
| 46 | +---------------------------------*/ | |
| 47 | +task wrapper(type: Wrapper) { | |
| 48 | + gradleVersion = '3.5' | |
| 49 | +} | |
| 50 | + | |
| 51 | + | |
| 52 | +task chatbotRun(type: Exec, dependsOn: war) { | |
| 53 | + workingDir 'docker' | |
| 54 | + commandLine 'docker-compose', 'up', '--build' | |
| 55 | +} | |
| 56 | + | |
| 57 | +task chatbotStop(type: Exec) { | |
| 58 | + workingDir 'docker' | |
| 59 | + commandLine 'docker-compose', 'down' | |
| 60 | +} | |
| 61 | + | |
| 62 | +task cleanWar(type: Delete) { | |
| 63 | + delete fileTree(dir: 'docker/wildfly/volumes/deployments/', include: '*.war') | |
| 64 | +} | |
| 65 | + | |
| 66 | +tasks.war.dependsOn(cleanWar) | ... | ... |
config/checkstyle/checkstyle.xml
0 → 100755
| 1 | +++ a/config/checkstyle/checkstyle.xml | |
| 1 | +<?xml version="1.0"?> | |
| 2 | +<!DOCTYPE module PUBLIC | |
| 3 | + "-//Puppy Crawl//DTD Check Configuration 1.3//EN" | |
| 4 | + "http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd"> | |
| 5 | + | |
| 6 | +<!-- | |
| 7 | + Checkstyle configuration that checks the sun coding conventions from: | |
| 8 | + - the Java Language Specification at | |
| 9 | + http://java.sun.com/docs/books/jls/second_edition/html/index.html | |
| 10 | + - the Sun Code Conventions at http://java.sun.com/docs/codeconv/ | |
| 11 | + - the Javadoc guidelines at | |
| 12 | + http://java.sun.com/j2se/javadoc/writingdoccomments/index.html | |
| 13 | + - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html | |
| 14 | + - some best practices | |
| 15 | + Checkstyle is very configurable. Be sure to read the documentation at | |
| 16 | + http://checkstyle.sf.net (or in your downloaded distribution). | |
| 17 | + Most Checks are configurable, be sure to consult the documentation. | |
| 18 | + To completely disable a check, just comment it out or delete it from the file. | |
| 19 | + Finally, it is worth reading the documentation. | |
| 20 | +--> | |
| 21 | + | |
| 22 | +<module name="Checker"> | |
| 23 | + <!-- | |
| 24 | + If you set the basedir property below, then all reported file | |
| 25 | + names will be relative to the specified directory. See | |
| 26 | + http://checkstyle.sourceforge.net/5.x/config.html#Checker | |
| 27 | + <property name="basedir" value="${basedir}"/> | |
| 28 | + --> | |
| 29 | + | |
| 30 | + <property name="fileExtensions" value="java, properties, xml"/> | |
| 31 | + | |
| 32 | + <!-- Checks that a package-info.java file exists for each package. --> | |
| 33 | + <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage --> | |
| 34 | + <module name="JavadocPackage"/> | |
| 35 | + | |
| 36 | + <!-- Checks whether files end with a new line. --> | |
| 37 | + <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile --> | |
| 38 | + <module name="NewlineAtEndOfFile"/> | |
| 39 | + | |
| 40 | + <!-- Checks that property files contain the same keys. --> | |
| 41 | + <!-- See http://checkstyle.sf.net/config_misc.html#Translation --> | |
| 42 | + <module name="Translation"/> | |
| 43 | + | |
| 44 | + <!-- Checks for Size Violations. --> | |
| 45 | + <!-- See http://checkstyle.sf.net/config_sizes.html --> | |
| 46 | + <module name="FileLength"/> | |
| 47 | + | |
| 48 | + <!-- Checks for whitespace --> | |
| 49 | + <!-- See http://checkstyle.sf.net/config_whitespace.html --> | |
| 50 | + <module name="FileTabCharacter"/> | |
| 51 | + | |
| 52 | + <!-- Miscellaneous other checks. --> | |
| 53 | + <!-- See http://checkstyle.sf.net/config_misc.html --> | |
| 54 | + <module name="RegexpSingleline"> | |
| 55 | + <property name="format" value="\s+$"/> | |
| 56 | + <property name="minimum" value="0"/> | |
| 57 | + <property name="maximum" value="0"/> | |
| 58 | + <property name="message" value="Line has trailing spaces."/> | |
| 59 | + </module> | |
| 60 | + | |
| 61 | + <!-- Checks for Headers --> | |
| 62 | + <!-- See http://checkstyle.sf.net/config_header.html --> | |
| 63 | + <!-- <module name="Header"> --> | |
| 64 | + <!-- <property name="headerFile" value="${checkstyle.header.file}"/> --> | |
| 65 | + <!-- <property name="fileExtensions" value="java"/> --> | |
| 66 | + <!-- </module> --> | |
| 67 | + | |
| 68 | + <module name="TreeWalker"> | |
| 69 | + | |
| 70 | + <!-- Checks for Javadoc comments. --> | |
| 71 | + <!-- See http://checkstyle.sf.net/config_javadoc.html --> | |
| 72 | + <module name="JavadocMethod"/> | |
| 73 | + <module name="JavadocType"/> | |
| 74 | + <module name="JavadocVariable"/> | |
| 75 | + <module name="JavadocStyle"/> | |
| 76 | + | |
| 77 | + <!-- Checks for Naming Conventions. --> | |
| 78 | + <!-- See http://checkstyle.sf.net/config_naming.html --> | |
| 79 | + <module name="ConstantName"/> | |
| 80 | + <module name="LocalFinalVariableName"/> | |
| 81 | + <module name="LocalVariableName"/> | |
| 82 | + <module name="MemberName"/> | |
| 83 | + <module name="MethodName"/> | |
| 84 | + <module name="PackageName"/> | |
| 85 | + <module name="ParameterName"/> | |
| 86 | + <module name="StaticVariableName"/> | |
| 87 | + <module name="TypeName"/> | |
| 88 | + | |
| 89 | + <!-- Checks for imports --> | |
| 90 | + <!-- See http://checkstyle.sf.net/config_import.html --> | |
| 91 | + <module name="AvoidStarImport"/> | |
| 92 | + <module name="IllegalImport"/> <!-- defaults to sun.* packages --> | |
| 93 | + <module name="RedundantImport"/> | |
| 94 | + <module name="UnusedImports"> | |
| 95 | + <property name="processJavadoc" value="false"/> | |
| 96 | + </module> | |
| 97 | + | |
| 98 | + <!-- Checks for Size Violations. --> | |
| 99 | + <!-- See http://checkstyle.sf.net/config_sizes.html --> | |
| 100 | + <module name="LineLength"/> | |
| 101 | + <module name="MethodLength"/> | |
| 102 | + <module name="ParameterNumber"/> | |
| 103 | + | |
| 104 | + <!-- Checks for whitespace --> | |
| 105 | + <!-- See http://checkstyle.sf.net/config_whitespace.html --> | |
| 106 | + <module name="EmptyForIteratorPad"/> | |
| 107 | + <module name="GenericWhitespace"/> | |
| 108 | + <module name="MethodParamPad"/> | |
| 109 | + <module name="NoWhitespaceAfter"/> | |
| 110 | + <module name="NoWhitespaceBefore"/> | |
| 111 | + <module name="OperatorWrap"/> | |
| 112 | + <module name="ParenPad"/> | |
| 113 | + <module name="TypecastParenPad"/> | |
| 114 | + <module name="WhitespaceAfter"/> | |
| 115 | + <module name="WhitespaceAround"/> | |
| 116 | + | |
| 117 | + <!-- Modifier Checks --> | |
| 118 | + <!-- See http://checkstyle.sf.net/config_modifiers.html --> | |
| 119 | + <module name="ModifierOrder"/> | |
| 120 | + <module name="RedundantModifier"/> | |
| 121 | + | |
| 122 | + <!-- Checks for blocks. You know, those {}'s --> | |
| 123 | + <!-- See http://checkstyle.sf.net/config_blocks.html --> | |
| 124 | + <module name="AvoidNestedBlocks"/> | |
| 125 | + <module name="EmptyBlock"/> | |
| 126 | + <module name="LeftCurly"/> | |
| 127 | + <module name="NeedBraces"/> | |
| 128 | + <module name="RightCurly"/> | |
| 129 | + | |
| 130 | + <!-- Checks for common coding problems --> | |
| 131 | + <!-- See http://checkstyle.sf.net/config_coding.html --> | |
| 132 | + <module name="AvoidInlineConditionals"/> | |
| 133 | + <module name="EmptyStatement"/> | |
| 134 | + <module name="EqualsHashCode"/> | |
| 135 | + <module name="HiddenField"/> | |
| 136 | + <module name="IllegalInstantiation"/> | |
| 137 | + <module name="InnerAssignment"/> | |
| 138 | + <module name="MagicNumber"/> | |
| 139 | + <module name="MissingSwitchDefault"/> | |
| 140 | + <module name="SimplifyBooleanExpression"/> | |
| 141 | + <module name="SimplifyBooleanReturn"/> | |
| 142 | + | |
| 143 | + <!-- Checks for class design --> | |
| 144 | + <!-- See http://checkstyle.sf.net/config_design.html --> | |
| 145 | + <module name="DesignForExtension"/> | |
| 146 | + <module name="FinalClass"/> | |
| 147 | + <module name="HideUtilityClassConstructor"/> | |
| 148 | + <module name="InterfaceIsType"/> | |
| 149 | + <module name="VisibilityModifier"/> | |
| 150 | + | |
| 151 | + <!-- Miscellaneous other checks. --> | |
| 152 | + <!-- See http://checkstyle.sf.net/config_misc.html --> | |
| 153 | + <module name="ArrayTypeStyle"/> | |
| 154 | + <module name="FinalParameters"/> | |
| 155 | + <module name="TodoComment"/> | |
| 156 | + <module name="UpperEll"/> | |
| 157 | + | |
| 158 | + </module> | |
| 159 | + | |
| 160 | +</module> | |
| 0 | 161 | \ No newline at end of file | ... | ... |
docker/docker-compose.yml
0 → 100755
| 1 | +++ a/docker/docker-compose.yml | |
| 1 | +version: '3' | |
| 2 | + | |
| 3 | +services: | |
| 4 | + app-server: | |
| 5 | + build: ./wildfly | |
| 6 | + container_name: chatbot-wildfly | |
| 7 | + image: bht-chatbot:latest | |
| 8 | + ports: | |
| 9 | + - "8080:8080" | |
| 10 | + - "8787:8787" | |
| 11 | + - "9990:9990" | |
| 12 | + volumes: | |
| 13 | + - ./wildfly/volumes/deployments/:/opt/jboss/wildfly/standalone/deployments/ | |
| 14 | + - ./wildfly/volumes/logs/:/opt/jboss/wildfly/standalone/log/ | |
| 15 | + - ./wildfly/volumes/conf/:/opt/jboss/wildfly/standalone/conf/ | |
| 16 | + links: | |
| 17 | + - rasa-server | |
| 18 | + command: /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 --debug | |
| 19 | + rasa-server: | |
| 20 | + build: ./rasa_nlu | |
| 21 | + container_name: rasa_nlu | |
| 22 | + image: rasa_nlu:latest | |
| 23 | + ports: | |
| 24 | + - "5000:5000" | |
| 25 | + volumes: | |
| 26 | + - ./rasa_nlu/volumes/data/api/:/app/data/api | |
| 27 | + - ./rasa_nlu/volumes/logs/:/app/logs/ | |
| 28 | + command: python -m rasa_nlu.server -c config/chatbot_config.json --server_model_dirs=default | |
| 0 | 29 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/Dockerfile
0 → 100755
| 1 | +++ a/docker/rasa_nlu/Dockerfile | |
| 1 | +FROM python:2.7-slim | |
| 2 | + | |
| 3 | +ENV RASA_NLU_DOCKER="YES" \ | |
| 4 | + RASA_NLU_HOME="/app" | |
| 5 | + | |
| 6 | +# Run updates, install basics and cleanup | |
| 7 | +# - build-essential: Compile specific dependencies | |
| 8 | +# - git-core and ssh: Checkout git repos | |
| 9 | +RUN apt-get update -qq && \ | |
| 10 | + apt-get install -y --no-install-recommends build-essential git-core wget && \ | |
| 11 | + apt-get clean && \ | |
| 12 | + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* | |
| 13 | + | |
| 14 | +WORKDIR ${RASA_NLU_HOME} | |
| 15 | + | |
| 16 | +# Install rasa and its dependencies | |
| 17 | +RUN pip install -U spacy scikit-learn scipy sklearn-crfsuite | |
| 18 | +RUN python -m spacy download de | |
| 19 | +RUN pip install rasa_nlu==0.9.1 | |
| 20 | + | |
| 21 | +# train the model | |
| 22 | +COPY rasa_config.json config/chatbot_config.json | |
| 23 | +COPY volumes/data/api/ data/api | |
| 24 | +RUN python -m rasa_nlu.train -c config/chatbot_config.json | |
| 25 | + | |
| 26 | +# Cleanup | |
| 27 | +RUN mv models/model_* models/default && rm -r data/api | |
| 28 | + | |
| 29 | +EXPOSE 5000 | |
| 0 | 30 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/rasa_config.json
0 → 100755
docker/rasa_nlu/volumes/data/api/agent.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/agent.json | |
| 1 | +{ | |
| 2 | + "description": "", | |
| 3 | + "language": "de", | |
| 4 | + "activeAssistantAgents": [ | |
| 5 | + "smalltalk-domain-on", | |
| 6 | + "smalltalk-fulfillment-on" | |
| 7 | + ], | |
| 8 | + "googleAssistant": { | |
| 9 | + "googleAssistantCompatible": false, | |
| 10 | + "welcomeIntentSignInRequired": false, | |
| 11 | + "startIntents": [], | |
| 12 | + "systemIntents": [], | |
| 13 | + "endIntentIds": [], | |
| 14 | + "oAuthLinking": { | |
| 15 | + "required": false, | |
| 16 | + "grantType": "AUTH_CODE_GRANT" | |
| 17 | + }, | |
| 18 | + "voiceType": "MALE_1", | |
| 19 | + "capabilities": [], | |
| 20 | + "protocolVersion": "V1" | |
| 21 | + }, | |
| 22 | + "defaultTimezone": "Europe/Madrid", | |
| 23 | + "webhook": { | |
| 24 | + "available": false, | |
| 25 | + "useForDomains": false | |
| 26 | + }, | |
| 27 | + "isPrivate": false, | |
| 28 | + "customClassifierMode": "use.after", | |
| 29 | + "mlMinConfidence": 0.2 | |
| 30 | +} | |
| 0 | 31 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/entities/date.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/entities/date.json | |
| 1 | +{ | |
| 2 | + "id": "7d5ec91f-9608-4a88-aa16-91f02a60ce60", | |
| 3 | + "name": "date", | |
| 4 | + "isOverridable": true, | |
| 5 | + "entries": [ | |
| 6 | + { | |
| 7 | + "value": "today", | |
| 8 | + "synonyms": [ | |
| 9 | + "today", | |
| 10 | + "heute", | |
| 11 | + "heut", | |
| 12 | + "heutigen" | |
| 13 | + ] | |
| 14 | + }, | |
| 15 | + { | |
| 16 | + "value": "tomorrow", | |
| 17 | + "synonyms": [ | |
| 18 | + "tomorrow", | |
| 19 | + "morgen" | |
| 20 | + ] | |
| 21 | + }, | |
| 22 | + { | |
| 23 | + "value": "dayaftertomorrow", | |
| 24 | + "synonyms": [ | |
| 25 | + "übermorgen", | |
| 26 | + "day after tomorrow" | |
| 27 | + ] | |
| 28 | + }, | |
| 29 | + { | |
| 30 | + "value": "Montag", | |
| 31 | + "synonyms": [ | |
| 32 | + "Montag" | |
| 33 | + ] | |
| 34 | + }, | |
| 35 | + { | |
| 36 | + "value": "Dienstag", | |
| 37 | + "synonyms": [ | |
| 38 | + "Dienstag" | |
| 39 | + ] | |
| 40 | + }, | |
| 41 | + { | |
| 42 | + "value": "Mittwoch", | |
| 43 | + "synonyms": [ | |
| 44 | + "Mittwoch" | |
| 45 | + ] | |
| 46 | + }, | |
| 47 | + { | |
| 48 | + "value": "Donnerstag", | |
| 49 | + "synonyms": [ | |
| 50 | + "Donnerstag" | |
| 51 | + ] | |
| 52 | + }, | |
| 53 | + { | |
| 54 | + "value": "Freitag", | |
| 55 | + "synonyms": [ | |
| 56 | + "Freitag" | |
| 57 | + ] | |
| 58 | + }, | |
| 59 | + { | |
| 60 | + "value": "yesterday", | |
| 61 | + "synonyms": [ | |
| 62 | + "gestern", | |
| 63 | + "yesterday" | |
| 64 | + ] | |
| 65 | + } | |
| 66 | + ], | |
| 67 | + "isEnum": false, | |
| 68 | + "automatedExpansion": false | |
| 69 | +} | |
| 0 | 70 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/entities/dishcategory.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/entities/dishcategory.json | |
| 1 | +{ | |
| 2 | + "id": "8a0a0ef7-e6b4-4abb-814d-482d5135bbec", | |
| 3 | + "name": "dishcategory", | |
| 4 | + "isOverridable": true, | |
| 5 | + "entries": [ | |
| 6 | + { | |
| 7 | + "value": "vorspeisen", | |
| 8 | + "synonyms": [ | |
| 9 | + "vorspeisen", | |
| 10 | + "Vorspeise", | |
| 11 | + "Vorspeisen" | |
| 12 | + ] | |
| 13 | + }, | |
| 14 | + { | |
| 15 | + "value": "salate", | |
| 16 | + "synonyms": [ | |
| 17 | + "salate", | |
| 18 | + "Salat", | |
| 19 | + "Salate" | |
| 20 | + ] | |
| 21 | + }, | |
| 22 | + { | |
| 23 | + "value": "suppen", | |
| 24 | + "synonyms": [ | |
| 25 | + "suppen", | |
| 26 | + "Suppe", | |
| 27 | + "Suppen" | |
| 28 | + ] | |
| 29 | + }, | |
| 30 | + { | |
| 31 | + "value": "aktionen", | |
| 32 | + "synonyms": [ | |
| 33 | + "aktionen", | |
| 34 | + "Aktion", | |
| 35 | + "Aktionen" | |
| 36 | + ] | |
| 37 | + }, | |
| 38 | + { | |
| 39 | + "value": "essen", | |
| 40 | + "synonyms": [ | |
| 41 | + "Hauptgerichte", | |
| 42 | + "Hauptspeise", | |
| 43 | + "Hauptspeisen" | |
| 44 | + ] | |
| 45 | + }, | |
| 46 | + { | |
| 47 | + "value": "beilagen", | |
| 48 | + "synonyms": [ | |
| 49 | + "beilagen", | |
| 50 | + "Beilage", | |
| 51 | + "Beilagen" | |
| 52 | + ] | |
| 53 | + }, | |
| 54 | + { | |
| 55 | + "value": "desserts", | |
| 56 | + "synonyms": [ | |
| 57 | + "desserts", | |
| 58 | + "Dessert", | |
| 59 | + "Nachspeise", | |
| 60 | + "Nachtisch", | |
| 61 | + "Nachspeisen", | |
| 62 | + "Desserts" | |
| 63 | + ] | |
| 64 | + } | |
| 65 | + ], | |
| 66 | + "isEnum": false, | |
| 67 | + "automatedExpansion": false | |
| 68 | +} | |
| 0 | 69 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/entities/dishtype.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/entities/dishtype.json | |
| 1 | +{ | |
| 2 | + "id": "4f3135fd-2367-4e89-8860-a80582f4523a", | |
| 3 | + "name": "dishtype", | |
| 4 | + "isOverridable": true, | |
| 5 | + "entries": [ | |
| 6 | + { | |
| 7 | + "value": "vegan", | |
| 8 | + "synonyms": [ | |
| 9 | + "vegan", | |
| 10 | + "veganes", | |
| 11 | + "veganer", | |
| 12 | + "vegane" | |
| 13 | + ] | |
| 14 | + }, | |
| 15 | + { | |
| 16 | + "value": "vegetarian", | |
| 17 | + "synonyms": [ | |
| 18 | + "vegetarisch", | |
| 19 | + "vegetarisches", | |
| 20 | + "vegetarier", | |
| 21 | + "ohne Fleisch", | |
| 22 | + "kein Fleisch", | |
| 23 | + "vegetarische" | |
| 24 | + ] | |
| 25 | + }, | |
| 26 | + { | |
| 27 | + "value": "bio", | |
| 28 | + "synonyms": [ | |
| 29 | + "bio" | |
| 30 | + ] | |
| 31 | + } | |
| 32 | + ], | |
| 33 | + "isEnum": false, | |
| 34 | + "automatedExpansion": false | |
| 35 | +} | |
| 0 | 36 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/entities/healthy.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/entities/healthy.json | |
| 1 | +{ | |
| 2 | + "id": "c61797ac-dedc-4881-8863-4c656eb47359", | |
| 3 | + "name": "healthy", | |
| 4 | + "isOverridable": true, | |
| 5 | + "entries": [ | |
| 6 | + { | |
| 7 | + "value": "green", | |
| 8 | + "synonyms": [ | |
| 9 | + "grün", | |
| 10 | + "gesund", | |
| 11 | + "gesunde", | |
| 12 | + "gesundes", | |
| 13 | + "Gruen" | |
| 14 | + ] | |
| 15 | + }, | |
| 16 | + { | |
| 17 | + "value": "red", | |
| 18 | + "synonyms": [ | |
| 19 | + "rot", | |
| 20 | + "ungesund", | |
| 21 | + "ungesunde", | |
| 22 | + "Ungesundes", | |
| 23 | + "fettig" | |
| 24 | + ] | |
| 25 | + }, | |
| 26 | + { | |
| 27 | + "value": "yellow", | |
| 28 | + "synonyms": [ | |
| 29 | + "gelb", | |
| 30 | + "gelbe" | |
| 31 | + ] | |
| 32 | + } | |
| 33 | + ], | |
| 34 | + "isEnum": false, | |
| 35 | + "automatedExpansion": false | |
| 36 | +} | |
| 0 | 37 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/entities/ingredients.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/entities/ingredients.json | |
| 1 | +{ | |
| 2 | + "id": "a940b7e1-44fe-4ec6-8a2f-e330821c6a07", | |
| 3 | + "name": "ingredients", | |
| 4 | + "isOverridable": true, | |
| 5 | + "entries": [ | |
| 6 | + { | |
| 7 | + "value": "laktosefree", | |
| 8 | + "synonyms": [ | |
| 9 | + "laktosefrei", | |
| 10 | + "ohne Laktose" | |
| 11 | + ] | |
| 12 | + }, | |
| 13 | + { | |
| 14 | + "value": "glutenfree", | |
| 15 | + "synonyms": [ | |
| 16 | + "glutenfrei", | |
| 17 | + "ohne Gluten" | |
| 18 | + ] | |
| 19 | + }, | |
| 20 | + { | |
| 21 | + "value": "sugarfree", | |
| 22 | + "synonyms": [ | |
| 23 | + "zuckerfrei", | |
| 24 | + "ohne Zucker" | |
| 25 | + ] | |
| 26 | + } | |
| 27 | + ], | |
| 28 | + "isEnum": false, | |
| 29 | + "automatedExpansion": false | |
| 30 | +} | |
| 0 | 31 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/entities/price.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/entities/price.json | |
| 1 | +{ | |
| 2 | + "id": "92b3c202-7cd4-43b1-a9fb-856a20c2ff87", | |
| 3 | + "name": "price", | |
| 4 | + "isOverridable": true, | |
| 5 | + "entries": [ | |
| 6 | + { | |
| 7 | + "value": "howmuch", | |
| 8 | + "synonyms": [ | |
| 9 | + "howmuch", | |
| 10 | + "Was kostet", | |
| 11 | + "wie teuer" | |
| 12 | + ] | |
| 13 | + }, | |
| 14 | + { | |
| 15 | + "value": "under", | |
| 16 | + "synonyms": [ | |
| 17 | + "unter", | |
| 18 | + "under", | |
| 19 | + "weniger als" | |
| 20 | + ] | |
| 21 | + } | |
| 22 | + ], | |
| 23 | + "isEnum": false, | |
| 24 | + "automatedExpansion": false | |
| 25 | +} | |
| 0 | 26 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/intents/Bye.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/intents/Bye.json | |
| 1 | +{ | |
| 2 | + "userSays": [ | |
| 3 | + { | |
| 4 | + "id": "96688a3e-5905-4a32-8887-99735525f0b5", | |
| 5 | + "data": [ | |
| 6 | + { | |
| 7 | + "text": "Tschüss." | |
| 8 | + } | |
| 9 | + ], | |
| 10 | + "isTemplate": false, | |
| 11 | + "count": 0 | |
| 12 | + }, | |
| 13 | + { | |
| 14 | + "id": "540dc163-d340-4ccf-ac32-2a4b46af9ad7", | |
| 15 | + "data": [ | |
| 16 | + { | |
| 17 | + "text": "Bye", | |
| 18 | + "userDefined": false | |
| 19 | + } | |
| 20 | + ], | |
| 21 | + "isTemplate": false, | |
| 22 | + "count": 1 | |
| 23 | + }, | |
| 24 | + { | |
| 25 | + "id": "45422bce-8688-45e8-bcf0-88a4db4c3fb0", | |
| 26 | + "data": [ | |
| 27 | + { | |
| 28 | + "text": "Auf Wiedersehen" | |
| 29 | + } | |
| 30 | + ], | |
| 31 | + "isTemplate": false, | |
| 32 | + "count": 0 | |
| 33 | + }, | |
| 34 | + { | |
| 35 | + "id": "8ec89276-d8f4-4b92-bd5f-8d74e2fa7258", | |
| 36 | + "data": [ | |
| 37 | + { | |
| 38 | + "text": "tschüss" | |
| 39 | + } | |
| 40 | + ], | |
| 41 | + "isTemplate": false, | |
| 42 | + "count": 0 | |
| 43 | + }, | |
| 44 | + { | |
| 45 | + "id": "7667c3bf-c8ea-4628-a09c-84f9acbf5414", | |
| 46 | + "data": [ | |
| 47 | + { | |
| 48 | + "text": "adieu" | |
| 49 | + } | |
| 50 | + ], | |
| 51 | + "isTemplate": false, | |
| 52 | + "count": 0 | |
| 53 | + }, | |
| 54 | + { | |
| 55 | + "id": "daeb2cdc-a213-40b4-9dd1-3ad60f39d64a", | |
| 56 | + "data": [ | |
| 57 | + { | |
| 58 | + "text": "ciao" | |
| 59 | + } | |
| 60 | + ], | |
| 61 | + "isTemplate": false, | |
| 62 | + "count": 0 | |
| 63 | + }, | |
| 64 | + { | |
| 65 | + "id": "88a42bc6-db2f-4826-aea6-abb434ef07bb", | |
| 66 | + "data": [ | |
| 67 | + { | |
| 68 | + "text": "lebe wohl" | |
| 69 | + } | |
| 70 | + ], | |
| 71 | + "isTemplate": false, | |
| 72 | + "count": 0 | |
| 73 | + } | |
| 74 | + ], | |
| 75 | + "id": "31c24025-1d89-4dab-8f61-fe14a0687129", | |
| 76 | + "name": "Bye", | |
| 77 | + "auto": true, | |
| 78 | + "contexts": [], | |
| 79 | + "responses": [ | |
| 80 | + { | |
| 81 | + "resetContexts": false, | |
| 82 | + "affectedContexts": [], | |
| 83 | + "parameters": [], | |
| 84 | + "messages": [ | |
| 85 | + { | |
| 86 | + "type": 0, | |
| 87 | + "speech": [] | |
| 88 | + } | |
| 89 | + ], | |
| 90 | + "defaultResponsePlatforms": {} | |
| 91 | + } | |
| 92 | + ], | |
| 93 | + "priority": 500000, | |
| 94 | + "webhookUsed": false, | |
| 95 | + "webhookForSlotFilling": false, | |
| 96 | + "fallbackIntent": false, | |
| 97 | + "events": [] | |
| 98 | +} | |
| 0 | 99 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/intents/Fallback.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/intents/Fallback.json | |
| 1 | +{ | |
| 2 | + "userSays": [], | |
| 3 | + "id": "27e9cc67-9092-47a7-a09a-04a876334133", | |
| 4 | + "name": "Fallback", | |
| 5 | + "auto": false, | |
| 6 | + "contexts": [], | |
| 7 | + "responses": [ | |
| 8 | + { | |
| 9 | + "resetContexts": false, | |
| 10 | + "affectedContexts": [], | |
| 11 | + "parameters": [], | |
| 12 | + "messages": [], | |
| 13 | + "defaultResponsePlatforms": {} | |
| 14 | + } | |
| 15 | + ], | |
| 16 | + "priority": 500000, | |
| 17 | + "webhookUsed": false, | |
| 18 | + "webhookForSlotFilling": false, | |
| 19 | + "fallbackIntent": true, | |
| 20 | + "events": [] | |
| 21 | +} | |
| 0 | 22 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/intents/Hello.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/intents/Hello.json | |
| 1 | +{ | |
| 2 | + "userSays": [ | |
| 3 | + { | |
| 4 | + "id": "a46d8cf9-13f8-4f7e-a6b6-701b616d3b1b", | |
| 5 | + "data": [ | |
| 6 | + { | |
| 7 | + "text": "Mahlzeit!" | |
| 8 | + } | |
| 9 | + ], | |
| 10 | + "isTemplate": false, | |
| 11 | + "count": 2 | |
| 12 | + }, | |
| 13 | + { | |
| 14 | + "id": "7e2cb139-ac8c-48f8-937f-5e561d7a5b21", | |
| 15 | + "data": [ | |
| 16 | + { | |
| 17 | + "text": "Hallo" | |
| 18 | + } | |
| 19 | + ], | |
| 20 | + "isTemplate": false, | |
| 21 | + "count": 1 | |
| 22 | + }, | |
| 23 | + { | |
| 24 | + "id": "c071bead-c204-416b-b6ed-74965cb1f12c", | |
| 25 | + "data": [ | |
| 26 | + { | |
| 27 | + "text": "Hallo bot." | |
| 28 | + } | |
| 29 | + ], | |
| 30 | + "isTemplate": false, | |
| 31 | + "count": 0 | |
| 32 | + }, | |
| 33 | + { | |
| 34 | + "id": "6aec7f9f-1ea8-4004-a6e2-eb0dd8274d5f", | |
| 35 | + "data": [ | |
| 36 | + { | |
| 37 | + "text": "hallo" | |
| 38 | + } | |
| 39 | + ], | |
| 40 | + "isTemplate": false, | |
| 41 | + "count": 7 | |
| 42 | + }, | |
| 43 | + { | |
| 44 | + "id": "55cd7273-87cf-472a-89b7-2664fd45982c", | |
| 45 | + "data": [ | |
| 46 | + { | |
| 47 | + "text": "Hallo Bot", | |
| 48 | + "userDefined": false | |
| 49 | + } | |
| 50 | + ], | |
| 51 | + "isTemplate": false, | |
| 52 | + "count": 0 | |
| 53 | + }, | |
| 54 | + { | |
| 55 | + "id": "fe2d3681-3461-4e71-a80a-f3755d03db89", | |
| 56 | + "data": [ | |
| 57 | + { | |
| 58 | + "text": "Hallo du", | |
| 59 | + "userDefined": false | |
| 60 | + } | |
| 61 | + ], | |
| 62 | + "isTemplate": false, | |
| 63 | + "count": 0 | |
| 64 | + }, | |
| 65 | + { | |
| 66 | + "id": "f39e8b17-6baf-4a7f-a130-029ed0486190", | |
| 67 | + "data": [ | |
| 68 | + { | |
| 69 | + "text": "Heyho" | |
| 70 | + } | |
| 71 | + ], | |
| 72 | + "isTemplate": false, | |
| 73 | + "count": 2 | |
| 74 | + }, | |
| 75 | + { | |
| 76 | + "id": "8a034279-2ae7-41f8-ace2-0be60fc11843", | |
| 77 | + "data": [ | |
| 78 | + { | |
| 79 | + "text": "Hallo Welt" | |
| 80 | + } | |
| 81 | + ], | |
| 82 | + "isTemplate": false, | |
| 83 | + "count": 0 | |
| 84 | + }, | |
| 85 | + { | |
| 86 | + "id": "27ade6fd-22a8-4026-80a0-dc464a133e5d", | |
| 87 | + "data": [ | |
| 88 | + { | |
| 89 | + "text": "Guten Tag" | |
| 90 | + } | |
| 91 | + ], | |
| 92 | + "isTemplate": false, | |
| 93 | + "count": 1 | |
| 94 | + }, | |
| 95 | + { | |
| 96 | + "id": "8251e097-7f65-46c8-82d7-4521360823f8", | |
| 97 | + "data": [ | |
| 98 | + { | |
| 99 | + "text": "Hello", | |
| 100 | + "userDefined": false | |
| 101 | + } | |
| 102 | + ], | |
| 103 | + "isTemplate": false, | |
| 104 | + "count": 1 | |
| 105 | + }, | |
| 106 | + { | |
| 107 | + "id": "7c16e6f9-df2c-44f7-ba9a-36315a5e9f47", | |
| 108 | + "data": [ | |
| 109 | + { | |
| 110 | + "text": "Hello Bot", | |
| 111 | + "userDefined": false | |
| 112 | + } | |
| 113 | + ], | |
| 114 | + "isTemplate": false, | |
| 115 | + "count": 0 | |
| 116 | + }, | |
| 117 | + { | |
| 118 | + "id": "535a9275-ab39-43f9-87df-431be10d09d5", | |
| 119 | + "data": [ | |
| 120 | + { | |
| 121 | + "text": "Tag" | |
| 122 | + } | |
| 123 | + ], | |
| 124 | + "isTemplate": false, | |
| 125 | + "count": 0 | |
| 126 | + }, | |
| 127 | + { | |
| 128 | + "id": "df882ea3-1cdb-4797-8d70-c3b661839f9b", | |
| 129 | + "data": [ | |
| 130 | + { | |
| 131 | + "text": "Servus" | |
| 132 | + } | |
| 133 | + ], | |
| 134 | + "isTemplate": false, | |
| 135 | + "count": 0 | |
| 136 | + }, | |
| 137 | + { | |
| 138 | + "id": "0aa700e1-6b51-4921-8c2d-c294ef7769cd", | |
| 139 | + "data": [ | |
| 140 | + { | |
| 141 | + "text": "Moin" | |
| 142 | + } | |
| 143 | + ], | |
| 144 | + "isTemplate": false, | |
| 145 | + "count": 0 | |
| 146 | + }, | |
| 147 | + { | |
| 148 | + "id": "9b7d796f-7c54-40f8-a04f-ceaea25d9b94", | |
| 149 | + "data": [ | |
| 150 | + { | |
| 151 | + "text": "Hi" | |
| 152 | + } | |
| 153 | + ], | |
| 154 | + "isTemplate": false, | |
| 155 | + "count": 0 | |
| 156 | + } | |
| 157 | + ], | |
| 158 | + "id": "298d49fa-5122-430d-bd63-ee2d4316274d", | |
| 159 | + "name": "Hello", | |
| 160 | + "auto": true, | |
| 161 | + "contexts": [], | |
| 162 | + "responses": [ | |
| 163 | + { | |
| 164 | + "resetContexts": false, | |
| 165 | + "affectedContexts": [], | |
| 166 | + "parameters": [], | |
| 167 | + "messages": [ | |
| 168 | + { | |
| 169 | + "type": 0, | |
| 170 | + "speech": [] | |
| 171 | + } | |
| 172 | + ], | |
| 173 | + "defaultResponsePlatforms": {} | |
| 174 | + } | |
| 175 | + ], | |
| 176 | + "priority": 500000, | |
| 177 | + "webhookUsed": false, | |
| 178 | + "webhookForSlotFilling": false, | |
| 179 | + "fallbackIntent": false, | |
| 180 | + "events": [] | |
| 181 | +} | |
| 0 | 182 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/intents/Start.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/intents/Start.json | |
| 1 | +{ | |
| 2 | + "userSays": [ | |
| 3 | + { | |
| 4 | + "id": "999fcf31-211e-4c43-a48c-200b2cc4ad0f", | |
| 5 | + "data": [ | |
| 6 | + { | |
| 7 | + "text": "start", | |
| 8 | + "userDefined": false | |
| 9 | + } | |
| 10 | + ], | |
| 11 | + "isTemplate": false, | |
| 12 | + "count": 1 | |
| 13 | + }, | |
| 14 | + { | |
| 15 | + "id": "b0d6aef8-fa8d-4151-b1f2-41162374f60d", | |
| 16 | + "data": [ | |
| 17 | + { | |
| 18 | + "text": "/start" | |
| 19 | + } | |
| 20 | + ], | |
| 21 | + "isTemplate": false, | |
| 22 | + "count": 1 | |
| 23 | + }, | |
| 24 | + { | |
| 25 | + "id": "a775b2f8-984a-4e4f-be8e-92dcf9d426a9", | |
| 26 | + "data": [ | |
| 27 | + { | |
| 28 | + "text": "Start" | |
| 29 | + } | |
| 30 | + ], | |
| 31 | + "isTemplate": false, | |
| 32 | + "count": 1 | |
| 33 | + } | |
| 34 | + ], | |
| 35 | + "id": "fd44ae16-5a7d-40d6-9216-cf528db47b93", | |
| 36 | + "name": "Start", | |
| 37 | + "auto": true, | |
| 38 | + "contexts": [], | |
| 39 | + "responses": [ | |
| 40 | + { | |
| 41 | + "resetContexts": false, | |
| 42 | + "affectedContexts": [], | |
| 43 | + "parameters": [], | |
| 44 | + "messages": [ | |
| 45 | + { | |
| 46 | + "type": 0, | |
| 47 | + "speech": [] | |
| 48 | + } | |
| 49 | + ] | |
| 50 | + } | |
| 51 | + ], | |
| 52 | + "priority": 500000, | |
| 53 | + "webhookUsed": false, | |
| 54 | + "webhookForSlotFilling": false, | |
| 55 | + "fallbackIntent": false, | |
| 56 | + "events": [] | |
| 57 | +} | |
| 0 | 58 | \ No newline at end of file | ... | ... |
docker/rasa_nlu/volumes/data/api/intents/showFood.json
0 → 100755
| 1 | +++ a/docker/rasa_nlu/volumes/data/api/intents/showFood.json | |
| 1 | +{ | |
| 2 | + "userSays": [ | |
| 3 | + { | |
| 4 | + "id": "fd32ca0d-bb7f-4d03-b1c8-5ad41ae4847a", | |
| 5 | + "data": [ | |
| 6 | + { | |
| 7 | + "text": "Bitte nur " | |
| 8 | + }, | |
| 9 | + { | |
| 10 | + "text": "vegetarisches", | |
| 11 | + "alias": "dishtype", | |
| 12 | + "meta": "@dishtype", | |
| 13 | + "userDefined": false | |
| 14 | + } | |
| 15 | + ], | |
| 16 | + "isTemplate": false, | |
| 17 | + "count": 0 | |
| 18 | + }, | |
| 19 | + { | |
| 20 | + "id": "7b2cce20-9ea4-4532-90f6-d86374d4ece6", | |
| 21 | + "data": [ | |
| 22 | + { | |
| 23 | + "text": "Schön " | |
| 24 | + }, | |
| 25 | + { | |
| 26 | + "text": "fettig", | |
| 27 | + "alias": "healthy", | |
| 28 | + "meta": "@healthy", | |
| 29 | + "userDefined": false | |
| 30 | + } | |
| 31 | + ], | |
| 32 | + "isTemplate": false, | |
| 33 | + "count": 0 | |
| 34 | + }, | |
| 35 | + { | |
| 36 | + "id": "56891d52-fe5c-4669-b4f4-20d394d0f291", | |
| 37 | + "data": [ | |
| 38 | + { | |
| 39 | + "text": "was gibt\u0027s zum " | |
| 40 | + }, | |
| 41 | + { | |
| 42 | + "text": "Nachtisch", | |
| 43 | + "alias": "dishcategory", | |
| 44 | + "meta": "@dishcategory", | |
| 45 | + "userDefined": false | |
| 46 | + }, | |
| 47 | + { | |
| 48 | + "text": "?" | |
| 49 | + } | |
| 50 | + ], | |
| 51 | + "isTemplate": false, | |
| 52 | + "count": 0 | |
| 53 | + }, | |
| 54 | + { | |
| 55 | + "id": "b85b0135-3a69-4564-9fea-d6dc168673c5", | |
| 56 | + "data": [ | |
| 57 | + { | |
| 58 | + "text": "Was gibt es " | |
| 59 | + }, | |
| 60 | + { | |
| 61 | + "text": "gesundes", | |
| 62 | + "alias": "healthy", | |
| 63 | + "meta": "@healthy", | |
| 64 | + "userDefined": false | |
| 65 | + } | |
| 66 | + ], | |
| 67 | + "isTemplate": false, | |
| 68 | + "count": 0 | |
| 69 | + }, | |
| 70 | + { | |
| 71 | + "id": "86306079-6fb2-4a85-a024-a415f67d17c2", | |
| 72 | + "data": [ | |
| 73 | + { | |
| 74 | + "text": "Wat gibts " | |
| 75 | + }, | |
| 76 | + { | |
| 77 | + "text": "gesundes", | |
| 78 | + "alias": "healthy", | |
| 79 | + "meta": "@healthy", | |
| 80 | + "userDefined": false | |
| 81 | + } | |
| 82 | + ], | |
| 83 | + "isTemplate": false, | |
| 84 | + "count": 0 | |
| 85 | + }, | |
| 86 | + { | |
| 87 | + "id": "d3bddb57-2a96-42d4-9517-2fe39b7eb81b", | |
| 88 | + "data": [ | |
| 89 | + { | |
| 90 | + "text": "Ick hab Knast" | |
| 91 | + } | |
| 92 | + ], | |
| 93 | + "isTemplate": false, | |
| 94 | + "count": 0 | |
| 95 | + }, | |
| 96 | + { | |
| 97 | + "id": "762b3473-f577-4b6f-9130-4cc36c9fea6c", | |
| 98 | + "data": [ | |
| 99 | + { | |
| 100 | + "text": "Man...! Sach mir was es zu " | |
| 101 | + }, | |
| 102 | + { | |
| 103 | + "text": "essen", | |
| 104 | + "meta": "@sys.ignore", | |
| 105 | + "userDefined": false | |
| 106 | + }, | |
| 107 | + { | |
| 108 | + "text": " gibt!" | |
| 109 | + } | |
| 110 | + ], | |
| 111 | + "isTemplate": false, | |
| 112 | + "count": 0 | |
| 113 | + }, | |
| 114 | + { | |
| 115 | + "id": "024e9b2b-6030-4e71-8a26-c1b2dcd302d2", | |
| 116 | + "data": [ | |
| 117 | + { | |
| 118 | + "text": "Zeig mir " | |
| 119 | + }, | |
| 120 | + { | |
| 121 | + "text": "futter", | |
| 122 | + "meta": "@sys.ignore", | |
| 123 | + "userDefined": false | |
| 124 | + } | |
| 125 | + ], | |
| 126 | + "isTemplate": false, | |
| 127 | + "count": 0 | |
| 128 | + }, | |
| 129 | + { | |
| 130 | + "id": "37884b73-ef5c-4788-8286-48741d1687ab", | |
| 131 | + "data": [ | |
| 132 | + { | |
| 133 | + "text": "Was gibbet" | |
| 134 | + } | |
| 135 | + ], | |
| 136 | + "isTemplate": false, | |
| 137 | + "count": 0 | |
| 138 | + }, | |
| 139 | + { | |
| 140 | + "id": "900ae728-5008-4ac1-a27e-9a5663b1f8a0", | |
| 141 | + "data": [ | |
| 142 | + { | |
| 143 | + "text": "Grün", | |
| 144 | + "alias": "healthy", | |
| 145 | + "meta": "@healthy", | |
| 146 | + "userDefined": false | |
| 147 | + } | |
| 148 | + ], | |
| 149 | + "isTemplate": false, | |
| 150 | + "count": 0 | |
| 151 | + }, | |
| 152 | + { | |
| 153 | + "id": "add47ed0-8ef8-4ff9-90e6-acdc33ea4b3c", | |
| 154 | + "data": [ | |
| 155 | + { | |
| 156 | + "text": "Was gibt es " | |
| 157 | + }, | |
| 158 | + { | |
| 159 | + "text": "heute", | |
| 160 | + "alias": "date", | |
| 161 | + "meta": "@date", | |
| 162 | + "userDefined": false | |
| 163 | + }, | |
| 164 | + { | |
| 165 | + "text": " zu Essen?" | |
| 166 | + } | |
| 167 | + ], | |
| 168 | + "isTemplate": false, | |
| 169 | + "count": 0 | |
| 170 | + }, | |
| 171 | + { | |
| 172 | + "id": "76068d03-8dfa-4053-a4d7-f9580d7c1269", | |
| 173 | + "data": [ | |
| 174 | + { | |
| 175 | + "text": "Gibt es irgendetwas " | |
| 176 | + }, | |
| 177 | + { | |
| 178 | + "text": "vegetarisches", | |
| 179 | + "alias": "dishtype", | |
| 180 | + "meta": "@dishtype", | |
| 181 | + "userDefined": false | |
| 182 | + }, | |
| 183 | + { | |
| 184 | + "text": "?" | |
| 185 | + } | |
| 186 | + ], | |
| 187 | + "isTemplate": false, | |
| 188 | + "count": 0 | |
| 189 | + }, | |
| 190 | + { | |
| 191 | + "id": "4fe7e652-929b-4a3b-840b-b24e1ecb9fcc", | |
| 192 | + "data": [ | |
| 193 | + { | |
| 194 | + "text": "Was gibt es " | |
| 195 | + }, | |
| 196 | + { | |
| 197 | + "text": "morgen", | |
| 198 | + "alias": "date", | |
| 199 | + "meta": "@date", | |
| 200 | + "userDefined": false | |
| 201 | + }, | |
| 202 | + { | |
| 203 | + "text": " " | |
| 204 | + }, | |
| 205 | + { | |
| 206 | + "text": "veganes", | |
| 207 | + "alias": "dishtype", | |
| 208 | + "meta": "@dishtype", | |
| 209 | + "userDefined": false | |
| 210 | + }, | |
| 211 | + { | |
| 212 | + "text": "?" | |
| 213 | + } | |
| 214 | + ], | |
| 215 | + "isTemplate": false, | |
| 216 | + "count": 0 | |
| 217 | + }, | |
| 218 | + { | |
| 219 | + "id": "7bac360a-65db-4698-b9fc-81024a052f7c", | |
| 220 | + "data": [ | |
| 221 | + { | |
| 222 | + "text": "Was gibt es für " | |
| 223 | + }, | |
| 224 | + { | |
| 225 | + "text": "Suppen", | |
| 226 | + "alias": "dishcategory", | |
| 227 | + "meta": "@dishcategory", | |
| 228 | + "userDefined": false | |
| 229 | + } | |
| 230 | + ], | |
| 231 | + "isTemplate": false, | |
| 232 | + "count": 0 | |
| 233 | + }, | |
| 234 | + { | |
| 235 | + "id": "1407d888-0d5a-451b-8d30-6c804dec373c", | |
| 236 | + "data": [ | |
| 237 | + { | |
| 238 | + "text": "Welche " | |
| 239 | + }, | |
| 240 | + { | |
| 241 | + "text": "Vorspeisen", | |
| 242 | + "alias": "dishcategory", | |
| 243 | + "meta": "@dishcategory", | |
| 244 | + "userDefined": false | |
| 245 | + }, | |
| 246 | + { | |
| 247 | + "text": " gibt es " | |
| 248 | + }, | |
| 249 | + { | |
| 250 | + "text": "heute", | |
| 251 | + "alias": "date", | |
| 252 | + "meta": "@date", | |
| 253 | + "userDefined": false | |
| 254 | + }, | |
| 255 | + { | |
| 256 | + "text": "?" | |
| 257 | + } | |
| 258 | + ], | |
| 259 | + "isTemplate": false, | |
| 260 | + "count": 0 | |
| 261 | + }, | |
| 262 | + { | |
| 263 | + "id": "d7fc8387-d1c6-4ed2-aeeb-a12466ebb7bb", | |
| 264 | + "data": [ | |
| 265 | + { | |
| 266 | + "text": "Was gibt es " | |
| 267 | + }, | |
| 268 | + { | |
| 269 | + "text": "heute", | |
| 270 | + "alias": "date", | |
| 271 | + "meta": "@date", | |
| 272 | + "userDefined": false | |
| 273 | + }, | |
| 274 | + { | |
| 275 | + "text": " zu essen?" | |
| 276 | + } | |
| 277 | + ], | |
| 278 | + "isTemplate": false, | |
| 279 | + "count": 0 | |
| 280 | + }, | |
| 281 | + { | |
| 282 | + "id": "3589c50d-8ec0-4276-aa21-a88145530ddb", | |
| 283 | + "data": [ | |
| 284 | + { | |
| 285 | + "text": "Was gibt es zu essen?" | |
| 286 | + } | |
| 287 | + ], | |
| 288 | + "isTemplate": false, | |
| 289 | + "count": 0 | |
| 290 | + }, | |
| 291 | + { | |
| 292 | + "id": "1f9d235d-eaae-4999-b5d2-0d19720e90e9", | |
| 293 | + "data": [ | |
| 294 | + { | |
| 295 | + "text": "Zeige mir " | |
| 296 | + }, | |
| 297 | + { | |
| 298 | + "text": "gesunde", | |
| 299 | + "alias": "healthy", | |
| 300 | + "meta": "@healthy", | |
| 301 | + "userDefined": true | |
| 302 | + }, | |
| 303 | + { | |
| 304 | + "text": " " | |
| 305 | + }, | |
| 306 | + { | |
| 307 | + "text": "Hauptgerichte", | |
| 308 | + "alias": "dishcategory", | |
| 309 | + "meta": "@dishcategory", | |
| 310 | + "userDefined": true | |
| 311 | + }, | |
| 312 | + { | |
| 313 | + "text": " " | |
| 314 | + }, | |
| 315 | + { | |
| 316 | + "text": "unter", | |
| 317 | + "alias": "price", | |
| 318 | + "meta": "@price", | |
| 319 | + "userDefined": true | |
| 320 | + }, | |
| 321 | + { | |
| 322 | + "text": " " | |
| 323 | + }, | |
| 324 | + { | |
| 325 | + "text": "5", | |
| 326 | + "meta": "@sys.ignore", | |
| 327 | + "userDefined": true | |
| 328 | + }, | |
| 329 | + { | |
| 330 | + "text": " Euro" | |
| 331 | + } | |
| 332 | + ], | |
| 333 | + "isTemplate": false, | |
| 334 | + "count": 0 | |
| 335 | + }, | |
| 336 | + { | |
| 337 | + "id": "8efb4896-f4ff-4864-af90-7e2b594afd4a", | |
| 338 | + "data": [ | |
| 339 | + { | |
| 340 | + "text": "Gibt es " | |
| 341 | + }, | |
| 342 | + { | |
| 343 | + "text": "heute", | |
| 344 | + "alias": "date", | |
| 345 | + "meta": "@date", | |
| 346 | + "userDefined": true | |
| 347 | + }, | |
| 348 | + { | |
| 349 | + "text": " " | |
| 350 | + }, | |
| 351 | + { | |
| 352 | + "text": "Hauptgerichte", | |
| 353 | + "alias": "dishcategory", | |
| 354 | + "meta": "@dishcategory", | |
| 355 | + "userDefined": true | |
| 356 | + }, | |
| 357 | + { | |
| 358 | + "text": "?" | |
| 359 | + } | |
| 360 | + ], | |
| 361 | + "isTemplate": false, | |
| 362 | + "count": 0 | |
| 363 | + }, | |
| 364 | + { | |
| 365 | + "id": "daab71ce-3882-42e9-8749-30cb4e1b41ee", | |
| 366 | + "data": [ | |
| 367 | + { | |
| 368 | + "text": "Gibt es " | |
| 369 | + }, | |
| 370 | + { | |
| 371 | + "text": "heute", | |
| 372 | + "alias": "date", | |
| 373 | + "meta": "@date", | |
| 374 | + "userDefined": true | |
| 375 | + }, | |
| 376 | + { | |
| 377 | + "text": " " | |
| 378 | + }, | |
| 379 | + { | |
| 380 | + "text": "vegetarische", | |
| 381 | + "alias": "dishtype", | |
| 382 | + "meta": "@dishtype", | |
| 383 | + "userDefined": true | |
| 384 | + }, | |
| 385 | + { | |
| 386 | + "text": " " | |
| 387 | + }, | |
| 388 | + { | |
| 389 | + "text": "Hauptgerichte", | |
| 390 | + "alias": "dishcategory", | |
| 391 | + "meta": "@dishcategory", | |
| 392 | + "userDefined": true | |
| 393 | + }, | |
| 394 | + { | |
| 395 | + "text": "?" | |
| 396 | + } | |
| 397 | + ], | |
| 398 | + "isTemplate": false, | |
| 399 | + "count": 0 | |
| 400 | + }, | |
| 401 | + { | |
| 402 | + "id": "ca1f84cc-504e-4c2c-9ba4-b6917653d396", | |
| 403 | + "data": [ | |
| 404 | + { | |
| 405 | + "text": "Was für " | |
| 406 | + }, | |
| 407 | + { | |
| 408 | + "text": "Hauptgerichte", | |
| 409 | + "alias": "dishcategory", | |
| 410 | + "meta": "@dishcategory", | |
| 411 | + "userDefined": true | |
| 412 | + }, | |
| 413 | + { | |
| 414 | + "text": " gibt es " | |
| 415 | + }, | |
| 416 | + { | |
| 417 | + "text": "heute", | |
| 418 | + "alias": "date", | |
| 419 | + "meta": "@date", | |
| 420 | + "userDefined": true | |
| 421 | + }, | |
| 422 | + { | |
| 423 | + "text": "?" | |
| 424 | + } | |
| 425 | + ], | |
| 426 | + "isTemplate": false, | |
| 427 | + "count": 0 | |
| 428 | + }, | |
| 429 | + { | |
| 430 | + "id": "3635fca1-e08b-49e2-93f5-754244a0b895", | |
| 431 | + "data": [ | |
| 432 | + { | |
| 433 | + "text": "Zeige mir " | |
| 434 | + }, | |
| 435 | + { | |
| 436 | + "text": "Suppen", | |
| 437 | + "alias": "dishcategory", | |
| 438 | + "meta": "@dishcategory", | |
| 439 | + "userDefined": true | |
| 440 | + }, | |
| 441 | + { | |
| 442 | + "text": " für " | |
| 443 | + }, | |
| 444 | + { | |
| 445 | + "text": "weniger als", | |
| 446 | + "alias": "price", | |
| 447 | + "meta": "@price", | |
| 448 | + "userDefined": true | |
| 449 | + }, | |
| 450 | + { | |
| 451 | + "text": " " | |
| 452 | + }, | |
| 453 | + { | |
| 454 | + "text": "2", | |
| 455 | + "meta": "@sys.ignore", | |
| 456 | + "userDefined": true | |
| 457 | + }, | |
| 458 | + { | |
| 459 | + "text": "€" | |
| 460 | + } | |
| 461 | + ], | |
| 462 | + "isTemplate": false, | |
| 463 | + "count": 0 | |
| 464 | + }, | |
| 465 | + { | |
| 466 | + "id": "68051902-f5a0-4c6e-8233-f390cd37299e", | |
| 467 | + "data": [ | |
| 468 | + { | |
| 469 | + "text": "Zeige " | |
| 470 | + }, | |
| 471 | + { | |
| 472 | + "text": "Hauptgerichte", | |
| 473 | + "alias": "dishcategory", | |
| 474 | + "meta": "@dishcategory", | |
| 475 | + "userDefined": true | |
| 476 | + }, | |
| 477 | + { | |
| 478 | + "text": " unter " | |
| 479 | + }, | |
| 480 | + { | |
| 481 | + "text": "5", | |
| 482 | + "meta": "@sys.ignore", | |
| 483 | + "userDefined": true | |
| 484 | + }, | |
| 485 | + { | |
| 486 | + "text": " Euro" | |
| 487 | + } | |
| 488 | + ], | |
| 489 | + "isTemplate": false, | |
| 490 | + "count": 0 | |
| 491 | + }, | |
| 492 | + { | |
| 493 | + "id": "76436c32-a320-4e39-929e-74fd301ea362", | |
| 494 | + "data": [ | |
| 495 | + { | |
| 496 | + "text": "Was kostet " | |
| 497 | + }, | |
| 498 | + { | |
| 499 | + "text": "weniger als", | |
| 500 | + "alias": "price", | |
| 501 | + "meta": "@price", | |
| 502 | + "userDefined": true | |
| 503 | + }, | |
| 504 | + { | |
| 505 | + "text": " " | |
| 506 | + }, | |
| 507 | + { | |
| 508 | + "text": "5", | |
| 509 | + "meta": "@sys.ignore", | |
| 510 | + "userDefined": true | |
| 511 | + }, | |
| 512 | + { | |
| 513 | + "text": "€?" | |
| 514 | + } | |
| 515 | + ], | |
| 516 | + "isTemplate": false, | |
| 517 | + "count": 0 | |
| 518 | + }, | |
| 519 | + { | |
| 520 | + "id": "fcd4493e-a39e-457b-801b-9514d4312b8c", | |
| 521 | + "data": [ | |
| 522 | + { | |
| 523 | + "text": "Was gibt es heute in der Mensa " | |
| 524 | + }, | |
| 525 | + { | |
| 526 | + "text": "unter", | |
| 527 | + "alias": "price", | |
| 528 | + "meta": "@price", | |
| 529 | + "userDefined": true | |
| 530 | + }, | |
| 531 | + { | |
| 532 | + "text": " " | |
| 533 | + }, | |
| 534 | + { | |
| 535 | + "text": "2", | |
| 536 | + "meta": "@sys.ignore", | |
| 537 | + "userDefined": true | |
| 538 | + }, | |
| 539 | + { | |
| 540 | + "text": " Euro?" | |
| 541 | + } | |
| 542 | + ], | |
| 543 | + "isTemplate": false, | |
| 544 | + "count": 0 | |
| 545 | + }, | |
| 546 | + { | |
| 547 | + "id": "c7bccc6f-4bcd-43a7-bf82-6edf055fb9f1", | |
| 548 | + "data": [ | |
| 549 | + { | |
| 550 | + "text": "Wie teuer", | |
| 551 | + "alias": "price", | |
| 552 | + "meta": "@price", | |
| 553 | + "userDefined": true | |
| 554 | + }, | |
| 555 | + { | |
| 556 | + "text": " ist ein großer " | |
| 557 | + }, | |
| 558 | + { | |
| 559 | + "text": "Salat", | |
| 560 | + "alias": "dishcategory", | |
| 561 | + "meta": "@dishcategory", | |
| 562 | + "userDefined": true | |
| 563 | + }, | |
| 564 | + { | |
| 565 | + "text": "?" | |
| 566 | + } | |
| 567 | + ], | |
| 568 | + "isTemplate": false, | |
| 569 | + "count": 0 | |
| 570 | + }, | |
| 571 | + { | |
| 572 | + "id": "76d924f8-3ebb-452b-834b-a701d0294112", | |
| 573 | + "data": [ | |
| 574 | + { | |
| 575 | + "text": "Was gibt es " | |
| 576 | + }, | |
| 577 | + { | |
| 578 | + "text": "über morgen", | |
| 579 | + "alias": "date", | |
| 580 | + "meta": "@date", | |
| 581 | + "userDefined": true | |
| 582 | + }, | |
| 583 | + { | |
| 584 | + "text": " in der Mensa?" | |
| 585 | + } | |
| 586 | + ], | |
| 587 | + "isTemplate": false, | |
| 588 | + "count": 1 | |
| 589 | + }, | |
| 590 | + { | |
| 591 | + "id": "03c11ea5-acca-4903-aee3-12ccc005fd27", | |
| 592 | + "data": [ | |
| 593 | + { | |
| 594 | + "text": "Was gibt es " | |
| 595 | + }, | |
| 596 | + { | |
| 597 | + "text": "morgen", | |
| 598 | + "alias": "date", | |
| 599 | + "meta": "@date", | |
| 600 | + "userDefined": true | |
| 601 | + }, | |
| 602 | + { | |
| 603 | + "text": " zu essen?" | |
| 604 | + } | |
| 605 | + ], | |
| 606 | + "isTemplate": false, | |
| 607 | + "count": 0 | |
| 608 | + }, | |
| 609 | + { | |
| 610 | + "id": "659ad693-d0bf-4586-a831-fb9fd83d2f57", | |
| 611 | + "data": [ | |
| 612 | + { | |
| 613 | + "text": "Was gibt es am " | |
| 614 | + }, | |
| 615 | + { | |
| 616 | + "text": "Dienstag", | |
| 617 | + "alias": "date", | |
| 618 | + "meta": "@date", | |
| 619 | + "userDefined": true | |
| 620 | + }, | |
| 621 | + { | |
| 622 | + "text": " zu essen?" | |
| 623 | + } | |
| 624 | + ], | |
| 625 | + "isTemplate": false, | |
| 626 | + "count": 0 | |
| 627 | + }, | |
| 628 | + { | |
| 629 | + "id": "dbfd7a39-dd3c-4d67-8190-5293d17efb72", | |
| 630 | + "data": [ | |
| 631 | + { | |
| 632 | + "text": "Was kostet", | |
| 633 | + "alias": "price", | |
| 634 | + "meta": "@price", | |
| 635 | + "userDefined": true | |
| 636 | + }, | |
| 637 | + { | |
| 638 | + "text": " die " | |
| 639 | + }, | |
| 640 | + { | |
| 641 | + "text": "Currywurst", | |
| 642 | + "alias": "ingredients", | |
| 643 | + "meta": "@ingredients", | |
| 644 | + "userDefined": true | |
| 645 | + }, | |
| 646 | + { | |
| 647 | + "text": "?" | |
| 648 | + } | |
| 649 | + ], | |
| 650 | + "isTemplate": false, | |
| 651 | + "count": 0 | |
| 652 | + }, | |
| 653 | + { | |
| 654 | + "id": "e5883e1d-4fba-457a-93d1-8c42827864f3", | |
| 655 | + "data": [ | |
| 656 | + { | |
| 657 | + "text": "Habe Lust auf " | |
| 658 | + }, | |
| 659 | + { | |
| 660 | + "text": "Suppe", | |
| 661 | + "alias": "dishcategory", | |
| 662 | + "meta": "@dishcategory", | |
| 663 | + "userDefined": true | |
| 664 | + }, | |
| 665 | + { | |
| 666 | + "text": ". Gibt es da heute was?" | |
| 667 | + } | |
| 668 | + ], | |
| 669 | + "isTemplate": false, | |
| 670 | + "count": 0 | |
| 671 | + }, | |
| 672 | + { | |
| 673 | + "id": "9133cd15-77ae-456d-b645-f4cb006a6e88", | |
| 674 | + "data": [ | |
| 675 | + { | |
| 676 | + "text": "was gibt es " | |
| 677 | + }, | |
| 678 | + { | |
| 679 | + "text": "heute", | |
| 680 | + "alias": "date", | |
| 681 | + "meta": "@date", | |
| 682 | + "userDefined": false | |
| 683 | + }, | |
| 684 | + { | |
| 685 | + "text": " in der mensa" | |
| 686 | + } | |
| 687 | + ], | |
| 688 | + "isTemplate": false, | |
| 689 | + "count": 23 | |
| 690 | + }, | |
| 691 | + { | |
| 692 | + "id": "d9491ecb-a4ef-4890-8c11-e1a74e3f6821", | |
| 693 | + "data": [ | |
| 694 | + { | |
| 695 | + "text": "was gibt es " | |
| 696 | + }, | |
| 697 | + { | |
| 698 | + "text": "heute", | |
| 699 | + "alias": "date", | |
| 700 | + "meta": "@date", | |
| 701 | + "userDefined": false | |
| 702 | + }, | |
| 703 | + { | |
| 704 | + "text": " " | |
| 705 | + }, | |
| 706 | + { | |
| 707 | + "text": "veganes", | |
| 708 | + "alias": "dishtype", | |
| 709 | + "meta": "@dishtype", | |
| 710 | + "userDefined": false | |
| 711 | + }, | |
| 712 | + { | |
| 713 | + "text": " in der mensa" | |
| 714 | + } | |
| 715 | + ], | |
| 716 | + "isTemplate": false, | |
| 717 | + "count": 4 | |
| 718 | + }, | |
| 719 | + { | |
| 720 | + "id": "23bbbd06-8919-49b4-8b77-f4f7167a71fa", | |
| 721 | + "data": [ | |
| 722 | + { | |
| 723 | + "text": "Was gibt es " | |
| 724 | + }, | |
| 725 | + { | |
| 726 | + "text": "morgen", | |
| 727 | + "alias": "date", | |
| 728 | + "meta": "@date", | |
| 729 | + "userDefined": false | |
| 730 | + }, | |
| 731 | + { | |
| 732 | + "text": " für " | |
| 733 | + }, | |
| 734 | + { | |
| 735 | + "text": "vegane", | |
| 736 | + "alias": "dishtype", | |
| 737 | + "meta": "@dishtype", | |
| 738 | + "userDefined": true | |
| 739 | + }, | |
| 740 | + { | |
| 741 | + "text": " Gerichte?" | |
| 742 | + } | |
| 743 | + ], | |
| 744 | + "isTemplate": false, | |
| 745 | + "count": 2 | |
| 746 | + }, | |
| 747 | + { | |
| 748 | + "id": "d288cb87-12fc-4875-947d-71d6094690ab", | |
| 749 | + "data": [ | |
| 750 | + { | |
| 751 | + "text": "Was gibt es " | |
| 752 | + }, | |
| 753 | + { | |
| 754 | + "text": "heute", | |
| 755 | + "alias": "date", | |
| 756 | + "meta": "@date", | |
| 757 | + "userDefined": false | |
| 758 | + }, | |
| 759 | + { | |
| 760 | + "text": " " | |
| 761 | + }, | |
| 762 | + { | |
| 763 | + "text": "vegetarisches", | |
| 764 | + "alias": "dishtype", | |
| 765 | + "meta": "@dishtype", | |
| 766 | + "userDefined": true | |
| 767 | + }, | |
| 768 | + { | |
| 769 | + "text": " in der Mensa?" | |
| 770 | + } | |
| 771 | + ], | |
| 772 | + "isTemplate": false, | |
| 773 | + "count": 1 | |
| 774 | + }, | |
| 775 | + { | |
| 776 | + "id": "65af4b91-d76c-4c98-a1d4-5dda5534a374", | |
| 777 | + "data": [ | |
| 778 | + { | |
| 779 | + "text": "Hallo Bot was gibt es " | |
| 780 | + }, | |
| 781 | + { | |
| 782 | + "text": "morgen", | |
| 783 | + "alias": "date", | |
| 784 | + "meta": "@date", | |
| 785 | + "userDefined": false | |
| 786 | + }, | |
| 787 | + { | |
| 788 | + "text": " in der Mensa." | |
| 789 | + } | |
| 790 | + ], | |
| 791 | + "isTemplate": false, | |
| 792 | + "count": 0 | |
| 793 | + }, | |
| 794 | + { | |
| 795 | + "id": "b35b3289-8345-4cf2-8f59-736f2b61004f", | |
| 796 | + "data": [ | |
| 797 | + { | |
| 798 | + "text": "Zeige mir alle Gerichte." | |
| 799 | + } | |
| 800 | + ], | |
| 801 | + "isTemplate": false, | |
| 802 | + "count": 0 | |
| 803 | + }, | |
| 804 | + { | |
| 805 | + "id": "70acf56e-8e2d-4d9a-b2d6-12cbc838b2ae", | |
| 806 | + "data": [ | |
| 807 | + { | |
| 808 | + "text": "Habe Lust auf " | |
| 809 | + }, | |
| 810 | + { | |
| 811 | + "text": "Suppe", | |
| 812 | + "alias": "dishcategory", | |
| 813 | + "meta": "@dishcategory", | |
| 814 | + "userDefined": true | |
| 815 | + }, | |
| 816 | + { | |
| 817 | + "text": ". Gibt es da " | |
| 818 | + }, | |
| 819 | + { | |
| 820 | + "text": "heute", | |
| 821 | + "alias": "date", | |
| 822 | + "meta": "@date", | |
| 823 | + "userDefined": false | |
| 824 | + }, | |
| 825 | + { | |
| 826 | + "text": " was?" | |
| 827 | + } | |
| 828 | + ], | |
| 829 | + "isTemplate": false, | |
| 830 | + "count": 0 | |
| 831 | + }, | |
| 832 | + { | |
| 833 | + "id": "cce7e036-4b08-4a0c-9a4f-219db43e3a18", | |
| 834 | + "data": [ | |
| 835 | + { | |
| 836 | + "text": "Was gibt es " | |
| 837 | + }, | |
| 838 | + { | |
| 839 | + "text": "morgen", | |
| 840 | + "alias": "date", | |
| 841 | + "meta": "@date", | |
| 842 | + "userDefined": false | |
| 843 | + }, | |
| 844 | + { | |
| 845 | + "text": " in der Mensa?" | |
| 846 | + } | |
| 847 | + ], | |
| 848 | + "isTemplate": false, | |
| 849 | + "count": 0 | |
| 850 | + }, | |
| 851 | + { | |
| 852 | + "id": "c87d3aff-b7c1-4ae7-a85e-b7d51081cb7c", | |
| 853 | + "data": [ | |
| 854 | + { | |
| 855 | + "text": "Was gab es " | |
| 856 | + }, | |
| 857 | + { | |
| 858 | + "text": "gestern", | |
| 859 | + "alias": "date", | |
| 860 | + "meta": "@date", | |
| 861 | + "userDefined": true | |
| 862 | + }, | |
| 863 | + { | |
| 864 | + "text": " in der Mensa?" | |
| 865 | + } | |
| 866 | + ], | |
| 867 | + "isTemplate": false, | |
| 868 | + "count": 0 | |
| 869 | + }, | |
| 870 | + { | |
| 871 | + "id": "c37a2f00-d350-4670-b7bb-0b7018c8840a", | |
| 872 | + "data": [ | |
| 873 | + { | |
| 874 | + "text": "Was gibt es " | |
| 875 | + }, | |
| 876 | + { | |
| 877 | + "text": "übermorgen", | |
| 878 | + "alias": "date", | |
| 879 | + "meta": "@date", | |
| 880 | + "userDefined": false | |
| 881 | + }, | |
| 882 | + { | |
| 883 | + "text": " in der Mensa?" | |
| 884 | + } | |
| 885 | + ], | |
| 886 | + "isTemplate": false, | |
| 887 | + "count": 1 | |
| 888 | + }, | |
| 889 | + { | |
| 890 | + "id": "749033aa-ff61-4fc4-8105-2a6e89e9db64", | |
| 891 | + "data": [ | |
| 892 | + { | |
| 893 | + "text": "Was gibt es " | |
| 894 | + }, | |
| 895 | + { | |
| 896 | + "text": "Freitag", | |
| 897 | + "alias": "date", | |
| 898 | + "meta": "@date", | |
| 899 | + "userDefined": true | |
| 900 | + }, | |
| 901 | + { | |
| 902 | + "text": " in der Mensa?" | |
| 903 | + } | |
| 904 | + ], | |
| 905 | + "isTemplate": false, | |
| 906 | + "count": 0 | |
| 907 | + }, | |
| 908 | + { | |
| 909 | + "id": "5db0b947-d27d-452a-b84c-85440876d490", | |
| 910 | + "data": [ | |
| 911 | + { | |
| 912 | + "text": "Was gibt es " | |
| 913 | + }, | |
| 914 | + { | |
| 915 | + "text": "Donnerstag", | |
| 916 | + "alias": "date", | |
| 917 | + "meta": "@date", | |
| 918 | + "userDefined": true | |
| 919 | + }, | |
| 920 | + { | |
| 921 | + "text": " in der Mensa?" | |
| 922 | + } | |
| 923 | + ], | |
| 924 | + "isTemplate": false, | |
| 925 | + "count": 0 | |
| 926 | + }, | |
| 927 | + { | |
| 928 | + "id": "ea2aa68e-3bb7-4902-a56d-36f96275800a", | |
| 929 | + "data": [ | |
| 930 | + { | |
| 931 | + "text": "Was gibt es " | |
| 932 | + }, | |
| 933 | + { | |
| 934 | + "text": "Mittwoch", | |
| 935 | + "alias": "date", | |
| 936 | + "meta": "@date", | |
| 937 | + "userDefined": true | |
| 938 | + }, | |
| 939 | + { | |
| 940 | + "text": " in der Mensa?" | |
| 941 | + } | |
| 942 | + ], | |
| 943 | + "isTemplate": false, | |
| 944 | + "count": 0 | |
| 945 | + }, | |
| 946 | + { | |
| 947 | + "id": "63084452-c279-40ac-b6bc-3baf51fb144f", | |
| 948 | + "data": [ | |
| 949 | + { | |
| 950 | + "text": "Was gibt es " | |
| 951 | + }, | |
| 952 | + { | |
| 953 | + "text": "Dienstag", | |
| 954 | + "alias": "date", | |
| 955 | + "meta": "@date", | |
| 956 | + "userDefined": true | |
| 957 | + }, | |
| 958 | + { | |
| 959 | + "text": " in der Mensa?" | |
| 960 | + } | |
| 961 | + ], | |
| 962 | + "isTemplate": false, | |
| 963 | + "count": 0 | |
| 964 | + }, | |
| 965 | + { | |
| 966 | + "id": "9c35b6e8-ea88-4165-94b0-6be5f83ba76c", | |
| 967 | + "data": [ | |
| 968 | + { | |
| 969 | + "text": "Was gibt es " | |
| 970 | + }, | |
| 971 | + { | |
| 972 | + "text": "Montag", | |
| 973 | + "alias": "date", | |
| 974 | + "meta": "@date", | |
| 975 | + "userDefined": true | |
| 976 | + }, | |
| 977 | + { | |
| 978 | + "text": " in der Mensa?" | |
| 979 | + } | |
| 980 | + ], | |
| 981 | + "isTemplate": false, | |
| 982 | + "count": 0 | |
| 983 | + }, | |
| 984 | + { | |
| 985 | + "id": "900221fa-f3d3-463b-b224-604521c503e3", | |
| 986 | + "data": [ | |
| 987 | + { | |
| 988 | + "text": "Was gibt es " | |
| 989 | + }, | |
| 990 | + { | |
| 991 | + "text": "heute", | |
| 992 | + "alias": "date", | |
| 993 | + "meta": "@date", | |
| 994 | + "userDefined": false | |
| 995 | + }, | |
| 996 | + { | |
| 997 | + "text": " in der Mensa?" | |
| 998 | + } | |
| 999 | + ], | |
| 1000 | + "isTemplate": false, | |
| 1001 | + "count": 0 | |
| 1002 | + }, | |
| 1003 | + { | |
| 1004 | + "id": "0d64638d-fe5d-47c9-807d-1be539af917c", | |
| 1005 | + "data": [ | |
| 1006 | + { | |
| 1007 | + "text": "Was gibt es " | |
| 1008 | + }, | |
| 1009 | + { | |
| 1010 | + "text": "morgen", | |
| 1011 | + "alias": "date", | |
| 1012 | + "meta": "@date", | |
| 1013 | + "userDefined": false | |
| 1014 | + }, | |
| 1015 | + { | |
| 1016 | + "text": " " | |
| 1017 | + }, | |
| 1018 | + { | |
| 1019 | + "text": "Ungesundes", | |
| 1020 | + "alias": "healthy", | |
| 1021 | + "meta": "@healthy", | |
| 1022 | + "userDefined": false | |
| 1023 | + }, | |
| 1024 | + { | |
| 1025 | + "text": " in der Mensa?" | |
| 1026 | + } | |
| 1027 | + ], | |
| 1028 | + "isTemplate": false, | |
| 1029 | + "count": 0 | |
| 1030 | + }, | |
| 1031 | + { | |
| 1032 | + "id": "8def9d65-14e0-4980-a57f-31be651b8e9f", | |
| 1033 | + "data": [ | |
| 1034 | + { | |
| 1035 | + "text": "Was gibt es " | |
| 1036 | + }, | |
| 1037 | + { | |
| 1038 | + "text": "heute", | |
| 1039 | + "alias": "date", | |
| 1040 | + "meta": "@date", | |
| 1041 | + "userDefined": false | |
| 1042 | + }, | |
| 1043 | + { | |
| 1044 | + "text": " " | |
| 1045 | + }, | |
| 1046 | + { | |
| 1047 | + "text": "gesundes", | |
| 1048 | + "alias": "healthy", | |
| 1049 | + "meta": "@healthy", | |
| 1050 | + "userDefined": false | |
| 1051 | + }, | |
| 1052 | + { | |
| 1053 | + "text": " in der Mensa?" | |
| 1054 | + } | |
| 1055 | + ], | |
| 1056 | + "isTemplate": false, | |
| 1057 | + "count": 0 | |
| 1058 | + }, | |
| 1059 | + { | |
| 1060 | + "id": "abbe2177-b8e7-4801-9872-3c9a359fa7fb", | |
| 1061 | + "data": [ | |
| 1062 | + { | |
| 1063 | + "text": "Was gibt es " | |
| 1064 | + }, | |
| 1065 | + { | |
| 1066 | + "text": "morgen", | |
| 1067 | + "alias": "date", | |
| 1068 | + "meta": "@date", | |
| 1069 | + "userDefined": false | |
| 1070 | + }, | |
| 1071 | + { | |
| 1072 | + "text": " " | |
| 1073 | + }, | |
| 1074 | + { | |
| 1075 | + "text": "vegetarisches", | |
| 1076 | + "alias": "dishtype", | |
| 1077 | + "meta": "@dishtype", | |
| 1078 | + "userDefined": false | |
| 1079 | + }, | |
| 1080 | + { | |
| 1081 | + "text": " in der Mensa?" | |
| 1082 | + } | |
| 1083 | + ], | |
| 1084 | + "isTemplate": false, | |
| 1085 | + "count": 0 | |
| 1086 | + }, | |
| 1087 | + { | |
| 1088 | + "id": "4255baf9-704a-4749-a441-0b24d8d716ad", | |
| 1089 | + "data": [ | |
| 1090 | + { | |
| 1091 | + "text": "Was gibt es " | |
| 1092 | + }, | |
| 1093 | + { | |
| 1094 | + "text": "morgen", | |
| 1095 | + "alias": "date", | |
| 1096 | + "meta": "@date", | |
| 1097 | + "userDefined": false | |
| 1098 | + }, | |
| 1099 | + { | |
| 1100 | + "text": " " | |
| 1101 | + }, | |
| 1102 | + { | |
| 1103 | + "text": "gesundes", | |
| 1104 | + "alias": "healthy", | |
| 1105 | + "meta": "@healthy", | |
| 1106 | + "userDefined": true | |
| 1107 | + }, | |
| 1108 | + { | |
| 1109 | + "text": " in der Mensa?" | |
| 1110 | + } | |
| 1111 | + ], | |
| 1112 | + "isTemplate": false, | |
| 1113 | + "count": 0 | |
| 1114 | + }, | |
| 1115 | + { | |
| 1116 | + "id": "05c9c76f-e7cc-417f-990d-fc9c0c3d202a", | |
| 1117 | + "data": [ | |
| 1118 | + { | |
| 1119 | + "text": "Ick hab Hunger..." | |
| 1120 | + } | |
| 1121 | + ], | |
| 1122 | + "isTemplate": false, | |
| 1123 | + "count": 0 | |
| 1124 | + }, | |
| 1125 | + { | |
| 1126 | + "id": "4c28ddca-a35e-475d-967b-bc513645cf19", | |
| 1127 | + "data": [ | |
| 1128 | + { | |
| 1129 | + "text": "Zeige Gerichte", | |
| 1130 | + "meta": "@sys.ignore", | |
| 1131 | + "userDefined": true | |
| 1132 | + }, | |
| 1133 | + { | |
| 1134 | + "text": " " | |
| 1135 | + }, | |
| 1136 | + { | |
| 1137 | + "text": "ohne Zucker", | |
| 1138 | + "alias": "ingredients", | |
| 1139 | + "meta": "@ingredients", | |
| 1140 | + "userDefined": true | |
| 1141 | + } | |
| 1142 | + ], | |
| 1143 | + "isTemplate": false, | |
| 1144 | + "count": 1 | |
| 1145 | + }, | |
| 1146 | + { | |
| 1147 | + "id": "823222a6-c09c-430d-8164-ac9398a3ae42", | |
| 1148 | + "data": [ | |
| 1149 | + { | |
| 1150 | + "text": "Zeige " | |
| 1151 | + }, | |
| 1152 | + { | |
| 1153 | + "text": "gesunde", | |
| 1154 | + "alias": "healthy", | |
| 1155 | + "meta": "@healthy", | |
| 1156 | + "userDefined": true | |
| 1157 | + }, | |
| 1158 | + { | |
| 1159 | + "text": " Gerichte" | |
| 1160 | + } | |
| 1161 | + ], | |
| 1162 | + "isTemplate": false, | |
| 1163 | + "count": 0 | |
| 1164 | + }, | |
| 1165 | + { | |
| 1166 | + "id": "26104cc6-c7d1-4952-bbe8-ea66c0a608b8", | |
| 1167 | + "data": [ | |
| 1168 | + { | |
| 1169 | + "text": "Ich habe " | |
| 1170 | + }, | |
| 1171 | + { | |
| 1172 | + "text": "Hunger", | |
| 1173 | + "meta": "@sys.ignore", | |
| 1174 | + "userDefined": true | |
| 1175 | + } | |
| 1176 | + ], | |
| 1177 | + "isTemplate": false, | |
| 1178 | + "count": 1 | |
| 1179 | + }, | |
| 1180 | + { | |
| 1181 | + "id": "0e61a171-092e-4100-ae11-8e96e4c8eb8a", | |
| 1182 | + "data": [ | |
| 1183 | + { | |
| 1184 | + "text": "Was gibt es " | |
| 1185 | + }, | |
| 1186 | + { | |
| 1187 | + "text": "veganes", | |
| 1188 | + "alias": "dishtype", | |
| 1189 | + "meta": "@dishtype", | |
| 1190 | + "userDefined": true | |
| 1191 | + }, | |
| 1192 | + { | |
| 1193 | + "text": "?" | |
| 1194 | + } | |
| 1195 | + ], | |
| 1196 | + "isTemplate": false, | |
| 1197 | + "count": 1 | |
| 1198 | + }, | |
| 1199 | + { | |
| 1200 | + "id": "9b0d67ca-09ea-4d7d-bc72-342e0e7c5088", | |
| 1201 | + "data": [ | |
| 1202 | + { | |
| 1203 | + "text": "Wie ist der aktuelle " | |
| 1204 | + }, | |
| 1205 | + { | |
| 1206 | + "text": "Speiseplan", | |
| 1207 | + "meta": "@sys.ignore", | |
| 1208 | + "userDefined": true | |
| 1209 | + } | |
| 1210 | + ], | |
| 1211 | + "isTemplate": false, | |
| 1212 | + "count": 0 | |
| 1213 | + }, | |
| 1214 | + { | |
| 1215 | + "id": "e4281c8d-f69d-4b90-a12f-d39edc59b052", | |
| 1216 | + "data": [ | |
| 1217 | + { | |
| 1218 | + "text": "Habe " | |
| 1219 | + }, | |
| 1220 | + { | |
| 1221 | + "text": "Hunger", | |
| 1222 | + "meta": "@sys.ignore", | |
| 1223 | + "userDefined": false | |
| 1224 | + } | |
| 1225 | + ], | |
| 1226 | + "isTemplate": false, | |
| 1227 | + "count": 1 | |
| 1228 | + }, | |
| 1229 | + { | |
| 1230 | + "id": "f7606b89-2724-41cb-973f-34210fa976fc", | |
| 1231 | + "data": [ | |
| 1232 | + { | |
| 1233 | + "text": "Ich möchte gerne etwas " | |
| 1234 | + }, | |
| 1235 | + { | |
| 1236 | + "text": "ohne Fleisch", | |
| 1237 | + "alias": "dishtype", | |
| 1238 | + "meta": "@dishtype", | |
| 1239 | + "userDefined": true | |
| 1240 | + }, | |
| 1241 | + { | |
| 1242 | + "text": " " | |
| 1243 | + }, | |
| 1244 | + { | |
| 1245 | + "text": "essen", | |
| 1246 | + "meta": "@sys.ignore", | |
| 1247 | + "userDefined": true | |
| 1248 | + } | |
| 1249 | + ], | |
| 1250 | + "isTemplate": false, | |
| 1251 | + "count": 0 | |
| 1252 | + }, | |
| 1253 | + { | |
| 1254 | + "id": "5cb17168-c227-4ac9-ac83-520b70a5252c", | |
| 1255 | + "data": [ | |
| 1256 | + { | |
| 1257 | + "text": "Was ist " | |
| 1258 | + }, | |
| 1259 | + { | |
| 1260 | + "text": "vegetarisch", | |
| 1261 | + "alias": "dishtype", | |
| 1262 | + "meta": "@dishtype", | |
| 1263 | + "userDefined": true | |
| 1264 | + } | |
| 1265 | + ], | |
| 1266 | + "isTemplate": false, | |
| 1267 | + "count": 1 | |
| 1268 | + }, | |
| 1269 | + { | |
| 1270 | + "id": "1a749580-2d92-4526-9f9c-d5fa76e509eb", | |
| 1271 | + "data": [ | |
| 1272 | + { | |
| 1273 | + "text": "Was kann ich " | |
| 1274 | + }, | |
| 1275 | + { | |
| 1276 | + "text": "essen", | |
| 1277 | + "meta": "@sys.ignore", | |
| 1278 | + "userDefined": true | |
| 1279 | + } | |
| 1280 | + ], | |
| 1281 | + "isTemplate": false, | |
| 1282 | + "count": 0 | |
| 1283 | + }, | |
| 1284 | + { | |
| 1285 | + "id": "f49e58ff-4782-4701-9661-07accede286c", | |
| 1286 | + "data": [ | |
| 1287 | + { | |
| 1288 | + "text": "Was gibt es " | |
| 1289 | + }, | |
| 1290 | + { | |
| 1291 | + "text": "heute", | |
| 1292 | + "alias": "date", | |
| 1293 | + "meta": "@date", | |
| 1294 | + "userDefined": true | |
| 1295 | + }, | |
| 1296 | + { | |
| 1297 | + "text": " in der Mensa" | |
| 1298 | + } | |
| 1299 | + ], | |
| 1300 | + "isTemplate": false, | |
| 1301 | + "count": 2 | |
| 1302 | + } | |
| 1303 | + ], | |
| 1304 | + "id": "fb49a221-02a6-4dff-8da4-9d31cf8f267b", | |
| 1305 | + "name": "showFood", | |
| 1306 | + "auto": true, | |
| 1307 | + "contexts": [], | |
| 1308 | + "responses": [ | |
| 1309 | + { | |
| 1310 | + "resetContexts": false, | |
| 1311 | + "affectedContexts": [], | |
| 1312 | + "parameters": [ | |
| 1313 | + { | |
| 1314 | + "dataType": "@date", | |
| 1315 | + "name": "date", | |
| 1316 | + "value": "$date", | |
| 1317 | + "isList": false | |
| 1318 | + }, | |
| 1319 | + { | |
| 1320 | + "dataType": "@dishtype", | |
| 1321 | + "name": "dishtype", | |
| 1322 | + "value": "$dishtype", | |
| 1323 | + "isList": false | |
| 1324 | + }, | |
| 1325 | + { | |
| 1326 | + "dataType": "@healthy", | |
| 1327 | + "name": "healthy", | |
| 1328 | + "value": "$healthy", | |
| 1329 | + "isList": false | |
| 1330 | + }, | |
| 1331 | + { | |
| 1332 | + "dataType": "@ingredients", | |
| 1333 | + "name": "ingredients", | |
| 1334 | + "value": "$ingredients", | |
| 1335 | + "isList": false | |
| 1336 | + }, | |
| 1337 | + { | |
| 1338 | + "dataType": "@price", | |
| 1339 | + "name": "price", | |
| 1340 | + "value": "$price", | |
| 1341 | + "isList": false | |
| 1342 | + }, | |
| 1343 | + { | |
| 1344 | + "dataType": "@dishcategory", | |
| 1345 | + "name": "dishcategory", | |
| 1346 | + "value": "$dishcategory", | |
| 1347 | + "isList": false | |
| 1348 | + } | |
| 1349 | + ], | |
| 1350 | + "messages": [ | |
| 1351 | + { | |
| 1352 | + "type": 0, | |
| 1353 | + "speech": [] | |
| 1354 | + } | |
| 1355 | + ], | |
| 1356 | + "defaultResponsePlatforms": {} | |
| 1357 | + } | |
| 1358 | + ], | |
| 1359 | + "priority": 500000, | |
| 1360 | + "webhookUsed": false, | |
| 1361 | + "webhookForSlotFilling": false, | |
| 1362 | + "fallbackIntent": false, | |
| 1363 | + "events": [] | |
| 1364 | +} | |
| 0 | 1365 | \ No newline at end of file | ... | ... |
docker/wildfly/Dockerfile
0 → 100755
docker/wildfly/standalone.xml
0 → 100755
| 1 | +++ a/docker/wildfly/standalone.xml | |
| 1 | +<?xml version='1.0' encoding='UTF-8'?> | |
| 2 | + | |
| 3 | +<server xmlns="urn:jboss:domain:4.2"> | |
| 4 | + | |
| 5 | + <extensions> | |
| 6 | + <extension module="org.jboss.as.clustering.infinispan"/> | |
| 7 | + <extension module="org.jboss.as.connector"/> | |
| 8 | + <extension module="org.jboss.as.deployment-scanner"/> | |
| 9 | + <extension module="org.jboss.as.ee"/> | |
| 10 | + <extension module="org.jboss.as.ejb3"/> | |
| 11 | + <extension module="org.jboss.as.jaxrs"/> | |
| 12 | + <extension module="org.jboss.as.jdr"/> | |
| 13 | + <extension module="org.jboss.as.jmx"/> | |
| 14 | + <extension module="org.jboss.as.jpa"/> | |
| 15 | + <extension module="org.jboss.as.jsf"/> | |
| 16 | + <extension module="org.jboss.as.logging"/> | |
| 17 | + <extension module="org.jboss.as.mail"/> | |
| 18 | + <extension module="org.jboss.as.naming"/> | |
| 19 | + <extension module="org.jboss.as.pojo"/> | |
| 20 | + <extension module="org.jboss.as.remoting"/> | |
| 21 | + <extension module="org.jboss.as.sar"/> | |
| 22 | + <extension module="org.jboss.as.security"/> | |
| 23 | + <extension module="org.jboss.as.transactions"/> | |
| 24 | + <extension module="org.jboss.as.webservices"/> | |
| 25 | + <extension module="org.jboss.as.weld"/> | |
| 26 | + <extension module="org.wildfly.extension.batch.jberet"/> | |
| 27 | + <extension module="org.wildfly.extension.bean-validation"/> | |
| 28 | + <extension module="org.wildfly.extension.io"/> | |
| 29 | + <extension module="org.wildfly.extension.messaging-activemq"/> | |
| 30 | + <extension module="org.wildfly.extension.request-controller"/> | |
| 31 | + <extension module="org.wildfly.extension.security.manager"/> | |
| 32 | + <extension module="org.wildfly.extension.undertow"/> | |
| 33 | + </extensions> | |
| 34 | + | |
| 35 | + | |
| 36 | + <management> | |
| 37 | + <security-realms> | |
| 38 | + <security-realm name="ManagementRealm"> | |
| 39 | + <authentication> | |
| 40 | + <local default-user="$local" skip-group-loading="true"/> | |
| 41 | + <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/> | |
| 42 | + </authentication> | |
| 43 | + <authorization map-groups-to-roles="false"> | |
| 44 | + <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/> | |
| 45 | + </authorization> | |
| 46 | + </security-realm> | |
| 47 | + <security-realm name="ApplicationRealm"> | |
| 48 | + <server-identities> | |
| 49 | + <ssl> | |
| 50 | + <keystore path="application.keystore" relative-to="jboss.server.config.dir" keystore-password="password" alias="server" key-password="password" generate-self-signed-certificate-host="localhost"/> | |
| 51 | + </ssl> | |
| 52 | + </server-identities> | |
| 53 | + <authentication> | |
| 54 | + <local default-user="$local" allowed-users="*" skip-group-loading="true"/> | |
| 55 | + <properties path="application-users.properties" relative-to="jboss.server.config.dir"/> | |
| 56 | + </authentication> | |
| 57 | + <authorization> | |
| 58 | + <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/> | |
| 59 | + </authorization> | |
| 60 | + </security-realm> | |
| 61 | + </security-realms> | |
| 62 | + <audit-log> | |
| 63 | + <formatters> | |
| 64 | + <json-formatter name="json-formatter"/> | |
| 65 | + </formatters> | |
| 66 | + <handlers> | |
| 67 | + <file-handler name="file" formatter="json-formatter" path="audit-log.log" relative-to="jboss.server.data.dir"/> | |
| 68 | + </handlers> | |
| 69 | + <logger log-boot="true" log-read-only="false" enabled="false"> | |
| 70 | + <handlers> | |
| 71 | + <handler name="file"/> | |
| 72 | + </handlers> | |
| 73 | + </logger> | |
| 74 | + </audit-log> | |
| 75 | + <management-interfaces> | |
| 76 | + <http-interface security-realm="ManagementRealm" http-upgrade-enabled="true"> | |
| 77 | + <socket-binding http="management-http"/> | |
| 78 | + </http-interface> | |
| 79 | + </management-interfaces> | |
| 80 | + <access-control provider="simple"> | |
| 81 | + <role-mapping> | |
| 82 | + <role name="SuperUser"> | |
| 83 | + <include> | |
| 84 | + <user name="$local"/> | |
| 85 | + </include> | |
| 86 | + </role> | |
| 87 | + </role-mapping> | |
| 88 | + </access-control> | |
| 89 | + </management> | |
| 90 | + | |
| 91 | + <profile> | |
| 92 | + <subsystem xmlns="urn:jboss:domain:logging:3.0"> | |
| 93 | + <console-handler name="CONSOLE"> | |
| 94 | + <level name="DEBUG"/> | |
| 95 | + <formatter> | |
| 96 | + <named-formatter name="COLOR-PATTERN"/> | |
| 97 | + </formatter> | |
| 98 | + </console-handler> | |
| 99 | + <periodic-rotating-file-handler name="FILE" autoflush="true"> | |
| 100 | + <formatter> | |
| 101 | + <named-formatter name="PATTERN"/> | |
| 102 | + </formatter> | |
| 103 | + <file relative-to="jboss.server.log.dir" path="server.log"/> | |
| 104 | + <suffix value=".yyyy-MM-dd"/> | |
| 105 | + <append value="true"/> | |
| 106 | + </periodic-rotating-file-handler> | |
| 107 | + <logger category="com.arjuna"> | |
| 108 | + <level name="WARN"/> | |
| 109 | + </logger> | |
| 110 | + <logger category="org.jboss.as.config"> | |
| 111 | + <level name="DEBUG"/> | |
| 112 | + </logger> | |
| 113 | + <logger category="sun.rmi"> | |
| 114 | + <level name="WARN"/> | |
| 115 | + </logger> | |
| 116 | + <logger category="de.bht.beuthbot"> | |
| 117 | + <level name="DEBUG"/> | |
| 118 | + </logger> | |
| 119 | + <root-logger> | |
| 120 | + <level name="INFO"/> | |
| 121 | + <handlers> | |
| 122 | + <handler name="CONSOLE"/> | |
| 123 | + <handler name="FILE"/> | |
| 124 | + </handlers> | |
| 125 | + </root-logger> | |
| 126 | + <formatter name="PATTERN"> | |
| 127 | + <pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/> | |
| 128 | + </formatter> | |
| 129 | + <formatter name="COLOR-PATTERN"> | |
| 130 | + <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/> | |
| 131 | + </formatter> | |
| 132 | + </subsystem> | |
| 133 | + <subsystem xmlns="urn:jboss:domain:batch-jberet:1.0"> | |
| 134 | + <default-job-repository name="in-memory"/> | |
| 135 | + <default-thread-pool name="batch"/> | |
| 136 | + <job-repository name="in-memory"> | |
| 137 | + <in-memory/> | |
| 138 | + </job-repository> | |
| 139 | + <thread-pool name="batch"> | |
| 140 | + <max-threads count="10"/> | |
| 141 | + <keepalive-time time="30" unit="seconds"/> | |
| 142 | + </thread-pool> | |
| 143 | + </subsystem> | |
| 144 | + <subsystem xmlns="urn:jboss:domain:bean-validation:1.0"/> | |
| 145 | + <subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0"> | |
| 146 | + <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" runtime-failure-causes-rollback="${jboss.deployment.scanner.rollback.on.failure:false}"/> | |
| 147 | + </subsystem> | |
| 148 | + <subsystem xmlns="urn:jboss:domain:ee:4.0"> | |
| 149 | + <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement> | |
| 150 | + <concurrent> | |
| 151 | + <context-services> | |
| 152 | + <context-service name="default" jndi-name="java:jboss/ee/concurrency/context/default" use-transaction-setup-provider="true"/> | |
| 153 | + </context-services> | |
| 154 | + <managed-thread-factories> | |
| 155 | + <managed-thread-factory name="default" jndi-name="java:jboss/ee/concurrency/factory/default" context-service="default"/> | |
| 156 | + </managed-thread-factories> | |
| 157 | + <managed-executor-services> | |
| 158 | + <managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" keepalive-time="5000"/> | |
| 159 | + </managed-executor-services> | |
| 160 | + <managed-scheduled-executor-services> | |
| 161 | + <managed-scheduled-executor-service name="default" jndi-name="java:jboss/ee/concurrency/scheduler/default" context-service="default" hung-task-threshold="60000" keepalive-time="3000"/> | |
| 162 | + </managed-scheduled-executor-services> | |
| 163 | + </concurrent> | |
| 164 | + <default-bindings context-service="java:jboss/ee/concurrency/context/default" datasource="java:jboss/datasources/ExampleDS" jms-connection-factory="java:jboss/DefaultJMSConnectionFactory" managed-executor-service="java:jboss/ee/concurrency/executor/default" managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default" managed-thread-factory="java:jboss/ee/concurrency/factory/default"/> | |
| 165 | + </subsystem> | |
| 166 | + <subsystem xmlns="urn:jboss:domain:ejb3:4.0"> | |
| 167 | + <session-bean> | |
| 168 | + <stateless> | |
| 169 | + <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/> | |
| 170 | + </stateless> | |
| 171 | + <stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/> | |
| 172 | + <singleton default-access-timeout="5000"/> | |
| 173 | + </session-bean> | |
| 174 | + <mdb> | |
| 175 | + <resource-adapter-ref resource-adapter-name="${ejb.resource-adapter-name:activemq-ra.rar}"/> | |
| 176 | + <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/> | |
| 177 | + </mdb> | |
| 178 | + <pools> | |
| 179 | + <bean-instance-pools> | |
| 180 | + <strict-max-pool name="slsb-strict-max-pool" derive-size="from-worker-pools" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/> | |
| 181 | + <strict-max-pool name="mdb-strict-max-pool" derive-size="from-cpu-count" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/> | |
| 182 | + </bean-instance-pools> | |
| 183 | + </pools> | |
| 184 | + <caches> | |
| 185 | + <cache name="simple"/> | |
| 186 | + <cache name="distributable" passivation-store-ref="infinispan" aliases="passivating clustered"/> | |
| 187 | + </caches> | |
| 188 | + <passivation-stores> | |
| 189 | + <passivation-store name="infinispan" cache-container="ejb" max-size="10000"/> | |
| 190 | + </passivation-stores> | |
| 191 | + <async thread-pool-name="default"/> | |
| 192 | + <timer-service thread-pool-name="default" default-data-store="default-file-store"> | |
| 193 | + <data-stores> | |
| 194 | + <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/> | |
| 195 | + </data-stores> | |
| 196 | + </timer-service> | |
| 197 | + <remote connector-ref="http-remoting-connector" thread-pool-name="default"/> | |
| 198 | + <thread-pools> | |
| 199 | + <thread-pool name="default"> | |
| 200 | + <max-threads count="10"/> | |
| 201 | + <keepalive-time time="100" unit="milliseconds"/> | |
| 202 | + </thread-pool> | |
| 203 | + </thread-pools> | |
| 204 | + <default-security-domain value="other"/> | |
| 205 | + <default-missing-method-permissions-deny-access value="true"/> | |
| 206 | + <log-system-exceptions value="true"/> | |
| 207 | + </subsystem> | |
| 208 | + <subsystem xmlns="urn:jboss:domain:io:1.1"> | |
| 209 | + <worker name="default"/> | |
| 210 | + <buffer-pool name="default"/> | |
| 211 | + </subsystem> | |
| 212 | + <subsystem xmlns="urn:jboss:domain:infinispan:4.0"> | |
| 213 | + <cache-container name="server" default-cache="default" module="org.wildfly.clustering.server"> | |
| 214 | + <local-cache name="default"> | |
| 215 | + <transaction mode="BATCH"/> | |
| 216 | + </local-cache> | |
| 217 | + </cache-container> | |
| 218 | + <cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan"> | |
| 219 | + <local-cache name="passivation"> | |
| 220 | + <locking isolation="REPEATABLE_READ"/> | |
| 221 | + <transaction mode="BATCH"/> | |
| 222 | + <file-store passivation="true" purge="false"/> | |
| 223 | + </local-cache> | |
| 224 | + <local-cache name="persistent"> | |
| 225 | + <locking isolation="REPEATABLE_READ"/> | |
| 226 | + <transaction mode="BATCH"/> | |
| 227 | + <file-store passivation="false" purge="false"/> | |
| 228 | + </local-cache> | |
| 229 | + <local-cache name="concurrent"> | |
| 230 | + <file-store passivation="true" purge="false"/> | |
| 231 | + </local-cache> | |
| 232 | + </cache-container> | |
| 233 | + <cache-container name="ejb" aliases="sfsb" default-cache="passivation" module="org.wildfly.clustering.ejb.infinispan"> | |
| 234 | + <local-cache name="passivation"> | |
| 235 | + <locking isolation="REPEATABLE_READ"/> | |
| 236 | + <transaction mode="BATCH"/> | |
| 237 | + <file-store passivation="true" purge="false"/> | |
| 238 | + </local-cache> | |
| 239 | + <local-cache name="persistent"> | |
| 240 | + <locking isolation="REPEATABLE_READ"/> | |
| 241 | + <transaction mode="BATCH"/> | |
| 242 | + <file-store passivation="false" purge="false"/> | |
| 243 | + </local-cache> | |
| 244 | + </cache-container> | |
| 245 | + <cache-container name="hibernate" default-cache="local-query" module="org.hibernate.infinispan"> | |
| 246 | + <local-cache name="entity"> | |
| 247 | + <transaction mode="NON_XA"/> | |
| 248 | + <eviction strategy="LRU" max-entries="10000"/> | |
| 249 | + <expiration max-idle="100000"/> | |
| 250 | + </local-cache> | |
| 251 | + <local-cache name="local-query"> | |
| 252 | + <eviction strategy="LRU" max-entries="10000"/> | |
| 253 | + <expiration max-idle="100000"/> | |
| 254 | + </local-cache> | |
| 255 | + <local-cache name="timestamps"/> | |
| 256 | + </cache-container> | |
| 257 | + <cache-container name="app-caches"> | |
| 258 | + <local-cache name="mensaCache"> | |
| 259 | + <!-- 30' cache --> | |
| 260 | + <expiration lifespan="1800000" /> | |
| 261 | + </local-cache> | |
| 262 | + <local-cache name="tokenCache"> | |
| 263 | + <!-- 9' cache --> | |
| 264 | + <expiration lifespan="540" /> | |
| 265 | + </local-cache> | |
| 266 | + <local-cache name="sessionCache"> | |
| 267 | + <!-- 12h idle cache --> | |
| 268 | + <expiration max-idle="43200000" /> | |
| 269 | + <file-store preload="true" path="/tmp/chatbot-sessions"> | |
| 270 | + <write-behind /> | |
| 271 | + </file-store> | |
| 272 | + </local-cache> | |
| 273 | + </cache-container> | |
| 274 | + </subsystem> | |
| 275 | + <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/> | |
| 276 | + <subsystem xmlns="urn:jboss:domain:jca:4.0"> | |
| 277 | + <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/> | |
| 278 | + <bean-validation enabled="true"/> | |
| 279 | + <default-workmanager> | |
| 280 | + <short-running-threads> | |
| 281 | + <core-threads count="50"/> | |
| 282 | + <queue-length count="50"/> | |
| 283 | + <max-threads count="50"/> | |
| 284 | + <keepalive-time time="10" unit="seconds"/> | |
| 285 | + </short-running-threads> | |
| 286 | + <long-running-threads> | |
| 287 | + <core-threads count="50"/> | |
| 288 | + <queue-length count="50"/> | |
| 289 | + <max-threads count="50"/> | |
| 290 | + <keepalive-time time="10" unit="seconds"/> | |
| 291 | + </long-running-threads> | |
| 292 | + </default-workmanager> | |
| 293 | + <cached-connection-manager/> | |
| 294 | + </subsystem> | |
| 295 | + <subsystem xmlns="urn:jboss:domain:jdr:1.0"/> | |
| 296 | + <subsystem xmlns="urn:jboss:domain:jmx:1.3"> | |
| 297 | + <expose-resolved-model/> | |
| 298 | + <expose-expression-model/> | |
| 299 | + <remoting-connector/> | |
| 300 | + </subsystem> | |
| 301 | + <subsystem xmlns="urn:jboss:domain:jpa:1.1"> | |
| 302 | + <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/> | |
| 303 | + </subsystem> | |
| 304 | + <subsystem xmlns="urn:jboss:domain:jsf:1.0"/> | |
| 305 | + <subsystem xmlns="urn:jboss:domain:mail:2.0"> | |
| 306 | + <mail-session name="default" jndi-name="java:jboss/mail/Default"> | |
| 307 | + <smtp-server outbound-socket-binding-ref="mail-smtp"/> | |
| 308 | + </mail-session> | |
| 309 | + </subsystem> | |
| 310 | + <subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0"> | |
| 311 | + <server name="default"> | |
| 312 | + <http-connector name="http-connector" socket-binding="http" endpoint="http-acceptor"/> | |
| 313 | + <http-connector name="http-connector-throughput" socket-binding="http" endpoint="http-acceptor-throughput"> | |
| 314 | + <param name="batch-delay" value="50"/> | |
| 315 | + </http-connector> | |
| 316 | + <in-vm-connector name="in-vm" server-id="0"/> | |
| 317 | + <http-acceptor name="http-acceptor" http-listener="default"/> | |
| 318 | + <http-acceptor name="http-acceptor-throughput" http-listener="default"> | |
| 319 | + <param name="batch-delay" value="50"/> | |
| 320 | + <param name="direct-deliver" value="false"/> | |
| 321 | + </http-acceptor> | |
| 322 | + <in-vm-acceptor name="in-vm" server-id="0"/> | |
| 323 | + <jms-topic name="messagesInbox" entries="java:/jms/messages/inbox"/> | |
| 324 | + <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/> | |
| 325 | + <pooled-connection-factory name="activemq-ra" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm" transaction="xa"/> | |
| 326 | + </server> | |
| 327 | + </subsystem> | |
| 328 | + <subsystem xmlns="urn:jboss:domain:naming:2.0"> | |
| 329 | + <remote-naming/> | |
| 330 | + </subsystem> | |
| 331 | + <subsystem xmlns="urn:jboss:domain:pojo:1.0"/> | |
| 332 | + <subsystem xmlns="urn:jboss:domain:remoting:3.0"> | |
| 333 | + <endpoint/> | |
| 334 | + <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/> | |
| 335 | + </subsystem> | |
| 336 | + <subsystem xmlns="urn:jboss:domain:resource-adapters:4.0"/> | |
| 337 | + <subsystem xmlns="urn:jboss:domain:request-controller:1.0"/> | |
| 338 | + <subsystem xmlns="urn:jboss:domain:sar:1.0"/> | |
| 339 | + <subsystem xmlns="urn:jboss:domain:security-manager:1.0"> | |
| 340 | + <deployment-permissions> | |
| 341 | + <maximum-set> | |
| 342 | + <permission class="java.security.AllPermission"/> | |
| 343 | + </maximum-set> | |
| 344 | + </deployment-permissions> | |
| 345 | + </subsystem> | |
| 346 | + <subsystem xmlns="urn:jboss:domain:security:1.2"> | |
| 347 | + <security-domains> | |
| 348 | + <security-domain name="other" cache-type="default"> | |
| 349 | + <authentication> | |
| 350 | + <login-module code="Remoting" flag="optional"> | |
| 351 | + <module-option name="password-stacking" value="useFirstPass"/> | |
| 352 | + </login-module> | |
| 353 | + <login-module code="RealmDirect" flag="required"> | |
| 354 | + <module-option name="password-stacking" value="useFirstPass"/> | |
| 355 | + </login-module> | |
| 356 | + </authentication> | |
| 357 | + </security-domain> | |
| 358 | + <security-domain name="jboss-web-policy" cache-type="default"> | |
| 359 | + <authorization> | |
| 360 | + <policy-module code="Delegating" flag="required"/> | |
| 361 | + </authorization> | |
| 362 | + </security-domain> | |
| 363 | + <security-domain name="jboss-ejb-policy" cache-type="default"> | |
| 364 | + <authorization> | |
| 365 | + <policy-module code="Delegating" flag="required"/> | |
| 366 | + </authorization> | |
| 367 | + </security-domain> | |
| 368 | + <security-domain name="jaspitest" cache-type="default"> | |
| 369 | + <authentication-jaspi> | |
| 370 | + <login-module-stack name="dummy"> | |
| 371 | + <login-module code="Dummy" flag="optional"/> | |
| 372 | + </login-module-stack> | |
| 373 | + <auth-module code="Dummy"/> | |
| 374 | + </authentication-jaspi> | |
| 375 | + </security-domain> | |
| 376 | + </security-domains> | |
| 377 | + </subsystem> | |
| 378 | + <subsystem xmlns="urn:jboss:domain:transactions:3.0"> | |
| 379 | + <core-environment> | |
| 380 | + <process-id> | |
| 381 | + <uuid/> | |
| 382 | + </process-id> | |
| 383 | + </core-environment> | |
| 384 | + <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/> | |
| 385 | + </subsystem> | |
| 386 | + <subsystem xmlns="urn:jboss:domain:undertow:3.1"> | |
| 387 | + <buffer-cache name="default"/> | |
| 388 | + <server name="default-server"> | |
| 389 | + <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/> | |
| 390 | + <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/> | |
| 391 | + <host name="default-host" alias="localhost"> | |
| 392 | + <location name="/" handler="welcome-content"/> | |
| 393 | + <filter-ref name="server-header"/> | |
| 394 | + <filter-ref name="x-powered-by-header"/> | |
| 395 | + </host> | |
| 396 | + </server> | |
| 397 | + <servlet-container name="default"> | |
| 398 | + <jsp-config/> | |
| 399 | + <websockets/> | |
| 400 | + </servlet-container> | |
| 401 | + <handlers> | |
| 402 | + <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/> | |
| 403 | + </handlers> | |
| 404 | + <filters> | |
| 405 | + <response-header name="server-header" header-name="Server" header-value="WildFly/10"/> | |
| 406 | + <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/> | |
| 407 | + </filters> | |
| 408 | + </subsystem> | |
| 409 | + <subsystem xmlns="urn:jboss:domain:webservices:2.0"> | |
| 410 | + <wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host> | |
| 411 | + <endpoint-config name="Standard-Endpoint-Config"/> | |
| 412 | + <endpoint-config name="Recording-Endpoint-Config"> | |
| 413 | + <pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM"> | |
| 414 | + <handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/> | |
| 415 | + </pre-handler-chain> | |
| 416 | + </endpoint-config> | |
| 417 | + <client-config name="Standard-Client-Config"/> | |
| 418 | + </subsystem> | |
| 419 | + <subsystem xmlns="urn:jboss:domain:weld:3.0"/> | |
| 420 | + </profile> | |
| 421 | + | |
| 422 | + <interfaces> | |
| 423 | + <interface name="management"> | |
| 424 | + <inet-address value="${jboss.bind.address.management:127.0.0.1}"/> | |
| 425 | + </interface> | |
| 426 | + <interface name="public"> | |
| 427 | + <inet-address value="${jboss.bind.address:127.0.0.1}"/> | |
| 428 | + </interface> | |
| 429 | + </interfaces> | |
| 430 | + | |
| 431 | + <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> | |
| 432 | + <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/> | |
| 433 | + <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/> | |
| 434 | + <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/> | |
| 435 | + <socket-binding name="http" port="${jboss.http.port:8080}"/> | |
| 436 | + <socket-binding name="https" port="${jboss.https.port:8443}"/> | |
| 437 | + <socket-binding name="txn-recovery-environment" port="4712"/> | |
| 438 | + <socket-binding name="txn-status-manager" port="4713"/> | |
| 439 | + <outbound-socket-binding name="mail-smtp"> | |
| 440 | + <remote-destination host="localhost" port="25"/> | |
| 441 | + </outbound-socket-binding> | |
| 442 | + </socket-binding-group> | |
| 443 | + | |
| 444 | +</server> | ... | ... |
docker/wildfly/volumes/conf/README.md
0 → 100755
docker/wildfly/volumes/conf/beuthbot.properties
0 → 100755
| 1 | +++ a/docker/wildfly/volumes/conf/beuthbot.properties | |
| 1 | +WEB_URL = https://yourdomain.com | |
| 2 | + | |
| 3 | + | |
| 4 | +# Webhook token you set in the Facebook App Settings | |
| 5 | +FACEBOOK_WEBHOOK_TOKEN = bhtchatbot | |
| 6 | + | |
| 7 | +# Facebook Message Token for your page | |
| 8 | +FACEBOOK_BOT_TOKEN = XXXXX | |
| 9 | + | |
| 10 | +FACEBOOK_ACCESS_TOKEN = XXXXX|XXXXX-XXXXX | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | +# API.ai client token | |
| 15 | +API_AI_TOKEN = XXXXX | |
| 16 | + | |
| 17 | + | |
| 18 | +# Your WebHook URL e.g.: https://yourdomain.com/webhook/ | |
| 19 | +TELEGRAM_WEBHOOK_URL = /telegram/getUpdates | |
| 20 | + | |
| 21 | + | |
| 22 | +# Your Bot Token e.g.: 000000000:AAAAa0aAA_aaA-Aaaa0A0Aa_a0aa0A0AAAA | |
| 23 | +TELEGRAM_BOT_TOKEN = XXXXX:XXXXX-XXXXX | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | +BING_SPEECH_LOCALE = global | |
| 28 | + | |
| 29 | +BING_SPEECH_GUID = XXXXX | |
| 30 | + | |
| 31 | +BING_SPEECH_SECRET_KEY = XXXXX | |
| 32 | + | |
| 33 | + | |
| 34 | +LOCAL_ATTACHMENT_PATH = /tmp/bhtchatbot/attachments | |
| 35 | + | |
| 36 | +RASA_URL = http://rasa_nlu:5000 | |
| 37 | + | |
| 38 | +RASA_UNIT_ON = on | |
| 39 | +APIAI_UNIT_ON = on | |
| 40 | +FACEBOOK_UNIT_ON = on | |
| 41 | +TELEGRAM_UNIT_ON = on | |
| 42 | +MAINBOT_UNIT_ON = on | |
| 43 | +BING_UNIT_ON = on | |
| 0 | 44 | \ No newline at end of file | ... | ... |
docker/wildfly/volumes/deployments/README.md
0 → 100755
docker/wildfly/volumes/logs/README.md
0 → 100755
docu/apiai.md
0 → 100755
| 1 | +++ a/docu/apiai.md | |
| 1 | +# api.ai API | |
| 2 | + | |
| 3 | +<!-- MarkdownTOC --> | |
| 4 | + | |
| 5 | +- [api.ai Setup](#api.ai-setup) | |
| 6 | +- [Bot Setup](#bot-setup) | |
| 7 | +- [About apiai package](#about-apiai-package) | |
| 8 | +- [Used online sources](#used-online-sources) | |
| 9 | + | |
| 10 | +<!-- /MarkdownTOC --> | |
| 11 | + | |
| 12 | +## api.ai Setup | |
| 13 | + | |
| 14 | +- Create new [api.ai Account](https://console.api.ai/api-client) | |
| 15 | +- Add a new agent "BHT-Chatbot" | |
| 16 | +- You can import our agent settings(which include all intents and entities we created) under 'Settings'->'Export and Import', search agents in the agent list or create an own one | |
| 17 | +- Our settings are located under src\main\docker\rasa_nlu\volumes\data\api ... put them into a zip and you are able to upload them as described above | |
| 18 | +- The 'Training'-tab helps you to improve your bot in understanding requests | |
| 19 | + | |
| 20 | +## Bot Setup | |
| 21 | +- Get your 'Client access token' in the api.ai agent settings and place it under 'API_AI_TOKEN' in the 'config.properties' | |
| 22 | +- If necessary, change the context and language in 'ApiAiConnector'->'onMessage' | |
| 23 | + | |
| 24 | +## About apiai package | |
| 25 | + | |
| 26 | +- The 'model' directory contains java classes which represent the json-response we get from api.ai requests, which makes it possible to parse these jsons into java classes | |
| 27 | +- ApiAiResponse implements NLUResponse and makes it possible to access the intents and entities of api.ai's answer | |
| 28 | +- <b>IMPORTANT:</b> 'Parameters' contains the entities given by api.ai and has to be changed on changes of the entities at your api.ai agent | |
| 29 | +- ApiAiMessage contains the given BotMessage but also the ApiAiResponse to send both to Drools | |
| 30 | + | |
| 31 | +## Used online sources | |
| 32 | +- [api.ai Docs](https://api.ai/docs/getting-started/basics) | |
| 0 | 33 | \ No newline at end of file | ... | ... |
docu/attachmentstore.md
0 → 100755
| 1 | +++ a/docu/attachmentstore.md | |
| 1 | +# AttachmentStore | |
| 2 | + | |
| 3 | +<!-- MarkdownTOC --> | |
| 4 | + | |
| 5 | +- [Description](#desription) | |
| 6 | +- [Functionality](#functionality) | |
| 7 | +- [AttachmentService](#attachmentService) | |
| 8 | + | |
| 9 | +<!-- /MarkdownTOC --> | |
| 10 | + | |
| 11 | +## Description | |
| 12 | + | |
| 13 | +The AttachmentStore represents a Service to persist Data in any variation. For example: an audio-file from a messenger need to be stored locally to be processed further. | |
| 14 | + | |
| 15 | +## Functionality | |
| 16 | + | |
| 17 | +* storing voice/audio files locally | |
| 18 | +** you can give FileURIs or ByteArrayOutputStreams | |
| 19 | +* create and return file pathes (local) | |
| 20 | +* create and return FileURIs for GET requests | |
| 21 | + | |
| 22 | +## AttachmentService | |
| 23 | + | |
| 24 | +* the AttachmentService is simple REST Service to provide the data upload via GET requests. | |
| 0 | 25 | \ No newline at end of file | ... | ... |
docu/bingspeechapi.md
0 → 100755
| 1 | +++ a/docu/bingspeechapi.md | |
| 1 | +# Bing Speech API | |
| 2 | + | |
| 3 | +Step by step Guide. | |
| 4 | +<!-- MarkdownTOC --> | |
| 5 | + | |
| 6 | +- [Requirements](#requirements) | |
| 7 | +- [Microsoft Azure](#microsoft-azure-registration) | |
| 8 | + - [Registration](#registration) | |
| 9 | + - [Subscription plan](#subscription-plan) | |
| 10 | + - [Bing Speech Service](#bing-speech-service) | |
| 11 | +- [BingConnector](#bing-connector) | |
| 12 | +- [Used online sources](#used-online-sources) | |
| 13 | + | |
| 14 | +<!-- /MarkdownTOC --> | |
| 15 | + | |
| 16 | +## Requirements | |
| 17 | + | |
| 18 | +- Valid Credit Card | |
| 19 | + - Service can be used for free! But you need to deposit a payment method. | |
| 20 | + | |
| 21 | +## Microsoft Azure | |
| 22 | + | |
| 23 | +### Registration | |
| 24 | + | |
| 25 | +- Create new [Azure](https://azure.microsoft.com/de-de/free/) Account | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | +- Deposit a Payment Method - e.g. Credit Card | |
| 30 | + - You will receive 170 Euro welcome bonus for the first month. (You have to spend that in this month) | |
| 31 | +- [Log-In](https://portal.azure.com/#dashboard/private) with your new Account | |
| 32 | + | |
| 33 | +### Subscription plan | |
| 34 | + | |
| 35 | +- You have two options: | |
| 36 | + 1. Use your free trial subscription (ends after 30 days) | |
| 37 | + - Go back to Azure Dashboard | |
| 38 | + | |
| 39 | + 2. Create a new subscription (recommended) | |
| 40 | + | |
| 41 | + - Create new subscription for user-based payment | |
| 42 | + | |
| 43 | +  | |
| 44 | + | |
| 45 | + - Click on that  button | |
| 46 | + - Create new subscription for user-based payment | |
| 47 | + - Go back to Azure Dashboard | |
| 48 | + | |
| 49 | +### Bing Speech Service | |
| 50 | + | |
| 51 | +- Create a new Bing Speech Service (initialization might take a while) | |
| 52 | + | |
| 53 | + - Choose your subscription plan | |
| 54 | + - Choose your pricing plan (here you should choose the F0 - free tier - for 5k calls in a month) | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | +- Go back to Azure Dashboard and click on your new Service | |
| 59 | +- The secret keys and your subscription id is necessary for your authentication. You have to copy & paste them to your config.properties | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | +## Bing Connector | |
| 64 | + | |
| 65 | +- For Text to Speech and Speech to Text requests. | |
| 66 | + | |
| 67 | +```java | |
| 68 | +public class BingConnector implements MessageListener { | |
| 69 | + | |
| 70 | + private void generateAccesToken(){} | |
| 71 | + | |
| 72 | + private void sendSpeechToTextRequest(final BotMessage botMessage){} | |
| 73 | + | |
| 74 | + private void sendTextToSpeechRequest(final BotMessage botMessage){} | |
| 75 | +} | |
| 76 | +``` | |
| 77 | + | |
| 78 | +- AccessToken is required to successfully send parsing-request. Token generates from secret-keys mentioned above. | |
| 79 | +- AccessToken decays after 10 mins. You need to refresh the Token. | |
| 80 | + | |
| 81 | +__Important:__ Speech to Text REST requests need to have **_Transfer-Endcoding: chunked_** Header! | |
| 82 | + | |
| 83 | +## Used online sources | |
| 84 | +- [Bing Speech API overview](https://docs.microsoft.com/de-de/azure/cognitive-services/speech/home) | |
| 0 | 85 | \ No newline at end of file | ... | ... |
docu/canteenParser.md
0 → 100755
| 1 | +++ a/docu/canteenParser.md | |
| 1 | +# Canteen Parser with JSoup | |
| 2 | + | |
| 3 | +<!-- MarkdownTOC --> | |
| 4 | + | |
| 5 | +- [Installation](#installation) | |
| 6 | +- [Procedure](#procedure) | |
| 7 | +- [Result](#result) | |
| 8 | + | |
| 9 | +<!-- /MarkdownTOC --> | |
| 10 | + | |
| 11 | +JSoup is a Java library for working with real-world HTML. It provides a very convenient API for extracting and manipulating data, using the best of DOM, CSS, and jquery-like methods. | |
| 12 | + | |
| 13 | +[Jsoup: Java HTML Parser](https://jsoup.org/) | |
| 14 | + | |
| 15 | +## Installation | |
| 16 | +Just add the following line to your gradle dependencies in your build.gradle and refresh the project. | |
| 17 | +```gradle | |
| 18 | +compile "org.jsoup:jsoup:1.10.2" | |
| 19 | +``` | |
| 20 | + | |
| 21 | +## Procedure | |
| 22 | +The parser collects data of the beuth university canteen in the Luxemburger Straße 9, 13353 Berlin. | |
| 23 | +To get the requested data, the parser has to navigate through the single pages. | |
| 24 | + | |
| 25 | +To get data for two weeks, we have to call a page for every day. So at first we have to get all dates for the current and the next week. | |
| 26 | + | |
| 27 | +The other thing we need is the `resource_id` for the canteen we like to parse. In our case it's the `527`. | |
| 28 | + | |
| 29 | +If we have the dates we wish to parse and the correct resource_id for our canteen, we loop the dates and call the URL: | |
| 30 | +`https://www.stw.berlin/xhr/speiseplan-wochentag.html` | |
| 31 | +with the date and resource_id as params. | |
| 32 | + | |
| 33 | +After calling: | |
| 34 | +```java | |
| 35 | +Document doc = Jsoup.connect("https://www.stw.berlin/xhr/speiseplan-wochentag.html").data(params).userAgent("Mozilla").post(); | |
| 36 | +``` | |
| 37 | +where params represents a string map containing the resource_id and the requested date, we got an Document which we can parse to get all needed data. | |
| 38 | + | |
| 39 | +The Parser is called right before a given message needs to be checked by the drools rules. | |
| 40 | + | |
| 41 | +## Result | |
| 42 | +As a result we got a CanteenData object containing information of dishes for the current and next week. | |
| 0 | 43 | \ No newline at end of file | ... | ... |
docu/drools.md
0 → 100755
| 1 | +++ a/docu/drools.md | |
| 1 | +#Drools | |
| 2 | + | |
| 3 | +<!-- MarkdownTOC --> | |
| 4 | + | |
| 5 | +- [examples](#examples) | |
| 6 | +- [preparation](#preparation) | |
| 7 | +- [kmodule](#kmodule) | |
| 8 | +- [rule](#rule) | |
| 9 | +- [usage](#usage) | |
| 10 | + | |
| 11 | +<!-- /MarkdownTOC --> | |
| 12 | + | |
| 13 | +Official documentation: | |
| 14 | +[Drools documentation](https://docs.jboss.org/drools/release/7.0.0.Final/drools-docs/html_single/index.html) | |
| 15 | + | |
| 16 | +## examples | |
| 17 | +On the bottom of the [drools website](https://www.drools.org/) you can find a ZIP with many examples. | |
| 18 | +Just download it and follow the instructions to execute the instructions given on this page. | |
| 19 | + | |
| 20 | +###preparation | |
| 21 | +Befor we can start, we need to edit our build.gradle as follows: | |
| 22 | +```gradle | |
| 23 | +repositories { | |
| 24 | + mavenCentral() | |
| 25 | + maven { | |
| 26 | + url 'https://repository.jboss.org/nexus/content/groups/public/' | |
| 27 | + } | |
| 28 | +} | |
| 29 | + | |
| 30 | +dependencies { | |
| 31 | + compile "org.drools:drools-compiler:7.0.0.Final" | |
| 32 | +} | |
| 33 | +``` | |
| 34 | +We have to set a dependency and declare another maven repository. The installation doesn't work with the standard mavenCentral() repository. | |
| 35 | + | |
| 36 | +###kmodule | |
| 37 | +Another thing what we need is the `kmodule.xml` file. A config file for drools to know, which rules-file to use. | |
| 38 | +This file has to be saved under `resources/META-INF/`. | |
| 39 | +```xml | |
| 40 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 41 | +<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 42 | + xmlns="http://www.drools.org/xsd/kmodule"> | |
| 43 | + <kbase name="TestKB" packages="my.example.de"> | |
| 44 | + <ksession name="TestKS"/> | |
| 45 | + </kbase> | |
| 46 | +</kmodule> | |
| 47 | +``` | |
| 48 | + | |
| 49 | +###rule | |
| 50 | +Rules are defined in Drools via .drl files and has to be saved in the `resources` folder. Such a file could look like this: | |
| 51 | +```drools | |
| 52 | +import my.example.de.TestObject | |
| 53 | +import my.example.de.TextEnum; | |
| 54 | + | |
| 55 | +global my.example.de.TestKlasse testKlasse | |
| 56 | + | |
| 57 | +rule "Test Rule" | |
| 58 | + dialect "java" | |
| 59 | + when | |
| 60 | + m : TestObject( attribute.equals("Test") ) | |
| 61 | + then | |
| 62 | + modify ( m ) { setAnotherAttribute("Test successful" )}; | |
| 63 | +end | |
| 64 | + | |
| 65 | +rule "Greeting" | |
| 66 | + dialect "java" | |
| 67 | + when | |
| 68 | + m : TestObject( attribute.equals(TestEnum.GREETING.getText())) | |
| 69 | + then | |
| 70 | + modify ( m ) { setAnotherAttribute(testKlasse.getGreetingMsg())}; | |
| 71 | +end | |
| 72 | +``` | |
| 73 | +If we want to use caches or similar objects, we have to set them as global variables. | |
| 74 | +This is shown by the line `global my.example.de.TestKlasse testKlasse`. | |
| 75 | + | |
| 76 | +All rules in a drools-file are processed on an object, if the `when`-block fits for the given object. | |
| 77 | + | |
| 78 | +After `rule` we give our rules names. | |
| 79 | + | |
| 80 | +There are two possible dialects in drools-files. Default is `java` and the other one is `mvel`. | |
| 81 | + | |
| 82 | +The `when`-block checks if a given object fits for this rule and in the `then`-block you can do stuff if conditions are met. | |
| 83 | + | |
| 84 | +###usage | |
| 85 | +Now, that we've set the necessary dependencies and defined some rules, we can start and use our rules on some objects. | |
| 86 | +``` | |
| 87 | + // KieServices is the factory for all KIE services | |
| 88 | + KieServices ks = KieServices.Factory.get(); | |
| 89 | + | |
| 90 | + // From the kie services, a container is created from the classpath | |
| 91 | + KieContainer kc = ks.getKieClasspathContainer(); | |
| 92 | + | |
| 93 | + // From the container, a session is created based on | |
| 94 | + // its definition and configuration in the META-INF/kmodule.xml file | |
| 95 | + KieSession ksession = kc.newKieSession("TestKS"); | |
| 96 | + | |
| 97 | + // Once the session is created, the application can interact with it | |
| 98 | + // In this case it is setting a global as defined in the | |
| 99 | + // org/drools/examples/helloworld/HelloWorld.drl file | |
| 100 | + Testklasse testKlasse = new TestKlasse(); | |
| 101 | + ksession.setGlobal("testKlasse", testKlasse); | |
| 102 | + | |
| 103 | + // Object, to fire rules on | |
| 104 | + TestObject testObject = new TestObject(); | |
| 105 | + | |
| 106 | + // The application can insert facts into the session | |
| 107 | + ksession.insert(testObject); | |
| 108 | + | |
| 109 | + // Test output before | |
| 110 | + System.out.println(testObject.getAnotherAttribute()); | |
| 111 | + | |
| 112 | + // and fire the rules | |
| 113 | + ksession.fireAllRules(); | |
| 114 | + | |
| 115 | + // Test output after | |
| 116 | + System.out.println(testObject.getAnotherAttribute()); | |
| 117 | + | |
| 118 | + // and then dispose the session | |
| 119 | + ksession.dispose(); | |
| 120 | +``` | |
| 121 | +The first line are just standard to create a `KieSession`. | |
| 122 | +On this `KieSession` we can set globals as mentioned in rules section. | |
| 123 | +Objects, on which we want to process the rules have to be inserted in this sessoin `ksession.insert(testObject);`. | |
| 124 | + | |
| 125 | +After we have inserted all objects we want to process, we start the procession by `kieSession.fireAllRules();`. | |
| 126 | + | |
| 127 | +This is it, after the last command is finished, all objects should be processed. | |
| 0 | 128 | \ No newline at end of file | ... | ... |
docu/facebook.md
0 → 100755
| 1 | +++ a/docu/facebook.md | |
| 1 | +# Facebook Adapter | |
| 2 | + | |
| 3 | +<!-- MarkdownTOC --> | |
| 4 | + | |
| 5 | +- [Framework](#framework) | |
| 6 | +- [Setup](#setup) | |
| 7 | +- [Structure](#structure) | |
| 8 | +- [Used online sources](#used-online-sources) | |
| 9 | + | |
| 10 | +<!-- /MarkdownTOC --> | |
| 11 | + | |
| 12 | +## Framework | |
| 13 | + | |
| 14 | +- Contrary to the Telegram Adapter, we did not use a Framework for Facebook and implemented the communication with Facebook by ourselves | |
| 15 | + | |
| 16 | +## Setup | |
| 17 | + | |
| 18 | +- You need: | |
| 19 | + 1. Facebook Page (https://www.facebook.com/pages/create/) | |
| 20 | + 2. Facebook App (https://developers.facebook.com/apps/) | |
| 21 | + 3. A Server with ssl certificate | |
| 22 | + | |
| 23 | +##### i. Facebook Page | |
| 24 | + | |
| 25 | +- your users communicate with this page while the App is working in the background | |
| 26 | +- use an existing one or create a new page | |
| 27 | + | |
| 28 | +##### ii. Facebook App | |
| 29 | + | |
| 30 | +- after you created the app, add the 'messenger product' in the control panel on the left side | |
| 31 | +- generate an messaging key for your Facebook page and store it under 'FACEBOOK_BOT_TOKEN' in the config.properties | |
| 32 | +- setup a webhook by using your webhook address (https://yourdomain.com/rest/facebook/getUpdates) and the identification key set in 'FACEBOOK_WEBHOOK_TOKEN' in the config.properties | |
| 33 | +- subscribe the webhook to your Facebook page | |
| 34 | +- NOTE: if you want to change the address of the webhook (for example if your server address changes) there are two possibilities: | |
| 35 | + 1. navigate to the webhook product on the left and select 'Edit Subscription' | |
| 36 | + 2. you can set the webhook to your current address by opening 'http(s)://yourdomain.com/rest/facebook/setWebhook', but this requires to set 'FACEBOOK_ACCESS_TOKEN' in the config.properties. You can get your access token at 'https://developers.facebook.com/tools/explorer/' by selecting your app. Be sure you select 'app access token' in the dropdown menu, otherwise it generates an user access token. The app token should look like this: '00000000000|XXXXXXXXX-XXXXXXX'. This possibility of changing the webhook path needs more time in setting it up at the beginning, but it's more comfortable in the end, especially when the amount of Messengers grows (e.g you set your Telegram webhook at 'http(s)://yourdomain.com/rest/telegram/setWebhook'). | |
| 37 | + | |
| 38 | +##### iii. ssl certificate | |
| 39 | + | |
| 40 | +- if you don't have a valid sll crtificate, there are several ways of setting up https for your domain for free. While we were in development, we used localtunnel to generate a https-URL which tunneled the port 8080 to our PCs. If you own a domain, you can also use Cloudflare as nameserver which makes it possible to use free SSL-certificates as well. | |
| 41 | + | |
| 42 | +## Structure | |
| 43 | + | |
| 44 | +- Facebook Adapter is split into three basic classes: | |
| 45 | + 1. FacebookReceiveAdapter | |
| 46 | + 2. FacebookSendAdapter | |
| 47 | + 3. FacebookUtils | |
| 48 | + | |
| 49 | +##### i. FacebookReceiveAdapter | |
| 50 | + | |
| 51 | +- For receiving new messages from Users and webhook requests. | |
| 52 | + | |
| 53 | +Using RESTEasy for HTTP Requests | |
| 54 | +```java | |
| 55 | +@Path("/facebook") | |
| 56 | +public class FacebookReceiveAdapter { | |
| 57 | +``` | |
| 58 | +POST Requests for incoming Facebook messages: | |
| 59 | +```java | |
| 60 | + @POST | |
| 61 | + @Path("/getUpdates") | |
| 62 | + @Consumes("application/json") | |
| 63 | + public String ReceiveMessage(String InputMessage) {} | |
| 64 | +``` | |
| 65 | +GET Requests for webhook verification: | |
| 66 | +```java | |
| 67 | + @GET | |
| 68 | + @Path("/getUpdates") | |
| 69 | + @Produces("text/plain") | |
| 70 | + public String verification(@Context HttpServletRequest request){} | |
| 71 | +``` | |
| 72 | +GET Requests for webhook initialization (if user opens http://yourdomain.com/rest/facebook/setWebhook to set the Facebook webhook to your current server address): | |
| 73 | +```java | |
| 74 | + @GET | |
| 75 | + @Path("/setWebhook") | |
| 76 | + @Produces("text/plain") | |
| 77 | + public String setWebhook(@Context HttpServletRequest request){} | |
| 78 | +``` | |
| 79 | +```java | |
| 80 | + } | |
| 81 | +``` | |
| 82 | + | |
| 83 | +##### ii. FacebookSendAdapter | |
| 84 | + | |
| 85 | +- For sending new messages to Users. | |
| 86 | + | |
| 87 | +Send Text Request: | |
| 88 | +- Facebook limits the character amount per message to 640, that's why we have to split messages if they are to long | |
| 89 | +- if the messages contain multiple entries (e.g. dishes), it makes sense to split them to avoid message-splits within entries | |
| 90 | +```java | |
| 91 | + private void sendMessage(Long recipient, String messageJson) { | |
| 92 | + Boolean seperateMessages = true; | |
| 93 | + String seperator = ", --------------------------"; | |
| 94 | + | |
| 95 | + for( String currentMessage : facebookUtils.splitIntoMultipleMessages(messageJson,600,seperateMessages,seperator) ) { | |
| 96 | + String payload = "{\"recipient\": {\"id\": \"" + recipient + "\"}, \"message\": { \"text\": \"" + currentMessage + "\"}}"; | |
| 97 | + facebookUtils.sendPostRequest(requestUrl, payload, facebookUtils.token()); | |
| 98 | + } | |
| 99 | + } | |
| 100 | +``` | |
| 101 | + | |
| 102 | +Send Media Request: | |
| 103 | +```java | |
| 104 | + private void sendMedia(BotMessage message,String mediaType){ | |
| 105 | + String fileURL=attachmentStore.loadAttachmentPath(message.getAttachments()[0].getId(), AttachmentStoreMode.FILE_URI); | |
| 106 | + String payload = "{recipient: { id: "+message.getSenderID()+" }, message: { attachment: { type: \""+mediaType+"\", payload: { url: \""+fileURL+"\" } } }} "; | |
| 107 | + String requestUrl = "https://graph.facebook.com/v2.6/me/messages" ; | |
| 108 | + facebookUtils.sendPostRequest(requestUrl, payload,facebookUtils.token()); | |
| 109 | + } | |
| 110 | +``` | |
| 111 | + | |
| 112 | +##### iii. FacebookUtils | |
| 113 | + | |
| 114 | +- Contains methods which are used by both, sender and receiver. | |
| 115 | +- While some methods just return property configs, these three are more important: | |
| 116 | + | |
| 117 | +Webhook activation: | |
| 118 | +- after the webhook is verified, it needs to be activated to subscribe to the incoming messages | |
| 119 | +- this has to be done after a short delay to ensure that the webhook is registered by Facebook | |
| 120 | +```java | |
| 121 | +public void activateWebhook() { | |
| 122 | + | |
| 123 | + Runnable activation = new Runnable() { | |
| 124 | + public void run() { | |
| 125 | + try { | |
| 126 | + Thread.sleep(5000); | |
| 127 | + } catch (InterruptedException e) { | |
| 128 | + e.printStackTrace(); | |
| 129 | + } | |
| 130 | + sendPostRequest("https://graph.facebook.com/v2.9/me/subscribed_apps","",token()); | |
| 131 | + } | |
| 132 | + }; | |
| 133 | + new Thread(activation).start(); | |
| 134 | + } | |
| 135 | +``` | |
| 136 | +Send requests to Facebook via our FacebookRESTServiceInterface: | |
| 137 | +```java | |
| 138 | + public String sendPostRequest(String requestUrl, String payload, String token) { | |
| 139 | + | |
| 140 | + ResteasyClient client = new ResteasyClientBuilder().build(); | |
| 141 | + ResteasyWebTarget target = client.target(UriBuilder.fromPath(requestUrl)); | |
| 142 | + FacebookRESTServiceInterface facebookProxy = target.proxy(FacebookRESTServiceInterface.class); | |
| 143 | + | |
| 144 | + Response response = facebookProxy.sendMessage(payload, token); | |
| 145 | + | |
| 146 | + String responseAsString = response.readEntity(String.class); | |
| 147 | + | |
| 148 | + | |
| 149 | + return responseAsString; | |
| 150 | + | |
| 151 | + } | |
| 152 | +``` | |
| 153 | +Split the message into multiple messages with sendable size: | |
| 154 | +- split at newlines and store message before char limit reached or between entries (if enabled) | |
| 155 | +- return list of messages which FacebookSend iterates through to send everything | |
| 156 | +```java | |
| 157 | +public List<String> splitIntoMultipleMessages(String messageJson, int charLimit, Boolean seperateMessages, String seperator){ | |
| 158 | + List<String> messages = new ArrayList<String>(); | |
| 159 | + | |
| 160 | + String linesOfMessage[] = messageJson.split("\\r?\\n"); | |
| 161 | + | |
| 162 | + String currentOutput = ""; | |
| 163 | + for (int i = 0; i < linesOfMessage.length; i++) { | |
| 164 | + String line = linesOfMessage[i]; | |
| 165 | + if ((currentOutput + "\\n" + line).length() > charLimit || (line.contains(seperator)&&seperateMessages)) { | |
| 166 | + messages.add(currentOutput); | |
| 167 | + | |
| 168 | + if(line.contains(seperator) && seperateMessages) { | |
| 169 | + line=""; | |
| 170 | + } | |
| 171 | + | |
| 172 | + currentOutput = line; | |
| 173 | + } else { | |
| 174 | + currentOutput = currentOutput + "\\n" + line; | |
| 175 | + } | |
| 176 | + | |
| 177 | + | |
| 178 | + } | |
| 179 | + messages.add(currentOutput); | |
| 180 | + | |
| 181 | + | |
| 182 | + return messages; | |
| 183 | + } | |
| 184 | +``` | |
| 185 | +## Used online sources | |
| 186 | + | |
| 187 | +- [Facebook API overview](https://developers.facebook.com/docs/) | |
| 0 | 188 | \ No newline at end of file | ... | ... |
docu/img/architecture.png
0 → 100755
11.7 KB
docu/img/bing/azure-registration.png
0 → 100755
46.1 KB
docu/img/bing/billing-menu.png
0 → 100755
32.3 KB
docu/img/bing/bing-speech-service-dashboard.png
0 → 100755
50.8 KB
docu/img/bing/create-new-bing-speech-service.png
0 → 100755
145 KB
docu/img/bing/manage-btn.png
0 → 100755
658 Bytes
docu/img/model.png
0 → 100755
5.4 KB
docu/project_documentation.md
0 → 100755
| 1 | +++ a/docu/project_documentation.md | |
| 1 | +# BHT-Chatbot Project | |
| 2 | +The hole project is build by gradle and divided into a couple of subprojects (cf. [Subprojects section](#subprojects) ). | |
| 3 | +Each module is loosely connected through a Java Message Service. The application is running on a Jboss Wildfly | |
| 4 | +inside of a docker container. Another docker container is used for the Rasa backend. | |
| 5 | + | |
| 6 | +## Infrastructure | |
| 7 | +- see [docker compose file](../docker/docker-compose.yml) | |
| 8 | + | |
| 9 | +The productive project is represented by a separate Git repository in absent of a continuous integration server. | |
| 10 | +Pushing into this repository will automatically trigger a rebuild of the productive environment. | |
| 11 | +- confer [post-receive](../scripts/post-receive) - Git hook for auto deploying the application | |
| 12 | + | |
| 13 | +### Subprojects | |
| 14 | + | |
| 15 | +#### MainBot | |
| 16 | +- [Canteen Parser](canteenParser.md) - web crawler for collecting data of the beuth university canteen | |
| 17 | +- Common - holding common classes used by all other subprojects | |
| 18 | +- [Drools](drools.md) - Business Rules Management System used to generate the right answer | |
| 19 | +- Global - global available services | |
| 20 | + | |
| 21 | +#### Natural Language Processing | |
| 22 | +- [ApiAi](apiai.md) - simple RESTEasy client application calling googles Api.ai API | |
| 23 | +- [Rasa](rasa.md) - simple RESTEasy client application calling the rasa backend rest API | |
| 24 | + | |
| 25 | +#### Messenger | |
| 26 | +- [Facebook](facebook.md) - Facebook Messenger connector | |
| 27 | +- [Telegram](telegram.md) - Telegram Messenger connector | |
| 28 | + | |
| 29 | +#### Text <-> Speech Processing | |
| 30 | +- [Bing Speech](binspeechapi.md) - REST client for Microsofts Bing Speech API | |
| 0 | 31 | \ No newline at end of file | ... | ... |
docu/rasa.md
0 → 100755
| 1 | +++ a/docu/rasa.md | |
| 1 | +# Rasa | |
| 2 | +The Rasa subproject is basically a simple RESTEasy client application calling the rasa backend REST API. | |
| 3 | + | |
| 4 | +## Update and train the model | |
| 5 | +We are using the same training data as used by Api.ai. Just extract the exported agent zip to `docker/rasa_nlu/volumes/data/api/` and rebuild the container. | |
| 6 | +You can login to the running container and execute `python -m rasa_nlu.train -c config/chatbot_config.json` also (cf. [rasa Dockerfile](../docker/rasa_nlu/Dockerfile)). | |
| 7 | +Be aware of that training the model can take some time. | |
| 8 | + | |
| 9 | +## Used online sources | |
| 10 | + - [rasa documentation](https://rasa-nlu.readthedocs.io/en/latest/tutorial.html) | |
| 11 | + - [RESTEasy 3.1.3](https://docs.jboss.org/resteasy/docs/3.1.3.Final/userguide/html/) | |
| 0 | 12 | \ No newline at end of file | ... | ... |
docu/telegram.md
0 → 100755
| 1 | +++ a/docu/telegram.md | |
| 1 | +# Telegram Adapter | |
| 2 | + | |
| 3 | +Step by step Guide. | |
| 4 | +<!-- MarkdownTOC --> | |
| 5 | + | |
| 6 | +- [Framework](#framework) | |
| 7 | +- [Structure](#structure) | |
| 8 | +- [Used online sources](#used-online-sources) | |
| 9 | + | |
| 10 | +<!-- /MarkdownTOC --> | |
| 11 | + | |
| 12 | +## Framework | |
| 13 | + | |
| 14 | +- Using [Java-Telegram-Bot-API](https://github.com/pengrad/java-telegram-bot-api) Framework from github user pengrad. | |
| 15 | + - Easy access to Telegram API via TelegramBot-Objects | |
| 16 | + - Well maintained repository (June 2017) | |
| 17 | + | |
| 18 | +## Structure | |
| 19 | + | |
| 20 | +- Telegram Adapter is split in two basic classes: | |
| 21 | + 1. TelegramReceiveAdapter | |
| 22 | + 2. TelegramSendAdapter | |
| 23 | +- Receiving messages via webhook. | |
| 24 | + | |
| 25 | +##### i. TelegramReceiveAdapter | |
| 26 | + | |
| 27 | +- For receiving new messages from Users. | |
| 28 | + | |
| 29 | +Using RESTEasy for HTTP Requests. | |
| 30 | +```java | |
| 31 | +@Path("/telegram") | |
| 32 | +public class TelegramReceiveAdapter { | |
| 33 | + | |
| 34 | + @POST | |
| 35 | + @Path("/getUpdates") | |
| 36 | + public void getUpdates(final String msg) {} | |
| 37 | + | |
| 38 | + ... | |
| 39 | +} | |
| 40 | +``` | |
| 41 | + | |
| 42 | + | |
| 43 | +##### ii. TelegramSendAdapter | |
| 44 | + | |
| 45 | +- For sending new messages to Users. | |
| 46 | + | |
| 47 | +Asynchronus Webhook verification. | |
| 48 | +```java | |
| 49 | +SetWebhook webhook = new SetWebhook().url(properties.getProperty("WEB_URL") + properties.getProperty("TELEGRAM_WEBHOOK_URL")); | |
| 50 | + | |
| 51 | +bot.execute(webhook, new Callback<SetWebhook, BaseResponse>() { | |
| 52 | + @Override | |
| 53 | + public void onResponse(final SetWebhook request, final BaseResponse response) { | |
| 54 | + logger.debug("No errors while setting Telegram webhook."); | |
| 55 | + } | |
| 56 | + @Override | |
| 57 | + public void onFailure(final SetWebhook request, final IOException e) { | |
| 58 | + logger.warn("An Error occured while setting Telegram webhook. BOT_TOKEN: " + properties.getProperty("TELEGRAM_BOT_TOKEN") + " - WEBHOOK_URL: " + properties.getProperty("WEB_URL") + properties.getProperty("TELEGRAM_WEBHOOK_URL")); | |
| 59 | + } | |
| 60 | +}); | |
| 61 | +``` | |
| 62 | + | |
| 63 | +Send Text Request. | |
| 64 | +```java | |
| 65 | +private void sendMessage(final Long senderId, final String message) { | |
| 66 | + SendMessage request = new SendMessage(senderId, message); | |
| 67 | + SendResponse sendResponse = bot.execute(request); | |
| 68 | + logger.debug("Send de.bht.chatbot.message: " + sendResponse.isOk()); | |
| 69 | + } | |
| 70 | +``` | |
| 71 | + | |
| 72 | +Send Audio Request. | |
| 73 | +```java | |
| 74 | +private void sendAudio(final BotMessage botMessage){ | |
| 75 | + SendAudio request; | |
| 76 | + | |
| 77 | + // check and send each attachement | |
| 78 | + for (Attachment attachment : botMessage.getAttachements()) { | |
| 79 | + request = new SendAudio(botMessage.getSenderID(), attachment.getFileURI()); | |
| 80 | + | |
| 81 | + if (attachment.getCaption() != null) | |
| 82 | + request.caption(attachment.getCaption()); | |
| 83 | + | |
| 84 | + SendResponse sendResponse = bot.execute(request); | |
| 85 | + logger.debug("Send Audio: " + sendResponse.isOk()); | |
| 86 | + } | |
| 87 | +} | |
| 88 | +``` | |
| 89 | + | |
| 90 | +## Used online sources | |
| 91 | + | |
| 92 | +- [Telegram API overview](https://core.telegram.org/bots/api) | |
| 93 | +- [Java-Telegram-Bot-API](https://github.com/pengrad/java-telegram-bot-api) (github - user: pengrad) | |
| 0 | 94 | \ No newline at end of file | ... | ... |
gradle/wrapper/gradle-wrapper.jar
0 → 100755
No preview for this file type
gradle/wrapper/gradle-wrapper.properties
0 → 100755
| 1 | +++ a/gradle/wrapper/gradle-wrapper.properties | |
| 1 | +#Thu May 04 17:39:29 CEST 2017 | |
| 2 | +distributionBase=GRADLE_USER_HOME | |
| 3 | +distributionPath=wrapper/dists | |
| 4 | +zipStoreBase=GRADLE_USER_HOME | |
| 5 | +zipStorePath=wrapper/dists | |
| 6 | +distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip | ... | ... |
gradlew
0 → 100755
| 1 | +++ a/gradlew | |
| 1 | +#!/usr/bin/env sh | |
| 2 | + | |
| 3 | +############################################################################## | |
| 4 | +## | |
| 5 | +## Gradle start up script for UN*X | |
| 6 | +## | |
| 7 | +############################################################################## | |
| 8 | + | |
| 9 | +# Attempt to set APP_HOME | |
| 10 | +# Resolve links: $0 may be a link | |
| 11 | +PRG="$0" | |
| 12 | +# Need this for relative symlinks. | |
| 13 | +while [ -h "$PRG" ] ; do | |
| 14 | + ls=`ls -ld "$PRG"` | |
| 15 | + link=`expr "$ls" : '.*-> \(.*\)$'` | |
| 16 | + if expr "$link" : '/.*' > /dev/null; then | |
| 17 | + PRG="$link" | |
| 18 | + else | |
| 19 | + PRG=`dirname "$PRG"`"/$link" | |
| 20 | + fi | |
| 21 | +done | |
| 22 | +SAVED="`pwd`" | |
| 23 | +cd "`dirname \"$PRG\"`/" >/dev/null | |
| 24 | +APP_HOME="`pwd -P`" | |
| 25 | +cd "$SAVED" >/dev/null | |
| 26 | + | |
| 27 | +APP_NAME="Gradle" | |
| 28 | +APP_BASE_NAME=`basename "$0"` | |
| 29 | + | |
| 30 | +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |
| 31 | +DEFAULT_JVM_OPTS="" | |
| 32 | + | |
| 33 | +# Use the maximum available, or set MAX_FD != -1 to use that value. | |
| 34 | +MAX_FD="maximum" | |
| 35 | + | |
| 36 | +warn ( ) { | |
| 37 | + echo "$*" | |
| 38 | +} | |
| 39 | + | |
| 40 | +die ( ) { | |
| 41 | + echo | |
| 42 | + echo "$*" | |
| 43 | + echo | |
| 44 | + exit 1 | |
| 45 | +} | |
| 46 | + | |
| 47 | +# OS specific support (must be 'true' or 'false'). | |
| 48 | +cygwin=false | |
| 49 | +msys=false | |
| 50 | +darwin=false | |
| 51 | +nonstop=false | |
| 52 | +case "`uname`" in | |
| 53 | + CYGWIN* ) | |
| 54 | + cygwin=true | |
| 55 | + ;; | |
| 56 | + Darwin* ) | |
| 57 | + darwin=true | |
| 58 | + ;; | |
| 59 | + MINGW* ) | |
| 60 | + msys=true | |
| 61 | + ;; | |
| 62 | + NONSTOP* ) | |
| 63 | + nonstop=true | |
| 64 | + ;; | |
| 65 | +esac | |
| 66 | + | |
| 67 | +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | |
| 68 | + | |
| 69 | +# Determine the Java command to use to start the JVM. | |
| 70 | +if [ -n "$JAVA_HOME" ] ; then | |
| 71 | + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | |
| 72 | + # IBM's JDK on AIX uses strange locations for the executables | |
| 73 | + JAVACMD="$JAVA_HOME/jre/sh/java" | |
| 74 | + else | |
| 75 | + JAVACMD="$JAVA_HOME/bin/java" | |
| 76 | + fi | |
| 77 | + if [ ! -x "$JAVACMD" ] ; then | |
| 78 | + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME | |
| 79 | + | |
| 80 | +Please set the JAVA_HOME variable in your environment to match the | |
| 81 | +location of your Java installation." | |
| 82 | + fi | |
| 83 | +else | |
| 84 | + JAVACMD="java" | |
| 85 | + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |
| 86 | + | |
| 87 | +Please set the JAVA_HOME variable in your environment to match the | |
| 88 | +location of your Java installation." | |
| 89 | +fi | |
| 90 | + | |
| 91 | +# Increase the maximum file descriptors if we can. | |
| 92 | +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then | |
| 93 | + MAX_FD_LIMIT=`ulimit -H -n` | |
| 94 | + if [ $? -eq 0 ] ; then | |
| 95 | + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then | |
| 96 | + MAX_FD="$MAX_FD_LIMIT" | |
| 97 | + fi | |
| 98 | + ulimit -n $MAX_FD | |
| 99 | + if [ $? -ne 0 ] ; then | |
| 100 | + warn "Could not set maximum file descriptor limit: $MAX_FD" | |
| 101 | + fi | |
| 102 | + else | |
| 103 | + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" | |
| 104 | + fi | |
| 105 | +fi | |
| 106 | + | |
| 107 | +# For Darwin, add options to specify how the application appears in the dock | |
| 108 | +if $darwin; then | |
| 109 | + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" | |
| 110 | +fi | |
| 111 | + | |
| 112 | +# For Cygwin, switch paths to Windows format before running java | |
| 113 | +if $cygwin ; then | |
| 114 | + APP_HOME=`cygpath --path --mixed "$APP_HOME"` | |
| 115 | + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` | |
| 116 | + JAVACMD=`cygpath --unix "$JAVACMD"` | |
| 117 | + | |
| 118 | + # We build the pattern for arguments to be converted via cygpath | |
| 119 | + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` | |
| 120 | + SEP="" | |
| 121 | + for dir in $ROOTDIRSRAW ; do | |
| 122 | + ROOTDIRS="$ROOTDIRS$SEP$dir" | |
| 123 | + SEP="|" | |
| 124 | + done | |
| 125 | + OURCYGPATTERN="(^($ROOTDIRS))" | |
| 126 | + # Add a user-defined pattern to the cygpath arguments | |
| 127 | + if [ "$GRADLE_CYGPATTERN" != "" ] ; then | |
| 128 | + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" | |
| 129 | + fi | |
| 130 | + # Now convert the arguments - kludge to limit ourselves to /bin/sh | |
| 131 | + i=0 | |
| 132 | + for arg in "$@" ; do | |
| 133 | + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` | |
| 134 | + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option | |
| 135 | + | |
| 136 | + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition | |
| 137 | + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` | |
| 138 | + else | |
| 139 | + eval `echo args$i`="\"$arg\"" | |
| 140 | + fi | |
| 141 | + i=$((i+1)) | |
| 142 | + done | |
| 143 | + case $i in | |
| 144 | + (0) set -- ;; | |
| 145 | + (1) set -- "$args0" ;; | |
| 146 | + (2) set -- "$args0" "$args1" ;; | |
| 147 | + (3) set -- "$args0" "$args1" "$args2" ;; | |
| 148 | + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; | |
| 149 | + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; | |
| 150 | + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; | |
| 151 | + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; | |
| 152 | + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; | |
| 153 | + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; | |
| 154 | + esac | |
| 155 | +fi | |
| 156 | + | |
| 157 | +# Escape application args | |
| 158 | +save ( ) { | |
| 159 | + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done | |
| 160 | + echo " " | |
| 161 | +} | |
| 162 | +APP_ARGS=$(save "$@") | |
| 163 | + | |
| 164 | +# Collect all arguments for the java command, following the shell quoting and substitution rules | |
| 165 | +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" | |
| 166 | + | |
| 167 | +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong | |
| 168 | +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then | |
| 169 | + cd "$(dirname "$0")" | |
| 170 | +fi | |
| 171 | + | |
| 172 | +exec "$JAVACMD" "$@" | ... | ... |
gradlew.bat
0 → 100755
| 1 | +++ a/gradlew.bat | |
| 1 | +@if "%DEBUG%" == "" @echo off | |
| 2 | +@rem ########################################################################## | |
| 3 | +@rem | |
| 4 | +@rem Gradle startup script for Windows | |
| 5 | +@rem | |
| 6 | +@rem ########################################################################## | |
| 7 | + | |
| 8 | +@rem Set local scope for the variables with windows NT shell | |
| 9 | +if "%OS%"=="Windows_NT" setlocal | |
| 10 | + | |
| 11 | +set DIRNAME=%~dp0 | |
| 12 | +if "%DIRNAME%" == "" set DIRNAME=. | |
| 13 | +set APP_BASE_NAME=%~n0 | |
| 14 | +set APP_HOME=%DIRNAME% | |
| 15 | + | |
| 16 | +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. | |
| 17 | +set DEFAULT_JVM_OPTS= | |
| 18 | + | |
| 19 | +@rem Find java.exe | |
| 20 | +if defined JAVA_HOME goto findJavaFromJavaHome | |
| 21 | + | |
| 22 | +set JAVA_EXE=java.exe | |
| 23 | +%JAVA_EXE% -version >NUL 2>&1 | |
| 24 | +if "%ERRORLEVEL%" == "0" goto init | |
| 25 | + | |
| 26 | +echo. | |
| 27 | +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. | |
| 28 | +echo. | |
| 29 | +echo Please set the JAVA_HOME variable in your environment to match the | |
| 30 | +echo location of your Java installation. | |
| 31 | + | |
| 32 | +goto fail | |
| 33 | + | |
| 34 | +:findJavaFromJavaHome | |
| 35 | +set JAVA_HOME=%JAVA_HOME:"=% | |
| 36 | +set JAVA_EXE=%JAVA_HOME%/bin/java.exe | |
| 37 | + | |
| 38 | +if exist "%JAVA_EXE%" goto init | |
| 39 | + | |
| 40 | +echo. | |
| 41 | +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% | |
| 42 | +echo. | |
| 43 | +echo Please set the JAVA_HOME variable in your environment to match the | |
| 44 | +echo location of your Java installation. | |
| 45 | + | |
| 46 | +goto fail | |
| 47 | + | |
| 48 | +:init | |
| 49 | +@rem Get command-line arguments, handling Windows variants | |
| 50 | + | |
| 51 | +if not "%OS%" == "Windows_NT" goto win9xME_args | |
| 52 | + | |
| 53 | +:win9xME_args | |
| 54 | +@rem Slurp the command line arguments. | |
| 55 | +set CMD_LINE_ARGS= | |
| 56 | +set _SKIP=2 | |
| 57 | + | |
| 58 | +:win9xME_args_slurp | |
| 59 | +if "x%~1" == "x" goto execute | |
| 60 | + | |
| 61 | +set CMD_LINE_ARGS=%* | |
| 62 | + | |
| 63 | +:execute | |
| 64 | +@rem Setup the command line | |
| 65 | + | |
| 66 | +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | |
| 67 | + | |
| 68 | +@rem Execute Gradle | |
| 69 | +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% | |
| 70 | + | |
| 71 | +:end | |
| 72 | +@rem End local scope for the variables with windows NT shell | |
| 73 | +if "%ERRORLEVEL%"=="0" goto mainEnd | |
| 74 | + | |
| 75 | +:fail | |
| 76 | +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of | |
| 77 | +rem the _cmd.exe /c_ return code! | |
| 78 | +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 | |
| 79 | +exit /b 1 | |
| 80 | + | |
| 81 | +:mainEnd | |
| 82 | +if "%OS%"=="Windows_NT" endlocal | |
| 83 | + | |
| 84 | +:omega | ... | ... |
scripts/deployment.sh
0 → 100755
scripts/post-receive
0 → 100755
| 1 | +++ a/scripts/post-receive | |
| 1 | +#!/bin/bash | |
| 2 | + | |
| 3 | +# git hook | |
| 4 | +while read oldrev newrev ref | |
| 5 | +do | |
| 6 | + # only checking out the master (or whatever branch you would like to deploy) | |
| 7 | + if [[ $ref =~ .*/master$ ]]; | |
| 8 | + then | |
| 9 | + echo "Master ref received. Deploying master branch to production..." | |
| 10 | + git --work-tree=/home/beuthbot/BeuthBotServer/ --git-dir=/home/beuthbot/BeuthBotServer.git/ checkout -f | |
| 11 | + cd /home/beuthbot/BeuthBotServer/ | |
| 12 | + ./scripts/deployment.sh | |
| 13 | + else | |
| 14 | + echo "Ref $ref successfully received. Doing nothing: only the master branch may be deployed on this server." | |
| 15 | + fi | |
| 16 | +done | |
| 0 | 17 | \ No newline at end of file | ... | ... |
services/ApiAi/build.gradle
0 → 100755
| 1 | +++ a/services/ApiAi/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | +} | |
| 8 | + | |
| 9 | +dependencies { | |
| 10 | + compile project(':services:Common'), | |
| 11 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 12 | + "com.google.code.gson:gson:2.8.1" | |
| 13 | + | |
| 14 | + providedCompile "org.slf4j:slf4j-api:1.7.25", | |
| 15 | + "org.jboss.resteasy:resteasy-client:3.1.3.Final" | |
| 16 | + | |
| 17 | + testCompile "org.jboss.arquillian.junit:arquillian-junit-container:1.1.13.Final", | |
| 18 | + "junit:junit:4.12" | |
| 19 | + | |
| 20 | + testRuntime "org.wildfly.arquillian:wildfly-arquillian-container-remote:2.0.2.Final", | |
| 21 | + "org.slf4j:slf4j-simple:1.7.25" | |
| 22 | +} | |
| 23 | + | |
| 24 | +sourceCompatibility = 1.8 | |
| 25 | + | |
| 26 | +war { | |
| 27 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 28 | + archiveName "apiai.war" | |
| 29 | +} | |
| 0 | 30 | \ No newline at end of file | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/ApiAiConnector.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/ApiAiConnector.java | |
| 1 | +package de.bht.beuthbot.nlp.apiai; | |
| 2 | + | |
| 3 | +import com.google.gson.Gson; | |
| 4 | +import de.bht.beuthbot.conf.Application; | |
| 5 | +import de.bht.beuthbot.conf.Configuration; | |
| 6 | +import de.bht.beuthbot.jms.ProcessQueue; | |
| 7 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 8 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 9 | +import de.bht.beuthbot.nlp.apiai.model.ApiAiMessage; | |
| 10 | +import de.bht.beuthbot.nlp.apiai.model.ApiAiResponse; | |
| 11 | +import org.jboss.resteasy.client.jaxrs.ResteasyClient; | |
| 12 | +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; | |
| 13 | +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; | |
| 14 | +import org.slf4j.Logger; | |
| 15 | +import org.slf4j.LoggerFactory; | |
| 16 | + | |
| 17 | +import javax.annotation.PostConstruct; | |
| 18 | +import javax.annotation.Resource; | |
| 19 | +import javax.ejb.ActivationConfigProperty; | |
| 20 | +import javax.ejb.MessageDriven; | |
| 21 | +import javax.jms.JMSException; | |
| 22 | +import javax.jms.Message; | |
| 23 | +import javax.jms.MessageListener; | |
| 24 | +import javax.ws.rs.core.Response; | |
| 25 | +import javax.ws.rs.core.UriBuilder; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * @authors: georg.glossmann@adesso.de (template) + oliverdavid@hotmail.de (content) | |
| 29 | + * Date: 04.06.17 | |
| 30 | + */ | |
| 31 | +@MessageDriven( | |
| 32 | + name = "ApiAiConnector", | |
| 33 | + activationConfig = { | |
| 34 | + @ActivationConfigProperty( | |
| 35 | + propertyName = "destinationType", | |
| 36 | + propertyValue = "javax.jms.Topic"), | |
| 37 | + @ActivationConfigProperty( | |
| 38 | + propertyName = "destination", | |
| 39 | + propertyValue = "jms/messages/inbox"), | |
| 40 | + @ActivationConfigProperty( | |
| 41 | + propertyName = "messageSelector", propertyValue = "NLU = 'in'") | |
| 42 | + } | |
| 43 | +) | |
| 44 | +public class ApiAiConnector implements MessageListener { | |
| 45 | + | |
| 46 | + /** Injected JMS MessageQueue */ | |
| 47 | + @Resource(lookup = "java:global/global/ProcessQueueBean") | |
| 48 | + private ProcessQueue processQueue; | |
| 49 | + | |
| 50 | + /** BeuthBot Application Bean */ | |
| 51 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 52 | + private Application application; | |
| 53 | + | |
| 54 | + private final Logger logger = LoggerFactory.getLogger(ApiAiConnector.class); | |
| 55 | + private ApiAiRESTServiceInterface apiaiProxy; | |
| 56 | + | |
| 57 | + @PostConstruct | |
| 58 | + public void init() { | |
| 59 | + | |
| 60 | + ResteasyClient client = new ResteasyClientBuilder().build(); | |
| 61 | + ResteasyWebTarget target = client.target(UriBuilder.fromPath("https://api.api.ai/api/query")); | |
| 62 | + apiaiProxy = target.proxy(ApiAiRESTServiceInterface.class); | |
| 63 | + } | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * process messages received over the JMS | |
| 67 | + * | |
| 68 | + * @param message from JMS which contains the bot message | |
| 69 | + */ | |
| 70 | + @Override | |
| 71 | + public void onMessage(final Message message) { | |
| 72 | + try { | |
| 73 | + ProcessQueueMessageProtocol botMessage = message.getBody(TaskMessage.class); | |
| 74 | + logger.debug("Receive message: {}", botMessage.toString()); | |
| 75 | + | |
| 76 | + String token = application.getConfiguration(Configuration.API_AI_TOKEN); | |
| 77 | + | |
| 78 | + String sessionID = String.valueOf(botMessage.getMessageID()); | |
| 79 | + String language = "de"; | |
| 80 | + | |
| 81 | + //create a requests to te API.ai server | |
| 82 | + Response response = apiaiProxy.processText(botMessage.getText(), language, sessionID, "BHT-Chatbot", "Bearer " + token); | |
| 83 | + String responseAsString = response.readEntity(String.class); | |
| 84 | + | |
| 85 | + //parse the response into ApiAiResponse | |
| 86 | + ApiAiResponse apiAiResponse = new Gson().fromJson(responseAsString, ApiAiResponse.class); | |
| 87 | + | |
| 88 | + //Create ApiAiMessage | |
| 89 | + ApiAiMessage apiAiMessage = new ApiAiMessage(botMessage, apiAiResponse); | |
| 90 | + | |
| 91 | + //logger.debug("API.AI RESPONSE:"+responseAsString); | |
| 92 | + | |
| 93 | + //put ApiAiMessage into messageQueue | |
| 94 | + processQueue.route(new TaskMessage(apiAiMessage)); | |
| 95 | + | |
| 96 | + } catch (JMSException e) { | |
| 97 | + logger.error("Could not process message.", e); | |
| 98 | + } | |
| 99 | + } | |
| 100 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/ApiAiRESTServiceInterface.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/ApiAiRESTServiceInterface.java | |
| 1 | +package de.bht.beuthbot.nlp.apiai; | |
| 2 | + | |
| 3 | +import javax.ws.rs.*; | |
| 4 | +import javax.ws.rs.core.MediaType; | |
| 5 | +import javax.ws.rs.core.Response; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * @author: georg.glossmann@adesso.de (template) + oliverdavid@hotmail.de (content) | |
| 9 | + * Date: 04.06.17 | |
| 10 | + * <p> | |
| 11 | + * Proxy interface to query api.ai REST api | |
| 12 | + */ | |
| 13 | +@Path("/") | |
| 14 | +public interface ApiAiRESTServiceInterface { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * Processing the given text for intent and entities | |
| 18 | + * | |
| 19 | + * @return JAX RS Response representing the result of querying the api.ai server | |
| 20 | + */ | |
| 21 | + @GET | |
| 22 | + @Produces({MediaType.APPLICATION_JSON}) | |
| 23 | + Response processText(@QueryParam("query") String text, @QueryParam("lang") String language, @QueryParam("sessionId") String sessionID, @QueryParam("contexts") String context, @HeaderParam("Authorization") String auth); | |
| 24 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/ApiAiMessage.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/ApiAiMessage.java | |
| 1 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 4 | +import de.bht.beuthbot.jms.Target; | |
| 5 | +import de.bht.beuthbot.model.Attachment; | |
| 6 | +import de.bht.beuthbot.model.Messenger; | |
| 7 | +import de.bht.beuthbot.model.nlp.NLUResponse; | |
| 8 | + | |
| 9 | +import java.util.List; | |
| 10 | +import java.util.Map; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * Created by oliver on 19.06.2017. | |
| 14 | + * <p> | |
| 15 | + * ApiAi-specific class of the NLUBotMessage Interface | |
| 16 | + */ | |
| 17 | +public class ApiAiMessage implements ProcessQueueMessageProtocol { | |
| 18 | + | |
| 19 | + //store BotMessage and NLUResponse to query necessary information | |
| 20 | + ProcessQueueMessageProtocol botMessage; | |
| 21 | + NLUResponse nluResponse; | |
| 22 | + | |
| 23 | + public ApiAiMessage(ProcessQueueMessageProtocol botMessage, NLUResponse nluResponse){ | |
| 24 | + this.botMessage=botMessage; | |
| 25 | + this.nluResponse=nluResponse; | |
| 26 | + } | |
| 27 | + | |
| 28 | + @Override | |
| 29 | + public Long getId() { | |
| 30 | + return botMessage.getId(); | |
| 31 | + } | |
| 32 | + | |
| 33 | + @Override | |
| 34 | + public Target getTarget() { | |
| 35 | + return Target.MAINBOT; | |
| 36 | + } | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public Long getMessageID() { | |
| 40 | + return botMessage.getMessageID(); | |
| 41 | + } | |
| 42 | + | |
| 43 | + @Override | |
| 44 | + public Long getSenderID() { | |
| 45 | + return botMessage.getSenderID(); | |
| 46 | + } | |
| 47 | + | |
| 48 | + @Override | |
| 49 | + public Messenger getMessenger() { | |
| 50 | + return botMessage.getMessenger(); | |
| 51 | + } | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public String getText() { | |
| 55 | + return botMessage.getText(); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Override | |
| 59 | + public boolean hasAttachments() { | |
| 60 | + return botMessage.hasAttachments(); | |
| 61 | + } | |
| 62 | + | |
| 63 | + @Override | |
| 64 | + public List<Attachment> getAttachments() { | |
| 65 | + return botMessage.getAttachments(); | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Override | |
| 69 | + public String getIntent() { | |
| 70 | + return nluResponse.getIntent(); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Override | |
| 74 | + public Map<String, String> getEntities() { | |
| 75 | + return nluResponse.getEntities(); | |
| 76 | + } | |
| 77 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/ApiAiResponse.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/ApiAiResponse.java | |
| 1 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 2 | + | |
| 3 | +import com.google.gson.annotations.Expose; | |
| 4 | +import com.google.gson.annotations.SerializedName; | |
| 5 | +import de.bht.beuthbot.model.nlp.NLUResponse; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | +import java.util.HashMap; | |
| 9 | +import java.util.Map; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @author: Oliver | |
| 13 | + * Date: 19.06.17 | |
| 14 | + * <p> | |
| 15 | + * ApiAi-specific class of the NLUResponse Interface | |
| 16 | + * class which represents the JSON received from ApiAI | |
| 17 | + */ | |
| 18 | +public class ApiAiResponse implements NLUResponse, Serializable { | |
| 19 | + | |
| 20 | + @SerializedName("id") | |
| 21 | + @Expose | |
| 22 | + private String id; | |
| 23 | + @SerializedName("timestamp") | |
| 24 | + @Expose | |
| 25 | + private String timestamp; | |
| 26 | + @SerializedName("lang") | |
| 27 | + @Expose | |
| 28 | + private String lang; | |
| 29 | + @SerializedName("result") | |
| 30 | + @Expose | |
| 31 | + private Result result; | |
| 32 | + @SerializedName("status") | |
| 33 | + @Expose | |
| 34 | + private Status status; | |
| 35 | + @SerializedName("sessionId") | |
| 36 | + @Expose | |
| 37 | + private String sessionId; | |
| 38 | + | |
| 39 | + @Override | |
| 40 | + public String getIntent() { | |
| 41 | + //TODO: implement getScore into NLUResponse Interface and move decision to Drools | |
| 42 | + // the following is not necessary anymore because api.ai should set the fallback event automatically | |
| 43 | + if (result.getScore() <= 0.2 || result.getMetadata().getIntentName() == null) { | |
| 44 | + return "Fallback"; | |
| 45 | + } else return result.getMetadata().getIntentName(); | |
| 46 | + } | |
| 47 | + | |
| 48 | + @Override | |
| 49 | + public Map<String, String> getEntities() { | |
| 50 | + if (result.getParameters() != null) { | |
| 51 | + return result.getParameters().getEntities(); | |
| 52 | + } else return new HashMap<String, String>(); | |
| 53 | + } | |
| 54 | + | |
| 55 | + public String getId() { | |
| 56 | + return id; | |
| 57 | + } | |
| 58 | + | |
| 59 | + public void setId(String id) { | |
| 60 | + this.id = id; | |
| 61 | + } | |
| 62 | + | |
| 63 | + public String getTimestamp() { | |
| 64 | + return timestamp; | |
| 65 | + } | |
| 66 | + | |
| 67 | + public void setTimestamp(String timestamp) { | |
| 68 | + this.timestamp = timestamp; | |
| 69 | + } | |
| 70 | + | |
| 71 | + public String getLang() { | |
| 72 | + return lang; | |
| 73 | + } | |
| 74 | + | |
| 75 | + public void setLang(String lang) { | |
| 76 | + this.lang = lang; | |
| 77 | + } | |
| 78 | + | |
| 79 | + public Result getResult() { | |
| 80 | + return result; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public void setResult(Result result) { | |
| 84 | + this.result = result; | |
| 85 | + } | |
| 86 | + | |
| 87 | + public Status getStatus() { | |
| 88 | + return status; | |
| 89 | + } | |
| 90 | + | |
| 91 | + public void setStatus(Status status) { | |
| 92 | + this.status = status; | |
| 93 | + } | |
| 94 | + | |
| 95 | + public String getSessionId() { | |
| 96 | + return sessionId; | |
| 97 | + } | |
| 98 | + | |
| 99 | + public void setSessionId(String sessionId) { | |
| 100 | + this.sessionId = sessionId; | |
| 101 | + } | |
| 102 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Fulfillment.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Fulfillment.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 3 | + | |
| 4 | +import java.io.Serializable; | |
| 5 | +import java.util.List; | |
| 6 | +import com.google.gson.annotations.Expose; | |
| 7 | +import com.google.gson.annotations.SerializedName; | |
| 8 | +/** | |
| 9 | + * @author: Oliver | |
| 10 | + * Date: 19.06.17 | |
| 11 | + */ | |
| 12 | +public class Fulfillment implements Serializable { | |
| 13 | + | |
| 14 | + @SerializedName("speech") | |
| 15 | + @Expose | |
| 16 | + private String speech; | |
| 17 | + @SerializedName("messages") | |
| 18 | + @Expose | |
| 19 | + private List<Message> messages = null; | |
| 20 | + | |
| 21 | + public String getSpeech() { | |
| 22 | + return speech; | |
| 23 | + } | |
| 24 | + | |
| 25 | + public void setSpeech(String speech) { | |
| 26 | + this.speech = speech; | |
| 27 | + } | |
| 28 | + | |
| 29 | + public List<Message> getMessages() { | |
| 30 | + return messages; | |
| 31 | + } | |
| 32 | + | |
| 33 | + public void setMessages(List<Message> messages) { | |
| 34 | + this.messages = messages; | |
| 35 | + } | |
| 36 | + | |
| 37 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Message.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Message.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @author: Oliver | |
| 11 | + * Date: 19.06.17 | |
| 12 | + */ | |
| 13 | +public class Message implements Serializable { | |
| 14 | + | |
| 15 | + @SerializedName("type") | |
| 16 | + @Expose | |
| 17 | + private Integer type; | |
| 18 | + @SerializedName("speech") | |
| 19 | + @Expose | |
| 20 | + private String speech; | |
| 21 | + | |
| 22 | + public Integer getType() { | |
| 23 | + return type; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void setType(Integer type) { | |
| 27 | + this.type = type; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public String getSpeech() { | |
| 31 | + return speech; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public void setSpeech(String speech) { | |
| 35 | + this.speech = speech; | |
| 36 | + } | |
| 37 | + | |
| 38 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Metadata.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Metadata.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @author: Oliver | |
| 11 | + * Date: 19.06.17 | |
| 12 | + */ | |
| 13 | +public class Metadata implements Serializable { | |
| 14 | + | |
| 15 | + @SerializedName("intentId") | |
| 16 | + @Expose | |
| 17 | + private String intentId; | |
| 18 | + @SerializedName("webhookUsed") | |
| 19 | + @Expose | |
| 20 | + private String webhookUsed; | |
| 21 | + @SerializedName("webhookForSlotFillingUsed") | |
| 22 | + @Expose | |
| 23 | + private String webhookForSlotFillingUsed; | |
| 24 | + @SerializedName("intentName") | |
| 25 | + @Expose | |
| 26 | + private String intentName; | |
| 27 | + | |
| 28 | + public String getIntentId() { | |
| 29 | + return intentId; | |
| 30 | + } | |
| 31 | + | |
| 32 | + public void setIntentId(String intentId) { | |
| 33 | + this.intentId = intentId; | |
| 34 | + } | |
| 35 | + | |
| 36 | + public String getWebhookUsed() { | |
| 37 | + return webhookUsed; | |
| 38 | + } | |
| 39 | + | |
| 40 | + public void setWebhookUsed(String webhookUsed) { | |
| 41 | + this.webhookUsed = webhookUsed; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public String getWebhookForSlotFillingUsed() { | |
| 45 | + return webhookForSlotFillingUsed; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public void setWebhookForSlotFillingUsed(String webhookForSlotFillingUsed) { | |
| 49 | + this.webhookForSlotFillingUsed = webhookForSlotFillingUsed; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public String getIntentName() { | |
| 53 | + return intentName; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public void setIntentName(String intentName) { | |
| 57 | + this.intentName = intentName; | |
| 58 | + } | |
| 59 | + | |
| 60 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Parameters.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Parameters.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | +import java.util.HashMap; | |
| 9 | +import java.util.Map; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @author: Oliver | |
| 13 | + * Date: 19.06.17 | |
| 14 | + */ | |
| 15 | +public class Parameters implements Serializable{ | |
| 16 | + | |
| 17 | + | |
| 18 | + @SerializedName("date") | |
| 19 | + @Expose | |
| 20 | + private String date; | |
| 21 | + @SerializedName("dishtype") | |
| 22 | + @Expose | |
| 23 | + private String dishtype; | |
| 24 | + @SerializedName("healthy") | |
| 25 | + @Expose | |
| 26 | + private String healthy; | |
| 27 | + @SerializedName("ingredients") | |
| 28 | + @Expose | |
| 29 | + private String ingredients; | |
| 30 | + @SerializedName("price") | |
| 31 | + @Expose | |
| 32 | + private String price; | |
| 33 | + @SerializedName("number") | |
| 34 | + @Expose | |
| 35 | + private String number; | |
| 36 | + @SerializedName("dishcategory") | |
| 37 | + @Expose | |
| 38 | + private String dishcategory; | |
| 39 | + | |
| 40 | + public String getDate() { | |
| 41 | + return date; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public void setDate(String date) { | |
| 45 | + this.date = date; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public String getDishtype() { | |
| 49 | + return dishtype; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public void setDishtype(String dishtype) { | |
| 53 | + this.dishtype = dishtype; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public String getHealthy() { | |
| 57 | + return healthy; | |
| 58 | + } | |
| 59 | + | |
| 60 | + public void setHealthy(String healthy) { | |
| 61 | + this.healthy = healthy; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public String getIngredients() { | |
| 65 | + return ingredients; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public void setIngredients(String ingredients) { | |
| 69 | + this.ingredients = ingredients; | |
| 70 | + } | |
| 71 | + | |
| 72 | + public String getPrice() { | |
| 73 | + return price; | |
| 74 | + } | |
| 75 | + | |
| 76 | + public void setPrice(String price) { | |
| 77 | + this.price = price; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public String getNumber() { | |
| 81 | + return number; | |
| 82 | + } | |
| 83 | + | |
| 84 | + public void setNumber(String number) { | |
| 85 | + this.number = number; | |
| 86 | + } | |
| 87 | + | |
| 88 | + public String getDishcategory() { | |
| 89 | + return dishcategory; | |
| 90 | + } | |
| 91 | + | |
| 92 | + public void setDishcategory(String dishcategory) { | |
| 93 | + this.dishcategory = dishcategory; | |
| 94 | + } | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * @return puts the given entities with their values into a Map | |
| 98 | + */ | |
| 99 | + public Map<String, String> getEntities(){ | |
| 100 | + Map<String, String> Entities = new HashMap<>(); | |
| 101 | + | |
| 102 | + if (date!=null)Entities.put("date",date); | |
| 103 | + if (dishtype!=null)Entities.put("dishtype",dishtype); | |
| 104 | + if (healthy!=null)Entities.put("healthy",healthy); | |
| 105 | + if (ingredients!=null)Entities.put("ingredients",ingredients); | |
| 106 | + if (price!=null)Entities.put("price",price); | |
| 107 | + if (number!=null)Entities.put("number",number); | |
| 108 | + if (dishcategory!=null)Entities.put("dishcategory",dishcategory); | |
| 109 | + | |
| 110 | + return Entities; | |
| 111 | + } | |
| 112 | + | |
| 113 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Result.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Result.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 3 | + | |
| 4 | +import java.io.Serializable; | |
| 5 | +import java.util.List; | |
| 6 | + | |
| 7 | +import com.google.gson.annotations.Expose; | |
| 8 | +import com.google.gson.annotations.SerializedName; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * @author: Oliver | |
| 12 | + * Date: 19.06.17 | |
| 13 | + */ | |
| 14 | +public class Result implements Serializable { | |
| 15 | + | |
| 16 | + @SerializedName("source") | |
| 17 | + @Expose | |
| 18 | + private String source; | |
| 19 | + @SerializedName("resolvedQuery") | |
| 20 | + @Expose | |
| 21 | + private String resolvedQuery; | |
| 22 | + @SerializedName("action") | |
| 23 | + @Expose | |
| 24 | + private String action; | |
| 25 | + @SerializedName("actionIncomplete") | |
| 26 | + @Expose | |
| 27 | + private Boolean actionIncomplete; | |
| 28 | + @SerializedName("parameters") | |
| 29 | + @Expose | |
| 30 | + private Parameters parameters; | |
| 31 | + @SerializedName("contexts") | |
| 32 | + @Expose | |
| 33 | + private List<Object> contexts = null; | |
| 34 | + @SerializedName("metadata") | |
| 35 | + @Expose | |
| 36 | + private Metadata metadata; | |
| 37 | + @SerializedName("fulfillment") | |
| 38 | + @Expose | |
| 39 | + private Fulfillment fulfillment; | |
| 40 | + @SerializedName("score") | |
| 41 | + @Expose | |
| 42 | + private Float score; | |
| 43 | + | |
| 44 | + public String getSource() { | |
| 45 | + return source; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public void setSource(String source) { | |
| 49 | + this.source = source; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public String getResolvedQuery() { | |
| 53 | + return resolvedQuery; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public void setResolvedQuery(String resolvedQuery) { | |
| 57 | + this.resolvedQuery = resolvedQuery; | |
| 58 | + } | |
| 59 | + | |
| 60 | + public String getAction() { | |
| 61 | + return action; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public void setAction(String action) { | |
| 65 | + this.action = action; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public Boolean getActionIncomplete() { | |
| 69 | + return actionIncomplete; | |
| 70 | + } | |
| 71 | + | |
| 72 | + public void setActionIncomplete(Boolean actionIncomplete) { | |
| 73 | + this.actionIncomplete = actionIncomplete; | |
| 74 | + } | |
| 75 | + | |
| 76 | + public Parameters getParameters(){ | |
| 77 | + return parameters; | |
| 78 | + } | |
| 79 | + | |
| 80 | + /*public Map<String,String> getEntities() { | |
| 81 | + Map<String, String> Entities = new HashMap<>(); | |
| 82 | + | |
| 83 | + JSONObject obj =new JSONObject(parameters); | |
| 84 | + for(Iterator iterator = obj.keySet().iterator(); iterator.hasNext();) { | |
| 85 | + String key = (String) iterator.next(); | |
| 86 | + Entities.put(key, obj.getString(key)); | |
| 87 | + } | |
| 88 | + | |
| 89 | + return Entities; | |
| 90 | + }*/ | |
| 91 | + | |
| 92 | + public void setParameters(Parameters parameters) { | |
| 93 | + this.parameters = parameters; | |
| 94 | + } | |
| 95 | + | |
| 96 | + public List<Object> getContexts() { | |
| 97 | + return contexts; | |
| 98 | + } | |
| 99 | + | |
| 100 | + public void setContexts(List<Object> contexts) { | |
| 101 | + this.contexts = contexts; | |
| 102 | + } | |
| 103 | + | |
| 104 | + public Metadata getMetadata() { | |
| 105 | + return metadata; | |
| 106 | + } | |
| 107 | + | |
| 108 | + public void setMetadata(Metadata metadata) { | |
| 109 | + this.metadata = metadata; | |
| 110 | + } | |
| 111 | + | |
| 112 | + public Fulfillment getFulfillment() { | |
| 113 | + return fulfillment; | |
| 114 | + } | |
| 115 | + | |
| 116 | + public void setFulfillment(Fulfillment fulfillment) { | |
| 117 | + this.fulfillment = fulfillment; | |
| 118 | + } | |
| 119 | + | |
| 120 | + public Float getScore() { | |
| 121 | + return score; | |
| 122 | + } | |
| 123 | + | |
| 124 | + public void setScore(Float score) { | |
| 125 | + this.score = score; | |
| 126 | + } | |
| 127 | + | |
| 128 | +} | ... | ... |
services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Status.java
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/java/de/bht/beuthbot/nlp/apiai/model/Status.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.nlp.apiai.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @author: Oliver | |
| 11 | + * Date: 19.06.17 | |
| 12 | + */ | |
| 13 | +public class Status implements Serializable { | |
| 14 | + | |
| 15 | + @SerializedName("code") | |
| 16 | + @Expose | |
| 17 | + private Integer code; | |
| 18 | + @SerializedName("errorType") | |
| 19 | + @Expose | |
| 20 | + private String errorType; | |
| 21 | + | |
| 22 | + public Integer getCode() { | |
| 23 | + return code; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void setCode(Integer code) { | |
| 27 | + this.code = code; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public String getErrorType() { | |
| 31 | + return errorType; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public void setErrorType(String errorType) { | |
| 35 | + this.errorType = errorType; | |
| 36 | + } | |
| 37 | + | |
| 38 | +} | ... | ... |
services/ApiAi/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/ApiAi/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/Bing/build.gradle
0 → 100755
| 1 | +++ a/services/Bing/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | +} | |
| 8 | + | |
| 9 | +dependencies { | |
| 10 | + compile project(':services:Common'), | |
| 11 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 12 | + "org.apache.httpcomponents:httpclient:4.5.3", | |
| 13 | + "org.apache.httpcomponents:httpmime:4.3.1" | |
| 14 | + | |
| 15 | + providedCompile "org.slf4j:slf4j-api:1.7.25" | |
| 16 | +} | |
| 17 | + | |
| 18 | +sourceCompatibility = 1.8 | |
| 19 | + | |
| 20 | +war { | |
| 21 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 22 | + archiveName "bing.war" | |
| 23 | +} | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/BingConnector.java
0 → 100755
| 1 | +++ a/services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/BingConnector.java | |
| 1 | +package de.bht.beuthbot.nsp.bing; | |
| 2 | + | |
| 3 | +import com.google.gson.Gson; | |
| 4 | +import de.bht.beuthbot.attachments.AttachmentStore; | |
| 5 | +import de.bht.beuthbot.attachments.model.AttachmentStoreMode; | |
| 6 | +import de.bht.beuthbot.conf.Application; | |
| 7 | +import de.bht.beuthbot.conf.Configuration; | |
| 8 | +import de.bht.beuthbot.jms.ProcessQueue; | |
| 9 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 10 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 11 | +import de.bht.beuthbot.model.Attachment; | |
| 12 | +import de.bht.beuthbot.model.AttachmentType; | |
| 13 | +import de.bht.beuthbot.nsp.bing.model.BingAttachment; | |
| 14 | +import de.bht.beuthbot.nsp.bing.model.BingDetailedResponse; | |
| 15 | +import de.bht.beuthbot.nsp.bing.model.BingMessage; | |
| 16 | +import de.bht.beuthbot.nsp.bing.model.BingSimpleResponse; | |
| 17 | +import org.apache.http.HttpEntity; | |
| 18 | +import org.apache.http.HttpResponse; | |
| 19 | +import org.apache.http.HttpStatus; | |
| 20 | +import org.apache.http.client.HttpClient; | |
| 21 | +import org.apache.http.client.methods.CloseableHttpResponse; | |
| 22 | +import org.apache.http.client.methods.HttpGet; | |
| 23 | +import org.apache.http.client.methods.HttpPost; | |
| 24 | +import org.apache.http.entity.ByteArrayEntity; | |
| 25 | +import org.apache.http.entity.ContentType; | |
| 26 | +import org.apache.http.entity.mime.HttpMultipartMode; | |
| 27 | +import org.apache.http.impl.client.HttpClientBuilder; | |
| 28 | +import org.apache.http.util.EntityUtils; | |
| 29 | +import org.slf4j.Logger; | |
| 30 | +import org.slf4j.LoggerFactory; | |
| 31 | + | |
| 32 | +import javax.annotation.Resource; | |
| 33 | +import javax.ejb.ActivationConfigProperty; | |
| 34 | +import javax.ejb.MessageDriven; | |
| 35 | +import javax.jms.JMSException; | |
| 36 | +import javax.jms.Message; | |
| 37 | +import javax.jms.MessageListener; | |
| 38 | +import javax.ws.rs.core.MediaType; | |
| 39 | +import java.io.ByteArrayOutputStream; | |
| 40 | +import java.util.HashMap; | |
| 41 | +import java.util.Map; | |
| 42 | + | |
| 43 | +/** | |
| 44 | + * @Author: Christopher Kümmel on 6/12/2017. | |
| 45 | + */ | |
| 46 | +@MessageDriven( | |
| 47 | + name = "BingConnector", | |
| 48 | + activationConfig = { | |
| 49 | + @ActivationConfigProperty( | |
| 50 | + propertyName = "destinationType", | |
| 51 | + propertyValue = "javax.jms.Topic"), | |
| 52 | + @ActivationConfigProperty( | |
| 53 | + propertyName = "destination", | |
| 54 | + propertyValue = "jms/messages/inbox"), | |
| 55 | + @ActivationConfigProperty( | |
| 56 | + propertyName = "maxSession", propertyValue = "1"), | |
| 57 | + @ActivationConfigProperty( | |
| 58 | + propertyName = "messageSelector", propertyValue = "BingConnector = 'in'" | |
| 59 | + ) | |
| 60 | + } | |
| 61 | +) | |
| 62 | +public class BingConnector implements MessageListener { | |
| 63 | + | |
| 64 | + /** slf4j Logger */ | |
| 65 | + private final Logger logger = LoggerFactory.getLogger(BingConnector.class); | |
| 66 | + | |
| 67 | + /** Bing Speech API Access Token */ | |
| 68 | + private String accessToken = ""; | |
| 69 | + | |
| 70 | + /** locale e.g. global */ | |
| 71 | + private String locale = ""; | |
| 72 | + | |
| 73 | + /** Bing Speech API User GUID */ | |
| 74 | + private String guid = ""; | |
| 75 | + | |
| 76 | + //TODO: distinguish between formats (simple or detailed) | |
| 77 | + /** Bing Speech API response format */ | |
| 78 | + private String format = "simple"; | |
| 79 | + | |
| 80 | + /** Injected JMS MessageQueue */ | |
| 81 | + @Resource(lookup = "java:global/global/ProcessQueueBean") | |
| 82 | + private ProcessQueue processQueue; | |
| 83 | + | |
| 84 | + /** Injected AttachmentStore */ | |
| 85 | + @Resource(lookup = "java:global/global/AttachmentStoreBean") | |
| 86 | + private AttachmentStore attachmentStore; | |
| 87 | + | |
| 88 | + /** BeuthBot Application Bean */ | |
| 89 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 90 | + private Application application; | |
| 91 | + | |
| 92 | + /** | |
| 93 | + * Process JMS Message | |
| 94 | + * @param message | |
| 95 | + */ | |
| 96 | + @Override | |
| 97 | + public void onMessage(final Message message) { | |
| 98 | + try { | |
| 99 | + ProcessQueueMessageProtocol botMessage = message.getBody(TaskMessage.class); | |
| 100 | + if (botMessage.hasAttachments()) { | |
| 101 | + // Speech to Text Request | |
| 102 | + for (Attachment attachment : botMessage.getAttachments()) { | |
| 103 | + sendSpeechToTextRequest(botMessage); | |
| 104 | + } | |
| 105 | + } else { | |
| 106 | + // Text to Speech Request | |
| 107 | + sendTextToSpeechRequest(botMessage); | |
| 108 | + } | |
| 109 | + } catch (JMSException e) { | |
| 110 | + logger.error("Error on receiving BotMessage-Object on BingConnector: ", e); | |
| 111 | + } | |
| 112 | + } | |
| 113 | + | |
| 114 | + //TODO: cyclically generate a Token - remove call in methods | |
| 115 | + /** | |
| 116 | + * Method to generate Bing Speech API Access Token. - Token decays after 10 minutes. -> Refresh every 9 minutes. | |
| 117 | + */ | |
| 118 | + private void generateAccessToken() { | |
| 119 | + try { | |
| 120 | + HttpClient client = HttpClientBuilder.create().build(); | |
| 121 | + String url = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken"; | |
| 122 | + HttpPost httpPost = new HttpPost(url); | |
| 123 | + | |
| 124 | + // get config Properties | |
| 125 | + locale = application.getConfiguration(Configuration.BING_SPEECH_LOCALE); | |
| 126 | + guid = application.getConfiguration(Configuration.BING_SPEECH_GUID); | |
| 127 | + | |
| 128 | + // headers | |
| 129 | + Map<String, String> postHeaders = new HashMap<>(); | |
| 130 | + postHeaders.put("Content-Type", MediaType.APPLICATION_FORM_URLENCODED); | |
| 131 | + postHeaders.put("Ocp-Apim-Subscription-Key", application.getConfiguration(Configuration.BING_SPEECH_SECRET_KEY)); | |
| 132 | + | |
| 133 | + for (Map.Entry<String, String> entry : postHeaders.entrySet()) { | |
| 134 | + httpPost.setHeader(entry.getKey(), entry.getValue()); | |
| 135 | + } | |
| 136 | + | |
| 137 | + // send request | |
| 138 | + HttpResponse httpResponse = client.execute(httpPost); | |
| 139 | + int responseCode = httpResponse.getStatusLine().getStatusCode(); | |
| 140 | + | |
| 141 | + logger.debug("AccessToken request returns: Response Code - " + String.valueOf(responseCode)); | |
| 142 | + | |
| 143 | + String result = EntityUtils.toString(httpResponse.getEntity()); | |
| 144 | + | |
| 145 | + if (responseCode == HttpStatus.SC_OK) { | |
| 146 | + accessToken = result; | |
| 147 | + logger.debug("new AccessToken: " + accessToken); | |
| 148 | + } else { | |
| 149 | + logger.warn("Could not generate new Bing Speech AccessToken"); | |
| 150 | + } | |
| 151 | + } catch (Exception e) { | |
| 152 | + logger.error("Exception while getting new AccessToken: ", e); | |
| 153 | + } | |
| 154 | + } | |
| 155 | + | |
| 156 | + /** | |
| 157 | + * Send Bing Speech to Text Request. | |
| 158 | + * @param botMessage Object to parse to Text | |
| 159 | + */ | |
| 160 | + private void sendSpeechToTextRequest(final ProcessQueueMessageProtocol botMessage) { | |
| 161 | + generateAccessToken(); | |
| 162 | + //TODO: different languages | |
| 163 | + String language = "de-DE"; | |
| 164 | + try { | |
| 165 | + HttpClient client = HttpClientBuilder.create().build(); | |
| 166 | + String url = "https://speech.platform.bing.com/speech/recognition/interactive/cognitiveservices/v1?language=" | |
| 167 | + + language + "&locale=" + locale + "&requestid=" + guid + "&format=" + format; | |
| 168 | + HttpPost httpPost = new HttpPost(url); | |
| 169 | + | |
| 170 | + // HEADERS | |
| 171 | + Map<String, String> postHeaders = new HashMap<>(); | |
| 172 | + postHeaders.put("Authorization", "Bearer " + accessToken); | |
| 173 | + postHeaders.put("Content-Type", "audio/mpeg; codec=\"audio/pcm\"; samplerate=16000"); | |
| 174 | + | |
| 175 | + for (Map.Entry<String, String> entry : postHeaders.entrySet()) { | |
| 176 | + httpPost.setHeader(entry.getKey(), entry.getValue()); | |
| 177 | + } | |
| 178 | + | |
| 179 | + for (Attachment attachment : botMessage.getAttachments()) { | |
| 180 | + | |
| 181 | + // audio file download | |
| 182 | + HttpGet get = new HttpGet(attachment.getFileURI()); | |
| 183 | + CloseableHttpResponse execute = HttpClientBuilder.create().build().execute(get); | |
| 184 | + HttpEntity entity = execute.getEntity(); | |
| 185 | + | |
| 186 | + ByteArrayOutputStream bArrOS = new ByteArrayOutputStream(); | |
| 187 | + entity.writeTo(bArrOS); | |
| 188 | + bArrOS.flush(); | |
| 189 | + ByteArrayEntity bArrEntity = new ByteArrayEntity(bArrOS.toByteArray()); | |
| 190 | + bArrOS.close(); | |
| 191 | + | |
| 192 | + // IMPORTANT! For Bing Speech API it is necessary to set Transfer-Encoding = chunked. Otherwise Bing wouldn't accept the file. | |
| 193 | + bArrEntity.setChunked(true); | |
| 194 | + bArrEntity.setContentEncoding(HttpMultipartMode.BROWSER_COMPATIBLE.toString()); | |
| 195 | + bArrEntity.setContentType(ContentType.DEFAULT_BINARY.toString()); | |
| 196 | + | |
| 197 | + //THIS CODE IS NOT WORKING PROPERLY - Check AttachmentStore for correct implementation | |
| 198 | +// // get audio file from AttachmentStore | |
| 199 | +// File file = new File(attachmentStore.loadAttachmentPath(attachment.getId(), AttachmentStoreMode.LOCAL_PATH)); | |
| 200 | +// FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY); | |
| 201 | +// MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); | |
| 202 | +// multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); | |
| 203 | +// multipartEntityBuilder.addPart("bin", fileBody); | |
| 204 | +// HttpEntity httpEntity = multipartEntityBuilder.build(); | |
| 205 | +// | |
| 206 | +// ByteArrayOutputStream bArrOS = new ByteArrayOutputStream(); | |
| 207 | +// httpEntity.writeTo(bArrOS); | |
| 208 | +// bArrOS.flush(); | |
| 209 | +// ByteArrayEntity bArrEntity = new ByteArrayEntity(bArrOS.toByteArray()); | |
| 210 | +// bArrOS.close(); | |
| 211 | +// | |
| 212 | +// // IMPORTANT! For Bing Speech API it is necessary to set Transfer-Encoding = chunked. Otherwise Bing wouldn't accept the file. | |
| 213 | +// bArrEntity.setChunked(true); | |
| 214 | +// bArrEntity.setContentEncoding(httpEntity.getContentEncoding()); | |
| 215 | +// bArrEntity.setContentType(httpEntity.getContentType()); | |
| 216 | + | |
| 217 | + // set ByteArrayEntity to HttpPost | |
| 218 | + httpPost.setEntity(bArrEntity); | |
| 219 | + | |
| 220 | + // send request | |
| 221 | + HttpResponse httpResponse = client.execute(httpPost); | |
| 222 | + int responseCode = httpResponse.getStatusLine().getStatusCode(); | |
| 223 | + | |
| 224 | + logger.debug("Speech to Text request returns: Response Code - " + String.valueOf(responseCode)); | |
| 225 | + | |
| 226 | + String result = EntityUtils.toString(httpResponse.getEntity()); | |
| 227 | + | |
| 228 | + if (responseCode == HttpStatus.SC_OK) { | |
| 229 | + // process response message | |
| 230 | + BingMessage bingMessage; | |
| 231 | + try { | |
| 232 | + switch (format){ | |
| 233 | + case "simple": | |
| 234 | + BingSimpleResponse bingSimpleResponse = new Gson().fromJson(result, BingSimpleResponse.class); | |
| 235 | + bingMessage = new BingMessage(bingSimpleResponse, botMessage); | |
| 236 | + logger.debug("Received message from bing: {}", result); | |
| 237 | + break; | |
| 238 | + case "detailed": | |
| 239 | + BingDetailedResponse bingDetailedResponse = new Gson().fromJson(result, BingDetailedResponse.class); | |
| 240 | + bingMessage = new BingMessage(bingDetailedResponse, botMessage); | |
| 241 | + break; | |
| 242 | + default: | |
| 243 | + logger.error("Could not parse BingSpeechResponse"); | |
| 244 | + return; | |
| 245 | + } | |
| 246 | + // return message | |
| 247 | + processQueue.route(new TaskMessage(bingMessage)); | |
| 248 | + } catch (Exception e) { | |
| 249 | + logger.error("Error while parsing BingSpeechResponse: ", e); | |
| 250 | + } | |
| 251 | + } else { | |
| 252 | + logger.warn("Could not process Speech to Text request. Returns: " + "Speech to Text request returns: " + result.toString()); | |
| 253 | + } | |
| 254 | + } | |
| 255 | + } catch (Exception e){ | |
| 256 | + logger.error("Error while processing Speech to Text request: ", e); | |
| 257 | + } | |
| 258 | + } | |
| 259 | + | |
| 260 | + /** | |
| 261 | + * Send Bing Text to Speech Request. | |
| 262 | + * @param botMessage Object to parse to Speech | |
| 263 | + */ | |
| 264 | + private void sendTextToSpeechRequest(final ProcessQueueMessageProtocol botMessage){ | |
| 265 | + generateAccessToken(); | |
| 266 | + | |
| 267 | + HttpClient client = HttpClientBuilder.create().build(); | |
| 268 | + String url = "https://speech.platform.bing.com/synthesize"; | |
| 269 | + HttpPost httpPost = new HttpPost(url); | |
| 270 | + | |
| 271 | + // HEADERS | |
| 272 | + Map<String, String> postHeaders = new HashMap<>(); | |
| 273 | + postHeaders.put("Content-Type", MediaType.APPLICATION_XML); | |
| 274 | + postHeaders.put("Authorization", "Bearer " + accessToken); | |
| 275 | + postHeaders.put("X-Microsoft-OutputFormat", "audio-16khz-32kbitrate-mono-mp3"); | |
| 276 | + | |
| 277 | + for (Map.Entry<String, String> entry : postHeaders.entrySet()) { | |
| 278 | + httpPost.setHeader(entry.getKey(), entry.getValue()); | |
| 279 | + } | |
| 280 | + | |
| 281 | + try { | |
| 282 | + //TODO: build a proper xml | |
| 283 | + // Bing Text to Speech uses the Speech Synthesis Markup Language (SSML) Standard | |
| 284 | + String xml = "<speak version='1.0' xml:lang='de-DE'><voice xml:lang='de-DE' xml:gender='Female' name='Microsoft Server Speech Text to Speech Voice (de-DE, HeddaRUS)'>" + botMessage.getText() + "</voice></speak>"; | |
| 285 | + HttpEntity entity = new ByteArrayEntity(xml.getBytes("UTF-8")); | |
| 286 | + httpPost.setEntity(entity); | |
| 287 | + | |
| 288 | + // send request | |
| 289 | + HttpResponse httpResponse = client.execute(httpPost); | |
| 290 | + int responseCode = httpResponse.getStatusLine().getStatusCode(); | |
| 291 | + | |
| 292 | + logger.debug("Send Text to Speech returns: Response Code - " + String.valueOf(responseCode)); | |
| 293 | + | |
| 294 | + if (responseCode == HttpStatus.SC_OK) { | |
| 295 | + // process response | |
| 296 | + ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
| 297 | + httpResponse.getEntity().writeTo(bos); | |
| 298 | + bos.flush(); | |
| 299 | + | |
| 300 | + // store file | |
| 301 | + Long id = attachmentStore.storeAttachment(bos, AttachmentType.AUDIO); | |
| 302 | + bos.close(); | |
| 303 | + String path = attachmentStore.loadAttachmentPath(id, AttachmentStoreMode.FILE_URI); | |
| 304 | + | |
| 305 | + BingMessage bingMessage = new BingMessage(botMessage, new BingAttachment(id, path)); | |
| 306 | + | |
| 307 | + processQueue.route(new TaskMessage(bingMessage)); | |
| 308 | + } else { | |
| 309 | + logger.warn("Could not process Speech to Text request. Returns: " + "Speech to Text request returns: " + httpResponse.toString()); | |
| 310 | + } | |
| 311 | + } catch (Exception e){ | |
| 312 | + logger.error("Error while processing Text to Speech request: ", e); | |
| 313 | + } | |
| 314 | + } | |
| 315 | +} | ... | ... |
services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingAttachment.java
0 → 100755
| 1 | +++ a/services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingAttachment.java | |
| 1 | +package de.bht.beuthbot.nsp.bing.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.model.Attachment; | |
| 4 | +import de.bht.beuthbot.model.AttachmentType; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * @Author: Christopher Kümmel on 6/15/2017. | |
| 8 | + */ | |
| 9 | +public class BingAttachment implements Attachment { | |
| 10 | + | |
| 11 | + /** generated unique id */ | |
| 12 | + private Long id; | |
| 13 | + /** URI where attachment is stored */ | |
| 14 | + private String fileURI; | |
| 15 | + /** caption of that attachment */ | |
| 16 | + private String caption; | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * Constructor | |
| 20 | + * @param id generated unique id | |
| 21 | + * @param fileURI URI where attachment is stored | |
| 22 | + */ | |
| 23 | + public BingAttachment(final Long id, final String fileURI){ | |
| 24 | + this.id = id; | |
| 25 | + this.caption = caption; | |
| 26 | + this.fileURI = fileURI; | |
| 27 | + } | |
| 28 | + | |
| 29 | + @Override | |
| 30 | + public Long getId() { | |
| 31 | + return id; | |
| 32 | + } | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public String getFileURI() { | |
| 36 | + return fileURI; | |
| 37 | + } | |
| 38 | + | |
| 39 | + @Override | |
| 40 | + public AttachmentType getAttachmentType() { | |
| 41 | + return AttachmentType.AUDIO; | |
| 42 | + } | |
| 43 | + | |
| 44 | + @Override | |
| 45 | + public String getCaption() { | |
| 46 | + return caption; | |
| 47 | + } | |
| 48 | +} | ... | ... |
services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingDetailedResponse.java
0 → 100755
| 1 | +++ a/services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingDetailedResponse.java | |
| 1 | +package de.bht.beuthbot.nsp.bing.model; | |
| 2 | + | |
| 3 | +import com.google.gson.annotations.SerializedName; | |
| 4 | +import de.bht.beuthbot.model.nsp.NSPResponse; | |
| 5 | + | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * Bing Speech API Java Class for JSON parsing. | |
| 10 | + * @Author: Christopher Kümmel on 6/14/2017. | |
| 11 | + */ | |
| 12 | +public class BingDetailedResponse implements NSPResponse { | |
| 13 | + | |
| 14 | + @SerializedName("RecognitionStatus") | |
| 15 | + private String recognitionStatus; | |
| 16 | + @SerializedName("Offset") | |
| 17 | + private String offset; | |
| 18 | + @SerializedName("Duration") | |
| 19 | + private String duration; | |
| 20 | + @SerializedName("N-Best") | |
| 21 | + private List<BingNBest> nBest = null; | |
| 22 | + | |
| 23 | + @Override | |
| 24 | + public String getText() { | |
| 25 | + double highestValue = 0; | |
| 26 | + for (BingNBest best : nBest){ | |
| 27 | + if (Double.valueOf(best.getConfidence()) > highestValue) highestValue = Double.valueOf(best.getConfidence()); | |
| 28 | + } | |
| 29 | + for (BingNBest best : nBest){ | |
| 30 | + if (Double.valueOf(best.getConfidence()) == highestValue) return best.getConfidence(); | |
| 31 | + } | |
| 32 | + return ""; | |
| 33 | + } | |
| 34 | + | |
| 35 | + @Override | |
| 36 | + public String getRecognitionStatus() { | |
| 37 | + return recognitionStatus; | |
| 38 | + } | |
| 39 | + | |
| 40 | + public void setRecognitionStatus(String recognitionStatus){this.recognitionStatus = recognitionStatus;} | |
| 41 | + | |
| 42 | + public String getOffset() { | |
| 43 | + return offset; | |
| 44 | + } | |
| 45 | + | |
| 46 | + public void setOffset(String offset) { | |
| 47 | + this.offset = offset; | |
| 48 | + } | |
| 49 | + | |
| 50 | + public String getDuration() { | |
| 51 | + return duration; | |
| 52 | + } | |
| 53 | + | |
| 54 | + public void setDuration(String duration) { | |
| 55 | + this.duration = duration; | |
| 56 | + } | |
| 57 | + | |
| 58 | + public List<BingNBest> getnBests() { | |
| 59 | + return nBest; | |
| 60 | + } | |
| 61 | + | |
| 62 | + public void setnBests(List<BingNBest> nBests) { | |
| 63 | + this.nBest = nBests; | |
| 64 | + } | |
| 65 | + | |
| 66 | +} | ... | ... |
services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingMessage.java
0 → 100755
| 1 | +++ a/services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingMessage.java | |
| 1 | +package de.bht.beuthbot.nsp.bing.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 4 | +import de.bht.beuthbot.jms.Target; | |
| 5 | +import de.bht.beuthbot.model.Attachment; | |
| 6 | +import de.bht.beuthbot.model.Messenger; | |
| 7 | +import de.bht.beuthbot.model.nsp.NSPResponse; | |
| 8 | + | |
| 9 | +import java.util.ArrayList; | |
| 10 | +import java.util.List; | |
| 11 | +import java.util.Map; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * @Author: Christopher Kümmel on 6/15/2017. | |
| 15 | + */ | |
| 16 | +public class BingMessage implements ProcessQueueMessageProtocol{ | |
| 17 | + | |
| 18 | + /** Display text */ | |
| 19 | + private String text; | |
| 20 | + | |
| 21 | + /** serial number */ | |
| 22 | + private Long messageID; | |
| 23 | + | |
| 24 | + /** unique sender id */ | |
| 25 | + private Long senderID; | |
| 26 | + | |
| 27 | + /** messenger type */ | |
| 28 | + private Messenger messenger; | |
| 29 | + | |
| 30 | + /** Attachment[] */ | |
| 31 | + private List<Attachment> attachments; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * Constructor | |
| 35 | + * @param botMessage | |
| 36 | + * @param attachment | |
| 37 | + */ | |
| 38 | + public BingMessage(final ProcessQueueMessageProtocol botMessage, final Attachment attachment){ | |
| 39 | + this.messageID = botMessage.getMessageID(); | |
| 40 | + this.senderID = botMessage.getSenderID(); | |
| 41 | + this.messenger = botMessage.getMessenger(); | |
| 42 | + this.attachments = new ArrayList<>(1); | |
| 43 | + this.attachments.add(attachment); | |
| 44 | + } | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * Constructor | |
| 48 | + * @param nspResponse | |
| 49 | + * @param botMessage | |
| 50 | + */ | |
| 51 | + public BingMessage(final NSPResponse nspResponse, final ProcessQueueMessageProtocol botMessage){ | |
| 52 | + this.text = nspResponse.getText(); | |
| 53 | + this.messageID = botMessage.getMessageID(); | |
| 54 | + this.senderID = botMessage.getSenderID(); | |
| 55 | + this.messenger = botMessage.getMessenger(); | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Override | |
| 59 | + public Long getId() { | |
| 60 | + return 1L; | |
| 61 | + } | |
| 62 | + | |
| 63 | + @Override | |
| 64 | + public Target getTarget() { | |
| 65 | + return Target.NTSP; | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Override | |
| 69 | + public Long getMessageID() { | |
| 70 | + return messageID; | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Override | |
| 74 | + public Long getSenderID() { | |
| 75 | + return senderID; | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Override | |
| 79 | + public Messenger getMessenger() { | |
| 80 | + return messenger; | |
| 81 | + } | |
| 82 | + | |
| 83 | + @Override | |
| 84 | + public String getText() { | |
| 85 | + return text; | |
| 86 | + } | |
| 87 | + | |
| 88 | + @Override | |
| 89 | + public boolean hasAttachments() { | |
| 90 | + return (attachments != null); | |
| 91 | + } | |
| 92 | + | |
| 93 | + @Override | |
| 94 | + public List<Attachment> getAttachments() { | |
| 95 | + return attachments; | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Override | |
| 99 | + public String getIntent() { | |
| 100 | + return null; | |
| 101 | + } | |
| 102 | + | |
| 103 | + @Override | |
| 104 | + public Map<String, String> getEntities() { | |
| 105 | + return null; | |
| 106 | + } | |
| 107 | +} | ... | ... |
services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingNBest.java
0 → 100755
| 1 | +++ a/services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingNBest.java | |
| 1 | +package de.bht.beuthbot.nsp.bing.model; | |
| 2 | + | |
| 3 | +import com.google.gson.annotations.SerializedName; | |
| 4 | + | |
| 5 | +import java.io.Serializable; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * Bing Speech API Java Class for JSON parsing. | |
| 9 | + * @Author: Christopher Kümmel on 6/15/2017. | |
| 10 | + */ | |
| 11 | +public class BingNBest implements Serializable{ | |
| 12 | + | |
| 13 | + @SerializedName("Confidence") | |
| 14 | + private String confidence; | |
| 15 | + @SerializedName("Lexical") | |
| 16 | + private String lexical; | |
| 17 | + @SerializedName("ITN") | |
| 18 | + private String iTN; | |
| 19 | + @SerializedName("MaskedITN") | |
| 20 | + private String maskedITN; | |
| 21 | + @SerializedName("Display") | |
| 22 | + private String display; | |
| 23 | + | |
| 24 | + public String getConfidence() { | |
| 25 | + return confidence; | |
| 26 | + } | |
| 27 | + | |
| 28 | + public void setConfidence(String confidence) { | |
| 29 | + this.confidence = confidence; | |
| 30 | + } | |
| 31 | + | |
| 32 | + public String getLexical() { | |
| 33 | + return lexical; | |
| 34 | + } | |
| 35 | + | |
| 36 | + public void setLexical(String lexical) { | |
| 37 | + this.lexical = lexical; | |
| 38 | + } | |
| 39 | + | |
| 40 | + public String getITN() { | |
| 41 | + return iTN; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public void setITN(String iTN) { | |
| 45 | + this.iTN = iTN; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public String getMaskedITN() { | |
| 49 | + return maskedITN; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public void setMaskedITN(String maskedITN) { | |
| 53 | + this.maskedITN = maskedITN; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public String getDisplay() { | |
| 57 | + return display; | |
| 58 | + } | |
| 59 | + | |
| 60 | + public void setDisplay(String display) { | |
| 61 | + this.display = display; | |
| 62 | + } | |
| 63 | + | |
| 64 | +} | ... | ... |
services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingSimpleResponse.java
0 → 100755
| 1 | +++ a/services/Bing/src/main/java/de/bht/beuthbot/nsp/bing/model/BingSimpleResponse.java | |
| 1 | +package de.bht.beuthbot.nsp.bing.model; | |
| 2 | + | |
| 3 | +import com.google.gson.annotations.SerializedName; | |
| 4 | +import de.bht.beuthbot.model.nsp.NSPResponse; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * Bing Speech API Java Class for JSON parsing. | |
| 8 | + * @Author: Christopher Kümmel on 6/14/2017. | |
| 9 | + */ | |
| 10 | +public class BingSimpleResponse implements NSPResponse { | |
| 11 | + | |
| 12 | + @SerializedName("RecognitionStatus") | |
| 13 | + private String recognitionStatus; | |
| 14 | + @SerializedName("DisplayText") | |
| 15 | + private String displayText; | |
| 16 | + @SerializedName("Offset") | |
| 17 | + private String offset; | |
| 18 | + @SerializedName("Duration") | |
| 19 | + private String duration; | |
| 20 | + | |
| 21 | + @Override | |
| 22 | + public String getText() { | |
| 23 | + return displayText; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void setText(String displayText){ | |
| 27 | + this.displayText = displayText; | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public String getRecognitionStatus() { | |
| 32 | + return recognitionStatus; | |
| 33 | + } | |
| 34 | + | |
| 35 | + public void setRecognitionStatus(String recognitionStatus){ | |
| 36 | + this.recognitionStatus = recognitionStatus; | |
| 37 | + } | |
| 38 | + | |
| 39 | + public String getOffset() { | |
| 40 | + return offset; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public void setOffset(String offset) { | |
| 44 | + this.offset = offset; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public String getDuration() { | |
| 48 | + return duration; | |
| 49 | + } | |
| 50 | + | |
| 51 | + public void setDuration(String duration) { | |
| 52 | + this.duration = duration; | |
| 53 | + } | |
| 54 | +} | ... | ... |
services/Bing/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/Bing/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/Common/build.gradle
0 → 100755
| 1 | +++ a/services/Common/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'checkstyle' | |
| 3 | + | |
| 4 | +repositories { | |
| 5 | + mavenCentral() | |
| 6 | +} | |
| 7 | + | |
| 8 | +dependencies { | |
| 9 | + compile "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 10 | + "com.google.code.gson:gson:2.8.1", | |
| 11 | + "org.slf4j:slf4j-api:1.7.25" | |
| 12 | +} | |
| 13 | + | |
| 14 | +sourceCompatibility = 1.8 | |
| 0 | 15 | \ No newline at end of file | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/attachments/AttachmentStore.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/attachments/AttachmentStore.java | |
| 1 | +package de.bht.beuthbot.attachments; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.attachments.model.AttachmentStoreMode; | |
| 4 | +import de.bht.beuthbot.model.AttachmentType; | |
| 5 | + | |
| 6 | +import javax.ejb.Remote; | |
| 7 | +import java.io.ByteArrayOutputStream; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @author: georg.glossmann@adesso.de | |
| 11 | + * Date: 05.07.17 | |
| 12 | + */ | |
| 13 | +@Remote | |
| 14 | +public interface AttachmentStore { | |
| 15 | + Long storeAttachment(String fileURI, AttachmentType attachmentType); | |
| 16 | + | |
| 17 | + Long storeAttachment(ByteArrayOutputStream byteArrayOutputStream, AttachmentType attachmentType); | |
| 18 | + | |
| 19 | + String loadAttachmentPath(long attachmentID, AttachmentStoreMode attachmentStoreMode); | |
| 20 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/attachments/model/AttachmentStoreMode.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/attachments/model/AttachmentStoreMode.java | |
| 1 | +package de.bht.beuthbot.attachments.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @Author: Christopher Kümmel on 7/2/2017. | |
| 5 | + */ | |
| 6 | +public enum AttachmentStoreMode { | |
| 7 | + /** Accessible File URI */ | |
| 8 | + FILE_URI, | |
| 9 | + /** Local File Path*/ | |
| 10 | + LOCAL_PATH | |
| 11 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/conf/Application.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/conf/Application.java | |
| 1 | +package de.bht.beuthbot.conf; | |
| 2 | + | |
| 3 | +import javax.ejb.Remote; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @author: georg.glossmann@adesso.de | |
| 7 | + * Date: 05.07.17 | |
| 8 | + */ | |
| 9 | +@Remote | |
| 10 | +public interface Application { | |
| 11 | + String getConfiguration(Configuration property); | |
| 12 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/conf/Configuration.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/conf/Configuration.java | |
| 1 | +package de.bht.beuthbot.conf; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @author: georg.glossmann@adesso.de | |
| 5 | + * Date: 03.07.17 | |
| 6 | + */ | |
| 7 | +public enum Configuration { | |
| 8 | + WEB_URL, | |
| 9 | + | |
| 10 | + TELEGRAM_WEBHOOK_URL, | |
| 11 | + TELEGRAM_BOT_TOKEN, | |
| 12 | + | |
| 13 | + FACEBOOK_WEBHOOK_TOKEN, | |
| 14 | + FACEBOOK_BOT_TOKEN, | |
| 15 | + FACEBOOK_ACCESS_TOKEN, | |
| 16 | + | |
| 17 | + API_AI_TOKEN, | |
| 18 | + | |
| 19 | + BING_SPEECH_LOCALE, | |
| 20 | + BING_SPEECH_GUID, | |
| 21 | + BING_SPEECH_SECRET_KEY, | |
| 22 | + | |
| 23 | + LOCAL_ATTACHMENT_PATH, | |
| 24 | + | |
| 25 | + RASA_URL, | |
| 26 | + | |
| 27 | + RASA_UNIT_ON, | |
| 28 | + APIAI_UNIT_ON, | |
| 29 | + FACEBOOK_UNIT_ON, | |
| 30 | + TELEGRAM_UNIT_ON, | |
| 31 | + MAINBOT_UNIT_ON, | |
| 32 | + BING_UNIT_ON; | |
| 33 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/jms/ProcessQueue.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/jms/ProcessQueue.java | |
| 1 | +package de.bht.beuthbot.jms; | |
| 2 | + | |
| 3 | +import javax.ejb.Remote; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @author: georg.glossmann@adesso.de | |
| 7 | + * Date: 05.07.17 | |
| 8 | + */ | |
| 9 | +@Remote | |
| 10 | +public interface ProcessQueue { | |
| 11 | + | |
| 12 | + /** | |
| 13 | + * Routing internal messages to there destination, based on the message content. | |
| 14 | + * @param taskMessage the internal message to route | |
| 15 | + */ | |
| 16 | + void route(TaskMessage taskMessage); | |
| 17 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/jms/ProcessQueueMessageProtocol.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/jms/ProcessQueueMessageProtocol.java | |
| 1 | +package de.bht.beuthbot.jms; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.model.Attachment; | |
| 4 | +import de.bht.beuthbot.model.Messenger; | |
| 5 | + | |
| 6 | +import java.io.Serializable; | |
| 7 | +import java.util.List; | |
| 8 | +import java.util.Map; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * @author: georg.glossmann@adesso.de | |
| 12 | + * Date: 10.07.17 | |
| 13 | + */ | |
| 14 | +public interface ProcessQueueMessageProtocol extends Serializable{ | |
| 15 | + Long getId(); | |
| 16 | + | |
| 17 | + Target getTarget(); | |
| 18 | + | |
| 19 | + Long getMessageID(); | |
| 20 | + | |
| 21 | + Long getSenderID(); | |
| 22 | + | |
| 23 | + Messenger getMessenger(); | |
| 24 | + | |
| 25 | + String getText(); | |
| 26 | + | |
| 27 | + boolean hasAttachments(); | |
| 28 | + | |
| 29 | + List<Attachment> getAttachments(); | |
| 30 | + | |
| 31 | + String getIntent(); | |
| 32 | + | |
| 33 | + Map<String, String> getEntities(); | |
| 34 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/jms/Target.java
0 → 100755
services/Common/src/main/java/de/bht/beuthbot/jms/TaskMessage.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/jms/TaskMessage.java | |
| 1 | +package de.bht.beuthbot.jms; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.model.Attachment; | |
| 4 | +import de.bht.beuthbot.model.Messenger; | |
| 5 | +import de.bht.beuthbot.utils.GsonUtils; | |
| 6 | + | |
| 7 | +import java.util.*; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @author: georg.glossmann@adesso.de | |
| 11 | + * Date: 06.07.17 | |
| 12 | + */ | |
| 13 | +public class TaskMessage implements ProcessQueueMessageProtocol { | |
| 14 | + | |
| 15 | + private static final long serialVersionUID = 8234160552216573531L; | |
| 16 | + | |
| 17 | + private final Long id; | |
| 18 | + private final Target target; | |
| 19 | + private final Long messageID; | |
| 20 | + private final Long senderID; | |
| 21 | + private final Messenger messenger; | |
| 22 | + private final String text; | |
| 23 | + private final List<Attachment> attachments; | |
| 24 | + private final String intent; | |
| 25 | + private final Map<String, String> entities; | |
| 26 | + | |
| 27 | + public TaskMessage(final ProcessQueueMessageProtocol message) { | |
| 28 | + this.id = message.getId(); | |
| 29 | + this.target = message.getTarget(); | |
| 30 | + this.messageID = message.getMessageID(); | |
| 31 | + this.senderID = message.getSenderID(); | |
| 32 | + this.messenger = message.getMessenger(); | |
| 33 | + this.text = message.getText(); | |
| 34 | + | |
| 35 | + this.attachments = new ArrayList<>(); | |
| 36 | + this.attachments.addAll(message.getAttachments()); | |
| 37 | + | |
| 38 | + this.intent = message.getIntent(); | |
| 39 | + this.entities = new HashMap<>(); | |
| 40 | + this.entities.putAll(message.getEntities()); | |
| 41 | + } | |
| 42 | + | |
| 43 | + public TaskMessage(final ProcessQueueMessageProtocol message, final Target target) { | |
| 44 | + this.id = message.getId(); | |
| 45 | + this.target = target; | |
| 46 | + this.messageID = message.getMessageID(); | |
| 47 | + this.senderID = message.getSenderID(); | |
| 48 | + this.messenger = message.getMessenger(); | |
| 49 | + this.text = message.getText(); | |
| 50 | + | |
| 51 | + this.attachments = new ArrayList<>(); | |
| 52 | + this.attachments.addAll(message.getAttachments()); | |
| 53 | + | |
| 54 | + this.intent = message.getIntent(); | |
| 55 | + this.entities = new HashMap<>(); | |
| 56 | + this.entities.putAll(message.getEntities()); | |
| 57 | + } | |
| 58 | + | |
| 59 | + @Override | |
| 60 | + public Long getId() { | |
| 61 | + return id; | |
| 62 | + } | |
| 63 | + | |
| 64 | + @Override | |
| 65 | + public Target getTarget() { | |
| 66 | + return target; | |
| 67 | + } | |
| 68 | + | |
| 69 | + @Override | |
| 70 | + public Long getMessageID() { | |
| 71 | + return messageID; | |
| 72 | + } | |
| 73 | + | |
| 74 | + @Override | |
| 75 | + public Long getSenderID() { | |
| 76 | + return senderID; | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public Messenger getMessenger() { | |
| 81 | + return messenger; | |
| 82 | + } | |
| 83 | + | |
| 84 | + @Override | |
| 85 | + public String getText() { | |
| 86 | + return text; | |
| 87 | + } | |
| 88 | + | |
| 89 | + @Override | |
| 90 | + public boolean hasAttachments() { | |
| 91 | + if (attachments == null) { | |
| 92 | + return false; | |
| 93 | + } | |
| 94 | + return attachments.size() > 0; | |
| 95 | + } | |
| 96 | + | |
| 97 | + @Override | |
| 98 | + public List<Attachment> getAttachments() { | |
| 99 | + if (attachments == null) { | |
| 100 | + return Collections.emptyList(); | |
| 101 | + } | |
| 102 | + return Collections.unmodifiableList(attachments); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public String getIntent() { | |
| 107 | + return intent; | |
| 108 | + } | |
| 109 | + | |
| 110 | + @Override | |
| 111 | + public Map<String, String> getEntities() { | |
| 112 | + if (entities == null) { | |
| 113 | + return Collections.emptyMap(); | |
| 114 | + } | |
| 115 | + return Collections.unmodifiableMap(entities); | |
| 116 | + } | |
| 117 | + | |
| 118 | + @Override | |
| 119 | + public String toString() { | |
| 120 | + return GsonUtils.toJson(this); | |
| 121 | + } | |
| 122 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/model/Attachment.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/model/Attachment.java | |
| 1 | +package de.bht.beuthbot.model; | |
| 2 | + | |
| 3 | +import java.io.Serializable; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @Author: Christopher Kümmel on 5/14/2017. | |
| 7 | + */ | |
| 8 | +public interface Attachment extends Serializable{ | |
| 9 | + public Long getId(); | |
| 10 | + | |
| 11 | + public String getFileURI(); | |
| 12 | + | |
| 13 | + public AttachmentType getAttachmentType(); | |
| 14 | + | |
| 15 | + public String getCaption(); | |
| 16 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/model/AttachmentType.java
0 → 100755
services/Common/src/main/java/de/bht/beuthbot/model/EntityName.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/model/EntityName.java | |
| 1 | +package de.bht.beuthbot.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by sJantzen on 29.06.2017. | |
| 5 | + */ | |
| 6 | +public enum EntityName { | |
| 7 | + | |
| 8 | + DATE("date"), DISH_TYPE("dishtype"), HEALTHY("healthy"), INGREDIENTS("ingredients"), DISH_CATEGORY("dishcategory"), | |
| 9 | + DISH_NAME("dishname"); | |
| 10 | + | |
| 11 | + private String text; | |
| 12 | + | |
| 13 | + EntityName(final String text) { | |
| 14 | + this.text = text; | |
| 15 | + } | |
| 16 | + | |
| 17 | + public String getText() { | |
| 18 | + return text; | |
| 19 | + } | |
| 20 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/model/Intent.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/model/Intent.java | |
| 1 | +package de.bht.beuthbot.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by sJantzen on 29.06.2017. | |
| 5 | + */ | |
| 6 | +public enum Intent { | |
| 7 | + | |
| 8 | + SHOW_FOOD("showFood"), HELLO("Hello"), GREET("greet"), BYE("Bye"), | |
| 9 | + GOODBYE("goodbye"), RESTAURANT_SEARCH("restaurant_search"), START("Start"), | |
| 10 | + SHOW_PRICE("showPrice"), FALLBACK("Fallback"); | |
| 11 | + | |
| 12 | + private String text; | |
| 13 | + | |
| 14 | + Intent(final String text) { | |
| 15 | + this.text = text; | |
| 16 | + } | |
| 17 | + | |
| 18 | + public String getText() { | |
| 19 | + return text; | |
| 20 | + } | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * Returns an intent matching the given text. | |
| 24 | + * @param text | |
| 25 | + * @return null if no matching intent is found. | |
| 26 | + */ | |
| 27 | + public Intent getIntent(final String text) { | |
| 28 | + for (Intent intent : Intent.values()) { | |
| 29 | + if (intent.getText().equals(text)){ | |
| 30 | + return intent; | |
| 31 | + } | |
| 32 | + } | |
| 33 | + return null; | |
| 34 | + } | |
| 35 | + | |
| 36 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/model/Messenger.java
0 → 100755
services/Common/src/main/java/de/bht/beuthbot/model/nlp/NLUResponse.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/model/nlp/NLUResponse.java | |
| 1 | +package de.bht.beuthbot.model.nlp; | |
| 2 | + | |
| 3 | +import java.util.Map; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @author: georg.glossmann@adesso.de | |
| 7 | + * Date: 04.06.17 | |
| 8 | + * | |
| 9 | + * The base result interface for every natural language processing unit like rasa_nlu and api.ai | |
| 10 | + */ | |
| 11 | +public interface NLUResponse { | |
| 12 | + | |
| 13 | + public String getIntent(); | |
| 14 | + | |
| 15 | + public Map<String, String> getEntities(); | |
| 16 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/model/nsp/NSPResponse.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/model/nsp/NSPResponse.java | |
| 1 | +package de.bht.beuthbot.model.nsp; | |
| 2 | + | |
| 3 | +import java.io.Serializable; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @Author: Christopher Kümmel on 6/14/2017. | |
| 7 | + */ | |
| 8 | +public interface NSPResponse extends Serializable { | |
| 9 | + | |
| 10 | + /** generated text from file */ | |
| 11 | + String getText(); | |
| 12 | + | |
| 13 | + /** probability of recognition */ | |
| 14 | + String getRecognitionStatus(); | |
| 15 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/utils/GsonUtils.java
0 → 100755
| 1 | +++ a/services/Common/src/main/java/de/bht/beuthbot/utils/GsonUtils.java | |
| 1 | +package de.bht.beuthbot.utils; | |
| 2 | + | |
| 3 | +import com.google.gson.Gson; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @author: georg.glossmann@adesso.de | |
| 7 | + * Date: 12.07.17 | |
| 8 | + */ | |
| 9 | +public class GsonUtils { | |
| 10 | + private static Gson gson = new Gson(); | |
| 11 | + | |
| 12 | + static { | |
| 13 | + // extra init logic goes here | |
| 14 | + } | |
| 15 | + | |
| 16 | + public static <T> T fromJson(final String json, final Class<T> classOfT) { | |
| 17 | + return gson.fromJson(json, classOfT); | |
| 18 | + } | |
| 19 | + | |
| 20 | + | |
| 21 | + public static String toJson(final Object object) { | |
| 22 | + if (object == null) { | |
| 23 | + return ""; | |
| 24 | + } | |
| 25 | + return gson.toJson(object); | |
| 26 | + } | |
| 27 | +} | ... | ... |
services/FaceBook/build.gradle
0 → 100755
| 1 | +++ a/services/FaceBook/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | +} | |
| 8 | + | |
| 9 | +dependencies { | |
| 10 | + | |
| 11 | + compile project(':services:Common'), | |
| 12 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 13 | + "org.apache.httpcomponents:httpclient:4.5.3", | |
| 14 | + "org.apache.httpcomponents:httpmime:4.3.1", | |
| 15 | + "org.json:json:20160810" | |
| 16 | + | |
| 17 | + providedCompile "org.slf4j:slf4j-api:1.7.25", | |
| 18 | + "org.jboss.resteasy:resteasy-client:3.1.3.Final", | |
| 19 | + "org.jboss.resteasy:resteasy-jaxrs-all:3.1.3.Final" | |
| 20 | + | |
| 21 | +} | |
| 22 | + | |
| 23 | +sourceCompatibility = 1.8 | |
| 24 | + | |
| 25 | +war { | |
| 26 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 27 | + archiveName "facebook.war" | |
| 28 | +} | |
| 0 | 29 | \ No newline at end of file | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookRESTServiceInterface.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookRESTServiceInterface.java | |
| 1 | +package de.bht.beuthbot.messenger.facebook; | |
| 2 | + | |
| 3 | +import javax.ws.rs.*; | |
| 4 | +import javax.ws.rs.core.MediaType; | |
| 5 | +import javax.ws.rs.core.Response; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * Created by oliver on 15.06.2017. | |
| 9 | + */ | |
| 10 | +@Path("/") | |
| 11 | +public interface FacebookRESTServiceInterface { | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * interface to communicate with facebook | |
| 15 | + * | |
| 16 | + * @param json data payload which contains all necessary data of the message (sender, content, etc.) | |
| 17 | + * @param token the API token for Facebook messages | |
| 18 | + * @return JAX RS Response representing the result of querying the facebook server | |
| 19 | + */ | |
| 20 | + @POST | |
| 21 | + @Consumes({MediaType.APPLICATION_JSON}) | |
| 22 | + Response sendMessage(String json, @QueryParam("access_token") String token); | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * update the webhook location for facebook | |
| 26 | + * | |
| 27 | + * @param object --> page because we use a facebook page for our bot | |
| 28 | + * @param callback_url --> url of our server were the webhook of facebook goes to | |
| 29 | + * @param fields --> fields we want to subscribe to | |
| 30 | + * @param verify_token --> webhook token | |
| 31 | + * @param access_token --> app access token | |
| 32 | + * @return answer of facebook | |
| 33 | + */ | |
| 34 | + @POST | |
| 35 | + @Consumes("text/plain") | |
| 36 | + Response sendHook(@QueryParam("object") String object, @QueryParam("callback_url") String callback_url, @QueryParam("fields") String fields, @QueryParam("verify_token") String verify_token, @QueryParam("access_token") String access_token); | |
| 37 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookReceiveAdapter.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookReceiveAdapter.java | |
| 1 | +package de.bht.beuthbot.messenger.facebook; | |
| 2 | + | |
| 3 | +import com.google.gson.Gson; | |
| 4 | + | |
| 5 | +import de.bht.beuthbot.attachments.AttachmentStore; | |
| 6 | +import de.bht.beuthbot.conf.Application; | |
| 7 | +import de.bht.beuthbot.conf.Configuration; | |
| 8 | +import de.bht.beuthbot.jms.ProcessQueue; | |
| 9 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 10 | +import de.bht.beuthbot.messenger.facebook.model.FacebookBotMessage; | |
| 11 | +import de.bht.beuthbot.messenger.facebook.model.FacebookInput; | |
| 12 | +import org.jboss.resteasy.client.jaxrs.ResteasyClient; | |
| 13 | +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; | |
| 14 | +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; | |
| 15 | +import org.json.JSONObject; | |
| 16 | +import org.slf4j.Logger; | |
| 17 | +import org.slf4j.LoggerFactory; | |
| 18 | + | |
| 19 | +import javax.annotation.PostConstruct; | |
| 20 | +import javax.annotation.Resource; | |
| 21 | +import javax.inject.Inject; | |
| 22 | +import javax.servlet.http.HttpServletRequest; | |
| 23 | +import javax.ws.rs.*; | |
| 24 | +import javax.ws.rs.core.Context; | |
| 25 | +import javax.ws.rs.core.Response; | |
| 26 | +import javax.ws.rs.core.UriBuilder; | |
| 27 | +import java.util.Map; | |
| 28 | + | |
| 29 | + | |
| 30 | +/** | |
| 31 | + * Created by Oliver on 14.05.2017. | |
| 32 | + */ | |
| 33 | +@Path("") | |
| 34 | +public class FacebookReceiveAdapter { | |
| 35 | + | |
| 36 | + | |
| 37 | + /** | |
| 38 | + * slf4j Logger | |
| 39 | + */ | |
| 40 | + private final Logger logger = LoggerFactory.getLogger(FacebookReceiveAdapter.class); | |
| 41 | + | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * Injected JMS MessageQueue | |
| 45 | + */ | |
| 46 | + @Resource(lookup = "java:global/global/ProcessQueueBean") | |
| 47 | + private ProcessQueue processQueue; | |
| 48 | + | |
| 49 | + /** | |
| 50 | + * Injected AttachmentStore | |
| 51 | + */ | |
| 52 | + @Resource(lookup = "java:global/global/AttachmentStoreBean") | |
| 53 | + private AttachmentStore attachmentStore; | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * BeuthBot Application Bean | |
| 57 | + */ | |
| 58 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 59 | + private Application application; | |
| 60 | + | |
| 61 | + @Inject | |
| 62 | + private FacebookUtils facebookUtils; | |
| 63 | + | |
| 64 | + private String webhookToken; | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Initialize TelegramBot with Token | |
| 68 | + */ | |
| 69 | + @PostConstruct | |
| 70 | + public void init() { | |
| 71 | + webhookToken = application.getConfiguration(Configuration.FACEBOOK_WEBHOOK_TOKEN); | |
| 72 | + } | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * listen to POST requests from facebook (which contain the received messages) and react to them | |
| 76 | + * | |
| 77 | + * @param InputMessage message send by facebook | |
| 78 | + * @return request-answer to return to facebook | |
| 79 | + * @throws IOException | |
| 80 | + */ | |
| 81 | + @POST | |
| 82 | + @Path("/getUpdates") | |
| 83 | + @Consumes("application/json") | |
| 84 | + public String ReceiveMessage(String InputMessage) { | |
| 85 | + | |
| 86 | + logger.debug("FACEBOOK_RECEIVE:Input:" + InputMessage); | |
| 87 | + | |
| 88 | + Boolean isEcho; | |
| 89 | + JSONObject obj; | |
| 90 | + | |
| 91 | + //parse the incoming json to a FacebookInput-object | |
| 92 | + FacebookInput facebookInput = new Gson().fromJson(InputMessage, FacebookInput.class); | |
| 93 | + | |
| 94 | + //iterate through all entries of the input (usually it's just 1) and create FacebookBotMessages | |
| 95 | + for (int i = 0; i < facebookInput.getEntry().size(); i++) { | |
| 96 | + //create a new FacebookBotMessage from the Entry object of the FacebookInput | |
| 97 | + FacebookBotMessage facebookBotMessage = new FacebookBotMessage(facebookInput.getEntry().get(i)); | |
| 98 | + | |
| 99 | + if (facebookBotMessage.isIncomingMessage()) { | |
| 100 | + | |
| 101 | + //generate ID if message has attachment | |
| 102 | + facebookBotMessage.generateAttachmentID(attachmentStore); | |
| 103 | + | |
| 104 | + //put message into JMS-queue | |
| 105 | + | |
| 106 | + processQueue.route(new TaskMessage(facebookBotMessage)); | |
| 107 | + | |
| 108 | + } | |
| 109 | + | |
| 110 | + } | |
| 111 | + | |
| 112 | + return "\nReceived\n"; | |
| 113 | + | |
| 114 | + } | |
| 115 | + | |
| 116 | + /** | |
| 117 | + * function to listen to webhook verification tries and verify and activate them if the webhook token is correct | |
| 118 | + * | |
| 119 | + * @param request request from facebook to verify webhook | |
| 120 | + * @return return hub.challenge to facebook to inform facebook about successful verification | |
| 121 | + */ | |
| 122 | + @GET | |
| 123 | + @Path("/getUpdates") | |
| 124 | + @Produces("text/plain") | |
| 125 | + public String verification(@Context HttpServletRequest request) { | |
| 126 | + | |
| 127 | + | |
| 128 | + logger.debug("FACEBOOK_WEBHOOK:request: " + request); | |
| 129 | + Map<String, String[]> parametersMap = request.getParameterMap(); | |
| 130 | + if (parametersMap.size() > 0) { | |
| 131 | + logger.debug("FACEBOOK_WEBHOOK:HUB_MODE: " + request.getParameter("hub.mode")); | |
| 132 | + logger.debug("FACEBOOK_WEBHOOK:HUB_VERIFY_TOKEN: " + request.getParameter("hub.verify_token")); | |
| 133 | + logger.debug("FACEBOOK_WEBHOOK:HUB_CHALLENGE: " + request.getParameter("hub.challenge")); | |
| 134 | + | |
| 135 | + //compare verification token in properties with token received from facebook | |
| 136 | + if ("subscribe".equals(request.getParameter("hub.mode")) && | |
| 137 | + webhookToken.equals(request.getParameter("hub.verify_token"))) { | |
| 138 | + logger.debug("FACEBOOK_WEBHOOK:VERIFIED"); | |
| 139 | + | |
| 140 | + //if all conditions apply, finish verification by returning hub-challenge and activate token after 5s delay | |
| 141 | + facebookUtils.activateWebhook(); | |
| 142 | + return request.getParameter("hub.challenge"); | |
| 143 | + } | |
| 144 | + } else { | |
| 145 | + logger.debug("FACEBOOK_WEBHOOK:No request parameters were given."); | |
| 146 | + } | |
| 147 | + | |
| 148 | + return "Webhook FAILED"; | |
| 149 | + } | |
| 150 | + | |
| 151 | + /** | |
| 152 | + * makes it possible to set the Facebook webhook to the current server adress | |
| 153 | + * just open /rest/facebook/setWebhook to update your hook | |
| 154 | + * you need an APP! access token from https://developers.facebook.com/tools/explorer/ | |
| 155 | + * | |
| 156 | + * @param request starts when user navigates to setWebhook page | |
| 157 | + * @return answer from Facebook "{"success":true}" if worked | |
| 158 | + */ | |
| 159 | + @GET | |
| 160 | + @Path("/setWebhook") | |
| 161 | + @Produces("text/plain") | |
| 162 | + public String setWebhook(@Context HttpServletRequest request) { | |
| 163 | + | |
| 164 | + String access_token = application.getConfiguration(Configuration.FACEBOOK_ACCESS_TOKEN); | |
| 165 | + | |
| 166 | + //access token contains the App-ID, which we need for our call | |
| 167 | + String appid = access_token.substring(0, access_token.indexOf("|")); | |
| 168 | + | |
| 169 | + String registrationAdress = "https://graph.facebook.com/v2.9/" + appid + "/subscriptions"; | |
| 170 | + ResteasyClient client = new ResteasyClientBuilder().build(); | |
| 171 | + ResteasyWebTarget target = client.target(UriBuilder.fromPath(registrationAdress)); | |
| 172 | + FacebookRESTServiceInterface facebookProxy = target.proxy(FacebookRESTServiceInterface.class); | |
| 173 | + | |
| 174 | + String fields = "messages, messaging_postbacks, messaging_optins, message_deliveries, message_reads, messaging_payments, messaging_pre_checkouts, messaging_checkout_updates, messaging_account_linking, messaging_referrals, message_echoes"; | |
| 175 | + | |
| 176 | + String callback_url = application.getConfiguration(Configuration.WEB_URL) + "/facebook/getUpdates"; | |
| 177 | + Response response = facebookProxy.sendHook("page", callback_url, fields, webhookToken, access_token); | |
| 178 | + | |
| 179 | + String responseAsString = response.readEntity(String.class); | |
| 180 | + | |
| 181 | + | |
| 182 | + return responseAsString; | |
| 183 | + } | |
| 184 | + | |
| 185 | + | |
| 186 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookSendAdapter.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookSendAdapter.java | |
| 1 | +package de.bht.beuthbot.messenger.facebook; | |
| 2 | + | |
| 3 | + | |
| 4 | +import de.bht.beuthbot.attachments.AttachmentStore; | |
| 5 | +import de.bht.beuthbot.attachments.model.AttachmentStoreMode; | |
| 6 | +import de.bht.beuthbot.conf.Application; | |
| 7 | +import de.bht.beuthbot.conf.Configuration; | |
| 8 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 9 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 10 | +import org.slf4j.Logger; | |
| 11 | +import org.slf4j.LoggerFactory; | |
| 12 | + | |
| 13 | +import javax.annotation.Resource; | |
| 14 | +import javax.ejb.ActivationConfigProperty; | |
| 15 | +import javax.ejb.MessageDriven; | |
| 16 | +import javax.inject.Inject; | |
| 17 | +import javax.jms.JMSException; | |
| 18 | +import javax.jms.Message; | |
| 19 | +import javax.jms.MessageListener; | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * Created by oliver on 22.05.2017. | |
| 23 | + */ | |
| 24 | +@MessageDriven( | |
| 25 | + name = "OutboxFacebookProcessor", | |
| 26 | + activationConfig = { | |
| 27 | + @ActivationConfigProperty( | |
| 28 | + propertyName = "destinationType", | |
| 29 | + propertyValue = "javax.jms.Topic"), | |
| 30 | + @ActivationConfigProperty( | |
| 31 | + propertyName = "destination", | |
| 32 | + propertyValue = "jms/messages/inbox"), | |
| 33 | + @ActivationConfigProperty( | |
| 34 | + propertyName = "maxSession", propertyValue = "1"), | |
| 35 | + @ActivationConfigProperty( | |
| 36 | + propertyName = "messageSelector", propertyValue = "FACEBOOK IS NOT NULL" | |
| 37 | + ) | |
| 38 | + } | |
| 39 | +) | |
| 40 | +public class FacebookSendAdapter implements MessageListener { | |
| 41 | + | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * slf4j Logger | |
| 45 | + */ | |
| 46 | + private final Logger logger = LoggerFactory.getLogger(FacebookSendAdapter.class); | |
| 47 | + | |
| 48 | + /** Injected AttachmentStore */ | |
| 49 | + @Resource(lookup = "java:global/global/AttachmentStoreBean") | |
| 50 | + | |
| 51 | + private AttachmentStore attachmentStore; | |
| 52 | + | |
| 53 | + /** BeuthBot Application Bean */ | |
| 54 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 55 | + private Application application; | |
| 56 | + | |
| 57 | + @Inject | |
| 58 | + private FacebookUtils facebookUtils; | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * Send Text Message | |
| 62 | + * build a payload from the given message and send it to the facebook url | |
| 63 | + */ | |
| 64 | + private void sendMessage(Long recipient, String messageJson) { | |
| 65 | + String requestUrl = "https://graph.facebook.com/v2.6/me/messages"; | |
| 66 | + | |
| 67 | + //do you want to put each entry (e.g. dish) into a seperate message? - this is suggested due to facebooks 640 characters limit | |
| 68 | + Boolean seperateMessages = true; | |
| 69 | + String seperator = ", --------------------------"; | |
| 70 | + | |
| 71 | + //split (maybe) long message into multiple messages of sendable size | |
| 72 | + for (String currentMessage : facebookUtils.splitIntoMultipleMessages(messageJson, 600, seperateMessages, seperator)) { | |
| 73 | + String payload = "{\"recipient\": {\"id\": \"" + recipient + "\"}, \"message\": { \"text\": \"" + currentMessage + "\"}}"; | |
| 74 | + try { | |
| 75 | + //send message | |
| 76 | + facebookUtils.sendPostRequest(requestUrl, payload, application.getConfiguration(Configuration.FACEBOOK_BOT_TOKEN)); | |
| 77 | + } catch (Exception ex) { | |
| 78 | + ex.printStackTrace(); | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | + } | |
| 83 | + | |
| 84 | + /** | |
| 85 | + * Send Media Method | |
| 86 | + * fill payload with media information and send it to facebook | |
| 87 | + */ | |
| 88 | + private void sendMedia(ProcessQueueMessageProtocol message, String mediaType){ | |
| 89 | + String fileURL=attachmentStore.loadAttachmentPath(message.getAttachments().get(0).getId(), AttachmentStoreMode.FILE_URI); | |
| 90 | + String payload = "{recipient: { id: "+message.getSenderID()+" }, message: { attachment: { type: \""+mediaType+"\", payload: { url: \""+fileURL+"\" } } }} "; | |
| 91 | + logger.debug("FACEBOOK_SEND:Output:"+payload); | |
| 92 | + String requestUrl = "https://graph.facebook.com/v2.6/me/messages" ; | |
| 93 | + try { | |
| 94 | + facebookUtils.sendPostRequest(requestUrl, payload, application.getConfiguration(Configuration.FACEBOOK_BOT_TOKEN)); | |
| 95 | + } | |
| 96 | + catch(Exception ex){ | |
| 97 | + ex.printStackTrace(); | |
| 98 | + } | |
| 99 | + } | |
| 100 | + | |
| 101 | + /** | |
| 102 | + * receive messages from JMS and forward them to Facebook | |
| 103 | + * | |
| 104 | + * @param messageIn message from JMS | |
| 105 | + */ | |
| 106 | + @Override | |
| 107 | + public void onMessage(Message messageIn) { | |
| 108 | + try { | |
| 109 | + ProcessQueueMessageProtocol message = messageIn.getBody(TaskMessage.class); | |
| 110 | + | |
| 111 | + // if message has attachment(s), use sendMedia function depending on type | |
| 112 | + // mediaType represents the possible media types for outgoing Facebook Messages | |
| 113 | + if (message.hasAttachments()) { | |
| 114 | + switch (message.getAttachments().get(0).getAttachmentType()) { | |
| 115 | + case AUDIO: | |
| 116 | + sendMedia(message, "audio"); | |
| 117 | + break; | |
| 118 | + case VOICE: | |
| 119 | + sendMedia(message, "audio"); | |
| 120 | + break; | |
| 121 | + case VIDEO: | |
| 122 | + sendMedia(message, "video"); | |
| 123 | + break; | |
| 124 | + case DOCUMENT: | |
| 125 | + sendMedia(message, "file"); | |
| 126 | + break; | |
| 127 | + case PHOTO: | |
| 128 | + sendMedia(message, "image"); | |
| 129 | + break; | |
| 130 | + case UNKOWN: | |
| 131 | + sendMessage(message.getSenderID(), "Sorry! I'm just a bot and my developers just implemented audio and voice attachments..."); | |
| 132 | + break; | |
| 133 | + } | |
| 134 | + } | |
| 135 | + // else use simple text message sending | |
| 136 | + else { | |
| 137 | + sendMessage(message.getSenderID(), message.getText()); | |
| 138 | + } | |
| 139 | + } catch (JMSException e) { | |
| 140 | + e.printStackTrace(); | |
| 141 | + } | |
| 142 | + } | |
| 143 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookUtils.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/FacebookUtils.java | |
| 1 | +package de.bht.beuthbot.messenger.facebook; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.conf.Application; | |
| 4 | +import de.bht.beuthbot.conf.Configuration; | |
| 5 | +import org.jboss.resteasy.client.jaxrs.ResteasyClient; | |
| 6 | +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; | |
| 7 | +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; | |
| 8 | +import org.slf4j.Logger; | |
| 9 | +import org.slf4j.LoggerFactory; | |
| 10 | + | |
| 11 | +import javax.annotation.Resource; | |
| 12 | +import javax.ws.rs.core.Response; | |
| 13 | +import javax.ws.rs.core.UriBuilder; | |
| 14 | +import java.util.ArrayList; | |
| 15 | +import java.util.List; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * Created by oliver on 03.07.2017. | |
| 19 | + */ | |
| 20 | +public class FacebookUtils { | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * slf4j Logger | |
| 24 | + */ | |
| 25 | + private final Logger logger = LoggerFactory.getLogger(FacebookUtils.class); | |
| 26 | + | |
| 27 | + /** BeuthBot Application Bean */ | |
| 28 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 29 | + private Application application; | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * activate Webhook: | |
| 33 | + * it is necessary to activate the Facebook Webhook before usage | |
| 34 | + */ | |
| 35 | + public void activateWebhook() { | |
| 36 | + | |
| 37 | + //Start function to activate webhook after 5 seconds (to ensure the activation starts after the verification is finished) | |
| 38 | + Runnable activation = new Runnable() { | |
| 39 | + public void run() { | |
| 40 | + try { | |
| 41 | + Thread.sleep(5000); | |
| 42 | + } catch (InterruptedException e) { | |
| 43 | + e.printStackTrace(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + sendPostRequest("https://graph.facebook.com/v2.9/me/subscribed_apps","", application.getConfiguration(Configuration.FACEBOOK_BOT_TOKEN)); | |
| 47 | + | |
| 48 | + } | |
| 49 | + }; | |
| 50 | + new Thread(activation).start(); | |
| 51 | + } | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * uses the FacebookRESTServiceInterface to post the JSON data to Facebook | |
| 55 | + * | |
| 56 | + * @param requestUrl the url to send the json to | |
| 57 | + * @param payload string which contains the payload in json structure | |
| 58 | + * @param token facebook API token | |
| 59 | + * @return response from web request | |
| 60 | + */ | |
| 61 | + public String sendPostRequest(String requestUrl, String payload, String token) { | |
| 62 | + | |
| 63 | + ResteasyClient client = new ResteasyClientBuilder().build(); | |
| 64 | + ResteasyWebTarget target = client.target(UriBuilder.fromPath(requestUrl)); | |
| 65 | + FacebookRESTServiceInterface facebookProxy = target.proxy(FacebookRESTServiceInterface.class); | |
| 66 | + | |
| 67 | + Response response = facebookProxy.sendMessage(payload, token); | |
| 68 | + | |
| 69 | + String responseAsString = response.readEntity(String.class); | |
| 70 | + | |
| 71 | + | |
| 72 | + return responseAsString; | |
| 73 | + | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * splits a Facebook output messages into smaller messages due to the charlimit set by facebook | |
| 78 | + * | |
| 79 | + * @param messageJson long input message | |
| 80 | + * @param charLimit the maximum amount of characters | |
| 81 | + * @param seperateMessages boolean whether you want to split at a specific string | |
| 82 | + * @param seperator specific string to split message at | |
| 83 | + * @return list of small messages | |
| 84 | + */ | |
| 85 | + public List<String> splitIntoMultipleMessages(String messageJson, int charLimit, Boolean seperateMessages, String seperator) { | |
| 86 | + List<String> messages = new ArrayList<String>(); | |
| 87 | + | |
| 88 | + //facebook allows a maximum of 640 characters, message must be split if necessary: | |
| 89 | + String linesOfMessage[] = messageJson.split("\\r?\\n"); | |
| 90 | + | |
| 91 | + String currentOutput = ""; | |
| 92 | + for (int i = 0; i < linesOfMessage.length; i++) { | |
| 93 | + String line = linesOfMessage[i]; | |
| 94 | + if ((currentOutput + "\\n" + line).length() > charLimit || (line.contains(seperator) && seperateMessages)) { | |
| 95 | + //if appending new line would increase the chars over charLimit, put current output and start new one | |
| 96 | + messages.add(currentOutput); | |
| 97 | + | |
| 98 | + //hide seperator if message is split by entries | |
| 99 | + if (line.contains(seperator) && seperateMessages) { | |
| 100 | + line = ""; | |
| 101 | + } | |
| 102 | + | |
| 103 | + //begin a new output with the current line (which was not send because 640 chars would have been reached) | |
| 104 | + currentOutput = line; | |
| 105 | + } else { | |
| 106 | + //append line if char limit not reached | |
| 107 | + currentOutput = currentOutput + "\\n" + line; | |
| 108 | + } | |
| 109 | + | |
| 110 | + | |
| 111 | + } | |
| 112 | + messages.add(currentOutput); | |
| 113 | + | |
| 114 | + | |
| 115 | + return messages; | |
| 116 | + } | |
| 117 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/JAXActivator.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/JAXActivator.java | |
| 1 | +package de.bht.beuthbot.messenger.facebook; | |
| 2 | + | |
| 3 | +import javax.ws.rs.ApplicationPath; | |
| 4 | +import javax.ws.rs.core.Application; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * JAXActivator is an arbitrary name, what is important is that javax.ws.rs.core.Application is extended | |
| 8 | + * and the @ApplicationPath annotation is used with a "rest" path. Without this the rest routes linked to | |
| 9 | + * from index.html would not be found. | |
| 10 | + */ | |
| 11 | +@ApplicationPath("") | |
| 12 | +public class JAXActivator extends Application { | |
| 13 | + // Left empty intentionally | |
| 14 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookAttachment.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookAttachment.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | +import de.bht.beuthbot.model.Attachment; | |
| 7 | +import de.bht.beuthbot.model.AttachmentType; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by oliver on 15.06.2017. | |
| 11 | + * <p> | |
| 12 | + * Facebook-specific class of the Attachment Interface which is also the class which represents the Attachment-node in the message-Json | |
| 13 | + */ | |
| 14 | +public class FacebookAttachment implements Attachment { | |
| 15 | + | |
| 16 | + @SerializedName("type") | |
| 17 | + @Expose | |
| 18 | + private String type; | |
| 19 | + @SerializedName("payload") | |
| 20 | + @Expose | |
| 21 | + private FacebookPayload payload; | |
| 22 | + private Long id; | |
| 23 | + | |
| 24 | + public String getType() { | |
| 25 | + return type; | |
| 26 | + } | |
| 27 | + | |
| 28 | + public void setType(String type) { | |
| 29 | + this.type = type; | |
| 30 | + } | |
| 31 | + | |
| 32 | + public FacebookPayload getPayload() { | |
| 33 | + return payload; | |
| 34 | + } | |
| 35 | + | |
| 36 | + public void setPayload(FacebookPayload payload) { | |
| 37 | + this.payload = payload; | |
| 38 | + } | |
| 39 | + | |
| 40 | + public void setID(Long id) { | |
| 41 | + this.id = id; | |
| 42 | + } | |
| 43 | + | |
| 44 | + @Override | |
| 45 | + public Long getId() { | |
| 46 | + return id; | |
| 47 | + } | |
| 48 | + | |
| 49 | + @Override | |
| 50 | + public String getFileURI() { | |
| 51 | + return payload.getUrl(); | |
| 52 | + } | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * parse facebook specific types to the types the Chatbot implements | |
| 56 | + * | |
| 57 | + * @return Bot-intern Attachment type | |
| 58 | + */ | |
| 59 | + @Override | |
| 60 | + public AttachmentType getAttachmentType() { | |
| 61 | + switch (type) { | |
| 62 | + case "audio": | |
| 63 | + return AttachmentType.AUDIO; | |
| 64 | + //TODO: handle all attachment types; at the moment MessageQueue only allows unknown, audio, voice | |
| 65 | + //case "video": | |
| 66 | + // return AttachmentType.VIDEO; | |
| 67 | + //case "file": | |
| 68 | + // return AttachmentType.DOCUMENT; | |
| 69 | + //case "image": | |
| 70 | + // return AttachmentType.PHOTO; | |
| 71 | + default: | |
| 72 | + return AttachmentType.UNKOWN; | |
| 73 | + } | |
| 74 | + | |
| 75 | + | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Override | |
| 79 | + public String getCaption() { | |
| 80 | + return "Caption"; | |
| 81 | + } | |
| 82 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookBotMessage.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookBotMessage.java | |
| 1 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.attachments.AttachmentStore; | |
| 4 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 5 | +import de.bht.beuthbot.jms.Target; | |
| 6 | +import de.bht.beuthbot.model.Attachment; | |
| 7 | +import de.bht.beuthbot.model.AttachmentType; | |
| 8 | +import de.bht.beuthbot.model.Messenger; | |
| 9 | + | |
| 10 | +import java.util.ArrayList; | |
| 11 | +import java.util.Collections; | |
| 12 | +import java.util.List; | |
| 13 | +import java.util.Map; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * Created by oliver on 15.06.2017. | |
| 17 | + * <p> | |
| 18 | + * Facebook-specific class of the BotMessage Interface | |
| 19 | + */ | |
| 20 | + | |
| 21 | +public class FacebookBotMessage implements ProcessQueueMessageProtocol { | |
| 22 | + | |
| 23 | + //stores a FacebookEntry object which contains all necessary information | |
| 24 | + private FacebookEntry facebookEntry; | |
| 25 | + | |
| 26 | + public FacebookBotMessage(FacebookEntry facebookEntry) { | |
| 27 | + | |
| 28 | + this.facebookEntry = facebookEntry; | |
| 29 | + | |
| 30 | + } | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public Long getId() { | |
| 34 | + //TODO: generate Chatbot-intern-ID | |
| 35 | + return 1L; | |
| 36 | + } | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public Target getTarget() { | |
| 40 | + return Target.NTSP; | |
| 41 | + } | |
| 42 | + | |
| 43 | + @Override | |
| 44 | + public Long getMessageID() { | |
| 45 | + return Long.valueOf(facebookEntry.getId()); | |
| 46 | + } | |
| 47 | + | |
| 48 | + @Override | |
| 49 | + public Long getSenderID() { | |
| 50 | + return Long.valueOf(facebookEntry.getMessaging().get(0).getSender().getId()); | |
| 51 | + } | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public Messenger getMessenger() { | |
| 55 | + return Messenger.FACEBOOK; | |
| 56 | + } | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * due to the possibility that a FacebookEntry can contain multiply FacebookMessaging objects, iterate through all | |
| 60 | + * | |
| 61 | + * @return Text containing all message-texts | |
| 62 | + */ | |
| 63 | + @Override | |
| 64 | + public String getText() { | |
| 65 | + StringBuilder stringBuilder = new StringBuilder(); | |
| 66 | + for (FacebookMessaging facebookMessaging : facebookEntry.getMessaging()) { | |
| 67 | + stringBuilder.append(facebookMessaging.getMessage().getText()); | |
| 68 | + } | |
| 69 | + return stringBuilder.toString(); | |
| 70 | + } | |
| 71 | + | |
| 72 | + @Override | |
| 73 | + public boolean hasAttachments() { | |
| 74 | + if (facebookEntry.getMessaging().get(0).getMessage().getAttachments() == null) | |
| 75 | + return false; | |
| 76 | + else return true; | |
| 77 | + } | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * get all Attachments from the message object | |
| 81 | + * | |
| 82 | + * @return List of attachments found | |
| 83 | + */ | |
| 84 | + @Override | |
| 85 | + public List<Attachment> getAttachments() { | |
| 86 | + | |
| 87 | + | |
| 88 | + if (hasAttachments()) { | |
| 89 | + List<Attachment> atts = new ArrayList<>(); | |
| 90 | + | |
| 91 | + for (int i = 0; i < facebookEntry.getMessaging().get(0).getMessage().getAttachments().size(); i++) { | |
| 92 | + atts.add(facebookEntry.getMessaging().get(0).getMessage().getAttachments().get(i)); | |
| 93 | + } | |
| 94 | + | |
| 95 | + return atts; | |
| 96 | + | |
| 97 | + } else { | |
| 98 | + return Collections.emptyList(); | |
| 99 | + } | |
| 100 | + } | |
| 101 | + | |
| 102 | + | |
| 103 | + public boolean isIncomingMessage() { | |
| 104 | + //check if Message-node of BotMessage object exists | |
| 105 | + if (facebookEntry.getMessaging().get(0).getMessage() != null) { | |
| 106 | + // 'IsEcho' means whether the message is a new incoming message or just an 'echo' of a message the bot sends out | |
| 107 | + if (!facebookEntry.getMessaging().get(0).getMessage().getIsEcho()) { | |
| 108 | + return true; | |
| 109 | + } | |
| 110 | + } | |
| 111 | + return false; | |
| 112 | + } | |
| 113 | + | |
| 114 | + public void generateAttachmentID(AttachmentStore attachmentStore) { | |
| 115 | + FacebookMessage facebookMessage = facebookEntry.getMessaging().get(0).getMessage(); | |
| 116 | + | |
| 117 | + //if Attachment --> get ID via AttachmentStore and put it into attachment | |
| 118 | + if (facebookMessage.getAttachments() != null) { | |
| 119 | + FacebookAttachment att = facebookMessage.getAttachments().get(0); | |
| 120 | + | |
| 121 | + //at the moment just audio files are supported --> saved | |
| 122 | + //TODO: add/support more attachment types | |
| 123 | + if (att.getAttachmentType() == AttachmentType.AUDIO) { | |
| 124 | + Long id = attachmentStore.storeAttachment(att.getFileURI(), att.getAttachmentType()); | |
| 125 | + facebookMessage.getAttachments().get(0).setID(id); | |
| 126 | + } | |
| 127 | + } | |
| 128 | + } | |
| 129 | + | |
| 130 | + | |
| 131 | + @Override | |
| 132 | + public String getIntent() { | |
| 133 | + return null; | |
| 134 | + } | |
| 135 | + | |
| 136 | + @Override | |
| 137 | + public Map<String, String> getEntities() { | |
| 138 | + return Collections.emptyMap(); | |
| 139 | + | |
| 140 | + } | |
| 141 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookEntry.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookEntry.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import java.io.Serializable; | |
| 5 | +import java.util.List; | |
| 6 | +import com.google.gson.annotations.Expose; | |
| 7 | +import com.google.gson.annotations.SerializedName; | |
| 8 | +/** | |
| 9 | + * Created by oliver on 15.06.2017. | |
| 10 | + */ | |
| 11 | +public class FacebookEntry implements Serializable{ | |
| 12 | + | |
| 13 | + @SerializedName("id") | |
| 14 | + @Expose | |
| 15 | + private String id; | |
| 16 | + @SerializedName("time") | |
| 17 | + @Expose | |
| 18 | + private String time; | |
| 19 | + @SerializedName("messaging") | |
| 20 | + @Expose | |
| 21 | + private List<FacebookMessaging> messaging = null; | |
| 22 | + | |
| 23 | + public String getId() { | |
| 24 | + return id; | |
| 25 | + } | |
| 26 | + | |
| 27 | + public void setId(String id) { | |
| 28 | + this.id = id; | |
| 29 | + } | |
| 30 | + | |
| 31 | + public String getTime() { | |
| 32 | + return time; | |
| 33 | + } | |
| 34 | + | |
| 35 | + public void setTime(String time) { | |
| 36 | + this.time = time; | |
| 37 | + } | |
| 38 | + | |
| 39 | + public List<FacebookMessaging> getMessaging() { | |
| 40 | + return messaging; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public void setMessaging(List<FacebookMessaging> messaging) { | |
| 44 | + this.messaging = messaging; | |
| 45 | + } | |
| 46 | + | |
| 47 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookInput.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookInput.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import java.io.Serializable; | |
| 5 | +import java.util.List; | |
| 6 | +import com.google.gson.annotations.Expose; | |
| 7 | +import com.google.gson.annotations.SerializedName; | |
| 8 | +/** | |
| 9 | + * Created by oliver on 15.06.2017. | |
| 10 | + * | |
| 11 | + * represents the highest node of the json-object received by facebook | |
| 12 | + */ | |
| 13 | +public class FacebookInput implements Serializable { | |
| 14 | + | |
| 15 | + @SerializedName("object") | |
| 16 | + @Expose | |
| 17 | + private String object; | |
| 18 | + @SerializedName("entry") | |
| 19 | + @Expose | |
| 20 | + private List<FacebookEntry> entry = null; | |
| 21 | + | |
| 22 | + public String getObject() { | |
| 23 | + return object; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void setObject(String object) { | |
| 27 | + this.object = object; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public List<FacebookEntry> getEntry() { | |
| 31 | + return entry; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public void setEntry(List<FacebookEntry> entry) { | |
| 35 | + this.entry = entry; | |
| 36 | + } | |
| 37 | + | |
| 38 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookMessage.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookMessage.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import java.io.Serializable; | |
| 5 | +import java.util.List; | |
| 6 | +import com.google.gson.annotations.Expose; | |
| 7 | +import com.google.gson.annotations.SerializedName; | |
| 8 | +/** | |
| 9 | + * Created by oliver on 15.06.2017. | |
| 10 | + */ | |
| 11 | +public class FacebookMessage implements Serializable { | |
| 12 | + | |
| 13 | + @SerializedName("is_echo") | |
| 14 | + @Expose | |
| 15 | + private Boolean isEcho; | |
| 16 | + @SerializedName("mid") | |
| 17 | + @Expose | |
| 18 | + private String mid; | |
| 19 | + @SerializedName("seq") | |
| 20 | + @Expose | |
| 21 | + private Integer seq; | |
| 22 | + @SerializedName("text") | |
| 23 | + @Expose | |
| 24 | + private String text; | |
| 25 | + @SerializedName("attachments") | |
| 26 | + @Expose | |
| 27 | + private List<FacebookAttachment> attachments = null; | |
| 28 | + | |
| 29 | + public Boolean getIsEcho() { | |
| 30 | + if(isEcho!=null) { | |
| 31 | + return isEcho; | |
| 32 | + } | |
| 33 | + else { | |
| 34 | + return false; | |
| 35 | + } | |
| 36 | + } | |
| 37 | + | |
| 38 | + public void setIsEcho(Boolean isEcho) { | |
| 39 | + this.isEcho = isEcho; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public String getMid() { | |
| 43 | + return mid; | |
| 44 | + } | |
| 45 | + | |
| 46 | + public void setMid(String mid) { | |
| 47 | + this.mid = mid; | |
| 48 | + } | |
| 49 | + | |
| 50 | + public Integer getSeq() { | |
| 51 | + return seq; | |
| 52 | + } | |
| 53 | + | |
| 54 | + public void setSeq(Integer seq) { | |
| 55 | + this.seq = seq; | |
| 56 | + } | |
| 57 | + | |
| 58 | + public String getText() { | |
| 59 | + return text; | |
| 60 | + } | |
| 61 | + | |
| 62 | + public void setText(String text) { | |
| 63 | + this.text = text; | |
| 64 | + } | |
| 65 | + | |
| 66 | + public List<FacebookAttachment> getAttachments() { | |
| 67 | + return attachments; | |
| 68 | + } | |
| 69 | + | |
| 70 | + public void setAttachments(List<FacebookAttachment> attachments) { | |
| 71 | + this.attachments = attachments; | |
| 72 | + } | |
| 73 | + | |
| 74 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookMessaging.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookMessaging.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by oliver on 15.06.2017. | |
| 11 | + */ | |
| 12 | +public class FacebookMessaging implements Serializable { | |
| 13 | + | |
| 14 | + @SerializedName("sender") | |
| 15 | + @Expose | |
| 16 | + private FacebookSender sender; | |
| 17 | + @SerializedName("recipient") | |
| 18 | + @Expose | |
| 19 | + private FacebookRecipient recipient; | |
| 20 | + @SerializedName("timestamp") | |
| 21 | + @Expose | |
| 22 | + private String timestamp; | |
| 23 | + @SerializedName("message") | |
| 24 | + @Expose | |
| 25 | + private FacebookMessage message; | |
| 26 | + | |
| 27 | + public FacebookSender getSender() { | |
| 28 | + return sender; | |
| 29 | + } | |
| 30 | + | |
| 31 | + public void setSender(FacebookSender sender) { | |
| 32 | + this.sender = sender; | |
| 33 | + } | |
| 34 | + | |
| 35 | + public FacebookRecipient getRecipient() { | |
| 36 | + return recipient; | |
| 37 | + } | |
| 38 | + | |
| 39 | + public void setRecipient(FacebookRecipient recipient) { | |
| 40 | + this.recipient = recipient; | |
| 41 | + } | |
| 42 | + | |
| 43 | + public String getTimestamp() { | |
| 44 | + return timestamp; | |
| 45 | + } | |
| 46 | + | |
| 47 | + public void setTimestamp(String timestamp) { | |
| 48 | + this.timestamp = timestamp; | |
| 49 | + } | |
| 50 | + | |
| 51 | + public FacebookMessage getMessage() { | |
| 52 | + return message; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public void setMessage(FacebookMessage message) { | |
| 56 | + this.message = message; | |
| 57 | + } | |
| 58 | + | |
| 59 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookPayload.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookPayload.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by oliver on 15.06.2017. | |
| 11 | + */ | |
| 12 | +public class FacebookPayload implements Serializable { | |
| 13 | + | |
| 14 | + @SerializedName("url") | |
| 15 | + @Expose | |
| 16 | + private String url; | |
| 17 | + | |
| 18 | + public String getUrl() { | |
| 19 | + return url; | |
| 20 | + } | |
| 21 | + | |
| 22 | + public void setUrl(String url) { | |
| 23 | + this.url = url; | |
| 24 | + } | |
| 25 | + | |
| 26 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookRecipient.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookRecipient.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by oliver on 15.06.2017. | |
| 11 | + */ | |
| 12 | +public class FacebookRecipient implements Serializable { | |
| 13 | + | |
| 14 | + @SerializedName("id") | |
| 15 | + @Expose | |
| 16 | + private String id; | |
| 17 | + | |
| 18 | + public String getId() { | |
| 19 | + return id; | |
| 20 | + } | |
| 21 | + | |
| 22 | + public void setId(String id) { | |
| 23 | + this.id = id; | |
| 24 | + } | |
| 25 | + | |
| 26 | +} | ... | ... |
services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookSender.java
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/java/de/bht/beuthbot/messenger/facebook/model/FacebookSender.java | |
| 1 | + | |
| 2 | +package de.bht.beuthbot.messenger.facebook.model; | |
| 3 | + | |
| 4 | +import com.google.gson.annotations.Expose; | |
| 5 | +import com.google.gson.annotations.SerializedName; | |
| 6 | + | |
| 7 | +import java.io.Serializable; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by oliver on 15.06.2017. | |
| 11 | + */ | |
| 12 | +public class FacebookSender implements Serializable { | |
| 13 | + | |
| 14 | + @SerializedName("id") | |
| 15 | + @Expose | |
| 16 | + private String id; | |
| 17 | + | |
| 18 | + public String getId() { | |
| 19 | + return id; | |
| 20 | + } | |
| 21 | + | |
| 22 | + public void setId(String id) { | |
| 23 | + this.id = id; | |
| 24 | + } | |
| 25 | + | |
| 26 | +} | ... | ... |
services/FaceBook/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/FaceBook/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/Global/build.gradle
0 → 100755
| 1 | +++ a/services/Global/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | +} | |
| 8 | + | |
| 9 | +dependencies { | |
| 10 | + compile project(':services:Common'), | |
| 11 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 12 | + "com.google.code.gson:gson:2.8.1", | |
| 13 | + "org.apache.httpcomponents:httpclient:4.5.3", | |
| 14 | + "commons-io:commons-io:2.5" | |
| 15 | + | |
| 16 | + | |
| 17 | + providedCompile "org.slf4j:slf4j-api:1.7.25" | |
| 18 | + | |
| 19 | + testCompile "org.jboss.arquillian.junit:arquillian-junit-container:1.1.13.Final", | |
| 20 | + "junit:junit:4.12" | |
| 21 | + | |
| 22 | + testRuntime "org.wildfly.arquillian:wildfly-arquillian-container-remote:2.0.2.Final", | |
| 23 | + "org.slf4j:slf4j-simple:1.7.25" | |
| 24 | +} | |
| 25 | + | |
| 26 | +sourceCompatibility = 1.8 | |
| 27 | + | |
| 28 | +war { | |
| 29 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 30 | + archiveName "global.war" | |
| 31 | +} | |
| 0 | 32 | \ No newline at end of file | ... | ... |
services/Global/src/main/java/de/bht/beuthbot/JAXActivator.java
0 → 100755
| 1 | +++ a/services/Global/src/main/java/de/bht/beuthbot/JAXActivator.java | |
| 1 | +package de.bht.beuthbot; | |
| 2 | + | |
| 3 | +import javax.ws.rs.ApplicationPath; | |
| 4 | +import javax.ws.rs.core.Application; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * JAXActivator is an arbitrary name, what is important is that javax.ws.rs.core.Application is extended | |
| 8 | + * and the @ApplicationPath annotation is used with a "rest" path. Without this the rest routes linked to | |
| 9 | + * from index.html would not be found. | |
| 10 | + */ | |
| 11 | +@ApplicationPath("") | |
| 12 | +public class JAXActivator extends Application { | |
| 13 | + // Left empty intentionally | |
| 14 | +} | ... | ... |
services/Global/src/main/java/de/bht/beuthbot/attachments/AttachmentService.java
0 → 100755
| 1 | +++ a/services/Global/src/main/java/de/bht/beuthbot/attachments/AttachmentService.java | |
| 1 | +package de.bht.beuthbot.attachments; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.attachments.model.AttachmentStoreMode; | |
| 4 | +import org.apache.http.HttpStatus; | |
| 5 | + | |
| 6 | +import javax.annotation.Resource; | |
| 7 | +import javax.ws.rs.GET; | |
| 8 | +import javax.ws.rs.Path; | |
| 9 | +import javax.ws.rs.PathParam; | |
| 10 | +import javax.ws.rs.Produces; | |
| 11 | +import javax.ws.rs.core.Response; | |
| 12 | +import java.io.File; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * @Author: Christopher Kümmel on 6/28/2017. | |
| 16 | + */ | |
| 17 | +@Path("/attachments") | |
| 18 | +public class AttachmentService { | |
| 19 | + | |
| 20 | + /** Injected AttachmentStore */ | |
| 21 | + @Resource(lookup = "java:global/global/AttachmentStoreBean") | |
| 22 | + private AttachmentStore attachmentStore; | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * filehandler for HTTP GET audio requests | |
| 26 | + * @param fileId to identify file | |
| 27 | + * @param ext file extension | |
| 28 | + * @return .mpg audio file | |
| 29 | + */ | |
| 30 | + @GET | |
| 31 | + @Path("/{directory:(audio|voice)*}/{fileID}.{ext}") | |
| 32 | + @Produces({"audio/mpeg"}) | |
| 33 | + public Response downloadAudioFile(@PathParam("fileID") final Long fileId, @PathParam("ext") final String ext) { | |
| 34 | + String filePath = attachmentStore.loadAttachmentPath(fileId, AttachmentStoreMode.LOCAL_PATH); | |
| 35 | + if (filePath != null) { | |
| 36 | + File file = new File(filePath); | |
| 37 | + if (file.exists()) { | |
| 38 | + Response.ResponseBuilder response = Response.ok((Object) file); | |
| 39 | + response.header("Content-Disposition", "attachment;filename=" + String.valueOf(fileId)); //+ "." + ext); | |
| 40 | + return response.build(); | |
| 41 | + } else { | |
| 42 | + return Response.status(HttpStatus.SC_NO_CONTENT).build(); | |
| 43 | + } | |
| 44 | + } else { | |
| 45 | + return Response.status(HttpStatus.SC_NO_CONTENT).build(); | |
| 46 | + } | |
| 47 | + } | |
| 48 | +} | ... | ... |
services/Global/src/main/java/de/bht/beuthbot/attachments/AttachmentStoreBean.java
0 → 100755
| 1 | +++ a/services/Global/src/main/java/de/bht/beuthbot/attachments/AttachmentStoreBean.java | |
| 1 | +package de.bht.beuthbot.attachments; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.attachments.model.AttachmentStoreMode; | |
| 4 | +import de.bht.beuthbot.conf.Application; | |
| 5 | +import de.bht.beuthbot.conf.Configuration; | |
| 6 | +import de.bht.beuthbot.model.AttachmentType; | |
| 7 | +import org.apache.http.HttpEntity; | |
| 8 | +import org.apache.http.client.methods.CloseableHttpResponse; | |
| 9 | +import org.apache.http.client.methods.HttpGet; | |
| 10 | +import org.apache.http.impl.client.HttpClientBuilder; | |
| 11 | +import org.slf4j.Logger; | |
| 12 | +import org.slf4j.LoggerFactory; | |
| 13 | + | |
| 14 | +import javax.annotation.Resource; | |
| 15 | +import javax.ejb.Singleton; | |
| 16 | +import java.io.ByteArrayOutputStream; | |
| 17 | +import java.io.File; | |
| 18 | +import java.io.FileOutputStream; | |
| 19 | +import java.io.OutputStream; | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * @author: georg.glossmann@adesso.de, Christopher Kümmel | |
| 23 | + * Date: 26.05.17 | |
| 24 | + */ | |
| 25 | +@Singleton | |
| 26 | +public class AttachmentStoreBean implements AttachmentStore { | |
| 27 | + | |
| 28 | + /** slf4j Logger */ | |
| 29 | + private static Logger logger = LoggerFactory.getLogger(AttachmentStoreBean.class); | |
| 30 | + | |
| 31 | + /** id counter for unique id. */ | |
| 32 | + private static Long idCounter = 0L; | |
| 33 | + | |
| 34 | + /** BeuthBot Application Bean */ | |
| 35 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 36 | + private Application application; | |
| 37 | + | |
| 38 | + /** path to local attachment directory. */ | |
| 39 | + private String localPath; | |
| 40 | + | |
| 41 | + /** accessible FileURI base Path. */ | |
| 42 | + private String fileURIPath; | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * Construtor for path generation. | |
| 46 | + */ | |
| 47 | + public AttachmentStoreBean() { | |
| 48 | + localPath = application.getConfiguration(Configuration.LOCAL_ATTACHMENT_PATH); | |
| 49 | + fileURIPath = application.getConfiguration(Configuration.WEB_URL) + "/attachments/"; | |
| 50 | + // make directories | |
| 51 | + File file = new File(localPath); | |
| 52 | + try { | |
| 53 | + if (file.exists()) { | |
| 54 | + // WORKAROUND: delete old data at system start | |
| 55 | + deleteDirectory(file); | |
| 56 | + } else { | |
| 57 | + file.mkdirs(); | |
| 58 | + } | |
| 59 | + } catch (Exception e) { | |
| 60 | + logger.error("Error while deleting or creating AttachmentStore Directory.", e); | |
| 61 | + } | |
| 62 | + } | |
| 63 | + | |
| 64 | + /** | |
| 65 | + * Delete attachment directory. | |
| 66 | + * @param file directory to delete | |
| 67 | + */ | |
| 68 | + private void deleteDirectory(final File file){ | |
| 69 | + File[] directoryFiles = file.listFiles(); | |
| 70 | + for (File directoryFile : directoryFiles) { | |
| 71 | + directoryFile.delete(); | |
| 72 | + } | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * Download and store file on Server. | |
| 77 | + * @param fileURI to store on Server | |
| 78 | + * @param attachmentType for file-ending and directory | |
| 79 | + * @return generated id for specific Attachment. null if attachment isn´t an audio or voice file | |
| 80 | + */ | |
| 81 | + @Override | |
| 82 | + public Long storeAttachment(final String fileURI, final AttachmentType attachmentType) { | |
| 83 | + | |
| 84 | + Long id = ++idCounter; | |
| 85 | + | |
| 86 | + if (attachmentType == AttachmentType.AUDIO || attachmentType == AttachmentType.VOICE) { | |
| 87 | + // download file then store it locally | |
| 88 | + try { | |
| 89 | + HttpGet get = new HttpGet(fileURI); | |
| 90 | + CloseableHttpResponse execute = HttpClientBuilder.create().build().execute(get); | |
| 91 | + HttpEntity entity = execute.getEntity(); | |
| 92 | + | |
| 93 | + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); | |
| 94 | + entity.writeTo(byteArrayOutputStream); | |
| 95 | + byteArrayOutputStream.flush(); | |
| 96 | + | |
| 97 | + OutputStream outputStream = getOutputStreamByAttachmentType(attachmentType); | |
| 98 | + | |
| 99 | + byteArrayOutputStream.writeTo(outputStream); | |
| 100 | + outputStream.flush(); | |
| 101 | + byteArrayOutputStream.close(); | |
| 102 | + outputStream.close(); | |
| 103 | + | |
| 104 | + } catch (Exception e) { | |
| 105 | + logger.error("Error occurred while try to store new attachment. ", e); | |
| 106 | + } | |
| 107 | + return id; | |
| 108 | + } else { | |
| 109 | + return null; | |
| 110 | + } | |
| 111 | + } | |
| 112 | + | |
| 113 | + /** | |
| 114 | + * Store file on Server. | |
| 115 | + * @param byteArrayOutputStream to store on Server | |
| 116 | + * @param attachmentType for file-ending and directory | |
| 117 | + * @return generated id for specific Attachment. null if attachment isn´t an audio or voice file | |
| 118 | + */ | |
| 119 | + @Override | |
| 120 | + public Long storeAttachment(final ByteArrayOutputStream byteArrayOutputStream, final AttachmentType attachmentType){ | |
| 121 | + | |
| 122 | + Long id = ++idCounter; | |
| 123 | + | |
| 124 | + if (attachmentType == AttachmentType.AUDIO || attachmentType == AttachmentType.VOICE) { | |
| 125 | + // store file locally | |
| 126 | + try{ | |
| 127 | + OutputStream outputStream = getOutputStreamByAttachmentType(attachmentType); | |
| 128 | + | |
| 129 | + byteArrayOutputStream.writeTo(outputStream); | |
| 130 | + outputStream.flush(); | |
| 131 | + byteArrayOutputStream.close(); | |
| 132 | + outputStream.close(); | |
| 133 | + | |
| 134 | + } catch (Exception e) { | |
| 135 | + logger.error("Error occurred while try to store new attachment. ", e); | |
| 136 | + } | |
| 137 | + return id; | |
| 138 | + } else { | |
| 139 | + return null; | |
| 140 | + } | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * Create OutputStream from given attachmentType | |
| 145 | + * @param attachmentType OutputStreamPath for given attachmentType | |
| 146 | + * @return null if attachmentType is undefined or error thrown | |
| 147 | + */ | |
| 148 | + private OutputStream getOutputStreamByAttachmentType(final AttachmentType attachmentType) { | |
| 149 | + try { | |
| 150 | + File file; | |
| 151 | + switch (attachmentType) { | |
| 152 | + case AUDIO: | |
| 153 | + file = new File(localPath + "/audio/" + String.valueOf(idCounter) + ".mpg"); | |
| 154 | + file.getParentFile().mkdirs(); | |
| 155 | + file.createNewFile(); | |
| 156 | + return new FileOutputStream(file); | |
| 157 | + case VOICE: | |
| 158 | + file = new File(localPath + "/voice/" + String.valueOf(idCounter) + ".mpg"); | |
| 159 | + file.getParentFile().mkdirs(); | |
| 160 | + file.createNewFile(); | |
| 161 | + return new FileOutputStream(file); | |
| 162 | + //TODO: implement more cases | |
| 163 | + default: | |
| 164 | + logger.warn("Undefined case for storing a new attachment!"); | |
| 165 | + break; | |
| 166 | + } | |
| 167 | + } catch (Exception e) { | |
| 168 | + logger.error("Error while creating OutputStream on AttachmentStore.", e); | |
| 169 | + } | |
| 170 | + return null; | |
| 171 | + } | |
| 172 | + | |
| 173 | + /** | |
| 174 | + * returns Attachment with local file path | |
| 175 | + * @param attachmentID to identify file | |
| 176 | + * @param attachmentStoreMode defines the response path to the file - accessible file URI or local path | |
| 177 | + * @return null if Attachment not found | |
| 178 | + */ | |
| 179 | + @Override | |
| 180 | + public String loadAttachmentPath(final long attachmentID, final AttachmentStoreMode attachmentStoreMode) { | |
| 181 | + // find local file | |
| 182 | + String localFilePath = findFile(new File(localPath).listFiles(), attachmentID); | |
| 183 | + | |
| 184 | + if (localFilePath != null) { | |
| 185 | + if (attachmentStoreMode == AttachmentStoreMode.LOCAL_PATH) { | |
| 186 | + return localFilePath; | |
| 187 | + } else { | |
| 188 | + //TODO: implement a better way | |
| 189 | + // find AttachmentType | |
| 190 | + String[] type = localFilePath.split("/"); | |
| 191 | + switch (type[type.length - 2]) { | |
| 192 | + case "audio": | |
| 193 | + return fileURIPath + "audio/" + String.valueOf(attachmentID) + ".mpg"; | |
| 194 | + case "voice": | |
| 195 | + return fileURIPath + "voice/" + String.valueOf(attachmentID) + ".mpg"; | |
| 196 | + default: | |
| 197 | + logger.warn("AttachmentStore couldn't find requested file!"); | |
| 198 | + return null; | |
| 199 | + } | |
| 200 | + } | |
| 201 | + } else { | |
| 202 | + logger.warn("AttachmentStore couldn't find requested file!"); | |
| 203 | + return null; | |
| 204 | + } | |
| 205 | + } | |
| 206 | + | |
| 207 | + /** | |
| 208 | + * Iterate through file directory and find file | |
| 209 | + * @param files list of files to compare | |
| 210 | + * @param id of the file | |
| 211 | + * @return null if file not found | |
| 212 | + */ | |
| 213 | + private String findFile(final File[] files, final Long id) { | |
| 214 | + for (File file : files) { | |
| 215 | + if (file.isDirectory()) { | |
| 216 | + String filePath = findFile(file.listFiles(), id); | |
| 217 | + if (filePath != null) return filePath; | |
| 218 | + } else { | |
| 219 | + String name = file.getName(); | |
| 220 | + int pos = name.lastIndexOf("."); | |
| 221 | + if (pos > 0) { | |
| 222 | + name = name.substring(0, pos); | |
| 223 | + } | |
| 224 | + if (name.equals(String.valueOf(id))) { | |
| 225 | + return file.getAbsolutePath(); | |
| 226 | + } | |
| 227 | + } | |
| 228 | + } | |
| 229 | + return null; | |
| 230 | + } | |
| 231 | +} | ... | ... |
services/Global/src/main/java/de/bht/beuthbot/conf/ApplicationBean.java
0 → 100755
| 1 | +++ a/services/Global/src/main/java/de/bht/beuthbot/conf/ApplicationBean.java | |
| 1 | +package de.bht.beuthbot.conf; | |
| 2 | + | |
| 3 | + | |
| 4 | +import org.apache.commons.io.FileUtils; | |
| 5 | +import org.slf4j.Logger; | |
| 6 | +import org.slf4j.LoggerFactory; | |
| 7 | + | |
| 8 | +import javax.ejb.Stateless; | |
| 9 | +import java.io.File; | |
| 10 | +import java.io.IOException; | |
| 11 | +import java.io.InputStream; | |
| 12 | +import java.util.Properties; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * @author: georg.glossmann@adesso.de | |
| 16 | + * Date: 03.07.17 | |
| 17 | + */ | |
| 18 | +@Stateless | |
| 19 | +public class ApplicationBean implements Application { | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * Path to application configuration file on target wildfly server | |
| 23 | + */ | |
| 24 | + private static final String CONFIGURATION_PATH = "/opt/jboss/wildfly/standalone/conf/"; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * Configuration file name | |
| 28 | + */ | |
| 29 | + private static final String CONFIGURATION_FILE = "beuthbot.properties"; | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * slf4j Logger | |
| 33 | + */ | |
| 34 | + private final Logger logger = LoggerFactory.getLogger(ApplicationBean.class); | |
| 35 | + | |
| 36 | + /** | |
| 37 | + * Properties defined in conf file | |
| 38 | + */ | |
| 39 | + private Properties properties; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * Loading defined properties from conf file | |
| 43 | + * @return | |
| 44 | + */ | |
| 45 | + private Properties loadProperties() { | |
| 46 | + if (properties == null) { | |
| 47 | + this.properties = new Properties(); | |
| 48 | + File confFile = new File(CONFIGURATION_PATH + CONFIGURATION_FILE); | |
| 49 | + try (InputStream inputStream = FileUtils.openInputStream(confFile)) { | |
| 50 | + properties.load(inputStream); | |
| 51 | + } catch (IOException e) { | |
| 52 | + logger.error("Error while reading file {}", confFile.getAbsolutePath(), e); | |
| 53 | + } | |
| 54 | + } | |
| 55 | + return properties; | |
| 56 | + } | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * Gets the value of configured property | |
| 60 | + * | |
| 61 | + * @param property enum of defined property in configuration file | |
| 62 | + * @return String of configured value | |
| 63 | + */ | |
| 64 | + public String getConfiguration(final Configuration property) { | |
| 65 | + return loadProperties().getProperty(property.name()); | |
| 66 | + } | |
| 67 | +} | ... | ... |
services/Global/src/main/java/de/bht/beuthbot/jms/ProcessQueueBean.java
0 → 100755
| 1 | +++ a/services/Global/src/main/java/de/bht/beuthbot/jms/ProcessQueueBean.java | |
| 1 | +package de.bht.beuthbot.jms; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.conf.Application; | |
| 4 | +import de.bht.beuthbot.conf.Configuration; | |
| 5 | +import de.bht.beuthbot.model.Attachment; | |
| 6 | +import de.bht.beuthbot.model.AttachmentType; | |
| 7 | +import org.slf4j.Logger; | |
| 8 | +import org.slf4j.LoggerFactory; | |
| 9 | + | |
| 10 | +import javax.annotation.PostConstruct; | |
| 11 | +import javax.annotation.Resource; | |
| 12 | +import javax.ejb.Stateful; | |
| 13 | +import javax.enterprise.context.ApplicationScoped; | |
| 14 | +import javax.jms.ConnectionFactory; | |
| 15 | +import javax.jms.JMSContext; | |
| 16 | +import javax.jms.Message; | |
| 17 | +import javax.jms.Topic; | |
| 18 | + | |
| 19 | +/** | |
| 20 | + * @author: georg.parkinson@adesso.de | |
| 21 | + * Date: 22.05.17 | |
| 22 | + */ | |
| 23 | +@Stateful | |
| 24 | +@ApplicationScoped | |
| 25 | +public class ProcessQueueBean implements ProcessQueue { | |
| 26 | + | |
| 27 | + private final Logger logger = LoggerFactory.getLogger(ProcessQueueBean.class); | |
| 28 | + | |
| 29 | + @Resource(lookup = "java:/jboss/DefaultJMSConnectionFactory") | |
| 30 | + private ConnectionFactory connectionFactory; | |
| 31 | + | |
| 32 | + @Resource(lookup = "java:/jms/messages/inbox") | |
| 33 | + private Topic topic; | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * BeuthBot Application Bean | |
| 37 | + */ | |
| 38 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 39 | + private Application application; | |
| 40 | + | |
| 41 | + private JMSContext context; | |
| 42 | + | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * Initialize the JMS context. | |
| 46 | + */ | |
| 47 | + @PostConstruct | |
| 48 | + public void init() { | |
| 49 | + context = connectionFactory.createContext(); | |
| 50 | + } | |
| 51 | + | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public void route(final TaskMessage taskMessage) { | |
| 55 | + Message message = context.createObjectMessage(taskMessage); | |
| 56 | + try { | |
| 57 | + switch (taskMessage.getTarget()) { | |
| 58 | + case NTSP: | |
| 59 | + if (!taskMessage.hasAttachments()) { | |
| 60 | + message.setStringProperty("NLP", "nlp"); | |
| 61 | + if ("on".equals(application.getConfiguration(Configuration.APIAI_UNIT_ON))) { | |
| 62 | + message.setStringProperty("APIAI", "apiai"); | |
| 63 | + } | |
| 64 | + if ("on".equals(application.getConfiguration(Configuration.RASA_UNIT_ON))) { | |
| 65 | + message.setStringProperty("RASA", "rasa"); | |
| 66 | + } | |
| 67 | + } else { | |
| 68 | + Attachment attachment = taskMessage.getAttachments().get(0); | |
| 69 | + if (attachment.getAttachmentType() == AttachmentType.AUDIO || attachment.getAttachmentType() == AttachmentType.VOICE) { | |
| 70 | + if ("on".equals(application.getConfiguration(Configuration.BING_UNIT_ON))) { | |
| 71 | + message.setStringProperty("BingConnector", "in"); | |
| 72 | + } | |
| 73 | + } else { | |
| 74 | + logger.warn("Unsupported attachment! Reroute message to {}.\nMessage: {}", Target.MAINBOT, taskMessage); | |
| 75 | + route(new TaskMessage(taskMessage, Target.MAINBOT)); | |
| 76 | + } | |
| 77 | + } | |
| 78 | + break; | |
| 79 | + case MAINBOT: | |
| 80 | + if ("on".equals(application.getConfiguration(Configuration.MAINBOT_UNIT_ON))) { | |
| 81 | + message.setStringProperty("DROOLS", "drools"); | |
| 82 | + } | |
| 83 | + break; | |
| 84 | + case MESSENGER: | |
| 85 | + switch (taskMessage.getMessenger()) { | |
| 86 | + case TELEGRAM: | |
| 87 | + if ("on".equals(application.getConfiguration(Configuration.TELEGRAM_UNIT_ON))) { | |
| 88 | + message.setStringProperty("TELEGRAM", "telegram"); | |
| 89 | + } | |
| 90 | + break; | |
| 91 | + case FACEBOOK: | |
| 92 | + if ("on".equals(application.getConfiguration(Configuration.FACEBOOK_UNIT_ON))) { | |
| 93 | + message.setStringProperty("FACEBOOK", "facebook"); | |
| 94 | + } | |
| 95 | + break; | |
| 96 | + default: | |
| 97 | + logger.error("No messenger assigned! Could not route internal message.\nMessage: {}", taskMessage); | |
| 98 | + } | |
| 99 | + break; | |
| 100 | + default: | |
| 101 | + logger.error("Target unknown! Could not route internal message.\nMessage: {}", taskMessage); | |
| 102 | + return; | |
| 103 | + } | |
| 104 | + } catch (Exception exception) { | |
| 105 | + logger.error("Could not route message.\nMessage: {}", taskMessage, exception); | |
| 106 | + return; | |
| 107 | + } | |
| 108 | + context.createProducer().send(topic, message); | |
| 109 | + } | |
| 110 | +} | ... | ... |
services/Global/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/Global/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/Global/src/main/webapp/WEB-INF/jboss-web.xml
0 → 100755
services/LoggingStatistics/build.gradle
0 → 100755
| 1 | +++ a/services/LoggingStatistics/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | +} | |
| 8 | + | |
| 9 | +dependencies { | |
| 10 | + | |
| 11 | + compile project(':services:Common'), | |
| 12 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final" | |
| 13 | + | |
| 14 | + providedCompile "org.slf4j:slf4j-api:1.7.25" | |
| 15 | + | |
| 16 | + testCompile "org.jboss.arquillian.junit:arquillian-junit-container:1.1.13.Final", | |
| 17 | + "junit:junit:4.12" | |
| 18 | + | |
| 19 | + testRuntime "org.wildfly.arquillian:wildfly-arquillian-container-remote:2.0.2.Final", | |
| 20 | + "org.slf4j:slf4j-simple:1.7.25" | |
| 21 | +} | |
| 22 | + | |
| 23 | +sourceCompatibility = 1.8 | |
| 24 | + | |
| 25 | +war { | |
| 26 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 27 | + archiveName "logging.war" | |
| 28 | +} | |
| 0 | 29 | \ No newline at end of file | ... | ... |
services/LoggingStatistics/src/main/java/de.bht.beuthbot.logging/ProcessQueueLogger.java
0 → 100755
| 1 | +++ a/services/LoggingStatistics/src/main/java/de.bht.beuthbot.logging/ProcessQueueLogger.java | |
| 1 | +package de.bht.beuthbot.logging; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 4 | +import org.slf4j.Logger; | |
| 5 | +import org.slf4j.LoggerFactory; | |
| 6 | + | |
| 7 | +import javax.ejb.ActivationConfigProperty; | |
| 8 | +import javax.ejb.MessageDriven; | |
| 9 | +import javax.jms.JMSException; | |
| 10 | +import javax.jms.Message; | |
| 11 | +import javax.jms.MessageListener; | |
| 12 | +import javax.jms.TextMessage; | |
| 13 | +import java.util.Enumeration; | |
| 14 | +import java.util.HashMap; | |
| 15 | +import java.util.Map; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * @author: georg.parkinson@adesso.de | |
| 19 | + * Date: 22.05.17 | |
| 20 | + */ | |
| 21 | +@MessageDriven( | |
| 22 | + name = "InboxLogger", | |
| 23 | + activationConfig = { | |
| 24 | + @ActivationConfigProperty( | |
| 25 | + propertyName = "destinationType", | |
| 26 | + propertyValue = "javax.jms.Topic"), | |
| 27 | + @ActivationConfigProperty( | |
| 28 | + propertyName = "destination", | |
| 29 | + propertyValue = "jms/messages/inbox"), | |
| 30 | + @ActivationConfigProperty( | |
| 31 | + propertyName = "maxSession", propertyValue = "1") | |
| 32 | + } | |
| 33 | +) | |
| 34 | +public class ProcessQueueLogger implements MessageListener { | |
| 35 | + | |
| 36 | + private Logger logger = LoggerFactory.getLogger(ProcessQueueLogger.class); | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public void onMessage(final Message message) { | |
| 40 | + try { | |
| 41 | + Map<String, String> customMessageHeaders = new HashMap<>(); | |
| 42 | + Enumeration propertyNames = message.getPropertyNames(); | |
| 43 | + while (propertyNames.hasMoreElements()) { | |
| 44 | + String propertyName = propertyNames.nextElement().toString(); | |
| 45 | + if (!propertyName.startsWith("JMS")) { | |
| 46 | + customMessageHeaders.put(propertyName, message.getStringProperty(propertyName)); | |
| 47 | + } | |
| 48 | + } | |
| 49 | + logger.info("Message [{}] with header {}: {}", message.getJMSMessageID(), customMessageHeaders, message.getBody(TaskMessage.class)); | |
| 50 | + } catch (JMSException e) { | |
| 51 | + logger.error("Error while interpreting message.", e); | |
| 52 | + } | |
| 53 | + } | |
| 54 | +} | ... | ... |
services/LoggingStatistics/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/LoggingStatistics/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/MainBot/build.gradle
0 → 100755
| 1 | +++ a/services/MainBot/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | + maven { | |
| 8 | + url 'https://repository.jboss.org/nexus/content/groups/public/' | |
| 9 | + } | |
| 10 | +} | |
| 11 | + | |
| 12 | +dependencies { | |
| 13 | + compile project(':services:Common'), | |
| 14 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 15 | + "com.google.code.gson:gson:2.8.1", | |
| 16 | + "org.drools:drools-compiler:7.0.0.Final", | |
| 17 | + "org.jsoup:jsoup:1.10.2", | |
| 18 | + "net.jodah:expiringmap:0.5.8" | |
| 19 | + | |
| 20 | + providedCompile "org.slf4j:slf4j-api:1.7.25" | |
| 21 | +} | |
| 22 | + | |
| 23 | +sourceCompatibility = 1.8 | |
| 24 | + | |
| 25 | +war { | |
| 26 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 27 | + archiveName "mainbot.war" | |
| 28 | +} | |
| 0 | 29 | \ No newline at end of file | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/canteen/Parser.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/canteen/Parser.java | |
| 1 | +package de.bht.beuthbot.canteen; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.canteen.model.*; | |
| 4 | +import net.jodah.expiringmap.ExpiringMap; | |
| 5 | +import org.jsoup.Jsoup; | |
| 6 | +import org.jsoup.nodes.Document; | |
| 7 | +import org.jsoup.nodes.Element; | |
| 8 | +import org.jsoup.select.Elements; | |
| 9 | +import org.slf4j.Logger; | |
| 10 | +import org.slf4j.LoggerFactory; | |
| 11 | + | |
| 12 | +import java.io.IOException; | |
| 13 | +import java.time.LocalDate; | |
| 14 | +import java.util.*; | |
| 15 | +import java.util.concurrent.TimeUnit; | |
| 16 | +import java.util.regex.Matcher; | |
| 17 | +import java.util.regex.Pattern; | |
| 18 | + | |
| 19 | +/** | |
| 20 | + * This class parses the current webpage of the beuth canteen. | |
| 21 | + * Created by sJantzen on 03.07.2017. | |
| 22 | + */ | |
| 23 | +public class Parser { | |
| 24 | + | |
| 25 | + private Logger logger = LoggerFactory.getLogger(Parser.class); | |
| 26 | + | |
| 27 | + private static final Pattern DATE_PATTERN = Pattern.compile(".*([0-9]{4}-[0-9]{2}-[0-9]{2}).*"); | |
| 28 | + private static final Pattern ICON_PATTERN = Pattern.compile(".*/([0-9]{1,2})\\.png"); | |
| 29 | + | |
| 30 | + private static final String CANTEENS_URL = "https://www.stw.berlin/xhr/speiseplan-und-standortdaten.html"; | |
| 31 | + private static final String DAYS_DISHES_URL = "https://www.stw.berlin/xhr/speiseplan-wochentag.html"; | |
| 32 | + private static final String PARAM_RESOURCE_ID_NAME = "resources_id"; | |
| 33 | + private static final String PARAM_RESOURCE_ID_VALUE = "527"; | |
| 34 | + private static final String PARAM_DATE_NAME = "date"; | |
| 35 | + | |
| 36 | + private static final String OPENING_HOURS = "Mo. - Fr. | 09:00 - 14:30"; | |
| 37 | + | |
| 38 | + private static final String CURRENT_DATA_KEY = "KEY"; | |
| 39 | + private static Map<String, CanteenData> currentCanteenData; | |
| 40 | + | |
| 41 | + static { | |
| 42 | + currentCanteenData = ExpiringMap.builder().expiration(1, TimeUnit.DAYS) | |
| 43 | + .build(); | |
| 44 | + } | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * Creates new CanteenData with all dishes of the current and next week by parsing | |
| 48 | + * the canteen url of the beuth university. | |
| 49 | + * @return | |
| 50 | + */ | |
| 51 | + public CanteenData parse() { | |
| 52 | + | |
| 53 | + if(currentCanteenData.containsKey(CURRENT_DATA_KEY)){ | |
| 54 | + logger.debug("Canteen Data already exists in Map."); | |
| 55 | + return currentCanteenData.get(CURRENT_DATA_KEY); | |
| 56 | + } | |
| 57 | + | |
| 58 | + String canteenName = ""; | |
| 59 | + | |
| 60 | + List<Dish> dishes = new ArrayList<>(); | |
| 61 | + | |
| 62 | + try { | |
| 63 | + Document doc = Jsoup.connect(CANTEENS_URL).data(PARAM_RESOURCE_ID_NAME, PARAM_RESOURCE_ID_VALUE).userAgent("Mozilla").post(); | |
| 64 | + | |
| 65 | + Elements canteenNameEle = doc.select("#listboxEinrichtungen option[value=" + PARAM_RESOURCE_ID_VALUE + "]"); | |
| 66 | + if(canteenNameEle != null && canteenNameEle.size() > 0) { | |
| 67 | + canteenName = canteenNameEle.first().text(); | |
| 68 | + } | |
| 69 | + | |
| 70 | + /* | |
| 71 | + * This is a list with dates of the current and next week. | |
| 72 | + * First we get all dates and than we will iterate over these dates, | |
| 73 | + * to get all dishes of the current and next week. | |
| 74 | + */ | |
| 75 | + List<String> dates = new ArrayList<>(); | |
| 76 | + | |
| 77 | + // Get all dates of the current week. | |
| 78 | + dates.addAll(getDates(doc)); | |
| 79 | + | |
| 80 | + /* | |
| 81 | + * Loop all days. | |
| 82 | + */ | |
| 83 | + Map<String, String> params = new HashMap<>(); | |
| 84 | + params.put(PARAM_RESOURCE_ID_NAME, PARAM_RESOURCE_ID_VALUE); | |
| 85 | + for (String day : dates) { | |
| 86 | + | |
| 87 | + params.put(PARAM_DATE_NAME, day); | |
| 88 | + | |
| 89 | + try { | |
| 90 | + doc = Jsoup.connect(DAYS_DISHES_URL).data(params).userAgent("Mozilla").post(); | |
| 91 | + Thread.sleep(1000); | |
| 92 | + } catch (Exception e) { | |
| 93 | + logger.debug("Exception while connecting to site: " + DAYS_DISHES_URL, e); | |
| 94 | + continue; | |
| 95 | + } | |
| 96 | + | |
| 97 | + /* | |
| 98 | + * Loop all dish categories of the current page. | |
| 99 | + */ | |
| 100 | + Elements dishCategories = doc.select("div.splGroupWrapper"); | |
| 101 | + | |
| 102 | + for (Element dishCategory : dishCategories) { | |
| 103 | + | |
| 104 | + /* | |
| 105 | + * Get name of the current dishCategory. | |
| 106 | + */ | |
| 107 | + Elements strCategories = dishCategory.select("div.splGroup"); | |
| 108 | + DishCategory category = null; | |
| 109 | + if(strCategories != null && strCategories.size() > 0 ) { | |
| 110 | + String strCategory = dishCategory.select("div.splGroup").first().text(); | |
| 111 | + category = DishCategory.getDishCategory(strCategory); | |
| 112 | + } | |
| 113 | + | |
| 114 | + /* | |
| 115 | + * Loop all dishes of the current category. | |
| 116 | + */ | |
| 117 | + Elements categoryDishes = dishCategory.select("div.splMeal"); | |
| 118 | + | |
| 119 | + for (Element categoryDish : categoryDishes) { | |
| 120 | + | |
| 121 | + Dish dish = new Dish(); | |
| 122 | + | |
| 123 | + dish.setDate(LocalDate.parse(day)); | |
| 124 | + dish.setDishCategory(category); | |
| 125 | + | |
| 126 | + /* | |
| 127 | + * Get markings for dish. | |
| 128 | + */ | |
| 129 | + if(categoryDish.attr("lang") != null) { | |
| 130 | + dish.getMarkings().addAll(Arrays.asList(categoryDish.attr("lang").trim().split(", "))); | |
| 131 | + } | |
| 132 | + | |
| 133 | + /* | |
| 134 | + * Get price string. | |
| 135 | + */ | |
| 136 | + Element strPrice = categoryDish.select("div.text-right").first(); | |
| 137 | + dish.setPrice(strPrice.text()); | |
| 138 | + | |
| 139 | + // check if 3 different prices are available or just one price for all | |
| 140 | + /* | |
| 141 | + if(!"".equals(dish.getPrice())) { | |
| 142 | + if (dish.getPrice().contains("/")) { | |
| 143 | + // 3 different prices | |
| 144 | + String[] prices = dish.getPrice().replace("€", "").replace("\\?", "").replace(",",".").trim().split("/"); | |
| 145 | + dish.setPriceStudent(new BigDecimal(prices[0])); | |
| 146 | + dish.setPriceEmployee(new BigDecimal(prices[1])); | |
| 147 | + dish.setPriceGuest(new BigDecimal(prices[2])); | |
| 148 | + } | |
| 149 | + else { | |
| 150 | + // only 1 price | |
| 151 | + logger.info("1: " + dish.getPrice()); | |
| 152 | + logger.info("1: " + dish.getPrice().replace("€", "")); | |
| 153 | + logger.info("1: " + dish.getPrice().replace("€", "").replace("\\?", "")); | |
| 154 | + logger.info("1: " + dish.getPrice().replace("€", "").replace("\\?", "").replace(",",".")); | |
| 155 | + logger.info("1: " + dish.getPrice().replace("€", "").replace("\\?", "").replace(",",".").trim()); | |
| 156 | + BigDecimal price = new BigDecimal(dish.getPrice().replace("€", "").replace("\\?", "").replace(",",".").trim()); | |
| 157 | + dish.setPriceStudent(price); | |
| 158 | + dish.setPriceEmployee(price); | |
| 159 | + dish.setPriceGuest(price); | |
| 160 | + } | |
| 161 | + } | |
| 162 | + */ | |
| 163 | + | |
| 164 | + /* | |
| 165 | + * Get name of dish. | |
| 166 | + */ | |
| 167 | + Element name = categoryDish.select("span.bold").first(); | |
| 168 | + dish.setName(name.text()); | |
| 169 | + | |
| 170 | + /* | |
| 171 | + * Loop icons for traffic lights and dish types. | |
| 172 | + */ | |
| 173 | + Elements icons = categoryDish.select("img.splIcon"); | |
| 174 | + | |
| 175 | + for (Element icon : icons) { | |
| 176 | + | |
| 177 | + /* | |
| 178 | + * Check if and set traffic light. | |
| 179 | + */ | |
| 180 | + if(icon.attr("src").contains("ampel")) { | |
| 181 | + if(icon.attr("src").contains("ampel_gelb")) { | |
| 182 | + dish.setTrafficLight(TrafficLight.YELLOW); | |
| 183 | + } else if (icon.attr("src").contains("ampel_gruen")){ | |
| 184 | + dish.setTrafficLight(TrafficLight.GREEN); | |
| 185 | + } else if (icon.attr("src").contains("ampel_rot")) { | |
| 186 | + dish.setTrafficLight(TrafficLight.RED); | |
| 187 | + } | |
| 188 | + } else { | |
| 189 | + /* | |
| 190 | + * Check for dishTypes and set them. | |
| 191 | + */ | |
| 192 | + Matcher m = ICON_PATTERN.matcher(icon.attr("src")); | |
| 193 | + while ( m.find() ) { | |
| 194 | + if(DishType.getDishTypeByNumber(m.group(1)) != null) { | |
| 195 | + dish.getDishTypes().add(DishType.getDishTypeByNumber(m.group(1))); | |
| 196 | + } | |
| 197 | + } | |
| 198 | + } | |
| 199 | + } | |
| 200 | + dishes.add(dish); | |
| 201 | + } | |
| 202 | + } | |
| 203 | + } | |
| 204 | + } catch (IOException e) { | |
| 205 | + logger.info("Got Error while parsing site: " + CANTEENS_URL, e); | |
| 206 | + } | |
| 207 | + | |
| 208 | + currentCanteenData.put(CURRENT_DATA_KEY, new CanteenData(canteenName, OPENING_HOURS, "", dishes)); | |
| 209 | + | |
| 210 | + return currentCanteenData.get(CURRENT_DATA_KEY); | |
| 211 | + } | |
| 212 | + | |
| 213 | + /** | |
| 214 | + * This method returns a string list of dates for all possible days with dishes | |
| 215 | + * for the current shown week. | |
| 216 | + * @param doc | |
| 217 | + * @return | |
| 218 | + */ | |
| 219 | + private static List<String> getDates(Document doc) { | |
| 220 | + List<String> dates = new ArrayList<>(); | |
| 221 | + Elements canteenLinks = doc.select("li[id^=spltag]"); | |
| 222 | + for(Element canteenLink : canteenLinks) { | |
| 223 | + Matcher m = DATE_PATTERN.matcher(canteenLink.attr("onClick")); | |
| 224 | + while ( m.find() ) { | |
| 225 | + dates.add(m.group(1)); | |
| 226 | + // Get date for the same day of the next week. | |
| 227 | + LocalDate ld = LocalDate.parse(m.group(1)); | |
| 228 | + ld = ld.plusDays(7); | |
| 229 | + dates.add(ld.toString()); | |
| 230 | + } | |
| 231 | + } | |
| 232 | + return dates; | |
| 233 | + } | |
| 234 | + | |
| 235 | +} | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/CanteenData.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/CanteenData.java | |
| 1 | +package de.bht.beuthbot.canteen.model; | |
| 2 | + | |
| 3 | +import org.slf4j.Logger; | |
| 4 | +import org.slf4j.LoggerFactory; | |
| 5 | + | |
| 6 | +import java.time.LocalDate; | |
| 7 | +import java.util.List; | |
| 8 | +import java.util.stream.Collectors; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * This class represents all data of dishes for the current and the next | |
| 12 | + * week of the canteen of the beuth university. | |
| 13 | + * Created by sJantzen on 11.06.2017. | |
| 14 | + */ | |
| 15 | +public class CanteenData { | |
| 16 | + | |
| 17 | + private Logger logger = LoggerFactory.getLogger(CanteenData.class); | |
| 18 | + | |
| 19 | + private String locationName; | |
| 20 | + private String openingHoursKitchen; | |
| 21 | + private String openingHours; | |
| 22 | + private List<Dish> dishes; | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * Default constructor. | |
| 26 | + */ | |
| 27 | + private CanteenData(){ | |
| 28 | + } | |
| 29 | + | |
| 30 | + /** | |
| 31 | + * Full constructor. | |
| 32 | + * @param locationName | |
| 33 | + * @param openingHoursKitchen | |
| 34 | + * @param openingHours | |
| 35 | + * @param dishes | |
| 36 | + */ | |
| 37 | + public CanteenData(final String locationName, final String openingHoursKitchen, final String openingHours, final List<Dish> dishes){ | |
| 38 | + this.locationName = locationName; | |
| 39 | + this.openingHoursKitchen = openingHoursKitchen; | |
| 40 | + this.openingHours = openingHours; | |
| 41 | + this.dishes = dishes; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public final String getLocationName() { | |
| 45 | + return locationName; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public final void setLocationName(final String locationName) { | |
| 49 | + this.locationName = locationName; | |
| 50 | + } | |
| 51 | + | |
| 52 | + public final String getOpeningHoursKitchen() { | |
| 53 | + return openingHoursKitchen; | |
| 54 | + } | |
| 55 | + | |
| 56 | + public final void setOpeningHoursKitchen(final String openingHoursKitchen) { | |
| 57 | + this.openingHoursKitchen = openingHoursKitchen; | |
| 58 | + } | |
| 59 | + | |
| 60 | + public final String getOpeningHours() { | |
| 61 | + return openingHours; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public final void setOpeningHours(final String openingHours) { | |
| 65 | + this.openingHours = openingHours; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public final List<Dish> getDishes() { | |
| 69 | + return dishes; | |
| 70 | + } | |
| 71 | + | |
| 72 | + public final void setDishes(final List<Dish> dishes) { | |
| 73 | + this.dishes = dishes; | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * Returns all dishes, matching the given parameters. | |
| 78 | + * @param pDate if you wish to get the dishes of the given date | |
| 79 | + * @param pHealthy gets all dishes having the given traffic light color | |
| 80 | + * @param pDishType gets dishes, containing all given dishTypes | |
| 81 | + * @param pMarkings gets dishes, containing all given markings | |
| 82 | + * @return | |
| 83 | + */ | |
| 84 | + public final List<Dish> getDishesFiltered(final String pDate, final String pHealthy, final String pDishType, | |
| 85 | + final String pMarkings, final String pDishCategory) { | |
| 86 | + | |
| 87 | + final LocalDate date = ("tomorrow".equals(pDate) ? LocalDate.now().plusDays(1) : LocalDate.now()); | |
| 88 | + | |
| 89 | + final TrafficLight trafficLight = (pHealthy != null && !"".equals(pHealthy) ? TrafficLight.getTrafficLight(pHealthy): null); | |
| 90 | + | |
| 91 | + final DishType dishType = (pDishType != null && !"".equals(pDishType) ? DishType.getDishTypeByName(pDishType) : null); | |
| 92 | + | |
| 93 | + final DishCategory dishCategory = (pDishCategory != null && !"".equals(pDishCategory) ? DishCategory.getDishCategory(pDishCategory) : null); | |
| 94 | + | |
| 95 | + //final List<String> markings = (pMarkings != null && !"".equals(pMarkings) ? Arrays.asList(pMarkings.split(",")) : null); | |
| 96 | + | |
| 97 | + /* | |
| 98 | + * TODO man könnte noch Suchmodi hinzufügen, also so etwas wie: | |
| 99 | + * Ein Gericht muss ALLE types enthalten | |
| 100 | + * Ein Gericht muss mindestens EINEN enthalten | |
| 101 | + * Ein Gericht darf KEINEN von beiden enthalten | |
| 102 | + */ | |
| 103 | + | |
| 104 | + return dishes.stream().filter(dish -> (date.equals(dish.getDate()))) | |
| 105 | + .filter(dish -> (trafficLight == null || trafficLight.equals(dish.getTrafficLight()))) | |
| 106 | + .filter(dish -> (dishType == null || dish.getDishTypes().contains(dishType))) | |
| 107 | + .filter(dish -> (dishCategory == null || dish.getDishCategory().equals(dishCategory))) | |
| 108 | + .collect(Collectors.toList()); | |
| 109 | + } | |
| 110 | + | |
| 111 | + /** | |
| 112 | + * Returns all dishes, matching the given parameters. | |
| 113 | + * @param pDate if you wish to get the dishes of the given date | |
| 114 | + * @param pHealthy gets all dishes having the given traffic light color | |
| 115 | + * @param pDishType gets dishes, containing all given dishTypes | |
| 116 | + * @param pMarkings gets dishes, containing all given markings | |
| 117 | + * @return | |
| 118 | + */ | |
| 119 | + public final String getDishesFilteredAsString(final String pDate, final String pHealthy, final String pDishType, | |
| 120 | + final String pMarkings, final String pDishCategory) { | |
| 121 | + | |
| 122 | + List<Dish> rv = getDishesFiltered(pDate, pHealthy, pDishType, pMarkings, pDishCategory); | |
| 123 | + | |
| 124 | + StringBuilder sb = new StringBuilder(); | |
| 125 | + for(Dish dish : rv) { | |
| 126 | + sb.append(dish.toString()); | |
| 127 | + } | |
| 128 | + | |
| 129 | + return sb.toString(); | |
| 130 | + } | |
| 131 | + | |
| 132 | + /** | |
| 133 | + * Returns all dishes of the given date. | |
| 134 | + * @param date | |
| 135 | + * @return | |
| 136 | + */ | |
| 137 | + public final List<Dish> getDishesByDate(final String date) { | |
| 138 | + return getDishesFiltered(date, null, null, null, null); | |
| 139 | + } | |
| 140 | + | |
| 141 | + /** | |
| 142 | + * Returns a list of dishes with the given dishTypes. | |
| 143 | + * @param dishTypes | |
| 144 | + * @return | |
| 145 | + */ | |
| 146 | + public final List<Dish> getDishesByDishType(final String dishTypes) { | |
| 147 | + return getDishesFiltered(null, null, dishTypes, null, null); | |
| 148 | + } | |
| 149 | + | |
| 150 | + /** | |
| 151 | + * Returns a list of dishes matching the given trafficLight. | |
| 152 | + * @param trafficLight | |
| 153 | + * @return | |
| 154 | + */ | |
| 155 | + public final List<Dish> getDishesByTrafficLight(final String trafficLight) { | |
| 156 | + return getDishesFiltered(null, trafficLight, null, null, null); | |
| 157 | + } | |
| 158 | + | |
| 159 | + /** | |
| 160 | + * Returns a list of dishes with the given markings. | |
| 161 | + * @param markings | |
| 162 | + * @return | |
| 163 | + */ | |
| 164 | + public final List<Dish> getDishesByMarkings(final String markings) { | |
| 165 | + return getDishesFiltered(null, null, null, markings, null); | |
| 166 | + } | |
| 167 | + | |
| 168 | + /** | |
| 169 | + * Returns a list of dishes with the given dishCategory. | |
| 170 | + * @param dishCategory | |
| 171 | + * @return | |
| 172 | + */ | |
| 173 | + public final List<Dish> getDishesByDishCategory(final String dishCategory) { | |
| 174 | + return getDishesFiltered(null, null, null, null, dishCategory); | |
| 175 | + } | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * Returns the price of the requested dish. | |
| 179 | + * @param dishName | |
| 180 | + * @returns price or default message, if no dish with the given name was found. | |
| 181 | + */ | |
| 182 | + public final String showPriceOfDish(final String dishName){ | |
| 183 | + | |
| 184 | + for(Dish dish : dishes){ | |
| 185 | + if(dish.getName().toLowerCase().contains(dishName.toLowerCase())) { | |
| 186 | + return dish.showPrice(); | |
| 187 | + } | |
| 188 | + } | |
| 189 | + return "Leider konnte ich das gewünschte Gericht nicht finden."; | |
| 190 | + } | |
| 191 | + | |
| 192 | + | |
| 193 | + public final String toString(){ | |
| 194 | + StringBuilder sb = new StringBuilder(); | |
| 195 | + sb.append("Location: " + locationName).append("\n"); | |
| 196 | + sb.append("Opening hours kitchen: " + openingHoursKitchen).append("\n"); | |
| 197 | + sb.append("Opening hours: " + openingHours).append("\n"); | |
| 198 | + sb.append("Dishes:").append("\n"); | |
| 199 | + for(Dish dish : dishes){ | |
| 200 | + sb.append(dish.toString()).append("\n"); | |
| 201 | + } | |
| 202 | + return sb.toString(); | |
| 203 | + } | |
| 204 | +} | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/Dish.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/Dish.java | |
| 1 | +package de.bht.beuthbot.canteen.model; | |
| 2 | + | |
| 3 | +import java.math.BigDecimal; | |
| 4 | +import java.time.LocalDate; | |
| 5 | +import java.time.format.DateTimeFormatter; | |
| 6 | +import java.util.ArrayList; | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * Created by sJantzen on 11.06.2017. | |
| 11 | + */ | |
| 12 | +public class Dish { | |
| 13 | + | |
| 14 | + private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd.MM.yyyy"); | |
| 15 | + | |
| 16 | + private String name; | |
| 17 | + private LocalDate date; | |
| 18 | + private String price; | |
| 19 | + private BigDecimal priceStudent; | |
| 20 | + private BigDecimal priceEmployee; | |
| 21 | + private BigDecimal priceGuest; | |
| 22 | + private TrafficLight trafficLight; | |
| 23 | + private List<DishType> dishTypes; | |
| 24 | + private List<String> markings; | |
| 25 | + private DishCategory dishCategory; | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * Default constructor. | |
| 29 | + */ | |
| 30 | + public Dish(){ | |
| 31 | + dishTypes = new ArrayList<>(); | |
| 32 | + markings = new ArrayList<>(); | |
| 33 | + } | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * Full constructor. | |
| 37 | + * @param name | |
| 38 | + * @param date | |
| 39 | + * @param price | |
| 40 | + * @param priceStudent | |
| 41 | + * @param priceEmployee | |
| 42 | + * @param priceGuest | |
| 43 | + * @param trafficLight | |
| 44 | + * @param dishTypes | |
| 45 | + * @param markings | |
| 46 | + * @param dishCategory | |
| 47 | + */ | |
| 48 | + public Dish(final String name, final LocalDate date, final String price, final BigDecimal priceStudent, final BigDecimal priceEmployee, | |
| 49 | + final BigDecimal priceGuest, final TrafficLight trafficLight, final List<DishType> dishTypes, | |
| 50 | + final List<String> markings, final DishCategory dishCategory){ | |
| 51 | + this.name = name; | |
| 52 | + this.date = date; | |
| 53 | + this.price = price; | |
| 54 | + this.priceStudent = priceStudent; | |
| 55 | + this.priceEmployee = priceEmployee; | |
| 56 | + this.priceGuest = priceGuest; | |
| 57 | + this.trafficLight = trafficLight; | |
| 58 | + this.dishTypes = dishTypes; | |
| 59 | + this.markings = markings; | |
| 60 | + this.dishCategory = dishCategory; | |
| 61 | + } | |
| 62 | + | |
| 63 | + public final String getName() { | |
| 64 | + return name; | |
| 65 | + } | |
| 66 | + | |
| 67 | + public final void setName(final String name) { | |
| 68 | + this.name = name; | |
| 69 | + } | |
| 70 | + | |
| 71 | + public final String getPrice() { | |
| 72 | + return price; | |
| 73 | + } | |
| 74 | + | |
| 75 | + public final void setPrice(final String price) { | |
| 76 | + this.price = price; | |
| 77 | + } | |
| 78 | + | |
| 79 | + public final TrafficLight getTrafficLight() { | |
| 80 | + return trafficLight; | |
| 81 | + } | |
| 82 | + | |
| 83 | + public final void setTrafficLight(final TrafficLight trafficLight) { | |
| 84 | + this.trafficLight = trafficLight; | |
| 85 | + } | |
| 86 | + | |
| 87 | + public final List<DishType> getDishTypes() { | |
| 88 | + return dishTypes; | |
| 89 | + } | |
| 90 | + | |
| 91 | + public final void setDishTypes(final List<DishType> dishTypes) { | |
| 92 | + this.dishTypes = dishTypes; | |
| 93 | + } | |
| 94 | + | |
| 95 | + public final List<String> getMarkings() { | |
| 96 | + return markings; | |
| 97 | + } | |
| 98 | + | |
| 99 | + public final void setMarkings(final List<String> markings) { | |
| 100 | + this.markings = markings; | |
| 101 | + } | |
| 102 | + | |
| 103 | + public final DishCategory getDishCategory() { | |
| 104 | + return dishCategory; | |
| 105 | + } | |
| 106 | + | |
| 107 | + public final void setDishCategory(final DishCategory dishCategory) { | |
| 108 | + this.dishCategory = dishCategory; | |
| 109 | + } | |
| 110 | + | |
| 111 | + public final LocalDate getDate() { | |
| 112 | + return date; | |
| 113 | + } | |
| 114 | + | |
| 115 | + public final void setDate(final LocalDate date) { | |
| 116 | + this.date = date; | |
| 117 | + } | |
| 118 | + | |
| 119 | + public final BigDecimal getPriceStudent() { | |
| 120 | + return priceStudent; | |
| 121 | + } | |
| 122 | + | |
| 123 | + public final void setPriceStudent(final BigDecimal priceStudent) { | |
| 124 | + this.priceStudent = priceStudent; | |
| 125 | + } | |
| 126 | + | |
| 127 | + public final BigDecimal getPriceEmployee() { | |
| 128 | + return priceEmployee; | |
| 129 | + } | |
| 130 | + | |
| 131 | + public final void setPriceEmployee(final BigDecimal priceEmployee) { | |
| 132 | + this.priceEmployee = priceEmployee; | |
| 133 | + } | |
| 134 | + | |
| 135 | + public final BigDecimal getPriceGuest() { | |
| 136 | + return priceGuest; | |
| 137 | + } | |
| 138 | + | |
| 139 | + public final void setPriceGuest(final BigDecimal priceGuest) { | |
| 140 | + this.priceGuest = priceGuest; | |
| 141 | + } | |
| 142 | + | |
| 143 | + public final String toString(){ | |
| 144 | + StringBuilder sb = new StringBuilder(); | |
| 145 | + sb.append("\n"); | |
| 146 | + //sb.append(date.format(dtf) + " - " + dishCategory + ":").append("\n"); | |
| 147 | + sb.append(name); | |
| 148 | + if (dishTypes != null && dishTypes.size() > 0) { | |
| 149 | + sb.append(" " + dishTypes.toString()); | |
| 150 | + } | |
| 151 | + sb.append("\n"); | |
| 152 | + if(price != null && !price.trim().equals("")) { | |
| 153 | + sb.append(price).append("\n"); | |
| 154 | + } | |
| 155 | + //sb.append("Studenten-Preis: " + priceStudent + " EUR").append("\n"); | |
| 156 | + //sb.append("Mitarbeiter-Preis: " + priceEmployee + " EUR").append("\n"); | |
| 157 | + //sb.append("Gäste-Preis: " + priceGuest + " EUR").append("\n"); | |
| 158 | + //sb.append("Ampel: " + trafficLight.getText()).append("\n"); | |
| 159 | + | |
| 160 | + /* | |
| 161 | + if (markings != null && markings.size() > 0) { | |
| 162 | + sb.append("Zusätze: " + String.join(", ", markings)); | |
| 163 | + } | |
| 164 | + */ | |
| 165 | + return sb.toString(); | |
| 166 | + } | |
| 167 | + | |
| 168 | + public final String showPrice(){ | |
| 169 | + return getName() + " kostet: " + getPrice(); | |
| 170 | + } | |
| 171 | +} | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/DishCategory.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/DishCategory.java | |
| 1 | +package de.bht.beuthbot.canteen.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by sJantzen on 11.06.2017. | |
| 5 | + */ | |
| 6 | +public enum DishCategory { | |
| 7 | + | |
| 8 | + STARTER("Vorspeisen"), SALAD("Salate"),SOUP("Suppen"), SPECIAL("Aktionen"), FOOD("Essen"), SIDE_DISH("Beilagen"), DESSERT("Desserts"); | |
| 9 | + | |
| 10 | + private String text; | |
| 11 | + | |
| 12 | + DishCategory(final String text){ | |
| 13 | + this.text = text; | |
| 14 | + } | |
| 15 | + | |
| 16 | + public String getText(){ | |
| 17 | + return text; | |
| 18 | + } | |
| 19 | + | |
| 20 | + public String toString(){ | |
| 21 | + return text; | |
| 22 | + } | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * Returns the assigned dish category to a given string. | |
| 26 | + * @param strCategory | |
| 27 | + * @return | |
| 28 | + */ | |
| 29 | + public static DishCategory getDishCategory(final String strCategory) { | |
| 30 | + switch (strCategory.toLowerCase()) { | |
| 31 | + case "vorspeisen": | |
| 32 | + return STARTER; | |
| 33 | + case "salate": | |
| 34 | + return SALAD; | |
| 35 | + case "suppen": | |
| 36 | + return SOUP; | |
| 37 | + case "aktionen": | |
| 38 | + return SPECIAL; | |
| 39 | + case "essen": | |
| 40 | + return FOOD; | |
| 41 | + case "beilagen": | |
| 42 | + return SIDE_DISH; | |
| 43 | + case "desserts": | |
| 44 | + return DESSERT; | |
| 45 | + default: | |
| 46 | + return null; | |
| 47 | + } | |
| 48 | + } | |
| 49 | +} | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/DishType.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/DishType.java | |
| 1 | +package de.bht.beuthbot.canteen.model; | |
| 2 | + | |
| 3 | +import java.util.ArrayList; | |
| 4 | +import java.util.Arrays; | |
| 5 | +import java.util.List; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * Created by sJantzen on 11.06.2017. | |
| 9 | + */ | |
| 10 | +public enum DishType { | |
| 11 | + | |
| 12 | + VEGETARIAN("vegetarian", "1"), VEGAN("vegan", "15"), CLIMATE_NEUTRAL("klimaessen", "43"), BIO("bio", "18"), MSC("msc", "38"); | |
| 13 | + | |
| 14 | + private String text; | |
| 15 | + private String number; | |
| 16 | + | |
| 17 | + DishType(final String text, final String number){ | |
| 18 | + this.text = text; | |
| 19 | + this.number = number; | |
| 20 | + } | |
| 21 | + | |
| 22 | + public String getText(){ | |
| 23 | + return text; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public String getNumber() { | |
| 27 | + return number; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public String toString(){ | |
| 31 | + return text; | |
| 32 | + } | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * Checks whether the given name matches with a dishType. | |
| 36 | + * @param name | |
| 37 | + * @returns dishType if matches, else null | |
| 38 | + */ | |
| 39 | + public static DishType getDishTypeByName(final String name) { | |
| 40 | + for (DishType dishType : DishType.values()) { | |
| 41 | + if(dishType.getText().equals(name)){ | |
| 42 | + return dishType; | |
| 43 | + } | |
| 44 | + } | |
| 45 | + return null; | |
| 46 | + } | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Checks whether the given number matches with a dishType. | |
| 50 | + * @param number | |
| 51 | + * @returns dishType if matches, else null | |
| 52 | + */ | |
| 53 | + public static DishType getDishTypeByNumber(final String number) { | |
| 54 | + for (DishType dishType : DishType.values()) { | |
| 55 | + if(dishType.getNumber().equals(number)){ | |
| 56 | + return dishType; | |
| 57 | + } | |
| 58 | + } | |
| 59 | + return null; | |
| 60 | + } | |
| 61 | + | |
| 62 | + /** | |
| 63 | + * Creates a list of dishTypes by a given string. | |
| 64 | + * @param strDishTypes | |
| 65 | + * @return | |
| 66 | + */ | |
| 67 | + public static List<DishType> getDishTypes(final String strDishTypes) { | |
| 68 | + List<DishType> rv = new ArrayList<>(); | |
| 69 | + | |
| 70 | + for (String dishType : Arrays.asList(strDishTypes.split("\\s*,\\s*"))) { | |
| 71 | + DishType dt = getDishTypeByName(dishType); | |
| 72 | + if(dt != null) { | |
| 73 | + rv.add(dt); | |
| 74 | + } | |
| 75 | + } | |
| 76 | + return rv; | |
| 77 | + } | |
| 78 | +} | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/TrafficLight.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/canteen/model/TrafficLight.java | |
| 1 | +package de.bht.beuthbot.canteen.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Created by sJantzen on 11.06.2017. | |
| 5 | + */ | |
| 6 | +public enum TrafficLight { | |
| 7 | + | |
| 8 | + GREEN("green"), YELLOW("yellow"), RED("red"); | |
| 9 | + | |
| 10 | + private String text; | |
| 11 | + | |
| 12 | + TrafficLight(final String text){ | |
| 13 | + this.text = text; | |
| 14 | + } | |
| 15 | + | |
| 16 | + public String getText(){ | |
| 17 | + return text; | |
| 18 | + } | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * Returns a trafficlight if matches with given text. | |
| 22 | + * @param text | |
| 23 | + * @returns null if no match was found. | |
| 24 | + */ | |
| 25 | + public static TrafficLight getTrafficLight(final String text){ | |
| 26 | + switch (text.toLowerCase()) { | |
| 27 | + case "green": | |
| 28 | + return TrafficLight.GREEN; | |
| 29 | + case "yellow": | |
| 30 | + return TrafficLight.YELLOW; | |
| 31 | + case "red": | |
| 32 | + return TrafficLight.RED; | |
| 33 | + default: | |
| 34 | + return null; | |
| 35 | + } | |
| 36 | + } | |
| 37 | + | |
| 38 | + public String toString(){ | |
| 39 | + return text; | |
| 40 | + } | |
| 41 | +} | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/drools/DroolsService.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/drools/DroolsService.java | |
| 1 | +package de.bht.beuthbot.drools; | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | +import com.google.gson.Gson; | |
| 7 | + | |
| 8 | + | |
| 9 | +import de.bht.beuthbot.attachments.AttachmentStore; | |
| 10 | +import de.bht.beuthbot.canteen.Parser; | |
| 11 | +import de.bht.beuthbot.canteen.model.CanteenData; | |
| 12 | +import de.bht.beuthbot.conf.Application; | |
| 13 | +import de.bht.beuthbot.drools.model.DroolsMessage; | |
| 14 | +import de.bht.beuthbot.jms.ProcessQueue; | |
| 15 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 16 | +import de.bht.beuthbot.jms.Target; | |
| 17 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 18 | +import org.kie.api.KieServices; | |
| 19 | +import org.kie.api.runtime.KieContainer; | |
| 20 | +import org.kie.api.runtime.KieSession; | |
| 21 | +import org.slf4j.Logger; | |
| 22 | +import org.slf4j.LoggerFactory; | |
| 23 | + | |
| 24 | +import javax.annotation.Resource; | |
| 25 | +import javax.ejb.ActivationConfigProperty; | |
| 26 | +import javax.ejb.MessageDriven; | |
| 27 | +import javax.inject.Inject; | |
| 28 | +import javax.jms.JMSException; | |
| 29 | +import javax.jms.Message; | |
| 30 | +import javax.jms.MessageListener; | |
| 31 | + | |
| 32 | +/** | |
| 33 | + * Created by sJantzen on 13.06.2017. | |
| 34 | + */ | |
| 35 | +@MessageDriven( | |
| 36 | + name = "DroolsProcessor", | |
| 37 | + activationConfig = { | |
| 38 | + @ActivationConfigProperty( | |
| 39 | + propertyName = "destinationType", | |
| 40 | + propertyValue = "javax.jms.Topic"), | |
| 41 | + @ActivationConfigProperty( | |
| 42 | + propertyName = "destination", | |
| 43 | + propertyValue = "jms/messages/inbox"), | |
| 44 | + @ActivationConfigProperty( | |
| 45 | + propertyName = "maxSession", propertyValue = "1"), | |
| 46 | + @ActivationConfigProperty( | |
| 47 | + propertyName = "messageSelector", propertyValue = "DROOLS IS NOT NULL" | |
| 48 | + ) | |
| 49 | + } | |
| 50 | +) | |
| 51 | +public class DroolsService implements MessageListener { | |
| 52 | + | |
| 53 | + private Logger logger = LoggerFactory.getLogger(DroolsService.class); | |
| 54 | + private Gson gson = new Gson(); | |
| 55 | + | |
| 56 | + | |
| 57 | + /** Injected JMS MessageQueue */ | |
| 58 | + @Resource(lookup = "java:global/global/ProcessQueueBean") | |
| 59 | + private ProcessQueue processQueue; | |
| 60 | + | |
| 61 | + /** Injected AttachmentStore */ | |
| 62 | + @Resource(lookup = "java:global/global/AttachmentStoreBean") | |
| 63 | + private AttachmentStore attachmentStore; | |
| 64 | + | |
| 65 | + /** BeuthBot Application Bean */ | |
| 66 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 67 | + private Application application; | |
| 68 | + | |
| 69 | + @Inject | |
| 70 | + private Parser parser; | |
| 71 | + | |
| 72 | + @Override | |
| 73 | + public void onMessage(Message message) { | |
| 74 | + try { | |
| 75 | + ProcessQueueMessageProtocol botMessage = message.getBody(TaskMessage.class); | |
| 76 | + | |
| 77 | + DroolsMessage droolsMessage = doRules(botMessage); | |
| 78 | + | |
| 79 | + logger.info("ANSWER: " + botMessage.getText()); | |
| 80 | + | |
| 81 | + if (droolsMessage.isAsVoiceMessage()) { | |
| 82 | + droolsMessage.setTarget(Target.NTSP); | |
| 83 | + processQueue.route(new TaskMessage(droolsMessage)); | |
| 84 | + } else { | |
| 85 | + droolsMessage.setTarget(Target.MESSENGER); | |
| 86 | + processQueue.route(new TaskMessage(droolsMessage)); | |
| 87 | + } | |
| 88 | + } catch (JMSException e) { | |
| 89 | + logger.error("Exception while setting bot message to the queue.", e); | |
| 90 | + } | |
| 91 | + } | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * Gets a botMessage and processes all fitting rules an it. | |
| 95 | + * @param botMessage | |
| 96 | + * @returns the botMessage with a new created answer text | |
| 97 | + */ | |
| 98 | + private DroolsMessage doRules(final ProcessQueueMessageProtocol botMessage){ | |
| 99 | + | |
| 100 | + // KieServices is the factory for all KIE services | |
| 101 | + KieServices ks = KieServices.Factory.get(); | |
| 102 | + | |
| 103 | + // From the kie services, a container is created from the classpath | |
| 104 | + KieContainer kc = ks.getKieClasspathContainer(); | |
| 105 | + | |
| 106 | + // From the container, a session is created based on | |
| 107 | + // its definition and configuration in the META-INF/kmodule.xml file | |
| 108 | + KieSession ksession = kc.newKieSession("CanteenKS"); | |
| 109 | + | |
| 110 | + // Once the session is created, the application can interact with it | |
| 111 | + // In this case it is setting a global as defined in the | |
| 112 | + // org/drools/examples/helloworld/HelloWorld.drl file | |
| 113 | + CanteenData canteenData = parser.parse(); | |
| 114 | + | |
| 115 | + ksession.setGlobal("canteenData", canteenData); | |
| 116 | + | |
| 117 | + // The application can insert facts into the session | |
| 118 | + // Map incoming ApiAiMessages and RasaMessages to DroolsMessage | |
| 119 | + DroolsMessage droolsMessage = new DroolsMessage(botMessage); | |
| 120 | + | |
| 121 | + ksession.insert(droolsMessage); | |
| 122 | + | |
| 123 | + // and fire the rules | |
| 124 | + ksession.fireAllRules(); | |
| 125 | + | |
| 126 | + // and then dispose the session | |
| 127 | + ksession.dispose(); | |
| 128 | + | |
| 129 | + return droolsMessage; | |
| 130 | + } | |
| 131 | +} | |
| 0 | 132 | \ No newline at end of file | ... | ... |
services/MainBot/src/main/java/de/bht/beuthbot/drools/model/DroolsMessage.java
0 → 100755
| 1 | +++ a/services/MainBot/src/main/java/de/bht/beuthbot/drools/model/DroolsMessage.java | |
| 1 | +package de.bht.beuthbot.drools.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 4 | +import de.bht.beuthbot.jms.Target; | |
| 5 | +import de.bht.beuthbot.model.Attachment; | |
| 6 | +import de.bht.beuthbot.model.Messenger; | |
| 7 | + | |
| 8 | +import java.util.Collections; | |
| 9 | +import java.util.List; | |
| 10 | +import java.util.Map; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * @Author: Christopher Kümmel on 6/19/2017. | |
| 14 | + */ | |
| 15 | +public class DroolsMessage implements ProcessQueueMessageProtocol { | |
| 16 | + | |
| 17 | + private Long messageID; | |
| 18 | + private Long senderID; | |
| 19 | + private Messenger messenger; | |
| 20 | + private String text; | |
| 21 | + private String intent; | |
| 22 | + private Map<String,String> entities; | |
| 23 | + private boolean asVoiceMessage; | |
| 24 | + private Target target; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * Default constructor. | |
| 28 | + */ | |
| 29 | + public DroolsMessage() { | |
| 30 | + } | |
| 31 | + | |
| 32 | + /** | |
| 33 | + * Copy constructor. | |
| 34 | + * @param nluBotMessage | |
| 35 | + */ | |
| 36 | + public DroolsMessage(final ProcessQueueMessageProtocol nluBotMessage) { | |
| 37 | + this.messageID = nluBotMessage.getMessageID(); | |
| 38 | + this.senderID = nluBotMessage.getSenderID(); | |
| 39 | + this.messenger = nluBotMessage.getMessenger(); | |
| 40 | + this.text = nluBotMessage.getText(); | |
| 41 | + this.intent = nluBotMessage.getIntent(); | |
| 42 | + this.entities = nluBotMessage.getEntities(); | |
| 43 | + } | |
| 44 | + | |
| 45 | + @Override | |
| 46 | + public Long getId() { | |
| 47 | + return 1L; | |
| 48 | + } | |
| 49 | + | |
| 50 | + @Override | |
| 51 | + public Target getTarget() { | |
| 52 | + return target; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public void setTarget(Target target) { | |
| 56 | + this.target = target; | |
| 57 | + } | |
| 58 | + | |
| 59 | + @Override | |
| 60 | + public Long getMessageID() { | |
| 61 | + return messageID; | |
| 62 | + } | |
| 63 | + | |
| 64 | + public void setMessageID(Long messageID){ | |
| 65 | + this.messageID = messageID; | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Override | |
| 69 | + public Long getSenderID() { | |
| 70 | + return senderID; | |
| 71 | + } | |
| 72 | + | |
| 73 | + public void setSenderID(Long senderID){ | |
| 74 | + this.senderID = senderID; | |
| 75 | + } | |
| 76 | + | |
| 77 | + @Override | |
| 78 | + public Messenger getMessenger() { | |
| 79 | + return messenger; | |
| 80 | + } | |
| 81 | + | |
| 82 | + public void setMessenger(Messenger messenger){ | |
| 83 | + this.messenger = messenger; | |
| 84 | + } | |
| 85 | + | |
| 86 | + @Override | |
| 87 | + public String getText() { | |
| 88 | + return text; | |
| 89 | + } | |
| 90 | + | |
| 91 | + public void setText(String text){ | |
| 92 | + this.text = text; | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + public boolean hasAttachments() { | |
| 97 | + return false; | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public List<Attachment> getAttachments() { | |
| 102 | + return Collections.emptyList(); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @Override | |
| 106 | + public String getIntent() { | |
| 107 | + return intent; | |
| 108 | + } | |
| 109 | + | |
| 110 | + public void setIntent(String intent){ | |
| 111 | + this.intent = intent; | |
| 112 | + } | |
| 113 | + | |
| 114 | + @Override | |
| 115 | + public Map<String,String> getEntities() { | |
| 116 | + return entities; | |
| 117 | + } | |
| 118 | + | |
| 119 | + public void setEntities(Map<String,String> entities){ | |
| 120 | + this.entities = entities; | |
| 121 | + } | |
| 122 | + | |
| 123 | + public boolean isAsVoiceMessage() { | |
| 124 | + return asVoiceMessage; | |
| 125 | + } | |
| 126 | + | |
| 127 | + public void setAsVoiceMessage(boolean asVoiceMessage) { | |
| 128 | + this.asVoiceMessage = asVoiceMessage; | |
| 129 | + } | |
| 130 | +} | ... | ... |
services/MainBot/src/main/resources/META-INF/kmodule.xml
0 → 100755
| 1 | +++ a/services/MainBot/src/main/resources/META-INF/kmodule.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 3 | + xmlns="http://www.drools.org/xsd/kmodule"> | |
| 4 | + | |
| 5 | + <kbase name="CanteenKB" packages="de.bht.beuthbot.drools"> | |
| 6 | + <ksession name="CanteenKS"/> | |
| 7 | + </kbase> | |
| 8 | +</kmodule> | |
| 0 | 9 | \ No newline at end of file | ... | ... |
services/MainBot/src/main/resources/de/bht/beuthbot/drools/Canteen.drl
0 → 100755
| 1 | +++ a/services/MainBot/src/main/resources/de/bht/beuthbot/drools/Canteen.drl | |
| 1 | +/* | |
| 2 | + * Copyright 2010 Red Hat, Inc. and/or its affiliates. | |
| 3 | + * | |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 5 | + * you may not use this file except in compliance with the License. | |
| 6 | + * You may obtain a copy of the License at | |
| 7 | + * | |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 | + * | |
| 10 | + * Unless required by applicable law or agreed to in writing, software | |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 | + * See the License for the specific language governing permissions and | |
| 14 | + * limitations under the License. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +package de.bht.beuthbot.drools | |
| 18 | + | |
| 19 | +import java.util.List | |
| 20 | +import java.util.ArrayList; | |
| 21 | +import java.util.Arrays; | |
| 22 | +import java.util.HashMap; | |
| 23 | + | |
| 24 | +import java.time.LocalDate; | |
| 25 | + | |
| 26 | +import de.bht.beuthbot.canteen.model.Dish | |
| 27 | +import de.bht.beuthbot.canteen.model.DishType; | |
| 28 | +import de.bht.beuthbot.model.Intent; | |
| 29 | +import de.bht.beuthbot.model.EntityName; | |
| 30 | +import de.bht.beuthbot.drools.model.DroolsMessage; | |
| 31 | + | |
| 32 | +global de.bht.beuthbot.canteen.model.CanteenData canteenData; | |
| 33 | + | |
| 34 | +// ---------------------- GREETING ------------------------------------ | |
| 35 | +rule "Hello Drools" | |
| 36 | + dialect "java" | |
| 37 | + when | |
| 38 | + m : DroolsMessage( intent.equals(Intent.HELLO.getText())) | |
| 39 | + then | |
| 40 | + modify ( m ) { setText("Guten Tag.")}; | |
| 41 | +end | |
| 42 | + | |
| 43 | +// ---------------------- SAYING GOODBYE ------------------------------------ | |
| 44 | + | |
| 45 | +rule "Saying goodbye" | |
| 46 | + dialect "java" | |
| 47 | + when | |
| 48 | + m : DroolsMessage( intent.equals(Intent.BYE.getText())) | |
| 49 | + then | |
| 50 | + modify( m ) { | |
| 51 | + setText("Auf Wiedersehen. Bis dann."), | |
| 52 | + setAsVoiceMessage(true) | |
| 53 | + }; | |
| 54 | +end | |
| 55 | + | |
| 56 | +// ------------------------ SHOW DISHES -------------------------------------- | |
| 57 | + | |
| 58 | +rule "Show all dishes" | |
| 59 | + dialect "java" | |
| 60 | + when | |
| 61 | + m : DroolsMessage( intent.equals(Intent.SHOW_FOOD.getText()) && entities.isEmpty()) | |
| 62 | + then | |
| 63 | + modify ( m ) { setText("Alle Gerichte dieser und nächster Woche: \n" + canteenData.getDishes())}; | |
| 64 | +end | |
| 65 | + | |
| 66 | +rule "Restaurant search" | |
| 67 | + dialect "java" | |
| 68 | + when | |
| 69 | + m : DroolsMessage( intent.equals(Intent.RESTAURANT_SEARCH.getText())) | |
| 70 | + then | |
| 71 | + modify ( m ){ setText("Restaurant gesucht")} | |
| 72 | +end | |
| 73 | + | |
| 74 | + | |
| 75 | +rule "Show dishes filtered" | |
| 76 | + dialect "java" | |
| 77 | + when | |
| 78 | + m : DroolsMessage( getIntent().equals(Intent.SHOW_FOOD.getText()) && !entities.isEmpty() ) | |
| 79 | + then | |
| 80 | + modify( m ) { | |
| 81 | + setText("Gerichte:\n" + canteenData.getDishesFilteredAsString( | |
| 82 | + (m.getEntities().containsKey(EntityName.DATE.getText()) ? m.getEntities().get(EntityName.DATE.getText()) : null), | |
| 83 | + (m.getEntities().containsKey(EntityName.HEALTHY.getText()) ? m.getEntities().get(EntityName.HEALTHY.getText()) : null), | |
| 84 | + (m.getEntities().containsKey(EntityName.DISH_TYPE.getText()) ? m.getEntities().get(EntityName.DISH_TYPE.getText()) : null), | |
| 85 | + (m.getEntities().containsKey(EntityName.INGREDIENTS.getText()) ? m.getEntities().get(EntityName.INGREDIENTS.getText()) : null), | |
| 86 | + (m.getEntities().containsKey(EntityName.DISH_CATEGORY.getText()) ? m.getEntities().get(EntityName.DISH_CATEGORY.getText()) : null) | |
| 87 | + )) | |
| 88 | + }; | |
| 89 | +end | |
| 90 | +// ----------------------------- START --------------------------- | |
| 91 | +rule "Start" | |
| 92 | + dialect "java" | |
| 93 | + when | |
| 94 | + m : DroolsMessage( getIntent().equals(Intent.START.getText())) | |
| 95 | + then | |
| 96 | + modify(m) {setText("Hallo und herzlich willkommen!\n\n Ich bin der BeuthBot.\n Ich gebe dir gerne aktuelle Informationen der Gerichte der Mensa.")} | |
| 97 | +end | |
| 98 | + | |
| 99 | +// ---------------------------- PRICE ----------------------------- | |
| 100 | +rule "Show price" | |
| 101 | + dialect "java" | |
| 102 | + when | |
| 103 | + m : DroolsMessage(getIntent().equals(Intent.SHOW_PRICE.getText())) | |
| 104 | + then | |
| 105 | + modify(m){setText(canteenData.showPriceOfDish(m.getEntities().containsKey(EntityName.DISH_NAME.getText()) ? m.getEntities().get(EntityName.DISH_NAME.getText()) : ""))} | |
| 106 | +end | |
| 107 | + | |
| 108 | +// --------------------------- Fallback ------------------------- | |
| 109 | +rule "Fallback" | |
| 110 | + dialect "java" | |
| 111 | + when | |
| 112 | + m : DroolsMessage(getIntent().equals(Intent.FALLBACK.getText())) | |
| 113 | + then | |
| 114 | + modify(m){setText("Die Anfrage konnte ich leider nicht verarbeiten. \nVersuche eine genauere Formulierung.")} | |
| 115 | +end | |
| 0 | 116 | \ No newline at end of file | ... | ... |
services/MainBot/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/MainBot/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/Rasa/build.gradle
0 → 100755
| 1 | +++ a/services/Rasa/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | +} | |
| 8 | + | |
| 9 | +dependencies { | |
| 10 | + compile project(':services:Common'), | |
| 11 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 12 | + "com.google.code.gson:gson:2.8.1" | |
| 13 | + | |
| 14 | + providedCompile "org.slf4j:slf4j-api:1.7.25", | |
| 15 | + "org.jboss.resteasy:resteasy-client:3.1.3.Final" | |
| 16 | + | |
| 17 | + testCompile "org.jboss.arquillian.junit:arquillian-junit-container:1.1.13.Final", | |
| 18 | + "junit:junit:4.12" | |
| 19 | + | |
| 20 | + testRuntime "org.wildfly.arquillian:wildfly-arquillian-container-remote:2.0.2.Final", | |
| 21 | + "org.slf4j:slf4j-simple:1.7.25" | |
| 22 | +} | |
| 23 | + | |
| 24 | +sourceCompatibility = 1.8 | |
| 25 | + | |
| 26 | +war { | |
| 27 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 28 | + archiveName "rasa.war" | |
| 29 | +} | |
| 0 | 30 | \ No newline at end of file | ... | ... |
services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/RasaConnector.java
0 → 100755
| 1 | +++ a/services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/RasaConnector.java | |
| 1 | +package de.bht.beuthbot.nlp.rasa; | |
| 2 | + | |
| 3 | +import com.google.gson.Gson; | |
| 4 | +import de.bht.beuthbot.conf.Application; | |
| 5 | +import de.bht.beuthbot.conf.Configuration; | |
| 6 | +import de.bht.beuthbot.jms.ProcessQueue; | |
| 7 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 8 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 9 | +import de.bht.beuthbot.nlp.rasa.model.RasaMessage; | |
| 10 | +import de.bht.beuthbot.nlp.rasa.model.RasaResponse; | |
| 11 | +import org.jboss.resteasy.client.jaxrs.ResteasyClient; | |
| 12 | +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; | |
| 13 | +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; | |
| 14 | +import org.slf4j.Logger; | |
| 15 | +import org.slf4j.LoggerFactory; | |
| 16 | + | |
| 17 | +import javax.annotation.PostConstruct; | |
| 18 | +import javax.annotation.Resource; | |
| 19 | +import javax.ejb.ActivationConfigProperty; | |
| 20 | +import javax.ejb.MessageDriven; | |
| 21 | +import javax.jms.JMSException; | |
| 22 | +import javax.jms.Message; | |
| 23 | +import javax.jms.MessageListener; | |
| 24 | +import javax.ws.rs.core.Response; | |
| 25 | +import javax.ws.rs.core.UriBuilder; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * @author: georg.glossmann@adesso.de | |
| 29 | + * Date: 04.06.17 | |
| 30 | + */ | |
| 31 | +@MessageDriven( | |
| 32 | + name = "RasaConnector", | |
| 33 | + activationConfig = { | |
| 34 | + @ActivationConfigProperty( | |
| 35 | + propertyName = "destinationType", | |
| 36 | + propertyValue = "javax.jms.Topic"), | |
| 37 | + @ActivationConfigProperty( | |
| 38 | + propertyName = "destination", | |
| 39 | + propertyValue = "jms/messages/inbox"), | |
| 40 | + @ActivationConfigProperty( | |
| 41 | + propertyName = "messageSelector", propertyValue = "NLP IS NOT NULL AND RASA IS NOT NULL") | |
| 42 | + } | |
| 43 | +) | |
| 44 | +public class RasaConnector implements MessageListener { | |
| 45 | + | |
| 46 | + private final Logger logger = LoggerFactory.getLogger(RasaConnector.class); | |
| 47 | + private RasaRESTServiceInterface rasaProxy; | |
| 48 | + private Gson gson; | |
| 49 | + | |
| 50 | + @Resource(lookup = "java:global/global/ProcessQueueBean") | |
| 51 | + private ProcessQueue processQueue; | |
| 52 | + | |
| 53 | + /** BeuthBot Application Bean */ | |
| 54 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 55 | + private Application application; | |
| 56 | + | |
| 57 | + | |
| 58 | + @PostConstruct | |
| 59 | + public void init() { | |
| 60 | + gson = new Gson(); | |
| 61 | + ResteasyClient client = new ResteasyClientBuilder().build(); | |
| 62 | + final String localRasaURL = application.getConfiguration(Configuration.RASA_URL); | |
| 63 | + ResteasyWebTarget target = client.target(UriBuilder.fromPath(localRasaURL)); | |
| 64 | + rasaProxy = target.proxy(RasaRESTServiceInterface.class); | |
| 65 | + } | |
| 66 | + | |
| 67 | + | |
| 68 | + @Override | |
| 69 | + public void onMessage(final Message message) { | |
| 70 | + try { | |
| 71 | + ProcessQueueMessageProtocol incomingChatMessage = message.getBody(TaskMessage.class); | |
| 72 | + String messageText = incomingChatMessage.getText(); | |
| 73 | + | |
| 74 | + Response response = rasaProxy.processText(messageText); | |
| 75 | + String responseAsString = response.readEntity(String.class); | |
| 76 | + | |
| 77 | + logger.debug("{}: {}", response.getStatus(), responseAsString); | |
| 78 | + | |
| 79 | + RasaResponse rasaResponse = gson.fromJson(responseAsString, RasaResponse.class); | |
| 80 | + TaskMessage messageToMainBot = new TaskMessage(new RasaMessage(incomingChatMessage, rasaResponse)); | |
| 81 | + processQueue.route(messageToMainBot); | |
| 82 | + } catch (JMSException e) { | |
| 83 | + logger.error("Error while processing message.", e); | |
| 84 | + } | |
| 85 | + } | |
| 86 | +} | ... | ... |
services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/RasaRESTServiceInterface.java
0 → 100755
| 1 | +++ a/services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/RasaRESTServiceInterface.java | |
| 1 | +package de.bht.beuthbot.nlp.rasa; | |
| 2 | + | |
| 3 | +import javax.ws.rs.GET; | |
| 4 | +import javax.ws.rs.Path; | |
| 5 | +import javax.ws.rs.Produces; | |
| 6 | +import javax.ws.rs.QueryParam; | |
| 7 | +import javax.ws.rs.core.MediaType; | |
| 8 | +import javax.ws.rs.core.Response; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * @author: georg.glossmann@adesso.de | |
| 12 | + * Date: 04.06.17 | |
| 13 | + * | |
| 14 | + * Proxy interface to query rasa_nlu REST api | |
| 15 | + */ | |
| 16 | +@Path("/parse") | |
| 17 | +public interface RasaRESTServiceInterface { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * Processing the given text for intent and entities | |
| 21 | + * @param text Text to get intent and entities from, using rasa_nlu | |
| 22 | + * @return JAX RS Response representing the result of querying the rasa_nlu server | |
| 23 | + */ | |
| 24 | + @GET | |
| 25 | + @Produces({ MediaType.APPLICATION_JSON}) | |
| 26 | + Response processText(@QueryParam("q") String text); | |
| 27 | +} | ... | ... |
services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaEntity.java
0 → 100755
| 1 | +++ a/services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaEntity.java | |
| 1 | +package de.bht.beuthbot.nlp.rasa.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @author: georg.glossmann@adesso.de | |
| 5 | + * Date: 04.06.17 | |
| 6 | + */ | |
| 7 | +public class RasaEntity { | |
| 8 | + | |
| 9 | + private String entity; | |
| 10 | + private String value; | |
| 11 | + | |
| 12 | + | |
| 13 | + public String getEntity() { | |
| 14 | + return entity; | |
| 15 | + } | |
| 16 | + | |
| 17 | + public void setEntity(String entity) { | |
| 18 | + this.entity = entity; | |
| 19 | + } | |
| 20 | + | |
| 21 | + public String getValue() { | |
| 22 | + return value; | |
| 23 | + } | |
| 24 | + | |
| 25 | + public void setValue(String value) { | |
| 26 | + this.value = value; | |
| 27 | + } | |
| 28 | +} | ... | ... |
services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaIntent.java
0 → 100755
| 1 | +++ a/services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaIntent.java | |
| 1 | +package de.bht.beuthbot.nlp.rasa.model; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @author: georg.glossmann@adesso.de | |
| 5 | + * Date: 04.06.17 | |
| 6 | + */ | |
| 7 | +public class RasaIntent { | |
| 8 | + private String name; | |
| 9 | + private String confidence; | |
| 10 | + | |
| 11 | + | |
| 12 | + public String getName() { | |
| 13 | + return name; | |
| 14 | + } | |
| 15 | + | |
| 16 | + public void setName(String name) { | |
| 17 | + this.name = name; | |
| 18 | + } | |
| 19 | + | |
| 20 | + public String getConfidence() { | |
| 21 | + return confidence; | |
| 22 | + } | |
| 23 | + | |
| 24 | + public void setConfidence(String confidence) { | |
| 25 | + this.confidence = confidence; | |
| 26 | + } | |
| 27 | +} | ... | ... |
services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaMessage.java
0 → 100755
| 1 | +++ a/services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaMessage.java | |
| 1 | +package de.bht.beuthbot.nlp.rasa.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 4 | +import de.bht.beuthbot.jms.Target; | |
| 5 | +import de.bht.beuthbot.model.Attachment; | |
| 6 | +import de.bht.beuthbot.model.Messenger; | |
| 7 | + | |
| 8 | +import java.util.List; | |
| 9 | +import java.util.Map; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @author: georg.glossmann@adesso.de | |
| 13 | + * Date: 26.06.17 | |
| 14 | + */ | |
| 15 | +public class RasaMessage implements ProcessQueueMessageProtocol { | |
| 16 | + | |
| 17 | + private ProcessQueueMessageProtocol inMessage; | |
| 18 | + private RasaResponse rasaResponse; | |
| 19 | + | |
| 20 | + public RasaMessage(final ProcessQueueMessageProtocol inMessage, final RasaResponse rasaResponse) { | |
| 21 | + this.inMessage = inMessage; | |
| 22 | + this.rasaResponse = rasaResponse; | |
| 23 | + } | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public Long getId() { | |
| 27 | + return inMessage.getId(); | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public Target getTarget() { | |
| 32 | + return Target.MAINBOT; | |
| 33 | + } | |
| 34 | + | |
| 35 | + @Override | |
| 36 | + public Long getMessageID() { | |
| 37 | + return inMessage.getMessageID(); | |
| 38 | + } | |
| 39 | + | |
| 40 | + @Override | |
| 41 | + public Long getSenderID() { | |
| 42 | + return inMessage.getSenderID(); | |
| 43 | + } | |
| 44 | + | |
| 45 | + @Override | |
| 46 | + public Messenger getMessenger() { | |
| 47 | + return inMessage.getMessenger(); | |
| 48 | + } | |
| 49 | + | |
| 50 | + @Override | |
| 51 | + public String getText() { | |
| 52 | + return inMessage.getText(); | |
| 53 | + } | |
| 54 | + | |
| 55 | + @Override | |
| 56 | + public boolean hasAttachments() { | |
| 57 | + return inMessage.hasAttachments(); | |
| 58 | + } | |
| 59 | + | |
| 60 | + @Override | |
| 61 | + public List<Attachment> getAttachments() { | |
| 62 | + return inMessage.getAttachments(); | |
| 63 | + } | |
| 64 | + | |
| 65 | + @Override | |
| 66 | + public Map<String, String> getEntities() { | |
| 67 | + return rasaResponse.getEntities(); | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Override | |
| 71 | + public String getIntent() { | |
| 72 | + return rasaResponse.getIntent(); | |
| 73 | + } | |
| 74 | +} | ... | ... |
services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaResponse.java
0 → 100755
| 1 | +++ a/services/Rasa/src/main/java/de/bht/beuthbot/nlp/rasa/model/RasaResponse.java | |
| 1 | +package de.bht.beuthbot.nlp.rasa.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.model.nlp.NLUResponse; | |
| 4 | + | |
| 5 | +import java.util.HashMap; | |
| 6 | +import java.util.List; | |
| 7 | +import java.util.Map; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @author: georg.glossmann@adesso.de | |
| 11 | + * Date: 04.06.17 | |
| 12 | + * <p> | |
| 13 | + * NLUResponse adapter for rasa_nlu | |
| 14 | + */ | |
| 15 | +public class RasaResponse implements NLUResponse { | |
| 16 | + | |
| 17 | + private List<RasaEntity> entities; | |
| 18 | + private RasaIntent intent; | |
| 19 | + private String text; | |
| 20 | + | |
| 21 | + | |
| 22 | + public List<RasaEntity> getRasaEntities() { | |
| 23 | + return entities; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public void setRasaEntities(List<RasaEntity> rasaEntities) { | |
| 27 | + this.entities = rasaEntities; | |
| 28 | + } | |
| 29 | + | |
| 30 | + public RasaIntent getRasaIntent() { | |
| 31 | + return intent; | |
| 32 | + } | |
| 33 | + | |
| 34 | + public void setRasaIntent(RasaIntent rasaIntent) { | |
| 35 | + this.intent = rasaIntent; | |
| 36 | + } | |
| 37 | + | |
| 38 | + public String getText() { | |
| 39 | + return text; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public void setText(String text) { | |
| 43 | + this.text = text; | |
| 44 | + } | |
| 45 | + | |
| 46 | + | |
| 47 | + public Map<String, String> getEntities() { | |
| 48 | + Map<String, String> entityMap = new HashMap<>(); | |
| 49 | + for (RasaEntity rasaEntity : entities) { | |
| 50 | + entityMap.put(rasaEntity.getEntity(), rasaEntity.getValue()); | |
| 51 | + } | |
| 52 | + return entityMap; | |
| 53 | + } | |
| 54 | + | |
| 55 | + public String getIntent() { | |
| 56 | + return intent.getName(); | |
| 57 | + } | |
| 58 | +} | ... | ... |
services/Rasa/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/Rasa/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
services/Rasa/src/test/java/DebugMessageGenerator.java
0 → 100755
| 1 | +++ a/services/Rasa/src/test/java/DebugMessageGenerator.java | |
| 1 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 2 | +import de.bht.beuthbot.jms.Target; | |
| 3 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 4 | +import de.bht.beuthbot.model.Attachment; | |
| 5 | +import de.bht.beuthbot.model.Messenger; | |
| 6 | +import org.jboss.arquillian.container.test.api.Deployment; | |
| 7 | +import org.jboss.arquillian.junit.Arquillian; | |
| 8 | +import org.jboss.shrinkwrap.api.ShrinkWrap; | |
| 9 | +import org.jboss.shrinkwrap.api.asset.EmptyAsset; | |
| 10 | +import org.jboss.shrinkwrap.api.spec.JavaArchive; | |
| 11 | +import org.junit.Test; | |
| 12 | +import org.junit.runner.RunWith; | |
| 13 | + | |
| 14 | +import javax.annotation.Resource; | |
| 15 | +import javax.jms.*; | |
| 16 | +import java.util.Collections; | |
| 17 | +import java.util.List; | |
| 18 | +import java.util.Map; | |
| 19 | + | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * @author: georg.glossmann@adesso.de | |
| 23 | + * Date: 04.06.17 | |
| 24 | + */ | |
| 25 | +@RunWith(Arquillian.class) | |
| 26 | +public class DebugMessageGenerator { | |
| 27 | + | |
| 28 | + @Deployment | |
| 29 | + public static JavaArchive createDeployment() { | |
| 30 | + return ShrinkWrap.create(JavaArchive.class) | |
| 31 | + .addPackages(true, "de.bht.beuthbot.jms", "de.bht.beuthbot.model") | |
| 32 | + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); | |
| 33 | + } | |
| 34 | + | |
| 35 | + @Resource(lookup = "java:/jboss/DefaultJMSConnectionFactory") | |
| 36 | + private ConnectionFactory connectionFactory; | |
| 37 | + | |
| 38 | + @Resource(lookup = "java:/jms/messages/inbox") | |
| 39 | + private Topic messageInbox; | |
| 40 | + | |
| 41 | + @Test | |
| 42 | + public void should_create_greeting() throws JMSException { | |
| 43 | + final JMSContext context = connectionFactory.createContext(); | |
| 44 | + | |
| 45 | + Message message = context.createObjectMessage(new TaskMessage(new TestMessage())); | |
| 46 | + message.setStringProperty("NLP", "nlp"); | |
| 47 | + message.setStringProperty("RASA", "rasa"); | |
| 48 | + context.createProducer().send(messageInbox, message); | |
| 49 | + } | |
| 50 | + | |
| 51 | + private class TestMessage implements ProcessQueueMessageProtocol { | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public Long getId() { | |
| 55 | + return -1L; | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Override | |
| 59 | + public Target getTarget() { | |
| 60 | + return Target.NTSP; | |
| 61 | + } | |
| 62 | + | |
| 63 | + @Override | |
| 64 | + public Long getMessageID() { | |
| 65 | + return -1L; | |
| 66 | + } | |
| 67 | + | |
| 68 | + @Override | |
| 69 | + public Long getSenderID() { | |
| 70 | + return -1L; | |
| 71 | + } | |
| 72 | + | |
| 73 | + @Override | |
| 74 | + public Messenger getMessenger() { | |
| 75 | + return Messenger.TELEGRAM; | |
| 76 | + } | |
| 77 | + | |
| 78 | + @Override | |
| 79 | + public String getText() { | |
| 80 | + return "Was gibt's heute zu essen?"; | |
| 81 | + } | |
| 82 | + | |
| 83 | + @Override | |
| 84 | + public boolean hasAttachments() { | |
| 85 | + return false; | |
| 86 | + } | |
| 87 | + | |
| 88 | + @Override | |
| 89 | + public List<Attachment> getAttachments() { | |
| 90 | + return Collections.emptyList(); | |
| 91 | + } | |
| 92 | + | |
| 93 | + @Override | |
| 94 | + public String getIntent() { | |
| 95 | + return null; | |
| 96 | + } | |
| 97 | + | |
| 98 | + @Override | |
| 99 | + public Map<String, String> getEntities() { | |
| 100 | + return Collections.emptyMap(); | |
| 101 | + } | |
| 102 | + } | |
| 103 | +} | ... | ... |
services/Rasa/src/test/resources/arquillian.xml
0 → 100755
| 1 | +++ a/services/Rasa/src/test/resources/arquillian.xml | |
| 1 | +<arquillian xmlns="http://jboss.org/schema/arquillian" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 2 | + xsi:schemaLocation=" | |
| 3 | + http://jboss.org/schema/arquillian | |
| 4 | + http://jboss.org/schema/arquillian/arquillian_1_0.xsd"> | |
| 5 | + | |
| 6 | + <!-- Sets the protocol which is how Arquillian talks and executes the tests inside the container --> | |
| 7 | + <defaultProtocol type="Servlet 3.0" /> | |
| 8 | + | |
| 9 | + <!-- Configuration to be used when the WidlFly remote profile is active --> | |
| 10 | + <container qualifier="widlfly-remote" default="true"> | |
| 11 | + <configuration> | |
| 12 | + <property name="managementAddress">localhost</property> | |
| 13 | + <property name="managementPort">9990</property> | |
| 14 | + <property name="username">admin</property> | |
| 15 | + <property name="password">Admin</property> | |
| 16 | + </configuration> | |
| 17 | + </container> | |
| 18 | + | |
| 19 | +</arquillian> | |
| 0 | 20 | \ No newline at end of file | ... | ... |
services/Telegram/build.gradle
0 → 100755
| 1 | +++ a/services/Telegram/build.gradle | |
| 1 | +apply plugin: 'java' | |
| 2 | +apply plugin: 'war' | |
| 3 | +apply plugin: 'checkstyle' | |
| 4 | + | |
| 5 | +repositories { | |
| 6 | + mavenCentral() | |
| 7 | +} | |
| 8 | + | |
| 9 | +dependencies { | |
| 10 | + | |
| 11 | + compile project(':services:Common'), | |
| 12 | + "org.jboss.spec:jboss-javaee-7.0:1.1.0.Final", | |
| 13 | + "org.apache.httpcomponents:httpclient:4.5.3", | |
| 14 | + "org.apache.httpcomponents:httpmime:4.3.1", | |
| 15 | + "com.github.pengrad:java-telegram-bot-api:3.0.0" | |
| 16 | + | |
| 17 | + providedCompile "org.slf4j:slf4j-api:1.7.25", | |
| 18 | + "org.jboss.resteasy:resteasy-client:3.1.3.Final", | |
| 19 | + "org.jboss.resteasy:resteasy-jaxrs-all:3.1.3.Final" | |
| 20 | + | |
| 21 | +} | |
| 22 | + | |
| 23 | +sourceCompatibility = 1.8 | |
| 24 | + | |
| 25 | +war { | |
| 26 | + destinationDir new File(project.rootProject.projectDir, 'docker/wildfly/volumes/deployments/') | |
| 27 | + archiveName "telegram.war" | |
| 28 | +} | |
| 0 | 29 | \ No newline at end of file | ... | ... |
services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/JAXActivator.java
0 → 100755
| 1 | +++ a/services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/JAXActivator.java | |
| 1 | +package de.bht.beuthbot.messenger.telegram; | |
| 2 | + | |
| 3 | +import javax.ws.rs.ApplicationPath; | |
| 4 | +import javax.ws.rs.core.Application; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * JAXActivator is an arbitrary name, what is important is that javax.ws.rs.core.Application is extended | |
| 8 | + * and the @ApplicationPath annotation is used with a "rest" path. Without this the rest routes linked to | |
| 9 | + * from index.html would not be found. | |
| 10 | + */ | |
| 11 | +@ApplicationPath("") | |
| 12 | +public class JAXActivator extends Application { | |
| 13 | + // Left empty intentionally | |
| 14 | +} | ... | ... |
services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/TelegramReceiveAdapter.java
0 → 100755
| 1 | +++ a/services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/TelegramReceiveAdapter.java | |
| 1 | +package de.bht.beuthbot.messenger.telegram; | |
| 2 | + | |
| 3 | +import com.pengrad.telegrambot.BotUtils; | |
| 4 | +import com.pengrad.telegrambot.TelegramBot; | |
| 5 | +import com.pengrad.telegrambot.TelegramBotAdapter; | |
| 6 | +import com.pengrad.telegrambot.model.File; | |
| 7 | +import com.pengrad.telegrambot.model.Message; | |
| 8 | +import com.pengrad.telegrambot.model.Update; | |
| 9 | +import com.pengrad.telegrambot.request.GetFile; | |
| 10 | +import com.pengrad.telegrambot.request.SetWebhook; | |
| 11 | +import com.pengrad.telegrambot.response.BaseResponse; | |
| 12 | +import com.pengrad.telegrambot.response.GetFileResponse; | |
| 13 | +import de.bht.beuthbot.attachments.AttachmentStore; | |
| 14 | +import de.bht.beuthbot.conf.Application; | |
| 15 | +import de.bht.beuthbot.conf.Configuration; | |
| 16 | +import de.bht.beuthbot.jms.ProcessQueue; | |
| 17 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 18 | +import de.bht.beuthbot.messenger.telegram.model.TelegramAttachment; | |
| 19 | +import de.bht.beuthbot.messenger.telegram.model.TelegramMessage; | |
| 20 | +import de.bht.beuthbot.model.Attachment; | |
| 21 | +import de.bht.beuthbot.model.AttachmentType; | |
| 22 | +import org.apache.http.HttpStatus; | |
| 23 | +import org.slf4j.Logger; | |
| 24 | +import org.slf4j.LoggerFactory; | |
| 25 | + | |
| 26 | +import javax.annotation.PostConstruct; | |
| 27 | +import javax.annotation.Resource; | |
| 28 | +import javax.ws.rs.POST; | |
| 29 | +import javax.ws.rs.Path; | |
| 30 | +import javax.ws.rs.core.Response; | |
| 31 | +import java.util.Properties; | |
| 32 | + | |
| 33 | +/** | |
| 34 | + * @Author: Christopher Kümmel on 5/14/2017. | |
| 35 | + */ | |
| 36 | +@Path("") | |
| 37 | +public class TelegramReceiveAdapter { | |
| 38 | + | |
| 39 | + /** slf4j Logger */ | |
| 40 | + private final Logger logger = LoggerFactory.getLogger(TelegramReceiveAdapter.class); | |
| 41 | + | |
| 42 | + /** Injected JMS MessageQueue */ | |
| 43 | + @Resource(lookup = "java:global/global/ProcessQueueBean") | |
| 44 | + private ProcessQueue processQueue; | |
| 45 | + | |
| 46 | + /** Injected AttachmentStore */ | |
| 47 | + @Resource(lookup = "java:global/global/AttachmentStoreBean") | |
| 48 | + private AttachmentStore attachmentStore; | |
| 49 | + | |
| 50 | + /** BeuthBot Application Bean */ | |
| 51 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 52 | + private Application application; | |
| 53 | + | |
| 54 | + /** com.pengrad.telegrambot.TelegramBot; */ | |
| 55 | + private TelegramBot bot; | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * Initialize TelegramBot with Token | |
| 59 | + */ | |
| 60 | + @PostConstruct | |
| 61 | + public void init(){ | |
| 62 | + bot = TelegramBotAdapter.build(application.getConfiguration(Configuration.TELEGRAM_BOT_TOKEN)); | |
| 63 | + } | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * RESTEasy HTTP Post as Webhook Endpoint | |
| 67 | + * @param msg Telegram Message | |
| 68 | + */ | |
| 69 | + @POST | |
| 70 | + @Path("/getUpdates") | |
| 71 | + public Response getUpdates(final String msg) { | |
| 72 | + try { | |
| 73 | + Update update = BotUtils.parseUpdate(msg); | |
| 74 | + logger.debug("Received new Telegram message: {}", update); | |
| 75 | + TelegramMessage message = new TelegramMessage(update.message()); | |
| 76 | + message.setAttachments(getAttachments(update.message())); | |
| 77 | + processQueue.route(new TaskMessage(message)); | |
| 78 | + } catch (Exception e) { | |
| 79 | + logger.error("Something went wrong while getting updates from Telegram!", e); | |
| 80 | + } finally { | |
| 81 | + return Response.status(HttpStatus.SC_OK).build(); | |
| 82 | + } | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Check and get for Attachments from com.pengrad.telegrambot.model.Update | |
| 87 | + * @param message com.pengrad.telegrambot.model.Update | |
| 88 | + * @return returns null if no Attachment available | |
| 89 | + */ | |
| 90 | + private Attachment[] getAttachments(final Message message) { | |
| 91 | + | |
| 92 | + // check for attachments | |
| 93 | + String fileID = null; | |
| 94 | + if (message.audio() != null) fileID = message.audio().fileId(); | |
| 95 | + if (message.voice() != null) fileID = message.voice().fileId(); | |
| 96 | + | |
| 97 | + | |
| 98 | + if (fileID != null) { | |
| 99 | + // get download link from Telegram | |
| 100 | + GetFile request = new GetFile(fileID); | |
| 101 | + GetFileResponse getFileResponse = bot.execute(request); | |
| 102 | + | |
| 103 | + File file = getFileResponse.file(); | |
| 104 | + String fullPath = bot.getFullFilePath(file); | |
| 105 | + logger.debug("Telegram attachment uri: {}", fullPath); | |
| 106 | + | |
| 107 | + Long id; | |
| 108 | + if (message.audio() != null) { | |
| 109 | + id = attachmentStore.storeAttachment(fullPath, AttachmentType.AUDIO); | |
| 110 | + TelegramAttachment[] telegramAttachments = {new TelegramAttachment(id, AttachmentType.AUDIO, message.caption(), fullPath)}; | |
| 111 | + return telegramAttachments; | |
| 112 | + } | |
| 113 | + if (message.voice() != null){ | |
| 114 | + id = attachmentStore.storeAttachment(fullPath, AttachmentType.VOICE); | |
| 115 | + TelegramAttachment[] telegramAttachments = {new TelegramAttachment(id, AttachmentType.VOICE, message.caption(), fullPath)}; | |
| 116 | + return telegramAttachments; | |
| 117 | + } | |
| 118 | + } | |
| 119 | + | |
| 120 | + // "unkown" undefined attachments | |
| 121 | + boolean unknownType = false; | |
| 122 | + if (fileID == null && message.text() == null) unknownType = true; | |
| 123 | + | |
| 124 | + if (unknownType){ | |
| 125 | + TelegramAttachment[] telegramAttachments = {new TelegramAttachment(AttachmentType.UNKOWN)}; | |
| 126 | + return telegramAttachments; | |
| 127 | + } else { | |
| 128 | + return null; | |
| 129 | + } | |
| 130 | + } | |
| 131 | + | |
| 132 | + | |
| 133 | + /** | |
| 134 | + * RESTEasy HTTP Post to set Webhook | |
| 135 | + */ | |
| 136 | + @POST | |
| 137 | + @Path("/setWebhook") | |
| 138 | + public Response setWebhook() { | |
| 139 | + int responseCode = verifyWebhook(); | |
| 140 | + return Response.status(responseCode).build(); | |
| 141 | + } | |
| 142 | + | |
| 143 | + /** | |
| 144 | + * Method to set TelegramWebhook | |
| 145 | + */ | |
| 146 | + private int verifyWebhook() { | |
| 147 | + SetWebhook webhook = new SetWebhook().url(application.getConfiguration(Configuration.WEB_URL) + application.getConfiguration(Configuration.TELEGRAM_WEBHOOK_URL)); | |
| 148 | + | |
| 149 | + BaseResponse response = bot.execute(webhook); | |
| 150 | + if (response.isOk()) { | |
| 151 | + logger.debug("Telegram Webhook was set."); | |
| 152 | + return HttpStatus.SC_OK; | |
| 153 | + } else { | |
| 154 | + logger.warn("Telegram Webhook could not be set!"); | |
| 155 | + return HttpStatus.SC_METHOD_FAILURE; | |
| 156 | + } | |
| 157 | + } | |
| 158 | +} | ... | ... |
services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/TelegramSendAdapter.java
0 → 100755
| 1 | +++ a/services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/TelegramSendAdapter.java | |
| 1 | +package de.bht.beuthbot.messenger.telegram; | |
| 2 | + | |
| 3 | +import com.pengrad.telegrambot.TelegramBot; | |
| 4 | +import com.pengrad.telegrambot.TelegramBotAdapter; | |
| 5 | +import com.pengrad.telegrambot.request.SendAudio; | |
| 6 | +import com.pengrad.telegrambot.request.SendMessage; | |
| 7 | +import com.pengrad.telegrambot.request.SendVoice; | |
| 8 | +import com.pengrad.telegrambot.response.SendResponse; | |
| 9 | +import de.bht.beuthbot.conf.Application; | |
| 10 | +import de.bht.beuthbot.conf.Configuration; | |
| 11 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 12 | +import de.bht.beuthbot.jms.TaskMessage; | |
| 13 | +import de.bht.beuthbot.model.Attachment; | |
| 14 | +import org.slf4j.Logger; | |
| 15 | +import org.slf4j.LoggerFactory; | |
| 16 | + | |
| 17 | +import javax.annotation.PostConstruct; | |
| 18 | +import javax.annotation.Resource; | |
| 19 | +import javax.ejb.ActivationConfigProperty; | |
| 20 | +import javax.ejb.MessageDriven; | |
| 21 | +import javax.jms.JMSException; | |
| 22 | +import javax.jms.Message; | |
| 23 | +import javax.jms.MessageListener; | |
| 24 | + | |
| 25 | +/** | |
| 26 | + * @Author: Christopher Kümmel on 5/22/2017. | |
| 27 | + */ | |
| 28 | +@MessageDriven( | |
| 29 | + name = "OutboxTelegramProcessor", | |
| 30 | + activationConfig = { | |
| 31 | + @ActivationConfigProperty( | |
| 32 | + propertyName = "destinationType", | |
| 33 | + propertyValue = "javax.jms.Topic"), | |
| 34 | + @ActivationConfigProperty( | |
| 35 | + propertyName = "destination", | |
| 36 | + propertyValue = "jms/messages/inbox"), | |
| 37 | + @ActivationConfigProperty( | |
| 38 | + propertyName = "maxSession", propertyValue = "1"), | |
| 39 | + @ActivationConfigProperty( | |
| 40 | + propertyName = "messageSelector", propertyValue = "TELEGRAM IS NOT NULL" | |
| 41 | + ) | |
| 42 | + } | |
| 43 | +) | |
| 44 | +public class TelegramSendAdapter implements MessageListener { | |
| 45 | + | |
| 46 | + /** slf4j Logger */ | |
| 47 | + private final Logger logger = LoggerFactory.getLogger(TelegramSendAdapter.class); | |
| 48 | + | |
| 49 | + /** BeuthBot Application Bean */ | |
| 50 | + @Resource(lookup = "java:global/global/ApplicationBean") | |
| 51 | + private Application application; | |
| 52 | + | |
| 53 | + /** com.pengrad.telegrambot.TelegramBot; */ | |
| 54 | + private TelegramBot bot; | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * Initialize TelegramBot with Token | |
| 58 | + */ | |
| 59 | + @PostConstruct | |
| 60 | + public void init(){ | |
| 61 | + bot = TelegramBotAdapter.build(application.getConfiguration(Configuration.TELEGRAM_BOT_TOKEN)); | |
| 62 | + } | |
| 63 | + | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * Process JMS Message | |
| 67 | + * @param message | |
| 68 | + */ | |
| 69 | + @Override | |
| 70 | + public void onMessage(final Message message) { | |
| 71 | + try { | |
| 72 | + ProcessQueueMessageProtocol botMessage = message.getBody(TaskMessage.class); | |
| 73 | + if (botMessage.hasAttachments()){ | |
| 74 | + for (Attachment attachment : botMessage.getAttachments()) { | |
| 75 | + switch (attachment.getAttachmentType()) { | |
| 76 | + case AUDIO: | |
| 77 | + sendAudio(botMessage); | |
| 78 | + break; | |
| 79 | + case VOICE: | |
| 80 | + sendVoice(botMessage); | |
| 81 | + break; | |
| 82 | + case UNKOWN: | |
| 83 | + sendMessage(botMessage.getSenderID(), "Sorry! I'm just a bot and my developers just implemented audio and voice attachments.."); | |
| 84 | + break; | |
| 85 | + default: | |
| 86 | + sendMessage(botMessage.getSenderID(), "Sorry! I'm just a bot and my developers just implemented audio and voice attachments.."); | |
| 87 | + logger.info("new OutMessage has Attachments but no defined AttachmentType Case."); | |
| 88 | + break; | |
| 89 | + } | |
| 90 | + } | |
| 91 | + } else { | |
| 92 | + sendMessage(botMessage.getSenderID(), botMessage.getText()); | |
| 93 | + } | |
| 94 | + } | |
| 95 | + catch (JMSException e) { | |
| 96 | + logger.error("Error on receiving BotMessage-Object on TelegramSendAdapter: ", e); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * Send Telegram Text message | |
| 102 | + * @param senderId Telegram Sender ID | |
| 103 | + * @param message to send | |
| 104 | + */ | |
| 105 | + private void sendMessage(final Long senderId, final String message) { | |
| 106 | + SendMessage request = new SendMessage(senderId, message); | |
| 107 | + SendResponse sendResponse = bot.execute(request); | |
| 108 | + logger.debug("Send message: " + sendResponse.isOk()); | |
| 109 | + } | |
| 110 | + | |
| 111 | + /** | |
| 112 | + * Send Telegram Audio message | |
| 113 | + * @param botMessage to send | |
| 114 | + */ | |
| 115 | + private void sendAudio(final ProcessQueueMessageProtocol botMessage){ | |
| 116 | + SendAudio request; | |
| 117 | + | |
| 118 | + // check & send each attachement | |
| 119 | + for (Attachment attachment : botMessage.getAttachments()) { | |
| 120 | + request = new SendAudio(botMessage.getSenderID(), attachment.getFileURI()); | |
| 121 | + | |
| 122 | + if (attachment.getCaption() != null) | |
| 123 | + request.caption(attachment.getCaption()); | |
| 124 | + | |
| 125 | + SendResponse sendResponse = bot.execute(request); | |
| 126 | + logger.debug("Send Audio: " + sendResponse.isOk()); | |
| 127 | + } | |
| 128 | + } | |
| 129 | + | |
| 130 | + /** | |
| 131 | + * Send Telegram Voice message | |
| 132 | + * @param botMessage to send | |
| 133 | + */ | |
| 134 | + private void sendVoice(final ProcessQueueMessageProtocol botMessage){ | |
| 135 | + SendVoice request; | |
| 136 | + | |
| 137 | + for (Attachment attachment : botMessage.getAttachments()) { | |
| 138 | + request = new SendVoice(botMessage.getSenderID(), attachment.getFileURI()); | |
| 139 | + | |
| 140 | + if (attachment.getCaption() != null) | |
| 141 | + request.caption(attachment.getCaption()); | |
| 142 | + | |
| 143 | + SendResponse sendResponse = bot.execute(request); | |
| 144 | + logger.debug("Send Voice: " + sendResponse.isOk()); | |
| 145 | + } | |
| 146 | + } | |
| 147 | +} | ... | ... |
services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/model/TelegramAttachment.java
0 → 100755
| 1 | +++ a/services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/model/TelegramAttachment.java | |
| 1 | +package de.bht.beuthbot.messenger.telegram.model; | |
| 2 | + | |
| 3 | +import de.bht.beuthbot.model.Attachment; | |
| 4 | +import de.bht.beuthbot.model.AttachmentType; | |
| 5 | + | |
| 6 | +import java.util.Random; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * @Author: Christopher Kümmel on 6/15/2017. | |
| 10 | + */ | |
| 11 | +public class TelegramAttachment implements Attachment { | |
| 12 | + | |
| 13 | + /** generated unique id */ | |
| 14 | + private Long id; | |
| 15 | + /** URI where attachment is stored */ | |
| 16 | + private String fileURI; | |
| 17 | + /** type of Attachment e.g. AUDIO, VIDEO, .. */ | |
| 18 | + private AttachmentType attachmentType; | |
| 19 | + /** caption of that attachment */ | |
| 20 | + private String caption; | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * Constructor | |
| 24 | + * @param id generated unique id | |
| 25 | + * @param attachmentType type of Attachment e.g. AUDIO, VIDEO, .. | |
| 26 | + * @param caption caption of that attachment | |
| 27 | + */ | |
| 28 | + public TelegramAttachment(final Long id, final AttachmentType attachmentType, final String caption, final String fileURI){ | |
| 29 | + this.attachmentType = attachmentType; | |
| 30 | + this.caption = caption; | |
| 31 | + this.id = id; | |
| 32 | + this.fileURI = fileURI; | |
| 33 | + } | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * Constructor | |
| 37 | + * @param attachmentType type of Attachment e.g. AUDIO, VIDEO, .. | |
| 38 | + */ | |
| 39 | + public TelegramAttachment(final AttachmentType attachmentType){ | |
| 40 | + this.attachmentType = attachmentType; | |
| 41 | + } | |
| 42 | + | |
| 43 | + @Override | |
| 44 | + public Long getId() { | |
| 45 | + return id; | |
| 46 | + } | |
| 47 | + | |
| 48 | + @Override | |
| 49 | + public String getFileURI() { | |
| 50 | + return fileURI; | |
| 51 | + } | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public AttachmentType getAttachmentType() { | |
| 55 | + return attachmentType; | |
| 56 | + } | |
| 57 | + | |
| 58 | + @Override | |
| 59 | + public String getCaption() { | |
| 60 | + return caption; | |
| 61 | + } | |
| 62 | + | |
| 63 | +} | ... | ... |
services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/model/TelegramMessage.java
0 → 100755
| 1 | +++ a/services/Telegram/src/main/java/de/bht/beuthbot/messenger/telegram/model/TelegramMessage.java | |
| 1 | +package de.bht.beuthbot.messenger.telegram.model; | |
| 2 | + | |
| 3 | +import com.pengrad.telegrambot.model.Message; | |
| 4 | +import de.bht.beuthbot.jms.ProcessQueueMessageProtocol; | |
| 5 | +import de.bht.beuthbot.jms.Target; | |
| 6 | +import de.bht.beuthbot.model.Attachment; | |
| 7 | +import de.bht.beuthbot.model.Messenger; | |
| 8 | +import de.bht.beuthbot.utils.GsonUtils; | |
| 9 | + | |
| 10 | +import java.util.ArrayList; | |
| 11 | +import java.util.Collections; | |
| 12 | +import java.util.List; | |
| 13 | +import java.util.Map; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * @Author: Christopher Kümmel on 6/15/2017. | |
| 17 | + */ | |
| 18 | +public class TelegramMessage implements ProcessQueueMessageProtocol{ | |
| 19 | + | |
| 20 | + /** com.pengrad.telegrambot.model.Message */ | |
| 21 | + private Message message; | |
| 22 | + | |
| 23 | + /** Attachment[] */ | |
| 24 | + private List<Attachment> attachments; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * Constructor | |
| 28 | + * @param message com.pengrad.telegrambot.model.Message | |
| 29 | + */ | |
| 30 | + public TelegramMessage(final Message message){ | |
| 31 | + this.message = message; | |
| 32 | + } | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public Long getId() { | |
| 36 | + return 1L; | |
| 37 | + } | |
| 38 | + | |
| 39 | + @Override | |
| 40 | + public Target getTarget() { | |
| 41 | + return Target.NTSP; | |
| 42 | + } | |
| 43 | + | |
| 44 | + @Override | |
| 45 | + public Long getMessageID() { | |
| 46 | + return Long.valueOf(message.messageId()); | |
| 47 | + } | |
| 48 | + | |
| 49 | + @Override | |
| 50 | + public Long getSenderID() { | |
| 51 | + return message.chat().id(); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @Override | |
| 55 | + public Messenger getMessenger() { | |
| 56 | + return Messenger.TELEGRAM; | |
| 57 | + } | |
| 58 | + | |
| 59 | + @Override | |
| 60 | + public String getText() { | |
| 61 | + return message.text(); | |
| 62 | + } | |
| 63 | + | |
| 64 | + @Override | |
| 65 | + public boolean hasAttachments() { | |
| 66 | + return (attachments != null); | |
| 67 | + } | |
| 68 | + | |
| 69 | + @Override | |
| 70 | + public List<Attachment> getAttachments() { | |
| 71 | + return attachments; | |
| 72 | + } | |
| 73 | + | |
| 74 | + @Override | |
| 75 | + public String getIntent() { | |
| 76 | + return null; | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + public Map<String, String> getEntities() { | |
| 81 | + return Collections.emptyMap(); | |
| 82 | + } | |
| 83 | + | |
| 84 | + /** | |
| 85 | + * Setter for Attachment[] | |
| 86 | + * @param attachments | |
| 87 | + */ | |
| 88 | + public void setAttachments(final Attachment[] attachments){ | |
| 89 | + this.attachments = new ArrayList<>(attachments.length); | |
| 90 | + for (Attachment attachment : attachments) { | |
| 91 | + this.attachments.add(attachment); | |
| 92 | + } | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + public String toString() { | |
| 97 | + return GsonUtils.toJson(this); | |
| 98 | + } | |
| 99 | +} | ... | ... |
services/Telegram/src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/services/Telegram/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
settings.gradle
0 → 100755
| 1 | +++ a/settings.gradle | |
| 1 | +include ( | |
| 2 | + 'services:Common', | |
| 3 | + 'services:Global', | |
| 4 | + 'services:FaceBook', | |
| 5 | + 'services:ApiAi', | |
| 6 | + 'services:Rasa', | |
| 7 | + 'services:Bing', | |
| 8 | + 'services:MainBot', | |
| 9 | + 'services:LoggingStatistics', | |
| 10 | + 'services:Telegram' | |
| 11 | +) | |
| 0 | 12 | \ No newline at end of file | ... | ... |
src/main/plantuml/architecture.puml
0 → 100755
| 1 | +++ a/src/main/plantuml/architecture.puml | |
| 1 | +@startuml | |
| 2 | + | |
| 3 | +package stage1 as "Adapter" { | |
| 4 | +[FacebookMessenger] | |
| 5 | +[Telegram] | |
| 6 | +} | |
| 7 | + | |
| 8 | +package stage2 as "Message Interpreter" { | |
| 9 | + [Text <--> Speech] | |
| 10 | + [Image recognition] | |
| 11 | + [Translation] | |
| 12 | + [Translation] | |
| 13 | +} | |
| 14 | + | |
| 15 | +package stage3 as "MainBot" { | |
| 16 | +[UserManagement] | |
| 17 | +[Answer Generator] - Tagger | |
| 18 | +[Answer Generator] -- [WebServices] | |
| 19 | +} | |
| 20 | + | |
| 21 | +queue queue as "JMS Message Queue" | |
| 22 | + | |
| 23 | +queue -up- stage1 | |
| 24 | +queue -left- stage2 | |
| 25 | +queue -down- stage3 | |
| 26 | + | |
| 27 | +@enduml | |
| 0 | 28 | \ No newline at end of file | ... | ... |
src/main/plantuml/model.puml
0 → 100755
| 1 | +++ a/src/main/plantuml/model.puml | |
| 1 | +@startuml | |
| 2 | +enum Messenger | |
| 3 | + | |
| 4 | +class Message { | |
| 5 | + ID: Long | |
| 6 | + messageID: String | |
| 7 | + senderID: String | |
| 8 | + messenger: Messenger | |
| 9 | + text: String | |
| 10 | + attechments: Attachment[] | |
| 11 | +} | |
| 12 | + | |
| 13 | +Message - Messenger | |
| 14 | +Message -- Attachment | |
| 15 | + | |
| 16 | +@enduml | |
| 0 | 17 | \ No newline at end of file | ... | ... |
src/main/webapp/WEB-INF/beans.xml
0 → 100755
| 1 | +++ a/src/main/webapp/WEB-INF/beans.xml | |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<!-- | |
| 3 | + JBoss, Home of Professional Open Source | |
| 4 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 5 | + contributors by the @authors tag. See the copyright.txt in the | |
| 6 | + distribution for a full listing of individual contributors. | |
| 7 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 8 | + you may not use this file except in compliance with the License. | |
| 9 | + You may obtain a copy of the License at | |
| 10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 11 | + Unless required by applicable law or agreed to in writing, software | |
| 12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | + See the License for the specific language governing permissions and | |
| 15 | + limitations under the License. | |
| 16 | +--> | |
| 17 | +<!-- Marker file indicating CDI should be enabled --> | |
| 18 | +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 19 | + xsi:schemaLocation=" | |
| 20 | + http://xmlns.jcp.org/xml/ns/javaee | |
| 21 | + http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" | |
| 22 | + bean-discovery-mode="all"> | |
| 23 | +</beans> | |
| 0 | 24 | \ No newline at end of file | ... | ... |
src/main/webapp/index.html
0 → 100755
| 1 | +++ a/src/main/webapp/index.html | |
| 1 | +<!-- | |
| 2 | + JBoss, Home of Professional Open Source | |
| 3 | + Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual | |
| 4 | + contributors by the @authors tag. See the copyright.txt in the | |
| 5 | + distribution for a full listing of individual contributors. | |
| 6 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 7 | + you may not use this file except in compliance with the License. | |
| 8 | + You may obtain a copy of the License at | |
| 9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | + Unless required by applicable law or agreed to in writing, software | |
| 11 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 | + See the License for the specific language governing permissions and | |
| 14 | + limitations under the License. | |
| 15 | +--> | |
| 16 | +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | |
| 17 | +<html> | |
| 18 | +<head> | |
| 19 | + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
| 20 | + <title>helloworld-rs</title> | |
| 21 | +</head> | |
| 22 | +<body> | |
| 23 | + | |
| 24 | +<p>Choose between <em>JSON</em> or <em>XML</em>: | |
| 25 | + | |
| 26 | +<ul> | |
| 27 | + <li><a href="rest/json">JSON</a></li> | |
| 28 | + <li><a href="rest/xml">XML</a></li> | |
| 29 | +</ul> | |
| 30 | +</body> | |
| 31 | +</html> | |
| 0 | 32 | \ No newline at end of file | ... | ... |
src/test/resources/arquillian.xml
0 → 100755
| 1 | +++ a/src/test/resources/arquillian.xml | |
| 1 | +<arquillian xmlns="http://jboss.org/schema/arquillian" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 2 | + xsi:schemaLocation=" | |
| 3 | + http://jboss.org/schema/arquillian | |
| 4 | + http://jboss.org/schema/arquillian/arquillian_1_0.xsd"> | |
| 5 | + | |
| 6 | + <!-- Sets the protocol which is how Arquillian talks and executes the tests inside the container --> | |
| 7 | + <defaultProtocol type="Servlet 3.0" /> | |
| 8 | + | |
| 9 | + <!-- Configuration to be used when the WidlFly remote profile is active --> | |
| 10 | + <container qualifier="wildfly-remote" default="true"> | |
| 11 | + <configuration> | |
| 12 | + <property name="managementAddress">localhost</property> | |
| 13 | + <property name="managementPort">9990</property> | |
| 14 | + <property name="username">admin</property> | |
| 15 | + <property name="password">Admin</property> | |
| 16 | + </configuration> | |
| 17 | + </container> | |
| 18 | + | |
| 19 | +</arquillian> | |
| 0 | 20 | \ No newline at end of file | ... | ... |