Skip to content

Commit b81dbba

Browse files
authored
Fix next episode prompt (#65)
* fix: Next episode prompt and many bugs completely. * Fix: Use prefetched links * Update: todo list
1 parent 21baf6f commit b81dbba

3 files changed

Lines changed: 279 additions & 296 deletions

File tree

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,7 @@ config file is located at ```~/.config/curd/curd.conf```
360360
| `SkipFiller` | Boolean | `true`, `false` | Skips filler episodes when supported. |
361361

362362
## Todo (fix)
363-
- Config: Nextepisodeprompt, Cli Mode, Problem: Quitting with quit button while ep is still playing doesnt update progress, even if past Mark Complete Threshold (Regression)
364363
- Use Powershell for windows token input instead of notepad or cmd
365-
- Add Rewatching list to "Show All" Option
366-
- Last episode doesnt prompt for anime score (Regression)
367364
- Find a way to get "Watching" instead of "Playing" Activity type in discord rpc (Implemented in [Dantotsu](https://github.com/aayush2622/Dartotsu) and [Premid](https://github.com/PreMiD/PreMiD))
368365
- Add a better way to do commands in windows (Convinience for users)
369366

cmd/curd/main.go

Lines changed: 117 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,14 @@ func main() {
329329
}
330330

331331
anime.Ep.IsCompleted = true
332-
if !userCurdConfig.NextEpisodePrompt || userCurdConfig.RofiSelection {
332+
if !userCurdConfig.NextEpisodePrompt {
333333
// fmt.Println("[DEBUG] Starting next episode from filler/recap skip")
334-
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile)
334+
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile, user.Token)
335+
} else {
336+
// When NextEpisodePrompt is enabled, just call StartNextEpisode - it handles Rofi prompting internally
337+
internal.ExitMPV(anime.Ep.Player.SocketPath)
338+
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile, user.Token)
339+
return
335340
}
336341
// Send command to close MPV
337342
_, err := internal.MPVSendCommand(anime.Ep.Player.SocketPath, []interface{}{"quit"})
@@ -414,27 +419,20 @@ func main() {
414419
}
415420
}()
416421

417-
// Thread to prompt for next episode in CLI Mode
422+
// Thread for continuous next episode prompt in CLI mode (throughout episode duration)
418423
go func() {
419-
if !userCurdConfig.RofiSelection && userCurdConfig.NextEpisodePrompt {
420-
for {
421-
select {
422-
case <-skipLoopDone:
423-
return
424-
default:
425-
internal.NextEpisodePrompt(&userCurdConfig)
426-
// Exit the skip loop - only close if not already closed
427-
select {
428-
case isClosed := <-skipLoopClosed:
429-
if !isClosed {
430-
close(skipLoopDone)
431-
skipLoopClosed <- true // Mark as closed
432-
}
433-
default:
434-
// Channel is busy, another goroutine is handling closure
435-
}
436-
return
424+
if userCurdConfig.NextEpisodePrompt && !userCurdConfig.RofiSelection {
425+
internal.NextEpisodePromptContinuous(&userCurdConfig, databaseFile, user.Token)
426+
// If the function returns, it means user made a decision
427+
// Exit the skip loop - only close if not already closed
428+
select {
429+
case isClosed := <-skipLoopClosed:
430+
if !isClosed {
431+
close(skipLoopDone)
432+
skipLoopClosed <- true // Mark as closed
437433
}
434+
default:
435+
// Channel is busy, another goroutine is handling closure
438436
}
439437
}
440438
}()
@@ -456,6 +454,11 @@ func main() {
456454
if err != nil {
457455
internal.Log("Error getting playback time: " + err.Error())
458456

457+
// For CLI mode with next episode prompt, let the continuous prompt handle everything
458+
if userCurdConfig.NextEpisodePrompt && !userCurdConfig.RofiSelection {
459+
continue
460+
}
461+
459462
// Check if the error is due to invalid JSON
460463
// User closed the video
461464
if anime.Ep.Started {
@@ -469,20 +472,50 @@ func main() {
469472
if int(percentageWatched) >= userCurdConfig.PercentageToMarkComplete {
470473
anime.Ep.IsCompleted = true
471474
if !userCurdConfig.NextEpisodePrompt {
472-
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile)
475+
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile, user.Token)
473476
} else {
474-
// When NextEpisodePrompt is enabled, show the prompt in both modes
477+
// For Rofi mode, show prompt immediately after completion
475478
if userCurdConfig.RofiSelection {
476-
// For Rofi mode
477-
internal.CurdOut("Showing next episode prompt in Rofi mode (playback ended)")
478-
internal.ExitMPV(anime.Ep.Player.SocketPath)
479-
internal.NextEpisodePrompt(&userCurdConfig)
480-
return
479+
shouldContinue := internal.NextEpisodePromptRofi(&userCurdConfig)
480+
if shouldContinue {
481+
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile, user.Token)
482+
} else {
483+
// Episode was already marked as completed above
484+
// Update local database with completed episode
485+
err := internal.LocalUpdateAnime(databaseFile, anime.AnilistId, anime.AllanimeId, anime.Ep.Number, anime.Ep.Player.PlaybackTime, internal.ConvertSecondsToMinutes(anime.Ep.Duration), internal.GetAnimeName(anime))
486+
if err != nil {
487+
internal.Log("Error updating local database on quit: " + err.Error())
488+
}
489+
490+
// Update Anilist progress if not rewatching
491+
if !anime.Rewatching {
492+
go func() {
493+
err = internal.UpdateAnimeProgress(user.Token, anime.AnilistId, anime.Ep.Number)
494+
if err != nil {
495+
internal.Log("Error updating Anilist progress on quit: " + err.Error())
496+
} else {
497+
internal.CurdOut(fmt.Sprintf("Episode completed! Progress updated: %d", anime.Ep.Number))
498+
}
499+
}()
500+
}
501+
502+
internal.ExitCurd(nil)
503+
}
481504
} else {
482-
// For CLI mode
483-
internal.NextEpisodePrompt(&userCurdConfig)
484-
return
505+
// For CLI mode, let the continuous prompt handle it
506+
internal.Log("Episode completed, exiting monitoring to let CLI prompt handle next episode")
485507
}
508+
// Exit the skip loop - only close if not already closed
509+
select {
510+
case isClosed := <-skipLoopClosed:
511+
if !isClosed {
512+
close(skipLoopDone)
513+
skipLoopClosed <- true // Mark as closed
514+
}
515+
default:
516+
// Channel is busy, another goroutine is handling closure
517+
}
518+
return
486519
}
487520
} else {
488521
internal.Log("Episode is not completed, exiting")
@@ -555,6 +588,11 @@ func main() {
555588
if err != nil {
556589
internal.Log("Error checking playback status: " + err.Error())
557590
} else if !hasPlayback {
591+
// For CLI mode with next episode prompt, let the continuous prompt handle everything
592+
if userCurdConfig.NextEpisodePrompt && !userCurdConfig.RofiSelection {
593+
continue
594+
}
595+
558596
// Nothing is playing, check percentage watched
559597
percentageWatched := internal.PercentageWatched(anime.Ep.Player.PlaybackTime, anime.Ep.Duration)
560598
// fmt.Printf("[DEBUG] Playback stopped - Percentage watched: %d%%, Required: %d%%\n",
@@ -564,20 +602,50 @@ func main() {
564602
if int(percentageWatched) >= userCurdConfig.PercentageToMarkComplete {
565603
anime.Ep.IsCompleted = true
566604
if !userCurdConfig.NextEpisodePrompt {
567-
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile)
605+
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile, user.Token)
568606
} else {
569-
// When NextEpisodePrompt is enabled, show the prompt in both modes
607+
// For Rofi mode, show prompt immediately after completion
570608
if userCurdConfig.RofiSelection {
571-
// For Rofi mode
572-
internal.CurdOut("Showing next episode prompt in Rofi mode (playback ended)")
573-
internal.ExitMPV(anime.Ep.Player.SocketPath)
574-
internal.NextEpisodePrompt(&userCurdConfig)
575-
return
609+
shouldContinue := internal.NextEpisodePromptRofi(&userCurdConfig)
610+
if shouldContinue {
611+
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile, user.Token)
612+
} else {
613+
// Episode was already marked as completed above
614+
// Update local database with completed episode
615+
err := internal.LocalUpdateAnime(databaseFile, anime.AnilistId, anime.AllanimeId, anime.Ep.Number, anime.Ep.Player.PlaybackTime, internal.ConvertSecondsToMinutes(anime.Ep.Duration), internal.GetAnimeName(anime))
616+
if err != nil {
617+
internal.Log("Error updating local database on quit: " + err.Error())
618+
}
619+
620+
// Update Anilist progress if not rewatching
621+
if !anime.Rewatching {
622+
go func() {
623+
err = internal.UpdateAnimeProgress(user.Token, anime.AnilistId, anime.Ep.Number)
624+
if err != nil {
625+
internal.Log("Error updating Anilist progress on quit: " + err.Error())
626+
} else {
627+
internal.CurdOut(fmt.Sprintf("Episode completed! Progress updated: %d", anime.Ep.Number))
628+
}
629+
}()
630+
}
631+
632+
internal.ExitCurd(nil)
633+
}
576634
} else {
577-
// For CLI mode
578-
internal.NextEpisodePrompt(&userCurdConfig)
579-
return
635+
// For CLI mode, let the continuous prompt handle it
636+
internal.Log("Episode completed, exiting monitoring to let CLI prompt handle next episode")
580637
}
638+
// Exit the skip loop - only close if not already closed
639+
select {
640+
case isClosed := <-skipLoopClosed:
641+
if !isClosed {
642+
close(skipLoopDone)
643+
skipLoopClosed <- true // Mark as closed
644+
}
645+
default:
646+
// Channel is busy, another goroutine is handling closure
647+
}
648+
return
581649
}
582650
} else {
583651
internal.Log("Episode is not completed, exiting")
@@ -697,29 +765,16 @@ func main() {
697765
// Handle next episode logic based on config
698766
if anime.Ep.IsCompleted {
699767
if userCurdConfig.NextEpisodePrompt {
700-
// Handle the special case where playback is still active (might happen with Rofi)
701-
// This ensures we don't show duplicate prompts if it was already handled in the playback monitor
702-
isPlaying, err := internal.HasActivePlayback(anime.Ep.Player.SocketPath)
703-
if err != nil {
704-
internal.Log(fmt.Sprintf("Error checking playback for prompt: %v", err))
705-
}
706-
707-
// Only show the prompt here if playback is still active - otherwise it was already handled
708-
if isPlaying {
709-
internal.CurdOut("Episode completed, showing next episode prompt from main loop")
710-
if userCurdConfig.RofiSelection {
711-
internal.NextEpisodePrompt(&userCurdConfig)
712-
// Exit after NextEpisodePrompt to avoid starting a new playback loop
713-
internal.ExitCurd(nil)
714-
}
715-
// For CLI mode, the prompt will be shown elsewhere
716-
} else {
717-
internal.Log("Playback already ended, prompt handled elsewhere")
768+
if !userCurdConfig.RofiSelection {
769+
// For CLI mode, the continuous prompt handles everything
770+
internal.CurdOut("CLI mode: continuous prompt handling next episode logic")
718771
}
772+
// For both modes, if we reach here, it means the monitoring thread exited
773+
// and the episode should transition. Let the normal flow continue.
719774
} else {
720-
// When NextEpisodePrompt is off, we continue automatically in both CLI and Rofi modes
721-
internal.CurdOut("Auto-continuing to next episode")
722-
// Don't need to do anything - the loop will continue naturally
775+
// When NextEpisodePrompt is off, continue automatically
776+
internal.StartNextEpisode(&anime, &userCurdConfig, databaseFile, user.Token)
777+
continue
723778
}
724779
}
725780

0 commit comments

Comments
 (0)