mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-03 09:20:08 +00:00
Merge branch 'main' of https://github.com/discordeno/discordeno into main
This commit is contained in:
@@ -22,11 +22,11 @@ export async function createChannel(bot: Bot, guildId: bigint, options?: CreateG
|
||||
position: options.position,
|
||||
parent_id: options.parentId?.toString(),
|
||||
nsfw: options.nsfw,
|
||||
permission_overwrites: options?.permissionOverwrites?.map((perm) => ({
|
||||
id: perm.id.toString(),
|
||||
type: perm.type,
|
||||
allow: perm.allow ? bot.utils.calculateBits(perm.allow) : "0",
|
||||
deny: perm.deny ? bot.utils.calculateBits(perm.deny) : "0",
|
||||
permission_overwrites: options?.permissionOverwrites?.map((overwrite) => ({
|
||||
id: overwrite.id.toString(),
|
||||
type: overwrite.type,
|
||||
allow: overwrite.allow ? bot.utils.calculateBits(overwrite.allow) : null,
|
||||
deny: overwrite.deny ? bot.utils.calculateBits(overwrite.deny) : null,
|
||||
})),
|
||||
type: options?.type || ChannelTypes.GuildText,
|
||||
reason,
|
||||
|
||||
@@ -46,13 +46,12 @@ export async function editChannel(bot: Bot, channelId: bigint, options: ModifyCh
|
||||
locked: options.locked,
|
||||
invitable: options.invitable,
|
||||
permission_overwrites: options.permissionOverwrites
|
||||
? options.permissionOverwrites?.map((overwrite) => {
|
||||
return {
|
||||
...overwrite,
|
||||
allow: overwrite.allow ? bot.utils.calculateBits(overwrite.allow) : "0",
|
||||
deny: overwrite.deny ? bot.utils.calculateBits(overwrite.deny) : "0",
|
||||
};
|
||||
})
|
||||
? options.permissionOverwrites?.map((overwrite) => ({
|
||||
id: overwrite.id.toString(),
|
||||
type: overwrite.type,
|
||||
allow: overwrite.allow ? bot.utils.calculateBits(overwrite.allow) : null,
|
||||
deny: overwrite.deny ? bot.utils.calculateBits(overwrite.deny) : null,
|
||||
}))
|
||||
: undefined,
|
||||
reason,
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function deleteChannel(bot: BotWithCache) {
|
||||
const deleteChannelOld = bot.helpers.deleteChannel;
|
||||
|
||||
bot.helpers.deleteChannel = function (channelId, reason) {
|
||||
bot.helpers.deleteChannel = async function (channelId, reason) {
|
||||
const channel = bot.channels.get(channelId);
|
||||
|
||||
if (channel?.guildId) {
|
||||
@@ -32,6 +32,6 @@ export default function deleteChannel(bot: BotWithCache) {
|
||||
);
|
||||
}
|
||||
|
||||
return deleteChannelOld(channelId, reason);
|
||||
return await deleteChannelOld(channelId, reason);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function deleteChannelOverwrite(bot: BotWithCache) {
|
||||
const deleteChannelOverwriteOld = bot.helpers.deleteChannelOverwrite;
|
||||
|
||||
bot.helpers.deleteChannelOverwrite = function (channelId, overwriteId) {
|
||||
bot.helpers.deleteChannelOverwrite = async function (channelId, overwriteId) {
|
||||
const channel = bot.channels.get(channelId);
|
||||
|
||||
if (channel?.guildId) {
|
||||
requireBotChannelPermissions(bot, channelId, ["MANAGE_ROLES"]);
|
||||
}
|
||||
|
||||
return deleteChannelOverwriteOld(channelId, overwriteId);
|
||||
return await deleteChannelOverwriteOld(channelId, overwriteId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function editChannel(bot: BotWithCache) {
|
||||
const editChannelOld = bot.helpers.editChannel;
|
||||
|
||||
bot.helpers.editChannel = function (channelId, options, reason) {
|
||||
bot.helpers.editChannel = async function (channelId, options, reason) {
|
||||
const channel = bot.channels.get(channelId);
|
||||
|
||||
if (channel?.guildId) {
|
||||
@@ -118,6 +118,6 @@ export default function editChannel(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
return editChannelOld(channelId, options, reason);
|
||||
return await editChannelOld(channelId, options, reason);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function editChannelOverwrite(bot: BotWithCache) {
|
||||
const editChannelOverwriteOld = bot.helpers.editChannelOverwrite;
|
||||
|
||||
bot.helpers.editChannelOverwrite = function (channelId, overwriteId, options) {
|
||||
bot.helpers.editChannelOverwrite = async function (channelId, overwriteId, options) {
|
||||
const channel = bot.channels.get(channelId);
|
||||
if (channel?.guildId) {
|
||||
requireBotChannelPermissions(bot, channelId, ["MANAGE_ROLES"]);
|
||||
}
|
||||
|
||||
return editChannelOverwriteOld(channelId, overwriteId, options);
|
||||
return await editChannelOverwriteOld(channelId, overwriteId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function followChannel(bot: BotWithCache) {
|
||||
const followChannelOld = bot.helpers.followChannel;
|
||||
|
||||
bot.helpers.followChannel = function (sourceChannelId, targetChannelId) {
|
||||
bot.helpers.followChannel = async function (sourceChannelId, targetChannelId) {
|
||||
const channel = bot.channels.get(targetChannelId);
|
||||
if (channel?.guildId) {
|
||||
requireBotChannelPermissions(bot, channel, ["MANAGE_WEBHOOKS"]);
|
||||
}
|
||||
|
||||
return followChannelOld(sourceChannelId, targetChannelId);
|
||||
return await followChannelOld(sourceChannelId, targetChannelId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function getChannelWebhooks(bot: BotWithCache) {
|
||||
const getChannelWebhooksOld = bot.helpers.getChannelWebhooks;
|
||||
|
||||
bot.helpers.getChannelWebhooks = function (channelId) {
|
||||
bot.helpers.getChannelWebhooks = async function (channelId) {
|
||||
const channel = bot.channels.get(channelId);
|
||||
if (channel?.guildId) {
|
||||
requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS"]);
|
||||
}
|
||||
|
||||
return getChannelWebhooksOld(channelId);
|
||||
return await getChannelWebhooksOld(channelId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export function createStageInstance(bot: BotWithCache) {
|
||||
const createStageInstanceOld = bot.helpers.createStageInstance;
|
||||
|
||||
bot.helpers.createStageInstance = function (channelId, topic, privacyLevel) {
|
||||
bot.helpers.createStageInstance = async function (channelId, topic, privacyLevel) {
|
||||
if (!bot.utils.validateLength(topic, { max: 120, min: 1 })) {
|
||||
throw new Error(
|
||||
"The topic length for creating a stage instance must be between 1-120.",
|
||||
@@ -17,35 +17,35 @@ export function createStageInstance(bot: BotWithCache) {
|
||||
"MOVE_MEMBERS",
|
||||
]);
|
||||
|
||||
return createStageInstanceOld(channelId, topic, privacyLevel);
|
||||
return await createStageInstanceOld(channelId, topic, privacyLevel);
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteStageInstance(bot: BotWithCache) {
|
||||
const deleteStageInstanceOld = bot.helpers.deleteStageInstance;
|
||||
|
||||
bot.helpers.deleteStageInstance = function (channelId) {
|
||||
bot.helpers.deleteStageInstance = async function (channelId) {
|
||||
requireBotChannelPermissions(bot, channelId, [
|
||||
"MANAGE_CHANNELS",
|
||||
"MUTE_MEMBERS",
|
||||
"MOVE_MEMBERS",
|
||||
]);
|
||||
|
||||
return deleteStageInstanceOld(channelId);
|
||||
return await deleteStageInstanceOld(channelId);
|
||||
};
|
||||
}
|
||||
|
||||
export function updateStageInstance(bot: BotWithCache) {
|
||||
const updateStageInstanceOld = bot.helpers.updateStageInstance;
|
||||
|
||||
bot.helpers.updateStageInstance = function (channelId, data) {
|
||||
bot.helpers.updateStageInstance = async function (channelId, data) {
|
||||
requireBotChannelPermissions(bot, channelId, [
|
||||
"MANAGE_CHANNELS",
|
||||
"MUTE_MEMBERS",
|
||||
"MOVE_MEMBERS",
|
||||
]);
|
||||
|
||||
return updateStageInstanceOld(channelId, data);
|
||||
return await updateStageInstanceOld(channelId, data);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function swapChannels(bot: BotWithCache) {
|
||||
const swapChannelsOld = bot.helpers.swapChannels;
|
||||
|
||||
bot.helpers.swapChannels = function (guildId, channelPositions) {
|
||||
bot.helpers.swapChannels = async function (guildId, channelPositions) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_CHANNELS"]);
|
||||
|
||||
return swapChannelsOld(guildId, channelPositions);
|
||||
return await swapChannelsOld(guildId, channelPositions);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@ export default function addToThread(bot: BotWithCache) {
|
||||
await requireBotChannelPermissions(bot, channel, ["SEND_MESSAGES"]);
|
||||
}
|
||||
|
||||
return addToThreadOld(threadId, userId);
|
||||
return await addToThreadOld(threadId, userId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,6 +15,6 @@ export default function getArchivedThreads(bot: BotWithCache) {
|
||||
);
|
||||
}
|
||||
|
||||
return getArchivedThreadsOld(channelId, options);
|
||||
return await getArchivedThreadsOld(channelId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { BotWithCache, GatewayIntents } from "../../../deps.ts";
|
||||
export default function getThreadMembers(bot: BotWithCache) {
|
||||
const getThreadMembersOld = bot.helpers.getThreadMembers;
|
||||
|
||||
bot.helpers.getThreadMembers = function (threadId) {
|
||||
bot.helpers.getThreadMembers = async function (threadId) {
|
||||
const hasIntent = bot.intents & GatewayIntents.GuildMembers;
|
||||
if (!hasIntent) {
|
||||
throw new Error(
|
||||
@@ -11,6 +11,6 @@ export default function getThreadMembers(bot: BotWithCache) {
|
||||
);
|
||||
}
|
||||
|
||||
return getThreadMembersOld(threadId);
|
||||
return await getThreadMembersOld(threadId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ import { BotWithCache } from "../../../deps.ts";
|
||||
export default function joinThread(bot: BotWithCache) {
|
||||
const joinThreadOld = bot.helpers.joinThread;
|
||||
|
||||
bot.helpers.joinThread = function (threadId) {
|
||||
bot.helpers.joinThread = async function (threadId) {
|
||||
const channel = bot.channels.get(threadId);
|
||||
|
||||
if (channel && !channel.archived) {
|
||||
throw new Error("You can not join an archived channel.");
|
||||
}
|
||||
|
||||
return joinThreadOld(threadId);
|
||||
return await joinThreadOld(threadId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ import { BotWithCache } from "../../../deps.ts";
|
||||
export default function leaveThread(bot: BotWithCache) {
|
||||
const leaveThreadOld = bot.helpers.leaveThread;
|
||||
|
||||
bot.helpers.leaveThread = function (threadId) {
|
||||
bot.helpers.leaveThread = async function (threadId) {
|
||||
const channel = bot.channels.get(threadId);
|
||||
|
||||
if (channel && !channel.archived) {
|
||||
throw new Error("You can not leave an archived channel.");
|
||||
}
|
||||
|
||||
return leaveThreadOld(threadId);
|
||||
return await leaveThreadOld(threadId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,6 +28,6 @@ export default function removeThreadMember(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
return removeThreadMemberOld(threadId, userId);
|
||||
return await removeThreadMemberOld(threadId, userId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,6 +40,6 @@ export default function connectToVoiceChannel(bot: BotWithCache) {
|
||||
|
||||
await requireBotChannelPermissions(bot, channel, permsNeeded);
|
||||
|
||||
return connectToVoiceChannelOld(guildId, channelId, options);
|
||||
return await connectToVoiceChannelOld(guildId, channelId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,40 +4,40 @@ import { requireBotGuildPermissions } from "./permissions.ts";
|
||||
export function addDiscoverySubcategory(bot: BotWithCache) {
|
||||
const addDiscoverySubcategoryOld = bot.helpers.addDiscoverySubcategory;
|
||||
|
||||
bot.helpers.addDiscoverySubcategory = function (guildId, categoryId) {
|
||||
bot.helpers.addDiscoverySubcategory = async function (guildId, categoryId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return addDiscoverySubcategoryOld(guildId, categoryId);
|
||||
return await addDiscoverySubcategoryOld(guildId, categoryId);
|
||||
};
|
||||
}
|
||||
|
||||
export function removeDiscoverySubcategory(bot: BotWithCache) {
|
||||
const removeDiscoverySubcategoryOld = bot.helpers.removeDiscoverySubcategory;
|
||||
|
||||
bot.helpers.removeDiscoverySubcategory = function (guildId, categoryId) {
|
||||
bot.helpers.removeDiscoverySubcategory = async function (guildId, categoryId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return removeDiscoverySubcategoryOld(guildId, categoryId);
|
||||
return await removeDiscoverySubcategoryOld(guildId, categoryId);
|
||||
};
|
||||
}
|
||||
|
||||
export function getDiscovery(bot: BotWithCache) {
|
||||
const getDiscoveryOld = bot.helpers.getDiscovery;
|
||||
|
||||
bot.helpers.getDiscovery = function (guildId) {
|
||||
bot.helpers.getDiscovery = async function (guildId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return getDiscoveryOld(guildId);
|
||||
return await getDiscoveryOld(guildId);
|
||||
};
|
||||
}
|
||||
|
||||
export function editDiscovery(bot: BotWithCache) {
|
||||
const editDiscoveryOld = bot.helpers.editDiscovery;
|
||||
|
||||
bot.helpers.editDiscovery = function (guildId, data) {
|
||||
bot.helpers.editDiscovery = async function (guildId, data) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return editDiscoveryOld(guildId, data);
|
||||
return await editDiscoveryOld(guildId, data);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,6 @@ export default function editMember(bot: BotWithCache) {
|
||||
...requiredPerms,
|
||||
]);
|
||||
|
||||
return editMemberOld(guildId, memberId, options);
|
||||
return await editMemberOld(guildId, memberId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,30 +4,30 @@ import { requireBotGuildPermissions } from "./permissions.ts";
|
||||
export function createEmoji(bot: BotWithCache) {
|
||||
const createEmojiOld = bot.helpers.createEmoji;
|
||||
|
||||
bot.helpers.createEmoji = function (guildId, id) {
|
||||
bot.helpers.createEmoji = async function (guildId, id) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]);
|
||||
|
||||
return createEmojiOld(guildId, id);
|
||||
return await createEmojiOld(guildId, id);
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteEmoji(bot: BotWithCache) {
|
||||
const deleteEmojiOld = bot.helpers.deleteEmoji;
|
||||
|
||||
bot.helpers.deleteEmoji = function (guildId, id) {
|
||||
bot.helpers.deleteEmoji = async function (guildId, id) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]);
|
||||
|
||||
return deleteEmojiOld(guildId, id);
|
||||
return await deleteEmojiOld(guildId, id);
|
||||
};
|
||||
}
|
||||
|
||||
export function editEmoji(bot: BotWithCache) {
|
||||
const editEmojiOld = bot.helpers.editEmoji;
|
||||
|
||||
bot.helpers.editEmoji = function (guildId, id, options) {
|
||||
bot.helpers.editEmoji = async function (guildId, id, options) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_EMOJIS"]);
|
||||
|
||||
return editEmojiOld(guildId, id, options);
|
||||
return await editEmojiOld(guildId, id, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { BotWithCache } from "../../deps.ts";
|
||||
export default function createGuild(bot: BotWithCache) {
|
||||
const createGuildOld = bot.helpers.createGuild;
|
||||
|
||||
bot.helpers.createGuild = function (options) {
|
||||
bot.helpers.createGuild = async function (options) {
|
||||
if (bot.guilds.size > 10) {
|
||||
throw new Error(
|
||||
"A bot can not create a guild if it is already in 10 guilds.",
|
||||
@@ -17,6 +17,6 @@ export default function createGuild(bot: BotWithCache) {
|
||||
throw new Error("The guild name must be between 2 and 100 characters.");
|
||||
}
|
||||
|
||||
return createGuildOld(options);
|
||||
return await createGuildOld(options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ import { BotWithCache } from "../../deps.ts";
|
||||
export default function deleteGuild(bot: BotWithCache) {
|
||||
const deleteGuildOld = bot.helpers.deleteGuild;
|
||||
|
||||
bot.helpers.deleteGuild = function (guildId) {
|
||||
bot.helpers.deleteGuild = async function (guildId) {
|
||||
const guild = bot.guilds.get(guildId);
|
||||
if (guild && guild.ownerId !== bot.id) {
|
||||
throw new Error("A bot can only delete a guild it owns.");
|
||||
}
|
||||
|
||||
return deleteGuildOld(guildId);
|
||||
return await deleteGuildOld(guildId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function editGuild(bot: BotWithCache) {
|
||||
const editGuildOld = bot.helpers.editGuild;
|
||||
|
||||
bot.helpers.editGuild = function (guildId, options, shardId) {
|
||||
bot.helpers.editGuild = async function (guildId, options, shardId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return editGuildOld(guildId, options, shardId);
|
||||
return await editGuildOld(guildId, options, shardId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions, requireBotGuildPermissions } from "../per
|
||||
export function createScheduledEvent(bot: BotWithCache) {
|
||||
const createScheduledEventOld = bot.helpers.createScheduledEvent;
|
||||
|
||||
bot.helpers.createScheduledEvent = function (guildId, options) {
|
||||
bot.helpers.createScheduledEvent = async function (guildId, options) {
|
||||
if (options.entityType === ScheduledEventEntityType.StageInstance) {
|
||||
if (!options.channelId) {
|
||||
throw new Error(
|
||||
@@ -64,14 +64,14 @@ export function createScheduledEvent(bot: BotWithCache) {
|
||||
"MANAGE_EVENTS",
|
||||
]);
|
||||
|
||||
return createScheduledEventOld(guildId, options);
|
||||
return await createScheduledEventOld(guildId, options);
|
||||
};
|
||||
}
|
||||
|
||||
export function editScheduledEvent(bot: BotWithCache) {
|
||||
const editScheduledEventOld = bot.helpers.editScheduledEvent;
|
||||
|
||||
bot.helpers.editScheduledEvent = function (guildId, eventId, options) {
|
||||
bot.helpers.editScheduledEvent = async function (guildId, eventId, options) {
|
||||
if (options.entityType === ScheduledEventEntityType.StageInstance) {
|
||||
if (!options.channelId) {
|
||||
throw new Error(
|
||||
@@ -131,7 +131,7 @@ export function editScheduledEvent(bot: BotWithCache) {
|
||||
"MANAGE_EVENTS",
|
||||
]);
|
||||
|
||||
return editScheduledEventOld(guildId, eventId, options);
|
||||
return await editScheduledEventOld(guildId, eventId, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function getAuditLogs(bot: BotWithCache) {
|
||||
const getAuditLogsOld = bot.helpers.getAuditLogs;
|
||||
|
||||
bot.helpers.getAuditLogs = function (guildId, options) {
|
||||
bot.helpers.getAuditLogs = async function (guildId, options) {
|
||||
requireBotGuildPermissions(bot, guildId, ["VIEW_AUDIT_LOG"]);
|
||||
|
||||
return getAuditLogsOld(guildId, options);
|
||||
return await getAuditLogsOld(guildId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function getBan(bot: BotWithCache) {
|
||||
const getBanOld = bot.helpers.getBan;
|
||||
|
||||
bot.helpers.getBan = function (guildId, memberId) {
|
||||
bot.helpers.getBan = async function (guildId, memberId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]);
|
||||
|
||||
return getBanOld(guildId, memberId);
|
||||
return await getBanOld(guildId, memberId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function getBans(bot: BotWithCache) {
|
||||
const getBansOld = bot.helpers.getBans;
|
||||
|
||||
bot.helpers.getBans = function (guildId) {
|
||||
bot.helpers.getBans = async function (guildId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]);
|
||||
|
||||
return getBansOld(guildId);
|
||||
return await getBansOld(guildId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function getPruneCount(bot: BotWithCache) {
|
||||
const getPruneCountOld = bot.helpers.getPruneCount;
|
||||
|
||||
bot.helpers.getPruneCount = function (guildId, options) {
|
||||
bot.helpers.getPruneCount = async function (guildId, options) {
|
||||
requireBotGuildPermissions(bot, guildId, ["KICK_MEMBERS"]);
|
||||
|
||||
return getPruneCountOld(guildId, options);
|
||||
return await getPruneCountOld(guildId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function getVanityUrl(bot: BotWithCache) {
|
||||
const getVanityUrlOld = bot.helpers.getVanityUrl;
|
||||
|
||||
bot.helpers.getVanityUrl = function (guildId) {
|
||||
bot.helpers.getVanityUrl = async function (guildId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return getVanityUrlOld(guildId);
|
||||
return await getVanityUrlOld(guildId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,23 +4,23 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export function getWelcomeScreen(bot: BotWithCache) {
|
||||
const getWelcomeScreenOld = bot.helpers.getWelcomeScreen;
|
||||
|
||||
bot.helpers.getWelcomeScreen = function (guildId) {
|
||||
bot.helpers.getWelcomeScreen = async function (guildId) {
|
||||
const guild = bot.guilds.get(guildId);
|
||||
if (!guild?.welcomeScreen) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
}
|
||||
|
||||
return getWelcomeScreenOld(guildId);
|
||||
return await getWelcomeScreenOld(guildId);
|
||||
};
|
||||
}
|
||||
|
||||
export function editWelcomeScreen(bot: BotWithCache) {
|
||||
const editWelcomeScreenOld = bot.helpers.editWelcomeScreen;
|
||||
|
||||
bot.helpers.editWelcomeScreen = function (guildId, options) {
|
||||
bot.helpers.editWelcomeScreen = async function (guildId, options) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return editWelcomeScreenOld(guildId, options);
|
||||
return await editWelcomeScreenOld(guildId, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export function editWidget(bot: BotWithCache) {
|
||||
const editWidgetOld = bot.helpers.editWidget;
|
||||
|
||||
bot.helpers.editWidget = function (guildId, enabled, channelId) {
|
||||
bot.helpers.editWidget = async function (guildId, enabled, channelId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return editWidgetOld(guildId, enabled, channelId);
|
||||
return await editWidgetOld(guildId, enabled, channelId);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,20 +4,20 @@ import { requireBotGuildPermissions } from "./permissions.ts";
|
||||
export function deleteIntegration(bot: BotWithCache) {
|
||||
const deleteIntegrationOld = bot.helpers.deleteIntegration;
|
||||
|
||||
bot.helpers.deleteIntegration = function (guildId, id) {
|
||||
bot.helpers.deleteIntegration = async function (guildId, id) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return deleteIntegrationOld(guildId, id);
|
||||
return await deleteIntegrationOld(guildId, id);
|
||||
};
|
||||
}
|
||||
|
||||
export function getIntegrations(bot: BotWithCache) {
|
||||
const getIntegrationsOld = bot.helpers.getIntegrations;
|
||||
|
||||
bot.helpers.getIntegrations = function (guildId) {
|
||||
bot.helpers.getIntegrations = async function (guildId) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return getIntegrationsOld(guildId);
|
||||
return await getIntegrationsOld(guildId);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ export function validateApplicationCommandOptions(
|
||||
export function createApplicationCommand(bot: BotWithCache) {
|
||||
const createApplicationCommandOld = bot.helpers.createApplicationCommand;
|
||||
|
||||
bot.helpers.createApplicationCommand = function (options, guildId) {
|
||||
bot.helpers.createApplicationCommand = async function (options, guildId) {
|
||||
const isChatInput = !options.type ||
|
||||
options.type === ApplicationCommandTypes.ChatInput;
|
||||
|
||||
@@ -135,14 +135,14 @@ export function createApplicationCommand(bot: BotWithCache) {
|
||||
options.options = validateApplicationCommandOptions(bot, options.options);
|
||||
}
|
||||
|
||||
return createApplicationCommandOld(options, guildId);
|
||||
return await createApplicationCommandOld(options, guildId);
|
||||
};
|
||||
}
|
||||
|
||||
export function editInteractionResponse(bot: BotWithCache) {
|
||||
const editInteractionResponseOld = bot.helpers.editInteractionResponse;
|
||||
|
||||
bot.helpers.editInteractionResponse = function (token, options) {
|
||||
bot.helpers.editInteractionResponse = async function (token, options) {
|
||||
if (options.content && options.content.length > 2000) {
|
||||
throw Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
|
||||
}
|
||||
@@ -191,7 +191,7 @@ export function editInteractionResponse(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
return editInteractionResponseOld(token, options);
|
||||
return await editInteractionResponseOld(token, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { AllowedMentionsTypes, BotWithCache } from "../../deps.ts";
|
||||
export default function editFollowupMessage(bot: BotWithCache) {
|
||||
const editFollowupMessageOld = bot.helpers.editFollowupMessage;
|
||||
|
||||
bot.helpers.editFollowupMessage = function (
|
||||
bot.helpers.editFollowupMessage = async function (
|
||||
token,
|
||||
messageId,
|
||||
options,
|
||||
@@ -56,6 +56,6 @@ export default function editFollowupMessage(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
return editFollowupMessageOld(token, messageId, options);
|
||||
return await editFollowupMessageOld(token, messageId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions } from "./permissions.ts";
|
||||
export function createInvite(bot: BotWithCache) {
|
||||
const createInviteOld = bot.helpers.createInvite;
|
||||
|
||||
bot.helpers.createInvite = function (channelId, options = {}) {
|
||||
bot.helpers.createInvite = async function (channelId, options = {}) {
|
||||
if (options.maxAge && (options.maxAge < 0 || options.maxAge > 604800)) {
|
||||
throw new Error(
|
||||
"The max age for an invite must be between 0 and 604800.",
|
||||
@@ -16,27 +16,27 @@ export function createInvite(bot: BotWithCache) {
|
||||
|
||||
requireBotChannelPermissions(bot, channelId, ["CREATE_INSTANT_INVITE"]);
|
||||
|
||||
return createInviteOld(channelId, options);
|
||||
return await createInviteOld(channelId, options);
|
||||
};
|
||||
}
|
||||
|
||||
export function getChannelInvites(bot: BotWithCache) {
|
||||
const getChannelInvitesOld = bot.helpers.getChannelInvites;
|
||||
|
||||
bot.helpers.getChannelInvites = function (channelId) {
|
||||
bot.helpers.getChannelInvites = async function (channelId) {
|
||||
requireBotChannelPermissions(bot, channelId, ["MANAGE_CHANNELS"]);
|
||||
|
||||
return getChannelInvitesOld(channelId);
|
||||
return await getChannelInvitesOld(channelId);
|
||||
};
|
||||
}
|
||||
|
||||
export function getInvites(bot: BotWithCache) {
|
||||
const getInvitesOld = bot.helpers.getInvites;
|
||||
|
||||
bot.helpers.getInvites = function (guildId) {
|
||||
bot.helpers.getInvites = async function (guildId) {
|
||||
requireBotChannelPermissions(bot, guildId, ["MANAGE_GUILD"]);
|
||||
|
||||
return getInvitesOld(guildId);
|
||||
return await getInvitesOld(guildId);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,20 +4,20 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export function banMember(bot: BotWithCache) {
|
||||
const banMemberOld = bot.helpers.banMember;
|
||||
|
||||
bot.helpers.banMember = function (guildId, id, options) {
|
||||
bot.helpers.banMember = async function (guildId, id, options) {
|
||||
requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]);
|
||||
|
||||
return banMemberOld(guildId, id, options);
|
||||
return await banMemberOld(guildId, id, options);
|
||||
};
|
||||
}
|
||||
|
||||
export function unbanMember(bot: BotWithCache) {
|
||||
const unbanMemberOld = bot.helpers.unbanMember;
|
||||
|
||||
bot.helpers.unbanMember = function (guildId, id) {
|
||||
bot.helpers.unbanMember = async function (guildId, id) {
|
||||
requireBotGuildPermissions(bot, guildId, ["BAN_MEMBERS"]);
|
||||
|
||||
return unbanMemberOld(guildId, id);
|
||||
return await unbanMemberOld(guildId, id);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function editBotNickname(bot: BotWithCache) {
|
||||
const editBotNicknameOld = bot.helpers.editBotNickname;
|
||||
|
||||
bot.helpers.editBotNickname = function (guildId, options) {
|
||||
bot.helpers.editBotNickname = async function (guildId, options) {
|
||||
requireBotGuildPermissions(bot, guildId, ["CHANGE_NICKNAME"]);
|
||||
|
||||
return editBotNicknameOld(guildId, options);
|
||||
return await editBotNicknameOld(guildId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function editMember(bot: BotWithCache) {
|
||||
const editMemberOld = bot.helpers.editMember;
|
||||
|
||||
bot.helpers.editMember = function (guildId, memberId, options) {
|
||||
bot.helpers.editMember = async function (guildId, memberId, options) {
|
||||
const requiredPerms: PermissionStrings[] = [];
|
||||
if (options.roles) requiredPerms.push("MANAGE_ROLES");
|
||||
// NULL IS ALLOWED
|
||||
@@ -17,6 +17,6 @@ export default function editMember(bot: BotWithCache) {
|
||||
requireBotGuildPermissions(bot, guildId, requiredPerms);
|
||||
}
|
||||
|
||||
return editMemberOld(guildId, memberId, options);
|
||||
return await editMemberOld(guildId, memberId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function kickMember(bot: BotWithCache) {
|
||||
const editMemberOld = bot.helpers.kickMember;
|
||||
|
||||
bot.helpers.kickMember = function (guildId, memberId, reason) {
|
||||
bot.helpers.kickMember = async function (guildId, memberId, reason) {
|
||||
requireBotGuildPermissions(bot, guildId, ["KICK_MEMBERS"]);
|
||||
|
||||
return editMemberOld(guildId, memberId, reason);
|
||||
return await editMemberOld(guildId, memberId, reason);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function pruneMembers(bot: BotWithCache) {
|
||||
const pruneMembersOld = bot.helpers.pruneMembers;
|
||||
|
||||
bot.helpers.pruneMembers = function (guildId, options) {
|
||||
bot.helpers.pruneMembers = async function (guildId, options) {
|
||||
requireBotGuildPermissions(bot, guildId, ["KICK_MEMBERS"]);
|
||||
|
||||
return pruneMembersOld(guildId, options);
|
||||
return await pruneMembersOld(guildId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export function sendMessage(bot: BotWithCache) {
|
||||
const sendMessageOld = bot.helpers.sendMessage;
|
||||
|
||||
bot.helpers.sendMessage = function (
|
||||
bot.helpers.sendMessage = async function (
|
||||
channelId,
|
||||
content,
|
||||
) {
|
||||
@@ -90,7 +90,7 @@ export function sendMessage(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
return sendMessageOld(channelId, content);
|
||||
return await sendMessageOld(channelId, content);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export function deleteMessage(bot: BotWithCache) {
|
||||
const deleteMessageOld = bot.helpers.deleteMessage;
|
||||
|
||||
bot.helpers.deleteMessage = function (
|
||||
bot.helpers.deleteMessage = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
reason,
|
||||
@@ -27,14 +27,14 @@ export function deleteMessage(bot: BotWithCache) {
|
||||
);
|
||||
}
|
||||
|
||||
return deleteMessageOld(channelId, messageId, reason, milliseconds);
|
||||
return await deleteMessageOld(channelId, messageId, reason, milliseconds);
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteMessages(bot: BotWithCache) {
|
||||
const deleteMessagesOld = bot.helpers.deleteMessages;
|
||||
|
||||
bot.helpers.deleteMessages = function (
|
||||
bot.helpers.deleteMessages = async function (
|
||||
channelId,
|
||||
ids,
|
||||
reason,
|
||||
@@ -70,7 +70,7 @@ export function deleteMessages(bot: BotWithCache) {
|
||||
"MANAGE_MESSAGES",
|
||||
]);
|
||||
|
||||
return deleteMessagesOld(channelId, ids, reason);
|
||||
return await deleteMessagesOld(channelId, ids, reason);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export function getMessage(bot: BotWithCache) {
|
||||
const getMessageOld = bot.helpers.getMessage;
|
||||
|
||||
bot.helpers.getMessage = function (
|
||||
bot.helpers.getMessage = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
) {
|
||||
@@ -15,14 +15,14 @@ export function getMessage(bot: BotWithCache) {
|
||||
]);
|
||||
}
|
||||
|
||||
return getMessageOld(channelId, messageId);
|
||||
return await getMessageOld(channelId, messageId);
|
||||
};
|
||||
}
|
||||
|
||||
export function getMessages(bot: BotWithCache) {
|
||||
const getMessagesOld = bot.helpers.getMessages;
|
||||
|
||||
bot.helpers.getMessages = function (
|
||||
bot.helpers.getMessages = async function (
|
||||
channelId,
|
||||
options,
|
||||
) {
|
||||
@@ -34,7 +34,7 @@ export function getMessages(bot: BotWithCache) {
|
||||
]);
|
||||
}
|
||||
|
||||
return getMessagesOld(channelId, options);
|
||||
return await getMessagesOld(channelId, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export function pinMessage(bot: BotWithCache) {
|
||||
const pinMessageOld = bot.helpers.pinMessage;
|
||||
|
||||
bot.helpers.pinMessage = function (
|
||||
bot.helpers.pinMessage = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
) {
|
||||
@@ -12,14 +12,14 @@ export function pinMessage(bot: BotWithCache) {
|
||||
"MANAGE_MESSAGES",
|
||||
]);
|
||||
|
||||
return pinMessageOld(channelId, messageId);
|
||||
return await pinMessageOld(channelId, messageId);
|
||||
};
|
||||
}
|
||||
|
||||
export function unpinMessage(bot: BotWithCache) {
|
||||
const unpinMessageOld = bot.helpers.unpinMessage;
|
||||
|
||||
bot.helpers.unpinMessage = function (
|
||||
bot.helpers.unpinMessage = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
) {
|
||||
@@ -27,7 +27,7 @@ export function unpinMessage(bot: BotWithCache) {
|
||||
"MANAGE_MESSAGES",
|
||||
]);
|
||||
|
||||
return unpinMessageOld(channelId, messageId);
|
||||
return await unpinMessageOld(channelId, messageId);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,20 +4,20 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export function addReaction(bot: BotWithCache) {
|
||||
const addReactionOld = bot.helpers.addReaction;
|
||||
|
||||
bot.helpers.addReaction = function (channelId, messageId, reaction) {
|
||||
bot.helpers.addReaction = async function (channelId, messageId, reaction) {
|
||||
requireBotChannelPermissions(bot, channelId, [
|
||||
"READ_MESSAGE_HISTORY",
|
||||
"ADD_REACTIONS",
|
||||
]);
|
||||
|
||||
return addReactionOld(channelId, messageId, reaction);
|
||||
return await addReactionOld(channelId, messageId, reaction);
|
||||
};
|
||||
}
|
||||
|
||||
export function addReactions(bot: BotWithCache) {
|
||||
const addReactionsOld = bot.helpers.addReactions;
|
||||
|
||||
bot.helpers.addReactions = function (
|
||||
bot.helpers.addReactions = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
reactions,
|
||||
@@ -28,14 +28,14 @@ export function addReactions(bot: BotWithCache) {
|
||||
"ADD_REACTIONS",
|
||||
]);
|
||||
|
||||
return addReactionsOld(channelId, messageId, reactions, ordered);
|
||||
return await addReactionsOld(channelId, messageId, reactions, ordered);
|
||||
};
|
||||
}
|
||||
|
||||
export function removeReaction(bot: BotWithCache) {
|
||||
const removeReactionOld = bot.helpers.removeReaction;
|
||||
|
||||
bot.helpers.removeReaction = function (
|
||||
bot.helpers.removeReaction = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
reactions,
|
||||
@@ -48,14 +48,14 @@ export function removeReaction(bot: BotWithCache) {
|
||||
]);
|
||||
}
|
||||
|
||||
return removeReactionOld(channelId, messageId, reactions, options);
|
||||
return await removeReactionOld(channelId, messageId, reactions, options);
|
||||
};
|
||||
}
|
||||
|
||||
export function removeAllReactions(bot: BotWithCache) {
|
||||
const removeAllReactionsOld = bot.helpers.removeAllReactions;
|
||||
|
||||
bot.helpers.removeAllReactions = function (
|
||||
bot.helpers.removeAllReactions = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
) {
|
||||
@@ -63,14 +63,14 @@ export function removeAllReactions(bot: BotWithCache) {
|
||||
"MANAGE_MESSAGES",
|
||||
]);
|
||||
|
||||
return removeAllReactionsOld(channelId, messageId);
|
||||
return await removeAllReactionsOld(channelId, messageId);
|
||||
};
|
||||
}
|
||||
|
||||
export function removeReactionEmoji(bot: BotWithCache) {
|
||||
const removeReactionEmojiOld = bot.helpers.removeReactionEmoji;
|
||||
|
||||
bot.helpers.removeReactionEmoji = function (
|
||||
bot.helpers.removeReactionEmoji = async function (
|
||||
channelId,
|
||||
messageId,
|
||||
reaction,
|
||||
@@ -79,7 +79,7 @@ export function removeReactionEmoji(bot: BotWithCache) {
|
||||
"MANAGE_MESSAGES",
|
||||
]);
|
||||
|
||||
return removeReactionEmojiOld(channelId, messageId, reaction);
|
||||
return await removeReactionEmojiOld(channelId, messageId, reaction);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { BotWithCache } from "../../deps.ts";
|
||||
export function editBotProfile(bot: BotWithCache) {
|
||||
const editBotProfileOld = bot.helpers.editBotProfile;
|
||||
|
||||
bot.helpers.editBotProfile = function (
|
||||
bot.helpers.editBotProfile = async function (
|
||||
options,
|
||||
) {
|
||||
// Nothing was edited
|
||||
@@ -36,7 +36,7 @@ export function editBotProfile(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
return editBotProfileOld(options);
|
||||
return await editBotProfileOld(options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { highestRole, requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function addRole(bot: BotWithCache) {
|
||||
const addRoleOld = bot.helpers.addRole;
|
||||
|
||||
bot.helpers.addRole = function (
|
||||
bot.helpers.addRole = async function (
|
||||
guildId,
|
||||
memberId,
|
||||
roleId,
|
||||
@@ -27,6 +27,6 @@ export default function addRole(bot: BotWithCache) {
|
||||
requireBotGuildPermissions(bot, guild, ["MANAGE_ROLES"]);
|
||||
}
|
||||
|
||||
return addRoleOld(guildId, memberId, roleId, reason);
|
||||
return await addRoleOld(guildId, memberId, roleId, reason);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function createRole(bot: BotWithCache) {
|
||||
const createRoleOld = bot.helpers.createRole;
|
||||
|
||||
bot.helpers.createRole = function (
|
||||
bot.helpers.createRole = async function (
|
||||
guildId,
|
||||
options,
|
||||
reason,
|
||||
) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]);
|
||||
|
||||
return createRoleOld(guildId, options, reason);
|
||||
return await createRoleOld(guildId, options, reason);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import { requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function deleteRole(bot: BotWithCache) {
|
||||
const deleteRoleOld = bot.helpers.deleteRole;
|
||||
|
||||
bot.helpers.deleteRole = function (
|
||||
bot.helpers.deleteRole = async function (
|
||||
guildId,
|
||||
id,
|
||||
) {
|
||||
requireBotGuildPermissions(bot, guildId, ["MANAGE_ROLES"]);
|
||||
|
||||
return deleteRoleOld(guildId, id);
|
||||
return await deleteRoleOld(guildId, id);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { highestRole, requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function editRole(bot: BotWithCache) {
|
||||
const editRoleOld = bot.helpers.editRole;
|
||||
|
||||
bot.helpers.editRole = function (
|
||||
bot.helpers.editRole = async function (
|
||||
guildId,
|
||||
id,
|
||||
options,
|
||||
@@ -26,6 +26,6 @@ export default function editRole(bot: BotWithCache) {
|
||||
requireBotGuildPermissions(bot, guild, ["MANAGE_ROLES"]);
|
||||
}
|
||||
|
||||
return editRoleOld(guildId, id, options);
|
||||
return await editRoleOld(guildId, id, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { highestRole, requireBotGuildPermissions } from "../permissions.ts";
|
||||
export default function removeRole(bot: BotWithCache) {
|
||||
const removeRoleOld = bot.helpers.removeRole;
|
||||
|
||||
bot.helpers.removeRole = function (
|
||||
bot.helpers.removeRole = async function (
|
||||
guildId,
|
||||
memberId,
|
||||
roleId,
|
||||
@@ -27,6 +27,6 @@ export default function removeRole(bot: BotWithCache) {
|
||||
requireBotGuildPermissions(bot, guild, ["MANAGE_ROLES"]);
|
||||
}
|
||||
|
||||
return removeRoleOld(guildId, memberId, roleId, reason);
|
||||
return await removeRoleOld(guildId, memberId, roleId, reason);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function createWebhook(bot: BotWithCache) {
|
||||
const createWebhookOld = bot.helpers.createWebhook;
|
||||
|
||||
bot.helpers.createWebhook = function (channelId, options) {
|
||||
bot.helpers.createWebhook = async function (channelId, options) {
|
||||
requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS"]);
|
||||
|
||||
if (
|
||||
@@ -17,6 +17,6 @@ export default function createWebhook(bot: BotWithCache) {
|
||||
);
|
||||
}
|
||||
|
||||
return createWebhookOld(channelId, options);
|
||||
return await createWebhookOld(channelId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function deleteWebhook(bot: BotWithCache) {
|
||||
const deleteWebhookOld = bot.helpers.deleteWebhook;
|
||||
|
||||
bot.helpers.deleteWebhook = function (channelId, options) {
|
||||
bot.helpers.deleteWebhook = async function (channelId, options) {
|
||||
requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS"]);
|
||||
|
||||
return deleteWebhookOld(channelId, options);
|
||||
return await deleteWebhookOld(channelId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { requireBotChannelPermissions } from "../permissions.ts";
|
||||
export default function editWebhook(bot: BotWithCache) {
|
||||
const editWebhookOld = bot.helpers.editWebhook;
|
||||
|
||||
bot.helpers.editWebhook = function (channelId, webhookId, options) {
|
||||
bot.helpers.editWebhook = async function (channelId, webhookId, options) {
|
||||
requireBotChannelPermissions(bot, channelId, ["MANAGE_WEBHOOKS"]);
|
||||
if (options.name) {
|
||||
if (
|
||||
@@ -18,6 +18,6 @@ export default function editWebhook(bot: BotWithCache) {
|
||||
}
|
||||
}
|
||||
|
||||
return editWebhookOld(channelId, webhookId, options);
|
||||
return await editWebhookOld(channelId, webhookId, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { validateComponents } from "../components.ts";
|
||||
export function editWebhookMessage(bot: BotWithCache) {
|
||||
const editWebhookMessageOld = bot.helpers.editWebhookMessage;
|
||||
|
||||
bot.helpers.editWebhookMessage = function (
|
||||
bot.helpers.editWebhookMessage = async function (
|
||||
webhookId,
|
||||
webhookToken,
|
||||
options,
|
||||
@@ -62,7 +62,7 @@ export function editWebhookMessage(bot: BotWithCache) {
|
||||
|
||||
if (options.components) validateComponents(bot, options.components);
|
||||
|
||||
return editWebhookMessageOld(webhookId, webhookToken, options);
|
||||
return await editWebhookMessageOld(webhookId, webhookToken, options);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { validateComponents } from "../components.ts";
|
||||
export default function sendWebhook(bot: BotWithCache) {
|
||||
const sendWebhookOld = bot.helpers.sendWebhook;
|
||||
|
||||
bot.helpers.sendWebhook = function (webhookId, webhookToken, options) {
|
||||
bot.helpers.sendWebhook = async function (webhookId, webhookToken, options) {
|
||||
if (
|
||||
options.content &&
|
||||
!bot.utils.validateLength(options.content, { max: 2000 })
|
||||
@@ -62,6 +62,6 @@ export default function sendWebhook(bot: BotWithCache) {
|
||||
);
|
||||
}
|
||||
|
||||
return sendWebhookOld(webhookId, webhookToken, options);
|
||||
return await sendWebhookOld(webhookId, webhookToken, options);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export function createRequestBody(rest: RestManager, queuedRequest: { request: R
|
||||
// IF A REASON IS PROVIDED ENCODE IT IN HEADERS
|
||||
if (queuedRequest.payload.body?.reason) {
|
||||
headers["X-Audit-Log-Reason"] = encodeURIComponent(queuedRequest.payload.body.reason as string);
|
||||
queuedRequest.payload.body.reason = undefined;
|
||||
}
|
||||
|
||||
// IF A FILE/ATTACHMENT IS PRESENT WE NEED SPECIAL HANDLING
|
||||
|
||||
@@ -10,9 +10,10 @@ import { RestPayload, RestRateLimitedPath, RestRequest } from "./rest.ts";
|
||||
import { runMethod } from "./runMethod.ts";
|
||||
import { simplifyUrl } from "./simplifyUrl.ts";
|
||||
import { baseEndpoints } from "../util/constants.ts";
|
||||
import { API_VERSION } from "../util/constants.ts";
|
||||
|
||||
export function createRestManager(options: CreateRestManagerOptions) {
|
||||
const version = options.version || "9";
|
||||
const version = options.version || API_VERSION;
|
||||
|
||||
if (options.customUrl) {
|
||||
baseEndpoints.BASE_URL = `${options.customUrl}/v${version}`;
|
||||
|
||||
4
site/docs/nodejs/CommandHandler/_category_.json
Normal file
4
site/docs/nodejs/CommandHandler/_category_.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Command Handler",
|
||||
"position": 7
|
||||
}
|
||||
91
site/docs/nodejs/CommandHandler/command-manager.md
Normal file
91
site/docs/nodejs/CommandHandler/command-manager.md
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Command Manager
|
||||
|
||||
Currently, you probably have something like this in your code:
|
||||
|
||||
```js
|
||||
const Discord = require("discordeno");
|
||||
// Ideally you should move to an `.env` file
|
||||
const config = require("./config.json");
|
||||
|
||||
const client = Discord.createBot({
|
||||
events: {
|
||||
messageCreate(client, message) {
|
||||
if (message.content === "!ping") {
|
||||
client.helpers.sendMessage(message.channelId, { content: "pong" });
|
||||
}
|
||||
},
|
||||
},
|
||||
intents: ["Guilds", "GuildMessages"],
|
||||
token: config.token,
|
||||
});
|
||||
|
||||
Discord.startBot(client);
|
||||
```
|
||||
|
||||
Of course, if you add more and more commands and as your code base grows, you can lose track very quickly.
|
||||
|
||||
To avoid this, it is recommended to store the commands in separate folders divided into different categories.
|
||||
|
||||
[Previously, we introduced you to our plugin structure, which has a lot of advantages.](../design.md)
|
||||
|
||||
```root
|
||||
├Plugins/
|
||||
├── General/
|
||||
│ ├── commands/
|
||||
│ │ ├── ping.js
|
||||
│ │ └── ...
|
||||
├── Developer/
|
||||
│ ├── commands/
|
||||
│ │ ├── eval.js
|
||||
│ │ └── ...
|
||||
└── ...
|
||||
```
|
||||
|
||||
**Get [this file](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/CommandManager.js) from
|
||||
the [nodejs template](https://github.com/discordeno/discordeno/tree/main/template)**
|
||||
|
||||
```js
|
||||
const CommandManager = require("./template/Managers/CommandManager.js");
|
||||
const manager = new CommandManager({});
|
||||
manager.load({ plugin: true }); // Load the commands
|
||||
client.commands = manager;
|
||||
|
||||
client.commands.cache.get("ping"); // Get the `ping` command
|
||||
```
|
||||
|
||||
The Manager will automatically iterate through all files in the folder and then load them into the cache property, which
|
||||
is mapped on the command name.
|
||||
|
||||
**Take a look at [Create Command](./create-command.md) to learn how to create a command.**
|
||||
|
||||
## Handle Command
|
||||
|
||||
The manager also contains a handler for executing the command when a message is received.
|
||||
|
||||
:::important
|
||||
|
||||
Currently checks for permissions, cooldowns, and rate limits are not covered, but these will be added soon.
|
||||
|
||||
:::
|
||||
|
||||
### Message Create Event:
|
||||
|
||||
```js
|
||||
module.exports = async (client, message) => {
|
||||
client.commands.isCommand(message);
|
||||
};
|
||||
```
|
||||
|
||||
### Interaction Create Event:
|
||||
|
||||
```js
|
||||
module.exports = async (client, interaction) => {
|
||||
client.commands.isInteraction(interaction);
|
||||
};
|
||||
```
|
||||
|
||||
You can also customize the `isCommand` function to your use case.
|
||||
61
site/docs/nodejs/CommandHandler/create-command.md
Normal file
61
site/docs/nodejs/CommandHandler/create-command.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Create Command
|
||||
|
||||
One of the most important features we wanted in our template, was that you can use the same code for handling
|
||||
`slash commands` and `message based commands`.
|
||||
|
||||
This can be done by saving the static class in the command cache, creating a constructor and passing the desired data.
|
||||
Moreover the `BaseCommand` is extended with the `Response Command` class, so you can take advantage of functions such as
|
||||
`.reply()`
|
||||
|
||||
**Copy the [`BaseCommand`](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Structures/BaseCommand.js)
|
||||
&
|
||||
[`CommandResponses`](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Structures/CommandResponses.js)
|
||||
code from the template**
|
||||
|
||||
### Creating a Ping Command:
|
||||
|
||||
```js
|
||||
const BaseCommand = require("../../../Structures/BaseCommand.js");
|
||||
const Embed = require("../../../Structures/Embed.js");
|
||||
|
||||
class pingCommand extends BaseCommand {
|
||||
static name = "ping";
|
||||
static description = "See if the bot latency is okay";
|
||||
static usage = "";
|
||||
static category = "General";
|
||||
static slash = { name: "ping", category: "info" };
|
||||
|
||||
constructor(data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
async execute() {
|
||||
const msg = await this.reply({content: `Pinging...`});
|
||||
// Assign properties to the response
|
||||
const ping = msg.timestamp - this.message.timestamp;
|
||||
|
||||
const embed = new Embed()
|
||||
.setTitle(`The Bots ping is ${ping} ms`)
|
||||
.toJSON();
|
||||
|
||||
// Edit Message with the Embed
|
||||
return await msg.edit({embeds: [embed] });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = pingCommand;
|
||||
```
|
||||
|
||||
- The `BaseCommand` is extended with the `CommandResponses` class.
|
||||
- The ping command class is been extended with the `BaseCommand` class.
|
||||
- Some static properties are assigned to the ping command class, in order to access it in the cache, such as `name`,
|
||||
`description`, `usage`, `category` and `slash`...
|
||||
- The `execute()` function will be called, when the command has been run by the user.
|
||||
- The constructor allows to access data, such as `this.message`, `this.args`, `this.client`...
|
||||
|
||||
You can customize the `CommandManager` file, in order to pass arguments in the `execute()` function.
|
||||
22
site/docs/nodejs/CommandHandler/getting-started.md
Normal file
22
site/docs/nodejs/CommandHandler/getting-started.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Getting Started with the Command Manager
|
||||
|
||||
One of the most important characteristics of bots is that they have commands that can be used to interact with the bot.
|
||||
|
||||
Hard coding your commands in an event function is not the best code practice and should be strictly prevented.
|
||||
|
||||
In the following we will show you how to create a command manager, which is compatible with Discordeno's Client.
|
||||
|
||||
- Load Commands
|
||||
- Handle Commands
|
||||
- Reload Commands
|
||||
|
||||
:::info template
|
||||
|
||||
You can also copy the
|
||||
[`CommandManager` from the template repo](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/CommandManager.js).
|
||||
|
||||
:::
|
||||
4
site/docs/nodejs/EventHandler/_category_.json
Normal file
4
site/docs/nodejs/EventHandler/_category_.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Event Handler",
|
||||
"position": 6
|
||||
}
|
||||
119
site/docs/nodejs/EventHandler/event-manager.md
Normal file
119
site/docs/nodejs/EventHandler/event-manager.md
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Create Event Manager
|
||||
|
||||
In order to process certain events, you must provide the Discordeno client with functions for these events.
|
||||
|
||||
```js
|
||||
const Discord = require("discordeno");
|
||||
const config = require("./config.json");
|
||||
|
||||
const client = Discord.createBot({
|
||||
events: {
|
||||
ready(client, payload) {
|
||||
console.log(`Successfully connected Shard ${payload.shardId} to the gateway`);
|
||||
},
|
||||
|
||||
async messageCreate(client, message) {
|
||||
if (message.content === "!ping") {
|
||||
await client.helpers.sendMessage(message.channelId, { content: "pong" });
|
||||
}
|
||||
|
||||
console.log(`Received message: ${message.content || message.embeds}`);
|
||||
},
|
||||
},
|
||||
intents: ["Guilds", "GuildMessages"],
|
||||
token: config.token,
|
||||
});
|
||||
|
||||
Discord.startBot(client);
|
||||
```
|
||||
|
||||
As you listen to more and more events, the functions code grows along with them, so you can quickly lose track.
|
||||
|
||||
To avoid this, we recommend storing the event functions divided into files in a separate folder.
|
||||
|
||||
## Create Event Folder
|
||||
|
||||
Create a folder called `events` in your project folder.
|
||||
|
||||
:::info note
|
||||
|
||||
The event files have to be named using camelCase so that they can be understood by the client. e.g `message` ->
|
||||
`messageCreate.js`. You can check the typings see how the events are called.
|
||||
|
||||
:::
|
||||
|
||||
Ready Event:
|
||||
|
||||
```js
|
||||
module.exports = (client, payload) => {
|
||||
if (payload.shardId + 1 === client.gateway.maxShards) {
|
||||
// All Shards are ready
|
||||
console.log(`Successfully connected to the gateway as ${payload.user.username}#${payload.user.discriminator}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Load your Events
|
||||
|
||||
```js
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const resolveFolder = (folderName) => path.resolve(__dirname, ".", folderName);
|
||||
|
||||
class EventManager {
|
||||
constructor(client) {
|
||||
this.cache = new Map();
|
||||
this._events = {};
|
||||
}
|
||||
|
||||
load(options = {}) {
|
||||
const eventsFolder = resolveFolder("../events");
|
||||
fs.readdirSync(eventsFolder).map(async (file) => {
|
||||
if (!file.endsWith(".js")) return;
|
||||
|
||||
const fileName = path.join(eventsFolder, file);
|
||||
const event = require(fileName);
|
||||
const eventName = file.split(".")[0];
|
||||
|
||||
this._events[`${eventName}`] = event;
|
||||
});
|
||||
|
||||
return this._events;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EventManager;
|
||||
```
|
||||
|
||||
The code above, which can also be found in the
|
||||
[template repo](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/EventManager.js) will loop
|
||||
through all the files in the `events` folder and load the functions into the `_events` object.
|
||||
|
||||
In order to let the client know which events should be processed, you need to pass the functions in the
|
||||
`createBot<options>.events` object.
|
||||
|
||||
```js
|
||||
const Discord = require("discordeno");
|
||||
const config = require("./config.json");
|
||||
|
||||
const EventManager = require("./Managers/EventManager.js");
|
||||
const events = new EventManager({});
|
||||
|
||||
const client = Discord.createBot({
|
||||
events: events.load({}),
|
||||
intents: ["Guilds", "GuildMessages"],
|
||||
token: config.token,
|
||||
});
|
||||
|
||||
Discord.startBot(client);
|
||||
```
|
||||
|
||||
Moreover, you can customize the `EventManager` and add more functionality to it and make it exactly fit your your needs
|
||||
or even emit events, by extending it.
|
||||
|
||||
Of course you wonder what you can do with all of this now. We will explain this further on the next page.
|
||||
29
site/docs/nodejs/EventHandler/getting-started.md
Normal file
29
site/docs/nodejs/EventHandler/getting-started.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Getting Started with the Event Handler
|
||||
|
||||
An event handler is essential to process the data, which Discord sends to you.
|
||||
|
||||
With a good implementation, you will have a nice code structure and thus have a good overview in long term.
|
||||
|
||||
Since the `EventEmitter` class is commonly used you probably already know it from other libraries.
|
||||
|
||||
Discordeno decided against it as it comes with several downsides which are mentioned below.
|
||||
|
||||
Performance plays a more important role than handling, however this event management system can be easily implemented
|
||||
since it only needs a few changes in your code.
|
||||
|
||||
- It's easy to create memory leaks, when you add too many listeners or go carelessly with it.
|
||||
- Many fragmented parts of event code complicate maintenance.
|
||||
- ErrorHandling is difficult and debugging is harder when many listeners are open for the same events.
|
||||
|
||||
In the following we will show you, how to create an event manager, which is compatible with Discordeno's Client.
|
||||
|
||||
:::info template
|
||||
|
||||
You can also copy the
|
||||
[`EventManager` from the template repo](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Managers/EventManager.js).
|
||||
|
||||
:::
|
||||
74
site/docs/nodejs/EventHandler/handle-event.md
Normal file
74
site/docs/nodejs/EventHandler/handle-event.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Handle Events
|
||||
|
||||
When an event is fired, Discordeno sends two important things: the `client` instance and the `payload`.
|
||||
|
||||
As mentioned in the `Structure` section the `payload` object, does not contain any functions, its a plain json object.
|
||||
|
||||
In order to take use of our nice built structures, we need to transform the payload into a structure.
|
||||
|
||||
:::info
|
||||
|
||||
The Structures can be found [here](https://github.com/discordeno/discordeno/tree/main/template/nodejs/Structures)
|
||||
|
||||
:::
|
||||
|
||||
Sometimes it's important to listen to events, in order to get informed of changes and updating the cache based on it.
|
||||
|
||||
### Message Event
|
||||
|
||||
This file should be called `messageCreate.js`.
|
||||
|
||||
```js
|
||||
const Message = require("./structures/Message");
|
||||
|
||||
module.exports = async (client, payload) => {
|
||||
const message = new Message(client, payload);
|
||||
|
||||
if (message.isBot) return;
|
||||
if (message.content === "!ping") return await message.reply("pong");
|
||||
};
|
||||
```
|
||||
|
||||
### Interaction Event
|
||||
|
||||
This file should be called `interactionCreate.js`.
|
||||
|
||||
```js
|
||||
const Interaction = require("./structures/Interaction");
|
||||
|
||||
module.exports = async (client, payload) => {
|
||||
const interaction = new Interaction(client, payload);
|
||||
|
||||
if (interaction.data.name === "ping") return await interaction.reply({ content: "pong" });
|
||||
};
|
||||
```
|
||||
|
||||
### Ready Event
|
||||
|
||||
This file should be called `ready.js`.
|
||||
|
||||
:::tip
|
||||
|
||||
There is a small difference with the `ready` Event. The Event is fired `shard` wise, in other words it fires every time
|
||||
a `shard` becomes ready.
|
||||
|
||||
:::
|
||||
|
||||
In order to fire the "real event" a small code snippet has to be added to the `ready` Event.
|
||||
|
||||
```js
|
||||
const User = require("../Structures/User");
|
||||
|
||||
module.exports = async (client, payload) => {
|
||||
client.user = new User(client, payload.user);
|
||||
|
||||
if (payload.shardId + 1 === client.gateway.maxShards) {
|
||||
// All Shards are ready
|
||||
console.log(`Successfully connected to the gateway as ${client.user.tag}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
4
site/docs/nodejs/Structures/_category_.json
Normal file
4
site/docs/nodejs/Structures/_category_.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Structures",
|
||||
"position": 5
|
||||
}
|
||||
219
site/docs/nodejs/Structures/components.md
Normal file
219
site/docs/nodejs/Structures/components.md
Normal file
@@ -0,0 +1,219 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Create Components
|
||||
|
||||
Since Discord has decided to make message content accessible only to privileged bots, components will play an
|
||||
increasingly important role in the future. Discord has released some components already and many more will follow. Of
|
||||
course, this opens up completely new possibilities. On the one hand, it improves the user experience and on the other
|
||||
hand, the interactions can be easily handled by the developer.
|
||||
|
||||
To take advantage of this, we'll go into more detail on how to use them.
|
||||
|
||||
:::note Runtime Overhead
|
||||
|
||||
Constructor classes are nice to use and make your code look better, but they incur a slight runtime overhead compared to
|
||||
just using raw data because they still execute methods, which takes more time to process.
|
||||
|
||||
:::
|
||||
|
||||
We already have a Template for `Components`, which can be found
|
||||
[here](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Component.js).
|
||||
|
||||
## Different Components:
|
||||
|
||||
There are many different components, which you can quickly read about here:
|
||||
|
||||
### Action Row (`type: 1`):
|
||||
|
||||
This is a top level component, which contains a limited amount of other components. It can be described as container.
|
||||
|
||||
An Action Row ...
|
||||
|
||||
- can not include an action row
|
||||
- can maximal have 5 Buttons
|
||||
- can have 1 SelectMenu
|
||||
- can have 1 Text Input (only available in modal responses)
|
||||
|
||||
### Button (`type: 2`):
|
||||
|
||||
Buttons are interactive components, are bound to a message and they sent an interaction payload, when a user clicks on
|
||||
it.
|
||||
|
||||

|
||||
|
||||
- Needs a customId, except the Link Button
|
||||
- An Action Row can have maximal 5 Buttons
|
||||
|
||||
There are different styles of buttons, which can be used:
|
||||
|
||||
- `1` - PRIMARY - blurple - customId required
|
||||
- `2` - DEFAULT - grey - customId required
|
||||
- `3` - SUCCESS - green - customId required
|
||||
- `4` - DANGER - red - customId required
|
||||
- `5` - LINK - grey - url required
|
||||
|
||||
### Select Menu (`type: 3`):
|
||||
|
||||
Select Menus are a simple drop-down with selectable options. They accept a set of allowed selects, which sends an
|
||||
interaction payload, when a user selects sth. from the menu.
|
||||
|
||||

|
||||
|
||||
- You can specify a range of allowed selects (`minValue` and `maxValue`)
|
||||
- Every Select Item can have an `emoji` and has a `value`, in order to identify the selected item
|
||||
- A default Select Item can be set
|
||||
- An Action Row can have maximal 1 Select Menu
|
||||
|
||||
### Text Input (`type: 4`):
|
||||
|
||||
Text Inputs are interactive components, which can just be sent with a modal response.
|
||||
|
||||
- You can specify a range of text length (`minLength` and `maxLength`)
|
||||
- You can add a placeholder, a pre-filled value and specify whether the text input is required
|
||||
- An Action Row can have maximal 1 Text Input
|
||||
|
||||
## Send Components
|
||||
|
||||
As mentioned above there are different types of components. This requires to define a type, so that Discord knows, which
|
||||
component you want to use.
|
||||
|
||||
```js
|
||||
class ActionRow {
|
||||
constructor(options = {}) {
|
||||
this.type = 1;
|
||||
}
|
||||
|
||||
setComponents(...components) {
|
||||
this.components = components;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
const button = new Button();
|
||||
const button2 = new Button();
|
||||
const actionRow = new ActionRow().setComponents(button, button2);
|
||||
```
|
||||
|
||||
This code will obviously not work because it's a missing a lot required of data. The other reason is that we can't send
|
||||
a class to Discord, we need sth. to transform it to a json object.
|
||||
|
||||
We have a pre-made class for components which you can find
|
||||
[here](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Component.js).
|
||||
|
||||
### Button
|
||||
|
||||
```js
|
||||
const button = new Component()
|
||||
.setType("BUTTON")
|
||||
.setStyle("LINK")
|
||||
.setLabel("Click me!")
|
||||
.setUrl("https://google.com")
|
||||
.toJSON();
|
||||
|
||||
// Button with raw types
|
||||
const button2 = new Component()
|
||||
.setType(2)
|
||||
.setStyle(4)
|
||||
.setLabel("DO NOT CLICK")
|
||||
.setCustomId("12345")
|
||||
.toJSON();
|
||||
|
||||
const actionRow = new Component()
|
||||
.setType("ACTION_ROW")
|
||||
.setComponents(button, button2)
|
||||
.toJSON();
|
||||
|
||||
// Message to send
|
||||
const messageOptions = { content: "hello", components: [actionRow] };
|
||||
|
||||
await client.helpers.sendMessage(channelId, messageOptions); // You can also use the Message Structure
|
||||
```
|
||||
|
||||
As you can see, for simplicity you can use strings instead of numbers (types), which are hard to remember.
|
||||
|
||||
### Select Menu
|
||||
|
||||
```js
|
||||
const selectMenu = new Component()
|
||||
.setType("SELECT_MENU")
|
||||
.setCustomId("12345")
|
||||
.setOptions([
|
||||
{
|
||||
label: "Option 1",
|
||||
value: "1",
|
||||
description: `This is option 1`,
|
||||
},
|
||||
{
|
||||
label: "Option 2",
|
||||
value: "2",
|
||||
description: `This is option 2`,
|
||||
},
|
||||
{
|
||||
label: "Default Option",
|
||||
value: "3",
|
||||
description: `Default option...`,
|
||||
default: true,
|
||||
},
|
||||
])
|
||||
.setPlaceholder("Select an option")
|
||||
.toJSON();
|
||||
|
||||
const actionRow = new Component()
|
||||
.setType("ACTION_ROW")
|
||||
.setComponents(selectMenu)
|
||||
.toJSON();
|
||||
|
||||
const messageOptions = { content: "hello", components: [actionRow] };
|
||||
|
||||
client.helpers.sendMessage(channelId, messageOptions); // You can also use the Message Structure
|
||||
```
|
||||
|
||||
### Text Input
|
||||
|
||||
```js
|
||||
const textInput = new Component()
|
||||
.setType("TEXT_INPUT")
|
||||
.setStyle("SHORT")
|
||||
.setCustomId("t1")
|
||||
.setLabel("User ID")
|
||||
.setPlaceholder("User ID")
|
||||
.setRequired(true)
|
||||
.setMaxLength(20)
|
||||
.setMinLength(1)
|
||||
.toJSON();
|
||||
|
||||
const textInput2 = new Component()
|
||||
.setType("TEXT_INPUT")
|
||||
.setStyle("PARAGRAPH")
|
||||
.setCustomId("t2")
|
||||
.setLabel("Reason")
|
||||
.setPlaceholder("Reason for Ban")
|
||||
.setRequired(false)
|
||||
.setMaxLength(300)
|
||||
.toJSON();
|
||||
|
||||
const actionRow = new Component().setType("ACTION_ROW").setComponents(textInput).toJSON();
|
||||
const actionRow2 = new Component().setType("ACTION_ROW").setComponents(textInput2).toJSON();
|
||||
|
||||
new Interaction(client, interaction).popupModal({
|
||||
customId: "ban_modal",
|
||||
title: "Ban User",
|
||||
components: [actionRow, actionRow2],
|
||||
});
|
||||
```
|
||||
|
||||
### Receive Interactions
|
||||
|
||||
When a user clicks a button or selects an option from a Select Menu, Discord sends an `interactionCreate` event, which
|
||||
contains the information necessary to process it.
|
||||
|
||||
:::note Collecting
|
||||
|
||||
An `InteractionCollector` can also be used to handle prompts, which requires some tweaks, but will be added soon in the
|
||||
guide and the template repo.
|
||||
|
||||
:::
|
||||
79
site/docs/nodejs/Structures/create-structure.md
Normal file
79
site/docs/nodejs/Structures/create-structure.md
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Create Structure
|
||||
|
||||
Structures are often used to transform data and add methods to existing objects. To make it easier to work with them.
|
||||
|
||||
Imagine you have a channel object to which you want to send a message.
|
||||
|
||||
```js
|
||||
const data = {
|
||||
id: 806947972004839444n,
|
||||
name: "spam-and-bots",
|
||||
};
|
||||
```
|
||||
|
||||
The recommended way would be:
|
||||
|
||||
```js
|
||||
await client.helpers.sendMessage(data.id, { content: "hello" });
|
||||
```
|
||||
|
||||
However, you probably want to use something shorter, such as the following:
|
||||
|
||||
```js
|
||||
const Channel {
|
||||
constructor(client, data) {
|
||||
this.client = client;
|
||||
this.id = data.id;
|
||||
this.name = data.name;
|
||||
}
|
||||
|
||||
async send(options) {
|
||||
return await client.helpers.sendMessage(this.id, options);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now you can use the `.send()` method on the channel object without using such a long code:
|
||||
|
||||
```js
|
||||
const channel = new Channel(client, data);
|
||||
await channel.send({ content: "hello" });
|
||||
```
|
||||
|
||||
Moreover, you can modify the `.send()` method to better suit your use case e.g not send the message if the channel is
|
||||
blacklisted.
|
||||
|
||||
This naturally opens a lot of opportunities and makes coding a lot easier. Because you decide what you want to do with
|
||||
the data, how the methods are named and how you want to process the request.
|
||||
|
||||
## Using Template Structures:
|
||||
|
||||
When you are migrating from another library, you'll likely choose to continue using special structures. Therefore why we
|
||||
have ready-made structures in our template repo:
|
||||
|
||||
- [Guild](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Guild.js)
|
||||
- [Channel](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Channel.js)
|
||||
- [Role](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Role.js)
|
||||
- [Member](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Member.js)
|
||||
- [User](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/User.js)
|
||||
- [Message](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Message.js)
|
||||
- [Interaction](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Interaction.js)
|
||||
|
||||
We recommend that you clone the whole template repo, since some structures are based on other files.
|
||||
|
||||
**Using the Structures:**
|
||||
|
||||
```js
|
||||
const Guild = require("./structures/Guild"); // Path to your structure
|
||||
const guild = new Guild(client, data); // DiscordenoClient and DiscordenoPayloadData
|
||||
```
|
||||
|
||||
Some popular methods have been added to the structures so that you can use them without having to come up with your own.
|
||||
Of course, you can add your own methods and customize the structures to fit your needs.
|
||||
|
||||
Next we're going to give a better insight into how create [`Embeds`](embeds) and [`Components`](components) with the
|
||||
template structures.
|
||||
107
site/docs/nodejs/Structures/embeds.md
Normal file
107
site/docs/nodejs/Structures/embeds.md
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Create Embeds
|
||||
|
||||
Embeds are widely used by bots in order to display messages in a fancy way.
|
||||
|
||||
Unfortunately, the Discord API does not accept funky classes such as `new MessageEmbed().setTitle("hello")`, instead it
|
||||
takes a json object, e.g. `{ title: "hello" }`. Therefore, we need to create an embed Structure that converts the
|
||||
user-supplied data into the format which Discord uses.
|
||||
|
||||
:::note Runtime Overhead
|
||||
|
||||
Constructor classes are nice to use and make your code look better, but they incur a slight runtime overhead compared to
|
||||
just using raw data because they still execute methods, which takes more time to process.
|
||||
|
||||
:::
|
||||
|
||||
```js
|
||||
class Embed() {
|
||||
constructor() {}
|
||||
|
||||
setTitle(title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now we have created a class which we can use to create embeds. But we can't just send this to Discord.
|
||||
|
||||
So we need an additional method which will convert the data from the class to the correct format.
|
||||
|
||||
```js
|
||||
class Embed(){
|
||||
constructor() {}
|
||||
|
||||
setTitle(title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
title: this.title
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Wow, now you can create a embed and send it to Discord.
|
||||
|
||||
```js
|
||||
const Channel = require("./structures/Channel"); // Path to structure
|
||||
|
||||
const channel = new Channel(client, data);
|
||||
await channel.send({ embeds: [embed] });
|
||||
```
|
||||
|
||||
You probably want more methods which you can use to create embeds.
|
||||
[We also have a Template for this](https://github.com/discordeno/discordeno/tree/main/template/nodejs/structures/Embed.js)
|
||||
|
||||
### Using the Embed Structure:
|
||||
|
||||
```js
|
||||
const Embed = require("./structures/Embed"); // Path to structure
|
||||
const Channel = require("./structures/Channel"); // Path to structure
|
||||
|
||||
const channel = new Channel(client, data);
|
||||
const showCaseEmbed = new Embed()
|
||||
.setColor(0x00AE86)
|
||||
.setTitle("A Random Title")
|
||||
.setURL("https://github.com/discordeno")
|
||||
.setAuthor({
|
||||
name: "Author name",
|
||||
iconUrl: "https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png",
|
||||
url: "https://github.com/discordeno",
|
||||
})
|
||||
.setDescription("A Random Description")
|
||||
.setThumbnail("https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png")
|
||||
.addFields(
|
||||
{ name: "Field 1 Name", value: "Normal Field Value" },
|
||||
{ name: "\u200B", value: "\u200B" },
|
||||
{ name: "Field 2 Name", value: "Inline Field Value", inline: true },
|
||||
{ name: "Field 3 Name", value: "Inline Field Value", inline: true },
|
||||
)
|
||||
.addField({ name: "Field 4", value: "Field Value" })
|
||||
.setImage("https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png")
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: "A Footer Text",
|
||||
iconUrl: "https://raw.githubusercontent.com/discordeno/discordeno/main/site/static/img/logo.png",
|
||||
})
|
||||
.toJSON();
|
||||
|
||||
await channel.send({ embeds: [showCaseEmbed] });
|
||||
```
|
||||
|
||||
### Embed Limits:
|
||||
|
||||
- Title: 256 characters
|
||||
- Description: 4096 characters
|
||||
- Field Name: 256 characters
|
||||
- Field Value: 1024 characters
|
||||
- Footer Text: 2048 characters
|
||||
- Author Name: 256 characters
|
||||
- 10 Embeds per message
|
||||
- In total over all 10 Embeds not more than 6000 characters
|
||||
30
site/docs/nodejs/Structures/getting-started.md
Normal file
30
site/docs/nodejs/Structures/getting-started.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Getting Started with Structures
|
||||
|
||||
As previously mentioned, Discordeno was built with as few classes as possible, this is in favor of performance.
|
||||
|
||||
For example, you cannot execute functions on objects.
|
||||
|
||||
```diff
|
||||
- message.channel.send({content: "hello"})
|
||||
+ client.helpers.sendMessage(message.channel.id, {content: "hello"})
|
||||
```
|
||||
|
||||
This seems to be more complicated at first, but has many advantages:
|
||||
|
||||
- You get full control over the actions
|
||||
- Errors are easier to debug
|
||||
- A validation by classes does not have to take place
|
||||
|
||||
One of the disadvantages is that you have to change a lot in your code.
|
||||
|
||||
Of course, we recommend that you try out the upper way, but we will introduce structures in this guide because they are
|
||||
used by many users who eventually want to migrate.
|
||||
|
||||
For example, if you want to get correctly formatted objects, structures are obviously beneficial, because they support
|
||||
the readability of the code by their ease of use
|
||||
|
||||
In the following, we will introduce how to create your own structures and how to use the ones available in the template.
|
||||
4
site/docs/nodejs/_category_.json
Normal file
4
site/docs/nodejs/_category_.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Nodejs",
|
||||
"position": 3
|
||||
}
|
||||
29
site/docs/nodejs/create-application.md
Normal file
29
site/docs/nodejs/create-application.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Create Application
|
||||
|
||||
1. Go to the [Developer Portal](https://discord.com/developers/applications) and create a new application.
|
||||
2. Navigate to the Section `Bot` and confirm with "Yes, do it!"
|
||||
3. Now copy your token and save it under a safe environment.
|
||||
|
||||
:::caution Token Security
|
||||
|
||||
Keep your token safe, because it is like a password that grants access to your bot, which then can be used for mass
|
||||
DMing, mass banning or any other kind of malicious activity.
|
||||
|
||||
:::
|
||||
|
||||
## Add your Bot to your Server
|
||||
|
||||
In order to use your Bot, it should be in a server where you can interact with it.
|
||||
|
||||
1. Go to the [Developer Portal](https://discord.com/developers/applications) and click on your previously created bot.
|
||||
2. Click on `OAuth2` and there go to the `URL Generator`.
|
||||
3. Select the `bot` and the `applications.commands` scope.
|
||||
4. Scroll down and select the `Administrator` permission.
|
||||
5. Copy the generated URL and open it in your browser.
|
||||
6. Select your Server and click the invite button.
|
||||
|
||||
The bot should now have been added to your server and show as an offline user.
|
||||
203
site/docs/nodejs/design.md
Normal file
203
site/docs/nodejs/design.md
Normal file
@@ -0,0 +1,203 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Design
|
||||
|
||||
In order to ensure long-term scalability and maintainability, the code structure is of enormous importance. In the
|
||||
following, we show how such a code structure could look like.
|
||||
|
||||
The essential parts are a `CommandHandler/CommandManager`, `EventHandler/EventManager`, lots of `Structures` in order to
|
||||
code faster and `Plugins`, where your different features will be, such as `Commands`, `DB Stuff`...
|
||||
|
||||
## Code Structure
|
||||
|
||||
We recommend following structure for your code:
|
||||
|
||||
```root
|
||||
├index.js
|
||||
├─Structures/
|
||||
├─Managers/
|
||||
├─events/
|
||||
├─Plugins/
|
||||
├── General/
|
||||
│ ├── commands/
|
||||
│ │ ├── ping.js
|
||||
│ │ └── ...
|
||||
├── Developer/
|
||||
│ ├── commands/
|
||||
│ │ ├── eval.js
|
||||
│ │ └── ...
|
||||
├─Util/
|
||||
└── ...
|
||||
```
|
||||
|
||||
The following explains why this structure is suitable. If you want to follow this guide further, you should create these
|
||||
folders.
|
||||
|
||||
In the `Managers` folder the Managers will be added e.g. `CommandManager.js`, `EventManager.js`. Generally codes, which
|
||||
manage the system.
|
||||
|
||||
While in the `Structures` folder mainly classes are added like `BaseCommand.js`, `CommandResponse.js`, `Embed.js`,
|
||||
`Components.js`, which make it easier to add methods to objects.
|
||||
|
||||
The `events` folder will contain the event handlers such as `messageCreate.js`, `debug.js`
|
||||
|
||||
Your many useful features and categories end up in the `Plugins` folder, where they should be categorically divided into
|
||||
many folders.
|
||||
|
||||
The `Util` folder contains functions or classes that help you convert certain things, such as timestamps, into a
|
||||
human-readable format.
|
||||
|
||||
## CommandHandler & BaseCommand
|
||||
|
||||
The `CommandHandler` is the main class of the bot, which will handle all the commands and the events received from
|
||||
Discord.
|
||||
|
||||
The `BaseCommand` is the base class of all commands, which will be extended with the`CommandResponse` class.
|
||||
|
||||
### Steps showed in the following Guide
|
||||
|
||||
- Loading commands from different plugins
|
||||
- Deploying slash commands
|
||||
- Handling `messageCreate` & `interactionCreate` events
|
||||
- Command rate limit handling
|
||||
- Handle `Interaction` & `Message` commands with the same code
|
||||
- Validating user provided arguments
|
||||
- Correct permission and error handling
|
||||
- Hot reloading commands
|
||||
- Creating message and interaction collectors
|
||||
|
||||
## EventHandler
|
||||
|
||||
You probably realized that Discordeno does not use an `EventEmitter` to fire the events, but your own event function is
|
||||
fired.
|
||||
|
||||
There are ways to adapt to an `EventEmitter`, but we decided against it for the following reasons:
|
||||
|
||||
- It's easy to create memory leaks, when you add too many listeners or go carelessly with it.
|
||||
- Many fragmented parts of event code complicate maintenance.
|
||||
- ErrorHandling is difficult and debugging is harder when many listeners are open for the same events.
|
||||
|
||||
## Structures
|
||||
|
||||
Structures are essential to abstract larger parts of code in smaller ready-made methods and to modify them if necessary.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
class Command {
|
||||
static name = "ping";
|
||||
static aliases = ["pong"];
|
||||
static botPermission = ["SEND_EMBED_LINKS"];
|
||||
|
||||
run(message, args) {
|
||||
// do something
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It would be annoying adding everytime the `botPermission` property to the class Command, when the Permission is used
|
||||
from every Command, then it is unnecessary to add it, when you can extend the class.
|
||||
|
||||
It would be annoying to add the `botPermission` property to the command class every time the same permissions are used
|
||||
by each command. Extending the class makes this extra step obsolete.
|
||||
|
||||
```js
|
||||
class BaseCommand {
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
this.basePermission = ["SEND_EMBED_LINKS"];
|
||||
}
|
||||
}
|
||||
|
||||
class Command extends BaseCommand {
|
||||
static name = "ping";
|
||||
static aliases = ["pong"];
|
||||
|
||||
constructor(data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
run(message, args) {
|
||||
// do something
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Plugins
|
||||
|
||||
The plugins folder helps you categorize your code into many parts to give some structure.
|
||||
|
||||
Of course, this has many advantages, you have a much clearer code, you can debug problems much easier.
|
||||
|
||||
This also opens possibilities for open source contributions, since not all parts of the code have to be published in
|
||||
order to add new plugins, since they are "independent".
|
||||
|
||||
There will be the main `Plugins` folder, which by default contains a `General` folder for all your base commands. The
|
||||
`Plugins` folder will also contain all your other plugins.
|
||||
|
||||
## Error Handling
|
||||
|
||||
One of the most important things is how to handle errors. This is done to provide a user-friendly experience and to find
|
||||
errors faster.
|
||||
|
||||
You should catch errors and log them in your logger so you can fix them later. There are several open source `Sentry`'s
|
||||
that give you a good overview of the latest errors through a website.
|
||||
|
||||
Sometimes errors have a positive effect on maintainability and scalability.
|
||||
|
||||
In addition, handling errors caused by users is very important to increase transparency. If they don't know why the
|
||||
error happened, then they'll be very surprised with what they did wrong and might even remove your bot from their
|
||||
server.
|
||||
|
||||
## Caching
|
||||
|
||||
Normally libraries cache all the info they get, which can of course be helpful at the beginning to discover all
|
||||
functionalities but later it turns out to be a resource-consuming method. Therefore, this way should be avoided.
|
||||
|
||||
Discordeno allows `Custom Caching` and even `Custom Property Caching` which gives you fine-grained control over the
|
||||
caching of data. Normally you only need 20% of the data received by Discord, which makes caching unnecessary in most
|
||||
cases.
|
||||
|
||||
There are also some `Filter` and `Sweeper` methods which help you to empty unused cache values.
|
||||
|
||||
## Cross Communication & Scaling
|
||||
|
||||
If you are running many different processes, such as a Welcomer API, communication is of central importance in order to
|
||||
send or receive data, with which you can then perform certain actions.
|
||||
|
||||
Cross communication can be easily done with sockets or a TCP client.
|
||||
|
||||
This brings up this Structure:
|
||||
|
||||
```js
|
||||
Bridge (Heart)
|
||||
- Machine 1
|
||||
- Cluster [0-9]
|
||||
- Machine 2
|
||||
- Cluster [10-18]
|
||||
- Machine 3 -> Welcomer Api
|
||||
- Machine 4 -> Dashboard
|
||||
```
|
||||
|
||||
It's important to use something fast to have a proper "real time" communication.
|
||||
|
||||
Discordeno already offers many internal options for scaling bots, no matter what size.
|
||||
|
||||
As you scale, you will likely separate many parts of your bot and put them in separate processes, such as a
|
||||
`RestManager`, a `Gateway Manager` etc.
|
||||
|
||||
This of course opens up a lot of possibilities:
|
||||
|
||||
- Zero downtime updates
|
||||
- Global cache
|
||||
- Synced rate limits
|
||||
|
||||
[Check the Github Readme for more information](https://github.com/discordeno/discordeno#features)
|
||||
|
||||
:::tip congratulations
|
||||
|
||||
You just learned how to design a scalable bot, let's get into implementing it with the next pages.
|
||||
|
||||
:::
|
||||
48
site/docs/nodejs/getting-started.md
Normal file
48
site/docs/nodejs/getting-started.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Getting Started
|
||||
|
||||
If you are reading this, you probably want to create a Discord bot with Discordeno or migrate from popular libraries
|
||||
like Discord.js.
|
||||
|
||||
If this is going to be your first time making a bot, you should use Deno instead of Node.js. Although in some cases Deno
|
||||
might not be suitable for you, because of missing packages or a code base which too large to migrate to a slightly
|
||||
different language.
|
||||
|
||||
This guide will help you making your first Discord Bot using Node.js or even migrating your Bot from a other Library.
|
||||
|
||||
:::important Disclaimer
|
||||
|
||||
Some features are not documented yet. If you want to know more about them, kindly ask for help in the
|
||||
[Discord Server](https://discord.gg/ddeno).
|
||||
|
||||
:::
|
||||
|
||||
## Why should I switch?
|
||||
|
||||
Discordeno was built with the purpose of being scalable, flexible and easy to use.
|
||||
|
||||
Libraries like `Discord.js` and `Eris` often have excessive caching behavior that can only be changed slightly without
|
||||
breaking the entire library. There is a lack of customization and many nested classes, which makes it almost impossible
|
||||
to edit the code without having unwanted side effects. Moreover scalability is only possible on a limited extend.
|
||||
|
||||
Discordeno has been kept plain and simple, which opens up a lot of opportunities for customization such as
|
||||
`custom-caching (custom-property-caching)`, [`Standalone Rest`](../big-bot-guide/rest.md),
|
||||
[`Gateway`](../big-bot-guide/gateway.md), [`Cache`](../big-bot-guide/cache.md) and more. Check the detailed advantages
|
||||
[here](https://github.com/discordeno/discordeno#features).
|
||||
|
||||
This guide will also help you making your code more scalable and easier to maintain with bringing you closer to the
|
||||
Discord API.
|
||||
|
||||
# Before you start
|
||||
|
||||
Before you start digging in this guide, you should have a solid understanding of `javascript`. If you are not familiar
|
||||
with it, then you should take a look at some popular resources.
|
||||
|
||||
- [W3Schools Course](https://www.w3schools.com/js/DEFAULT.asp)
|
||||
- [Mozilla Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
||||
- [JavaScript.Info](https://javascript.info)
|
||||
|
||||
A basic understanding is of great importance in order to solve problems skillfully.
|
||||
46
site/docs/nodejs/initial-setup.md
Normal file
46
site/docs/nodejs/initial-setup.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Initial Setup
|
||||
|
||||
## Config File
|
||||
|
||||
Ideally, you should save your configs in an `.env` file. Out of simplicity for this guide, we are saving it in a
|
||||
`config.json` file.
|
||||
|
||||
Create a file named `config.json` in your project folder and insert the following content:
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "YOUR_TOKEN_HERE",
|
||||
"prefix": "!"
|
||||
}
|
||||
```
|
||||
|
||||
## Edit the main file
|
||||
|
||||
Open the `index.js` file which you have created earlier and then insert the following content:
|
||||
|
||||
```js
|
||||
const Discord = require("discordeno");
|
||||
const config = require("./config.json");
|
||||
|
||||
const client = Discord.createBot({
|
||||
events: {
|
||||
ready(client, payload) {
|
||||
console.log(`Successfully connected Shard ${payload.shardId} to the gateway`);
|
||||
},
|
||||
},
|
||||
intents: ["Guilds", "GuildMessages"],
|
||||
token: config.token,
|
||||
});
|
||||
|
||||
Discord.startBot(client);
|
||||
```
|
||||
|
||||
Now you can start your bot by running the following command in your terminal:
|
||||
|
||||
```cli
|
||||
$ node index.js
|
||||
```
|
||||
29
site/docs/nodejs/installion.md
Normal file
29
site/docs/nodejs/installion.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Installing Node.js and Discordeno
|
||||
|
||||
To use the Discordeno library you first need to install Node.js and then Discordeno from NPM.
|
||||
|
||||
Go to [nodejs.org](https://nodejs.org/en/) and download the latest version of Node.js. Open the downloaded file and
|
||||
follow the instructions of the installer to install Node.js.
|
||||
|
||||
## Create a Folder
|
||||
|
||||
Open your file manager and create a new folder (e.g.: `discordbot`) in your desired directory. Then open the code editor
|
||||
of your choice and create a new file (e.g.: `index.js`) in the folder you just have created.
|
||||
|
||||
### Initalize NPM & Install Discordeno
|
||||
|
||||
In order to keep track of the dependencies, you need to initialize NPM, which generates a `package.json` file.
|
||||
|
||||
```cli
|
||||
$ npm init --yes
|
||||
```
|
||||
|
||||
Then you need to install Discordeno. Go to your terminal and run the following command:
|
||||
|
||||
```cli
|
||||
$ npm install discordeno
|
||||
```
|
||||
64
site/docs/nodejs/slash-command.md
Normal file
64
site/docs/nodejs/slash-command.md
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Slash Commands
|
||||
|
||||
Since Discord has decided to make message content accessible only to privileged bots, message commands will play a
|
||||
subordinate role in the future. Discord users will be more used to slash commands. That's why it's essential that every
|
||||
bot offers them.
|
||||
|
||||
In the following we will show you how to create slash commands:
|
||||
|
||||
## Deploying Slash Commands
|
||||
|
||||
There is a difference between global and guild commands. Global commands take a while to appear in all guilds. Guild
|
||||
commands show up directly.
|
||||
|
||||
For this reason, we will now show how to create guild commands, in order to test them immediately.
|
||||
|
||||
```js
|
||||
const guildId = BigInt("YOUR_GUILD_ID");
|
||||
const command = {
|
||||
name: "ping",
|
||||
description: "Retrieves the Bot latency",
|
||||
options: [],
|
||||
};
|
||||
|
||||
client.helpers.createApplicationCommand(command, guildId);
|
||||
```
|
||||
|
||||
This is just very simple example, you can also add sub commands, select options and much more.
|
||||
|
||||
## Handling Slash Commands
|
||||
|
||||
Discord sends a WebSocket Event, when a user runs a slash command. You can listen to this event by add the
|
||||
`interactionCreate` function in the client.
|
||||
|
||||
```js
|
||||
const Discord = require("discordeno");
|
||||
const config = require("./config.json");
|
||||
|
||||
const client = Discord.createBot({
|
||||
events: {
|
||||
ready(client, payload) {
|
||||
console.log(`Successfully connected Shard ${payload.shardId} to the gateway`);
|
||||
},
|
||||
async interactionCreate(client, interaction) {
|
||||
if (interaction.data?.name === "ping") {
|
||||
return await client.helpers.sendInteractionResponse(interaction.id, interaction.token, {
|
||||
type: Discord.InteractionResponseTypes.ChannelMessageWithSource,
|
||||
data: { content: "🏓 Pong!" },
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
intents: ["Guilds"],
|
||||
token: config.token,
|
||||
});
|
||||
|
||||
Discord.startBot(client);
|
||||
```
|
||||
|
||||
The handling may see complicated in the beginning, but as mentioned before, we will introduce structures to make it
|
||||
easier.
|
||||
12
site/package-lock.json
generated
12
site/package-lock.json
generated
@@ -6140,9 +6140,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.7",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
||||
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
|
||||
"version": "1.14.8",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
|
||||
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -17396,9 +17396,9 @@
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.7",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
||||
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ=="
|
||||
"version": "1.14.8",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
|
||||
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA=="
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin": {
|
||||
"version": "6.5.0",
|
||||
|
||||
17
template/nodejs/Managers/ChannelManager.js
Normal file
17
template/nodejs/Managers/ChannelManager.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const Channel = require("../Structures/Channel");
|
||||
class Channels {
|
||||
constructor(client, data = {}, options = {}) {
|
||||
this.client = client;
|
||||
|
||||
if (options.guild) this.guild = options.guild;
|
||||
}
|
||||
|
||||
async create(options = {}, reason) {
|
||||
return new Channel(this.client, options).create(options, reason);
|
||||
}
|
||||
|
||||
forge(data = {}) {
|
||||
return new Channel(this.client, data);
|
||||
}
|
||||
}
|
||||
module.exports = Channels;
|
||||
136
template/nodejs/Managers/CommandManager.js
Normal file
136
template/nodejs/Managers/CommandManager.js
Normal file
@@ -0,0 +1,136 @@
|
||||
const resolveFolder = (folderName) => path.resolve(__dirname, ".", folderName);
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
class CommandManager {
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
this.cache = new Map();
|
||||
this.aliases = new Map();
|
||||
}
|
||||
load(options = {}) {
|
||||
const commandFolderPath = options.path || "../Plugins";
|
||||
const commandFolder = resolveFolder(commandFolderPath);
|
||||
if (options.category === undefined) options.category = true;
|
||||
if (options.plugins === undefined) options.plugins = true;
|
||||
//PluginMode will iterate through all SubFolders
|
||||
fs.readdirSync(commandFolder).map(async (dir) => {
|
||||
if (dir.endsWith(".txt")) return;
|
||||
if (!options.category && dir.endsWith(".js")) {
|
||||
const commandPath = path.join(commandFolder, dir);
|
||||
this.loadCommand(commandPath);
|
||||
} else {
|
||||
fs.readdirSync(path.join(commandFolder, dir)).map((cmd) => {
|
||||
if (cmd.endsWith(".js") && !options.plugins) {
|
||||
const commandPath = path.join(commandFolder, dir, cmd);
|
||||
this.loadCommand(commandPath);
|
||||
} else if (commandFolderPath === "../Plugins") {
|
||||
if (cmd !== "commands") return;
|
||||
fs.readdirSync(path.join(commandFolder, dir, cmd)).map((cmdfile) => {
|
||||
if (!cmdfile.endsWith(".js")) return;
|
||||
const commandPath = path.join(commandFolder, dir, cmd, cmdfile);
|
||||
this.loadCommand(commandPath);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadCommand(commandPath) {
|
||||
const pull = require(path.join(commandPath));
|
||||
if (pull.name) {
|
||||
pull.path = commandPath;
|
||||
this.cache.set(pull.name, pull);
|
||||
}
|
||||
if (pull.aliases) {
|
||||
pull.aliases.map((p) => this.aliases.set(p, pull));
|
||||
}
|
||||
return pull;
|
||||
}
|
||||
|
||||
reloadCommand(commandName) {
|
||||
const command = this.cache.get(commandName);
|
||||
if (!command) return;
|
||||
const commandPath = path.join(command.path);
|
||||
delete require.cache[require.resolve(commandPath)];
|
||||
return this.loadCommand(commandPath);
|
||||
}
|
||||
|
||||
isCommand(message) {
|
||||
if (message.isBot) return false;
|
||||
const prefix = "!";
|
||||
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const prefixRegex = new RegExp(`^(<@!?${this.client.id}>|${escapeRegex(prefix)})\\s*`);
|
||||
if (!prefixRegex.test(message.content)) return false;
|
||||
|
||||
const [, matchedPrefix] = message.content.match(prefixRegex);
|
||||
const args = message.content.slice(matchedPrefix.length).trim().split(/ +/);
|
||||
|
||||
this.onMessage(message, prefix, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
isInteraction(interaction) {
|
||||
if (interaction.type !== 2) return;
|
||||
this.onInteraction(interaction);
|
||||
}
|
||||
|
||||
async onMessage(message, guild, args) {
|
||||
const commandName = args.shift().toLowerCase();
|
||||
const command = this.cache.get(commandName); //|| this.cache.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
|
||||
if (!command && message.content.includes(this.client.id)) {
|
||||
//Handle, when Command has not been found
|
||||
const options = { content: "I did not found the Command!" };
|
||||
this.client.helpers.sendMessage(message.channelId, options);
|
||||
}
|
||||
if (!command) return;
|
||||
|
||||
const messagecommand = new command({
|
||||
manager: this,
|
||||
message: message,
|
||||
client: this.client,
|
||||
args: args,
|
||||
settings: {},
|
||||
commandName: command.name,
|
||||
});
|
||||
messagecommand.execute()?.catch?.((error) => {
|
||||
console.log(error);
|
||||
// Call Function on CommandResponse.js, handle the error
|
||||
return messagecommand.onError(error ?? "custom");
|
||||
});
|
||||
}
|
||||
|
||||
async onInteraction(interaction) {
|
||||
const command = this.cache.get(interaction.data.name);
|
||||
if (!command) return;
|
||||
|
||||
const args = [];
|
||||
//Map all Values and Args
|
||||
interaction.data.options.map((o) => {
|
||||
if (o.name) args.push(o.name);
|
||||
if (o.options) {
|
||||
o.options.map((o2) => {
|
||||
if (o2.value) return args.push(o2.value);
|
||||
if (o2.name) args.push(o2.name);
|
||||
if (o2.options) o2.options.map((v) => args.push(v.value));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const messagecommand = new command({
|
||||
manager: this,
|
||||
interaction: interaction,
|
||||
client: this.client,
|
||||
args: args,
|
||||
settings: {},
|
||||
commandName: command.name,
|
||||
});
|
||||
messagecommand.execute()?.catch?.((error) => {
|
||||
console.log(error);
|
||||
// Call Function on CommandResponse.js, handle the error
|
||||
return messagecommand.onError(error ?? "custom");
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = CommandManager;
|
||||
32
template/nodejs/Managers/EventManager.js
Normal file
32
template/nodejs/Managers/EventManager.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const resolveFolder = (folderName) => path.resolve(__dirname, ".", folderName);
|
||||
|
||||
const EventEmitter = require("events");
|
||||
|
||||
class EventManager extends EventEmitter {
|
||||
constructor(client) {
|
||||
super();
|
||||
this.cache = new Map();
|
||||
this._events = {};
|
||||
}
|
||||
|
||||
load(options = {}) {
|
||||
const eventsFolder = resolveFolder("../events");
|
||||
fs.readdirSync(eventsFolder).map(async (file) => {
|
||||
if (!file.endsWith(".js")) return;
|
||||
const fileName = path.join(eventsFolder, file);
|
||||
const event = require(fileName);
|
||||
const eventName = file.split(".")[0];
|
||||
this._events[`${eventName}`] = event;
|
||||
/* When the event should be emitted on client.events.on(eventName, (...args) => {...})
|
||||
this._events[`${eventName}`] = function(...args) {
|
||||
this.emit(eventName, ...args);
|
||||
return event(...args);
|
||||
};
|
||||
*/
|
||||
});
|
||||
return this._events;
|
||||
}
|
||||
}
|
||||
module.exports = EventManager;
|
||||
13
template/nodejs/Managers/MemberManager.js
Normal file
13
template/nodejs/Managers/MemberManager.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const Member = require("../Structures/Member");
|
||||
class Members {
|
||||
constructor(client, data = {}, options = {}) {
|
||||
this.client = client;
|
||||
|
||||
if (options.guild) this.guild = options.guild;
|
||||
}
|
||||
|
||||
forge(data = {}) {
|
||||
return new Member(this.client, data, { guild: this.guild });
|
||||
}
|
||||
}
|
||||
module.exports = Members;
|
||||
29
template/nodejs/Managers/RoleManager.js
Normal file
29
template/nodejs/Managers/RoleManager.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const Role = require("../Structures/Role");
|
||||
class Roles {
|
||||
constructor(client, data = {}, options = {}) {
|
||||
this.client = client;
|
||||
if (options.member) this.member = options.member;
|
||||
if (options.guild) this.guild = options.guild;
|
||||
}
|
||||
|
||||
async create(options = {}, reason) {
|
||||
return new Role(this.client, options).create(options, reason);
|
||||
}
|
||||
|
||||
forge(data = {}) {
|
||||
return new Roles(this.client, data);
|
||||
}
|
||||
|
||||
async add(options = {}, reason) {
|
||||
const guildId = (this.guild ? this.guild.id : options.guildId);
|
||||
const memberId = (this.member ? this.member.id : options.memberId);
|
||||
return this.client.helpers.addRole(guildId, memberId, options.roleId, reason);
|
||||
}
|
||||
|
||||
async remove(options = {}, reason) {
|
||||
const guildId = (this.guild ? this.guild.id : options.guildId);
|
||||
const memberId = (this.member ? this.member.id : options.memberId);
|
||||
return this.client.helpers.removeRole(guildId, memberId, options.roleId, reason);
|
||||
}
|
||||
}
|
||||
module.exports = Roles;
|
||||
49
template/nodejs/Plugins/Developer/commands/eval.js
Normal file
49
template/nodejs/Plugins/Developer/commands/eval.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const BaseCommand = require("../../../Structures/BaseCommand.js");
|
||||
const Embed = require("../../../Structures/Embed.js");
|
||||
class evalcommand extends BaseCommand {
|
||||
static name = "eval";
|
||||
static description = "danger !!!";
|
||||
static category = "Developer";
|
||||
static slash = { name: "eval", category: "dev" };
|
||||
constructor(data) {
|
||||
super(data);
|
||||
}
|
||||
async execute() {
|
||||
if (!this.client.config.owners.includes(String(this.user.id))) return;
|
||||
if (!(this.args.length > 0)) return this.reply({ content: "**You must provide something to eval!**" });
|
||||
|
||||
let inputOfEval = this.args.join(" ");
|
||||
let outputOfEval;
|
||||
let typeOfEval;
|
||||
|
||||
try {
|
||||
if (this.args.includes("await")) {
|
||||
outputOfEval = await eval("(async () => {" + inputOfEval + "})()");
|
||||
} else {
|
||||
outputOfEval = await eval(inputOfEval);
|
||||
}
|
||||
} catch (e) {
|
||||
outputOfEval = e.message;
|
||||
typeOfEval = e.name;
|
||||
}
|
||||
|
||||
var seen = [];
|
||||
outputOfEval = typeof outputOfEval === "object"
|
||||
? JSON.stringify(outputOfEval, (_, value) => {
|
||||
if (value == `Bot ${this.client.config.token}`) return `BOT_TOKEN`;
|
||||
if (typeof value === "bigint") value = value.toString();
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (seen.indexOf(value) !== -1) return;
|
||||
else seen.push(value);
|
||||
}
|
||||
return value;
|
||||
}, 1)
|
||||
: outputOfEval;
|
||||
|
||||
const embed = new Embed()
|
||||
.addField({ name: "Input", value: "```js\n" + inputOfEval + "```" })
|
||||
.addField({ name: "Output", value: "```json\n" + `${outputOfEval}`.slice(0, 1000) + "```" });
|
||||
this.reply({ embeds: [embed] });
|
||||
}
|
||||
}
|
||||
module.exports = evalcommand;
|
||||
19
template/nodejs/Plugins/Developer/commands/reload.js
Normal file
19
template/nodejs/Plugins/Developer/commands/reload.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const BaseCommand = require("../../../Structures/BaseCommand.js");
|
||||
const Embed = require("../../../Structures/Embed.js");
|
||||
class reloadcommand extends BaseCommand {
|
||||
static name = "reload";
|
||||
static description = "Reloads a Command";
|
||||
static category = "Developer";
|
||||
static slash = { name: "reload", category: "dev" };
|
||||
constructor(data) {
|
||||
super(data);
|
||||
}
|
||||
async execute() {
|
||||
if (!this.client.config.owners.includes(String(this.user.id))) return;
|
||||
if (!this.args[0]) return this.reply({ content: "**You must provide a command to reload!**" });
|
||||
const op = this.client.commands.reloadCommand(this.args[0]);
|
||||
if (!op) return this.reply({ content: "**That command doesn't exist!**" });
|
||||
return this.reply({ content: "**Reloaded Command: `" + this.args[0] + "`**" });
|
||||
}
|
||||
}
|
||||
module.exports = reloadcommand;
|
||||
0
template/nodejs/Plugins/Developer/index.js
Normal file
0
template/nodejs/Plugins/Developer/index.js
Normal file
24
template/nodejs/Plugins/General/commands/ping.js
Normal file
24
template/nodejs/Plugins/General/commands/ping.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const BaseCommand = require("../../../Structures/BaseCommand.js");
|
||||
const Embed = require("../../../Structures/Embed.js");
|
||||
class pingcommand extends BaseCommand {
|
||||
static name = "ping";
|
||||
static description = "See if the bot latency is okay";
|
||||
static usage = "";
|
||||
static category = "General";
|
||||
static slash = { name: "ping", category: "info" };
|
||||
constructor(data) {
|
||||
super(data);
|
||||
}
|
||||
async execute() {
|
||||
const msg = await this.reply({ content: `Pinging...` });
|
||||
//Assign properties to the response
|
||||
const ping = msg.timestamp - this.message.timestamp;
|
||||
|
||||
const embed = new Embed()
|
||||
.setTitle(`The Bots ping is ${ping} ms`)
|
||||
.toJSON();
|
||||
//Edit Message with the Embed
|
||||
return msg.edit({ embeds: [embed] });
|
||||
}
|
||||
}
|
||||
module.exports = pingcommand;
|
||||
0
template/nodejs/Plugins/General/index.js
Normal file
0
template/nodejs/Plugins/General/index.js
Normal file
40
template/nodejs/Plugins/Moderation/commands/ban.js
Normal file
40
template/nodejs/Plugins/Moderation/commands/ban.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const BaseCommand = require("../../../Structures/BaseCommand.js");
|
||||
const Component = require("../../../Structures/Component.js");
|
||||
|
||||
class bancommand extends BaseCommand {
|
||||
static name = "ban";
|
||||
static description = "Ban a user from the server";
|
||||
static usage = "";
|
||||
static category = "Moderation";
|
||||
static slash = { name: "ban", category: "mod" };
|
||||
constructor(data) {
|
||||
super(data);
|
||||
}
|
||||
async execute() {
|
||||
//Show Case Modal
|
||||
|
||||
// Because no permission system has not been added
|
||||
if (!this.client.config.owners.includes(String(this.user.id))) return;
|
||||
|
||||
const textinput = new Component()
|
||||
.setType("TEXT_INPUT")
|
||||
.setStyle("SHORT")
|
||||
.setCustomId("t1")
|
||||
.setLabel("User ID")
|
||||
.setPlaceholder("User ID")
|
||||
.setRequired(true)
|
||||
.setMaxLength(20)
|
||||
.setMinLength(1)
|
||||
.setValue(this.args[0])
|
||||
.toJSON();
|
||||
const textinput2 = new Component().setType("TEXT_INPUT").setStyle("PARAGRAPH").setCustomId("t2")
|
||||
.setLabel("Reason").setPlaceholder("Reason for Ban").setRequired(false)
|
||||
.setMaxLength(300).toJSON();
|
||||
|
||||
const actionrow = new Component().setType(1).setComponents(textinput).toJSON();
|
||||
const actionrow2 = new Component().setType(1).setComponents(textinput2).toJSON();
|
||||
|
||||
this.interaction.popupModal({ customId: "ban_modal", title: "Ban User", components: [actionrow, actionrow2] });
|
||||
}
|
||||
}
|
||||
module.exports = bancommand;
|
||||
0
template/nodejs/Plugins/Moderation/index.js
Normal file
0
template/nodejs/Plugins/Moderation/index.js
Normal file
17
template/nodejs/Structures/BaseCommand.js
Normal file
17
template/nodejs/Structures/BaseCommand.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const UtilCommand = require("./CommandResponse.js");
|
||||
const Message = require("./Message.js");
|
||||
const Interaction = require("./Interaction.js");
|
||||
class BaseCommand extends UtilCommand {
|
||||
constructor(data) {
|
||||
super(data);
|
||||
this.message = data.message && new Message(data.client, data.message);
|
||||
this.interaction = data.interaction && new Interaction(data.client, data.interaction);
|
||||
this.user = this.message ? this.message.author : this.interaction.user;
|
||||
this.guild = this.message ? this.message.guild : this.interaction.guild;
|
||||
this.member = this.message ? this.message.member : this.interaction.member;
|
||||
this.channel = this.message ? this.message.channel : this.interaction.channel;
|
||||
this.client = data.client;
|
||||
this.settings = data.settings ?? {};
|
||||
}
|
||||
}
|
||||
module.exports = BaseCommand;
|
||||
29
template/nodejs/Structures/Channel.js
Normal file
29
template/nodejs/Structures/Channel.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const DestructObject = require("./DestructObject");
|
||||
const Guild = require("./Guild");
|
||||
|
||||
class Channel extends DestructObject {
|
||||
constructor(client, channel = {}, options = {}) {
|
||||
super(channel);
|
||||
if (options.guild) this.guild = options.guild;
|
||||
else if (channel.guildId) this.guild = new Guild(client, { id: channel.guildId });
|
||||
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async create(options = {}, reason) {
|
||||
return this.client.helpers.createChannel(this.guildId, options, reason);
|
||||
}
|
||||
|
||||
async edit(options = {}, reason) {
|
||||
return this.client.helpers.editChannel(this.id, options, reason);
|
||||
}
|
||||
|
||||
async delete(reason) {
|
||||
return this.client.helpers.deleteChannel(this.id, reason);
|
||||
}
|
||||
|
||||
async send(options = {}) {
|
||||
return this.client.helpers.sendMessage(this.id, options);
|
||||
}
|
||||
}
|
||||
module.exports = Channel;
|
||||
57
template/nodejs/Structures/CommandResponse.js
Normal file
57
template/nodejs/Structures/CommandResponse.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const Message = require("./Message");
|
||||
|
||||
class Responses {
|
||||
constructor(data) {
|
||||
this.manager = data.manager;
|
||||
this.args = this._validateArguments(data.args);
|
||||
this.replied = false;
|
||||
}
|
||||
|
||||
async reply(content) {
|
||||
// When just a string is passed, we assume it's the content -> transform to correct formatted payload
|
||||
if (typeof content === "string") content = { content };
|
||||
if (this.interaction) {
|
||||
if (this.replied) return this.followUp(content);
|
||||
const reply = await this.interaction.reply(content);
|
||||
|
||||
//Assign properties to the response
|
||||
const response = new Message(this.client, reply);
|
||||
|
||||
this.replied = true;
|
||||
return response;
|
||||
}
|
||||
if (this.message) {
|
||||
if (this.replied) return this.followUp(content);
|
||||
|
||||
const msg = await this.message.channel.send(content);
|
||||
|
||||
//Assign properties to the response
|
||||
const response = new Message(this.client, msg);
|
||||
this.replied = true;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
async followUp(content) {
|
||||
if (this.interaction) {
|
||||
const reply = await this.interaction.followUp(content);
|
||||
const response = new Message(this.client, reply);
|
||||
return response;
|
||||
}
|
||||
if (this.message) {
|
||||
const msg = await this.message.channel.send(content);
|
||||
const response = new Message(this.client, msg);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
onError(error) {
|
||||
return this.reply({ content: `A unknown Error happend: \n> ${error}` });
|
||||
}
|
||||
|
||||
_validateArguments(args) {
|
||||
this.args = args;
|
||||
return args;
|
||||
}
|
||||
}
|
||||
module.exports = Responses;
|
||||
171
template/nodejs/Structures/Component.js
Normal file
171
template/nodejs/Structures/Component.js
Normal file
@@ -0,0 +1,171 @@
|
||||
const Constants = {
|
||||
PRIMARY: 1,
|
||||
SECONDARY: 2,
|
||||
SUCCESS: 3,
|
||||
DANGER: 4,
|
||||
LINK: 5,
|
||||
SHORT: 1,
|
||||
PARAGRAPH: 2,
|
||||
|
||||
ACTION_ROW: 1,
|
||||
BUTTON: 2,
|
||||
SELECT_MENU: 3,
|
||||
TEXT_INPUT: 4,
|
||||
};
|
||||
class Component {
|
||||
constructor(options = {}) {
|
||||
this.type = options.type;
|
||||
this.custom_id = options.custom_id ?? options.customId;
|
||||
this.disabled = options.disabled;
|
||||
this.style = options.style;
|
||||
this.label = options.label;
|
||||
this.emoji = options.emoji;
|
||||
this.url = options.url;
|
||||
|
||||
//Select Menu
|
||||
this.options = options.options;
|
||||
this.placeholder = options.placeholder;
|
||||
this.min_values = options.min_values ?? options.minValues;
|
||||
this.max_values = options.max_values ?? options.maxValues;
|
||||
|
||||
//Action Row
|
||||
this.components = options.components;
|
||||
|
||||
//Modal
|
||||
this.value = options.value;
|
||||
this.min_length = options.min_length ?? options.minLength;
|
||||
this.max_length = options.max_length ?? options.maxLength;
|
||||
this.required = options.required;
|
||||
}
|
||||
|
||||
setType(type) {
|
||||
if (typeof type === "string") {
|
||||
this.type = Constants[type.toUpperCase()];
|
||||
if (!this.type) throw new Error(`Invalid Component Type: ${type}`);
|
||||
} else this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
setCustomId(custom_id) {
|
||||
if (!this.url) this.custom_id = custom_id;
|
||||
return this;
|
||||
}
|
||||
|
||||
setDisabled(disabled) {
|
||||
this.disabled = disabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
setRequired(required) {
|
||||
this.required = required;
|
||||
return this;
|
||||
}
|
||||
|
||||
setStyle(style) {
|
||||
if (!this.url) {
|
||||
if (typeof style === "string") {
|
||||
this.style = Constants[style.toUpperCase()];
|
||||
if (!this.style) throw new Error(`Invalid Button Style Type: ${type}`);
|
||||
} else this.style = style;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
setLabel(label) {
|
||||
this.label = label;
|
||||
return this;
|
||||
}
|
||||
|
||||
setEmoji(emoji) {
|
||||
this.emoji = emoji;
|
||||
return this;
|
||||
}
|
||||
|
||||
setUrl(url) {
|
||||
this.url = url;
|
||||
this.style = 5;
|
||||
this.custom_id = undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
setOptions(options) {
|
||||
this.options = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
setValue(value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
setPlaceholder(placeholder) {
|
||||
this.placeholder = placeholder;
|
||||
return this;
|
||||
}
|
||||
|
||||
setMinValues(min_values) {
|
||||
this.min_values = min_values;
|
||||
return this;
|
||||
}
|
||||
|
||||
setMaxValues(max_values) {
|
||||
this.max_values = max_values;
|
||||
return this;
|
||||
}
|
||||
|
||||
setMinLength(min_values) {
|
||||
this.min_length = min_values;
|
||||
return this;
|
||||
}
|
||||
|
||||
setMaxLength(max_values) {
|
||||
this.max_length = max_values;
|
||||
return this;
|
||||
}
|
||||
|
||||
setComponents(...components) {
|
||||
this.components = components;
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
if (!this.type) throw new Error("Component must have a type");
|
||||
const json = {
|
||||
type: this.type,
|
||||
};
|
||||
if (this.type === 1) {
|
||||
json.components = this.components;
|
||||
}
|
||||
|
||||
if (this.type === 2) {
|
||||
json.customId = this.custom_id;
|
||||
json.style = this.style;
|
||||
json.label = this.label;
|
||||
json.emoji = this.emoji;
|
||||
json.url = this.url;
|
||||
json.disabled = this.disabled;
|
||||
}
|
||||
|
||||
if (this.type === 3) {
|
||||
json.customId = this.custom_id;
|
||||
json.options = this.options;
|
||||
json.placeholder = this.placeholder;
|
||||
json.minValues = this.min_values;
|
||||
json.maxValues = this.max_values;
|
||||
json.disabled = this.disabled;
|
||||
}
|
||||
|
||||
if (this.type === 4) {
|
||||
json.customId = this.custom_id;
|
||||
json.style = this.style;
|
||||
json.label = this.label;
|
||||
json.minLength = this.min_length;
|
||||
json.maxLength = this.max_length;
|
||||
json.required = this.required;
|
||||
json.value = this.value;
|
||||
json.placeholder = this.placeholder;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
||||
module.exports = Component;
|
||||
16
template/nodejs/Structures/DestructObject.js
Normal file
16
template/nodejs/Structures/DestructObject.js
Normal file
@@ -0,0 +1,16 @@
|
||||
class DestructObject {
|
||||
constructor(message = {}) {
|
||||
this.destructObject(message);
|
||||
}
|
||||
destructObject(message) {
|
||||
for (let [key, value] of Object.entries(message)) {
|
||||
this[key] = value;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
module.exports = DestructObject;
|
||||
99
template/nodejs/Structures/Embed.js
Normal file
99
template/nodejs/Structures/Embed.js
Normal file
@@ -0,0 +1,99 @@
|
||||
class Embed {
|
||||
constructor(options = {}) {
|
||||
this.title = options.title;
|
||||
this.description = options.description;
|
||||
this.fields = options.fields;
|
||||
this.thumbnail = options.thumbnail;
|
||||
this.image = options.image;
|
||||
this.author = options.author;
|
||||
this.color = options.color;
|
||||
this.timestamp = options.timestamp;
|
||||
this.footer = options.footer;
|
||||
this.url = options.url;
|
||||
this.fields = options.fields ?? [];
|
||||
}
|
||||
setTitle(title) {
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
setDescription(description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
setThumbnail(thumbnail) {
|
||||
this.thumbnail = thumbnail;
|
||||
return this;
|
||||
}
|
||||
|
||||
setImage(image) {
|
||||
this.image = image;
|
||||
return this;
|
||||
}
|
||||
|
||||
setAuthor(author) {
|
||||
if (typeof author !== "object") throw new Error("Author must be an object");
|
||||
this.author = author;
|
||||
return this;
|
||||
}
|
||||
|
||||
setColor(color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
setTimestamp(timestamp) {
|
||||
this.timestamp = timestamp ?? Date.now();
|
||||
return this;
|
||||
}
|
||||
|
||||
setFooter(footer) {
|
||||
if (typeof footer !== "object") throw new Error("Footer must be an object");
|
||||
this.footer = footer;
|
||||
return this;
|
||||
}
|
||||
|
||||
setURL(url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
addField(field) {
|
||||
this.fields.push(field);
|
||||
return this;
|
||||
}
|
||||
|
||||
addFields(...fields) {
|
||||
fields.map((x) => this.addField(x));
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
title: this.title,
|
||||
type: "rich",
|
||||
description: this.description,
|
||||
color: this.color,
|
||||
timestamp: this.timestamp ? new Date(this.timestamp).toISOString() : null,
|
||||
thumbnail: this.thumbnail,
|
||||
image: this.image,
|
||||
fields: this.fields,
|
||||
url: this.url,
|
||||
author: this.author
|
||||
? {
|
||||
name: this.author.name,
|
||||
url: this.author.url,
|
||||
iconUrl: this.author.icon_url || this.author.iconUrl,
|
||||
}
|
||||
: null,
|
||||
footer: this.footer
|
||||
? {
|
||||
text: this.footer.text,
|
||||
iconUrl: this.footer.icon_url || this.footer.iconUrl,
|
||||
}
|
||||
: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
module.exports = Embed;
|
||||
18
template/nodejs/Structures/Guild.js
Normal file
18
template/nodejs/Structures/Guild.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const DestructObject = require("./DestructObject");
|
||||
|
||||
const RoleManager = require("../Managers/RoleManager");
|
||||
const MemberManager = require("../Managers/MemberManager");
|
||||
const ChannelManager = require("../Managers/ChannelManager");
|
||||
|
||||
class Guild extends DestructObject {
|
||||
constructor(client, guild = {}) {
|
||||
super(guild);
|
||||
this.client = client;
|
||||
|
||||
//Managers:
|
||||
this.roles = new RoleManager(client, {}, { guild: this });
|
||||
this.members = new MemberManager(client, {}, { guild: this });
|
||||
this.channels = new ChannelManager(client, {}, { guild: this });
|
||||
}
|
||||
}
|
||||
module.exports = Guild;
|
||||
116
template/nodejs/Structures/Interaction.js
Normal file
116
template/nodejs/Structures/Interaction.js
Normal file
@@ -0,0 +1,116 @@
|
||||
const DestructObject = require("./DestructObject");
|
||||
const Guild = require("./Guild");
|
||||
const Channel = require("./Channel");
|
||||
const Constants = {
|
||||
DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE: 5,
|
||||
CHANNEL_MESSAGE_WITH_SOURCE: 4,
|
||||
DEFERRED_UPDATE_MESSAGE: 6,
|
||||
UPDATE_MESSAGE: 7,
|
||||
APPLICATION_COMMAND_AUTOCOMPLETE_RESULT: 8,
|
||||
MODAL: 9,
|
||||
FLAGS: { EPHEMERAL: 64 },
|
||||
INTERACTION_TYPES: {
|
||||
CHAT_INPUT: 1,
|
||||
APPLICATION_COMMAND: 2,
|
||||
CONTEXT_MENU: 2,
|
||||
MESSAGE_COMPONENT: 3,
|
||||
APPLICATION_COMMAND_AUTOCOMPLETE: 4,
|
||||
},
|
||||
};
|
||||
class Interaction extends DestructObject {
|
||||
constructor(client, interaction = {}) {
|
||||
super(interaction);
|
||||
this.raw = interaction;
|
||||
this.client = client;
|
||||
|
||||
this.guild = new Guild(client, { id: this.guild_id || this.guildId });
|
||||
this.channel = new Channel(client, { id: this.channel_id || this.channelId }, {
|
||||
internal: true,
|
||||
guild: this.guild,
|
||||
});
|
||||
}
|
||||
|
||||
isCommand() {
|
||||
return this.type === Constants.INTERACTION_TYPES.APPLICATION_COMMAND;
|
||||
}
|
||||
|
||||
// @todo check Context Menu type and Component Type
|
||||
isChatInputCommand() {
|
||||
return this.type === Constants.INTERACTION_TYPES.CHAT_INPUT;
|
||||
}
|
||||
isContextMenuCommand() {
|
||||
return this.isCommand();
|
||||
}
|
||||
isAutoComplete() {
|
||||
return this.type === Constants.INTERACTION_TYPES.APPLICATION_COMMAND_AUTOCOMPLETE;
|
||||
}
|
||||
isMessageComponent() {
|
||||
return this.type === Constants.INTERACTION_TYPES.MESSAGE_COMPONENT;
|
||||
}
|
||||
isSelectMenu() {
|
||||
return this.type === Constants.INTERACTION_TYPES.MESSAGE_COMPONENT;
|
||||
}
|
||||
isButton() {
|
||||
return this.type === Constants.INTERACTION_TYPES.MESSAGE_COMPONENT;
|
||||
}
|
||||
|
||||
async deferReply(options = {}) {
|
||||
if (this.deferred || this.replied) throw new Error("Interaction has been already replied");
|
||||
const Payload = { data: {}, type: Constants.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE };
|
||||
options.type = 5;
|
||||
if (this.ephemeral) options.private = true;
|
||||
this.ephemeral = options.ephemeral || false;
|
||||
this.deferred = true;
|
||||
return this.client.helpers.sendInteractionResponse(this.id, this.token, options);
|
||||
}
|
||||
|
||||
async deferUpdate(options = {}) {
|
||||
if (this.deferred || this.replied) throw new Error("Interaction has been already replied");
|
||||
this.deferred = true;
|
||||
const Payload = { data: options, type: Constants.DEFERRED_UPDATE_MESSAGE };
|
||||
return this.client.helpers.sendInteractionResponse(this.id, this.token, Payload);
|
||||
}
|
||||
|
||||
async reply(options = {}) {
|
||||
if (this.deferred || this.replied) throw new Error("Interaction has been already replied");
|
||||
this.ephemeral = options.ephemeral || false;
|
||||
if (this.ephemeral) options.private = true;
|
||||
this.replied = true;
|
||||
const Payload = { data: options, type: Constants.CHANNEL_MESSAGE_WITH_SOURCE };
|
||||
return this.client.helpers.sendInteractionResponse(this.id, this.token, Payload);
|
||||
}
|
||||
|
||||
async popupModal(options = {}) {
|
||||
if (this.deferred || this.replied) throw new Error("Interaction has been already replied");
|
||||
const Payload = { data: options, type: Constants.MODAL };
|
||||
this.replied = true;
|
||||
return this.client.helpers.sendInteractionResponse(this.id, this.token, Payload);
|
||||
}
|
||||
|
||||
async editReply(options = {}) {
|
||||
if (!this.deferred && !this.replied) throw new Error("Interaction has not been replied");
|
||||
this.replied = true;
|
||||
const messageId = this.messageId ? this.messageId : options.messageId;
|
||||
return this.client.helpers.editInteractionResponse(this.token, options);
|
||||
}
|
||||
|
||||
async deleteReply(options = {}) {
|
||||
if (this.ephemeral) throw new Error("Ephemeral messages cannot be deleted");
|
||||
const messageId = this.messageId ? this.messageId : options.messageId;
|
||||
return this.client.helpers.deleteInteractionResponse(this.token, messageId);
|
||||
}
|
||||
|
||||
async followUp(options = {}) {
|
||||
if (!this.replied || !this.deferred) throw new Error("Interaction has not been replied");
|
||||
const Payload = { data: options, type: Constants.CHANNEL_MESSAGE_WITH_SOURCE };
|
||||
return this.client.helpers.sendInteractionResponse(this.id, this.token, Payload);
|
||||
}
|
||||
|
||||
async update(options = {}) {
|
||||
if (this.deferred || this.replied) throw new Error("Interaction has been already replied");
|
||||
const Payload = { data: options, type: Constants.UPDATE_MESSAGE };
|
||||
this.replied = true;
|
||||
return this.client.helpers.sendInteractionResponse(this.id, this.token, Payload);
|
||||
}
|
||||
}
|
||||
module.exports = Interaction;
|
||||
16
template/nodejs/Structures/Member.js
Normal file
16
template/nodejs/Structures/Member.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const DestructObject = require("./DestructObject");
|
||||
const Guild = require("./Guild");
|
||||
const RoleManager = require("../Managers/RoleManager");
|
||||
|
||||
class Member extends DestructObject {
|
||||
constructor(client, member = {}, options = {}) {
|
||||
super(member);
|
||||
this.client = client;
|
||||
|
||||
if (options.guild) this.guild = options.guild;
|
||||
else if (member.guildId) this.guild = new Guild(client, { id: member.guildId });
|
||||
|
||||
this.roles = new RoleManager(client, {}, { guild: this.guild, member: this });
|
||||
}
|
||||
}
|
||||
module.exports = Member;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user