skillserver

package
v0.0.0-...-a6af545 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2018 License: MIT Imports: 23 Imported by: 0

README

go-alexa/skillserver

A simple Go framework to quickly create an Amazon Alexa Skills web service.

Updates

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.

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)!

What?

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.

You can see the SDK documentation here: 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]

Requirements

Amazon has a list of requirements to get a new Skill up and running

  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
  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
  3. A formatted JSON response.
  4. SSL connection required, even for development.
  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

How skillserver Helps

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.)

An Example App

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.

Here's a simple, but complete web service example:

package main

import (
	alexa "github.com/mikeflynn/go-alexa/skillserver"
)

var Applications = map[string]interface{}{
	"/echo/helloworld": alexa.EchoApplication{ // Route
		AppID:    "xxxxxxxx", // Echo App ID from Amazon Dashboard
		OnIntent: EchoIntentHandler,
		OnLaunch: EchoIntentHandler,
	},
}

func main() {
	alexa.Run(Applications, "3000")
}

func EchoIntentHandler(echoReq *alexa.EchoRequest, echoResp *alexa.EchoResponse) {
	echoResp.OutputSpeech("Hello world from my new Echo test app!").Card("Hello World", "This is a test card.")
}

Details:

  • You define your endpoints by creating a map[string]interface{} and loading it with EchoApplication types that specify the Application ID and handler function.
  • All Skill endpoints must start with /echo/ as that's the route grouping that has the security middleware.
  • The easiest way to get started is define handler functions by using OnIntent, OnLaunch, or OnSessionEnded that take an EchoRequest and an EchoResponse.
  • ...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.
  • The JSON from the Echo request is already parsed for you. Grab it by calling skillserver.GetEchoRequest(r *http.Request).
  • 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.

The SSL Requirement

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 Lamda service that takes care of SSL for you but Go isn't an option on Lamda. 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.

Contributors

Mike Flynn (@thatmikeflynn)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HTTPError

func HTTPError(w http.ResponseWriter, logMsg string, err string, errCode int)

HTTPError is a convenience method for logging a message and writing the provided error message and error code to the HTTP response.

func IsValidAlexaRequest

func IsValidAlexaRequest(w http.ResponseWriter, r *http.Request) bool

IsValidAlexaRequest handles all the necessary steps to validate that an incoming http.Request has actually come from the Alexa service. If an error occurs during the validation process, an http.Error will be written to the provided http.ResponseWriter. The required steps for request validation can be found on this page: --insecure-skip-verify flag will disable all validations https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service#hosting-a-custom-skill-as-a-web-service

func Run

func Run(apps map[string]interface{}, port string)

Run will initialize the apps provided and start an HTTP server listening on the specified port.

func RunSSL

func RunSSL(apps map[string]interface{}, port, cert, key string)

RunSSL takes in a map of application, server port, certificate and key files, and tries to start a TLS server which alexa can directly pass commands to. It panics out with the error if the server couldn't be started. Or else the method blocks at ListenAndServeTLS line. If the server starts succcessfully and there are connection errors afterwards, they are logged to the stdout and no error is returned. For generating a testing cert and key, read the following: https://developer.amazon.com/docs/custom-skills/configure-web-service-self-signed-certificate.html

func SetEchoPrefix

func SetEchoPrefix(prefix string)

SetEchoPrefix provides a way to specify a single path prefix that all EchoApplications will share.SetEchoPrefix All incoming requests to an initialized EchoApplication will need to have a path that starts with this prefix.

func SetRootPrefix

func SetRootPrefix(prefix string)

SetRootPrefix allows a single path prefix to be applied to the request path of all StdApplications. All requests to the StdApplications provided will need to begin with this prefix.

Types

type ConfirmationStatus

type ConfirmationStatus string

ConfirmationStatus represents the status of either a dialog or slot confirmation.

const (
	// ConfConfirmed indicates the intent or slot has been confirmed by the end user.
	ConfConfirmed ConfirmationStatus = "CONFIRMED"

	// ConfDenied means the end user indicated the intent or slot should NOT proceed.
	ConfDenied ConfirmationStatus = "DENIED"

	// ConfNone means there has been not acceptance or denial of the intent or slot.
	ConfNone ConfirmationStatus = "NONE"
)

type EchoApplication

