From cdee69947d1489f8572f406e1edf05632c97b40e Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 18 Mar 2026 23:28:00 -0400 Subject: [PATCH] fix: replace get_event_loop with get_running_loop and utcnow consistently --- backend/app/services/gallery_dl.py | 36 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/backend/app/services/gallery_dl.py b/backend/app/services/gallery_dl.py index b852658..b1bc31a 100644 --- a/backend/app/services/gallery_dl.py +++ b/backend/app/services/gallery_dl.py @@ -16,6 +16,7 @@ from pathlib import Path from typing import Optional from app.config import get_settings +from app.models.base import utcnow logger = logging.getLogger(__name__) @@ -369,6 +370,22 @@ class GalleryDLService: ] has_actual_error = any(err in combined for err in actual_error_indicators) + # Per-item access warnings (e.g., "Not allowed to view post" on Patreon + # /c/user/posts URLs) are normal in multi-post downloads where some posts + # are paywalled. These shouldn't block skip detection when the overall + # download proceeded successfully with skips. + if has_actual_error and (skip_line_count > 0 or has_skip_text): + per_item_patterns = ["not allowed to view", "unable to get post"] + error_lines = [ + line for line in combined.split('\n') + if any(ind in line for ind in actual_error_indicators) + ] + if error_lines and all( + any(p in line for p in per_item_patterns) + for line in error_lines + ): + has_actual_error = False + # If we have skip evidence and no real errors, it's no_new_content if (skip_line_count > 0 or has_skip_text) and not has_actual_error: return ErrorType.NO_NEW_CONTENT, "No new content to download" @@ -487,9 +504,11 @@ class GalleryDLService: if "no suitable" in combined or "unsupported" in combined or "no extractor" in combined: return ErrorType.UNSUPPORTED_URL, "URL format not supported by gallery-dl" - # If we got here with return code 1 and saw some activity but no error patterns matched, - # it's likely just no new content (gallery-dl returns 1 when nothing to download) - if return_code == 1 and stdout.strip() and not has_actual_error: + # If we got here with a non-catastrophic return code, saw skip activity, and no + # specific error patterns matched, it's likely just no new content. + # gallery-dl exit codes: 1 = some extractions skipped, 4 = no URLs extracted + # (common with /c/user/posts Patreon URLs where all content is already archived) + if return_code in (1, 4) and (skip_line_count > 0 or has_skip_text) and not has_actual_error: return ErrorType.NO_NEW_CONTENT, "No new content to download" # Final fallback - genuine unknown error @@ -537,10 +556,9 @@ class GalleryDLService: Downloads are saved to: {download_path}/{subscription_name}/{platform}/{post_folders} """ import asyncio - from datetime import datetime start_time = time.time() - started_at = datetime.utcnow().isoformat() + started_at = utcnow().isoformat() # Use default config if none provided if source_config is None: @@ -595,7 +613,7 @@ class GalleryDLService: # Execute subprocess # Run in thread pool to not block async event loop - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() proc = await loop.run_in_executor( None, lambda: subprocess.run( @@ -607,7 +625,7 @@ class GalleryDLService: ) duration = time.time() - start_time - completed_at = datetime.utcnow().isoformat() + completed_at = utcnow().isoformat() # Log output if proc.stdout: @@ -668,7 +686,7 @@ class GalleryDLService: error_message=f"Download timed out after {source_config.timeout} seconds", duration_seconds=duration, started_at=started_at, - completed_at=datetime.utcnow().isoformat(), + completed_at=utcnow().isoformat(), ) except Exception as e: @@ -684,7 +702,7 @@ class GalleryDLService: error_message=str(e), duration_seconds=duration, started_at=started_at, - completed_at=datetime.utcnow().isoformat(), + completed_at=utcnow().isoformat(), ) finally: