Compare commits
4 Commits
3c7ca15376
...
a433df84db
Author | SHA1 | Date | |
---|---|---|---|
a433df84db | |||
76ea4f73ec | |||
fb2d5fbdea | |||
3b5518113e |
@ -355,43 +355,10 @@ func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) Ani
|
||||
return post
|
||||
}
|
||||
|
||||
func (a *App) AniListUpdateEntry(
|
||||
mediaId int,
|
||||
progress int,
|
||||
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 int `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"`
|
||||
}
|
||||
func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) interface{} {
|
||||
body := struct {
|
||||
Query string `json:"query"`
|
||||
Variables Variables `json:"variables"`
|
||||
Variables AniListUpdateVariables `json:"variables"`
|
||||
}{
|
||||
Query: `
|
||||
mutation(
|
||||
@ -433,24 +400,8 @@ func (a *App) AniListUpdateEntry(
|
||||
}
|
||||
}
|
||||
`,
|
||||
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,
|
||||
},
|
||||
}}
|
||||
Variables: updateBody,
|
||||
}
|
||||
|
||||
returnedBody, _ := AniListQuery(body, true)
|
||||
|
||||
|
@ -112,6 +112,27 @@ type MediaList struct {
|
||||
} `json:"user"`
|
||||
}
|
||||
|
||||
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 AniListUpdateVariables struct {
|
||||
MediaId int `json:"mediaId"`
|
||||
Progress int `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"`
|
||||
}
|
||||
|
||||
//var MediaListSort = struct {
|
||||
// MediaId string
|
||||
// MediaIdDesc string
|
||||
|
@ -54,3 +54,21 @@ func (a *App) GetMyAnimeList(count int) MALWatchlist {
|
||||
|
||||
return malList
|
||||
}
|
||||
|
||||
func (a *App) MyAnimeListUpdate(anime MALAnime, update interface{}) MyListStatus {
|
||||
//var body url.Values
|
||||
|
||||
return MyListStatus{}
|
||||
}
|
||||
|
||||
func (a *App) GetMyAnimeListAnime(id int) MALAnime {
|
||||
malUrl := "https://api.myanimelist.net/v2/anime/" + strconv.Itoa(id) + "?fields=id,title,main_picture,alternative_titles,start_date,end_date,synopsis,mean,rank,popularity,num_list_users,num_scoring_users,nsfw,genres,created_at,updated_at,media_type,status,my_list_status,num_episodes,start_season,broadcast,source,average_episode_duration,rating,pictures,background,related_anime,recommendations,studios,statistics"
|
||||
respBody := MALHelper("GET", malUrl, nil)
|
||||
var malAnime MALAnime
|
||||
err := json.Unmarshal(respBody, &malAnime)
|
||||
if err != nil {
|
||||
log.Printf("Failed to unmarshal json response, %s\n", err)
|
||||
}
|
||||
|
||||
return malAnime
|
||||
}
|
||||
|
87
MALTypes.go
87
MALTypes.go
@ -65,3 +65,90 @@ type MALWatchlist struct {
|
||||
Next string `json:"next" ts_type:"next"`
|
||||
} `json:"paging" ts_type:"paging"`
|
||||
}
|
||||
|
||||
type MALAnime struct {
|
||||
Id int `json:"id" ts_type:"id"`
|
||||
Title string `json:"title" ts_type:"title"`
|
||||
MainPicture struct {
|
||||
Large string `json:"large" json:"large"`
|
||||
Medium string `json:"medium" json:"medium"`
|
||||
} `json:"main_picture" json:"mainPicture"`
|
||||
AlternativeTitles struct {
|
||||
Synonyms []string `json:"synonyms" ts_type:"synonyms"`
|
||||
En string `json:"en" ts_type:"en"`
|
||||
Ja string `json:"ja" ts_type:"ja"`
|
||||
} `json:"alternative_titles" ts_type:"alternativeTitles"`
|
||||
StartDate string `json:"start_date" ts_type:"startDate"`
|
||||
EndDate string `json:"end_date" ts_type:"endDate"`
|
||||
Synopsis string `json:"synopsis" ts_type:"synopsis"`
|
||||
Mean float64 `json:"mean" ts_type:"mean"`
|
||||
Rank int `json:"rank" ts_type:"rank"`
|
||||
Popularity int `json:"popularity" ts_type:"popularity"`
|
||||
NumListUsers int `json:"num_list_users" ts_type:"numListUsers"`
|
||||
NumScoringUsers int `json:"num_scoring_users" ts_type:"numScoringUsers"`
|
||||
NSFW string `json:"nsfw" ts_type:"nsfw"`
|
||||
Genres []struct {
|
||||
Id int `json:"id" ts_type:"id"`
|
||||
Name string `json:"name" ts_type:"name"`
|
||||
} `json:"genres" ts_type:"genres"`
|
||||
CreatedAt string `json:"created_at" ts_type:"createdAt"`
|
||||
UpdatedAt string `json:"updated_at" ts_type:"updatedAt"`
|
||||
MediaType string `json:"media_type" ts_type:"mediaType"`
|
||||
Status string `json:"status" ts_type:"status"`
|
||||
MyListStatus MyListStatus `json:"my_list_status" ts_type:"myListStatus"`
|
||||
NumEpisodes int `json:"num_episodes" ts_type:"numEpisodes"`
|
||||
StartSeason struct {
|
||||
Year int `json:"year" ts_type:"year"`
|
||||
Season string `json:"season" ts_type:"season"`
|
||||
} `json:"start_season" ts_type:"startSeason"`
|
||||
Broadcast struct {
|
||||
DayOfTheWeek string `json:"day_of_the_week" ts_type:"dayOfTheWeek"`
|
||||
StartTime string `json:"start_time" ts_type:"startTime"`
|
||||
} `json:"broadcast" ts_type:"broadcast"`
|
||||
Source string `json:"source" ts_type:"source"`
|
||||
AverageEpisodeDuration int `json:"average_episode_duration" ts_type:"averageEpisodeDuration"`
|
||||
Rating string `json:"rating" ts_type:"rating"`
|
||||
Studios []struct {
|
||||
Id int `json:"id" ts_type:"id"`
|
||||
Name string `json:"name" ts_type:"name"`
|
||||
} `json:"studios" ts_type:"studios"`
|
||||
Pictures []struct {
|
||||
Large string `json:"large" ts_type:"large"`
|
||||
Medium string `json:"medium" ts_type:"medium"`
|
||||
} `json:"pictures" ts_type:"pictures"`
|
||||
Background string `json:"background" ts_type:"background"`
|
||||
RelatedAnime []struct {
|
||||
Node MALAnime `json:"node" ts_type:"node"`
|
||||
RelationType string `json:"relation_type" ts_type:"relationType"`
|
||||
RelationTypeFormatted string `json:"relation_type_formatted" ts_type:"relationTypeFormatted"`
|
||||
} `json:"related_anime" ts_type:"relatedAnime"`
|
||||
Recommendations []struct {
|
||||
Node MALAnime `json:"node" ts_type:"node"`
|
||||
NumRecommendations int `json:"num_recommendations" ts_type:"numRecommendations"`
|
||||
} `json:"recommendations" ts_type:"recommendations"`
|
||||
Statistics struct {
|
||||
NumListUsers int `json:"num_list_users" ts_type:"numListUsers"`
|
||||
Status struct {
|
||||
Watching string `json:"watching" ts_type:"watching"`
|
||||
Completed string `json:"completed" ts_type:"completed"`
|
||||
OnHold string `json:"on_hold" ts_type:"onHold"`
|
||||
Dropped string `json:"dropped" ts_type:"dropped"`
|
||||
PlanToWatch string `json:"plan_to_watch" ts_type:"planToWatch"`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type MyListStatus struct {
|
||||
Status string `json:"status" ts_type:"status"`
|
||||
Score int `json:"score" ts_type:"score"`
|
||||
NumEpisodesWatched int `json:"num_episodes_watched" ts_type:"numEpisodesWatched"`
|
||||
IsRewatching bool `json:"is_rewatching" ts_type:"isRewatching"`
|
||||
StartDate string `json:"start_date" ts_type:"startDate"`
|
||||
FinishDate string `json:"finish_date" ts_type:"finishDate"`
|
||||
Priority int `json:"priority" ts_type:"priority"`
|
||||
NumTimesRewatched int `json:"num_times_rewatched" ts_type:"numTimesRewatched"`
|
||||
RewatchValue int `json:"rewatch_value" ts_type:"rewatchValue"`
|
||||
Tags []string `json:"tags" ts_type:"tags"`
|
||||
Comments string `json:"comments" ts_type:"comments"`
|
||||
UpdatedAt string `json:"updated_at" ts_type:"updatedAt"`
|
||||
}
|
||||
|
19
bruno/AniTrack/MAL/Get Single Anime.bru
Normal file
19
bruno/AniTrack/MAL/Get Single Anime.bru
Normal file
@ -0,0 +1,19 @@
|
||||
meta {
|
||||
name: Get Single Anime
|
||||
type: http
|
||||
seq: 5
|
||||
}
|
||||
|
||||
get {
|
||||
url: https://api.myanimelist.net/v2/anime/52991?fields=id,title,main_picture,alternative_titles,start_date,end_date,synopsis,mean,rank,popularity,num_list_users,num_scoring_users,nsfw,genres,created_at,updated_at,media_type,status,my_list_status,num_episodes,start_season,broadcast,source,average_episode_duration,rating,pictures,background,related_anime,recommendations,studios,statistics
|
||||
body: none
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
params:query {
|
||||
fields: id,title,main_picture,alternative_titles,start_date,end_date,synopsis,mean,rank,popularity,num_list_users,num_scoring_users,nsfw,genres,created_at,updated_at,media_type,status,my_list_status,num_episodes,start_season,broadcast,source,average_episode_duration,rating,pictures,background,related_anime,recommendations,studios,statistics
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{MAL_ACCESS_TOKEN}}
|
||||
}
|
15
bruno/AniTrack/MAL/Update Anime Status.bru
Normal file
15
bruno/AniTrack/MAL/Update Anime Status.bru
Normal file
@ -0,0 +1,15 @@
|
||||
meta {
|
||||
name: Update Anime Status
|
||||
type: http
|
||||
seq: 4
|
||||
}
|
||||
|
||||
patch {
|
||||
url: https://api.myanimelist.net/v2/anime/50205/my_list_status
|
||||
body: formUrlEncoded
|
||||
auth: bearer
|
||||
}
|
||||
|
||||
auth:bearer {
|
||||
token: {{MAL_ACCESS_TOKEN}}
|
||||
}
|
@ -14,7 +14,8 @@
|
||||
title,
|
||||
watchListPage,
|
||||
animePerPage,
|
||||
malWatchList
|
||||
malWatchList,
|
||||
malPrimary
|
||||
} from "./GlobalVariablesAndHelperFunctions.svelte";
|
||||
import {
|
||||
CheckIfAniListLoggedIn,
|
||||
@ -38,11 +39,13 @@
|
||||
|
||||
let isAniListLoggedIn: boolean
|
||||
let isAniListPrimary: boolean
|
||||
let isMalPrimary: boolean
|
||||
let aniListWatchListLoaded: AniListCurrentUserWatchList
|
||||
|
||||
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
|
||||
aniListPrimary.subscribe((value) => isAniListPrimary = value)
|
||||
aniListWatchlist.subscribe((value) => aniListWatchListLoaded = value)
|
||||
malPrimary.subscribe((value) => isMalPrimary = value)
|
||||
|
||||
|
||||
let page: number
|
||||
@ -72,10 +75,14 @@
|
||||
if (loggedIn) {
|
||||
GetMyAnimeListLoggedInUser().then(user => {
|
||||
malUser.set(user)
|
||||
if (isMalPrimary){
|
||||
GetMyAnimeList(1000).then(watchList => {
|
||||
malWatchList.set(watchList)
|
||||
malLoggedIn.set(loggedIn)
|
||||
})
|
||||
} else {
|
||||
malLoggedIn.set(loggedIn)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -98,7 +105,14 @@
|
||||
|
||||
<main>
|
||||
{#if isAniListLoggedIn}
|
||||
<div class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8">
|
||||
<div class="mx-auto max-w-2xl p-4 sm:p-6 lg:max-w-7xl lg:px-8 relative items-center">
|
||||
<div id="spinner" role="status" class="fixed hidden -translate-x-1/2 -translate-y-1/2 top-2/4 left-1/2">
|
||||
<svg aria-hidden="true" class="inline w-16 h-16 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
||||
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
||||
</svg>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
<h1 class="text-left text-xl font-bold mb-4">Your AniList WatchList</h1>
|
||||
|
||||
<Pagination />
|
||||
@ -107,7 +121,11 @@
|
||||
{#each aniListWatchListLoaded.data.Page.mediaList as media}
|
||||
<div class="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg xl:aspect-h-8 xl:aspect-w-7">
|
||||
<div class="flex flex-col items-center group">
|
||||
<button on:click={() => GetAniListSingleItemAndOpenModal(media.media.id, true)}>
|
||||
<button on:click={() => {
|
||||
let spinner = document.querySelector("#spinner")
|
||||
spinner.classList.toggle("hidden", false)
|
||||
GetAniListSingleItemAndOpenModal(media.media.id, true).then(() => spinner.classList.toggle("hidden", true))
|
||||
}}>
|
||||
<img class="rounded-lg" src={media.media.coverImage.large} alt={
|
||||
media.media.title.english === "" ?
|
||||
media.media.title.romaji :
|
||||
|
@ -3,7 +3,9 @@
|
||||
anilistModal,
|
||||
simklWatchList,
|
||||
aniListLoggedIn,
|
||||
simklLoggedIn
|
||||
simklLoggedIn,
|
||||
malLoggedIn,
|
||||
malAnime
|
||||
} from "./GlobalVariablesAndHelperFunctions.svelte";
|
||||
import {aniListAnime} from "./GlobalVariablesAndHelperFunctions.svelte";
|
||||
import {Button} from "flowbite-svelte";
|
||||
@ -14,16 +16,28 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import type {SimklAnime} from "./simkl/types/simklTypes";
|
||||
import { get } from 'svelte/store';
|
||||
import {AniListUpdateEntry, SimklSyncEpisodes, SimklSyncRating, SimklSyncStatus} from "../wailsjs/go/main/App";
|
||||
import {
|
||||
AniListUpdateEntry,
|
||||
SimklSyncEpisodes,
|
||||
SimklSyncRating,
|
||||
SimklSyncStatus
|
||||
} from "../wailsjs/go/main/App";
|
||||
import type {MALAnime} from "./mal/types/MALTypes";
|
||||
import type {AniListUpdateVariables} from "./anilist/types/AniListTypes";
|
||||
|
||||
const simklWatch = get(simklWatchList);
|
||||
let isAniListLoggedIn: boolean
|
||||
let isMalLoggedIn: boolean
|
||||
let isSimklLoggedIn: boolean
|
||||
let simklAnimeIndex: number
|
||||
let currentMalAnime: MALAnime
|
||||
let simklAnime: SimklAnime | undefined = undefined
|
||||
|
||||
aniListLoggedIn.subscribe((value) => isAniListLoggedIn = value)
|
||||
malLoggedIn.subscribe((value) => isMalLoggedIn = value)
|
||||
simklLoggedIn.subscribe((value) => isSimklLoggedIn = value)
|
||||
malAnime.subscribe((value) => currentMalAnime = value)
|
||||
|
||||
|
||||
for (let i = 0; i < simklWatch.anime.length; i++) {
|
||||
if (Number(simklWatch.anime[i].show.ids.mal) === aniListAnime.data.MediaList.media.idMal) {
|
||||
@ -35,23 +49,34 @@
|
||||
type statusOption = {
|
||||
id: number,
|
||||
aniList: string,
|
||||
mal: string,
|
||||
simkl: string,
|
||||
}
|
||||
|
||||
const statusOptions: statusOption[] = [
|
||||
{ id: 0, aniList: "CURRENT", simkl: "watching"},
|
||||
{ id: 1, aniList: "PLANNING", simkl: "plantowatch"},
|
||||
{ id: 2, aniList: "COMPLETED", simkl: "completed"},
|
||||
{ id: 3, aniList: "DROPPED", simkl: "dropped"},
|
||||
{ id: 4, aniList: "PAUSED", simkl: "hold"},
|
||||
{ id: 5, aniList: "REPEATING", simkl: "watching"}
|
||||
{ id: 0, aniList: "CURRENT", mal: "watching", simkl: "watching"},
|
||||
{ id: 1, aniList: "PLANNING", mal: "plan_to_watch", simkl: "plantowatch"},
|
||||
{ id: 2, aniList: "COMPLETED", mal: "completed", simkl: "completed"},
|
||||
{ id: 3, aniList: "DROPPED", mal: "dropped", simkl: "dropped"},
|
||||
{ id: 4, aniList: "PAUSED", mal: "on_hold", simkl: "hold"},
|
||||
{ id: 5, aniList: "REPEATING", mal: "rewatching", simkl: "watching"}
|
||||
]
|
||||
|
||||
let startingAnilistStatusOption: statusOption
|
||||
|
||||
startingAnilistStatusOption = statusOptions.filter(option => aniListAnime.data.MediaList.status === option.aniList)[0]
|
||||
|
||||
let items = [];
|
||||
let items = [] as {
|
||||
id: number
|
||||
service: string
|
||||
progress: number
|
||||
status: string
|
||||
startedAt: string
|
||||
completedAt: string
|
||||
score: number
|
||||
repeat: number
|
||||
notes: string
|
||||
}[];
|
||||
|
||||
if(isAniListLoggedIn) {
|
||||
items.push({
|
||||
@ -67,6 +92,20 @@
|
||||
})
|
||||
}
|
||||
|
||||
if(isMalLoggedIn) {
|
||||
items.push({
|
||||
id: currentMalAnime.id,
|
||||
service: "MyAnimeList",
|
||||
progress: currentMalAnime.my_list_status.num_episodes_watched,
|
||||
status: currentMalAnime.my_list_status.status,
|
||||
startedAt: currentMalAnime.my_list_status.start_date,
|
||||
completedAt: currentMalAnime.my_list_status.finish_date,
|
||||
score: currentMalAnime.my_list_status.score,
|
||||
repeat: currentMalAnime.my_list_status.num_times_rewatched,
|
||||
notes: currentMalAnime.my_list_status.comments
|
||||
})
|
||||
}
|
||||
|
||||
if(isSimklLoggedIn && simklAnime !== undefined) {
|
||||
items.push({
|
||||
id: simklAnime.show.ids.simkl,
|
||||
@ -114,7 +153,7 @@
|
||||
|
||||
const ratingInWords = {
|
||||
0: "Not Reviewed",
|
||||
1: "Apalling",
|
||||
1: "Appalling",
|
||||
2: "Horrible",
|
||||
3: "Very Bad",
|
||||
4: "Bad",
|
||||
@ -213,43 +252,45 @@
|
||||
}
|
||||
|
||||
const submitData = async () => {
|
||||
await AniListUpdateEntry(
|
||||
aniListAnime.data.MediaList.mediaId,
|
||||
values.progress,
|
||||
values.status.aniList,
|
||||
values.score,
|
||||
values.repeat,
|
||||
values.notes,
|
||||
values.startedAt.year,
|
||||
values.startedAt.month,
|
||||
values.startedAt.day,
|
||||
values.completedAt.year,
|
||||
values.completedAt.month,
|
||||
values.completedAt.day
|
||||
).then((value) => {
|
||||
let body: AniListUpdateVariables = {
|
||||
mediaId: aniListAnime.data.MediaList.mediaId,
|
||||
progress: values.progress,
|
||||
status: values.status.aniList,
|
||||
score: values.score,
|
||||
repeat: values.repeat,
|
||||
notes: values.notes,
|
||||
startedAt: {
|
||||
year: values.startedAt.year,
|
||||
month: values.startedAt.month,
|
||||
day: values.startedAt.day
|
||||
},
|
||||
completedAt: {
|
||||
year: values.completedAt.year,
|
||||
month: values.completedAt.month,
|
||||
day: values.completedAt.day
|
||||
}
|
||||
}
|
||||
await AniListUpdateEntry(body).then((value) => {
|
||||
console.log(value)
|
||||
})
|
||||
|
||||
if (simklLoggedIn) {
|
||||
if (simklAnime.watched_episodes_count !== values.progress) {
|
||||
await SimklSyncEpisodes(simklAnime, values.progress).then(value => {
|
||||
console.log(value)
|
||||
await SimklSyncEpisodes(simklAnime, values.progress).then(() => {
|
||||
simklAnime.watched_episodes_count = values.progress
|
||||
simklWatch.anime[simklAnimeIndex].watched_episodes_count = values.progress
|
||||
})
|
||||
}
|
||||
|
||||
if (simklAnime.user_rating !== values.score) {
|
||||
await SimklSyncRating(simklAnime, values.score).then(value => {
|
||||
console.log(value)
|
||||
await SimklSyncRating(simklAnime, values.score).then(() => {
|
||||
simklAnime.user_rating = values.score
|
||||
simklWatch.anime[simklAnimeIndex].user_rating = values.score
|
||||
})
|
||||
}
|
||||
|
||||
if (simklAnime.status !== values.status.simkl) {
|
||||
SimklSyncStatus(simklAnime, values.status.simkl).then(value => {
|
||||
console.log(value)
|
||||
SimklSyncStatus(simklAnime, values.status.simkl).then(() => {
|
||||
simklAnime.status = values.status.simkl
|
||||
simklWatch.anime[simklAnimeIndex].status = values.status.simkl
|
||||
})
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts" context="module">
|
||||
import {
|
||||
GetAniListItem,
|
||||
GetAniListLoggedInUser, GetAniListUserWatchingList, GetMyAnimeListLoggedInUser,
|
||||
GetAniListLoggedInUser, GetAniListUserWatchingList, GetMyAnimeListAnime, GetMyAnimeListLoggedInUser,
|
||||
GetSimklLoggedInUser, LogoutAniList, LogoutMyAnimeList, LogoutSimkl
|
||||
} from "../wailsjs/go/main/App";
|
||||
import type {
|
||||
@ -11,7 +11,7 @@
|
||||
import {writable} from 'svelte/store'
|
||||
import type {SimklUser, SimklWatchList} from "./simkl/types/simklTypes";
|
||||
import {type AniListUser, MediaListSort} from "./anilist/types/AniListTypes";
|
||||
import type {MALWatchlist, MyAnimeListUser} from "./mal/types/MALTypes";
|
||||
import type {MALAnime, MALWatchlist, MyAnimeListUser} from "./mal/types/MALTypes";
|
||||
|
||||
export let aniListAnime: AniListGetSingleAnime
|
||||
export let title = writable("")
|
||||
@ -21,11 +21,13 @@
|
||||
export let malLoggedIn = writable(false)
|
||||
export let simklWatchList = writable({} as SimklWatchList)
|
||||
export let aniListPrimary = writable(true)
|
||||
export let malPrimary = writable(false)
|
||||
export let simklUser = writable({} as SimklUser)
|
||||
export let aniListUser = writable({} as AniListUser)
|
||||
export let malUser = writable({} as MyAnimeListUser)
|
||||
export let aniListWatchlist = writable({} as AniListCurrentUserWatchList)
|
||||
export let malWatchList = writable({} as MALWatchlist)
|
||||
export let malAnime = writable({} as MALAnime)
|
||||
|
||||
export let watchListPage = writable(1)
|
||||
export let animePerPage = writable(20)
|
||||
@ -35,19 +37,34 @@
|
||||
let perPage: number
|
||||
let aniWatchlist: AniListCurrentUserWatchList
|
||||
|
||||
let isMalLoggedIn: boolean
|
||||
|
||||
aniListPrimary.subscribe(value => isAniListPrimary = value)
|
||||
watchListPage.subscribe(value => page = value)
|
||||
animePerPage.subscribe(value => perPage = value)
|
||||
aniListWatchlist.subscribe(value => aniWatchlist = value)
|
||||
malLoggedIn.subscribe(value => isMalLoggedIn = value)
|
||||
|
||||
export function GetAniListSingleItemAndOpenModal(aniId: number, login: boolean): void {
|
||||
GetAniListItem(aniId, login).then(result => {
|
||||
aniListAnime = result
|
||||
|
||||
export async function GetAniListSingleItemAndOpenModal(aniId: number, login: boolean): Promise<""> {
|
||||
await GetAniListItem(aniId, login).then(aniListResult => {
|
||||
aniListAnime = aniListResult
|
||||
title.set(aniListAnime.data.MediaList.media.title.english === "" ?
|
||||
aniListAnime.data.MediaList.media.title.romaji :
|
||||
aniListAnime.data.MediaList.media.title.english)
|
||||
if(isMalLoggedIn) {
|
||||
GetMyAnimeListAnime(aniListAnime.data.MediaList.media.idMal).then(malResult => {
|
||||
console.log(malResult)
|
||||
malAnime.set(malResult)
|
||||
anilistModal.set(true)
|
||||
return ""
|
||||
})
|
||||
} else {
|
||||
anilistModal.set(true)
|
||||
return ""
|
||||
}
|
||||
})
|
||||
return ""
|
||||
}
|
||||
|
||||
export function loginToSimkl(): void {
|
||||
|
@ -56,14 +56,18 @@
|
||||
<li class="w-full">
|
||||
<div class="flex w-full items-start p-1 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white rounded-lg">
|
||||
<button on:click={() => {
|
||||
GetAniListSingleItemAndOpenModal(media.id, false)
|
||||
let spinner = document.querySelector("#spinner")
|
||||
spinner.classList.toggle("hidden", false)
|
||||
GetAniListSingleItemAndOpenModal(media.id, false).then(() => spinner.classList.toggle("hidden", true))
|
||||
}}
|
||||
>
|
||||
<img class="rounded-bl-lg rounded-tl-lg max-w-24 max-h-24" src={media.coverImage.large}
|
||||
alt="{media.title.english === '' || media.title.english === null ? media.title.romaji : media.title.english} Cover">
|
||||
</button>
|
||||
<button class="rounded-bl-lg rounded-tl-lg w-full h-24" on:click={() => {
|
||||
GetAniListSingleItemAndOpenModal(media.id, false)
|
||||
let spinner = document.querySelector("#spinner")
|
||||
spinner.classList.toggle("hidden", false)
|
||||
GetAniListSingleItemAndOpenModal(media.id, false).then(() => spinner.classList.toggle("hidden", true))
|
||||
}} >{media.title.english === '' || media.title.english === null ? media.title.romaji : media.title.english }</button>
|
||||
</div>
|
||||
</li>
|
||||
|
@ -81,3 +81,26 @@ export enum MediaListSort {
|
||||
MediaPopularity = "MEDIA_POPULARITY",
|
||||
MediaPopularityDesc = "MEDIA_POPULARITY_DESC"
|
||||
}
|
||||
|
||||
export interface StartedAt {
|
||||
year: number
|
||||
month: number
|
||||
day: number
|
||||
}
|
||||
|
||||
export interface CompletedAt {
|
||||
year: number
|
||||
month: number
|
||||
day: number
|
||||
}
|
||||
|
||||
export interface AniListUpdateVariables {
|
||||
mediaId: number
|
||||
progress: number
|
||||
status: string
|
||||
score: number
|
||||
repeat: number
|
||||
notes: string
|
||||
startedAt: StartedAt
|
||||
completedAt: CompletedAt
|
||||
}
|
@ -31,13 +31,15 @@ export interface AnimeStatistics {
|
||||
}
|
||||
|
||||
export interface MALWatchlist {
|
||||
data: {
|
||||
node: Node
|
||||
listStatus: ListStatus
|
||||
}[]
|
||||
data: [MALAnimeFromList]
|
||||
paging: Paging
|
||||
}
|
||||
|
||||
export interface MALAnimeFromList {
|
||||
node: Node
|
||||
listStatus: ListStatus | MyListStatus
|
||||
}
|
||||
|
||||
export interface Node {
|
||||
id: number
|
||||
title: string
|
||||
@ -63,3 +65,90 @@ export interface Paging {
|
||||
previous: string
|
||||
next: string
|
||||
}
|
||||
|
||||
export interface MALAnime {
|
||||
id: number;
|
||||
title: string;
|
||||
main_picture: {
|
||||
large: string;
|
||||
medium: string;
|
||||
};
|
||||
alternative_titles: {
|
||||
synonyms: string[];
|
||||
en: string;
|
||||
ja: string;
|
||||
};
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
synopsis: string;
|
||||
mean: number;
|
||||
rank: number;
|
||||
popularity: number;
|
||||
num_list_users: number;
|
||||
num_scoring_users: number;
|
||||
nsfw: string;
|
||||
genres: {
|
||||
id: number;
|
||||
name: string;
|
||||
}[];
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
media_type: string;
|
||||
status: string;
|
||||
my_list_status: MyListStatus;
|
||||
num_episodes: number;
|
||||
start_season: {
|
||||
year: number;
|
||||
season: string;
|
||||
};
|
||||
broadcast: {
|
||||
day_of_the_week: string;
|
||||
start_time: string;
|
||||
};
|
||||
source: string;
|
||||
average_episode_duration: number;
|
||||
rating: string;
|
||||
studios: {
|
||||
id: number;
|
||||
name: string;
|
||||
}[];
|
||||
pictures: {
|
||||
large: string;
|
||||
medium: string;
|
||||
}[];
|
||||
background: string;
|
||||
related_anime: {
|
||||
node: MALAnime;
|
||||
relation_type: string;
|
||||
relation_type_formatted: string;
|
||||
}[];
|
||||
recommendations: {
|
||||
node: MALAnime;
|
||||
num_recommendations: number;
|
||||
}[];
|
||||
Statistics: {
|
||||
num_list_users: number;
|
||||
Status: {
|
||||
watching: string;
|
||||
completed: string;
|
||||
on_hold: string;
|
||||
dropped: string;
|
||||
plan_to_watch: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface MyListStatus {
|
||||
status: string;
|
||||
score: number;
|
||||
num_episodes_watched: number;
|
||||
is_rewatching: boolean;
|
||||
start_date: string;
|
||||
finish_date: string;
|
||||
priority: number;
|
||||
num_times_rewatched: number;
|
||||
rewatch_value: number;
|
||||
tags: string[];
|
||||
comments: string;
|
||||
updated_at: string;
|
||||
}
|
6
frontend/wailsjs/go/main/App.d.ts
vendored
6
frontend/wailsjs/go/main/App.d.ts
vendored
@ -6,7 +6,7 @@ export function AniListLogin():Promise<void>;
|
||||
|
||||
export function AniListSearch(arg1:string):Promise<any>;
|
||||
|
||||
export function AniListUpdateEntry(arg1:number,arg2:number,arg3:string,arg4:number,arg5:number,arg6:string,arg7:number,arg8:number,arg9:number,arg10:number,arg11:number,arg12:number):Promise<any>;
|
||||
export function AniListUpdateEntry(arg1:main.AniListUpdateVariables):Promise<any>;
|
||||
|
||||
export function CheckIfAniListLoggedIn():Promise<boolean>;
|
||||
|
||||
@ -22,6 +22,8 @@ export function GetAniListUserWatchingList(arg1:number,arg2:number,arg3:string):
|
||||
|
||||
export function GetMyAnimeList(arg1:number):Promise<main.MALWatchlist>;
|
||||
|
||||
export function GetMyAnimeListAnime(arg1:number):Promise<main.MALAnime>;
|
||||
|
||||
export function GetMyAnimeListLoggedInUser():Promise<main.MyAnimeListUser>;
|
||||
|
||||
export function GetSimklLoggedInUser():Promise<main.SimklUser>;
|
||||
@ -34,6 +36,8 @@ export function LogoutSimkl():Promise<string>;
|
||||
|
||||
export function MyAnimeListLogin():Promise<void>;
|
||||
|
||||
export function MyAnimeListUpdate(arg1:main.MALAnime,arg2:any):Promise<main.MyListStatus>;
|
||||
|
||||
export function SimklGetUserWatchlist():Promise<main.SimklWatchList>;
|
||||
|
||||
export function SimklLogin():Promise<void>;
|
||||
|
@ -10,8 +10,8 @@ export function AniListSearch(arg1) {
|
||||
return window['go']['main']['App']['AniListSearch'](arg1);
|
||||
}
|
||||
|
||||
export function AniListUpdateEntry(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) {
|
||||
return window['go']['main']['App']['AniListUpdateEntry'](arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
|
||||
export function AniListUpdateEntry(arg1) {
|
||||
return window['go']['main']['App']['AniListUpdateEntry'](arg1);
|
||||
}
|
||||
|
||||
export function CheckIfAniListLoggedIn() {
|
||||
@ -42,6 +42,10 @@ export function GetMyAnimeList(arg1) {
|
||||
return window['go']['main']['App']['GetMyAnimeList'](arg1);
|
||||
}
|
||||
|
||||
export function GetMyAnimeListAnime(arg1) {
|
||||
return window['go']['main']['App']['GetMyAnimeListAnime'](arg1);
|
||||
}
|
||||
|
||||
export function GetMyAnimeListLoggedInUser() {
|
||||
return window['go']['main']['App']['GetMyAnimeListLoggedInUser']();
|
||||
}
|
||||
@ -66,6 +70,10 @@ export function MyAnimeListLogin() {
|
||||
return window['go']['main']['App']['MyAnimeListLogin']();
|
||||
}
|
||||
|
||||
export function MyAnimeListUpdate(arg1, arg2) {
|
||||
return window['go']['main']['App']['MyAnimeListUpdate'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function SimklGetUserWatchlist() {
|
||||
return window['go']['main']['App']['SimklGetUserWatchlist']();
|
||||
}
|
||||
|
@ -60,6 +60,82 @@ export namespace main {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
export class CompletedAt {
|
||||
year: number;
|
||||
month: number;
|
||||
day: number;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new CompletedAt(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.year = source["year"];
|
||||
this.month = source["month"];
|
||||
this.day = source["day"];
|
||||
}
|
||||
}
|
||||
export class StartedAt {
|
||||
year: number;
|
||||
month: number;
|
||||
day: number;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new StartedAt(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.year = source["year"];
|
||||
this.month = source["month"];
|
||||
this.day = source["day"];
|
||||
}
|
||||
}
|
||||
export class AniListUpdateVariables {
|
||||
mediaId: number;
|
||||
progress: number;
|
||||
status: string;
|
||||
score: number;
|
||||
repeat: number;
|
||||
notes: string;
|
||||
startedAt: StartedAt;
|
||||
completedAt: CompletedAt;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new AniListUpdateVariables(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.mediaId = source["mediaId"];
|
||||
this.progress = source["progress"];
|
||||
this.status = source["status"];
|
||||
this.score = source["score"];
|
||||
this.repeat = source["repeat"];
|
||||
this.notes = source["notes"];
|
||||
this.startedAt = this.convertValues(source["startedAt"], StartedAt);
|
||||
this.completedAt = this.convertValues(source["completedAt"], CompletedAt);
|
||||
}
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
}
|
||||
if (a.slice && a.map) {
|
||||
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||
} else if ("object" === typeof a) {
|
||||
if (asMap) {
|
||||
for (const key of Object.keys(a)) {
|
||||
a[key] = new classs(a[key]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return new classs(a);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
export class AniListUser {
|
||||
// Go type: struct { Viewer struct { ID int "json:\"id\""; Name string "json:\"name\""; Avatar struct { Large string "json:\"large\""; Medium string "json:\"medium\"" } "json:\"avatar\""; BannerImage string "json:\"bannerImage\""; SiteUrl string "json:\"siteUrl\"" } "json:\"Viewer\"" }
|
||||
data: any;
|
||||
@ -121,6 +197,96 @@ export namespace main {
|
||||
this.anime_type = source["anime_type"];
|
||||
}
|
||||
}
|
||||
|
||||
export class MALAnime {
|
||||
id: id;
|
||||
title: title;
|
||||
// Go type: struct { Large string "json:\"large\" json:\"large\""; Medium string "json:\"medium\" json:\"medium\"" }
|
||||
main_picture: any;
|
||||
alternative_titles: alternativeTitles;
|
||||
start_date: startDate;
|
||||
end_date: endDate;
|
||||
synopsis: synopsis;
|
||||
mean: mean;
|
||||
rank: rank;
|
||||
popularity: popularity;
|
||||
num_list_users: numListUsers;
|
||||
num_scoring_users: numScoringUsers;
|
||||
nsfw: nsfw;
|
||||
genres: genres;
|
||||
created_at: createdAt;
|
||||
updated_at: updatedAt;
|
||||
media_type: mediaType;
|
||||
status: status;
|
||||
my_list_status: myListStatus;
|
||||
num_episodes: numEpisodes;
|
||||
start_season: startSeason;
|
||||
broadcast: broadcast;
|
||||
source: source;
|
||||
average_episode_duration: averageEpisodeDuration;
|
||||
rating: rating;
|
||||
studios: studios;
|
||||
pictures: pictures;
|
||||
background: background;
|
||||
related_anime: relatedAnime;
|
||||
recommendations: recommendations;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new MALAnime(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.id = source["id"];
|
||||
this.title = source["title"];
|
||||
this.main_picture = this.convertValues(source["main_picture"], Object);
|
||||
this.alternative_titles = source["alternative_titles"];
|
||||
this.start_date = source["start_date"];
|
||||
this.end_date = source["end_date"];
|
||||
this.synopsis = source["synopsis"];
|
||||
this.mean = source["mean"];
|
||||
this.rank = source["rank"];
|
||||
this.popularity = source["popularity"];
|
||||
this.num_list_users = source["num_list_users"];
|
||||
this.num_scoring_users = source["num_scoring_users"];
|
||||
this.nsfw = source["nsfw"];
|
||||
this.genres = source["genres"];
|
||||
this.created_at = source["created_at"];
|
||||
this.updated_at = source["updated_at"];
|
||||
this.media_type = source["media_type"];
|
||||
this.status = source["status"];
|
||||
this.my_list_status = source["my_list_status"];
|
||||
this.num_episodes = source["num_episodes"];
|
||||
this.start_season = source["start_season"];
|
||||
this.broadcast = source["broadcast"];
|
||||
this.source = source["source"];
|
||||
this.average_episode_duration = source["average_episode_duration"];
|
||||
this.rating = source["rating"];
|
||||
this.studios = source["studios"];
|
||||
this.pictures = source["pictures"];
|
||||
this.background = source["background"];
|
||||
this.related_anime = source["related_anime"];
|
||||
this.recommendations = source["recommendations"];
|
||||
}
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
}
|
||||
if (a.slice && a.map) {
|
||||
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||
} else if ("object" === typeof a) {
|
||||
if (asMap) {
|
||||
for (const key of Object.keys(a)) {
|
||||
a[key] = new classs(a[key]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return new classs(a);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
export class MALWatchlist {
|
||||
data: struct { Node struct { Id int "json:\"id\" ts_type:\"id\""; Title string "json:\"title\" ts_type:\"title\""; MainPicture struct { Medium string "json:\"medium\" json:\"medium\""; Large string "json:\"large\" json:\"large\"" } "json:\"main_picture\" json:\"mainPicture\"" } "json:\"node\" json:\"node\""; ListStatus struct { Status string "json:\"status\" ts_type:\"status\""; Score int "json:\"score\" ts_type:\"score\""; NumEpisodesWatched int "json:\"num_episodes_watched\" ts_type:\"numEpisodesWatched\""; IsRewatching bool "json:\"is_rewatching\" ts_type:\"isRewatching\""; UpdatedAt time.Time "json:\"updated_at\" ts_type:\"updatedAt\""; StartDate string "json:\"start_date\" ts_type:\"startDate\""; FinishDate string "json:\"finish_date\" ts_type:\"finishDate\"" } "json:\"list_status\" ts_type:\"listStatus\"" }[];
|
||||
paging: paging;
|
||||
@ -267,6 +433,40 @@ export namespace main {
|
||||
this.is_supporter = source["is_supporter"];
|
||||
}
|
||||
}
|
||||
export class MyListStatus {
|
||||
status: status;
|
||||
score: score;
|
||||
num_episodes_watched: numEpisodesWatched;
|
||||
is_rewatching: isRewatching;
|
||||
start_date: startDate;
|
||||
finish_date: finishDate;
|
||||
priority: priority;
|
||||
num_times_rewatched: numTimesRewatched;
|
||||
rewatch_value: rewatchValue;
|
||||
tags: tags;
|
||||
comments: comments;
|
||||
updated_at: updatedAt;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new MyListStatus(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.status = source["status"];
|
||||
this.score = source["score"];
|
||||
this.num_episodes_watched = source["num_episodes_watched"];
|
||||
this.is_rewatching = source["is_rewatching"];
|
||||
this.start_date = source["start_date"];
|
||||
this.finish_date = source["finish_date"];
|
||||
this.priority = source["priority"];
|
||||
this.num_times_rewatched = source["num_times_rewatched"];
|
||||
this.rewatch_value = source["rewatch_value"];
|
||||
this.tags = source["tags"];
|
||||
this.comments = source["comments"];
|
||||
this.updated_at = source["updated_at"];
|
||||
}
|
||||
}
|
||||
export class SimklUser {
|
||||
user: user;
|
||||
account: account;
|
||||
@ -333,6 +533,41 @@ export namespace struct { MediaList main {
|
||||
|
||||
}
|
||||
|
||||
export namespace struct { Node main {
|
||||
|
||||
export class {
|
||||
node: node;
|
||||
num_recommendations: numRecommendations;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new (source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.node = source["node"];
|
||||
this.num_recommendations = source["num_recommendations"];
|
||||
}
|
||||
}
|
||||
export class {
|
||||
node: node;
|
||||
relation_type: relationType;
|
||||
relation_type_formatted: relationTypeFormatted;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new (source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.node = source["node"];
|
||||
this.relation_type = source["relation_type"];
|
||||
this.relation_type_formatted = source["relation_type_formatted"];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace struct { Node struct { Id int "json:\"id\" ts_type:\"id\""; Title string "json:\"title\" ts_type:\"title\""; MainPicture struct { Medium string "json:\"medium\" json:\"medium\""; Large string "json:\"large\" json:\"large\"" } "json:\"main_picture\" json:\"mainPicture\"" } "json:\"node\" json:\"node\""; ListStatus struct { Status string "json:\"status\" ts_type:\"status\""; Score int "json:\"score\" ts_type:\"score\""; NumEpisodesWatched int "json:\"num_episodes_watched\" ts_type:\"numEpisodesWatched\""; IsRewatching bool "json:\"is_rewatching\" ts_type:\"isRewatching\""; UpdatedAt time {
|
||||
|
||||
export class {
|
||||
|
Loading…
Reference in New Issue
Block a user