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
Customized slash command registration #11843
Comments
Hi, I'd like to grab this one :) |
Hi @lieut-data! , I'm currently working on this issue and I've been reading about plugins and so on to know how is it done, etc. I've also read your proposal and I have a couple of questions about the ticket:
I'm trying to understand the whole picture and the issue before I start coding something. Thank you very much |
Thanks for tackling the effort, @ethervoid! To answer your questions in order:
|
Thank you @lieut-data for your answers :) I have more questions: I've been thinking about the implementation so the idea is the following:
I have two questions about this workflow if it's correct what I'm putting above: First questionI've been thinking about how to store the callbacks functions. I've seen there is a KV object for plugins but it stores byte slices so I can't use it to store the callbacks. I've seen how the commands are stored in a Is there any other data structure that stores plugin objects? Second questionMy second question is about the callback execution. I've added to the But even passing the plugin object I think is not possible because the non-exported methods (lowercase ones if I'm not mistaken) are going to be out of the package scope and the helper is not going to be able to execute them. Am I right? Are you thinking on other approach that I'm not seeing? Thank you very much :) |
Hey @ethervoid! With regards to your first question, it’s not possible to store a callback in the KV store — nor is it necessary. The helper code is part of the compiled binary, and just can just allocate, say, a map, to keep track of all the callbacks. It won’t conflict with other plugins. Consider using With regards to your second question, if you just invoke the callback given by the plugin, it will already contain the receive variable that is the Hope that helps! |
@RajatVaryani has kindly agreed to tackle this issue. Can't assign him in GitHub right now for some reason. |
@lieut-data Now you can. |
@lieut-data Even before staring working on this issue I would like to understand the overall vision for slash commands w.r.t plugins. In the PR raised there were comments raised wanting a full interface like cobra and cobra has lot of features which might or might not be useful. I want to look at the problem from a macroscopic point of view and understand the usecase we are trying to cater to. The reason I am asking is because using cobra for a usecase like ours is going to come with its own set of caveats like proxying data like plugin context and returning |
@RajatVaryani, the primary goal here is to make it much easier for plugin authors to define and implement slash commands. Today, that requires manually parsing the incoming string and rebuilding a lot of functionality that already comes for free with Cobra, e.g. subcommands, positional arguments, and named arguments. You can see how things are done today in other plugins, but ideally we'd set a pattern that would simplify for everyone. I think it's fine to restrict the scope if there are cobra-specific features that wouldn't make sense for a plugin. |
@lieut-data Thank you. Here is an initial design. Please take note of the flaws in current design.
Here is a code snippet: https://gist.github.com/RajatVaryani/a8121661a112b6fc41d5ea13975e724f Thoughts? |
Thanks for sharing the code snipper and design, @RajatVaryani! I'll take a closer look and get you feedback. |
@lieut-data A gentle reminder. |
Thanks, @RajatVaryani! A few thoughts:
|
@lieut-data Thank you for the nudge. I re-looked my approach. I came to the conclusion If we are able to proxy data (arguments) in the cobra command we would find an effective solution. In order to do that I have embedded a Along with it I also had to expose additional helpers methods to get and set the data required in cobra commands. Please note this code snippet only supports a single root command (which will be changed while implementing it) and is thread safe. Code snippet: link |
@lieut-data A gentle reminder. |
@RajatVaryani, thanks again for meeting the entire Toolkit team today and presenting your proposal. Key takeaways from that discussion:
Thanks for driving this improvement! |
@lieut-data Thank you for the opportunity. 😄 I second the team's opinion about serialization being a showstopper. Let me try to find a workaround using your idea. I will also add extraction of positional and named arguments in the proof of concept. |
@lieut-data Just an update. I did not get chance to work on this. I will be working in this week. |
Hi @lieut-data , I have made the changes. To avoid serialization I am making use of Code snippet: link Also I doubt using sync.Map over normal Map as our usecase does not satisfy. 0/5 Thank you. |
Thanks for exploring this space, @RajatVaryani! I'll definitely take a look :) |
A common pattern seen in plugins is to hook into
ExecuteCommand
, splitargs.Command
by fields, and check the first field to match against the desired slash command. There’s a lot of power in the command abstraction, but some of it is overkill for the typical slash command interaction.Let’s extend the plugin helper API (not the RPC API) by adding a
RegisterSlashCommand
helper method to thegithub.com/mattermost/mattermost-server/plugin
package (seeHelpers
andHelpersImpl
) that accepts the usualmodel.Command
along with a callback:The plugin would use
RegisterSlashCommand
inOnActivate
(or anywhere else) and manually proxy theExecuteCommand
to the helpers:The registered callback function should be executed whenever the helpers determined that the trigger in question matched. The
originalArgs
would expose all the original data, but the callback is likely to just use the newslashCommandArgs
that the helpers fill in automatically:This is a modest improvement, but for bonus points, it would be incredible to integrate https://github.com/spf13/cobra into this equation. The plugin would register commands via cobra as usual, and the helpers would proxy the data through cobra’s
SetArgs
andExecute
APIs to trigger the command. Perhaps aRegisterCobraSlashCommand
for this purpose. Challenges here is Cobra’s single-threaded assumption and the potential race between a call toSetArgs
and theExecute
, plus the need to proxy context and potentially return aCommandResponse
.Example of the current pattern: https://github.com/mattermost/mattermost-plugin-github/blob/092af14724e60178ebf16393bf177d9f7dc9ad82/server/command.go#L56 that this helper seeks to improve.
JIRA Ticket: https://mattermost.atlassian.net/browse/MM-16801
If you're interested in this ticket, please comment here and come join our "Contributors" community channel on our daily build server, where you can discuss questions with community members and the Mattermost core team. For technical advice or questions, please join our "Developers" community channel.
New contributors please see our Developer's Guide.
The text was updated successfully, but these errors were encountered: