Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/stream-cli_chat_truncate-channel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
## stream-cli chat truncate-channel

Truncate a channel

### Synopsis

Truncates a channel by removing all messages but keeping the channel metadata and members.

Optional flags allow you to perform a hard delete, add a system message, skip push notifications,
and define the truncating user ID (for server-side calls).


```
stream-cli chat truncate-channel --type [channel-type] --id [channel-id] [flags]
```

### Examples

```
# Truncate messages in 'general' channel of type messaging
$ stream-cli chat truncate-channel --type messaging --id general

# Truncate with hard delete and system message
$ stream-cli chat truncate-channel --type messaging --id general --hard --message "Channel reset" --user-id system-user

```

### Options

```
--hard [optional] Permanently delete messages instead of hiding them
-h, --help help for truncate-channel
-i, --id string [required] Channel ID
--message string [optional] System message to include in truncation (requires --message-user-id)
--message-user-id string [optional] User id for the message to include in truncation (required if --message is set)
--skip-push [optional] Skip push notifications
-t, --type string [required] Channel type such as 'messaging'
--user-id string [optional] User ID who performs the truncation
```

### 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

80 changes: 80 additions & 0 deletions pkg/cmd/chat/channel/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func NewCmds() []*cobra.Command {
assignRoleCmd(),
hideCmd(),
showCmd(),
truncateChannelCmd(),
}
}

Expand Down Expand Up @@ -610,3 +611,82 @@ func showCmd() *cobra.Command {

return cmd
}

func truncateChannelCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "truncate-channel --type [channel-type] --id [channel-id] [flags]",
Short: "Truncate a channel",
Long: heredoc.Doc(`
Truncates a channel by removing all messages but keeping the channel metadata and members.

Optional flags allow you to perform a hard delete, add a system message, skip push notifications,
and define the truncating user ID (for server-side calls).
`),
Example: heredoc.Doc(`
# Truncate messages in 'general' channel of type messaging
$ stream-cli chat truncate-channel --type messaging --id general

# Truncate with hard delete and system message
$ stream-cli chat truncate-channel --type messaging --id general --hard --message "Channel reset" --user-id system-user
`),
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")
hard, _ := cmd.Flags().GetBool("hard")
userID, _ := cmd.Flags().GetString("user-id")
messageUserID, _ := cmd.Flags().GetString("message-user-id")
msgText, _ := cmd.Flags().GetString("message")
skipPush, _ := cmd.Flags().GetBool("skip-push")

// If a message is provided, a message user id must also be provided
if msgText != "" && messageUserID == "" {
return errors.New("when using --message, you must also supply --message-user-id")
}

var opts []stream.TruncateOption

if hard {
opts = append(opts, stream.TruncateWithHardDelete())
}
if skipPush {
opts = append(opts, stream.TruncateWithSkipPush())
}
if userID != "" {
opts = append(opts, stream.TruncateWithUserID(userID))
}
if msgText != "" {
opts = append(opts, stream.TruncateWithMessage(&stream.Message{
Text: msgText,
User: &stream.User{ID: messageUserID},
}))
}

ch := client.Channel(typ, id)
_, err = ch.Truncate(cmd.Context(), opts...)
if err != nil {
return err
}
cmd.Printf("Successfully truncated channel [%s]\n", id)
return nil
},
}

fl := cmd.Flags()
fl.StringP("type", "t", "", "[required] Channel type such as 'messaging'")
fl.StringP("id", "i", "", "[required] Channel ID")
fl.String("user-id", "", "[optional] User ID who performs the truncation")
fl.String("message", "", "[optional] System message to include in truncation (requires --message-user-id)")
fl.String("message-user-id", "", "[optional] User id for the message to include in truncation (required if --message is set)")
fl.Bool("hard", false, "[optional] Permanently delete messages instead of hiding them")
fl.Bool("skip-push", false, "[optional] Skip push notifications")

_ = cmd.MarkFlagRequired("type")
_ = cmd.MarkFlagRequired("id")

return cmd
}
36 changes: 36 additions & 0 deletions pkg/cmd/chat/channel/channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 TestTruncateChannel(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 and send a message
cmd.SetArgs([]string{"add-members", "-t", "messaging", "-i", ch, u})
_, _ = cmd.ExecuteC()

client := test.InitClient()
ctx := context.Background()
_, err := client.Channel("messaging", ch).SendMessage(ctx, &stream.Message{
Text: "Pre-truncate message",
User: &stream.User{ID: u},
}, u)
require.NoError(t, err)

// Truncate the channel
cmd.SetArgs([]string{"truncate-channel", "-t", "messaging", "-i", ch, "--hard", "--message", "Channel reset", "--message-user-id", u})
_, err = cmd.ExecuteC()
require.NoError(t, err)

out := cmd.OutOrStdout().(*bytes.Buffer).String()
require.Contains(t, out, "Successfully truncated channel")

// Verify that message history is empty
resp, err := client.Channel("messaging", ch).Query(ctx, &stream.QueryRequest{})
require.NoError(t, err)
require.Empty(t, resp.Messages)
}