Update DB when Google Calendar Event change - node.js

I have been implementing some functions of google calendar api. I have a custom calendar which have the capability to sync with google calendar. This means, you can create, and edit calendars and events from my dashboard to google calendar account. The main problem I am facing is, if I update the event directly from my google calendar. I have implemented push notifications and getting response like this:
{
"Google_channel_ID": "19835150 - 0057 - 11e6 - bc9c - 1735798 ca540",
"Google_channel_token": "calendar_id = 4e7 d5c20ht9lpfdtuukcsvgeq4 #group.calendar.google.com & user_id = 43e d7rxeqqce3fk09ahszc",
"Google_channel_expiration": "Tue,12 Apr 2016 12: 34: 36 GMT",
"Google_resource_id": "oLMEEhHAw5Xo3r2187CWykjAtm0",
"Google_resource_URI": "https: //www.googleapis.com/calendar/v3/calendars/4e7d5c20ht9lpfdtuukcsvgeq4#group.calendar.google.com/events?alt=json",
"Google_resource_state": "sync",
"Google_message_number": "1"
}
But this response is very general. For example, If I have 1000 events on this calendar, and update the complete 1000 events. I will receive always the same notification 1000. I would like to know, if it is possible to get which event id has change, so I can perform and update to my DB.
The way I init the watch is like this:
exports.watch = function(req, res){
var channel_id = uuid.v1();
var user_id = req.body.user_id;
var calendar_id = req.body.calendar_id;
authorize(user_id, function(oauth2Client){
var data = {
auth: oauth2Client,
calendarId: calendar_id,
resource: {
id: channel_id,
token: 'calendar_id='+ calendar_id + '&user_id=' + user_id,
address: 'https://api.medradr.com/google-watch',
type: 'web_hook',
params: {
ttl: '36000'
}
}
};
calendar.events.watch(data, function (err, response) {
if (err) {
console.error('The API returned an error: ' + err);
return;
}else{
res.send({ok: true, message: 'Listener created', result:response});
}
});
});
}

For people who are looking for a good way to get which events changed when the web hook triggers. When your web hook is triggered, you will get something like this:
X-Goog-Channel-ID: channel-ID-value
X-Goog-Channel-Token: channel-token-value
X-Goog-Channel-Expiration: expiration-date-and-time // In human-readable format; present only if channel expires.
X-Goog-Resource-ID: identifier-for-the-watched-resource
X-Goog-Resource-URI: version-specific-URI-of-the-watched-resource
X-Goog-Resource-State: sync
X-Goog-Message-Number: 1
On X-Goog-Resource-URI you will get something like this:
https://www.googleapis.com/calendar/v3/calendars/4e7d5c20ht9lpfdtuukcsvgeq4#group.calendar.google.com/events?alt=json
With you OAuth authentication, you can make a GET request to this URL to fetch all events that belongs to this calendar. Now the trick to know which resources have been changed is really simple. For each event you will get something like this:
{
event_id: 335,
user_id: '43ed7rxeqqce3fk09ahszc',
kind: 'calendar#event',
etag: '"2921213870180000"',
google_id: 'cpbcesg966skprb3rh1p1ud668',
status: 'confirmed',
htmlLink: 'https://www.google.com/calendar/event?eid=Y3BiY2VzZzk2NnNrcHJiM3JoMXAxdWQ2NjggNGU3ZDVjMjBodDlscGZkdHV1a2NzdmdlcTRAZw',
created: Thu Apr 14 2016 00:00:00 GMT-0500 (CDT),
updated: Thu Apr 14 2016 00:00:00 GMT-0500 (CDT),
summary: 'Testing google notifications',
description: '',
creator: 'guizarkrg#gmail.com',
organizer: '4e7d5c20ht9lpfdtuukcsvgeq4#group.calendar.google.com',
start: Sat Apr 09 2016 00:00:00 GMT-0500 (CDT),
end: Sun Apr 10 2016 00:00:00 GMT-0500 (CDT),
iCalUID: 'cpbcesg966skprb3rh1p1ud668#google.com',
event_type_id: 0,
calendar_id: 0,
timezone_id: 0,
sequence: 0,
calendar_color_id: ''
}
As you can see, the is a sequence: 0, this is incremental. This means, each time you apply some changes on your event (summary, description, start date, end date, etc). This number will be incremented +1. You can save this on your database, so each time web hook triggers, you update only events which sequence is > than saved sequence. So basically, you update the event and save the new value of sequence. Next time that web hook triggers, it will only update on your DB the events that are included in this condition.
Hope it helps, happy coding.

