mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
feat(command): extend slash command system with new commands and UX improvements
Add 9 new command groups (/model, /memory, /search, /browser, /usage, /email, /heartbeat, /skill, /fs) and improve existing commands by hiding internal UUIDs, resolving IDs to human-readable names in /settings, and switching /schedule to name-based references.
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/memohai/memoh/internal/schedule"
|
||||
)
|
||||
|
||||
func (h *Handler) buildScheduleGroup() *CommandGroup {
|
||||
g := newCommandGroup("schedule", "Manage scheduled tasks")
|
||||
g.Register(SubCommand{
|
||||
Name: "list",
|
||||
Usage: "list - List all schedules",
|
||||
Handler: func(cc CommandContext) (string, error) {
|
||||
items, err := h.scheduleService.List(cc.Ctx, cc.BotID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(items) == 0 {
|
||||
return "No schedules found.", nil
|
||||
}
|
||||
records := make([][]kv, 0, len(items))
|
||||
for _, item := range items {
|
||||
records = append(records, []kv{
|
||||
{"Name", item.Name},
|
||||
{"Pattern", item.Pattern},
|
||||
{"Enabled", boolStr(item.Enabled)},
|
||||
{"Description", truncate(item.Description, 30)},
|
||||
})
|
||||
}
|
||||
return formatItems(records), nil
|
||||
},
|
||||
})
|
||||
g.Register(SubCommand{
|
||||
Name: "get",
|
||||
Usage: "get <name> - Get schedule details",
|
||||
Handler: func(cc CommandContext) (string, error) {
|
||||
if len(cc.Args) < 1 {
|
||||
return "Usage: /schedule get <name>", nil
|
||||
}
|
||||
item, err := h.findScheduleByName(cc, cc.Args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
maxCalls := "unlimited"
|
||||
if item.MaxCalls != nil {
|
||||
maxCalls = fmt.Sprintf("%d", *item.MaxCalls)
|
||||
}
|
||||
return formatKV([]kv{
|
||||
{"Name", item.Name},
|
||||
{"Description", item.Description},
|
||||
{"Pattern", item.Pattern},
|
||||
{"Command", item.Command},
|
||||
{"Enabled", boolStr(item.Enabled)},
|
||||
{"Max Calls", maxCalls},
|
||||
{"Current Calls", fmt.Sprintf("%d", item.CurrentCalls)},
|
||||
{"Created", item.CreatedAt.Format("2006-01-02 15:04:05")},
|
||||
{"Updated", item.UpdatedAt.Format("2006-01-02 15:04:05")},
|
||||
}), nil
|
||||
},
|
||||
})
|
||||
g.Register(SubCommand{
|
||||
Name: "create",
|
||||
Usage: "create <name> <pattern> <command> - Create a schedule",
|
||||
IsWrite: true,
|
||||
Handler: func(cc CommandContext) (string, error) {
|
||||
if len(cc.Args) < 3 {
|
||||
return "Usage: /schedule create <name> <pattern> <command>\nExample: /schedule create daily-report \"0 9 * * *\" \"Send daily report\"", nil
|
||||
}
|
||||
name := cc.Args[0]
|
||||
pattern := cc.Args[1]
|
||||
command := strings.Join(cc.Args[2:], " ")
|
||||
item, err := h.scheduleService.Create(cc.Ctx, cc.BotID, schedule.CreateRequest{
|
||||
Name: name,
|
||||
Description: name,
|
||||
Pattern: pattern,
|
||||
Command: command,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("Schedule %q created.", item.Name), nil
|
||||
},
|
||||
})
|
||||
g.Register(SubCommand{
|
||||
Name: "update",
|
||||
Usage: "update <name> [--pattern P] [--command C] - Update a schedule",
|
||||
IsWrite: true,
|
||||
Handler: func(cc CommandContext) (string, error) {
|
||||
if len(cc.Args) < 1 {
|
||||
return "Usage: /schedule update <name> [--pattern P] [--command C]", nil
|
||||
}
|
||||
item, err := h.findScheduleByName(cc, cc.Args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req := schedule.UpdateRequest{}
|
||||
args := cc.Args[1:]
|
||||
for i := 0; i < len(args); i++ {
|
||||
if i+1 >= len(args) {
|
||||
break
|
||||
}
|
||||
switch args[i] {
|
||||
case "--name":
|
||||
i++
|
||||
req.Name = &args[i]
|
||||
case "--pattern":
|
||||
i++
|
||||
req.Pattern = &args[i]
|
||||
case "--command":
|
||||
i++
|
||||
val := strings.Join(args[i:], " ")
|
||||
req.Command = &val
|
||||
i = len(args)
|
||||
case "--enabled":
|
||||
i++
|
||||
v := strings.ToLower(args[i]) == "true"
|
||||
req.Enabled = &v
|
||||
}
|
||||
}
|
||||
updated, err := h.scheduleService.Update(cc.Ctx, item.ID, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("Schedule %q updated.", updated.Name), nil
|
||||
},
|
||||
})
|
||||
g.Register(SubCommand{
|
||||
Name: "delete",
|
||||
Usage: "delete <name> - Delete a schedule",
|
||||
IsWrite: true,
|
||||
Handler: func(cc CommandContext) (string, error) {
|
||||
if len(cc.Args) < 1 {
|
||||
return "Usage: /schedule delete <name>", nil
|
||||
}
|
||||
item, err := h.findScheduleByName(cc, cc.Args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := h.scheduleService.Delete(cc.Ctx, item.ID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("Schedule %q deleted.", cc.Args[0]), nil
|
||||
},
|
||||
})
|
||||
g.Register(SubCommand{
|
||||
Name: "enable",
|
||||
Usage: "enable <name> - Enable a schedule",
|
||||
IsWrite: true,
|
||||
Handler: func(cc CommandContext) (string, error) {
|
||||
if len(cc.Args) < 1 {
|
||||
return "Usage: /schedule enable <name>", nil
|
||||
}
|
||||
item, err := h.findScheduleByName(cc, cc.Args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
enabled := true
|
||||
_, err = h.scheduleService.Update(cc.Ctx, item.ID, schedule.UpdateRequest{Enabled: &enabled})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("Schedule %q enabled.", cc.Args[0]), nil
|
||||
},
|
||||
})
|
||||
g.Register(SubCommand{
|
||||
Name: "disable",
|
||||
Usage: "disable <name> - Disable a schedule",
|
||||
IsWrite: true,
|
||||
Handler: func(cc CommandContext) (string, error) {
|
||||
if len(cc.Args) < 1 {
|
||||
return "Usage: /schedule disable <name>", nil
|
||||
}
|
||||
item, err := h.findScheduleByName(cc, cc.Args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
enabled := false
|
||||
_, err = h.scheduleService.Update(cc.Ctx, item.ID, schedule.UpdateRequest{Enabled: &enabled})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("Schedule %q disabled.", cc.Args[0]), nil
|
||||
},
|
||||
})
|
||||
return g
|
||||
}
|
||||
|
||||
func (h *Handler) findScheduleByName(cc CommandContext, name string) (schedule.Schedule, error) {
|
||||
items, err := h.scheduleService.List(cc.Ctx, cc.BotID)
|
||||
if err != nil {
|
||||
return schedule.Schedule{}, err
|
||||
}
|
||||
for _, item := range items {
|
||||
if strings.EqualFold(item.Name, name) {
|
||||
return item, nil
|
||||
}
|
||||
}
|
||||
return schedule.Schedule{}, fmt.Errorf("schedule %q not found", name)
|
||||
}
|
||||
Reference in New Issue
Block a user