2020-12-02 12:29:52 +00:00
|
|
|
import {
|
|
|
|
DISCORD_API_URL,
|
|
|
|
DISCORD_API_VERSION
|
|
|
|
} from '../consts/urlsAndVersions.ts'
|
|
|
|
import { Client } from '../models/client.ts'
|
|
|
|
import { RESTManager } from '../models/rest.ts'
|
|
|
|
import { MessageOption } from '../types/channel.ts'
|
|
|
|
import { UserPayload } from '../types/user.ts'
|
|
|
|
import { WebhookPayload } from '../types/webhook.ts'
|
|
|
|
import { Embed } from './embed.ts'
|
|
|
|
import { Message } from './message.ts'
|
|
|
|
import { TextChannel } from './textChannel.ts'
|
|
|
|
import { User } from './user.ts'
|
|
|
|
import { fetchAuto } from 'https://raw.githubusercontent.com/DjDeveloperr/fetch-base64/main/mod.ts'
|
|
|
|
|
|
|
|
export interface WebhookMessageOptions extends MessageOption {
|
|
|
|
embeds?: Embed[]
|
|
|
|
name?: string
|
|
|
|
avatar?: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export type AllWebhookMessageOptions = string | WebhookMessageOptions
|
|
|
|
|
|
|
|
export interface WebhookEditOptions {
|
|
|
|
/** New name to set for Webhook. */
|
|
|
|
name?: string
|
|
|
|
/** New avatar to set for Webhook. URL of image or base64 encoded data. */
|
|
|
|
avatar?: string
|
|
|
|
/** New channel for Webhook. Requires authentication. */
|
|
|
|
channelID?: string
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Webhook follows different way of instantiation */
|
|
|
|
export class Webhook {
|
|
|
|
client?: Client
|
|
|
|
id: string
|
|
|
|
type: 1 | 2
|
|
|
|
guildID?: string
|
|
|
|
channelID: string
|
|
|
|
user?: User
|
|
|
|
userRaw?: UserPayload
|
|
|
|
name?: string
|
|
|
|
avatar?: string
|
|
|
|
token?: string
|
|
|
|
applicationID?: string
|
|
|
|
rest: RESTManager
|
|
|
|
|
|
|
|
get url(): string {
|
|
|
|
return `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/webhooks/${this.id}/${this.token}`
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(data: WebhookPayload, client?: Client, rest?: RESTManager) {
|
|
|
|
this.id = data.id
|
|
|
|
this.type = data.type
|
|
|
|
this.channelID = data.channel_id
|
|
|
|
this.guildID = data.guild_id
|
|
|
|
this.user =
|
|
|
|
data.user === undefined || client === undefined
|
|
|
|
? undefined
|
|
|
|
: new User(client, data.user)
|
|
|
|
if (data.user !== undefined && client === undefined)
|
|
|
|
this.userRaw = data.user
|
|
|
|
this.name = data.name
|
|
|
|
this.avatar = data.avatar
|
|
|
|
this.token = data.token
|
|
|
|
this.applicationID = data.application_id
|
|
|
|
|
|
|
|
if (rest !== undefined) this.rest = rest
|
|
|
|
else if (client !== undefined) this.rest = client.rest
|
|
|
|
else this.rest = new RESTManager()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fromPayload(data: WebhookPayload): Webhook {
|
|
|
|
this.id = data.id
|
|
|
|
this.type = data.type
|
|
|
|
this.channelID = data.channel_id
|
|
|
|
this.guildID = data.guild_id
|
|
|
|
this.user =
|
|
|
|
data.user === undefined || this.client === undefined
|
|
|
|
? undefined
|
|
|
|
: new User(this.client, data.user)
|
|
|
|
if (data.user !== undefined && this.client === undefined)
|
|
|
|
this.userRaw = data.user
|
|
|
|
this.name = data.name
|
|
|
|
this.avatar = data.avatar
|
|
|
|
this.token = data.token
|
|
|
|
this.applicationID = data.application_id
|
|
|
|
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Sends a Message through Webhook. */
|
2020-12-02 12:29:52 +00:00
|
|
|
async send(
|
|
|
|
text?: string | AllWebhookMessageOptions,
|
|
|
|
option?: AllWebhookMessageOptions
|
|
|
|
): Promise<Message> {
|
|
|
|
if (typeof text === 'object') {
|
|
|
|
option = text
|
|
|
|
text = undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
if (text === undefined && option === undefined) {
|
|
|
|
throw new Error('Either text or option is necessary.')
|
|
|
|
}
|
|
|
|
|
|
|
|
if (option instanceof Embed)
|
|
|
|
option = {
|
|
|
|
embeds: [option]
|
|
|
|
}
|
|
|
|
|
|
|
|
const payload: any = {
|
|
|
|
content: text,
|
|
|
|
embeds:
|
|
|
|
(option as WebhookMessageOptions)?.embed !== undefined
|
|
|
|
? [(option as WebhookMessageOptions).embed]
|
|
|
|
: (option as WebhookMessageOptions)?.embeds !== undefined
|
|
|
|
? (option as WebhookMessageOptions).embeds
|
|
|
|
: undefined,
|
|
|
|
file: (option as WebhookMessageOptions)?.file,
|
|
|
|
tts: (option as WebhookMessageOptions)?.tts,
|
|
|
|
allowed_mentions: (option as WebhookMessageOptions)?.allowedMentions
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((option as WebhookMessageOptions)?.name !== undefined) {
|
|
|
|
payload.username = (option as WebhookMessageOptions)?.name
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((option as WebhookMessageOptions)?.avatar !== undefined) {
|
|
|
|
payload.avatar = (option as WebhookMessageOptions)?.avatar
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
payload.embeds !== undefined &&
|
|
|
|
payload.embeds instanceof Array &&
|
|
|
|
payload.embeds.length > 10
|
|
|
|
)
|
|
|
|
throw new Error(`Cannot send more than 10 embeds through Webhook`)
|
|
|
|
|
|
|
|
const resp = await this.rest.post(this.url + '?wait=true', payload)
|
|
|
|
|
|
|
|
const res = new Message(
|
|
|
|
this.client as Client,
|
|
|
|
resp,
|
|
|
|
(this as unknown) as TextChannel,
|
|
|
|
(this as unknown) as User
|
|
|
|
)
|
|
|
|
await res.mentions.fromPayload(resp)
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-12-05 02:24:08 +00:00
|
|
|
* Creates a Webhook object from URL
|
2020-12-02 12:29:52 +00:00
|
|
|
* @param url URL of the Webhook
|
|
|
|
* @param client Client (bot) object, if any.
|
|
|
|
*/
|
|
|
|
static async fromURL(url: string | URL, client?: Client): Promise<Webhook> {
|
|
|
|
const rest = client !== undefined ? client.rest : new RESTManager()
|
|
|
|
|
|
|
|
const raw = await rest.get(typeof url === 'string' ? url : url.toString())
|
|
|
|
if (typeof raw !== 'object')
|
|
|
|
throw new Error(`Failed to load Webhook from URL: ${url}`)
|
|
|
|
|
|
|
|
const webhook = new Webhook(raw, client, rest)
|
|
|
|
return webhook
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-12-05 02:24:08 +00:00
|
|
|
* Edits the Webhook name, avatar, or channel (requires authentication).
|
2020-12-02 12:29:52 +00:00
|
|
|
* @param options Options to edit the Webhook.
|
|
|
|
*/
|
|
|
|
async edit(options: WebhookEditOptions): Promise<Webhook> {
|
|
|
|
if (options.channelID !== undefined && this.rest.client === undefined)
|
|
|
|
throw new Error('Authentication is required for editing Webhook Channel')
|
|
|
|
if (
|
|
|
|
options.avatar !== undefined &&
|
|
|
|
(options.avatar.startsWith('http:') ||
|
|
|
|
options.avatar.startsWith('https:'))
|
|
|
|
) {
|
|
|
|
options.avatar = await fetchAuto(options.avatar)
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = await this.rest.patch(this.url, options)
|
|
|
|
this.fromPayload(data)
|
|
|
|
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
2020-12-05 02:24:08 +00:00
|
|
|
/** Deletes the Webhook. */
|
2020-12-02 12:29:52 +00:00
|
|
|
async delete(): Promise<boolean> {
|
|
|
|
const resp = await this.rest.delete(this.url, undefined, 0, undefined, true)
|
|
|
|
if (resp.response.status !== 204) return false
|
|
|
|
else return true
|
|
|
|
}
|
|
|
|
}
|