github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/cmd/mattermost/commands/webhook.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package commands
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"strings"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/audit"
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  	"github.com/mattermost/mattermost-server/v5/store"
    14  	"github.com/pkg/errors"
    15  	"github.com/spf13/cobra"
    16  )
    17  
    18  var WebhookCmd = &cobra.Command{
    19  	Use:   "webhook",
    20  	Short: "Management of webhooks",
    21  }
    22  
    23  var WebhookListCmd = &cobra.Command{
    24  	Use:     "list",
    25  	Short:   "List webhooks",
    26  	Long:    "list all webhooks",
    27  	Example: "  webhook list myteam",
    28  	RunE:    listWebhookCmdF,
    29  }
    30  
    31  var WebhookShowCmd = &cobra.Command{
    32  	Use:     "show [webhookId]",
    33  	Short:   "Show a webhook",
    34  	Long:    "Show the webhook specified by [webhookId]",
    35  	Args:    cobra.ExactArgs(1),
    36  	Example: "  webhook show w16zb5tu3n1zkqo18goqry1je",
    37  	RunE:    showWebhookCmdF,
    38  }
    39  
    40  var WebhookCreateIncomingCmd = &cobra.Command{
    41  	Use:     "create-incoming",
    42  	Short:   "Create incoming webhook",
    43  	Long:    "create incoming webhook which allows external posting of messages to specific channel",
    44  	Example: "  webhook create-incoming --channel [channelID] --user [userID] --display-name [displayName] --description [webhookDescription] --lock-to-channel --icon [iconURL]",
    45  	RunE:    createIncomingWebhookCmdF,
    46  }
    47  
    48  var WebhookModifyIncomingCmd = &cobra.Command{
    49  	Use:     "modify-incoming",
    50  	Short:   "Modify incoming webhook",
    51  	Long:    "Modify existing incoming webhook by changing its title, description, channel or icon url",
    52  	Example: "  webhook modify-incoming [webhookID] --channel [channelID] --display-name [displayName] --description [webhookDescription] --lock-to-channel --icon [iconURL]",
    53  	RunE:    modifyIncomingWebhookCmdF,
    54  }
    55  
    56  var WebhookCreateOutgoingCmd = &cobra.Command{
    57  	Use:   "create-outgoing",
    58  	Short: "Create outgoing webhook",
    59  	Long:  "create outgoing webhook which allows external posting of messages from a specific channel",
    60  	Example: `  webhook create-outgoing --team myteam --user myusername --display-name mywebhook --trigger-word "build" --trigger-word "test" --url http://localhost:8000/my-webhook-handler
    61  	webhook create-outgoing --team myteam --channel mychannel --user myusername --display-name mywebhook --description "My cool webhook" --trigger-when start --trigger-word build --trigger-word test --icon http://localhost:8000/my-slash-handler-bot-icon.png --url http://localhost:8000/my-webhook-handler --content-type "application/json"`,
    62  	RunE: createOutgoingWebhookCmdF,
    63  }
    64  
    65  var WebhookModifyOutgoingCmd = &cobra.Command{
    66  	Use:     "modify-outgoing",
    67  	Short:   "Modify outgoing webhook",
    68  	Long:    "Modify existing outgoing webhook by changing its title, description, channel, icon, url, content-type, and triggers",
    69  	Example: `  webhook modify-outgoing [webhookId] --channel [channelId] --display-name [displayName] --description "New webhook description" --icon http://localhost:8000/my-slash-handler-bot-icon.png --url http://localhost:8000/my-webhook-handler --content-type "application/json" --trigger-word test --trigger-when start`,
    70  	RunE:    modifyOutgoingWebhookCmdF,
    71  }
    72  
    73  var WebhookDeleteCmd = &cobra.Command{
    74  	Use:     "delete",
    75  	Short:   "Delete webhooks",
    76  	Long:    "Delete webhook with given id",
    77  	Example: "  webhook delete [webhookID]",
    78  	RunE:    deleteWebhookCmdF,
    79  }
    80  
    81  var WebhookMoveOutgoingCmd = &cobra.Command{
    82  	Use:     "move-outgoing",
    83  	Short:   "Move outgoing webhook",
    84  	Long:    "Move outgoing webhook with an id",
    85  	Example: "  webhook move-outgoing newteam oldteam:webhook-id --channel new-default-channel",
    86  	Args:    cobra.ExactArgs(2),
    87  	RunE:    moveOutgoingWebhookCmd,
    88  }
    89  
    90  func listWebhookCmdF(command *cobra.Command, args []string) error {
    91  	app, err := InitDBCommandContextCobra(command)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	defer app.Srv().Shutdown()
    96  
    97  	var teams []*model.Team
    98  	if len(args) < 1 {
    99  		var getErr *model.AppError
   100  		// If no team is specified, list all teams
   101  		teams, getErr = app.GetAllTeams()
   102  		if getErr != nil {
   103  			return getErr
   104  		}
   105  	} else {
   106  		teams = getTeamsFromTeamArgs(app, args)
   107  	}
   108  
   109  	for i, team := range teams {
   110  		if team == nil {
   111  			CommandPrintErrorln("Unable to find team '" + args[i] + "'")
   112  			continue
   113  		}
   114  
   115  		// Fetch all hooks with a very large limit so we get them all.
   116  		incomingResult := make(chan store.StoreResult, 1)
   117  		go func() {
   118  			incomingHooks, err := app.Srv().Store.Webhook().GetIncomingByTeam(team.Id, 0, 100000000)
   119  			incomingResult <- store.StoreResult{Data: incomingHooks, NErr: err}
   120  			close(incomingResult)
   121  		}()
   122  		outgoingResult := make(chan store.StoreResult, 1)
   123  		go func() {
   124  			outgoingHooks, err := app.Srv().Store.Webhook().GetOutgoingByTeam(team.Id, 0, 100000000)
   125  			outgoingResult <- store.StoreResult{Data: outgoingHooks, NErr: err}
   126  			close(outgoingResult)
   127  		}()
   128  
   129  		if result := <-incomingResult; result.NErr == nil {
   130  			CommandPrettyPrintln(fmt.Sprintf("Incoming webhooks for %s (%s):", team.DisplayName, team.Name))
   131  			hooks := result.Data.([]*model.IncomingWebhook)
   132  			for _, hook := range hooks {
   133  				CommandPrettyPrintln("\t" + hook.DisplayName + " (" + hook.Id + ")")
   134  			}
   135  		} else {
   136  			CommandPrintErrorln("Unable to list incoming webhooks for '" + args[i] + "'")
   137  		}
   138  
   139  		if result := <-outgoingResult; result.NErr == nil {
   140  			hooks := result.Data.([]*model.OutgoingWebhook)
   141  			CommandPrettyPrintln(fmt.Sprintf("Outgoing webhooks for %s (%s):", team.DisplayName, team.Name))
   142  			for _, hook := range hooks {
   143  				CommandPrettyPrintln("\t" + hook.DisplayName + " (" + hook.Id + ")")
   144  			}
   145  		} else {
   146  			CommandPrintErrorln("Unable to list outgoing webhooks for '" + args[i] + "'")
   147  		}
   148  	}
   149  	return nil
   150  }
   151  
   152  func createIncomingWebhookCmdF(command *cobra.Command, args []string) error {
   153  	app, err := InitDBCommandContextCobra(command)
   154  	if err != nil {
   155  		return err
   156  	}
   157  	defer app.Srv().Shutdown()
   158  
   159  	channelArg, errChannel := command.Flags().GetString("channel")
   160  	if errChannel != nil || channelArg == "" {
   161  		return errors.New("Channel is required")
   162  	}
   163  	channel := getChannelFromChannelArg(app, channelArg)
   164  	if channel == nil {
   165  		return errors.New("Unable to find channel '" + channelArg + "'")
   166  	}
   167  
   168  	userArg, errUser := command.Flags().GetString("user")
   169  	if errUser != nil || userArg == "" {
   170  		return errors.New("User is required")
   171  	}
   172  	user := getUserFromUserArg(app, userArg)
   173  	if user == nil {
   174  		return errors.New("Unable to find user '" + userArg + "'")
   175  	}
   176  
   177  	displayName, _ := command.Flags().GetString("display-name")
   178  	description, _ := command.Flags().GetString("description")
   179  	iconURL, _ := command.Flags().GetString("icon")
   180  	channelLocked, _ := command.Flags().GetBool("lock-to-channel")
   181  
   182  	incomingWebhook := &model.IncomingWebhook{
   183  		ChannelId:     channel.Id,
   184  		DisplayName:   displayName,
   185  		Description:   description,
   186  		IconURL:       iconURL,
   187  		ChannelLocked: channelLocked,
   188  	}
   189  
   190  	createdIncoming, errIncomingWebhook := app.CreateIncomingWebhookForChannel(user.Id, channel, incomingWebhook)
   191  	if errIncomingWebhook != nil {
   192  		return errIncomingWebhook
   193  	}
   194  
   195  	CommandPrettyPrintln("Id: " + createdIncoming.Id)
   196  	CommandPrettyPrintln("Display Name: " + createdIncoming.DisplayName)
   197  
   198  	auditRec := app.MakeAuditRecord("createIncomingWebhook", audit.Success)
   199  	auditRec.AddMeta("user", user)
   200  	auditRec.AddMeta("channel", channel)
   201  	auditRec.AddMeta("hook", createdIncoming)
   202  	app.LogAuditRec(auditRec, nil)
   203  
   204  	return nil
   205  }
   206  
   207  func modifyIncomingWebhookCmdF(command *cobra.Command, args []string) (cmdError error) {
   208  	app, err := InitDBCommandContextCobra(command)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	defer app.Srv().Shutdown()
   213  
   214  	if len(args) < 1 {
   215  		return errors.New("WebhookID is not specified")
   216  	}
   217  
   218  	webhookArg := args[0]
   219  	oldHook, getErr := app.GetIncomingWebhook(webhookArg)
   220  	if getErr != nil {
   221  		return errors.New("Unable to find webhook '" + webhookArg + "'")
   222  	}
   223  
   224  	updatedHook := oldHook
   225  
   226  	auditRec := app.MakeAuditRecord("createIncomingWebhook", audit.Fail)
   227  	defer func() { app.LogAuditRec(auditRec, cmdError) }()
   228  	auditRec.AddMeta("hook", oldHook)
   229  
   230  	channelArg, _ := command.Flags().GetString("channel")
   231  	if channelArg != "" {
   232  		channel := getChannelFromChannelArg(app, channelArg)
   233  		if channel == nil {
   234  			return errors.New("Unable to find channel '" + channelArg + "'")
   235  		}
   236  		updatedHook.ChannelId = channel.Id
   237  	}
   238  
   239  	displayName, _ := command.Flags().GetString("display-name")
   240  	if displayName != "" {
   241  		updatedHook.DisplayName = displayName
   242  	}
   243  	description, _ := command.Flags().GetString("description")
   244  	if description != "" {
   245  		updatedHook.Description = description
   246  	}
   247  	iconUrl, _ := command.Flags().GetString("icon")
   248  	if iconUrl != "" {
   249  		updatedHook.IconURL = iconUrl
   250  	}
   251  	channelLocked, _ := command.Flags().GetBool("lock-to-channel")
   252  	updatedHook.ChannelLocked = channelLocked
   253  
   254  	updatedIncomingHook, errUpdated := app.UpdateIncomingWebhook(oldHook, updatedHook)
   255  	if errUpdated != nil {
   256  		return errUpdated
   257  	}
   258  
   259  	auditRec.Success()
   260  	auditRec.AddMeta("update", updatedIncomingHook)
   261  
   262  	return nil
   263  }
   264  
   265  func createOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
   266  	app, err := InitDBCommandContextCobra(command)
   267  	if err != nil {
   268  		return err
   269  	}
   270  	defer app.Srv().Shutdown()
   271  
   272  	teamArg, errTeam := command.Flags().GetString("team")
   273  	if errTeam != nil || teamArg == "" {
   274  		return errors.New("Team is required")
   275  	}
   276  	team := getTeamFromTeamArg(app, teamArg)
   277  	if team == nil {
   278  		return errors.New("Unable to find team: " + teamArg)
   279  	}
   280  
   281  	userArg, errUser := command.Flags().GetString("user")
   282  	if errUser != nil || userArg == "" {
   283  		return errors.New("User is required")
   284  	}
   285  	user := getUserFromUserArg(app, userArg)
   286  	if user == nil {
   287  		return errors.New("Unable to find user: " + userArg)
   288  	}
   289  
   290  	displayName, errName := command.Flags().GetString("display-name")
   291  	if errName != nil || displayName == "" {
   292  		return errors.New("Display name is required")
   293  	}
   294  
   295  	triggerWords, errWords := command.Flags().GetStringArray("trigger-word")
   296  	if errWords != nil || len(triggerWords) == 0 {
   297  		return errors.New("Trigger word or words required")
   298  	}
   299  
   300  	callbackURLs, errURL := command.Flags().GetStringArray("url")
   301  	if errURL != nil || len(callbackURLs) == 0 {
   302  		return errors.New("Callback URL or URLs required")
   303  	}
   304  
   305  	triggerWhenString, _ := command.Flags().GetString("trigger-when")
   306  	var triggerWhen int
   307  	if triggerWhenString == "exact" {
   308  		triggerWhen = 0
   309  	} else if triggerWhenString == "start" {
   310  		triggerWhen = 1
   311  	} else {
   312  		return errors.New("Invalid trigger when parameter")
   313  	}
   314  	description, _ := command.Flags().GetString("description")
   315  	contentType, _ := command.Flags().GetString("content-type")
   316  	iconURL, _ := command.Flags().GetString("icon")
   317  
   318  	outgoingWebhook := &model.OutgoingWebhook{
   319  		CreatorId:    user.Id,
   320  		Username:     user.Username,
   321  		TeamId:       team.Id,
   322  		TriggerWords: triggerWords,
   323  		TriggerWhen:  triggerWhen,
   324  		CallbackURLs: callbackURLs,
   325  		DisplayName:  displayName,
   326  		Description:  description,
   327  		ContentType:  contentType,
   328  		IconURL:      iconURL,
   329  	}
   330  
   331  	var channel *model.Channel
   332  	channelArg, _ := command.Flags().GetString("channel")
   333  	if channelArg != "" {
   334  		channel = getChannelFromChannelArg(app, channelArg)
   335  		if channel != nil {
   336  			outgoingWebhook.ChannelId = channel.Id
   337  		}
   338  	}
   339  
   340  	createdOutgoing, errOutgoing := app.CreateOutgoingWebhook(outgoingWebhook)
   341  	if errOutgoing != nil {
   342  		return errOutgoing
   343  	}
   344  
   345  	CommandPrettyPrintln("Id: " + createdOutgoing.Id)
   346  	CommandPrettyPrintln("Display Name: " + createdOutgoing.DisplayName)
   347  
   348  	auditRec := app.MakeAuditRecord("createOutgoingWebhook", audit.Success)
   349  	auditRec.AddMeta("user", user)
   350  	auditRec.AddMeta("hook", createdOutgoing)
   351  	if channel != nil {
   352  		auditRec.AddMeta("channel", channel)
   353  	}
   354  	app.LogAuditRec(auditRec, nil)
   355  
   356  	return nil
   357  }
   358  
   359  func modifyOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
   360  	app, err := InitDBCommandContextCobra(command)
   361  	if err != nil {
   362  		return err
   363  	}
   364  	defer app.Srv().Shutdown()
   365  
   366  	if len(args) < 1 {
   367  		return errors.New("WebhookID is not specified")
   368  	}
   369  
   370  	webhookArg := args[0]
   371  	oldHook, appErr := app.GetOutgoingWebhook(webhookArg)
   372  	if appErr != nil {
   373  		return fmt.Errorf("unable to find webhook '%s'", webhookArg)
   374  	}
   375  
   376  	updatedHook := model.OutgoingWebhookFromJson(strings.NewReader(oldHook.ToJson()))
   377  
   378  	channelArg, _ := command.Flags().GetString("channel")
   379  	if channelArg != "" {
   380  		channel := getChannelFromChannelArg(app, channelArg)
   381  		if channel == nil {
   382  			return fmt.Errorf("unable to find channel '%s'", channelArg)
   383  		}
   384  		updatedHook.ChannelId = channel.Id
   385  	}
   386  
   387  	displayName, _ := command.Flags().GetString("display-name")
   388  	if displayName != "" {
   389  		updatedHook.DisplayName = displayName
   390  	}
   391  
   392  	description, _ := command.Flags().GetString("description")
   393  	if description != "" {
   394  		updatedHook.Description = description
   395  	}
   396  
   397  	triggerWords, err := command.Flags().GetStringArray("trigger-word")
   398  	if err != nil {
   399  		return errors.Wrap(err, "invalid trigger-word parameter")
   400  	}
   401  	if len(triggerWords) > 0 {
   402  		updatedHook.TriggerWords = triggerWords
   403  	}
   404  
   405  	triggerWhenString, _ := command.Flags().GetString("trigger-when")
   406  	if triggerWhenString != "" {
   407  		var triggerWhen int
   408  		if triggerWhenString == "exact" {
   409  			triggerWhen = 0
   410  		} else if triggerWhenString == "start" {
   411  			triggerWhen = 1
   412  		} else {
   413  			return errors.New("invalid trigger-when parameter")
   414  		}
   415  		updatedHook.TriggerWhen = triggerWhen
   416  	}
   417  
   418  	iconURL, _ := command.Flags().GetString("icon")
   419  	if iconURL != "" {
   420  		updatedHook.IconURL = iconURL
   421  	}
   422  
   423  	contentType, _ := command.Flags().GetString("content-type")
   424  	if contentType != "" {
   425  		updatedHook.ContentType = contentType
   426  	}
   427  
   428  	callbackURLs, err := command.Flags().GetStringArray("url")
   429  	if err != nil {
   430  		return errors.Wrap(err, "invalid URL parameter")
   431  	}
   432  	if len(callbackURLs) > 0 {
   433  		updatedHook.CallbackURLs = callbackURLs
   434  	}
   435  
   436  	updatedWebhook, appErr := app.UpdateOutgoingWebhook(oldHook, updatedHook)
   437  	if appErr != nil {
   438  		return appErr
   439  	}
   440  
   441  	auditRec := app.MakeAuditRecord("modifyOutgoingWebhook", audit.Success)
   442  	auditRec.AddMeta("hook", oldHook)
   443  	auditRec.AddMeta("update", updatedWebhook)
   444  	app.LogAuditRec(auditRec, nil)
   445  
   446  	return nil
   447  }
   448  
   449  func deleteWebhookCmdF(command *cobra.Command, args []string) error {
   450  	app, err := InitDBCommandContextCobra(command)
   451  	if err != nil {
   452  		return err
   453  	}
   454  	defer app.Srv().Shutdown()
   455  
   456  	if len(args) < 1 {
   457  		return errors.New("WebhookID is not specified")
   458  	}
   459  
   460  	webhookId := args[0]
   461  	errIncomingWebhook := app.DeleteIncomingWebhook(webhookId)
   462  	errOutgoingWebhook := app.DeleteOutgoingWebhook(webhookId)
   463  
   464  	if errIncomingWebhook != nil && errOutgoingWebhook != nil {
   465  		return errors.New("Unable to delete webhook '" + webhookId + "'")
   466  	}
   467  
   468  	auditRec := app.MakeAuditRecord("deleteWebhook", audit.Success)
   469  	auditRec.AddMeta("hook_id", webhookId)
   470  	app.LogAuditRec(auditRec, nil)
   471  
   472  	return nil
   473  }
   474  
   475  func showWebhookCmdF(command *cobra.Command, args []string) error {
   476  	app, err := InitDBCommandContextCobra(command)
   477  	if err != nil {
   478  		return err
   479  	}
   480  	defer app.Srv().Shutdown()
   481  
   482  	webhookId := args[0]
   483  	if incomingWebhook, err := app.GetIncomingWebhook(webhookId); err == nil {
   484  		fmt.Printf("%s", prettyPrintStruct(*incomingWebhook))
   485  		return nil
   486  	}
   487  	if outgoingWebhook, err := app.GetOutgoingWebhook(webhookId); err == nil {
   488  		fmt.Printf("%s", prettyPrintStruct(*outgoingWebhook))
   489  		return nil
   490  	}
   491  
   492  	return errors.New("Webhook with id " + webhookId + " not found")
   493  }
   494  
   495  func moveOutgoingWebhookCmd(command *cobra.Command, args []string) (cmdError error) {
   496  	app, err := InitDBCommandContextCobra(command)
   497  	if err != nil {
   498  		return err
   499  	}
   500  	defer app.Srv().Shutdown()
   501  
   502  	newTeamId := args[0]
   503  	_, teamError := app.GetTeam(newTeamId)
   504  	if teamError != nil {
   505  		return teamError
   506  	}
   507  
   508  	webhookInformation := strings.Split(args[1], ":")
   509  	sourceTeam := webhookInformation[0]
   510  	_, teamErr := app.GetTeam(sourceTeam)
   511  	if teamErr != nil {
   512  		return teamErr
   513  	}
   514  
   515  	webhookId := webhookInformation[1]
   516  	webhook, appError := app.GetOutgoingWebhook(webhookId)
   517  	if appError != nil {
   518  		return appError
   519  	}
   520  
   521  	auditRec := app.MakeAuditRecord("moveOutgoingWebhook", audit.Fail)
   522  	defer func() { app.LogAuditRec(auditRec, cmdError) }()
   523  	auditRec.AddMeta("hook", webhook)
   524  
   525  	channelName, channelErr := command.Flags().GetString("channel")
   526  	if channelErr != nil {
   527  		return channelErr
   528  	}
   529  	channel, getChannelErr := app.GetChannelByName(channelName, newTeamId, false)
   530  
   531  	if webhook.ChannelId != "" {
   532  		if getChannelErr != nil {
   533  			return getChannelErr
   534  		}
   535  		webhook.ChannelId = channel.Id
   536  	} else if channelName != "" {
   537  		webhook.ChannelId = channel.Id
   538  	}
   539  
   540  	deleteErr := app.DeleteOutgoingWebhook(webhook.Id)
   541  	if deleteErr != nil {
   542  		return deleteErr
   543  	}
   544  
   545  	webhook.Id = ""
   546  	webhook.TeamId = newTeamId
   547  
   548  	updatedWebHook, createErr := app.CreateOutgoingWebhook(webhook)
   549  	if createErr != nil {
   550  		return model.NewAppError("moveOutgoingWebhookCmd", "cli.outgoing_webhook.inconsistent_state.app_error", nil, "", http.StatusInternalServerError)
   551  	}
   552  
   553  	auditRec.Success()
   554  	auditRec.AddMeta("update", updatedWebHook)
   555  
   556  	return nil
   557  }
   558  
   559  func init() {
   560  	WebhookCreateIncomingCmd.Flags().String("channel", "", "Channel ID (required)")
   561  	WebhookCreateIncomingCmd.Flags().String("user", "", "User ID (required)")
   562  	WebhookCreateIncomingCmd.Flags().String("display-name", "", "Incoming webhook display name")
   563  	WebhookCreateIncomingCmd.Flags().String("description", "", "Incoming webhook description")
   564  	WebhookCreateIncomingCmd.Flags().String("icon", "", "Icon URL")
   565  	WebhookCreateIncomingCmd.Flags().Bool("lock-to-channel", false, "Lock to channel")
   566  
   567  	WebhookModifyIncomingCmd.Flags().String("channel", "", "Channel ID")
   568  	WebhookModifyIncomingCmd.Flags().String("display-name", "", "Incoming webhook display name")
   569  	WebhookModifyIncomingCmd.Flags().String("description", "", "Incoming webhook description")
   570  	WebhookModifyIncomingCmd.Flags().String("icon", "", "Icon URL")
   571  	WebhookModifyIncomingCmd.Flags().Bool("lock-to-channel", false, "Lock to channel")
   572  
   573  	WebhookCreateOutgoingCmd.Flags().String("team", "", "Team name or ID (required)")
   574  	WebhookCreateOutgoingCmd.Flags().String("channel", "", "Channel name or ID")
   575  	WebhookCreateOutgoingCmd.Flags().String("user", "", "User username, email, or ID (required)")
   576  	WebhookCreateOutgoingCmd.Flags().String("display-name", "", "Outgoing webhook display name (required)")
   577  	WebhookCreateOutgoingCmd.Flags().String("description", "", "Outgoing webhook description")
   578  	WebhookCreateOutgoingCmd.Flags().StringArray("trigger-word", []string{}, "Word to trigger webhook (required)")
   579  	WebhookCreateOutgoingCmd.Flags().String("trigger-when", "exact", "When to trigger webhook (exact: for first word matches a trigger word exactly, start: for first word starts with a trigger word)")
   580  	WebhookCreateOutgoingCmd.Flags().String("icon", "", "Icon URL")
   581  	WebhookCreateOutgoingCmd.Flags().StringArray("url", []string{}, "Callback URL (required)")
   582  	WebhookCreateOutgoingCmd.Flags().String("content-type", "", "Content-type")
   583  
   584  	WebhookModifyOutgoingCmd.Flags().String("channel", "", "Channel name or ID")
   585  	WebhookModifyOutgoingCmd.Flags().String("display-name", "", "Outgoing webhook display name")
   586  	WebhookModifyOutgoingCmd.Flags().String("description", "", "Outgoing webhook description")
   587  	WebhookModifyOutgoingCmd.Flags().StringArray("trigger-word", []string{}, "Word to trigger webhook")
   588  	WebhookModifyOutgoingCmd.Flags().String("trigger-when", "", "When to trigger webhook (exact: for first word matches a trigger word exactly, start: for first word starts with a trigger word)")
   589  	WebhookModifyOutgoingCmd.Flags().String("icon", "", "Icon URL")
   590  	WebhookModifyOutgoingCmd.Flags().StringArray("url", []string{}, "Callback URL")
   591  	WebhookModifyOutgoingCmd.Flags().String("content-type", "", "Content-type")
   592  
   593  	WebhookMoveOutgoingCmd.Flags().String("channel", "", "Channel name or ID")
   594  
   595  	WebhookCmd.AddCommand(
   596  		WebhookListCmd,
   597  		WebhookCreateIncomingCmd,
   598  		WebhookModifyIncomingCmd,
   599  		WebhookCreateOutgoingCmd,
   600  		WebhookModifyOutgoingCmd,
   601  		WebhookDeleteCmd,
   602  		WebhookShowCmd,
   603  		WebhookMoveOutgoingCmd,
   604  	)
   605  
   606  	RootCmd.AddCommand(WebhookCmd)
   607  }