Tried to follow the sample code as this
app.intent('intent1', (conv) => {
const lifespan = 5;
const contextParameters = {
color: 'red',
};
conv.contexts.set('context1', lifespan, contextParameters);
// ...
});
app.intent('intent2', (conv) => {
const context1 = conv.contexts.get('context1');
const contextParameters = context1.parameters;
// ...
});
app.intent('intent3', (conv) => {
conv.contexts.delete('context1');
// ...
});
Here is my code...
app.intent('ask_recipe_intent', (conv, {name}) => {
const term = name.toLowerCase();
const termRef = collectionRef.doc(term);
//Set the context to store the parameter information
const lifespan =5;
const contextParameters = {
name: name,
};
conv.contexts.set('name', 5, name);
return termRef.get()
.then((snapshot) => {
const {city, name, count} = snapshot.data();
return termRef.update({count: count+1})
.then(() => {
conv.ask(`Here you go, ${name}, ${city}. ` +
`do you want to check all the Ingredients needed?`);
});
}).catch((e) => {
console.log('error:', e);
conv.close('Sorry, I did not catch you, can you say again or try another word.');
});
});
app.intent('yes_list_ingredient_intent', conv => {
const termRef = conv.contexts.get(name);
const contextParameters = name.parameters;
conv.ask(`The ingredients of ${name} includes ${ingredientall}. ` +
`do you want to add to shopping list or go to steps of cooking?`);
});
app.intent('no_steps2cook_intent', conv => {
conv.contexts.delete(name);
conv.ask(`The steps to cook for ${name} as following ${stepsall}. ` +
`enjoy cooking`);
});
But got "Webhook error (206) Malformed Response"
What's wrong with my code and where can I get more samples to learn except Temperature Converter Trivia which seems to be the older version.
You have several references to a variable name in your code, such as
const termRef = conv.contexts.get(name);
but nowhere do you define what name is.
When you set the context, you're setting it to the context that is literally named "name", but you're trying to set it with parameters that are stored in the name variable, and that isn't defined:
conv.contexts.set('name', 5, name);
I am guessing that the latter is supposed to be something like
conv.contexts.set('name', 5, contextParameters);
since you define contextParameters, but never use them. And that you mean to call your context "name" since thats the name you use for the name in that call.
Related
I'm trying to pass a variable into a page.evaluate() function in Puppeteer, but when I use the following very simplified example, the variable evalVar is undefined.
I can't find any examples to build on, so I need help passing that variable into the page.evaluate() function so I can use it inside.
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const evalVar = 'WHUT??';
try {
await page.goto('https://www.google.com.au');
await page.waitForSelector('#fbar');
const links = await page.evaluate((evalVar) => {
console.log('evalVar:', evalVar); // appears undefined
const urls = [];
hrefs = document.querySelectorAll('#fbar #fsl a');
hrefs.forEach(function(el) {
urls.push(el.href);
});
return urls;
})
console.log('links:', links);
} catch (err) {
console.log('ERR:', err.message);
} finally {
// browser.close();
}
})();
You have to pass the variable as an argument to the pageFunction like this:
const links = await page.evaluate((evalVar) => {
console.log(evalVar); // 2. should be defined now
…
}, evalVar); // 1. pass variable as an argument
You can pass in multiple variables by passing more arguments to page.evaluate():
await page.evaluate((a, b c) => { console.log(a, b, c) }, a, b, c)
The arguments must either be serializable as JSON or JSHandles of in-browser objects: https://pptr.dev/#?show=api-pageevaluatepagefunction-args
I encourage you to stick on this style, because it's more convenient and readable.
let name = 'jack';
let age = 33;
let location = 'Berlin/Germany';
await page.evaluate(({name, age, location}) => {
console.log(name);
console.log(age);
console.log(location);
},{name, age, location});
Single Variable:
You can pass one variable to page.evaluate() using the following syntax:
await page.evaluate(example => { /* ... */ }, example);
Note: You do not need to enclose the variable in (), unless you are going to be passing multiple variables.
Multiple Variables:
You can pass multiple variables to page.evaluate() using the following syntax:
await page.evaluate((example_1, example_2) => { /* ... */ }, example_1, example_2);
Note: Enclosing your variables within {} is not necessary.
It took me quite a while to figure out that console.log() in evaluate() can't show in node console.
Ref: https://github.com/GoogleChrome/puppeteer/issues/1944
everything that is run inside the page.evaluate function is done in the context of the browser page. The script is running in the browser not in node.js so if you log it will show in the browsers console which if you are running headless you will not see. You also can't set a node breakpoint inside the function.
Hope this can help.
For pass a function, there are two ways you can do it.
// 1. Defined in evaluationContext
await page.evaluate(() => {
window.yourFunc = function() {...};
});
const links = await page.evaluate(() => {
const func = window.yourFunc;
func();
});
// 2. Transform function to serializable(string). (Function can not be serialized)
const yourFunc = function() {...};
const obj = {
func: yourFunc.toString()
};
const otherObj = {
foo: 'bar'
};
const links = await page.evaluate((obj, aObj) => {
const funStr = obj.func;
const func = new Function(`return ${funStr}.apply(null, arguments)`)
func();
const foo = aObj.foo; // bar, for object
window.foo = foo;
debugger;
}, obj, otherObj);
You can add devtools: true to the launch options for test
I have a typescript example that could help someone new in typescript.
const hyperlinks: string [] = await page.evaluate((url: string, regex: RegExp, querySelect: string) => {
.........
}, url, regex, querySelect);
Slightly different version from #wolf answer above. Make code much more reusable between different context.
// util functions
export const pipe = (...fns) => initialVal => fns.reduce((acc, fn) => fn(acc), initialVal)
export const pluck = key => obj => obj[key] || null
export const map = fn => item => fn(item)
// these variables will be cast to string, look below at fn.toString()
const updatedAt = await page.evaluate(
([selector, util]) => {
let { pipe, map, pluck } = util
pipe = new Function(`return ${pipe}`)()
map = new Function(`return ${map}`)()
pluck = new Function(`return ${pluck}`)()
return pipe(
s => document.querySelector(s),
pluck('textContent'),
map(text => text.trim()),
map(date => Date.parse(date)),
map(timeStamp => Promise.resolve(timeStamp))
)(selector)
},
[
'#table-announcements tbody td:nth-child(2) .d-none',
{ pipe: pipe.toString(), map: map.toString(), pluck: pluck.toString() },
]
)
Also not that functions inside pipe cant used something like this
// incorrect, which is i don't know why
pipe(document.querySelector)
// should be
pipe(s => document.querySelector(s))
I am implementing function monthlyRevenue.
Simply, it will return total monthly revenue,and it takes arguments of station array which will make revenues, month and year.
Problem
Inside of this function I have getStationPortion which will fetch the revenue portion of user's.
So I would like to make it return object like this.
stationsPortion = {station1 : 30, station2 : 20}
In the monthlyRevenue
const stationPortions = await getStationPortions(stations)
console.log("portion map", stationPortions //it will be shown very beginning with empty
getStationPortions
const getStationPortions = async (stations) => {
let stationPortions = {}
stations.map(async (value) => {
const doc = await fdb.collection('Stations').doc(value).get()
if (!doc.exists) {
console.log("NO DOC")
} else {
stationPortions[value] = doc.data().salesPortion
console.log(stationPortions) //it will be shown at the last.
}
})
return stationPortions
}
I thought that async function should wait for the result, but it does not.
I am kind of confusing if my understanding is wrong.
Thank you
(by the way, fdb is firebase admin(firestore)
Working code
const getStationPortions = async (stations) => {
let stationPortions = {}
await Promise.all(stations.map(async (value) => {
const doc = await fdb.collection('Stations').doc(value).get()
if (!doc.exists) {
console.log("NO DOC")
} else {
stationPortions[value] = doc.data().salesPortion
console.log(stationPortions)
}
}))
return stationPortions
}
module.exports = router;
I want to book an ambulance while having conversation with user via google assistant.I have to get the distance between the pickup point and destination point to calculate fare as per the kms.
I have the user's location in longitudes and latitudes. and the destination location as a address(Fortis Hospital at Bhoiwada, Kalyan). How do I calculate the distance?
'use strict';
const functions = require('firebase-functions');
const { dialogflow } = require('actions-on-google');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const {Permission,Place} = require('actions-on-google');
const app = dialogflow();
app.intent('Default Welcome Intent', conv => {
conv.close(`Welcome to my agent!`);
conv.ask('which type of ambulance would you like to book?');
});
app.intent('Default Fallback Intent', conv=> {
conv.close('sorry i did not understand');
});
app.intent('typeofambulance',conv => {
conv.ask('ac or non-ac?');
});
app.intent('ac', conv => {
conv.ask('do you want to book it from your current location?');
});
app.intent('location', (conv) => {
conv.data.requestedPermission = 'DEVICE_PRECISE_LOCATION';
return conv.ask(new Permission({
context: 'to locate you',
permissions: conv.data.requestedPermission,
}));
});
app.intent('receive', (conv, params, permissionGranted) => {
//conv.ask('rr');
if (permissionGranted) {
// conv.ask('entered');
const {
requestedPermission
} = conv.data;
const {
coordinates
} = conv.device.location;
conv.ask(`You are at latitude ${coordinates.latitude} and longitude
${coordinates.longitude}` );
conv.ask('destination please!');
} else {
return conv.close('Sorry, permission denied.');
}
});
app.intent('destination', conv => {
conv.ask(new Place({
prompt: 'Destination point?',
context: 'To find a place to pick you up',
}));
});
app.intent('actions.intent.PLACE', (conv, input, place, status) => {
if (place) {
conv.ask(` Ah, I see. You want to get dropped at
${place.formattedAddress}`);
const ll=place.formattedAddress;
}
else {
// Possibly do something with status
conv.ask(`Sorry, I couldn't find where you want to get picked up`);
}
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
Distance calculation is possible given lat/lng, but the problem is that it won't really give you the distance it will take an ambulance to drive from one to the other, it will only get you the straight-line distance.
What you really need is to calculate (I am assuming) a route distance. You can calculate this using the Google Maps "Direction" API (since you're clearly already using Google things). This will require a valid Google Maps API key! Luckily, this has already been answered on Stack Overflow.
The basic idea is to use the directions service to get the route, then look at then result object for the distance between the start and end points (note that this code is hijacked from that other answer):
const directionsService = new DirectionsService;
const origin = "start address";
const destination = "end address";
const waypoints = addresses.map(stop => ({location: stop}));
directionsService.route({
origin,
waypoints,
destination,
travelMode: TravelMode.DRIVING,
}, (response, status) => {
if(status === DirectionsStatus.OK) {
let totalDistance = 0;
const legs = directionsResult.routes[0].legs;
for(let i=0; i<legs.length; ++i) {
totalDistance += legs[i].distance.value;
}
console.log(totalDistance);
} else {
return reject(new Error(status));
}
});
Here I have code that trigger ref /tugas_course/{course_id}/{tugas_id} whenever child added will send notification to the android device. It already doing really well. But I want to add one more function inside it, I want to add child outside this ref called flag_tugas and will be populate with flag_tugas-course_id-tugas_id-user.uid: "o". I dont know how to add it, because the return value already take it all and how to get users id in cloud function.
export const onNotifTugas = functions.database.ref('/tugas_course/{course_id}/{tugas_id}')
.onCreate((snapshot, context) =>{
const course_id = context.params.course_id;
const tugas_id = context.params.tugas_id;
console.log(`New Message ${course_id} in ${tugas_id}`);
return admin.database().ref('/tugas/' + tugas_id +'/').once('value').then(snap => {
const tugasData = snap.val();
const notifDataSend = { // buat structure data json dgn nama const notifDataSend untul cloud messaging
data: {
data_type: "tugas",
title: "Anda mendapatkan notifikasi baru..", // data bebas (key, value)
body: `Tugas ${tugasData.nama_tugas} baru`, // chatId = const chatId
sound: "default"
}
};
console.log(`data yang dikirim `);
return admin.messaging().sendToTopic(course_id, notifDataSend)
.then(function(response) {
console.log("Successfully sent message:", response);
})
.catch(function(error) {
console.log("Error sending message:", error);
});
}).catch(error => {
console.log(error);
})
});
}
Actually adding the new child under eclassapp
Really thanks for your time and answer..
I am not sure to fully understand where you want to add the timestamp in your node tree (under /tugas_course/{course_id}/{tugas_id}/new_child or under /tugas_course/{course_id}/{tugas_id}) but the following code will work for adding a timestamp value right under /tugas_course/{course_id}/{tugas_id}. If you need you can change the value of ref to write the timestamp where you want.
exports.onNotifTugas = functions.database
.ref('/tugas_course/{course_id}/{tugas_id}')
.onCreate((snapshot, context) => {
const ref = snapshot.ref;
const ts = admin.database.ServerValue.TIMESTAMP;
return ref.update({
date_time: ts
});
});
Note however that you don't need a Cloud Function to add a timestamp from the server, see https://firebase.google.com/docs/reference/js/firebase.database.ServerValue
So in your case you would do something like:
var tugaRef = firebase.database().ref("/tugas_course/course_id/tugas_id");
tugaRef.push({
foo: bar, //Other data of your 'tugas' object
createdAt: firebase.database.ServerValue.TIMESTAMP
})
Ok, so I searched for a while, but I couldn't find any information on how to delete all messages in a discord channel. And by all messages I mean every single message ever written in that channel. Any clues?
Try this
async () => {
let fetched;
do {
fetched = await channel.fetchMessages({limit: 100});
message.channel.bulkDelete(fetched);
}
while(fetched.size >= 2);
}
Discord does not allow bots to delete more than 100 messages, so you can't delete every message in a channel. You can delete less then 100 messages, using BulkDelete.
Example:
const Discord = require("discord.js");
const client = new Discord.Client();
const prefix = "!";
client.on("ready" () => {
console.log("Successfully logged into client.");
});
client.on("message", msg => {
if (msg.content.toLowerCase().startsWith(prefix + "clearchat")) {
async function clear() {
msg.delete();
const fetched = await msg.channel.fetchMessages({limit: 99});
msg.channel.bulkDelete(fetched);
}
clear();
}
});
client.login("BOT_TOKEN");
Note, it has to be in a async function for the await to work.
Here's my improved version that is quicker and lets you know when its done in the console but you'll have to run it for each username that you used in a channel (if you changed your username at some point):
// Turn on Developer Mode under User Settings > Appearance > Developer Mode (at the bottom)
// Then open the channel you wish to delete all of the messages (could be a DM) and click the three dots on the far right.
// Click "Copy ID" and paste that instead of LAST_MESSAGE_ID.
// Copy / paste the below script into the JavaScript console.
var before = 'LAST_MESSAGE_ID';
var your_username = ''; //your username
var your_discriminator = ''; //that 4 digit code e.g. username#1234
var foundMessages = false;
clearMessages = function(){
const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
const channel = window.location.href.split('/').pop();
const baseURL = `https://discordapp.com/api/channels/${channel}/messages`;
const headers = {"Authorization": authToken };
let clock = 0;
let interval = 500;
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration);
});
}
fetch(baseURL + '?before=' + before + '&limit=100', {headers})
.then(resp => resp.json())
.then(messages => {
return Promise.all(messages.map((message) => {
before = message.id;
foundMessages = true;
if (
message.author.username == your_username
&& message.author.discriminator == your_discriminator
) {
return delay(clock += interval).then(() => fetch(`${baseURL}/${message.id}`, {headers, method: 'DELETE'}));
}
}));
}).then(() => {
if (foundMessages) {
foundMessages = false;
clearMessages();
} else {
console.log('DONE CHECKING CHANNEL!!!')
}
});
}
clearMessages();
The previous script I found for deleting your own messages without a bot...
// Turn on Developer Mode under User Settings > Appearance > Developer Mode (at the bottom)
// Then open the channel you wish to delete all of the messages (could be a DM) and click the three dots on the far right.
// Click "Copy ID" and paste that instead of LAST_MESSAGE_ID.
// Copy / paste the below script into the JavaScript console.
// If you're in a DM you will receive a 403 error for every message the other user sent (you don't have permission to delete their messages).
var before = 'LAST_MESSAGE_ID';
clearMessages = function(){
const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
const channel = window.location.href.split('/').pop();
const baseURL = `https://discordapp.com/api/channels/${channel}/messages`;
const headers = {"Authorization": authToken };
let clock = 0;
let interval = 500;
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration);
});
}
fetch(baseURL + '?before=' + before + '&limit=100', {headers})
.then(resp => resp.json())
.then(messages => {
return Promise.all(messages.map((message) => {
before = message.id;
return delay(clock += interval).then(() => fetch(`${baseURL}/${message.id}`, {headers, method: 'DELETE'}));
}));
}).then(() => clearMessages());
}
clearMessages();
Reference: https://gist.github.com/IMcPwn/0c838a6248772c6fea1339ddad503cce
This will work on discord.js version 12.2.0
Just put this inside your client on message event
and type the command: !nuke-this-channel
Every message on channel will get wiped
then, a kim jong un meme will be posted.
if (msg.content.toLowerCase() == '!nuke-this-channel') {
async function wipe() {
var msg_size = 100;
while (msg_size == 100) {
await msg.channel.bulkDelete(100)
.then(messages => msg_size = messages.size)
.catch(console.error);
}
msg.channel.send(`<#${msg.author.id}>\n> ${msg.content}`, { files: ['http://www.quickmeme.com/img/cf/cfe8938e72eb94d41bbbe99acad77a50cb08a95e164c2b7163d50877e0f86441.jpg'] })
}
wipe()
}
This will work so long your bot has appropriate permissions.
module.exports = {
name: "clear",
description: "Clear messages from the channel.",
args: true,
usage: "<number greater than 0, less than 100>",
execute(message, args) {
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return message.reply("that doesn't seem to be a valid number.");
} else if (amount <= 1 || amount > 100) {
return message.reply("you need to input a number between 1 and 99.");
}
message.channel.bulkDelete(amount, true).catch((err) => {
console.error(err);
message.channel.send(
"there was an error trying to prune messages in this channel!"
);
});
},
};
In case you didn't read the DiscordJS docs, you should have an index.js file that looks a little something like this:
const Discord = require("discord.js");
const { prefix, token } = require("./config.json");
const client = new Discord.Client();
client.commands = new Discord.Collection();
const commandFiles = fs
.readdirSync("./commands")
.filter((file) => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
//client portion:
client.once("ready", () => {
console.log("Ready!");
});
client.on("message", (message) => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
if (command.args && !args.length) {
let reply = `You didn't provide any arguments, ${message.author}!`;
if (command.usage) {
reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply("there was an error trying to execute that command!");
}
});
client.login(token);
Another approach could be cloning the channel and deleting the one with the messages you want deleted:
// Clears all messages from a channel by cloning channel and deleting old channel
async function clearAllMessagesByCloning(channel) {
// Clone channel
const newChannel = await channel.clone()
console.log(newChannel.id) // Do with this new channel ID what you want
// Delete old channel
channel.delete()
}
I prefer this method rather than the ones listed on this thread because it most likely takes less time to process and (I'm guessing) puts the Discord API under less stress. Also, channel.bulkDelete() is only able to delete messages that are newer than two weeks, which means you won't be able to delete every channel message in case your channel has messages that are older than two weeks.
The possible downside is the channel changing id. In case you rely on storing ids in a database or such, don't forget to update those documents with the id of the newly cloned channel!
Here's #Kiyokodyele answer but with some changes from #user8690818 answer.
(async () => {
let deleted;
do {
deleted = await channel.bulkDelete(100);
} while (deleted.size != 0);
})();