feat: implement channel webhook collection

This commit is contained in:
Paul Makles
2023-06-03 18:56:43 +01:00
parent a2b602782d
commit 21b4b4643b
8 changed files with 208 additions and 1 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
"strings": false,
"identifiers": false,
"templates": false,
"skipWords": ["uri", "webhook", "unreads"],
"skipWords": ["uri", "webhook", "webhooks", "unreads"],
"minLength": 3
}
],
+3
View File
@@ -9,6 +9,7 @@ import {
BotCollection,
ChannelCollection,
ChannelUnreadCollection,
ChannelWebhookCollection,
EmojiCollection,
MessageCollection,
ServerCollection,
@@ -148,6 +149,7 @@ export class Client extends EventEmitter<Events> {
readonly bots;
readonly channels;
readonly channelUnreads;
readonly channelWebhooks;
readonly emojis;
readonly messages;
readonly servers;
@@ -219,6 +221,7 @@ export class Client extends EventEmitter<Events> {
this.bots = new BotCollection(this);
this.channels = new ChannelCollection(this);
this.channelUnreads = new ChannelUnreadCollection(this);
this.channelWebhooks = new ChannelWebhookCollection(this);
this.emojis = new EmojiCollection(this);
this.messages = new MessageCollection(this);
this.servers = new ServerCollection(this);
+17
View File
@@ -390,6 +390,23 @@ export class Channel {
);
}
/**
* Fetch a channel's webhooks
* @requires `TextChannel`, `Group`
* @returns Webhooks
*/
async fetchWebhooks() {
const webhooks = await this.#collection.client.api.get(
`/channels/${this.id as ""}/webhooks`
);
return batch(() =>
webhooks.map((webhook) =>
this.#collection.client.channelWebhooks.getOrCreate(webhook.id, webhook)
)
);
}
/**
* Edit a channel
* @param data Changes
+94
View File
@@ -0,0 +1,94 @@
import { DataEditWebhook } from "revolt-api";
import { ChannelWebhookCollection } from "../collections";
import { hydrate } from "../hydration";
/**
* Channel Webhook Class
*/
export class ChannelWebhook {
readonly #collection: ChannelWebhookCollection;
readonly id: string;
/**
* Construct Channel Webhook
* @param collection Collection
* @param id Webhook
*/
constructor(collection: ChannelWebhookCollection, id: string) {
this.#collection = collection;
this.id = id;
}
/**
* Webhook name
*/
get name() {
return this.#collection.getUnderlyingObject(this.id).name;
}
/**
* Webhook avatar
*/
get avatar() {
return this.#collection.getUnderlyingObject(this.id).avatar;
}
/**
* Webhook avatar URL
*/
get avatarURL() {
return this.#collection
.getUnderlyingObject(this.id)
.avatar?.createFileURL({ max_side: 256 });
}
/**
* Channel ID this webhook belongs to
*/
get channelId() {
return this.#collection.getUnderlyingObject(this.id).channelId;
}
/**
* Channel this webhook belongs to
*/
get channel() {
return this.#collection.client.channels.get(
this.#collection.getUnderlyingObject(this.id).channelId
);
}
/**
* Secret token for sending messages to this webhook
*/
get token() {
return this.#collection.getUnderlyingObject(this.id).token;
}
/**
* Edit this webhook
*/
async edit(data: DataEditWebhook) {
const webhook = await this.#collection.client.api.patch(
`/webhooks/${this.id as ""}/${this.token as ""}`,
data
);
this.#collection.updateUnderlyingObject(
this.id,
hydrate("channelWebhook", webhook, this.#collection.client)
);
}
/**
* Delete this webhook
*/
async delete() {
await this.#collection.client.api.delete(
`/webhooks/${this.id}/${this.token}`
);
this.#collection.delete(this.id);
}
}
@@ -0,0 +1,55 @@
import { API } from "..";
import { ChannelWebhook } from "../classes/ChannelWebhook";
import { HydratedChannelWebhook } from "../hydration/channelWebhook";
import { ClassCollection } from ".";
/**
* Collection of Channel Webhooks
*/
export class ChannelWebhookCollection extends ClassCollection<
ChannelWebhook,
HydratedChannelWebhook
> {
/**
* Fetch webhook by ID
* @param id Id
* @returns Webhook
*/
async fetch(id: string): Promise<ChannelWebhook> {
const webhook = this.get(id);
if (webhook) return webhook;
const data = await this.client.api.get(`/webhooks/${id as ""}`);
return this.getOrCreate(data.id, data as API.Webhook);
}
/**
* Create webhook with ID and token
* @param id Id
* @param token Token
* @returns Webhook
*/
async fromToken(id: string, token: string): Promise<ChannelWebhook> {
const webhook = this.get(id);
if (webhook) return webhook;
const data = await this.client.api.get(
`/webhooks/${id as ""}/${token as ""}`
);
return this.getOrCreate(data.id, data);
}
/**
* Get or create
* @param id Id
* @param data Data
*/
getOrCreate(id: string, data: API.Webhook) {
if (this.has(id)) {
return this.get(id)!;
} else {
const instance = new ChannelWebhook(this, id);
this.create(id, "channelWebhook", instance, this.client, data);
return instance;
}
}
}
+1
View File
@@ -3,6 +3,7 @@ export * from "./Collection";
export { BotCollection } from "./BotCollection";
export { ChannelCollection } from "./ChannelCollection";
export { ChannelUnreadCollection } from "./ChannelUnreadCollection";
export { ChannelWebhookCollection } from "./ChannelWebhookCollection";
export { EmojiCollection } from "./EmojiCollection";
export { MessageCollection } from "./MessageCollection";
export { ServerCollection } from "./ServerCollection";
+34
View File
@@ -0,0 +1,34 @@
import { API, Client, File } from "..";
import type { Merge } from "../lib/merge";
import { Hydrate } from ".";
export type HydratedChannelWebhook = {
id: string;
name: string;
avatar?: File;
channelId: string;
token: string;
};
export const channelWebhookHydration: Hydrate<
Merge<API.Webhook>,
HydratedChannelWebhook
> = {
keyMapping: {
id: "id",
name: "name",
avatar: "avatar",
channel_id: "channelId",
token: "token",
},
functions: {
id: (webhook) => webhook.id,
name: (webhook) => webhook.name,
avatar: (webhook, ctx) =>
webhook.avatar ? new File(ctx as Client, webhook.avatar) : undefined,
channelId: (webhook) => webhook.channel_id,
token: (webhook) => webhook.token!,
},
initialHydration: () => ({}),
};
+3
View File
@@ -1,6 +1,7 @@
import { botHydration } from "./bot";
import { channelHydration } from "./channel";
import { channelUnreadHydration } from "./channelUnread";
import { channelWebhookHydration } from "./channelWebhook";
import { emojiHydration } from "./emoji";
import { messageHydration } from "./message";
import { serverHydration } from "./server";
@@ -15,6 +16,7 @@ export { UserBadges, UserFlags } from "./user";
export type { HydratedBot } from "./bot";
export type { HydratedChannel } from "./channel";
export type { HydratedChannelUnread } from "./channelUnread";
export type { HydratedChannelWebhook } from "./channelWebhook";
export type { HydratedEmoji } from "./emoji";
export type { HydratedMessage } from "./message";
export type { HydratedServer } from "./server";
@@ -77,6 +79,7 @@ const hydrators = {
bot: botHydration,
channel: channelHydration,
channelUnread: channelUnreadHydration,
channelWebhook: channelWebhookHydration,
emoji: emojiHydration,
message: messageHydration,
server: serverHydration,