Skip to content

Commit

Permalink
Fix: Continue last and filler block progress update after few episode…
Browse files Browse the repository at this point in the history
…s (api unfuck)
  • Loading branch information
Wraient committed Dec 18, 2024
1 parent 3957bf0 commit 53899cc
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 109 deletions.
16 changes: 10 additions & 6 deletions cmd/curd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ func main() {

// If not filler/recap (or skip is disabled), break and continue with playback
if !((anime.Ep.IsFiller && userCurdConfig.SkipFiller) || (anime.Ep.IsRecap && userCurdConfig.SkipRecap)) {
if anime.Ep.LastWasSkipped {
go internal.UpdateAnimeProgress(user.Token, anime.AnilistId, anime.Ep.Number-1)
}
break
}

Expand All @@ -231,11 +234,12 @@ func main() {
} else {
internal.CurdOut(fmt.Sprint("Recap episode, skipping: ", anime.Ep.Number))
}

anime.Ep.Number++
anime.Ep.LastWasSkipped = true
anime.Ep.Started = false
internal.LocalUpdateAnime(databaseFile, anime.AnilistId, anime.AllanimeId, anime.Ep.Number, 0, 0, internal.GetAnimeName(anime))

// Check if we've reached the end of the series
if anime.Ep.Number > anime.TotalEpisodes {
internal.CurdOut("Reached end of series")
Expand Down Expand Up @@ -447,9 +451,8 @@ func main() {
}
}
_, err := internal.MPVSendCommand(anime.Ep.Player.SocketPath, []interface{}{"get_property", "time-pos"})
if err == nil && anime.Ep.Started{
if err == nil && anime.Ep.Started {
anime.Ep.Player.Speed, err = internal.GetMPVPlaybackSpeed(anime.Ep.Player.SocketPath)
internal.Log(anime.Ep.Player.Speed, logFile)
if err != nil {
internal.Log("Failed to get mpv speed "+err.Error(), logFile)
}
Expand All @@ -466,6 +469,7 @@ func main() {
wg = sync.WaitGroup{}

if anime.Ep.IsCompleted && !anime.Rewatching {
// Update progress for both regular episodes and skipped fillers
go func() {
err = internal.UpdateAnimeProgress(user.Token, anime.AnilistId, anime.Ep.Number-1)
if err != nil {
Expand All @@ -481,7 +485,7 @@ func main() {
err = internal.RateAnime(user.Token, anime.AnilistId)
if err != nil {
internal.Log("Error rating anime: "+err.Error(), logFile)
internal.CurdOut("Error rating anime: "+err.Error())
internal.CurdOut("Error rating anime: " + err.Error())
}
internal.LocalDeleteAnime(databaseFile, anime.AnilistId, anime.AllanimeId)
internal.ExitCurd(nil)
Expand All @@ -499,7 +503,7 @@ func main() {
"yes": "Yes",
"no": "No",
}

selectedOption, err := internal.DynamicSelect(options, false)
if err != nil {
internal.ExitCurd(err)
Expand Down
160 changes: 97 additions & 63 deletions internal/curd.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,11 @@ func SetupCurd(userCurdConfig *CurdConfig, anime *Anime, user *User, databaseAni
var anilistUserData map[string]interface{}
var anilistUserDataPreview map[string]interface{}

// Filter anime list based on selected category
var animeListMap map[string]string
var animeListMapPreview map[string]RofiSelectPreview


// Get user id, username and Anime list
user.Id, user.Username, err = GetAnilistUserID(user.Token)
if err != nil {
Expand All @@ -579,77 +584,106 @@ func SetupCurd(userCurdConfig *CurdConfig, anime *Anime, user *User, databaseAni
user.AnimeList = ParseAnimeList(anilistUserData)
}

// Skip category selection if Current flag is set
var categorySelection SelectionOption
if userCurdConfig.CurrentCategory {
categorySelection = SelectionOption{
Key: "CURRENT",
Label: "Currently Watching",
}
} else {
// Create category selection map
categories := map[string]string{
"ALL": "Show All",
"CURRENT": "Currently Watching",
"PAUSED": "On Hold",
"PLANNING": "Plan to Watch",
"COMPLETED": "Completed",
"DROPPED": "Dropped",
"UPDATE": "Update Anime Entry",
"UNTRACKED": "Untracked Watching",
// If continueLast flag is set, directly get the last watched anime
if anime.Ep.ContinueLast {
// Get the last anime ID from the curd_id file
idFilePath := filepath.Join(os.ExpandEnv(userCurdConfig.StoragePath), "curd_id")
idBytes, err := os.ReadFile(idFilePath)
if err != nil {
Log("Error reading curd_id file: "+err.Error(), logFile)
ExitCurd(fmt.Errorf("No last watched anime found"))
}

// Select category using DynamicSelect
var err error
categorySelection, err = DynamicSelect(categories, false)

anilistID, err := strconv.Atoi(string(idBytes))
if err != nil {
Log(fmt.Sprintf("Failed to select category: %v", err), logFile)
ExitCurd(fmt.Errorf("Failed to select category"))
Log("Error converting anilist ID: "+err.Error(), logFile)
ExitCurd(fmt.Errorf("Invalid anime ID in curd_id file"))
}

if categorySelection.Key == "-1" {
ExitCurd(nil)
// Find the anime in database
animePointer := LocalFindAnime(*databaseAnimes, anilistID, "")
if animePointer == nil {
ExitCurd(fmt.Errorf("Last watched anime not found in database"))
}

// Handle UPDATE option
if categorySelection.Key == "UPDATE" {
ClearScreen()
UpdateAnimeEntry(userCurdConfig, user, logFile)
ExitCurd(nil)
} else if categorySelection.Key == "UNTRACKED" {
ClearScreen()
WatchUntracked(userCurdConfig, logFile)
}
// Set the anime details
anime.AnilistId = animePointer.AnilistId
// anime.AllanimeId = animePointer.AllanimeId
// anime.Title = animePointer.Title
// anime.Ep.Number = animePointer.Ep.Number
// anime.Ep.Player.PlaybackTime = animePointer.Ep.Player.PlaybackTime
// anime.Ep.Resume = true

} else {
// Skip category selection if Current flag is set
var categorySelection SelectionOption
if userCurdConfig.CurrentCategory {
categorySelection = SelectionOption{
Key: "CURRENT",
Label: "Currently Watching",
}
} else {
// Create category selection map
categories := map[string]string{
"ALL": "Show All",
"CURRENT": "Currently Watching",
"PAUSED": "On Hold",
"PLANNING": "Plan to Watch",
"COMPLETED": "Completed",
"DROPPED": "Dropped",
"UPDATE": "Update Anime Entry",
"UNTRACKED": "Untracked Watching",
}

ClearScreen()
}
// Select category using DynamicSelect
var err error
categorySelection, err = DynamicSelect(categories, false)
if err != nil {
Log(fmt.Sprintf("Failed to select category: %v", err), logFile)
ExitCurd(fmt.Errorf("Failed to select category"))
}

// Filter anime list based on selected category
var animeListMap map[string]string
var animeListMapPreview map[string]RofiSelectPreview

if userCurdConfig.RofiSelection && userCurdConfig.ImagePreview {
animeListMapPreview = make(map[string]RofiSelectPreview)
for _, entry := range getEntriesByCategory(user.AnimeList, categorySelection.Key) {
title := entry.Media.Title.English
if title == "" || userCurdConfig.AnimeNameLanguage == "romaji" {
title = entry.Media.Title.Romaji
}
animeListMapPreview[strconv.Itoa(entry.Media.ID)] = RofiSelectPreview{
Title: title,
CoverImage: entry.CoverImage,
}
}
} else {
animeListMap = make(map[string]string)
for _, entry := range getEntriesByCategory(user.AnimeList, categorySelection.Key) {
title := entry.Media.Title.English
if title == "" || userCurdConfig.AnimeNameLanguage == "romaji" {
title = entry.Media.Title.Romaji
}
animeListMap[strconv.Itoa(entry.Media.ID)] = title
}
}
if categorySelection.Key == "-1" {
ExitCurd(nil)
}

// Handle UPDATE option
if categorySelection.Key == "UPDATE" {
ClearScreen()
UpdateAnimeEntry(userCurdConfig, user, logFile)
ExitCurd(nil)
} else if categorySelection.Key == "UNTRACKED" {
ClearScreen()
WatchUntracked(userCurdConfig, logFile)
}

ClearScreen()
}


if userCurdConfig.RofiSelection && userCurdConfig.ImagePreview {
animeListMapPreview = make(map[string]RofiSelectPreview)
for _, entry := range getEntriesByCategory(user.AnimeList, categorySelection.Key) {
title := entry.Media.Title.English
if title == "" || userCurdConfig.AnimeNameLanguage == "romaji" {
title = entry.Media.Title.Romaji
}
animeListMapPreview[strconv.Itoa(entry.Media.ID)] = RofiSelectPreview{
Title: title,
CoverImage: entry.CoverImage,
}
}
} else {
animeListMap = make(map[string]string)
for _, entry := range getEntriesByCategory(user.AnimeList, categorySelection.Key) {
title := entry.Media.Title.English
if title == "" || userCurdConfig.AnimeNameLanguage == "romaji" {
title = entry.Media.Title.Romaji
}
animeListMap[strconv.Itoa(entry.Media.ID)] = title
}
}
}

var anilistSelectedOption SelectionOption
var selectedAllanimeAnime SelectionOption
Expand Down
81 changes: 41 additions & 40 deletions internal/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ type AnimeTitle struct {

type Anime struct {
Title AnimeTitle `json:"title"`
Ep Episode `json:"ep"`
CoverImage string `json:"url"` // Assuming this field corresponds to the cover image URL
TotalEpisodes int `json:"total_episodes"` // If provided by the API
Ep Episode `json:"ep"`
CoverImage string `json:"url"` // Assuming this field corresponds to the cover image URL
TotalEpisodes int `json:"total_episodes"` // If provided by the API
MalId int `json:"mal_id"`
AnilistId int `json:"anilist_id"` // Assuming you have an Anilist ID in your struct
Rewatching bool
AllanimeId string // Can be populated as necessary
AllanimeId string // Can be populated as necessary
}

type Skip struct {
Expand All @@ -28,34 +28,35 @@ type SkipTimes struct {
}

type Episode struct {
Title AnimeTitle `json:"title"`
Number int `json:"number"`
SkipTimes SkipTimes `json:"skip_times"`
Player playingVideo `json:"player"`
Resume bool `json:"resume"`
Started bool `json:"started"`
Duration int `json:"duration"`
Links []string `json:"links"`
IsFiller bool `json:"filler"`
IsRecap bool `json:"recap"`
Aired string `json:"aired"`
Synopsis string `json:"synopsis"`
ContinueLast bool
IsCompleted bool
Title AnimeTitle `json:"title"`
Number int `json:"number"`
SkipTimes SkipTimes `json:"skip_times"`
Player playingVideo `json:"player"`
Resume bool `json:"resume"`
Started bool `json:"started"`
Duration int `json:"duration"`
Links []string `json:"links"`
IsFiller bool `json:"filler"`
IsRecap bool `json:"recap"`
Aired string `json:"aired"`
Synopsis string `json:"synopsis"`
ContinueLast bool
LastWasSkipped bool // used in filler check
IsCompleted bool
}

type playingVideo struct {
Url string
Speed float64 `json:"speed"`
PlaybackTime int `json:"playback_time"`
SocketPath string
SocketPath string
}

type User struct {
Token string
Username string
Id int
AnimeList AnimeList
Token string
Username string
Id int
AnimeList AnimeList
}

// AniListAnime is the struct for the API response
Expand All @@ -82,29 +83,29 @@ type ResponseData struct {
}

type Media struct {
Duration int `json:"duration"`
Episodes int `json:"episodes"`
ID int `json:"id"`
Title AnimeTitle `json:"title"`
Duration int `json:"duration"`
Episodes int `json:"episodes"`
ID int `json:"id"`
Title AnimeTitle `json:"title"`
}

type Entry struct {
Media Media `json:"media"`
Progress int `json:"progress"`
Score float64 `json:"score"`
Status string `json:"status"`
CoverImage string `json:"coverImage"`
Media Media `json:"media"`
Progress int `json:"progress"`
Score float64 `json:"score"`
Status string `json:"status"`
CoverImage string `json:"coverImage"`
}

type AnimeList struct {
Watching []Entry `json:"watching"`
Completed []Entry `json:"completed"`
Paused []Entry `json:"paused"`
Dropped []Entry `json:"dropped"`
Planning []Entry `json:"planning"`
Watching []Entry `json:"watching"`
Completed []Entry `json:"completed"`
Paused []Entry `json:"paused"`
Dropped []Entry `json:"dropped"`
Planning []Entry `json:"planning"`
}

type RofiSelectPreview struct {
Title string `json:"title"`
CoverImage string `json:"coverImage"`
}
Title string `json:"title"`
CoverImage string `json:"coverImage"`
}

0 comments on commit 53899cc

Please sign in to comment.