diff --git a/internal/db/db.go b/internal/db/db.go index 59686a88..325ce8c3 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -196,6 +196,17 @@ func WhereLike(column string, value string) func(db *gorm.DB) *gorm.DB { } } +func WhereMovieNameLikeOrURLLike(name, url string) func(db *gorm.DB) *gorm.DB { + return func(db *gorm.DB) *gorm.DB { + switch dbType { + case conf.DatabaseTypePostgres: + return db.Where("base_name ILIKE ? OR base_url ILIKE ?", utils.LIKE(name), utils.LIKE(url)) + default: + return db.Where("base_name LIKE ? OR base_url LIKE ?", utils.LIKE(name), utils.LIKE(url)) + } + } +} + func WhereRoomNameLikeOrCreatorInOrIDLike(name string, ids []string, id string) func(db *gorm.DB) *gorm.DB { return func(db *gorm.DB) *gorm.DB { switch dbType { diff --git a/internal/op/movies.go b/internal/op/movies.go index a1ba3c7b..b2eaf880 100644 --- a/internal/op/movies.go +++ b/internal/op/movies.go @@ -192,10 +192,13 @@ func (m *movies) SwapMoviePositions(id1, id2 string) error { return db.SwapMoviePositions(m.roomID, id1, id2) } -func (m *movies) GetMoviesWithPage(page, pageSize int, parentID string) ([]*model.Movie, int64, error) { +func (m *movies) GetMoviesWithPage(keyword string, page, pageSize int, parentID string) ([]*model.Movie, int64, error) { scopes := []func(*gorm.DB) *gorm.DB{ db.WithParentMovieID(parentID), } + if keyword != "" { + scopes = append(scopes, db.WhereMovieNameLikeOrURLLike(keyword, keyword)) + } count, err := db.GetMoviesCountByRoomID(m.roomID, append(scopes, db.Paginate(page, pageSize))...) if err != nil { return nil, 0, err diff --git a/internal/op/room.go b/internal/op/room.go index 1411e10c..f3124f2b 100644 --- a/internal/op/room.go +++ b/internal/op/room.go @@ -474,8 +474,8 @@ func (r *Room) SwapMoviePositions(id1, id2 string) error { return r.movies.SwapMoviePositions(id1, id2) } -func (r *Room) GetMoviesWithPage(page, pageSize int, parentID string) ([]*model.Movie, int64, error) { - return r.movies.GetMoviesWithPage(page, pageSize, parentID) +func (r *Room) GetMoviesWithPage(keyword string, page, pageSize int, parentID string) ([]*model.Movie, int64, error) { + return r.movies.GetMoviesWithPage(keyword, page, pageSize, parentID) } func (r *Room) NewClient(user *User, conn *websocket.Conn) (*Client, error) { diff --git a/internal/op/user.go b/internal/op/user.go index e5ab9f9d..d2119302 100644 --- a/internal/op/user.go +++ b/internal/op/user.go @@ -498,11 +498,11 @@ func (u *User) VerifyRetrievePasswordCaptchaEmail(e, captcha string) (bool, erro return email.VerifyRetrievePasswordCaptchaEmail(u.ID, e, captcha) } -func (u *User) GetRoomMoviesWithPage(room *Room, page, pageSize int, parentID string) ([]*model.Movie, int64, error) { +func (u *User) GetRoomMoviesWithPage(room *Room, keyword string, page, pageSize int, parentID string) ([]*model.Movie, int64, error) { if !u.HasRoomPermission(room, model.PermissionGetMovieList) { return nil, 0, model.ErrNoPermission } - return room.GetMoviesWithPage(page, pageSize, parentID) + return room.GetMoviesWithPage(keyword, page, pageSize, parentID) } func (u *User) SetRoomCurrentStatus(room *Room, playing bool, seek, rate, timeDiff float64) (*Status, error) { diff --git a/server/handlers/movie.go b/server/handlers/movie.go index 241ca2ab..1e342ea6 100644 --- a/server/handlers/movie.go +++ b/server/handlers/movie.go @@ -11,6 +11,7 @@ import ( "math/rand/v2" "net/http" "path/filepath" + "slices" "strings" "github.com/gin-gonic/gin" @@ -187,7 +188,7 @@ func Movies(ctx *gin.Context) { return } if mv.IsDynamicFolder() { - resp, err := listVendorDynamicMovie(ctx, user, room, mv, ctx.Query("subPath"), page, _max) + resp, err := listVendorDynamicMovie(ctx, user, room, mv, ctx.Query("subPath"), ctx.Query("keyword"), page, _max) if err != nil { log.Errorf("vendor dynamic movie list error: %v", err) ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err)) @@ -198,7 +199,7 @@ func Movies(ctx *gin.Context) { } } - m, total, err := user.GetRoomMoviesWithPage(room, page, _max, id) + m, total, err := user.GetRoomMoviesWithPage(room, ctx.Query("keyword"), page, _max, id) if err != nil { log.Errorf("get room movies with page error: %v", err) ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err)) @@ -239,15 +240,7 @@ func Movies(ctx *gin.Context) { } func getParentMoviePath(room *op.Room, id string) ([]*model.MoviePath, error) { - paths := []*model.MoviePath{ - { - Name: "Home", - ID: "", - }, - } - if id == "" { - return paths, nil - } + paths := []*model.MoviePath{} for id != "" { p, err := room.GetMovieByID(id) if err != nil { @@ -259,10 +252,15 @@ func getParentMoviePath(room *op.Room, id string) ([]*model.MoviePath, error) { }) id = p.ParentID.String() } + paths = append(paths, &model.MoviePath{ + Name: "Home", + ID: "", + }) + slices.Reverse(paths) return paths, nil } -func listVendorDynamicMovie(ctx context.Context, reqUser *op.User, room *op.Room, movie *op.Movie, subPath string, page, _max int) (*model.MoviesResp, error) { +func listVendorDynamicMovie(ctx context.Context, reqUser *op.User, room *op.Room, movie *op.Movie, subPath string, keyword string, page, _max int) (*model.MoviesResp, error) { if reqUser.ID != movie.CreatorID { return nil, fmt.Errorf("list vendor dynamic folder error: %w", dbModel.ErrNoPermission) } @@ -275,7 +273,7 @@ func listVendorDynamicMovie(ctx context.Context, reqUser *op.User, room *op.Room if err != nil { return nil, err } - dynamic, err := vendor.ListDynamicMovie(ctx, reqUser, subPath, page, _max) + dynamic, err := vendor.ListDynamicMovie(ctx, reqUser, subPath, keyword, page, _max) if err != nil { return nil, err } diff --git a/server/handlers/vendors/vendorAlist/alist.go b/server/handlers/vendors/vendorAlist/alist.go index c9fc1b1c..cedd0dc3 100644 --- a/server/handlers/vendors/vendorAlist/alist.go +++ b/server/handlers/vendors/vendorAlist/alist.go @@ -43,7 +43,7 @@ func (s *AlistVendorService) Client() alist.AlistHTTPServer { return vendor.LoadAlistClient(s.movie.VendorInfo.Backend) } -func (s *AlistVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, page, _max int) (*model.MovieList, error) { +func (s *AlistVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, keyword string, page, _max int) (*model.MovieList, error) { if reqUser.ID != s.movie.CreatorID { return nil, fmt.Errorf("list vendor dynamic folder error: %w", dbModel.ErrNoPermission) } diff --git a/server/handlers/vendors/vendorBilibili/bilibili.go b/server/handlers/vendors/vendorBilibili/bilibili.go index f3eed2f7..c3dcd54d 100644 --- a/server/handlers/vendors/vendorBilibili/bilibili.go +++ b/server/handlers/vendors/vendorBilibili/bilibili.go @@ -42,7 +42,7 @@ func (s *BilibiliVendorService) Client() bilibili.BilibiliHTTPServer { return vendor.LoadBilibiliClient(s.movie.VendorInfo.Backend) } -func (s *BilibiliVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, page, _max int) (*model.MovieList, error) { +func (s *BilibiliVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, keyword string, page, _max int) (*model.MovieList, error) { return nil, errors.New("bilibili vendor not support list dynamic movie") } diff --git a/server/handlers/vendors/vendorEmby/emby.go b/server/handlers/vendors/vendorEmby/emby.go index 6a0f96b4..ee734d06 100644 --- a/server/handlers/vendors/vendorEmby/emby.go +++ b/server/handlers/vendors/vendorEmby/emby.go @@ -41,7 +41,7 @@ func (s *EmbyVendorService) Client() emby.EmbyHTTPServer { return vendor.LoadEmbyClient(s.movie.VendorInfo.Backend) } -func (s *EmbyVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, page, _max int) (*model.MovieList, error) { +func (s *EmbyVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, keyword string, page, _max int) (*model.MovieList, error) { if reqUser.ID != s.movie.CreatorID { return nil, fmt.Errorf("list vendor dynamic folder error: %w", dbModel.ErrNoPermission) } @@ -72,6 +72,7 @@ func (s *EmbyVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.Us UserId: aucd.UserID, Limit: uint64(_max), StartIndex: uint64((page - 1) * _max), + SearchTerm: keyword, }) if err != nil { return nil, fmt.Errorf("emby fs list error: %w", err) diff --git a/server/handlers/vendors/vendoralist/alist.go b/server/handlers/vendors/vendoralist/alist.go index c9fc1b1c..cedd0dc3 100644 --- a/server/handlers/vendors/vendoralist/alist.go +++ b/server/handlers/vendors/vendoralist/alist.go @@ -43,7 +43,7 @@ func (s *AlistVendorService) Client() alist.AlistHTTPServer { return vendor.LoadAlistClient(s.movie.VendorInfo.Backend) } -func (s *AlistVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, page, _max int) (*model.MovieList, error) { +func (s *AlistVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, keyword string, page, _max int) (*model.MovieList, error) { if reqUser.ID != s.movie.CreatorID { return nil, fmt.Errorf("list vendor dynamic folder error: %w", dbModel.ErrNoPermission) } diff --git a/server/handlers/vendors/vendorbilibili/bilibili.go b/server/handlers/vendors/vendorbilibili/bilibili.go index f3eed2f7..c3dcd54d 100644 --- a/server/handlers/vendors/vendorbilibili/bilibili.go +++ b/server/handlers/vendors/vendorbilibili/bilibili.go @@ -42,7 +42,7 @@ func (s *BilibiliVendorService) Client() bilibili.BilibiliHTTPServer { return vendor.LoadBilibiliClient(s.movie.VendorInfo.Backend) } -func (s *BilibiliVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, page, _max int) (*model.MovieList, error) { +func (s *BilibiliVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, keyword string, page, _max int) (*model.MovieList, error) { return nil, errors.New("bilibili vendor not support list dynamic movie") } diff --git a/server/handlers/vendors/vendoremby/emby.go b/server/handlers/vendors/vendoremby/emby.go index 6a0f96b4..ee734d06 100644 --- a/server/handlers/vendors/vendoremby/emby.go +++ b/server/handlers/vendors/vendoremby/emby.go @@ -41,7 +41,7 @@ func (s *EmbyVendorService) Client() emby.EmbyHTTPServer { return vendor.LoadEmbyClient(s.movie.VendorInfo.Backend) } -func (s *EmbyVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, page, _max int) (*model.MovieList, error) { +func (s *EmbyVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, keyword string, page, _max int) (*model.MovieList, error) { if reqUser.ID != s.movie.CreatorID { return nil, fmt.Errorf("list vendor dynamic folder error: %w", dbModel.ErrNoPermission) } @@ -72,6 +72,7 @@ func (s *EmbyVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.Us UserId: aucd.UserID, Limit: uint64(_max), StartIndex: uint64((page - 1) * _max), + SearchTerm: keyword, }) if err != nil { return nil, fmt.Errorf("emby fs list error: %w", err) diff --git a/server/handlers/vendors/vendors.go b/server/handlers/vendors/vendors.go index e58758d7..c0db42d4 100644 --- a/server/handlers/vendors/vendors.go +++ b/server/handlers/vendors/vendors.go @@ -33,7 +33,7 @@ func Backends(ctx *gin.Context) { } type VendorService interface { - ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, page, _max int) (*model.MovieList, error) + ListDynamicMovie(ctx context.Context, reqUser *op.User, subPath string, keyword string, page, _max int) (*model.MovieList, error) ProxyMovie(ctx *gin.Context) GenMovieInfo(ctx context.Context, reqUser *op.User, userAgent, userToken string) (*dbModel.Movie, error) }