adding node_modules + dist
This commit is contained in:
parent
7675d627d8
commit
bbf1865f1a
6 changed files with 257 additions and 2 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#javascript build files #
|
#javascript build files #
|
||||||
public/**/*
|
public/**/*
|
||||||
dist/**/*
|
|
||||||
|
|
||||||
# Tmp files #
|
# Tmp files #
|
||||||
tmp
|
tmp
|
||||||
|
@ -11,7 +10,6 @@ tmp
|
||||||
|
|
||||||
## ENV Vars ##
|
## ENV Vars ##
|
||||||
.env
|
.env
|
||||||
config/client_google_auth.json
|
|
||||||
|
|
||||||
## Docker ##
|
## Docker ##
|
||||||
build_image.sh
|
build_image.sh
|
||||||
|
|
57
dist/GameSource.js
vendored
Normal file
57
dist/GameSource.js
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
require('dotenv').config();
|
||||||
|
const axios_1 = __importDefault(require("axios"));
|
||||||
|
const node_html_parser_1 = require("node-html-parser");
|
||||||
|
const moment_1 = __importDefault(require("moment")); // require
|
||||||
|
// This calss will be the game source.
|
||||||
|
// search for upcomming games
|
||||||
|
class GameSource {
|
||||||
|
async getGamesFromHaifa() {
|
||||||
|
const sourceUrl = `https://mhaifafc.com/games?lang=en`;
|
||||||
|
const result = await axios_1.default.get(sourceUrl);
|
||||||
|
const parsedResult = (0, node_html_parser_1.parse)(result.data.toString());
|
||||||
|
const gameBoxs = parsedResult.querySelectorAll(".game-box");
|
||||||
|
const games = [];
|
||||||
|
for (let gameBox of gameBoxs) {
|
||||||
|
const teamsPlaying = gameBox.querySelectorAll(".team-name").map((team) => team.text);
|
||||||
|
const regex = /[\r\n\s]+/g;
|
||||||
|
const gameHeader = gameBox.querySelector(".game-header").text.replace(regex, " ").trim();
|
||||||
|
const headerSplit = gameHeader.split(",");
|
||||||
|
// In data, if there is no time, it means it's the last game for the calender
|
||||||
|
const lastGameForCalender = headerSplit.length < 4;
|
||||||
|
if (lastGameForCalender)
|
||||||
|
break;
|
||||||
|
const gameDate = headerSplit[2].trim();
|
||||||
|
const gameTime = headerSplit[3].trim();
|
||||||
|
const start = (0, moment_1.default)(gameDate + gameTime, "DD/MM/YYYYHH:mm").toISOString();
|
||||||
|
const end = (0, moment_1.default)(gameDate + gameTime, "DD/MM/YYYYHH:mm").add(2, "hours").toISOString();
|
||||||
|
games.push({
|
||||||
|
summary: 'Maccabi Haifa F.C.',
|
||||||
|
location: "Ofir's stadium",
|
||||||
|
description: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
|
||||||
|
start: {
|
||||||
|
dateTime: start,
|
||||||
|
timeZone: 'Asia/Jerusalem'
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
dateTime: end,
|
||||||
|
timeZone: 'Asia/Jerusalem'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return games;
|
||||||
|
}
|
||||||
|
getOpponentIndexByStadium(stadium) {
|
||||||
|
if (stadium === "Sammy Ofer Stadium") {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = GameSource;
|
87
dist/GoogleCalendar.js
vendored
Normal file
87
dist/GoogleCalendar.js
vendored
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const google_auth_library_1 = require("google-auth-library");
|
||||||
|
const googleapis_1 = require("googleapis");
|
||||||
|
require('dotenv').config();
|
||||||
|
const env = process.env;
|
||||||
|
class GoogleCalendar {
|
||||||
|
constructor() {
|
||||||
|
this.gamesMap = {};
|
||||||
|
this.clientSecret = env.GOOGLE_CLIENT_SECRET;
|
||||||
|
this.clientId = env.GOOGLE_CLIENT_ID;
|
||||||
|
this.calenderId = env.GOOGLE_CALENDAR_ID;
|
||||||
|
this.clientEmail = env.GOOGLE_CLIENT_EMAIL;
|
||||||
|
this.googlePrivateKey = env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n');
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
console.log("INIT GOOGLE CALENDAR");
|
||||||
|
const jwtClient = await this.authorize();
|
||||||
|
this.calendar = googleapis_1.google.calendar({ version: 'v3', auth: jwtClient });
|
||||||
|
}
|
||||||
|
async authorize() {
|
||||||
|
console.log("AUTHORIZE GOOGLE CALENDAR");
|
||||||
|
this.JWT_client = new google_auth_library_1.JWT({
|
||||||
|
email: this.clientEmail,
|
||||||
|
key: this.googlePrivateKey,
|
||||||
|
scopes: [
|
||||||
|
'https://www.googleapis.com/auth/calendar',
|
||||||
|
'https://www.googleapis.com/auth/calendar.events'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
const { access_token } = await this.JWT_client.authorize();
|
||||||
|
this.token = access_token;
|
||||||
|
if (!this.token) {
|
||||||
|
throw new Error('Failed to connect to google calendar');
|
||||||
|
}
|
||||||
|
console.log("GOOGLE CALENDAR AUTHORIZED SUCCESSFULLY");
|
||||||
|
return this.JWT_client;
|
||||||
|
}
|
||||||
|
async updateNewEvent(upcomingEvents) {
|
||||||
|
// console.log(upcomingEvents)
|
||||||
|
setTimeout(async () => {
|
||||||
|
upcomingEvents.forEach(async (event) => {
|
||||||
|
console.log("UPDATE NEW EVENT", upcomingEvents);
|
||||||
|
const options = {
|
||||||
|
auth: this.JWT_client,
|
||||||
|
calendarId: this.calenderId,
|
||||||
|
resource: {
|
||||||
|
summary: event.summary,
|
||||||
|
location: event.location,
|
||||||
|
description: event.description,
|
||||||
|
start: { dateTime: event.start.dateTime, timeZone: 'Asia/Jerusalem' },
|
||||||
|
end: { dateTime: event.end.dateTime, timeZone: 'Asia/Jerusalem' }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
await this.calendar.events.insert(options, function (err, event) {
|
||||||
|
if (err) {
|
||||||
|
console.log('There was an error contacting the Calendar service: ' + err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(event.description + ' created');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
async isDuplicateEvent(startTime, endTime, title) {
|
||||||
|
if (this.gamesMap[startTime]) {
|
||||||
|
console.log("duplicate event");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.gamesMap[startTime] = true;
|
||||||
|
console.log("checking for duplicate event");
|
||||||
|
try {
|
||||||
|
const response = await this.calendar.events.list({
|
||||||
|
calendarId: this.calenderId,
|
||||||
|
timeMin: startTime,
|
||||||
|
timeMax: endTime,
|
||||||
|
q: title, // Search for events with the same title
|
||||||
|
});
|
||||||
|
return response.data.items.length > 0;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = GoogleCalendar;
|
69
dist/Ics.js
vendored
Normal file
69
dist/Ics.js
vendored
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
"use strict";
|
||||||
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||||
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||||
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||||
|
}
|
||||||
|
Object.defineProperty(o, k2, desc);
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
|
o[k2] = m[k];
|
||||||
|
}));
|
||||||
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
|
}) : function(o, v) {
|
||||||
|
o["default"] = v;
|
||||||
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
|
__setModuleDefault(result, mod);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const ics = __importStar(require("ics"));
|
||||||
|
const uuid = require('uuid').v4();
|
||||||
|
class Ics {
|
||||||
|
constructor() {
|
||||||
|
this.generateIcsOutputFromGames = (games) => {
|
||||||
|
let output = [];
|
||||||
|
games.forEach((game) => {
|
||||||
|
output.push(this.generateIcsOutputFromGame(game));
|
||||||
|
});
|
||||||
|
console.log(output);
|
||||||
|
const { error, value } = ics.createEvents(output);
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
this.generateIcsOutputFromGame = (game) => {
|
||||||
|
const { summary, location, description, start, end } = game;
|
||||||
|
const icsEvent = {
|
||||||
|
title: description,
|
||||||
|
description,
|
||||||
|
location,
|
||||||
|
start: [start.dateTime[0], start.dateTime[1], start.dateTime[2], start.dateTime[3], start.dateTime[4]],
|
||||||
|
end: [end.dateTime[0], end.dateTime[1], end.dateTime[2], end.dateTime[3], end.dateTime[4]],
|
||||||
|
status: 'CONFIRMED',
|
||||||
|
busyStatus: "BUSY",
|
||||||
|
productId: '-//kfir.dayanhub.com',
|
||||||
|
recurrenceRule: '',
|
||||||
|
attendees: [],
|
||||||
|
alarms: [],
|
||||||
|
categories: [],
|
||||||
|
organizer: { name: 'Maccabi Haifa F.C.', email: '' },
|
||||||
|
};
|
||||||
|
return icsEvent;
|
||||||
|
};
|
||||||
|
this.convertIcsToIcal = (icsEvents) => {
|
||||||
|
const icalEvents = icsEvents.replace(/BEGIN:VEVENT/g, 'BEGIN:VEVENT\r\nUID:' + uuid);
|
||||||
|
return icalEvents;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = Ics;
|
42
dist/index.js
vendored
Normal file
42
dist/index.js
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const GameSource_1 = __importDefault(require("./GameSource"));
|
||||||
|
const GoogleCalendar_1 = __importDefault(require("./GoogleCalendar"));
|
||||||
|
const dotenv_1 = __importDefault(require("dotenv"));
|
||||||
|
const node_cron_1 = __importDefault(require("node-cron"));
|
||||||
|
dotenv_1.default.config();
|
||||||
|
class App {
|
||||||
|
constructor() {
|
||||||
|
this.gameSource = new GameSource_1.default();
|
||||||
|
this.googleCalendar = new GoogleCalendar_1.default();
|
||||||
|
}
|
||||||
|
async startCronJob() {
|
||||||
|
console.log("START CRON JOB");
|
||||||
|
await this.googleCalendar.init();
|
||||||
|
// Schedule the job to run daily at a specific time (e.g., 1:00 AM)
|
||||||
|
node_cron_1.default.schedule("* * * * *", async () => {
|
||||||
|
try {
|
||||||
|
const games = await app.gameSource.getGamesFromHaifa();
|
||||||
|
for (const game of games) {
|
||||||
|
const isDuplicateEvent = await this.googleCalendar.isDuplicateEvent(game.start.dateTime, game.end.dateTime, game.summary);
|
||||||
|
if (!isDuplicateEvent) {
|
||||||
|
console.log("Event does not exist");
|
||||||
|
await this.googleCalendar.updateNewEvent([game]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Event already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error("Error in cron job:", error.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const app = new App();
|
||||||
|
app.startCronJob();
|
||||||
|
// app.startWebServer();
|
2
dist/types/index.js
vendored
Normal file
2
dist/types/index.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
Loading…
Reference in a new issue