type EchoApplication struct {
	AppID              string
	Handler            func(http.ResponseWriter, *http.Request)
	OnLaunch           func(*EchoRequest, *EchoResponse)
	OnIntent           func(*EchoRequest, *EchoResponse)
	OnSessionEnded     func(*EchoRequest, *EchoResponse)
	OnAudioPlayerState func(*EchoRequest, *EchoResponse)
}

EchoApplication represents a single Alexa application server. This application type needs to include the application ID from the Alexa developer portal that will be making requests to the server. This AppId needs to be verified to ensure the requests are coming from the correct app. Handlers can also be provied for different types of requests sent by the Alexa Skills Kit such as OnLaunch or OnIntent.

type EchoContext

type EchoContext struct {
	System struct {
		Device struct {
			DeviceID string `json:"deviceId,omitempty"`
		} `json:"device,omitempty"`
		Application struct {
			ApplicationID string `json:"applicationId,omitempty"`
		} `json:"application,omitempty"`
	} `json:"System,omitempty"`
}

EchoContext contains information about the context in which the request was sent. This could be information about the device from which the request was sent or about the invoked Alexa application.

type EchoDirective

type EchoDirective struct {
	Type            dialog.Type `json:"type"`
	UpdatedIntent   *EchoIntent `json:"updatedIntent,omitempty"`
	SlotToConfirm   string      `json:"slotToConfirm,omitempty"`
	SlotToElicit    string      `json:"slotToElicit,omitempty"`
	IntentToConfirm string      `json:"intentToConfirm,omitempty"`
}

EchoDirective includes information about intents and slots that should be confirmed or elicted from the user. The type value can be used to delegate the action to the Alexa service. In this case, a pre-configured prompt will be used from the developer console.

type EchoIntent

type EchoIntent struct {
	Name               string              `json:"name"`
	Slots              map[string]EchoSlot `json:"slots"`
	ConfirmationStatus ConfirmationStatus  `json:"confirmationStatus"`
}

EchoIntent represents the intent that is sent as part of an EchoRequest. This includes the name of the intent configured in the Alexa developers dashboard as well as any slots and the optional confirmation status if one is needed to complete an intent.

type EchoReprompt

type EchoReprompt struct {
	OutputSpeech EchoRespPayload `json:"outputSpeech,omitempty"`
}

EchoReprompt contains speech that should be spoken back to the end user to retrieve additional information or to confirm an action.

type EchoReqBody

type EchoReqBody struct {
	Type        string     `json:"type"`
	RequestID   string     `json:"requestId"`
	Timestamp   string     `json:"timestamp"`
	Intent      EchoIntent `json:"intent,omitempty"`
	Reason      string     `json:"reason,omitempty"`
	Locale      string     `json:"locale,omitempty"`
	DialogState string     `json:"dialogState,omitempty"`
}

EchoReqBody contains all data related to the type of request sent.

type EchoRequest

type EchoRequest struct {
	Version string      `json:"version"`
	Session EchoSession `json:"session"`
	Request EchoReqBody `json:"request"`
	Context EchoContext `json:"context"`
}

EchoRequest represents all fields sent from the Alexa service to the skillserver. Convenience methods are provided to pull commonly used properties out of the request.

func GetEchoRequest

func GetEchoRequest(r *http.Request) *EchoRequest

GetEchoRequest is a convenience method for retrieving and casting an `EchoRequest` out of a standard `http.Request`.

func (*EchoRequest) AllSlots

func (r *EchoRequest) AllSlots() map[string]EchoSlot

AllSlots will return a map of all the slots in the EchoRequest mapped by their name.

func (*EchoRequest) GetIntentName

func (r *EchoRequest) GetIntentName() string

GetIntentName is a convenience method for getting the intent name out of an EchoRequest.

func (*EchoRequest) GetRequestType

func (r *EchoRequest) GetRequestType() string

GetRequestType is a convenience method for getting the request type out of an EchoRequest.

func (*EchoRequest) GetSessionID

func (r *EchoRequest) GetSessionID() string

GetSessionID is a convenience method for getting the session ID out of an EchoRequest.

func (*EchoRequest) GetSlot

func (r *EchoRequest) GetSlot(slotName string) (EchoSlot, error)

GetSlot will return an EchoSlot from the EchoRequest with the given name.

func (*EchoRequest) GetSlotValue

func (r *EchoRequest) GetSlotValue(slotName string) (string, error)

GetSlotValue is a convenience method for getting the value of the specified slot out of an EchoRequest as a string. An error is returned if a slot with that value is not found in the request.

