sox/main.go
2026-01-21 20:33:17 -07:00

176 lines
4.3 KiB
Go

package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"os/exec"
"bytes"
// "log"
"time"
"strings"
)
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 main() {
fmt.Println("Sox started")
http.HandleFunc("/", commandHandler)
port := os.Getenv("PORT")
if port == "" {
port = "8096"
}
panic(http.ListenAndServe(":"+port, nil))
}
func SplitFirstWord(input string) (firstWord string, restOfString string) {
words := strings.Fields(input)
if len(words) == 0 {
return "", ""
}
firstWord = words[0]
restOfString = strings.Join(words[1:], " ")
return strings.ToLower(firstWord), restOfString
}
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, "-999nopreviouscommand", ""))
return
}
func executeCommand(msg BotMessage, c string, b string)(string) {
fmt.Println("Last command: " + c)
command, arguments := SplitFirstWord(msg.Message.Body.Plain)
// value, exists := userLastCommandType[msg.User.Name]
if c != "-999nopreviouscommand" {
command = c
}
switch command {
case "ping":
fmt.Println("ping command received")
userLastCommandType[msg.User.Name] = command;
return "Pong!"
// case "trace":
// fmt.Println("trace command received")
// var j = traceHandler(w, r, arguments, msg.User.Name)
// return j
case "math":
userLastCommandType[msg.User.Name] = command;
return runMath(b+arguments)
case "hi":
userLastCommandType[msg.User.Name] = command;
return "Hello " + msg.User.Name + "! How are you doing today?"
default:
value, exists := userLastCommandType[msg.User.Name]
if exists {
return executeCommand(msg, value, command)
} else {
c = "-999invalidcommand"
return "Command is: " + command + " arguments are: " + arguments + ". Not sure what to do..."
}
}
// if c != "-999invalidcommand" {
// userLastCommandType[msg.User.Name] = command;
// }
return "error"
}
func runMath(s string)(string){
cmd := exec.Command("qalc", s)
// cmd.Stdin = strings.NewReader("and old falcon")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
// log.Warn(err)
fmt.Println(err)
}
return out.String()
// fmt.Printf("translated phrase: %q\n", out.String())
}
func traceHandler(w http.ResponseWriter, r *http.Request, urlstring string, username string)(string) {
var msg BotMessage
err := json.NewDecoder(r.Body).Decode(&msg)
uri, err := url.Parse(urlstring)
if err != nil || (uri.Scheme != "http" && uri.Scheme != "https") {
return "That doesn't look like a valid URL for to me to call"
}
response, err := timeRequest(username, uri)
if err != nil {
// fmt.Fprintf(w, "Failed to time the request (%s)", err)
// return
return "Failed to time the request " //+ err
}
// fmt.Fprintln(w, response)
return response
}
func timeRequest(username string, uri *url.URL) (string, error) {
trace, err := TraceRequest(uri)
if err != nil {
return "", err
}
result := fmt.Sprintf("Hi %s! I've checked %s for you, and here's what I found:<br><br>\n", username, uri)
result += formatDuration("DNS lookup", trace.DNSStart, trace.DNSDone)
result += formatDuration("Connect", trace.ConnectStart, trace.ConnectDone)
result += formatDuration("TLS negotiation", trace.TLSStart, trace.TLSDone)
result += formatDuration("Sending headers", trace.ConnectionReady(), trace.WroteHeaders)
result += formatDuration("Time to first byte", trace.WroteHeaders, trace.FirstByte)
result += formatDuration("Time to last byte", trace.WroteHeaders, trace.AllDone)
return result, nil
}
func errorResponse(w http.ResponseWriter, status int, msg string) {
w.WriteHeader(status)
fmt.Fprintf(w, "Error: %s", msg)
}
func formatDuration(label string, start, end time.Time) string {
dur := end.Sub(start).String()
if start.IsZero() || end.IsZero() {
dur = "n/a"
}
return fmt.Sprintf("%s: <strong>%s</strong><br>\n", label, dur)
}