Skip to content
This repository has been archived by the owner on Jan 14, 2025. It is now read-only.

Add Amazon Alexa Skills Kit event #10

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions service/lambda/runtime/event/alexaskillsevt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<a id="top" name="top"></a>

# Amazon Alexa Skills Kit Events

[<img src="/_asset/misc_home.png" alt="Back to Home" align="right">](/)
[![Go Doc][badge-doc-go]][eawsy-doc]
[![AWS Doc][badge-doc-aws]][aws-doc]

This package allows you to write AWS Lambda functions to process Amazon Alexa Skill Kit Events.

[<img src="/_asset/misc_arrow-up.png" align="right">](#top)
## Quick Hands-On

> For step by step instructions on how to author your AWS Lambda function code in Go, see
[eawsy/aws-lambda-go-shim][eawsy-runtime].

```sh
go get -u -d github.com/eawsy/aws-lambda-go-event/...
```

```go
package main

import (
"log"

"github.com/eawsy/aws-lambda-go-event/service/lambda/runtime/event/alexaskillsevt"
"github.com/eawsy/aws-lambda-go-core/service/lambda/runtime"
)

func Handle(evt *alexaskillsevt.Event, ctx *runtime.Context) (interface{}, error) {
// See details about request types at https://developer.amazon.com/docs/custom-skills/request-types-reference.html
if evt.Request.Type == "IntentRequest" {
// sent when the user invokes your skill with a specific intent
switch evt.Request.Intent.Name {
case "Intent1":
log.Println("Handle Intent1")
// respond with PlainText speech and will keep session open for another request
resp := alexaskillsevt.NewResponse().WithSpeechPlainText("Im responding to intent 1").WithCardSimple("My title here", "Card body will contain this text for intent 1 response").WithRepromptPlainText("Anything else I can help you with?").Get()
return resp, nil
case "Intent2":
log.Println("Handle Intent2")
// respond with SSML speech and will end the session
resp := alexaskillsevt.NewResponse().WithSpeechSSML(`<p>Im <emphasis level="strong">responding</emphasis> to intent 2.</p><p>This will be said after a short pause</p>`).WithCardSimple("My title here", "Card body will contain this text for intent 2 response").WithEndSession().Get()
return resp, nil
default:
log.Println("Unknown intent")
return nil, errors.New("Unknown intent")
}
} else if evt.Request.Type == "LaunchRequest" {
// sent when the user invokes your skill without providing a specific intent
resp := alexaskillsevt.NewResponse().WithSpeechPlainText("Welcome to my Alexa Skill").WithCardSimple("Welcome", "Hello there").Get()
return resp, nil
}

return nil, nil
}
```

[eawsy-runtime]: https://github.com/eawsy/aws-lambda-go-shim
[eawsy-doc]: https://godoc.org/github.com/eawsy/aws-lambda-go-event/service/lambda/runtime/event/alexaskillsevt

[Amazon Alexa Developer]: https://developer.amazon.com/alexa
[Speech Synthesis Markup Language (SSML)]: https://developer.amazon.com/docs/custom-skills/speech-synthesis-markup-language-ssml-reference.html
93 changes: 93 additions & 0 deletions service/lambda/runtime/event/alexaskillsevt/definition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//
// Copyright 2016 Alsanium, SAS. or its affiliates. All rights reserved.
// Modifications copyright 2018 Kyle Vanek. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package alexaskillsevt

import (
"encoding/json"
"time"
)

// EventSession provides session details for an Amazon Alexa Skills Events
type EventSession struct {
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 interface{} `json:"accessToken"`
Permissions map[string]interface{} `json:"permissions"`
} `json:"user"`
New bool `json:"new"`
}

// EventRequest provides request infomration for an Amazon Alexa Skills Event
// https://developer.amazon.com/docs/custom-skills/request-types-reference.html
type EventRequest struct {
Type string `json:"type"`
Requestid string `json:"requestId"`
Timestamp time.Time `json:"timestamp"`
DialogState string `json:"dialogState"`
Locale string `json:"locale"`
Intent struct {
Name string `json:"name"`
Slots map[string]struct {
Name string `json:"name"`
Value string `json:"value"`
ConfirmationStatus string `json:"confirmationStatus"`
Resolutions struct {
ResolutionsPerAuthority []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"`
} `json:"resolutionsPerAuthority"`
} `json:"resolutions"`
} `json:"slots"`
} `json:"intent"`
Reason interface{} `json:"reason"`
Error struct {
Type string `json:"type"`
Message string `json:"message"`
} `json:"error"`
}

// Event represents an Amazon Alexa Skills Event.
type Event struct {
// Skill Event Session
Session *EventSession `json:"session"`

// Skill Event Request
Request *EventRequest `json:"request"`
}

// String returns the string representation.
func (e *Event) String() string {
s, _ := json.Marshal(e)
return string(s)
}

// GoString returns the string representation.
func (e *Event) GoString() string {
return e.String()
}
22 changes: 22 additions & 0 deletions service/lambda/runtime/event/alexaskillsevt/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// Copyright 2016 Alsanium, SAS. or its affiliates. All rights reserved.
// Modifications copyright 2018 Kyle Vanek. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/*
Package alexaskillsevt allows you to write AWS Lambda functions to process Amazon Alexa Skills
Event requests.
*/
package alexaskillsevt
191 changes: 191 additions & 0 deletions service/lambda/runtime/event/alexaskillsevt/response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
//
// Copyright 2018 Kyle Vanek. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package alexaskillsevt

