diff --git a/src/charts/charts.service.ts b/src/charts/charts.service.ts index 917abea..5c7cfa9 100644 --- a/src/charts/charts.service.ts +++ b/src/charts/charts.service.ts @@ -85,15 +85,45 @@ export class ChartsService { } } + // Кэш названий станций — чтобы отсеивать джинглы/шоу из чарта + private stationNames = new Set(); + private stationNamesAt = 0; + + private async getStationNames(): Promise> { + 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) async recordPlay(params: RecordPlayParams): Promise { 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 = - 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({ where: { normKey },