From 75850d9f95de52a501caa1c913879c660d43e3c2 Mon Sep 17 00:00:00 2001 From: Kyle Vanek <> Date: Thu, 2 Nov 2017 15:40:16 -0700 Subject: [PATCH 1/2] Add EventSourceARN to DynamoDB stream event's definition --- service/lambda/runtime/event/dynamodbstreamsevt/definition.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/service/lambda/runtime/event/dynamodbstreamsevt/definition.go b/service/lambda/runtime/event/dynamodbstreamsevt/definition.go index b21ea75..5a00141 100644 --- a/service/lambda/runtime/event/dynamodbstreamsevt/definition.go +++ b/service/lambda/runtime/event/dynamodbstreamsevt/definition.go @@ -123,6 +123,9 @@ type EventRecord struct { // In our case the value is always "aws:dynamodb". EventSource string + // The DynamoDB table's ARN from which the stream record originated. + EventSourceARN string + // The region in which the GetRecords request was received. AWSRegion string From 40c1438671add2b4556f92bae5817e840d6b366a Mon Sep 17 00:00:00 2001 From: Kyle Vanek <> Date: Tue, 16 Jan 2018 16:45:48 -0800 Subject: [PATCH 2/2] Initial commit to add new Amazon Alexa Skills Kit Event type along with a response builder --- .../runtime/event/alexaskillsevt/README.md | 64 ++++++ .../event/alexaskillsevt/definition.go | 93 +++++++++ .../runtime/event/alexaskillsevt/doc.go | 22 ++ .../runtime/event/alexaskillsevt/response.go | 191 ++++++++++++++++++ 4 files changed, 370 insertions(+) create mode 100644 service/lambda/runtime/event/alexaskillsevt/README.md create mode 100644 service/lambda/runtime/event/alexaskillsevt/definition.go create mode 100644 service/lambda/runtime/event/alexaskillsevt/doc.go create mode 100644 service/lambda/runtime/event/alexaskillsevt/response.go diff --git a/service/lambda/runtime/event/alexaskillsevt/README.md b/service/lambda/runtime/event/alexaskillsevt/README.md new file mode 100644 index 0000000..59252c3 --- /dev/null +++ b/service/lambda/runtime/event/alexaskillsevt/README.md @@ -0,0 +1,64 @@ + + +# Amazon Alexa Skills Kit Events + +[Back to Home](/) +[![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. + +[](#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(`

Im responding to intent 2.

This will be said after a short pause

`).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 \ No newline at end of file diff --git a/service/lambda/runtime/event/alexaskillsevt/definition.go b/service/lambda/runtime/event/alexaskillsevt/definition.go new file mode 100644 index 0000000..f565077 --- /dev/null +++ b/service/lambda/runtime/event/alexaskillsevt/definition.go @@ -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() +} diff --git a/service/lambda/runtime/event/alexaskillsevt/doc.go b/service/lambda/runtime/event/alexaskillsevt/doc.go new file mode 100644 index 0000000..78224c5 --- /dev/null +++ b/service/lambda/runtime/event/alexaskillsevt/doc.go @@ -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 diff --git a/service/lambda/runtime/event/alexaskillsevt/response.go b/service/lambda/runtime/event/alexaskillsevt/response.go new file mode 100644 index 0000000..24f1ab2 --- /dev/null +++ b/service/lambda/runtime/event/alexaskillsevt/response.go @@ -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: `` + text + ``, + } + 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"` +}