From 9cbeda7ccc5a82dc74f9dc32c462f2d2a573bbbf Mon Sep 17 00:00:00 2001 From: Mario LOPEZ-RAMOS Date: Mon, 25 Nov 2019 19:15:18 +0100 Subject: [PATCH] Before saying goodbye and stopping, check first whether this skill is currently playing audio. --- multiple-streams/lambda/src/index.js | 26 +++++++-- .../stop_intent_while_not_playing.json | 51 +++++++++++++++++ .../test/test_stop_while_not_playing.js | 55 +++++++++++++++++++ single-stream/lambda/src/IntentHandlers.ts | 10 +++- .../lambda/test/request/pause_intent.json | 2 +- .../stop_intent_while_not_playing.json | 42 ++++++++++++++ .../test_stop_intent_while_not_playing.ts | 50 +++++++++++++++++ 7 files changed, 230 insertions(+), 6 deletions(-) create mode 100644 multiple-streams/lambda/test/requests/stop_intent_while_not_playing.json create mode 100644 multiple-streams/lambda/test/test_stop_while_not_playing.js create mode 100644 single-stream/lambda/test/request/stop_intent_while_not_playing.json create mode 100644 single-stream/lambda/test/test_stop_intent_while_not_playing.ts diff --git a/multiple-streams/lambda/src/index.js b/multiple-streams/lambda/src/index.js index 7163d8d..d1b5565 100755 --- a/multiple-streams/lambda/src/index.js +++ b/multiple-streams/lambda/src/index.js @@ -488,10 +488,28 @@ const controller = { return responseBuilder.getResponse(); }, - stop(handlerInput) { - return handlerInput.responseBuilder - .addAudioPlayerStopDirective() - .getResponse(); + async stop(handlerInput) { + + // Get the token of what was playing last + const playbackInfo = await getPlaybackInfo(handlerInput); + const { + playOrder, + offsetInMilliseconds, + index + } = playbackInfo; + const token = playOrder[index]; + + // Stop and say goodbye only if this skill is playing audio + if (handlerInput.requestEnvelope.context + && handlerInput.requestEnvelope.context.AudioPlayer + && handlerInput.requestEnvelope.context.AudioPlayer.playerActivity === "PLAYING" + && handlerInput.requestEnvelope.context.AudioPlayer.token === token) { + return handlerInput.responseBuilder + .addAudioPlayerStopDirective() + .getResponse(); + } else { + return handlerInput.responseBuilder.getResponse(); + } }, async playNext(handlerInput) { const { diff --git a/multiple-streams/lambda/test/requests/stop_intent_while_not_playing.json b/multiple-streams/lambda/test/requests/stop_intent_while_not_playing.json new file mode 100644 index 0000000..41befa9 --- /dev/null +++ b/multiple-streams/lambda/test/requests/stop_intent_while_not_playing.json @@ -0,0 +1,51 @@ +{ + "version": "1.0", + "session": { + "new": false, + "sessionId": "amzn1.echo-api.session.123", + "application": { + "applicationId": "amzn1.ask.skill.123" + }, + "user": { + "userId": "amzn1.ask.account.123" + } + }, + "context": { + "AudioPlayer": { + "playerActivity": "STOPPED" + }, + "Display": { + "token": "" + }, + "System": { + "application": { + "applicationId": "amzn1.ask.skill.123" + }, + "user": { + "userId": "amzn1.ask.account.123" + }, + "device": { + "deviceId": "amzn1.ask.device.123", + "supportedInterfaces": { + "AudioPlayer": {}, + "Display": { + "templateVersion": "1.0", + "markupVersion": "1.0" + } + } + }, + "apiEndpoint": "https://api.eu.amazonalexa.com", + "apiAccessToken": "ey...yw" + } + }, + "request" : { + "type": "IntentRequest", + "requestId": "amzn1.echo-api.request.123", + "timestamp": "2018-05-01T06:57:17Z", + "locale": "en-GB", + "intent": { + "name": "AMAZON.StopIntent", + "confirmationStatus": "NONE" + } + } +} \ No newline at end of file diff --git a/multiple-streams/lambda/test/test_stop_while_not_playing.js b/multiple-streams/lambda/test/test_stop_while_not_playing.js new file mode 100644 index 0000000..6a4ab3b --- /dev/null +++ b/multiple-streams/lambda/test/test_stop_while_not_playing.js @@ -0,0 +1,55 @@ +'use strict'; + +let chai = require('chai'); +chai.use(require('chai-string')); + +let should = chai.should(); +let assert = chai.assert; + +let response; + +describe('Multiple Stream Audio Player Test : Stop Intent while not playing audio', function () { + + this.timeout(5000); + + // pre-requisites + before(() => { + return new Promise((resolve, reject) => { + const event = require('./requests/stop_intent_while_not_playing.json') + let lambda = require('../src/index'); + lambda.handler(event, null, (error, result) => { + console.log('******* RESPONSE *********'); + console.log(JSON.stringify(result, null, 2)); + console.log('**************************'); + response = result; + resolve(); + }); + }); + }); + + it('responds with valid response structure ', () => { + + response.should.have.property("version"); + response.version.should.equal("1.0"); + }), + + it('does not respond with output speech ', () => { + + response.should.have.property("response"); + let r = response.response; + + r.should.not.have.property("outputSpeech"); + + }), + + it('does not respond with a directive ', () => { + + let r = response.response; + r.should.have.property("shouldEndSession"); + r.shouldEndSession.should.be.true; + + r.should.have.property("directives"); + r.directives.should.have.lengthOf(0); + + }); +}); \ No newline at end of file diff --git a/single-stream/lambda/src/IntentHandlers.ts b/single-stream/lambda/src/IntentHandlers.ts index 84444de..713205b 100644 --- a/single-stream/lambda/src/IntentHandlers.ts +++ b/single-stream/lambda/src/IntentHandlers.ts @@ -177,7 +177,15 @@ class Util { return this['AMAZON.StopIntent'](input); }, 'AMAZON.StopIntent': async function (input: HandlerInput): Promise { - return Promise.resolve(audio.stop(i18n.S(input.requestEnvelope.request, 'STOP_MSG'))); + // Stop and say goodbye only if this skill is playing audio + if (input.requestEnvelope.context + && input.requestEnvelope.context.AudioPlayer + && input.requestEnvelope.context.AudioPlayer.playerActivity === "PLAYING" + && input.requestEnvelope.context.AudioPlayer.token === audioData(input.requestEnvelope.request).url) { + return Promise.resolve(audio.stop(i18n.S(input.requestEnvelope.request, 'STOP_MSG'))); + } else { + return Promise.resolve(input.responseBuilder.getResponse()); + } }, 'AMAZON.ResumeIntent': async function (input: HandlerInput): Promise { diff --git a/single-stream/lambda/test/request/pause_intent.json b/single-stream/lambda/test/request/pause_intent.json index 80cbc98..c1b9240 100644 --- a/single-stream/lambda/test/request/pause_intent.json +++ b/single-stream/lambda/test/request/pause_intent.json @@ -14,7 +14,7 @@ "AudioPlayer": { "offsetInMilliseconds": 3768, "token": "https://audio1.maxi80.com", - "playerActivity": "STOPPED" + "playerActivity": "PLAYING" }, "System": { "application": { diff --git a/single-stream/lambda/test/request/stop_intent_while_not_playing.json b/single-stream/lambda/test/request/stop_intent_while_not_playing.json new file mode 100644 index 0000000..31e5e89 --- /dev/null +++ b/single-stream/lambda/test/request/stop_intent_while_not_playing.json @@ -0,0 +1,42 @@ +{ + "version": "1.0", + "session": { + "new": true, + "sessionId": "amzn1.echo-api.session.123", + "application": { + "applicationId": "amzn1.ask.skill.123" + }, + "user": { + "userId": "amzn1.ask.account.123" + } + }, + "context": { + "AudioPlayer": { + "offsetInMilliseconds": 255764, + "token": "https://audio1.maxi80.com", + "playerActivity": "STOPPED" + }, + "System": { + "application": { + "applicationId": "amzn1.ask.skill.123" + }, + "user": { + "userId": "amzn1.ask.account.123" + }, + "device": { + "supportedInterfaces": { + "AudioPlayer": {} + } + } + } + }, + "request": { + "type": "IntentRequest", + "requestId": "amzn1.echo-api.request.123", + "timestamp": "2017-03-13T22:39:07Z", + "locale": "en-GB", + "intent": { + "name": "AMAZON.StopIntent" + } + } +} \ No newline at end of file diff --git a/single-stream/lambda/test/test_stop_intent_while_not_playing.ts b/single-stream/lambda/test/test_stop_intent_while_not_playing.ts new file mode 100644 index 0000000..496b0b5 --- /dev/null +++ b/single-stream/lambda/test/test_stop_intent_while_not_playing.ts @@ -0,0 +1,50 @@ +'use strict'; + +import 'mocha'; +import { expect } from 'chai'; +import { RequestEnvelope, ResponseEnvelope } from 'ask-sdk-model'; +import { handler as skill } from '../src/index'; + +import r from './request/stop_intent_while_not_playing.json'; // tslint:disable-line +const request: RequestEnvelope = r; + +import { Assertion } from './utils/Assertion'; +const A = new Assertion(); + +const USER_ID = "amzn1.ask.account.123"; +let skill_response: ResponseEnvelope; + + +describe('Audio Player Test : StopIntent while not playing audio', function () { + + // pre-requisites + before(() => { + + this.timeout(5000); + + return new Promise((resolve, reject) => { + skill(request, null, (error, responseEnvelope) => { + skill_response = responseEnvelope; + resolve(); + }); + }); + }); + + + it('responds with valid response structure ', () => { + + A.checkResponseStructure(skill_response); + }), + + it('does not respond with output speech ', () => { + + A.checkNoOutputSpeach(skill_response); + }), + + it('responds with no directive ', () => { + + let r = skill_response.response; + expect(r).to.not.have.property("directives"); + + }); +}); \ No newline at end of file