Related

lastmessageID always null except for me

Presentation
Goal: Find when the last message of a designated was send
How: Use property of User, lastmessageID, fetch the message corresponding to this ID to find the property createdTimestamp
Problem: I'm the only one in the was doesn't have the property lastmessageID equal to null even if the user had send message a few minute ago
Question: Is it coming from my coding or from Discord.js ? Is there a way to bypass this problem ?
NOTE: I know it's cached:
When someone send a message while the bot is alive give the same result.
For the sake of the test, I summon a bot that so I give me a"fresh" message when testing
CODE SAMPLE
every "..." is to protect personal data
SCRIPT
function findID() {
var IDarray = userm.users.map((user) => user.lastMessageID)
console.log("IDarray: ", IDarray)
var ID = IDarray[0]
console.log("ID: ", ID)
msg(ID)
}
function msg(lastmsgID) {
var lastmsg = message.channel.messages.fetch(lastmsgID).then(message => time(message)).catch(console.error);
}
function time(msg){
...
}
findID();
RESULTS
WITH ME
user: [
User {
id: '...',
bot: false,
username: '...',
discriminator: '....',
avatar: '...',
flags: UserFlags { bitfield: ... },
lastMessageID: '...',
lastMessageChannelID: '...'
}
]
IDarray: [ '...' ]
ID: ...
<Wed Oct 07 2020 00:30:52 GMT+0200 (GMT+02:00)> : Recieved Message to ..., content /test <#!...>
Date as YYYY-MM-DD hh:mm:ss ==> 2020-10-07 00:30:54
RESULTS
WITH ANYONE
user: [
User {
id: '...',
bot: false,
username: '...',
discriminator: '...',
avatar: '...',
lastMessageID: null,
lastMessageChannelID: null,
flags: UserFlags { bitfield: ... }
}
]
IDarray: [ null ]
ID: null
<Wed Oct 07 2020 00:26:44 GMT+0200 (GMT+02:00)> : Recieved Message to ..., content /test <#...>
Date as YYYY-MM-DD hh:mm:ss ==> NaN-aN-aN aN:aN:aN
If you think I can improve this question by anyway, don't hesitate to tell me !
Thanks for reading !
Try client.users.fetch('uid'); to fetch the user then pull the info you need. This pulls updates the user from Discord not from the cache.
This is a problem with the cache. The bot will only give lastMessage if the message was sent after the bot is started. You would need to fetch all the messages from all the channels for it to work, or just wait for the users to post a message after to bot is started.

How to get the original input using Joi.raw()

I'm trying to validate some input with hapijs/joi and joi-date-extensions
. I write this code example1.js:
const BaseJoi = require('joi');
const Extension = require('joi-date-extensions');
const Joi = BaseJoi.extend(Extension);
const schema = Joi.object().keys({
start_date: Joi.date().format('YYYY-MM-DD').raw(),
end_date: Joi.date().min(Joi.ref('start_date')).format('YYYY-MM-DD').raw(),
});
const obj = {
start_date: '2018-07-01',
end_date: '2018-06-30',
}
console.log(schema.validate(obj));
the code returns this error:
child "end_date" fails because ["end_date" must be larger than or equal to "Sun Jul 01 2018 01:00:00 GMT+0100 (CET)"]
However I want to get the original input in the error, somthing like that:
child "end_date" fails because ["end_date" must be larger than or equal to "2018-07-01"]
When I tried this instruction in the example2.js:
start_date = Joi.date().format('YYYY-MM-DD');
console.log(start_date.validate('2018-07-31'));
The result was:
Tue Jul 31 2018 00:00:00 GMT+0100 (CET)
when I use the raw() in the example3.js:
start_date = Joi.date().format('YYYY-MM-DD').raw();
console.log(start_date.validate('2018-07-31'));
it returns:
"2018-07-31"
In the example1.js I want to get the original date entred by my code. How can I fix that?
.raw controls how data is transmitted to Joi.validate's callback, i.e. what your data looks like after the validation process. It does not control what happens on errors.
To do that, you may want to use .error. I never used it but I guess it'd be something like this:
Joi.date().min(Joi.ref('start_date')).format('YYYY-MM-DD').raw().error(function (errors) {
var out = [];
errors.forEach(function (e) {
out.push(e.message.replace(/".*?"/g, function(match) {
var dateMatch = Date.parse(match);
if (isNaN(dateMatch)) {
return match;
} else {
// return formatted date from `dateMatch` here, too lazy to write it in p[l]ain JS...
}
}));
});
return out;
})

