package handlers import ( "FanslySync/structs" "encoding/json" "fmt" "io" "net/http" "time" "github.com/wailsapp/wails/v2/pkg/logger" ) type FanslyAPIController struct { client *http.Client token string logger logger.Logger } // New creates a new Fansly client with the provided token (optional). func NewFanslyAPIController(token string, log logger.Logger) *FanslyAPIController { client := &http.Client{ Timeout: 30 * time.Second, } return &FanslyAPIController{ client: client, token: token, logger: log, } } // GET issues a GET to /api/v1/{path}, optionally adding the Auth header, // and unmarshals the JSON response into the result parameter. func (f *FanslyAPIController) GET(path string, needsAuth bool, out interface{}) error { // build request url := "https://apiv3.fansly.com/api/v1/" + path req, err := http.NewRequest("GET", url, nil) if err != nil { f.logger.Error("[FanslyAPIController] NewRequest GET " + path + ": " + err.Error()) return err } // Set headers req.Header.Set("User-Agent", "FanslySync/3.0 sticks@teamhydra.dev") req.Header.Set("Accept", "application/json") // set auth if needsAuth && f.token != "" { req.Header.Set("Authorization", f.token) } // send resp, err := f.client.Do(req) if err != nil { f.logger.Error("[FanslyAPIController] Do GET " + path + ": " + err.Error()) return err } defer resp.Body.Close() // non-200 if resp.StatusCode != http.StatusOK { f.logger.Error(fmt.Sprintf("[FanslyAPIController] GET %s failed: %s", path, resp.Status)) // read body for logs body, _ := io.ReadAll(resp.Body) f.logger.Info("[FanslyAPIController] Response body: " + string(body)) return fmt.Errorf("unexpected status %s", resp.Status) } // 200 ok, log f.logger.Debug(fmt.Sprintf("[FanslyAPIController] GET %s succeeded: %s", path, resp.Status)) // read body and unmarshal body, err := io.ReadAll(resp.Body) if err != nil { f.logger.Error("[FanslyAPIController] Request was OK, but failed to read body: " + err.Error()) return err } // unmarshal into our expected response type err = json.Unmarshal(body, &out) if err != nil { f.logger.Error("[FanslyAPIController] GET " + path + " failed to unmarshal response: " + err.Error()) return err } return nil } // SetToken updates the authorization token for subsequent requests. func (f *FanslyAPIController) SetToken(token string) { f.token = token } // Returns the current user's account information from the Fansly API. // // Will error if the token is not set or the request fails. // // Returns a FanslyAccount struct containing the account information. func (f *FanslyAPIController) GetMe() (*structs.FanslyAccount, error) { var response structs.FanslyBaseResponse[structs.FanslyAccountResponse] err := f.GET("account/me", true, &response) if err != nil { f.logger.Error("[FanslyAPIController] GetMe failed: " + err.Error()) return nil, err } // Return the account info return &response.Response.Account, nil }