fix(now-playing): Орфей — чиним кодировку (двойная мойибейк cp1251) + режем хекс-хвосты
status-json смешанной кодировки: часть тайтлов нормальный UTF-8, часть — cp1251- байты, прочитанные как latin1 и завёрнутые в UTF-8 (мойибейк «Íèêîëà»→«Никола»). fixEncoding: реальную кириллицу не трогаем, мойибейк (À-ÿ) восстанавливаем latin1→windows-1251. Срезаем приклеенный служебный id трека (- f0098627), фильтр hex/числовых плейсхолдеров усилен. Каналы без реального произведения — без подписи. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -89,22 +89,52 @@ export class OrpheusNowPlayingService {
|
|||||||
return m ? m[1] : null;
|
return m ? m[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Разбирает title «Артист — Произведение», отсекая мусор. */
|
/**
|
||||||
|
* Чинит кодировку: реальную кириллицу (U+0400-04FF) не трогаем; «двойную
|
||||||
|
* мойибейк» (cp1251-байты, прочитанные как latin1 и завёрнутые в UTF-8 —
|
||||||
|
* признак латиницы-1 À-ÿ) восстанавливаем latin1→windows-1251.
|
||||||
|
*/
|
||||||
|
private fixEncoding(s: string): string {
|
||||||
|
if (/[Ѐ-ӿ]/.test(s)) return s; // уже корректная кириллица
|
||||||
|
if (/[À-ÿ]/.test(s)) {
|
||||||
|
try {
|
||||||
|
return new TextDecoder('windows-1251').decode(Buffer.from(s, 'latin1'));
|
||||||
|
} catch {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Разбирает title «Артист — Произведение», чиня кодировку и отсекая мусор/служебные id. */
|
||||||
private parseTitle(title?: string): { artist: string; song: string } | null {
|
private parseTitle(title?: string): { artist: string; song: string } | null {
|
||||||
if (!title) return null;
|
if (!title) return null;
|
||||||
const t = title.trim();
|
let t = this.fixEncoding(title).replace(/\s+/g, ' ').trim();
|
||||||
if (!t || t === 'undefined') return null;
|
if (!t || t.toLowerCase() === 'undefined') return null;
|
||||||
// hex-плейсхолдеры (0003b6d2), URL-источники (http://fonotron.ru), JSON
|
// Срезаем хвостовой служебный id трека: « - f0098627», « - 147-1-10», « - 263-2-01»
|
||||||
if (/^[0-9a-f]{6,}$/i.test(t) || t.startsWith('http') || t.startsWith('{')) {
|
t = t
|
||||||
|
.replace(/\s*[-—]\s*[0-9a-f]{6,}\s*$/i, '')
|
||||||
|
.replace(/\s*[-—]\s*\d+-\d+(?:-\d+)?\s*$/, '')
|
||||||
|
.trim();
|
||||||
|
if (!t) return null;
|
||||||
|
// Целиком мусор: hex-плейсхолдер, числовой код, URL, JSON
|
||||||
|
if (
|
||||||
|
/^[0-9a-f]{4,}$/i.test(t) ||
|
||||||
|
/^\d+-\d+/.test(t) ||
|
||||||
|
t.startsWith('http') ||
|
||||||
|
t.startsWith('{')
|
||||||
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Разделитель — длинное тире или дефис с пробелами
|
// Разделитель — длинное тире или дефис с пробелами (оба длиной 3 символа: « X »)
|
||||||
const idx = t.indexOf(' — ') >= 0 ? t.indexOf(' — ') : t.indexOf(' - ');
|
const emIdx = t.indexOf(' — ');
|
||||||
|
const idx = emIdx >= 0 ? emIdx : t.indexOf(' - ');
|
||||||
if (idx < 0) return null;
|
if (idx < 0) return null;
|
||||||
const sepLen = t.indexOf(' — ') >= 0 ? 3 : 3;
|
|
||||||
const artist = t.slice(0, idx).trim();
|
const artist = t.slice(0, idx).trim();
|
||||||
const song = t.slice(idx + sepLen).trim();
|
const song = t.slice(idx + 3).trim();
|
||||||
if (!artist || !song) return null;
|
if (!artist || !song) return null;
|
||||||
|
// Часть после чистки всё ещё мусорная
|
||||||
|
if (/^[0-9a-f]{4,}$/i.test(song) || /^[0-9a-f]{4,}$/i.test(artist)) return null;
|
||||||
return { artist, song };
|
return { artist, song };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user