9 Commits

12 changed files with 206 additions and 152 deletions

View File

@ -31,12 +31,15 @@ func AniListQuery(body interface{}, login bool) (json.RawMessage, string) {
defer res.Body.Close()
returnedBody, err := io.ReadAll(res.Body)
if err != nil {
return nil, "Could not read the returned body."
}
return returnedBody, res.Status
}
func (a *App) GetAniListItem(aniId int, login bool) AniListGetSingleAnime {
var user = a.GetAniListLoggedInUser()
user := a.GetAniListLoggedInUser()
var neededVariables interface{}
@ -141,7 +144,7 @@ func (a *App) GetAniListItem(aniId int, login bool) AniListGetSingleAnime {
returnedBody, status := AniListQuery(body, login)
var post AniListGetSingleAnime
if status == "404 Not Found" && login == false {
if status == "404 Not Found" && !login {
return post
}
@ -154,7 +157,7 @@ func (a *App) GetAniListItem(aniId int, login bool) AniListGetSingleAnime {
log.Printf("Failed at unmarshal, %s\n", err)
}
if login == false {
if !login {
post.Data.MediaList.UserID = user.Data.Viewer.ID
post.Data.MediaList.Status = ""
post.Data.MediaList.StartedAt.Year = 0
@ -249,7 +252,7 @@ func (a *App) AniListSearch(query string) any {
}
func (a *App) GetAniListUserWatchingList(page int, perPage int, sort string) AniListCurrentUserWatchList {
var user = a.GetAniListLoggedInUser()
user := a.GetAniListLoggedInUser()
type Variables struct {
Page int `json:"page"`
PerPage int `json:"perPage"`

View File

@ -30,11 +30,11 @@ var aniCtxShutdown, aniCancel = context.WithCancel(context.Background())
func (a *App) CheckIfAniListLoggedIn() bool {
if (AniListJWT{} == aniListJwt) {
tokenType, err := aniRing.Get("anilistTokenType")
expiresIn, err := aniRing.Get("anilistTokenExpiresIn")
accessToken, err := aniRing.Get("anilistAccessToken")
refreshToken, err := aniRing.Get("anilistRefreshToken")
if err != nil || len(accessToken.Data) == 0 {
tokenType, tokenErr := aniRing.Get("anilistTokenType")
expiresIn, expiresInErr := aniRing.Get("anilistTokenExpiresIn")
refreshToken, refreshTokenErr := aniRing.Get("anilistRefreshToken")
accessToken, accessTokenErr := aniRing.Get("anilistAccessToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
return false
} else {
aniListJwt.TokenType = string(tokenType.Data)
@ -50,11 +50,11 @@ func (a *App) CheckIfAniListLoggedIn() bool {
func (a *App) AniListLogin() {
if (AniListJWT{} == aniListJwt) {
tokenType, err := aniRing.Get("anilistTokenType")
expiresIn, err := aniRing.Get("anilistTokenExpiresIn")
accessToken, err := aniRing.Get("anilistAccessToken")
refreshToken, err := aniRing.Get("anilistRefreshToken")
if err != nil || len(accessToken.Data) == 0 {
tokenType, tokenErr := aniRing.Get("anilistTokenType")
expiresIn, expiresInErr := aniRing.Get("anilistTokenExpiresIn")
refreshToken, refreshTokenErr := aniRing.Get("anilistRefreshToken")
accessToken, accessTokenErr := aniRing.Get("anilistAccessToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
getAniListCodeUrl := "https://anilist.co/api/v2/oauth/authorize?client_id=" + Environment.ANILIST_APP_ID + "&redirect_uri=" + Environment.ANILIST_CALLBACK_URI + "&response_type=code"
runtime.BrowserOpenURL(*wailsContext, getAniListCodeUrl)
@ -160,6 +160,9 @@ func getAniListAuthorizationToken(content string) AniListJWT {
defer res.Body.Close()
returnedBody, err := io.ReadAll(res.Body)
if err != nil {
log.Printf("Could not read returned body, %s\n.", err)
}
var post AniListJWT
err = json.Unmarshal(returnedBody, &post)
@ -204,13 +207,12 @@ func (a *App) GetAniListLoggedInUser() AniListUser {
func (a *App) LogoutAniList() string {
if (AniListJWT{} != aniListJwt) {
err := aniRing.Remove("anilistTokenType")
err = aniRing.Remove("anilistTokenExpiresIn")
err = aniRing.Remove("anilistAccessToken")
err = aniRing.Remove("anilistRefreshToken")
if err != nil {
fmt.Println("AniList Logout Failed", err)
typeErr := aniRing.Remove("anilistTokenType")
expiresInErr := aniRing.Remove("anilistTokenExpiresIn")
accessTokenErr := aniRing.Remove("anilistAccessToken")
refreshTokenErr := aniRing.Remove("anilistRefreshToken")
if typeErr != nil || expiresInErr != nil || accessTokenErr != nil || refreshTokenErr != nil {
fmt.Println("AniList Logout Failed")
}
aniListJwt = AniListJWT{}
}

View File

@ -46,10 +46,10 @@ type MALWatchlist 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"`
Medium string `json:"medium" ts_type:"medium"`
Large string `json:"large" ts_type:"large"`
} `json:"main_picture" ts_type:"mainPicture"`
} `json:"node" ts_type:"node"`
ListStatus struct {
Status string `json:"status" ts_type:"status"`
Score int `json:"score" ts_type:"score"`
@ -59,7 +59,7 @@ type MALWatchlist struct {
StartDate string `json:"start_date" ts_type:"startDate"`
FinishDate string `json:"finish_date" ts_type:"finishDate"`
} `json:"list_status" ts_type:"listStatus"`
} `json:"data" json:"data"`
} `json:"data" ts_type:"data"`
Paging struct {
Previous string `json:"previous" ts_type:"previous"`
Next string `json:"next" ts_type:"next"`
@ -70,9 +70,9 @@ 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"`
Large string `json:"large" ts_type:"large"`
Medium string `json:"medium" ts_type:"medium"`
} `json:"main_picture" ts_type:"mainPicture"`
AlternativeTitles struct {
Synonyms []string `json:"synonyms" ts_type:"synonyms"`
En string `json:"en" ts_type:"en"`

View File

@ -50,7 +50,7 @@ func base64URLEncode(str []byte) string {
func verifier() (*CodeVerifier, error) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
b := make([]byte, length, length)
b := make([]byte, length)
for i := 0; i < length; i++ {
b[i] = byte(r.Intn(255))
}
@ -70,17 +70,19 @@ func (v *CodeVerifier) CodeChallengeS256() string {
}
func (a *App) CheckIfMyAnimeListLoggedIn() bool {
fmt.Println("check function reached")
if (MyAnimeListJWT{} == myAnimeListJwt) {
tokenType, err := myAnimeListRing.Get("MyAnimeListTokenType")
expiresIn, err := myAnimeListRing.Get("MyAnimeListExpiresIn")
accessToken, err := myAnimeListRing.Get("MyAnimeListAccessToken")
refreshToken, err := myAnimeListRing.Get("MyAnimeListRefreshToken")
if err != nil || len(accessToken.Data) == 0 {
tokenType, tokenErr := myAnimeListRing.Get("MyAnimeListTokenType")
expiresIn, expiresInErr := myAnimeListRing.Get("MyAnimeListExpiresIn")
refreshToken, refreshTokenErr := myAnimeListRing.Get("MyAnimeListAccessToken")
accessToken, accessTokenErr := myAnimeListRing.Get("MyAnimeListRefreshToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
return false
} else {
var expresInConvertErr error
myAnimeListJwt.TokenType = string(tokenType.Data)
myAnimeListJwt.ExpiresIn, err = strconv.Atoi(string(expiresIn.Data))
if err != nil {
myAnimeListJwt.ExpiresIn, expresInConvertErr = strconv.Atoi(string(expiresIn.Data))
if expresInConvertErr != nil {
fmt.Println("unable to convert string to int")
}
myAnimeListJwt.AccessToken = string(accessToken.Data)
@ -93,12 +95,14 @@ func (a *App) CheckIfMyAnimeListLoggedIn() bool {
}
func (a *App) MyAnimeListLogin() {
if a.CheckIfMyAnimeListLoggedIn() == false {
tokenType, err := myAnimeListRing.Get("MyAnimeListTokenType")
expiresIn, err := myAnimeListRing.Get("MyAnimeListExpiresIn")
accessToken, err := myAnimeListRing.Get("MyAnimeListAccessToken")
refreshToken, err := myAnimeListRing.Get("MyAnimeListRefreshToken")
if err != nil || len(accessToken.Data) == 0 {
fmt.Println("login function reached")
if !a.CheckIfMyAnimeListLoggedIn() {
fmt.Println("check logged in function failed")
tokenType, tokenErr := myAnimeListRing.Get("MyAnimeListTokenType")
expiresIn, expiresInErr := myAnimeListRing.Get("MyAnimeListExpiresIn")
refreshToken, refreshTokenErr := myAnimeListRing.Get("MyAnimeListAccessToken")
accessToken, accessTokenErr := myAnimeListRing.Get("MyAnimeListRefreshToken")
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
verifier, _ := verifier()
getMyAnimeListCodeUrl := "https://myanimelist.net/v1/oauth2/authorize?response_type=code&client_id=" + Environment.MAL_CLIENT_ID + "&redirect_uri=" + Environment.MAL_CALLBACK_URI + "&code_challenge=" + verifier.Value + "&code_challenge_method=plain"
runtime.BrowserOpenURL(*wailsContext, getMyAnimeListCodeUrl)
@ -107,9 +111,10 @@ func (a *App) MyAnimeListLogin() {
a.handleMyAnimeListCallback(serverDone, verifier)
serverDone.Wait()
} else {
var expresInConvertErr error
myAnimeListJwt.TokenType = string(tokenType.Data)
myAnimeListJwt.ExpiresIn, err = strconv.Atoi(string(expiresIn.Data))
if err != nil {
myAnimeListJwt.ExpiresIn, expresInConvertErr = strconv.Atoi(string(expiresIn.Data))
if expresInConvertErr != nil {
fmt.Println("unable to convert string to int in Login function")
}
myAnimeListJwt.AccessToken = string(accessToken.Data)
@ -218,6 +223,9 @@ func getMyAnimeListAuthorizationToken(content string, verifier *CodeVerifier) My
defer res.Body.Close()
returnedBody, err := io.ReadAll(res.Body)
if err != nil {
log.Printf("Could not read returned body, %s\n", err)
}
var post MyAnimeListJWT
err = json.Unmarshal(returnedBody, &post)
@ -265,6 +273,9 @@ func refreshMyAnimeListAuthorizationToken() {
defer res.Body.Close()
returnedBody, err := io.ReadAll(res.Body)
if err != nil {
log.Printf("Could not read returned body, %s\n", err)
}
err = json.Unmarshal(returnedBody, &myAnimeListJwt)
if err != nil {
@ -291,12 +302,9 @@ func refreshMyAnimeListAuthorizationToken() {
Title: "MyAnimeList Authorization",
Message: "It is now safe to close your browser tab",
})
if err != nil {
fmt.Println(err)
}
return
}
func (a *App) GetMyAnimeListLoggedInUser() MyAnimeListUser {
@ -311,7 +319,6 @@ func (a *App) GetMyAnimeListLoggedInUser() MyAnimeListUser {
req.Header.Add("myAnimeList-api-key", Environment.MAL_CLIENT_ID)
response, err := client.Do(req)
if err != nil {
log.Printf("Failed at request, %s\n", err)
return MyAnimeListUser{}
@ -333,13 +340,12 @@ func (a *App) GetMyAnimeListLoggedInUser() MyAnimeListUser {
func (a *App) LogoutMyAnimeList() string {
if (MyAnimeListJWT{} != myAnimeListJwt) {
err := myAnimeListRing.Remove("MyAnimeListTokenType")
err = myAnimeListRing.Remove("MyAnimeListExpiresIn")
err = myAnimeListRing.Remove("MyAnimeListAccessToken")
err = myAnimeListRing.Remove("MyAnimeListRefreshToken")
if err != nil {
fmt.Println("MAL Logout Failed", err)
typeErr := myAnimeListRing.Remove("MyAnimeListTokenType")
expiresInErr := myAnimeListRing.Remove("MyAnimeListExpiresIn")
accessTokenErr := myAnimeListRing.Remove("MyAnimeListAccessToken")
refreshTokenErr := myAnimeListRing.Remove("MyAnimeListRefreshToken")
if typeErr != nil || expiresInErr != nil || accessTokenErr != nil || refreshTokenErr != nil {
fmt.Println("MAL Logout Failed")
}
myAnimeListJwt = MyAnimeListJWT{}
}

View File

@ -31,7 +31,6 @@ func SimklHelper(method string, url string, body interface{}) json.RawMessage {
req.Header.Add("simkl-api-key", Environment.SIMKL_CLIENT_ID)
resp, err := client.Do(req)
if err != nil {
fmt.Println("Errored when sending request to the server")
message, _ := json.Marshal(struct {
@ -47,7 +46,6 @@ func SimklHelper(method string, url string, body interface{}) json.RawMessage {
respBody, _ := io.ReadAll(resp.Body)
return respBody
}
func (a *App) SimklGetUserWatchlist() SimklWatchListType {
@ -62,7 +60,6 @@ func (a *App) SimklGetUserWatchlist() SimklWatchListType {
}
err := json.Unmarshal(respBody, &errCheck)
if err != nil {
log.Printf("Failed at unmarshal, %s\n", err)
}
@ -85,7 +82,6 @@ func (a *App) SimklGetUserWatchlist() SimklWatchListType {
}
func (a *App) SimklSyncEpisodes(anime SimklAnime, progress int) SimklAnime {
var episodes []Episode
var url string
var shows []SimklPostShow
@ -140,7 +136,7 @@ func (a *App) SimklSyncEpisodes(anime SimklAnime, progress int) SimklAnime {
func (a *App) SimklSyncRating(anime SimklAnime, rating int) SimklAnime {
var url string
var showWithRating = ShowWithRating{
showWithRating := ShowWithRating{
Title: anime.Show.Title,
Ids: Ids{
Simkl: anime.Show.Ids.Simkl,
@ -150,7 +146,7 @@ func (a *App) SimklSyncRating(anime SimklAnime, rating int) SimklAnime {
Rating: rating,
}
var showWithoutRating = ShowWithoutRating{
showWithoutRating := ShowWithoutRating{
Title: anime.Show.Title,
Ids: Ids{
Simkl: anime.Show.Ids.Simkl,
@ -197,7 +193,7 @@ func (a *App) SimklSyncRating(anime SimklAnime, rating int) SimklAnime {
func (a *App) SimklSyncStatus(anime SimklAnime, status string) SimklAnime {
url := "https://api.simkl.com/sync/add-to-list"
var show = SimklShowStatus{
show := SimklShowStatus{
Title: anime.Show.Title,
Ids: Ids{
Simkl: anime.Show.Ids.Simkl,
@ -300,7 +296,7 @@ func (a *App) SimklSyncRemove(anime SimklAnime) bool {
url := "https://api.simkl.com/sync/history/remove"
var showArray []SimklShowStatus
var singleShow = SimklShowStatus{
singleShow := SimklShowStatus{
Title: anime.Show.Title,
Ids: Ids{
Simkl: anime.Show.Ids.Simkl,
@ -349,5 +345,4 @@ func WatchListUpdate(anime SimklAnime) {
if !updated {
SimklWatchList.Anime = append(SimklWatchList.Anime, anime)
}
return
}

View File

@ -28,10 +28,10 @@ var simklCtxShutdown, simklCancel = context.WithCancel(context.Background())
func (a *App) CheckIfSimklLoggedIn() bool {
if (SimklJWT{} == simklJwt) {
tokenType, err := simklRing.Get("SimklTokenType")
accessToken, err := simklRing.Get("SimklAccessToken")
scope, err := simklRing.Get("SimklScope")
if err != nil || len(accessToken.Data) == 0 {
tokenType, tokenTypeErr := simklRing.Get("SimklTokenType")
accessToken, accessTokenErr := simklRing.Get("SimklAccessToken")
scope, scopeErr := simklRing.Get("SimklScope")
if (tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil) || len(accessToken.Data) == 0 {
return false
} else {
simklJwt.TokenType = string(tokenType.Data)
@ -45,11 +45,11 @@ func (a *App) CheckIfSimklLoggedIn() bool {
}
func (a *App) SimklLogin() {
if a.CheckIfSimklLoggedIn() == false {
tokenType, err := simklRing.Get("SimklTokenType")
accessToken, err := simklRing.Get("SimklAccessToken")
scope, err := simklRing.Get("SimklScope")
if err != nil || len(accessToken.Data) == 0 {
if !a.CheckIfSimklLoggedIn() {
tokenType, tokenTypeErr := simklRing.Get("SimklTokenType")
accessToken, accessTokenErr := simklRing.Get("SimklAccessToken")
scope, scopeErr := simklRing.Get("SimklScope")
if (tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil) || len(accessToken.Data) == 0 {
getSimklCodeUrl := "https://simkl.com/oauth/authorize?response_type=code&client_id=" + Environment.SIMKL_CLIENT_ID + "&redirect_uri=" + Environment.SIMKL_CALLBACK_URI
runtime.BrowserOpenURL(*wailsContext, getSimklCodeUrl)
@ -155,6 +155,9 @@ func getSimklAuthorizationToken(content string) SimklJWT {
defer res.Body.Close()
returnedBody, err := io.ReadAll(res.Body)
if err != nil {
log.Printf("Could not read returned body, %s\n.", err)
}
var post SimklJWT
err = json.Unmarshal(returnedBody, &post)
@ -177,7 +180,6 @@ func (a *App) GetSimklLoggedInUser() SimklUser {
req.Header.Add("simkl-api-key", Environment.SIMKL_CLIENT_ID)
response, err := client.Do(req)
if err != nil {
log.Printf("Failed at request, %s\n", err)
return SimklUser{}
@ -193,7 +195,6 @@ func (a *App) GetSimklLoggedInUser() SimklUser {
}
err = json.Unmarshal(respBody, &errCheck)
if err != nil {
log.Printf("Failed at unmarshal, %s\n", err)
}
@ -215,12 +216,12 @@ func (a *App) GetSimklLoggedInUser() SimklUser {
func (a *App) LogoutSimkl() string {
if (SimklJWT{} != simklJwt) {
err := simklRing.Remove("SimklTokenType")
err = simklRing.Remove("SimklAccessToken")
err = simklRing.Remove("SimklScope")
tokenTypeErr := simklRing.Remove("SimklTokenType")
accessTokenErr := simklRing.Remove("SimklAccessToken")
scopeErr := simklRing.Remove("SimklScope")
if err != nil {
fmt.Println("Simkl Logout Failed", err)
if tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil {
fmt.Println("Simkl Logout Failed")
}
simklJwt = SimklJWT{}
}

11
build/AniTrack.desktop Executable file
View File

@ -0,0 +1,11 @@
[Desktop Entry]
Name=AniTrack
Comment=A manual synchronizer for various Anime trackers.
Exec=/home/nymusicman/Applications/AniTrack
Icon=AniTrack
Terminal=false
Type=Application
StartupNotify=true
Categories=Internet
Keywords=anitrack;anilist;simkl;mal;myanimelist;anime;sync
Path=

View File

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -193,9 +193,9 @@
};
await AniListUpdateEntry(body).then(
(value: AniListGetSingleAnime) => {
// in future when you inevitably add tags to typescript, until Anilist fixes the api bug
// where tags break the SaveMediaListEntry return, you'll want to use this delete line
// delete value.data.MediaList.media.tags
/* TODO in future when you inevitably add tags to typescript, until Anilist fixes the api bug
where tags break the SaveMediaListEntry return, you'll want to use this delete line
delete value.data.MediaList.media.tags */
aniListAnime.update((newValue) => {
newValue = value;
return newValue;
@ -397,6 +397,20 @@
submitSuccess.set(true);
setTimeout(() => submitSuccess.set(false), 2000);
};
let max = 999;
if (currentAniListAnime.data.MediaList.media.episodes !== 0) {
max = currentAniListAnime.data.MediaList.media.episodes;
}
if (
currentAniListAnime.data.MediaList.media.episodes === 0 &&
currentAniListAnime.data.MediaList.media.nextAiringEpisode.episode !== 0
) {
max =
currentAniListAnime.data.MediaList.media.nextAiringEpisode.episode -
1;
}
</script>
<form on:submit|preventDefault={handleSubmit} class="container pt-3 pb-10">
@ -423,24 +437,81 @@
class="text-left block mb-2 text-sm font-medium text-white"
>Episode Progress</label
>
<div class="relative flex items-center max-w-[8rem]">
<button
type="button"
id="decrement-button"
data-input-counter-decrement="quantity-input"
on:click={() =>
(currentAniListAnime.data.MediaList.progress -= 1)}
class="bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 hover:bg-gray-200 border border-gray-300 rounded-s-lg p-3 h-11 focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none"
>
<svg
class="w-3 h-3 text-gray-900 dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 18 2"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M1 1h16"
/>
</svg>
</button>
<input
type="number"
name="episodes"
min="0"
max={currentAniListAnime.data.MediaList.media.episodes}
{max}
id="episodes"
class="border {currentAniListAnime.data.MediaList
.progress < 0 ||
class="border border-x-0 p-2.5 h-11 text-center text-sm block w-full placeholder-gray-400 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none
{currentAniListAnime.data.MediaList.progress < 0 ||
(currentAniListAnime.data.MediaList.media.episodes >
0 &&
currentAniListAnime.data.MediaList.progress >
currentAniListAnime.data.MediaList.media
.episodes)
.episodes) ||
(currentAniListAnime.data.MediaList.media
.nextAiringEpisode.episode > 0 &&
currentAniListAnime.data.MediaList.progress >
currentAniListAnime.data.MediaList.media
.nextAiringEpisode.episode -
1)
? 'border-red-500 border-[2px] text-rose-300 focus:ring-red-500 focus:border-red-500'
: 'border-gray-500 text-white focus:ring-blue-500 focus:border-blue-500'} text-sm rounded-lg block w-24 p-2.5 bg-gray-600 placeholder-gray-400"
bind:value={currentAniListAnime.data.MediaList.progress}
: 'bg-gray-700 hover:bg-gray-600 border-gray-600 text-white focus:ring-blue-500 focus:border-blue-500'} w-24"
bind:value={currentAniListAnime.data.MediaList
.progress}
required
/>
<button
type="button"
id="increment-button"
data-input-counter-increment="quantity-input"
on:click={() =>
(currentAniListAnime.data.MediaList.progress += 1)}
class="bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 hover:bg-gray-200 border border-gray-300 rounded-e-lg p-3 h-11 focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none"
>
<svg
class="w-3 h-3 text-gray-900 dark:text-white"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 18 18"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 1v16M1 9h16"
/>
</svg>
</button>
</div>
<div>
/ {currentAniListAnime.data.MediaList.media
.nextAiringEpisode.episode !== 0
@ -448,9 +519,12 @@
.nextAiringEpisode.episode - 1
: currentAniListAnime.data.MediaList.media.episodes}
</div>
{#if currentAniListAnime.data.MediaList.media.nextAiringEpisode.episode !== 0}
<div>
of {currentAniListAnime.data.MediaList.media.episodes}
of {currentAniListAnime.data.MediaList.media
.episodes}
</div>
{/if}
</div>
<div>

View File

@ -202,8 +202,7 @@ export namespace main {
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;
main_picture: mainPicture;
alternative_titles: alternativeTitles;
start_date: startDate;
end_date: endDate;
@ -242,7 +241,7 @@ export namespace main {
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.main_picture = source["main_picture"];
this.alternative_titles = source["alternative_titles"];
this.start_date = source["start_date"];
this.end_date = source["end_date"];
@ -314,7 +313,7 @@ export namespace main {
}
}
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\"" }[];
data: data;
paging: paging;
static createFrom(source: any = {}) {
@ -323,27 +322,9 @@ export namespace main {
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.data = this.convertValues(source["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\"" });
this.data = source["data"];
this.paging = source["paging"];
}
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 MalListStatus {
status: status;
@ -624,11 +605,10 @@ export namespace struct { Node main {
}
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 namespace struct { Node struct { Id int "json:\"id\" ts_type:\"id\""; Title string "json:\"title\" ts_type:\"title\""; MainPicture struct { Medium string "json:\"medium\" ts_type:\"medium\""; Large string "json:\"large\" ts_type:\"large\"" } "json:\"main_picture\" ts_type:\"mainPicture\"" } "json:\"node\" ts_type:\"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 {
// Go type: 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\"" }
node: any;
node: node;
list_status: listStatus;
static createFrom(source: any = {}) {
@ -637,27 +617,9 @@ export namespace struct { Node struct { Id int "json:\"id\" ts_type:\"id\""; Tit
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.node = this.convertValues(source["node"], Object);
this.node = source["node"];
this.list_status = source["list_status"];
}
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;
}
}
}

View File

@ -34,7 +34,7 @@ func main() {
app,
},
Linux: &linux.Options{
Icon: []byte("./build/appicon.png"),
Icon: []byte("./build/AniTrack.png"),
WindowIsTranslucent: false,
WebviewGpuPolicy: linux.WebviewGpuPolicyAlways,
ProgramName: "AniTrack",

View File

@ -12,6 +12,6 @@
},
"info": {
"productName": "AniTrack",
"productVersion": "0.1.2"
"productVersion": "0.1.4"
}
}