Commit aa62787f6ca23d814c166b762bec959e5a53852b

Authored by Thomas Ziemer
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
  1 +++ a/docker/rasa_nlu/rasa_config.json
  1 +{
  2 + "pipeline": "spacy_sklearn",
  3 + "num_threads": 2,
  4 + "language": "de",
  5 + "path": "/app/models",
  6 + "data": "/app/data/api",
  7 + "response_log": "/app/logs"
  8 +}
... ...
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
  1 +++ a/docker/wildfly/Dockerfile
  1 +FROM jboss/wildfly:10.1.0.Final
  2 +RUN /opt/jboss/wildfly/bin/add-user.sh admin Admin
  3 +COPY standalone.xml /opt/jboss/wildfly/standalone/configuration/standalone.xml
0 4 \ No newline at end of file
... ...
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
  1 +++ a/docker/wildfly/volumes/conf/README.md
  1 +## Conf Directory
  2 +This is the conf directory which holds the BeuthBot runtime configuration and will be mounted into the docker wildfly container.
0 3 \ No newline at end of file
... ...
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
  1 +++ a/docker/wildfly/volumes/deployments/README.md
  1 +## Deployment Directory
  2 +This is the deployment directory which will be mounted into the docker wildfly container.
0 3 \ No newline at end of file
... ...
docker/wildfly/volumes/logs/README.md 0 → 100755
  1 +++ a/docker/wildfly/volumes/logs/README.md
  1 +## Log Directory
  2 +This is the log directory which will be mounted into the docker wildfly container.
0 3 \ No newline at end of file
... ...
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 +![Azure Registration](img/bing/azure-registration.png)
  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 + ![Billing Menu](img/bing/billing-menu.png)
  44 +
  45 + - Click on that ![Manage Button](img/bing/manage-btn.png) 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 +![Create Service](img/bing/create-new-bing-speech-service.png)
  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 +![Bing Speech Service](img/bing/bing-speech-service-dashboard.png)
  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
  1 +++ a/scripts/deployment.sh
  1 +#!/usr/bin/env bash
  2 +./gradlew war
  3 +cd src/main/docker
  4 +docker-compose down && docker-compose up --build -d
0 5 \ No newline at end of file
... ...
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
  1 +++ a/services/Common/src/main/java/de/bht/beuthbot/jms/Target.java
  1 +package de.bht.beuthbot.jms;
  2 +
  3 +/**
  4 + * @author: georg.glossmann@adesso.de
  5 + * Date: 06.07.17
  6 + */
  7 +public enum Target {
  8 + MESSENGER, NTSP, MAINBOT
  9 +}
... ...
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
  1 +++ a/services/Common/src/main/java/de/bht/beuthbot/model/AttachmentType.java
  1 +package de.bht.beuthbot.model;
  2 +
  3 +/**
  4 + * Created by Chris on 5/22/2017.
  5 + */
  6 +public enum AttachmentType {
  7 + AUDIO, VIDEO, VOICE, DOCUMENT, PHOTO, UNKOWN
  8 +}
... ...
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
  1 +++ a/services/Common/src/main/java/de/bht/beuthbot/model/Messenger.java
  1 +package de.bht.beuthbot.model;
  2 +
  3 +/**
  4 + * Created by Chris on 5/14/2017.
  5 + */
  6 +public enum Messenger {
  7 + TELEGRAM, FACEBOOK
  8 +}
... ...
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
  1 +++ a/services/Global/src/main/webapp/WEB-INF/jboss-web.xml
  1 +<jboss-web>
  2 + <context-root>/</context-root>
  3 +</jboss-web>
0 4 \ No newline at end of file
... ...
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
... ...