refactor(commands): move /switch channel to /check channel

/switch channel only validates availability, not actually switching.
Rename to /check channel to match actual behavior. /switch channel
now shows a redirect message pointing users to the new command.

Addresses review feedback from yinwm on PR #959.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
mingmxren 2026-03-06 16:44:08 +08:00
parent d248c91611
commit a96382640c
4 changed files with 88 additions and 21 deletions

View file

@ -11,5 +11,6 @@ func BuiltinDefinitions() []Definition {
showCommand(), showCommand(),
listCommand(), listCommand(),
switchCommand(), switchCommand(),
checkCommand(),
} }
} }

33
pkg/commands/cmd_check.go Normal file
View file

@ -0,0 +1,33 @@
package commands
import (
"context"
"fmt"
)
func checkCommand() Definition {
return Definition{
Name: "check",
Description: "Check channel availability",
SubCommands: []SubCommand{
{
Name: "channel",
Description: "Check if a channel is available",
ArgsUsage: "<name>",
Handler: func(_ context.Context, req Request, rt *Runtime) error {
if rt == nil || rt.SwitchChannel == nil {
return req.Reply(unavailableMsg)
}
value := nthToken(req.Text, 2)
if value == "" {
return req.Reply("Usage: /check channel <name>")
}
if err := rt.SwitchChannel(value); err != nil {
return req.Reply(err.Error())
}
return req.Reply(fmt.Sprintf("Channel '%s' is available and enabled", value))
},
},
},
}
}

View file

@ -8,7 +8,7 @@ import (
func switchCommand() Definition { func switchCommand() Definition {
return Definition{ return Definition{
Name: "switch", Name: "switch",
Description: "Switch model or channel", Description: "Switch model",
SubCommands: []SubCommand{ SubCommands: []SubCommand{
{ {
Name: "model", Name: "model",
@ -32,20 +32,9 @@ func switchCommand() Definition {
}, },
{ {
Name: "channel", Name: "channel",
Description: "Switch to a different channel", Description: "Moved to /check channel",
ArgsUsage: "to <name>", Handler: func(_ context.Context, req Request, _ *Runtime) error {
Handler: func(_ context.Context, req Request, rt *Runtime) error { return req.Reply("This command has moved. Please use: /check channel <name>")
if rt == nil || rt.SwitchChannel == nil {
return req.Reply(unavailableMsg)
}
value := nthToken(req.Text, 3)
if nthToken(req.Text, 2) != "to" || value == "" {
return req.Reply("Usage: /switch channel to <name>")
}
if err := rt.SwitchChannel(value); err != nil {
return req.Reply(err.Error())
}
return req.Reply(fmt.Sprintf("Channel '%s' is available and enabled", value))
}, },
}, },
}, },

View file

@ -122,7 +122,27 @@ func TestSwitchModel_NilDep(t *testing.T) {
} }
} }
func TestSwitchChannel_Success(t *testing.T) { func TestSwitchChannel_Redirect(t *testing.T) {
ex := NewExecutor(NewRegistry(BuiltinDefinitions()), &Runtime{})
var reply string
res := ex.Execute(context.Background(), Request{
Text: "/switch channel to telegram",
Reply: func(text string) error {
reply = text
return nil
},
})
if res.Outcome != OutcomeHandled {
t.Fatalf("outcome=%v, want=%v", res.Outcome, OutcomeHandled)
}
want := "This command has moved. Please use: /check channel <name>"
if reply != want {
t.Fatalf("reply=%q, want=%q", reply, want)
}
}
func TestCheckChannel_Success(t *testing.T) {
rt := &Runtime{ rt := &Runtime{
SwitchChannel: func(value string) error { SwitchChannel: func(value string) error {
return nil return nil
@ -132,7 +152,7 @@ func TestSwitchChannel_Success(t *testing.T) {
var reply string var reply string
res := ex.Execute(context.Background(), Request{ res := ex.Execute(context.Background(), Request{
Text: "/switch channel to telegram", Text: "/check channel telegram",
Reply: func(text string) error { Reply: func(text string) error {
reply = text reply = text
return nil return nil
@ -147,7 +167,7 @@ func TestSwitchChannel_Success(t *testing.T) {
} }
} }
func TestSwitchChannel_Error(t *testing.T) { func TestCheckChannel_Error(t *testing.T) {
rt := &Runtime{ rt := &Runtime{
SwitchChannel: func(value string) error { SwitchChannel: func(value string) error {
return fmt.Errorf("channel '%s' not found", value) return fmt.Errorf("channel '%s' not found", value)
@ -157,7 +177,7 @@ func TestSwitchChannel_Error(t *testing.T) {
var reply string var reply string
res := ex.Execute(context.Background(), Request{ res := ex.Execute(context.Background(), Request{
Text: "/switch channel to unknown", Text: "/check channel unknown",
Reply: func(text string) error { Reply: func(text string) error {
reply = text reply = text
return nil return nil
@ -171,12 +191,12 @@ func TestSwitchChannel_Error(t *testing.T) {
} }
} }
func TestSwitchChannel_NilDep(t *testing.T) { func TestCheckChannel_NilDep(t *testing.T) {
ex := NewExecutor(NewRegistry(BuiltinDefinitions()), &Runtime{}) ex := NewExecutor(NewRegistry(BuiltinDefinitions()), &Runtime{})
var reply string var reply string
res := ex.Execute(context.Background(), Request{ res := ex.Execute(context.Background(), Request{
Text: "/switch channel to telegram", Text: "/check channel telegram",
Reply: func(text string) error { Reply: func(text string) error {
reply = text reply = text
return nil return nil
@ -190,6 +210,30 @@ func TestSwitchChannel_NilDep(t *testing.T) {
} }
} }
func TestCheckChannel_MissingValue(t *testing.T) {
rt := &Runtime{
SwitchChannel: func(value string) error {
return nil
},
}
ex := NewExecutor(NewRegistry(BuiltinDefinitions()), rt)
var reply string
res := ex.Execute(context.Background(), Request{
Text: "/check channel",
Reply: func(text string) error {
reply = text
return nil
},
})
if res.Outcome != OutcomeHandled {
t.Fatalf("outcome=%v, want=%v", res.Outcome, OutcomeHandled)
}
if reply != "Usage: /check channel <name>" {
t.Fatalf("reply=%q, want usage message", reply)
}
}
func TestSwitch_BangPrefix(t *testing.T) { func TestSwitch_BangPrefix(t *testing.T) {
rt := &Runtime{ rt := &Runtime{
SwitchModel: func(value string) (string, error) { SwitchModel: func(value string) (string, error) {