mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-10 16:43:31 +01:00
add webhooks v8 (#759)
* add webhook structure and getChannelWebhooks as well as getServerWebhooks * add sendMessage * add the ability to edit create and delete hooks * remove server wide cache and add getter.
This commit is contained in:
@@ -1177,6 +1177,54 @@ export default class Client extends EventEmitter {
|
||||
.then(dataCallback(callback), errorCallback(callback));
|
||||
}
|
||||
|
||||
getServerWebhooks(guild, callback = (/*err, {}*/) => {}) {
|
||||
return this.internal.getServerWebhooks(guild)
|
||||
.then(dataCallback(callback), errorCallback(callback));
|
||||
}
|
||||
|
||||
getChannelWebhooks(channel, callback = (/*err, {}*/) => {}) {
|
||||
return this.internal.getChannelWebhooks(channel)
|
||||
.then(dataCallback(callback), errorCallback(callback));
|
||||
}
|
||||
|
||||
sendWebhookMessage(webhook, content, options = {}, callback = (/*err, {}*/) => {}) {
|
||||
if (typeof options === "function") {
|
||||
// options is the callback
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
return this.internal.sendWebhookMessage(webhook, content, options)
|
||||
.then(dataCallback(callback), errorCallback(callback));
|
||||
}
|
||||
|
||||
editWebhook(webhook, options = {}, callback = (/*err, {}*/) => {}) {
|
||||
if (typeof options === "function") {
|
||||
// options is the callback
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
return this.internal.editWebhook(webhook, options)
|
||||
.then(dataCallback(callback), errorCallback(callback));
|
||||
}
|
||||
|
||||
createWebhook(webhook, options = {}, callback = (/*err, {}*/) => {}) {
|
||||
if (typeof options === "function") {
|
||||
// options is the callback
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
return this.internal.createWebhook(webhook, options)
|
||||
.then(dataCallback(callback), errorCallback(callback));
|
||||
}
|
||||
|
||||
deleteWebhook(webhook, callback = (/*err, {}*/) => {}) {
|
||||
return this.internal.createWebhook(webhook)
|
||||
.then(dataCallback(callback), errorCallback(callback));
|
||||
}
|
||||
|
||||
// def getOAuthApplication
|
||||
getOAuthApplication(appID, callback = (/*err, bans*/) => { }) {
|
||||
if (typeof appID === "function") {
|
||||
|
||||
@@ -21,6 +21,7 @@ import Server from "../Structures/Server";
|
||||
import Message from "../Structures/Message";
|
||||
import Role from "../Structures/Role";
|
||||
import Invite from "../Structures/Invite";
|
||||
import Webhook from "../Structures/Webhook";
|
||||
import VoiceConnection from "../Voice/VoiceConnection";
|
||||
import TokenCacher from "../Util/TokenCacher";
|
||||
|
||||
@@ -58,7 +59,7 @@ export default class InternalClient {
|
||||
var promise = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
})
|
||||
});
|
||||
var buckets = [];
|
||||
var match = url.match(/\/channels\/([0-9]+)\/messages(\/[0-9]+)?$/);
|
||||
if(match) {
|
||||
@@ -311,7 +312,7 @@ export default class InternalClient {
|
||||
"self_deaf": false
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var joinVoice = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -349,7 +350,7 @@ export default class InternalClient {
|
||||
this.client.on("raw", check);
|
||||
joinSendWS();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var existingServerConn = this.voiceConnections.get("server", channel.server); // same server connection
|
||||
if (existingServerConn) {
|
||||
@@ -1438,7 +1439,7 @@ export default class InternalClient {
|
||||
var options = {
|
||||
avatar: this.resolver.resolveToBase64(data.avatar) || this.user.avatar,
|
||||
username: data.username || this.user.username
|
||||
}
|
||||
};
|
||||
|
||||
if (this.email || data.email) {
|
||||
options.email = data.email || this.email;
|
||||
@@ -1507,7 +1508,7 @@ export default class InternalClient {
|
||||
position: (data.position ? data.position : channel.position),
|
||||
user_limit: (data.userLimit ? data.userLimit : channel.userLimit),
|
||||
bitrate: (data.bitrate ? data.bitrate : channel.bitrate ? channel.bitrate : undefined)
|
||||
}
|
||||
};
|
||||
|
||||
if (data.position < 0) {
|
||||
return Promise.reject(new Error("Position cannot be less than 0"));
|
||||
@@ -1566,6 +1567,130 @@ export default class InternalClient {
|
||||
return this.apiRequest("delete", `${Endpoints.FRIENDS}/${user.id}`, true);
|
||||
}
|
||||
|
||||
getServerWebhooks(server) {
|
||||
server = this.resolver.resolveServer(server);
|
||||
|
||||
if (!server) {
|
||||
return Promise.reject(new Error("Failed to resolve server"));
|
||||
}
|
||||
|
||||
return this.apiRequest("get", Endpoints.SERVER_WEBHOOKS(server.id), true)
|
||||
.then(res => res.map(
|
||||
webhook => {
|
||||
let channel = this.channels.get("id", webhook.channel_id);
|
||||
return channel.webhooks.add(new Webhook(
|
||||
webhook,
|
||||
server,
|
||||
channel,
|
||||
this.users.get("id", webhook.user.id)
|
||||
))
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
getChannelWebhooks(channel) {
|
||||
return this.resolver.resolveChannel(channel).then(channel => {
|
||||
if (!channel) {
|
||||
return Promise.reject(new Error("Failed to resolve channel"));
|
||||
}
|
||||
|
||||
return this.apiRequest("get", Endpoints.CHANNEL_WEBHOOKS(channel.id), true)
|
||||
.then(res => res.map(
|
||||
webhook => channel.webhooks.add(new Webhook(
|
||||
webhook,
|
||||
this.servers.get("id", webhook.guild_id),
|
||||
channel,
|
||||
this.users.get("id", webhook.user.id)
|
||||
))
|
||||
));
|
||||
})
|
||||
}
|
||||
|
||||
editWebhook(webhook, options = {}) {
|
||||
return this.resolver.resolveWebhook(webhook).then(webhook => {
|
||||
if (!webhook) {
|
||||
return Promise.reject(new Error(" Failed to resolve webhook"))
|
||||
}
|
||||
|
||||
if (options.hasOwnProperty("avatar")) {
|
||||
options.avatar = this.resolver.resolveToBase64(options.avatar);
|
||||
}
|
||||
|
||||
return this.apiRequest("patch", Endpoints.WEBHOOK(webhook.id), true, options)
|
||||
.then(res => {
|
||||
webhook.name = res.name;
|
||||
webhook.avatar = res.hasOwnProperty('avatar') ? res.avatar : webhook.avatar;
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
createWebhook(channel, options = {}) {
|
||||
return this.resolver.resolveChannel(channel)
|
||||
.then(destination => {
|
||||
if (!channel) {
|
||||
return Promise.reject(new Error(" Failed to resolve channel"))
|
||||
}
|
||||
|
||||
if (options.hasOwnProperty("avatar")) {
|
||||
options.avatar = this.resolver.resolveToBase64(options.avatar);
|
||||
}
|
||||
|
||||
return this.apiRequest("post", Endpoints.CHANNEL_WEBHOOKS(destination.id), true, options)
|
||||
.then(webhook => channel.webhooks.add(new Webhook(
|
||||
webhook,
|
||||
this.servers.get("id", webhook.guild_id),
|
||||
channel,
|
||||
this.users.get("id", webhook.user.id)
|
||||
)));
|
||||
});
|
||||
}
|
||||
|
||||
deleteWebhook(webhook) {
|
||||
return this.resolver.resolveWebhook(webhook).then(webhook => {
|
||||
if (!webhook) {
|
||||
return Promise.reject(new Error(" Failed to resolve webhook"))
|
||||
}
|
||||
|
||||
return this.apiRequest("delete", Endpoints.WEBHOOK(webhook.id), true)
|
||||
.then(() => {
|
||||
webhook.channel.webhooks.remove(webhook);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
sendWebhookMessage(webhook, _content, options = {}) {
|
||||
return this.resolver.resolveWebhook(webhook)
|
||||
.then(destination => {
|
||||
var content = this.resolver.resolveString(_content);
|
||||
|
||||
if (this.client.options.disableEveryone || options.disableEveryone) {
|
||||
content = content.replace(/(@)(everyone|here)/g, '$1\u200b$2');
|
||||
}
|
||||
|
||||
if (!options.hasOwnProperty("username")) {
|
||||
options.username = this.user.username;
|
||||
}
|
||||
|
||||
let slack;
|
||||
if (options.hasOwnProperty("slack")) {
|
||||
slack = options.slack;
|
||||
delete options["slack"];
|
||||
}
|
||||
|
||||
options.content = _content;
|
||||
|
||||
return this.apiRequest(
|
||||
"post",
|
||||
`${Endpoints.WEBHOOK_MESSAGE(destination.id, destination.token)}${slack ? "/slack" : ""}?wait=true`,
|
||||
true,
|
||||
options
|
||||
)
|
||||
.catch(console.error)
|
||||
.then(res => destination.channel.messages.add(new Message(res, destination.channel, this.client)));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//def getOAuthApplication
|
||||
getOAuthApplication(appID) {
|
||||
appID = appID || "@me";
|
||||
|
||||
@@ -43,6 +43,7 @@ import Role from "../../Structures/Role";
|
||||
import Server from "../../Structures/Server";
|
||||
import Message from "../../Structures/Message";
|
||||
import Invite from "../../Structures/Invite";
|
||||
import Webhook from "../../Structures/Webhook";
|
||||
import VoiceConnection from "../../Voice/VoiceConnection";
|
||||
|
||||
export default class Resolver {
|
||||
@@ -211,6 +212,25 @@ export default class Resolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
resolveWebhook(resource) {
|
||||
/*
|
||||
accepts a Webhook
|
||||
*/
|
||||
if (resource instanceof Webhook) {
|
||||
return Promise.resolve(resource);
|
||||
}
|
||||
if (resource instanceof String || typeof resource === "string") {
|
||||
let server = this.internal.servers.find(s => s.webhooks.has("id", resource));
|
||||
if (server) {
|
||||
return Promise.resolve(server.webhooks.get("id", resource));
|
||||
}
|
||||
}
|
||||
|
||||
var error = new Error("Could not resolve webhook");
|
||||
error.resource = resource;
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
resolveMessage(resource) {
|
||||
// accepts a Message, PMChannel & TextChannel
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ const Endpoints = Constants.Endpoints = {
|
||||
SERVER_INTEGRATIONS: (serverID) => `${Endpoints.SERVER(serverID) }/integrations`,
|
||||
SERVER_MEMBERS: (serverID) => `${Endpoints.SERVER(serverID) }/members`,
|
||||
SERVER_CHANNELS: (serverID) => `${Endpoints.SERVER(serverID) }/channels`,
|
||||
SERVER_WEBHOOKS: (serverID) => `${Endpoints.SERVER(serverID) }/webhooks`,
|
||||
|
||||
// channels
|
||||
CHANNELS: `${API}/channels`,
|
||||
@@ -44,6 +45,15 @@ const Endpoints = Constants.Endpoints = {
|
||||
CHANNEL_MESSAGE: (channelID, messageID) => `${Endpoints.CHANNEL_MESSAGES(channelID)}/${messageID}`,
|
||||
CHANNEL_PINS: (channelID) => `${Endpoints.CHANNEL(channelID) }/pins`,
|
||||
CHANNEL_PIN: (channelID, messageID) => `${Endpoints.CHANNEL_PINS(channelID) }/${messageID}`,
|
||||
CHANNEL_WEBHOOKS: (channelID) => `${Endpoints.CHANNEL(channelID) }/webhooks`,
|
||||
|
||||
// webhooks
|
||||
WEBHOOKS: `${API}/webhooks`,
|
||||
WEBHOOK: (webhookID) => `${Endpoints.WEBHOOKS}/${webhookID}`,
|
||||
WEBHOOK_WITH_TOKEN: (webhookID, webhookToken) => `${Endpoints.WEBHOOKS}/${webhookToken}`,
|
||||
WEBHOOK_MESSAGE: (webhookID, webhookToken) => `${Endpoints.WEBHOOK(webhookID)}/${webhookToken}`,
|
||||
WEBHOOK_MESSAGE_SLACK: (webhookID, webhookToken) => `${Endpoints.WEBHOOK_MESSAGE(webhookID, webhookToken)}/slack`,
|
||||
|
||||
|
||||
// friends
|
||||
FRIENDS: `${API}/users/@me/relationships`
|
||||
|
||||
@@ -132,6 +132,19 @@ export default class Server extends Equality {
|
||||
}
|
||||
}
|
||||
|
||||
get webhooks() {
|
||||
return this.channels
|
||||
.map(c => c.webhooks)
|
||||
.reduce((previousChannel, currentChannel) => {
|
||||
if (currentChannel) {
|
||||
currentChannel.forEach(webhook => {
|
||||
previousChannel.add(webhook);
|
||||
})
|
||||
}
|
||||
return previousChannel;
|
||||
}, new Cache("id"));
|
||||
}
|
||||
|
||||
get createdAt() {
|
||||
return new Date((+this.id / 4194304) + 1420070400000);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export default class TextChannel extends ServerChannel{
|
||||
|
||||
this.topic = data.topic;
|
||||
this.lastMessageID = data.last_message_id || data.lastMessageID;
|
||||
this.webhooks = new Cache("id");
|
||||
this.messages = new Cache("id", client.options.maxCachedMessages);
|
||||
}
|
||||
|
||||
|
||||
39
src/Structures/Webhook.js
Normal file
39
src/Structures/Webhook.js
Normal file
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
|
||||
import {Endpoints} from "../Constants";
|
||||
/* example data
|
||||
{
|
||||
id: '164585980739846145'
|
||||
name: 'wlfSS',
|
||||
roles: [ '135829612780322816' ],
|
||||
require_colons: false,
|
||||
managed: true,
|
||||
}
|
||||
*/
|
||||
|
||||
export default class Webhook {
|
||||
constructor(data, server, channel, user) {
|
||||
this.server = server;
|
||||
this.channel = channel;
|
||||
this.id = data.id;
|
||||
this.user = user || data.user;
|
||||
this.name = data.name;
|
||||
this.avatar = data.avatar;
|
||||
this.token = data.token
|
||||
}
|
||||
|
||||
get getURL() {
|
||||
return `https://canary.discordapp.com/api/webhooks/${this.channel.id}/${this.token.id}`;
|
||||
}
|
||||
|
||||
toObject() {
|
||||
let keys = ['id', 'name', 'avatar', 'token'],
|
||||
obj = {};
|
||||
|
||||
for (let k of keys) {
|
||||
obj[k] = this[k];
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import ServerChannel from "./Structures/ServerChannel";
|
||||
import TextChannel from "./Structures/TextChannel";
|
||||
import User from "./Structures/User";
|
||||
import VoiceChannel from "./Structures/VoiceChannel";
|
||||
import Webhook from "./Structures/Webhook";
|
||||
import Constants from "./Constants";
|
||||
import Cache from "./Util/Cache.js";
|
||||
|
||||
@@ -60,6 +61,7 @@ export default {
|
||||
TextChannel,
|
||||
User,
|
||||
VoiceChannel,
|
||||
Webhook,
|
||||
Constants,
|
||||
Cache
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user