package main import ( "encoding/json" "fmt" "io" "log" "net/http" "os" "raindrop-glance/raindrop" ) func sendJSON(w http.ResponseWriter, data any, status int) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) if err := json.NewEncoder(w).Encode(data); err != nil { http.Error(w, err.Error(), 500) } } func main() { authConfigPath := os.Getenv("AUTH_CONFIG") if authConfigPath == "" { log.Fatalf("AUTH_CONFIG env is missing") } if _, err := os.Stat(authConfigPath); os.IsNotExist(err) { os.Create(authConfigPath) os.WriteFile(authConfigPath, []byte("{}"), 0644) } data, err := os.ReadFile(authConfigPath) if err != nil { log.Fatalf("failed to read auth config file: %v\n", err) } config := new(raindrop.TokensResponse) if err := json.Unmarshal(data, config); err != nil { log.Fatalf("failed to decode auth config file: %v\n", err) } rdClient, err := raindrop.NewClient(raindrop.ClientConfig{ ClientId: os.Getenv("CLIENT_ID"), ClientSecret: os.Getenv("CLIENT_SECRET"), RedirectURI: os.Getenv("REDIRECT_URI"), }) if err != nil { log.Fatalf("failed to create raindrop client: %v\n", err) } if config.AccessToken != "" { rdClient.SetApiToken(config.TokenType, config.AccessToken) } mux := http.NewServeMux() mux.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) { rdClient.OauthRedirect(w, r) }) mux.HandleFunc("GET /oauth/redirect", func(w http.ResponseWriter, r *http.Request) { code := r.URL.Query().Get("code") if code == "" { http.Error(w, "invalid request", 400) return } resp, err := rdClient.ExchangeOauthCode(code) if err != nil { http.Error(w, err.Error(), 500) return } config = resp jsonData, err := json.MarshalIndent(resp, "", " ") if err != nil { http.Error(w, fmt.Sprintf("failed to encode config file: %v", err), 500) return } if err := os.WriteFile(authConfigPath, jsonData, 0644); err != nil { http.Error(w, fmt.Sprintf("failed to save config file: %v", err), 500) return } rdClient.SetApiToken(resp.TokenType, resp.AccessToken) w.WriteHeader(200) fmt.Fprintf(w, "ok") }) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { baseURL := "https://api.raindrop.io/rest/v1" req, err := http.NewRequest(r.Method, baseURL+r.URL.Path, r.Body) if err != nil { http.Error(w, fmt.Sprintf("failed to create request: %v", err), 500) return } req.URL.RawQuery = r.URL.RawQuery if config.AccessToken != "" { authHeader := fmt.Sprintf("%s %s", config.TokenType, config.AccessToken) req.Header.Add("Authorization", authHeader) } resp, err := http.DefaultClient.Do(req) if err != nil { http.Error(w, err.Error(), 500) return } defer resp.Body.Close() for header, values := range resp.Header { for _, v := range values { w.Header().Add(header, v) } } if _, err := io.Copy(w, resp.Body); err != nil { http.Error(w, err.Error(), 500) } // data, err, status := rdClient.MakeApiRequest(r.Method, r.URL.Path, r.Body, r.URL.Query()) // if err != nil { // http.Error(w, err.Error(), status) // return // } // w.Header().Set("Content-Type", "application/json") // w.WriteHeader(status) // w.Write(data) }) log.Println("starting http server") if err := http.ListenAndServe(":5000", mux); err != nil { log.Fatalf("failed to start http server: %v\n", err) } }