From e0990540b9786cec4caa76ebf764e052ccae280e Mon Sep 17 00:00:00 2001 From: nk Date: Wed, 3 Jun 2026 10:38:05 +0300 Subject: [PATCH] =?UTF-8?q?fix(charts):=20=D0=BE=D1=82=D1=81=D0=B5=D0=BA?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20=D0=B4=D0=B6=D0=B8=D0=BD=D0=B3=D0=BB=D1=8B?= =?UTF-8?q?/=D1=88=D0=BE=D1=83/=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=81=D1=82=D0=B0=D0=BD=D1=86=D0=B8=D0=B9=20=D0=B8?= =?UTF-8?q?=D0=B7=20=D1=81=D0=B1=D0=BE=D1=80=D0=B0=20=D1=87=D0=B0=D1=80?= =?UTF-8?q?=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Record API при эфире шоу/джингла возвращает название станции/сети как трек (пустой artist/song или совпадение с названием станции). Такие записи накапливали проигрывания и забивали топ. Теперь recordPlay их пропускает (кэш названий станций). --- src/charts/charts.service.ts | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) 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 },