package main import ( "bytes" "context" "encoding/json" "fmt" "io" "log" "net/http" "os" "sync" "github.com/99designs/keyring" "github.com/wailsapp/wails/v2/pkg/runtime" ) var simklJwt SimklJWT var simklRing, _ = keyring.Open(keyring.Config{ ServiceName: "AniTrack", }) var simklCtxShutdown, simklCancel = context.WithCancel(context.Background()) func (a *App) CheckIfSimklLoggedIn() bool { if (SimklJWT{} == simklJwt) { tokenType, err := simklRing.Get("SimklTokenType") accessToken, err := simklRing.Get("SimklAccessToken") scope, err := simklRing.Get("SimklScope") if err != nil || len(accessToken.Data) == 0 { return false } else { simklJwt.TokenType = string(tokenType.Data) simklJwt.AccessToken = string(accessToken.Data) simklJwt.Scope = string(scope.Data) return true } } else { return true } } func (a *App) SimklLogin() { if a.CheckIfSimklLoggedIn() == false { tokenType, err := simklRing.Get("SimklTokenType") accessToken, err := simklRing.Get("SimklAccessToken") scope, err := simklRing.Get("SimklScope") if err != nil || len(accessToken.Data) == 0 { getSimklCodeUrl := "https://simkl.com/oauth/authorize?response_type=code&client_id=" + os.Getenv("SIMKL_CLIENT_ID") + "&redirect_uri=" + os.Getenv("SIMKL_CALLBACK_URI") runtime.BrowserOpenURL(a.ctx, getSimklCodeUrl) serverDone := &sync.WaitGroup{} serverDone.Add(1) handleSimklCallback(serverDone) serverDone.Wait() } else { simklJwt.TokenType = string(tokenType.Data) simklJwt.AccessToken = string(accessToken.Data) simklJwt.Scope = string(scope.Data) } } } func handleSimklCallback(wg *sync.WaitGroup) { mux := http.NewServeMux() srv := &http.Server{Addr: ":6734", Handler: mux} mux.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) { select { case <-simklCtxShutdown.Done(): fmt.Println("Shutting down...") return default: } content := r.FormValue("code") if content != "" { simklJwt = getSimklAuthorizationToken(content) _ = simklRing.Set(keyring.Item{ Key: "SimklTokenType", Data: []byte(simklJwt.TokenType), }) _ = simklRing.Set(keyring.Item{ Key: "SimklAccessToken", Data: []byte(simklJwt.AccessToken), }) _ = simklRing.Set(keyring.Item{ Key: "SimklScope", Data: []byte(simklJwt.Scope), }) fmt.Println("Shutting down...") simklCancel() err := srv.Shutdown(context.Background()) if err != nil { log.Println("server.Shutdown:", err) } } else { _, err := fmt.Fprintf(w, "Getting code failed.") if err != nil { return } } }) go func() { defer wg.Done() if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %s\n", err) } fmt.Println("Shutting down...") }() } func getSimklAuthorizationToken(content string) SimklJWT { data := struct { GrantType string `json:"grant_type"` ClientID string `json:"client_id"` ClientSecret string `json:"client_secret"` RedirectURI string `json:"redirect_uri"` Code string `json:"code"` }{ GrantType: "authorization_code", ClientID: os.Getenv("SIMKL_CLIENT_ID"), ClientSecret: os.Getenv("SIMKL_CLIENT_SECRET"), RedirectURI: os.Getenv("SIMKL_CALLBACK_URI"), Code: content, } jsonData, err := json.Marshal(data) if err != nil { log.Fatal(err) } response, err := http.NewRequest("POST", "https://api.simkl.com/oauth/token", bytes.NewBuffer(jsonData)) if err != nil { log.Printf("Failed at response, %s\n", err) } response.Header.Add("Content-Type", "application/json") client := &http.Client{} res, reserr := client.Do(response) if reserr != nil { log.Printf("Failed at res, %s\n", err) } defer res.Body.Close() returnedBody, err := io.ReadAll(res.Body) var post SimklJWT err = json.Unmarshal(returnedBody, &post) if err != nil { log.Printf("Failed at unmarshal, %s\n", err) } return post } func (a *App) GetSimklLoggedInUser() SimklUser { a.SimklLogin() client := &http.Client{} req, _ := http.NewRequest("POST", "https://api.simkl.com/users/settings", nil) req.Header.Add("Content-Type", "application/json") req.Header.Add("Authorization", "Bearer "+simklJwt.AccessToken) req.Header.Add("simkl-api-key", os.Getenv("SIMKL_CLIENT_ID")) response, err := client.Do(req) if err != nil { log.Printf("Failed at request, %s\n", err) return SimklUser{} } defer response.Body.Close() var user SimklUser respBody, _ := io.ReadAll(response.Body) err = json.Unmarshal(respBody, &user) if err != nil { log.Printf("Failed at unmarshal, %s\n", err) } return user }