Hardware components | ||||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
|
Here at thirteen23 we are huge fans of movies from the 1980s. We have an Echo here at the office and thought, "Wouldn't it be cool if we could ask Alexa for sound clips from our favorite movies?" Well, it didn't take long to make that a reality. And of course we had to call this Alexa skill Totally 80s.
Totally 80s is here to help you remember the movies of that era! Remember the first National Lampoon's Vacation? John Candy in Planes, Trains and Automobiles? Stallone in Rambo? Bruce Willis in Die Hard? These movies had some awesome lines, and we've created an app to bring them back to life in the comfort of our home through the Amazon Echo. We have clips from the following movies:
- Back to the Future
- Breakfast Club
- Better Off Dead
- Big Trouble in Little China
- Caddyshack
- Christmas Vacation
- Coming to America
- Die Hard
- E.T.
- Fast Times at Ridgemont High
- Ferris Bueller's Day Off
- Ghostbusters
- Raiders of the Lost Ark
- The Lost Boys
- Planes, Trains & Automobiles
- Poltergeist
- Pretty In Pink
- Rambo
- Real Genius
- Revenge of the Nerds
- Say Anything
- Scarface
- Sixteen Candles
- Spaceballs
- The Terminator
- The Karate Kid
- The Princess Bride
- The Shining
- Top Gun
- Vacation
- Weird Science
I assume you have an Echo. You do, right? Ok. Follow these steps and you are golden.
- Open the Alexa app
- Go to the Skills section
- Search for Totally 80s
- Enable Totally 80s
- Follow the directions on the Totally 80s page. For instance, try this:"Alexa, ask Totally 80s for a quote from Planes, Trains & Automobiles"
Probably the hardest thing about building this Skill was converting all of the audio clips. Some are sourced from the web, some are recorded. All are different formats. But Amazon requires very specific audio specs in order to play an audio clip by using the tag. Namely:
- The MP3 must be hosted at an Internet-accessible HTTPS endpoint. HTTPS is required, and the domain hosting the MP3 file must present a valid, trusted SSL certificate. Self-signed certificates cannot be used.
- The MP3 must not contain any customer-specific or other sensitive information.
- The MP3 must be a valid MP3 file (MPEG version 2).
- The audio file cannot be longer than ninety (90) seconds.
- The bit rate must be 48 kbps. Note that this bit rate gives a good result when used with spoken content, but is generally not a high enough quality for music.
I knew I had to find some way to batch-convert the audio files, otherwise I would be spending several nights doing it all by hand. Thus how I came across FFmpeg. FFmpeg is a utility for converting files using the command line. With a few attempts I was able to create a command line like this in order to do what I needed:
find . -name "*.wav" -exec bash -c 'ffmpeg -i "{}" -ab 48k -c mp3 -ac 2 -ar 16000 -af volume=2 "${0/.wav}.mp3"' {} \;
From there I saved those files up to our S3 server and we were good to go!
index.js
JavaScript/**
Copyright 2016 thirteen23. 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. A copy of the License is located at
http://aws.amazon.com/apache2.0/
or in the "license" file accompanying this file. This file 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.
*/
/**
* This skill is for remembering those silly quotes from movies gone by. The 1980s
* to be specific. It was time of innocence. A time when John Hughes ruled the teen
* movie space (see all his movies below). And a time when the internet didn't exist
* as we know it today. The skill is called Bueller, as in Ferris Bueller. And
* Bueller can call up lots of movie quotes from the following movies: Back to the Future,
* Breakfast Club, Better Off Dead, Big Trouble in Little China, Caddyshack, Christmas
* Vacation, Coming to America, Die Hard, E.T., Fast Times at Ridgemont High,
* Ferris Bueller's Day Off, Ghostbusters, Raiders of the Lost Ark, The Lost Boys,
* Planes, Trains and Automobiles, Poltergeist, Pretty In Pink, Rambo, Real
* Genius, Revenge of the Nerds, Say Anything, Scarface, Sixteen Candles, Spaceballs,
* The Terminator, The Karate Kid, The Princess Bride, The Shining, Top Gun,
* Vacation, and Weird Science. See below on how to hear a clip and have fun!
*
* Examples:
* One-shot model:
* User: "Alexa, ask Bueller for a quote."
* Alexa: <random movie clip>
* Specific movie model:
* User: "Alexa, ask Bueller for a quote from <insert movie name>"
* Alexa: <random movie clip from spoken movie name>
*/
/**
* App ID for the skill
*/
var APP_ID = "amzn1.echo-sdk-ams.app.4547d96d-cdd1-4fbd-b6d3-5d43c95b1694";
/**
* Prefix for the S3 server that holds the audio files.
*/
var serverPrefix = "https://s3.amazonaws.com/t23-play/audio/";
/**
* Arrays of all movies and their corresponding audio files.
*/
var BACKTOTHEFUTURE_QUOTES = [
"blindspot.mp3",
"calvinklein.mp3",
"gimmeatab.mp3",
"gotthehots.mp3",
"greatscott.mp3",
"jumpship.mp3",
"lightning.mp3",
"meltmybrain.mp3",
"myreports.mp3",
"nuclear.mp3",
"planetvulcan.mp3",
"plutonium2.mp3",
"ronaldreagan.mp3",
"savetheclock.mp3",
"seriousBLEEP.mp3",
"soheavy.mp3",
"television.mp3",
"thelybians.mp3",
"timemachine.mp3",
"toodarnloud.mp3",
"tothefuture.mp3",
"weekin1955.mp3",
"youraslacker.mp3",
"yourmymo.mp3"
];
var BREAKFASTCLUB_QUOTES = [
"breakfast_club.mp3",
"couldntignoreme.mp3",
"getthehorns.mp3",
"illadvised.mp3",
"itssushi.mp3",
"raidwardrobe.mp3",
"ruckus.mp3",
"skulls.mp3"
];
var BETTEROFFDEAD_QUOTES = [
"2dollars.mp3",
"2dollars2.mp3",
"2dollars4weeks.mp3",
"7years.mp3",
"adime.mp3",
"barneybeth.mp3",
"bethdumps.mp3",
"blewup.mp3",
"buckup.mp3",
"christmas.mp3",
"crydate.mp3",
"dates_team.mp3",
"drugs.mp3",
"entrance.mp3",
"friend.mp3",
"frzbrain.mp3",
"gothtway.mp3",
"hisnose.mp3",
"kickass.mp3",
"mailman_beth.mp3",
"memorize.mp3",
"meyer.mp3",
"mother_says.mp3",
"northern_ca.mp3",
"nose_flat.mp3",
"puresnow.mp3",
"race_lose_die.mp3",
"race01.mp3",
"raisins.mp3",
"relish.mp3",
"smut.mp3",
"spk_french.mp3",
"sunburn.mp3",
"thats_nice.mp3",
"virginity.mp3",
"whiteboy.mp3",
"worried.mp3",
"wtr_ballet.mp3"
];
var BIGTROUBLEINLITTLECHINA_QUOTES = [
"btlc-blackblood.mp3",
"btlc-comeon.mp3",
"btlc-see.mp3",
"CallThePrez.mp3",
"ComeOn.mp3",
"PissOff.mp3",
"ShutUp.mp3"
];
var CADDYSHACK_QUOTES = [
"1000buks.mp3",
"badhat.mp3",
"barkdog.mp3",
"bighit.mp3",
"cannonbl.mp3",
"cinderla.mp3",
"forkeeps.mp3",
"getlaid.mp3",
"gungagag.mp3",
"hegotall.mp3",
"inthehol.mp3",
"lean.mp3",
"letsgo.mp3",
"opencrtn.mp3",
"poontang.mp3",
"russia.mp3",
"shewrote.mp3",
"slouch.mp3",
"stepduck.mp3",
"tiemeup.mp3"
];
var CHRISTMASVACATION_QUOTES = [
"breakwind.mp3",
"eddie.mp3",
"grace.mp3",
"jellyfothemonth.mp3",
"lipfungus.mp3",
"merrychristmas.mp3",
"misery.mp3",
"mississippi.mp3",
"myboss.mp3",
"overdoingit.mp3",
"playball.mp3",
"snots.mp3",
"surprised.mp3",
"tenyards.mp3",
"thatsound.mp3",
"treelots.mp3",
"treethatbig.mp3",
"yulelog.mp3"
];
var COMINGTOAMERICA_QUOTES = [
"fineline.mp3",
"next.mp3",
"reallife.mp3"
];
var DIEHARD_QUOTES = [
"diehrd01.mp3",
"diehrd03.mp3",
"diehrd06.mp3",
"diehrd07.mp3",
"diehrd10.mp3",
"diehrd11.mp3",
"diehrd12.mp3"
];
var ET_QUOTES = [
"Mjg5MTIyNzcyODkxNzE_6IK1qQqT0r8.mp3",
"MTk3MjIyNzcxOTcyMzE_qU_2bNSlZoays.mp3",
"MzQwNTIyNzczNDA1OTI__2beTl9CbUM9Y.mp3",
"NjkzMjIyNzc2OTMzMDI_gk7z8j7DDaI.mp3",
"NzEzODIyNzc3MTM5MDM_RXnSAp2CJyE.mp3",
"Nzk3OTIyNzc3OTgwNjU_2RVEj279rSA.mp3",
"ODA0NjIyNzc4MDQ3MDE_ZLIRkji_2frGA.mp3",
"ODU5MDIyNzc4NTkwOTk_VlWQR7NlTBY.mp3"
];
var FASTTIMES_QUOTES = [
"class.mp3",
"fags.mp3",
"getajob.mp3",
"gnarly.mp3",
"halucin8.mp3",
"hey_bud.mp3",
"i-have.mp3",
"imwasted.mp3",
"moron.mp3",
"mr_hand.mp3",
"no-shirt.mp3",
"on-dope.mp3",
"playboy.mp3",
"prick.mp3",
"problem.mp3",
"tappin.mp3",
"thatdude.mp3",
"totally.mp3",
"ushistry.mp3",
"wasted.mp3",
"wus.mp3",
"yeah.mp3",
"you-dick.mp3"
];
var FERRISBUELLER_QUOTES = [
"batter.mp3",
"bezerk.mp3",
"BLEEPhole.mp3",
"dankeshn.mp3",
"diamond.mp3",
"dude.mp3",
"ferrari.mp3",
"holyBLEEP.mp3",
"ill_go.mp3",
"life.mp3",
"likenass.mp3",
"mortuary.mp3",
"playsick.mp3",
"psandqs.mp3",
"school.mp3",
"testicle.mp3",
"understd.mp3"
];
var GHOSTBUSTERS_QUOTES = [
"backoff.mp3",
"bad.mp3",
"bedroom.mp3",
"bitch.mp3",
"busthds.mp3",
"chore.mp3",
"dick.mp3",
"disaster.mp3",
"dog.mp3",
"goodeve.mp3",
"kicked.mp3",
"ok.mp3",
"results.mp3",
"rule.mp3",
"split_up.mp3",
"toast.mp3",
"toys.mp3"
];
var INDIANAJONES_QUOTES = [
"asps.mp3",
"backbone.mp3",
"how.mp3",
"snakes.mp3",
"thirsty.mp3"
];
var LOSTBOYS_QUOTES = [
"lbinvit.mp3",
"lbnite2.mp3",
"lbrules.mp3",
"lbstop.mp3",
"lbvamp.mp3"
];
var KARATEKID_QUOTES = [
"MjQ0OTU5ODU4MjQ0OTQx_p0dR42DQ9KY.mp3",
"MTI5MTU5ODU4MTI5MTMz_y1W63RpjwPY.mp3",
"MzM2MjU5ODU4MzM2MjQ5_w4VG6L1PioY.mp3",
"NjAwNDU5ODU4NjAwNTE4_PlzgwkNG5EA.mp3",
"NTc2NDU5ODU4NTc2NTM1_BMwScC8wKgo.mp3",
"NzE3MDU5ODU4NzE3MTM3_ITxsVPHUEn0.mp3",
"NzExMzU5ODU4NzExNDYw_D8b8OEWtcYo.mp3",
"NzYwMDU5ODU4NzYwMDgz_UUSAhd3Xo5I.mp3",
"OTA3MTU5ODU4OTA3Mjcx_Yqm9SemF44E.mp3",
"OTEyNjU5ODU4OTEyNzAz_K3phodHOfS0.mp3",
"OTMzMTU5ODU4OTMzMjI0_8mdQtimi_2b_2bE.mp3"
];
var PLANESTRAINSAUTOS_QUOTES = [
"pta001.mp3",
"pta002.mp3",
"pta003.mp3",
"pta004.mp3",
"pta005.mp3",
"pta007.mp3",
"pta009.mp3",
"pta010.mp3",
"pta012.mp3",
"pta015.mp3",
"pta016.mp3",
"pta018.mp3",
"pta019.mp3",
"pta020.mp3",
"pta024.mp3",
"pta025.mp3",
"pta026.mp3"
];
var POLTERGEIST_QUOTES = [
"cross_over.mp3",
"dream_state.mp3",
"get_it_away.mp3",
"life_force.mp3",
"mommy.mp3",
"never_sensed.mp3",
"pg2back.mp3",
"pg2tv.mp3",
"pgcann.mp3"
];
var PRETTYINPINK_QUOTES = [
"pip-admire.mp3",
"pip-bed.mp3",
"pip-believe.mp3",
"pip-believe2.mp3",
"pip-blaine.mp3",
"pip-breakme.mp3",
"pip-dontknow.mp3",
"pip-herelong.mp3",
"pip-ifyouleave.mp3",
"pip-kissed.mp3",
"pip-marvelous.mp3",
"pip-mother.mp3",
"pip-nexttime.mp3",
"pip-offend.mp3",
"pip-pretty.mp3",
"pip-ridebike.mp3",
"pip-ruining.mp3",
"pip-taste.mp3",
"pip-thatsit.mp3",
"pip-thetruth.mp3",
"pip-whatsthis.mp3",
"pip-woman.mp3"
];
var RAMBO_QUOTES = [
"fbbusy.mp3",
"fblife.mp3",
"fbmiss.mp3",
"fbres.mp3",
"fbwar.mp3"
];
var REALGENIUS_QUOTES = [
"NjE3NDY3ODM5NjE3NTIx_xWGxyMTA4VQ.mp3",
"NjUxODY3ODM5NjUxODcz_QDY_2fXpzeIXI.mp3",
"NTY3MzY3ODM5NTY3NDQ1_OdSy0OUoB14.mp3"
];
var REVENGEOFTHENERDS_QUOTES = [
"NDk3OTI5MDE0OTgwMzk_6CGMt_2faTERM.mp3",
"NTIxMjI5MDE1MjEzMDM_Xsn2Tx7sb34.mp3",
"NTk0NTI5MDE1OTQ1NzM_1FAciaMq6TM.mp3",
"NTM5NjI5MDE1Mzk2Njg_Vq2Y1ZVxBDc.mp3",
"ODA0NjI5MDE4MDQ3Mzc_WvUC7YgGII4.mp3",
"ODM5NjI5MDE4Mzk3NTg_gaj_2fGsBs_2bow.mp3"
];
var SAYANYTHING_QUOTES = [
"clip1.mp3",
"clip2.mp3",
"clip3.mp3",
"clip4.mp3",
"clip5.mp3",
"clip6.mp3"
];
var SCARFACE_QUOTES = [
"scarface_bad_guy.mp3",
"scarface_money.mp3",
"scarface_say_hello.mp3"
];
var SIXTEENCANDLES_QUOTES = [
"geek.mp3",
"hotstuff.mp3",
"nomore.mp3"
];
var SPACEBALLS_QUOTES = [
"chicken.mp3",
"dolls3.mp3",
"goodumb.mp3",
"half-man-half-dog.mp3",
"self-destruct-button.mp3",
"swartz.mp3"
];
var TERMINATOR_QUOTES = [
"t1_be_back.mp3",
"t1_clothes_x.mp3",
"t2_learning_computer_x.mp3"
];
var THEPRINCESSBRIDE_QUOTES = [
"boo.mp3",
"breasts.mp3",
"brutesquad.mp3",
"bye.mp3",
"coward.mp3",
"dead.mp3",
"decent.mp3",
"despair.mp3",
"killed.mp3",
"marraige.mp3",
"pry.mp3",
"rous.mp3",
"truelove.mp3",
"witch.mp3",
"worst.mp3"
];
var THESHINING_QUOTES = [
"allofredrum.mp3",
"heresjohnny.mp3",
"inmymouth.mp3",
"littlepigs.mp3",
"myconcentration.mp3",
"playwithus.mp3",
"room237.mp3",
"setemup.mp3",
"stayhere.mp3",
"wendyimhome.mp3",
"youlikelamb.mp3"
];
var TOPGUN_QUOTES = [
"aircraft.mp3",
"dangerous.mp3",
"defense2.mp3",
"flyby.mp3",
"hitbrake.mp3",
"lovinf.mp3",
"migdata.mp3",
"migstory.mp3",
"speed.mp3",
"stud.mp3"
];
var VACATION_QUOTES = [
"bro.mp3",
"helper.mp3",
"kiss.mp3",
"sorry.mp3"
];
var WEIRDSCIENCE_QUOTES = [
"brasonhead.mp3",
"chess.mp3",
"dickweed.mp3",
"dofirst.mp3",
"dontruinthefantasy.mp3",
"morgue.mp3",
"partyanimal.mp3",
"pukes.mp3",
"sandwich.mp3",
"seriousbitch.mp3",
"shutup.mp3",
"sprain.mp3",
"toaster.mp3",
"wanker.mp3",
"yourestewed.mp3"
];
/**
* This Array puts it all together: the movie title as lower case and no spaces, array of audio clips,
* and the audio folder name on the S3 server.
*/
var MOVIES = [
{title:"backtothefuture",ary:BACKTOTHEFUTURE_QUOTES,audioFolder:"backtothefuture"},
{title:"breakfastclub",ary:BREAKFASTCLUB_QUOTES,audioFolder:"bc"},
{title:"betteroffdead",ary:BETTEROFFDEAD_QUOTES,audioFolder:"bod"},
{title:"bigtroubleinlittlechina",ary:BIGTROUBLEINLITTLECHINA_QUOTES,audioFolder:"bigtroubleinlittlechina"},
{title:"caddyshack",ary:CADDYSHACK_QUOTES,audioFolder:"cs"},
{title:"christmasvacation",ary:CHRISTMASVACATION_QUOTES,audioFolder:"christmasvacation"},
{title:"comingtoamerica",ary:COMINGTOAMERICA_QUOTES,audioFolder:"comingtoamerica"},
{title:"diehard",ary:DIEHARD_QUOTES,audioFolder:"diehard"},
{title:"et",ary:ET_QUOTES,audioFolder:"et"},
{title:"fasttimesatridgemonthigh",ary:FASTTIMES_QUOTES,audioFolder:"fasttimes"},
{title:"ferrisbuellersdayoff",ary:FERRISBUELLER_QUOTES,audioFolder:"ferrisbueller"},
{title:"ghostbusters",ary:GHOSTBUSTERS_QUOTES,audioFolder:"ghostbusters"},
{title:"indianajones",ary:INDIANAJONES_QUOTES,audioFolder:"indianajones"},
{title:"raidersofthelostark",ary:INDIANAJONES_QUOTES,audioFolder:"indianajones"},
{title:"lostboys",ary:LOSTBOYS_QUOTES,audioFolder:"lostboys"},
{title:"thelostboys",ary:LOSTBOYS_QUOTES,audioFolder:"lostboys"},
{title:"karatekid",ary:KARATEKID_QUOTES,audioFolder:"karatekid"},
{title:"thekaratekid",ary:KARATEKID_QUOTES,audioFolder:"karatekid"},
{title:"planestrainsandautomobiles",ary:PLANESTRAINSAUTOS_QUOTES,audioFolder:"planestrainsandautos"},
{title:"poltergeist",ary:POLTERGEIST_QUOTES,audioFolder:"poltergeist"},
{title:"prettyinpink",ary:PRETTYINPINK_QUOTES,audioFolder:"pip"},
{title:"rambo",ary:RAMBO_QUOTES,audioFolder:"rambo"},
{title:"realgenius",ary:REALGENIUS_QUOTES,audioFolder:"realgenius"},
{title:"revengeofthenerds",ary:REVENGEOFTHENERDS_QUOTES,audioFolder:"revengeofthenerds"},
{title:"sayanything",ary:SAYANYTHING_QUOTES,audioFolder:"sayanything"},
{title:"scarface",ary:SCARFACE_QUOTES,audioFolder:"scarface"},
{title:"sixteencandles",ary:SIXTEENCANDLES_QUOTES,audioFolder:"sc"},
{title:"spaceballs",ary:SPACEBALLS_QUOTES,audioFolder:"spaceballs"},
{title:"terminator",ary:TERMINATOR_QUOTES,audioFolder:"terminator"},
{title:"theterminator",ary:TERMINATOR_QUOTES,audioFolder:"terminator"},
{title:"theprincessbride",ary:THEPRINCESSBRIDE_QUOTES,audioFolder:"princessbride"},
{title:"princessbride",ary:THEPRINCESSBRIDE_QUOTES,audioFolder:"princessbride"},
{title:"theshining",ary:THESHINING_QUOTES,audioFolder:"theshining"},
{title:"shining",ary:THESHINING_QUOTES,audioFolder:"theshining"},
{title:"16candles",ary:SIXTEENCANDLES_QUOTES,audioFolder:"sc"},
{title:"topgun",ary:TOPGUN_QUOTES,audioFolder:"topgun"},
{title:"vacation",ary:VACATION_QUOTES,audioFolder:"vacation"},
{title:"weirdscience",ary:WEIRDSCIENCE_QUOTES,audioFolder:"weirdscience"}
];
/**
* The AlexaSkill prototype and helper functions
*/
var AlexaSkill = require('./AlexaSkill');
/**
* Bueller is a child of AlexaSkill.
* To read more about inheritance in JavaScript, see the link below.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
*/
var Bueller = function () {
AlexaSkill.call(this, APP_ID);
};
// Extend AlexaSkill
Bueller.prototype = Object.create(AlexaSkill.prototype);
Bueller.prototype.constructor = Bueller;
/**
* Function to invoke anything when starting up. (nothing at this time)
*/
Bueller.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
console.log("Bueller onSessionStarted requestId: " + sessionStartedRequest.requestId
+ ", sessionId: " + session.sessionId);
};
/**
* Once launched we go ahead and handle the request from the Echo.
*/
Bueller.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
console.log("Bueller onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
//Call for a movie quote with no movie title
handleNewFactRequest(response, null);
};
/**
* Overridden to show that a subclass can override this function to teardown session state.
*/
Bueller.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
console.log("Bueller onSessionEnded requestId: " + sessionEndedRequest.requestId
+ ", sessionId: " + session.sessionId);
// any cleanup logic goes here
};
Bueller.prototype.intentHandlers = {
"GetRandomQuoteIntent": function (intent, session, response) {
//Grab the movie title, whether it exists or not
var movieSlot = intent.slots.Movie;
//Call for a movie quote with possible movie title
handleNewFactRequest(response, movieSlot);
},
"AMAZON.HelpIntent": function (intent, session, response) {
response.ask("You can get a random movie clip by saying open bueller. You can also say Alexa, ask bueller for a quote. If you want a specific movie, you can say, for example, Alexa, ask bueller for a quote from die hard.", "What can I help you with?");
},
"AMAZON.StopIntent": function (intent, session, response) {
var speechOutput = "Goodbye";
response.tell(speechOutput);
},
"AMAZON.CancelIntent": function (intent, session, response) {
var speechOutput = "Goodbye";
response.tell(speechOutput);
}
};
/**
* Gets a random movie clip to play or a clip specific to the movie passed in.
*/
function handleNewFactRequest(response, movieSlot) {
var index = 0;
if (movieSlot && movieSlot.value) {
// First we need to see if the movie spoken exists in our set of movie titles.
var movieKey = movieSlot.value.toLowerCase();
movieKey = movieKey.replace(/\s/g, '');
console.log("movie name: " + movieKey);
for (var j = 0; j < MOVIES.length; j++) {
var tempObj = MOVIES[j];
//console.log("lengths: " + tempObj.title.length + "::" + movieKey.length);
if ((tempObj.title.indexOf(movieKey) >= 0) && (tempObj.title.length == movieKey.length)) {
index = j;
break;
}
}
} else {
// If it doesn't, we grab a random movie.
index = Math.floor(Math.random() * MOVIES.length);
}
// Get the folder where the audio file exists to help build the URL.
var audioFolder = MOVIES[index].audioFolder;
// Get the array of audio files for that movie.
var moviesList = MOVIES[index].ary;
// Get a random index for grabbing a random clip from the list.
index = Math.floor(Math.random() * moviesList.length);
// Build the URL for the movie quote.
var quote = serverPrefix + audioFolder + "/" + moviesList[index];
// Create speech output
var speechOutput = "<speak><audio src='" + quote + "' /> </speak>";
console.log("output: " + speechOutput);
response.tellWithCard(speechOutput, "Bueller", speechOutput);
}
// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
// Create an instance of the Bueller skill.
var bueller_new = new Bueller();
bueller_new.execute(event, context);
};
/**
Copyright 2014-2015 Amazon.com, Inc. or its affiliates. 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. A copy of the License is located at
http://aws.amazon.com/apache2.0/
or in the "license" file accompanying this file. This file 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.
*/
'use strict';
function AlexaSkill(appId) {
this._appId = appId;
}
AlexaSkill.speechOutputType = {
PLAIN_TEXT: 'PlainText',
SSML: 'SSML'
}
AlexaSkill.prototype.requestHandlers = {
LaunchRequest: function (event, context, response) {
this.eventHandlers.onLaunch.call(this, event.request, event.session, response);
},
IntentRequest: function (event, context, response) {
this.eventHandlers.onIntent.call(this, event.request, event.session, response);
},
SessionEndedRequest: function (event, context) {
this.eventHandlers.onSessionEnded(event.request, event.session);
context.succeed();
}
};
/**
* Override any of the eventHandlers as needed
*/
AlexaSkill.prototype.eventHandlers = {
/**
* Called when the session starts.
* Subclasses could have overriden this function to open any necessary resources.
*/
onSessionStarted: function (sessionStartedRequest, session) {
},
/**
* Called when the user invokes the skill without specifying what they want.
* The subclass must override this function and provide feedback to the user.
*/
onLaunch: function (launchRequest, session, response) {
throw "onLaunch should be overriden by subclass";
},
/**
* Called when the user specifies an intent.
*/
onIntent: function (intentRequest, session, response) {
var intent = intentRequest.intent,
intentName = intentRequest.intent.name,
intentHandler = this.intentHandlers[intentName];
if (intentHandler) {
console.log('dispatch intent = ' + intentName);
intentHandler.call(this, intent, session, response);
} else {
throw 'Unsupported intent = ' + intentName;
}
},
/**
* Called when the user ends the session.
* Subclasses could have overriden this function to close any open resources.
*/
onSessionEnded: function (sessionEndedRequest, session) {
}
};
/**
* Subclasses should override the intentHandlers with the functions to handle specific intents.
*/
AlexaSkill.prototype.intentHandlers = {};
AlexaSkill.prototype.execute = function (event, context) {
try {
console.log("session applicationId: " + event.session.application.applicationId);
// Validate that this request originated from authorized source.
if (this._appId && event.session.application.applicationId !== this._appId) {
console.log("The applicationIds don't match : " + event.session.application.applicationId + " and "
+ this._appId);
throw "Invalid applicationId";
}
if (!event.session.attributes) {
event.session.attributes = {};
}
if (event.session.new) {
this.eventHandlers.onSessionStarted(event.request, event.session);
}
// Route the request to the proper handler which may have been overriden.
var requestHandler = this.requestHandlers[event.request.type];
requestHandler.call(this, event, context, new Response(context, event.session));
} catch (e) {
console.log("Unexpected exception " + e);
context.fail(e);
}
};
var Response = function (context, session) {
this._context = context;
this._session = session;
};
function createSpeechObject(optionsParam) {
if (optionsParam && optionsParam.type === 'SSML') {
return {
type: optionsParam.type,
ssml: optionsParam.speech
};
} else {
return {
//type: optionsParam.type || 'PlainText',
//HACK
type: optionsParam.type || 'SSML',
//text: optionsParam.speech || optionsParam
ssml: optionsParam.speech || optionsParam
}
}
}
Response.prototype = (function () {
var buildSpeechletResponse = function (options) {
var alexaResponse = {
outputSpeech: createSpeechObject(options.output),
shouldEndSession: options.shouldEndSession
};
if (options.reprompt) {
alexaResponse.reprompt = {
outputSpeech: createSpeechObject(options.reprompt)
};
}
if (options.cardTitle && options.cardContent) {
alexaResponse.card = {
type: "Simple",
title: options.cardTitle,
content: options.cardContent
};
}
var returnResult = {
version: '1.0',
response: alexaResponse
};
if (options.session && options.session.attributes) {
returnResult.sessionAttributes = options.session.attributes;
}
return returnResult;
};
return {
tell: function (speechOutput) {
this._context.succeed(buildSpeechletResponse({
session: this._session,
output: speechOutput,
shouldEndSession: true
}));
},
tellWithCard: function (speechOutput, cardTitle, cardContent) {
this._context.succeed(buildSpeechletResponse({
session: this._session,
output: speechOutput,
cardTitle: cardTitle,
cardContent: cardContent,
shouldEndSession: true
}));
},
ask: function (speechOutput, repromptSpeech) {
this._context.succeed(buildSpeechletResponse({
session: this._session,
output: speechOutput,
reprompt: repromptSpeech,
shouldEndSession: false
}));
},
askWithCard: function (speechOutput, repromptSpeech, cardTitle, cardContent) {
this._context.succeed(buildSpeechletResponse({
session: this._session,
output: speechOutput,
reprompt: repromptSpeech,
cardTitle: cardTitle,
cardContent: cardContent,
shouldEndSession: false
}));
}
};
})();
module.exports = AlexaSkill;
Comments