Javascript Alexa Skill:可以让Alexa从Alexa开发者控制台播放.mp3吗?

Javascript Alexa Skill:可以让Alexa从Alexa开发者控制台播放.mp3吗?,javascript,node.js,alexa,alexa-skills-kit,alexa-slot,Javascript,Node.js,Alexa,Alexa Skills Kit,Alexa Slot,我正在尝试为Alexa创建一个基于我选择的tg类别复制.mp3文件的技能。 我声明我从未使用过node.js,并且我看了一门关于如何创建alexa技能的课程。 到目前为止,我已经创建了该技能的框架,并创建了一个database.json文件,其中包含各种类别的新闻以及附加的链接 INDEX.JS const Alexa = require('ask-sdk-core'); const database = require('./database'); function getCategory

我正在尝试为Alexa创建一个基于我选择的tg类别复制.mp3文件的技能。 我声明我从未使用过
node.js
,并且我看了一门关于如何创建alexa技能的课程。 到目前为止,我已经创建了该技能的框架,并创建了一个
database.json
文件,其中包含各种类别的新闻以及附加的链接

INDEX.JS

const Alexa = require('ask-sdk-core');
const database = require('./database'); 

function getCategoryStreamUrl(name) { 
    let category = database.find(e => e.name === name);
    if (category !== null && category !== undefined) {
        return category.StreamUrl;
    } else {
        return "";
    }
}

function getCategoryUpdateDate(name) { 
    let category = database.find(e => e.name === name);
    if (category !== null && category !== undefined) {
        return category.UpdateDate;
    } else {
        return "";
    }
}

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle(handlerInput) {
        const speakOutput = 'Welcome, with this skill you can listen to our TG. You can choose a category or say Help.';
        const repromptOutput = 'You can choose a category or say Help. What do you want to do?'
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(repromptOutput)
            .getResponse();
    }
};
const ScegliCategoriaIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'ScegliCategoriaIntent';
    },
    handle(handlerInput) {
        const speakOutput = 'The TGs available are: Political, Lazio, Environment, Health, School, Pediatrics, Rehabilitation, Agriculture, Psychology and Youth. Which do you want to hear?'
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(repromptOutput)
            .getResponse();
    }
};
 const CategoriaIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'CategoriaIntent';
    },
    handle(handlerInput) {
        const filledSlots = handlerInput.requestEnvelope.request.intent.slots;
        const slotValues = getSlotValues(filledSlots);

        console.log("CategoriaIntentHandler >>>>>>>>>>>>>>>>");
        console.log(slotValues);

        const categoryName = slotValues["category"].synonym
        const categoryStreamUrl = getCategoryStreamUrl(categoryName);
        const categoryUpdateDate = getCategoryUpdateDate(categoryName);

        var speakOutput = "";
        if (categoryStreamUrl !== "") {
            speakOutput = "You have chosen the TG " + categoryName + ". The TG was updated on " + categoryUpdateDate + ". " + categoryStreamUrl + ". If you want to hear other news, name another TG or you can say STOP to close this skill.";
        } else {
            speakOutput = "I'm sorry, the selected TG is not available. You can say the name of another TG or 'categories' to hear the list of available categories. What do you want to do?";
        }

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt("If you want to hear more news, say the name of another TG. You can say 'categories' to listen to the list of available categories or you can say STOP to close this skill. What do you want to do?")
            .getResponse();
    }
};
const HelpIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
    },
    handle(handlerInput) {
        const speakOutput = "You can say 'categories' to listen to the list of available categories or you can say STOP to close this skill. What do you want to do?";
        const repromptOutput = "If you want to stop listening, say STOP."

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(repromptOutput)
            .getResponse();
    }
};
const CancelAndStopIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
                || Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
    },
    handle(handlerInput) {
        const speakOutput = "Goodbye!";
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .getResponse();
    }
};
const SessionEndedRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
    },
    handle(handlerInput) {
        // Any cleanup logic goes here.
        return handlerInput.responseBuilder.getResponse();
    }
};

// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
    },
    handle(handlerInput) {
        const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
        const speakOutput = `You just triggered ${intentName}`;

        return handlerInput.responseBuilder
            .speak(speakOutput)
            //.reprompt('add a reprompt if you want to keep the session open for the user to respond')
            .getResponse();
    }
};

// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
    canHandle() {
        return true;
    },
    handle(handlerInput, error) {
        console.log(`~~~~ Error handled: ${error.stack}`);
        const speakOutput = `I'm sorry I did not understand. Say 'Help' to know the available commands.`;

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();
    }
};

function getSlotValues (filledSlots) {

    let slotValues = {}; //

    console.log('The filled slots: ' + JSON.stringify(filledSlots));
    Object.keys(filledSlots).forEach(function(item) {

    var name = filledSlots[item].name;

    if(filledSlots[item]&&
        filledSlots[item].resolutions &&
        filledSlots[item].resolutions.resolutionsPerAuthority[0] &&
        filledSlots[item].resolutions.resolutionsPerAuthority[0].status &&
        filledSlots[item].resolutions.resolutionsPerAuthority[0].status.code ) {

        switch (filledSlots[item].resolutions.resolutionsPerAuthority[0].status.code) {
            case "ER_SUCCESS_MATCH": 
                slotValues[name] = {
                    "synonym": filledSlots[item].value,
                    "resolved": filledSlots[item].resolutions.resolutionsPerAuthority[0].values[0].value.name,
                    "isValidated": true
                };
                break;
            case "ER_SUCCESS_NO_MATCH": 
                slotValues[name] = {
                    "synonym": filledSlots[item].value,
                    "resolved": filledSlots[item].value,
                    "isValidated":false
                };
                break;
            }
        } else { 
            slotValues[name] = {
                "synonym": filledSlots[item].value,
                "resolved": filledSlots[item].value,
                "isValidated": false
            };
        }
    },this);
    return slotValues;
}

// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
    .addRequestHandlers(
        LaunchRequestHandler,
        ScegliCategoriaIntentHandler,
        CategoriaIntentHandler,
        HelpIntentHandler,
        CancelAndStopIntentHandler,
        SessionEndedRequestHandler,
        IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
    )
    .addErrorHandlers(
        ErrorHandler,
    )
    .lambda();

DATABASE.JSON

[
    {
        "uid":"ID",
        "updateDate": "DATA",
        "name": "NAME SLOT",
        "titleText": "TG 01",
        "mainText":"",
        "streamUrl":"https://www.mysite.it/tg.mp3",
        "redirectionUrl":"https://www.mysite.it/category/tg"
          },
    {
        etc_01
        },
{
        etc_02
        },
{
        etc_03
        },
]
问题是现在它不起作用了,事实上,当我让alexa告诉我TG 01时,她告诉我:

“您已选择TG 01。TG已更新为未定义。未定义。另一个TG或您可以说“停止”关闭此技能。”

简而言之,它无法识别
类别更新日期
类别流URL


我要怎么做才能修复它?

您在两个函数中都返回了错误的数据:

它们应该是:
category.updateDate
category.streamUrl
,因为您正在读取JSON文件。(可能通过阅读来更好地理解如何读取和访问JSON属性等等)

function getCategoryStreamUrl(name) { 
    let category = database.find(e => e.name === name);
    if (category !== null && category !== undefined) {
        return category.streamUrl;
    } else {
        return "";
    }
}

function getCategoryUpdateDate(name) { 
    let category = database.find(e => e.name === name);
    if (category !== null && category !== undefined) {
        return category.updateDate;
    } else {
        return "";
    }
}