Compare commits

..

No commits in common. "3d8306b225f10ee08b9ecf41a68f46afe0092dc6" and "15932a0c9d919228f66d80c08f3796bd67452d57" have entirely different histories.

4 changed files with 187 additions and 167 deletions

146
dist/GameSource.js vendored
View file

@ -5,90 +5,100 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
require("dotenv").config(); require("dotenv").config();
const axios_1 = __importDefault(require("axios")); const axios_1 = __importDefault(require("axios"));
const moment_1 = __importDefault(require("moment")); 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 { class GameSource {
async getGamesFromHaifa(logger) { async getGamesFromHaifa() {
console.log("Trying to get games from Haifa..."); const sourceUrl = `https://mhaifafc.com/games?lang=en`;
console.log('Trying to get games from Haifa...');
try { try {
// Get the current date and time in the required format const result = await axios_1.default.get(sourceUrl, {
const currentDate = (0, moment_1.default)().format("DD/MM/YYYY HH:mm"); headers: {
// Construct the filters object with the current date 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
const filters = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
date: { 'Accept-Language': 'en-US,en;q=0.9',
startDate: currentDate, 'Accept-Encoding': 'gzip, deflate, br',
endDate: "", 'DNT': '1',
}, 'Connection': 'keep-alive',
league: "", 'Upgrade-Insecure-Requests': '1',
session: "",
gamesDirection: "1",
};
// Encode the filters for the URL
const filtersParam = encodeURIComponent(JSON.stringify(filters));
// Construct the API URL with the encoded filters
const sourceUrl = `https://api.mhaifafc.com/api/content/games-lobby?filters=${filtersParam}&start=0&limit=20&sortDirection=ASC&app=web&lang=he`;
// Get the authorization token from environment variables
const authorizationToken = process.env.HAIFA_API_AUTH_TOKEN;
// Set up the request headers
const headers = {
Accept: "*/*",
"Accept-Language": "en-US,en;q=0.7",
Authorization: `Bearer ${authorizationToken}`,
"User-Agent": "Mozilla/5.0",
Origin: "https://www.mhaifafc.com",
Referer: "https://www.mhaifafc.com/",
};
// Make the API request
const response = await axios_1.default.get(sourceUrl, {
headers,
responseType: "json",
responseEncoding: "utf8", // Ensure UTF-8 encoding
});
// Extract the games data from the response
const gamesData = response.data.games.items;
const games = [];
// Loop through each game and construct the GoogleCalendarEvent objects
for (const game of gamesData) {
const gameDetails = game.gameDetails;
const gameTime = gameDetails.gameTime; // ISO string
const isFinalGameDate = gameDetails.isFinalGameDate;
const gameLocation = gameDetails.gameLocation;
// Skip games without a game time
if (!gameTime)
continue;
const hostTeam = game.hostTeam;
const guestTeam = game.guestTeam;
// Get team names
const hostTeamName = hostTeam.teamName;
const guestTeamName = guestTeam.teamName;
const summary = `${hostTeamName} vs. ${guestTeamName}`;
// Include a note if the game date is not final
let description = `${hostTeamName} vs. ${guestTeamName}`;
if (!isFinalGameDate) {
description += " (Date and time are subject to change)";
} }
// Calculate start and end times });
const startDateTime = (0, moment_1.default)(gameTime).toISOString(); const parsedResult = (0, node_html_parser_1.parse)(result.data.toString());
const endDateTime = (0, moment_1.default)(gameTime).add(2, "hours").toISOString(); const gameBoxs = parsedResult.querySelectorAll(".game-box");
// Add the event to the games array 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;
const location = headerSplit[headerSplit.length - 1].trim();
if (location === 'נדחה')
continue;
if (lastGameForCalender)
break;
const gameDate = this.findDate(headerSplit);
const gameTime = this.findTime(headerSplit);
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({ games.push({
summary: summary, summary: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
location: gameLocation, location: headerSplit[headerSplit.length - 1].trim(),
description: description, description: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
start: { start: {
dateTime: startDateTime, dateTime: start,
timeZone: "Asia/Jerusalem", timeZone: "Asia/Jerusalem",
}, },
end: { end: {
dateTime: endDateTime, dateTime: end,
timeZone: "Asia/Jerusalem", timeZone: "Asia/Jerusalem",
}, },
}); });
} }
// return [];
return games; return games;
} }
catch (error) { catch (error) {
console.error(error); console.error(error);
return []; }
}
findTime(headerSplit) {
let time = '';
headerSplit.forEach((item) => {
if (/\d{2}:\d{2}/.test(item)) {
time = item;
return;
}
});
return time.trim();
}
findDate(headerSplit) {
// if it's a date format, return it like: 19/08/2023
let date = '';
headerSplit.forEach((item) => {
if (/\d{2}\/\d{2}\/\d{4}/.test(item)) {
date = item;
return;
}
});
return date.trim();
}
getOpponentIndexByStadium(stadium) {
if (stadium === "Sammy Ofer Stadium") {
return 1;
}
else {
return 0;
} }
} }
} }

