diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/api/accounts.ts | 7 | ||||
-rw-r--r-- | server/middlewares/validators/videos/video-playlists.ts | 13 | ||||
-rw-r--r-- | server/models/video/video-playlist.ts | 31 |
3 files changed, 45 insertions, 6 deletions
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 5a1d652f2..c49da3c0a 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts | |||
@@ -27,7 +27,10 @@ import { VideoChannelModel } from '../../models/video/video-channel' | |||
27 | import { JobQueue } from '../../lib/job-queue' | 27 | import { JobQueue } from '../../lib/job-queue' |
28 | import { logger } from '../../helpers/logger' | 28 | import { logger } from '../../helpers/logger' |
29 | import { VideoPlaylistModel } from '../../models/video/video-playlist' | 29 | import { VideoPlaylistModel } from '../../models/video/video-playlist' |
30 | import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists' | 30 | import { |
31 | commonVideoPlaylistFiltersValidator, | ||
32 | videoPlaylistsSearchValidator | ||
33 | } from '../../middlewares/validators/videos/video-playlists' | ||
31 | 34 | ||
32 | const accountsRouter = express.Router() | 35 | const accountsRouter = express.Router() |
33 | 36 | ||
@@ -72,6 +75,7 @@ accountsRouter.get('/:accountName/video-playlists', | |||
72 | setDefaultSort, | 75 | setDefaultSort, |
73 | setDefaultPagination, | 76 | setDefaultPagination, |
74 | commonVideoPlaylistFiltersValidator, | 77 | commonVideoPlaylistFiltersValidator, |
78 | videoPlaylistsSearchValidator, | ||
75 | asyncMiddleware(listAccountPlaylists) | 79 | asyncMiddleware(listAccountPlaylists) |
76 | ) | 80 | ) |
77 | 81 | ||
@@ -135,6 +139,7 @@ async function listAccountPlaylists (req: express.Request, res: express.Response | |||
135 | } | 139 | } |
136 | 140 | ||
137 | const resultList = await VideoPlaylistModel.listForApi({ | 141 | const resultList = await VideoPlaylistModel.listForApi({ |
142 | search: req.query.search, | ||
138 | followerActorId: serverActor.id, | 143 | followerActorId: serverActor.id, |
139 | start: req.query.start, | 144 | start: req.query.start, |
140 | count: req.query.count, | 145 | count: req.query.count, |
diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts index 27ee62b1f..1d67e8666 100644 --- a/server/middlewares/validators/videos/video-playlists.ts +++ b/server/middlewares/validators/videos/video-playlists.ts | |||
@@ -166,6 +166,18 @@ const videoPlaylistsGetValidator = (fetchType: VideoPlaylistFetchType) => { | |||
166 | ] | 166 | ] |
167 | } | 167 | } |
168 | 168 | ||
169 | const videoPlaylistsSearchValidator = [ | ||
170 | query('search').optional().not().isEmpty().withMessage('Should have a valid search'), | ||
171 | |||
172 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
173 | logger.debug('Checking videoPlaylists search query', { parameters: req.query }) | ||
174 | |||
175 | if (areValidationErrors(req, res)) return | ||
176 | |||
177 | return next() | ||
178 | } | ||
179 | ] | ||
180 | |||
169 | const videoPlaylistsAddVideoValidator = [ | 181 | const videoPlaylistsAddVideoValidator = [ |
170 | param('playlistId') | 182 | param('playlistId') |
171 | .custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'), | 183 | .custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'), |
@@ -354,6 +366,7 @@ export { | |||
354 | videoPlaylistsUpdateValidator, | 366 | videoPlaylistsUpdateValidator, |
355 | videoPlaylistsDeleteValidator, | 367 | videoPlaylistsDeleteValidator, |
356 | videoPlaylistsGetValidator, | 368 | videoPlaylistsGetValidator, |
369 | videoPlaylistsSearchValidator, | ||
357 | 370 | ||
358 | videoPlaylistsAddVideoValidator, | 371 | videoPlaylistsAddVideoValidator, |
359 | videoPlaylistsUpdateOrRemoveVideoValidator, | 372 | videoPlaylistsUpdateOrRemoveVideoValidator, |
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts index 278d80ac0..ef87a7ee9 100644 --- a/server/models/video/video-playlist.ts +++ b/server/models/video/video-playlist.ts | |||
@@ -13,10 +13,11 @@ import { | |||
13 | Model, | 13 | Model, |
14 | Scopes, | 14 | Scopes, |
15 | Table, | 15 | Table, |
16 | UpdatedAt | 16 | UpdatedAt, |
17 | Sequelize | ||
17 | } from 'sequelize-typescript' | 18 | } from 'sequelize-typescript' |
18 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' | 19 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' |
19 | import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getSort, isOutdated, throwIfNotValid } from '../utils' | 20 | import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getSort, isOutdated, throwIfNotValid, createSimilarityAttribute } from '../utils' |
20 | import { | 21 | import { |
21 | isVideoPlaylistDescriptionValid, | 22 | isVideoPlaylistDescriptionValid, |
22 | isVideoPlaylistNameValid, | 23 | isVideoPlaylistNameValid, |
@@ -67,7 +68,8 @@ type AvailableForListOptions = { | |||
67 | type?: VideoPlaylistType | 68 | type?: VideoPlaylistType |
68 | accountId?: number | 69 | accountId?: number |
69 | videoChannelId?: number | 70 | videoChannelId?: number |
70 | privateAndUnlisted?: boolean | 71 | privateAndUnlisted?: boolean, |
72 | search?: string | ||
71 | } | 73 | } |
72 | 74 | ||
73 | @Scopes(() => ({ | 75 | @Scopes(() => ({ |
@@ -163,6 +165,23 @@ type AvailableForListOptions = { | |||
163 | }) | 165 | }) |
164 | } | 166 | } |
165 | 167 | ||
168 | if (options.search) { | ||
169 | const escapedSearch = VideoPlaylistModel.sequelize.escape(options.search) | ||
170 | const escapedLikeSearch = VideoPlaylistModel.sequelize.escape('%' + options.search + '%') | ||
171 | whereAnd.push({ | ||
172 | id: { | ||
173 | [ Op.in ]: Sequelize.literal( | ||
174 | '(' + | ||
175 | 'SELECT "videoPlaylist"."id" FROM "videoPlaylist" ' + | ||
176 | 'WHERE ' + | ||
177 | 'lower(immutable_unaccent("videoPlaylist"."name")) % lower(immutable_unaccent(' + escapedSearch + ')) OR ' + | ||
178 | 'lower(immutable_unaccent("videoPlaylist"."name")) LIKE lower(immutable_unaccent(' + escapedLikeSearch + '))' + | ||
179 | ')' | ||
180 | ) | ||
181 | } | ||
182 | }) | ||
183 | } | ||
184 | |||
166 | const where = { | 185 | const where = { |
167 | [Op.and]: whereAnd | 186 | [Op.and]: whereAnd |
168 | } | 187 | } |
@@ -291,7 +310,8 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> { | |||
291 | type?: VideoPlaylistType, | 310 | type?: VideoPlaylistType, |
292 | accountId?: number, | 311 | accountId?: number, |
293 | videoChannelId?: number, | 312 | videoChannelId?: number, |
294 | privateAndUnlisted?: boolean | 313 | privateAndUnlisted?: boolean, |
314 | search?: string | ||
295 | }) { | 315 | }) { |
296 | const query = { | 316 | const query = { |
297 | offset: options.start, | 317 | offset: options.start, |
@@ -308,7 +328,8 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> { | |||
308 | followerActorId: options.followerActorId, | 328 | followerActorId: options.followerActorId, |
309 | accountId: options.accountId, | 329 | accountId: options.accountId, |
310 | videoChannelId: options.videoChannelId, | 330 | videoChannelId: options.videoChannelId, |
311 | privateAndUnlisted: options.privateAndUnlisted | 331 | privateAndUnlisted: options.privateAndUnlisted, |
332 | search: options.search | ||
312 | } as AvailableForListOptions | 333 | } as AvailableForListOptions |
313 | ] | 334 | ] |
314 | }, | 335 | }, |