diff --git a/AniListFunctions.go b/AniListFunctions.go index 4c88520..db13e51 100644 --- a/AniListFunctions.go +++ b/AniListFunctions.go @@ -355,7 +355,7 @@ func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) Ani return post } -func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) interface{} { +func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) AniListGetSingleAnime { body := struct { Query string `json:"query"` Variables AniListUpdateVariables `json:"variables"` @@ -381,12 +381,33 @@ func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) interface{} startedAt:$startedAt completedAt:$completedAt ){ + id mediaId - progress + userId + media { + id + idMal + title { + romaji + english + native + } + description + coverImage { + large + } + season + seasonYear + status + episodes + nextAiringEpisode { + airingAt + timeUntilAiring + episode + } + isAdult + } status - score - repeat - notes startedAt{ year month @@ -397,6 +418,27 @@ func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) interface{} month day } + notes + progress + score + repeat + user { + id + name + avatar{ + large + medium + } + statistics{ + anime{ + count + statuses{ + status + count + } + } + } + } } } `, @@ -405,11 +447,15 @@ func (a *App) AniListUpdateEntry(updateBody AniListUpdateVariables) interface{} returnedBody, _ := AniListQuery(body, true) - var post interface{} - err := json.Unmarshal(returnedBody, &post) + var returnedJson AniListUpdateReturn + err := json.Unmarshal(returnedBody, &returnedJson) if err != nil { log.Printf("Failed at unmarshal, %s\n", err) } + var post AniListGetSingleAnime + + post.Data.MediaList = returnedJson.Data.SaveMediaListEntry + return post } diff --git a/AniListTypes.go b/AniListTypes.go index 1d51f27..6cad8e6 100644 --- a/AniListTypes.go +++ b/AniListTypes.go @@ -43,6 +43,12 @@ type AniListGetSingleAnime struct { } `json:"data"` } +type AniListUpdateReturn struct { + Data struct { + SaveMediaListEntry MediaList `json:"SaveMediaListEntry"` + } +} + type MediaList struct { ID int `json:"id"` MediaID int `json:"mediaId"` diff --git a/MALFunctions.go b/MALFunctions.go index f19ea1e..6758c0b 100644 --- a/MALFunctions.go +++ b/MALFunctions.go @@ -55,7 +55,7 @@ func (a *App) GetMyAnimeList(count int) MALWatchlist { return malList } -func (a *App) MyAnimeListUpdate(anime MALAnime, update MALUploadStatus) MyListStatus { +func (a *App) MyAnimeListUpdate(anime MALAnime, update MALUploadStatus) MalListStatus { if update.NumTimesRewatched >= 1 { update.IsRewatching = true } else { @@ -70,7 +70,7 @@ func (a *App) MyAnimeListUpdate(anime MALAnime, update MALUploadStatus) MyListSt body.Set("comments", update.Comments) malUrl := "https://api.myanimelist.net/v2/anime/" + strconv.Itoa(anime.Id) + "/my_list_status" - var status MyListStatus + var status MalListStatus respBody := MALHelper("PATCH", malUrl, body) err := json.Unmarshal(respBody, &status) if err != nil { diff --git a/MALTypes.go b/MALTypes.go index e5fb078..2248902 100644 --- a/MALTypes.go +++ b/MALTypes.go @@ -91,13 +91,13 @@ type MALAnime 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 { + 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"` + MalListStatus MalListStatus `json:"my_list_status" ts_type:"MalListStatus"` + 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"` @@ -138,7 +138,7 @@ type MALAnime struct { } } -type MyListStatus struct { +type MalListStatus struct { Status string `json:"status" ts_type:"status"` Score int `json:"score" ts_type:"score"` NumEpisodesWatched int `json:"num_episodes_watched" ts_type:"numEpisodesWatched"` diff --git a/bruno/AniTrack/AniList/Get Items/AniList Item.bru b/bruno/AniTrack/AniList/Get Items/AniList Item.bru index 967138d..f1ad7a8 100644 --- a/bruno/AniTrack/AniList/Get Items/AniList Item.bru +++ b/bruno/AniTrack/AniList/Get Items/AniList Item.bru @@ -93,7 +93,7 @@ body:graphql { body:graphql:vars { { "userId": 413504, - "mediaId": 110, + "mediaId": 1, "listType": "ANIME" } } diff --git a/bruno/AniTrack/AniList/Set Items/AniList Change Episode Watched.bru b/bruno/AniTrack/AniList/Set Items/AniList Change Episode Watched.bru index 5cb35e7..831bfa6 100644 --- a/bruno/AniTrack/AniList/Set Items/AniList Change Episode Watched.bru +++ b/bruno/AniTrack/AniList/Set Items/AniList Change Episode Watched.bru @@ -19,12 +19,33 @@ headers { body:graphql { mutation($mediaId:Int, $progress:Int, $status:MediaListStatus){ SaveMediaListEntry(mediaId:$mediaId, progress:$progress, status:$status){ + id mediaId - progress + userId + media { + id + idMal + title { + romaji + english + native + } + description + coverImage { + large + } + season + seasonYear + status + episodes + nextAiringEpisode { + airingAt + timeUntilAiring + episode + } + isAdult + } status - score - repeat - notes startedAt{ year month @@ -35,14 +56,35 @@ body:graphql { month day } + notes + progress + score + repeat + user { + id + name + avatar{ + large + medium + } + statistics{ + anime{ + count + statuses{ + status + count + } + } + } + } } } } body:graphql:vars { { - "mediaId": 1, - "progress": 26, + "mediaId": 169417, + "progress": 12, "status":"COMPLETED" } } diff --git a/frontend/package.json b/frontend/package.json index f78b56d..ab77dba 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@popperjs/core": "^2.11.8", + "@tanstack/svelte-table": "^8.20.5", "flowbite": "^2.4.1", "flowbite-svelte": "^0.46.15", "moment": "^2.30.1" diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index b244ed9..e626869 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -112,6 +112,7 @@ '/anime/:id': wrap({ asyncComponent: () => import('./routes/Anime.svelte'), conditions: [ + () => $aniListLoggedIn, async (detail) => { await GetAniListSingleItem(Number(detail.params.id), true) return Object.keys($aniListAnime).length!==0 diff --git a/frontend/src/helperComponents/AddAnimeServiceToTable.svelte b/frontend/src/helperComponents/AddAnimeServiceToTable.svelte new file mode 100644 index 0000000..9197fac --- /dev/null +++ b/frontend/src/helperComponents/AddAnimeServiceToTable.svelte @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/frontend/src/helperComponents/AnimeTable.svelte b/frontend/src/helperComponents/AnimeTable.svelte new file mode 100644 index 0000000..ee22c9b --- /dev/null +++ b/frontend/src/helperComponents/AnimeTable.svelte @@ -0,0 +1,68 @@ + + + + + sortTable('id')}>ID + sortTable('service')}>Service + sortTable('progress')}>Episode Progress + sortTable('status')}>Status + sortTable('startedAt')}>Date Started + sortTable('completedAt')}>Date Completed + sortTable('score')}>Rating + sortTable('repeat')}>Rewatches + Notes + + + {#each $sortItems as item} + + {item.id} + {item.service} + {item.progress} + {item.status} + {item.startedAt} + {item.completedAt} + {item.score} + {item.repeat} + {item.notes} + + {/each} + +
\ No newline at end of file diff --git a/frontend/src/helperComponents/GlobalVariablesAndHelperFunctions.svelte b/frontend/src/helperComponents/GlobalVariablesAndHelperFunctions.svelte index a4a3817..ff10b01 100644 --- a/frontend/src/helperComponents/GlobalVariablesAndHelperFunctions.svelte +++ b/frontend/src/helperComponents/GlobalVariablesAndHelperFunctions.svelte @@ -20,6 +20,7 @@ import type {SimklAnime, SimklUser, SimklWatchList} from "../simkl/types/simklTypes"; import {type AniListUser, MediaListSort} from "../anilist/types/AniListTypes"; import type {MALAnime, MALWatchlist, MyAnimeListUser} from "../mal/types/MALTypes"; + import type {TableItems} from "../helperTypes/TableTypes"; export let aniListAnime = writable({} as AniListGetSingleAnime) export let title = writable("") @@ -38,6 +39,7 @@ export let malAnime = writable({} as MALAnime) export let simklAnime = writable({} as SimklAnime) export let loading = writable(false) + export let tableItems = writable([] as TableItems) export let watchListPage = writable(1) export let animePerPage = writable(20) diff --git a/frontend/src/helperComponents/Rating.svelte b/frontend/src/helperComponents/Rating.svelte new file mode 100644 index 0000000..26f89fd --- /dev/null +++ b/frontend/src/helperComponents/Rating.svelte @@ -0,0 +1,50 @@ + + +
+ +

Rating: {config.score * 2}

+

{ratingInWords[config.score * 2]}

+
diff --git a/frontend/src/helperFunctions/convertAniListDateToString.ts b/frontend/src/helperFunctions/convertAniListDateToString.ts new file mode 100644 index 0000000..e5ba3b1 --- /dev/null +++ b/frontend/src/helperFunctions/convertAniListDateToString.ts @@ -0,0 +1,17 @@ +import moment from "moment"; + +export default (date: { + year?: number, + month?: number, + day?: number, +}): string => { + if (date.year === undefined || date.year === 0 + && date.month === undefined || date.month === 0 + && date.day === undefined || date.day === 0 + ) { + return "" + } + const newISODate = new Date(date.year, date.month - 1, date.day) + const newMoment = moment(newISODate) + return newMoment.format('YYYY-MM-DD') +} \ No newline at end of file diff --git a/frontend/src/helperFunctions/convertDateStringToAniList.ts b/frontend/src/helperFunctions/convertDateStringToAniList.ts new file mode 100644 index 0000000..fb98ec5 --- /dev/null +++ b/frontend/src/helperFunctions/convertDateStringToAniList.ts @@ -0,0 +1,22 @@ +type Date = { + year: number, + month: number, + day: number, +} + +export default (date: string): Date => { + if (date === "") { + return { + year: 0, + month: 0, + day: 0, + } + } + const re = /^([0-9]{4})-([0-9]{2})-([0-9]{2})/ + const newDate = re.exec(date) + return { + year: Number(newDate[1]), + month: Number(newDate[2]), + day: Number(newDate[3]) + } +} \ No newline at end of file diff --git a/frontend/src/helperTypes/StatusTypes.ts b/frontend/src/helperTypes/StatusTypes.ts new file mode 100644 index 0000000..5afb4ad --- /dev/null +++ b/frontend/src/helperTypes/StatusTypes.ts @@ -0,0 +1,8 @@ +export type StatusOptions = StatusOption[] + +export type StatusOption = { + id: number, + aniList: string, + mal: string, + simkl: string, +} \ No newline at end of file diff --git a/frontend/src/helperTypes/TableTypes.ts b/frontend/src/helperTypes/TableTypes.ts new file mode 100644 index 0000000..67052ff --- /dev/null +++ b/frontend/src/helperTypes/TableTypes.ts @@ -0,0 +1,13 @@ +export type TableItems = TableItem[] + +export type TableItem = { + id: number + service: string + progress: number + status: string + startedAt: string + completedAt: string + score: number + repeat: number + notes: string +} \ No newline at end of file diff --git a/frontend/src/mal/types/MALTypes.ts b/frontend/src/mal/types/MALTypes.ts index 5a627b2..e08f7cc 100644 --- a/frontend/src/mal/types/MALTypes.ts +++ b/frontend/src/mal/types/MALTypes.ts @@ -37,7 +37,7 @@ export interface MALWatchlist { export interface MALAnimeFromList { node: Node - listStatus: ListStatus | MyListStatus + listStatus: ListStatus | MalListStatus } export interface Node { @@ -51,15 +51,6 @@ export interface MainPicture { large: string } -export interface ListStatus { - status: string - score: number - numEpisodesWatched: number - isRewatching: boolean - updated_at: string - startDate: string - finishDate: string -} export interface Paging { previous: string @@ -95,7 +86,7 @@ export interface MALAnime { updated_at: string; media_type: string; status: string; - my_list_status: MyListStatus; + my_list_status: MalListStatus; num_episodes: number; start_season: { year: number; @@ -138,7 +129,7 @@ export interface MALAnime { }; } -export interface MyListStatus { +export interface MalListStatus { status: string; score: number; num_episodes_watched: number; @@ -160,4 +151,14 @@ export interface MALUploadStatus { num_watched_episodes: number num_times_rewatched: number comments: string +} + +export interface ListStatus { + status: string + score: number + numEpisodesWatched: number + isRewatching: boolean + updated_at: string + startDate: string + finishDate: string } \ No newline at end of file diff --git a/frontend/src/routes/Anime.svelte b/frontend/src/routes/Anime.svelte index 8f35f3d..444f185 100644 --- a/frontend/src/routes/Anime.svelte +++ b/frontend/src/routes/Anime.svelte @@ -1,426 +1,282 @@ -
+
- {title} Cover Image - -

Rating: {config.score * 2}

-

{ratingInWords[config.score * 2]}

+ {title} Cover Image +
-
@@ -441,11 +297,11 @@
- + bind:value={currentAniListAnime.data.MediaList.notes}>
-
+

AniList

- - - sortTable('id')}>ID - sortTable('service')}>Service - sortTable('progress')}>Episode Progress - sortTable('status')}>Status - sortTable('startedAt')}>Date Started - sortTable('completedAt')}>Date Completed - sortTable('score')}>Rating - sortTable('repeat')}>Rewatches - Notes - - - {#each $sortItems as item} - - {item.id} - {item.service} - {item.progress} - {item.status} - {item.startedAt} - {item.completedAt} - {item.score} - {item.repeat} - {item.notes} - - {/each} - -
- +
@@ -599,4 +432,4 @@

{@html currentAniListAnime.data.MediaList.media.description}

-
\ No newline at end of file + \ No newline at end of file diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 8667655..004a4bc 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -6,7 +6,7 @@ export function AniListLogin():Promise; export function AniListSearch(arg1:string):Promise; -export function AniListUpdateEntry(arg1:main.AniListUpdateVariables):Promise; +export function AniListUpdateEntry(arg1:main.AniListUpdateVariables):Promise; export function CheckIfAniListLoggedIn():Promise; @@ -36,7 +36,7 @@ export function LogoutSimkl():Promise; export function MyAnimeListLogin():Promise; -export function MyAnimeListUpdate(arg1:main.MALAnime,arg2:main.MALUploadStatus):Promise; +export function MyAnimeListUpdate(arg1:main.MALAnime,arg2:main.MALUploadStatus):Promise; export function SimklGetUserWatchlist():Promise; diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index 2390c8b..e333d6e 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -188,7 +188,7 @@ export namespace main { updated_at: updatedAt; media_type: mediaType; status: status; - my_list_status: myListStatus; + my_list_status: MalListStatus; num_episodes: numEpisodes; start_season: startSeason; broadcast: broadcast; @@ -311,6 +311,40 @@ export namespace main { return a; } } + export class MalListStatus { + 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 MalListStatus(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 MediaList { id: number; mediaId: number; @@ -425,40 +459,6 @@ 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 SimklAnime { last_watched_at: last_watched_at; status: status;