Skip to content

Commit

Permalink
feat(deps)!: support for djs v14 (#434)
Browse files Browse the repository at this point in the history
* feat(deps): support for djs v14

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jeroen Claassens <support@favware.tech>
Co-authored-by: A. Román <kyradiscord@gmail.com>
Co-authored-by: Hezekiah Hendry <hezekiah.hendry@gmail.com>
Co-authored-by: Kaname <56084970+kaname-png@users.noreply.github.com>
  • Loading branch information
6 people committed Jan 8, 2023
1 parent cd98c48 commit 2e2c3e9
Show file tree
Hide file tree
Showing 23 changed files with 812 additions and 869 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration.yml
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Install Dependencies
run: yarn --immutable
- name: Build test dependencies
run: yarn turbo run build --filter="@sapphire/async-queue" --filter="@sapphire/*utilities" --filter="@sapphire/duration" --filter="@sapphire/fetch" --filter="@sapphire/lexure" --filter="@sapphire/ratelimits" --filter="@sapphire/result" --filter="@sapphire/timer-manager" --filter="@sapphire/stopwatch" --no-deps
run: yarn turbo run build --filter="@sapphire/async-queue" --filter="@sapphire/*utilities" --filter="@sapphire/duration" --filter="@sapphire/fetch" --filter="@sapphire/lexure" --filter="@sapphire/ratelimits" --filter="@sapphire/result" --filter="@sapphire/timer-manager" --filter="@sapphire/stopwatch" --filter="@sapphire/snowflake" --no-deps
- name: Run tests
run: yarn test
- name: Store code coverage report
Expand Down
6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -25,16 +25,16 @@
"@favware/cliff-jumper": "^1.9.0",
"@favware/npm-deprecate": "^1.0.7",
"@favware/rollup-type-bundler": "^2.0.0",
"@sapphire/framework": "^3.2.0",
"@sapphire/framework": "pr-512",
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.18",
"@types/ws": "^8.5.4",
"@typescript-eslint/eslint-plugin": "^5.48.0",
"@typescript-eslint/parser": "^5.48.0",
"@vitest/coverage-c8": "^0.26.3",
"cz-conventional-changelog": "^3.3.0",
"discord-api-types": "^0.33.5",
"discord.js": "^13.12.0",
"discord-api-types": "^0.37.26",
"discord.js": "^14.7.1",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1",
Expand Down
64 changes: 32 additions & 32 deletions packages/decorators/src/djs-decorators.ts
@@ -1,6 +1,6 @@
import { isDMChannel, isGuildBasedChannel } from '@sapphire/discord.js-utilities';
import { UserError } from '@sapphire/framework';
import { Message, PermissionResolvable, Permissions } from 'discord.js';
import { Message, PermissionFlagsBits, PermissionResolvable, PermissionsBitField } from 'discord.js';
import { createFunctionPrecondition, FunctionFallback } from './utils';

export enum DecoratorIdentifiers {
Expand All @@ -10,31 +10,31 @@ export enum DecoratorIdentifiers {
RequiresUserPermissionsMissingPermissions = 'requiresUserPermissionsMissingPermissions'
}

const DMAvailablePermissions = new Permissions(
~new Permissions([
const DMAvailablePermissions = new PermissionsBitField(
~new PermissionsBitField([
//
'ADD_REACTIONS',
'ATTACH_FILES',
'EMBED_LINKS',
'READ_MESSAGE_HISTORY',
'SEND_MESSAGES',
'USE_EXTERNAL_EMOJIS',
'VIEW_CHANNEL'
]).bitfield & Permissions.ALL
PermissionFlagsBits.AddReactions,
PermissionFlagsBits.AttachFiles,
PermissionFlagsBits.EmbedLinks,
PermissionFlagsBits.ReadMessageHistory,
PermissionFlagsBits.SendMessages,
PermissionFlagsBits.UseExternalEmojis,
PermissionFlagsBits.ViewChannel
]).bitfield & PermissionsBitField.All
);

const DMAvailableUserPermissions = new Permissions(
~new Permissions([
'ADD_REACTIONS',
'ATTACH_FILES',
'EMBED_LINKS',
'READ_MESSAGE_HISTORY',
'SEND_MESSAGES',
'USE_EXTERNAL_EMOJIS',
'VIEW_CHANNEL',
'USE_EXTERNAL_STICKERS',
'MENTION_EVERYONE'
]).bitfield & Permissions.ALL
const DMAvailableUserPermissions = new PermissionsBitField(
~new PermissionsBitField([
PermissionFlagsBits.AddReactions,
PermissionFlagsBits.AttachFiles,
PermissionFlagsBits.EmbedLinks,
PermissionFlagsBits.ReadMessageHistory,
PermissionFlagsBits.SendMessages,
PermissionFlagsBits.UseExternalEmojis,
PermissionFlagsBits.ViewChannel,
PermissionFlagsBits.UseExternalStickers,
PermissionFlagsBits.MentionEveryone
]).bitfield & PermissionsBitField.All
);

/**
Expand All @@ -45,15 +45,15 @@ const DMAvailableUserPermissions = new Permissions(
* @example
* ```typescript
* import { ApplyOptions, RequiresClientPermissions } from '@sapphire/decorators';
* import { SubCommandPluginCommand, SubCommandPluginCommandOptions } from '@sapphire/plugin-subcommands';
* import { Subcommand } from '@sapphire/plugin-subcommands';
* import type { Message } from 'discord.js';
*
* (at)ApplyOptions<SubCommandPluginCommandOptions>({
* (at)ApplyOptions<Subcommand.Options>({
* aliases: ['cws'],
* description: 'A basic command with some subcommands',
* subCommands: ['add', 'remove', 'reset', { input: 'show', default: true }]
* })
* export default class extends SubCommandPluginCommand {
* export default class extends Subcommand {
* // Anyone should be able to view the result, but not modify
* public async show(message: Message) {
* return message.channel.send('Showing!');
Expand All @@ -77,7 +77,7 @@ const DMAvailableUserPermissions = new Permissions(
* ```
*/
export const RequiresClientPermissions = (...permissionsResolvable: PermissionResolvable[]): MethodDecorator => {
const resolved = new Permissions(permissionsResolvable);
const resolved = new PermissionsBitField(permissionsResolvable);
const resolvedIncludesServerPermissions = Boolean(resolved.bitfield & DMAvailablePermissions.bitfield);

return createFunctionPrecondition((message: Message) => {
Expand All @@ -89,7 +89,7 @@ export const RequiresClientPermissions = (...permissionsResolvable: PermissionRe
}

if (isGuildBasedChannel(message.channel)) {
const missingPermissions = message.channel.permissionsFor(message.guild!.me!).missing(resolved);
const missingPermissions = message.channel.permissionsFor(message.guild!.members.me!).missing(resolved);

if (missingPermissions.length) {
throw new UserError({
Expand All @@ -114,15 +114,15 @@ export const RequiresClientPermissions = (...permissionsResolvable: PermissionRe
* @example
* ```typescript
* import { ApplyOptions, RequiresUserPermissions } from '@sapphire/decorators';
* import { SubCommandPluginCommand, SubCommandPluginCommandOptions } from '@sapphire/plugin-subcommands';
* import { Subcommand } from '@sapphire/plugin-subcommands';
* import type { Message } from 'discord.js';
*
* (at)ApplyOptions<SubCommandPluginCommandOptions>({
* (at)ApplyOptions<Subcommand.Options>({
* aliases: ['cws'],
* description: 'A basic command with some subcommands',
* subCommands: ['add', 'remove', 'reset', { input: 'show', default: true }]
* })
* export default class extends SubCommandPluginCommand {
* export default class extends Subcommand {
* // Anyone should be able to view the result, but not modify
* public async show(message: Message) {
* return message.channel.send('Showing!');
Expand All @@ -146,7 +146,7 @@ export const RequiresClientPermissions = (...permissionsResolvable: PermissionRe
* ```
*/
export const RequiresUserPermissions = (...permissionsResolvable: PermissionResolvable[]): MethodDecorator => {
const resolved = new Permissions(permissionsResolvable);
const resolved = new PermissionsBitField(permissionsResolvable);
const resolvedIncludesServerPermissions = Boolean(resolved.bitfield & DMAvailableUserPermissions.bitfield);

return createFunctionPrecondition((message: Message) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/decorators/src/piece-decorators.ts
Expand Up @@ -30,7 +30,7 @@ import { createClassDecorator, createProxy } from './utils';
* ```typescript
* import { ApplyOptions } from '@sapphire/decorators';
* import { Listener } from '@sapphire/framework';
* import { GatewayDispatchEvents, GatewayMessageDeleteDispatch } from 'discord-api-types/v9';
* import { GatewayDispatchEvents, GatewayMessageDeleteDispatch } from 'discord.js';
*
* @ApplyOptions<Listener.Options>(({ container }) => ({
* description: 'Handle Raw Message Delete events',
Expand Down
40 changes: 21 additions & 19 deletions packages/decorators/tests/djs/RequiresClientPermissions.test.ts
@@ -1,10 +1,10 @@
import { UserError } from '@sapphire/framework';
import { Message as DJSMessage, PermissionResolvable, Permissions, PermissionString } from 'discord.js';
import { ChannelType, Message as DJSMessage, PermissionFlagsBits, PermissionResolvable, PermissionsBitField, PermissionsString } from 'discord.js';
import diff from 'lodash/difference';
import { DecoratorIdentifiers, RequiresClientPermissions } from '../../src';

interface BitField {
missing(resolvedPermissions: Permissions): PermissionString[];
missing(resolvedPermissions: PermissionsBitField): PermissionsString[];
}

interface Message {
Expand All @@ -13,67 +13,69 @@ interface Message {
permissionsFor(): BitField;
};
guild: {
me: any;
members: any;
};
}

function buildMissing(resolvedPermissions: Permissions, ...givenPermissions: PermissionResolvable[]) {
return diff(resolvedPermissions.toArray(), new Permissions(givenPermissions).toArray());
function buildMissing(resolvedPermissions: PermissionsBitField, ...givenPermissions: PermissionResolvable[]) {
return diff(resolvedPermissions.toArray(), new PermissionsBitField(givenPermissions).toArray());
}

function buildMessage(channelType: DJSMessage['channel']['type'], ...givenPermissions: PermissionResolvable[]): Message {
return {
channel: {
type: channelType,
permissionsFor: () => ({ missing: (resolvedPermissions: Permissions) => buildMissing(resolvedPermissions, givenPermissions) })
permissionsFor: () => ({ missing: (resolvedPermissions: PermissionsBitField) => buildMissing(resolvedPermissions, givenPermissions) })
},
guild: {
me: ''
members: { me: '' }
}
};
}

describe('RequiresClientPermissions', () => {
describe('WITH DM-compatible permissions', () => {
class Test {
@RequiresClientPermissions(['SEND_MESSAGES', 'ATTACH_FILES'])
@RequiresClientPermissions(['SendMessages', 'AttachFiles'])
public getValue(_message: Message) {
return Promise.resolve('Resolved');
}
}

const instance = new Test();

describe('WITH channel === GUILD_TEXT', () => {
describe('WITH channel === GuildTest', () => {
test('GIVEN has permission THEN returns resolved', async () => {
const result = await instance.getValue(buildMessage('GUILD_TEXT', 'SEND_MESSAGES', 'ATTACH_FILES'));
const result = await instance.getValue(
buildMessage(ChannelType.GuildText, PermissionFlagsBits.SendMessages, PermissionFlagsBits.AttachFiles)
);

expect(result).toBe('Resolved');
});

test('GIVEN lacking 1 permission THEN throws UserError', async () => {
const result = instance.getValue(buildMessage('GUILD_TEXT', 'SEND_MESSAGES'));
const result = instance.getValue(buildMessage(ChannelType.GuildText, PermissionFlagsBits.SendMessages));

await expect(result).rejects.toThrowError(
new UserError({
identifier: DecoratorIdentifiers.RequiresClientPermissionsMissingPermissions,
message: `Sorry, but I am not allowed to do that. I am missing the permissions: ATTACH_FILES`,
message: `Sorry, but I am not allowed to do that. I am missing the permissions: AttachFiles`,
context: {
missing: ['ATTACH_FILES']
missing: ['AttachFiles']
}
})
);
});

test('GIVEN lacking 2 permissions THEN throws UserError', async () => {
const result = instance.getValue(buildMessage('GUILD_TEXT'));
const result = instance.getValue(buildMessage(ChannelType.GuildText));

await expect(result).rejects.toThrowError(
new UserError({
identifier: DecoratorIdentifiers.RequiresClientPermissionsMissingPermissions,
message: `Sorry, but I am not allowed to do that. I am missing the permissions: SEND_MESSAGES,ATTACH_FILES`,
message: `Sorry, but I am not allowed to do that. I am missing the permissions: SendMessages,AttachFiles`,
context: {
missing: ['SEND_MESSAGES', 'ATTACH_FILES']
missing: ['SendMessages', 'AttachFiles']
}
})
);
Expand All @@ -82,7 +84,7 @@ describe('RequiresClientPermissions', () => {

describe('WITH channel === DM', () => {
test('GIVEN no additional permissions THEN resolves', async () => {
const result = await instance.getValue(buildMessage('DM'));
const result = await instance.getValue(buildMessage(ChannelType.DM));

expect(result).toBe('Resolved');
});
Expand All @@ -91,7 +93,7 @@ describe('RequiresClientPermissions', () => {

describe('WITH DM-incompatible permissions', () => {
class Test {
@RequiresClientPermissions(['MANAGE_MESSAGES', 'ADD_REACTIONS', 'EMBED_LINKS'])
@RequiresClientPermissions([PermissionFlagsBits.ManageMessages, PermissionFlagsBits.AddReactions, PermissionFlagsBits.EmbedLinks])
public getValue(_message: Message) {
return Promise.resolve('Resolved');
}
Expand All @@ -101,7 +103,7 @@ describe('RequiresClientPermissions', () => {

describe('WITH channel === DM', () => {
test('GIVEN no additional permissions THEN resolves', async () => {
const result = instance.getValue(buildMessage('DM'));
const result = instance.getValue(buildMessage(ChannelType.DM));

await expect(result).rejects.toThrowError(
new UserError({
Expand Down

0 comments on commit 2e2c3e9

Please sign in to comment.