5
dist/index.js vendored
View file

@ -15,11 +15,12 @@ class App {
this.googleCalendar = new GoogleCalendar_1.default(); this.googleCalendar = new GoogleCalendar_1.default();
} }
async startCronJob() { async startCronJob() {
this.writeLog('START Haifa Reminder'); // Log when the cron job starts this.writeLog('START CRON JOB'); // Log when the cron job starts
console.log("START Haifa Reminder");
const newGamesAdded = []; const newGamesAdded = [];
await this.googleCalendar.init(); await this.googleCalendar.init();
try { try {
const games = await this.gameSource.getGamesFromHaifa(this.writeLog); const games = await this.gameSource.getGamesFromHaifa();
for (const game of games) { for (const game of games) {
const isDuplicateEvent = await this.googleCalendar.isDuplicateEvent(game.start.dateTime, game.end.dateTime, game.summary); const isDuplicateEvent = await this.googleCalendar.isDuplicateEvent(game.start.dateTime, game.end.dateTime, game.summary);
console.log(game); console.log(game);

View file

@ -1,106 +1,113 @@
require("dotenv").config(); require("dotenv").config();
import axios from "axios"; import axios from "axios";
import { GoogleCalendarEvent } from "./types"; import { GoogleCalendarEvent } from "./types";
import moment from "moment"; import { parse } from "node-html-parser";
import moment from "moment"; // require
// This calss will be the game source.
// search for upcomming games
export default class GameSource { export default class GameSource {
async getGamesFromHaifa(logger: Function): Promise<GoogleCalendarEvent[]> { async getGamesFromHaifa(): Promise<GoogleCalendarEvent[]> {
console.log("Trying to get games from Haifa..."); const sourceUrl = `https://mhaifafc.com/games?lang=en`;
console.log('Trying to get games from Haifa...');
try { try {
// Get the current date and time in the required format const result = await axios.get(sourceUrl,
const currentDate = moment().format("DD/MM/YYYY HH:mm"); {
headers: {
// Construct the filters object with the current date 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
const filters = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
date: { 'Accept-Language': 'en-US,en;q=0.9',
startDate: currentDate, 'Accept-Encoding': 'gzip, deflate, br',
endDate: "", 'DNT': '1',
}, 'Connection': 'keep-alive',
league: "", 'Upgrade-Insecure-Requests': '1',
session: "", }
gamesDirection: "1",
};
// Encode the filters for the URL
const filtersParam = encodeURIComponent(JSON.stringify(filters));
// Construct the API URL with the encoded filters
const sourceUrl = `https://api.mhaifafc.com/api/content/games-lobby?filters=${filtersParam}&start=0&limit=20&sortDirection=ASC&app=web&lang=he`;
// Get the authorization token from environment variables
const authorizationToken = process.env.HAIFA_API_AUTH_TOKEN;
// Set up the request headers
const headers = {
Accept: "*/*",
"Accept-Language": "en-US,en;q=0.7",
Authorization: `Bearer ${authorizationToken}`,
"User-Agent": "Mozilla/5.0",
Origin: "https://www.mhaifafc.com",
Referer: "https://www.mhaifafc.com/",
};
// Make the API request
const response = await axios.get(sourceUrl, {
headers,
responseType: "json", // Ensure the response is parsed as JSON
responseEncoding: "utf8", // Ensure UTF-8 encoding
}); });
// Extract the games data from the response const parsedResult = parse(result.data.toString());
const gamesData = response.data.games.items; const gameBoxs = parsedResult.querySelectorAll(".game-box");
const games: GoogleCalendarEvent[] = []; const games: GoogleCalendarEvent[] = [];
// Loop through each game and construct the GoogleCalendarEvent objects for (let gameBox of gameBoxs) {
for (const game of gamesData) { const teamsPlaying = gameBox
const gameDetails = game.gameDetails; .querySelectorAll(".team-name")
const gameTime = gameDetails.gameTime; // ISO string .map((team: any) => team.text);
const isFinalGameDate = gameDetails.isFinalGameDate; const regex = /[\r\n\s]+/g;
const gameLocation = gameDetails.gameLocation; const gameHeader = gameBox
.querySelector(".game-header")
.text.replace(regex, " ")
.trim();
const headerSplit = gameHeader.split(",");
// Skip games without a game time // In data, if there is no time, it means it's the last game for the calender
if (!gameTime) continue; const lastGameForCalender = headerSplit.length < 4;
const location = headerSplit[headerSplit.length - 1].trim();
const hostTeam = game.hostTeam; if (location === 'נדחה') continue;
const guestTeam = game.guestTeam; if (lastGameForCalender) break;
// Get team names const gameDate = this.findDate(headerSplit);
const hostTeamName = hostTeam.teamName; const gameTime = this.findTime(headerSplit);
const guestTeamName = guestTeam.teamName;
const summary = `${hostTeamName} vs. ${guestTeamName}`; const start = moment(
gameDate + gameTime,
"DD/MM/YYYYHH:mm"
).toISOString();
const end = moment(gameDate + gameTime, "DD/MM/YYYYHH:mm")
.add(2, "hours")
.toISOString();
// Include a note if the game date is not final
let description = `${hostTeamName} vs. ${guestTeamName}`;
if (!isFinalGameDate) {
description += " (Date and time are subject to change)";
}
// Calculate start and end times
const startDateTime = moment(gameTime).toISOString();
const endDateTime = moment(gameTime).add(2, "hours").toISOString();
// Add the event to the games array
games.push({ games.push({
summary: summary, summary: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
location: gameLocation, location: headerSplit[headerSplit.length - 1].trim(),
description: description, description: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
start: { start: {
dateTime: startDateTime, dateTime: start,
timeZone: "Asia/Jerusalem", timeZone: "Asia/Jerusalem",
}, },
end: { end: {
dateTime: endDateTime, dateTime: end,
timeZone: "Asia/Jerusalem", timeZone: "Asia/Jerusalem",
}, },
}); });
} }
// return [];
return games; return games;
} catch (error) { }
catch (error) {
console.error(error); console.error(error);
return []; }
}
private findTime(headerSplit: string[]) {
let time = '';
headerSplit.forEach((item) => {
if (/\d{2}:\d{2}/.test(item)) {
time = item;
return
}
});
return time.trim();
}
private findDate(headerSplit: string[]) {
// if it's a date format, return it like: 19/08/2023
let date = '';
headerSplit.forEach((item) => {
if(/\d{2}\/\d{2}\/\d{4}/.test(item)) {
date = item;
return;
}
})
return date.trim();
}
getOpponentIndexByStadium(stadium: string) {
if (stadium === "Sammy Ofer Stadium") {
return 1;
} else {
return 0;
} }
} }
} }

View file

@ -17,11 +17,13 @@ class App {
} }
async startCronJob() { async startCronJob() {
this.writeLog('START Haifa Reminder'); // Log when the cron job starts this.writeLog('START CRON JOB'); // Log when the cron job starts
console.log("START Haifa Reminder");
const newGamesAdded = []; const newGamesAdded = [];
await this.googleCalendar.init(); await this.googleCalendar.init();
try { try {
const games = await this.gameSource.getGamesFromHaifa(this.writeLog); const games = await this.gameSource.getGamesFromHaifa();
for (const game of games) { for (const game of games) {
const isDuplicateEvent = await this.googleCalendar.isDuplicateEvent( const isDuplicateEvent = await this.googleCalendar.isDuplicateEvent(
game.start.dateTime, game.start.dateTime,