notebookVb

This commit is contained in:
administrator
2026-06-06 06:26:42 +02:00
parent 82de38f02a
commit ee14efbd48
21 changed files with 923 additions and 0 deletions
+125
View File
@@ -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()
+48
View File
@@ -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()
+27
View File
@@ -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()
+32
View File
@@ -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.")
+41
View File
@@ -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.")
+40
View File
@@ -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()
+44
View File
@@ -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.")
+38
View File
@@ -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.")
+34
View File
@@ -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()