how are you? English are my native language, so I apologize right away.
what I have is a bot in the dialogflow, which with some interactions marks events on the agenda.
an example:
Bot: hello welcome to the hairdresser, would you like to make an appointment?
User: Yes
Bot: What's your name?
User: Welyson
Bot: What day would you like?
User: tomorrow
Bot: What time?
User: 3pm
If you have space on the google calendar
Bot: Okay, you were scheduled for February 21st at 3pm
-If you don't have space on the google calendar
Bot: Oops, it appears that we have no vacancies for that day or time, type check to try another time.
Where I got the code as an example
The code below does this:
'use strict';
const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');
// Enter your calendar ID below and service account JSON below
const calendarId = "id google agenda ";
const serviceAccount = {json file}; // Starts with {"type": "service_account",...
// Set up Google Calendar Service account credentials
const serviceAccountAuth = new google.auth.JWT({
email: serviceAccount.client_email,
key: serviceAccount.private_key,
scopes: 'https://www.googleapis.com/auth/calendar'
});
const calendar = google.calendar('v3');
process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements
const timeZoneOffset = '-03:00';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
const appointment_nome = agent.parameters.nome;
function makeAppointment (agent) {
const dateTimeStart = new Date(Date.parse(agent.parameters.date.split('T')[0] + 'T' + agent.parameters.time.split('T')[1].split('-')[0] + timeZoneOffset));
const dateTimeEnd = new Date(new Date(dateTimeStart).setHours(dateTimeStart.getHours() + 1));
const agendamentoString = FormtData(new Date(agent.parameters.date.split('T')[0])) + " às " + agent.parameters.time.split('T')[1].split('-')[0];
// Check the availibility of the time, and make an appointment if there is time on the calendar
return createCalendarEvent(dateTimeStart, dateTimeEnd, appointment_nome).then(() => {
let mensagem = `Okay, you were scheduled for *${agendamentoString}* ✅.`;
response.json({"fulfillmentText": mensagem});
}).catch(() => {
let mensagem = `Oops, it appears that we have no vacancies for that day or time, type **check** to try another time.`;
response.json({"fulfillmentText": mensagem});
});
}
let intentMap = new Map();
//intentMap.set('Schedule Appointment', makeAppointment);
intentMap.set('Default Welcome Intent - yes', makeAppointment);
agent.handleRequest(intentMap);
});
function createCalendarEvent (dateTimeStart, dateTimeEnd, appointment_nome) {
return new Promise((resolve, reject) => {
calendar.events.list({
auth: serviceAccountAuth, // List events for time period
calendarId: calendarId,
timeMin: dateTimeStart.toISOString(),
timeMax: dateTimeEnd.toISOString()
}, (err, calendarResponse) => {
// Check if there is a event already on the Calendar
if (err || calendarResponse.data.items.length > 0) {
reject(err || new Error('Requested time conflicts with another appointment'));
} else {
// Create event for the requested time period
calendar.events.insert({ auth: serviceAccountAuth,
calendarId: calendarId,
resource: {summary:"Cliente: " + appointment_nome, description: "Cliente: " + appointment_nome,
start: {dateTime: dateTimeStart},
end: {dateTime: dateTimeEnd}}
}, (err, event) => {
err ? reject(err) : resolve(event);
}
);
}
});
});
}
function FormtData(date){
var nomesMes = [
"Janeiro", "Fevereiro", "Março",
"Abril", "Maio", "Junho","Julho",
"Agosto", "Setembro", "Outubro",
"Novembro", "Dezembro"
];
var dia = date.getDate();
var mesIndex = date.getMonth();
var ano = date.getFullYear();
return dia + ' ' + nomesMes[mesIndex];
}
But the problem is that if my schedule has too many times scheduled, the schedule will become tiring for the user!
I thought of something, like
Bot: Would you like to schedule a haircut?
User: yes
Bot: How about February 21st at 1 pm?
-If the user agrees the time is marked in the agenda:
User: Yes
Bot: Okay, you were scheduled for February 21st at 1pm
-If the user disagrees he goes to the next available time:
User: No
Bot: How about February 21st at 2 pm?
I tried something with the CalDAV API to read the google calendar, I didn't get any progress
Does anyone have any idea how I would do this? Thank you very much in advance
Related
I've been trying to add a cooldown to this part of my code for its too spammable to the point where I had to ban certain ppl from using it. So I've researched into cooldowns, trying different methods with no avail so I want to ask here if anyone has some hints or possible solutions to this. Thanks in advance.
const Telegraf = require('telegraf');
const Telegram = require('telegraf/telegram')
const bot = new Telegraf('******')
bot.hears(['oe', 'Oe', 'OE'], (ctx) => {
if (ctx.message.reply_to_message && ctx.message.reply_to_message.from.username != 'a username' && ctx.from.id != '****') { // Check if you're replying and if you're someone banned to use this command
var a = ctx.message.reply_to_message.from.username
ctx.reply('¿# este usuario?', {
reply_markup: {
inline_keyboard: [
[{ text: "Si", callback_data: "AD" }, { text: "Sin't", callback_data: "ADNT" }]
]
}
})
bot.action('AD', (ctx) => {
ctx.deleteMessage()
ctx.reply('#' + a + ' oe')
ctx.replyWithSticker('CAACAgEAAxkBAAOsX9WKywuspdVls5VSf9xV6ZLHrqAAAg8AA5390hUNDOUjryN26R4E')
})
bot.action('ADNT', (ctx) => {
ctx.deleteMessage()
})
} else {
console.log('No reply_to_message found! or the user is banned from doing this command')
}
})/**/ ```
Timestamps
Date.now will give you a timestamp in milliseconds. When the bot triggers, see if it has a timestamp. If it does, get a current timestamp and get the difference between timestamps. If it's under your threshold (say 5 seconds (5000ms)), skip replying. If it's over your threshold, update your saved timestamp with your current timestamp and have the bot reply.
Complete Guess
I'm not able to run the code and I'm not certain how it works, but my guess would be something along these lines
const Telegraf = require('telegraf');
const Telegram = require('telegraf/telegram')
const bot = new Telegraf('******')
let timestamp;
bot.hears(['oe', 'Oe', 'OE'], (ctx) => {
const rightNow = Date.now();
if(timestamp) {
// we have a timestamp from the last time we triggered
// so let's see if we've waited long enough...
const difference = rightNow - timestamp;
if(difference >= (5 * 1000) {
// enough time has elapsed, go ahead and do our thing
// but first, reset the timestamp for next time
timestamp = rightNow;
} else {
// nope, haven't waited long enough, abort, abort!
return;
}
} else {
// no timestamp available so this must be the first time
timestamp = rightNow;
}
if (ctx.message.reply_to_message && ctx.message.reply_to_message.from.username != 'a username' && ctx.from.id != '****') { // Check if you're replying and if you're someone banned to use this command
var a = ctx.message.reply_to_message.from.username
ctx.reply('¿# este usuario?', {
reply_markup: {
inline_keyboard: [
[{ text: "Si", callback_data: "AD" }, { text: "Sin't", callback_data: "ADNT" }]
]
}
})
bot.action('AD', (ctx) => {
ctx.deleteMessage()
ctx.reply('#' + a + ' oe')
ctx.replyWithSticker('CAACAgEAAxkBAAOsX9WKywuspdVls5VSf9xV6ZLHrqAAAg8AA5390hUNDOUjryN26R4E')
})
bot.action('ADNT', (ctx) => {
ctx.deleteMessage()
})
} else {
console.log('No reply_to_message found! or the user is banned from doing this command')
}
})/**/
My lock command is not working for some reason. It was working before and recently it has been annoying me. A terminal picture is below.
My code was working a month ago and now recently it has been acting up every time I add new code. I have compared my code from a month ago, only new code that I wrote was added.
const Discord = module.require("discord.js");
const fs =require("fs");
module.exports = {
name: "Timed Lockdown",
description: "Start a timed lockdown in a channel.",
run: async(client, message, args) => {
const time = args.join(" ");
if (!time) {
return message.channel.send("Enter a valid time period in `Seconds`, `Minutes` or `Hours`")
}
if (!message.member.hasPermission("MANAGE_SERVER", "MANAGE_CHANNELS")) {
return message.channel.send(`You don't have enough Permisions`)
}
message.channel.overwritePermissions([
{
id: message.guild.id,
deny : ['SEND_MESSAGES'],
},
],);
const embed = new Discord.MessageEmbed()
.setTitle("Channel Updates")
.setDescription(`${message.channel} has been locked for **${time}**`)
.setColor("RANDOM");
message.channel.send(embed)
let time1 = (`${time}`)
setTimeout(function(){
message.channel.overwritePermissions([
{
id: message.guild.id,
null: ['SEND_MESSAGES'],
},
],);
const embed2 = new Discord.MessageEmbed()
.setTitle("Channel Updates")
.setDescription(`Locked has been lifted in ${message.channel}`)
.setColor("RANDOM");
message.channel.send(embed2);
}, ms(time1));
message.delete();
}
}
You only have a run method in the object you're exporting from lock.js and you're calling execute in main.js.
You either need to update the method name in lock.js like this (and leave main.js as is:
module.exports = {
name: "Timed Lockdown",
description: "Start a timed lockdown in a channel.",
execute: async(client, message, args) => {
const time = args.join(" ");
// ... rest of code
Or call the run method in main.js like this:
if (command === "lock") {
client.commands.get("lock").run(message, args);
}
I am currently trying to make a Discord.js command where the first person who reacts wins the prize. There are 2 issues that I am encountering right now. First, the bot is picking up the last prize that was entered through with the command rather than the current one. Secondly, the giveaway sent before a bot restart won't work after the bot restarts.
Here is the code:
const DropModel = require('../modules/DropModel');
const { MessageEmbed, ReactionCollector } = require("discord.js")
const { COLOR, MONGO } = require("../util/BotUtil");
module.exports = {
name: "drop",
description: "First to react wins the giveaway!",
async execute(message, args) {
let prizes = args.slice(0).join(' ').toString()
if (!prizes) return message.channel.send("You didn't provide a prize.");
const newDrop = new DropModel({
guildId: message.guild.id,
prize: prizes,
channelId: message.channel.id,
createdBy: message.author,
timeCreated: new Date(),
});
newDrop.save();
let Drops = await DropModel.findOne({ guildId: message.guild.id, channelId: message.channel.id });
if (!Drops) return;
const { prize, createdBy } = Drops;
const DropEmbed = new MessageEmbed()
.setTitle(`${prize}`)
.setDescription(`First to React with 🎁 wins the giveaway
Hosted by: ${createdBy}`)
.setColor(COLOR)
.setTimestamp();
const dropMsg = await message.channel.send(`🎁 **giveaway** 🎁`, DropEmbed);
await Drops.remove();
await dropMsg.react('🎁');
const filter = (reaction, user) => !user.bot;
const reaction = new ReactionCollector(dropMsg, filter, { max: 1 });
reaction.on('collect', async (reaction, user) => {
const { embeds } = dropMsg;
const embed = embeds[0];
embed.setTitle(`Someone called giveaway!`);
embed.setDescription(`Winner: ${user.toString()}
Please contact ${createdBy} to claim your giveaway!`);
await dropMsg.edit(embed);
dropMsg.channel.send(`${user.toString()} won **${prize}**!`);
});
}
}
Any help regarding the issues mentioned above would be appreciated! Thanks!
You can save the giveaway end timestamp in JSON file or whatever database and then delete it when it's finished.
I want to send a notification within 1 hour of the data I added to Firebase and I want to cancel the notification 1 day after adding the data. Because I don't know JavaScript, and I'm new to the software world yet, I couldn't quite figure out its algorithm, and I wrote something like that. The addedNewCard method works, but I couldn't adjust the time.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().functions);
var newData;
exports.addedNewCard =
functions.firestore.document('Users/{userID}/Cards/{cardID}').onCreate(async
(snapshot, context) => {
const cardID = context.params.cardID;
if (snapshot.empty) {
console.log('No Devices');
return;
}
newData = snapshot.data();
const cardAddedDate = newData.cardAddedDate;
const deviceIdTokens = await admin
.firestore()
.collection('DeviceToken')
.get();
var tokens = [];
for (var token of deviceIdTokens.docs) {
tokens.push(token.data().deviceToken);
}
var payload = {
notification: {
title: 'Tekrar vakti',
body: 'Tekrar etmen gereken kelimeler var!!!',
sound: 'default',
},
data: {
click_action: 'FLUTTER_NOTIFICATIoN_CLICK',
sendCardID: cardID,
}
};
const options = {
priority: "high",
};
try {
await admin.messaging().sendToDevice(tokens, payload, options);
console.log('Notification sent successfully');
} catch (err) {
console.log(err);
}
})
exports.timeSettings = functions.pubsub.schedule('every 1 mins').onRun(async
(context) => {
console.log(context.timestamp);
let now = new Date();
const finishWorking = now.setDate(now.getDate + 1);
const finishWorkingStamp = admin.firestore.Timestamp.fromDate(finishWorking);
db.collection('Users/{userID}/Cards').where('cardAddedDate', '<',
finishWorkingStamp).get().then((snap) => {
if (snap.exist) {
snap.forEach(() => {
return addedNewCard();
}).catch((e) => {
return console.log(e);
});
}
});
})
Thanks to your comment, I would recommend you to use Cloud Task. With Cloud Task you can delay an execution in the futur.
When a user send a data, you can plan the 24H notification in advance (with 1 notification every 15 minutes, for 1 day -> create 96 tasks, the next one with 15 minutes more in the delay than the previous one).
You have code sample here. Have a look on this part, to change the delay
if (inSeconds) {
// The time when the task is scheduled to be attempted.
task.scheduleTime = {
seconds: inSeconds + Date.now() / 1000,
};
}
I wouldn't do the schedule notification in client side, instead, config and send schedule by server side. Try to create thread for client for processing the notifications.
You have to create a firebase cloud function where you need to upgrade your firebase account subscription and use pub-sub.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.scheduledFunctionCrontab = functions.pubsub.schedule('*/15 * * * *').timeZone('Asia/Kolkata').onRun(async (context) => {
console.log('This will be run every 15 minutes');
return null});
I am working on an employee time tracking application with its backend on node.js. The problem is when the site is hosted locally it registers the time in gmt +05:30 which is correct as i live in india but when i hosted the site on heroku server (which i think the heroku's server time zone is set to 00:00) and accesses it from same computer. then, it registers the time in gmt +00:00.
Now what i want is that when its hosted on heroku server it should know the time zone of the user (Example if user resides in Los Angeles and creates an entry. then, it should register the entry in GMT-7 timezone)
Screenshot
Code
const postSchema = {
username: String,
entry: String,
rawEntry: Number,
exit: String,
rawExit: Number,
duration: String,
complete: Boolean,
createdAt: {
type: Date,
default: Date.now()
}
};
logEntry Route
app.get('/logEntry', function(req, res) {
if (req.isAuthenticated()) {
const t = new Date();
const now = date.format(t, 'DD/MMM/YYYY ddd hh:mm:ss A Z');
const rawNow = Date.now();
const post = new Post({
username: nameUser,
entry: now,
rawEntry: rawNow,
complete: false
});
post.save(function(err) {
if (err) {
console.log(err);
}
res.redirect('/logged');
});
} else {
res.redirect('/');
}
});
This is a very common problem that we face with timezone.
Client side get getTimezoneOffset and add or remove seconds that are over.
const d = new Date();
const n = d.getTimezoneOffset();
console.log("your PC or laptop timezone more or less in seconds", n); // -330
So, when you will run this code in local that time as you told you are having gmt +05:30 getTimezoneOffset will output -330 sec means 5 hour and 30 mins.
So you can remove these seconds from the current time and set accordingly.
or
You can use in build javascript function
const d1 = new Date();
console.log(d1); //Thu Aug 29 2019 17:56:14 GMT+0530
d1.toUTCString(); // Thu, 29 Aug 2019 12:26:39 GMT
Check the differance is +5:30 hours.
I solved this problem by executing new Date() on the client side and then passing in url to the server for further action.
Client side code =>
<button onclick="createLogin()" class="btn btn-outline-primary btn-lg btn-block entryBtn">
CREATE LOGIN ENTRY
</button>
<script>
function createLogin() {
let t = new Date();
console.log(t);
let url = '/logEntry/' + t;
window.location = url;
}
</script>
Server side code =>
app.get('/logEntry/:date', function(req, res) {
if (req.isAuthenticated()) {
const now = req.params.date;
const nowDayTime = now.substring(0, 25);
const timeZone = now.substring(25, now.length);
const rawNow = Date.now();
const post = new Post({
username: nameUser,
entryDayTime: nowDayTime,
entryTimeZone: timeZone,
rawEntry: rawNow,
complete: false
});
post.save(function(err) {
if (err) {
console.log(err);
}
res.redirect('/logged');
});
} else {
res.redirect('/');
}
});