anitrack/SimklUserFunctions.go

210 lines
5.1 KiB
Go

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)
a.handleSimklCallback(serverDone)
serverDone.Wait()
} else {
simklJwt.TokenType = string(tokenType.Data)
simklJwt.AccessToken = string(accessToken.Data)
simklJwt.Scope = string(scope.Data)
}
}
}
func (a *App) 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),
})
_, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
Title: "Simkl Authorization",
Message: "It is now safe to close your browser tab",
})
if err != nil {
log.Println(err)
}
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
}
func (a *App) LogoutSimkl() string {
if (SimklJWT{} != simklJwt) {
err := simklRing.Remove("SimklTokenType")
err = simklRing.Remove("SimklAccessToken")
err = simklRing.Remove("SimklScope")
if err != nil {
fmt.Println("Simkl Logout Failed", err)
}
}
return "Simkl Logged Out Successfully"
}