node build fixed

This commit is contained in:
ra_ma
2025-09-20 14:08:38 +01:00
parent c6ebbe069d
commit 3d298fa434
1516 changed files with 535727 additions and 2 deletions

View File

@@ -0,0 +1,327 @@
package handlers
import (
"errors"
"fmt"
"os"
"seanime/internal/database/db_bridge"
"seanime/internal/library/anime"
"seanime/internal/library/filesystem"
"time"
"github.com/goccy/go-json"
"github.com/labstack/echo/v4"
"github.com/samber/lo"
"github.com/sourcegraph/conc/pool"
)
// HandleGetLocalFiles
//
// @summary returns all local files.
// @desc Reminder that local files are scanned from the library path.
// @route /api/v1/library/local-files [GET]
// @returns []anime.LocalFile
func (h *Handler) HandleGetLocalFiles(c echo.Context) error {
lfs, _, err := db_bridge.GetLocalFiles(h.App.Database)
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, lfs)
}
func (h *Handler) HandleDumpLocalFilesToFile(c echo.Context) error {
lfs, _, err := db_bridge.GetLocalFiles(h.App.Database)
if err != nil {
return h.RespondWithError(c, err)
}
filename := fmt.Sprintf("seanime-localfiles-%s.json", time.Now().Format("2006-01-02_15-04-05"))
c.Response().Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
c.Response().Header().Set("Content-Type", "application/json")
jsonData, err := json.MarshalIndent(lfs, "", " ")
if err != nil {
return h.RespondWithError(c, err)
}
return c.Blob(200, "application/json", jsonData)
}
// HandleImportLocalFiles
//
// @summary imports local files from the given path.
// @desc This will import local files from the given path.
// @desc The response is ignored, the client should refetch the entire library collection and media entry.
// @route /api/v1/library/local-files/import [POST]
func (h *Handler) HandleImportLocalFiles(c echo.Context) error {
type body struct {
DataFilePath string `json:"dataFilePath"`
}
b := new(body)
if err := c.Bind(b); err != nil {
return h.RespondWithError(c, err)
}
contentB, err := os.ReadFile(b.DataFilePath)
if err != nil {
return h.RespondWithError(c, err)
}
var lfs []*anime.LocalFile
if err := json.Unmarshal(contentB, &lfs); err != nil {
return h.RespondWithError(c, err)
}
if len(lfs) == 0 {
return h.RespondWithError(c, errors.New("no local files found"))
}
_, err = db_bridge.InsertLocalFiles(h.App.Database, lfs)
if err != nil {
return h.RespondWithError(c, err)
}
h.App.Database.TrimLocalFileEntries()
return h.RespondWithData(c, true)
}
// HandleLocalFileBulkAction
//
// @summary performs an action on all local files.
// @desc This will perform the given action on all local files.
// @desc The response is ignored, the client should refetch the entire library collection and media entry.
// @route /api/v1/library/local-files [POST]
// @returns []anime.LocalFile
func (h *Handler) HandleLocalFileBulkAction(c echo.Context) error {
type body struct {
Action string `json:"action"`
}
b := new(body)
if err := c.Bind(b); err != nil {
return h.RespondWithError(c, err)
}
// Get all the local files
lfs, lfsId, err := db_bridge.GetLocalFiles(h.App.Database)
if err != nil {
return h.RespondWithError(c, err)
}
switch b.Action {
case "lock":
for _, lf := range lfs {
// Note: Don't lock local files that are not associated with a media.
// Else refreshing the library will ignore them.
if lf.MediaId != 0 {
lf.Locked = true
}
}
case "unlock":
for _, lf := range lfs {
lf.Locked = false
}
}
// Save the local files
retLfs, err := db_bridge.SaveLocalFiles(h.App.Database, lfsId, lfs)
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, retLfs)
}
// HandleUpdateLocalFileData
//
// @summary updates the local file with the given path.
// @desc This will update the local file with the given path.
// @desc The response is ignored, the client should refetch the entire library collection and media entry.
// @route /api/v1/library/local-file [PATCH]
// @returns []anime.LocalFile
func (h *Handler) HandleUpdateLocalFileData(c echo.Context) error {
type body struct {
Path string `json:"path"`
Metadata *anime.LocalFileMetadata `json:"metadata"`
Locked bool `json:"locked"`
Ignored bool `json:"ignored"`
MediaId int `json:"mediaId"`
}
b := new(body)
if err := c.Bind(b); err != nil {
return h.RespondWithError(c, err)
}
// Get all the local files
lfs, lfsId, err := db_bridge.GetLocalFiles(h.App.Database)
if err != nil {
return h.RespondWithError(c, err)
}
lf, found := lo.Find(lfs, func(i *anime.LocalFile) bool {
return i.HasSamePath(b.Path)
})
if !found {
return h.RespondWithError(c, errors.New("local file not found"))
}
lf.Metadata = b.Metadata
lf.Locked = b.Locked
lf.Ignored = b.Ignored
lf.MediaId = b.MediaId
// Save the local files
retLfs, err := db_bridge.SaveLocalFiles(h.App.Database, lfsId, lfs)
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, retLfs)
}
// HandleUpdateLocalFiles
//
// @summary updates local files with the given paths.
// @desc The client should refetch the entire library collection and media entry.
// @route /api/v1/library/local-files [PATCH]
// @returns bool
func (h *Handler) HandleUpdateLocalFiles(c echo.Context) error {
type body struct {
Paths []string `json:"paths"`
Action string `json:"action"`
MediaId int `json:"mediaId,omitempty"`
}
b := new(body)
if err := c.Bind(b); err != nil {
return h.RespondWithError(c, err)
}
// Get all the local files
lfs, lfsId, err := db_bridge.GetLocalFiles(h.App.Database)
if err != nil {
return h.RespondWithError(c, err)
}
// Update the files
for _, path := range b.Paths {
lf, found := lo.Find(lfs, func(i *anime.LocalFile) bool {
return i.HasSamePath(path)
})
if !found {
continue
}
switch b.Action {
case "lock":
lf.Locked = true
case "unlock":
lf.Locked = false
case "ignore":
lf.MediaId = 0
lf.Ignored = true
lf.Locked = false
case "unignore":
lf.Ignored = false
lf.Locked = false
case "unmatch":
lf.MediaId = 0
lf.Locked = false
lf.Ignored = false
case "match":
lf.MediaId = b.MediaId
lf.Locked = true
lf.Ignored = false
}
}
// Save the local files
_, err = db_bridge.SaveLocalFiles(h.App.Database, lfsId, lfs)
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, true)
}
// HandleDeleteLocalFiles
//
// @summary deletes local files with the given paths.
// @desc This will delete the local files with the given paths.
// @desc The client should refetch the entire library collection and media entry.
// @route /api/v1/library/local-files [DELETE]
// @returns bool
func (h *Handler) HandleDeleteLocalFiles(c echo.Context) error {
type body struct {
Paths []string `json:"paths"`
}
b := new(body)
if err := c.Bind(b); err != nil {
return h.RespondWithError(c, err)
}
// Get all the local files
lfs, lfsId, err := db_bridge.GetLocalFiles(h.App.Database)
if err != nil {
return h.RespondWithError(c, err)
}
// Delete the files
p := pool.New().WithErrors()
for _, path := range b.Paths {
path := path
p.Go(func() error {
err := os.Remove(path)
if err != nil {
return err
}
return nil
})
}
if err := p.Wait(); err != nil {
return h.RespondWithError(c, err)
}
// Remove the files from the list
lfs = lo.Filter(lfs, func(i *anime.LocalFile, _ int) bool {
return !lo.Contains(b.Paths, i.Path)
})
// Save the local files
_, err = db_bridge.SaveLocalFiles(h.App.Database, lfsId, lfs)
if err != nil {
return h.RespondWithError(c, err)
}
return h.RespondWithData(c, true)
}
// HandleRemoveEmptyDirectories
//
// @summary removes empty directories.
// @desc This will remove empty directories in the library path.
// @route /api/v1/library/empty-directories [DELETE]
// @returns bool
func (h *Handler) HandleRemoveEmptyDirectories(c echo.Context) error {
libraryPaths, err := h.App.Database.GetAllLibraryPathsFromSettings()
if err != nil {
return h.RespondWithError(c, err)
}
for _, path := range libraryPaths {
filesystem.RemoveEmptyDirectories(path, h.App.Logger)
}
return h.RespondWithData(c, true)
}