diff --git a/README.md b/README.md index 875910c..092348d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ write your own voice application fast. ## Top features - Dialogflow V2 API reference implementation written in Kotlin +- Multiplatform support, one service for Alexa and Google Assistant - Intercepter API for adding e.g. tracking - Spring reference implementation - SSML builder for creating rich responses @@ -110,6 +111,57 @@ the spring-sample project as template for your own project. When you use our plu injection. The best it that we use it also for discovering your intent handler automatically. For the fallback intent you should use the annotation `@FallbackIntentHandler`, if it is missing you service won't start up. +## Adding Multiplatform Support + +You can add the Alexa plugin to build a service which can serve Alexa and the Google Assistant at once. You just have +to change your IntentHandler to implement the MultiplatformIntentHandler. + + class WelcomeIntentHandler : MultiPlatformIntentHandler { + + override fun canHandleAlexa(input: HandlerInput) = + input.matches(Predicates.requestType(LaunchRequest::class.java)) + + override fun handleAlexa(input: HandlerInput): Optional { + return input.responseBuilder + .withSpeech("Welcome to Dialog!") + .build() + } + + override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { + return handler.action?.equals("input.welcome") ?: false + } + + override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { + return handler.responseBuilder.withText("Welcome to Dialog!") + } + } + +If you're using Dialog with Spring you can add the `alexa-spring-plugin` which will automatically provide a Bean of +`IntentHandlerHolder`. This call contains the list of all Alexa `RequestHandler` which can be added to the +`CustomSkillBuilder` like in the following example. + + @Configuration + class AlexaConfig { + + @Bean + fun provideSkill( + intentHandlerHolder: IntentHandlerConfig.IntentHandlerHolder, + interceptorHolder: InterceptorConfig.InterceptorHolder + ): Skill = + CustomSkillBuilder() + .addRequestHandlers(intentHandlerHolder.intentHandlers) + .apply { + interceptorHolder.requestInterceptors.forEach { + addRequestInterceptor(it) + } + interceptorHolder.responseInterceptors.forEach { + addResponseInterceptor(it) + } + } + .withApiClient(ApacheHttpApiClient.standard()) + .build() + } + ## License The MIT license (MIT) @@ -142,4 +194,4 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR [DialogflowIntentHandler]: docs/core/org.rewedigital.dialog.handler/-dialogflow-intent-handler/index.md [intent-methods]: docs/core/org.rewedigital.dialog.handler/-dialogflow-intent-handler/index.md#Functions [ResponseBuilder]: docs/core/org.rewedigital.dialog.handler/-dialogflow-response-builder/index.md -[RequestInterceptor]: docs/core/org.rewedigital.dialog.interceptors/-request-interceptor/index.md +[RequestInterceptor]: docs/core/org.rewedigital.dialog.interceptors/-request-interceptor/index.md \ No newline at end of file diff --git a/alexa-plugin/build.gradle b/alexa-plugin/build.gradle new file mode 100644 index 0000000..4a9eb2a --- /dev/null +++ b/alexa-plugin/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'kotlin' +apply from: '../docu.gradle' + +group 'org.rewedigital.voice.dialog' +version rootProject.ext.versions.alexa +description 'The Alexa plugin for Dialog to write voice applications for Dialogflow and Alexa.' + +dependencies { + implementation project(":core") + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + implementation "com.amazon.alexa:ask-sdk-core:2.11.2" +} + +dokka { + externalDocumentationLink { + url = new URL("https://github.com/rewe-digital-incubator/${rootProject.name}/blob/master/docs/core/") + packageListUrl = java.nio.file.Paths.get("$rootDir/docs/core/package-list").toUri().toURL() + } +} + +task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { + outputFormat = 'javadoc' + outputDirectory = "$buildDir/javadoc" +} + +apply from: '../publish.gradle' \ No newline at end of file diff --git a/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformIntentHandler.kt b/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformIntentHandler.kt new file mode 100644 index 0000000..842d098 --- /dev/null +++ b/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformIntentHandler.kt @@ -0,0 +1,19 @@ +package org.rewedigital.dialog.alexa + +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.dispatcher.request.handler.RequestHandler +import com.amazon.ask.model.Response +import org.rewedigital.dialog.handler.DialogflowIntentHandler +import java.util.* + + +interface MultiPlatformIntentHandler : DialogflowIntentHandler, RequestHandler { + + override fun canHandle(input: HandlerInput) = canHandleAlexa(input) + + override fun handle(input: HandlerInput) = handleAlexa(input) + + fun canHandleAlexa(input: HandlerInput): Boolean + + fun handleAlexa(input: HandlerInput): Optional +} \ No newline at end of file diff --git a/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformRequestInterceptor.kt b/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformRequestInterceptor.kt new file mode 100644 index 0000000..83e3fa9 --- /dev/null +++ b/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformRequestInterceptor.kt @@ -0,0 +1,13 @@ +package org.rewedigital.dialog.alexa + +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import org.rewedigital.dialog.interceptors.RequestInterceptor + + +interface MultiPlatformRequestInterceptor : RequestInterceptor, + com.amazon.ask.dispatcher.request.interceptor.RequestInterceptor { + + override fun process(input: HandlerInput) = onAlexaRequest(input) + + fun onAlexaRequest(input: HandlerInput) +} \ No newline at end of file diff --git a/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformResponseInterceptor.kt b/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformResponseInterceptor.kt new file mode 100644 index 0000000..0d138ad --- /dev/null +++ b/alexa-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/MultiPlatformResponseInterceptor.kt @@ -0,0 +1,15 @@ +package org.rewedigital.dialog.alexa + +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import org.rewedigital.dialog.interceptors.ResponseInterceptor +import java.util.* + + +interface MultiPlatformResponseInterceptor : ResponseInterceptor, + com.amazon.ask.dispatcher.request.interceptor.ResponseInterceptor { + + override fun process(input: HandlerInput, response: Optional) = onAlexaResponse(input, response) + + fun onAlexaResponse(input: HandlerInput, response: Optional) +} \ No newline at end of file diff --git a/alexa-spring-plugin/build.gradle b/alexa-spring-plugin/build.gradle new file mode 100644 index 0000000..e67fdd4 --- /dev/null +++ b/alexa-spring-plugin/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'kotlin' +apply plugin: 'kotlin-spring' +apply from: '../docu.gradle' + +group 'org.rewedigital.voice.dialog' +version rootProject.ext.versions.alexa +description 'The Alexa plugin for the Spring plugin of Dialog.' + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath("org.jetbrains.kotlin:kotlin-allopen:${rootProject.ext.versions.kotlin}") + } +} + +dependencies { + implementation project(':core') + implementation project(':alexa-plugin') + implementation project(':spring-plugin') + + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + implementation 'org.jetbrains.kotlin:kotlin-reflect' + implementation 'org.springframework:spring-context:5.1.4.RELEASE' + implementation 'com.amazon.alexa:ask-sdk-core:2.11.2' +} + +task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { + outputFormat = 'javadoc' + outputDirectory = "$buildDir/javadoc" +} + +apply from: '../publish.gradle' \ No newline at end of file diff --git a/alexa-spring-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/spring/IntentHandlerConfig.kt b/alexa-spring-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/spring/IntentHandlerConfig.kt new file mode 100644 index 0000000..2d69bb1 --- /dev/null +++ b/alexa-spring-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/spring/IntentHandlerConfig.kt @@ -0,0 +1,29 @@ +package org.rewedigital.dialog.alexa.spring + +import com.amazon.ask.dispatcher.request.handler.RequestHandler +import org.rewedigital.dialog.spring.annotations.IntentHandler +import org.springframework.context.ApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import java.lang.instrument.IllegalClassFormatException + + +@Configuration +class IntentHandlerConfig { + + data class IntentHandlerHolder(val intentHandlers: List) + + @Bean + fun provideIntentHandlerHolder(context: ApplicationContext): IntentHandlerHolder { + + val allIntentHandler = + context + .getBeanNamesForAnnotation(IntentHandler::class.java) + .map { + context.getBean(it) as? RequestHandler + ?: throw IllegalClassFormatException("Your IntentHandler must implement the interface MultiPlatformIntentHandler") + } + + return IntentHandlerHolder(allIntentHandler) + } +} \ No newline at end of file diff --git a/alexa-spring-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/spring/InterceptorConfig.kt b/alexa-spring-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/spring/InterceptorConfig.kt new file mode 100644 index 0000000..a5a2320 --- /dev/null +++ b/alexa-spring-plugin/src/main/kotlin/org/rewedigital/dialog/alexa/spring/InterceptorConfig.kt @@ -0,0 +1,40 @@ +package org.rewedigital.dialog.alexa.spring + +import com.amazon.ask.dispatcher.request.interceptor.RequestInterceptor +import com.amazon.ask.dispatcher.request.interceptor.ResponseInterceptor +import org.rewedigital.dialog.spring.annotations.Interceptor +import org.springframework.context.ApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + + +@Configuration +class InterceptorConfig { + + data class InterceptorHolder( + val requestInterceptors: List, + val responseInterceptors: List + ) + + @Bean + fun provideInterceptorHolder(context: ApplicationContext): InterceptorHolder { + + val requestInterceptors = mutableListOf() + val responseInterceptors = mutableListOf() + + context.getBeanNamesForAnnotation(Interceptor::class.java) + .forEach { beanName -> + context.getBean(beanName) + .also { bean -> + if (bean is RequestInterceptor) { + requestInterceptors.add(bean) + } + if (bean is ResponseInterceptor) { + responseInterceptors.add(bean) + } + } + } + + return InterceptorHolder(requestInterceptors, responseInterceptors) + } +} \ No newline at end of file diff --git a/alexa-spring-plugin/src/main/resources/META-INF/spring.factories b/alexa-spring-plugin/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..1847672 --- /dev/null +++ b/alexa-spring-plugin/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.rewedigital.dialog.alexa.spring.IntentHandlerConfig,org.rewedigital.dialog.alexa.spring.InterceptorConfig \ No newline at end of file diff --git a/build.gradle b/build.gradle index b6baeaf..353b9a6 100644 --- a/build.gradle +++ b/build.gradle @@ -5,21 +5,23 @@ buildscript { ext.versions = [:] ext.versions.kotlin = '1.3.21' ext.versions.dokka = '0.9.17' - ext.versions.core = '1.0' - ext.versions.ssml = '1.0' - ext.versions.ssml_plugin = '1.0' - ext.versions.spring_plugin = '1.0' - ext.versions.konversation_plugin = '1.0' + ext.versions.core = '1.0.1' + ext.versions.alexa = '1.0.1' + ext.versions.ssml = '1.0.1' + ext.versions.ssml_plugin = '1.0.1' + ext.versions.spring_plugin = '1.0.1' + ext.versions.konversation_plugin = '1.0.1' repositories { mavenLocal() jcenter() + maven { url 'https://novoda.bintray.com/snapshots' } } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0' classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}" - classpath 'com.novoda:bintray-release:0.9' + classpath 'com.novoda:bintray-release:SNAPSHOT-13' } } diff --git a/core/build.gradle b/core/build.gradle index 6e98326..3a8f66a 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,10 +1,9 @@ apply plugin: 'kotlin' -apply plugin: 'maven-publish' -apply plugin: 'com.novoda.bintray-release' apply from: '../docu.gradle' -group "org.rewedigital.voice" -version "${rootProject.ext.versions.core}" +group 'org.rewedigital.voice:dialog' +version rootProject.ext.versions.core +description 'Dialog is a Dialogflow v2 API implementation written in Kotlin. With some great optional extensions you can use to write your own voice applications fast.' dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" @@ -15,71 +14,4 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { outputDirectory = "$buildDir/javadoc" } -task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier = 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { - archiveClassifier = 'javadoc' - from "$buildDir/javadoc" -} - -publishing.publications { - core(MavenPublication) { - groupId = "org.rewedigital.voice" - artifactId = "dialog" - version = "${rootProject.ext.versions.core}" - artifact sourcesJar { - archiveClassifier = 'sources' - } - artifact javadocJar { - archiveClassifier = 'javadoc' - } - from components.java - pom { - name = 'dialog' - description = 'Dialog is a Dialogflow v2 API implementation written in Kotlin. With some great optional extensions you can use to write your own voice application fast.' - url = 'https://github.com/rewe-digital-incubator/dialog' - licenses { - license { - name = 'MIT License' - url = 'https://opensource.org/licenses/MIT' - distribution = 'repo' - } - } - developers { - // TODO use the MAINTAINERS file - developer { - name = 'Volkmar Vogel' - email = 'volkmar.vogel@rewe-digital.com' - } - developer { - name = 'René Kilczan' - email = 'rene.kilczan@rewe-digital.com' - } - } - - scm { - connection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - developerConnection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - url = 'https://github.com/rewe-digital-incubator/dialog' - } - } - } -} - -publish { - userOrg = 'rewe-digital' - groupId = 'org.rewedigital.voice' - artifactId = 'core' - repoName = 'dialog' - publishVersion = rootProject.ext.versions.core - desc = 'Dialog is a Dialogflow v2 API implementation written in Kotlin. With some great optional extensions you can use to write your own voice applications fast.' - website = 'https://github.com/rewe-digital-incubator/dialog' - licences = ['MIT'] - bintrayUser = project.properties['bintray.user'] - bintrayKey = project.properties['bintray.apikey'] - dryRun = false - publications = ['core'] -} \ No newline at end of file +apply from: '../publish.gradle' \ No newline at end of file diff --git a/konversation-plugin/build.gradle b/konversation-plugin/build.gradle index cf58c90..9588c72 100644 --- a/konversation-plugin/build.gradle +++ b/konversation-plugin/build.gradle @@ -1,14 +1,14 @@ -group 'org.rewedigital.voice' -version rootProject.ext.versions.konversation_plugin - apply plugin: 'kotlin' -apply plugin: 'maven-publish' apply from: '../docu.gradle' -apply plugin: 'com.novoda.bintray-release' + +group 'org.rewedigital.voice.dialog' +version rootProject.ext.versions.konversation_plugin +description 'This is the Konversation plugin for Dialog to write voice applications fast.' dependencies { + implementation project(":core") + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - implementation "org.rewedigital.voice:dialog:${rootProject.ext.versions.core}" compile 'org.rewedigital.voice:konversation:1.0-rc1' } @@ -17,66 +17,4 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { outputDirectory = "$buildDir/javadoc" } -task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier = 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { - archiveClassifier = 'javadoc' - from "$buildDir/javadoc" -} - -publishing.publications { - konversationPlugin(MavenPublication) { - groupId = 'org.rewedigital.voice.dialog' - artifactId = 'konversation-plugin' - from components.java - version = "${rootProject.ext.versions.core}" - artifact sourcesJar { - archiveClassifier = 'sources' - } - artifact javadocJar { - archiveClassifier = 'javadoc' - } - pom { - name = 'dialog' - description = 'This is the Konversation plugin for Dialog to write voice applications fast.' - url = 'https://github.com/rewe-digital-incubator/dialog' - licenses { - license { - name = 'MIT License' - url = 'https://opensource.org/licenses/MIT' - distribution = 'repo' - } - } - developers { - developer { - name = 'René Kilczan' - email = 'rene.kilczan@rewe-digital.com' - } - } - - scm { - connection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - developerConnection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - url = 'https://github.com/rewe-digital-incubator/dialog' - } - } - } -} - -publish { - userOrg = 'rewe-digital' - groupId = 'org.rewedigital.voice.dialog' - artifactId = 'konversation-plugin' - repoName = 'dialog' - publishVersion = rootProject.ext.versions.core - desc = 'This is the Konversation plugin for Dialog to write voice applications fast.' - website = 'https://github.com/rewe-digital-incubator/dialog' - licences = ['MIT'] - bintrayUser = project.properties['bintray.user'] - bintrayKey = project.properties['bintray.apikey'] - dryRun = false - publications = ['konversationPlugin'] -} \ No newline at end of file +apply from: '../publish.gradle' \ No newline at end of file diff --git a/publish.gradle b/publish.gradle new file mode 100644 index 0000000..5327aa6 --- /dev/null +++ b/publish.gradle @@ -0,0 +1,84 @@ +apply plugin: 'com.novoda.bintray-release' + +// small hack to override the artifact ID via group name, if it is clean the project name will be used as artifactId +def groupID, artifactID +if (project.group.contains(":")) { + (groupID, artifactID) = project.group.split(":") +} else { + groupID = project.group + artifactID = project.name +} + +logger.info("desc: " + project.description) +logger.info("group: " + groupID) +logger.info("version: " + project.version) +logger.info("artifactId: " + artifactID) + +task sourcesJar(type: Jar, dependsOn: classes) { + archiveClassifier = 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { + archiveClassifier = 'javadoc' + from "$buildDir/javadoc" +} + +publish { + userOrg = 'rewe-digital' + groupId = groupID + artifactId = artifactID + repoName = rootProject.name + publishVersion = project.version + desc = project.description + bintrayUser = project.properties['bintray.user'] + bintrayKey = project.properties['bintray.apikey'] + dryRun = false + publications = ['maven'] +} + +publishing.publications { + maven(MavenPublication) { + groupId = groupID + artifactId = artifactID + from components.java + version = project.version + artifact sourcesJar { + archiveClassifier = 'sources' + } + artifact javadocJar { + archiveClassifier = 'javadoc' + } + + pom { + name = project.name + description = project.description + url = "https://rewe-digital-incubator.github.io/${rootProject.name}/${project.name}" + licenses { + license { + name = 'MIT License' + url = 'https://opensource.org/licenses/MIT' + distribution = 'repo' + } + } + developers { + def maintainers = [:] + file("$rootDir/MAINTAINERS").text.eachLine { line -> + def (name, mail) = line.split('<') + maintainers[name.trim()] = mail.replace('>', '').trim() + } + maintainers.entrySet().forEach { dev -> + developer { + name = dev.key + email = dev.value + } + } + } + scm { + connection = "scm:git:git://github.com/rewe-digital-incubator/${rootProject.name}.git" + developerConnection = "scm:git:git://github.com/rewe-digital-incubator/${rootProject.name}.git" + url = "https://github.com/rewe-digital-incubator/${rootProject.name}" + } + } + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 8a6e1e6..8dde0c3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,6 @@ include 'ssml' include 'ssml-plugin' include 'spring-sample' include 'spring-plugin' -include 'konversation-plugin' \ No newline at end of file +include 'konversation-plugin' +include 'alexa-plugin' +include 'alexa-spring-plugin' \ No newline at end of file diff --git a/spring-plugin/build.gradle b/spring-plugin/build.gradle index b22f263..bdcd3cb 100644 --- a/spring-plugin/build.gradle +++ b/spring-plugin/build.gradle @@ -1,8 +1,3 @@ -import java.nio.file.Paths - -group 'org.rewedigital.voice.dialog' -version rootProject.ext.versions.spring_plugin - buildscript { repositories { jcenter() @@ -14,21 +9,24 @@ buildscript { apply plugin: 'kotlin' apply plugin: 'kotlin-spring' -apply plugin: 'maven-publish' apply from: '../docu.gradle' -apply plugin: 'com.novoda.bintray-release' + +group 'org.rewedigital.voice.dialog' +version rootProject.ext.versions.spring_plugin +description 'This is the Spring plugin from Dialog to write voice applications fast.' dependencies { - implementation "org.rewedigital.voice:dialog:${rootProject.ext.versions.core}" - implementation "org.jetbrains.kotlin:kotlin-reflect" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - implementation "org.springframework:spring-context:5.1.4.RELEASE" + implementation project(':core') + + implementation 'org.jetbrains.kotlin:kotlin-reflect' + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' + implementation 'org.springframework:spring-context:5.1.4.RELEASE' } dokka { externalDocumentationLink { url = new URL("https://github.com/rewe-digital-incubator/${rootProject.name}/blob/master/docs/core/") - packageListUrl = Paths.get("$rootDir/docs/core/package-list").toUri().toURL() + packageListUrl = java.nio.file.Paths.get("$rootDir/docs/core/package-list").toUri().toURL() } externalDocumentationLink { url = new URL("https://docs.spring.io/spring-framework/docs/current/javadoc-api/") @@ -41,71 +39,4 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { outputDirectory = "$buildDir/javadoc" } -task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier = 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { - archiveClassifier = 'javadoc' - from "$buildDir/javadoc" -} - -publishing.publications { - springPlugin(MavenPublication) { - groupId = 'org.rewedigital.voice.dialog' - artifactId = 'spring-plugin' - from components.java - version = "${rootProject.ext.versions.core}" - artifact sourcesJar { - archiveClassifier = 'sources' - } - artifact javadocJar { - archiveClassifier = 'javadoc' - } - pom { - name = 'dialog' - description = 'This is the Spring plugin from Dialog to write voice applications fast.' - url = 'https://github.com/rewe-digital-incubator/dialog' - licenses { - license { - name = 'MIT License' - url = 'https://opensource.org/licenses/MIT' - distribution = 'repo' - } - } - developers { - // TODO use the MAINTAINERS file - developer { - name = 'Volkmar Vogel' - email = 'volkmar.vogel@rewe-digital.com' - } - developer { - name = 'René Kilczan' - email = 'rene.kilczan@rewe-digital.com' - } - } - - scm { - connection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - developerConnection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - url = 'https://github.com/rewe-digital-incubator/dialog' - } - } - } -} - -publish { - userOrg = 'rewe-digital' - groupId = 'org.rewedigital.voice' - artifactId = 'spring-plugin' - repoName = 'dialog' - publishVersion = rootProject.ext.versions.core - desc = 'Dialog is a Dialogflow v2 API implementation written in Kotlin. With some great optional extensions you can use to write your own voice application fast.' - website = 'https://github.com/rewe-digital-incubator/dialog' - licences = ['MIT'] - bintrayUser = project.properties['bintray.user'] - bintrayKey = project.properties['bintray.apikey'] - dryRun = false - publications = ['springPlugin'] -} \ No newline at end of file +apply from: '../publish.gradle' \ No newline at end of file diff --git a/spring-sample/build.gradle b/spring-sample/build.gradle index 398b5e9..9a458b2 100644 --- a/spring-sample/build.gradle +++ b/spring-sample/build.gradle @@ -1,7 +1,5 @@ -import java.nio.file.Paths - -group = 'org.rewedigital.voice' -version = '1.0.0-SNAPSHOT' +group 'org.rewedigital.voice' +version '1.0.0-SNAPSHOT' buildscript { ext { @@ -21,7 +19,6 @@ apply plugin: 'kotlin-spring' apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' -apply from: '../docu.gradle' sourceCompatibility = 1.8 compileKotlin { @@ -37,31 +34,27 @@ compileTestKotlin { } } -repositories { - mavenCentral() -} - dependencies { - implementation('org.rewedigital.voice:dialog:1.0') - implementation('org.rewedigital.voice:ssml-builder:1.0') - implementation('org.rewedigital.voice.dialog:ssml-plugin:1.0') - implementation('org.rewedigital.voice.dialog:spring-plugin:1.0') - implementation('org.rewedigital.voice.dialog:konversation-plugin:1.0') + def askSdkVersion = '2.11.2' + + implementation project(':core') + implementation project(':ssml') + implementation project(':ssml-plugin') + implementation project(':spring-plugin') + implementation project(':konversation-plugin') + implementation project(':alexa-plugin') + implementation project(':alexa-spring-plugin') implementation('org.springframework.boot:spring-boot-starter-web') implementation('com.fasterxml.jackson.module:jackson-module-kotlin') - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - implementation("org.jetbrains.kotlin:kotlin-reflect") + implementation('org.jetbrains.kotlin:kotlin-stdlib-jdk8') + implementation('org.jetbrains.kotlin:kotlin-reflect') + implementation("com.amazon.alexa:ask-sdk-core:$askSdkVersion") + implementation("com.amazon.alexa:ask-sdk-servlet-support:$askSdkVersion") + implementation("com.amazon.alexa:ask-sdk-apache-client:$askSdkVersion") testImplementation('org.springframework.boot:spring-boot-starter-test') } -dokka { - externalDocumentationLink { - url = new URL("https://github.com/rewe-digital-incubator/${rootProject.name}/blob/master/docs/core/") - packageListUrl = Paths.get("$rootDir/docs/core/package-list").toUri().toURL() - } - externalDocumentationLink { - url = new URL("https://github.com/rewe-digital-incubator/${rootProject.name}/blob/master/docs/spring-plugin/") - packageListUrl = Paths.get("$rootDir/docs/spring-plugin/package-list").toUri().toURL() - } +configurations { + all*.exclude module: 'spring-boot-starter-logging' } \ No newline at end of file diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/alexa/AlexaConfig.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/alexa/AlexaConfig.kt new file mode 100644 index 0000000..c5c5633 --- /dev/null +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/alexa/AlexaConfig.kt @@ -0,0 +1,31 @@ +package org.rewedigital.dialog.springsample.alexa + +import com.amazon.ask.Skill +import com.amazon.ask.builder.CustomSkillBuilder +import com.amazon.ask.services.ApacheHttpApiClient +import org.rewedigital.dialog.alexa.spring.IntentHandlerConfig +import org.rewedigital.dialog.alexa.spring.InterceptorConfig +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class AlexaConfig { + + @Bean + fun provideSkill( + intentHandlerHolder: IntentHandlerConfig.IntentHandlerHolder, + interceptorHolder: InterceptorConfig.InterceptorHolder + ): Skill = + CustomSkillBuilder() + .addRequestHandlers(intentHandlerHolder.intentHandlers) + .apply { + interceptorHolder.requestInterceptors.forEach { + addRequestInterceptor(it) + } + interceptorHolder.responseInterceptors.forEach { + addResponseInterceptor(it) + } + } + .withApiClient(ApacheHttpApiClient.standard()) + .build() +} \ No newline at end of file diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/alexa/ServletConfig.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/alexa/ServletConfig.kt new file mode 100644 index 0000000..8c78594 --- /dev/null +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/alexa/ServletConfig.kt @@ -0,0 +1,15 @@ +package org.rewedigital.dialog.springsample.alexa + +import com.amazon.ask.Skill +import com.amazon.ask.servlet.SkillServlet +import org.springframework.boot.web.servlet.ServletRegistrationBean +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class ServletConfig { + + @Bean + fun provideAlexaSkillServlet(skill: Skill) = + ServletRegistrationBean(SkillServlet(skill), "/alexaIntent") +} \ No newline at end of file diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/DialogflowIntentController.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/dialogflow/DialogflowIntentController.kt similarity index 94% rename from spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/DialogflowIntentController.kt rename to spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/dialogflow/DialogflowIntentController.kt index 42227a7..b9a436b 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/DialogflowIntentController.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/dialogflow/DialogflowIntentController.kt @@ -1,4 +1,4 @@ -package org.rewedigital.dialog.springsample +package org.rewedigital.dialog.springsample.dialogflow import org.rewedigital.dialog.model.dialogflow.WebhookRequest import org.rewedigital.dialog.model.dialogflow.WebhookResponse diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/FallbackIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/FallbackIntentHandler.kt index 01369ce..f87a40e 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/FallbackIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/FallbackIntentHandler.kt @@ -1,18 +1,21 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler -import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.spring.annotations.FallbackIntentHandler +import java.util.* @FallbackIntentHandler -class FallbackIntentHandler : DialogflowIntentHandler { +class FallbackIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return false - } + override fun canHandleAlexa(input: HandlerInput) = false - override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { - return handler.responseBuilder.withText("Fallback!!!") - } + override fun handleAlexa(input: HandlerInput): Optional = Optional.empty() + + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = false + + override fun handleDialogflowIntent(handler: DialogflowHandler) = + handler.responseBuilder.withText("Fallback!!!") } \ No newline at end of file diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/KonversationExampleIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/KonversationExampleIntentHandler.kt index 2ae659b..addd8f6 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/KonversationExampleIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/KonversationExampleIntentHandler.kt @@ -1,20 +1,26 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.spring.annotations.IntentHandler import org.rewedigital.dialog.utils.loadKonversation import org.rewedigital.dialog.utils.withGoogleReprompts import org.rewedigital.dialog.utils.withGoogleSimpleResponse import org.rewedigital.dialog.utils.withGoogleSuggestions +import java.util.* @IntentHandler -class KonversationExampleIntentHandler : DialogflowIntentHandler { +class KonversationExampleIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return handler.action?.equals("input.welcome2") ?: false - } + override fun canHandleAlexa(input: HandlerInput) = false + + override fun handleAlexa(input: HandlerInput): Optional = Optional.empty() + + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + handler.action?.equals("input.welcome2") ?: false override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionIntentHandler.kt index e644407..a8a4339 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionIntentHandler.kt @@ -1,17 +1,30 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import com.amazon.ask.request.Predicates +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.spring.annotations.IntentHandler +import org.rewedigital.dialog.ssml.SsmlBuilder +import java.util.* @IntentHandler -class LocationPermissionIntentHandler : DialogflowIntentHandler { +class LocationPermissionIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return handler.action?.equals("input.location_permission") ?: false - } + override fun canHandleAlexa(input: HandlerInput): Boolean = + input.matches(Predicates.intentName("input.location_permission")) + + override fun handleAlexa(input: HandlerInput): Optional = + input.responseBuilder + .withSpeech(SsmlBuilder("To use this feature we need your permission.").asSsmlString()) + .withAskForPermissionsConsentCard(listOf("read::alexa:device:all:address")) + .build() + + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + handler.action?.equals("input.location_permission") ?: false override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionResultIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionResultIntentHandler.kt index 680ced9..204a727 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionResultIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/LocationPermissionResultIntentHandler.kt @@ -1,17 +1,23 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.spring.annotations.IntentHandler +import java.util.* @IntentHandler -class LocationPermissionResultIntentHandler : DialogflowIntentHandler { +class LocationPermissionResultIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return handler.action?.equals("input.location_permission.result") ?: false - } + override fun canHandleAlexa(input: HandlerInput) = false + + override fun handleAlexa(input: HandlerInput): Optional = Optional.empty() + + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + handler.action?.equals("input.location_permission.result") ?: false override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/MoreUiElementsIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/MoreUiElementsIntentHandler.kt index 935b806..a134808 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/MoreUiElementsIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/MoreUiElementsIntentHandler.kt @@ -1,21 +1,27 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.model.google.GoogleCarouselItem import org.rewedigital.dialog.model.google.OptionInfo import org.rewedigital.dialog.spring.annotations.IntentHandler +import java.util.* @IntentHandler -class MoreUiElementsIntentHandler : DialogflowIntentHandler { +class MoreUiElementsIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return (handler.action?.equals("input.more") ?: false) + override fun canHandleAlexa(input: HandlerInput) = false + + override fun handleAlexa(input: HandlerInput): Optional = Optional.empty() + + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + ((handler.action?.equals("input.more") ?: false) && (handler.getContextParam("default-context", "LAST_INTENT_HANDLER") as? String) - .equals(UiElementsIntentHandler::class.java.simpleName) - } + .equals(UiElementsIntentHandler::class.java.simpleName)) override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInIntentHandler.kt index 0b2bb68..724c2df 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInIntentHandler.kt @@ -1,18 +1,32 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import com.amazon.ask.request.Predicates +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.spring.annotations.IntentHandler +import org.rewedigital.dialog.ssml.SsmlBuilder +import java.util.* @IntentHandler -class SignInIntentHandler : DialogflowIntentHandler { +class SignInIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return handler.action?.equals("input.sign_in") ?: false + override fun canHandleAlexa(input: HandlerInput) = input.matches(Predicates.intentName("input.sign_in")) + + override fun handleAlexa(input: HandlerInput): Optional { + input.attributesManager.sessionAttributes["LAST_INTENT_HANDLER"] = this.javaClass.simpleName + return input.responseBuilder + .withSpeech(SsmlBuilder("Please link your Account.").asSsmlString()) + .withLinkAccountCard() + .build() } + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + handler.action?.equals("input.sign_in") ?: false + override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) return handler.responseBuilder.askGoogleForSignIn() diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInResultIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInResultIntentHandler.kt index 6bacd5d..6a4a932 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInResultIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/SignInResultIntentHandler.kt @@ -1,18 +1,24 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.model.google.Status import org.rewedigital.dialog.spring.annotations.IntentHandler +import java.util.* @IntentHandler -class SignInResultIntentHandler : DialogflowIntentHandler { +class SignInResultIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return handler.action?.equals("input.sign_in.result") ?: false - } + override fun canHandleAlexa(input: HandlerInput) = false + + override fun handleAlexa(input: HandlerInput): Optional = Optional.empty() + + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + handler.action?.equals("input.sign_in.result") ?: false override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/UiElementsIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/UiElementsIntentHandler.kt index 667380d..88e276d 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/UiElementsIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/UiElementsIntentHandler.kt @@ -1,20 +1,25 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder -import org.rewedigital.dialog.model.google.GoogleBasicCard import org.rewedigital.dialog.model.google.GoogleButton import org.rewedigital.dialog.model.google.OpenUrlAction import org.rewedigital.dialog.spring.annotations.IntentHandler +import java.util.* @IntentHandler -class UiElementsIntentHandler : DialogflowIntentHandler { +class UiElementsIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return handler.action?.equals("input.ui_elements") ?: false - } + override fun canHandleAlexa(input: HandlerInput) = false + + override fun handleAlexa(input: HandlerInput): Optional = Optional.empty() + + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + handler.action?.equals("input.ui_elements") ?: false override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/WelcomeIntentHandler.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/WelcomeIntentHandler.kt index f2ff94a..edcdf9b 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/WelcomeIntentHandler.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/intenthandler/WelcomeIntentHandler.kt @@ -1,21 +1,53 @@ package org.rewedigital.dialog.springsample.intenthandler +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.LaunchRequest +import com.amazon.ask.model.Response +import com.amazon.ask.request.Predicates +import org.rewedigital.dialog.alexa.MultiPlatformIntentHandler import org.rewedigital.dialog.handler.DialogflowHandler -import org.rewedigital.dialog.handler.DialogflowIntentHandler import org.rewedigital.dialog.handler.DialogflowResponseBuilder import org.rewedigital.dialog.spring.annotations.IntentHandler import org.rewedigital.dialog.ssml.Emphasis import org.rewedigital.dialog.ssml.SsmlBuilder import org.rewedigital.dialog.utils.withGoogleSimpleResponse +import java.util.* @IntentHandler -class WelcomeIntentHandler : DialogflowIntentHandler { +class WelcomeIntentHandler : MultiPlatformIntentHandler { - override fun canHandleDialogflowIntent(handler: DialogflowHandler): Boolean { - return handler.action?.equals("input.welcome") ?: false + override fun canHandleAlexa(input: HandlerInput) = + input.matches(Predicates.requestType(LaunchRequest::class.java)) + + override fun handleAlexa(input: HandlerInput): Optional { + input.attributesManager.sessionAttributes["LAST_INTENT_HANDLER"] = this.javaClass.simpleName + + val ssmlBuilder = SsmlBuilder() + when (input.request.locale) { + "de" -> ssmlBuilder + .appendText("Willkommen bei deinem ") + .appendEmphasis(Emphasis.STRONG, "Demo Assistenten. ") + .appendAudio("https://actions.google.com/sounds/v1/alarms/beep_short.ogg") + .appendBreak() + .appendSlowText("Wie kann ich dir helfen?") + "en" -> ssmlBuilder + .appendText("Welcome to your ") + .appendEmphasis(Emphasis.STRONG, "Demo Assistant. ") + .appendAudio("https://actions.google.com/sounds/v1/alarms/beep_short.ogg") + .appendBreak() + .appendSlowText("How can I help?") + } + + return input.responseBuilder + .withShouldEndSession(false) + .withSpeech(ssmlBuilder.asSsmlString()) + .build() } + override fun canHandleDialogflowIntent(handler: DialogflowHandler) = + handler.action?.equals("input.welcome") ?: false + override fun handleDialogflowIntent(handler: DialogflowHandler): DialogflowResponseBuilder { handler.setContextParam("default-context", "LAST_INTENT_HANDLER", this.javaClass.simpleName) diff --git a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/interceptors/LoggingInterceptor.kt b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/interceptors/LoggingInterceptor.kt index 001a674..4078dee 100644 --- a/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/interceptors/LoggingInterceptor.kt +++ b/spring-sample/src/main/kotlin/org/rewedigital/dialog/springsample/interceptors/LoggingInterceptor.kt @@ -1,15 +1,30 @@ package org.rewedigital.dialog.springsample.interceptors +import com.amazon.ask.dispatcher.request.handler.HandlerInput +import com.amazon.ask.model.Response import com.fasterxml.jackson.databind.ObjectMapper -import org.rewedigital.dialog.interceptors.RequestInterceptor -import org.rewedigital.dialog.interceptors.ResponseInterceptor +import org.rewedigital.dialog.alexa.MultiPlatformRequestInterceptor +import org.rewedigital.dialog.alexa.MultiPlatformResponseInterceptor import org.rewedigital.dialog.model.dialogflow.WebhookRequest import org.rewedigital.dialog.model.dialogflow.WebhookResponse import org.rewedigital.dialog.spring.annotations.Interceptor +import java.util.* @Interceptor -class LoggingInterceptor(private val objectMapper: ObjectMapper) : RequestInterceptor, ResponseInterceptor { +class LoggingInterceptor(private val objectMapper: ObjectMapper) : + MultiPlatformRequestInterceptor, + MultiPlatformResponseInterceptor { + + override fun onAlexaRequest(input: HandlerInput) { + println(input.requestEnvelope.toString()) + } + + override fun onAlexaResponse(input: HandlerInput, response: Optional) { + response.ifPresent { + println(it.toString()) + } + } override fun onDialogflowRequest(webhookRequest: WebhookRequest) { println(objectMapper.writeValueAsString(webhookRequest)) diff --git a/ssml-plugin/build.gradle b/ssml-plugin/build.gradle index 84b6529..968c9a4 100644 --- a/ssml-plugin/build.gradle +++ b/ssml-plugin/build.gradle @@ -1,17 +1,16 @@ import java.nio.file.Paths group 'org.rewedigital.voice.dialog' +description 'This is the SSML-Builder plugin for Dialog to write voice applications fast.' version rootProject.ext.versions.ssml_plugin apply plugin: 'kotlin' -apply plugin: 'maven-publish' apply from: '../docu.gradle' -apply plugin: 'com.novoda.bintray-release' dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - implementation "org.rewedigital.voice:dialog:${rootProject.ext.versions.core}" - implementation "org.rewedigital.voice:ssml-builder:${rootProject.ext.versions.ssml}" + implementation project(':core') + implementation project(':ssml') } dokka { @@ -26,71 +25,4 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { outputDirectory = "$buildDir/javadoc" } -task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier = 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { - archiveClassifier = 'javadoc' - from "$buildDir/javadoc" -} - -publishing.publications { - ssmlPlugin(MavenPublication) { - groupId = 'org.rewedigital.voice.dialog' - artifactId = 'ssml-plugin' - from components.java - version = "${rootProject.ext.versions.core}" - artifact sourcesJar { - archiveClassifier = 'sources' - } - artifact javadocJar { - archiveClassifier = 'javadoc' - } - pom { - name = 'dialog' - description = 'This is the SSML-Builder plugin for Dialog to write voice applications fast.' - url = 'https://github.com/rewe-digital-incubator/dialog' - licenses { - license { - name = 'MIT License' - url = 'https://opensource.org/licenses/MIT' - distribution = 'repo' - } - } - developers { - // TODO use the MAINTAINERS file - developer { - name = 'Volkmar Vogel' - email = 'volkmar.vogel@rewe-digital.com' - } - developer { - name = 'René Kilczan' - email = 'rene.kilczan@rewe-digital.com' - } - } - - scm { - connection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - developerConnection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - url = 'https://github.com/rewe-digital-incubator/dialog' - } - } - } -} - -publish { - userOrg = 'rewe-digital' - groupId = 'org.rewedigital.voice.dialog' - artifactId = 'ssml-plugin' - repoName = 'dialog' - publishVersion = rootProject.ext.versions.core - desc = 'This is the SSML-Builder plugin for Dialog to write voice applications fast.' - website = 'https://github.com/rewe-digital-incubator/dialog' - licences = ['MIT'] - bintrayUser = project.properties['bintray.user'] - bintrayKey = project.properties['bintray.apikey'] - dryRun = false - publications = ['ssmlPlugin'] -} \ No newline at end of file +apply from: '../publish.gradle' \ No newline at end of file diff --git a/ssml/build.gradle b/ssml/build.gradle index dd5f4c2..0fc34f5 100644 --- a/ssml/build.gradle +++ b/ssml/build.gradle @@ -1,13 +1,12 @@ -group 'org.rewedigital.voice' -version rootProject.ext.versions.ssml - apply plugin: 'kotlin' -apply plugin: 'maven-publish' apply from: '../docu.gradle' -apply plugin: 'com.novoda.bintray-release' + +group 'org.rewedigital.voice' +version rootProject.ext.versions.ssml +description 'This library helps you to creates Speech Synthesis Markup Language (SSML) for your voice applications.' dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' } task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { @@ -15,71 +14,4 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) { outputDirectory = "$buildDir/javadoc" } -task sourcesJar(type: Jar, dependsOn: classes) { - archiveClassifier = 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: dokkaJavadoc) { - archiveClassifier = 'javadoc' - from "$buildDir/javadoc" -} - -publishing.publications { - ssmlBuilder(MavenPublication) { - groupId = 'org.rewedigital.voice' - artifactId = 'ssml-builder' - from components.java - version = "${rootProject.ext.versions.core}" - artifact sourcesJar { - archiveClassifier = 'sources' - } - artifact javadocJar { - archiveClassifier = 'javadoc' - } - pom { - name = 'dialog' - description = 'This library helps you to creates Speech Synthesis Markup Language (SSML) for your voice applications.' - url = 'https://github.com/rewe-digital-incubator/dialog' - licenses { - license { - name = 'MIT License' - url = 'https://opensource.org/licenses/MIT' - distribution = 'repo' - } - } - developers { - // TODO use the MAINTAINERS file - developer { - name = 'Volkmar Vogel' - email = 'volkmar.vogel@rewe-digital.com' - } - developer { - name = 'René Kilczan' - email = 'rene.kilczan@rewe-digital.com' - } - } - - scm { - connection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - developerConnection = 'scm:git:git://github.com/rewe-digital-incubator/dialog.git' - url = 'https://github.com/rewe-digital-incubator/dialog' - } - } - } -} - -publish { - userOrg = 'rewe-digital' - groupId = 'org.rewedigital.voice' - artifactId = 'ssml-builder' - repoName = 'dialog' - publishVersion = rootProject.ext.versions.core - desc = 'This library helps you to creates Speech Synthesis Markup Language (SSML) for your voice applications.' - website = 'https://github.com/rewe-digital-incubator/dialog' - licences = ['MIT'] - bintrayUser = project.properties['bintray.user'] - bintrayKey = project.properties['bintray.apikey'] - dryRun = false - publications = ['ssmlBuilder'] -} \ No newline at end of file +apply from: '../publish.gradle' \ No newline at end of file