added information being pulled from anilist

This commit is contained in:
2024-07-24 09:18:45 -04:00
parent b1880690dc
commit 4e11b218be
6 changed files with 498 additions and 196 deletions

View File

@ -1,89 +1,13 @@
package AniList
package main
import (
"AniTrack"
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/wailsapp/wails/v2/pkg/runtime"
"io"
"log"
"net/http"
"net/url"
"os"
"strings"
"sync"
)
type AniListJWT struct {
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}
type AniListUser struct {
Data struct {
Viewer struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"Viewer"`
} `json:"data"`
}
type AniListCurrentUserWatchList struct {
Data struct {
Page struct {
PageInfo struct {
Total int `json:"total"`
PerPage int `json:"perPage"`
CurrentPage int `json:"currentPage"`
LastPage int `json:"lastPage"`
HasNextPage bool `json:"hasNextPage"`
} `json:"pageInfo"`
MediaList []struct {
ID int `json:"id"`
MediaID int `json:"mediaId"`
Media struct {
ID int `json:"id"`
IDMal int `json:"idMal"`
Title struct {
Romaji string `json:"romaji"`
English string `json:"english"`
Native string `json:"native"`
} `json:"title"`
Description string `json:"description"`
CoverImage struct {
Large string `json:"large"`
} `json:"coverImage"`
Season string `json:"season"`
SeasonYear int `json:"seasonYear"`
Episodes int `json:"episodes"`
} `json:"media"`
Status string `json:"status"`
Notes string `json:"notes"`
Progress int `json:"progress"`
Score int `json:"score"`
Repeat int `json:"repeat"`
User struct {
Statistics struct {
Anime struct {
Count int `json:"count"`
Statuses []struct {
Status string `json:"status"`
Count int `json:"count"`
} `json:"statuses"`
} `json:"anime"`
} `json:"statistics"`
} `json:"user"`
} `json:"mediaList"`
} `json:"Page"`
} `json:"data"`
}
var jwt AniListJWT
func AniListQuery(body interface{}, login bool) (json.RawMessage, string) {
reader, _ := json.Marshal(body)
response, err := http.NewRequest("POST", "https://graphql.anilist.co", bytes.NewBuffer(reader))
@ -93,7 +17,7 @@ func AniListQuery(body interface{}, login bool) (json.RawMessage, string) {
if login && (AniListJWT{}) != jwt {
response.Header.Add("Authorization", "Bearer "+jwt.AccessToken)
} else if login {
return nil, "Please login to AniList to make this request"
return nil, "Please login to anilist to make this request"
}
response.Header.Add("Content-Type", "application/json")
response.Header.Add("Accept", "application/json")
@ -108,17 +32,10 @@ func AniListQuery(body interface{}, login bool) (json.RawMessage, string) {
returnedBody, err := io.ReadAll(res.Body)
//var post interface{}
//err = json.Unmarshal(returnedBody, &post)
//if err != nil {
// log.Printf("Failed at unmarshal, %s\n", err)
//}
//
//return post
return returnedBody, ""
}
func (a *main.App) GetAniListItem(aniId int) any {
func (a *App) GetAniListItem(aniId int) any {
type Variables struct {
ID int `json:"id"`
ListType string `json:"listType"`
@ -173,7 +90,7 @@ func (a *main.App) GetAniListItem(aniId int) any {
return post
}
func (a *main.App) AniListSearch(query string) any {
func (a *App) AniListSearch(query string) any {
type Variables struct {
Search string `json:"search"`
ListType string `json:"listType"`
@ -223,127 +140,120 @@ func (a *main.App) AniListSearch(query string) any {
return post
}
var ctxShutdown, cancel = context.WithCancel(context.Background())
func (a *main.App) AniListLogin() {
getAniListCodeUrl := "https://anilist.co/api/v2/oauth/authorize?client_id=" + os.Getenv("ANILIST_APP_ID") + "&redirect_uri=" + os.Getenv("ANILIST_CALLBACK_URI") + "&response_type=code"
runtime.BrowserOpenURL(a.ctx, getAniListCodeUrl)
serverDone := &sync.WaitGroup{}
serverDone.Add(1)
handleAniListCallback(serverDone)
serverDone.Wait()
}
func handleAniListCallback(wg *sync.WaitGroup) {
srv := &http.Server{Addr: ":6734"}
http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
select {
case <-ctxShutdown.Done():
fmt.Println("Shutting down...")
return
default:
}
content := r.FormValue("code")
if content != "" {
jwt = getAniListAuthorizationToken(content)
fmt.Println("Shutting down...")
cancel()
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 getAniListAuthorizationToken(content string) AniListJWT {
apiUrl := "https://anilist.co/api/v2/oauth/token"
resource := "/api/v2/oauth/token"
data := url.Values{}
data.Set("grant_type", "authorization_code")
data.Set("client_id", os.Getenv("ANILIST_APP_ID"))
data.Set("client_secret", os.Getenv("ANILIST_SECRET_TOKEN"))
data.Set("redirect_uri", os.Getenv("ANILIST_CALLBACK_URI"))
data.Set("code", content)
u, _ := url.ParseRequestURI(apiUrl)
u.Path = resource
urlStr := u.String()
response, err := http.NewRequest("POST", urlStr, strings.NewReader(data.Encode()))
if err != nil {
log.Printf("Failed at response, %s\n", err)
}
response.Header.Add("content-type", "application/x-www-form-urlencoded")
response.Header.Add("Content-Type", "application/json")
response.Header.Add("Accept", "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 AniListJWT
err = json.Unmarshal(returnedBody, &post)
if err != nil {
log.Printf("Failed at unmarshal, %s\n", err)
}
return post
}
func (a *main.App) GetAniListLoggedInUserId() AniListUser {
if (AniListJWT{}) == jwt {
a.AniListLogin()
func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) AniListCurrentUserWatchList {
var user = a.GetAniListLoggedInUserId()
type Variables struct {
Page int `json:"page"`
PerPage int `json:"perPage"`
UserId int `json:"userId"`
ListType string `json:"listType"`
Status string `json:"status"`
Sort string `json:"sort"`
}
body := struct {
Query string `json:"query"`
Query string `json:"query"`
Variables Variables `json:"variables"`
}{
Query: `
query {
Viewer {
id
name
}
}
query(
$page: Int
$perPage: Int
$userId: Int
$listType: MediaType
$status: MediaListStatus
$sort:[MediaListSort]
) {
Page(page: $page, perPage: $perPage) {
pageInfo {
total
perPage
currentPage
lastPage
hasNextPage
}
mediaList(userId: $userId, type: $listType, status: $status, sort: $sort) {
id
mediaId
userId
media {
id
idMal
title {
romaji
english
native
}
description
coverImage {
large
}
season
seasonYear
status
episodes
nextAiringEpisode{
airingAt
timeUntilAiring
episode
}
}
status
notes
progress
score
repeat
user {
id
name
avatar{
large
medium
}
statistics {
anime {
count
statuses {
status
count
}
}
}
}
}
}
}
`,
Variables: Variables{
Page: page,
PerPage: perPage,
UserId: user.Data.Viewer.ID,
ListType: "ANIME",
Status: "CURRENT",
Sort: sort,
},
}
user, _ := AniListQuery(body, true)
returnedBody, _ := AniListQuery(body, true)
var post AniListUser
err := json.Unmarshal(user, &post)
var post AniListCurrentUserWatchList
err := json.Unmarshal(returnedBody, &post)
if err != nil {
log.Printf("Failed at unmarshal, %s\n", err)
}
fmt.Println("UserInfo: ", post)
// Getting the real total, finding the real last page and storing that in the Page info
statuses := post.Data.Page.MediaList[0].User.Statistics.Anime.Statuses
var total int
for _, status := range statuses {
if status.Status == "CURRENT" {
total = status.Count
}
}
lastPage := total / perPage
post.Data.Page.PageInfo.Total = total
post.Data.Page.PageInfo.LastPage = lastPage
return post
}
func (a *main.App) GetAniListUserWatchingList() {
}