package main import ( "bytes" "encoding/json" "io" "log" "net/http" ) 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)) if err != nil { log.Printf("Failed at response, %s\n", err) } if login && (AniListJWT{}) != aniListJwt { response.Header.Add("Authorization", "Bearer "+aniListJwt.AccessToken) } else if login { return nil, "Please login to anilist to make this request" } 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) return returnedBody, "" } func (a *App) GetAniListItem(aniId int, login bool) AniListGetSingleAnime { var user = a.GetAniListLoggedInUser() var neededVariables interface{} if login { neededVariables = struct { MediaId int `json:"mediaId"` UserId int `json:"userId"` ListType string `json:"listType"` }{ MediaId: aniId, UserId: user.Data.Viewer.ID, ListType: "ANIME", } } else { neededVariables = struct { MediaId int `json:"mediaId"` ListType string `json:"listType"` }{ MediaId: aniId, ListType: "ANIME", } } body := struct { Query string `json:"query"` Variables interface{} `json:"variables"` }{ Query: ` query($userId: Int, $mediaId: Int, $listType: MediaType) { MediaList(mediaId: $mediaId, userId: $userId, type: $listType) { id mediaId userId media { id idMal title { romaji english native } description coverImage { large } season seasonYear status episodes nextAiringEpisode { airingAt timeUntilAiring episode } } status startedAt{ year month day } completedAt{ year month day } notes progress score repeat user { id name avatar { large medium } statistics { anime { count statuses { status count } } } } } } `, Variables: neededVariables, } returnedBody, _ := AniListQuery(body, false) var post AniListGetSingleAnime err := json.Unmarshal(returnedBody, &post) if err != nil { log.Printf("Failed at unmarshal, %s\n", err) } return post } func (a *App) AniListSearch(query string) any { 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) { id idMal title { romaji english native } description coverImage { large } season seasonYear status episodes nextAiringEpisode{ airingAt timeUntilAiring episode } } } } `, Variables: Variables{ Search: query, ListType: "ANIME", }, } 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 } func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) AniListCurrentUserWatchList { var user = a.GetAniListLoggedInUser() 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"` Variables Variables `json:"variables"` }{ Query: ` 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 startedAt { year month day } completedAt { year month day } 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, }, } returnedBody, _ := AniListQuery(body, true) var post AniListCurrentUserWatchList err := json.Unmarshal(returnedBody, &post) if err != nil { log.Printf("Failed at unmarshal, %s\n", err) } // 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 *App) AniListUpdateEntry( mediaId int, progress string, status string, score float64, repeat int, notes string, startYear int, startMonth int, startDay int, completeYear int, completeMonth int, completeDay int, ) interface{} { type StartedAt struct { Year int `json:"year"` Month int `json:"month"` Day int `json:"day"` } type CompletedAt struct { Year int `json:"year"` Month int `json:"month"` Day int `json:"day"` } type Variables struct { MediaId int `json:"mediaId"` Progress string `json:"progress"` Status string `json:"status"` Score float64 `json:"score"` Repeat int `json:"repeat"` Notes string `json:"notes"` StartedAt StartedAt `json:"startedAt"` CompletedAt CompletedAt `json:"completedAt"` } body := struct { Mutation string `json:"mutation"` Variables Variables `json:"variables"` }{ Mutation: ` 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 ){ mediaId progress status score repeat notes startedAt{ year month day } completedAt{ year month day } } } `, Variables: Variables{ MediaId: mediaId, Progress: progress, Status: status, Score: score, Repeat: repeat, Notes: notes, StartedAt: StartedAt{ Year: startYear, Month: startMonth, Day: startDay, }, CompletedAt: CompletedAt{ Year: completeYear, Month: completeMonth, Day: completeDay, }, }} returnedBody, _ := AniListQuery(body, true) var post interface{} err := json.Unmarshal(returnedBody, &post) if err != nil { log.Printf("Failed at unmarshal, %s\n", err) } return post }