From 1b82343dd0bcb778714e30d6ed52b915f78a4a04 Mon Sep 17 00:00:00 2001 From: Cosmic Predator Date: Thu, 6 Feb 2025 21:16:20 +0530 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20[cmd=5Flist.go]=20Added=20REPEA?= =?UTF-8?q?TING=20list=20to=20rows=20=E2=9C=A8=20[media=5Flist.go]=20Added?= =?UTF-8?q?=20STATUS=20field=20and=20merge=20REPEATING=20with=20CURRENT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/cmd_list.go | 30 ++++++++++++++++++++++++++---- internal/media_list.go | 20 +++++++++++++++----- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/cmd/cmd_list.go b/cmd/cmd_list.go index d7f4787..ec4c547 100644 --- a/cmd/cmd_list.go +++ b/cmd/cmd_list.go @@ -41,6 +41,28 @@ func handleLs() { } rows := [][]string{} + + for _, lists := range mediaList.Data.MediaListCollection.Lists { + for _, entry := range lists.Entries { + var progress string + if mediaType == "ANIME" { + progress = fmt.Sprintf("%d/%d", entry.Progress, entry.Media.Episodes) + } else { + progress = fmt.Sprintf("%d/%d", entry.Progress, entry.Media.Chapters) + } + + if lists.Status == "REPEATING" { + entry.Media.Title.UserPreferred = "(R) " + entry.Media.Title.UserPreferred + } + + rows = append(rows, []string{ + strconv.Itoa(entry.Media.Id), + entry.Media.Title.UserPreferred, + progress, + }) + } + } + for _, i := range mediaList.Data.MediaListCollection.Lists[0].Entries { var progress string if mediaType == "ANIME" { @@ -85,9 +107,9 @@ func handleLs() { } var mediaListCmd = &cobra.Command{ - Use: "list", - Short: "List your current anime/manga list", - Aliases: []string{ "ls" }, + Use: "list", + Short: "List your current anime/manga list", + Aliases: []string{"ls"}, Run: func(cmd *cobra.Command, args []string) { handleLs() }, @@ -98,6 +120,6 @@ func init() { &listMediaType, "type", "t", "anime", "Type of media. for anime, pass 'anime' or 'a', for manga, use 'manga' or 'm'", ) mediaListCmd.Flags().StringVarP( - &listStatus, "status", "s", "watching", "Status of the media. Can be 'watching/w or reading/r', 'planning/p', 'completed/c', 'dropped/d', 'paused/ps', 'repeating/rp'", + &listStatus, "status", "s", "watching", "Status of the media. Can be 'watching/w or reading/r', 'planning/p', 'completed/c', 'dropped/d', 'paused/ps'", ) } diff --git a/internal/media_list.go b/internal/media_list.go index fdd3dd9..2023897 100644 --- a/internal/media_list.go +++ b/internal/media_list.go @@ -6,6 +6,7 @@ type MediaList struct { Data struct { MediaListCollection struct { Lists []struct { + Status string `json:"status"` Entries []struct { Progress int `json:"progress"` ProgressVolumes int `json:"progressVolumes"` @@ -36,8 +37,6 @@ func parseMediaStatus(status string) string { return "DROPPED" case "paused", "ps": return "PAUSED" - case "repeating", "rp": - return "REPEATING" default: return "CURRENT" } @@ -53,9 +52,10 @@ func (ml *MediaList) Get(mediaType string, status string) error { } query := - `query($userId: Int, $type: MediaType, $status: MediaListStatus) { - MediaListCollection(userId: $userId, type: $type, status: $status) { + `query($userId: Int, $type: MediaType, $status: [MediaListStatus]) { + MediaListCollection(userId: $userId, type: $type, status_in: $status) { lists { + status entries { progress progressVolumes @@ -73,12 +73,22 @@ func (ml *MediaList) Get(mediaType string, status string) error { } }` + parsedStatus := parseMediaStatus(status) + + var parsedStatusSlice []string = make([]string, 0) + + if parsedStatus == "CURRENT" { + parsedStatusSlice = append(parsedStatusSlice, parsedStatus, "REPEATING") + } else { + parsedStatusSlice = append(parsedStatusSlice, parsedStatus) + } + err = anilistClient.ExecuteGraqhQL( query, map[string]interface{}{ "type": mediaType, "userId": tokenConfig.UserId, - "status": parseMediaStatus(status), + "status": parsedStatusSlice, }, &ml, ) From b76dc6c13c7fd0830fde6a0b99bb886c383a812c Mon Sep 17 00:00:00 2001 From: Cosmic Predator Date: Thu, 6 Feb 2025 22:25:34 +0530 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20[media=5Fupdate.go]=20added=20p?= =?UTF-8?q?arsers=20for=20dynamic=20episode=20increment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/cmd_add.go | 4 +- cmd/cmd_list.go | 15 ----- cmd/cmd_update.go | 25 +++++--- internal/media_list.go | 38 +++++++------ internal/media_update.go | 120 +++++++++++++++++++++++++++++---------- 5 files changed, 129 insertions(+), 73 deletions(-) diff --git a/cmd/cmd_add.go b/cmd/cmd_add.go index fec3148..6b76d50 100644 --- a/cmd/cmd_add.go +++ b/cmd/cmd_add.go @@ -35,12 +35,12 @@ func handleMediaAdd(mediaId int) { mediaUpdate := internal.NewMediaUpdate() if mediaAddStatus == "CURRENT" { currDate := fmt.Sprintf("%d/%d/%d", time.Now().Day(), time.Now().Month(), time.Now().Year()) - err := mediaUpdate.Get(true, mediaId, 0, mediaAddStatus, currDate) + err := mediaUpdate.Get(true, mediaId, "0", mediaAddStatus, currDate) if err != nil { ErrorMessage(err.Error()) } } else { - err := mediaUpdate.Get(true, mediaId, 0, mediaAddStatus, "") + err := mediaUpdate.Get(true, mediaId, "0", mediaAddStatus, "") if err != nil { ErrorMessage(err.Error()) } diff --git a/cmd/cmd_list.go b/cmd/cmd_list.go index ec4c547..536de0c 100644 --- a/cmd/cmd_list.go +++ b/cmd/cmd_list.go @@ -63,21 +63,6 @@ func handleLs() { } } - for _, i := range mediaList.Data.MediaListCollection.Lists[0].Entries { - var progress string - if mediaType == "ANIME" { - progress = fmt.Sprintf("%d/%d", i.Progress, i.Media.Episodes) - } else { - progress = fmt.Sprintf("%d/%d", i.Progress, i.Media.Chapters) - } - - rows = append(rows, []string{ - strconv.Itoa(i.Media.Id), - i.Media.Title.UserPreferred, - progress, - }) - } - // get size of terminal tw, _, err := term.GetSize((os.Stdout.Fd())) if err != nil { diff --git a/cmd/cmd_update.go b/cmd/cmd_update.go index 8d2d0c5..f6f941e 100644 --- a/cmd/cmd_update.go +++ b/cmd/cmd_update.go @@ -9,18 +9,22 @@ import ( ) // TODO: Update progress relatively. For example "+2", "-10" etc., -var progress int +var progress string func handleUpdate(mediaId int) { CheckIfTokenExists() - if progress == 0 { - fmt.Println( - ERROR_MESSAGE_TEMPLATE.Render("The flag 'progress' should be greater than 0."), - ) + + progressInt, err := strconv.Atoi(progress) + if err == nil { + if progressInt == 0 { + fmt.Println( + ERROR_MESSAGE_TEMPLATE.Render("The flag 'progress' should be greater than 0."), + ) + } } mediaUpdate := internal.NewMediaUpdate() - err := mediaUpdate.Get(false, mediaId, progress, "", "") + err = mediaUpdate.Get(false, mediaId, progress, "", "") if err != nil { ErrorMessage(err.Error()) @@ -35,8 +39,11 @@ func handleUpdate(mediaId int) { var mediaUpdateCmd = &cobra.Command{ Use: "update [id]", Short: "Update a list entry", - Args: cobra.ExactArgs(1), + Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { + if len(args) == 2 { + progress = args[1] + } id, err := strconv.Atoi(args[0]) if err != nil { fmt.Println( @@ -48,11 +55,11 @@ var mediaUpdateCmd = &cobra.Command{ } func init() { - mediaUpdateCmd.Flags().IntVarP( + mediaUpdateCmd.Flags().StringVarP( &progress, "progress", "p", - 0, + "0", "The number of episodes/chapter to update", ) } diff --git a/internal/media_list.go b/internal/media_list.go index 2023897..791938b 100644 --- a/internal/media_list.go +++ b/internal/media_list.go @@ -2,26 +2,28 @@ package internal import "github.com/CosmicPredator/chibi/types" +type ListCollection struct { + Lists []struct { + Status string `json:"status"` + Entries []struct { + Progress int `json:"progress"` + ProgressVolumes int `json:"progressVolumes"` + Media struct { + Id int `json:"id"` + Title struct { + UserPreferred string `json:"userPreferred"` + } `json:"title"` + Chapters int `json:"chapters"` + Volumes int `json:"volumes"` + Episodes int `json:"episodes"` + } `json:"media"` + } `json:"entries"` + } `json:"lists"` +} + type MediaList struct { Data struct { - MediaListCollection struct { - Lists []struct { - Status string `json:"status"` - Entries []struct { - Progress int `json:"progress"` - ProgressVolumes int `json:"progressVolumes"` - Media struct { - Id int `json:"id"` - Title struct { - UserPreferred string `json:"userPreferred"` - } `json:"title"` - Chapters int `json:"chapters"` - Volumes int `json:"volumes"` - Episodes int `json:"episodes"` - } `json:"media"` - } `json:"entries"` - } `json:"lists"` - } `json:"MediaListCollection"` + MediaListCollection ListCollection `json:"MediaListCollection"` } `json:"data"` } diff --git a/internal/media_update.go b/internal/media_update.go index d9119e3..508a97b 100644 --- a/internal/media_update.go +++ b/internal/media_update.go @@ -1,53 +1,100 @@ package internal import ( + "errors" "fmt" "os" "strconv" "strings" "time" + "github.com/CosmicPredator/chibi/types" "github.com/charmbracelet/huh" "github.com/charmbracelet/lipgloss" ) -func getTotalEps(mediaId int) (int, error) { +type MediaListUpdate struct { + Data struct { + AnimeListCollection ListCollection `json:"AnimeListCollection"` + MangaListCollection ListCollection `json:"MangaListCollection"` + } `json:"data"` +} + +func getTotalCurrent(mediaId int) (int, int, error) { query := `query ($id: Int) { - Media(id: $id) { - episodes - chapters - type - } - }` + AnimeListCollection: MediaListCollection(userId: $id, type: ANIME, status_in:[CURRENT, REPEATING]){ + lists { + status + entries { + progress + media { + id + title { + userPreferred + } + episodes + chapters + } + } + } + } + MangaListCollection: MediaListCollection(userId: $id, type: MANGA, status_in:[CURRENT, REPEATING]){ + lists { + status + entries { + progress + media { + id + title { + userPreferred + } + episodes + chapters + } + } + } + } + }` + + tokenConfig := types.NewTokenConfig() + err := tokenConfig.ReadFromJsonFile() - var reponseData struct { - Data struct { - Media struct { - Episodes int `json:"episodes"` - Chapters int `json:"chapters"` - Type string `json:"type"` - } `json:"media"` - } `json:"data"` + if err != nil { + return 0, 0, err } + var responseObj MediaListUpdate + anilistClient := NewAnilistClient() - err := anilistClient.ExecuteGraqhQL( + err = anilistClient.ExecuteGraqhQL( query, map[string]interface{}{ - "id": mediaId, + "id": tokenConfig.UserId, }, - &reponseData, + &responseObj, ) if err != nil { - return 0, err + return 0, 0, err + } + + for _, list := range responseObj.Data.AnimeListCollection.Lists { + for _, entry := range list.Entries { + if entry.Media.Id == mediaId { + return entry.Progress, entry.Media.Episodes, nil + } + } } - if reponseData.Data.Media.Type == "ANIME" { - return reponseData.Data.Media.Episodes, nil - } else { - return reponseData.Data.Media.Chapters, nil + for _, list := range responseObj.Data.MangaListCollection.Lists { + for _, entry := range list.Entries { + if entry.Media.Id == mediaId { + return entry.Progress, entry.Media.Chapters, nil + } + } } + + return 0, 0, errors.New("list empty") } type updateMediaFields struct { @@ -118,17 +165,32 @@ type MediaUpdate struct { } `json:"data"` } -func (mu *MediaUpdate) Get(isMediaAdd bool, mediaId int, progress int, status string, startDate string) error { +func (mu *MediaUpdate) Get(isMediaAdd bool, mediaId int, progress string, status string, startDate string) error { if status == "" { status = "COMPLETED" } + var accumulatedProgress int + current, total, err := getTotalCurrent(mediaId) + + if strings.Contains(progress, "+") || strings.Contains(progress, "-") { + if progress[:1] == "+" { + prgInt, _ := strconv.Atoi(progress[1:]) + accumulatedProgress = current + prgInt + } else { + if current == 0 { + accumulatedProgress = 0 + } else { + prgInt, _ := strconv.Atoi(progress[1:]) + accumulatedProgress = current - prgInt + } + } + } - total, err := getTotalEps(mediaId) if err != nil { return err } - if progress > total { + if total != 0 && accumulatedProgress > total { fmt.Println(lipgloss.NewStyle().Foreground(lipgloss.Color("#FF0000")).Render( fmt.Sprintf("Entered value is greater than total episodes / chapters, which is %d", total), )) @@ -199,7 +261,7 @@ func (mu *MediaUpdate) Get(isMediaAdd bool, mediaId int, progress int, status st var canEditList bool = false - if progress == total { + if accumulatedProgress == total { huh.NewConfirm(). Title("Seems like you completed the anime/manga. Do you want to mark this as completed?"). Affirmative("Yes!"). @@ -218,7 +280,7 @@ func (mu *MediaUpdate) Get(isMediaAdd bool, mediaId int, progress int, status st mutation, map[string]interface{}{ "id": mediaId, - "progress": progress, + "progress": accumulatedProgress, "score": mediaFields.Score, "notes": mediaFields.Notes, "cDate": mediaFields.CompletedAtDate, @@ -234,7 +296,7 @@ func (mu *MediaUpdate) Get(isMediaAdd bool, mediaId int, progress int, status st mutation, map[string]interface{}{ "id": mediaId, - "progress": progress, + "progress": accumulatedProgress, }, &mu, ) From 832353f11fb404258c5bca4d131d1fc93a941991 Mon Sep 17 00:00:00 2001 From: Cosmic Predator Date: Thu, 6 Feb 2025 22:32:50 +0530 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=9D=20Update=20Changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f28f461..1165210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ ### ✨ What's New -- You can now find the docs on https://chibi-cli.pages.dev/ -- You can now install chibi in windows via winget. To do so, type in +- The `ls` command now shows Rewatching/Rereading Media along with Current Media. The Rewatching/Rereading media will be marked by **"(R)"** before the media title. +- You can now pass incremental or decremental progress to `update` command. For example, + To increment progress of a media by 2, ```shell - winget install CosmicPredator.Chibi + $ chibi update 8861 -p +2 + ``` + + To decrement progress of a media by 5, + ```shell + $ chibi update 8861 -p -5 ``` -- Added install/uninstall scripts for linux and macOS. ### 🐛 Bug Fixes -- Undo gitignoring `go.sum` for nix flake builds. \ No newline at end of file +- None for now 👽️ \ No newline at end of file From 3a06888683d16cf12e5e7b52cf107533f7c70a41 Mon Sep 17 00:00:00 2001 From: Cosmic Predator Date: Thu, 6 Feb 2025 22:40:51 +0530 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20Accumulated=20progre?= =?UTF-8?q?ss=20always=20zero=20on=20static=20progress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/media_update.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/media_update.go b/internal/media_update.go index 508a97b..191b522 100644 --- a/internal/media_update.go +++ b/internal/media_update.go @@ -184,6 +184,12 @@ func (mu *MediaUpdate) Get(isMediaAdd bool, mediaId int, progress string, status accumulatedProgress = current - prgInt } } + } else { + pgrInt, err := strconv.Atoi(progress) + if err != nil { + return err + } + accumulatedProgress = pgrInt } if err != nil {