Index
- ๐ค Why?
- ๐คจ How?
- How did I do it?
- Code Showcase
- Final Results
- ๐ค Conclusion
๐ค Why?
Around 1 month ago I started university, and one of the things I found myself doing all the time was looking at my schedule looking for what classes I had and in what classroom it was. I found that really annoying, mostly because the only way to check it was in a online page. ๐ฃ
One of the things I like to do is to automate things I do more than once. And this type of project is why I got into programming in the first place.
So, I have to use my programming skills to solve / automate this scenario which will save my screen time.
๐คจ How?
How I did it?
First, I learned how to use the Google Calendar in Node.js. Then, I realized that I had to do everything because there isn't any tool already created to do what I want. So I decided to roll up my sleeves and get down to business. ๐ช
In this first version it was a lot more manual than I had hoped for, but it gave me a foundation that I could build upon and improve in future versions. ๐ค
Well, by manual I mean I had to do this steps:
- Open google chrome developer console
- Navigate into the schedule page
- Login with my credentials
- Check the network (in the console) for the response that contained the schedule .json
- Save that file to my desktop
- Run my application
And after all that is done I have my schedule in my calendar, which then synchronizes in all my devices, including my smartphone.
Code Showcase
Here are the overall steps and gist.
-
Then I had to authenticate into google calendar, for that I used this npm package for node.js:
googleapis / google-api-nodejs-client
Google's officially supported Node.js client library for accessing Google APIs. Support for authorization and authentication with OAuth 2.0, API Keys and JWT (Service Tokens) is included.
It wasn't that difficult as long as you follow the quick guide that google provides:
/** | |
* @license | |
* Copyright Google Inc. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* https://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
// [START calendar_quickstart] | |
const fs = require('fs'); | |
const readline = require('readline'); | |
const {google} = require('googleapis'); | |
// If modifying these scopes, delete token.json. | |
const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']; | |
// The file token.json stores the user's access and refresh tokens, and is | |
// created automatically when the authorization flow completes for the first | |
// time. | |
const TOKEN_PATH = 'token.json'; | |
// Load client secrets from a local file. | |
fs.readFile('credentials.json', (err, content) => { | |
if (err) return console.log('Error loading client secret file:', err); | |
// Authorize a client with credentials, then call the Google Calendar API. | |
authorize(JSON.parse(content), listEvents); | |
}); | |
/** | |
* Create an OAuth2 client with the given credentials, and then execute the | |
* given callback function. | |
* @param {Object} credentials The authorization client credentials. | |
* @param {function} callback The callback to call with the authorized client. | |
*/ | |
function authorize(credentials, callback) { | |
const {client_secret, client_id, redirect_uris} = credentials.installed; | |
const oAuth2Client = new google.auth.OAuth2( | |
client_id, client_secret, redirect_uris[0]); | |
// Check if we have previously stored a token. | |
fs.readFile(TOKEN_PATH, (err, token) => { | |
if (err) return getAccessToken(oAuth2Client, callback); | |
oAuth2Client.setCredentials(JSON.parse(token)); | |
callback(oAuth2Client); | |
}); | |
} | |
/** | |
* Get and store new token after prompting for user authorization, and then | |
* execute the given callback with the authorized OAuth2 client. | |
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for. | |
* @param {getEventsCallback} callback The callback for the authorized client. | |
*/ | |
function getAccessToken(oAuth2Client, callback) { | |
const authUrl = oAuth2Client.generateAuthUrl({ | |
access_type: 'offline', | |
scope: SCOPES, | |
}); | |
console.log('Authorize this app by visiting this url:', authUrl); | |
const rl = readline.createInterface({ | |
input: process.stdin, | |
output: process.stdout, | |
}); | |
rl.question('Enter the code from that page here: ', (code) => { | |
rl.close(); | |
oAuth2Client.getToken(code, (err, token) => { | |
if (err) return console.error('Error retrieving access token', err); | |
oAuth2Client.setCredentials(token); | |
// Store the token to disk for later program executions | |
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => { | |
if (err) return console.error(err); | |
console.log('Token stored to', TOKEN_PATH); | |
}); | |
callback(oAuth2Client); | |
}); | |
}); | |
} | |
// [END calendar_quickstart] | |
module.exports = { | |
SCOPES, | |
listEvents, | |
}; |
- Next, I looped through all the Classes and Created a Event for each to add to Google Calendar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
let event = { 'summary': aula.nomeUC, 'description': `Sala: ${aula.sala}\nTurno: ${aula.turnoUC}`, 'colorId': '7', 'start': { 'dateTime': moment().add(aula.diaSemana - dia, 'days').hours(inicio[0]).minutes(inicio[1]).seconds(0).format(), 'timeZone': 'Europe/Lisbon', }, 'end': { 'dateTime': moment().add(aula.diaSemana - dia, 'days').hours(fim[0]).minutes(fim[1]).seconds(0).format(), 'timeZone': 'Europe/Lisbon', } }; This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersfunction CalendarHelper() { this.InsertEvent = function(calendar, event) { calendar.events.insert({ calendarId: 'primary', resource: event }, (err, event) => { if(err) { console.error("Error Contacting Calendar Service: ", err.errors); return; } console.log(ยด[HorarioHelper] ${event.summary} - Added!ยด); }); } } module.exports = CalendarHelper;
Final Results
In this first version I had the functionality working, even though it's not really automated it does what I need to.
And this is what I got:
๐ค Conclusion
This is what technology is all about. Identify the problem and come up with a solution, even if the solution takes some versions to be good.
There are so many possibilities with the combination of the tools like GoogleApi and Node.js. And with those we can increase our productivity.
!!! Be sure to Comment ๐ ... You guys all Rock !!!
P.S: This is my first post. Feel free to point out any mistakes so I can improve
P.S2: When I have the time I will post the second part where I really automate it
Top comments (0)