package main import ( "github.com/atotto/clipboard" "github.com/getlantern/systray" "io/ioutil" "log" "math/rand" "meow.tf/streamdeck-remote-server/icon" "net/http" "net/url" "os" "strings" "time" ) func init() { rand.Seed(time.Now().UnixNano()) } func main() { systray.Run(onReady, onExit) } func onReady() { systray.SetIcon(icon.Data) systray.SetTitle("StreamDeck Remote") systray.SetTooltip("StreamDeck Remote Server (Running)") mCopy := systray.AddMenuItem("Copy Token", "Copy the token to the clipboard") mQuit := systray.AddMenuItem("Quit", "Close StreamDeck Remote Server") go listenServer() go func() { for { select { case <-mCopy.ClickedCh: clipboard.WriteAll(token) case <-mQuit.ClickedCh: systray.Quit() } } }() } func onExit() { // clean up here } var ( token string ) func loadToken() { if _, err := os.Stat("token.txt"); os.IsNotExist(err) { token = RandStringRunes(32) f, err := os.Create("token.txt") if err != nil { log.Fatalln("Unable to save token:", err) } defer f.Close() f.WriteString(token) } else { f, err := os.Open("token.txt") if err != nil { log.Fatalln("Unable to open token file:", err) } defer f.Close() b, err := ioutil.ReadAll(f) if err != nil { f.Close() log.Fatalln("Unable to read token file:", err) } token = string(b) } } func listenServer() { loadToken() if _, err := os.Stat("server.crt"); os.IsNotExist(err) { err = generateCert("server.crt", "server.key") if err != nil { log.Fatalln("Unable to generate certificates:", err) } } mux := http.NewServeMux() mux.HandleFunc("/url/open", authenticationHandler(requirePost(urlOpenHandler))) http.ListenAndServeTLS(":4443", "server.crt", "server.key", mux) } func authenticationHandler(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // Check authorization header auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2) if len(auth) != 2 || auth[0] != "Bearer" || auth[1] != token { log.Println("Authentication failed, got:", auth[1]) http.Error(w, "authorization failed", http.StatusUnauthorized) return } next(w, r) } } func urlOpenHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() urlStr := r.Form.Get("url") if urlStr == "" { w.WriteHeader(http.StatusBadRequest) log.Println("empty url") return } u, err := url.Parse(urlStr) if err != nil || u.Scheme == "" || u.Host == "" { w.WriteHeader(http.StatusBadRequest) log.Println("invalid url scheme/host or err:", err) return } log.Println("Opening URL", urlStr) openUrl(urlStr) }