Files
mwitnessing/src/helpers/calendar.js
2024-03-13 12:23:22 +02:00

498 lines
16 KiB
JavaScript

const fs = require("fs").promises;
const path = require("path");
const process = require("process");
const { google } = require("googleapis");
const { OAuth2Client } = require("google-auth-library");
const http = require("http");
const url = require("url");
// const destroyer = require('server-destroy');
const CON = require("./const");
const TOKEN_PATH = path.join(process.cwd(), "content/token.json");
const CREDENTIALS_PATH = path.join(
process.cwd(),
"content/client_secret_926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com.json"
);
//generates iCalendar file for a single shift
GenerateICS = function (shifts) {
// https://stackoverflow.com/questions/3665115/create-a-file-in-memory-for-user-to-download-not-through-server
var content = "BEGIN:VCALENDAR\n";
content += "VERSION:2.0\n";
content += "PRODID:-//JW Cart//Shift Info//EN\n";
content += "CALSCALE:GREGORIAN\n";
content += "METHOD:PUBLISH\n";
content += "X-WR-CALNAME:Колички София-Изток\n";
content += "X-WR-TIMEZONE:Europe/Sofia\n";
content += "BEGIN:VTIMEZONE\n";
content += "TZID:Europe/Sofia\n";
content += "BEGIN:DAYLIGHT\n";
content += "TZOFFSETFROM:+0200\n";
content += "TZOFFSETTO:+0300\n";
content += "TZNAME:EEST\n";
content += "DTSTART:19700329T020000\n";
content += "RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\n";
content += "END:DAYLIGHT\n";
content += "BEGIN:STANDARD\n";
content += "TZOFFSETFROM:+0300\n";
content += "TZOFFSETTO:+0200\n";
content += "TZNAME:EET\n";
content += "DTSTART:19701025T030000\n";
content += "RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\n";
content += "END:STANDARD\n";
content += "END:VTIMEZONE\n";
content += shifts?.map((shift) => {
var content = "BEGIN:VEVENT\n";
content += "DTSTAMP:" + new Date().getTime() + "\n";
content += "UID:" + shift.id + "\n";
content +=
"DTSTART;TZID=Europe/Sofia:" +
CON.GetDateTimeShort(shift.startTime) +
"\n";
content +=
"DTEND;TZID=Europe/Sofia:" +
CON.GetDateTimeShort(shift.endTime.getTime()) +
"\n";
content += "LOCATION:" + shift.cartEvent.location.name + "\n";
// content += "SUMMARY:" + shift.cartEvent.location.name + "\n";
// Adding a VALARM component for a reminder 1 day before the event
content += "BEGIN:VALARM\n";
content += "TRIGGER:-P1D\n"; // Trigger alarm 1 day before the event
content += "ACTION:DISPLAY\n";
content += "DESCRIPTION:Reminder\n";
content += "END:VALARM\n";
content += "END:VEVENT";
return content;
})
.join("\n");
content += "END:VCALENDAR\n";
//encode content in base64 to be send as attachment
return Buffer.from(content).toString("base64");
};
// /**
// * Reads previously authorized credentials from the save file.
// *
// * @return {Promise<OAuth2Client|null>}
// */
// loadSavedCredentialsIfExist = async function loadSavedCredentialsIfExist() {
// try {
// const content = await fs.readFile(TOKEN_PATH);
// const credentials = JSON.parse(content);
// return google.auth.fromJSON(credentials);
// } catch (err) {
// return null;
// }
// }
// /**
// * Serializes credentials to a file compatible with GoogleAUth.fromJSON.
// *
// * @param {OAuth2Client} client
// * @return {Promise<void>}
// */
// saveCredentials = async function saveCredentials(client) {
// const content = await fs.readFile(CREDENTIALS_PATH);
// const keys = JSON.parse(content);
// const key = keys.installed || keys.web;
// const payload = JSON.stringify({
// type: 'authorized_user',
// client_id: key.client_id,
// client_secret: key.client_secret,
// refresh_token: client.credentials.refresh_token,
// });
// await fs.writeFile(TOKEN_PATH, payload);
// }
// /**
// * Load or request or authorization to call APIs.
// *
// */
// authorize = async function authorize() {
// let client = await exports.loadSavedCredentialsIfExist();
// if (client) {
// return client;
// }
// client = await exports.authenticate({
// scopes: SCOPES,
// keyfilePath: CREDENTIALS_PATH,
// });
// if (client.credentials) {
// await saveCredentials(client);
// }
// return client;
// }
// /**
// * Lists the next 10 events on the user's primary calendar.
// * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
// */
// listEvents = async function listEvents(auth) {
// const calendar = google.calendar({ version: 'v3', auth });
// const res = await calendar.events.list({
// calendarId: 'primary',
// timeMin: new Date().toISOString(),
// maxResults: 10,
// singleEvents: true,
// orderBy: 'startTime',
// });
// const events = res.data.items;
// if (!events || events.length === 0) {
// console.log('No upcoming events found.');
// return;
// }
// console.log('Upcoming 10 events:');
// events.map((event, i) => {
// const start = event.start.dateTime || event.start.date;
// console.log(`${start} - ${event.summary}`);
// });
// }
// //usage
// GetEvents = async function GetEvents(dateTime = new Date()) {
// var events = exports.authorize().then(exports.listEvents).catch(console.error);
// }
// // const calendar = google.calendar({ version: 'v3', auth });
// const eventTest = {
// summary: 'Test Event',
// start: {
// dateTime: '2023-01-01T09:00:00-07:00',
// timeZone: 'Europe/Sofia',
// },
// end: {
// dateTime: '2023-01-01T17:00:00-07:00',
// timeZone: 'Europe/Sofia',
// },
// };
// const TOKEN_PATH = path.join(process.cwd(), 'content/token.json');
// const CREDENTIALS_PATH = path.join(process.cwd(), 'content/client_secret_926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com.json');
createEvent = async function createEvent(id) {
// var eventTest2 = {
// 'summary': 'Google I/O 2015',
// 'location': '800 Howard St., San Francisco, CA 94103',
// 'description': 'A chance to hear more about Google\'s developer products.',
// 'start': {
// 'dateTime': '2015-05-28T09:00:00-07:00',
// 'timeZone': 'America/Los_Angeles',
// },
// 'end': {
// 'dateTime': '2015-05-28T17:00:00-07:00',
// 'timeZone': 'America/Los_Angeles',
// },
// 'recurrence': [
// 'RRULE:FREQ=DAILY;COUNT=2'
// ],
// 'attendees': [
// { 'email': '' },
// ],
// 'reminders': {
// 'useDefault': false,
// 'overrides': [
// { 'method': 'email', 'minutes': 24 * 60 },
// { 'method': 'popup', 'minutes': 10 },
// ],
// },
// };
// var errors;
// var auth = await exports.authorize().then((auth) => {
// const calendar = google.calendar({ version: 'v3', auth });
// const res = calendar.events.insert({
// calendarId: 'primary',
// resource: eventTest,
// }, (err, event) => {
// if (err) {
// console.log(`There was an error creating the event: ${err}`);
// return;
// }
// console.log(`Event created: ${event.data.htmlLink}`);
// });
// }).catch(console.error).then((err) => {
// errors = err;
// });
// return errors;
// }
// authorizeNew = async function authorizeNew() {
// let client = await loadSavedCredentialsIfExist();
// if (client) {
// return client;
// }
// // Set up the Google Calendar API client
// const calendar = google.calendar({ version: 'v3', auth });
// // Load the client secrets from a JSON file
fs.readFile("./path/to/client_secret.json", (err, content) => {
if (err) return console.error("Error loading client secret file:", err);
// Authorize a client with the loaded credentials
authorizeOA(JSON.parse(content), calendar.calendarList.list);
});
if (client.credentials) {
await saveCredentials(client);
}
return client;
};
// var googletoken = axiosInstance.get("/content/google_token.json");
// console.log("googletoken: " + googletoken);
// if (!googletoken) {
// toast.error("Google token not found. redirecting to google login");
// const { data, error } = axiosInstance.get('/content/client_secret_926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com.json',
// { headers: { 'Content-Type': 'application/json' } });
// console.log("data: " + JSON.stringify(data));
// console.log("error: " + JSON.stringify(error));
// var secrets = data;
// const { google } = await import('googleapis');
// const { OAuth2 } = google.auth;
// const oAuth2Client = new OAuth2(
// secrets.web.client_id,
// secrets.web.client_secret,
// secrets.web.redirect_uris[0]
// );
// const authorizationUrl = oauth2Client.generateAuthUrl({
// // 'online' (default) or 'offline' (gets refresh_token)
// access_type: 'offline',
// /** Pass in the scopes array defined above.
// * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
// scope: scopes,
// // Enable incremental authorization. Recommended as a best practice.
// include_granted_scopes: true
// });
// return { redirect: authorizationUrl };
/**
* 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 authorizeOA(credentials, callback) {
const { client_secret, client_id, redirect_uris } =
credentials.installed || credentials.web;
const oAuth2Client = new OAuth2Client(
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: ["https://www.googleapis.com/auth/calendar"],
});
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);
});
});
}
// // /**
// // * Lists the next 10 events on the user's primary calendar.
// // * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
// // * @param {getEventsCallback} callback The callback for the authorized client.
// // *
// // */
// // function listEvents(auth) {
// // const calendar = google.calendar({ version: 'v3', auth });
// // calendar.events.list({
// // calendarId: 'primary',
// // timeMin: (new Date()).toISOString(),
// // maxResults: 10,
// // singleEvents: true,
// // orderBy: 'startTime',
// // }, (err, res) => {
// // if (err) return console.error('The API returned an error: ' + err);
// // const events = res.data.items;
// // if (events.length) {
// // console.log('Upcoming 10 events:');
// // events.map((event, i) => {
// // const start = event.start.dateTime || event.start.date;
// // console.log(`${start} - ${event.summary}`);
// // });
// // } else {
// // console.log('No upcoming events found.');
// // }
// // });
// // }
// // [END calendar_quickstart]
// module.exports = {
// GenerateICS,
// createEvent,
// authorize,
// TOKEN_PATH,
// CREDENTIALS_PATH
// }
async function importModules() {
const openModule = await import('open');
const getPortModule = await import('get-port');
return {
open: openModule.default,
getPort: getPortModule.default
};
}
createEvent = async (event) => {
const { open, getPort } = await importModules();
event = event || {
summary: "Test Event",
location: "Online",
start: {
dateTime: "2022-12-19T09:00:00Z",
timeZone: "UTC",
},
end: {
dateTime: "2022-12-19T10:00:00Z",
timeZone: "UTC",
},
};
try {
const fc = await fs.readFile(CREDENTIALS_PATH);
// const auth = new google.auth.fromClientSecret(fc);
const secrets = JSON.parse(fc);
const { google } = await import("googleapis");
const { OAuth2 } = google.auth;
var callbackUrl = secrets.web.redirect_uris[0];
const freePort = await getPort();
const url = new URL(callbackUrl);
url.port = freePort;
callbackUrl = url.toString();
const oAuth2Client = new OAuth2(
secrets.web.client_id,
secrets.web.client_secret,
callbackUrl
);
// Generate the url that will be used for the consent dialog.
const authorizeUrl = oAuth2Client.generateAuthUrl({
access_type: "offline",
scope: "https://www.googleapis.com/auth/userinfo.profile",
});
let doAuth = await new Promise((resolve, reject) => {
const server = http
.createServer(async (req, res) => {
try {
if (req.url.indexOf("/oauth2callback") > -1) {
// acquire the code from the querystring, and close the web server.
const qs = new url.URL(req.url, "http://localhost:3003")
.searchParams;
const code = qs.get("code");
console.log(`Code is ${code}`);
res.end(
"Authentication successful! Please return to the console."
);
server.destroy();
// Now that we have the code, use that to acquire tokens.
const r = await oAuth2Client.getToken(code);
// Make sure to set the credentials on the OAuth2 client.
oAuth2Client.setCredentials(r.tokens);
auth = oAuth2Client;
console.info("Tokens acquired.");
resolve(oAuth2Client);
}
} catch (e) {
reject(e);
}
})
.listen(3003, () => {
// open the browser to the authorize url to start the workflow
open(authorizeUrl, { wait: false }).then((cp) => cp.unref());
console.log(
"Server started for auth flow to complete: " + authorizeUrl
);
});
// destroyer(server);
});
doAuth.then((auth) => {
const calendar = google.calendar({ version: "v3", auth: auth });
calendar.events.insert(
{
auth: auth,
calendarId: "primary",
resource: event,
},
function (err, event) {
if (err) {
console.log(
"There was an error contacting the Calendar service: " + err
);
return;
}
console.log("Event created: %s", event.htmlLink);
}
);
});
} catch (err) {
console.log(err);
}
};
SaveEventsInGoogleCalendar = async function SaveEventsInGoogleCalendar(events) {
// Load client secrets from a local file.
try {
const content = await fs.readFile(CREDENTIALS_PATH);
// Authorize a client with credentials, then call the Google Calendar API.
authorize(JSON.parse(content), createEvent);
} catch (err) {
console.log("Error loading client secret file:", err);
}
};
exports.GenerateICS = GenerateICS;
exports.createEvent = createEvent;
exports.SaveEventsInGoogleCalendar = SaveEventsInGoogleCalendar;
//createEvent();