I'm trying to make a skill where after the LaunchRequest, an initial welcome message is played in the function StartGame asking the user for their school, and then the user says their school in the SetSchool intent, and then the skill says a message. Right now there's a bug in the last part, and I don't know how to debug it.
The error:
My code:
/* eslint-disable func-names */
/* eslint-disable dot-notation */
/* eslint-disable new-cap */
/* 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 questions = require('./question');
const ANSWER_COUNT = 4; // The number of possible answers per trivia question.
const GAME_LENGTH = 10; // The number of questions per trivia game.
const GAME_STATES = {
TRIVIA: '_TRIVIAMODE', // Asking trivia questions.
START: '_STARTMODE', // Entry point, start the game.
HELP: '_HELPMODE', // The user is asking for help.
};
const APP_ID = undefined; // TODO replace with your app ID (OPTIONAL)
const languageString = {
'en': {
'translation': {
'QUESTIONS': questions['HS_QUESTIONS_EN_US'],
'GAME_NAME': 'Science Bowl',
'HELP_MESSAGE': 'I will ask you %s multiple choice questions. Respond with the number of the answer. ' +
'For example, say one, two, three, or four. To start a new game at any time, say, start game. ',
'REPEAT_QUESTION_MESSAGE': 'To repeat the last question, say, repeat. ',
'ASK_MESSAGE_START': 'Would you like to start playing?',
...
},
},
};
const newSessionHandlers = {
'LaunchRequest': function () {
this.handler.state = GAME_STATES.START;
this.emitWithState('StartGame', true);
},
'SetSchool': function() {
this.handler.state = GAME_STATES.START;
this.emitWithState('School', true);
},
'AMAZON.StartOverIntent': function () {
this.handler.state = GAME_STATES.START;
this.emitWithState('StartGame', true);
},
'AMAZON.HelpIntent': function () {
this.handler.state = GAME_STATES.HELP;
this.emitWithState('helpTheUser', true);
},
'Unhandled': function () {
const speechOutput = this.t('START_UNHANDLED');
this.emit(':ask', speechOutput, speechOutput);
},
};
...
const startStateHandlers = Alexa.CreateStateHandler(GAME_STATES.START, {
'StartGame': function (newGame) {
let speechOutput = newGame ? this.t('NEW_GAME_MESSAGE', this.t('GAME_NAME')) + this.t('WELCOME_MESSAGE', GAME_LENGTH.toString()) : '';
this.handler.state = GAME_STATES.START;
this.emit(':ask', speechOutput, speechOutput);
},
'School': function(newGame) {
this.handler.state = GAME_STATES.START;
this.response.speak('test');
this.emit(':responseReady');
}
});
exports.handler = function (event, context) {
const alexa = Alexa.handler(event, context);
alexa.appId = APP_ID;
// To enable string internationalization (i18n) features, set a resources object.
alexa.resources = languageString;
alexa.registerHandlers(newSessionHandlers, startStateHandlers, triviaStateHandlers, helpStateHandlers); // these were defined earlier
alexa.execute();
};
I excluded most of the code so it would fit here. I would like to try and debug it but I don't even know how to view the error messages. What do I do?
If you're hosting on AWS Lambda logs can be found in CloudWatch.
From the AWS console open cloudwatch, then click on the Logs link in the left hand menu. you should be able to find your Lambda service from there.
That said your problem seems to be an issue of Intent definition by state.
You've already set the state to START but the startStateHandlers doesn't have the SetSchool Intent defined.
To fix you'd either have to add a SetSchool intent definition to the startStateHandlers OR reset the state to one that does contain the SetSchool intent before emitting your response in the StartGame handler.
Related
I want to know if it's possible to train Dialogflow CX through API. By placing the new training phrases in my code (I am using NodeJS) and automatically update the list of phrases in that intent. One thing to add, I want to add a new phrase to the intent list no update an existing phrase.
Thank you in advance!
I was reading the documentation of Dialogflow CX and found this, https://github.com/googleapis/nodejs-dialogflow-cx/blob/main/samples/update-intent.js. But, this implementation will update a specific phrase instead of add it to the list.
Using the sample code that you have provided in your question, I updated it to show how to add a new phrase to the list. newTrainingPhrase will contain the training phrase, append newTrainingPhrase to intent[0].trainingPhrases and set updateMask to "training_phrases" to point to the part of the intent you would like to update.
See code below:
'use strict';
async function main(projectId, agentId, intentId, location, displayName) {
const {IntentsClient} = require('#google-cloud/dialogflow-cx');
const intentClient = new IntentsClient({apiEndpoint: 'us-central1-dialogflow.googleapis.com'});
async function updateIntent() {
const projectId = 'your-project-id';
const agentId = 'your-agent-id';
const intentId = 'your-intent-id';
const location = 'us-central1'; // define your location
const displayName = 'store.hours'; // define display name
const agentPath = intentClient.projectPath(projectId);
const intentPath = `${agentPath}/locations/${location}/agents/${agentId}/intents/${intentId}`;
//define your training phrase
var newTrainingPhrase = {
"parts": [
{
"text": "What time do you open?",
"parameterId": ""
}
],
"id": "",
"repeatCount": 1
};
const intent = await intentClient.getIntent({name: intentPath});
intent[0].trainingPhrases.push(newTrainingPhrase);
const updateMask = {
paths: ['training_phrases'],
};
const updateIntentRequest = {
intent: intent[0],
updateMask,
languageCode: 'en',
};
//Send the request for update the intent.
const result = await intentClient.updateIntent(updateIntentRequest);
console.log(result);
}
updateIntent();
}
process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});
main(...process.argv.slice(2));
Hi i am making a finance application that depends on Events from blockchain,
Basically i update my database based on Events i receive using web3js, and when user asks i sign with private key for the contract to be able to give user Money.
My only concern is can i depend on events? like can there be a case where i miss events?
here is my code for doing so :
const contract = new web3.eth.Contract(abi, contract_address)
const stale_keccak256 = "0x507ac39eb33610191cd8fd54286e91c5cc464c262861643be3978f5a9f18ab02";
const unStake_keccak256 = "0x4ac743692c9ced0a3f0052fb9917c0856b6b12671016afe41b649643a89b1ad5";
const getReward_keccak256 = "0x25c30c62c42b51e4f667b70ef60f1f683c376f6ace28312ed45a40665e01af37";
let userRepository: Repository<UserData> = connection.getRepository(UserData);
let globalRepository: Repository<GlobalStakingInfo> = connection.getRepository(GlobalStakingInfo);
let userStakingRepository: Repository<UserStakingInfo> = connection.getRepository(UserStakingInfo);
let transactionRepository: Repository<Transaction> = connection.getRepository(Transaction);
const topics = []
web3.eth.subscribe('logs', {
address: contract_address, topics: topics
},
function (error: Error, result: Log) {
if (error) console.log(error)
}).on("data", async function (log: Log) {
let response: Boolean = false;
try {
response = await SaveTransaction(rpc_url, log.address, log.transactionHash, transactionRepository)
} catch (e) {
}
if (response) {
try {
let global_instance: GlobalStakingInfo | null = await globalRepository.findOne({where: {id: 1}})
if (!global_instance) {
global_instance = new GlobalStakingInfo()
global_instance.id = 1;
global_instance = await globalRepository.save(global_instance);
}
if (log.topics[0] === stale_keccak256) {
await onStake(web3, log, contract, userRepository, globalRepository, userStakingRepository, global_instance);
} else if (log.topics[0] === unStake_keccak256) {
await onUnStake(web3, log, contract, userStakingRepository, userRepository, globalRepository, global_instance)
} else if (log.topics[0] === getReward_keccak256) {
await onGetReward(web3, log, userRepository)
}
} catch (e) {
console.log("I MADE A BOBO", e)
}
}
}
)
The Code works and everything, i am just concerned if i could maybe miss a event? cause finance is related and people will lose money if missing event is a thing.
Please advise
You can increase redundancy by adding more instances of the listener connected to other nodes.
And also by polling past logs - again recommended to use a separate node.
Having multiple instances doing practically the same thing will result in multiplication of incoming data, so don't forget to store only unique logs. This might be a bit tricky, because theoretically one transaction ID can produce the same log twice (e.g. through a multicall), so the unique key could be a combination of a transaction ID as well as the log index (unique per block).
I need to open a new google meet room, and send it. I can't use standard "share" button in app. I need to catch the final url.
I can't catch that with curl (it's not a normal redirect).
My idea is that i need to open a request/link in background or in the same page, wait some second and catch the link, after i can release the page and user can enter.
Do you know something that can help me?
Edit:
Yes, i had miss to tell that i need to generate a room from a click and catch the url from code. Generally, i should to make this with Google Calendar API, but in this case i can't.
I use google Calendar API. I make a webApp for my organization, that from a form (with user information to send togheter meet link) make a google calendar event with google meet room (from google loggedin user account), catch the link and send it by a smsGateway.
function FormForMeet (Args) {
// get calendar name, if it already exists
var meetsCalendar = CalendarApp.getCalendarsByName ('CalendarName');
Logger.log (meetsCalendar.length)
if (meetsCalendar.length> = 1) {
// if some calendar be found, it catch the first, obviously here you can use some differet method. I had choose this because I don't expect to find more than 1
var calendar = meetsCalendar [0] .getId ();
}
else
{
// If miss, create new one.
var calendar = CalendarApp.createCalendar ('CalendarName', {summary: 'descrip Calendar',
// set a color of calendar label :D
color: CalendarApp.Color.PURPLE});
calendar = calendar.getId ();
}
// Call function to create meet
var LinkMeet = CreateConference_ (calendar);
// here you can use what you want for send Args + LinkMeet);
// if you want return link
return LinkMeet;
}
// Function to create Conference. You can obviously use the code up without make a new function.
function CreateConference_ (calendarId) {
// Custom of event, here I created the conferences according to my needs (now, with 1 h / conference)
var now = new Date ();
var start = new Date (now.getTime ()). toISOString ();
var end = new Date (now.getTime () + (1 * 60 * 60 * 1000)). toISOString ();
// generate random string to request
var rdmreqId = genStrg ();
var event = {
"end": {
"dateTime": end
},
"start": {
"dateTime": start
},
"summary": "conferenceName",
"conferenceData": {
"createRequest": {
"conferenceSolutionKey": {
"type": "hangoutsMeet"
},
"requestId": rdmreqId
}
}
};
// insert event in calendar
event = Calendar.Events.insert (event, calendarId, {
"conferenceDataVersion": 1});
// if use the function you can return the link to send
return event.hangoutLink
}
// random strind
function genStrg () {
var data = "something";
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789! # # $% & <> * -";
for (var j = 2; j <= data.length; j ++) {
text = ""; // Reset text to empty string
for (var i = 0; i <possible.length; i ++) {
text + = possible.charAt (Math.floor (Math.random () * possible.length));
}
return text;
}
}
all google meet links look something like this:
https://meet.google.com/abc-defg-hij
You should be able to just copy and paste this link from your browser page. If someone enters this link, they will be taken to the meet lobby and they can enter at any time.
If you can't access this link for some reason, like if you're on mobile, you have to put your meet code (the abc-defg-hij) at the end of the aforementioned url.
edit: You actually can find the link if you're on mobile by going into your meeting lobby and scrolling down until you get to "joining information". Under that there should be the meeting link and the numbers to join by phone.
I'm trying to make dose schedule app that when the user set the alarm the app shows a page to check if the user takes a medicine or not. and the user should choose snooze or done with swiping ("done" to the left, "snooze" to the right).
I want the app gets opened automatically from the background on time.
I've already tried "nativescript-local-notification", but this one, the user must press the notification to open or enter the app and read "nativescript background service" but it seems to be the same as I've tried.
Could you tell me the way or give me some example to do?
I've solved it by myself. I put the solution that might be helped someone like me.
First you have set an alarm.
alarm.helper.js
import * as AlarmReceiver from '#/services/AlarmReceiver' // Do not remove
export const setAlarm = data => {
const ad = utils.ad
const context = ad.getApplicationContext()
const alarmManager = application.android.context.getSystemService(android.content.Context.ALARM_SERVICE)
const intent = new android.content.Intent(context, io.nerdrun.AlarmReceiver.class)
const { id, time, title, name } = data
// set up alarm
intent.putExtra('id', id)
intent.putExtra('title', title)
intent.putExtra('name', name)
intent.putExtra('time', time.toString())
const pendingIntent = android.app.PendingIntent.getBroadcast(context, id, intent, android.app.PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.setExact(alarmManager.RTC_WAKEUP, time.getTime(), pendingIntent)
console.log('registered alarm')
}
Extends AlarmReceiver on Android.
AlarmReceiver.js
export const AlarmReceiver = android.content.BroadcastReceiver.extend('io.nerdrun.AlarmReceiver', {
init: function() {
console.log('init receiver')
},
onReceive: function(context, intent) {
console.log('You got the receiver man!!')
const activityIntent = new android.content.Intent(context, com.tns.NativeScriptActivity.class)
const id = intent.getExtras().getInt('id')
const title = intent.getExtras().getString('title')
const name = intent.getExtras().getString('name')
const time = intent.getExtras().getString('time')
activityIntent.putExtra('id', id)
activityIntent.putExtra('title', title)
activityIntent.putExtra('name', name)
activityIntent.putExtra('time', time)
activityIntent.setFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(activityIntent)
}
})
register receiver to your manifest.
AndroidManifest.xml
<receiver android:name="io.nerdrun.AlarmReceiver" />
Of course, you can extend Activity on android into your project, but I haven't implemented it.
After the receiver worked it would navigate to Main Activity, you might control whatever you want in app.js below:
app.js
application.on(application.resumeEvent, args => {
if(args.android) {
console.log('resume succeed!!!')
const android = args.android
const intent = android.getIntent()
const extras = intent.getExtras()
if(extras) {
const id = extras.getInt('id')
const title = extras.getString('title')
const name = extras.getString('name')
const time = extras.getString('time')
Vue.prototype.$store = store
Vue.prototype.$navigateTo(routes.home, { clearHistory: true, props: props })
}
}
}
})
Is it possible to run alexa skill locally with ngrok instead AWS? I built a skill in AWS Lambda but I would rather use my own server. What can I do to run Alexa locally?
I tried https://github.com/alexa-js/alexa-app-server but it makes any sense because I would need to rewrite my whole code :( The better solution is http://docs.bespoken.tools/en/latest/tutorials/tutorial_lambda_nodejs/ but it isn't the best. It just works only for a wellcome intent and freezes after that :(
Terminal Logs from bespken command:
BST: v0.9.35 Node: v7.8.0
Your URL for Alexa Skill configuration:
https://proxy.bespoken.tools?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d
INFO 2017-04-25T20:27:20.628Z Connected - proxy.bespoken.tools:5000
INFO 2017-04-25T20:27:26.812Z RequestReceived: POST /?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d ID: 1493152039146
INFO 2017-04-25T20:27:26.815Z Forwarding localhost:10000
Current hour: 24
Warning: Application ID is not set
INFO 2017-04-25T20:27:27.939Z ResponseReceived ID: 1493152039146
INFO 2017-04-25T20:28:10.755Z RequestReceived: POST /?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d ID: 1493152078963
INFO 2017-04-25T20:28:10.756Z Forwarding localhost:10000
Warning: Application ID is not set
INFO 2017-04-25T20:28:11.157Z ResponseReceived ID: 1493152078963
INFO 2017-04-25T20:28:51.073Z RequestReceived: POST /?node-id=33efccba-2246-477f-bbb8-2e1e510cce9d ID: 1493152113739
INFO 2017-04-25T20:28:51.073Z Forwarding localhost:10000
Warning: Application ID is not set
INFO 2017-04-25T20:28:51.995Z ResponseReceived ID: 1493152113739
Yes, there are several solutions for running your node lambda locally. I've been using node-lambda, for example. Like most solutions it is oriented to users who want to test locally and then easily deploy to AWS Lambda.
If you want to run them yourself, I would note that MS and IBM have made their implementations of lambda open-source (here's MS's and IBM's). I haven't actually tried it myself, and I would note that with AWS, GCP, and Azure all providing Lambda services for node the market for these is healthy and the lock-in is minimal so I feel less need to be able to run it myself than for something like Dynamo.
But I also recommend that you continue to pursue BST. I'm using some of my own pieces for testing my skills because I got started before I heard of their stuff, but what I have tried of their's (BSTAlexa) is very useful and I see that they provide some of the other pieces you need for easy and effective testing of your skill.
Here's some sample code that you can use to easily run a Lambda locally, call this file AlexaLambda.js:
const log = require('console');
var AWS = require('aws-sdk');
AWS.config.region = "us-east-1";
AWS.config.update({
accessKeyId: "----",
secretAccessKey: "----",
});
/**
* Wraps the actual underlying Alexa lambda initialization in a
* Promise. Injects test mocks where appropriate.
*/
var initializerPromise = new Promise(function(fulfill, reject) {
// Mock out certain imports here if you want but not necessary
/*
var Module = require('module');
var originalRequire = Module.prototype.require;
Module.prototype.require = function() {
if ((arguments[0] == 'S3FeedService') ||
(arguments[0] == './lib/S3FeedService')) {
return MockS3Service;
} else if ((arguments[0] == 'WebsocketService') ||
(arguments[0] == './lib/WebsocketService')) {
return WSMockService;
} else if ((arguments[0] == 'SQSService') ||
(arguments[0] == './lib/SQSService')) {
return SQSMockService;
} else {
return originalRequire.apply(this, arguments);
}
};*/
// Import your actual lambda here.
var lambda = require('../src/index.js');
fulfill(lambda);
});
/**
* The Alexa Lambda context object which is called upon completion
* of lambda execution. Also wraps the callback which contains the
* test assertion code of the caller.
* #param callback - must be of the form function(error, result) {};
* #returns
*/
function Context(callback) {
this.clientContext = {"env": {}};
this.callback = callback;
}
Context.prototype.done = function(error, result) {
if (typeof error != "undefined" && error) {
this.callback(error, null);
} else {
this.callback(null, result);
}
}
Context.prototype.succeed = function(result) {
this.callback(null, result);
}
Context.prototype.fail = function(error) {
this.callback(error, null);
}
/**
* The AlexaLambda object that's exposed for test cases.
* #returns
*/
function AlexaLambda() {
}
/**
* Executes the lambda function, provided an inputEvent and a
* callback.
* #param inputEvent - the input event that includes the intent.
* #param callback - called upon completion of lambda execution.
*/
AlexaLambda.prototype.execute = function(inputEvent, callback) {
initializerPromise.then(function(lambda) {
var context = new Context(callback);
lambda.handler(inputEvent, context);
});
}
/**
* Export the lambda class, importers instantiate via new AlexaLambda();
*/
module.exports = AlexaLambda;
Then you can use this 'AlexaLambda' in your tests like so (in my case, I'm using Mocha):
var AlexaLambda = require('./AlexaLambda');
var Event = require('./Event'); // My 'fake' Event class
describe("Guest User Test", function() {
var alexaLambda = new AlexaLambda();
it("Alexa, open/launch 60db", function(done) {
var event = Event.createLaunchEvent();
alexaLambda.execute(event, function(error, result) {
validateYourResultHere();
done();
})
});
Then it's just a matter of running your test via whatever framework you're using.
You can test your alexa skill locally by following the following tutorial:
How to test Alexa locally