176 lines
4.3 KiB
Go
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)
|
|
}
|