diff --git a/src/equicordplugins/fileUpload/index.tsx b/src/equicordplugins/fileUpload/index.tsx index 4a59451aa..0cd895db2 100644 --- a/src/equicordplugins/fileUpload/index.tsx +++ b/src/equicordplugins/fileUpload/index.tsx @@ -74,7 +74,7 @@ function interceptUploadAddFiles(event: unknown): void { if (payload.draftType !== DraftType.ChannelMessage) return; - if (!Boolean((settings.store as { interceptDiscordUpload?: boolean; }).interceptDiscordUpload) || !isConfigured()) return; + if (!settings.store.bypassDiscordUpload || !isConfigured()) return; const files = [ ...extractFilesFromValue(payload.files), @@ -283,7 +283,7 @@ export default definePlugin({ } }, shouldBypassDiscordUploadSizeCheck(): boolean { - return Boolean((settings.store as { interceptDiscordUpload?: boolean; }).interceptDiscordUpload) && isConfigured(); + return Boolean(settings.store.bypassDiscordUpload) && isConfigured(); }, renderUploadProgress() { return ; diff --git a/src/equicordplugins/fileUpload/native.ts b/src/equicordplugins/fileUpload/native.ts index 1cd40c374..ad401217d 100644 --- a/src/equicordplugins/fileUpload/native.ts +++ b/src/equicordplugins/fileUpload/native.ts @@ -418,6 +418,46 @@ export async function uploadToPixelVault( } } +export async function uploadToPixelDrain( + _: IpcMainInvokeEvent, + fileBuffer: ArrayBuffer, + filename: string, + apiKey?: string +): Promise { + try { + const headers: Record = {}; + if (apiKey?.trim()) { + headers.Authorization = `Basic ${Buffer.from(`:${apiKey.trim()}`).toString("base64")}`; + } + + const response = await fetch(`https://pixeldrain.com/api/file/${encodeURIComponent(filename)}`, { + method: "PUT", + headers, + body: new Blob([fileBuffer]) + }); + + const text = await response.text(); + let data: { id?: string; message?: string; } | null = null; + try { + data = text ? JSON.parse(text) : null; + } catch { + data = null; + } + + if (!response.ok) { + return { success: false, error: data?.message || `Upload failed: ${response.status} ${text}` }; + } + + if (!data?.id) { + return { success: false, error: data?.message || "No URL returned from upload" }; + } + + return { success: true, url: `https://pixeldrain.com/u/${data.id}` }; + } catch (e) { + return { success: false, error: e instanceof Error ? e.message : "Unknown error" }; + } +} + export async function fetchFile( _: IpcMainInvokeEvent, diff --git a/src/equicordplugins/fileUpload/settings.tsx b/src/equicordplugins/fileUpload/settings.tsx index 234b8d85c..896a3e7df 100644 --- a/src/equicordplugins/fileUpload/settings.tsx +++ b/src/equicordplugins/fileUpload/settings.tsx @@ -34,6 +34,7 @@ const serviceOptions = [ { label: "temp.sh", value: ServiceType.TEMPSH }, { label: "filebin.net", value: ServiceType.FILEBIN }, { label: "PixelVault", value: ServiceType.PIXELVAULT }, + { label: "PixelDrain", value: ServiceType.PIXELDRAIN }, { label: "ShareX Custom Uploader", value: ServiceType.SHAREX } ]; @@ -207,6 +208,12 @@ export const settings = definePluginSettings({ default: "", hidden: true }, + pixelDrainKey: { + type: OptionType.STRING, + description: "Optional PixelDrain API key", + default: "", + hidden: true + }, uploadTimeoutMs: { type: OptionType.NUMBER, description: "Upload timeout in milliseconds", @@ -366,6 +373,7 @@ export function SettingsComponent() { const isLitterbox = store.serviceType === ServiceType.LITTERBOX; const isGofile = store.serviceType === ServiceType.GOFILE; const isPixelVault = store.serviceType === ServiceType.PIXELVAULT; + const isPixelDrain = store.serviceType === ServiceType.PIXELDRAIN; const isShareX = store.serviceType === ServiceType.SHAREX; const validateShareXConfig = () => { @@ -576,6 +584,16 @@ export function SettingsComponent() { /> )} + {isPixelDrain && ( + store.pixelDrainKey = v} + placeholder="Your PixelDrain API key" + /> + )} + {isShareX && ( <> = { @@ -35,7 +36,8 @@ export const serviceLabels: Record = { [ServiceType.BUZZHEAVIER]: "buzzheavier.com", [ServiceType.TEMPSH]: "temp.sh", [ServiceType.FILEBIN]: "filebin.net", - [ServiceType.PIXELVAULT]: "PixelVault" + [ServiceType.PIXELVAULT]: "PixelVault", + [ServiceType.PIXELDRAIN]: "PixelDrain" }; export const fallbackServiceOrder: ServiceType[] = [ @@ -52,6 +54,7 @@ export const fallbackServiceOrder: ServiceType[] = [ ServiceType.TEMPSH, ServiceType.FILEBIN, ServiceType.PIXELVAULT, + ServiceType.PIXELDRAIN, ServiceType.SHAREX ]; diff --git a/src/equicordplugins/fileUpload/utils/upload.ts b/src/equicordplugins/fileUpload/utils/upload.ts index f70b9e188..78d3518b3 100644 --- a/src/equicordplugins/fileUpload/utils/upload.ts +++ b/src/equicordplugins/fileUpload/utils/upload.ts @@ -374,6 +374,7 @@ export function isConfigured(): boolean { case ServiceType.BUZZHEAVIER: case ServiceType.TEMPSH: case ServiceType.FILEBIN: + case ServiceType.PIXELDRAIN: return true; case ServiceType.PIXELVAULT: return Boolean((settings.store as { pixelVaultKey?: string; }).pixelVaultKey); @@ -714,6 +715,45 @@ async function uploadToPixelVault(fileBlob: Blob, filename: string): Promise { + const { pixelDrainKey } = settings.store as { pixelDrainKey?: string; }; + + if (Native) { + const result = await Native.uploadToPixelDrain(await fileBlob.arrayBuffer(), filename, pixelDrainKey?.trim() || undefined); + if (!result.success || !result.url) throw new Error(result.error || "No URL returned from upload"); + return result.url; + } + + const headers: Record = {}; + if (pixelDrainKey?.trim()) { + headers.Authorization = `Basic ${btoa(`:${pixelDrainKey.trim()}`)}`; + } + + const response = await fetchWithTimeout(`https://pixeldrain.com/api/file/${encodeURIComponent(filename)}`, { + method: "PUT", + headers, + body: fileBlob + }); + + const text = await response.text(); + let data: { id?: string; success?: boolean; message?: string; } | null = null; + try { + data = text ? JSON.parse(text) : null; + } catch { + data = null; + } + + if (!response.ok) { + throw new Error(data?.message || `Upload failed: ${response.status} ${text}`); + } + + if (!data?.id) { + throw new Error(data?.message || "No URL returned from upload"); + } + + return `https://pixeldrain.com/u/${data.id}`; +} + async function uploadToService(serviceType: ServiceType, fileBlob: Blob, filename: string): Promise { switch (serviceType) { case ServiceType.ZIPLINE: @@ -744,6 +784,8 @@ async function uploadToService(serviceType: ServiceType, fileBlob: Blob, filenam return uploadToFilebin(fileBlob, filename); case ServiceType.PIXELVAULT: return uploadToPixelVault(fileBlob, filename); + case ServiceType.PIXELDRAIN: + return uploadToPixelDrain(fileBlob, filename); default: throw new Error("Unknown service type"); }