diff options
-rw-r--r-- | server/models/video/video.ts | 50 | ||||
-rw-r--r-- | server/tests/api/search/search-videos.ts | 10 |
2 files changed, 40 insertions, 20 deletions
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 7e3512fe1..73e0d2345 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -59,8 +59,6 @@ import { | |||
59 | ACTIVITY_PUB, | 59 | ACTIVITY_PUB, |
60 | API_VERSION, | 60 | API_VERSION, |
61 | CONSTRAINTS_FIELDS, | 61 | CONSTRAINTS_FIELDS, |
62 | HLS_REDUNDANCY_DIRECTORY, | ||
63 | HLS_STREAMING_PLAYLIST_DIRECTORY, | ||
64 | LAZY_STATIC_PATHS, | 62 | LAZY_STATIC_PATHS, |
65 | REMOTE_SCHEME, | 63 | REMOTE_SCHEME, |
66 | STATIC_DOWNLOAD_PATHS, | 64 | STATIC_DOWNLOAD_PATHS, |
@@ -143,7 +141,8 @@ import { | |||
143 | import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../typings/models/video/video-file' | 141 | import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../typings/models/video/video-file' |
144 | import { MThumbnail } from '../../typings/models/video/thumbnail' | 142 | import { MThumbnail } from '../../typings/models/video/thumbnail' |
145 | import { VideoFile } from '@shared/models/videos/video-file.model' | 143 | import { VideoFile } from '@shared/models/videos/video-file.model' |
146 | import { getTorrentFileName, getTorrentFilePath, getVideoFilename, getVideoFilePath, getHLSDirectory } from '@server/lib/video-paths' | 144 | import { getHLSDirectory, getTorrentFileName, getTorrentFilePath, getVideoFilename, getVideoFilePath } from '@server/lib/video-paths' |
145 | import * as validator from 'validator' | ||
147 | 146 | ||
148 | // FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation | 147 | // FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation |
149 | const indexes: (ModelIndexesOptions & { where?: WhereOptions })[] = [ | 148 | const indexes: (ModelIndexesOptions & { where?: WhereOptions })[] = [ |
@@ -1352,24 +1351,35 @@ export class VideoModel extends Model<VideoModel> { | |||
1352 | const escapedSearch = VideoModel.sequelize.escape(options.search) | 1351 | const escapedSearch = VideoModel.sequelize.escape(options.search) |
1353 | const escapedLikeSearch = VideoModel.sequelize.escape('%' + options.search + '%') | 1352 | const escapedLikeSearch = VideoModel.sequelize.escape('%' + options.search + '%') |
1354 | if (options.search) { | 1353 | if (options.search) { |
1355 | whereAnd.push( | 1354 | const trigramSearch = { |
1356 | { | 1355 | id: { |
1357 | id: { | 1356 | [ Op.in ]: Sequelize.literal( |
1358 | [ Op.in ]: Sequelize.literal( | 1357 | '(' + |
1359 | '(' + | 1358 | 'SELECT "video"."id" FROM "video" ' + |
1360 | 'SELECT "video"."id" FROM "video" ' + | 1359 | 'WHERE ' + |
1361 | 'WHERE ' + | 1360 | 'lower(immutable_unaccent("video"."name")) % lower(immutable_unaccent(' + escapedSearch + ')) OR ' + |
1362 | 'lower(immutable_unaccent("video"."name")) % lower(immutable_unaccent(' + escapedSearch + ')) OR ' + | 1361 | 'lower(immutable_unaccent("video"."name")) LIKE lower(immutable_unaccent(' + escapedLikeSearch + '))' + |
1363 | 'lower(immutable_unaccent("video"."name")) LIKE lower(immutable_unaccent(' + escapedLikeSearch + '))' + | 1362 | 'UNION ALL ' + |
1364 | 'UNION ALL ' + | 1363 | 'SELECT "video"."id" FROM "video" LEFT JOIN "videoTag" ON "videoTag"."videoId" = "video"."id" ' + |
1365 | 'SELECT "video"."id" FROM "video" LEFT JOIN "videoTag" ON "videoTag"."videoId" = "video"."id" ' + | 1364 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
1366 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 1365 | 'WHERE "tag"."name" = ' + escapedSearch + |
1367 | 'WHERE "tag"."name" = ' + escapedSearch + | 1366 | ')' |
1368 | ')' | 1367 | ) |
1369 | ) | ||
1370 | } | ||
1371 | } | 1368 | } |
1372 | ) | 1369 | } |
1370 | |||
1371 | if (validator.isUUID(options.search)) { | ||
1372 | whereAnd.push({ | ||
1373 | [Op.or]: [ | ||
1374 | trigramSearch, | ||
1375 | { | ||
1376 | uuid: options.search | ||
1377 | } | ||
1378 | ] | ||
1379 | }) | ||
1380 | } else { | ||
1381 | whereAnd.push(trigramSearch) | ||
1382 | } | ||
1373 | 1383 | ||
1374 | attributesInclude.push(createSimilarityAttribute('VideoModel.name', options.search)) | 1384 | attributesInclude.push(createSimilarityAttribute('VideoModel.name', options.search)) |
1375 | } | 1385 | } |
diff --git a/server/tests/api/search/search-videos.ts b/server/tests/api/search/search-videos.ts index a3e05156b..7882d9373 100644 --- a/server/tests/api/search/search-videos.ts +++ b/server/tests/api/search/search-videos.ts | |||
@@ -20,6 +20,7 @@ const expect = chai.expect | |||
20 | describe('Test videos search', function () { | 20 | describe('Test videos search', function () { |
21 | let server: ServerInfo = null | 21 | let server: ServerInfo = null |
22 | let startDate: string | 22 | let startDate: string |
23 | let videoUUID: string | ||
23 | 24 | ||
24 | before(async function () { | 25 | before(async function () { |
25 | this.timeout(30000) | 26 | this.timeout(30000) |
@@ -46,6 +47,7 @@ describe('Test videos search', function () { | |||
46 | const attributes3 = immutableAssign(attributes1, { name: attributes1.name + ' - 3', language: undefined }) | 47 | const attributes3 = immutableAssign(attributes1, { name: attributes1.name + ' - 3', language: undefined }) |
47 | const res = await uploadVideo(server.url, server.accessToken, attributes3) | 48 | const res = await uploadVideo(server.url, server.accessToken, attributes3) |
48 | const videoId = res.body.video.id | 49 | const videoId = res.body.video.id |
50 | videoUUID = res.body.video.uuid | ||
49 | 51 | ||
50 | await createVideoCaption({ | 52 | await createVideoCaption({ |
51 | url: server.url, | 53 | url: server.url, |
@@ -439,6 +441,14 @@ describe('Test videos search', function () { | |||
439 | } | 441 | } |
440 | }) | 442 | }) |
441 | 443 | ||
444 | it('Should search by UUID', async function () { | ||
445 | const search = videoUUID | ||
446 | const res = await advancedVideosSearch(server.url, { search }) | ||
447 | |||
448 | expect(res.body.total).to.equal(1) | ||
449 | expect(res.body.data[0].name).to.equal('1111 2222 3333 - 3') | ||
450 | }) | ||
451 | |||
442 | after(async function () { | 452 | after(async function () { |
443 | await cleanupTests([ server ]) | 453 | await cleanupTests([ server ]) |
444 | }) | 454 | }) |