diff options
author | Chocobozzz <me@florianbigard.com> | 2021-07-28 16:40:21 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-07-28 16:40:21 +0200 |
commit | fbd67e7f386504e50f2504cb6386700a58906f16 (patch) | |
tree | 1a7143aaea76ce4e195fb9d6214a0cd769c556ea /server/models/video/video-channel.ts | |
parent | 164c8d46cf5c948a28b4ac0e596fad9b83b2c229 (diff) | |
download | PeerTube-fbd67e7f386504e50f2504cb6386700a58906f16.tar.gz PeerTube-fbd67e7f386504e50f2504cb6386700a58906f16.tar.zst PeerTube-fbd67e7f386504e50f2504cb6386700a58906f16.zip |
Add ability to search by uuids/actor names
Diffstat (limited to 'server/models/video/video-channel.ts')
-rw-r--r-- | server/models/video/video-channel.ts | 76 |
1 files changed, 48 insertions, 28 deletions
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 9aa271711..327f49304 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -59,6 +59,7 @@ type AvailableForListOptions = { | |||
59 | actorId: number | 59 | actorId: number |
60 | search?: string | 60 | search?: string |
61 | host?: string | 61 | host?: string |
62 | names?: string[] | ||
62 | } | 63 | } |
63 | 64 | ||
64 | type AvailableWithStatsOptions = { | 65 | type AvailableWithStatsOptions = { |
@@ -84,18 +85,20 @@ export type SummaryOptions = { | |||
84 | // Only list local channels OR channels that are on an instance followed by actorId | 85 | // Only list local channels OR channels that are on an instance followed by actorId |
85 | const inQueryInstanceFollow = buildServerIdsFollowedBy(options.actorId) | 86 | const inQueryInstanceFollow = buildServerIdsFollowedBy(options.actorId) |
86 | 87 | ||
87 | const whereActor = { | 88 | const whereActorAnd: WhereOptions[] = [ |
88 | [Op.or]: [ | 89 | { |
89 | { | 90 | [Op.or]: [ |
90 | serverId: null | 91 | { |
91 | }, | 92 | serverId: null |
92 | { | 93 | }, |
93 | serverId: { | 94 | { |
94 | [Op.in]: Sequelize.literal(inQueryInstanceFollow) | 95 | serverId: { |
96 | [Op.in]: Sequelize.literal(inQueryInstanceFollow) | ||
97 | } | ||
95 | } | 98 | } |
96 | } | 99 | ] |
97 | ] | 100 | } |
98 | } | 101 | ] |
99 | 102 | ||
100 | let serverRequired = false | 103 | let serverRequired = false |
101 | let whereServer: WhereOptions | 104 | let whereServer: WhereOptions |
@@ -106,8 +109,16 @@ export type SummaryOptions = { | |||
106 | } | 109 | } |
107 | 110 | ||
108 | if (options.host === WEBSERVER.HOST) { | 111 | if (options.host === WEBSERVER.HOST) { |
109 | Object.assign(whereActor, { | 112 | whereActorAnd.push({ |
110 | [Op.and]: [ { serverId: null } ] | 113 | serverId: null |
114 | }) | ||
115 | } | ||
116 | |||
117 | if (options.names) { | ||
118 | whereActorAnd.push({ | ||
119 | preferredUsername: { | ||
120 | [Op.in]: options.names | ||
121 | } | ||
111 | }) | 122 | }) |
112 | } | 123 | } |
113 | 124 | ||
@@ -118,7 +129,9 @@ export type SummaryOptions = { | |||
118 | exclude: unusedActorAttributesForAPI | 129 | exclude: unusedActorAttributesForAPI |
119 | }, | 130 | }, |
120 | model: ActorModel, | 131 | model: ActorModel, |
121 | where: whereActor, | 132 | where: { |
133 | [Op.and]: whereActorAnd | ||
134 | }, | ||
122 | include: [ | 135 | include: [ |
123 | { | 136 | { |
124 | model: ServerModel, | 137 | model: ServerModel, |
@@ -454,26 +467,23 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` | |||
454 | 467 | ||
455 | static searchForApi (options: { | 468 | static searchForApi (options: { |
456 | actorId: number | 469 | actorId: number |
457 | search: string | 470 | search?: string |
458 | start: number | 471 | start: number |
459 | count: number | 472 | count: number |
460 | sort: string | 473 | sort: string |
461 | 474 | ||
462 | host?: string | 475 | host?: string |
476 | names?: string[] | ||
463 | }) { | 477 | }) { |
464 | const attributesInclude = [] | 478 | let attributesInclude: any[] = [ literal('0 as similarity') ] |
465 | const escapedSearch = VideoChannelModel.sequelize.escape(options.search) | 479 | let where: WhereOptions |
466 | const escapedLikeSearch = VideoChannelModel.sequelize.escape('%' + options.search + '%') | ||
467 | attributesInclude.push(createSimilarityAttribute('VideoChannelModel.name', options.search)) | ||
468 | 480 | ||
469 | const query = { | 481 | if (options.search) { |
470 | attributes: { | 482 | const escapedSearch = VideoChannelModel.sequelize.escape(options.search) |
471 | include: attributesInclude | 483 | const escapedLikeSearch = VideoChannelModel.sequelize.escape('%' + options.search + '%') |
472 | }, | 484 | attributesInclude = [ createSimilarityAttribute('VideoChannelModel.name', options.search) ] |
473 | offset: options.start, | 485 | |
474 | limit: options.count, | 486 | where = { |
475 | order: getSort(options.sort), | ||
476 | where: { | ||
477 | [Op.or]: [ | 487 | [Op.or]: [ |
478 | Sequelize.literal( | 488 | Sequelize.literal( |
479 | 'lower(immutable_unaccent("VideoChannelModel"."name")) % lower(immutable_unaccent(' + escapedSearch + '))' | 489 | 'lower(immutable_unaccent("VideoChannelModel"."name")) % lower(immutable_unaccent(' + escapedSearch + '))' |
@@ -485,9 +495,19 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` | |||
485 | } | 495 | } |
486 | } | 496 | } |
487 | 497 | ||
498 | const query = { | ||
499 | attributes: { | ||
500 | include: attributesInclude | ||
501 | }, | ||
502 | offset: options.start, | ||
503 | limit: options.count, | ||
504 | order: getSort(options.sort), | ||
505 | where | ||
506 | } | ||
507 | |||
488 | return VideoChannelModel | 508 | return VideoChannelModel |
489 | .scope({ | 509 | .scope({ |
490 | method: [ ScopeNames.FOR_API, { actorId: options.actorId, host: options.host } as AvailableForListOptions ] | 510 | method: [ ScopeNames.FOR_API, { actorId: options.actorId, host: options.host, names: options.names } as AvailableForListOptions ] |
491 | }) | 511 | }) |
492 | .findAndCountAll(query) | 512 | .findAndCountAll(query) |
493 | .then(({ rows, count }) => { | 513 | .then(({ rows, count }) => { |