package main import ( "fmt" "html/template" "io" "log" "net/http" "os" "strings" "github.com/joho/godotenv" ) const youtubeAPI = "https://www.googleapis.com/youtube/v3/" var tmpl = template.Must(template.ParseFiles("templates/watch.html")) func apiRequest(w http.ResponseWriter, r *http.Request, endpoint string, videoIdParam string, part string) { videoID := r.URL.Query().Get("id") if videoID == "" { msg := "Missing ?id=VIDEO_ID parameter" http.Error(w, msg, http.StatusBadRequest) return } apiKey := os.Getenv("API_KEY") if apiKey == "" { msg := "API_KEY environment variable not set" http.Error(w, msg, http.StatusInternalServerError) log.Println(msg) return } //url := fmt.Sprintf("%s?part=snippet&id=%s&key=%s", youtubeAPI, videoID, apiKey) url := fmt.Sprintf("%s?part=%s&%s=%s&key=%s", youtubeAPI + endpoint, part, videoIdParam, videoID, apiKey) resp, err := http.Get(url) if err != nil { msg := "Failed to fetch video info: " + err.Error() http.Error(w, msg, http.StatusInternalServerError) log.Println(msg) return } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { msg := "YouTube API error: " + resp.Status http.Error(w, msg, http.StatusBadGateway) log.Println(msg) return } w.Header().Set("Content-Type", "application/json") io.Copy(w, resp.Body) } func videoDetailsHandler(w http.ResponseWriter, r *http.Request) { apiRequest(w, r, "videos", "id", "snippet,statistics,topicDetails") } func commentThreadsHandler(w http.ResponseWriter, r *http.Request) { apiRequest(w, r, "commentThreads", "videoId", "snippet,replies&maxResults=100") } func handler(w http.ResponseWriter, r *http.Request) { path := strings.Trim(r.URL.Path, "/") if path == "" { path = "world" } data := struct { Id string }{ Id: path, } err := tmpl.Execute(w, data) if err != nil { msg := "Template execution error" http.Error(w, msg, http.StatusInternalServerError) log.Println(msg) } } func main() { // load .env file if it exists godotenv.Load() // setup routes http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) http.HandleFunc("/api/details", videoDetailsHandler) http.HandleFunc("/api/comments", commentThreadsHandler) http.HandleFunc("/", handler) log.Println("Listening on http://localhost:8080") err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal(err) } }