var (
// Version specifies the response version number. Defaults to "1.0" if not defined
Version string
)

// NewResponse creates a new response object
func NewResponse() *CreateResponse {
if Version == "" {
Version = "1.0"
}
return &CreateResponse{
resp: &EventResponse{Version: Version},
}
}

// CreateResponse object type
type CreateResponse struct {
resp *EventResponse
}

// Get returns the actual EventResponse for Lambda to return
func (r *CreateResponse) Get() *EventResponse {
if r.resp.Version == "" {
r.resp.Version = "1.0"
}
return r.resp
}

// WithEndSession specifies that the session will end after this response
func (r *CreateResponse) WithEndSession() *CreateResponse {
r.resp.Response.ShouldEndSession = true
return r
}

// WithSpeechPlainText sets the speechlet response to the specified PlainText text
func (r *CreateResponse) WithSpeechPlainText(text string) *CreateResponse {
r.resp.Response.OutputSpeech = &ResponseOutputSpeech{
Type: "PlainText",
Text: text,
}
return r
}

// WithSpeechSSML sets the speechlet response to the specified SSML text
func (r *CreateResponse) WithSpeechSSML(text string) *CreateResponse {
r.resp.Response.OutputSpeech = &ResponseOutputSpeech{
Type: "SSML",
SSML: `<speak>` + text + `</speak>`,
}
return r
}

// WithCardSimple sets the card to a Simple card type with a title and text
func (r *CreateResponse) WithCardSimple(title string, text string) *CreateResponse {
r.resp.Response.Card = &ResponseCard{
Type: "Simple",
Title: title,
Content: text,
}

return r
}

// WithCardStandard sets the card to a Standard card type with a title, text, and either/both a small and large image using specified URLs
func (r *CreateResponse) WithCardStandard(title string, text string, imageSmallURL string, imageLargeURL string) *CreateResponse {
r.resp.Response.Card = &ResponseCard{
Type: "Standard",
Title: title,
Text: text,
Image: &ResponseCardImage{
SmallImageURL: imageSmallURL,
LargeImageURL: imageLargeURL,
},
}

return r
}

// WithCardLinkAccount sets the card to a LinkAccount card type
func (r *CreateResponse) WithCardLinkAccount() *CreateResponse {
r.resp.Response.Card = &ResponseCard{
Type: "LinkAccount",
}

return r
}

// WithRepromptPlainText sets the reprompt to the specified PlainText text in the response
func (r *CreateResponse) WithRepromptPlainText(text string) *CreateResponse {
r.resp.Response.Reprompt = &ResponseReprompt{
OutputSpeech: &ResponseOutputSpeech{
Type: "PlainText",
Text: text,
},
}

return r
}

// WithRepromptSSML sets the reprompt to the specified SSML text in the response
func (r *CreateResponse) WithRepromptSSML(text string) *CreateResponse {
r.resp.Response.Reprompt = &ResponseReprompt{
OutputSpeech: &ResponseOutputSpeech{
Type: "SSML",
SSML: text,
},
}

return r
}

// WithSessionAttribute adds a session attribute to the response
func (r *CreateResponse) WithSessionAttribute(key string, item interface{}) *CreateResponse {
if r.resp.SessionAttributes == nil {
r.resp.SessionAttributes = map[string]interface{}{}
}
r.resp.SessionAttributes[key] = item

return r
}

// WithDirective adds a directive to the response
func (r *CreateResponse) WithDirective(directive map[string]interface{}) *CreateResponse {
if r.resp.Response.Directives == nil {
r.resp.Response.Directives = make([]interface{}, 1)
}
r.resp.Response.Directives = append(r.resp.Response.Directives, directive)

return r
}

// EventResponse provides information about an Amazon Alexa Skills event response
type EventResponse struct {
Version string `json:"version"`
SessionAttributes map[string]interface{} `json:"sessionAttributes"`
Response ResponseValue `json:"response"`
}

// ResponseValue provides specific response information in a EventResponse
type ResponseValue struct {
OutputSpeech *ResponseOutputSpeech `json:"outputSpeech,omitempty"`
Card *ResponseCard `json:"card,omitempty"`
Reprompt *ResponseReprompt `json:"reprompt,omitempty"`
Directives []interface{} `json:"directives,omitempty"` // See directives for interface information at https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#card-object
ShouldEndSession bool `json:"shouldEndSession"`
}

// ResponseOutputSpeech provides OutputSpeech information in an EventResponse
type ResponseOutputSpeech struct {
Type string `json:"type,omitempty"`
Text string `json:"text,omitempty"`
SSML string `json:"ssml,omitempty"`
}

// ResponseCard provides Card information in an EventResponse
type ResponseCard struct {
Type string `json:"type,omitempty"`
Title string `json:"title,omitempty"`
Content string `json:"content,omitempty"`
Text string `json:"text,omitempty"`
Image *ResponseCardImage `json:"image,omitempty"`
}

// ResponseCardImage provides image URLs for cards
type ResponseCardImage struct {
SmallImageURL string `json:"smallImageUrl,omitempty"`
LargeImageURL string `json:"largeImageUrl,omitempty"`
}

// ResponseReprompt provides OutputSpeech information for a reprompt in an EventResponse
type ResponseReprompt struct {
OutputSpeech *ResponseOutputSpeech `json:"outputSpeech,omitempty"`
}