more fixes

This commit is contained in:
Skillz4Killz
2021-11-10 20:26:23 +00:00
committed by GitHub
parent e0955df780
commit e3539934db
17 changed files with 101 additions and 13 deletions

View File

@@ -91,6 +91,7 @@ import { transformWebhook } from "./transformers/webhook.ts";
import { transformAuditlogEntry } from "./transformers/auditlogEntry.ts";
import { transformApplicationCommandPermission } from "./transformers/applicationCommandPermission.ts";
import { StatusUpdate } from "./types/gateway/status_update.ts";
import { calculateBits, calculatePermissions } from "./util/permissions.ts";
type CacheOptions =
| {
@@ -307,6 +308,8 @@ export function createUtils(options: Partial<HelperUtils>) {
urlToBase64,
formatImageURL,
validateSlashCommands,
calculateBits,
calculatePermissions,
};
}
@@ -325,6 +328,8 @@ export interface HelperUtils {
urlToBase64: typeof urlToBase64;
formatImageURL: typeof formatImageURL;
validateSlashCommands: typeof validateSlashCommands;
calculateBits: typeof calculateBits;
calculatePermissions: typeof calculatePermissions;
}
export function createGatewayManager(

View File

@@ -1,6 +1,7 @@
import type { ApplicationCommand } from "../../../types/interactions/commands/application_command.ts";
import type { CreateGlobalApplicationCommand } from "../../../types/interactions/commands/create_global_application_command.ts";
import type { Bot } from "../../../bot.ts";
import { ApplicationCommandOption } from "../../../types/interactions/commands/application_command_option.ts";
/**
* There are two kinds of Slash Commands: global commands and guild commands. Global commands are available for every guild that adds your app; guild commands are specific to the guild you specify when making them. Command names are unique per application within each scope (global and guild). That means:
@@ -22,6 +23,24 @@ export async function createSlashCommand(bot: Bot, options: CreateGlobalApplicat
guildId
? bot.constants.endpoints.COMMANDS_GUILD(bot.applicationId, guildId)
: bot.constants.endpoints.COMMANDS(bot.applicationId),
options
{
name: options.name,
description: options.description,
type: options.type,
options: options.options ? makeOptionsForCommand(options.options) : undefined,
}
);
}
// @ts-ignore TODO: see if we can make this not circular
export function makeOptionsForCommand(options: ApplicationCommandOption[]) {
return options.map((option) => ({
type: option.type,
name: option.name,
description: option.description,
required: option.required,
choices: option.choices,
options: option.options ? makeOptionsForCommand(option.options) : undefined,
channel_types: option.channelTypes,
}));
}

View File

@@ -1,6 +1,7 @@
import type { ApplicationCommand } from "../../../types/interactions/commands/application_command.ts";
import type { EditGlobalApplicationCommand } from "../../../types/interactions/commands/edit_global_application_command.ts";
import type { Bot } from "../../../bot.ts";
import { makeOptionsForCommand } from "./create_slash_command.ts";
/**
* Edit an existing slash command. If this command did not exist, it will create it.
@@ -19,6 +20,11 @@ export async function upsertSlashCommand(
guildId
? bot.constants.endpoints.COMMANDS_GUILD_ID(bot.applicationId, guildId, commandId)
: bot.constants.endpoints.COMMANDS_ID(bot.applicationId, commandId),
options
{
name: options.name,
description: options.description,
type: options.type,
options: options.options ? makeOptionsForCommand(options.options) : undefined,
}
);
}

View File

@@ -1,14 +1,16 @@
import type { Bot } from "../../bot.ts";
/** Edit the nickname of the bot in this guild */
export async function editBotNickname(bot: Bot, guildId: bigint, nickname: string | null) {
export async function editBotNickname(
bot: Bot,
guildId: bigint,
options: { nick: string | null; reason?: string }
) {
const response = await bot.rest.runMethod<{ nick: string }>(
bot.rest,
"patch",
bot.constants.endpoints.USER_NICK(guildId),
{
nick: nickname,
}
options
);
return response.nick;

View File

@@ -56,6 +56,7 @@ export function transformMember(
mute: payload.mute,
pending: payload.pending,
cachedAt: Date.now(),
avatar: payload.avatar ? bot.utils.iconHashToBigInt(payload.avatar) : undefined,
};
}
@@ -80,4 +81,6 @@ export interface DiscordenoMember {
mute?: boolean;
/** Whether or not this member is pending in server verification. */
pending?: boolean;
/** The members avatar for this server. */
avatar?: bigint;
}

View File

@@ -27,10 +27,12 @@ export function transformRole(
? bot.transformers.snowflake(payload.role.tags.integration_id)
: undefined,
permissions: bot.transformers.snowflake(payload.role.permissions),
icon: payload.role.icon ? bot.utils.iconHashToBigInt(payload.role.icon) : undefined,
unicodeEmoji: payload.role.unicode_emoji,
};
}
export interface DiscordenoRole extends Omit<Role, "tags" | "id" | "permissions" | "hoist" | "mentionable" | "managed"> {
export interface DiscordenoRole extends Omit<Role, "tags" | "id" | "permissions" | "hoist" | "mentionable" | "managed" | "icon"> {
/** The role id */
id: bigint;
/** The bot id that is associated with this role. */
@@ -43,4 +45,8 @@ export interface DiscordenoRole extends Omit<Role, "tags" | "id" | "permissions"
permissions: bigint;
/** Holds all the boolean toggles. */
bitfield: bigint;
/** The role icon emoji icon */
icon?: bigint;
/** The role icon emoji unicode */
unicodeEmoji?: string;
}

View File

@@ -70,6 +70,7 @@ export enum DiscordJsonErrorCodes {
MaximumNumberOfBansFetchesHasBeenReached = 30037,
MaximumNumberOfStickersReached = 30039,
MaximumNumberOfPruneRequestsHasBeenReachedTryAgainLater,
MaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReachedTryAgainLater = 30042,
UnauthorizedProvideAValidTokenAndTryAgain = 40001,
YouNeedToVerifyYourAccountInOrderToPerformThisAction,
YouAreOpeningDirectMessagesTooFast,

View File

@@ -11,6 +11,8 @@ export interface CreateGuildRole {
hoist?: boolean;
/** Whether the role should be mentionable, default: false */
mentionable?: boolean;
/** The role's unicode emoji (if the guild has the `ROLE_ICONS` feature) */
unicodeEmoji?: string;
}
/** https://discord.com/developers/docs/resources/guild#create-guild-role */

View File

@@ -38,9 +38,14 @@ export enum DiscordGuildFeatures {
MonetizationEnabled = "MONETIZATION_ENABLED",
/** Guild has increased custom sticker slots */
MoreStickers = "MORE_STICKERS",
/** Guild has access to the three day archive time for threads */
ThreeDayThreadArchive = "THREE_DAY_THREAD_ARCHIVE",
/** Guild has access to the seven day archive time for threads */
SevenDayThreadArchive = "SEVEN_DAY_THREAD_ARCHIVE",
/** Guild has access to create private threads */
PrivateThreads = "PRIVATE_THREADS",
/** Guild is able to set role icons */
RoleIcons = "ROLE_ICONS",
}
export type GuildFeatures = DiscordGuildFeatures;

View File

@@ -19,4 +19,6 @@ export interface ApplicationCommand {
defaultPermission?: boolean;
/** The type of command. By default this is a slash command(ChatInput). */
type?: ApplicationCommandTypes;
/** Autoincrementing version identifier updated during substantial record changes */
version: string;
}

View File

@@ -1,3 +1,4 @@
import { ChannelTypes } from "../../channels/channel_types.ts";
import { ApplicationCommandOptionChoice } from "./application_command_option_choice.ts";
import { DiscordApplicationCommandOptionTypes } from "./application_command_option_types.ts";
@@ -15,4 +16,6 @@ export interface ApplicationCommandOption {
choices?: ApplicationCommandOptionChoice[];
/** If the option is a subcommand or subcommand group type, this nested options will be the parameters */
options?: ApplicationCommandOption[];
/** If the option is a channel type, the channels shown will be restricted to these types */
channelTypes?: ChannelTypes[];
}

View File

@@ -18,6 +18,8 @@ export interface GuildMember {
mute?: boolean;
/** Whether the user has not yet passed the guild's Membership Screening requirements */
pending?: boolean;
/** The members custom avatar for this server. */
avatar?: string;
}
// We use these types much since user always exists unless its a `CREATE_MESSAGE` or `MESSAGE_UPDATE` event

View File

@@ -16,4 +16,6 @@ export interface Attachment {
height?: number | null;
/** Width of file (if image) */
width?: number | null;
/** Whether this attachment is ephemeral */
ephemeral?: boolean;
}

View File

@@ -22,7 +22,7 @@ export enum DiscordBitwisePermissionFlags {
STREAM = 0x00000200,
/** Allows guild members to view a channel, which includes reading messages in text channels */
VIEW_CHANNEL = 0x00000400,
/** Allows for sending messages in a channel */
/** Allows for sending messages in a channel. (does not allow sending messages in threads) */
SEND_MESSAGES = 0x00000800,
/** Allows for sending of /tts messages */
SEND_TTS_MESSAGES = 0x00001000,
@@ -68,12 +68,16 @@ export enum DiscordBitwisePermissionFlags {
REQUEST_TO_SPEAK = 0x0100000000,
/** Allows for deleting and archiving threads, and viewing all private threads */
MANAGE_THREADS = 0x0400000000,
/** Allows for creating and participating in threads */
USE_PUBLIC_THREADS = 0x0800000000,
/** Allows for creating and participating in private threads */
USE_PRIVATE_THREADS = 0x1000000000,
/** Allows for creating threads */
CREATE_PUBLIC_THREADS = 0x0800000000,
/** Allows for creating private threads */
CREATE_PRIVATE_THREADS = 0x1000000000,
/** Allows the usage of custom stickers from other servers */
USE_EXTERNAL_STICKERS = 0x2000000000,
/** Allows for sending messages in threads */
SEND_MESSAGES_IN_THREADS = 0x4000000000,
/** Allows for launching activities (applications with the `EMBEDDED` flag) in a voice channel. */
START_EMBEDDED_ACTIVITIES = 0x8000000000,
}
export type BitwisePermissions = DiscordBitwisePermissionFlags;

View File

@@ -20,4 +20,8 @@ export interface Role {
mentionable: boolean;
/** The tags this role has */
tags?: RoleTags;
/** role unicode emoji */
unicodeEmoji?: string;
/** the role emoji hash */
icon?: string;
}

View File

@@ -150,7 +150,7 @@ export const endpoints = {
USER_DEFAULT_AVATAR: (icon: number) => `${baseEndpoints.CDN_URL}/embed/avatars/${icon}.png`,
USER_DM: `${baseEndpoints.BASE_URL}/users/@me/channels`,
USER_CONNECTIONS: `${baseEndpoints.BASE_URL}/users/@me/connections`,
USER_NICK: (guildId: bigint) => `${GUILDS_BASE(guildId)}/members/@me/nick`,
USER_NICK: (guildId: bigint) => `${GUILDS_BASE(guildId)}/members/@me`,
// Discovery Endpoints
DISCOVERY_CATEGORIES: `${baseEndpoints.BASE_URL}/discovery/categories`,

22
src/util/permissions.ts Normal file
View File

@@ -0,0 +1,22 @@
import { DiscordBitwisePermissionFlags } from "../types/permissions/bitwise_permission_flags.ts";
import { PermissionStrings } from "../types/permissions/permission_strings.ts";
/** This function converts a bitwise string to permission strings */
export function calculatePermissions(permissionBits: bigint) {
return Object.keys(DiscordBitwisePermissionFlags).filter((permission) => {
// Since Object.keys() not only returns the permission names but also the bit values we need to return false if it is a Number
if (Number(permission)) return false;
// Check if permissionBits has this permission
return permissionBits & BigInt(DiscordBitwisePermissionFlags[permission as PermissionStrings]);
}) as PermissionStrings[];
}
/** This function converts an array of permissions into the bitwise string. */
export function calculateBits(permissions: PermissionStrings[]) {
return permissions
.reduce((bits, perm) => {
bits |= BigInt(DiscordBitwisePermissionFlags[perm]);
return bits;
}, 0n)
.toString();
}