diff --git a/rest/createRequestBody.ts b/rest/createRequestBody.ts index 97855debd..e07e7cc99 100644 --- a/rest/createRequestBody.ts +++ b/rest/createRequestBody.ts @@ -1,10 +1,9 @@ import { RestManager } from "./restManager.ts"; import { FileContent } from "../types/discordeno.ts"; import { USER_AGENT } from "../util/constants.ts"; -import { RequestMethod, RestPayload, RestRequest } from "./rest.ts"; +import { RequestMethod } from "./rest.ts"; /** Creates the request body and headers that are necessary to send a request. Will handle different types of methods and everything necessary for discord. */ -// export function createRequestBody(rest: RestManager, queuedRequest: { request: RestRequest; payload: RestPayload }) { export function createRequestBody(rest: RestManager, options: CreateRequestBodyOptions) { const headers: Record = { "user-agent": USER_AGENT, @@ -38,15 +37,28 @@ export function createRequestBody(rest: RestManager, options: CreateRequestBodyO const form = new FormData(); - for (let i = 0; i < (options.body.file as FileContent[]).length; i++) { - form.append( - `file${i}`, - (options.body.file as FileContent[])[i].blob, - (options.body.file as FileContent[])[i].name, - ); + // WHEN CREATING A STICKER, DISCORD WANTS FORM DATA ONLY + if (options.url?.endsWith("/stickers") && options.method === "POST") { + form.append( + `file`, + (options.body.file as FileContent[])[0].blob, + (options.body.file as FileContent[])[0].name, + ); + form.append(`name`, options.body.name as string); + form.append(`description`, options.body.description as string); + form.append(`tags`, options.body.tags as string); + } else { + for (let i = 0; i < (options.body.file as FileContent[]).length; i++) { + form.append( + `file${i}`, + (options.body.file as FileContent[])[i].blob, + (options.body.file as FileContent[])[i].name, + ); + } + + form.append("payload_json", JSON.stringify({ ...options.body, file: undefined })); } - form.append("payload_json", JSON.stringify({ ...options.body, file: undefined })); options.body.file = form; } else if (options.body && !["GET", "DELETE"].includes(options.method)) { headers["Content-Type"] = "application/json"; @@ -64,4 +76,5 @@ export interface CreateRequestBodyOptions { method: RequestMethod; body?: Record; unauthorized?: boolean; + url?: string; } diff --git a/rest/processGlobalQueue.ts b/rest/processGlobalQueue.ts index 79c5bfa84..2d89f9ec6 100644 --- a/rest/processGlobalQueue.ts +++ b/rest/processGlobalQueue.ts @@ -73,6 +73,7 @@ export async function processGlobalQueue(rest: RestManager) { payload: rest.createRequestBody(rest, { method: request.request.method, body: request.payload.body, + url: request.urlToUse, }), }) // Should be handled in sendRequest, this catch just prevents bots from dying diff --git a/rest/runMethod.ts b/rest/runMethod.ts index ad34db4a2..2f72054cc 100644 --- a/rest/runMethod.ts +++ b/rest/runMethod.ts @@ -1,4 +1,6 @@ +import { FileContent } from "../mod.ts"; import { API_VERSION, BASE_URL, baseEndpoints } from "../util/constants.ts"; +import { encode } from "../util/urlToBase64.ts"; import { RequestMethod, RestRequestRejection, RestRequestResponse } from "./rest.ts"; import { RestManager } from "./restManager.ts"; @@ -6,7 +8,7 @@ export async function runMethod( rest: RestManager, method: RequestMethod, route: string, - body?: unknown, + body?: any, options?: { retryCount?: number; bucketId?: string; @@ -29,6 +31,21 @@ export async function runMethod( // For proxies we don't need to do any of the legwork so we just forward the request if (!baseEndpoints.BASE_URL.startsWith(BASE_URL) && route[0] === "/") { + // Special handling for sending blobs across http to proxy + if (body?.file) { + if (!Array.isArray(body.file)) { + body.file = [body.file]; + } + // convert blobs to string before sending to proxy + body.file = await Promise.all( + body.file.map(async (f: FileContent) => { + const url = encode(await (f.blob).arrayBuffer()); + + return { name: f.name, blob: `data:${f.blob.type};base64,${url}` }; + }), + ); + } + const result = await fetch(`${baseEndpoints.BASE_URL}${route}`, { body: body ? JSON.stringify(body) : undefined, headers: { diff --git a/tests/rest.ts b/tests/rest.ts index d3bef78e7..a80047bc7 100644 --- a/tests/rest.ts +++ b/tests/rest.ts @@ -54,6 +54,13 @@ async function handleRequest(conn: Deno.Conn) { const text = await requestEvent.request.text(); const json = text ? JSON.parse(text) : undefined; + if (json?.file) { + json.file = await Promise.all(json.file.map(async (f: any) => ({ + name: f.name, + blob: await (await fetch(f.blob)).blob(), + }))); + } + const result = await rest.runMethod( rest, requestEvent.request.method as RequestMethod,