diff --git a/.gitignore b/.gitignore index c6a732b..e520303 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,8 @@ node_modules #javascript build files # -public/**/* -dist/**/* +# public/**/* +# dist/**/* # Tmp files # tmp diff --git a/dist/GameSource.js b/dist/GameSource.js new file mode 100644 index 0000000..18fc61e --- /dev/null +++ b/dist/GameSource.js @@ -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: headerSplit[4].trim(), + 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; diff --git a/dist/GoogleCalendar.js b/dist/GoogleCalendar.js new file mode 100644 index 0000000..6af9997 --- /dev/null +++ b/dist/GoogleCalendar.js @@ -0,0 +1,88 @@ +"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"], + }); + 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" }, + sendNotifications: true, + }, + }; + 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; diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..840538f --- /dev/null +++ b/dist/index.js @@ -0,0 +1,49 @@ +"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")); +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"); + const newGamesAdded = []; + await this.googleCalendar.init(); + // Schedule the job to run daily at a specific time (e.g., 1:00 AM) + 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) { + newGamesAdded.push(game); + console.log("Event does not exist"); + await this.googleCalendar.updateNewEvent([game]); + } + else { + console.log("Event already exists"); + } + } + if (newGamesAdded.length > 0) { + console.log("New games added:", newGamesAdded); + } + else { + console.log("No new games added"); + } + } + catch (error) { + console.error("Error in cron job:", error.message); + } + } +} +const app = new App(); +app.startCronJob().catch((error) => { + console.error("Error in app:", error.message); +}); +// app.startWebServer(); diff --git a/dist/types/index.js b/dist/types/index.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/dist/types/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true });