From 055808ea6d9ed211d186143ad244727e1586376c Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 4 Feb 2026 15:02:50 -0500 Subject: [PATCH] polish for failed retry mechanic and consistent sub naming --- .claude/settings.local.json | 3 +- backend/app/api/downloads.py | 39 ++++++++++-- extension/manifest.json | 2 +- .../gallerysubscriber-1.1.1.zip | Bin 0 -> 21774 bytes frontend/src/views/Dashboard.vue | 57 ++++++++++++++---- summary.md | 2 +- 6 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 extension/web-ext-artifacts/gallerysubscriber-1.1.1.zip diff --git a/.claude/settings.local.json b/.claude/settings.local.json index d41d16e..7e8e1bd 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -17,7 +17,8 @@ "WebFetch(domain:raw.githubusercontent.com)", "Bash(python -m py_compile:*)", "Bash(powershell:*)", - "Bash(python:*)" + "Bash(python:*)", + "Bash(xargs basename:*)" ] } } diff --git a/backend/app/api/downloads.py b/backend/app/api/downloads.py index 7d8fafe..fac7728 100644 --- a/backend/app/api/downloads.py +++ b/backend/app/api/downloads.py @@ -29,8 +29,10 @@ async def list_downloads(): async with current_app.db_engine.connect() as conn: session = AsyncSession(bind=conn) - # Build query - query = select(Download) + # Build query - eager load source and subscription for labeling + query = select(Download).options( + selectinload(Download.source).selectinload(Source.subscription) + ) count_query = select(func.count()).select_from(Download) filters = [] @@ -58,8 +60,20 @@ async def list_downloads(): result = await session.execute(query) downloads = result.scalars().all() + # Include source info with each download + items = [] + for d in downloads: + item = d.to_dict() + if d.source: + item["subscription_name"] = d.source.subscription.name if d.source.subscription else None + item["platform"] = d.source.platform + else: + item["subscription_name"] = None + item["platform"] = None + items.append(item) + return jsonify({ - "items": [d.to_dict() for d in downloads], + "items": items, "total": total, "page": page, "per_page": per_page, @@ -147,8 +161,11 @@ async def recent_activity(): session = AsyncSession(bind=conn) # Get failed downloads OR completed with files (noteworthy activity) + # Eager load source and subscription for labeling from sqlalchemy import or_ - query = select(Download).where( + query = select(Download).options( + selectinload(Download.source).selectinload(Source.subscription) + ).where( and_( Download.created_at >= cutoff, or_( @@ -164,8 +181,20 @@ async def recent_activity(): result = await session.execute(query) downloads = result.scalars().all() + # Include source info with each download + items = [] + for d in downloads: + item = d.to_dict() + if d.source: + item["subscription_name"] = d.source.subscription.name if d.source.subscription else None + item["platform"] = d.source.platform + else: + item["subscription_name"] = None + item["platform"] = None + items.append(item) + return jsonify({ - "items": [d.to_dict() for d in downloads], + "items": items, "count": len(downloads), }) diff --git a/extension/manifest.json b/extension/manifest.json index 72b27f4..5c32255 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "GallerySubscriber", - "version": "1.1.0", + "version": "1.1.1", "description": "Export cookies from supported platforms to GallerySubscriber for automated downloads", "browser_specific_settings": { diff --git a/extension/web-ext-artifacts/gallerysubscriber-1.1.1.zip b/extension/web-ext-artifacts/gallerysubscriber-1.1.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..25fa33fe8a1d5e1515ca6d49b85754db99d71efc GIT binary patch literal 21774 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 fS!L - {{ truncate(dl.url, 30) }} + {{ getDownloadLabel(dl) }} @@ -211,7 +211,7 @@ - {{ truncate(download.url, 40) }} + {{ getDownloadLabel(download) }} {{ formatRelativeTime(download.created_at) }} @@ -255,20 +255,18 @@ - Name - Platform - Error Count + Source + Last Error Last Check Actions - {{ source.subscription_name || source.subscription?.name || 'Unknown' }} - {{ source.platform }} + {{ getSourceLabel(source) }} - {{ source.error_count }} errors + {{ source.last_error_type || 'failed' }} {{ formatDate(source.last_check) }} @@ -318,7 +316,7 @@ const credentialsStore = useCredentialsStore() const notifications = useNotificationStore() // Supported platforms for credential status -const supportedPlatforms = ['patreon', 'subscribestar', 'hentaifoundry', 'discord'] +const supportedPlatforms = ['patreon', 'subscribestar', 'hentaifoundry', 'discord', 'pixiv', 'deviantart'] // State const checkingAll = ref(false) @@ -335,9 +333,27 @@ let refreshInterval = null // Computed const stats = computed(() => downloadsStore.stats) const recentActivity = computed(() => downloadsStore.recentActivity) -const sourcesWithErrors = computed(() => - sourcesStore.sources.filter(s => s.error_count > 0).slice(0, 5) -) + +// Sources with recent failures - derived from recent activity +// Only shows sources where a recent download failed (not cumulative error_count) +const sourcesWithErrors = computed(() => { + const failedDownloads = recentActivity.value.filter(d => d.status === 'failed') + // Group by source_id and keep unique sources with their most recent failure + const sourceMap = new Map() + for (const dl of failedDownloads) { + if (dl.source_id && !sourceMap.has(dl.source_id)) { + sourceMap.set(dl.source_id, { + id: dl.source_id, + subscription_name: dl.subscription_name, + platform: dl.platform, + last_error_type: dl.error_type, + last_check: dl.created_at, + }) + } + } + return Array.from(sourceMap.values()).slice(0, 5) +}) + const failedCount = computed(() => stats.value?.failed || 0) const activeDownloadsCount = computed(() => (stats.value?.queued || 0) + (stats.value?.running || 0) @@ -565,10 +581,25 @@ function truncate(str, length) { return str.substring(0, length) + '...' } +function getDownloadLabel(download) { + if (download.subscription_name && download.platform) { + return `${download.subscription_name}:${download.platform}` + } + // Fallback to truncated URL if source info not available + return truncate(download.url, 35) +} + +function getSourceLabel(source) { + const name = source.subscription_name || source.subscription?.name || 'Unknown' + return `${name}:${source.platform}` +} + async function retrySource(source) { try { await sourcesStore.triggerCheck(source.id) - notifications.success(`Queued check for ${source.subscription_name || source.platform}`) + notifications.success(`Queued check for ${getSourceLabel(source)}`) + // Refresh recent activity after retrying + await downloadsStore.fetchRecentActivity({ limit: 10 }) } catch (error) { notifications.error(`Failed to queue check: ${error.message}`) } diff --git a/summary.md b/summary.md index e241f5a..99937c0 100644 --- a/summary.md +++ b/summary.md @@ -1,6 +1,6 @@ # GallerySubscriber - Project Summary -**Updated:** 2026-02-04 (Fixed Pixiv authentication - requires OAuth refresh token) +**Updated:** 2026-02-04 (Pixiv OAuth in extension, improved failed/naming display) ## Overview