sox/main.go
Waldo 0b2e83ba0c Fix test isolation bug and refactor command handling into plugins
Use unique user in unknown command test to avoid last-command fallback
interference. Add plugin architecture with registered commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 21:27:53 -07:00

87 lines
1.7 KiB
Go

package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type BotMessage struct {
User struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"user"`
Room struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"room"`
Message struct {
ID int `json:"id"`
Body struct {
HTML string `json:"html"`
Plain string `json:"plain"`
} `json:"body"`
} `json:"message"`
}
var userLastCommandType = make(map[string]string)
func init() {
registerPlugin(PingPlugin{})
registerPlugin(MathPlugin{})
registerPlugin(HiPlugin{})
registerPlugin(TracePlugin{})
registerPlugin(HelpPlugin{})
}
func main() {
fmt.Println("Sox started")
http.HandleFunc("/", commandHandler)
port := os.Getenv("PORT")
if port == "" {
port = "4567"
}
panic(http.ListenAndServe(":"+port, nil))
}
func commandHandler(w http.ResponseWriter, r *http.Request) {
var msg BotMessage
err := json.NewDecoder(r.Body).Decode(&msg)
if err != nil {
errorResponse(w, http.StatusBadRequest, "invalid request body")
return
}
fmt.Fprintln(w, executeCommand(msg))
}
func executeCommand(msg BotMessage) string {
command, arguments := SplitFirstWord(msg.Message.Body.Plain)
if p, ok := registry[command]; ok {
if command != "help" {
userLastCommandType[msg.User.Name] = command
}
return p.Execute(msg, arguments)
}
// Fall back to last command, treating full message as new args
if last, ok := userLastCommandType[msg.User.Name]; ok {
if p, ok := registry[last]; ok {
return p.Execute(msg, msg.Message.Body.Plain)
}
}
return "Not sure what to do... Try `help` to see what I can do!"
}
func errorResponse(w http.ResponseWriter, status int, msg string) {
w.WriteHeader(status)
fmt.Fprintf(w, "Error: %s", msg)
}