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:
29
app/app.py
29
app/app.py
@@ -471,11 +471,15 @@ def _verify_password(stored: str, pw: Optional[str]) -> bool:
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_or_create_album_dir(album_name: str, public_subfolder: Optional[str] = None, relative_path: Optional[str] = None) -> str:
|
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 the path."""
|
"""
|
||||||
|
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):
|
if not album_name or not isinstance(album_name, str):
|
||||||
album_name = "public"
|
album_name = "public"
|
||||||
|
|
||||||
|
display_album_name = album_name
|
||||||
if album_name == "public":
|
if album_name == "public":
|
||||||
try:
|
try:
|
||||||
tz = pytz.timezone(SETTINGS.timezone)
|
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)
|
slug = slugify(public_subfolder)
|
||||||
if slug:
|
if slug:
|
||||||
today = f"{today}-{slug}"
|
today = f"{today}-{slug}"
|
||||||
|
display_album_name = today
|
||||||
base_save_dir = os.path.join("./data/uploads", "public", today)
|
base_save_dir = os.path.join("./data/uploads", "public", today)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("Timezone logic failed, falling back to 'public' album. Timezone: %s. Error: %s", SETTINGS.timezone, 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")
|
base_save_dir = os.path.join("./data/uploads", "public")
|
||||||
|
display_album_name = "public"
|
||||||
else:
|
else:
|
||||||
safe_album_name = sanitize_filename(album_name)
|
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)
|
base_save_dir = os.path.join("./data/uploads", "albums", safe_album_name)
|
||||||
|
|
||||||
safe_subpath = get_safe_subpath(relative_path)
|
safe_subpath = get_safe_subpath(relative_path)
|
||||||
save_dir = os.path.join(base_save_dir, safe_subpath) if safe_subpath else base_save_dir
|
save_dir = os.path.join(base_save_dir, safe_subpath) if safe_subpath else base_save_dir
|
||||||
|
|
||||||
os.makedirs(save_dir, exist_ok=True)
|
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:
|
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."""
|
"""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")
|
await send_progress(session_id, item_id, "error", 100, "Public uploads disabled")
|
||||||
return JSONResponse({"error": "public_upload_disabled"}, status_code=403)
|
return JSONResponse({"error": "public_upload_disabled"}, status_code=403)
|
||||||
try:
|
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"))
|
safe_name = sanitize_filename(os.path.basename(file.filename or "file"))
|
||||||
save_path = os.path.join(save_dir, safe_name)
|
save_path = os.path.join(save_dir, safe_name)
|
||||||
# Avoid overwriting
|
# Avoid overwriting
|
||||||
@@ -720,10 +727,10 @@ async def api_upload(
|
|||||||
with open(save_path, "wb") as f:
|
with open(save_path, "wb") as f:
|
||||||
f.write(raw)
|
f.write(raw)
|
||||||
db_insert_upload(checksum, file.filename, size, device_asset_id, None, created_iso)
|
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()
|
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)
|
await send_progress(session_id, item_id, "done", 100, msg)
|
||||||
|
|
||||||
# Increment invite usage on success
|
# 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)
|
return JSONResponse({"error": "public_upload_disabled"}, status_code=403)
|
||||||
|
|
||||||
try:
|
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"))
|
safe_name = sanitize_filename(os.path.basename(file_like_name or "file"))
|
||||||
save_path = os.path.join(save_dir, safe_name)
|
save_path = os.path.join(save_dir, safe_name)
|
||||||
if os.path.exists(save_path):
|
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:
|
with open(save_path, "wb") as f:
|
||||||
f.write(raw)
|
f.write(raw)
|
||||||
db_insert_upload(checksum, file_like_name, file_size, device_asset_id, None, created_iso)
|
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)
|
await send_progress(session_id_local, item_id_local, "done", 100, msg)
|
||||||
|
|
||||||
if invite_token:
|
if invite_token:
|
||||||
@@ -1199,7 +1206,7 @@ async def api_albums_create(request: Request) -> JSONResponse:
|
|||||||
if not name:
|
if not name:
|
||||||
return JSONResponse({"error": "missing_name"}, status_code=400)
|
return JSONResponse({"error": "missing_name"}, status_code=400)
|
||||||
try:
|
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)
|
return JSONResponse({"id": name, "albumName": name}, status_code=201)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception("Create album directory failed: %s", e)
|
logger.exception("Create album directory failed: %s", e)
|
||||||
@@ -1295,7 +1302,7 @@ async def api_invites_create(request: Request) -> JSONResponse:
|
|||||||
album_name = "public"
|
album_name = "public"
|
||||||
|
|
||||||
# Ensure album directory exists
|
# 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
|
resolved_album_id = None # not used
|
||||||
# Compute expiry
|
# Compute expiry
|
||||||
expires_at = None
|
expires_at = None
|
||||||
|
|||||||
Reference in New Issue
Block a user