mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-03 01:10:07 +00:00
channel rate limit for editing
This commit is contained in:
@@ -41,6 +41,7 @@ export const endpoints = {
|
||||
GUILD_BANNER: (id: string, icon: string) =>
|
||||
`${baseEndpoints.CDN_URL}/banners/${id}/${icon}`,
|
||||
GUILD_CHANNELS: (id: string) => `${GUILDS_BASE(id)}/channels`,
|
||||
GUILD_CHANNEL: (id: string) => `${baseEndpoints.BASE_URL}/channels/${id}`,
|
||||
GUILD_EMBED: (id: string) => `${GUILDS_BASE(id)}/embed`,
|
||||
GUILD_EMOJI: (id: string, emoji_id: string) =>
|
||||
`${GUILDS_BASE(id)}/emojis/${emoji_id}`,
|
||||
|
||||
@@ -204,6 +204,85 @@ export function getChannelWebhooks(channel: Channel) {
|
||||
return RequestManager.get(endpoints.CHANNEL_WEBHOOKS(channel.id));
|
||||
}
|
||||
|
||||
export function editChannel(channel: Channel, options: ChannelEditOptions) {
|
||||
return RequestManager.patch(endpoints.GUILD_CHANNELS(channel.id), options);
|
||||
interface EditChannelRequest {
|
||||
amount: number;
|
||||
timestamp: number;
|
||||
channelID: string;
|
||||
items: {
|
||||
channel: Channel;
|
||||
options: ChannelEditOptions;
|
||||
}[];
|
||||
}
|
||||
|
||||
const editChannelNameTopicQueue = new Map<string, EditChannelRequest>();
|
||||
let editChannelProcessing = false;
|
||||
|
||||
function processEditChannelQueue() {
|
||||
if (!editChannelProcessing) return;
|
||||
|
||||
const now = Date.now();
|
||||
editChannelNameTopicQueue.forEach((request) => {
|
||||
if (now > request.timestamp) return;
|
||||
// 10 minutes have passed so we can reset this channel again
|
||||
if (!request.items.length) {
|
||||
return editChannelNameTopicQueue.delete(request.channelID);
|
||||
}
|
||||
request.amount = 0;
|
||||
// There are items to process for this request
|
||||
const details = request.items.shift();
|
||||
|
||||
if (!details) return;
|
||||
|
||||
editChannel(details.channel, details.options);
|
||||
const secondDetails = request.items.shift();
|
||||
if (!secondDetails) return;
|
||||
|
||||
return editChannel(secondDetails.channel, secondDetails.options);
|
||||
});
|
||||
|
||||
if (editChannelNameTopicQueue.size) {
|
||||
setTimeout(() => processEditChannelQueue(), 600000);
|
||||
} else {
|
||||
editChannelProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
export function editChannel(channel: Channel, options: ChannelEditOptions) {
|
||||
if (!channel.guildID) throw new Error(Errors.CHANNEL_NOT_IN_GUILD);
|
||||
console.log(1);
|
||||
if (
|
||||
!botHasPermission(channel.guildID, [Permissions.MANAGE_CHANNELS])
|
||||
) {
|
||||
throw new Error(Errors.MISSING_MANAGE_CHANNELS);
|
||||
}
|
||||
console.log(2);
|
||||
if (options.name || options.topic) {
|
||||
const request = editChannelNameTopicQueue.get(channel.id);
|
||||
if (!request) {
|
||||
// If this hasnt been done before simply add 1 for it
|
||||
editChannelNameTopicQueue.set(channel.id, {
|
||||
channelID: channel.id,
|
||||
amount: 1,
|
||||
// 10 minutes from now
|
||||
timestamp: Date.now() + 600000,
|
||||
items: [],
|
||||
});
|
||||
} else if (request.amount === 1) {
|
||||
// Start queuing future requests to this channel
|
||||
request.amount = 2;
|
||||
request.timestamp = Date.now() + 600000;
|
||||
} else {
|
||||
// 2 have already been used add to queue
|
||||
request.items.push({ channel, options });
|
||||
if (editChannelProcessing) return;
|
||||
editChannelProcessing = true;
|
||||
processEditChannelQueue();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return RequestManager.patch(
|
||||
endpoints.GUILD_CHANNEL(channel.id),
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,12 @@ async function runMethod(
|
||||
retryCount = 0,
|
||||
bucketID?: string | null,
|
||||
) {
|
||||
eventHandlers.debug?.({ type: 'requestManager', data: { method, url, body, retryCount, bucketID } });
|
||||
eventHandlers.debug?.(
|
||||
{
|
||||
type: "requestManager",
|
||||
data: { method, url, body, retryCount, bucketID },
|
||||
},
|
||||
);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = async () => {
|
||||
@@ -144,20 +149,28 @@ async function runMethod(
|
||||
if (retryCount > 10) {
|
||||
throw new Error(Errors.RATE_LIMIT_RETRY_MAXED);
|
||||
}
|
||||
await delay(json.retry_after);
|
||||
return runMethod(
|
||||
method,
|
||||
url,
|
||||
body,
|
||||
retryCount++,
|
||||
bucketIDFromHeaders,
|
||||
|
||||
return setTimeout(
|
||||
() =>
|
||||
runMethod(method, url, body, retryCount++, bucketIDFromHeaders),
|
||||
json.retry_after,
|
||||
);
|
||||
}
|
||||
|
||||
eventHandlers.debug?.({ type: 'requestManagerSuccess', data: { method, url, body, retryCount, bucketID } });
|
||||
eventHandlers.debug?.(
|
||||
{
|
||||
type: "requestManagerSuccess",
|
||||
data: { method, url, body, retryCount, bucketID },
|
||||
},
|
||||
);
|
||||
return resolve(json);
|
||||
} catch (error) {
|
||||
eventHandlers.debug?.({ type: 'requestManagerFailed', data: { method, url, body, retryCount, bucketID } });
|
||||
eventHandlers.debug?.(
|
||||
{
|
||||
type: "requestManagerFailed",
|
||||
data: { method, url, body, retryCount, bucketID },
|
||||
},
|
||||
);
|
||||
return reject(error);
|
||||
}
|
||||
};
|
||||
@@ -175,7 +188,10 @@ async function runMethod(
|
||||
}
|
||||
|
||||
function handleStatusCode(status: number) {
|
||||
if (status >= 200 && status < 400) {
|
||||
if (
|
||||
(status >= 200 && status < 400) ||
|
||||
status === HttpResponseCode.TooManyRequests
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -185,10 +201,9 @@ function handleStatusCode(status: number) {
|
||||
case HttpResponseCode.Forbidden:
|
||||
case HttpResponseCode.NotFound:
|
||||
case HttpResponseCode.MethodNotAllowed:
|
||||
case HttpResponseCode.TooManyRequests:
|
||||
throw new Error(Errors.REQUEST_CLIENT_ERROR);
|
||||
throw new Error(Errors.REQUEST_CLIENT_ERROR);
|
||||
case HttpResponseCode.GatewayUnavailable:
|
||||
throw new Error(Errors.REQUEST_SERVER_ERROR);
|
||||
throw new Error(Errors.REQUEST_SERVER_ERROR);
|
||||
}
|
||||
|
||||
// left are all unknown
|
||||
@@ -227,7 +242,9 @@ function processHeaders(url: string, headers: Headers) {
|
||||
// If there is no remaining global limit, we save it in cache
|
||||
if (global) {
|
||||
const reset = Date.now() + Number(retryAfter);
|
||||
eventHandlers.debug?.({ type: 'globallyRateLimited', data: { url, reset }})
|
||||
eventHandlers.debug?.(
|
||||
{ type: "globallyRateLimited", data: { url, reset } },
|
||||
);
|
||||
globallyRateLimited = true;
|
||||
ratelimited = true;
|
||||
|
||||
|
||||
@@ -27,4 +27,5 @@ export enum Errors {
|
||||
REQUEST_SERVER_ERROR = "REQUEST_SERVER_ERROR",
|
||||
REQUEST_UNKNOWN_ERROR = "REQUEST_UNKNOWN_ERROR",
|
||||
BOTS_HIGHEST_ROLE_TOO_LOW = "BOTS_HIGHEST_ROLE_TOO_LOW",
|
||||
CHANNEL_NOT_IN_GUILD = "CHANNEL_NOT_IN_GUILD",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user