Skip to content

Commit 2ebafb7

Browse files
committed
refactor: Enhance validation and error handling in DownloadAllAnimeSmartRange function
1 parent 40b8e58 commit 2ebafb7

File tree

1 file changed

+65
-33
lines changed

1 file changed

+65
-33
lines changed

internal/api/allanime_smart.go

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,17 @@ import (
1919
// DownloadAllAnimeSmartRange downloads a range of episodes exclusively for AllAnime.
2020
// It prioritizes high-quality mirrors and writes AniSkip sidecar files for intro/outro skipping.
2121
func DownloadAllAnimeSmartRange(anime *models.Anime, startEp, endEp int, quality string) error {
22-
// Validate source
23-
if !isAllAnimeSourceAPI(anime) {
24-
return fmt.Errorf("AllAnime Smart Range is only available for AllAnime sources")
25-
}
26-
27-
if quality == "" {
28-
quality = "best"
22+
// Validate
23+
if err := validateSmartRangeInputs(anime, startEp, endEp, &quality); err != nil {
24+
return err
2925
}
3026

3127
util.Debug("AllAnime Smart Range start",
3228
"anime", anime.Name,
3329
"range", fmt.Sprintf("%d-%d", startEp, endEp),
3430
"quality", quality)
3531

36-
// Fetch episodes using enhanced path (this enables AniSkip enrichment when MAL ID is available)
32+
// Fetch episodes using enhanced path (enables AniSkip enrichment)
3733
episodes, err := GetAnimeEpisodesEnhanced(anime)
3834
if err != nil {
3935
return fmt.Errorf("failed to get episodes: %w", err)
@@ -56,40 +52,28 @@ func DownloadAllAnimeSmartRange(anime *models.Anime, startEp, endEp int, quality
5652
ep := episodes[i-1]
5753
filePath := filepath.Join(outDir, fmt.Sprintf("%d.mp4", i))
5854

59-
if stat, err := os.Stat(filePath); err == nil && stat.Size() > 1024 {
55+
if alreadyDownloaded(filePath) {
6056
util.Infof("Episode %d already exists, skipping", i)
61-
// Even if file exists, (re)write sidecar if needed
62-
_ = WriteAniSkipSidecar(filePath, &ep)
57+
_ = WriteAniSkipSidecar(filePath, &ep) // refresh sidecar if needed
6358
continue
6459
}
6560

66-
util.Infof("Resolving stream URL for episode %d...", i)
67-
streamURL, err := GetEpisodeStreamURLEnhanced(&ep, anime, quality)
68-
if err != nil || streamURL == "" {
69-
// Fallback to non-enhanced AllAnime-aware function
70-
streamURL, err = GetEpisodeStreamURL(&ep, anime, quality)
71-
if err != nil || streamURL == "" {
72-
util.Errorf("Failed to get stream URL for episode %d: %v", i, err)
73-
continue
74-
}
61+
streamURL, err := resolveStreamURLForEpisode(&ep, anime, quality)
62+
if err != nil {
63+
util.Errorf("Failed to get stream URL for episode %d: %v", i, err)
64+
continue
7565
}
7666

77-
util.Debug("Stream URL resolved", "episode", i, "len", len(streamURL))
78-
79-
// Prefer yt-dlp for HLS and known hosters used by AllAnime
8067
if err := smartDownload(streamURL, filePath); err != nil {
8168
util.Errorf("Download failed for episode %d: %v", i, err)
8269
continue
8370
}
8471

85-
// Write AniSkip sidecar markers if available
8672
if err := WriteAniSkipSidecar(filePath, &ep); err != nil {
8773
util.Debugf("Failed to write AniSkip sidecar for episode %d: %v", i, err)
8874
}
89-
9075
util.Infof("Episode %d downloaded successfully", i)
9176
}
92-
9377
return nil
9478
}
9579

@@ -100,13 +84,8 @@ func smartDownload(url, dest string) error {
10084
return err
10185
}
10286

103-
// Use yt-dlp for most AllAnime links (m3u8, wixmp, blogger, sharepoint, etc.)
104-
if strings.Contains(url, ".m3u8") ||
105-
strings.Contains(url, "master.m3u8") ||
106-
strings.Contains(url, "wixmp.com") || strings.Contains(url, "repackager.wixmp.com") ||
107-
strings.Contains(url, "blogger.com") ||
108-
strings.Contains(url, "sharepoint.com") ||
109-
strings.Contains(url, "allanime") || strings.Contains(url, "allmanga") {
87+
// Use yt-dlp for HLS/known hosters
88+
if shouldUseYtDlp(url) {
11089
ctx := context.Background()
11190
ytdlp.MustInstall(ctx, nil)
11291
dl := ytdlp.New().Output(dest)
@@ -211,3 +190,56 @@ func sanitizeSmart(name string) string {
211190
}
212191
return name
213192
}
193+
194+
// Helpers to reduce complexity
195+
196+
// validateSmartRangeInputs ensures correct source and quality defaulting
197+
func validateSmartRangeInputs(anime *models.Anime, startEp, endEp int, quality *string) error {
198+
if !isAllAnimeSourceAPI(anime) {
199+
return fmt.Errorf("AllAnime Smart Range is only available for AllAnime sources")
200+
}
201+
if quality != nil && *quality == "" {
202+
*quality = "best"
203+
}
204+
if startEp < 1 || endEp < startEp {
205+
return fmt.Errorf("invalid range %d-%d", startEp, endEp)
206+
}
207+
return nil
208+
}
209+
210+
// shouldUseYtDlp decides if yt-dlp is preferred for a given URL
211+
func shouldUseYtDlp(u string) bool {
212+
l := strings.ToLower(u)
213+
return strings.Contains(l, ".m3u8") ||
214+
strings.Contains(l, "master.m3u8") ||
215+
strings.Contains(l, "wixmp.com") || strings.Contains(l, "repackager.wixmp.com") ||
216+
strings.Contains(l, "blogger.com") ||
217+
strings.Contains(l, "sharepoint.com") ||
218+
strings.Contains(l, "allanime") || strings.Contains(l, "allmanga")
219+
}
220+
221+
// alreadyDownloaded checks if the file exists and seems valid (>1KB)
222+
func alreadyDownloaded(path string) bool {
223+
if st, err := os.Stat(path); err == nil {
224+
return st.Size() > 1024
225+
}
226+
return false
227+
}
228+
229+
// resolveStreamURLForEpisode resolves the streaming URL with enhanced fallback
230+
func resolveStreamURLForEpisode(ep *models.Episode, anime *models.Anime, quality string) (string, error) {
231+
if ep == nil || anime == nil {
232+
return "", fmt.Errorf("nil episode or anime")
233+
}
234+
url, err := GetEpisodeStreamURLEnhanced(ep, anime, quality)
235+
if err == nil && url != "" {
236+
util.Debug("Stream URL resolved (enhanced)", "len", len(url))
237+
return url, nil
238+
}
239+
url, err = GetEpisodeStreamURL(ep, anime, quality)
240+
if err != nil || url == "" {
241+
return "", fmt.Errorf("fallback stream URL resolution failed: %w", err)
242+
}
243+
util.Debug("Stream URL resolved (fallback)", "len", len(url))
244+
return url, nil
245+
}

0 commit comments

Comments
 (0)