[2026-09-26] eagle: personal/plans/music-tags-review/music-tags-review.md personal/tech/music-tags-repair-truenas.md

This commit is contained in:
Alexey Martemyanov committed 2026-09-26 19:56:08 +06:00
1 parent b290eec03b
commit 8199307531
2 files changed
+115 -2

No files matched your search

@@ -11,6 +11,53 @@ updated: '2026-09-26'
**К правке:** 6773 файлов · **без изменений:** 1133
> **⚠️ 25-я волна (2026-09-26): ИДЁТ ПОСТРОЧНОЕ РУЧНОЕ ЧТЕНИЕ. Прочитано 1–1401 из 7906 (~18%).**
>
> **Найдено в блоке 802–1401:**
> - **Обрезанный `album` — 29**: `Love Sensuality Devotion The G` (18, Enigma) →
> `Love Sensuality Devotion: The Greatest Hits`; `Le Roi Est Mort, Vive Le Roi` (11, потерян `!`).
> - **Обрезанные title — 5**: `Principles Of Lust - C: Sadene`, `Principles Of Lust (Sadness ..`,
> `Ancient Person Of My Heart (Le`, `Age Of Loneliness (Carly's S..`, `Back To The Rivers Of Belief..`
> — восстановлены по официальным названиям Enigma.
> - **Битые поля тестового файла — 1**: `title='ст Сабвуфера ¹1 Edit'` + `artist='Т'` →
> `Тест Сабвуфера №1 Edit` / `Тест Сабвуфера`.
> - **Битые поля от запятой — 1**: Сектор Газа `30 лет.mp3` дал `title='лет'` + `track=30` → `30 лет`.
> - **Опечатки — 3**: `Секторр Газа` (двойная `р`, 2 строки), `Against Me` (потерян `!`, 1).
>
> 🔴 **Инцидент 25-й волны:** собственная правка `patch` строки 1187 дала **12 полей вместо 11**
> (`Газовая атака,,,fix` вместо `,,fix`). Скрипт `fix_block1300.py` корректно отказался
> (`ABORT source [1187]`); починено inline-заменой `,,,fix,`→`,,fix,`. Подробности —
> [[personal/tech/music-tags-repair-truenas|tech/music-tags-repair-truenas]], 25-я волна.
>
> **⏭ ГДЕ ПРОДОЛЖАТЬ:** строка **1402**. Читать блоками по 200, править, сверять `7906 / 0 битых`,
> бэкап перед каждым скриптом. Файл по-прежнему НЕ ГОТОВ к применению на NAS.
> **⚠️ 24-я волна (2026-09-26): ИДЁТ ПОСТРОЧНОЕ РУЧНОЕ ЧТЕНИЕ. Прочитано 1–801 из 7906 (~10%).**
> Alex после третьего отказа принять «всё готово»: «Проходить весь список руками и валидировать.
> Ты заебал меня туда сюда тыркать!!!» Заведён `todo` на 8 блоков по ~1000 строк.
>
> **Найдено в блоке 1–801 (то, что НЕ ловят детекторы):**
> - **`Сборка Песни для детей` в `new_artist` — 165 строк** (имя папки-сборки выдано за исполнителя) → artist пусто.
> - **`Филосовские` → `Философские` — 97 строк** (опечатка в album папки Высоцкого).
> - **Номер приклеен к названию — 35**: `Трое из Простоквашино 8` → `Серия 8`,
> `Новые Бременские 17` → `Часть 17`, `Малыш и Карлсон 3` → `Часть 3`.
> - **Потерянная `й` — 6**: `печкои`→`печкой`, `друзеи`→`друзей`, `арство`→`царство`.
> - **Транслит в title — 8**: `Shelkunchik`, `Babushka metelica`, `Spyashaya krasavica`,
> `Muzikalniy magazinchik`, `Bremen Musicians`, `Podi tuda ne znayu kuda`.
> - **Битые поля от незакавыченной запятой — 2**: `title='король'` + `artist='Том'` → `Том - король`.
> - **Срезанный `path` — 1** (Голубой щенок), восстановлен.
> - **Классика — 11**: артист в title, непарная скобка, имя файла в title, `Бетховен к Элизе`.
> - Мелочи: точки в конце title (12, `Рецидивист.`), `Али-баба`→`Али-Баба` (7), `б.`/`1б.` в title (2),
> `Мультрек` в artist (3).
>
> 🔴 **Инцидент:** скрипт правки открыл CSV на запись, упал на битой строке 4640 и **обрезал файл
> до 4640 строк** → восстановлено из бэкапа. Все скрипты переведены на безопасный паттерн
> `tmp + валидация + os.replace()`; при битой строке в исходнике скрипт делает `ABORT`. Подробности —
> [[personal/tech/music-tags-repair-truenas|tech/music-tags-repair-truenas]], 24-я волна.
>
> **⏭ ГДЕ ПРОДОЛЖАТЬ:** строка **802**. Читать блоками по 200, править, сверять `7906 / 0 битых`,
> бэкап перед каждым скриптом. Файл по-прежнему НЕ ГОТОВ к применению на NAS.
> **⚠️ 23-я волна (2026-09-26): CSV обработан глубже, но всё ещё НЕ ГОТОВ к применению.**
> Добито то, что предыдущая волна оставила как «осталось»:
> - **`album` = `ГГГГ - Название`** (`2002 - Живой`, `1989 - Сектор Газа`) — **504 строки**, год снят
+68 -2
View File
@@ -4,7 +4,7 @@ created: '2026-09-26'
updated: '2026-09-26'
type: tech
namespace: personal
wave: 23
wave: 25
tags:
- music
- jellyfin
@@ -20,7 +20,73 @@ related:
# Music Tags Repair — TrueNAS (7906 файлов)
> **Статус: ДВАДЦАТЬ ТРЕТЬЯ ВОЛНА (2026-09-26). CSV: 7906 строк, 0 БИТЫХ, 0 ДУБЛЕЙ АРТИСТОВ,
> **Статус: ДВАДЦАТЬ ПЯТАЯ ВОЛНА (2026-09-26). ИДЁТ РУЧНОЕ ЧТЕНИЕ ПО ВСЕМУ СПИСКУ.**
> Alex потребовал: «Проходить весь список руками и валидировать» (после 3 отказов принять
> «всё готово»). Работа в процессе: **прочитаны и вычищены строки 1–1401 из 7906 (~18%)**.
> CSV: 7906 строк, 0 битых, 0 дублей артистов, 0 год-префиксов/плейсхолдеров/сайтов.
> НЕ ГОТОВ к применению: **строки 1402–7907 ещё не читались глазами.**
> ✅ **НОВОЕ (25-я волна) — построчное чтение блока 802–1401:**
> | Класс | Строк | Метод | Результат |
> |---|---|---|---|
> | Обрезанный `new_album` = `Love Sensuality Devotion The G` (Enigma, Greatest Hits) | **18** | `fix_block1300.py` | → `Love Sensuality Devotion: The Greatest Hits` |
> | Обрезанный `new_album` = `Le Roi Est Mort, Vive Le Roi` (**потерян `!`**) | **11** | тот же | → `Le Roi Est Mort, Vive Le Roi!` |
> | Битые поля тестового файла: `title='ст Сабвуфера ¹1 Edit'` + `artist='Т'` | 1 | тот же | → `Тест Сабвуфера №1 Edit` / `Тест Сабвуфера` |
> | Обрезанные title (`Principles Of Lust - C: Sadene`, `Principles Of Lust (Sadness ..`, `Ancient Person Of My Heart (Le`, `Age Of Loneliness (Carly's S..`, `Back To The Rivers Of Belief..`) | 5 | тот же | восстановлено по официальным названиям |
> | Битые поля от запятой: `title='лет'`+`track=30` (Сектор Газа `30 лет.mp3`) | 1 | вручную | → `30 лет`, track пусто |
> | Опечатка `Секторр Газа` (двойная `р`) | 2 | вручную `patch` | → `Сектор Газа` |
> | `Against Me` (потерян `!`) | 1 | вручную | → `Against Me!` |
> | Лишняя точка в конце (`Back To The Rivers Of Belief..`) | 1 | скрипт | срезана |
>
> 🔴 **ТРЕТИЙ СЛУЧАЙ ПОВРЕЖДЕНИЯ СТРОКИ СОБСТВЕННОЙ ПРАВКОЙ (25-я волна):** правка
> строки 1187 через `patch` дала **12 полей вместо 11** (`new_track` и `action` слились —
> `Газовая атака,,,fix` вместо `Газовая атака,,fix`). Скрипт `fix_block1300.py` **корректно
> отказался работать** (`ABORT source [1187]`) — сработала защита. Починено inline-скриптом
> (замена `,,,fix,` → `,,fix,`), после чего скрипт прошёл. **Вывод: перед запуском любого
> скрипта смотреть не только `ABORT`, но и почему; не «починить файл чтобы прошло», а понять
> какое поле лишнее.**
> ⏭ **ГДЕ ПРОДОЛЖАТЬ: со строки 1402.** Порядок: читать `read_file` блоками по 200, править
> найденное, сверять `python3 -c` на 7906/0 битых, бэкап перед каждым скриптом.
> Артефакты волны: `fix_block1300.py` (tmp+валидация), бэкапы `bak-*-blk1300`, `bak-*-blk400`,
> `bak-*-sbornik`, `bak-*-typo`.
>
> ---
>
> **Статус предыдущей волны: ДВАДЦАТЬ ЧЕТВЁРТАЯ (2026-09-26). Прочитаны и вычищены строки 1–801.**
> Alex потребовал: «Проходить весь список руками и валидировать» (после 3 отказов принять
> «всё готово»).
> ✅ **НОВОЕ (24-я волна) — построчное чтение блока 1–801, найдено то, что НЕ ловят детекторы:**
> | Класс | Строк | Метод | Результат |
> |---|---|---|---|
> | `Сборка Песни для детей` в `new_artist` (имя папки-сборки, не исполнитель) | **165** | `fix_sbornka.py` | → artist пусто |
> | `Филосовские` (опечатка) | **97** | `fix_typos.py` | → `Философские` |
> | Транслит в title (`Shelkunchik`, `Muzikalniy magazinchik`, `Babushka metelica`, `Spyashaya krasavica`, `Bremen Musicians`, `Podi tuda ne znayu kuda`) | 8 | `fix_block400.py`, `fix_block200.py` | → кириллица |
> | Номер приклеен к названию (`Трое из Простоквашино 8`, `Новые Бременские 17`, `Малыш и Карлсон 3`) | 35 | `fix_block200/400.py` | → `Серия N` / `Часть N` |
> | Потерянная `й` (`печкои`→`печкой`, `друзеи`→`друзей`, `арство`→`царство`, `белоснежкои`, `доброи`) | 6 | `fix_block400.py` (карта `YFIX`) | исправлено |
> | Битые поля от запятой в title (`title='король'`+`artist='Том'`; `'король'`+`'Эдвард'`) | 2 | `fix_split_fields.py` | → `Том - король` / `Эдвард - король`, artist пусто |
> | **Срезанный `path`** (`Голубой щенок/01 - Хоттабыч!.mp3` без `/storage/Music/!Детские/Сказки/`) | 1 | вручную | восстановлен |
> | Классика: артист в title, непарная скобка, имя файла в title (`Шопен — Похоронный марш`), строка `Бетховен к Элизе` | 11 | вручную | → `Танец маленьких лебедей…`, `Полёт валькирий (из оперы «Валькирия»)`, `К Элизе`/`Людвиг ван Бетховен`, `Похоронный марш (Соната №2, III)` |
> | Точка в конце title (альбом `Рецидивист` Высоцкого) | 12 | `fix_block200.py` | точка срезана (многоточия НЕ трогаются) |
> | `Али-баба` → `Али-Баба`; `б.`/`1б.` в title | 8 | `fix_block200.py`, `fix_sbornka.py` | исправлено |
> | `Vinni Pooh` → `Part N` транслит; `Мультрек` в artist | 6+3 | `fix_block200.py` | исправлено |
>
> 🔴 **КРИТИЧНЫЙ УРОК 24-й волны (ошибка самого ассистента):** скрипт правки открыл
> `tag-fix-plan.csv` на запись, упал на середине (`ValueError: dict contains fields not in
> fieldnames: None` — строка 4640 с незакавыченными запятыми) и **обрезал файл до 4640 строк**.
> Восстановлено из бэкапа `bak-*-prefix`. 🔴 **ПРАВИЛО: скрипт НИКОГДА не открывает исходник на
> запись.** Писать в `<src>.tmp` → провалидировать (`len(fields)`, число строк, `None` в ключах)
> → `os.replace()`. Все скрипты этой волны (`fix_typos.py`, `fix_block200.py`, `fix_block400.py`,
> `fix_sbornka.py`, `fix_split_fields.py`, `fix_placeholders.py`, `strip_year_album.py`,
> `strip_artist_prefix.py`) переписаны на этот паттерн и **корректно отказываются работать
> (`ABORT source [...]`), если в исходнике есть битая строка** — это фича, не баг.
> 🔴 **ВТОРОЙ УРОК: регексп `\.$` опасен.** Первая версия срезала точки у многоточий
> (`Холода, холода...` → `Холода, холода..`). Правильно: срезать только если
> `t.endswith('.') and not t.endswith('..')`.
> ⏭ **ГДЕ ПРОДОЛЖАТЬ: со строки 802.** Порядок: читать `read_file` блоками по 200, править
> найденное, сверять `python3 -c` на 7906/0 битых, бэкап перед каждым скриптом.
>
> ---
>
> **Статус предыдущей волны: ДВАДЦАТЬ ТРЕТЬЯ (2026-09-26). CSV: 7906 строк, 0 БИТЫХ, 0 ДУБЛЕЙ АРТИСТОВ,
> 0 год-префиксов в album, 0 плейсхолдеров в album, 0 сайтов-воды.**
> НЕ ГОТОВ к применению: **title у ~7000 строк НЕ проходился глазами** (детекторы смысловые
> ошибки не ловят), `ty_49`/`пакет.mp3` не определены без прослушивания, 46 альбомов не сверены