Files
gob-alert/apps/api/src/discovery/discovery.controller.ts
alexandrump 82f3464565 first commit
2026-02-09 01:02:53 +01:00

64 lines
2.2 KiB
TypeScript

import { Controller, Get, Query } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository } from 'typeorm';
import { CatalogService } from '../catalog/catalog.service';
import { ClassificationTagEntity } from '../entities/classification-tag.entity';
@Controller('discover')
export class DiscoveryController {
constructor(
private readonly catalog: CatalogService,
@InjectRepository(ClassificationTagEntity)
private readonly tags: Repository<ClassificationTagEntity>,
) {}
@Get('changes')
async changes(@Query('days') days?: string, @Query('limit') limit?: string) {
const daysCount = this.clampDays(days ? Number(days) : 7);
const take = limit ? Math.min(Number(limit) || 20, 200) : 20;
const since = this.startOfDayOffset(daysCount - 1);
let changes = await this.catalog.listChangesSince(since);
changes = changes.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
changes = changes.slice(0, take);
const itemIds = Array.from(new Set(changes.map((c) => c.itemId).filter(Boolean)));
const tags = itemIds.length
? await this.tags.find({ where: { itemId: In(itemIds) } })
: [];
const tagsByItem = new Map<string, ClassificationTagEntity[]>();
for (const tag of tags) {
const list = tagsByItem.get(tag.itemId) || [];
list.push(tag);
tagsByItem.set(tag.itemId, list);
}
return changes.map((change) => ({
...change,
tags: this.groupTags(tagsByItem.get(change.itemId) || []),
}));
}
private groupTags(tags: ClassificationTagEntity[]) {
return {
topics: tags.filter((t) => t.type === 'topic').map((t) => t.value),
territories: tags.filter((t) => t.type === 'territory').map((t) => t.value),
formats: tags.filter((t) => t.type === 'format').map((t) => t.value),
publishers: tags.filter((t) => t.type === 'publisher').map((t) => t.value),
};
}
private clampDays(value: number) {
if (!value || Number.isNaN(value)) return 7;
return Math.min(Math.max(value, 1), 90);
}
private startOfDayOffset(offsetDays: number) {
const date = new Date();
date.setHours(0, 0, 0, 0);
date.setDate(date.getDate() - offsetDays);
return date;
}
}