pre-main
This commit is contained in:
@@ -5,107 +5,114 @@ import { ScraperService, ScrapedGame } from '../scraper/scraper.service';
|
||||
|
||||
@Injectable()
|
||||
export class SyncService {
|
||||
private readonly logger = new Logger(SyncService.name);
|
||||
private readonly logger = new Logger(SyncService.name);
|
||||
|
||||
// Define target URLs - could be moved to Config/DB
|
||||
private readonly TARGET_URLS = [
|
||||
'https://insider-gaming.com/calendar/',
|
||||
// Add other URLs here as needed
|
||||
];
|
||||
// Define target URLs - could be moved to Config/DB
|
||||
private readonly TARGET_URLS = [
|
||||
'https://insider-gaming.com/calendar/',
|
||||
// Add other URLs here as needed
|
||||
];
|
||||
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly scraper: ScraperService,
|
||||
) { }
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly scraper: ScraperService,
|
||||
) {}
|
||||
|
||||
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)
|
||||
async handleDailySync() {
|
||||
this.logger.log('Starting daily game synchronization job...');
|
||||
for (const url of this.TARGET_URLS) {
|
||||
await this.syncUrl(url);
|
||||
}
|
||||
this.logger.log('Daily game synchronization job completed.');
|
||||
@Cron(CronExpression.EVERY_HOUR)
|
||||
async handleDailySync() {
|
||||
this.logger.log('Starting daily game synchronization job...');
|
||||
for (const url of this.TARGET_URLS) {
|
||||
await this.syncUrl(url);
|
||||
}
|
||||
this.logger.log('Daily game synchronization job completed.');
|
||||
}
|
||||
|
||||
async syncUrl(url: string) {
|
||||
try {
|
||||
const games = await this.scraper.scrapeUrl(url);
|
||||
this.logger.log(`Syncing ${games.length} games from ${url}`);
|
||||
|
||||
for (const gameData of games) {
|
||||
await this.upsertGame(gameData);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Failed to sync URL ${url}: ${error.message}`,
|
||||
error.stack,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async upsertGame(data: ScrapedGame) {
|
||||
const slug = this.generateSlug(data.title);
|
||||
const { releaseDate, isTBD, dateText } = this.parseDate(data.releaseDate);
|
||||
|
||||
try {
|
||||
// Simplistic Upsert
|
||||
await this.prisma.game.upsert({
|
||||
where: { slug: slug },
|
||||
update: {
|
||||
title: data.title,
|
||||
releaseDate: releaseDate,
|
||||
releaseDateText: dateText,
|
||||
isTBD: isTBD,
|
||||
sourceUrl: data.sourceUrl,
|
||||
// TODO: Handle platform mapping if needed
|
||||
},
|
||||
create: {
|
||||
title: data.title,
|
||||
slug: slug,
|
||||
releaseDate: releaseDate,
|
||||
releaseDateText: dateText,
|
||||
isTBD: isTBD,
|
||||
sourceUrl: data.sourceUrl,
|
||||
},
|
||||
});
|
||||
// this.logger.debug(`Upserted game: ${data.title}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Error saving game ${data.title}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private generateSlug(title: string): string {
|
||||
return title
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/(^-|-$)+/g, '');
|
||||
}
|
||||
|
||||
private parseDate(rawDate?: string): {
|
||||
releaseDate: Date | null;
|
||||
isTBD: boolean;
|
||||
dateText: string | null;
|
||||
} {
|
||||
if (!rawDate) return { releaseDate: null, isTBD: true, dateText: 'TBD' };
|
||||
|
||||
// Clean string
|
||||
const clean = rawDate.trim();
|
||||
let date: Date | null = null;
|
||||
let isTBD = false;
|
||||
|
||||
// Check for TBD/TBA
|
||||
if (clean.match(/tbd|tba|to be announced/i)) {
|
||||
isTBD = true;
|
||||
return { releaseDate: null, isTBD, dateText: clean };
|
||||
}
|
||||
|
||||
async syncUrl(url: string) {
|
||||
try {
|
||||
const games = await this.scraper.scrapeUrl(url);
|
||||
this.logger.log(`Syncing ${games.length} games from ${url}`);
|
||||
|
||||
for (const gameData of games) {
|
||||
await this.upsertGame(gameData);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(`Failed to sync URL ${url}: ${error.message}`, error.stack);
|
||||
}
|
||||
// Try parsing standard JS Date
|
||||
const parsed = new Date(clean);
|
||||
if (!isNaN(parsed.getTime())) {
|
||||
date = parsed;
|
||||
} else {
|
||||
// Check for Month Year (e.g. "October 2026") -> Default to 1st of month
|
||||
// Check for "Q3 2026"
|
||||
isTBD = true; // If we can't get a specific day, marked as TBD-ish or just keep dateText
|
||||
}
|
||||
|
||||
private async upsertGame(data: ScrapedGame) {
|
||||
const slug = this.generateSlug(data.title);
|
||||
const { releaseDate, isTBD, dateText } = this.parseDate(data.releaseDate);
|
||||
|
||||
try {
|
||||
// Simplistic Upsert
|
||||
await this.prisma.game.upsert({
|
||||
where: { slug: slug },
|
||||
update: {
|
||||
title: data.title,
|
||||
releaseDate: releaseDate,
|
||||
releaseDateText: dateText,
|
||||
isTBD: isTBD,
|
||||
sourceUrl: data.sourceUrl,
|
||||
// TODO: Handle platform mapping if needed
|
||||
},
|
||||
create: {
|
||||
title: data.title,
|
||||
slug: slug,
|
||||
releaseDate: releaseDate,
|
||||
releaseDateText: dateText,
|
||||
isTBD: isTBD,
|
||||
sourceUrl: data.sourceUrl,
|
||||
}
|
||||
});
|
||||
// this.logger.debug(`Upserted game: ${data.title}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Error saving game ${data.title}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private generateSlug(title: string): string {
|
||||
return title
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '-')
|
||||
.replace(/(^-|-$)+/g, '');
|
||||
}
|
||||
|
||||
private parseDate(rawDate?: string): { releaseDate: Date | null, isTBD: boolean, dateText: string | null } {
|
||||
if (!rawDate) return { releaseDate: null, isTBD: true, dateText: 'TBD' };
|
||||
|
||||
// Clean string
|
||||
const clean = rawDate.trim();
|
||||
let date: Date | null = null;
|
||||
let isTBD = false;
|
||||
|
||||
// Check for TBD/TBA
|
||||
if (clean.match(/tbd|tba|to be announced/i)) {
|
||||
isTBD = true;
|
||||
return { releaseDate: null, isTBD, dateText: clean };
|
||||
}
|
||||
|
||||
// Try parsing standard JS Date
|
||||
const parsed = new Date(clean);
|
||||
if (!isNaN(parsed.getTime())) {
|
||||
date = parsed;
|
||||
} else {
|
||||
// Check for Month Year (e.g. "October 2026") -> Default to 1st of month
|
||||
// Check for "Q3 2026"
|
||||
isTBD = true; // If we can't get a specific day, marked as TBD-ish or just keep dateText
|
||||
}
|
||||
|
||||
return {
|
||||
releaseDate: date,
|
||||
isTBD: date === null,
|
||||
dateText: clean
|
||||
};
|
||||
}
|
||||
return {
|
||||
releaseDate: date,
|
||||
isTBD: date === null,
|
||||
dateText: clean,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user