Compare commits
2 commits
427423d3e8
...
5588c999a7
Author | SHA1 | Date | |
---|---|---|---|
5588c999a7 | |||
fd7e2377e1 |
7 changed files with 97 additions and 77 deletions
50
dist/GameSource.js
vendored
50
dist/GameSource.js
vendored
|
@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": 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 node_html_parser_1 = require("node-html-parser");
|
const node_html_parser_1 = require("node-html-parser");
|
||||||
const moment_1 = __importDefault(require("moment")); // require
|
const moment_1 = __importDefault(require("moment")); // require
|
||||||
|
@ -17,34 +17,62 @@ class GameSource {
|
||||||
const gameBoxs = parsedResult.querySelectorAll(".game-box");
|
const gameBoxs = parsedResult.querySelectorAll(".game-box");
|
||||||
const games = [];
|
const games = [];
|
||||||
for (let gameBox of gameBoxs) {
|
for (let gameBox of gameBoxs) {
|
||||||
const teamsPlaying = gameBox.querySelectorAll(".team-name").map((team) => team.text);
|
const teamsPlaying = gameBox
|
||||||
|
.querySelectorAll(".team-name")
|
||||||
|
.map((team) => team.text);
|
||||||
const regex = /[\r\n\s]+/g;
|
const regex = /[\r\n\s]+/g;
|
||||||
const gameHeader = gameBox.querySelector(".game-header").text.replace(regex, " ").trim();
|
const gameHeader = gameBox
|
||||||
|
.querySelector(".game-header")
|
||||||
|
.text.replace(regex, " ")
|
||||||
|
.trim();
|
||||||
const headerSplit = gameHeader.split(",");
|
const headerSplit = gameHeader.split(",");
|
||||||
// In data, if there is no time, it means it's the last game for the calender
|
// In data, if there is no time, it means it's the last game for the calender
|
||||||
const lastGameForCalender = headerSplit.length < 4;
|
const lastGameForCalender = headerSplit.length < 4;
|
||||||
if (lastGameForCalender)
|
if (lastGameForCalender)
|
||||||
break;
|
break;
|
||||||
const gameDate = headerSplit[2].trim();
|
const gameDate = this.findDate(headerSplit);
|
||||||
const gameTime = headerSplit[3].trim();
|
const gameTime = this.findTime(headerSplit);
|
||||||
const start = (0, moment_1.default)(gameDate + gameTime, "DD/MM/YYYYHH:mm").toISOString();
|
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();
|
const end = (0, moment_1.default)(gameDate + gameTime, "DD/MM/YYYYHH:mm")
|
||||||
|
.add(2, "hours")
|
||||||
|
.toISOString();
|
||||||
games.push({
|
games.push({
|
||||||
summary: 'Maccabi Haifa F.C.',
|
summary: "Maccabi Haifa F.C.",
|
||||||
location: headerSplit[4].trim(),
|
location: headerSplit[headerSplit.length - 1].trim(),
|
||||||
description: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
|
description: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
|
||||||
start: {
|
start: {
|
||||||
dateTime: start,
|
dateTime: start,
|
||||||
timeZone: 'Asia/Jerusalem'
|
timeZone: "Asia/Jerusalem",
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
dateTime: end,
|
dateTime: end,
|
||||||
timeZone: 'Asia/Jerusalem'
|
timeZone: "Asia/Jerusalem",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return games;
|
return games;
|
||||||
}
|
}
|
||||||
|
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) {
|
getOpponentIndexByStadium(stadium) {
|
||||||
if (stadium === "Sammy Ofer Stadium") {
|
if (stadium === "Sammy Ofer Stadium") {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
2
dist/index.js
vendored
2
dist/index.js
vendored
|
@ -28,6 +28,8 @@ class App {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("Event already exists");
|
console.log("Event already exists");
|
||||||
|
console.log("Event:");
|
||||||
|
console.log("Happening at:");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newGamesAdded.length > 0) {
|
if (newGamesAdded.length > 0) {
|
||||||
|
|
37
package-lock.json
generated
37
package-lock.json
generated
|
@ -6,12 +6,10 @@
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
"cron": "^2.3.0",
|
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"googleapis": "^122.0.0",
|
"googleapis": "^122.0.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"moment-timezone": "^0.5.43",
|
"moment-timezone": "^0.5.43",
|
||||||
"node-cron": "^3.0.2",
|
|
||||||
"node-html-parser": "^6.1.5",
|
"node-html-parser": "^6.1.5",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
|
@ -191,14 +189,6 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cron": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/cron/-/cron-2.3.0.tgz",
|
|
||||||
"integrity": "sha512-ZN5HP8zDY41sJolMsbc+GksRATcbvkPKF5wR/qc8FrV4NBVi9ORQa1HmYa5GydaysUB80X9XpRlRkooa5uEtTA==",
|
|
||||||
"dependencies": {
|
|
||||||
"luxon": "^3.2.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/css-select": {
|
"node_modules/css-select": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||||
|
@ -578,14 +568,6 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/luxon": {
|
|
||||||
"version": "3.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz",
|
|
||||||
"integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mime-db": {
|
"node_modules/mime-db": {
|
||||||
"version": "1.52.0",
|
"version": "1.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
@ -629,25 +611,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
"node_modules/node-cron": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.2.tgz",
|
|
||||||
"integrity": "sha512-iP8l0yGlNpE0e6q1o185yOApANRe47UPbLf4YxfbiNHt/RU5eBcGB/e0oudruheSf+LQeDMezqC5BVAb5wwRcQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"uuid": "8.3.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/node-cron/node_modules/uuid": {
|
|
||||||
"version": "8.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
|
||||||
"bin": {
|
|
||||||
"uuid": "dist/bin/uuid"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.6.12",
|
"version": "2.6.12",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
"cron": "^2.3.0",
|
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"googleapis": "^122.0.0",
|
"googleapis": "^122.0.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"moment-timezone": "^0.5.43",
|
"moment-timezone": "^0.5.43",
|
||||||
"node-cron": "^3.0.2",
|
|
||||||
"node-html-parser": "^6.1.5",
|
"node-html-parser": "^6.1.5",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,57 +1,87 @@
|
||||||
require('dotenv').config();
|
require("dotenv").config();
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { GoogleCalendarEvent } from "./types";
|
import { GoogleCalendarEvent } from "./types";
|
||||||
import { parse } from 'node-html-parser';
|
import { parse } from "node-html-parser";
|
||||||
import moment from 'moment'; // require
|
import moment from "moment"; // require
|
||||||
|
|
||||||
// This calss will be the game source.
|
// This calss will be the game source.
|
||||||
// search for upcomming games
|
// search for upcomming games
|
||||||
|
|
||||||
export default class GameSource {
|
export default class GameSource {
|
||||||
|
|
||||||
async getGamesFromHaifa(): Promise<GoogleCalendarEvent[]> {
|
async getGamesFromHaifa(): Promise<GoogleCalendarEvent[]> {
|
||||||
const sourceUrl = `https://mhaifafc.com/games?lang=en`;
|
const sourceUrl = `https://mhaifafc.com/games?lang=en`;
|
||||||
const result = await axios.get(sourceUrl);
|
const result = await axios.get(sourceUrl);
|
||||||
const parsedResult = parse(result.data.toString())
|
const parsedResult = parse(result.data.toString());
|
||||||
const gameBoxs = parsedResult.querySelectorAll(".game-box");
|
const gameBoxs = parsedResult.querySelectorAll(".game-box");
|
||||||
|
|
||||||
const games: GoogleCalendarEvent[] = [];
|
const games: GoogleCalendarEvent[] = [];
|
||||||
|
|
||||||
for (let gameBox of gameBoxs) {
|
for (let gameBox of gameBoxs) {
|
||||||
|
const teamsPlaying = gameBox
|
||||||
const teamsPlaying = gameBox.querySelectorAll(".team-name").map((team: any) => team.text);
|
.querySelectorAll(".team-name")
|
||||||
|
.map((team: any) => team.text);
|
||||||
const regex = /[\r\n\s]+/g;
|
const regex = /[\r\n\s]+/g;
|
||||||
const gameHeader = gameBox.querySelector(".game-header").text.replace(regex, " ").trim();
|
const gameHeader = gameBox
|
||||||
|
.querySelector(".game-header")
|
||||||
|
.text.replace(regex, " ")
|
||||||
|
.trim();
|
||||||
const headerSplit = gameHeader.split(",");
|
const headerSplit = gameHeader.split(",");
|
||||||
|
|
||||||
// In data, if there is no time, it means it's the last game for the calender
|
// In data, if there is no time, it means it's the last game for the calender
|
||||||
const lastGameForCalender = headerSplit.length < 4;
|
const lastGameForCalender = headerSplit.length < 4;
|
||||||
|
|
||||||
if (lastGameForCalender) break;
|
if (lastGameForCalender) break;
|
||||||
|
|
||||||
const gameDate = headerSplit[2].trim();
|
|
||||||
const gameTime = headerSplit[3].trim();
|
|
||||||
|
|
||||||
const start = moment(gameDate + gameTime, "DD/MM/YYYYHH:mm").toISOString();
|
|
||||||
const end = moment(gameDate + gameTime, "DD/MM/YYYYHH:mm").add(2, "hours").toISOString();
|
|
||||||
|
|
||||||
|
const gameDate = this.findDate(headerSplit);
|
||||||
|
const gameTime = this.findTime(headerSplit);
|
||||||
|
|
||||||
|
const start = moment(
|
||||||
games.push({
|
gameDate + gameTime,
|
||||||
summary: 'Maccabi Haifa F.C.',
|
"DD/MM/YYYYHH:mm"
|
||||||
location: headerSplit[4].trim(),
|
).toISOString();
|
||||||
|
const end = moment(gameDate + gameTime, "DD/MM/YYYYHH:mm")
|
||||||
|
.add(2, "hours")
|
||||||
|
.toISOString();
|
||||||
|
|
||||||
|
games.push({
|
||||||
|
summary: "Maccabi Haifa F.C.",
|
||||||
|
location: headerSplit[headerSplit.length - 1].trim(),
|
||||||
description: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
|
description: `${teamsPlaying[0]} vs. ${teamsPlaying[1]}`,
|
||||||
start: {
|
start: {
|
||||||
dateTime: start,
|
dateTime: start,
|
||||||
timeZone: 'Asia/Jerusalem'
|
timeZone: "Asia/Jerusalem",
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
dateTime: end,
|
dateTime: end,
|
||||||
timeZone: 'Asia/Jerusalem'
|
timeZone: "Asia/Jerusalem",
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
return games;
|
return games;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
getOpponentIndexByStadium(stadium: string) {
|
||||||
if (stadium === "Sammy Ofer Stadium") {
|
if (stadium === "Sammy Ofer Stadium") {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -59,4 +89,4 @@ export default class GameSource {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import GameSource from "./GameSource";
|
import GameSource from "./GameSource";
|
||||||
import GoogleCalendar from "./GoogleCalendar";
|
import GoogleCalendar from "./GoogleCalendar";
|
||||||
import env from "dotenv";
|
import env from "dotenv";
|
||||||
import cron from "node-cron";
|
|
||||||
|
|
||||||
env.config();
|
env.config();
|
||||||
|
|
||||||
|
@ -19,7 +18,6 @@ class App {
|
||||||
console.log("START CRON JOB");
|
console.log("START CRON JOB");
|
||||||
const newGamesAdded = [];
|
const newGamesAdded = [];
|
||||||
await this.googleCalendar.init();
|
await this.googleCalendar.init();
|
||||||
|
|
||||||
// Schedule the job to run daily at a specific time (e.g., 1:00 AM)
|
// Schedule the job to run daily at a specific time (e.g., 1:00 AM)
|
||||||
try {
|
try {
|
||||||
const games = await app.gameSource.getGamesFromHaifa();
|
const games = await app.gameSource.getGamesFromHaifa();
|
||||||
|
|
3
start.sh
3
start.sh
|
@ -1,2 +1,3 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
docker run -p 3000:3000 -d --restart=unless-stopped --name haifareminder docker.io/kfda89/haifareminder
|
docker run -p 3000:3000 -d --restart=unless-stopped --name haifareminder docker.io/kfda89/haifareminder
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue