From fb2d5fbdeaa3069fb10bef2948a6fc76bfea1294 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Fri, 16 Aug 2024 15:07:06 -0400 Subject: [PATCH] added ability to get anime as needed from MAL --- MALFunctions.go | 18 ++ MALTypes.go | 87 +++++++ frontend/src/App.svelte | 15 +- frontend/src/ChangeDataDialogue.svelte | 101 +++++--- .../GlobalVariablesAndHelperFunctions.svelte | 24 +- frontend/src/anilist/types/AniListTypes.ts | 23 ++ frontend/src/mal/types/MALTypes.ts | 97 +++++++- frontend/wailsjs/go/main/App.d.ts | 6 +- frontend/wailsjs/go/main/App.js | 12 +- frontend/wailsjs/go/models.ts | 235 ++++++++++++++++++ 10 files changed, 572 insertions(+), 46 deletions(-) diff --git a/MALFunctions.go b/MALFunctions.go index 64b129e..140a838 100644 --- a/MALFunctions.go +++ b/MALFunctions.go @@ -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 +} diff --git a/MALTypes.go b/MALTypes.go index 6206917..940676b 100644 --- a/MALTypes.go +++ b/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"` +} diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index df4de48..92d5821 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -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) - GetMyAnimeList(1000).then(watchList => { - malWatchList.set(watchList) + if (isMalPrimary){ + GetMyAnimeList(1000).then(watchList => { + malWatchList.set(watchList) + malLoggedIn.set(loggedIn) + }) + } else { malLoggedIn.set(loggedIn) - }) + } }) } }) diff --git a/frontend/src/ChangeDataDialogue.svelte b/frontend/src/ChangeDataDialogue.svelte index bf0fc1b..e031604 100644 --- a/frontend/src/ChangeDataDialogue.svelte +++ b/frontend/src/ChangeDataDialogue.svelte @@ -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 }) diff --git a/frontend/src/GlobalVariablesAndHelperFunctions.svelte b/frontend/src/GlobalVariablesAndHelperFunctions.svelte index 8b0021e..b5602fa 100644 --- a/frontend/src/GlobalVariablesAndHelperFunctions.svelte +++ b/frontend/src/GlobalVariablesAndHelperFunctions.svelte @@ -1,7 +1,7 @@