first commit
This commit is contained in:
63
apps/api/src/discovery/discovery.controller.ts
Normal file
63
apps/api/src/discovery/discovery.controller.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user