package main import ( "encoding/json" "log" "net/http" "os" "strconv" "ao3scraper/ao3" ) var client *ao3.Client func main() { client = ao3.NewClient() port := os.Getenv("PORT") if port == "" { port = "8080" } mux := http.NewServeMux() mux.HandleFunc("GET /autocomplete", handleAutocomplete) mux.HandleFunc("GET /search", handleSearch) mux.HandleFunc("GET /tags/{tag}/works", handleTagWorks) mux.HandleFunc("GET /works/{id}", handleWork) log.Printf("listening on :%s", port) log.Fatal(http.ListenAndServe(":"+port, mux)) } func handleAutocomplete(w http.ResponseWriter, r *http.Request) { term := r.URL.Query().Get("term") tagType := r.URL.Query().Get("type") if term == "" { jsonError(w, "term required", http.StatusBadRequest) return } tags, err := client.AutocompleteTags(r.Context(), term, tagType) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonOK(w, tags) } func handleSearch(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() page, _ := strconv.Atoi(q.Get("page")) minWords, _ := strconv.Atoi(q.Get("min_words")) maxWords, _ := strconv.Atoi(q.Get("max_words")) result, err := client.SearchWorks(r.Context(), ao3.SearchParams{ Query: q.Get("query"), Fandom: q.Get("fandom"), Tag: q.Get("tag"), Rating: q.Get("rating"), MinWords: minWords, MaxWords: maxWords, Page: page, }) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonOK(w, result) } func handleTagWorks(w http.ResponseWriter, r *http.Request) { tag := r.PathValue("tag") page, _ := strconv.Atoi(r.URL.Query().Get("page")) result, err := client.WorksByTag(r.Context(), tag, page) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonOK(w, result) } func handleWork(w http.ResponseWriter, r *http.Request) { id, err := strconv.Atoi(r.PathValue("id")) if err != nil { jsonError(w, "invalid id", http.StatusBadRequest) return } work, err := client.GetWork(r.Context(), id) if err != nil { jsonError(w, err.Error(), http.StatusInternalServerError) return } jsonOK(w, work) } func jsonOK(w http.ResponseWriter, v any) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(v) } func jsonError(w http.ResponseWriter, msg string, code int) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) json.NewEncoder(w).Encode(map[string]string{"error": msg}) }