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) SimklLogin() { if (SimklJWT{}) == simklJwt { tokenType, err := simklRing.Get("SimklTokenType") accessToken, err := simklRing.Get("SimklAccessToken") scope, err := simklRing.Get("SimklScope") if err != nil { 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) { srv := &http.Server{Addr: ":6734"} http.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) GetSimklLoggedInUserId() SimklUser { a.SimklLogin() body := struct { Query string `json:"query"` }{ Query: ` query { Viewer { id name } } `, } user, _ := SimklQuery(body, true) var post SimklUser err := json.Unmarshal(user, &post) if err != nil { log.Printf("Failed at unmarshal, %s\n", err) } return post }