summaryrefslogtreecommitdiffstats
path: root/app/plugin.go
diff options
context:
space:
mode:
authorChris <ccbrown112@gmail.com>2017-12-08 13:55:41 -0600
committerGitHub <noreply@github.com>2017-12-08 13:55:41 -0600
commit4c17bdff1bb871fb31520b7b547f584c53ed854f (patch)
treeedf1e3295d6ff7d67281efc585b2e913b4efda3d /app/plugin.go
parent7ed1177a2b676aa4c93515268642c855cfe57a37 (diff)
downloadchat-4c17bdff1bb871fb31520b7b547f584c53ed854f.tar.gz
chat-4c17bdff1bb871fb31520b7b547f584c53ed854f.tar.bz2
chat-4c17bdff1bb871fb31520b7b547f584c53ed854f.zip
Add plugin slash command support (#7941)
* add plugin slash command support * remove unused string * rebase
Diffstat (limited to 'app/plugin.go')
-rw-r--r--app/plugin.go147
1 files changed, 127 insertions, 20 deletions
diff --git a/app/plugin.go b/app/plugin.go
index f91a2e414..661f6ed5d 100644
--- a/app/plugin.go
+++ b/app/plugin.go
@@ -8,6 +8,7 @@ import (
"context"
"crypto/sha256"
"encoding/base64"
+ "fmt"
"io"
"io/ioutil"
"net/http"
@@ -101,20 +102,28 @@ func (a *App) ActivatePlugins() {
l4g.Info("Activated %v plugin", id)
} else if !pluginState.Enable && active {
- if err := a.PluginEnv.DeactivatePlugin(id); err != nil {
+ if err := a.deactivatePlugin(plugin.Manifest); err != nil {
l4g.Error(err.Error())
- continue
}
+ }
+ }
+}
- if plugin.Manifest.HasClient() {
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PLUGIN_DEACTIVATED, "", "", "", nil)
- message.Add("manifest", plugin.Manifest.ClientManifest())
- a.Publish(message)
- }
+func (a *App) deactivatePlugin(manifest *model.Manifest) *model.AppError {
+ if err := a.PluginEnv.DeactivatePlugin(manifest.Id); err != nil {
+ return model.NewAppError("removePlugin", "app.plugin.deactivate.app_error", nil, err.Error(), http.StatusBadRequest)
+ }
- l4g.Info("Deactivated %v plugin", id)
- }
+ a.UnregisterPluginCommands(manifest.Id)
+
+ if manifest.HasClient() {
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PLUGIN_DEACTIVATED, "", "", "", nil)
+ message.Add("manifest", manifest.ClientManifest())
+ a.Publish(message)
}
+
+ l4g.Info("Deactivated %v plugin", manifest.Id)
+ return nil
}
// InstallPlugin unpacks and installs a plugin but does not activate it.
@@ -253,15 +262,9 @@ func (a *App) removePlugin(id string, allowPrepackaged bool) *model.AppError {
}
if a.PluginEnv.IsPluginActive(id) {
- err := a.PluginEnv.DeactivatePlugin(id)
+ err := a.deactivatePlugin(manifest)
if err != nil {
- return model.NewAppError("removePlugin", "app.plugin.deactivate.app_error", nil, err.Error(), http.StatusBadRequest)
- }
-
- if manifest.HasClient() {
- message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PLUGIN_DEACTIVATED, "", "", "", nil)
- message.Add("manifest", manifest.ClientManifest())
- a.Publish(message)
+ return err
}
}
@@ -341,7 +344,7 @@ func (a *App) DisablePlugin(id string) *model.AppError {
return nil
}
-func (a *App) InitPlugins(pluginPath, webappPath string) {
+func (a *App) InitPlugins(pluginPath, webappPath string, supervisorOverride pluginenv.SupervisorProviderFunc) {
if !*a.Config().PluginSettings.Enable {
return
}
@@ -362,7 +365,7 @@ func (a *App) InitPlugins(pluginPath, webappPath string) {
return
}
- if env, err := pluginenv.New(
+ options := []pluginenv.Option{
pluginenv.SearchPath(pluginPath),
pluginenv.WebappPath(webappPath),
pluginenv.APIProvider(func(m *model.Manifest) (plugin.API, error) {
@@ -375,7 +378,13 @@ func (a *App) InitPlugins(pluginPath, webappPath string) {
},
}, nil
}),
- ); err != nil {
+ }
+
+ if supervisorOverride != nil {
+ options = append(options, pluginenv.SupervisorProvider(supervisorOverride))
+ }
+
+ if env, err := pluginenv.New(options...); err != nil {
l4g.Error("failed to start up plugins: " + err.Error())
return
} else {
@@ -533,3 +542,101 @@ func (a *App) DeletePluginKey(pluginId string, key string) *model.AppError {
return result.Err
}
+
+type PluginCommand struct {
+ Command *model.Command
+ PluginId string
+}
+
+func (a *App) RegisterPluginCommand(pluginId string, command *model.Command) error {
+ if command.Trigger == "" {
+ return fmt.Errorf("invalid command")
+ }
+
+ command = &model.Command{
+ Trigger: strings.ToLower(command.Trigger),
+ TeamId: command.TeamId,
+ AutoComplete: command.AutoComplete,
+ AutoCompleteDesc: command.AutoCompleteDesc,
+ DisplayName: command.DisplayName,
+ }
+
+ a.pluginCommandsLock.Lock()
+ defer a.pluginCommandsLock.Unlock()
+
+ for _, pc := range a.pluginCommands {
+ if pc.Command.Trigger == command.Trigger && pc.Command.TeamId == command.TeamId {
+ if pc.PluginId == pluginId {
+ pc.Command = command
+ return nil
+ }
+ }
+ }
+
+ a.pluginCommands = append(a.pluginCommands, &PluginCommand{
+ Command: command,
+ PluginId: pluginId,
+ })
+ return nil
+}
+
+func (a *App) UnregisterPluginCommand(pluginId, teamId, trigger string) {
+ trigger = strings.ToLower(trigger)
+
+ a.pluginCommandsLock.Lock()
+ defer a.pluginCommandsLock.Unlock()
+
+ var remaining []*PluginCommand
+ for _, pc := range a.pluginCommands {
+ if pc.Command.TeamId != teamId || pc.Command.Trigger != trigger {
+ remaining = append(remaining, pc)
+ }
+ }
+ a.pluginCommands = remaining
+}
+
+func (a *App) UnregisterPluginCommands(pluginId string) {
+ a.pluginCommandsLock.Lock()
+ defer a.pluginCommandsLock.Unlock()
+
+ var remaining []*PluginCommand
+ for _, pc := range a.pluginCommands {
+ if pc.PluginId != pluginId {
+ remaining = append(remaining, pc)
+ }
+ }
+ a.pluginCommands = remaining
+}
+
+func (a *App) PluginCommandsForTeam(teamId string) []*model.Command {
+ a.pluginCommandsLock.RLock()
+ defer a.pluginCommandsLock.RUnlock()
+
+ var commands []*model.Command
+ for _, pc := range a.pluginCommands {
+ if pc.Command.TeamId == "" || pc.Command.TeamId == teamId {
+ commands = append(commands, pc.Command)
+ }
+ }
+ return commands
+}
+
+func (a *App) ExecutePluginCommand(args *model.CommandArgs) (*model.Command, *model.CommandResponse, *model.AppError) {
+ parts := strings.Split(args.Command, " ")
+ trigger := parts[0][1:]
+ trigger = strings.ToLower(trigger)
+
+ a.pluginCommandsLock.RLock()
+ defer a.pluginCommandsLock.RUnlock()
+
+ for _, pc := range a.pluginCommands {
+ if (pc.Command.TeamId == "" || pc.Command.TeamId == args.TeamId) && pc.Command.Trigger == trigger {
+ response, appErr, err := a.PluginEnv.HooksForPlugin(pc.PluginId).ExecuteCommand(args)
+ if err != nil {
+ return pc.Command, nil, model.NewAppError("ExecutePluginCommand", "model.plugin_command.error.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
+ }
+ return pc.Command, response, appErr
+ }
+ }
+ return nil, nil, nil
+}