mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(upload-automation): harden android and electron failure handling
Updated Android/Electron upload paths to fail deterministically and report consistent stage details, while removing unsafe stage casting and path/package mismatches. This keeps postimages automation behavior intact and makes failures easier to diagnose.
This commit is contained in:
@@ -6,7 +6,23 @@ import { formatAggregatedError, formatPreferredModeError, type ProviderAttempt }
|
||||
import { getProviderOrder } from '../lib/media-hosting/provider-order';
|
||||
import { orchestrateElectronUpload } from '../lib/media-hosting/upload-orchestrator';
|
||||
import useMediaHostingStore from '../stores/use-media-hosting-store';
|
||||
import type { ProviderId } from '../lib/media-hosting/types';
|
||||
import type { ProviderId, UploadAttemptStage } from '../lib/media-hosting/types';
|
||||
|
||||
/** Maps Android plugin stage strings to UploadAttemptStage (avoids unsafe cast). Includes pass-through for valid stages. */
|
||||
const ANDROID_STAGE_MAP: Record<string, UploadAttemptStage> = {
|
||||
input_not_found: 'file_input',
|
||||
chooser_not_triggered: 'file_input',
|
||||
upload_timed_out: 'timeout',
|
||||
blocked_detected: 'blocked',
|
||||
no_recipe: 'unknown',
|
||||
page_loaded: 'page_load',
|
||||
blocked: 'blocked',
|
||||
file_input: 'file_input',
|
||||
submit: 'submit',
|
||||
timeout: 'timeout',
|
||||
page_load: 'page_load',
|
||||
unknown: 'unknown',
|
||||
};
|
||||
|
||||
const FILE_SELECTION_CANCELLED_ERROR = 'File selection cancelled';
|
||||
|
||||
@@ -52,7 +68,7 @@ function normalizeAndroidRejection(error: unknown): Error & { attempts?: Provide
|
||||
provider: provider as ProviderId,
|
||||
success: Boolean(item?.success),
|
||||
error: typeof item?.error === 'string' ? item.error : undefined,
|
||||
stage: typeof item?.stage === 'string' && item.stage ? (item.stage as ProviderAttempt['stage']) : undefined,
|
||||
stage: typeof item?.stage === 'string' && item.stage ? (ANDROID_STAGE_MAP[item.stage] ?? 'unknown') : undefined,
|
||||
elapsedMs: ms,
|
||||
matchedSelectors: sel?.length ? sel : undefined,
|
||||
};
|
||||
|
||||
@@ -20,9 +20,11 @@ describe('direct-url', () => {
|
||||
expect(isDirectMediaUrl('https://example.com/video.gifv')).toBe(true);
|
||||
});
|
||||
|
||||
it('strips query strings before checking', () => {
|
||||
it('strips query strings and fragments before checking', () => {
|
||||
expect(isDirectMediaUrl('https://example.com/photo.jpg?size=large')).toBe(true);
|
||||
expect(isDirectMediaUrl('https://example.com/page.html?img=photo.jpg')).toBe(false);
|
||||
expect(isDirectMediaUrl('https://example.com/photo.png#section')).toBe(true);
|
||||
expect(isDirectMediaUrl('https://example.com/photo.gif#')).toBe(true);
|
||||
});
|
||||
|
||||
it('is case insensitive', () => {
|
||||
|
||||
@@ -4,7 +4,7 @@ const DIRECT_MEDIA_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.web
|
||||
/** Returns true if the URL appears to point to a direct media file (image or video) */
|
||||
export function isDirectMediaUrl(url: string): boolean {
|
||||
try {
|
||||
const normalized = url.split('?')[0].toLowerCase();
|
||||
const normalized = url.split('?')[0].split('#')[0].toLowerCase();
|
||||
return DIRECT_MEDIA_EXTENSIONS.some((ext) => normalized.endsWith(ext));
|
||||
} catch {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user