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()
|
||||
Reference in New Issue
Block a user