Проблемы с получением значений из базы данных Airtable (Alexa Skill) - PullRequest
0 голосов
/ 08 октября 2018

Я работаю над навыком Alexa (ASK-SDK v.2 для Node.js), который выполняет GET из базы данных Airtable.Пользователь запрашивает имя персонажа, а навык проверяет его по этой базе данных, чтобы в результате получить краткое описание.

Однако, когда я провожу некоторое тестирование в Skill Builder, даже если я говорю «Имя персонажа», которое делает ER_SUCCESS_MATCH в моем входе JSON, JSON OUTPUT возвращает разрешенное значение (фактически, любые действительные имена) как «НЕ УКАЗАНО»,Я слышу ответное сообщение: «Я не могу найти НЕ УКАЗАНО в своей базе данных», независимо от имени персонажа, о котором я спрашиваю.

Я считаю, что навыку не удается подключиться к моей базе Airtable, чтобы получить персонажа.Имя, даже если я считаю, что предоставил правильный код API и ключ AirtableGet в своем коде.Кроме того, я должен видеть запись «IN AIRTABLE GET» в моих лямбда-журналах AWS, прямо между IN CHARACTER HANDLER и обычным END RequestID, но пока я прыгаю с IN CHARACTER HANDLER прямо на END RequestID, поэтому Airtable dbкажется, не вызывается.

Вот полный код Index.js (за исключением номера навыка, ключа API и ключа столбца «Имя персонажа»).Можете ли вы заметить какие-либо ошибки?Заранее спасибо за помощь!

'use strict';
const Alexa = require('ask-sdk');
const https = require('https');

const APP_ID = "amzn1.ask.skill.xxxxxxxxxxxxxxxxxxxx";

const EmptyHandler = {
    canHandle(handlerInput) {
        return false;
    },
    handle(handlerInput, error) {
        return handlerInput.responseBuilder
                .speak()
                .reprompt()
                .getResponse();
    }
};

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === "LaunchRequest";
    },
    handle(handlerInput, error) {
        console.log("IN LAUNCH REQUEST");
        return handlerInput.responseBuilder
            .speak("Accessing the Skill. Say any name.")
            .reprompt("Go on, start.")
            .getResponse();
  },
};

const CharacterHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === "IntentRequest" &&
               handlerInput.requestEnvelope.request.intent.name === "CharacterIntent";
    },
    handle(handlerInput, error) {
        console.log("IN CHARACTER HANDLER");

        var spokenValue = getSpokenValue(handlerInput.requestEnvelope, "character");
        var resolvedValues = getResolvedValues(handlerInput.requestEnvelope, "character");

        //NO MATCHES FOUND
        if (resolvedValues === undefined)
        {
            return handlerInput.responseBuilder
                   .speak("I can't find " + spokenValue + " in my database." + getRandomQuestion())
                   .reprompt("" + spokenValue + " is not in my database. " + getRandomQuestion())
                   .getResponse();
        }
        //ONLY ONE MATCH FOUND
        else if (resolvedValues.length === 1)
        {
            var filter = "&filterByFormula=%7BName%7D%3D%22" + encodeURIComponent(resolvedValues[0].value.name) + "%22";

            return new Promise((resolve) => {
                airtableGet("appXXXXXXXXXX", "Character", filter, (record) => {
                    console.log("AIRTABLE RECORD = " + JSON.stringify(record));
                    var speechText = "Accessing to " + spokenValue + "<break time='.5s'/>" + record.records[0].fields.VoiceDescription;

                    console.log("RESPONSE BUILDER = " + JSON.stringify(handlerInput.responseBuilder));

                    resolve(handlerInput.responseBuilder
                       .speak(speechText)
                       .reprompt(getRandomQuestion())
                       .getResponse());
                });
            });
        }
        //MORE THAN ONE MATCH FOUND.  DISAMBIGUATE.
        else if (resolvedValues.length > 1)
        {
            var valuesString = getValuesString(resolvedValues);

            return handlerInput.responseBuilder
                   .speak("You asked for " + spokenValue + ", but I have different matches for that name.  Do you mean " + valuesString + "?")
                   .reprompt("Do you want to talk about" + valuesString + "?")
                   .getResponse();
        }
  }
};

const HelpHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === "IntentRequest" &&
               handlerInput.requestEnvelope.request.intent.name === "AMAZON.HelpIntent";
    },
    handle(handlerInput, error) {
        console.log("IN " +  handlerInput.requestEnvelope.request.intent.name.toUpperCase())
        return handlerInput.responseBuilder
                .speak("I know a lot of things about these characters. Tell me something about them.")
                .reprompt("Go on.")
                .getResponse();
    }
};

const StopHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === "IntentRequest" &&
               (handlerInput.requestEnvelope.request.intent.name === "AMAZON.StopIntent" ||
                handlerInput.requestEnvelope.request.intent.name === "AMAZON.CancelIntent");
    },
    handle(handlerInput, error) {
        console.log("IN " + handlerInput.requestEnvelope.request.intent.name.toUpperCase())
        return handlerInput.responseBuilder
                .speak("Okey. See you!")
                .getResponse();
    }
};

const SessionEndedHandler = { 
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
    },
    handle(handlerInput) {
      console.log("IN SESSIONENDEDHANDLER");
              return handlerInput.responseBuilder
                  .speak(getRandomGoodbye())
                  .getResponse();
     }
  };

function getRandomQuestion()
{
    var questions = ["Say another name when you're ready.", "Tell me another    name.", "Say another one.", "Any other names?"];
    var random = getRandom(0, questions.length-1);
    return "<break time='.5s'/>" + questions[random]; 
}

function getRandom(min, max)
{
    return Math.floor(Math.random() * (max-min+1)+min);
}

function getSpokenValue(envelope, slotName)
{
    if (envelope &&
        envelope.request &&
        envelope.request.intent &&
        envelope.request.intent.slots &&
        envelope.request.intent.slots[slotName] &&
        envelope.request.intent.slots[slotName].value)
    {
        return envelope.request.intent.slots[slotName].value;    
    }
    else return undefined;
}

function getResolvedValues(envelope, slotName)
{
    if (envelope &&
        envelope.request &&
        envelope.request.intent &&
        envelope.request.intent.slots &&
        envelope.request.intent.slots[slotName] &&
        envelope.request.intent.slots[slotName].resolutions &&
        envelope.request.intent.slots[slotName].resolutions.resolutionsPerAuthority &&
        envelope.request.intent.slots[slotName].resolutions.resolutionsPerAuthority[0] &&
        envelope.request.intent.slots[slotName].resolutions.resolutionsPerAuthority[0].values)
    {
        return envelope.request.intent.slots[slotName].resolutions.resolutionsPerAuthority[0].values;
    }
    else return undefined;
}

function getSlotName(envelope)
{
    if (envelope &&
        envelope.request &&
        envelope.request.intent &&
        envelope.request.intent.slots &&
        envelope.request.intent.slots[0] &&
        envelope.request.intent.slots[0].name)
    {
        return envelope.request.intent.slots[0].name;
    }
    else return undefined;
}

function getValuesString(values)
{
    var string = "";
    for (var i = 0;i<values.length; i++)
    {
        if (i != 0) string += ", ";
        if (i === (values.length-1)) string += " or ";
        string += values[i].value.name;
    }
    return string;
}

function airtableGet(base, table, filter, callback) {
    console.log("IN AIRTABLE GET");
    console.log("BASE = " + base);
    console.log("TABLE = " + table);
    console.log("FILTER = " + filter);

    var options = {
        host: "api.airtable.com",
        port: 443,
        path: "/v0/" + base + "/" + table + "?api_key=keyXXXXXXXXXX" + filter,
        method: 'GET',
    };

    console.log("PATH = https://" + options.host + options.path);

    var req = https.request(options, res => {
        res.setEncoding('utf8');
        var returnData = "";

        res.on('data', chunk => {
            returnData = returnData + chunk;
        });

        res.on('end', () => {
            var data = JSON.parse(returnData);
            console.log("DATA = " + JSON.stringify(data));
            callback(data);
        });
    });
    req.end();
}

const RequestLog = {
    process(handlerInput) {
        console.log("REQUEST ENVELOPE = " + JSON.stringify(handlerInput.requestEnvelope));    
        return;
    }
};

const ErrorHandler = {
    canHandle() {
        return true;
    },
    handle(handlerInput, error) {
        console.log("Error handled: " + JSON.stringify(error.message));
        console.log('handlerInput:' + JSON.stringify(handlerInput));
        return handlerInput.responseBuilder
            .speak('I am sorry, something went wrong on my side.')
            .getResponse();
  },
};

exports.handler = Alexa.SkillBuilders.standard() 
.addRequestHandlers(
    LaunchRequestHandler,
    CharacterHandler,
    HelpHandler,
    StopHandler,
    SessionEndedHandler    
  )
.addRequestInterceptors(RequestLog)
.addErrorHandlers(ErrorHandler)
.lambda();
...