notebookVb
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
immich_upload.py — nahrava wanted fotky z DB fotky_buzalkovi do Immiche.
|
||||
Cte primo ze zalohy (NFS), nahrava KOPII pres Immich API. Zalohu nesaha.
|
||||
Resumable: tabulka immich_upload (zaloha_id -> asset id, status).
|
||||
|
||||
Spousti se v kontejneru python-runner:
|
||||
docker exec python-runner python3 /scripts/immich_upload.py --like '...%' --limit 200
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import requests
|
||||
import psycopg
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", dbname="fotky_buzalkovi")
|
||||
IMMICH = "http://192.168.1.76:8888"
|
||||
APIKEY = "UQV5PS1Td50hKOZTItnXEcXVkfQSUxcUH0XHZYxc"
|
||||
|
||||
SRC_PREFIX = "/mnt/user/ZalohaVsechObrazku" # jak je cesta v DB
|
||||
DST_PREFIX = "/mnt/ZalohaVsechObrazku" # jak ji vidi kontejner
|
||||
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--like", default=None, help="filtr na z.cesta_zalohy LIKE")
|
||||
ap.add_argument("--category", default=None, help="filtr na p.category")
|
||||
ap.add_argument("--limit", type=int, default=0)
|
||||
ap.add_argument("--dry-run", action="store_true")
|
||||
args = ap.parse_args()
|
||||
|
||||
conn = psycopg.connect(**DB, autocommit=True)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
CREATE TABLE IF NOT EXISTS immich_upload(
|
||||
zaloha_id bigint PRIMARY KEY,
|
||||
immich_id uuid,
|
||||
status text,
|
||||
uploaded_at timestamptz DEFAULT now()
|
||||
)
|
||||
""")
|
||||
|
||||
sql = """
|
||||
SELECT z.id, z.cesta_zalohy, p.taken_at
|
||||
FROM photos p
|
||||
JOIN zaloha_obrazku z ON p.zaloha_id = z.id
|
||||
LEFT JOIN immich_upload iu ON iu.zaloha_id = z.id
|
||||
WHERE p.wanted = TRUE AND iu.zaloha_id IS NULL
|
||||
"""
|
||||
params = []
|
||||
if args.category:
|
||||
sql += " AND p.category = %s"; params.append(args.category)
|
||||
if args.like:
|
||||
sql += " AND z.cesta_zalohy LIKE %s"; params.append(args.like)
|
||||
sql += " ORDER BY z.cesta_zalohy"
|
||||
if args.limit:
|
||||
sql += " LIMIT %s"; params.append(args.limit)
|
||||
|
||||
cur.execute(sql, params)
|
||||
rows = cur.fetchall()
|
||||
total = len(rows)
|
||||
print(f"K nahrani (jeste nenahrano): {total:,}")
|
||||
if args.dry_run:
|
||||
miss = sum(1 for _, c, _ in rows if not os.path.isfile(c.replace(SRC_PREFIX, DST_PREFIX, 1)))
|
||||
print(f"DRY-RUN: chybejicich souboru: {miss}")
|
||||
sys.exit(0)
|
||||
|
||||
sess = requests.Session()
|
||||
sess.headers.update({"x-api-key": APIKEY, "Accept": "application/json"})
|
||||
|
||||
created = dup = err = 0
|
||||
for i, (zid, cesta, taken) in enumerate(rows, 1):
|
||||
path = cesta.replace(SRC_PREFIX, DST_PREFIX, 1)
|
||||
if not os.path.isfile(path):
|
||||
err += 1
|
||||
print("MISSING:", path)
|
||||
continue
|
||||
st = os.stat(path)
|
||||
fmod = datetime.fromtimestamp(st.st_mtime, tz=timezone.utc)
|
||||
fcreated = taken if taken else fmod
|
||||
if fcreated.tzinfo is None:
|
||||
fcreated = fcreated.replace(tzinfo=timezone.utc)
|
||||
try:
|
||||
with open(path, "rb") as fh:
|
||||
r = sess.post(
|
||||
IMMICH + "/api/assets",
|
||||
files={"assetData": (os.path.basename(path), fh, "application/octet-stream")},
|
||||
data={
|
||||
"deviceAssetId": f"fb-{zid}",
|
||||
"deviceId": "fotky-buzalkovi",
|
||||
"fileCreatedAt": fcreated.isoformat(),
|
||||
"fileModifiedAt": fmod.isoformat(),
|
||||
"isFavorite": "false",
|
||||
},
|
||||
timeout=300,
|
||||
)
|
||||
j = r.json()
|
||||
status = j.get("status")
|
||||
aid = j.get("id")
|
||||
cur.execute(
|
||||
"""INSERT INTO immich_upload(zaloha_id, immich_id, status)
|
||||
VALUES (%s,%s,%s)
|
||||
ON CONFLICT (zaloha_id) DO UPDATE
|
||||
SET immich_id=EXCLUDED.immich_id, status=EXCLUDED.status, uploaded_at=now()""",
|
||||
(zid, aid, status),
|
||||
)
|
||||
if status == "created":
|
||||
created += 1
|
||||
elif status == "duplicate":
|
||||
dup += 1
|
||||
else:
|
||||
err += 1
|
||||
print("? neznamy status:", status, j)
|
||||
except Exception as e:
|
||||
err += 1
|
||||
print("ERR", zid, repr(e))
|
||||
if i % 50 == 0 or i == total:
|
||||
print(f"... {i}/{total} created={created} dup={dup} err={err}", flush=True)
|
||||
|
||||
print(f"\nHOTOVO. created={created} dup={dup} err={err}")
|
||||
conn.close()
|
||||
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
mark_cache_unwanted.py — Označí celé adresáře Tower/appdata a Tower/Sabnzbd
|
||||
jako nechceme (cache PhotoPrism/Immich + usenet download cache).
|
||||
|
||||
wanted=FALSE, category='Odpad-cache'
|
||||
|
||||
Idempotentní: díky filtru `category IS DISTINCT FROM 'Odpad-cache'` přepíše
|
||||
jen řádky, které ještě nejsou označené (vč. těch, co camera-rules omylem
|
||||
označily jako Rodina — jde o duplicitní cache kopie, ne originály).
|
||||
|
||||
Jediná DB session, autocommit — žádné paralelní běhy (deadlock).
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
DIRS = [
|
||||
("Tower/appdata (PhotoPrism/Immich cache)",
|
||||
"/mnt/user/ZalohaVsechObrazku/Tower/appdata%"),
|
||||
("Tower/Sabnzbd (usenet download cache)",
|
||||
"/mnt/user/ZalohaVsechObrazku/Tower/Sabnzbd%"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
total = 0
|
||||
for popis, like in DIRS:
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE,
|
||||
category = 'Odpad-cache'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.category IS DISTINCT FROM 'Odpad-cache'
|
||||
""", (like,))
|
||||
print(f" {popis}: {cur.rowcount:,} řádků aktualizováno")
|
||||
total += cur.rowcount
|
||||
|
||||
print(f"\nHotovo. Celkem aktualizováno: {total:,} řádků.")
|
||||
conn.close()
|
||||
@@ -0,0 +1,48 @@
|
||||
"""
|
||||
mark_colddata_junk.py — Označí jasně odpadní podsložky v Tower1/#ColdData
|
||||
jako nechceme. NEoznačuje SynologyMaly, Honza, VladkoSoubory, Qnap, Tatinek,
|
||||
DedupPhotos (ty se zkoumají zvlášť).
|
||||
|
||||
Kategorie:
|
||||
Porno*, MadelineIsWicked -> 'Porno'
|
||||
000 TORENT OBRAZKY, MoMA, Dali,
|
||||
hudební alba, eBooky -> 'Odpad-torrent'
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
BASE = "/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/"
|
||||
|
||||
# (popis, LIKE vzor, kategorie)
|
||||
RULES = [
|
||||
("Porno", BASE + "Porno/%", "Porno"),
|
||||
("Porno1", BASE + "Porno1/%", "Porno"),
|
||||
("MadelineIsWicked", BASE + "MadelineIsWicked/%", "Porno"),
|
||||
("000 TORENT OBRAZKY",BASE + "000 TORENT OBRAZKY/%","Odpad-torrent"),
|
||||
("Museum of Modern Art NY", BASE + "Museum of Modern Art NY/%", "Odpad-torrent"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
total = 0
|
||||
for popis, like, kat in RULES:
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE, category = %s
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.category IS DISTINCT FROM %s
|
||||
""", (kat, like, kat))
|
||||
print(f" {popis:28s} -> {kat:14s}: {cur.rowcount:,}")
|
||||
total += cur.rowcount
|
||||
|
||||
print(f"\nHotovo. Celkem: {total:,} řádků označeno jako odpad.")
|
||||
conn.close()
|
||||
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
mark_colddata_zbytek.py — Zbytek #ColdData (vše dosud neroztříděné):
|
||||
DropBox (software help obrázky), hudební alba, Salvador Dali, eBooky,
|
||||
Truecrypt, Delikatesy ... -> odpad.
|
||||
wanted=FALSE, category='Odpad-cache'
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE, category = 'Odpad-cache'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE '/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/%'
|
||||
AND p.category IS NULL
|
||||
""")
|
||||
|
||||
print(f"#ColdData zbytek -> Odpad-cache: {cur.rowcount:,} řádků")
|
||||
conn.close()
|
||||
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
mark_dedup_rodina.py — DedupPhotos (Samsung S7 Edge 2019, 285 ks).
|
||||
Ověřeno: všechny unikátní, žádné duplikáty jinde -> Rodina.
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = TRUE, category = 'Rodina'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND (p.wanted = FALSE OR p.category IS DISTINCT FROM 'Rodina')
|
||||
""", ('/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/DedupPhotos/%',))
|
||||
|
||||
print(f"DedupPhotos -> Rodina: {cur.rowcount:,} řádků")
|
||||
conn.close()
|
||||
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
mark_ltbs_212.py — Potvrzeno uživatelem:
|
||||
LTBS -> Rodina (rodinné fotky, názvy obsahují BUZALKA)
|
||||
212 -> Odpad-dokumenty (skeny smluv Confidentiality Agreement)
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
B = "/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/"
|
||||
RULES = [
|
||||
("LTBS", B + "LTBS/%", True, "Rodina"),
|
||||
("212", B + "212/%", False, "Odpad-dokumenty"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
for popis, like, wanted, kat in RULES:
|
||||
cur.execute("""
|
||||
UPDATE photos p SET wanted=%s, category=%s
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id=z.id AND z.cesta_zalohy LIKE %s
|
||||
AND (p.wanted IS DISTINCT FROM %s OR p.category IS DISTINCT FROM %s)
|
||||
""", (wanted, kat, like, wanted, kat))
|
||||
print(f" {popis:6s} -> {kat:16s} (wanted={wanted}): {cur.rowcount:,}")
|
||||
conn.close()
|
||||
print("Hotovo.")
|
||||
@@ -0,0 +1,41 @@
|
||||
"""
|
||||
mark_pomoc.py — Tower1/#ColdData/pomoc, potvrzeno uživatelem:
|
||||
Samsung GT-S5230 (s EXIF) -> Rodina
|
||||
porno snapshoty (bez EXIF) -> Porno
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
P = "/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/pomoc/%"
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
# Samsung (s EXIF) -> Rodina
|
||||
cur.execute("""
|
||||
UPDATE photos p SET wanted=TRUE, category='Rodina'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id=z.id AND z.cesta_zalohy LIKE %s
|
||||
AND p.camera_make IS NOT NULL
|
||||
AND (p.wanted=FALSE OR p.category IS DISTINCT FROM 'Rodina')
|
||||
""", (P,))
|
||||
print(f" pomoc Samsung -> Rodina: {cur.rowcount:,}")
|
||||
|
||||
# porno (bez EXIF) -> Porno
|
||||
cur.execute("""
|
||||
UPDATE photos p SET wanted=FALSE, category='Porno'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id=z.id AND z.cesta_zalohy LIKE %s
|
||||
AND p.camera_make IS NULL
|
||||
AND p.category IS DISTINCT FROM 'Porno'
|
||||
""", (P,))
|
||||
print(f" pomoc porno -> Porno : {cur.rowcount:,}")
|
||||
|
||||
conn.close()
|
||||
print("Hotovo.")
|
||||
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
mark_qnap_exif_odpad.py — Qnap fotky s EXIF jsou CD inlety/obaly -> odpad.
|
||||
Potvrzeno uživatelem přes náhled (81 ks).
|
||||
wanted=FALSE, category='Odpad-obaly'
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE, category = 'Odpad-obaly'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.camera_make IS NOT NULL
|
||||
AND p.category IS DISTINCT FROM 'Odpad-obaly'
|
||||
""", ('/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/Qnap/%',))
|
||||
|
||||
print(f"Qnap (EXIF) -> Odpad-obaly: {cur.rowcount:,} řádků")
|
||||
conn.close()
|
||||
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
mark_qnap_nepotrebne.py — Qnap_nepotrebne (COMPLETED TORRENTS: komiksy,
|
||||
učebnice, software) -> odpad. Potvrzeno uživatelem.
|
||||
wanted=FALSE, category='Odpad-torrent'
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE, category = 'Odpad-torrent'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.category IS DISTINCT FROM 'Odpad-torrent'
|
||||
""", ('/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/Qnap_nepotrebne/%',))
|
||||
|
||||
print(f"Qnap_nepotrebne -> Odpad-torrent: {cur.rowcount:,} řádků")
|
||||
conn.close()
|
||||
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
mark_qnap_zbytek_odpad.py — Zbytek Qnap bez EXIF (obaly alb, downloads,
|
||||
kurzové thumbnaily) -> odpad. Potvrzeno uživatelem.
|
||||
wanted=FALSE, category='Odpad-cache'
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE, category = 'Odpad-cache'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.camera_make IS NULL
|
||||
AND p.category IS DISTINCT FROM 'Odpad-cache'
|
||||
""", ('/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/Qnap/%',))
|
||||
|
||||
print(f"Qnap (zbytek bez EXIF) -> Odpad-cache: {cur.rowcount:,} řádků")
|
||||
conn.close()
|
||||
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
mark_synology_photo_rodina.py — Označí celý rodinný fotoarchiv
|
||||
Tower1/#ColdData/SynologyMaly/photo/ jako Rodina.
|
||||
|
||||
Potvrzeno uživatelem přes náhled. Foťáky 1998-2015 (Canon S40/A40/IXUS,
|
||||
Nikon D80, iPhony, Lumia...). 99 % má EXIF, archiv je unikátní (bez duplikátů).
|
||||
|
||||
wanted=TRUE, category='Rodina'
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = TRUE, category = 'Rodina'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND (p.wanted = FALSE OR p.category IS DISTINCT FROM 'Rodina')
|
||||
""", ('/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/SynologyMaly/photo/%',))
|
||||
|
||||
print(f"SynologyMaly/photo -> Rodina: {cur.rowcount:,} řádků (wanted=TRUE)")
|
||||
conn.close()
|
||||
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
mark_synology_rodina.py — #Synology fotoarchivy potvrzené uživatelem -> Rodina:
|
||||
#SERVER/Y/HD02#FOTKY (~30 789)
|
||||
#SERVER/Y/HD02#FOTKY MAMKA (~1 167)
|
||||
DropboxFotky (~14 882)
|
||||
HD02#DVD OSOBNI (~5 834)
|
||||
Fotky (~2 138)
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
S = "/mnt/user/ZalohaVsechObrazku/Tower1/#Synology/Public/"
|
||||
LIKES = [
|
||||
("HD02#FOTKY", S + "#SERVER/Y/HD02#FOTKY/%"),
|
||||
("HD02#FOTKY MAMKA", S + "#SERVER/Y/HD02#FOTKY MAMKA/%"),
|
||||
("DropboxFotky", S + "DropboxFotky/%"),
|
||||
("HD02#DVD OSOBNI", S + "HD02#DVD OSOBNI/%"),
|
||||
("Fotky", S + "Fotky/%"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
total = 0
|
||||
for popis, like in LIKES:
|
||||
cur.execute("""
|
||||
UPDATE photos p SET wanted=TRUE, category='Rodina'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id=z.id AND z.cesta_zalohy LIKE %s
|
||||
AND (p.wanted=FALSE OR p.category IS DISTINCT FROM 'Rodina')
|
||||
""", (like,))
|
||||
print(f" {popis:18s}: {cur.rowcount:,}")
|
||||
total += cur.rowcount
|
||||
|
||||
print(f"\nHotovo. Celkem nově/změněno na Rodina: {total:,}")
|
||||
conn.close()
|
||||
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
mark_synology_x_odpad.py — Označí Tower1/#ColdData/SynologyMaly/Public/X/
|
||||
jako odpad (skenovaná série publikací e0xxx, 3744x5616, bez EXIF).
|
||||
Potvrzeno uživatelem přes náhled.
|
||||
|
||||
wanted=FALSE, category='Odpad-sken'
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE, category = 'Odpad-sken'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.category IS DISTINCT FROM 'Odpad-sken'
|
||||
""", ('/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/SynologyMaly/Public/X/%',))
|
||||
|
||||
print(f"SynologyMaly/Public/X -> Odpad-sken: {cur.rowcount:,} řádků")
|
||||
conn.close()
|
||||
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
mark_synology_zbytek.py — Dokončí SynologyMaly:
|
||||
Public/Dropbox -> Rodina (chceme, potvrzeno uživatelem)
|
||||
music/web/video -> Odpad-cache (obaly, web obrázky)
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
BASE = "/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/SynologyMaly/"
|
||||
|
||||
RULES = [
|
||||
("Public/Dropbox", BASE + "Public/Dropbox/%", True, "Rodina"),
|
||||
("music", BASE + "music/%", False, "Odpad-cache"),
|
||||
("web", BASE + "web/%", False, "Odpad-cache"),
|
||||
("video", BASE + "video/%", False, "Odpad-cache"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
for popis, like, wanted, kat in RULES:
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = %s, category = %s
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND (p.wanted IS DISTINCT FROM %s OR p.category IS DISTINCT FROM %s)
|
||||
""", (wanted, kat, like, wanted, kat))
|
||||
print(f" {popis:16s} -> {kat:12s} (wanted={wanted}): {cur.rowcount:,}")
|
||||
|
||||
conn.close()
|
||||
print("Hotovo.")
|
||||
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
mark_tatinek_cast1.py — Tatinek U, rozhodnuté části (potvrzeno uživatelem):
|
||||
Fractal (iPhone 13) -> Rodina (chceme)
|
||||
DarthAnihilator + Screenshots-> Odpad-screenshot
|
||||
Duplicates/Compass (dokumenty)-> Odpad-dokumenty
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
T = "/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/Tatinek U/"
|
||||
|
||||
RULES = [
|
||||
("Fractal (iPhone)", T + "D/!!!Days/%Fractal%", True, "Rodina"),
|
||||
("DarthAnihilator", T + "DarthAnihilator/%", False, "Odpad-screenshot"),
|
||||
("Screenshots", T + "Screenshots/%", False, "Odpad-screenshot"),
|
||||
("Compass dokumenty", T + "Duplicates/Compass/%",False, "Odpad-dokumenty"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
for popis, like, wanted, kat in RULES:
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = %s, category = %s
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND (p.wanted IS DISTINCT FROM %s OR p.category IS DISTINCT FROM %s)
|
||||
""", (wanted, kat, like, wanted, kat))
|
||||
print(f" {popis:20s} -> {kat:18s} (wanted={wanted}): {cur.rowcount:,}")
|
||||
|
||||
conn.close()
|
||||
print("Hotovo.")
|
||||
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
mark_tatinek_zbytek.py — Zbytek Tatinek U (produktové letáky, Sudoku,
|
||||
screenshoty, web obrázky) -> odpad. Potvrzeno uživatelem.
|
||||
Vše krom Fractal/DarthAnihilator/Screenshots/Compass -> Odpad-cache.
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE, category = 'Odpad-cache'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE '/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/Tatinek U/%'
|
||||
AND z.cesta_zalohy NOT LIKE '%Fractal%'
|
||||
AND z.cesta_zalohy NOT LIKE '%/DarthAnihilator/%'
|
||||
AND z.cesta_zalohy NOT LIKE '%/Screenshots/%'
|
||||
AND z.cesta_zalohy NOT LIKE '%/Duplicates/Compass/%'
|
||||
AND p.category IS DISTINCT FROM 'Odpad-cache'
|
||||
""")
|
||||
|
||||
print(f"Tatinek U (zbytek) -> Odpad-cache: {cur.rowcount:,} řádků")
|
||||
conn.close()
|
||||
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
mark_torrents_unwanted.py — Označí celé Tower/Torrents a Tower1/Torrents
|
||||
jako nechceme (stažený torrent obsah: komiksy, vystřihovánky, speleologie,
|
||||
porno, textury...). Žádné rodinné originály (ověřeno pixel-hashem + adresáři).
|
||||
|
||||
wanted=FALSE, category='Odpad-torrent'
|
||||
|
||||
Idempotentní + jedna session, autocommit (žádné paralelní běhy → bez deadlocku).
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
DIRS = [
|
||||
("Tower/Torrents", "/mnt/user/ZalohaVsechObrazku/Tower/Torrents%"),
|
||||
("Tower1/Torrents", "/mnt/user/ZalohaVsechObrazku/Tower1/Torrents%"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
total = 0
|
||||
for popis, like in DIRS:
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = FALSE,
|
||||
category = 'Odpad-torrent'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.category IS DISTINCT FROM 'Odpad-torrent'
|
||||
""", (like,))
|
||||
print(f" {popis}: {cur.rowcount:,} řádků")
|
||||
total += cur.rowcount
|
||||
|
||||
print(f"\nHotovo. Celkem: {total:,} řádků → wanted=FALSE, category='Odpad-torrent'")
|
||||
conn.close()
|
||||
@@ -0,0 +1,44 @@
|
||||
"""
|
||||
mark_webs.py — #Synology/.../#SERVER/Y/WEBS (starý web Buzalka.cz/.com):
|
||||
galerijní alba (g1/Albums, g2data/albums) -> Rodina (potvrzeno uživatelem)
|
||||
zbytek (web šablony, moduly, skiny, e-shop) -> Odpad-cache
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
WEBS = "/mnt/user/ZalohaVsechObrazku/Tower1/#Synology/Public/#SERVER/Y/WEBS/%"
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
# Galerijní alba -> Rodina
|
||||
cur.execute("""
|
||||
UPDATE photos p SET wanted=TRUE, category='Rodina'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id=z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND (z.cesta_zalohy LIKE '%%/Albums/%%' OR z.cesta_zalohy LIKE '%%/g2data/albums/%%')
|
||||
AND (p.wanted=FALSE OR p.category IS DISTINCT FROM 'Rodina')
|
||||
""", (WEBS,))
|
||||
print(f" WEBS galerie -> Rodina: {cur.rowcount:,}")
|
||||
|
||||
# Zbytek WEBS -> Odpad-cache
|
||||
cur.execute("""
|
||||
UPDATE photos p SET wanted=FALSE, category='Odpad-cache'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id=z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND z.cesta_zalohy NOT LIKE '%%/Albums/%%'
|
||||
AND z.cesta_zalohy NOT LIKE '%%/g2data/albums/%%'
|
||||
AND p.category IS DISTINCT FROM 'Odpad-cache'
|
||||
""", (WEBS,))
|
||||
print(f" WEBS zbytek -> Odpad-cache: {cur.rowcount:,}")
|
||||
|
||||
conn.close()
|
||||
print("Hotovo.")
|
||||
@@ -0,0 +1,38 @@
|
||||
"""
|
||||
mark_xperie_vladko.py — Osobní složky v #ColdData, chceme zachovat:
|
||||
Honza fotky z Xperie -> kamarad Jan Luxemburk -> category 'Kamaradi'
|
||||
VladkoSoubory -> syn Vladimir Buzalka ml -> category 'Rodina'
|
||||
Obojí wanted=TRUE (potvrzeno uživatelem).
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
BASE = "/mnt/user/ZalohaVsechObrazku/Tower1/#ColdData/"
|
||||
|
||||
RULES = [
|
||||
("Honza fotky z Xperie", BASE + "Honza fotky z Xperie/%", "Kamaradi"),
|
||||
("VladkoSoubory", BASE + "VladkoSoubory/%", "Rodina"),
|
||||
]
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
for popis, like, kat in RULES:
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = TRUE, category = %s
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND (p.wanted = FALSE OR p.category IS DISTINCT FROM %s)
|
||||
""", (kat, like, kat))
|
||||
print(f" {popis:22s} -> {kat:10s}: {cur.rowcount:,}")
|
||||
|
||||
conn.close()
|
||||
print("Hotovo.")
|
||||
@@ -0,0 +1,34 @@
|
||||
"""
|
||||
restore_maminka.py — Vrátí jedinečné iPhone fotky z
|
||||
Tower/appdata/photoprism/sidecar/Maminka zpět na wanted=TRUE, category='Rodina'.
|
||||
|
||||
Tyto soubory jsem omylem označil jako Odpad-cache, ačkoli jde o jediné kopie
|
||||
rodinných fotek v záloze (žádný originál jinde neexistuje).
|
||||
|
||||
Filtr camera_make IS NOT NULL = bereme jen skutečné fotky, ne případné
|
||||
technické soubory v té složce.
|
||||
"""
|
||||
import sys
|
||||
import psycopg2
|
||||
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
|
||||
DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
|
||||
password="Vlado7309208104++", database="fotky_buzalkovi")
|
||||
|
||||
conn = psycopg2.connect(**DB)
|
||||
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
UPDATE photos p
|
||||
SET wanted = TRUE,
|
||||
category = 'Rodina'
|
||||
FROM zaloha_obrazku z
|
||||
WHERE p.zaloha_id = z.id
|
||||
AND z.cesta_zalohy LIKE %s
|
||||
AND p.camera_make IS NOT NULL
|
||||
""", ('/mnt/user/ZalohaVsechObrazku/Tower/appdata/photoprism/sidecar/Maminka%',))
|
||||
|
||||
print(f"Vráceno na Rodina: {cur.rowcount:,} řádků (wanted=TRUE, category='Rodina')")
|
||||
conn.close()
|
||||
@@ -104,6 +104,121 @@ Tyto cesty **nechceme** — `wanted` zůstane FALSE, nezpracovávat:
|
||||
|
||||
---
|
||||
|
||||
## Session 2026-06-05
|
||||
|
||||
### Nástroje — nový web preview na Toweru
|
||||
|
||||
- **`00 PictureCollector/preview_server.py`** — HTTP server běžící v Docker kontejneru
|
||||
`python-runner` na Toweru. Renderuje thumbnaily lokálně (rychlé), má lightbox
|
||||
(klik = plné rozlišení přes `/image?id=`).
|
||||
- URL: `http://192.168.1.76:8766/preview?ids=101,202,303&thumb=320`
|
||||
- Kontejner má mount `/mnt/remotes/TOWER1.LAN_ZalohaVsechObrazku` → `/mnt/ZalohaVsechObrazku:ro`
|
||||
- Knihovny v image: `psycopg` (v3!), `Pillow` (zabakováno přes `docker commit`)
|
||||
- **MCP konektor `fotky-buzalkovi`** — `query/tables/describe_table/stats`. SQL dotazy
|
||||
pouštím přímo, bez mezikroku.
|
||||
|
||||
### Pracovní metodika (důležité!)
|
||||
|
||||
- **NEoznačovat nechtěné proaktivně** — vždy jen po explicitním pokynu uživatele.
|
||||
- Před každým hromadným označením složky za odpad: **ověřit jedinečnost přes
|
||||
pixel/file-hash** (`sha256_pixels`, `sha256_file`). V cache/odpadních složkách se
|
||||
můžou skrývat unikátní rodinné fotky (viz „Maminka" níže).
|
||||
- UPDATE pouštět vždy jako **jedna session, autocommit** — paralelní běhy způsobují
|
||||
deadlock. Před každým během kontrola `pg_stat_activity` na zaseklé UPDATE.
|
||||
- Marker skripty: `mark_*.py` v `00 PictureCollector/` (idempotentní přes filtr
|
||||
`category IS DISTINCT FROM ...`).
|
||||
|
||||
### Kategorie (rozšířený číselník)
|
||||
|
||||
| category | wanted | význam |
|
||||
|---|---|---|
|
||||
| `Rodina` | TRUE | rodinné fotky |
|
||||
| `Kamaradi` | TRUE | fotky kamarádů (Jan Luxemburk – Xperie) |
|
||||
| `Fotopast` | TRUE | fotopast |
|
||||
| `Odpad-cache` | FALSE | cache aplikací, obaly, web obrázky |
|
||||
| `Odpad-torrent` | FALSE | stažené torrenty (komiksy, vystřihovánky, software) |
|
||||
| `Odpad-sken` | FALSE | skenované publikace (série stránek) |
|
||||
| `Odpad-obaly` | FALSE | CD inlety/obaly s EXIF |
|
||||
| `Odpad-dokumenty` | FALSE | skeny dokumentů/smluv |
|
||||
| `Odpad-screenshot` | FALSE | screenshoty z her/aplikací |
|
||||
| `Porno` | FALSE | porno |
|
||||
| `Skener-nechceme` | FALSE | skenery (viz session 2026-06-04) |
|
||||
|
||||
### Zpracované velké složky
|
||||
|
||||
| Složka | Fotek | Výsledek |
|
||||
|---|---:|---|
|
||||
| **Tower/appdata** | 1 006 032 | odpad (Odpad-cache); **zachráněno 2 274** fotek Maminky (iPhone 12) z `photoprism/sidecar/Maminka` → Rodina |
|
||||
| **Tower/Sabnzbd** | 48 442 | celé odpad (usenet downloads, profi Nikon D5/D4 = stažené, ne rodina) |
|
||||
| **Tower/Torrents + Tower1/Torrents** | 100 938 | celé odpad (Odpad-torrent) |
|
||||
| **Tower1/#ColdData** | 84 374 | roztříděno 100 %, viz níže |
|
||||
| **Tower1/#Synology** | 66 462 | rozpracováno (~95 %), viz níže |
|
||||
|
||||
### #Synology — rozpracováno (Public/...)
|
||||
|
||||
Velký rodinný NAS fotoarchiv. Hash-check potvrdil, že `HD02#FOTKY` je z 99,6 %
|
||||
**unikátní** (jen 132 fotek má kopii jinde) — není to duplikát jiné zálohy.
|
||||
|
||||
**Rodina (chceme) — HOTOVO:**
|
||||
- `#SERVER/Y/HD02#FOTKY` (30 789) — hlavní archiv 2008–2020
|
||||
- `#SERVER/Y/HD02#FOTKY MAMKA` (1 167)
|
||||
- `DropboxFotky` (14 882)
|
||||
- `HD02#DVD OSOBNI` (5 834)
|
||||
- `Fotky` (2 138)
|
||||
- `#SERVER/Y/WEBS` galerijní alba (906) — starý web Buzalka.com/Gallery2,
|
||||
alba akcí (USA 2006, lyžování Stoderzinken 2007, Orlík, Střetávka…)
|
||||
|
||||
**Odpad — HOTOVO:**
|
||||
- `#SERVER/Y/WEBS` zbytek (2 153) — web šablony/skiny/moduly Buzalka.cz e-shop → Odpad-cache
|
||||
|
||||
**JEŠTĚ NEROZHODNUTO (zbývá ~9 200):**
|
||||
- `AFotkyFotky` (4 550, 2 245 EXIF) — pravděpodobně fotky
|
||||
- `#SERVER/JNJ` (1 835, 45 modelů) — smíšené
|
||||
- `#SERVER/E` (1 629) — smíšené
|
||||
- `VideoMichalkaiCloud` (277) — Michalka iCloud, pravděpodobně rodina
|
||||
- `GoPro` (70) — pravděpodobně rodina
|
||||
- drobnosti (`###StatSoft`, `#SOFTWARE`, `HD02#AUDIO CD A DVD`, `#Kurzy`, `X`…) ~220 → odpad
|
||||
|
||||
### #ColdData — detailní rozpad
|
||||
|
||||
**Rodina (chceme):**
|
||||
- `SynologyMaly/photo` (24 198) + `SynologyMaly/Public/Dropbox` (447) — rodinný archiv 1998–2015 (Canon S40/A40/IXUS, Nikon D80, iPhony, Lumia). Unikátní (bez duplikátů).
|
||||
- `VladkoSoubory` (871) — syn Vladimír Buzalka ml.
|
||||
- `DedupPhotos` (285) — Samsung S7 Edge 2019, ověřeno unikátní.
|
||||
- `LTBS` (40) — rodina (názvy souborů obsahují BUZALKA).
|
||||
- `Tatinek U/.../Fractal` (19) — iPhone 13, táta.
|
||||
- `pomoc` Samsung GT-S5230 (26) — rodina.
|
||||
|
||||
**Kamaradi (chceme):** `Honza fotky z Xperie` (2 047) — kamarád Jan Luxemburk.
|
||||
|
||||
**Odpad:**
|
||||
- `Porno`, `Porno1`, `MadelineIsWicked` → Porno
|
||||
- `000 TORENT OBRAZKY`, `Qnap_nepotrebne` (X-Men komiksy, učebnice, software) → Odpad-torrent
|
||||
- `SynologyMaly/Public/X` (9 134, série e0xxx skenů) → Odpad-sken
|
||||
- `Qnap` (MP3 obaly, downloads, 81 EXIF CD inletů) → Odpad-cache/Odpad-obaly
|
||||
- `Museum of Modern Art NY`, hudební alba, Salvador Dali, eBooky, Truecrypt, `DropBox` (software help obrázky) → Odpad-cache
|
||||
- `Tatinek U` Compass dokumenty + `212` smlouvy → Odpad-dokumenty; DarthAnihilator/Screenshots → Odpad-screenshot
|
||||
- `pomoc` LegalPorno/Kink snapshoty (28) → Porno
|
||||
|
||||
**Výsledek #ColdData:** Rodina 25 889 · Kamaradi 2 047 · Porno 23 502 · Odpad-torrent 21 300 · Odpad-sken 9 134 · Odpad-cache 2 269 · ostatní odpad 228.
|
||||
|
||||
### Poučení
|
||||
|
||||
- **Cache/download složky ≠ čistý odpad.** PhotoPrism si do `sidecar/` ukládá unikátní
|
||||
JPEG kopie fotek, jejichž originály v záloze nejsou → před smazáním vždy hash-check.
|
||||
- Camera-rules (např. „všechny Nikon D5/D4 = Rodina") dávají **false-positives** ve
|
||||
stažených složkách → path má přednost, ale ověřit obsah.
|
||||
|
||||
### Na řadě
|
||||
|
||||
- [ ] **Dokončit #Synology** — zbývá ~9 200: `AFotkyFotky`, `JNJ`, `E`,
|
||||
`VideoMichalkaiCloud`, `GoPro` (náhledy → rozhodnout), drobnosti → odpad
|
||||
- [ ] Velké zbývající: `TW22/D` (63 706), `Tower1/#Pomoc` (34 500), `Tower1/#Synologymaly` (29 934)
|
||||
- [ ] Dokončit Canony (a pak ostatní značky foťáků)
|
||||
- [ ] „BEZ KAMERY" skupina (path-based)
|
||||
|
||||
---
|
||||
|
||||
## Backlog otevřených otázek
|
||||
|
||||
1. Co s "sirotky" bez EXIF — `mtime` / odmítnout / označit?
|
||||
|
||||
Reference in New Issue
Block a user