diff --git a/personal/plans/music-tags-review/music-tags-review.md b/personal/plans/music-tags-review/music-tags-review.md index e44c24c3..59cbc1c1 100755 --- a/personal/plans/music-tags-review/music-tags-review.md +++ b/personal/plans/music-tags-review/music-tags-review.md @@ -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 строки**, год снят diff --git a/personal/tech/music-tags-repair-truenas.md b/personal/tech/music-tags-repair-truenas.md index 3349c03b..155c8677 100755 --- a/personal/tech/music-tags-repair-truenas.md +++ b/personal/tech/music-tags-repair-truenas.md @@ -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`. 🔴 **ПРАВИЛО: скрипт НИКОГДА не открывает исходник на +> запись.** Писать в `.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 альбомов не сверены