Date is one day off when referenced inside nodejs application

Ok so this question has been asked here however the solutions given don't seem to resolve my issue.
I have the following:
When I click save I refer to the these fields and create a date as shown here:
this.profile.date_of_birth = new Date(this.editProfileForm.value['year'], this.editProfileForm.value['month'], this.editProfileForm.value['day']);
Which when logged to the console reads:
Fri Dec 23 1988 00:00:00 GMT+1100 (AEDT)
I then make a call to my nodejs application which is running on http://localhost:3005, which takes the data and saves it to mongodb, before the save happens I log the value of date_of_birth as shown here:
api.put('/update', authenticate, (req, res) => {
console.log(req.body.date_of_birth);
// Save properties
});
however this logs:
1988-12-22T13:00:00.000Z
which is a day off....
I'm not doing any formatting before creating a new date when the user presses save, so I'm unsure into why when it leaves the front end application, and gets to the backend application the date is displayed incorrect....
The actual call to the nodejs application is here:
saveProfile(profileId: string, token: string, profile: Profile): Observable<any> {
var body = {
"id": profile.id,
"date_of_birth": profile.date_of_birth,
}
return this.http.put(UPDATE_EDIT_PROFILE, body, {
headers: this.setHeaders(token)
}).map((res: any) => res.json());
}
Can anyone recommend what could possibly going wrong?
Fri Dec 23 1988 00:00:00 GMT+1100 (AEDT) is date with the current timezone. and your server seems using UTC according to 1988-12-22T13:00:00.000Z.
you can use Date.UTC to create a Date Object with standart timezone of UTC which keeps same to your server.
var year = 1988;
var month = 12;
var day = 23;
console.log(new Date(year, month - 1, day));
console.log(new Date(Date.UTC(year, month - 1, day)));

Strange date behaviour with MongoDB

