fix(charts): отсекать джинглы/шоу/названия станций из сбора чартов

Record API при эфире шоу/джингла возвращает название станции/сети как трек
(пустой artist/song или совпадение с названием станции). Такие записи
накапливали проигрывания и забивали топ. Теперь recordPlay их пропускает
(кэш названий станций).
This commit is contained in:
nk
2026-06-03 10:38:05 +03:00
parent 38fe92d695
commit e0990540b9

View File

@@ -85,15 +85,45 @@ export class ChartsService {
} }
} }
// Кэш названий станций — чтобы отсеивать джинглы/шоу из чарта
private stationNames = new Set<string>();
private stationNamesAt = 0;
private async getStationNames(): Promise<Set<string>> {
const now = Date.now();
if (now - this.stationNamesAt > 10 * 60 * 1000 || this.stationNames.size === 0) {
const rows = await this.prisma.station.findMany({ select: { name: true } });
this.stationNames = new Set(
rows.map((r) => r.name.trim().toLowerCase()).filter((n) => n.length > 0),
);
this.stationNamesAt = now;
}
return this.stationNames;
}
// Записывает факт смены трека на станции (вызывается из NowPlayingService) // Записывает факт смены трека на станции (вызывается из NowPlayingService)
async recordPlay(params: RecordPlayParams): Promise<void> { async recordPlay(params: RecordPlayParams): Promise<void> {
try { try {
const { artist, song, coverUrl, stationDbId } = params; const artist = (params.artist ?? '').trim();
const song = (params.song ?? '').trim();
const { coverUrl, stationDbId } = params;
// Отсекаем не-музыкальные записи: пустые поля, либо когда артист/песня
// совпадает с названием станции (это джинглы, шоу, сетевые промо).
if (!artist || !song) return;
const stationNames = await this.getStationNames();
if (
stationNames.has(artist.toLowerCase()) ||
stationNames.has(song.toLowerCase())
) {
return;
}
// Нормализованный ключ: нижний регистр, схлопнуть пробелы // Нормализованный ключ: нижний регистр, схлопнуть пробелы
const normKey = const normKey =
artist.trim().toLowerCase().replace(/\s+/g, ' ') + artist.toLowerCase().replace(/\s+/g, ' ') +
'|' + '|' +
song.trim().toLowerCase().replace(/\s+/g, ' '); song.toLowerCase().replace(/\s+/g, ' ');
const track = await this.prisma.track.upsert({ const track = await this.prisma.track.upsert({
where: { normKey }, where: { normKey },