nukes everything

This commit is contained in:
Skillz4Killz
2021-11-09 20:47:14 +00:00
committed by GitHub
parent ccd06bf2ac
commit cdb67ba95a
61 changed files with 156 additions and 751 deletions
+19 -5
View File
@@ -1074,8 +1074,22 @@ export interface EventHandlers {
voiceServerUpdate: (bot: Bot, payload: { token: string; endpoint?: string; guildId: bigint }) => any;
voiceStateUpdate: (
bot: Bot,
voiceState: DiscordenoVoiceState,
payload: { guild?: DiscordenoGuild; member?: DiscordenoMember; user?: DiscordenoUser }
voiceState: {
guildId?: bigint;
channelId?: bigint;
userId: bigint;
member?: DiscordenoMember;
user?: DiscordenoUser;
sessionId: string;
deaf: boolean;
mute: boolean;
selfDeaf: boolean;
selfMute: boolean;
selfStream?: boolean;
selfVideo: boolean;
suppress: boolean;
requestToSpeakTimestamp?: number;
}
) => any;
channelCreate: (bot: Bot, channel: DiscordenoChannel) => any;
dispatchRequirements: (bot: Bot, data: GatewayPayload, shardId: number) => any;
@@ -1136,9 +1150,9 @@ export interface EventHandlers {
guildDelete: (bot: Bot, id: bigint, shardId: number) => any;
guildUpdate: (bot: Bot, guild: DiscordenoGuild) => any;
raw: (bot: Bot, data: GatewayPayload, shardId: number) => any;
roleCreate: (bot: Bot, guild: DiscordenoGuild, role: DiscordenoRole) => any;
roleDelete: (bot: Bot, guild: DiscordenoGuild, role: DiscordenoRole) => any;
roleUpdate: (bot: Bot, guild: DiscordenoGuild, role: DiscordenoRole, oldRole?: DiscordenoRole) => any;
roleCreate: (bot: Bot, role: DiscordenoRole) => any;
roleDelete: (bot: Bot, payload: { guildId: bigint; roleId: bigint }) => any;
roleUpdate: (bot: Bot, role: DiscordenoRole) => any;
webhooksUpdate: (bot: Bot, payload: { channelId: bigint; guildId: bigint }) => any;
botUpdate: (bot: Bot, user: DiscordenoUser) => any;
typingStart: (
-3
View File
@@ -212,7 +212,6 @@ export type AsyncCacheHandler<T> = {
export type CacheExecutor = (
type:
| "GET_ALL_MEMBERS"
| "FILTER_CATEGORY_CHILDREN_CHANNELS"
| "DELETE_MESSAGES_FROM_CHANNEL"
| "DELETE_ROLE_FROM_MEMBER"
| "BULK_DELETE_MESSAGES"
@@ -228,8 +227,6 @@ export type CacheExecutor = (
export function createExecute(cache: Cache): CacheExecutor {
return function (type, options) {
switch (type) {
case "FILTER_CATEGORY_CHILDREN_CHANNELS":
return cache.channels.filter((c) => c.parentId === options.parentChannelId);
case "DELETE_MESSAGES_FROM_CHANNEL":
cache.messages.forEach((message) => {
if (message.channelId === options.channelId) {
+4 -11
View File
@@ -5,15 +5,8 @@ import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
export async function handleGuildRoleCreate(bot: Bot, data: DiscordGatewayPayload) {
const payload = data.d as SnakeCasedPropertiesDeep<GuildRoleCreate>;
const guildId = bot.transformers.snowflake(payload.guild_id);
const guild = await bot.cache.guilds.get(guildId);
if (!guild) return;
const role = bot.transformers.role(bot, { role: payload.role, guildId });
guild.roles = guild.roles.set(role.id, role);
await bot.cache.guilds.set(guild.id, guild);
bot.events.roleCreate(bot, guild, role);
bot.events.roleCreate(
bot,
bot.transformers.role(bot, { role: payload.role, guildId: bot.transformers.snowflake(payload.guild_id) })
);
}
+1 -15
View File
@@ -5,19 +5,5 @@ import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
export async function handleGuildRoleDelete(bot: Bot, data: DiscordGatewayPayload) {
const payload = data.d as SnakeCasedPropertiesDeep<GuildRoleDelete>;
const guildId = bot.transformers.snowflake(payload.guild_id);
const guild = await bot.cache.guilds.get(guildId);
if (!guild) return;
const roleId = bot.transformers.snowflake(payload.role_id);
const cachedRole = guild.roles.get(roleId);
guild.roles.delete(roleId);
await bot.cache.guilds.set(guild.id, guild);
if (cachedRole) bot.events.roleDelete(bot, guild, cachedRole);
// For bots without GUILD_MEMBERS member.roles is never updated breaking permissions checking.
await bot.cache.execute("DELETE_ROLE_FROM_MEMBER", { guildId: guild.id, roleId });
bot.events.roleDelete(bot, { roleId: bot.transformers.snowflake(payload.role_id), guildId: bot.transformers.snowflake(payload.guild_id) });
}
+4 -8
View File
@@ -5,13 +5,9 @@ import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
export async function handleGuildRoleUpdate(bot: Bot, data: DiscordGatewayPayload) {
const payload = data.d as SnakeCasedPropertiesDeep<GuildRoleUpdate>;
const guildId = bot.transformers.snowflake(payload.guild_id);
const guild = await bot.cache.guilds.get(guildId);
if (!guild) return;
const role = bot.transformers.role(bot, { role: payload.role, guildId });
guild.roles = guild.roles.set(role.id, role);
await bot.cache.guilds.set(guild.id, guild);
bot.events.roleUpdate(bot, guild, role, guild.roles.get(role.id));
bot.events.roleUpdate(
bot,
bot.transformers.role(bot, { role: payload.role, guildId: bot.transformers.snowflake(payload.guild_id) })
);
}
+19 -11
View File
@@ -8,16 +8,24 @@ export async function handleVoiceStateUpdate(bot: Bot, data: DiscordGatewayPaylo
if (!payload.guild_id) return;
const guildId = bot.transformers.snowflake(payload.guild_id);
const voiceState = bot.transformers.voiceState(bot, { voiceState: payload, guildId });
const userId = bot.transformers.snowflake(payload.user_id);
const guild = await bot.cache.guilds.get(guildId);
if (guild) {
guild.voiceStates.set(voiceState.userId, voiceState);
await bot.cache.guilds.set(guild.id, guild);
}
const user = payload.member ? bot.transformers.user(bot, payload.member.user) : undefined;
const member = payload.member ? bot.transformers.member(bot, payload.member, guildId, user!.id) : undefined;
bot.events.voiceStateUpdate(bot, voiceState, { guild, member, user });
bot.events.voiceStateUpdate(bot, {
guildId,
userId,
channelId: payload.channel_id ? bot.transformers.snowflake(payload.channel_id) : undefined,
member: payload.member ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined,
user: payload.member ? bot.transformers.user(bot, payload.member.user) : undefined,
sessionId: payload.session_id,
deaf: payload.deaf,
mute: payload.mute,
selfDeaf: payload.self_deaf,
selfMute: payload.self_mute,
selfStream: payload.self_stream,
selfVideo: payload.self_video,
suppress: payload.suppress,
requestToSpeakTimestamp: payload.request_to_speak_timestamp
? Date.parse(payload.request_to_speak_timestamp)
: undefined,
});
}
@@ -1,8 +0,0 @@
import { Bot } from "../../bot.ts";
/** Gets an array of all the channels ids that are the children of this category.
* ⚠️ This does not work for custom cache users!
*/
export async function categoryChildren(bot: Bot, parentChannelId: bigint) {
return await bot.cache.execute("FILTER_CATEGORY_CHILDREN_CHANNELS", { parentChannelId });
}
+14 -15
View File
@@ -1,23 +1,22 @@
import type { Bot } from "../../bot.ts";
import { separate } from "../../transformers/channel.ts";
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
import { DiscordenoChannel, separate } from "../../transformers/channel.ts";
import type { CreateGuildChannel } from "../../types/guilds/create_guild_channel.ts";
/** Create a copy of a channel */
export async function cloneChannel(bot: Bot, channelId: bigint, reason?: string) {
const channelToClone = await bot.cache.channels.get(channelId);
if (!channelToClone) throw new Error(bot.constants.Errors.CHANNEL_NOT_FOUND);
//Check for DM channel
if (channelToClone.type === DiscordChannelTypes.DM || channelToClone.type === DiscordChannelTypes.GroupDm) {
throw new Error(bot.constants.Errors.CHANNEL_NOT_IN_GUILD);
}
export async function cloneChannel(bot: Bot, channel: DiscordenoChannel, reason?: string) {
if (!channel.guildId) throw new Error(`Cannot clone a channel outside a guild`);
const createChannelOptions: CreateGuildChannel = {
...channelToClone,
name: channelToClone.name!,
topic: channelToClone.topic || undefined,
permissionOverwrites: channelToClone.permissionOverwrites.map((overwrite) => {
type: channel.type,
bitrate: channel.bitrate,
userLimit: channel.userLimit,
rateLimitPerUser: channel.rateLimitPerUser,
position: channel.position,
parentId: channel.parentId,
nsfw: channel.nsfw,
name: channel.name!,
topic: channel.topic || undefined,
permissionOverwrites: channel.permissionOverwrites.map((overwrite) => {
const [type, id, allow, deny] = separate(overwrite);
return {
@@ -30,5 +29,5 @@ export async function cloneChannel(bot: Bot, channelId: bigint, reason?: string)
};
//Create the channel (also handles permissions)
return await bot.helpers.createChannel(channelToClone.guildId!, createChannelOptions, reason);
return await bot.helpers.createChannel(channel.guildId!, createChannelOptions, reason);
}
+1 -8
View File
@@ -5,10 +5,6 @@ import type { Bot } from "../../bot.ts";
/** Create a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */
export async function createChannel(bot: Bot, guildId: bigint, options?: CreateGuildChannel, reason?: string) {
if (options?.permissionOverwrites) {
await bot.utils.requireOverwritePermissions(bot, guildId, options.permissionOverwrites);
}
// BITRATES ARE IN THOUSANDS SO IF USER PROVIDES 32 WE CONVERT TO 32000
if (options?.bitrate && options.bitrate < 1000) options.bitrate *= 1000;
@@ -38,8 +34,5 @@ export async function createChannel(bot: Bot, guildId: bigint, options?: CreateG
: {}
);
const channel = bot.transformers.channel(bot, { channel: result, guildId });
await bot.cache.channels.set(channel.id, channel);
return channel;
return bot.transformers.channel(bot, { channel: result, guildId });
}
@@ -1,20 +1,9 @@
import type { StageInstance } from "../../types/channels/stage_instance.ts";
import type { Bot } from "../../bot.ts";
import { ChannelTypes } from "../../types/channels/channel_types.ts";
import { PrivacyLevel } from "../../types/channels/privacy_level.ts";
/** Creates a new Stage instance associated to a Stage channel. Requires the user to be a moderator of the Stage channel. */
export async function createStageInstance(bot: Bot, channelId: bigint, topic: string, privacyLevel?: PrivacyLevel) {
const channel = await bot.cache.channels.get(channelId);
if (channel) {
if (channel.type !== ChannelTypes.GuildStageVoice) {
throw new Error(bot.constants.Errors.CHANNEL_NOT_STAGE_VOICE);
}
await bot.utils.requireBotChannelPermissions(bot, channel, ["MANAGE_CHANNELS", "MUTE_MEMBERS", "MOVE_MEMBERS"]);
}
if (!bot.utils.validateLength(topic, { max: 120, min: 1 })) {
throw new Error(bot.constants.Errors.INVALID_TOPIC_LENGTH);
}
-17
View File
@@ -2,23 +2,6 @@ import type { Bot } from "../../bot.ts";
/** Delete a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */
export async function deleteChannel(bot: Bot, channelId: bigint, reason?: string) {
const channel = await bot.cache.channels.get(channelId);
if (channel?.guildId) {
const guild = await bot.cache.guilds.get(channel.guildId);
if (!guild) throw new Error(bot.constants.Errors.GUILD_NOT_FOUND);
if (guild.rulesChannelId === channelId) {
throw new Error(bot.constants.Errors.RULES_CHANNEL_CANNOT_BE_DELETED);
}
if (guild.publicUpdatesChannelId === channelId) {
throw new Error(bot.constants.Errors.UPDATES_CHANNEL_CANNOT_BE_DELETED);
}
await bot.utils.requireBotGuildPermissions(bot, guild, ["MANAGE_CHANNELS"]);
}
return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.CHANNEL_BASE(channelId), {
reason,
});
@@ -1,17 +1,6 @@
import { ChannelTypes } from "../../types/channels/channel_types.ts";
import type { Bot } from "../../bot.ts";
/** Deletes the Stage instance. Requires the user to be a moderator of the Stage channel. */
export async function deleteStageInstance(bot: Bot, channelId: bigint) {
const channel = await bot.cache.channels.get(channelId);
if (channel) {
if (channel.type !== ChannelTypes.GuildStageVoice) {
throw new Error(bot.constants.Errors.CHANNEL_NOT_STAGE_VOICE);
}
await bot.utils.requireBotChannelPermissions(bot, channel, ["MUTE_MEMBERS", "MANAGE_CHANNELS", "MOVE_MEMBERS"]);
}
return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.STAGE_INSTANCE(channelId));
}
-8
View File
@@ -5,14 +5,6 @@ import { DiscordenoChannel } from "../../transformers/channel.ts";
/** Update a channel's settings. Requires the `MANAGE_CHANNELS` permission for the guild. */
export async function editChannel(bot: Bot, channelId: bigint, options: ModifyChannel, reason?: string) {
const channel = await bot.cache.channels.get(channelId);
if (channel) {
if (options.permissionOverwrites && Array.isArray(options.permissionOverwrites)) {
await bot.utils.requireOverwritePermissions(bot, channel.guildId, options.permissionOverwrites);
}
}
if (options.name || options.topic) {
const request = editChannelNameTopicQueue.get(channelId);
if (!request) {
+2 -7
View File
@@ -5,16 +5,11 @@ import type { Channel } from "../../types/channels/channel.ts";
*
* ⚠️ **If you need this, you are probably doing something wrong. This is not intended for use. Your channels will be cached in your guild.**
*/
export async function getChannel(bot: Bot, channelId: bigint, addToCache = true) {
export async function getChannel(bot: Bot, channelId: bigint) {
const result = await bot.rest.runMethod<Channel>(bot.rest, "get", bot.constants.endpoints.CHANNEL_BASE(channelId));
const discordenoChannel = bot.transformers.channel(bot, {
return bot.transformers.channel(bot, {
channel: result,
guildId: result.guild_id ? bot.transformers.snowflake(result.guild_id) : undefined,
});
if (addToCache) {
await bot.cache.channels.set(discordenoChannel.id, discordenoChannel);
}
return discordenoChannel;
}
+2 -13
View File
@@ -6,21 +6,10 @@ import type { Bot } from "../../bot.ts";
*
* ⚠️ **If you need this, you are probably doing something wrong. This is not intended for use. Your channels will be cached in your guild.**
*/
export async function getChannels(bot: Bot, guildId: bigint, addToCache = true) {
export async function getChannels(bot: Bot, guildId: bigint) {
const result = await bot.rest.runMethod<Channel[]>(bot.rest, "get", bot.constants.endpoints.GUILD_CHANNELS(guildId));
return new Collection(
(
await Promise.all(
result.map(async (res) => {
const channel = bot.transformers.channel(bot, { channel: res, guildId });
if (addToCache) {
await bot.cache.channels.set(channel.id, channel);
}
return channel;
})
)
).map((c) => [c.id, c])
result.map((res) => bot.transformers.channel(bot, { channel: res, guildId })).map((c) => [c.id, c])
);
}
@@ -1,16 +1,7 @@
import { ChannelTypes } from "../../types/channels/channel_types.ts";
import type { StageInstance } from "../../types/channels/stage_instance.ts";
import type { Bot } from "../../bot.ts";
/** Gets the stage instance associated with the Stage channel, if it exists. */
export async function getStageInstance(bot: Bot, channelId: bigint) {
const channel = await bot.cache.channels.get(channelId);
if (channel) {
if (channel.type !== ChannelTypes.GuildStageVoice) {
throw new Error(bot.constants.Errors.CHANNEL_NOT_STAGE_VOICE);
}
}
return await bot.rest.runMethod<StageInstance>(bot.rest, "get", bot.constants.endpoints.STAGE_INSTANCE(channelId));
}
-24
View File
@@ -1,24 +0,0 @@
import type { Bot } from "../../bot.ts";
import { separate } from "../../transformers/channel.ts";
/** Checks whether a channel is synchronized with its parent/category channel or not. */
export async function isChannelSynced(bot: Bot, channelId: bigint) {
const channel = await bot.cache.channels.get(channelId);
if (!channel?.parentId) return false;
const parentChannel = await bot.cache.channels.get(channel.parentId);
if (!parentChannel) return false;
return channel.permissionOverwrites?.every((overwrite) => {
const [type, id, allow, deny] = separate(overwrite);
const permission = parentChannel.permissionOverwrites?.find((ow) => {
const [_, owID] = separate(ow);
return owID === id;
});
if (!permission) return false;
const [parentType, parentId, parentAllow, parentDeny] = separate(permission);
return !(allow !== parentAllow || deny !== parentDeny);
});
}
-23
View File
@@ -7,28 +7,5 @@ import type { Bot } from "../../bot.ts";
* this endpoint may be called to let the user know that the bot is processing their message.
*/
export async function startTyping(bot: Bot, channelId: bigint) {
const channel = await bot.cache.channels.get(channelId);
// If the channel is cached, we can do extra checks/safety
if (channel) {
if (
![
DiscordChannelTypes.DM,
DiscordChannelTypes.GuildNews,
DiscordChannelTypes.GuildText,
DiscordChannelTypes.GuildNewsThread,
DiscordChannelTypes.GuildPrivateThread,
DiscordChannelTypes.GuildPublicThread,
DiscordChannelTypes.GuildVoice,
].includes(channel.type)
) {
throw new Error(bot.constants.Errors.CHANNEL_NOT_TEXT_BASED);
}
const hasSendMessagesPerm = await bot.utils.botHasChannelPermissions(bot, channelId, ["SEND_MESSAGES"]);
if (!hasSendMessagesPerm) {
throw new Error(bot.constants.Errors.MISSING_SEND_MESSAGES);
}
}
return await bot.rest.runMethod<undefined>(bot.rest, "post", bot.constants.endpoints.CHANNEL_TYPING(channelId));
}
@@ -2,17 +2,5 @@ import type { Bot } from "../../../bot.ts";
/** Adds a user to a thread. Requires the ability to send messages in the thread. Requires the thread is not archived. */
export async function addToThread(bot: Bot, threadId: bigint, userId: bigint) {
// const thread = await bot.cache.threads.get(threadId);
// if (thread) {
// if (thread.archived) {
// throw new Error(bot.constants.Errors.CANNOT_ADD_USER_TO_ARCHIVED_THREADS);
// }
// // If a user id is provided SEND_MESSAGES is required.
// const channel = await bot.cache.channels.get(thread.parentId);
// // TODO: does MANAGE_THREADS override this????
// if (channel) await bot.utils.requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES"]);
// }
return await bot.rest.runMethod<undefined>(bot.rest, "put", bot.constants.endpoints.THREAD_USER(threadId, userId));
}
@@ -2,13 +2,7 @@ import type { Bot } from "../../../bot.ts";
/** Delete a thread in your server. Bot needs MANAGE_THREADS permissions in the server. */
export async function deleteThread(bot: Bot, threadId: bigint, reason?: string) {
// const thread = await bot.cache.threads.get(threadId);
// if (thread) {
// const channel = await bot.cache.channels.get(thread?.parentId);
// if (channel?.guildId) await bot.utils.requireBotGuildPermissions(bot, channel.guildId, ["MANAGE_THREADS"]);
// }
// return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.CHANNEL_BASE(threadId), {
// reason,
// });
return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.CHANNEL_BASE(threadId), {
reason,
});
}
@@ -6,24 +6,18 @@ import { Collection } from "../../../util/collection.ts";
/** Returns thread members objects that are members of the thread. */
export async function getThreadMembers(bot: Bot, threadId: bigint) {
// // Check if intents is not 0 as proxy ws won't set intents in other instances
// if (
// bot.gateway.identifyPayload.intents &&
// !(bot.gateway.identifyPayload.intents & DiscordGatewayIntents.GuildMembers)
// ) {
// throw new Error(bot.constants.Errors.MISSING_INTENT_GUILD_MEMBERS);
// }
// const thread = await bot.cache.threads.get(threadId);
// if (thread?.isPrivate) {
// const channel = await bot.cache.channels.get(thread.parentId);
// if (channel && !(await bot.utils.botHasChannelPermissions(bot, channel, ["MANAGE_THREADS"])) && !thread.botIsMember)
// throw new Error(bot.constants.Errors.CANNOT_GET_MEMBERS_OF_AN_UNJOINED_PRIVATE_THREAD);
// }
// const result = await bot.rest.runMethod<ThreadMember[]>(
// bot.rest,
// "get",
// bot.constants.endpoints.THREAD_MEMBERS(threadId)
// );
// const members = result.map((member) => threadMemberModified(member));
// return new Collection(members.map((member) => [member.id, member]));
const result = await bot.rest.runMethod<ThreadMember[]>(
bot.rest,
"get",
bot.constants.endpoints.THREAD_MEMBERS(threadId)
);
return result;
// return new Collection(result.map((res) => [bot.transformers.snowflake(result.userId), {
// id?: string;
// /** The id of the user */
// userId?: string;
// /** The time the current user last joined the thread */
// joinTimestamp: string;
// }]));
}
+1 -6
View File
@@ -2,10 +2,5 @@ import type { Bot } from "../../../bot.ts";
/** Adds the bot to the thread. Cannot join an archived thread. */
export async function joinThread(bot: Bot, threadId: bigint) {
// const thread = await bot.cache.threads.get(threadId);
// if (thread?.archived) {
// throw new Error(bot.constants.Errors.CANNOT_ADD_USER_TO_ARCHIVED_THREADS);
// }
// return await bot.rest.runMethod<undefined>(bot.rest, "put", bot.constants.endpoints.THREAD_ME(threadId));
return await bot.rest.runMethod<undefined>(bot.rest, "put", bot.constants.endpoints.THREAD_ME(threadId));
}
+1 -4
View File
@@ -2,8 +2,5 @@ import type { Bot } from "../../../bot.ts";
/** Removes the bot from a thread. Requires the thread is not archived. */
export async function leaveThread(bot: Bot, threadId: bigint) {
// const thread = await bot.cache.threads.get(threadId);
// if (thread?.archived) throw new Error(bot.constants.Errors.CANNOT_LEAVE_ARCHIVED_THREAD);
// return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.THREAD_ME(threadId));
return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.THREAD_ME(threadId));
}
@@ -2,15 +2,5 @@ import type { Bot } from "../../../bot.ts";
/** Removes a user from a thread. Requires the MANAGE_THREADS permission or that you are the creator of the thread. Also requires the thread is not archived. */
export async function removeThreadMember(bot: Bot, threadId: bigint, userId: bigint) {
// const thread = await bot.cache.threads.get(threadId);
// if (thread) {
// if (thread.archived) throw new Error(bot.constants.Errors.CANNOT_REMOVE_FROM_ARCHIVED_THREAD);
// if (thread.ownerId !== bot.id) {
// const channel = await bot.cache.channels.get(thread.parentId);
// if (channel) await bot.utils.requireBotChannelPermissions(bot, channel, ["MANAGE_THREADS"]);
// }
// }
// return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.THREAD_USER(threadId, userId));
return await bot.rest.runMethod<undefined>(bot.rest, "delete", bot.constants.endpoints.THREAD_USER(threadId, userId));
}
@@ -9,22 +9,13 @@ export async function startThreadWithMessage(
messageId: bigint,
options: StartThreadWithMessage
) {
// const channel = await bot.cache.channels.get(channelId);
// if (channel) {
// if (!channel.isGuildTextBasedChannel) {
// throw new Error(bot.constants.Errors.INVALID_THREAD_PARENT_CHANNEL_TYPE);
// }
// await bot.utils.requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES", "USE_PUBLIC_THREADS"]);
// }
// return channelToThread(
// await bot.rest.runMethod<Channel>(
// bot.rest,
// "post",
// bot.constants.endpoints.THREAD_START_PUBLIC(channelId, messageId),
// {
// name: options.name,
// auto_archive_duration: options.autoArchiveDuration,
// }
// )
// );
return await bot.rest.runMethod<Channel>(
bot.rest,
"post",
bot.constants.endpoints.THREAD_START_PUBLIC(channelId, messageId),
{
name: options.name,
auto_archive_duration: options.autoArchiveDuration,
}
);
}
@@ -4,17 +4,8 @@ import type { Bot } from "../../../bot.ts";
/** Creates a new private thread. Returns a thread channel. */
export async function startThreadWithoutMessage(bot: Bot, channelId: bigint, options: StartThreadWithoutMessage) {
// const channel = await bot.cache.channels.get(channelId);
// if (channel) {
// if (!channel.isGuildTextBasedChannel) throw new Error(bot.constants.Errors.INVALID_THREAD_PARENT_CHANNEL_TYPE);
// if (channel.isNewsChannel) throw new Error(bot.constants.Errors.GUILD_NEWS_CHANNEL_ONLY_SUPPORT_PUBLIC_THREADS);
// await bot.utils.requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES", "USE_PRIVATE_THREADS"]);
// }
// if (options.invitable && options.type !== PRIVATETHREAD) throw new Error("Invitiable option requires private threads.");
// return channelToThread(
// await bot.rest.runMethod<Channel>(bot.rest, "post", bot.constants.endpoints.THREAD_START_PRIVATE(channelId), {
// name: options.name,
// auto_archive_duration: options.autoArchiveDuration,
// })
// );
return await bot.rest.runMethod<Channel>(bot.rest, "post", bot.constants.endpoints.THREAD_START_PRIVATE(channelId), {
name: options.name,
auto_archive_duration: options.autoArchiveDuration,
});
}
@@ -8,16 +8,6 @@ export async function updateStageInstance(
channelId: bigint,
data: Partial<Pick<StageInstance, "topic" | "privacyLevel">> = {}
) {
const channel = await bot.cache.channels.get(channelId);
if (channel) {
if (channel.type !== ChannelTypes.GuildStageVoice) {
throw new Error(bot.constants.Errors.CHANNEL_NOT_STAGE_VOICE);
}
await bot.utils.requireBotChannelPermissions(bot, channel, ["MOVE_MEMBERS", "MUTE_MEMBERS", "MANAGE_CHANNELS"]);
}
if (
data?.topic &&
!bot.utils.validateLength(data.topic, {
+1 -10
View File
@@ -8,14 +8,5 @@ import type { Bot } from "../../bot.ts";
* ⚠️ **If you need this, you are probably doing something wrong. Always use cache.guilds.get()?.emojis
*/
export async function getEmoji(bot: Bot, guildId: bigint, emojiId: bigint, addToCache = true) {
const result = await bot.rest.runMethod<Emoji>(bot.rest, "get", bot.constants.endpoints.GUILD_EMOJI(guildId, emojiId));
if (addToCache) {
const guild = await bot.cache.guilds.get(guildId);
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
guild.emojis.set(emojiId, result);
await bot.cache.guilds.set(guildId, guild);
}
return result;
return await bot.rest.runMethod<Emoji>(bot.rest, "get", bot.constants.endpoints.GUILD_EMOJI(guildId, emojiId));
}
+1 -13
View File
@@ -11,17 +11,5 @@ import { Collection } from "../../util/collection.ts";
export async function getEmojis(bot: Bot, guildId: bigint, addToCache = true) {
const result = await bot.rest.runMethod<Emoji[]>(bot.rest, "get", bot.constants.endpoints.GUILD_EMOJIS(guildId));
if (addToCache) {
const guild = await bot.cache.guilds.get(guildId);
if (!guild) throw new Error(Errors.GUILD_NOT_FOUND);
result.forEach((emoji) => {
bot.events.debug(`Running forEach loop in get_emojis file.`);
guild.emojis.set(bot.transformers.snowflake(emoji.id!), emoji);
});
await bot.cache.guilds.set(guildId, guild);
}
return new Collection(result.map((e) => [e.id!, e]));
return new Collection(result.map((e) => [bot.transformers.snowflake(e.id), bot.transformers.emoji(bot, e)]));
}
+1 -7
View File
@@ -18,11 +18,5 @@ export async function createGuild(bot: Bot, options: CreateGuild) {
verification_level: options.verificationLevel,
});
const guild = bot.transformers.guild(bot, { guild: result, shardId: 0 });
// MANUALLY CACHE THE GUILD
await bot.cache.guilds.set(guild.id, guild);
// MANUALLY CACHE THE BOT
await bot.helpers.getMember(guild.id, bot.id);
return guild;
return bot.transformers.guild(bot, { guild: result, shardId: 0 });
}
+8 -6
View File
@@ -3,9 +3,7 @@ import type { Guild } from "../../types/guilds/guild.ts";
import type { ModifyGuild } from "../../types/guilds/modify_guild.ts";
/** Modify a guilds settings. Requires the MANAGE_GUILD permission. */
export async function editGuild(bot: Bot, guildId: bigint, options: ModifyGuild) {
await bot.utils.requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
export async function editGuild(bot: Bot, guildId: bigint, options: ModifyGuild, shardId: number) {
if (options.icon && !options.icon.startsWith("data:image/")) {
options.icon = await bot.utils.urlToBase64(options.icon);
}
@@ -18,11 +16,15 @@ export async function editGuild(bot: Bot, guildId: bigint, options: ModifyGuild)
options.splash = await bot.utils.urlToBase64(options.splash);
}
const result = await bot.rest.runMethod<Guild>(bot.rest, "patch", bot.constants.endpoints.GUILDS_BASE(guildId), {});
const result = await bot.rest.runMethod<Guild>(
bot.rest,
"patch",
bot.constants.endpoints.GUILDS_BASE(guildId),
options
);
const cached = await bot.cache.guilds.get(guildId);
return bot.transformers.guild(bot, {
guild: result,
shardId: cached?.shardId || bot.utils.calculateShardId(bot.gateway, guildId),
shardId,
});
}
+1 -6
View File
@@ -13,21 +13,16 @@ export async function getGuild(
guildId: bigint,
options: { counts?: boolean; addToCache?: boolean } = {
counts: true,
addToCache: true,
}
) {
const result = await bot.rest.runMethod<Guild>(bot.rest, "get", bot.constants.endpoints.GUILDS_BASE(guildId), {
with_counts: options.counts,
});
const guild = await bot.transformers.guild(bot, {
const guild = bot.transformers.guild(bot, {
guild: result,
shardId: bot.utils.calculateShardId(bot.gateway, guildId),
});
if (options.addToCache) {
await bot.cache.guilds.set(guild.id, guild);
}
return guild;
}
+1 -7
View File
@@ -2,13 +2,7 @@ import type { GuildWidgetDetails } from "../../types/guilds/guild_widget_details
import type { Bot } from "../../bot.ts";
/** Returns the widget for the guild. */
export async function getWidget(bot: Bot, guildId: bigint, options?: { force: boolean }) {
if (!options?.force) {
const guild = await bot.cache.guilds.get(guildId);
if (!guild) throw new Error(bot.constants.Errors.GUILD_NOT_FOUND);
if (!guild?.widgetEnabled) throw new Error(bot.constants.Errors.GUILD_WIDGET_NOT_ENABLED);
}
export async function getWidget(bot: Bot, guildId: bigint) {
return await bot.rest.runMethod<GuildWidgetDetails>(
bot.rest,
"get",
+1 -11
View File
@@ -2,16 +2,6 @@ import type { Bot } from "../../bot.ts";
import type { GetGuildWidgetImageQuery } from "../../types/guilds/get_guild_widget_image.ts";
/** Returns the widget image URL for the guild. */
export async function getWidgetImageURL(
bot: Bot,
guildId: bigint,
options?: GetGuildWidgetImageQuery & { force?: boolean }
) {
if (!options?.force) {
const guild = await bot.cache.guilds.get(guildId);
if (!guild) throw new Error(bot.constants.Errors.GUILD_NOT_FOUND);
if (!guild.widgetEnabled) throw new Error(bot.constants.Errors.GUILD_WIDGET_NOT_ENABLED);
}
export async function getWidgetImageURL(bot: Bot, guildId: bigint, options?: GetGuildWidgetImageQuery) {
return `${bot.constants.endpoints.GUILD_WIDGET(guildId)}.png?style=${options?.style ?? "shield"}`;
}
+2 -16
View File
@@ -1,21 +1,7 @@
import type { InviteMetadata } from "../../types/invites/invite_metadata.ts";
import type { Bot } from "../../bot.ts";
import { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Deletes an invite for the given code. Requires `MANAGE_CHANNELS` or `MANAGE_GUILD` permission */
export async function deleteInvite(bot: Bot, channelId: bigint, inviteCode: string) {
const channel = await bot.cache.channels.get(channelId);
if (channel) {
const hasPerm = await bot.utils.botHasChannelPermissions(bot, channel, ["MANAGE_CHANNELS"]);
if (!hasPerm) {
await bot.utils.requireBotGuildPermissions(bot, channel.guildId, ["MANAGE_GUILD"]);
}
}
return await bot.rest.runMethod<InviteMetadata>(
bot.rest,
"delete",
bot.constants.endpoints.INVITE(inviteCode)
);
export async function deleteInvite(bot: Bot, inviteCode: string) {
return await bot.rest.runMethod<InviteMetadata>(bot.rest, "delete", bot.constants.endpoints.INVITE(inviteCode));
}
-38
View File
@@ -2,47 +2,9 @@ import type { ModifyGuildMember } from "../../types/guilds/modify_guild_member.t
import type { GuildMemberWithUser } from "../../types/members/guild_member.ts";
import type { PermissionStrings } from "../../types/permissions/permission_strings.ts";
import type { Bot } from "../../bot.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Edit the member */
export async function editMember(bot: Bot, guildId: bigint, memberId: bigint, options: ModifyGuildMember) {
const requiredPerms: Set<PermissionStrings> = new Set();
if (options.nick) {
if (options.nick.length > 32) {
throw new Error(bot.constants.Errors.NICKNAMES_MAX_LENGTH);
}
requiredPerms.add("MANAGE_NICKNAMES");
}
if (options.roles) requiredPerms.add("MANAGE_ROLES");
if (options.mute !== undefined || options.deaf !== undefined || options.channelId !== undefined) {
const memberVoiceState = (await bot.cache.guilds.get(guildId))?.voiceStates.get(memberId);
if (!memberVoiceState?.channelId) {
throw new Error(bot.constants.Errors.MEMBER_NOT_IN_VOICE_CHANNEL);
}
if (options.mute !== undefined) {
requiredPerms.add("MUTE_MEMBERS");
}
if (options.deaf !== undefined) {
requiredPerms.add("DEAFEN_MEMBERS");
}
if (options.channelId) {
const requiredVoicePerms: Set<PermissionStrings> = new Set(["CONNECT", "MOVE_MEMBERS"]);
if (memberVoiceState) {
await bot.utils.requireBotChannelPermissions(bot, memberVoiceState?.channelId, [...requiredVoicePerms]);
}
await bot.utils.requireBotChannelPermissions(bot, options.channelId, [...requiredVoicePerms]);
}
}
await bot.utils.requireBotGuildPermissions(bot, guildId, [...requiredPerms]);
const result = await bot.rest.runMethod<GuildMemberWithUser>(
bot.rest,
"patch",
@@ -1,7 +0,0 @@
import { Bot } from "../../bot.ts";
import { RequestGuildMembers } from "../../types/members/request_guild_members.ts";
export async function fetchAndRetrieveMembers(bot: Bot, shardId: number, options: RequestGuildMembers) {
await bot.helpers.fetchMembers(options.guildId, shardId, options);
return await bot.cache.execute("GET_ALL_MEMBERS", { guildId: options.guildId });
}
+2 -8
View File
@@ -5,18 +5,12 @@ import type { Bot } from "../../bot.ts";
*
* ⚠️ **ADVANCED USE ONLY: Your members will be cached in your guild most likely. Only use this when you are absolutely sure the member is not cached.**
*/
export async function getMember(bot: Bot, guildId: bigint, id: bigint, options?: { force?: boolean }) {
const guild = await bot.cache.guilds.get(guildId);
if (!guild && !options?.force) return;
export async function getMember(bot: Bot, guildId: bigint, id: bigint) {
const data = await bot.rest.runMethod<GuildMemberWithUser>(
bot.rest,
"get",
bot.constants.endpoints.GUILD_MEMBER(guildId, id)
);
const discordenoMember = bot.transformers.member(bot, data, guildId, id);
await bot.cache.members.set(discordenoMember.id, discordenoMember);
return discordenoMember;
return bot.transformers.member(bot, data, guildId, id);
}
+6 -26
View File
@@ -13,20 +13,12 @@ import type { DiscordenoMember } from "../../transformers/member.ts";
* REST(this function): 50/s global(across all shards) rate limit with ALL requests this included
* GW(fetchMembers): 120/m(PER shard) rate limit. Meaning if you have 8 shards your limit is 960/m.
*/
export async function getMembers(bot: Bot, guildId: bigint, options?: ListGuildMembers & { addToCache?: boolean }) {
// Check if intents is not 0 as proxy ws won't set intents in other instances
if (bot.intents && !(bot.intents & DiscordGatewayIntents.GuildMembers)) {
throw new Error(bot.constants.Errors.MISSING_INTENT_GUILD_MEMBERS);
}
const guild = await bot.cache.guilds.get(guildId);
if (!guild) throw new Error(bot.constants.Errors.GUILD_NOT_FOUND);
export async function getMembers(bot: Bot, guildId: bigint, options: ListGuildMembers & { memberCount: number }) {
const members = new Collection<bigint, DiscordenoMember>();
let membersLeft = options?.limit ?? guild.memberCount;
let membersLeft = options?.limit ?? options.memberCount;
let loops = 1;
while ((options?.limit ?? guild.memberCount) > members.size && membersLeft > 0) {
while ((options?.limit ?? options.memberCount) > members.size && membersLeft > 0) {
bot.events.debug("Running while loop in getMembers function.");
if (options?.limit && options.limit > 1000) {
@@ -41,21 +33,8 @@ export async function getMembers(bot: Bot, guildId: bigint, options?: ListGuildM
}`
);
const discordenoMembers = await Promise.all(
result.map(async (member) => {
const discordenoMember = bot.transformers.member(
bot,
member,
guildId,
bot.transformers.snowflake(member.user.id)
);
if (options?.addToCache !== false) {
await bot.cache.members.set(discordenoMember.id, discordenoMember);
}
return discordenoMember;
})
const discordenoMembers = result.map((member) =>
bot.transformers.member(bot, member, guildId, bot.transformers.snowflake(member.user.id))
);
if (!discordenoMembers.length) break;
@@ -68,6 +47,7 @@ export async function getMembers(bot: Bot, guildId: bigint, options?: ListGuildM
options = {
limit: options?.limit,
after: discordenoMembers[discordenoMembers.length - 1].id.toString(),
memberCount: options.memberCount,
};
membersLeft -= 1000;
+4 -17
View File
@@ -2,8 +2,6 @@ import type { GuildMemberWithUser } from "../../types/members/guild_member.ts";
import type { SearchGuildMembers } from "../../types/members/search_guild_members.ts";
import { Collection } from "../../util/collection.ts";
import { Bot } from "../../bot.ts";
import { DiscordenoMember } from "../../transformers/member.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/**
* ⚠️ BEGINNER DEVS!! YOU SHOULD ALMOST NEVER NEED THIS AND YOU CAN GET FROM cache.members.filter()
@@ -35,21 +33,10 @@ export async function searchMembers(
}
);
const members = await Promise.all(
result.map(async (member) => {
const discordenoMember = bot.transformers.member(
bot,
member,
guildId,
bot.transformers.snowflake(member.user.id)
);
if (options?.cache) {
await bot.cache.members.set(discordenoMember.id, discordenoMember);
}
return discordenoMember;
return new Collection(
result.map((member) => {
const m = bot.transformers.member(bot, member, guildId, bot.transformers.snowflake(member.user.id));
return [m.id, m];
})
);
return new Collection<bigint, DiscordenoMember>(members.map((member) => [member.id, member]));
}
+5 -16
View File
@@ -1,24 +1,13 @@
import type { Channel } from "../../types/channels/channel.ts";
import type { CreateMessage } from "../../types/messages/create_message.ts";
import type { Bot } from "../../bot.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Send a message to a users DM. Note: this takes 2 API calls. 1 is to fetch the users dm channel. 2 is to send a message to that channel. */
export async function sendDirectMessage(bot: Bot, memberId: bigint, content: string | CreateMessage) {
export async function getDmChannel(bot: Bot, memberId: bigint, content: string | CreateMessage) {
if (memberId === bot.id) throw new Error(bot.constants.Errors.YOU_CAN_NOT_DM_THE_BOT_ITSELF);
let dmChannel = await bot.cache.channels.get(memberId);
if (!dmChannel) {
// If not available in cache create a new one.
const dmChannelData = await bot.rest.runMethod<Channel>(bot.rest, "post", bot.constants.endpoints.USER_DM, {
recipient_id: memberId.toString(),
});
const discordenoChannel = bot.transformers.channel(bot, { channel: dmChannelData });
// Recreate the channel and add it under the users id
await bot.cache.channels.set(memberId, discordenoChannel);
dmChannel = discordenoChannel;
}
// If it does exist try sending a message to this user
return await bot.helpers.sendMessage(dmChannel.id, content);
const dmChannelData = await bot.rest.runMethod<Channel>(bot.rest, "post", bot.constants.endpoints.USER_DM, {
recipient_id: memberId.toString(),
});
return bot.transformers.channel(bot, { channel: dmChannelData });
}
-6
View File
@@ -9,12 +9,6 @@ export async function deleteMessage(
reason?: string,
delayMilliseconds = 0
) {
const message = await bot.cache.messages.get(messageId);
if (message && message.authorId !== bot.id) {
await bot.utils.requireBotChannelPermissions(bot, message.channelId, ["MANAGE_MESSAGES"]);
}
if (delayMilliseconds) await bot.utils.delay(delayMilliseconds);
return await bot.rest.runMethod<undefined>(
-14
View File
@@ -1,24 +1,10 @@
// import { cacheHandlers } from "../../cache.ts";
import type { EditMessage } from "../../types/messages/edit_message.ts";
import type { Message } from "../../types/messages/message.ts";
import type { PermissionStrings } from "../../types/permissions/permission_strings.ts";
import type { Bot } from "../../bot.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
import { DiscordMessageComponentTypes } from "../../types/messages/components/message_component_types.ts";
/** Edit the message. */
export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint, content: string | EditMessage) {
const message = await bot.cache.messages.get(messageId);
if (message) {
if (message.authorId !== bot.id) {
throw new Error("You can only edit a message that was sent by the bot.");
}
const requiredPerms: PermissionStrings[] = ["SEND_MESSAGES"];
await bot.utils.requireBotChannelPermissions(bot, message.channelId, requiredPerms);
}
if (typeof content === "string") content = { content };
if (content.components?.length) {
-4
View File
@@ -3,10 +3,6 @@ import type { Bot } from "../../bot.ts";
/** Fetch a single message from the server. Requires VIEW_CHANNEL and READ_MESSAGE_HISTORY */
export async function getMessage(bot: Bot, channelId: bigint, id: bigint) {
if (await bot.cache.channels.has(channelId)) {
await bot.utils.requireBotChannelPermissions(bot, channelId, ["VIEW_CHANNEL", "READ_MESSAGE_HISTORY"]);
}
const result = await bot.rest.runMethod<Message>(
bot.rest,
"get",
+1 -23
View File
@@ -1,32 +1,10 @@
import type { Bot } from "../../bot.ts";
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
/** Pin a message in a channel. Requires MANAGE_MESSAGES. Max pins allowed in a channel = 50. */
export async function pin(bot: Bot, channelId: bigint, messageId: bigint) {
const channel = await bot.cache.channels.get(channelId);
if (channel) {
if (
![
DiscordChannelTypes.DM,
DiscordChannelTypes.GuildNews,
DiscordChannelTypes.GuildText,
DiscordChannelTypes.GuildPublicThread,
DiscordChannelTypes.GuildPrivateThread,
DiscordChannelTypes.GuildNewsThread,
].includes(channel.type)
) {
throw new Error(bot.constants.Errors.CHANNEL_NOT_TEXT_BASED);
}
await bot.utils.requireBotChannelPermissions(bot, channel, ["MANAGE_MESSAGES"]);
}
export async function pinMessage(bot: Bot, channelId: bigint, messageId: bigint) {
return await bot.rest.runMethod<undefined>(
bot.rest,
"put",
bot.constants.endpoints.CHANNEL_PIN(channelId, messageId)
);
}
// aliases
export { pin as pinMessage };
-34
View File
@@ -1,9 +1,6 @@
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
import { Errors } from "../../types/discordeno/errors.ts";
import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts";
import type { CreateMessage } from "../../types/messages/create_message.ts";
import type { Message } from "../../types/messages/message.ts";
import type { PermissionStrings } from "../../types/permissions/permission_strings.ts";
import type { Bot } from "../../bot.ts";
import { DiscordMessageComponentTypes } from "../../types/messages/components/message_component_types.ts";
@@ -11,37 +8,6 @@ import { DiscordMessageComponentTypes } from "../../types/messages/components/me
export async function sendMessage(bot: Bot, channelId: bigint, content: string | CreateMessage) {
if (typeof content === "string") content = { content };
const channel = await bot.cache.channels.get(channelId);
if (channel) {
if (
![
DiscordChannelTypes.DM,
DiscordChannelTypes.GuildNews,
DiscordChannelTypes.GuildText,
DiscordChannelTypes.GuildPublicThread,
DiscordChannelTypes.GuildPrivateThread,
DiscordChannelTypes.GuildNewsThread,
DiscordChannelTypes.GuildVoice,
].includes(channel.type)
) {
throw new Error(Errors.CHANNEL_NOT_TEXT_BASED);
}
const requiredPerms: Set<PermissionStrings> = new Set(["SEND_MESSAGES", "VIEW_CHANNEL"]);
if (content.tts) requiredPerms.add("SEND_TTS_MESSAGES");
if (content.embeds?.length) {
requiredPerms.add("EMBED_LINKS");
content.embeds?.splice(10);
}
if (content.messageReference?.messageId || content.allowedMentions?.repliedUser) {
requiredPerms.add("READ_MESSAGE_HISTORY");
}
await bot.utils.requireBotChannelPermissions(bot, channelId, [...requiredPerms]);
}
// Use ... for content length due to unicode characters and js .length handling
if (content.content && !bot.utils.validateLength(content.content, { max: 2000 })) {
throw new Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
-6
View File
@@ -1,14 +1,8 @@
import type { Bot } from "../../bot.ts";
// import { cacheHandlers } from "../../cache.ts";
import type { Message } from "../../types/messages/message.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Suppress all the embeds in this message */
export async function suppressEmbeds(bot: Bot, channelId: bigint, messageId: bigint) {
const message = await bot.cache.messages.get(messageId);
await bot.utils.requireBotChannelPermissions(bot, channelId, message ? ["MANAGE_MESSAGES"] : ["SEND_MESSAGES"]);
const result = await bot.rest.runMethod<Message>(
bot.rest,
"patch",
-2
View File
@@ -1,4 +1,3 @@
import { categoryChildren } from "./channels/category_children.ts";
import { channelOverwriteHasPermission } from "./channels/channel_overwrite_has_permission.ts";
import { createChannel } from "./channels/create_channel.ts";
import { deleteChannel } from "./channels/delete_channel.ts";
@@ -164,7 +163,6 @@ export {
ban,
banMember,
batchEditSlashCommandPermissions,
categoryChildren,
channelOverwriteHasPermission,
cloneChannel,
connectToVoiceChannel,
-8
View File
@@ -1,7 +1,6 @@
import type { CreateGuildRole } from "../../types/guilds/create_guild_role.ts";
import type { Role } from "../../types/permissions/role.ts";
import type { Bot } from "../../bot.ts";
import type { SnakeCasedPropertiesDeep } from "../../types/util.ts";
/** Create a new role for the guild. Requires the MANAGE_ROLES permission. */
export async function createRole(bot: Bot, guildId: bigint, options: CreateGuildRole, reason?: string) {
@@ -25,12 +24,5 @@ export async function createRole(bot: Bot, guildId: bigint, options: CreateGuild
guildId,
});
const guild = await bot.cache.guilds.get(guildId);
if (guild) {
guild.roles.set(role.id, role);
await bot.cache.guilds.set(guildId, guild);
}
return role;
}
+2 -12
View File
@@ -7,22 +7,12 @@ import { DiscordenoRole } from "../../transformers/role.ts";
*
* ⚠️ **If you need this, you are probably doing something wrong. This is not intended for use. Your roles will be cached in your guild.**
*/
export async function getRoles(bot: Bot, guildId: bigint, addToCache = true) {
export async function getRoles(bot: Bot, guildId: bigint) {
await bot.utils.requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]);
const result = await bot.rest.runMethod<Role[]>(bot.rest, "get", bot.constants.endpoints.GUILD_ROLES(guildId));
const roleStructures = result.map((role) => bot.transformers.role(bot, { role, guildId }));
const roles = new Collection(roleStructures.map((role: DiscordenoRole) => [role.id, role]));
if (addToCache) {
const guild = await bot.cache.guilds.get(guildId);
if (guild) {
guild.roles = roles;
await bot.cache.guilds.set(guild.id, guild);
}
}
return roleStructures;
return new Collection(roleStructures.map((role: DiscordenoRole) => [role.id, role]));
}
@@ -7,10 +7,6 @@ import type { Bot } from "../../bot.ts";
* NOTE: This endpoint can be used only by bots in less than 10 guilds.
*/
export async function createGuildFromTemplate(bot: Bot, templateCode: string, data: CreateGuildFromTemplate) {
if ((await bot.cache.guilds.size()) >= 10) {
throw new Error("This function can only be used by bots in less than 10 guilds.");
}
if (data.icon) {
data.icon = await bot.utils.urlToBase64(data.icon);
}
-20
View File
@@ -12,12 +12,6 @@ export function transformGuild(
payload: { guild: SnakeCasedPropertiesDeep<Guild> } & { shardId: number }
): DiscordenoGuild {
const guildId = bot.transformers.snowflake(payload.guild.id);
const channels = payload.guild.channels || [];
channels.forEach(async (channel) => {
const chnl = bot.transformers.channel(bot, { channel, guildId });
await bot.cache.channels.set(chnl.id, chnl);
});
return {
afkTimeout: payload.guild.afk_timeout,
@@ -78,25 +72,11 @@ export function transformGuild(
icon: payload.guild.icon ? iconHashToBigInt(payload.guild.icon) : undefined,
banner: payload.guild.banner ? iconHashToBigInt(payload.guild.banner) : undefined,
splash: payload.guild.splash ? iconHashToBigInt(payload.guild.splash) : undefined,
// TRANSFORMED STUFF BELOW
// TODO: Handle channels/threads in a better way?
// channels: (payload.guild.channels || []).map((channel) =>
// bot.transformers.channel(bot, { channel, guildId: bot.transformers.snowflake(payload.guild.id) })
// ),
// threads: (payload.guild.threads || []).map((channel) => channelToThread(channel)),
roles: new Collection(
(payload.guild.roles || [])
.map((role) => bot.transformers.role(bot, { role, guildId: bot.transformers.snowflake(payload.guild.id) }))
.map((role) => [role.id, role])
),
// presences: new Collection(
// (payload.guild.presences || []).map((p) => [
// bot.transformers.snowflake(p.user!.id),
// bot.transformers.presence(bot, p),
// ])
// ),
emojis: new Collection((payload.guild.emojis || []).map((emoji) => [bot.transformers.snowflake(emoji.id!), emoji])),
voiceStates: new Collection(
(payload.guild.voice_states || [])
-99
View File
@@ -1,99 +0,0 @@
import { Bot } from "../bot.ts";
import type { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts";
import type { Guild } from "../types/guilds/guild.ts";
import { SnakeCasedPropertiesDeep } from "../types/util.ts";
const processing = new Set<bigint>();
export async function dispatchRequirements(bot: Bot, data: DiscordGatewayPayload, shardId: number) {
if (!bot.isReady) return;
// DELETE MEANS WE DONT NEED TO FETCH. CREATE SHOULD HAVE DATA TO CACHE
if (data.t && ["GUILD_CREATE", "GUILD_DELETE"].includes(data.t)) return;
const id = bot.utils.snowflakeToBigint(
(data.t && ["GUILD_UPDATE"].includes(data.t)
? // deno-lint-ignore no-explicit-any
(data.d as any)?.id
: // deno-lint-ignore no-explicit-any
(data.d as any)?.guild_id) ?? ""
);
if (!id || bot.activeGuildIds.has(id)) return;
// If this guild is in cache, it has not been swept and we can cancel
if (await bot.cache.guilds.has(id)) {
bot.activeGuildIds.add(id);
return;
}
if (processing.has(id)) {
bot.events.debug(`[DISPATCH] New Guild ID already being processed: ${id} in ${data.t} event`);
let runs = 0;
do {
await bot.utils.delay(500);
runs++;
} while (processing.has(id) && runs < 40);
if (!processing.has(id)) return;
return bot.events.debug(
`[DISPATCH] Already processed guild was not successfully fetched: ${id} in ${data.t} event`
);
}
processing.add(id);
// New guild id has appeared, fetch all relevant data
bot.events.debug(`[DISPATCH] New Guild ID has appeared: ${id} in ${data.t} event`);
const rawGuild = (await bot.helpers
.getGuild(id, {
counts: true,
addToCache: false,
})
.catch(console.log)) as SnakeCasedPropertiesDeep<Guild> | undefined;
if (!rawGuild) {
processing.delete(id);
return bot.events.debug(`[DISPATCH] Guild ID ${id} failed to fetch.`);
}
bot.events.debug(`[DISPATCH] Guild ID ${id} has been found. ${rawGuild.name}`);
const [channels, botMember] = await Promise.all([
bot.helpers.getChannels(id, false),
bot.helpers.getMember(id, bot.id, { force: true }),
]).catch((error) => {
bot.events.debug(error);
return [];
});
if (!botMember || !channels) {
processing.delete(id);
return bot.events.debug(
`[DISPATCH] Guild ID ${id} Name: ${rawGuild.name} failed. Unable to get botMember or channels`
);
}
const guild = bot.transformers.guild(bot, {
guild: {
...rawGuild,
member_count: rawGuild.approximate_member_count,
},
shardId,
});
// Add to cache
await bot.cache.guilds.set(id, guild);
bot.cache.dispatchedGuildIds.delete(id);
channels.forEach((channel) => {
bot.cache.dispatchedChannelIds.delete(channel.id);
bot.cache.channels.set(channel.id, channel);
});
processing.delete(id);
bot.events.debug(`[DISPATCH] Guild ID ${id} Name: ${guild.name} completely loaded.`);
}
+1 -1
View File
@@ -33,7 +33,7 @@ export async function categoryChildrenTest(bot: Bot, guildId: bigint, t: Deno.Te
throw new Error("The channels seemed to be created but it was not cached.");
}
const ids = await bot.helpers.categoryChildren(category.id);
const ids = bot.cache.channels.filter((c) => c.parentId === category.id);
if (ids.size !== channels.length || !channels.every((c) => ids.has(c.id))) {
console.log("cccc 1", ids.size, channels.length);
console.log(
+2 -2
View File
@@ -13,9 +13,9 @@ export async function createEmojiTest(bot: Bot, guildId: bigint, t: Deno.TestCon
assertExists(emoji);
// Delay the execution to allow event to be processed
await delayUntil(10000, async () => (await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id));
await delayUntil(10000, async () => bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id));
if (!(await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id)) {
if (!bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id)) {
throw new Error("The emoji seemed to be created but it was not cached.");
}
}
+4 -4
View File
@@ -13,17 +13,17 @@ export async function ifItFailsBlameWolf(bot: Bot, guildId: bigint, reason?: str
assertExists(emoji);
// Delay the execution to allow event to be processed
await delayUntil(10000, async () => (await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id));
await delayUntil(10000, async () => bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id));
if (!(await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id)) {
if (!bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id)) {
throw new Error("The emoji seemed to be created but it was not cached.");
}
await bot.helpers.deleteEmoji(guildId, emoji.id, reason);
await delayUntil(10000, async () => !(await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id));
await delayUntil(10000, async () => !bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id));
if ((await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id)) {
if (bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id)) {
throw new Error("The emoji seemed to be deleted but it's still cached.");
}
}
+4 -4
View File
@@ -13,9 +13,9 @@ export async function editEmojiTest(bot: Bot, guildId: bigint, t: Deno.TestConte
assertExists(emoji);
// Delay the execution to allow event to be processed
await delayUntil(10000, async () => (await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id));
await delayUntil(10000, async () => bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id));
if (!(await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id)) {
if (!bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id)) {
throw new Error("The emoji seemed to be created but it was not cached.");
}
@@ -25,10 +25,10 @@ export async function editEmojiTest(bot: Bot, guildId: bigint, t: Deno.TestConte
await delayUntil(
10000,
async () => (await bot.cache.guilds.get(guildId))?.emojis?.get(emoji.id)?.name === "blamewolf_infinite"
async () => bot.cache.guilds.get(guildId)?.emojis?.get(emoji.id)?.name === "blamewolf_infinite"
);
if ((await bot.cache.guilds.get(guildId))?.emojis?.get(emoji.id)?.name !== "blamewolf_infinite") {
if (bot.cache.guilds.get(guildId)?.emojis?.get(emoji.id)?.name !== "blamewolf_infinite") {
throw new Error("The emoji seemed to be edited but the cache was not updated.");
}
}
+5 -5
View File
@@ -13,13 +13,13 @@ export async function getEmojiTest(bot: Bot, guildId: bigint, t: Deno.TestContex
assertExists(emoji);
// Delay the execution to allow event to be processed
await delayUntil(10000, async () => (await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id));
await delayUntil(10000, async () => bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id));
if (!(await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id)) {
if (!bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id)) {
throw new Error("The emoji seemed to be created but it was not cached.");
}
(await bot.cache.guilds.get(guildId))?.emojis?.delete(emoji.id);
bot.cache.guilds.get(guildId)?.emojis?.delete(emoji.id);
const getEmoji = await bot.helpers.getEmoji(guildId, emoji.id, true);
@@ -27,9 +27,9 @@ export async function getEmojiTest(bot: Bot, guildId: bigint, t: Deno.TestContex
assertExists(getEmoji);
// Delay the execution to allow event to be processed
await delayUntil(10000, async () => (await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id));
await delayUntil(10000, async () => bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id));
if (!(await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id)) {
if (!bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id)) {
throw new Error("The emoji didn't got added to cache after using the getEmoji function.");
}
}
+2 -2
View File
@@ -13,9 +13,9 @@ export async function getEmojisTest(bot: Bot, guildId: bigint, t: Deno.TestConte
assertExists(emoji);
// Delay the execution to allow event to be processed
await delayUntil(10000, async () => (await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id));
await delayUntil(10000, async () => bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id));
if (!(await bot.cache.guilds.get(guildId))?.emojis?.has(emoji.id)) {
if (!bot.cache.guilds.get(guildId)?.emojis?.has(emoji.id)) {
throw new Error("The emoji seemed to be created but it was not cached.");
}
+1 -1
View File
@@ -13,7 +13,7 @@ export async function editGuildTests(bot: Bot, guildId: bigint, t: Deno.TestCont
assertExists(guild);
// Delay the execution to allow event to be processed
await delayUntil(10000, async () => (await bot.cache.guilds.get(guild.id))?.name === "Discordeno Test 1.0");
await delayUntil(10000, async () => bot.cache.guilds.get(guild.id)?.name === "Discordeno Test 1.0");
if (!bot.cache.guilds.has(guild.id)) {
throw new Error(`The guild seemed to be edited but the cache didn't got updated.`);
+2 -2
View File
@@ -18,9 +18,9 @@ export async function editMessageTest(bot: Bot, channelId: bigint, t: Deno.TestC
await bot.helpers.editMessage(channelId, message.id, "Goodbye World!");
// Wait to give it time for MESSAGE_UPDATE event
await delayUntil(10000, async () => (await bot.cache.messages.get(message.id))?.content === "Goodbye World!");
await delayUntil(10000, async () => bot.cache.messages.get(message.id)?.content === "Goodbye World!");
// Make sure it was edited
if ((await bot.cache.messages.get(message.id))?.content !== "Goodbye World!") {
if (bot.cache.messages.get(message.id)?.content !== "Goodbye World!") {
throw new Error("The message should have been edited but it was not.");
}
}