func (*EchoRequest) GetUserID

func (r *EchoRequest) GetUserID() string

GetUserID is a convenience method for getting the user identifier out of an EchoRequest.

func (*EchoRequest) Locale

func (r *EchoRequest) Locale() string

Locale returns the locale specified in the request.

func (*EchoRequest) VerifyAppID

func (r *EchoRequest) VerifyAppID(myAppID string) bool

VerifyAppID check that the incoming application ID matches the application ID provided when running the server. This is a step required for skill certification.

func (*EchoRequest) VerifyTimestamp

func (r *EchoRequest) VerifyTimestamp() bool

VerifyTimestamp will parse the timestamp in the EchoRequest and verify that it is in the correct format and is not too old. True will be returned if the timestamp is valid; false otherwise.

type EchoResolution

type EchoResolution struct {
	ResolutionsPerAuthority []EchoResolutionPerAuthority `json:"resolutionsPerAuthority"`
}

EchoResolution contains the results of entity resolutions when it relates to slots and how the values are resolved. The resolutions will be organized by authority, for custom slots the authority will be the custom slot type that was defined. Find more information here: https://developer.amazon.com/docs/custom-skills/define-synonyms-and-ids-for-slot-type-values-entity-resolution.html#intentrequest-changes

type EchoResolutionPerAuthority

type EchoResolutionPerAuthority struct {
	Authority string `json:"authority"`
	Status    struct {
		Code string `json:"code"`
	} `json:"status"`
	Values []map[string]struct {
		Name string `json:"name"`
		ID   string `json:"id"`
	} `json:"values"`
}

EchoResolutionPerAuthority contains information about a single slot resolution from a single authority. The values silce will contain all possible matches for different slots. These resolutions are most interesting when working with synonyms.

type EchoRespBody

type EchoRespBody struct {
	OutputSpeech     *EchoRespPayload `json:"outputSpeech,omitempty"`
	Card             *EchoRespPayload `json:"card,omitempty"`
	Reprompt         *EchoReprompt    `json:"reprompt,omitempty"` // Pointer so it's dropped if empty in JSON response.
	ShouldEndSession bool             `json:"shouldEndSession"`
	Directives       []*EchoDirective `json:"directives,omitempty"`
}

EchoRespBody contains the body of the response to be sent back to the Alexa service. This includes things like the text that should be spoken or any cards that should be shown in the Alexa companion app.

type EchoRespImage

type EchoRespImage struct {
	SmallImageURL string `json:"smallImageUrl,omitempty"`
	LargeImageURL string `json:"largeImageUrl,omitempty"`
}

EchoRespImage represents a single image with two variants that should be returned as part of a response. Small and Large image sizes can be provided.

type EchoRespPayload

type EchoRespPayload struct {
	Type    string        `json:"type,omitempty"`
	Title   string        `json:"title,omitempty"`
	Text    string        `json:"text,omitempty"`
	SSML    string        `json:"ssml,omitempty"`
	Content string        `json:"content,omitempty"`
	Image   EchoRespImage `json:"image,omitempty"`
}

EchoRespPayload contains the interesting parts of the Echo response including text to be spoken, card attributes, and images.

type EchoResponse

type EchoResponse struct {
	Version           string                 `json:"version"`
	SessionAttributes map[string]interface{} `json:"sessionAttributes,omitempty"`
	Response          EchoRespBody           `json:"response"`
}

EchoResponse represents the information that should be sent back to the Alexa service from the skillserver.

func NewEchoResponse

func NewEchoResponse() *EchoResponse

NewEchoResponse will construct a new response instance with the required metadata and an empty speech string. By default the response will indicate that the session should be ended. Use the `EndSession(bool)` method if the session should be left open.

func (*EchoResponse) Card

func (r *EchoResponse) Card(title string, content string) *EchoResponse

Card will add a card to the Alexa app's response with the provided title and content strings.

func (*EchoResponse) EndSession

func (r *EchoResponse) EndSession(flag bool) *EchoResponse

EndSession is a convenience method for setting the flag in the response that will indicate if the session between the end user's device and the skillserver should be closed.

func (*EchoResponse) LinkAccountCard

func (r *EchoResponse) LinkAccountCard() *EchoResponse

LinkAccountCard is used to indicate that account linking still needs to be completed to continue using the Alexa skill. This will force an account linking card to be shown in the user's companion app.

func (*EchoResponse) OutputSpeech

