package handlers import ( "errors" "seanime/internal/database/db_bridge" "seanime/internal/library/scanner" "seanime/internal/library/summary" "github.com/labstack/echo/v4" ) // HandleScanLocalFiles // // @summary scans the user's library. // @desc This will scan the user's library. // @desc The response is ignored, the client should re-fetch the library after this. // @route /api/v1/library/scan [POST] // @returns []anime.LocalFile func (h *Handler) HandleScanLocalFiles(c echo.Context) error { type body struct { Enhanced bool `json:"enhanced"` SkipLockedFiles bool `json:"skipLockedFiles"` SkipIgnoredFiles bool `json:"skipIgnoredFiles"` } var b body if err := c.Bind(&b); err != nil { return h.RespondWithError(c, err) } // Retrieve the user's library path libraryPath, err := h.App.Database.GetLibraryPathFromSettings() if err != nil { return h.RespondWithError(c, err) } additionalLibraryPaths, err := h.App.Database.GetAdditionalLibraryPathsFromSettings() if err != nil { return h.RespondWithError(c, err) } // Get the latest local files existingLfs, _, err := db_bridge.GetLocalFiles(h.App.Database) if err != nil { return h.RespondWithError(c, err) } // +---------------------+ // | Scanner | // +---------------------+ // Create scan summary logger scanSummaryLogger := summary.NewScanSummaryLogger() // Create a new scan logger scanLogger, err := scanner.NewScanLogger(h.App.Config.Logs.Dir) if err != nil { return h.RespondWithError(c, err) } defer scanLogger.Done() // Create a new scanner sc := scanner.Scanner{ DirPath: libraryPath, OtherDirPaths: additionalLibraryPaths, Enhanced: b.Enhanced, Platform: h.App.AnilistPlatform, Logger: h.App.Logger, WSEventManager: h.App.WSEventManager, ExistingLocalFiles: existingLfs, SkipLockedFiles: b.SkipLockedFiles, SkipIgnoredFiles: b.SkipIgnoredFiles, ScanSummaryLogger: scanSummaryLogger, ScanLogger: scanLogger, MetadataProvider: h.App.MetadataProvider, MatchingAlgorithm: h.App.Settings.GetLibrary().ScannerMatchingAlgorithm, MatchingThreshold: h.App.Settings.GetLibrary().ScannerMatchingThreshold, } // Scan the library allLfs, err := sc.Scan(c.Request().Context()) if err != nil { if errors.Is(err, scanner.ErrNoLocalFiles) { return h.RespondWithData(c, []interface{}{}) } else { return h.RespondWithError(c, err) } } // Insert the local files lfs, err := db_bridge.InsertLocalFiles(h.App.Database, allLfs) if err != nil { return h.RespondWithError(c, err) } // Save the scan summary _ = db_bridge.InsertScanSummary(h.App.Database, scanSummaryLogger.GenerateSummary()) go h.App.AutoDownloader.CleanUpDownloadedItems() return h.RespondWithData(c, lfs) }