0.9.6.29: Shadowtree stabilisieren und Namensprüfung entfernen

This commit is contained in:
Terranom674
2026-08-19 19:55:32 +02:00
parent 55294643b4
commit 6df469ab7a
3 changed files with 228 additions and 343 deletions

View File

@@ -1,9 +1,9 @@
#!/usr/bin/env python3
"""Build a placeholder-backed local source tree from Nextcloud WebDAV.
This is intentionally additive: it does not replace the existing local-storage
connector path. It creates only tiny placeholder files plus a metadata mapping;
no Nextcloud original media is downloaded.
This creates only tiny placeholder files plus a metadata mapping; no Nextcloud
original media is downloaded. The authenticated Nextcloud user is never used as
an album name.
"""
from __future__ import annotations
@@ -26,8 +26,6 @@ from pathlib import Path, PurePosixPath
DAV = "DAV:"
OC = "http://owncloud.org/ns"
SUPPORTED_IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp"}
# 1x1 transparent GIF, 34 bytes. The filename keeps the remote extension;
# the placeholder exists only so Piwigo can discover the logical image entry.
PLACEHOLDER = base64.b64decode("R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==")
@@ -148,13 +146,7 @@ def link_placeholder(seed: Path, target: Path) -> None:
target.write_bytes(PLACEHOLDER)
def build_root(
client: WebDavClient,
remote_root: str,
local_root: Path,
seed: Path,
mapping: dict[str, dict[str, object]],
) -> tuple[int, int, int]:
def build_root(client: WebDavClient, remote_root: str, local_root: Path, seed: Path, mapping: dict[str, dict[str, object]]) -> tuple[int, int, int]:
files = 0
folders = 0
skipped = 0
@@ -253,22 +245,36 @@ def main() -> int:
mapping: dict[str, dict[str, object]] = {}
manifest: list[str] = []
total_files = total_folders = total_skipped = 0
used_names: set[str] = set()
used_fileids: set[int] = set()
for remote_root_raw in args.root:
remote_root = validate_relative(remote_root_raw)
current, _ = client.list_collection(remote_root)
current, root_children = client.list_collection(remote_root)
fileid = int(current["fileid"])
display = str(current.get("display_name", "")).strip() or (PurePosixPath(remote_root).name if remote_root else args.user)
local_name = f"root-{fileid}"
if local_name in used_names:
if fileid in used_fileids:
fail(f"duplicate selected Nextcloud root fileid: {fileid}")
used_names.add(local_name)
used_fileids.add(fileid)
local_name = f"root-{fileid}"
local_root = staging / local_name
files, folders, skipped = build_root(client, remote_root, local_root, seed, mapping)
total_files += files
total_folders += folders
total_skipped += skipped
if remote_root == "":
for child in sorted(root_children, key=lambda item: str(item.get("display_name", "")).casefold()):
name = safe_local_name(str(child.get("display_name", "")))
child_fileid = int(child.get("fileid", 0))
if child_fileid < 1:
fail(f"Nextcloud returned no stable fileid for root child {name!r}")
child_path = source_dir / local_name / name
if bool(child.get("is_dir")):
manifest.append(f"webdav:{child_fileid}\tfolder\t{name}\t{child_path}")
elif Path(name).suffix.lower() in SUPPORTED_IMAGE_EXTENSIONS:
manifest.append(f"webdav:{child_fileid}\tfile\t{name}\t{child_path}")
continue
display = str(current.get("display_name", "")).strip() or PurePosixPath(remote_root).name
manifest.append(f"webdav:{fileid}\tfolder\t{display}\t{source_dir / local_name}")
if previous.exists():

View File

@@ -252,8 +252,6 @@ try
);
decode_ws(http_request($base_url.'/ws.php?format=json', array('method'=>'bratonien.nc.syncProductive', 'site_id'=>$site_id), $headers));
$orphan = decode_ws(http_request($base_url.'/ws.php?format=json', array('method'=>'bratonien.nc.syncOrphans', 'site_id'=>$site_id, 'simulate'=>0), $headers));
// Entfernt alte technische bratonien-webdav-N Wrapper aus Site 1,
// nachdem deren generierte Verzeichnisse beim Reconcile entfernt wurden.
if ($site_id !== 1)
{
decode_ws(http_request($base_url.'/ws.php?format=json', array('method'=>'bratonien.nc.syncOrphans', 'site_id'=>1, 'simulate'=>0), $headers));
@@ -284,16 +282,31 @@ try
try
{
decode_ws(http_request($base_url.'/ws.php?format=json', array('method'=>'pwg.session.login', 'username'=>$fallback_user, 'password'=>$fallback_password), array(), $cookie_file));
http_request(
$base_url.'/admin.php?page=site_update&site='.$site_id,
array('sync'=>'files','display_info'=>1,'privacy_level'=>0,'sync_meta'=>1,'simulate'=>0,'subcats-included'=>1,'bratonien_connector'=>1,'submit'=>1),
// Der Fallback darf keinen zweiten Strukturpfad benutzen. Auch mit
// Benutzer/Passwort wird exakt derselbe Bratonien-Sync wie mit API-Key
// ausgefuehrt. Dadurch werden alte technische WebDAV-Kategorien entfernt
// und vorhandene Piwigo-Alben wiederverwendet.
decode_ws(http_request(
$base_url.'/ws.php?format=json',
array('method'=>'bratonien.nc.syncProductive', 'site_id'=>$site_id),
array(),
$cookie_file
);
$orphan = decode_ws(http_request($base_url.'/ws.php?format=json', array('method'=>'bratonien.nc.syncOrphans', 'site_id'=>$site_id, 'simulate'=>0), array(), $cookie_file));
));
$orphan = decode_ws(http_request(
$base_url.'/ws.php?format=json',
array('method'=>'bratonien.nc.syncOrphans', 'site_id'=>$site_id, 'simulate'=>0),
array(),
$cookie_file
));
if ($site_id !== 1)
{
decode_ws(http_request($base_url.'/ws.php?format=json', array('method'=>'bratonien.nc.syncOrphans', 'site_id'=>1, 'simulate'=>0), array(), $cookie_file));
decode_ws(http_request(
$base_url.'/ws.php?format=json',
array('method'=>'bratonien.nc.syncOrphans', 'site_id'=>1, 'simulate'=>0),
array(),
$cookie_file
));
}
$added = (int)($orphan['added_orphans'] ?? 0);
$deleted = (int)($orphan['deleted_orphans'] ?? 0);