-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
215 lines (198 loc) · 7.31 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/******************************************************************************/
/* app.js */
/* Author: Seung Jae Lee */
/* Parts of code from */
/* https://developers.google.com/google-apps/calendar/quickstart/node */
/******************************************************************************/
var fs = require('fs');
var readline = require('readline');
var google = require('googleapis');
var googleAuth = require('google-auth-library');
var chrono = require('chrono-node')
// read/write access except delete for gmail, and read/write access to calendar
var SCOPES = ['https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/calendar'];
var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
process.env.USERPROFILE) + '/.credentials/';
var TOKEN_PATH = TOKEN_DIR + 'gmail-calendar-nodejs-tigercal.json';
// Load client secrets from a local file.
fs.readFile('client_secret.json', function processClientSecrets(err, content) {
if (err) {
console.log('Error loading client secret file: ' + err);
return;
}
// Authorize a client with the loaded credentials, then call the
// main program.
authorize(JSON.parse(content), main);
});
/**
* 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) {
var clientSecret = credentials.installed.client_secret;
var clientId = credentials.installed.client_id;
var redirectUrl = credentials.installed.redirect_uris[0];
var auth = new googleAuth();
var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, function(err, token) {
if (err) {
getNewToken(oauth2Client, callback);
} else {
oauth2Client.credentials = 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 to call with the authorized
* client.
*/
function getNewToken(oauth2Client, callback) {
var authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
console.log('Authorize this app by visiting this url: ', authUrl);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Enter the code from that page here: ', function(code) {
rl.close();
oauth2Client.getToken(code, function(err, token) {
if (err) {
console.log('Error while trying to retrieve access token', err);
return;
}
oauth2Client.credentials = token;
storeToken(token);
callback(oauth2Client);
});
});
}
/**
* Store token to disk be used in later program executions.
*
* @param {Object} token The token to store to disk.
*/
function storeToken(token) {
try {
fs.mkdirSync(TOKEN_DIR);
} catch (err) {
if (err.code != 'EEXIST') {
throw err;
}
}
fs.writeFile(TOKEN_PATH, JSON.stringify(token));
console.log('Token stored to ' + TOKEN_PATH);
}
/**
* Parses events from all unread emails, adds them to calendar, and marks them
* as read.
*
* @param {Object} auth Authorization credentials for Google APIs.
*/
var main = function (auth) {
// set auth as a global default
google.options({auth: auth});
google.gmail('v1').users.messages.list({ // Get unread message list
userId: 'me',
q: 'is:unread',
}, function (err, res) {
// if unread message exists
if (!err && res && res.messages && res.messages.length) {
for(var i = 0; i < res.messages.length; i++) {
var messageId = res.messages[i].id;
// Mark email as read by deleting UNREAD label
// FIXME: Should default behavior be leaving them unread?
google.gmail('v1').users.messages.modify({
userId: 'me',
id: messageId,
resource: { removeLabelIds: ['UNREAD'] },
});
// Get content of email
google.gmail('v1').users.messages.get({
userId: 'me',
id: messageId,
}, function(err, result) {
if(result && result.payload && result.payload.parts
&& result.payload.parts.length
&& result.payload.parts[0].body
&& result.payload.parts[0].body.data) {
// Subject/Title of email
var subject = result.payload.headers.find(x => x.name === 'Subject').value;
// Text body of the email encoded by base64
var encodedbody = result.payload.parts[0].body.data;
// Text body of the email
var body = Buffer.from(encodedbody, 'base64').toString("ascii");;
// Parse event
var event = parseEvent({subject: subject, text: body});
if(event != null) {
// Add event to calendar
// FIXME: Should return if calendar returned error
addEvent(event);
}
}
});
}
} else {
console.log('No unread message exists');
}
});
};
/**
* Parse event from an email object and returns event object.
*
* @param {Object} email The email with subject and text to parse.
*/
function parseEvent(email) {
var ref = new Date();
var results = chrono.parse(email.text, ref);
if(results.length == 0) {
return null;
}
var startTime = results[0].start.date().toISOString();
var endTime = startTime;
if (results[0].end) {
endTime = results[0].end.date().toISOString();
}
// create event object
var event = {
'summary': email.subject,
'start': {
'dateTime': startTime,
'timeZone': 'America/New_York',
},
'end': {
'dateTime': endTime,
'timeZone': 'America/New_York',
},
};
return event;
}
/**
* Add given event object to calendar.
*
* @param {Object} event The event to add to calendar.
*/
function addEvent(event) {
var calendar = google.calendar('v3');
calendar.events.insert({
calendarId: 'primary',
resource: event,
}, function(err, event) {
if (err) {
console.log('There was an error contacting the Calendar service: ' + err);
}
// console.log('Event created: %s', event.htmlLink);
});
}