feat: Display date-based directory name for public uploads

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2026-01-21 12:30:38 -07:00
parent 675080ae71
commit 506d658073

View File

@@ -471,11 +471,15 @@ def _verify_password(stored: str, pw: Optional[str]) -> bool:
except Exception:
return False
def get_or_create_album_dir(album_name: str, public_subfolder: Optional[str] = None, relative_path: Optional[str] = None) -> str:
"""Get or create a directory for an album, including subdirectories. Returns the path."""
def get_or_create_album_dir(album_name: str, public_subfolder: Optional[str] = None, relative_path: Optional[str] = None) -> Tuple[str, str]:
"""
Get or create a directory for an album, including subdirectories.
Returns a tuple of (full_save_path, display_album_name).
"""
if not album_name or not isinstance(album_name, str):
album_name = "public"
display_album_name = album_name
if album_name == "public":
try:
tz = pytz.timezone(SETTINGS.timezone)
@@ -484,19 +488,22 @@ def get_or_create_album_dir(album_name: str, public_subfolder: Optional[str] = N
slug = slugify(public_subfolder)
if slug:
today = f"{today}-{slug}"
display_album_name = today
base_save_dir = os.path.join("./data/uploads", "public", today)
except Exception as e:
logger.warning("Timezone logic failed, falling back to 'public' album. Timezone: %s. Error: %s", SETTINGS.timezone, e)
base_save_dir = os.path.join("./data/uploads", "public")
display_album_name = "public"
else:
safe_album_name = sanitize_filename(album_name)
display_album_name = safe_album_name
base_save_dir = os.path.join("./data/uploads", "albums", safe_album_name)
safe_subpath = get_safe_subpath(relative_path)
save_dir = os.path.join(base_save_dir, safe_subpath) if safe_subpath else base_save_dir
os.makedirs(save_dir, exist_ok=True)
return save_dir
return save_dir, display_album_name
async def send_progress(session_id: str, item_id: str, status: str, progress: int = 0, message: str = "", response_id: Optional[str] = None) -> None:
"""Push a progress update over WebSocket for one queue item."""
@@ -707,7 +714,7 @@ async def api_upload(
await send_progress(session_id, item_id, "error", 100, "Public uploads disabled")
return JSONResponse({"error": "public_upload_disabled"}, status_code=403)
try:
save_dir = get_or_create_album_dir(album_for_saving, public_folder_name, relative_path)
save_dir, display_album_name = get_or_create_album_dir(album_for_saving, public_folder_name, relative_path)
safe_name = sanitize_filename(os.path.basename(file.filename or "file"))
save_path = os.path.join(save_dir, safe_name)
# Avoid overwriting
@@ -720,10 +727,10 @@ async def api_upload(
with open(save_path, "wb") as f:
f.write(raw)
db_insert_upload(checksum, file.filename, size, device_asset_id, None, created_iso)
await add_file_to_batch(file.filename, size, album_for_saving, bool(invite_token))
await add_file_to_batch(file.filename, size, display_album_name, bool(invite_token))
await reset_telegram_debounce()
msg = f"Saved to {album_for_saving}/{os.path.basename(save_path)}"
msg = f"Saved to {display_album_name}/{os.path.basename(save_path)}"
await send_progress(session_id, item_id, "done", 100, msg)
# Increment invite usage on success
@@ -1044,7 +1051,7 @@ async def api_upload_chunk_complete(request: Request) -> JSONResponse:
return JSONResponse({"error": "public_upload_disabled"}, status_code=403)
try:
save_dir = get_or_create_album_dir(album_for_saving, public_folder_name, relative_path)
save_dir, display_album_name = get_or_create_album_dir(album_for_saving, public_folder_name, relative_path)
safe_name = sanitize_filename(os.path.basename(file_like_name or "file"))
save_path = os.path.join(save_dir, safe_name)
if os.path.exists(save_path):
@@ -1056,9 +1063,9 @@ async def api_upload_chunk_complete(request: Request) -> JSONResponse:
with open(save_path, "wb") as f:
f.write(raw)
db_insert_upload(checksum, file_like_name, file_size, device_asset_id, None, created_iso)
await add_file_to_batch(file_like_name, file_size, album_for_saving, bool(invite_token))
await add_file_to_batch(file_like_name, file_size, display_album_name, bool(invite_token))
msg = f"Saved to {album_for_saving}/{os.path.basename(save_path)}"
msg = f"Saved to {display_album_name}/{os.path.basename(save_path)}"
await send_progress(session_id_local, item_id_local, "done", 100, msg)
if invite_token:
@@ -1199,7 +1206,7 @@ async def api_albums_create(request: Request) -> JSONResponse:
if not name:
return JSONResponse({"error": "missing_name"}, status_code=400)
try:
get_or_create_album_dir(name)
_save_dir, _display_name = get_or_create_album_dir(name)
return JSONResponse({"id": name, "albumName": name}, status_code=201)
except Exception as e:
logger.exception("Create album directory failed: %s", e)
@@ -1295,7 +1302,7 @@ async def api_invites_create(request: Request) -> JSONResponse:
album_name = "public"
# Ensure album directory exists
get_or_create_album_dir(album_name)
_save_dir, _display_name = get_or_create_album_dir(album_name)
resolved_album_id = None # not used
# Compute expiry
expires_at = None