Files
Taekwondo-Admin/packages/api/src/services/foundEvents/foundEventsService.ts
T
2026-03-16 00:46:30 +01:00

106 lines
3.7 KiB
TypeScript

import { PlaywrightCrawler } from "crawlee";
import * as dateFns from "date-fns";
import type { Request } from "express";
import type { FoundEventDto } from "../../dtos/foundEvents.js";
import { inject } from "../../infrastructure/di/index.js";
import { Injectable } from "../../infrastructure/di/injectable-decorator.js";
import { DatabaseService } from "../db/prisma.js";
import { EnvironmentService } from "../environmentService.js";
import { parseTUS, parseTUSDetail } from "./parseTUS.js";
import { FoundEventSource } from "./sources.js";
@Injectable()
export class FoundEventsService {
private readonly environmnent = inject(EnvironmentService);
private readonly database = inject(DatabaseService);
private readonly crawler: PlaywrightCrawler;
public constructor() {
const top = this;
this.crawler = new PlaywrightCrawler({
maxRequestsPerMinute: 100,
maxConcurrency: 2,
requestHandler: async ({ request, page, log }) => {
// if (request.retryCount > 0) return;
const label = request.label;
switch (label) {
case "TUS":
const tusDetails = await parseTUS(page, top.database);
await top.crawler.addRequests(
tusDetails.map(url => ({
url: url,
label: "TUS_DETAIL",
})),
);
break;
case "TUS_DETAIL":
await parseTUSDetail(
request.loadedUrl,
page,
top.database,
);
break;
// case "DTU":
// events = parseDTU(page);
// break;
// case "BTU":
// events = parseBTU(page);
// break;
// case "MAGOSCH":
// events = parseMAGOSCH(page);
// break;
default:
log.warning(`Unknown source ${label}`);
}
},
headless: !this.environmnent.isDev(),
});
}
public async crawl() {
const sources = Object.entries(FoundEventSource).map(([key, url]) => ({
url,
label: key,
}));
return await this.crawler.run(sources);
}
public async getFutureEvents(request: Request): Promise<FoundEventDto[]> {
const allEvents = await this.database.doRequest(
async prisma =>
prisma.foundEvents.findMany({
include: {
attachedFiles: true,
},
}),
request,
);
const today = new Date(Date.now());
return allEvents.filter(event => {
const parts = event.eventDate?.split("-");
let date: Date | null = null;
if (!parts) {
return true;
}
if (parts.length == 1) {
// like '10.05.2012'
date = dateFns.parse(parts[0]!, "dd.MM.yyyy", new Date());
}
if (parts.length == 2) {
// like '12.-25.04.2026'
date = dateFns.parse(parts[1]!, "dd.MM.yyyy", new Date());
}
if (!date) {
console.warn("Unknown Date Format", event.eventDate);
return true;
}
return isNaN(date.valueOf()) || date >= today;
});
}
}