df
This commit is contained in:
@@ -2,9 +2,13 @@ from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from urllib.parse import quote
|
||||
|
||||
import httpx
|
||||
|
||||
from SYS.logger import debug, log
|
||||
@@ -1099,6 +1103,94 @@ class HydrusNetwork(Store):
|
||||
debug(f"{self._log_prefix()} get_file: url={browser_url}")
|
||||
return browser_url
|
||||
|
||||
def download_to_temp(
|
||||
self,
|
||||
file_hash: str,
|
||||
*,
|
||||
temp_root: Optional[Path] = None,
|
||||
) -> Optional[Path]:
|
||||
"""Download a Hydrus file to a temporary path for downstream uploads."""
|
||||
|
||||
try:
|
||||
client = self._client
|
||||
if client is None:
|
||||
return None
|
||||
|
||||
h = str(file_hash or "").strip().lower()
|
||||
if len(h) != 64 or not all(ch in "0123456789abcdef" for ch in h):
|
||||
return None
|
||||
|
||||
created_tmp = False
|
||||
base_tmp = Path(temp_root) if temp_root is not None else Path(
|
||||
tempfile.mkdtemp(prefix="hydrus-file-")
|
||||
)
|
||||
if temp_root is None:
|
||||
created_tmp = True
|
||||
base_tmp.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def _safe_filename(raw: str) -> str:
|
||||
cleaned = re.sub(r"[\\/:*?\"<>|]", "_", str(raw or "")).strip()
|
||||
if not cleaned:
|
||||
return h
|
||||
cleaned = cleaned.strip(". ") or h
|
||||
return cleaned
|
||||
|
||||
# Prefer ext/title from metadata when available.
|
||||
fname = h
|
||||
ext_val = ""
|
||||
try:
|
||||
meta = self.get_metadata(h) or {}
|
||||
if isinstance(meta, dict):
|
||||
title_val = str(meta.get("title") or "").strip()
|
||||
if title_val:
|
||||
fname = _safe_filename(title_val)
|
||||
ext_val = str(meta.get("ext") or "").strip().lstrip(".")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not fname:
|
||||
fname = h
|
||||
if ext_val and not fname.lower().endswith(f".{ext_val.lower()}"):
|
||||
fname = f"{fname}.{ext_val}"
|
||||
|
||||
try:
|
||||
file_url = client.file_url(h)
|
||||
except Exception:
|
||||
file_url = f"{self.URL.rstrip('/')}/get_files/file?hash={quote(h)}"
|
||||
|
||||
dest_path = base_tmp / fname
|
||||
with httpx.stream(
|
||||
"GET",
|
||||
file_url,
|
||||
headers={"Hydrus-Client-API-Access-Key": self.API},
|
||||
follow_redirects=True,
|
||||
timeout=60.0,
|
||||
verify=False,
|
||||
) as resp:
|
||||
resp.raise_for_status()
|
||||
with dest_path.open("wb") as fh:
|
||||
for chunk in resp.iter_bytes():
|
||||
if chunk:
|
||||
fh.write(chunk)
|
||||
|
||||
if dest_path.exists():
|
||||
return dest_path
|
||||
|
||||
if created_tmp:
|
||||
try:
|
||||
shutil.rmtree(base_tmp, ignore_errors=True)
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
except Exception as exc:
|
||||
log(f"{self._log_prefix()} download_to_temp failed: {exc}", file=sys.stderr)
|
||||
try:
|
||||
if temp_root is None and "base_tmp" in locals():
|
||||
shutil.rmtree(base_tmp, ignore_errors=True) # type: ignore[arg-type]
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def delete_file(self, file_identifier: str, **kwargs: Any) -> bool:
|
||||
"""Delete a file from Hydrus, then clear the deletion record.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user