Cristian Muraru
Published © GPL3+

Movie World

Movie World is a tool helping users to find info from the movies world. Right now it can be asked for the best/popular movies and actors.

IntermediateWork in progress12 hours261
Movie World

Things used in this project

Story

Read more

Schematics

Movie World - Alexa flows

These are the Alexa flows implemented so far by Movie World. Soon will be added new Alexa Skills to the Movie World app so that this chart will improve

Code

index.js

JavaScript
Nodejs pivot file into the AWS Lambda
    // JavaScript Document
    /* eslint-disable  func-names */
    /* eslint quote-props: ["error", "consistent"]*/
    /**
     * This sample demonstrates a simple skill built with the Amazon Alexa Skills
     * nodejs skill development kit.
     * This sample supports en-US lauguage.
     * The Intent Schema, Custom Slots and Sample Utterances for this skill, as well
     * as testing instructions are located at https://github.com/alexa/skill-sample-nodejs-trivia
     **/
    
    'use strict';
    
    const Alexa = require('alexa-sdk');
    const https = require('https');
    const arrDigits =[
      "zero",
      "one",
      "two",
      "three",
      "four",
      "five",
      "six",
      "seven",
      "eight",
      "nine",
      "ten"
    ];
    
    const APP_NAME = 'Movie World';
    const APP_ID =  'amzn1.ask.skill.xxx';
    
    const APP_STATES = {
        TRIVIA: '_TRIVIAMODE', // Asking trivia questions.
        START: '_STARTMODE', // Entry point, start the app.
        HELP: '_HELPMODE', // The user is asking for help.
    };
    
    const newSessionHandlers = {
        /**
         * Entry point. Start a new app on new session. Handle any setup logic here.
         */
        'NewSession': function () {
            this.handler.state = APP_STATES.START;
            if (this.event.request.type === 'LaunchRequest') {
                this.emitWithState('AppStart', true);
            } else if (this.event.request.type === 'IntentRequest') {
                //console.log(`current intent: ${this.event.request.intent.name
                //    }, current state:${this.handler.state}`);
                const intent = this.event.request.intent.name;
                //console.log(`nume intent: ${intent}`);
                this.emitWithState(intent);
            }
        },
    
        'SessionEndedRequest': function () {
            const speechOutput = 'OK, Goodbye!';
            this.emit(':tell', speechOutput);
        },
    };
    
    const createStateHandler = Alexa.CreateStateHandler;
    
    const triviaStateHandlers = createStateHandler(APP_STATES.START, {
        
        'HelloMovieWorldIntent': function() {
            const speechOutput = 'Welcome to Movie World! We\'re very happy to hear you. Let\'s start our conversation. Ask me anything you want to know about movie world.';
            //console.log(`Din Movie World intent!`);
            this.emit(':tell', speechOutput);    
        },
        
        'AppStart': function() {
            const speechOutput = 'Welcome to Movie World! I love you Ecaterina! Now, let\'s start our conversation.';
            //console.log(`Din Movie World intent!`);
            this.emit(':tell', speechOutput);    
        },
        'AskActorIntent' : function() {
            var filme = [];
            var strActorName = this.event.request.intent.slots.ACTORNAME.value;
            var objP = this;
            
            if ((typeof(strActorName) !== 'undefined')) {
                
              //if (intNbMovies > 10) {
              //  intNbMovies = 10;
              //}
              var strActorNameSanit = strActorName.replace(/ /g, "%20");  
              console.log(`Actorul sanitizat: `+strActorNameSanit)
              var options = {
                "method": "GET",
                "hostname": "api.themoviedb.org",
                "port": null,
                "path": "/3/search/person?include_adult=true&page=1&query="+strActorNameSanit+"&language=en-US&api_key=ddd",
                "headers": {}
              };
              
              var req = https.request(options, function (res) {
                var chunks = [];
                //console.log(`A intrat in responsul lui request...`);
                
                res.on("data", function (chunk) {
                  chunks.push(chunk);
                  //console.log(`Scrie data...`);
                });
              
                res.on("end", function () {
                  var body = Buffer.concat(chunks);
                  //console.log(body.toString());
                  //console.log(`Am scris data.`);
                  var objData = JSON.parse(body);
                  
                  var speechOutput = '';
                  
                  if (typeof(objData) !== 'undefined'){ 
                      if (objData["results"].length < 1) {
                          speechOutput += 'Sorry, we don\'t know who \"'+ strActorName +'\" is. Please try again with a real comedian !';
                          //this.emit(':tell', speechOutput);                         
                      }else{
                          speechOutput += 'Yes \"'+ strActorName +'\" is known in the Movie World for the folowing movies:';
                          for (var i = 0, len = objData["results"][0]["known_for"].length; i < len; i++) {
                            filme[i] = (typeof(objData["results"][0]["known_for"][i].title) !== 'undefined' ? objData["results"][0]["known_for"][i].title : objData["results"][0]["known_for"][i].name);
                          } 
                          var intLimit = 10;
                          if(filme.length < intLimit){
                            intLimit = filme.length;
                          }                      
                           for (var j = 0, ln = intLimit; j < ln; j++) {
                              if(j == (ln-1)){
                                speechOutput += ' and';
                              }
                              speechOutput += ' the number ' + arrDigits[(j+1)] + ' is \"' + filme[j].replace(/!'[\W_]+/g," ") +'\"';
                              if(j < (ln-2) ){
                                speechOutput += ',';
                              }
                          }                         
                      }
                      //'Please look into the Alexa logs.';
                      //console.log(`Uita-te in loguri ca urmeaza promptul !`);
                      //console.log(speechOutput); 
                      objP.emit(':tell', speechOutput.toString());                   
                  }else{
                      speechOutput += ' Ups this is a technical issue: unfortunatelly the web service didn\'t answer properly. Please try again! ';
                      this.emit(':tell', speechOutput);
                  }
                  //console.log(JSON.stringify(this, null, 4));
                  //console.dir(this, { depth: null })
                  //const speechOutput1 = speechOutput;
                  //this.emit(':tell', speechOutput);
                });
              });
              //console.log(`Inainte de req.write`);
              req.write("{}");
              //console.log(`Dupa de req.write`);
              req.end();
              //console.log(`Dupa de req.end`);
            } else{
                const speechOutput = 'Sorry, we didn\'t understand who you asked for. Please try again with a real actor!';
                this.emit(':tell', speechOutput);          
            }
        },
        
        'AskMovieIntent': function() {
            var filme = [];
            var intNbMovies = this.event.request.intent.slots.NBMOVIES.value;
            var objP = this;
            
            if ((typeof(intNbMovies) !== 'undefined') && (intNbMovies > 0)) {
                
              if (intNbMovies > 10) {
                intNbMovies = 10;
              }
              var options = {
                "method": "GET",
                "hostname": "api.themoviedb.org",
                "port": null,
                "path": "/3/discover/movie?page=1&include_video=true&include_adult=false&sort_by=popularity.desc&language=en-US&api_key=ddd",
                "headers": {}
              };
              
              var req = https.request(options, function (res) {
                var chunks = [];
                //console.log(`A intrat in responsul lui request...`);
                
                res.on("data", function (chunk) {
                  chunks.push(chunk);
                  //console.log(`Scrie data...`);
                });
              
                res.on("end", function () {
                  var body = Buffer.concat(chunks);
                  //console.log(body.toString());
                  //console.log(`Am scris data.`);
                  var objData = JSON.parse(body);
                  
                  var speechOutput = '';
                  
                  if (typeof(objData) !== 'undefined'){ 
                      if (objData["results"].length < intNbMovies) {
                          intNbMovies = objData["results"].length;
                      }
                      for (var i = 0, len = intNbMovies; i < len; i++) {
                        filme[i] = objData["results"][i].title;
                      }
                      //console.log(filme.toString()); 
                      if(intNbMovies == 1){
                          speechOutput += 'The best movie is \"' + filme[0] +'\"';
                      }else{
                          speechOutput += 'The best ' + arrDigits[intNbMovies] + ' movies are: ';
                          
                          for (var j = 0, ln = filme.length; j < ln; j++) {
                              if(j == (ln-1)){
                                  speechOutput += ' and';
                              }
                              speechOutput += ' the number ' + arrDigits[(j+1)] + ' is \"' + filme[j] +'\"';
                              if(j < (ln-2) ){
                                  speechOutput += ',';
                              }
                          }                
                      }
                      //'Please look into the Alexa logs.';
                      //console.log(`Uita-te in loguri ca urmeaza promptul !`);
                      //console.log(speechOutput); 
                      objP.emit(':tell', speechOutput.toString());                   
                  }else{
                      speechOutput += ' Ups this is a technical issue: unfortunatelly the web service didn\'t answer properly. Please try again! ';
                      this.emit(':tell', speechOutput);
                  }
                  //console.log(JSON.stringify(this, null, 4));
                  //console.dir(this, { depth: null })
                  //const speechOutput1 = speechOutput;
                  //this.emit(':tell', speechOutput);
                });
              });
              //console.log(`Inainte de req.write`);
              req.write("{}");
              //console.log(`Dupa de req.write`);
              req.end();
              //console.log(`Dupa de req.end`);
            } else{
                const speechOutput = 'You should tell me how many movies do you want to have into the response.';
                //console.log(`Numar filme nu e specificat !`);
                this.emit(':tell', speechOutput);          
            }
        },
        
        'AnswerIntent': function () {
            //handleUserGuess.call(this, false);
        },
        'DontKnowIntent': function () {
            //handleUserGuess.call(this, true);
        },
        'AMAZON.StartOverIntent': function () {
            this.handler.state = APP_STATES.START;
            this.emitWithState('AppStart', false);
        },
        'AMAZON.RepeatIntent': function () {
            this.emit(':ask', this.attributes.speechOutput, this.attributes.repromptText);
        },
        'AMAZON.HelpIntent': function () {
            this.handler.state = APP_STATES.HELP;
            this.emitWithState('helpTheUser', false);
        },
        'AMAZON.StopIntent': function () {
            this.handler.state = APP_STATES.HELP;
            const speechOutput = 'Would you like to keep talking?';
            this.emit(':ask', speechOutput, speechOutput);
        },
        'AMAZON.CancelIntent': function () {
            this.emit(':tell', 'Ok, let\'s talk again soon.');
        },
        'Unhandled': function () {
            const speechOutput = 'Would you like to keep talking?';
            this.emit(':ask', speechOutput, speechOutput);
        },
        'SessionEndedRequest': function () {
            const speechOutput = 'OK, Goodbye!';
            this.emit(':tell', speechOutput);
        },
    });
    
    const helpStateHandlers = createStateHandler(APP_STATES.HELP, {
        'helpTheUser': function (newApp) {
            const askMessage = newApp ? 'Would you like to start Movie World?' : 'To repeat the last question, say, repeat. Would you like to keep using Movie World?';
            
            const speechOutput = ` Here are a few examples of things you can say:`
                + ` What are the most popular movies `
                + ` What are the best drama\'s  . ${askMessage}`;
            const repromptText = `To give an answer to a question, respond with the number of the answer . ${askMessage}`;
    
            this.emit(':ask', speechOutput, speechOutput);
        },
        'StartApp': function () {
            this.handler.state = APP_STATES.START;
            this.emitWithState('AppStart', false);
        },
        'AMAZON.RepeatIntent': function () {
            this.emitWithState('helpTheUser');
        },
        'AMAZON.HelpIntent': function () {
            this.emitWithState('helpTheUser', false);
        },
        'AMAZON.YesIntent': function () {
            if (this.attributes.speechOutput && this.attributes.repromptText) {
                this.handler.state = APP_STATES.TRIVIA;
                this.emitWithState('AMAZON.RepeatIntent');
            } else {
                this.handler.state = APP_STATES.START;
                this.emitWithState('StartApp', false);
            }
        },
        'AMAZON.NoIntent': function () {
            const speechOutput = 'Ok, we\'ll talk another time. Goodbye!';
            this.emit(':tell', speechOutput);
        },
        'AMAZON.StopIntent': function () {
            const speechOutput = 'Would you like to keep talking?';
            this.emit(':ask', speechOutput, speechOutput);
        },
        'AMAZON.CancelIntent': function () {
            this.handler.state = APP_STATES.TRIVIA;
            this.emitWithState('AMAZON.RepeatIntent');
        },
        'Unhandled': function () {
            const speechOutput = 'Say yes to continue, or no to end the session.';
            this.emit(':ask', speechOutput, speechOutput);
        },
        'SessionEndedRequest': function () {
            const speechOutput = 'OK, Goodbye!';
            this.emit(':tell', speechOutput);
        },
    });
    
    
    exports.handler = (event, context) => {
        const alexa = Alexa.handler(event, context);
        alexa.registerHandlers(newSessionHandlers, triviaStateHandlers, helpStateHandlers);
        alexa.appId = APP_ID;
        alexa.execute();
    };

ASK intent schema

JSON
Tells Alexa how to handle Movie World sentences
{
  "intents": [
    {
      "intent": "HelloMovieWorldIntent"
    },
    {
      "intent": "AskMovieIntent",
      "slots":[
            {
               "name":"NBMOVIES",
               "type":"AMAZON.NUMBER"
            }
			]
    },
        {
      "intent": "AskActorIntent",
      "slots":[
            {
               "name":"ACTORNAME",
               "type":"ACTOR_NAME"
            }
			]
    },
    {
      "intent": "AMAZON.HelpIntent"
    }
  ]
}

Sample utterances

snippets
HelloMovieWorldIntent say hello
AskMovieIntent which the {NBMOVIES} most popular movies are
AskMovieIntent what are the {NBMOVIES} most popular movies
AskMovieIntent which are the {NBMOVIES} most popular movies
AskActorIntent if {ACTORNAME} is an actor
AskActorIntent who {ACTORNAME} is
AskActorIntent if {ACTORNAME} is an actress
AskActorIntent if {ACTORNAME} is a comedian
AskActorIntent is {ACTORNAME} an actress
AskActorIntent is {ACTORNAME} an actor
AskActorIntent is {ACTORNAME} a comedian

Credits

Cristian Muraru

Cristian Muraru

1 project • 0 followers

Comments