mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
chore(media-upload): remove Postimages provider
Postimages cannot support WebView automation (site blocks automated uploads). Imgur works reliably. Keep only Catbox and Imgur as supported providers.
This commit is contained in:
+1
-1
@@ -21,7 +21,7 @@ const mockSetUploadMode = vi.fn();
|
||||
const mockSetPreferredProvider = vi.fn();
|
||||
const uploadModeRef = vi.hoisted(() => ({ value: 'random' as 'random' | 'preferred' | 'none' }));
|
||||
const preferredProviderRef = vi.hoisted(() => ({
|
||||
value: 'catbox' as 'catbox' | 'imgur' | 'postimages',
|
||||
value: 'catbox' as 'catbox' | 'imgur',
|
||||
}));
|
||||
vi.mock('../../../../stores/use-media-hosting-store', async (importOriginal) => {
|
||||
const mod = await importOriginal<typeof import('../../../../stores/use-media-hosting-store')>();
|
||||
|
||||
@@ -35,12 +35,12 @@ vi.mock('../../lib/media-hosting/provider-order', () => ({
|
||||
getProviderOrder: vi.fn((opts: { mode: string; preferredProvider: string; runtime: string }) => {
|
||||
if (opts.mode === 'none') return [];
|
||||
if (opts.runtime === 'web') return opts.preferredProvider === 'catbox' ? ['catbox'] : [];
|
||||
return opts.mode === 'preferred' ? [opts.preferredProvider] : ['catbox', 'imgur', 'postimages'];
|
||||
return opts.mode === 'preferred' ? [opts.preferredProvider] : ['catbox', 'imgur'];
|
||||
}),
|
||||
}));
|
||||
|
||||
const uploadModeRef = vi.hoisted(() => ({ value: 'random' as 'random' | 'preferred' | 'none' }));
|
||||
const preferredProviderRef = vi.hoisted(() => ({ value: 'catbox' as 'catbox' | 'imgur' | 'postimages' }));
|
||||
const preferredProviderRef = vi.hoisted(() => ({ value: 'catbox' as 'catbox' | 'imgur' }));
|
||||
vi.mock('../../stores/use-media-hosting-store', () => ({
|
||||
default: (selector: (s: { uploadMode: string; preferredProvider: string }) => unknown) =>
|
||||
selector({ uploadMode: uploadModeRef.value, preferredProvider: preferredProviderRef.value }),
|
||||
|
||||
@@ -26,7 +26,7 @@ const ANDROID_STAGE_MAP: Record<string, UploadAttemptStage> = {
|
||||
|
||||
const FILE_SELECTION_CANCELLED_ERROR = 'File selection cancelled';
|
||||
|
||||
const VALID_PROVIDERS: ProviderId[] = ['catbox', 'imgur', 'postimages'];
|
||||
const VALID_PROVIDERS: ProviderId[] = ['catbox', 'imgur'];
|
||||
|
||||
/** Raw attempt shape from Android plugin rejection payload */
|
||||
interface RawAttempt {
|
||||
|
||||
@@ -6,25 +6,24 @@ describe('provider-order', () => {
|
||||
it('returns single-element array with preferred provider', () => {
|
||||
expect(getPreferredOrder('catbox')).toEqual(['catbox']);
|
||||
expect(getPreferredOrder('imgur')).toEqual(['imgur']);
|
||||
expect(getPreferredOrder('postimages')).toEqual(['postimages']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRandomOrder', () => {
|
||||
it('returns shuffled copy (Fisher-Yates) with default rng', () => {
|
||||
const providers = ['catbox', 'imgur', 'postimages'] as const;
|
||||
const providers = ['catbox', 'imgur'] as const;
|
||||
const result = getRandomOrder(providers);
|
||||
expect(result).toHaveLength(3);
|
||||
expect([...result].sort()).toEqual(['catbox', 'imgur', 'postimages']);
|
||||
expect(result).toHaveLength(2);
|
||||
expect([...result].sort()).toEqual(['catbox', 'imgur']);
|
||||
expect(result).not.toBe(providers);
|
||||
});
|
||||
|
||||
it('uses provided rng for deterministic shuffle', () => {
|
||||
const providers = ['catbox', 'imgur', 'postimages'] as const;
|
||||
const providers = ['catbox', 'imgur'] as const;
|
||||
const rng = vi.fn().mockReturnValue(0.5);
|
||||
const result = getRandomOrder(providers, rng);
|
||||
expect(rng).toHaveBeenCalled();
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result).toHaveLength(2);
|
||||
});
|
||||
|
||||
it('handles empty array', () => {
|
||||
@@ -80,8 +79,8 @@ describe('provider-order', () => {
|
||||
preferredProvider: 'catbox',
|
||||
runtime: 'electron',
|
||||
});
|
||||
expect(order).toHaveLength(3);
|
||||
expect([...order].sort()).toEqual(['catbox', 'imgur', 'postimages']);
|
||||
expect(order).toHaveLength(2);
|
||||
expect([...order].sort()).toEqual(['catbox', 'imgur']);
|
||||
});
|
||||
|
||||
it('filters by runtime for random mode', () => {
|
||||
|
||||
@@ -56,14 +56,14 @@ describe('orchestrateElectronUpload', () => {
|
||||
const file = new File(['z'], 'z.png', { type: 'image/png' });
|
||||
|
||||
try {
|
||||
await orchestrateElectronUpload(file, ['postimages']);
|
||||
await orchestrateElectronUpload(file, ['imgur']);
|
||||
throw new Error('Expected orchestrateElectronUpload to throw');
|
||||
} catch (error) {
|
||||
const typedError = error as Error & {
|
||||
attempts?: Array<{ provider: string; error?: string; elapsedMs?: number; stage?: string }>;
|
||||
};
|
||||
expect(typedError.message).toBe('All providers failed');
|
||||
expect(typedError.attempts?.[0]?.provider).toBe('postimages');
|
||||
expect(typedError.attempts?.[0]?.provider).toBe('imgur');
|
||||
expect(typedError.attempts?.[0]?.error).toContain('File path required for Electron automation');
|
||||
expect(typedError.attempts?.[0]?.elapsedMs).toBeGreaterThanOrEqual(0);
|
||||
expect(typedError.attempts?.[0]?.stage).toBeDefined();
|
||||
@@ -115,21 +115,19 @@ describe('orchestrateElectronUpload', () => {
|
||||
|
||||
it('parses timeout stage when upload or URL extraction times out', async () => {
|
||||
const electronApi = createElectronApiMock();
|
||||
electronApi.automateUploadMedia = vi
|
||||
.fn()
|
||||
.mockRejectedValue(new Error('Upload timeout or no direct URL extracted for postimages (elapsed: 45000ms, timeout: 45000ms)'));
|
||||
electronApi.automateUploadMedia = vi.fn().mockRejectedValue(new Error('Upload timeout or no direct URL extracted for imgur (elapsed: 45000ms, timeout: 45000ms)'));
|
||||
window.electronApi = electronApi;
|
||||
|
||||
const file = new File(['x'], 'x.png', { type: 'image/png' });
|
||||
|
||||
try {
|
||||
await orchestrateElectronUpload(file, ['postimages']);
|
||||
await orchestrateElectronUpload(file, ['imgur']);
|
||||
throw new Error('Expected orchestrateElectronUpload to throw');
|
||||
} catch (error) {
|
||||
const typedError = error as Error & {
|
||||
attempts?: Array<{ provider: string; stage?: string }>;
|
||||
};
|
||||
expect(typedError.attempts?.[0]?.provider).toBe('postimages');
|
||||
expect(typedError.attempts?.[0]?.provider).toBe('imgur');
|
||||
expect(typedError.attempts?.[0]?.stage).toBe('timeout');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -22,12 +22,6 @@ export const MEDIA_HOSTING_PROVIDERS: readonly ProviderDefinition[] = [
|
||||
homepageUrl: 'https://imgur.com',
|
||||
supportedRuntimes: ['electron', 'android'],
|
||||
},
|
||||
{
|
||||
id: 'postimages',
|
||||
label: 'Postimages',
|
||||
homepageUrl: 'https://postimages.org',
|
||||
supportedRuntimes: ['electron', 'android'],
|
||||
},
|
||||
] as const;
|
||||
|
||||
/** Provider IDs for ordering */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** Supported media hosting provider identifiers */
|
||||
export type ProviderId = 'catbox' | 'imgur' | 'postimages';
|
||||
export type ProviderId = 'catbox' | 'imgur';
|
||||
|
||||
/** User-facing upload mode */
|
||||
export type UploadMode = 'random' | 'preferred' | 'none';
|
||||
|
||||
@@ -58,11 +58,11 @@ function resolveElectronFilePath(file: File): string | null {
|
||||
|
||||
/**
|
||||
* Uploads a file via a single provider. Catbox uses the web API;
|
||||
* imgur/postimages use Electron automation when available.
|
||||
* imgur uses Electron automation when available.
|
||||
*/
|
||||
async function uploadViaProvider(provider: ProviderId, file: File): Promise<string> {
|
||||
if (provider === 'catbox') return uploadToCatbox(file);
|
||||
if (provider === 'imgur' || provider === 'postimages') {
|
||||
if (provider === 'imgur') {
|
||||
const fn = typeof window !== 'undefined' && window.electronApi?.automateUploadMedia;
|
||||
if (fn) {
|
||||
const filePath = resolveElectronFilePath(file);
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('useMediaHostingStore', () => {
|
||||
|
||||
it('exports MEDIA_HOSTING_PROVIDERS with ids, labels, homepage URLs, runtime metadata', () => {
|
||||
expect(MEDIA_HOSTING_PROVIDERS).toBeDefined();
|
||||
expect(MEDIA_HOSTING_PROVIDERS.length).toBe(3);
|
||||
expect(MEDIA_HOSTING_PROVIDERS.length).toBe(2);
|
||||
const catbox = MEDIA_HOSTING_PROVIDERS.find((p) => p.id === 'catbox');
|
||||
expect(catbox).toEqual({
|
||||
id: 'catbox',
|
||||
|
||||
Reference in New Issue
Block a user