package main import ( "embed" "encoding/json" "fmt" "io" "net/http" "strings" "github.com/go-chi/chi" ) //go:embed dist/* var fs embed.FS type entity struct { AvatarURL *string `json:"avatar_url"` IconURL *string `json:"icon_url"` Description *string `json:"description"` Color *string `json:"color"` } var baseURL = "https://api.pluralkit.me/v2" var version = "dev" const defaultEmbed = ` ` func main() { r := chi.NewRouter() r.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { rw.Header().Set("X-PluralKit-Version", version) next.ServeHTTP(rw, r) }) }) r.NotFound(notFoundHandler) r.Get("/profile/{type}/{id}", func(rw http.ResponseWriter, r *http.Request) { defer func() { if a := recover(); a != nil { notFoundHandler(rw, r) return } }() createEmbed(rw, r) }) http.ListenAndServe(":8080", r) } func notFoundHandler(rw http.ResponseWriter, r *http.Request) { var data []byte var err error // lol if strings.HasSuffix(r.URL.Path, ".js") { data, err = fs.ReadFile("dist" + r.URL.Path) rw.Header().Add("content-type", "application/javascript") } else if strings.HasSuffix(r.URL.Path, ".css") { data, err = fs.ReadFile("dist" + r.URL.Path) rw.Header().Add("content-type", "text/css") } else if strings.HasSuffix(r.URL.Path, ".map") { data, err = fs.ReadFile("dist" + r.URL.Path) } else { data, err = fs.ReadFile("dist/index.html") rw.Header().Add("content-type", "text/html") data = []byte(strings.Replace(string(data), ``, defaultEmbed, 1)) } if err != nil { panic(err) } rw.Write(data) } // explanation for createEmbed: // we don't care about errors, we just want to return a HTML page as soon as possible // `panic(nil)` is caught by upstream, which then returns the raw HTML page func createEmbed(rw http.ResponseWriter, r *http.Request) { entityType := chi.URLParam(r, "type") id := chi.URLParam(r, "id") var path string switch entityType { case "s": path = "/systems/" + id case "m": path = "/members/" + id case "g": path = "/groups/" + id default: panic(nil) } res, err := http.Get(baseURL + path) if err != nil { panic(nil) } if res.StatusCode != 200 { panic(nil) } var data entity body, _ := io.ReadAll(res.Body) err = json.Unmarshal(body, &data) if err != nil { panic(nil) } text := fmt.Sprintf(`%s`, baseURL, path, "\n") if data.AvatarURL != nil { text += fmt.Sprintf(`%s`, *data.AvatarURL, "\n") } else if data.IconURL != nil { text += fmt.Sprintf(`%s`, *data.IconURL, "\n") } if data.Description != nil { text += fmt.Sprintf(`%s`, *data.Description, "\n") } if data.Color != nil { text += fmt.Sprintf(`%s`, *data.Color, "\n") } html, err := fs.ReadFile("dist/index.html") if err != nil { panic(nil) } html = []byte(strings.Replace(string(html), ``, text, 1)) rw.Header().Add("content-type", "text/html") rw.Write(html) }