buttons buttons and more buttons

This commit is contained in:
Skillz
2021-05-01 08:16:28 -04:00
parent b0ce5c2e56
commit 6de8e1d428
28 changed files with 235 additions and 63 deletions
+11 -2
View File
@@ -1,3 +1,4 @@
import { cacheHandlers } from "../../cache.ts";
import { rest } from "../../rest/rest.ts";
import { structures } from "../../structures/mod.ts";
import { Guild } from "../../types/guilds/guild.ts";
@@ -5,6 +6,7 @@ import { ModifyGuild } from "../../types/guilds/modify_guild.ts";
import { endpoints } from "../../util/constants.ts";
import { requireBotGuildPermissions } from "../../util/permissions.ts";
import { urlToBase64 } from "../../util/utils.ts";
import { ws } from "../../ws/ws.ts";
/** Modify a guilds settings. Requires the MANAGE_GUILD permission. */
export async function editGuild(guildId: string, options: ModifyGuild) {
@@ -28,6 +30,13 @@ export async function editGuild(guildId: string, options: ModifyGuild) {
options,
);
// TODO: use ws.botGatewayData to calculate the shard ID
return structures.createDiscordenoGuild(result, -1);
const cached = await cacheHandlers.get("guilds", guildId);
return structures.createDiscordenoGuild(
result,
cached?.shardId ||
Number(
(BigInt(result.id) >> 22n % BigInt(ws.botGatewayData.shards))
.toString(),
),
);
}
+2 -2
View File
@@ -1,5 +1,6 @@
import { cacheHandlers } from "../../cache.ts";
import { rest } from "../../rest/rest.ts";
import { GuildWidgetDetails } from "../../types/guilds/guild_widget_details.ts";
import { Errors } from "../../types/misc/errors.ts";
import { endpoints } from "../../util/constants.ts";
@@ -11,6 +12,5 @@ export async function getWidget(guildId: string, options?: { force: boolean }) {
if (!guild?.widgetEnabled) throw new Error(Errors.GUILD_WIDGET_NOT_ENABLED);
}
// TODO: add return type
return await rest.runMethod("get", `${endpoints.GUILD_WIDGET(guildId)}.json`);
return await rest.runMethod("get", `${endpoints.GUILD_WIDGET(guildId)}.json`) as GuildWidgetDetails;
}
+8 -2
View File
@@ -1,6 +1,7 @@
import { rest } from "../../rest/rest.ts";
import { CreateChannelInvite } from "../../types/invites/create_channel_invite.ts";
import { Invite } from "../../types/mod.ts";
import { Invite } from "../../types/invites/invite.ts";
import { Errors } from "../../types/misc/errors.ts";
import { endpoints } from "../../util/constants.ts";
import { requireBotChannelPermissions } from "../../util/permissions.ts";
@@ -11,7 +12,12 @@ export async function createInvite(
) {
await requireBotChannelPermissions(channelId, ["CREATE_INSTANT_INVITE"]);
// TODO: add proper options validation
if (options.maxAge && (options.maxAge < 0 || options.maxAge > 604800)) {
throw new Error(Errors.INVITE_MAX_AGE_INVALID);
}
if (options.maxUses && (options.maxUses < 0 || options.maxUses > 100)) {
throw new Error(Errors.INVITE_MAX_USES_INVALID);
}
return await rest.runMethod<Invite>(
"post",
+2 -2
View File
@@ -1,9 +1,9 @@
import { identifyPayload } from "../../bot.ts";
import { DiscordenoMember } from "../../structures/member.ts";
import { DiscordGatewayIntents } from "../../types/gateway/gateway_intents.ts";
import { RequestGuildMembers } from "../../types/guilds/request_guild_members.ts";
import { Errors } from "../../types/misc/errors.ts";
import { Collection } from "../../util/collection.ts";
import { ws } from "../../ws/ws.ts";
/**
* ⚠️ BEGINNER DEVS!! YOU SHOULD ALMOST NEVER NEED THIS AND YOU CAN GET FROM cache.members.get()
@@ -21,7 +21,7 @@ export function fetchMembers(
// You can request 1 member without the intent
if (
(!options?.limit || options.limit > 1) &&
!(identifyPayload.intents && DiscordGatewayIntents.GUILD_MEMBERS)
!(ws.identifyPayload.intents && DiscordGatewayIntents.GUILD_MEMBERS)
) {
throw new Error(Errors.MISSING_INTENT_GUILD_MEMBERS);
}
+3 -2
View File
@@ -1,4 +1,4 @@
import { eventHandlers, identifyPayload } from "../../bot.ts";
import { eventHandlers } from "../../bot.ts";
import { cacheHandlers } from "../../cache.ts";
import { rest } from "../../rest/rest.ts";
import { DiscordenoMember } from "../../structures/member.ts";
@@ -9,6 +9,7 @@ import { ListGuildMembers } from "../../types/guilds/list_guild_members.ts";
import { Errors } from "../../types/misc/errors.ts";
import { Collection } from "../../util/collection.ts";
import { endpoints } from "../../util/constants.ts";
import { ws } from "../../ws/ws.ts";
/**
* ⚠️ BEGINNER DEVS!! YOU SHOULD ALMOST NEVER NEED THIS AND YOU CAN GET FROM cache.members.get()
@@ -19,7 +20,7 @@ import { endpoints } from "../../util/constants.ts";
* GW(fetchMembers): 120/m(PER shard) rate limit. Meaning if you have 8 shards your limit is 960/m.
*/
export async function getMembers(guildId: string, options?: ListGuildMembers) {
if (!(identifyPayload.intents && DiscordGatewayIntents.GUILD_MEMBERS)) {
if (!(ws.identifyPayload.intents && DiscordGatewayIntents.GUILD_MEMBERS)) {
throw new Error(Errors.MISSING_INTENT_GUILD_MEMBERS);
}
+57
View File
@@ -3,6 +3,7 @@ import { rest } from "../../rest/rest.ts";
import { structures } from "../../structures/mod.ts";
import { DiscordChannelTypes } from "../../types/channels/channel_types.ts";
import { DiscordAllowedMentionsTypes } from "../../types/messages/allowed_mentions_types.ts";
import { ButtonStyles } from "../../types/messages/components/button_styles.ts";
import { CreateMessage } from "../../types/messages/create_message.ts";
import { DiscordMessage, Message } from "../../types/messages/message.ts";
import { Errors } from "../../types/misc/errors.ts";
@@ -11,6 +12,8 @@ import { endpoints } from "../../util/constants.ts";
import { requireBotChannelPermissions } from "../../util/permissions.ts";
import { camelKeysToSnakeCase } from "../../util/utils.ts";
import { validateLength } from "../../util/validate_length.ts";
import { isActionRow } from "../type_guards/is_action_row.ts";
import { isButton } from "../type_guards/is_button.ts";
/** Send a message to the channel. Requires SEND_MESSAGES permission. */
export async function sendMessage(
@@ -93,6 +96,60 @@ export async function sendMessage(
}
}
if (content.components?.length) {
let actionRowCounter = 0;
for (const component of content.components) {
// 5 Link buttons can not have a custom_id
if (isButton(component)) {
if (
component.type === ButtonStyles.Link &&
component.customId
) {
throw new Error(Errors.LINK_BUTTON_CANNOT_HAVE_CUSTOM_ID);
}
if (
!component.customId
) {
if (component.type !== ButtonStyles.Link) {
throw new Error(Errors.BUTTON_REQUIRES_CUSTOM_ID);
}
}
if (!validateLength(component.label, { max: 80 })) {
throw new Error(Errors.COMPONENT_LABEL_TOO_BIG);
}
if (
component.customId &&
!validateLength(component.customId, { max: 100 })
) {
throw new Error(Errors.COMPONENT_CUSTOM_ID_TOO_BIG);
}
}
if (!isActionRow(component)) {
continue;
}
actionRowCounter++;
// Max of 5 ActionRows per message
if (actionRowCounter > 5) throw new Error(Errors.TOO_MANY_ACTION_ROWS);
// Max of 5 Buttons (or any component type) within an ActionRow
if (component.components?.length > 5) {
throw new Error(Errors.TOO_MANY_COMPONENTS);
}
}
}
if (
content.nonce &&
!validateLength(content.nonce.toString(), { max: 25 })
) {
throw new Error(Errors.NONCE_TOO_LONG);
}
const result = await rest.runMethod<Message>(
"post",
endpoints.CHANNEL_MESSAGES(channelId),
+8
View File
@@ -0,0 +1,8 @@
import { ActionRow } from "../../types/messages/components/action_row.ts";
import { MessageComponent } from "../../types/messages/components/message_components.ts";
import { MessageComponentTypes } from "../../types/messages/components/message_component_types.ts";
/** A type guard function to tell if it is a action row component */
export function isActionRow(component: MessageComponent): component is ActionRow {
return component.type === MessageComponentTypes.ActionRow
}
+10
View File
@@ -0,0 +1,10 @@
import { ButtonComponent } from "../../types/messages/components/button_component.ts";
import { MessageComponent } from "../../types/messages/components/message_components.ts";
import { MessageComponentTypes } from "../../types/messages/components/message_component_types.ts";
/** A type guard function to tell if it is a button component */
export function isButton(
component: MessageComponent,
): component is ButtonComponent {
return component.type === MessageComponentTypes.Button;
}