[2026-09-27] eagle: personal/plans/music-artist-albumartist-repair.md personal/tech/music-tags-repair-truenas.md personal/tech/scripts/find_aa_hijack.py
This commit is contained in:
1 parent
042cac0216
commit
c0a76a56c9
3 files changed
+341
-6
No files matched your search
@@ -4,7 +4,7 @@ created: '2026-09-27'
|
||||
updated: '2026-09-27'
|
||||
type: plan
|
||||
namespace: personal
|
||||
status: session4-done-diff-rebuilt-4864-rows-0-losses
|
||||
status: session6-open-7-albumartist-hijack-folders
|
||||
tags:
|
||||
- music
|
||||
- metadata
|
||||
@@ -23,6 +23,30 @@ related:
|
||||
|
||||
# Music `artist` + `albumartist` Repair — правила Alex и ход работ
|
||||
|
||||
> ## 🔴 АКТУАЛЬНО НА КОНЕЦ СЕССИИ 6 (2026-09-27)
|
||||
>
|
||||
> ```
|
||||
> APPLY-PLAN.csv 7861 строка md5 c8d43cc56d82cd35a67a0efe8173cd4b
|
||||
> DIFF-new-vs-38.csv 4864 строки md5 3ebc67c9d6abe5fce2d927fcc7726808
|
||||
> tag-fix-plan.csv не тронут (база 38-го, источник истины для диффа)
|
||||
> ```
|
||||
>
|
||||
> **Пустых полей в плане — 0** (`new_album` / `new_albumartist` / `new_artist` / `new_title` / `new_genre`).
|
||||
> Дифф проверен: `ПОТЕРЯНО 0 · ЛИШНИХ 0 · ИТОГ: ПОТЕРЬ НЕТ, дифф ПОЛНЫЙ`.
|
||||
>
|
||||
> 🔴 **ОТКРЫТО, ЖДЁТ «go» (главное сессии 6):** класс дефекта **«`albumartist` размножен от чужого
|
||||
> файла в корне папки»** — найдено **7 папок** (`The Prodigy`→`DJ Feel`, `Банд Эрос`→`VIP77`,
|
||||
> `Дискотека Авария`, `Жуки`, `Потап & Каменских`, `Король и Шут`, `Ленинград`). Детали и
|
||||
> детектор-скрипт — в разделе **«🔷 СЕССИЯ 6»** в конце документа.
|
||||
>
|
||||
> **Формат `album` для папок `!Radio/*` ИЗМЕНЁН (сессия 5):** `Radio - <имя>`
|
||||
> (`Radio - OOF`, `Radio - Старое`, `Radio - Df1`) — **вытесняет** прежние `OOF Radio` /
|
||||
> `Старое Radio` / `RADIO 1 DRIVE`. Упоминания старого формата ниже по тексту — устарели.
|
||||
>
|
||||
> **Всё остальное о формате `album` в старых разделах ниже — историческое.** Хронология
|
||||
> сессий 1-5 и все разобранные питфоллы — в разделах «🔷 СЕССИЯ N» в конце документа.
|
||||
> **Свежие правила всегда в последнем разделе.**
|
||||
>
|
||||
> ## 🔴 ПУТИ ПЕРЕЕХАЛИ (2026-09-27, вечер) — `~/milestones` БОЛЬШЕ НЕТ
|
||||
>
|
||||
> Alex: «какой блядь ~/milestones?! мы блядь работаем в `/Users/admin/Downloads/music-tags/`!
|
||||
@@ -2317,5 +2341,255 @@ python3 verify_diff_completeness.py # exit 0 = чисто
|
||||
не нужна, а в диффе строка есть. Пользователь обозначил принцип: **в диффе только то,
|
||||
что реально поменяется.**
|
||||
|
||||
---
|
||||
|
||||
## 🔷 СЕССИЯ 5 (2026-09-27): ЗАКРЫТИЕ ПУСТЫХ ПОЛЕЙ + РУЧНЫЕ ПРАВКИ `album`/`albumartist`
|
||||
|
||||
### Задача Alex
|
||||
|
||||
> «блядь поправь пустые!»
|
||||
> «OOF Radio -> Radio - OOF / Старое Radio -> Radio - Старое / Df1 -> Radio - Df1 /
|
||||
> Infected Mushroom - Other Track's -> Other Tracks»
|
||||
> «!Rock&Folk/Rammstein — треки в корне тоже кстати Rammstein - misc сделай»
|
||||
> «Benassi Bros/2003 Hypnotica Bonus — albumartist Various Artists исправь» → «ну ставь benassi bros»
|
||||
> «!Pop, Club, Любэ/Dj Tiesto — там не Tiesto должен быть разве albumartist?»
|
||||
|
||||
### 1️⃣ ЗАКРЫТЫ ВСЕ ПУСТЫЕ ПОЛЯ (0 пустых)
|
||||
|
||||
| # | Файл | Поле | Было | Стало |
|
||||
|---|---|---|---|---|
|
||||
| 1 | `z Другое, Enigma, Ленинград/Красная плесень - На дискотеку сельскую.mp3` | `album` | пусто | `Сосни попса` |
|
||||
| 2 | `z Другое, Enigma, Ленинград/Красная Плесень - Заебал мой кот.mp3` | `album` | пусто | `Сосни попса` |
|
||||
| 3 | `!Pop, Club, Любэ/!Radio/t 2009-07 c6Or_NICK/10 Boom (Bimbo Jones Mix).mp3` | `artist` | мусор `ÿþd` (UTF-16-обрывок) | `Bimbo Jones` |
|
||||
|
||||
Файлы №1-2 лежали **в корне папки-КАТЕГОРИИ** `z Другое, Enigma, Ленинград` (внутри —
|
||||
подпапки `Красная Плесень`, `Ленинград`, `Сектор Газа`, `Enigma`, `Саундтреки` и др.).
|
||||
Имя папки-категории в `album` — мусор; оба файла принадлежат альбому `Сосни попса`
|
||||
(в дереве есть `Красная Плесень/Сосни попса/`, 16 файлов).
|
||||
|
||||
**Итог: пустых `new_album` / `new_albumartist` / `new_artist` / `new_title` / `new_genre` = 0.**
|
||||
|
||||
### 🔴 ПИТФОЛЛ: поиск мусора по точному значению промахивается
|
||||
|
||||
Я искал битый `artist` по литералу `'ÿþd'` — **не нашёл**, файл проскочил. Значение реально
|
||||
было **пустой строкой** после нормализации. Правильный фильтр — не по литералу, а **по
|
||||
свойствам**: `if not s.strip() or not s.isprintable() or any(ord(c) < 32 for c in s)`.
|
||||
|
||||
**Мораль:** искать мусор по списку известных значений = гарантированный пропуск.
|
||||
Искать по предикату свойства.
|
||||
|
||||
### 🔴 ЧЕСТНОСТЬ В ОТЧЁТЕ: я сказал «пустого `new_artist` нет» — это была неправда
|
||||
|
||||
Первый ответ был «empty=1, сейчас назову» → затем «моя ошибка, значение есть, просто мусорное».
|
||||
Alex отреагировал резко («шо??»). **Нельзя объявлять «0 пустых», не перепроверив все поля
|
||||
по предикату.** Потеря доверия к отчёту дороже, чем задержка на проверку.
|
||||
|
||||
### 2️⃣ РУЧНЫЕ ПРАВКИ `album` — 61 файл (команда Alex)
|
||||
|
||||
| Папка | Файлов | Было | Стало |
|
||||
|---|---:|---|---|
|
||||
| `!Radio/y OOF` | 29 | `OOF Radio` | **`Radio - OOF`** |
|
||||
| `!Radio/z Старое` (корень) | 16 | `Старое Radio` | **`Radio - Старое`** |
|
||||
| `Df1` | 12 | `Df1` | **`Radio - Df1`** |
|
||||
| `Infected Mushroom - Other Track's` | 2 | `Infected Mushroom - Other Track's` | **`Other Tracks`** |
|
||||
| `!Rock&Folk/Rammstein` (корень) | 2 | `Rammstein` | **`Rammstein - misc`** |
|
||||
|
||||
**Принцип формат-имени: `Radio - <имя>`** — вытесняет прежний суффиксный `OOF Radio` /
|
||||
прежний префиксный `RADIO 1 DRIVE`. 🔴 Актуальный формат папок `!Radio/*` снизу —
|
||||
`Radio - OOF`, `Radio - Старое`, `Radio - Df1` (не `OOF Radio`).
|
||||
|
||||
**Не тронуто (осознанно — это НЕ имя папки, а реальные альбомы):**
|
||||
- `Df1/My CD` (`Vino Vino Vinyl`, `Nachtschicht Vol 24 CD1`, `FR0NT0700510`…) — 4 файла
|
||||
- `Rammstein/Rammstein - Kokain.mp3` — уже `Das Modell`
|
||||
- 21 файл в `Other Track's` со своими альбомами (`Unreleased Tracks` 14, `Magnet`, `Voom…`)
|
||||
- реальные альбомы внутри `y OOF` / `z Старое` (`Вспышка Сверхновой 2007 Club`, `Borat`, `Bucovina`…)
|
||||
|
||||
> 🔴 **Питфолл точности:** «Infected Mushroom — Other Track's» переименовывалось **только там,
|
||||
> где `new_album` буквально равен имени папки**. Слепой заменой по папке было бы испорчено
|
||||
> 21 файл с настоящими альбомами. Правило: править по совпадению `new_album == имя_папки`,
|
||||
> а не по предикату «файл лежит в папке X».
|
||||
|
||||
### 3️⃣ `albumartist` Benassi Bros — 20 файлов
|
||||
|
||||
| Папка | Файлов | Было | Стало |
|
||||
|---|---:|---|---|
|
||||
| `Benassi Bros/2003 Hypnotica Bonus` | 5 | `Various Artists` | **`Benassi Bros`** |
|
||||
| `Benassi Bros/Re Sfaction` | 15 | `Various Artists` | **`Benassi Bros`** |
|
||||
|
||||
Alex выбрал `Benassi Bros` (не `Benny Benassi`). Оба — **АЛЬБОМЫ с гостевыми фитами**, не сборники
|
||||
(`Re Sfaction`: In-Grid, Sonique, Electric Six, Ann Lee, KMC Feat. Sandy, Gambafreaks).
|
||||
|
||||
> ⏳ **Обнаружена несогласованность внутри группы `Benassi Bros/`:** часть папок
|
||||
> `Benny Benassi` (`2003 Hypnotica`, `2004 Puphonia`, `2008 Rock N Rave`, `2003 MegaMix`,
|
||||
> `2003 Satisfaction*`, `2003 Pres_the_Biz…`), часть `Benassi Bros` (`2005 Phobia` + эти две).
|
||||
> Alex не подтвердил приведение к одному имени — **не трогать без указания**.
|
||||
|
||||
### 4️⃣ `Dj Tiesto` — ВОПРОС ОТКРЫТ (ждёт ответа Alex)
|
||||
|
||||
`!Pop, Club, Любэ/Dj Tiesto` — 14 файлов, все `new_albumartist = 'Various Artists'`.
|
||||
|
||||
| Файлов | `new_album` | Состав |
|
||||
|---:|---|---|
|
||||
| 13 | `In Search of Sunrise 3` | компиляция-микс Tiesto: Nalin & Kane, Andain, Way Out West, Solar Stone, Choir… |
|
||||
| 1 | `PoW - Team PoW - 2oo4` | `artist = Tiesto`, чужой сборник, в дереве альбома нет |
|
||||
|
||||
**Предложено (НЕ применено):** `In Search of Sunrise 3` → `albumartist = Tiesto`
|
||||
(DJ-микс серии, автор компиляции — диджей; `artist` каждого трека остаётся свой),
|
||||
`PoW` — оставить `Various Artists`. **Ждём «go».**
|
||||
|
||||
---
|
||||
|
||||
### 📊 АКТУАЛЬНЫЕ АРТЕФАКТЫ (конец сессии 5)
|
||||
|
||||
```
|
||||
APPLY-PLAN.csv 7861 строка md5 87ab8406509fb99651762886645e35e8
|
||||
DIFF-new-vs-38.csv 4864 строки md5 6852b25fd36fe14e97eb7788cdfa844a
|
||||
tag-fix-plan.csv не тронут (база 38-го, источник истины для диффа)
|
||||
```
|
||||
|
||||
**Цепочка MD5 `APPLY-PLAN.csv` (сессия 5):**
|
||||
```
|
||||
bb724716… начало сессии 5 (0 пустых, до ручных правок)
|
||||
88e1059c… + 61 файл Radio-формат / Other Tracks / Rammstein - misc
|
||||
87ab8406… ⬅ ТЕКУЩИЙ, + Benassi Bros albumartist (20 файлов)
|
||||
```
|
||||
|
||||
**Цепочка MD5 `DIFF-new-vs-38.csv` (сессия 5):**
|
||||
```
|
||||
0d7a31ca… начало сессии 5
|
||||
a0a52be9… + 61 файл Radio-формат / Other Tracks / Rammstein - misc
|
||||
6852b25f… ⬅ ТЕКУЩИЙ, + Benassi Bros albumartist
|
||||
```
|
||||
|
||||
**Проверка после каждой правки (оба скрипта, выход):**
|
||||
```
|
||||
diff_new_vs_38.py: ВСЕГО правок 18558, assert OK: потерь нет
|
||||
verify_diff_completeness.py: ПОТЕРЯНО 0 · ЛИШНИХ 0
|
||||
НЕТ-В-38 41=41 · ТОЛЬКО-В-38 85=85
|
||||
ИТОГ: ПОТЕРЬ НЕТ, дифф ПОЛНЫЙ
|
||||
```
|
||||
|
||||
> 🔴 **Рабочий цикл правки CSV (установлен, повторять):**
|
||||
> 1. `shutil.copy2(p, p + '.bak-before-<тема>-' + ts)` — бэкап **до** правки;
|
||||
> 2. правка скриптом из **файла** (`write_file` в `/tmp`), не инлайном;
|
||||
> 3. `python3 diff_new_vs_38.py > /tmp/log 2>&1` (**не через пайп**);
|
||||
> 4. `python3 verify_diff_completeness.py` → `exit 0`;
|
||||
> 5. отчёт Alex: «Готово, проверяй» + что изменено + **MD5 до/после**.
|
||||
|
||||
Бэкапы сессии 5: `.bak-before-finalempty-20260927-134959`, `.bak-before-artistempty-20260927-135034`,
|
||||
`.bak-before-radiofix-20260927-140315`, `.bak-before-benassi-20260927-140435`.
|
||||
|
||||
---
|
||||
|
||||
### ⏳ НЕ ЗАКРЫТО (актуализировано, конец сессии 6)
|
||||
|
||||
| # | Вопрос | Статус |
|
||||
|---|---|---|
|
||||
| 1 | 🔴 **`albumartist`-перехват чужим файлом — 7 папок** (`The Prodigy`→`The Prodigy`, `Банд Эрос`→`Банд'Эрос`, `Дискотека Авария`→`Дискотека Авария`, `Жуки`→`Жуки`, `Потап & Каменских`→`Потап и Настя Каменских`, `Король и Шут`→`Король и Шут`, `Ленинград` корень → `Ленинград` ×3 + `Сергей Шнуров` ×1) | 🔴 план предложен, **ждёт «go» Alex** |
|
||||
| 2 | `Benassi Bros/` — свести `Benny Benassi` и `Benassi Bros` к одному имени? | ⏳ Alex не подтвердил |
|
||||
| 3 | `track = '238'` у 56 файлов (`Красная Плесень/Золушка`) | ⏳ верное значение неизвестно |
|
||||
| 4 | `track` пуст у 1438, из них **9 с непустым `cur_track`** → тег `TRCK` будет УДАЛЁН | ⏳ решение Alex |
|
||||
| 5 | `changed = 'no'` у 213 строк (50 файлов / 61 строка в диффе) | ⏳ уточнить трактовку |
|
||||
| 6 | Боевой прогон `--apply --verify` | 🔴 не запущен |
|
||||
| 7 | Контейнер `snapcur` на NAS (только чтение, `:ro`) | ⏳ не убран — Alex не подтвердил |
|
||||
| 8 | Глазами пройти `field=album` (305 строк) в диффе | ⏳ следующий шаг по указанию Alex |
|
||||
| 9 | `ДДТ/2008 L'Echoppe` — `ДДТ` (2 файла `ДДТ`) vs 10 файлов `Юрий Шевчук & Константин Казански` | ✅ вердикт: **НЕ порча**, дуэт-альбом, не трогать |
|
||||
|
||||
---
|
||||
|
||||
# 🔷 СЕССИЯ 6 (2026-09-27, вечер) — `albumartist`-ПЕРЕХВАТ ЧУЖИМ ФАЙЛОМ ПАПКИ
|
||||
|
||||
Триггер: Alex по очереди указывал корневые папки — «`Dj Tiesto` — там не Tiesto должен быть
|
||||
разве albumartist?», «`Банд Эрос` — че за VIP77?», «`The Prodigy` — почему dj feel?».
|
||||
|
||||
## 🔴 ГЛАВНАЯ НАХОДКА: класс дефекта «`albumartist` размножен от чужого файла в корне»
|
||||
|
||||
**Механизм.** Правило «у корневых файлов папки `albumartist` = имя артиста папки» брало значение
|
||||
**от первого попавшегося файла в корне**. Если в корень папки артиста затесался ОДИН файл чужого
|
||||
исполнителя (из сборника), его `albumartist` **расходился на все файлы** папки.
|
||||
|
||||
**Проявления (подтверждено фактом, найдено Alex):**
|
||||
```
|
||||
The Prodigy DJ Feel ← из трека DJ Feel (Trancemission Vol.9) — 3 файла Prodigy испорчены
|
||||
Банд Эрос VIP77 ← из трека VIP77 (Russian R'n'B vol.1) — 6 файлов испорчены
|
||||
```
|
||||
|
||||
> ⚠️ **Это не гипотеза — порча видна в `cur_albumartist`**: у `Prodigy/Hotride [EP].mp3`
|
||||
> и `Prodigy/Record Super Chart (15.08.09).mp3` было `cur_albumartist = 'The Prodigy'`,
|
||||
> а план ставил `DJ Feel` — **прямое затирание верного значения**.
|
||||
|
||||
## 🔧 ДЕТЕКТОР КЛАССА (обязателен после каждой пакетной правки `albumartist`)
|
||||
|
||||
📄 **Скрипт сохранён в vault: `personal/tech/scripts/find_aa_hijack.py`**
|
||||
(копия также в `/tmp/find_aa_hijack.py` — `/tmp` очищается!).
|
||||
|
||||
Алгоритм: для каждой папки, где `new_albumartist` **один на всю
|
||||
папку**, сравнить его с `new_artist` файлов. Признак порчи:
|
||||
|
||||
```
|
||||
new_albumartist не совпадает с top-артистом папки
|
||||
И не совпадает с именем папки
|
||||
И совпадает с МИНОРИТАРНЫМ артистом папки
|
||||
→ ПОДОЗРЕВАЕМЫЙ
|
||||
```
|
||||
|
||||
**Результат прогона: 11 подозреваемых папок.** Разбор:
|
||||
|
||||
| Папка | `albumartist` (у скольких) | Должен быть (у скольких) | Вердикт |
|
||||
|---|---|---|---|
|
||||
| `The Prodigy` | `DJ Feel` (1) | `The Prodigy` (3) | 🔴 порча |
|
||||
| `Банд Эрос` | `VIP77` (1) | `Банд'Эрос` (6) | 🔴 порча |
|
||||
| `Дискотека Авария` | `ДА и Меньшиков` (1) | `Дискотека Авария` (6) | 🔴 порча |
|
||||
| `Жуки` | `Виктор Жуков` (1) | `Жуки` (10) | 🔴 порча |
|
||||
| `Потап & Каменских` | `Мика Ньютон` (1) | `Потап и Настя Каменских` (7) | 🔴 порча |
|
||||
| `Король и Шут` | `КняZz` (1) | `Король и Шут` (3) | 🔴 порча |
|
||||
| `Ленинград` (корень) | `Бумер` (1) | `Ленинград` (3) + `Сергей Шнуров` (1) | 🔴 порча |
|
||||
| `ДДТ/2008 L'Echoppe` | `ДДТ` (2) | — | ✅ НЕ порча: `ДДТ` — верный albumartist, 10 файлов = дуэт Шевчук+Казански |
|
||||
| `Benassi Bros/Re Sfaction` | `Benassi Bros` (3) | — | ✅ решение Alex (сессия 5) |
|
||||
| `IM/S Is Here (Yahel Mix)` | `Infected Mushroom` (1) | — | ✅ решение Alex (сессия 6) |
|
||||
| `Детские/Сборка/L` | `Детские песни` (4) | — | ✅ сборник, верно |
|
||||
|
||||
**СЕССИЯ 6 ЗАКОНЧИЛАСЬ НА ЭТОМ СПИСКЕ — 7 папок ожидают «go» Alex.**
|
||||
|
||||
## ✅ ПРИМЕНЕНО В СЕССИИ 6 (19 файлов)
|
||||
|
||||
| Папка | Файлов | Было | Стало | Основание |
|
||||
|---|---:|---|---|---|
|
||||
| `Dj Tiesto` | 14 | `Various Artists` | **`Tiesto`** | Alex: «тоже» (13 `In Search of Sunrise 3` + 1 `PoW`) |
|
||||
| `IM/Life System … Electro Panic … -2016` | 2 | `Various Artists` | **`Infected Mushroom`** | Alex — папка внутри IM |
|
||||
| `IM/Unreleased/Remixes, Mixes/(2001) … S Is Here (Yahel Mix)` | 3 | `Various Artists` | **`Infected Mushroom`** | Alex: «то же» |
|
||||
|
||||
```
|
||||
MD5 до: 6852b25fd36fe14e97eb7788cdfa844a (DIFF) / 87ab8406509fb99651762886645e35e8 (PLAN)
|
||||
MD5 после: 3ebc67c9d6abe5fce2d927fcc7726808 (DIFF) / c8d43cc56d82cd35a67a0efe8173cd4b (PLAN)
|
||||
```
|
||||
Бэкап: `.bak-before-aa-tiesto-im-20260927-140556`.
|
||||
Проверка: `ВСЕГО правок 18558 · assert OK · ПОТЕРЯНО 0 · ЛИШНИХ 0 · дифф ПОЛНЫЙ`.
|
||||
|
||||
## 📋 КОНТРОЛЬНАЯ ПРОВЕРКА «ЗАТИРАНИЙ» `cur_albumartist` (765 строк)
|
||||
|
||||
Скрипт `/tmp/check_aa_overwrite.py`: `cur_albumartist` непуст **и** `new_albumartist != cur_albumartist`
|
||||
→ **765 строк**. ⚠️ **Почти все — ЗАКОННЫЕ**, это нормализация:
|
||||
|
||||
| Класс | Пример | Объём |
|
||||
|---|---|---|
|
||||
| CP1251-мойибаке → кириллица | `Èëüÿ ×åðò` → `Илья Чёрт` | ~основная масса |
|
||||
| Транслит → кириллица | `Vladimir Vysockij` → `Владимир Высоцкий`, `Nautilus Pompilius` → `Наутилус Помпилиус` | — |
|
||||
| Регистр/пунктуация | `ДИСКОТЕКА АВАРИЯ` → `Дискотека Авария`, `Ногу свело!` → `Ногу Свело!` | — |
|
||||
| Смена артиста по решению | `OverClocked ReMix` → `Various Artists` (Final Fantasy VI) | 64 |
|
||||
|
||||
> 🔴 **Урок: счётчик «765 затираний» — ШУМ, а не список дефектов.** Реальные порчи —
|
||||
> только те, где значение взято **от чужого файла той же папки** (детектор из раздела выше,
|
||||
> нашёл 11 подозреваемых из 765). Не рапортовать число 765 как «проблему».
|
||||
|
||||
## 🔴 ПРАВИЛО, ВЫВЕДЕННОЕ В СЕССИИ 6
|
||||
|
||||
`albumartist` трека = **его собственный артист**, если альбом не сборник.
|
||||
Значение `albumartist` **НИКОГДА** не размножается на файлы других исполнителей внутри папки.
|
||||
Если в корне папки артиста лежат треки разных исполнителей — **у каждого свой `albumartist`**
|
||||
(например, `КняZz` у 1 файла, `Король и Шут` у 3; `Бумер` у 1, `Ленинград` у 3,
|
||||
`Сергей Шнуров` у 1).
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,19 +23,24 @@ related:
|
||||
|
||||
# Music Tags Repair — TrueNAS (7906 → 7905 файлов)
|
||||
|
||||
> ### 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (2026-09-27) — ЧИТАЙ ЭТО ПЕРВЫМ
|
||||
> ## 🔴 АКТУАЛЬНОЕ СОСТОЯНИЕ (2026-09-27, конец сессии 6) — ЧИТАЙ ЭТО ПЕРВЫМ
|
||||
>
|
||||
> **Этот файл — исторический лог волны 38 (завершена). Актуальная работа идёт здесь:**
|
||||
>
|
||||
> | Документ | О чём |
|
||||
> |---|---|
|
||||
> | **[[personal/plans/tagwriter-container]]** | ⭐ скрипт-писатель `apply_tags_v2.py` (566 стр): логика полей, ID3v1-снос, тесты, 18 питфоллов, запуск |
|
||||
> | **[[personal/plans/music-artist-albumartist-repair]]** | правила формирования плана, сборка `APPLY-PLAN-FINAL2.csv` |
|
||||
> | **[[personal/plans/music-artist-albumartist-repair]]** | ⭐ **правила формирования плана, `APPLY-PLAN.csv`, дифф `DIFF-new-vs-38.csv`, сессии 1-6** |
|
||||
> | **[[personal/tech/music-broken-toload]]** | 29 битых/DRM файлов на перезагрузку |
|
||||
>
|
||||
> **Состояние:** скрипт готов и протестирован, **боевой прогон НЕ запущен — ждёт «go» от Alex.**
|
||||
> Боевой вход: `~/Downloads/music-tags/APPLY-PLAN-FINAL2.csv` (7861 строка).
|
||||
> Скрипты: `~/Automation/music-tags/`.
|
||||
> **Состояние:** план `APPLY-PLAN.csv` доведён до **0 пустых полей** и проверенного диффа
|
||||
> (`ПОТЕРЯНО 0 · ЛИШНИХ 0`). **Боевой прогон НЕ запущен — ждёт «go» от Alex.**
|
||||
> 🔴 Открыт класс дефекта **«`albumartist` размножен от чужого файла в корне папки»** (7 папок) —
|
||||
> см. сессию 6 в [[personal/plans/music-artist-albumartist-repair]].
|
||||
>
|
||||
> Боевой вход: `/Users/admin/Downloads/music-tags/APPLY-PLAN.csv` (**7861 строка**,
|
||||
> md5 `c8d43cc56d82cd35a67a0efe8173cd4b`). Рабочая папка — **`~/Downloads/music-tags/`**
|
||||
> (`~/milestones/` больше НЕ существует). Скрипты: `~/Automation/music-tags/`.
|
||||
>
|
||||
> ⚠️ Волна 38 (TIT2/TPE1/TALB/TRCK, 7041 файл) — **завершена**, описывается ниже как история.
|
||||
> Её дефекты (`apply_tags.py` испортил 16 не-MP3, `fix40.py` убил 40 MP3) разобраны в
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Детектор класса «albumartist размножен от чужого файла в корне папки».
|
||||
|
||||
Сессия 6, 2026-09-27. Нашёл 7 испорченных папок из 11 подозреваемых
|
||||
(The Prodigy->DJ Feel, Банд Эрос->VIP77, Дискотека Авария, Жуки,
|
||||
Потап & Каменских, Король и Шут, Ленинград).
|
||||
|
||||
ПРИЗНАК ПОРЧИ:
|
||||
для папки, где new_albumartist ОДИН на всю папку:
|
||||
он не совпадает с top-артистом папки
|
||||
И не совпадает с именем папки
|
||||
И совпадает с МИНОРИТАРНЫМ артистом папки
|
||||
-> ПОДОЗРЕВАЕМЫЙ
|
||||
|
||||
ЗАПУСК: python3 find_aa_hijack.py
|
||||
Не меняет файлы. Только печатает.
|
||||
"""
|
||||
import csv
|
||||
import collections
|
||||
import os
|
||||
|
||||
P = '/Users/admin/Downloads/music-tags/APPLY-PLAN.csv'
|
||||
rows = list(csv.DictReader(open(P, encoding='utf-8-sig', newline='')))
|
||||
|
||||
|
||||
def s(v):
|
||||
return (v or '').strip()
|
||||
|
||||
|
||||
by_folder = collections.defaultdict(list)
|
||||
for r in rows:
|
||||
by_folder[r['folder']].append(r)
|
||||
|
||||
suspects = []
|
||||
for folder, rs in sorted(by_folder.items()):
|
||||
aa_vals = collections.Counter(s(r['new_albumartist']) for r in rs if s(r['new_albumartist']))
|
||||
if len(aa_vals) != 1:
|
||||
continue # смешанные папки — отдельный случай
|
||||
aa = next(iter(aa_vals))
|
||||
art = collections.Counter(s(r['new_artist']) for r in rs if s(r['new_artist']))
|
||||
if not art:
|
||||
continue
|
||||
top_artist, top_n = art.most_common(1)[0]
|
||||
folder_name = os.path.basename(folder)
|
||||
if aa != top_artist and aa != folder_name and aa in art:
|
||||
minority = art[aa]
|
||||
if minority < top_n:
|
||||
suspects.append((folder, aa, top_artist, top_n, minority, len(rs)))
|
||||
|
||||
print(f"ПОДОЗРЕВАЕМЫХ ПАПОК: {len(suspects)}")
|
||||
print()
|
||||
for folder, aa, top, tn, mn, tot in suspects:
|
||||
print(f" albumartist={aa!r} (у {mn} из {tot})")
|
||||
print(f" должен быть {top!r} (у {tn})")
|
||||
print(f" {folder}")
|
||||
Reference in new issue
Block a user