133 lines
3.8 KiB
TypeScript
133 lines
3.8 KiB
TypeScript
|
import type { Embed } from '../structures/embed.ts'
|
||
|
import type { MessageAttachment } from '../structures/message.ts'
|
||
|
import type { RESTManager } from './manager.ts'
|
||
|
import type { RequestMethods } from './types.ts'
|
||
|
|
||
|
export interface RequestOptions {
|
||
|
headers?: { [name: string]: string }
|
||
|
query?: { [name: string]: string }
|
||
|
files?: MessageAttachment[]
|
||
|
data?: any
|
||
|
reason?: string
|
||
|
rawResponse?: boolean
|
||
|
route?: string
|
||
|
}
|
||
|
|
||
|
export class APIRequest {
|
||
|
retries = 0
|
||
|
route: string
|
||
|
|
||
|
constructor(
|
||
|
public rest: RESTManager,
|
||
|
public method: RequestMethods,
|
||
|
public path: string,
|
||
|
public options: RequestOptions
|
||
|
) {
|
||
|
this.route = options.route ?? path
|
||
|
if (typeof options.query === 'object') {
|
||
|
const entries = Object.entries(options.query)
|
||
|
if (entries.length > 0) {
|
||
|
this.path += '?'
|
||
|
entries.forEach((entry, i) => {
|
||
|
this.path += `${i === 0 ? '' : '&'}${encodeURIComponent(
|
||
|
entry[0]
|
||
|
)}=${encodeURIComponent(entry[1])}`
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let _files: undefined | MessageAttachment[]
|
||
|
if (
|
||
|
options.data?.embed?.files !== undefined &&
|
||
|
Array.isArray(options.data?.embed?.files)
|
||
|
) {
|
||
|
_files = [...options.data?.embed?.files]
|
||
|
}
|
||
|
if (
|
||
|
options.data?.embeds !== undefined &&
|
||
|
Array.isArray(options.data?.embeds)
|
||
|
) {
|
||
|
const files1 = options.data?.embeds
|
||
|
.map((e: Embed) => e.files)
|
||
|
.filter((e: MessageAttachment[]) => e !== undefined)
|
||
|
for (const files of files1) {
|
||
|
for (const file of files) {
|
||
|
if (_files === undefined) _files = []
|
||
|
_files?.push(file)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (options.data?.file !== undefined) {
|
||
|
if (_files === undefined) _files = []
|
||
|
_files.push(options.data?.file)
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
options.data?.files !== undefined &&
|
||
|
Array.isArray(options.data?.files)
|
||
|
) {
|
||
|
if (_files === undefined) _files = []
|
||
|
options.data?.files.forEach((file: any) => {
|
||
|
_files!.push(file)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
if (_files !== undefined && _files.length > 0) {
|
||
|
if (options.files === undefined) options.files = _files
|
||
|
else options.files = [...options.files, ..._files]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async execute(): Promise<Response> {
|
||
|
let contentType: string | undefined
|
||
|
let body: any = this.options.data
|
||
|
if (this.options.files !== undefined && this.options.files.length > 0) {
|
||
|
contentType = undefined
|
||
|
const form = new FormData()
|
||
|
this.options.files.forEach((file, i) =>
|
||
|
form.append(`file${i === 0 ? '' : i}`, file.blob, file.name)
|
||
|
)
|
||
|
form.append('payload_json', JSON.stringify(body))
|
||
|
body = form
|
||
|
} else {
|
||
|
contentType = 'application/json'
|
||
|
body = JSON.stringify(body)
|
||
|
}
|
||
|
|
||
|
const controller = new AbortController()
|
||
|
const timer = setTimeout(() => {
|
||
|
controller.abort()
|
||
|
}, this.rest.requestTimeout)
|
||
|
this.rest.timers.add(timer)
|
||
|
|
||
|
const url = this.path.startsWith('http')
|
||
|
? this.path
|
||
|
: `${this.rest.apiURL}/v${this.rest.version}${this.path}`
|
||
|
|
||
|
const headers: any = {
|
||
|
'User-Agent':
|
||
|
this.rest.userAgent ??
|
||
|
`DiscordBot (harmony, https://github.com/harmonyland/harmony)`,
|
||
|
Authorization:
|
||
|
this.rest.token === undefined
|
||
|
? undefined
|
||
|
: `${this.rest.tokenType} ${this.rest.token}`.trim()
|
||
|
}
|
||
|
|
||
|
if (contentType !== undefined) headers['Content-Type'] = contentType
|
||
|
|
||
|
const init: RequestInit = {
|
||
|
method: this.method.toUpperCase(),
|
||
|
signal: controller.signal,
|
||
|
headers: Object.assign(headers, this.rest.headers, this.options.headers),
|
||
|
body
|
||
|
}
|
||
|
|
||
|
return fetch(url, init).finally(() => {
|
||
|
clearTimeout(timer)
|
||
|
this.rest.timers.delete(timer)
|
||
|
})
|
||
|
}
|
||
|
}
|