func (r *EchoResponse) OutputSpeech(text string) *EchoResponse

OutputSpeech will replace any existing text that should be spoken with this new value. If the output needs to be constructed in steps or special speech tags need to be used, see the `SSMLTextBuilder`.

func (*EchoResponse) OutputSpeechSSML

func (r *EchoResponse) OutputSpeechSSML(text string) *EchoResponse

OutputSpeechSSML will add the text string provided and indicate the speech type is SSML in the response. This should only be used if the text to speech string includes special SSML tags.

func (*EchoResponse) Reprompt

func (r *EchoResponse) Reprompt(text string) *EchoResponse

Reprompt will send a prompt back to the user, this could be used to request additional information from the user.

func (*EchoResponse) RepromptSSML

func (r *EchoResponse) RepromptSSML(text string) *EchoResponse

RepromptSSML is similar to the `Reprompt` method but should be used when the prompt to the user should include special speech tags.

func (*EchoResponse) RespondToIntent

func (r *EchoResponse) RespondToIntent(name dialog.Type, intent *EchoIntent, slot *EchoSlot) *EchoResponse

RespondToIntent is used to Delegate/Elicit/Confirm a dialog or an entire intent with user of alexa. The func takes in name of the dialog, updated intent/intent to confirm if any and optional slot value. It prepares a Echo Response to be returned. Multiple directives can be returned by calling the method in chain (eg. RespondToIntent(...).RespondToIntent(...), each RespondToIntent call appends the data to Directives array and will return the same at the end.

func (*EchoResponse) SimpleCard

func (r *EchoResponse) SimpleCard(title string, content string) *EchoResponse

SimpleCard will indicate that a card should be included in the Alexa companion app as part of the response. The card will be shown with the provided title and content.

func (*EchoResponse) StandardCard

func (r *EchoResponse) StandardCard(title string, content string, smallImg string, largeImg string) *EchoResponse

StandardCard will indicate that a card should be shown in the Alexa companion app as part of the response. The card shown will include the provided title and content as well as images loaded from the locations provided as remote locations.

func (*EchoResponse) String

func (r *EchoResponse) String() ([]byte, error)

type EchoSession

type EchoSession struct {
	New         bool   `json:"new"`
	SessionID   string `json:"sessionId"`
	Application struct {
		ApplicationID string `json:"applicationId"`
	} `json:"application"`
	Attributes map[string]interface{} `json:"attributes"`
	User       struct {
		UserID      string `json:"userId"`
		AccessToken string `json:"accessToken,omitempty"`
	} `json:"user"`
}

EchoSession contains information about the ongoing session between the Alexa server and the skillserver. This session is stored as part of each request.

type EchoSlot

type EchoSlot struct {
	Name               string             `json:"name"`
	Value              string             `json:"value"`
	Resolutions        EchoResolution     `json:"resolutions"`
	ConfirmationStatus ConfirmationStatus `json:"confirmationStatus"`
}

EchoSlot represents variable values that can be sent that were specified by the end user when invoking the Alexa application.

type PhoneticAlphabet

type PhoneticAlphabet string

PhoneticAlphabet represents the alphabet to be used when appending phonemes

const (
	// Ipa is the International Phonetic Alphabet
	Ipa PhoneticAlphabet = "ipa"
	// XSampa is the Extended Speech Assesment Methods Phonetic Alphabet
	XSampa PhoneticAlphabet = "x-sampa"
)

type SSMLTextBuilder

type SSMLTextBuilder struct {
	// contains filtered or unexported fields
}

SSMLTextBuilder implements the builder pattern for constructing a speech string which may or may not contain SSML tags.

func NewSSMLTextBuilder

func NewSSMLTextBuilder() *SSMLTextBuilder

NewSSMLTextBuilder is a convenienve method for constructing a new SSMLTextBuilder instance that starts with no speech text added.

func (*SSMLTextBuilder) AppendAmazonEffect

func (builder *SSMLTextBuilder) AppendAmazonEffect(text, name string) *SSMLTextBuilder

AppendAmazonEffect will add a new speech string with the provided effect name. Check the SSML reference page for a list of available effects.

func (*SSMLTextBuilder) AppendAudio

func (builder *SSMLTextBuilder) AppendAudio(src string) *SSMLTextBuilder

AppendAudio will append the playback of an MP3 file to the response. The audio playback will take place at the specific point in the text to speech response.

func (*SSMLTextBuilder) AppendBreak

func (builder *SSMLTextBuilder) AppendBreak(strength, time string) *SSMLTextBuilder

AppendBreak will add a pause to the text to speech output. The default is a medium pause. Refer to the SSML reference for the available strength values.

func (*SSMLTextBuilder) AppendEmphasis

func (builder *SSMLTextBuilder) AppendEmphasis(text, level string) *SSMLTextBuilder

AppendEmphasis will include a set of text to be spoken with the specific level of emphasis. Refer to the SSML reference for available emphasis level values.

func (*SSMLTextBuilder) AppendParagraph

func (builder *SSMLTextBuilder) AppendParagraph(text string) *SSMLTextBuilder

AppendParagraph will append the specific text as a new paragraph. Extra strong breaks will be used before and after this text.

func (*SSMLTextBuilder) AppendPartOfSpeech

func (builder *SSMLTextBuilder) AppendPartOfSpeech(role WordRole, text string) *SSMLTextBuilder

AppendPartOfSpeech is used to explictily define the part of speech for a word that is being appended to the text to speech output sent in a skill server response.

func (*SSMLTextBuilder) AppendPhoneme

func (builder *SSMLTextBuilder) AppendPhoneme(alphabet PhoneticAlphabet, phoneme, text string) *SSMLTextBuilder

AppendPhoneme is used to specify a phonetic pronunciation for a piece of text to be appended to the response.

func (*SSMLTextBuilder) AppendPlainSpeech

func (builder *SSMLTextBuilder) AppendPlainSpeech(text string) *SSMLTextBuilder

AppendPlainSpeech will append the supplied text as regular speech to be spoken by the Alexa device.

func (*SSMLTextBuilder) AppendProsody

func (builder *SSMLTextBuilder) AppendProsody(text, rate, pitch, volume string) *SSMLTextBuilder

AppendProsody provides a way to modify the rate, pitch, and volume of a piece of spoken text.

func (*SSMLTextBuilder) AppendSayAs

func (builder *SSMLTextBuilder) AppendSayAs(interpretAs, format, text string) *SSMLTextBuilder

AppendSayAs is used to provide additional information about how the text string being appended should be interpreted. For example this can be used to interpret the string as a list of individual characters or to read out digits one at a time. The format string is ignored unless the interpret-as argument is `date`. Refer to the SSML referene for valid values for the interpretAs parameter.

func (*SSMLTextBuilder) AppendSentence

func (builder *SSMLTextBuilder) AppendSentence(text string) *SSMLTextBuilder

AppendSentence will indicate the provided text should be spoken as a new sentence. This text will include strong breaks before and after.

func (*SSMLTextBuilder) AppendSubstitution

func (builder *SSMLTextBuilder) AppendSubstitution(text, alias string) *SSMLTextBuilder

AppendSubstitution provides a way to indicate an alternate pronunciation for a piece of text.

func (*SSMLTextBuilder) Build

func (builder *SSMLTextBuilder) Build() string

Build will construct the appropriate speech string including any SSML tags that were added to the Builder.

type StdApplication

type StdApplication struct {
	Methods string
	Handler func(http.ResponseWriter, *http.Request)
}

StdApplication is a type of application that allows the user to accept and manually process requests from an Alexa application on an existing HTTP server. Request validation and parsing will need to be done manually to ensure compliance with the requirements of the Alexa Skills Kit.

type WordRole

type WordRole string

WordRole is used as the role argument in the AppendPartOfSpeech method. This should be one of the constants defined in the Amazon SSML Reference docs.

const (
	// PresentSimple is used to pronounce the word as a verb
	PresentSimple WordRole = "amazon:VB"
	// PastParticle is used to pronounce the word as a past particle
	PastParticle WordRole = "amazon:VBD"
	// Noun is used to pronounce the word as a noun
	Noun WordRole = "amazon:NN"
	// AlternateSense is used to select the alternate sense for a specific word. According
	// to the Amazon SSML Reference:
	// 		" Use the non-default sense of the word. For example, the noun "bass" is pronounced
	//		differently depending on meaning. The "default" meaning is the lowest part of the
	// 		musical range. The alternate sense (which is still a noun) is a freshwater fish.
	// 		Specifying <speak><w role="amazon:SENSE_1">bass</w>"</speak> renders the non-default
	// 		pronunciation (freshwater fish)."
	AlternateSense WordRole = "amazon:SENSE_1"
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL