2024-07-24 09:18:45 -04:00
|
|
|
package main
|
2024-07-21 10:25:21 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
2024-07-24 09:15:52 -04:00
|
|
|
func AniListQuery(body interface{}, login bool) (json.RawMessage, string) {
|
2024-07-21 10:25:21 -04:00
|
|
|
reader, _ := json.Marshal(body)
|
|
|
|
response, err := http.NewRequest("POST", "https://graphql.anilist.co", bytes.NewBuffer(reader))
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Failed at response, %s\n", err)
|
|
|
|
}
|
2024-07-30 12:59:21 -04:00
|
|
|
if login && (AniListJWT{}) != aniListJwt {
|
|
|
|
response.Header.Add("Authorization", "Bearer "+aniListJwt.AccessToken)
|
2024-07-21 10:25:21 -04:00
|
|
|
} else if login {
|
2024-07-24 09:18:45 -04:00
|
|
|
return nil, "Please login to anilist to make this request"
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
|
2024-09-16 12:45:57 -04:00
|
|
|
return returnedBody, res.Status
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
|
2024-07-27 21:18:03 -04:00
|
|
|
func (a *App) GetAniListItem(aniId int, login bool) AniListGetSingleAnime {
|
2024-07-30 20:41:18 -04:00
|
|
|
var user = a.GetAniListLoggedInUser()
|
2024-07-27 21:18:03 -04:00
|
|
|
|
|
|
|
var neededVariables interface{}
|
|
|
|
|
|
|
|
if login {
|
2024-07-29 16:54:05 -04:00
|
|
|
neededVariables = struct {
|
|
|
|
MediaId int `json:"mediaId"`
|
2024-07-27 21:18:03 -04:00
|
|
|
UserId int `json:"userId"`
|
|
|
|
ListType string `json:"listType"`
|
2024-07-29 16:54:05 -04:00
|
|
|
}{
|
2024-07-27 21:18:03 -04:00
|
|
|
MediaId: aniId,
|
|
|
|
UserId: user.Data.Viewer.ID,
|
|
|
|
ListType: "ANIME",
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
neededVariables = struct {
|
2024-07-29 16:54:05 -04:00
|
|
|
MediaId int `json:"mediaId"`
|
2024-07-27 21:18:03 -04:00
|
|
|
ListType string `json:"listType"`
|
2024-07-29 16:54:05 -04:00
|
|
|
}{
|
2024-07-27 21:18:03 -04:00
|
|
|
MediaId: aniId,
|
|
|
|
ListType: "ANIME",
|
|
|
|
}
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
body := struct {
|
2024-07-29 16:54:05 -04:00
|
|
|
Query string `json:"query"`
|
2024-07-27 21:18:03 -04:00
|
|
|
Variables interface{} `json:"variables"`
|
2024-07-21 10:25:21 -04:00
|
|
|
}{
|
|
|
|
Query: `
|
2024-07-25 09:19:27 -04:00
|
|
|
query($userId: Int, $mediaId: Int, $listType: MediaType) {
|
|
|
|
MediaList(mediaId: $mediaId, userId: $userId, type: $listType) {
|
2024-07-21 10:25:21 -04:00
|
|
|
id
|
2024-07-25 09:19:27 -04:00
|
|
|
mediaId
|
|
|
|
userId
|
|
|
|
media {
|
|
|
|
id
|
|
|
|
idMal
|
|
|
|
title {
|
2024-07-21 10:25:21 -04:00
|
|
|
romaji
|
|
|
|
english
|
2024-07-25 09:19:27 -04:00
|
|
|
native
|
|
|
|
}
|
|
|
|
description
|
|
|
|
coverImage {
|
2024-07-21 10:25:21 -04:00
|
|
|
large
|
2024-07-25 09:19:27 -04:00
|
|
|
}
|
|
|
|
season
|
|
|
|
seasonYear
|
|
|
|
status
|
|
|
|
episodes
|
|
|
|
nextAiringEpisode {
|
|
|
|
airingAt
|
|
|
|
timeUntilAiring
|
|
|
|
episode
|
|
|
|
}
|
2024-08-09 15:07:41 -04:00
|
|
|
tags{
|
|
|
|
id
|
|
|
|
name
|
|
|
|
description
|
|
|
|
rank
|
|
|
|
isMediaSpoiler
|
|
|
|
isAdult
|
|
|
|
}
|
|
|
|
isAdult
|
2024-07-25 09:19:27 -04:00
|
|
|
}
|
|
|
|
status
|
|
|
|
startedAt{
|
|
|
|
year
|
|
|
|
month
|
|
|
|
day
|
|
|
|
}
|
|
|
|
completedAt{
|
|
|
|
year
|
|
|
|
month
|
|
|
|
day
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
2024-07-25 09:19:27 -04:00
|
|
|
notes
|
|
|
|
progress
|
|
|
|
score
|
|
|
|
repeat
|
|
|
|
user {
|
|
|
|
id
|
|
|
|
name
|
|
|
|
avatar {
|
|
|
|
large
|
|
|
|
medium
|
|
|
|
}
|
|
|
|
statistics {
|
|
|
|
anime {
|
|
|
|
count
|
|
|
|
statuses {
|
|
|
|
status
|
|
|
|
count
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
2024-07-25 09:19:27 -04:00
|
|
|
}
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
`,
|
2024-07-27 21:18:03 -04:00
|
|
|
Variables: neededVariables,
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
|
2024-09-16 12:45:57 -04:00
|
|
|
returnedBody, status := AniListQuery(body, login)
|
2024-07-25 09:19:27 -04:00
|
|
|
var post AniListGetSingleAnime
|
2024-09-16 12:45:57 -04:00
|
|
|
|
|
|
|
if status == "404 Not Found" && login == false {
|
|
|
|
return post
|
|
|
|
}
|
|
|
|
|
|
|
|
if status == "404 Not Found" && login {
|
|
|
|
post = a.GetAniListItem(aniId, false)
|
|
|
|
}
|
|
|
|
|
2024-07-24 09:15:52 -04:00
|
|
|
err := json.Unmarshal(returnedBody, &post)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Failed at unmarshal, %s\n", err)
|
|
|
|
}
|
|
|
|
|
2024-09-16 12:45:57 -04:00
|
|
|
if login == false {
|
|
|
|
post.Data.MediaList.UserID = user.Data.Viewer.ID
|
|
|
|
post.Data.MediaList.Status = ""
|
|
|
|
post.Data.MediaList.StartedAt.Year = 0
|
|
|
|
post.Data.MediaList.StartedAt.Month = 0
|
|
|
|
post.Data.MediaList.StartedAt.Day = 0
|
|
|
|
post.Data.MediaList.CompletedAt.Year = 0
|
|
|
|
post.Data.MediaList.CompletedAt.Month = 0
|
|
|
|
post.Data.MediaList.CompletedAt.Day = 0
|
|
|
|
post.Data.MediaList.Notes = ""
|
|
|
|
post.Data.MediaList.Progress = 0
|
|
|
|
post.Data.MediaList.Score = 0
|
|
|
|
post.Data.MediaList.Repeat = 0
|
|
|
|
post.Data.MediaList.User.ID = user.Data.Viewer.ID
|
|
|
|
post.Data.MediaList.User.Name = user.Data.Viewer.Name
|
|
|
|
post.Data.MediaList.User.Avatar.Large = user.Data.Viewer.Avatar.Large
|
|
|
|
post.Data.MediaList.User.Avatar.Medium = user.Data.Viewer.Avatar.Medium
|
|
|
|
post.Data.MediaList.User.Statistics.Anime.Count = 0
|
|
|
|
// This provides an empty array and frees up the memory from the garbage collector
|
|
|
|
post.Data.MediaList.User.Statistics.Anime.Statuses = nil
|
|
|
|
}
|
|
|
|
|
2024-07-24 09:15:52 -04:00
|
|
|
return post
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
func (a *App) AniListSearch(query string) any {
|
2024-07-21 10:25:21 -04:00
|
|
|
type Variables struct {
|
|
|
|
Search string `json:"search"`
|
|
|
|
ListType string `json:"listType"`
|
|
|
|
}
|
|
|
|
body := struct {
|
|
|
|
Query string `json:"query"`
|
|
|
|
Variables Variables `json:"variables"`
|
|
|
|
}{
|
|
|
|
Query: `
|
|
|
|
query ($search: String!, $listType: MediaType) {
|
|
|
|
Page (page: 1, perPage: 100) {
|
|
|
|
pageInfo {
|
|
|
|
total
|
|
|
|
currentPage
|
|
|
|
lastPage
|
|
|
|
hasNextPage
|
|
|
|
perPage
|
|
|
|
}
|
|
|
|
media (search: $search, type: $listType) {
|
2024-07-25 09:19:27 -04:00
|
|
|
id
|
|
|
|
idMal
|
|
|
|
title {
|
|
|
|
romaji
|
|
|
|
english
|
|
|
|
native
|
|
|
|
}
|
|
|
|
description
|
|
|
|
coverImage {
|
|
|
|
large
|
|
|
|
}
|
|
|
|
season
|
|
|
|
seasonYear
|
|
|
|
status
|
|
|
|
episodes
|
|
|
|
nextAiringEpisode{
|
|
|
|
airingAt
|
|
|
|
timeUntilAiring
|
|
|
|
episode
|
|
|
|
}
|
2024-08-09 15:07:41 -04:00
|
|
|
tags{
|
|
|
|
id
|
|
|
|
name
|
|
|
|
description
|
|
|
|
rank
|
|
|
|
isMediaSpoiler
|
|
|
|
isAdult
|
|
|
|
}
|
|
|
|
isAdult
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
2024-07-25 09:19:27 -04:00
|
|
|
}
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
`,
|
|
|
|
Variables: Variables{
|
|
|
|
Search: query,
|
|
|
|
ListType: "ANIME",
|
|
|
|
},
|
|
|
|
}
|
2024-07-24 09:15:52 -04:00
|
|
|
returnedBody, _ := AniListQuery(body, false)
|
|
|
|
|
|
|
|
var post interface{}
|
|
|
|
err := json.Unmarshal(returnedBody, &post)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Failed at unmarshal, %s\n", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return post
|
2024-07-21 10:25:21 -04:00
|
|
|
}
|
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) AniListCurrentUserWatchList {
|
2024-07-30 20:41:18 -04:00
|
|
|
var user = a.GetAniListLoggedInUser()
|
2024-07-24 09:18:45 -04:00
|
|
|
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"`
|
2024-07-24 09:15:52 -04:00
|
|
|
}
|
|
|
|
body := struct {
|
2024-07-24 09:18:45 -04:00
|
|
|
Query string `json:"query"`
|
|
|
|
Variables Variables `json:"variables"`
|
2024-07-24 09:15:52 -04:00
|
|
|
}{
|
|
|
|
Query: `
|
2024-07-24 09:18:45 -04:00
|
|
|
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
|
|
|
|
}
|
2024-08-09 15:07:41 -04:00
|
|
|
tags{
|
|
|
|
id
|
|
|
|
name
|
|
|
|
description
|
|
|
|
rank
|
|
|
|
isMediaSpoiler
|
|
|
|
isAdult
|
|
|
|
}
|
|
|
|
isAdult
|
2024-07-24 09:18:45 -04:00
|
|
|
}
|
|
|
|
status
|
2024-07-25 09:19:27 -04:00
|
|
|
startedAt {
|
|
|
|
year
|
|
|
|
month
|
|
|
|
day
|
|
|
|
}
|
|
|
|
completedAt {
|
|
|
|
year
|
|
|
|
month
|
|
|
|
day
|
|
|
|
}
|
2024-07-24 09:18:45 -04:00
|
|
|
notes
|
|
|
|
progress
|
|
|
|
score
|
|
|
|
repeat
|
|
|
|
user {
|
|
|
|
id
|
|
|
|
name
|
|
|
|
avatar{
|
|
|
|
large
|
|
|
|
medium
|
|
|
|
}
|
|
|
|
statistics {
|
|
|
|
anime {
|
|
|
|
count
|
|
|
|
statuses {
|
|
|
|
status
|
|
|
|
count
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-07-24 09:15:52 -04:00
|
|
|
`,
|
2024-07-24 09:18:45 -04:00
|
|
|
Variables: Variables{
|
|
|
|
Page: page,
|
|
|
|
PerPage: perPage,
|
|
|
|
UserId: user.Data.Viewer.ID,
|
|
|
|
ListType: "ANIME",
|
|
|
|
Status: "CURRENT",
|
|
|
|
Sort: sort,
|
|
|
|
},
|
2024-07-24 09:15:52 -04:00
|
|
|
}
|
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
returnedBody, _ := AniListQuery(body, true)
|
2024-07-24 09:15:52 -04:00
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
var post AniListCurrentUserWatchList
|
|
|
|
err := json.Unmarshal(returnedBody, &post)
|
2024-07-24 09:15:52 -04:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("Failed at unmarshal, %s\n", err)
|
|
|
|
}
|
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
2024-07-24 09:15:52 -04:00
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
lastPage := total / perPage
|
2024-07-24 09:15:52 -04:00
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
post.Data.Page.PageInfo.Total = total
|
|
|
|
post.Data.Page.PageInfo.LastPage = lastPage
|
2024-07-24 09:15:52 -04:00
|
|
|
|
2024-07-24 09:18:45 -04:00
|
|
|
return post
|
2024-07-24 09:15:52 -04:00
|
|
|
}
|
2024-07-25 09:19:27 -04:00
|
|
|
|
2024-09-05 15:29:42 -04:00
|
|
|
func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) AniListGetSingleAnime {
|
2024-07-25 09:19:27 -04:00
|
|
|
body := struct {
|
2024-08-16 15:04:34 -04:00
|
|
|
Query string `json:"query"`
|
|
|
|
Variables AniListUpdateVariables `json:"variables"`
|
2024-07-25 09:19:27 -04:00
|
|
|
}{
|
2024-08-09 15:07:41 -04:00
|
|
|
Query: `
|
2024-07-25 09:19:27 -04:00
|
|
|
mutation(
|
|
|
|
$mediaId:Int,
|
|
|
|
$progress:Int,
|
|
|
|
$status:MediaListStatus,
|
|
|
|
$score:Float,
|
|
|
|
$repeat:Int,
|
|
|
|
$notes:String,
|
|
|
|
$startedAt:FuzzyDateInput,
|
|
|
|
$completedAt:FuzzyDateInput,
|
|
|
|
){
|
|
|
|
SaveMediaListEntry(
|
|
|
|
mediaId:$mediaId,
|
|
|
|
progress:$progress,
|
|
|
|
status:$status,
|
|
|
|
score:$score,
|
|
|
|
repeat:$repeat,
|
|
|
|
notes:$notes,
|
|
|
|
startedAt:$startedAt
|
|
|
|
completedAt:$completedAt
|
|
|
|
){
|
2024-09-05 15:29:42 -04:00
|
|
|
id
|
2024-07-25 09:19:27 -04:00
|
|
|
mediaId
|
2024-09-05 15:29:42 -04:00
|
|
|
userId
|
|
|
|
media {
|
|
|
|
id
|
|
|
|
idMal
|
|
|
|
title {
|
|
|
|
romaji
|
|
|
|
english
|
|
|
|
native
|
|
|
|
}
|
|
|
|
description
|
|
|
|
coverImage {
|
|
|
|
large
|
|
|
|
}
|
|
|
|
season
|
|
|
|
seasonYear
|
|
|
|
status
|
|
|
|
episodes
|
|
|
|
nextAiringEpisode {
|
|
|
|
airingAt
|
|
|
|
timeUntilAiring
|
|
|
|
episode
|
|
|
|
}
|
|
|
|
isAdult
|
|
|
|
}
|
2024-07-25 09:19:27 -04:00
|
|
|
status
|
|
|
|
startedAt{
|
|
|
|
year
|
|
|
|
month
|
|
|
|
day
|
|
|
|
}
|
|
|
|
completedAt{
|
|
|
|
year
|
|
|
|
month
|
|
|
|
day
|
|
|
|
}
|
2024-09-05 15:29:42 -04:00
|
|
|
notes
|
|
|
|
progress
|
|
|
|
score
|
|
|
|
repeat
|
|
|
|
user {
|
|
|
|
id
|
|
|
|
name
|
|
|
|
avatar{
|
|
|
|
large
|
|
|
|
medium
|
|
|
|
}
|
|
|
|
statistics{
|
|
|
|
anime{
|
|
|
|
count
|
|
|
|
statuses{
|
|
|
|
status
|
|
|
|
count
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-07-25 09:19:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
2024-08-16 15:04:34 -04:00
|
|
|
Variables: updateBody,
|
|
|
|
}
|
2024-07-25 09:19:27 -04:00
|
|
|
|
|
|
|
returnedBody, _ := AniListQuery(body, true)
|
|
|
|
|
2024-09-05 15:29:42 -04:00
|
|
|
var returnedJson AniListUpdateReturn
|
|
|
|
err := json.Unmarshal(returnedBody, &returnedJson)
|
2024-07-25 09:19:27 -04:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("Failed at unmarshal, %s\n", err)
|
|
|
|
}
|
|
|
|
|
2024-09-05 15:29:42 -04:00
|
|
|
var post AniListGetSingleAnime
|
|
|
|
|
|
|
|
post.Data.MediaList = returnedJson.Data.SaveMediaListEntry
|
|
|
|
|
2024-07-25 09:19:27 -04:00
|
|
|
return post
|
|
|
|
}
|
2024-09-18 14:05:41 -04:00
|
|
|
|
|
|
|
func (a *App) AniListDeleteEntry(mediaListId int) DeleteAniListReturn {
|
|
|
|
type Variables = struct {
|
|
|
|
Id int `json:"id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
body := struct {
|
|
|
|
Query string `json:"query"`
|
|
|
|
Variables Variables `json:"variables"`
|
|
|
|
}{
|
|
|
|
Query: `
|
|
|
|
mutation(
|
|
|
|
$id:Int,
|
|
|
|
){
|
|
|
|
DeleteMediaListEntry(
|
|
|
|
id:$id,
|
|
|
|
){
|
|
|
|
deleted
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`,
|
|
|
|
Variables: Variables{
|
|
|
|
Id: mediaListId,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
returnedBody, _ := AniListQuery(body, true)
|
|
|
|
|
|
|
|
var post DeleteAniListReturn
|
|
|
|
err := json.Unmarshal(returnedBody, &post)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Failed at unmarshal, %s\n", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return post
|
|
|
|
}
|