I'm writing a React Application that uses MongoDB as its database. There seems to be some strange behaviour when saving and retrieving dates from the database, specifically when updating the date in a particular document.
When I create a new document, everything is fine. However, if I try to edit the date on that document using an ajax call, the date stored in MongoDB is one day earlier than the one I selected and what is displayed in the browser. Code below to explain a little more.
The date is selected using an HTML5 <input type='date' /> element. Here's some of the code. I've included console logs at various points to show the output. Let's assume I'm selecting '30 October 2016' as the date. The date and the year get split up for display purposes elsewhere, but then joined together in the form of a JS Date object before sending to the server (see code below)
React component method:
saveChanges(e, cancel){
e.preventDefault();
const cancelled = cancel ? true : false
console.log(this.state.date); // 30 Oct
console.log(this.state.year); // 2016
const saveData = {
id: this.props.data.id,
venue: this.state.venue,
unitNumber: this.state.unitNumber,
unitName: this.state.unitName,
date: this.state.date,
year: this.state.year,
day: this.state.day,
tutorID: this.state.tutorID,
cancelled: cancelled
}
editWorkshop(saveData, (data) => {
this.props.getWorkshopDetails();
this.props.workshopDetailsSaved(data);
});
}
The above method sends the data to editWorkshop.js, an external ajax call, using axios:
import axios from 'axios';
export default function editWorkshop(input, callback){
const date = new Date(input.date + ' ' + input.year) // Rejoin date and year and convert to Date object
console.log(date); // Sun Oct 30 2016 00:00:00 GMT+0100 (BST)
const data = {
id: input.id,
venue: input.venue,
unitNumber: input.unitNumber,
unitName: input.unitName,
date: date,
day: input.day,
tutorID: input.tutorID,
cancelled: input.cancelled
}
axios.post('/editWorkshop', data).then(function(res){
callback(res.data);
})
}
And finally the express route which handles the ajax call
const express = require('express');
const Workshop = require('../data/models/Workshop');
module.exports = function(req, res){
const data = req.body
console.log(data.date); // 2016-10-29T23:00:00.000Z - here is where it seems to go wrong - notice that the date has changed to 2016-10-29 instead of 10-30. This now gets written to the database
Workshop.update({ _id: data.id }, {
$set: {
unitNumber: data.unitNumber,
date: data.date,
venue: data.venue,
tutor: data.tutorID,
session: data.day,
cancelled: data.cancelled
}
}, function(err){
if (err) {
res.send(err);
return
}
var message = 'Workshop updated'
res.send({
success: true,
message: message
});
})
}
What's really strange is that when I retrieve the data from the database elsewhere in the application, it shows the correct date in the browser - 30 Oct 2016.
Arguably this isn't a problem as the correct date is being displayed, but I'm not comfortable with this as these dates are a fundamental part of the app and I'm concerned that there could be scope for a bug in the future.
Can anyone shed any light on this?
2016-10-29T23:00:00.000Z is same as Sun Oct 30 2016 00:00:00 GMT+0100 (BST).
2016-10-29T23:00:00.000Z is in UTC(GMT) timezone. If you convert that to BST you will get the same value.
MongoDB saves the date values as UTC milliseconds since the Epoch.
From the docs:
MongoDB stores times in UTC by default, and will convert any local
time representations into this form. Applications that must operate or
report on some unmodified local time value may store the time zone
alongside the UTC timestamp, and compute the original local time in
their application logic.

Mongodb sorts by day of the week instead of actual date. What am I doing wrong?

I'm new to Node.js and Mongodb so bear with me here.
I have read from multiple places that the best way to store dates is with new Date(). So before I store my dates in the Mongodb I convert them with new Date('10/07/2014'), turning it into 'Tue Oct 07 2014 00:00:00 GMT-0400 (Eastern Daylight Time)'.
The problem is that if I try to run a sort on the collection it sorts them by the day of the week(Mon, Tues, Wed, etc) and not by their actual dates. What am I doing wrong here? Heres some actual code:
//get date from a field and convert it
var date = new Date($('#inputDate').val());
//after storing it in the database I call this line and it sorts it by day of the week.
db.collection('gameslist').find().sort({date:1})
Printing out the sorted collection their dates come out in this order, which is by day of the week and not by actual date.
Fri Feb 20 2015 00:00:00 GMT-0500 (Eastern Standard Time)
Mon Oct 13 2014 00:00:00 GMT-0400 (Eastern Daylight Time)
Sun Feb 15 2015 00:00:00 GMT-0500 (Eastern Standard Time)
Tue Oct 07 2014 00:00:00 GMT-0400 (Eastern Daylight Time)
I've noticed in other posts when people do something like new Date() their dates don't come out like mine but instead come out with less fluff.
EDIT: Adding my actual code.
gamelist.js file that has a function that does an ajax call.
dateCompleted = new Date($('#addgame div input#inputDateCompleted').val());
var newGame = {
'title': $('#addgame div input#inputTitle').val(),
'datecompleted': dateCompleted,
'rating': $('#addgame div select#inputRating').val(),
}
// Use AJAX to post the object to our addgame service
$.ajax({
type: 'POST',
data: newGame,
url: '/games/addgame',
dataType: 'JSON'
})
addgame router at /games/addgame:
/*
* POST to addgame.
*/
router.post('/addgame', function(req, res) {
var db = req.db;
db.collection('gameslist').insert(req.body, function(err, result){
res.send(
(err === null) ? { msg: '' } : { msg: err }
);
});
});

Resources