diff --git a/docs/stream-cli_chat_mute-channel.md b/docs/stream-cli_chat_mute-channel.md new file mode 100644 index 0000000..d9a8e29 --- /dev/null +++ b/docs/stream-cli_chat_mute-channel.md @@ -0,0 +1,49 @@ +## stream-cli chat mute-channel + +Mute a channel for a user + +### Synopsis + +Mutes a channel for a specific user. Muted channels do not trigger notifications, +affect unread counts, or unhide themselves when new messages are added. + +You can optionally set an expiration time for the mute using the --expiration flag, +such as '1h', '24h', etc. + + +``` +stream-cli chat mute-channel --type [channel-type] --id [channel-id] --user-id [user-id] [--expiration duration] [flags] +``` + +### Examples + +``` +# Mute a channel indefinitely for user 'john' +$ stream-cli chat mute-channel --type messaging --id redteam --user-id john + +# Mute a channel for 6 hours +$ stream-cli chat mute-channel --type messaging --id redteam --user-id john --expiration 6h + +``` + +### Options + +``` + --expiration string [optional] Expiration duration (e.g., '1h', '6h') + -h, --help help for mute-channel + -i, --id string [required] Channel ID + -t, --type string [required] Channel type such as 'messaging' + -u, --user-id string [required] User ID +``` + +### Options inherited from parent commands + +``` + --app string [optional] Application name to use as it's defined in the configuration file + --config string [optional] Explicit config file path +``` + +### SEE ALSO + +* [stream-cli chat](stream-cli_chat.md) - Allows you to interact with your Chat applications + diff --git a/pkg/cmd/chat/channel/channel.go b/pkg/cmd/chat/channel/channel.go index 3887ad0..53e28b3 100644 --- a/pkg/cmd/chat/channel/channel.go +++ b/pkg/cmd/chat/channel/channel.go @@ -3,6 +3,7 @@ package channel import ( "encoding/json" "errors" + "fmt" "time" stream "github.com/GetStream/stream-chat-go/v5" @@ -28,6 +29,7 @@ func NewCmds() []*cobra.Command { assignRoleCmd(), hideCmd(), showCmd(), + muteChannelCmd(), } } @@ -610,3 +612,65 @@ func showCmd() *cobra.Command { return cmd } + +func muteChannelCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "mute-channel --type [channel-type] --id [channel-id] --user-id [user-id] [--expiration duration]", + Short: "Mute a channel for a user", + Long: heredoc.Doc(` + Mutes a channel for a specific user. Muted channels do not trigger notifications, + affect unread counts, or unhide themselves when new messages are added. + + You can optionally set an expiration time for the mute using the --expiration flag, + such as '1h', '24h', etc. + `), + Example: heredoc.Doc(` + # Mute a channel indefinitely for user 'john' + $ stream-cli chat mute-channel --type messaging --id redteam --user-id john + + # Mute a channel for 6 hours + $ stream-cli chat mute-channel --type messaging --id redteam --user-id john --expiration 6h + `), + RunE: func(cmd *cobra.Command, args []string) error { + client, err := config.GetConfig(cmd).GetClient(cmd) + if err != nil { + return err + } + + typ, _ := cmd.Flags().GetString("type") + id, _ := cmd.Flags().GetString("id") + user, _ := cmd.Flags().GetString("user-id") + expStr, _ := cmd.Flags().GetString("expiration") + + var exp *time.Duration + if expStr != "" { + d, err := time.ParseDuration(expStr) + if err != nil { + return fmt.Errorf("invalid expiration duration: %w", err) + } + exp = &d + } + + ch := client.Channel(typ, id) + _, err = ch.Mute(cmd.Context(), user, exp) + if err != nil { + return err + } + + cmd.Printf("Successfully muted channel [%s] for user [%s]\n", id, user) + return nil + }, + } + + fl := cmd.Flags() + fl.StringP("type", "t", "", "[required] Channel type such as 'messaging'") + fl.StringP("id", "i", "", "[required] Channel ID") + fl.StringP("user-id", "u", "", "[required] User ID") + fl.String("expiration", "", "[optional] Expiration duration (e.g., '1h', '6h')") + + _ = cmd.MarkFlagRequired("type") + _ = cmd.MarkFlagRequired("id") + _ = cmd.MarkFlagRequired("user-id") + + return cmd +} diff --git a/pkg/cmd/chat/channel/channel_test.go b/pkg/cmd/chat/channel/channel_test.go index fd300a7..38703a5 100644 --- a/pkg/cmd/chat/channel/channel_test.go +++ b/pkg/cmd/chat/channel/channel_test.go @@ -204,3 +204,39 @@ func TestHideAndShowChannel(t *testing.T) { require.NoError(t, err) require.Contains(t, cmd.OutOrStdout().(*bytes.Buffer).String(), "Successfully shown channel") } + +func TestMuteChannel(t *testing.T) { + cmd := test.GetRootCmdWithSubCommands(NewCmds()...) + ch := test.InitChannel(t) + u := test.CreateUser() + + t.Cleanup(func() { + test.DeleteChannel(ch) + test.DeleteUser(u) + }) + + // Add user to channel so mute works + cmd.SetArgs([]string{"add-members", "-t", "messaging", "-i", ch, u}) + _, err := cmd.ExecuteC() + require.NoError(t, err) + + // Mute the channel for the user + cmd.SetArgs([]string{"mute-channel", "-t", "messaging", "-i", ch, "-u", u}) + _, err = cmd.ExecuteC() + require.NoError(t, err) + + // Check that output contains success message + out := cmd.OutOrStdout().(*bytes.Buffer).String() + require.Contains(t, out, "Successfully muted channel") + + // OPTIONAL: Verify via SDK that user mute exists + client := test.InitClient() + ctx := context.Background() + userResp, err := client.QueryUsers(ctx, &stream.QueryOption{ + Filter: map[string]interface{}{"id": u}, + }) + require.NoError(t, err) + require.Len(t, userResp.Users, 1) + require.NotEmpty(t, userResp.Users[0].ChannelMutes) + require.Equal(t, ch, userResp.Users[0].ChannelMutes[0].Channel.ID) +}