Files
obsidian-vault/personal/tech/scripts/find_aa_hijack.py
T

61 lines
2.2 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Detector A1 — albumartist hijacked from a random ROOT file of the folder.
Rule (Alex): a track's albumartist = its OWN artist, unless the album is a genuine
compilation. A value taken from one stray file in the root must NOT be propagated.
Finds folders where the folder-level albumartist equals the `artist` of a MINORITY
file, but is neither the top artist nor the folder name.
Benign hits to review manually (NOT corruption):
- eponymous compilation (ДДТ/2008 L'Echoppe — files are a duet credit)
- letter sub-folder of a set (Сборка Песни для детей/L)
- category root (z Другое, Enigma, Ленинград)
- any folder the user explicitly decided (Re Sfaction, S Is Here)
Usage:
python3 find_aa_hijack.py [путь_к_APPLY-PLAN.csv]
"""
import sys
import csv
import collections
import os
P = sys.argv[1] if len(sys.argv) > 1 else '/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 # mixed folder — separate case
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)
# albumartist matches a MINORITY artist, not the top one, not the folder name
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}")