Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/mainline' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
deegles committed Aug 24, 2016
2 parents 4a36c9f + 590ea5d commit 852ed37
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 8 deletions.
156 changes: 151 additions & 5 deletions lib/alexa.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ function AlexaRequestEmitter() {
util.inherits(AlexaRequestEmitter, EventEmitter);

function alexaRequestHandler(event, context, callback) {
if(!event.session['attributes']) {
if (!event.session) {
event.session = { 'attributes': {} };
} else if (!event.session['attributes']) {
event.session['attributes'] = {};
}

Expand Down Expand Up @@ -83,7 +85,19 @@ function HandleLambdaEvent() {
var event = this._event;
var context = this._context;
var handlerAppId = this.appId;
var requestAppId = event.session.application.applicationId;

var requestAppId = '';
var userId = '';

// Long-form audio enabled skills use event.context
if (event.context) {
requestAppId = event.context.System.application.applicationId;
userId = event.context.System.user.userId;
} else if (event.session) {
requestAppId = event.session.application.applicationId;
userId = event.session.user.userId;
}


if(!handlerAppId){
console.log('Warning: Application ID is not set');
Expand All @@ -96,8 +110,8 @@ function HandleLambdaEvent() {
return context.fail('Invalid ApplicationId: ' + handlerAppId);
}

if(this.dynamoDBTableName && event.session['new']) {
attributesHelper.get(this.dynamoDBTableName, event.session.user.userId, (err, data) => {
if(this.dynamoDBTableName && (!event.session.sessionId || event.session['new']) ) {
attributesHelper.get(this.dynamoDBTableName, userId, (err, data) => {
if(err) {
return context.fail('Error fetching user state: ' + err);
}
Expand Down Expand Up @@ -128,6 +142,10 @@ function EmitEvent() {
eventString = this._event.request.intent.name;
} else if (this._event.request.type === 'SessionEndedRequest'){
eventString = 'SessionEndedRequest';
} else if (this._event.request.type.substring(0,11) === 'AudioPlayer') {
eventString = this._event.request.type.substring(12);
} else if (this._event.request.type.substring(0,18) === 'PlaybackController') {
eventString = this._event.request.type.substring(19);
}

eventString += this.state;
Expand Down Expand Up @@ -174,7 +192,8 @@ function RegisterHandlers() {
attributes: this._event.session.attributes,
context: this._context,
name: eventName,
isOverridden: IsOverridden.bind(this, eventName)
isOverridden: IsOverridden.bind(this, eventName),
response: ResponseBuilder(this)
};

this.on(eventName, handlerObject[eventNames[i]].bind(handlerContext));
Expand All @@ -190,6 +209,133 @@ function IsOverridden(name) {
return this.listenerCount(name) > 1;
}

function ResponseBuilder(self) {
var responseObject = self.response;
responseObject.version = '1.0';
responseObject.response = {
shouldEndSession: true
};
responseObject.sessionAttributes = self._event.session.attributes;

return (function () {
return {
'speak': function (speechOutput) {
responseObject.response.outputSpeech = createSSMLSpeechObject(speechOutput);
return this;
},
'listen': function (repromptSpeech) {
responseObject.response.reprompt = {
outputSpeech: createSSMLSpeechObject(repromptSpeech)
};
responseObject.response.shouldEndSession = false;
return this;
},
'cardRenderer': function (cardTitle, cardContent, cardImage) {
var card = {
type: 'Simple',
title: cardTitle,
content: cardContent
};

if(cardImage && (cardImage.smallImageUrl || cardImage.largeImageUrl)) {
card.type = 'Standard';
card['image'] = {};

delete card.content;
card.text = cardContent;

if(cardImage.smallImageUrl) {
card.image['smallImageUrl'] = cardImage.smallImageUrl;
}

if(cardImage.largeImageUrl) {
card.image['largeImageUrl'] = cardImage.largeImageUrl;
}
}

responseObject.response.card = card;
return this;
},
'linkAccountCard': function () {
responseObject.response.card = {
type: 'LinkAccount'
};
return this;
},
'audioPlayer': function (directiveType, behavior, url, token, expectedPreviousToken, offsetInMilliseconds) {
var audioPlayerDirective;
if (directiveType === 'play') {
audioPlayerDirective = {
"type": "AudioPlayer.Play",
"playBehavior": behavior,
"audioItem": {
"stream": {
"url": url,
"token": token,
"expectedPreviousToken": expectedPreviousToken,
"offsetInMilliseconds": offsetInMilliseconds
}
}
};
} else if (directiveType === 'stop') {
audioPlayerDirective = {
"type": "AudioPlayer.Stop"
};
} else {
audioPlayerDirective = {
"type": "AudioPlayer.Stop",
"clearBehavior": behavior
};
}

responseObject.response.directives = [audioPlayerDirective];
return this;
},
'audioPlayerPlay': function (behavior, url, token, expectedPreviousToken, offsetInMilliseconds) {
var audioPlayerDirective = {
"type": "AudioPlayer.Play",
"playBehavior": behavior,
"audioItem": {
"stream": {
"url": url,
"token": token,
"expectedPreviousToken": expectedPreviousToken,
"offsetInMilliseconds": offsetInMilliseconds
}
}
};

responseObject.response.directives = [audioPlayerDirective];
return this;
},
'audioPlayerStop': function () {
var audioPlayerDirective = {
"type": "AudioPlayer.Stop"
};

responseObject.response.directives = [audioPlayerDirective];
return this;
},
'audioPlayerClearQueue': function (clearBehavior) {
var audioPlayerDirective = {
"type": "AudioPlayer.ClearQueue",
"playBehavior": clearBehavior
};

responseObject.response.directives = [audioPlayerDirective];
return this;
}
}
})();
}

function createSSMLSpeechObject(message) {
return {
type: 'SSML',
ssml: `<speak> ${message} </speak>`
};
}

function createStateHandler(state, obj){
if(!obj) {
obj = {};
Expand Down
21 changes: 18 additions & 3 deletions lib/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,31 @@ module.exports = (function () {
this.attributes['STATE'] = this.handler.state;
}

var userId = '';

// Long-form audio enabled skills use event.context
if (this.event.context) {
userId = this.event.context.System.user.userId;
} else if (this.event.session) {
userId = this.event.session.user.userId;
}

if(this.saveBeforeResponse || forceSave || this.handler.response.response.shouldEndSession) {
attributesHelper.set(this.handler.dynamoDBTableName, this.event.session.user.userId, this.attributes,
attributesHelper.set(this.handler.dynamoDBTableName, userId, this.attributes,
(err) => {
if(err) {
return this.emit(':saveStateError', err);
}

// To save the state when AudioPlayer Requests come without sending a response.
if (Object.keys(this.handler.response).length === 0 && this.handler.response.constructor === Object) {
this.handler.response = true;
}

this.context.succeed(this.handler.response);
});
});
} else {
this.context.succeed(this.handler.response);
this.context.succeed(this.handler.response || true);
}
},
':saveStateError': function(err) {
Expand Down

0 comments on commit 852ed37

Please sign in to comment.