2020-11-28 05:14:37 +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
}
/** Send a Message through Webhook. */
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
}
/ * *
* Create a Webhook object from URL
* @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
}
/ * *
* Edit the Webhook name , avatar , or channel ( requires authentication ) .
* @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
}
/** Delete the Webhook. */
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
}
}