├── skillserver
├── examples
│ ├── jeopardy
│ │ ├── .gitignore
│ │ ├── intent_schema.json
│ │ ├── README.md
│ │ ├── utterances.txt
│ │ └── jeopardy.go
│ └── helloworld.go
├── .gitignore
├── dialog
│ └── default.go
├── README.md
├── ssml-builder.go
├── skillserver.go
└── echo.go
├── .travis.yml
├── LICENSE
└── README.md
/skillserver/examples/jeopardy/.gitignore:
--------------------------------------------------------------------------------
1 | *.sh
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | matrix:
4 | include:
5 | - go: "tip"
6 | - go: "1.x"
7 | - go: "1.10"
8 | - go: "1.9"
9 | - go: "1.8"
10 | allow_failures:
11 | - go: tip
12 |
--------------------------------------------------------------------------------
/skillserver/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
2 | *.o
3 | *.a
4 | *.so
5 |
6 | # Folders
7 | _obj
8 | _test
9 |
10 | # Architecture specific extensions/prefixes
11 | *.[568vq]
12 | [568vq].out
13 |
14 | *.cgo1.go
15 | *.cgo2.c
16 | _cgo_defun.c
17 | _cgo_gotypes.go
18 | _cgo_export.*
19 |
20 | _testmain.go
21 |
22 | *.exe
23 | *.test
24 | *.prof
25 |
26 |
--------------------------------------------------------------------------------
/skillserver/examples/helloworld.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | alexa "github.com/mikeflynn/go-alexa/skillserver"
5 | )
6 |
7 | var applications = map[string]interface{}{
8 | "/echo/helloworld": alexa.EchoApplication{ // Route
9 | AppID: "xxxxxxxx", // Echo App ID from Amazon Dashboard
10 | OnIntent: echoIntentHandler,
11 | OnLaunch: echoIntentHandler,
12 | },
13 | }
14 |
15 | func main() {
16 | alexa.Run(applications, "3000")
17 | }
18 |
19 | func echoIntentHandler(echoReq *alexa.EchoRequest, echoResp *alexa.EchoResponse) {
20 | echoResp.OutputSpeech("Hello world from my new Echo test app!").Card("Hello World", "This is a test card.")
21 | }
22 |
--------------------------------------------------------------------------------
/skillserver/examples/jeopardy/intent_schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "intents": [
3 | {
4 | "intent": "StartJeopardy",
5 | "slots": []
6 | },
7 | {
8 | "intent": "PickCategory",
9 | "slots": [
10 | {
11 | "name": "Category",
12 | "type": "LITERAL"
13 | }
14 | ]
15 | },
16 | {
17 | "intent": "AnswerQuestion",
18 | "slots": [
19 | {
20 | "name": "Answer",
21 | "type": "LITERAL"
22 | }
23 | ]
24 | },
25 | {
26 | "intent": "QuitGame",
27 | "slots": []
28 | },
29 | {
30 | "intent": "ListCategories",
31 | "slots": []
32 | },
33 | {
34 | "intent": "RepeatQuestion",
35 | "slots": []
36 | }
37 | ]
38 | }
--------------------------------------------------------------------------------
/skillserver/examples/jeopardy/README.md:
--------------------------------------------------------------------------------
1 | ## Alexa Skill: Jeopardy
2 |
3 | [](https://www.youtube.com/watch?v=mDIEGUtoSjw)
4 |
5 | ### Requirements
6 | * Compiled Go code
7 | * MongoDB running on localhost
8 |
9 | ### Functionality
10 | * "Alexa, ask Jeopardy to start a game."
11 |
12 | Jeopardy uses the amazing [jservice.io](http://jservice.io) API to pull actual Jeopardy questions and categories.
13 |
14 | ### Potential Future Enhancements:
15 | * Allow selection of point value when selecting the category.
16 | * Allow for category selection when you star the game.
17 | * Use Amazon User ID to continue previous game, or keep track of all-time score.
18 | * Pull random categories.
19 | * Double Jeopardy!
20 | * Final Jeopardy!
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Mike Flynn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/skillserver/dialog/default.go:
--------------------------------------------------------------------------------
1 | package dialog
2 |
3 | // Type will indicate type of dialog interaction to be sent to the user.
4 | type Type string
5 |
6 | const (
7 | // Delegate will indicate that the Alexa service should continue the dialog ineraction.
8 | Delegate Type = "Dialog.Delegate"
9 |
10 | // ElicitSlot will indicate to the Alexa service that the specific slot should be elicited from the user.
11 | ElicitSlot Type = "Dialog.ElicitSlot"
12 |
13 | // ConfirmSlot indicates to the Alexa service that the slot value should be confirmed by the user.
14 | ConfirmSlot Type = "Dialog.ConfirmSlot"
15 |
16 | // ConfirmIntent indicates to the Alexa service that the complete intent should be confimed by the user.
17 | ConfirmIntent Type = "Dialog.ConfirmIntent"
18 | )
19 |
20 | const (
21 | // Started indicates that the dialog interaction has just begun.
22 | Started string = "STARTED"
23 |
24 | // InProgress indicates that the dialog interation is continuing.
25 | InProgress string = "IN_PROGRESS"
26 |
27 | // Completed indicates that the dialog interaction has finished.
28 | // The intent and slot confirmation status should be checked.
29 | Completed string = "COMPLETED"
30 | )
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## `go-alexa`: A Go toolset for creating Amazon Alexa Skills
2 |
3 |
4 | [![build status badge][travis-badge]][travis-job]
5 |
6 | [![GoDoc][1]][2]
7 | [![GoCard][3]][4]
8 |
9 | [1]: https://godoc.org/github.com/mikeflynn/go-alexa?status.svg
10 | [2]: https://godoc.org/github.com/mikeflynn/go-alexa
11 | [3]: https://goreportcard.com/badge/github.com/mikeflynn/go-alexa
12 | [4]: https://goreportcard.com/report/github.com/mikeflynn/go-alexa
13 | [travis-badge]: https://travis-ci.org/mikeflynn/go-alexa.svg?branch=master
14 | [travis-job]: https://travis-ci.org/mikeflynn/go-alexa
15 |
16 | The Amazon Echo, with it's voice assitant Alexa, is a surprisingly amazing tool. Having the power of voice recognition tied to the web ready at any time is quite powerful and now that Amazon has opened up a developer platform it's even more exciting!
17 |
18 | Amazon has supplied packages for Java and Node.js (tied to the AWS Lamda platform) but I wanted to develop my skills in Go. As I moved through the process making my app work with Amazon's spec, a simple web framework that took care all the heavy lifting on security and crafting the response object formed. I'm looking forward to more Go-based tools getting created and living in this `go-alexa` bucket but for now the `skillserver` is the first tool.
19 |
20 | Mike Flynn gave a talk about this library an conversational applications in general at the 2016 Strange Loop Conference: ["Exploring Conversational Interfaces with Amazon Alexa and Go"](https://www.youtube.com/watch?v=pDdE3PKy6mo)
21 |
22 | ### Tools
23 |
24 | * [`skillserver`](skillserver/) - A framework to quickly create a skill web service that handles all of the Amazon requirements.
25 | * Example: [Jeopardy](skillserver/examples/jeopardy)
26 |
27 | ### Future Proposed Tools
28 |
29 | * An Amazon Echo request simulator
30 | * A library for Alexa responses
31 |
32 | ### Original Author
33 |
34 | Mike Flynn ([@thatmikeflynn](http://twitter.com/thatmikeflynn))
35 |
--------------------------------------------------------------------------------
/skillserver/examples/jeopardy/utterances.txt:
--------------------------------------------------------------------------------
1 | QuitGame goodbye
2 | QuitGame i'm done
3 | QuitGame i am done
4 | QuitGame game over
5 | QuitGame quit
6 | StartJeopardy lets play a game
7 | StartJeopardy wanna play
8 | StartJeopardy start a game
9 | StartJeopardy to start a game
10 | StartJeopardy play a game
11 | ListCategories list the categories
12 | ListCategories give me the categories
13 | ListCategories what are the categories again
14 | ListCategories what are the categories
15 | ListCategories to list the categories
16 | PickCategory give me a {food|Category} question
17 | PickCategory lets start with {hodgepodge|Category}
18 | PickCategory ask a {history|Category} question
19 | PickCategory any category
20 | PickCategory i will take {sports|Category}
21 | PickCategory i'll take {science|Category}
22 | PickCategory {food|Category}
23 | PickCategory {hodgepodge|Category}
24 | PickCategory {history|Category}
25 | PickCategory {sports|Category}
26 | PickCategory {science|Category}
27 | PickCategory {television|Category}
28 | PickCategory {people|Category}
29 | PickCategory {rhyme time|Category}
30 | PickCategory {pop music|Category}
31 | PickCategory {quotations|Category}
32 | PickCategory lets go with a {food|Category} question
33 | PickCategory how about {television|Category}
34 | PickCategory i'll start with {people|Category}
35 | PickCategory give me a {sports|Category} question
36 | PickCategory i'll take {sports|Category}
37 | RepeatQuestion can you repeat the question
38 | RepeatQuestion repeat the question
39 | RepeatQuestion say question again
40 | RepeatQuestion can you say the question again
41 | AnswerQuestion who is {abraham lincoln|Answer}
42 | AnswerQuestion what is a {robot|Answer}
43 | AnswerQuestion what is {sweet tea|Answer}
44 | AnswerQuestion where is {the washington monument|Answer}
45 | AnswerQuestion who are {the doobie brothers|Answer}
46 | AnswerQuestion what are {pancakes|Answer}
47 | AnswerQuestion where are {the rocky mountains|Answer}
48 | AnswerQuestion i don't know
49 | AnswerQuestion not sure
50 | AnswerQuestion no idea
51 | AnswerQuestion i give up
52 |
--------------------------------------------------------------------------------
/skillserver/README.md:
--------------------------------------------------------------------------------
1 | ## `go-alexa/skillserver`
2 |
3 | A simple Go framework to quickly create an Amazon Alexa Skills web service.
4 |
5 | ### Updates
6 | 10/3/16: Go 1.7 is required now as `go-alexa` uses the new core context library. It's not ideal to require 1.7, but with Go's no breaking changes promise it should be an easy upgrade for the vast majority of projects out there and it's better to keep up with the current release. If this change causes any issues, please reach out with an issue.
7 |
8 | 4/5/16: After taking a few good addtions from the community recently, I also just added new hooks that make it even easier to get going since you don't have to write a full `net/http` handler (see the new Hello World below)!
9 |
10 | ### What?
11 |
12 | After beta testing the Amazon Echo (and it's voice assistant Alexa) for several months, Amazon has released the product to the public and created an SDK for developers to add new "Alexa Skills" to the product.
13 |
14 | You can see the SDK documentation here: [developer.amazon.com/public/solutions/alexa/alexa-skills-kit](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit) but in short, a developer can make a web service that allows a user to say: _Alexa, ask [your service] to [some action your service provides]_
15 |
16 | ### Requirements
17 |
18 | Amazon has a list of requirements to get a new Skill up and running
19 |
20 | 1. Creating your new Skill on their Development Dashboard populating it with details and example phrases. That process is documented here: [developer.amazon.com/appsandservices/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface](https://developer.amazon.com/appsandservices/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface)
21 | 2. A lengthy request validation proces. Documented here: [developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service)
22 | 3. A formatted JSON response.
23 | 4. SSL connection required, even for development.
24 | 5. If you don't wish to validate the certificate, you can use --insecure-skip-verify which disables all certificate validations. ***NOT RECOMMENDED FOR PRODUCTION USE***
25 |
26 | ### How `skillserver` Helps
27 |
28 | The `go-alexa/skillserver` takes care of #2 and #3 for you so you can concentrate on #1 and coding your app. (#4 is what it is. See the section on SSL below.)
29 |
30 | ### An Example App
31 |
32 | Creating an Alexa Skill web service is easy with `go-alexa/skillserver`. Simply import the project as any other Go project, define your app, and write your endpoint. All the web service, security checks, and assistance in creating the response objects are done for you.
33 |
34 | Here's a simple, but complete web service example:
35 |
36 | ```go
37 | package main
38 |
39 | import (
40 | alexa "github.com/mikeflynn/go-alexa/skillserver"
41 | )
42 |
43 | var Applications = map[string]interface{}{
44 | "/echo/helloworld": alexa.EchoApplication{ // Route
45 | AppID: "xxxxxxxx", // Echo App ID from Amazon Dashboard
46 | OnIntent: EchoIntentHandler,
47 | OnLaunch: EchoIntentHandler,
48 | },
49 | }
50 |
51 | func main() {
52 | alexa.Run(Applications, "3000")
53 | }
54 |
55 | func EchoIntentHandler(echoReq *alexa.EchoRequest, echoResp *alexa.EchoResponse) {
56 | echoResp.OutputSpeech("Hello world from my new Echo test app!").Card("Hello World", "This is a test card.")
57 | }
58 | ```
59 |
60 | Details:
61 | * You define your endpoints by creating a `map[string]interface{}` and loading it with `EchoApplication` types that specify the Application ID and handler function.
62 | * All Skill endpoints must start with `/echo/` as that's the route grouping that has the security middleware.
63 | * The easiest way to get started is define handler functions by using `OnIntent`, `OnLaunch`, or `OnSessionEnded` that take an EchoRequest and an EchoResponse.
64 | * ...but if you want full control you can still use the `EchoApplication.Handler` hook to write a regular `net/http` handler so you have full access to the request and ResponseWriter.
65 | * The JSON from the Echo request is already parsed for you. Grab it by calling `skillserver.GetEchoRequest(r *http.Request)`.
66 | * You generate the Echo Response by using the EchoResponse struct that has methods to generate each part and that's it! ...unless you use the `EchoApplication.Handler` hook. In that case you need to write your JSON to the string with the `EchoResponse.toString()` method.
67 |
68 | ### The SSL Requirement
69 |
70 | Amazon requires an SSL connection for all steps in the Skill process, even local development (which still gets requests from the Echo web service). Amazon is pushing their AWS Lambda service that takes care of SSL for you ~~but Go isn't an option on Lambda~~. What I've done personally is put Nginx in front of my Go app and let Nginx handle the SSL (a self-signed cert for development and a real cert when pushing to production). More information here on [nginx.com](https://www.nginx.com/blog/nginx-ssl/).
71 |
72 | ### Contributors
73 |
74 | Mike Flynn ([@thatmikeflynn](https://twitter.com/thatmikeflynn))
75 |
--------------------------------------------------------------------------------
/skillserver/ssml-builder.go:
--------------------------------------------------------------------------------
1 | package skillserver
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | )
7 |
8 | /**
9 | * Details about the Speech Synthesis Markup Language (SSML) can be found on this page:
10 | * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference
11 | */
12 |
13 | // Helper Types
14 |
15 | // SSMLTextBuilder implements the builder pattern for constructing a speech string
16 | // which may or may not contain SSML tags.
17 | type SSMLTextBuilder struct {
18 | buffer *bytes.Buffer
19 | }
20 |
21 | // WordRole is used as the role argument in the AppendPartOfSpeech method. This should
22 | // be one of the constants defined in the Amazon SSML Reference docs.
23 | type WordRole string
24 |
25 | const (
26 | // PresentSimple is used to pronounce the word as a verb
27 | PresentSimple WordRole = "amazon:VB"
28 | // PastParticle is used to pronounce the word as a past particle
29 | PastParticle WordRole = "amazon:VBD"
30 | // Noun is used to pronounce the word as a noun
31 | Noun WordRole = "amazon:NN"
32 | // AlternateSense is used to select the alternate sense for a specific word. According
33 | // to the Amazon SSML Reference:
34 | // " Use the non-default sense of the word. For example, the noun "bass" is pronounced
35 | // differently depending on meaning. The "default" meaning is the lowest part of the
36 | // musical range. The alternate sense (which is still a noun) is a freshwater fish.
37 | // Specifying bass" renders the non-default
38 | // pronunciation (freshwater fish)."
39 | AlternateSense WordRole = "amazon:SENSE_1"
40 | )
41 |
42 | // PhoneticAlphabet represents the alphabet to be used when appending phonemes
43 | type PhoneticAlphabet string
44 |
45 | const (
46 | // Ipa is the International Phonetic Alphabet
47 | Ipa PhoneticAlphabet = "ipa"
48 | // XSampa is the Extended Speech Assesment Methods Phonetic Alphabet
49 | XSampa PhoneticAlphabet = "x-sampa"
50 | )
51 |
52 | // NewSSMLTextBuilder is a convenienve method for constructing a new SSMLTextBuilder
53 | // instance that starts with no speech text added.
54 | func NewSSMLTextBuilder() *SSMLTextBuilder {
55 | return &SSMLTextBuilder{bytes.NewBufferString("")}
56 | }
57 |
58 | // AppendPlainSpeech will append the supplied text as regular speech to be spoken by the Alexa device.
59 | func (builder *SSMLTextBuilder) AppendPlainSpeech(text string) *SSMLTextBuilder {
60 |
61 | builder.buffer.WriteString(text)
62 |
63 | return builder
64 | }
65 |
66 | // AppendAmazonEffect will add a new speech string with the provided effect name.
67 | // Check the SSML reference page for a list of available effects.
68 | func (builder *SSMLTextBuilder) AppendAmazonEffect(text, name string) *SSMLTextBuilder {
69 |
70 | builder.buffer.WriteString(fmt.Sprintf("%s", name, text))
71 |
72 | return builder
73 | }
74 |
75 | // AppendAudio will append the playback of an MP3 file to the response. The audio playback
76 | // will take place at the specific point in the text to speech response.
77 | func (builder *SSMLTextBuilder) AppendAudio(src string) *SSMLTextBuilder {
78 |
79 | builder.buffer.WriteString(fmt.Sprintf("