Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ApplicationCommands): allow managing commands for uncached guilds #5729

Merged
merged 3 commits into from Jun 11, 2021

Conversation

ckohen
Copy link
Member

@ckohen ckohen commented Jun 2, 2021

Please describe the changes this PR makes and why it should be merged:

The way the library currently handles global and guild application commands is via a manager that exists on the application or guild respectively. This poses a problem for applications that have guilds authorized only with applications.commands as the guild is not cached and therefore does not have a guild application command manager.

This PR addresses this issue by allowing the global application command manger to take guildID in all of its methods. It also moves the permissions methods from GuildApplicationCommandManager to ApplicationCommandManager for the same reason.

It also introduces a new typedef that will be used in an upcoming PR for more consistency in managers. 🚀

  • Application Commands fetched from ApplicationCommandManager never have guild even when they are guild commands. I haven't been able to come up with a super good way to document this, suggestions welcome.

Status and versioning classification:

  • Code changes have been tested against the Discord API, or there are no code changes
  • I know how to update typings and have done so, or typings don't need updating
  • This PR changes the library's interface (methods or parameters added)
  • This PR includes breaking changes (methods removed or renamed, parameters moved or removed)

/**
* Fetches the permissions for one or multiple commands.
* <warn>When calling this on ApplicationCommandManager, guildID is required.
* To fetch all permissions for an uncached guild use `fetchPermissions(undefined, '123456789012345678')`</warn>
Copy link
Member Author

@ckohen ckohen Jun 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to make a note here about passing undefined. I don't love this pattern, but as Monbrey said in the discord, I don't love having to pass { command: '123456789012345678' } either.

Copy link
Member

@monbrey monbrey Jun 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the guild ID is the required one, put it first?

fetchPermissions(guild)
fetchPermissions(guild, command)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when called from a GuildApplicationCommandManager its not required, although I suppose I could just use super in that class.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I tried to do this, and it simply doesn't work as wanted.
Putting guildID as the first parameter means implementing fetchPermissions and setPermissions in GuildApplicationCommandManager which we can do in js, but because guildID is not a parameter there, typescript really doesn't like it, suggesting this is a bad pattern in general.

Copy link
Member Author

@ckohen ckohen Jun 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any other suggestions for this (or a suggestion for how to make typescript happy with different method signatures 😆 )?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

override still doesn't let you remove / repurpose parameters in the signature though from what I can tell.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not nice, but you could allow either just a command resolvable, or an object with it and the guild.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is precedent for this elsewhere in the library actulaly, so it works, will do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A CommandResolvable can't be accepted as the only parameter because this.resolve (when providing an id) can't resolve guild application commands, which are required when not passing guildID so that we can get command.guild.id instead. And typescript will complain if I try to make it ApplicationCommand | { guildID: Snowflake | command?: ApplciationCommandResolvable } and then override that to ApplicationCommandResolvable in the subclass

Copy link

@zakuciael zakuciael Jun 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excuse a stranger, but if I've understood correctly the goal here is to somehow put the guildId parameter to the fetchPermissions method (possibly to more methods) and at the same time satisfy the TypeScript compiler in the GuildApplicationCommandManager, right?

So I've created a small "demo" of my approach on the TS Playground here and with this solution you can pass all combinations: no params, only command and guild id + previous combinations. I've based it on the @SpaceEEC suggestion to put either a resolvable or an object with guildId and the command.

Note: The GuildApplicationCommandResolvable type can be simplified to this (see below) by doing that the usage of the Optional<T> type can be avoided.

type GuildApplicationCommandResolvable = { guildId: Snowflake, command?: ApplicationCommandResolvable }

(I know that I wrote it entirely in TypeScript, and it may or may not be 100% applicable but maybe at the very least it will notch you guys in the right direction, hope I've helped)

src/managers/ApplicationCommandManager.js Outdated Show resolved Hide resolved
src/managers/ApplicationCommandManager.js Outdated Show resolved Hide resolved
src/managers/ApplicationCommandManager.js Outdated Show resolved Hide resolved
src/managers/ApplicationCommandManager.js Outdated Show resolved Hide resolved
src/managers/ApplicationCommandManager.js Outdated Show resolved Hide resolved
@iCrawl
Copy link
Member

iCrawl commented Jun 3, 2021

This needs a rebase.

@iCrawl iCrawl requested a review from kyranet June 6, 2021 18:51
Copy link
Member

@SpaceEEC SpaceEEC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM

src/managers/ApplicationCommandManager.js Outdated Show resolved Hide resolved
src/managers/ApplicationCommandManager.js Outdated Show resolved Hide resolved
src/structures/ApplicationCommand.js Outdated Show resolved Hide resolved
src/structures/ApplicationCommand.js Outdated Show resolved Hide resolved
@iCrawl
Copy link
Member

iCrawl commented Jun 9, 2021

This needs a rebase on top of the changes requested.

docs: fixes typedef for GuildApplicationCommandPermissionData
@iCrawl iCrawl merged commit 24e5868 into discordjs:master Jun 11, 2021
@iCrawl iCrawl added this to the Version 13 milestone Jun 27, 2021
@ckohen ckohen deleted the uncached-guild-commands branch June 30, 2021 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants