ScuttleBot
Merge pull request #134 from ConflictHQ/feature/86-wire-bot-commands feat: wire command router into all 10 system bots
Commit
e8d318d9d3a13a71c484ad84a549efe3d4f716b53a2d19dda0ff7abae6950cd3
Parent
ba75f34cff38b3e…
10 files changed
+16
-2
+27
+14
-1
+21
-1
+20
-1
+29
-2
+21
+27
+27
+33
-1
~
internal/bots/auditbot/auditbot.go
~
internal/bots/herald/herald.go
~
internal/bots/oracle/oracle.go
~
internal/bots/scribe/scribe.go
~
internal/bots/scroll/scroll.go
~
internal/bots/sentinel/sentinel.go
~
internal/bots/snitch/snitch.go
~
internal/bots/steward/steward.go
~
internal/bots/systembot/systembot.go
~
internal/bots/warden/warden.go
+16
-2
| --- internal/bots/auditbot/auditbot.go | ||
| +++ internal/bots/auditbot/auditbot.go | ||
| @@ -20,10 +20,11 @@ | ||
| 20 | 20 | "strings" |
| 21 | 21 | "time" |
| 22 | 22 | |
| 23 | 23 | "github.com/lrstanley/girc" |
| 24 | 24 | |
| 25 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 25 | 26 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 26 | 27 | ) |
| 27 | 28 | |
| 28 | 29 | const botNick = "auditbot" |
| 29 | 30 | |
| @@ -133,17 +134,30 @@ | ||
| 133 | 134 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 134 | 135 | cl.Cmd.Join(ch) |
| 135 | 136 | } |
| 136 | 137 | }) |
| 137 | 138 | |
| 138 | - c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { | |
| 139 | + router := cmdparse.NewRouter(botNick) | |
| 140 | + router.Register(cmdparse.Command{ | |
| 141 | + Name: "query", | |
| 142 | + Usage: "QUERY <nick|#channel>", | |
| 143 | + Description: "show recent audit events for a nick or channel", | |
| 144 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 145 | + }) | |
| 146 | + | |
| 147 | + c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { | |
| 139 | 148 | if len(e.Params) < 1 { |
| 140 | 149 | return |
| 150 | + } | |
| 151 | + // Dispatch commands (DMs and channel messages). | |
| 152 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 153 | + cl.Cmd.Message(reply.Target, reply.Text) | |
| 154 | + return | |
| 141 | 155 | } |
| 142 | 156 | channel := e.Params[0] |
| 143 | 157 | if !strings.HasPrefix(channel, "#") { |
| 144 | - return // ignore DMs | |
| 158 | + return // non-command DMs ignored | |
| 145 | 159 | } |
| 146 | 160 | text := e.Last() |
| 147 | 161 | env, err := protocol.Unmarshal([]byte(text)) |
| 148 | 162 | if err != nil { |
| 149 | 163 | return // non-envelope PRIVMSG ignored |
| 150 | 164 |
| --- internal/bots/auditbot/auditbot.go | |
| +++ internal/bots/auditbot/auditbot.go | |
| @@ -20,10 +20,11 @@ | |
| 20 | "strings" |
| 21 | "time" |
| 22 | |
| 23 | "github.com/lrstanley/girc" |
| 24 | |
| 25 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 26 | ) |
| 27 | |
| 28 | const botNick = "auditbot" |
| 29 | |
| @@ -133,17 +134,30 @@ | |
| 133 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 134 | cl.Cmd.Join(ch) |
| 135 | } |
| 136 | }) |
| 137 | |
| 138 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 139 | if len(e.Params) < 1 { |
| 140 | return |
| 141 | } |
| 142 | channel := e.Params[0] |
| 143 | if !strings.HasPrefix(channel, "#") { |
| 144 | return // ignore DMs |
| 145 | } |
| 146 | text := e.Last() |
| 147 | env, err := protocol.Unmarshal([]byte(text)) |
| 148 | if err != nil { |
| 149 | return // non-envelope PRIVMSG ignored |
| 150 |
| --- internal/bots/auditbot/auditbot.go | |
| +++ internal/bots/auditbot/auditbot.go | |
| @@ -20,10 +20,11 @@ | |
| 20 | "strings" |
| 21 | "time" |
| 22 | |
| 23 | "github.com/lrstanley/girc" |
| 24 | |
| 25 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 26 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 27 | ) |
| 28 | |
| 29 | const botNick = "auditbot" |
| 30 | |
| @@ -133,17 +134,30 @@ | |
| 134 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 135 | cl.Cmd.Join(ch) |
| 136 | } |
| 137 | }) |
| 138 | |
| 139 | router := cmdparse.NewRouter(botNick) |
| 140 | router.Register(cmdparse.Command{ |
| 141 | Name: "query", |
| 142 | Usage: "QUERY <nick|#channel>", |
| 143 | Description: "show recent audit events for a nick or channel", |
| 144 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 145 | }) |
| 146 | |
| 147 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 148 | if len(e.Params) < 1 { |
| 149 | return |
| 150 | } |
| 151 | // Dispatch commands (DMs and channel messages). |
| 152 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 153 | cl.Cmd.Message(reply.Target, reply.Text) |
| 154 | return |
| 155 | } |
| 156 | channel := e.Params[0] |
| 157 | if !strings.HasPrefix(channel, "#") { |
| 158 | return // non-command DMs ignored |
| 159 | } |
| 160 | text := e.Last() |
| 161 | env, err := protocol.Unmarshal([]byte(text)) |
| 162 | if err != nil { |
| 163 | return // non-envelope PRIVMSG ignored |
| 164 |
| --- internal/bots/herald/herald.go | ||
| +++ internal/bots/herald/herald.go | ||
| @@ -17,10 +17,12 @@ | ||
| 17 | 17 | "strings" |
| 18 | 18 | "sync" |
| 19 | 19 | "time" |
| 20 | 20 | |
| 21 | 21 | "github.com/lrstanley/girc" |
| 22 | + | |
| 23 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 22 | 24 | ) |
| 23 | 25 | |
| 24 | 26 | const botNick = "herald" |
| 25 | 27 | |
| 26 | 28 | // Event is a notification pushed to herald for delivery. |
| @@ -165,10 +167,35 @@ | ||
| 165 | 167 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 166 | 168 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 167 | 169 | cl.Cmd.Join(ch) |
| 168 | 170 | } |
| 169 | 171 | }) |
| 172 | + | |
| 173 | + router := cmdparse.NewRouter(botNick) | |
| 174 | + router.Register(cmdparse.Command{ | |
| 175 | + Name: "status", | |
| 176 | + Usage: "STATUS", | |
| 177 | + Description: "show webhook endpoint status and recent events", | |
| 178 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 179 | + }) | |
| 180 | + router.Register(cmdparse.Command{ | |
| 181 | + Name: "test", | |
| 182 | + Usage: "TEST #channel", | |
| 183 | + Description: "send a test event to a channel", | |
| 184 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 185 | + }) | |
| 186 | + | |
| 187 | + c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { | |
| 188 | + if len(e.Params) < 1 || e.Source == nil { | |
| 189 | + return | |
| 190 | + } | |
| 191 | + // Dispatch commands (DMs and channel messages). | |
| 192 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 193 | + cl.Cmd.Message(reply.Target, reply.Text) | |
| 194 | + return | |
| 195 | + } | |
| 196 | + }) | |
| 170 | 197 | |
| 171 | 198 | b.client = c |
| 172 | 199 | |
| 173 | 200 | errCh := make(chan error, 1) |
| 174 | 201 | go func() { |
| 175 | 202 |
| --- internal/bots/herald/herald.go | |
| +++ internal/bots/herald/herald.go | |
| @@ -17,10 +17,12 @@ | |
| 17 | "strings" |
| 18 | "sync" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | ) |
| 23 | |
| 24 | const botNick = "herald" |
| 25 | |
| 26 | // Event is a notification pushed to herald for delivery. |
| @@ -165,10 +167,35 @@ | |
| 165 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 166 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 167 | cl.Cmd.Join(ch) |
| 168 | } |
| 169 | }) |
| 170 | |
| 171 | b.client = c |
| 172 | |
| 173 | errCh := make(chan error, 1) |
| 174 | go func() { |
| 175 |
| --- internal/bots/herald/herald.go | |
| +++ internal/bots/herald/herald.go | |
| @@ -17,10 +17,12 @@ | |
| 17 | "strings" |
| 18 | "sync" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | |
| 23 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 24 | ) |
| 25 | |
| 26 | const botNick = "herald" |
| 27 | |
| 28 | // Event is a notification pushed to herald for delivery. |
| @@ -165,10 +167,35 @@ | |
| 167 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 168 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 169 | cl.Cmd.Join(ch) |
| 170 | } |
| 171 | }) |
| 172 | |
| 173 | router := cmdparse.NewRouter(botNick) |
| 174 | router.Register(cmdparse.Command{ |
| 175 | Name: "status", |
| 176 | Usage: "STATUS", |
| 177 | Description: "show webhook endpoint status and recent events", |
| 178 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 179 | }) |
| 180 | router.Register(cmdparse.Command{ |
| 181 | Name: "test", |
| 182 | Usage: "TEST #channel", |
| 183 | Description: "send a test event to a channel", |
| 184 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 185 | }) |
| 186 | |
| 187 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 188 | if len(e.Params) < 1 || e.Source == nil { |
| 189 | return |
| 190 | } |
| 191 | // Dispatch commands (DMs and channel messages). |
| 192 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 193 | cl.Cmd.Message(reply.Target, reply.Text) |
| 194 | return |
| 195 | } |
| 196 | }) |
| 197 | |
| 198 | b.client = c |
| 199 | |
| 200 | errCh := make(chan error, 1) |
| 201 | go func() { |
| 202 |
+14
-1
| --- internal/bots/oracle/oracle.go | ||
| +++ internal/bots/oracle/oracle.go | ||
| @@ -21,10 +21,11 @@ | ||
| 21 | 21 | "sync" |
| 22 | 22 | "time" |
| 23 | 23 | |
| 24 | 24 | "github.com/lrstanley/girc" |
| 25 | 25 | |
| 26 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 26 | 27 | "github.com/conflicthq/scuttlebot/pkg/chathistory" |
| 27 | 28 | "github.com/conflicthq/scuttlebot/pkg/toon" |
| 28 | 29 | ) |
| 29 | 30 | |
| 30 | 31 | const ( |
| @@ -188,14 +189,26 @@ | ||
| 188 | 189 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 189 | 190 | cl.Cmd.Join(ch) |
| 190 | 191 | } |
| 191 | 192 | }) |
| 192 | 193 | |
| 193 | - // Only handle DMs — oracle ignores channel messages. | |
| 194 | + router := cmdparse.NewRouter(botNick) | |
| 195 | + router.Register(cmdparse.Command{ | |
| 196 | + Name: "summarize", | |
| 197 | + Usage: "SUMMARIZE [#channel] [duration]", | |
| 198 | + Description: "summarize recent channel activity", | |
| 199 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 200 | + }) | |
| 201 | + | |
| 194 | 202 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 195 | 203 | if len(e.Params) < 1 || e.Source == nil { |
| 196 | 204 | return |
| 205 | + } | |
| 206 | + // Dispatch commands (DMs and channel messages). | |
| 207 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 208 | + cl.Cmd.Message(reply.Target, reply.Text) | |
| 209 | + return | |
| 197 | 210 | } |
| 198 | 211 | target := e.Params[0] |
| 199 | 212 | if strings.HasPrefix(target, "#") { |
| 200 | 213 | return // channel message — ignore |
| 201 | 214 | } |
| 202 | 215 |
| --- internal/bots/oracle/oracle.go | |
| +++ internal/bots/oracle/oracle.go | |
| @@ -21,10 +21,11 @@ | |
| 21 | "sync" |
| 22 | "time" |
| 23 | |
| 24 | "github.com/lrstanley/girc" |
| 25 | |
| 26 | "github.com/conflicthq/scuttlebot/pkg/chathistory" |
| 27 | "github.com/conflicthq/scuttlebot/pkg/toon" |
| 28 | ) |
| 29 | |
| 30 | const ( |
| @@ -188,14 +189,26 @@ | |
| 188 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 189 | cl.Cmd.Join(ch) |
| 190 | } |
| 191 | }) |
| 192 | |
| 193 | // Only handle DMs — oracle ignores channel messages. |
| 194 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 195 | if len(e.Params) < 1 || e.Source == nil { |
| 196 | return |
| 197 | } |
| 198 | target := e.Params[0] |
| 199 | if strings.HasPrefix(target, "#") { |
| 200 | return // channel message — ignore |
| 201 | } |
| 202 |
| --- internal/bots/oracle/oracle.go | |
| +++ internal/bots/oracle/oracle.go | |
| @@ -21,10 +21,11 @@ | |
| 21 | "sync" |
| 22 | "time" |
| 23 | |
| 24 | "github.com/lrstanley/girc" |
| 25 | |
| 26 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 27 | "github.com/conflicthq/scuttlebot/pkg/chathistory" |
| 28 | "github.com/conflicthq/scuttlebot/pkg/toon" |
| 29 | ) |
| 30 | |
| 31 | const ( |
| @@ -188,14 +189,26 @@ | |
| 189 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 190 | cl.Cmd.Join(ch) |
| 191 | } |
| 192 | }) |
| 193 | |
| 194 | router := cmdparse.NewRouter(botNick) |
| 195 | router.Register(cmdparse.Command{ |
| 196 | Name: "summarize", |
| 197 | Usage: "SUMMARIZE [#channel] [duration]", |
| 198 | Description: "summarize recent channel activity", |
| 199 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 200 | }) |
| 201 | |
| 202 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 203 | if len(e.Params) < 1 || e.Source == nil { |
| 204 | return |
| 205 | } |
| 206 | // Dispatch commands (DMs and channel messages). |
| 207 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 208 | cl.Cmd.Message(reply.Target, reply.Text) |
| 209 | return |
| 210 | } |
| 211 | target := e.Params[0] |
| 212 | if strings.HasPrefix(target, "#") { |
| 213 | return // channel message — ignore |
| 214 | } |
| 215 |
+21
-1
| --- internal/bots/scribe/scribe.go | ||
| +++ internal/bots/scribe/scribe.go | ||
| @@ -15,10 +15,11 @@ | ||
| 15 | 15 | "strings" |
| 16 | 16 | "time" |
| 17 | 17 | |
| 18 | 18 | "github.com/lrstanley/girc" |
| 19 | 19 | |
| 20 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 20 | 21 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 21 | 22 | ) |
| 22 | 23 | |
| 23 | 24 | const botNick = "scribe" |
| 24 | 25 | |
| @@ -76,19 +77,38 @@ | ||
| 76 | 77 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 77 | 78 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 78 | 79 | cl.Cmd.Join(ch) |
| 79 | 80 | } |
| 80 | 81 | }) |
| 82 | + | |
| 83 | + router := cmdparse.NewRouter(botNick) | |
| 84 | + router.Register(cmdparse.Command{ | |
| 85 | + Name: "search", | |
| 86 | + Usage: "SEARCH <term>", | |
| 87 | + Description: "search channel logs", | |
| 88 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 89 | + }) | |
| 90 | + router.Register(cmdparse.Command{ | |
| 91 | + Name: "stats", | |
| 92 | + Usage: "STATS", | |
| 93 | + Description: "show channel message statistics", | |
| 94 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 95 | + }) | |
| 81 | 96 | |
| 82 | 97 | // Log PRIVMSG — the agent message stream. |
| 83 | 98 | c.Handlers.AddBg(girc.PRIVMSG, func(client *girc.Client, e girc.Event) { |
| 84 | 99 | if len(e.Params) < 1 || e.Source == nil { |
| 85 | 100 | return |
| 101 | + } | |
| 102 | + // Dispatch commands (DMs and channel messages). | |
| 103 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 104 | + client.Cmd.Message(reply.Target, reply.Text) | |
| 105 | + return | |
| 86 | 106 | } |
| 87 | 107 | channel := e.Params[0] |
| 88 | 108 | if !strings.HasPrefix(channel, "#") { |
| 89 | - return // ignore DMs to scribe itself | |
| 109 | + return // non-command DMs ignored | |
| 90 | 110 | } |
| 91 | 111 | text := e.Last() |
| 92 | 112 | nick := e.Source.Name |
| 93 | 113 | b.writeEntry(channel, nick, text) |
| 94 | 114 | }) |
| 95 | 115 |
| --- internal/bots/scribe/scribe.go | |
| +++ internal/bots/scribe/scribe.go | |
| @@ -15,10 +15,11 @@ | |
| 15 | "strings" |
| 16 | "time" |
| 17 | |
| 18 | "github.com/lrstanley/girc" |
| 19 | |
| 20 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 21 | ) |
| 22 | |
| 23 | const botNick = "scribe" |
| 24 | |
| @@ -76,19 +77,38 @@ | |
| 76 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 77 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 78 | cl.Cmd.Join(ch) |
| 79 | } |
| 80 | }) |
| 81 | |
| 82 | // Log PRIVMSG — the agent message stream. |
| 83 | c.Handlers.AddBg(girc.PRIVMSG, func(client *girc.Client, e girc.Event) { |
| 84 | if len(e.Params) < 1 || e.Source == nil { |
| 85 | return |
| 86 | } |
| 87 | channel := e.Params[0] |
| 88 | if !strings.HasPrefix(channel, "#") { |
| 89 | return // ignore DMs to scribe itself |
| 90 | } |
| 91 | text := e.Last() |
| 92 | nick := e.Source.Name |
| 93 | b.writeEntry(channel, nick, text) |
| 94 | }) |
| 95 |
| --- internal/bots/scribe/scribe.go | |
| +++ internal/bots/scribe/scribe.go | |
| @@ -15,10 +15,11 @@ | |
| 15 | "strings" |
| 16 | "time" |
| 17 | |
| 18 | "github.com/lrstanley/girc" |
| 19 | |
| 20 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 21 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 22 | ) |
| 23 | |
| 24 | const botNick = "scribe" |
| 25 | |
| @@ -76,19 +77,38 @@ | |
| 77 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 78 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 79 | cl.Cmd.Join(ch) |
| 80 | } |
| 81 | }) |
| 82 | |
| 83 | router := cmdparse.NewRouter(botNick) |
| 84 | router.Register(cmdparse.Command{ |
| 85 | Name: "search", |
| 86 | Usage: "SEARCH <term>", |
| 87 | Description: "search channel logs", |
| 88 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 89 | }) |
| 90 | router.Register(cmdparse.Command{ |
| 91 | Name: "stats", |
| 92 | Usage: "STATS", |
| 93 | Description: "show channel message statistics", |
| 94 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 95 | }) |
| 96 | |
| 97 | // Log PRIVMSG — the agent message stream. |
| 98 | c.Handlers.AddBg(girc.PRIVMSG, func(client *girc.Client, e girc.Event) { |
| 99 | if len(e.Params) < 1 || e.Source == nil { |
| 100 | return |
| 101 | } |
| 102 | // Dispatch commands (DMs and channel messages). |
| 103 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 104 | client.Cmd.Message(reply.Target, reply.Text) |
| 105 | return |
| 106 | } |
| 107 | channel := e.Params[0] |
| 108 | if !strings.HasPrefix(channel, "#") { |
| 109 | return // non-command DMs ignored |
| 110 | } |
| 111 | text := e.Last() |
| 112 | nick := e.Source.Name |
| 113 | b.writeEntry(channel, nick, text) |
| 114 | }) |
| 115 |
+20
-1
| --- internal/bots/scroll/scroll.go | ||
| +++ internal/bots/scroll/scroll.go | ||
| @@ -20,10 +20,11 @@ | ||
| 20 | 20 | "sync" |
| 21 | 21 | "time" |
| 22 | 22 | |
| 23 | 23 | "github.com/lrstanley/girc" |
| 24 | 24 | |
| 25 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 25 | 26 | "github.com/conflicthq/scuttlebot/internal/bots/scribe" |
| 26 | 27 | "github.com/conflicthq/scuttlebot/pkg/chathistory" |
| 27 | 28 | "github.com/conflicthq/scuttlebot/pkg/toon" |
| 28 | 29 | ) |
| 29 | 30 | |
| @@ -93,14 +94,32 @@ | ||
| 93 | 94 | } |
| 94 | 95 | hasCH := cl.HasCapability("chathistory") || cl.HasCapability("draft/chathistory") |
| 95 | 96 | b.log.Info("scroll connected", "channels", b.channels, "chathistory", hasCH) |
| 96 | 97 | }) |
| 97 | 98 | |
| 98 | - // Only respond to DMs — ignore anything in a channel. | |
| 99 | + router := cmdparse.NewRouter(botNick) | |
| 100 | + router.Register(cmdparse.Command{ | |
| 101 | + Name: "replay", | |
| 102 | + Usage: "REPLAY [#channel] [count]", | |
| 103 | + Description: "replay recent channel messages", | |
| 104 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 105 | + }) | |
| 106 | + router.Register(cmdparse.Command{ | |
| 107 | + Name: "search", | |
| 108 | + Usage: "SEARCH [#channel] <term>", | |
| 109 | + Description: "search channel history", | |
| 110 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 111 | + }) | |
| 112 | + | |
| 99 | 113 | c.Handlers.AddBg(girc.PRIVMSG, func(client *girc.Client, e girc.Event) { |
| 100 | 114 | if len(e.Params) < 1 || e.Source == nil { |
| 101 | 115 | return |
| 116 | + } | |
| 117 | + // Dispatch commands (DMs and channel messages). | |
| 118 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 119 | + client.Cmd.Message(reply.Target, reply.Text) | |
| 120 | + return | |
| 102 | 121 | } |
| 103 | 122 | target := e.Params[0] |
| 104 | 123 | if strings.HasPrefix(target, "#") { |
| 105 | 124 | return // channel message, ignore |
| 106 | 125 | } |
| 107 | 126 |
| --- internal/bots/scroll/scroll.go | |
| +++ internal/bots/scroll/scroll.go | |
| @@ -20,10 +20,11 @@ | |
| 20 | "sync" |
| 21 | "time" |
| 22 | |
| 23 | "github.com/lrstanley/girc" |
| 24 | |
| 25 | "github.com/conflicthq/scuttlebot/internal/bots/scribe" |
| 26 | "github.com/conflicthq/scuttlebot/pkg/chathistory" |
| 27 | "github.com/conflicthq/scuttlebot/pkg/toon" |
| 28 | ) |
| 29 | |
| @@ -93,14 +94,32 @@ | |
| 93 | } |
| 94 | hasCH := cl.HasCapability("chathistory") || cl.HasCapability("draft/chathistory") |
| 95 | b.log.Info("scroll connected", "channels", b.channels, "chathistory", hasCH) |
| 96 | }) |
| 97 | |
| 98 | // Only respond to DMs — ignore anything in a channel. |
| 99 | c.Handlers.AddBg(girc.PRIVMSG, func(client *girc.Client, e girc.Event) { |
| 100 | if len(e.Params) < 1 || e.Source == nil { |
| 101 | return |
| 102 | } |
| 103 | target := e.Params[0] |
| 104 | if strings.HasPrefix(target, "#") { |
| 105 | return // channel message, ignore |
| 106 | } |
| 107 |
| --- internal/bots/scroll/scroll.go | |
| +++ internal/bots/scroll/scroll.go | |
| @@ -20,10 +20,11 @@ | |
| 20 | "sync" |
| 21 | "time" |
| 22 | |
| 23 | "github.com/lrstanley/girc" |
| 24 | |
| 25 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 26 | "github.com/conflicthq/scuttlebot/internal/bots/scribe" |
| 27 | "github.com/conflicthq/scuttlebot/pkg/chathistory" |
| 28 | "github.com/conflicthq/scuttlebot/pkg/toon" |
| 29 | ) |
| 30 | |
| @@ -93,14 +94,32 @@ | |
| 94 | } |
| 95 | hasCH := cl.HasCapability("chathistory") || cl.HasCapability("draft/chathistory") |
| 96 | b.log.Info("scroll connected", "channels", b.channels, "chathistory", hasCH) |
| 97 | }) |
| 98 | |
| 99 | router := cmdparse.NewRouter(botNick) |
| 100 | router.Register(cmdparse.Command{ |
| 101 | Name: "replay", |
| 102 | Usage: "REPLAY [#channel] [count]", |
| 103 | Description: "replay recent channel messages", |
| 104 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 105 | }) |
| 106 | router.Register(cmdparse.Command{ |
| 107 | Name: "search", |
| 108 | Usage: "SEARCH [#channel] <term>", |
| 109 | Description: "search channel history", |
| 110 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 111 | }) |
| 112 | |
| 113 | c.Handlers.AddBg(girc.PRIVMSG, func(client *girc.Client, e girc.Event) { |
| 114 | if len(e.Params) < 1 || e.Source == nil { |
| 115 | return |
| 116 | } |
| 117 | // Dispatch commands (DMs and channel messages). |
| 118 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 119 | client.Cmd.Message(reply.Target, reply.Text) |
| 120 | return |
| 121 | } |
| 122 | target := e.Params[0] |
| 123 | if strings.HasPrefix(target, "#") { |
| 124 | return // channel message, ignore |
| 125 | } |
| 126 |
+29
-2
| --- internal/bots/sentinel/sentinel.go | ||
| +++ internal/bots/sentinel/sentinel.go | ||
| @@ -20,10 +20,12 @@ | ||
| 20 | 20 | "strings" |
| 21 | 21 | "sync" |
| 22 | 22 | "time" |
| 23 | 23 | |
| 24 | 24 | "github.com/lrstanley/girc" |
| 25 | + | |
| 26 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 25 | 27 | ) |
| 26 | 28 | |
| 27 | 29 | const defaultNick = "sentinel" |
| 28 | 30 | |
| 29 | 31 | // LLMProvider calls a language model to evaluate channel content. |
| @@ -162,17 +164,42 @@ | ||
| 162 | 164 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 163 | 165 | cl.Cmd.Join(ch) |
| 164 | 166 | } |
| 165 | 167 | }) |
| 166 | 168 | |
| 167 | - c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { | |
| 169 | + router := cmdparse.NewRouter(b.cfg.Nick) | |
| 170 | + router.Register(cmdparse.Command{ | |
| 171 | + Name: "report", | |
| 172 | + Usage: "REPORT [#channel]", | |
| 173 | + Description: "on-demand policy review", | |
| 174 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 175 | + }) | |
| 176 | + router.Register(cmdparse.Command{ | |
| 177 | + Name: "status", | |
| 178 | + Usage: "STATUS", | |
| 179 | + Description: "show current incidents", | |
| 180 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 181 | + }) | |
| 182 | + router.Register(cmdparse.Command{ | |
| 183 | + Name: "dismiss", | |
| 184 | + Usage: "DISMISS <incident-id>", | |
| 185 | + Description: "dismiss a false positive", | |
| 186 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 187 | + }) | |
| 188 | + | |
| 189 | + c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { | |
| 168 | 190 | if len(e.Params) < 1 || e.Source == nil { |
| 169 | 191 | return |
| 192 | + } | |
| 193 | + // Dispatch commands (DMs and channel messages). | |
| 194 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 195 | + cl.Cmd.Message(reply.Target, reply.Text) | |
| 196 | + return | |
| 170 | 197 | } |
| 171 | 198 | channel := e.Params[0] |
| 172 | 199 | if !strings.HasPrefix(channel, "#") { |
| 173 | - return // ignore DMs | |
| 200 | + return // non-command DMs ignored | |
| 174 | 201 | } |
| 175 | 202 | if channel == b.cfg.ModChannel { |
| 176 | 203 | return // don't analyse the mod channel itself |
| 177 | 204 | } |
| 178 | 205 | nick := e.Source.Name |
| 179 | 206 |
| --- internal/bots/sentinel/sentinel.go | |
| +++ internal/bots/sentinel/sentinel.go | |
| @@ -20,10 +20,12 @@ | |
| 20 | "strings" |
| 21 | "sync" |
| 22 | "time" |
| 23 | |
| 24 | "github.com/lrstanley/girc" |
| 25 | ) |
| 26 | |
| 27 | const defaultNick = "sentinel" |
| 28 | |
| 29 | // LLMProvider calls a language model to evaluate channel content. |
| @@ -162,17 +164,42 @@ | |
| 162 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 163 | cl.Cmd.Join(ch) |
| 164 | } |
| 165 | }) |
| 166 | |
| 167 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 168 | if len(e.Params) < 1 || e.Source == nil { |
| 169 | return |
| 170 | } |
| 171 | channel := e.Params[0] |
| 172 | if !strings.HasPrefix(channel, "#") { |
| 173 | return // ignore DMs |
| 174 | } |
| 175 | if channel == b.cfg.ModChannel { |
| 176 | return // don't analyse the mod channel itself |
| 177 | } |
| 178 | nick := e.Source.Name |
| 179 |
| --- internal/bots/sentinel/sentinel.go | |
| +++ internal/bots/sentinel/sentinel.go | |
| @@ -20,10 +20,12 @@ | |
| 20 | "strings" |
| 21 | "sync" |
| 22 | "time" |
| 23 | |
| 24 | "github.com/lrstanley/girc" |
| 25 | |
| 26 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 27 | ) |
| 28 | |
| 29 | const defaultNick = "sentinel" |
| 30 | |
| 31 | // LLMProvider calls a language model to evaluate channel content. |
| @@ -162,17 +164,42 @@ | |
| 164 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 165 | cl.Cmd.Join(ch) |
| 166 | } |
| 167 | }) |
| 168 | |
| 169 | router := cmdparse.NewRouter(b.cfg.Nick) |
| 170 | router.Register(cmdparse.Command{ |
| 171 | Name: "report", |
| 172 | Usage: "REPORT [#channel]", |
| 173 | Description: "on-demand policy review", |
| 174 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 175 | }) |
| 176 | router.Register(cmdparse.Command{ |
| 177 | Name: "status", |
| 178 | Usage: "STATUS", |
| 179 | Description: "show current incidents", |
| 180 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 181 | }) |
| 182 | router.Register(cmdparse.Command{ |
| 183 | Name: "dismiss", |
| 184 | Usage: "DISMISS <incident-id>", |
| 185 | Description: "dismiss a false positive", |
| 186 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 187 | }) |
| 188 | |
| 189 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 190 | if len(e.Params) < 1 || e.Source == nil { |
| 191 | return |
| 192 | } |
| 193 | // Dispatch commands (DMs and channel messages). |
| 194 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 195 | cl.Cmd.Message(reply.Target, reply.Text) |
| 196 | return |
| 197 | } |
| 198 | channel := e.Params[0] |
| 199 | if !strings.HasPrefix(channel, "#") { |
| 200 | return // non-command DMs ignored |
| 201 | } |
| 202 | if channel == b.cfg.ModChannel { |
| 203 | return // don't analyse the mod channel itself |
| 204 | } |
| 205 | nick := e.Source.Name |
| 206 |
| --- internal/bots/snitch/snitch.go | ||
| +++ internal/bots/snitch/snitch.go | ||
| @@ -17,10 +17,12 @@ | ||
| 17 | 17 | "strings" |
| 18 | 18 | "sync" |
| 19 | 19 | "time" |
| 20 | 20 | |
| 21 | 21 | "github.com/lrstanley/girc" |
| 22 | + | |
| 23 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 22 | 24 | ) |
| 23 | 25 | |
| 24 | 26 | const defaultNick = "snitch" |
| 25 | 27 | |
| 26 | 28 | // Config controls snitch's thresholds and alert destination. |
| @@ -196,14 +198,33 @@ | ||
| 196 | 198 | if len(e.Params) < 1 || e.Source == nil { |
| 197 | 199 | return |
| 198 | 200 | } |
| 199 | 201 | b.recordJoinPart(e.Params[0], e.Source.Name) |
| 200 | 202 | }) |
| 203 | + | |
| 204 | + router := cmdparse.NewRouter(b.cfg.Nick) | |
| 205 | + router.Register(cmdparse.Command{ | |
| 206 | + Name: "status", | |
| 207 | + Usage: "STATUS", | |
| 208 | + Description: "show current active alerts", | |
| 209 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 210 | + }) | |
| 211 | + router.Register(cmdparse.Command{ | |
| 212 | + Name: "acknowledge", | |
| 213 | + Usage: "ACKNOWLEDGE <alert-id>", | |
| 214 | + Description: "acknowledge an alert", | |
| 215 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 216 | + }) | |
| 201 | 217 | |
| 202 | 218 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 203 | 219 | if len(e.Params) < 1 || e.Source == nil { |
| 204 | 220 | return |
| 221 | + } | |
| 222 | + // Dispatch commands (DMs and channel messages). | |
| 223 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 224 | + c.Cmd.Message(reply.Target, reply.Text) | |
| 225 | + return | |
| 205 | 226 | } |
| 206 | 227 | channel := e.Params[0] |
| 207 | 228 | nick := e.Source.Name |
| 208 | 229 | if nick == b.cfg.Nick { |
| 209 | 230 | return |
| 210 | 231 |
| --- internal/bots/snitch/snitch.go | |
| +++ internal/bots/snitch/snitch.go | |
| @@ -17,10 +17,12 @@ | |
| 17 | "strings" |
| 18 | "sync" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | ) |
| 23 | |
| 24 | const defaultNick = "snitch" |
| 25 | |
| 26 | // Config controls snitch's thresholds and alert destination. |
| @@ -196,14 +198,33 @@ | |
| 196 | if len(e.Params) < 1 || e.Source == nil { |
| 197 | return |
| 198 | } |
| 199 | b.recordJoinPart(e.Params[0], e.Source.Name) |
| 200 | }) |
| 201 | |
| 202 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 203 | if len(e.Params) < 1 || e.Source == nil { |
| 204 | return |
| 205 | } |
| 206 | channel := e.Params[0] |
| 207 | nick := e.Source.Name |
| 208 | if nick == b.cfg.Nick { |
| 209 | return |
| 210 |
| --- internal/bots/snitch/snitch.go | |
| +++ internal/bots/snitch/snitch.go | |
| @@ -17,10 +17,12 @@ | |
| 17 | "strings" |
| 18 | "sync" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | |
| 23 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 24 | ) |
| 25 | |
| 26 | const defaultNick = "snitch" |
| 27 | |
| 28 | // Config controls snitch's thresholds and alert destination. |
| @@ -196,14 +198,33 @@ | |
| 198 | if len(e.Params) < 1 || e.Source == nil { |
| 199 | return |
| 200 | } |
| 201 | b.recordJoinPart(e.Params[0], e.Source.Name) |
| 202 | }) |
| 203 | |
| 204 | router := cmdparse.NewRouter(b.cfg.Nick) |
| 205 | router.Register(cmdparse.Command{ |
| 206 | Name: "status", |
| 207 | Usage: "STATUS", |
| 208 | Description: "show current active alerts", |
| 209 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 210 | }) |
| 211 | router.Register(cmdparse.Command{ |
| 212 | Name: "acknowledge", |
| 213 | Usage: "ACKNOWLEDGE <alert-id>", |
| 214 | Description: "acknowledge an alert", |
| 215 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 216 | }) |
| 217 | |
| 218 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 219 | if len(e.Params) < 1 || e.Source == nil { |
| 220 | return |
| 221 | } |
| 222 | // Dispatch commands (DMs and channel messages). |
| 223 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 224 | c.Cmd.Message(reply.Target, reply.Text) |
| 225 | return |
| 226 | } |
| 227 | channel := e.Params[0] |
| 228 | nick := e.Source.Name |
| 229 | if nick == b.cfg.Nick { |
| 230 | return |
| 231 |
| --- internal/bots/steward/steward.go | ||
| +++ internal/bots/steward/steward.go | ||
| @@ -29,10 +29,12 @@ | ||
| 29 | 29 | "strings" |
| 30 | 30 | "sync" |
| 31 | 31 | "time" |
| 32 | 32 | |
| 33 | 33 | "github.com/lrstanley/girc" |
| 34 | + | |
| 35 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 34 | 36 | ) |
| 35 | 37 | |
| 36 | 38 | const defaultNick = "steward" |
| 37 | 39 | |
| 38 | 40 | // Config controls steward's behaviour. |
| @@ -145,14 +147,39 @@ | ||
| 145 | 147 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 146 | 148 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 147 | 149 | cl.Cmd.Join(ch) |
| 148 | 150 | } |
| 149 | 151 | }) |
| 152 | + | |
| 153 | + router := cmdparse.NewRouter(b.cfg.Nick) | |
| 154 | + router.Register(cmdparse.Command{ | |
| 155 | + Name: "act", | |
| 156 | + Usage: "ACT <incident-id>", | |
| 157 | + Description: "manually trigger action on incident", | |
| 158 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 159 | + }) | |
| 160 | + router.Register(cmdparse.Command{ | |
| 161 | + Name: "override", | |
| 162 | + Usage: "OVERRIDE <incident-id>", | |
| 163 | + Description: "override pending action", | |
| 164 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 165 | + }) | |
| 166 | + router.Register(cmdparse.Command{ | |
| 167 | + Name: "status", | |
| 168 | + Usage: "STATUS", | |
| 169 | + Description: "show current pending actions", | |
| 170 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 171 | + }) | |
| 150 | 172 | |
| 151 | 173 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 152 | 174 | if len(e.Params) < 1 || e.Source == nil { |
| 153 | 175 | return |
| 176 | + } | |
| 177 | + // Dispatch commands (DMs and channel messages). | |
| 178 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 179 | + c.Cmd.Message(reply.Target, reply.Text) | |
| 180 | + return | |
| 154 | 181 | } |
| 155 | 182 | target := e.Params[0] |
| 156 | 183 | nick := e.Source.Name |
| 157 | 184 | text := strings.TrimSpace(e.Last()) |
| 158 | 185 | |
| 159 | 186 |
| --- internal/bots/steward/steward.go | |
| +++ internal/bots/steward/steward.go | |
| @@ -29,10 +29,12 @@ | |
| 29 | "strings" |
| 30 | "sync" |
| 31 | "time" |
| 32 | |
| 33 | "github.com/lrstanley/girc" |
| 34 | ) |
| 35 | |
| 36 | const defaultNick = "steward" |
| 37 | |
| 38 | // Config controls steward's behaviour. |
| @@ -145,14 +147,39 @@ | |
| 145 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 146 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 147 | cl.Cmd.Join(ch) |
| 148 | } |
| 149 | }) |
| 150 | |
| 151 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 152 | if len(e.Params) < 1 || e.Source == nil { |
| 153 | return |
| 154 | } |
| 155 | target := e.Params[0] |
| 156 | nick := e.Source.Name |
| 157 | text := strings.TrimSpace(e.Last()) |
| 158 | |
| 159 |
| --- internal/bots/steward/steward.go | |
| +++ internal/bots/steward/steward.go | |
| @@ -29,10 +29,12 @@ | |
| 29 | "strings" |
| 30 | "sync" |
| 31 | "time" |
| 32 | |
| 33 | "github.com/lrstanley/girc" |
| 34 | |
| 35 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 36 | ) |
| 37 | |
| 38 | const defaultNick = "steward" |
| 39 | |
| 40 | // Config controls steward's behaviour. |
| @@ -145,14 +147,39 @@ | |
| 147 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 148 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 149 | cl.Cmd.Join(ch) |
| 150 | } |
| 151 | }) |
| 152 | |
| 153 | router := cmdparse.NewRouter(b.cfg.Nick) |
| 154 | router.Register(cmdparse.Command{ |
| 155 | Name: "act", |
| 156 | Usage: "ACT <incident-id>", |
| 157 | Description: "manually trigger action on incident", |
| 158 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 159 | }) |
| 160 | router.Register(cmdparse.Command{ |
| 161 | Name: "override", |
| 162 | Usage: "OVERRIDE <incident-id>", |
| 163 | Description: "override pending action", |
| 164 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 165 | }) |
| 166 | router.Register(cmdparse.Command{ |
| 167 | Name: "status", |
| 168 | Usage: "STATUS", |
| 169 | Description: "show current pending actions", |
| 170 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 171 | }) |
| 172 | |
| 173 | c.Handlers.AddBg(girc.PRIVMSG, func(_ *girc.Client, e girc.Event) { |
| 174 | if len(e.Params) < 1 || e.Source == nil { |
| 175 | return |
| 176 | } |
| 177 | // Dispatch commands (DMs and channel messages). |
| 178 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 179 | c.Cmd.Message(reply.Target, reply.Text) |
| 180 | return |
| 181 | } |
| 182 | target := e.Params[0] |
| 183 | nick := e.Source.Name |
| 184 | text := strings.TrimSpace(e.Last()) |
| 185 | |
| 186 |
| --- internal/bots/systembot/systembot.go | ||
| +++ internal/bots/systembot/systembot.go | ||
| @@ -17,10 +17,12 @@ | ||
| 17 | 17 | "strconv" |
| 18 | 18 | "strings" |
| 19 | 19 | "time" |
| 20 | 20 | |
| 21 | 21 | "github.com/lrstanley/girc" |
| 22 | + | |
| 23 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 22 | 24 | ) |
| 23 | 25 | |
| 24 | 26 | const botNick = "systembot" |
| 25 | 27 | |
| 26 | 28 | // EntryKind classifies a system event. |
| @@ -177,10 +179,35 @@ | ||
| 177 | 179 | if e.Source != nil { |
| 178 | 180 | nick = e.Source.Name |
| 179 | 181 | } |
| 180 | 182 | b.write(Entry{Kind: KindMode, Channel: channel, Nick: nick, Text: strings.Join(e.Params, " ")}) |
| 181 | 183 | }) |
| 184 | + | |
| 185 | + router := cmdparse.NewRouter(botNick) | |
| 186 | + router.Register(cmdparse.Command{ | |
| 187 | + Name: "status", | |
| 188 | + Usage: "STATUS", | |
| 189 | + Description: "show connected users and channel counts", | |
| 190 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 191 | + }) | |
| 192 | + router.Register(cmdparse.Command{ | |
| 193 | + Name: "who", | |
| 194 | + Usage: "WHO [#channel]", | |
| 195 | + Description: "show detailed user list", | |
| 196 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 197 | + }) | |
| 198 | + | |
| 199 | + c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { | |
| 200 | + if len(e.Params) < 1 || e.Source == nil { | |
| 201 | + return | |
| 202 | + } | |
| 203 | + // Dispatch commands (DMs and channel messages). | |
| 204 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 205 | + cl.Cmd.Message(reply.Target, reply.Text) | |
| 206 | + return | |
| 207 | + } | |
| 208 | + }) | |
| 182 | 209 | |
| 183 | 210 | b.client = c |
| 184 | 211 | |
| 185 | 212 | errCh := make(chan error, 1) |
| 186 | 213 | go func() { |
| 187 | 214 |
| --- internal/bots/systembot/systembot.go | |
| +++ internal/bots/systembot/systembot.go | |
| @@ -17,10 +17,12 @@ | |
| 17 | "strconv" |
| 18 | "strings" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | ) |
| 23 | |
| 24 | const botNick = "systembot" |
| 25 | |
| 26 | // EntryKind classifies a system event. |
| @@ -177,10 +179,35 @@ | |
| 177 | if e.Source != nil { |
| 178 | nick = e.Source.Name |
| 179 | } |
| 180 | b.write(Entry{Kind: KindMode, Channel: channel, Nick: nick, Text: strings.Join(e.Params, " ")}) |
| 181 | }) |
| 182 | |
| 183 | b.client = c |
| 184 | |
| 185 | errCh := make(chan error, 1) |
| 186 | go func() { |
| 187 |
| --- internal/bots/systembot/systembot.go | |
| +++ internal/bots/systembot/systembot.go | |
| @@ -17,10 +17,12 @@ | |
| 17 | "strconv" |
| 18 | "strings" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | |
| 23 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 24 | ) |
| 25 | |
| 26 | const botNick = "systembot" |
| 27 | |
| 28 | // EntryKind classifies a system event. |
| @@ -177,10 +179,35 @@ | |
| 179 | if e.Source != nil { |
| 180 | nick = e.Source.Name |
| 181 | } |
| 182 | b.write(Entry{Kind: KindMode, Channel: channel, Nick: nick, Text: strings.Join(e.Params, " ")}) |
| 183 | }) |
| 184 | |
| 185 | router := cmdparse.NewRouter(botNick) |
| 186 | router.Register(cmdparse.Command{ |
| 187 | Name: "status", |
| 188 | Usage: "STATUS", |
| 189 | Description: "show connected users and channel counts", |
| 190 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 191 | }) |
| 192 | router.Register(cmdparse.Command{ |
| 193 | Name: "who", |
| 194 | Usage: "WHO [#channel]", |
| 195 | Description: "show detailed user list", |
| 196 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 197 | }) |
| 198 | |
| 199 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 200 | if len(e.Params) < 1 || e.Source == nil { |
| 201 | return |
| 202 | } |
| 203 | // Dispatch commands (DMs and channel messages). |
| 204 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 205 | cl.Cmd.Message(reply.Target, reply.Text) |
| 206 | return |
| 207 | } |
| 208 | }) |
| 209 | |
| 210 | b.client = c |
| 211 | |
| 212 | errCh := make(chan error, 1) |
| 213 | go func() { |
| 214 |
+33
-1
| --- internal/bots/warden/warden.go | ||
| +++ internal/bots/warden/warden.go | ||
| @@ -18,10 +18,11 @@ | ||
| 18 | 18 | "sync" |
| 19 | 19 | "time" |
| 20 | 20 | |
| 21 | 21 | "github.com/lrstanley/girc" |
| 22 | 22 | |
| 23 | + "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" | |
| 23 | 24 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 24 | 25 | ) |
| 25 | 26 | |
| 26 | 27 | const botNick = "warden" |
| 27 | 28 | |
| @@ -216,18 +217,49 @@ | ||
| 216 | 217 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 217 | 218 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 218 | 219 | cl.Cmd.Join(ch) |
| 219 | 220 | } |
| 220 | 221 | }) |
| 222 | + | |
| 223 | + router := cmdparse.NewRouter(botNick) | |
| 224 | + router.Register(cmdparse.Command{ | |
| 225 | + Name: "warn", | |
| 226 | + Usage: "WARN <nick> [reason]", | |
| 227 | + Description: "issue a warning to a user", | |
| 228 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 229 | + }) | |
| 230 | + router.Register(cmdparse.Command{ | |
| 231 | + Name: "mute", | |
| 232 | + Usage: "MUTE <nick> [duration]", | |
| 233 | + Description: "mute a user", | |
| 234 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 235 | + }) | |
| 236 | + router.Register(cmdparse.Command{ | |
| 237 | + Name: "kick", | |
| 238 | + Usage: "KICK <nick> [reason]", | |
| 239 | + Description: "kick a user from channel", | |
| 240 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 241 | + }) | |
| 242 | + router.Register(cmdparse.Command{ | |
| 243 | + Name: "status", | |
| 244 | + Usage: "STATUS", | |
| 245 | + Description: "show current warnings and mutes", | |
| 246 | + Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, | |
| 247 | + }) | |
| 221 | 248 | |
| 222 | 249 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 223 | 250 | if len(e.Params) < 1 || e.Source == nil { |
| 224 | 251 | return |
| 252 | + } | |
| 253 | + // Dispatch commands (DMs and channel messages). | |
| 254 | + if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { | |
| 255 | + cl.Cmd.Message(reply.Target, reply.Text) | |
| 256 | + return | |
| 225 | 257 | } |
| 226 | 258 | channel := e.Params[0] |
| 227 | 259 | if !strings.HasPrefix(channel, "#") { |
| 228 | - return | |
| 260 | + return // non-command DMs ignored | |
| 229 | 261 | } |
| 230 | 262 | nick := e.Source.Name |
| 231 | 263 | text := e.Last() |
| 232 | 264 | |
| 233 | 265 | cs := b.channelStateFor(channel) |
| 234 | 266 |
| --- internal/bots/warden/warden.go | |
| +++ internal/bots/warden/warden.go | |
| @@ -18,10 +18,11 @@ | |
| 18 | "sync" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | |
| 23 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 24 | ) |
| 25 | |
| 26 | const botNick = "warden" |
| 27 | |
| @@ -216,18 +217,49 @@ | |
| 216 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 217 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 218 | cl.Cmd.Join(ch) |
| 219 | } |
| 220 | }) |
| 221 | |
| 222 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 223 | if len(e.Params) < 1 || e.Source == nil { |
| 224 | return |
| 225 | } |
| 226 | channel := e.Params[0] |
| 227 | if !strings.HasPrefix(channel, "#") { |
| 228 | return |
| 229 | } |
| 230 | nick := e.Source.Name |
| 231 | text := e.Last() |
| 232 | |
| 233 | cs := b.channelStateFor(channel) |
| 234 |
| --- internal/bots/warden/warden.go | |
| +++ internal/bots/warden/warden.go | |
| @@ -18,10 +18,11 @@ | |
| 18 | "sync" |
| 19 | "time" |
| 20 | |
| 21 | "github.com/lrstanley/girc" |
| 22 | |
| 23 | "github.com/conflicthq/scuttlebot/internal/bots/cmdparse" |
| 24 | "github.com/conflicthq/scuttlebot/pkg/protocol" |
| 25 | ) |
| 26 | |
| 27 | const botNick = "warden" |
| 28 | |
| @@ -216,18 +217,49 @@ | |
| 217 | c.Handlers.AddBg(girc.INVITE, func(cl *girc.Client, e girc.Event) { |
| 218 | if ch := e.Last(); strings.HasPrefix(ch, "#") { |
| 219 | cl.Cmd.Join(ch) |
| 220 | } |
| 221 | }) |
| 222 | |
| 223 | router := cmdparse.NewRouter(botNick) |
| 224 | router.Register(cmdparse.Command{ |
| 225 | Name: "warn", |
| 226 | Usage: "WARN <nick> [reason]", |
| 227 | Description: "issue a warning to a user", |
| 228 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 229 | }) |
| 230 | router.Register(cmdparse.Command{ |
| 231 | Name: "mute", |
| 232 | Usage: "MUTE <nick> [duration]", |
| 233 | Description: "mute a user", |
| 234 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 235 | }) |
| 236 | router.Register(cmdparse.Command{ |
| 237 | Name: "kick", |
| 238 | Usage: "KICK <nick> [reason]", |
| 239 | Description: "kick a user from channel", |
| 240 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 241 | }) |
| 242 | router.Register(cmdparse.Command{ |
| 243 | Name: "status", |
| 244 | Usage: "STATUS", |
| 245 | Description: "show current warnings and mutes", |
| 246 | Handler: func(_ *cmdparse.Context, _ string) string { return "not implemented yet" }, |
| 247 | }) |
| 248 | |
| 249 | c.Handlers.AddBg(girc.PRIVMSG, func(cl *girc.Client, e girc.Event) { |
| 250 | if len(e.Params) < 1 || e.Source == nil { |
| 251 | return |
| 252 | } |
| 253 | // Dispatch commands (DMs and channel messages). |
| 254 | if reply := router.Dispatch(e.Source.Name, e.Params[0], e.Last()); reply != nil { |
| 255 | cl.Cmd.Message(reply.Target, reply.Text) |
| 256 | return |
| 257 | } |
| 258 | channel := e.Params[0] |
| 259 | if !strings.HasPrefix(channel, "#") { |
| 260 | return // non-command DMs ignored |
| 261 | } |
| 262 | nick := e.Source.Name |
| 263 | text := e.Last() |
| 264 | |
| 265 | cs := b.channelStateFor(channel) |
| 266 |