Refactor search query options
This commit is contained in:
parent
b033851fb5
commit
d688602710
|
@ -1,6 +1,6 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
import { pickCommonVideoQuery } from '@server/helpers/query'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { VideosWithSearchCommonQuery } from '@shared/models'
|
|
||||||
import { buildNSFWFilter, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
|
import { buildNSFWFilter, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
|
||||||
import { getFormattedObjects } from '../../helpers/utils'
|
import { getFormattedObjects } from '../../helpers/utils'
|
||||||
import { JobQueue } from '../../lib/job-queue'
|
import { JobQueue } from '../../lib/job-queue'
|
||||||
|
@ -159,27 +159,19 @@ async function listAccountVideos (req: express.Request, res: express.Response) {
|
||||||
const account = res.locals.account
|
const account = res.locals.account
|
||||||
const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined
|
const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined
|
||||||
const countVideos = getCountVideos(req)
|
const countVideos = getCountVideos(req)
|
||||||
const query = req.query as VideosWithSearchCommonQuery
|
const query = pickCommonVideoQuery(req.query)
|
||||||
|
|
||||||
const apiOptions = await Hooks.wrapObject({
|
const apiOptions = await Hooks.wrapObject({
|
||||||
|
...query,
|
||||||
|
|
||||||
followerActorId,
|
followerActorId,
|
||||||
start: query.start,
|
search: req.query.search,
|
||||||
count: query.count,
|
|
||||||
sort: query.sort,
|
|
||||||
includeLocalVideos: true,
|
includeLocalVideos: true,
|
||||||
categoryOneOf: query.categoryOneOf,
|
|
||||||
licenceOneOf: query.licenceOneOf,
|
|
||||||
languageOneOf: query.languageOneOf,
|
|
||||||
tagsOneOf: query.tagsOneOf,
|
|
||||||
tagsAllOf: query.tagsAllOf,
|
|
||||||
filter: query.filter,
|
|
||||||
isLive: query.isLive,
|
|
||||||
nsfw: buildNSFWFilter(res, query.nsfw),
|
nsfw: buildNSFWFilter(res, query.nsfw),
|
||||||
withFiles: false,
|
withFiles: false,
|
||||||
accountId: account.id,
|
accountId: account.id,
|
||||||
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
|
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
|
||||||
countVideos,
|
countVideos
|
||||||
search: query.search
|
|
||||||
}, 'filter:api.accounts.videos.list.params')
|
}, 'filter:api.accounts.videos.list.params')
|
||||||
|
|
||||||
const resultList = await Hooks.wrapPromiseFun(
|
const resultList = await Hooks.wrapPromiseFun(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { sanitizeUrl } from '@server/helpers/core-utils'
|
import { sanitizeUrl } from '@server/helpers/core-utils'
|
||||||
|
import { pickSearchChannelQuery } from '@server/helpers/query'
|
||||||
import { doJSONRequest } from '@server/helpers/requests'
|
import { doJSONRequest } from '@server/helpers/requests'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
import { WEBSERVER } from '@server/initializers/constants'
|
import { WEBSERVER } from '@server/initializers/constants'
|
||||||
|
@ -7,7 +8,7 @@ import { Hooks } from '@server/lib/plugins/hooks'
|
||||||
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
|
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { HttpStatusCode, ResultList, VideoChannel } from '@shared/models'
|
import { HttpStatusCode, ResultList, VideoChannel } from '@shared/models'
|
||||||
import { VideoChannelsSearchQuery } from '../../../../shared/models/search'
|
import { VideoChannelsSearchQueryAfterSanitize } from '../../../../shared/models/search'
|
||||||
import { isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
|
import { isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
|
||||||
import { logger } from '../../../helpers/logger'
|
import { logger } from '../../../helpers/logger'
|
||||||
import { getFormattedObjects } from '../../../helpers/utils'
|
import { getFormattedObjects } from '../../../helpers/utils'
|
||||||
|
@ -45,7 +46,7 @@ export { searchChannelsRouter }
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function searchVideoChannels (req: express.Request, res: express.Response) {
|
function searchVideoChannels (req: express.Request, res: express.Response) {
|
||||||
const query: VideoChannelsSearchQuery = req.query
|
const query = pickSearchChannelQuery(req.query)
|
||||||
let search = query.search || ''
|
let search = query.search || ''
|
||||||
|
|
||||||
const parts = search.split('@')
|
const parts = search.split('@')
|
||||||
|
@ -66,7 +67,7 @@ function searchVideoChannels (req: express.Request, res: express.Response) {
|
||||||
return searchVideoChannelsDB(query, res)
|
return searchVideoChannelsDB(query, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchVideoChannelsIndex (query: VideoChannelsSearchQuery, res: express.Response) {
|
async function searchVideoChannelsIndex (query: VideoChannelsSearchQueryAfterSanitize, res: express.Response) {
|
||||||
const result = await buildMutedForSearchIndex(res)
|
const result = await buildMutedForSearchIndex(res)
|
||||||
|
|
||||||
const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-channels.index.list.params')
|
const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-channels.index.list.params')
|
||||||
|
@ -90,17 +91,13 @@ async function searchVideoChannelsIndex (query: VideoChannelsSearchQuery, res: e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchVideoChannelsDB (query: VideoChannelsSearchQuery, res: express.Response) {
|
async function searchVideoChannelsDB (query: VideoChannelsSearchQueryAfterSanitize, res: express.Response) {
|
||||||
const serverActor = await getServerActor()
|
const serverActor = await getServerActor()
|
||||||
|
|
||||||
const apiOptions = await Hooks.wrapObject({
|
const apiOptions = await Hooks.wrapObject({
|
||||||
actorId: serverActor.id,
|
...query,
|
||||||
search: query.search,
|
|
||||||
start: query.start,
|
actorId: serverActor.id
|
||||||
count: query.count,
|
|
||||||
sort: query.sort,
|
|
||||||
host: query.host,
|
|
||||||
handles: query.handles
|
|
||||||
}, 'filter:api.search.video-channels.local.list.params')
|
}, 'filter:api.search.video-channels.local.list.params')
|
||||||
|
|
||||||
const resultList = await Hooks.wrapPromiseFun(
|
const resultList = await Hooks.wrapPromiseFun(
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as express from 'express'
|
||||||
import { sanitizeUrl } from '@server/helpers/core-utils'
|
import { sanitizeUrl } from '@server/helpers/core-utils'
|
||||||
import { isUserAbleToSearchRemoteURI } from '@server/helpers/express-utils'
|
import { isUserAbleToSearchRemoteURI } from '@server/helpers/express-utils'
|
||||||
import { logger } from '@server/helpers/logger'
|
import { logger } from '@server/helpers/logger'
|
||||||
|
import { pickSearchPlaylistQuery } from '@server/helpers/query'
|
||||||
import { doJSONRequest } from '@server/helpers/requests'
|
import { doJSONRequest } from '@server/helpers/requests'
|
||||||
import { getFormattedObjects } from '@server/helpers/utils'
|
import { getFormattedObjects } from '@server/helpers/utils'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
|
@ -12,7 +13,7 @@ import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@ser
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { VideoPlaylistModel } from '@server/models/video/video-playlist'
|
import { VideoPlaylistModel } from '@server/models/video/video-playlist'
|
||||||
import { MVideoPlaylistFullSummary } from '@server/types/models'
|
import { MVideoPlaylistFullSummary } from '@server/types/models'
|
||||||
import { HttpStatusCode, ResultList, VideoPlaylist, VideoPlaylistsSearchQuery } from '@shared/models'
|
import { HttpStatusCode, ResultList, VideoPlaylist, VideoPlaylistsSearchQueryAfterSanitize } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
asyncMiddleware,
|
asyncMiddleware,
|
||||||
openapiOperationDoc,
|
openapiOperationDoc,
|
||||||
|
@ -44,7 +45,7 @@ export { searchPlaylistsRouter }
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function searchVideoPlaylists (req: express.Request, res: express.Response) {
|
function searchVideoPlaylists (req: express.Request, res: express.Response) {
|
||||||
const query: VideoPlaylistsSearchQuery = req.query
|
const query = pickSearchPlaylistQuery(req.query)
|
||||||
const search = query.search
|
const search = query.search
|
||||||
|
|
||||||
if (isURISearch(search)) return searchVideoPlaylistsURI(search, res)
|
if (isURISearch(search)) return searchVideoPlaylistsURI(search, res)
|
||||||
|
@ -56,7 +57,7 @@ function searchVideoPlaylists (req: express.Request, res: express.Response) {
|
||||||
return searchVideoPlaylistsDB(query, res)
|
return searchVideoPlaylistsDB(query, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchVideoPlaylistsIndex (query: VideoPlaylistsSearchQuery, res: express.Response) {
|
async function searchVideoPlaylistsIndex (query: VideoPlaylistsSearchQueryAfterSanitize, res: express.Response) {
|
||||||
const result = await buildMutedForSearchIndex(res)
|
const result = await buildMutedForSearchIndex(res)
|
||||||
|
|
||||||
const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-playlists.index.list.params')
|
const body = await Hooks.wrapObject(Object.assign(query, result), 'filter:api.search.video-playlists.index.list.params')
|
||||||
|
@ -80,17 +81,13 @@ async function searchVideoPlaylistsIndex (query: VideoPlaylistsSearchQuery, res:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchVideoPlaylistsDB (query: VideoPlaylistsSearchQuery, res: express.Response) {
|
async function searchVideoPlaylistsDB (query: VideoPlaylistsSearchQueryAfterSanitize, res: express.Response) {
|
||||||
const serverActor = await getServerActor()
|
const serverActor = await getServerActor()
|
||||||
|
|
||||||
const apiOptions = await Hooks.wrapObject({
|
const apiOptions = await Hooks.wrapObject({
|
||||||
followerActorId: serverActor.id,
|
...query,
|
||||||
search: query.search,
|
|
||||||
start: query.start,
|
followerActorId: serverActor.id
|
||||||
count: query.count,
|
|
||||||
sort: query.sort,
|
|
||||||
host: query.host,
|
|
||||||
uuids: query.uuids
|
|
||||||
}, 'filter:api.search.video-playlists.local.list.params')
|
}, 'filter:api.search.video-playlists.local.list.params')
|
||||||
|
|
||||||
const resultList = await Hooks.wrapPromiseFun(
|
const resultList = await Hooks.wrapPromiseFun(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import { sanitizeUrl } from '@server/helpers/core-utils'
|
import { sanitizeUrl } from '@server/helpers/core-utils'
|
||||||
|
import { pickSearchVideoQuery } from '@server/helpers/query'
|
||||||
import { doJSONRequest } from '@server/helpers/requests'
|
import { doJSONRequest } from '@server/helpers/requests'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
import { WEBSERVER } from '@server/initializers/constants'
|
import { WEBSERVER } from '@server/initializers/constants'
|
||||||
|
@ -7,7 +8,7 @@ import { getOrCreateAPVideo } from '@server/lib/activitypub/videos'
|
||||||
import { Hooks } from '@server/lib/plugins/hooks'
|
import { Hooks } from '@server/lib/plugins/hooks'
|
||||||
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
|
import { buildMutedForSearchIndex, isSearchIndexSearch, isURISearch } from '@server/lib/search'
|
||||||
import { HttpStatusCode, ResultList, Video } from '@shared/models'
|
import { HttpStatusCode, ResultList, Video } from '@shared/models'
|
||||||
import { VideosSearchQuery } from '../../../../shared/models/search'
|
import { VideosSearchQueryAfterSanitize } from '../../../../shared/models/search'
|
||||||
import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
|
import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../../helpers/express-utils'
|
||||||
import { logger } from '../../../helpers/logger'
|
import { logger } from '../../../helpers/logger'
|
||||||
import { getFormattedObjects } from '../../../helpers/utils'
|
import { getFormattedObjects } from '../../../helpers/utils'
|
||||||
|
@ -46,7 +47,7 @@ export { searchVideosRouter }
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
function searchVideos (req: express.Request, res: express.Response) {
|
function searchVideos (req: express.Request, res: express.Response) {
|
||||||
const query: VideosSearchQuery = req.query
|
const query = pickSearchVideoQuery(req.query)
|
||||||
const search = query.search
|
const search = query.search
|
||||||
|
|
||||||
if (isURISearch(search)) {
|
if (isURISearch(search)) {
|
||||||
|
@ -60,10 +61,10 @@ function searchVideos (req: express.Request, res: express.Response) {
|
||||||
return searchVideosDB(query, res)
|
return searchVideosDB(query, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchVideosIndex (query: VideosSearchQuery, res: express.Response) {
|
async function searchVideosIndex (query: VideosSearchQueryAfterSanitize, res: express.Response) {
|
||||||
const result = await buildMutedForSearchIndex(res)
|
const result = await buildMutedForSearchIndex(res)
|
||||||
|
|
||||||
let body: VideosSearchQuery = Object.assign(query, result)
|
let body = { ...query, ...result }
|
||||||
|
|
||||||
// Use the default instance NSFW policy if not specified
|
// Use the default instance NSFW policy if not specified
|
||||||
if (!body.nsfw) {
|
if (!body.nsfw) {
|
||||||
|
@ -97,13 +98,18 @@ async function searchVideosIndex (query: VideosSearchQuery, res: express.Respons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchVideosDB (query: VideosSearchQuery, res: express.Response) {
|
async function searchVideosDB (query: VideosSearchQueryAfterSanitize, res: express.Response) {
|
||||||
const apiOptions = await Hooks.wrapObject(Object.assign(query, {
|
const apiOptions = await Hooks.wrapObject({
|
||||||
|
...query,
|
||||||
|
|
||||||
includeLocalVideos: true,
|
includeLocalVideos: true,
|
||||||
nsfw: buildNSFWFilter(res, query.nsfw),
|
|
||||||
filter: query.filter,
|
filter: query.filter,
|
||||||
user: res.locals.oauth ? res.locals.oauth.token.User : undefined
|
|
||||||
}), 'filter:api.search.videos.local.list.params')
|
nsfw: buildNSFWFilter(res, query.nsfw),
|
||||||
|
user: res.locals.oauth
|
||||||
|
? res.locals.oauth.token.User
|
||||||
|
: undefined
|
||||||
|
}, 'filter:api.search.videos.local.list.params')
|
||||||
|
|
||||||
const resultList = await Hooks.wrapPromiseFun(
|
const resultList = await Hooks.wrapPromiseFun(
|
||||||
VideoModel.searchAndPopulateAccountAndServer,
|
VideoModel.searchAndPopulateAccountAndServer,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'multer'
|
import 'multer'
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
import { pickCommonVideoQuery } from '@server/helpers/query'
|
||||||
import { sendUndoFollow } from '@server/lib/activitypub/send'
|
import { sendUndoFollow } from '@server/lib/activitypub/send'
|
||||||
import { VideoChannelModel } from '@server/models/video/video-channel'
|
import { VideoChannelModel } from '@server/models/video/video-channel'
|
||||||
import { VideosCommonQuery } from '@shared/models'
|
|
||||||
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
|
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
|
||||||
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
|
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
|
||||||
import { getFormattedObjects } from '../../../helpers/utils'
|
import { getFormattedObjects } from '../../../helpers/utils'
|
||||||
|
@ -170,20 +170,13 @@ async function getUserSubscriptions (req: express.Request, res: express.Response
|
||||||
async function getUserSubscriptionVideos (req: express.Request, res: express.Response) {
|
async function getUserSubscriptionVideos (req: express.Request, res: express.Response) {
|
||||||
const user = res.locals.oauth.token.User
|
const user = res.locals.oauth.token.User
|
||||||
const countVideos = getCountVideos(req)
|
const countVideos = getCountVideos(req)
|
||||||
const query = req.query as VideosCommonQuery
|
const query = pickCommonVideoQuery(req.query)
|
||||||
|
|
||||||
const resultList = await VideoModel.listForApi({
|
const resultList = await VideoModel.listForApi({
|
||||||
start: query.start,
|
...query,
|
||||||
count: query.count,
|
|
||||||
sort: query.sort,
|
|
||||||
includeLocalVideos: false,
|
includeLocalVideos: false,
|
||||||
categoryOneOf: query.categoryOneOf,
|
|
||||||
licenceOneOf: query.licenceOneOf,
|
|
||||||
languageOneOf: query.languageOneOf,
|
|
||||||
tagsOneOf: query.tagsOneOf,
|
|
||||||
tagsAllOf: query.tagsAllOf,
|
|
||||||
nsfw: buildNSFWFilter(res, query.nsfw),
|
nsfw: buildNSFWFilter(res, query.nsfw),
|
||||||
filter: query.filter,
|
|
||||||
withFiles: false,
|
withFiles: false,
|
||||||
followerActorId: user.Account.Actor.id,
|
followerActorId: user.Account.Actor.id,
|
||||||
user,
|
user,
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
import { pickCommonVideoQuery } from '@server/helpers/query'
|
||||||
import { Hooks } from '@server/lib/plugins/hooks'
|
import { Hooks } from '@server/lib/plugins/hooks'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { MChannelBannerAccountDefault } from '@server/types/models'
|
import { MChannelBannerAccountDefault } from '@server/types/models'
|
||||||
import { ActorImageType, VideoChannelCreate, VideoChannelUpdate, VideosCommonQuery } from '../../../shared'
|
import { ActorImageType, VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
|
||||||
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
|
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
|
||||||
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger'
|
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger'
|
||||||
import { resetSequelizeInstance } from '../../helpers/database-utils'
|
import { resetSequelizeInstance } from '../../helpers/database-utils'
|
||||||
|
@ -309,20 +310,13 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon
|
||||||
const videoChannelInstance = res.locals.videoChannel
|
const videoChannelInstance = res.locals.videoChannel
|
||||||
const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined
|
const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined
|
||||||
const countVideos = getCountVideos(req)
|
const countVideos = getCountVideos(req)
|
||||||
const query = req.query as VideosCommonQuery
|
const query = pickCommonVideoQuery(req.query)
|
||||||
|
|
||||||
const apiOptions = await Hooks.wrapObject({
|
const apiOptions = await Hooks.wrapObject({
|
||||||
|
...query,
|
||||||
|
|
||||||
followerActorId,
|
followerActorId,
|
||||||
start: query.start,
|
|
||||||
count: query.count,
|
|
||||||
sort: query.sort,
|
|
||||||
includeLocalVideos: true,
|
includeLocalVideos: true,
|
||||||
categoryOneOf: query.categoryOneOf,
|
|
||||||
licenceOneOf: query.licenceOneOf,
|
|
||||||
languageOneOf: query.languageOneOf,
|
|
||||||
tagsOneOf: query.tagsOneOf,
|
|
||||||
tagsAllOf: query.tagsAllOf,
|
|
||||||
filter: query.filter,
|
|
||||||
nsfw: buildNSFWFilter(res, query.nsfw),
|
nsfw: buildNSFWFilter(res, query.nsfw),
|
||||||
withFiles: false,
|
withFiles: false,
|
||||||
videoChannelId: videoChannelInstance.id,
|
videoChannelId: videoChannelInstance.id,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
import toInt from 'validator/lib/toInt'
|
import toInt from 'validator/lib/toInt'
|
||||||
|
import { pickCommonVideoQuery } from '@server/helpers/query'
|
||||||
import { doJSONRequest } from '@server/helpers/requests'
|
import { doJSONRequest } from '@server/helpers/requests'
|
||||||
import { LiveManager } from '@server/lib/live'
|
import { LiveManager } from '@server/lib/live'
|
||||||
import { openapiOperationDoc } from '@server/middlewares/doc'
|
import { openapiOperationDoc } from '@server/middlewares/doc'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { MVideoAccountLight } from '@server/types/models'
|
import { MVideoAccountLight } from '@server/types/models'
|
||||||
import { VideosCommonQuery } from '../../../../shared'
|
|
||||||
import { HttpStatusCode } from '../../../../shared/models'
|
import { HttpStatusCode } from '../../../../shared/models'
|
||||||
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
|
import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../helpers/audit-logger'
|
||||||
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
|
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
|
||||||
|
@ -211,22 +211,14 @@ async function getVideoFileMetadata (req: express.Request, res: express.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listVideos (req: express.Request, res: express.Response) {
|
async function listVideos (req: express.Request, res: express.Response) {
|
||||||
const query = req.query as VideosCommonQuery
|
const query = pickCommonVideoQuery(req.query)
|
||||||
const countVideos = getCountVideos(req)
|
const countVideos = getCountVideos(req)
|
||||||
|
|
||||||
const apiOptions = await Hooks.wrapObject({
|
const apiOptions = await Hooks.wrapObject({
|
||||||
start: query.start,
|
...query,
|
||||||
count: query.count,
|
|
||||||
sort: query.sort,
|
|
||||||
includeLocalVideos: true,
|
includeLocalVideos: true,
|
||||||
categoryOneOf: query.categoryOneOf,
|
|
||||||
licenceOneOf: query.licenceOneOf,
|
|
||||||
languageOneOf: query.languageOneOf,
|
|
||||||
tagsOneOf: query.tagsOneOf,
|
|
||||||
tagsAllOf: query.tagsAllOf,
|
|
||||||
nsfw: buildNSFWFilter(res, query.nsfw),
|
nsfw: buildNSFWFilter(res, query.nsfw),
|
||||||
isLive: query.isLive,
|
|
||||||
filter: query.filter,
|
|
||||||
withFiles: false,
|
withFiles: false,
|
||||||
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
|
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
|
||||||
countVideos
|
countVideos
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { pick } from '@shared/core-utils'
|
||||||
|
import {
|
||||||
|
VideoChannelsSearchQueryAfterSanitize,
|
||||||
|
VideoPlaylistsSearchQueryAfterSanitize,
|
||||||
|
VideosCommonQueryAfterSanitize,
|
||||||
|
VideosSearchQueryAfterSanitize
|
||||||
|
} from '@shared/models'
|
||||||
|
|
||||||
|
function pickCommonVideoQuery (query: VideosCommonQueryAfterSanitize) {
|
||||||
|
return pick(query, [
|
||||||
|
'start',
|
||||||
|
'count',
|
||||||
|
'sort',
|
||||||
|
'nsfw',
|
||||||
|
'isLive',
|
||||||
|
'categoryOneOf',
|
||||||
|
'licenceOneOf',
|
||||||
|
'languageOneOf',
|
||||||
|
'tagsOneOf',
|
||||||
|
'tagsAllOf',
|
||||||
|
'filter',
|
||||||
|
'skipCount'
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
function pickSearchVideoQuery (query: VideosSearchQueryAfterSanitize) {
|
||||||
|
return {
|
||||||
|
...pickCommonVideoQuery(query),
|
||||||
|
|
||||||
|
...pick(query, [
|
||||||
|
'searchTarget',
|
||||||
|
'search',
|
||||||
|
'host',
|
||||||
|
'startDate',
|
||||||
|
'endDate',
|
||||||
|
'originallyPublishedStartDate',
|
||||||
|
'originallyPublishedEndDate',
|
||||||
|
'durationMin',
|
||||||
|
'durationMax',
|
||||||
|
'uuids'
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pickSearchChannelQuery (query: VideoChannelsSearchQueryAfterSanitize) {
|
||||||
|
return pick(query, [
|
||||||
|
'searchTarget',
|
||||||
|
'search',
|
||||||
|
'start',
|
||||||
|
'count',
|
||||||
|
'sort',
|
||||||
|
'host',
|
||||||
|
'handles'
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
function pickSearchPlaylistQuery (query: VideoPlaylistsSearchQueryAfterSanitize) {
|
||||||
|
return pick(query, [
|
||||||
|
'searchTarget',
|
||||||
|
'search',
|
||||||
|
'start',
|
||||||
|
'count',
|
||||||
|
'sort',
|
||||||
|
'host',
|
||||||
|
'uuids'
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
pickCommonVideoQuery,
|
||||||
|
pickSearchVideoQuery,
|
||||||
|
pickSearchPlaylistQuery,
|
||||||
|
pickSearchChannelQuery
|
||||||
|
}
|
|
@ -1070,7 +1070,8 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
|
||||||
const trendingDays = options.sort.endsWith('trending')
|
const trendingDays = options.sort.endsWith('trending')
|
||||||
? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS
|
? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS
|
||||||
: undefined
|
: undefined
|
||||||
let trendingAlgorithm
|
|
||||||
|
let trendingAlgorithm: string
|
||||||
if (options.sort.endsWith('hot')) trendingAlgorithm = 'hot'
|
if (options.sort.endsWith('hot')) trendingAlgorithm = 'hot'
|
||||||
if (options.sort.endsWith('best')) trendingAlgorithm = 'best'
|
if (options.sort.endsWith('best')) trendingAlgorithm = 'best'
|
||||||
|
|
||||||
|
|
|
@ -211,6 +211,39 @@ describe('Test videos search', function () {
|
||||||
const search = { ...baseSearch, host: 'framatube.org' }
|
const search = { ...baseSearch, host: 'framatube.org' }
|
||||||
await check(search, true)
|
await check(search, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const goodUUID = '9c9de5e8-0a1e-484a-b099-e80766180a6d'
|
||||||
|
const goodShortUUID = 'kkGMgK9ZtnKfYAgnEtQxbv'
|
||||||
|
const badUUID = 'c29c5b77-4a04-493d-96a9-2e9267e308f0'
|
||||||
|
const badShortUUID = 'rP5RgUeX9XwTSrspCdkDej'
|
||||||
|
|
||||||
|
{
|
||||||
|
const uuidsMatrix = [
|
||||||
|
[ goodUUID ],
|
||||||
|
[ goodUUID, badShortUUID ],
|
||||||
|
[ badShortUUID, goodShortUUID ],
|
||||||
|
[ goodUUID, goodShortUUID ]
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const uuids of uuidsMatrix) {
|
||||||
|
const search = { ...baseSearch, uuids }
|
||||||
|
await check(search, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const uuidsMatrix = [
|
||||||
|
[ badUUID ],
|
||||||
|
[ badShortUUID ]
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const uuids of uuidsMatrix) {
|
||||||
|
const search = { ...baseSearch, uuids }
|
||||||
|
await check(search, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have a correct pagination', async function () {
|
it('Should have a correct pagination', async function () {
|
||||||
|
@ -315,15 +348,6 @@ describe('Test videos search', function () {
|
||||||
|
|
||||||
describe('Playlists search', async function () {
|
describe('Playlists search', async function () {
|
||||||
|
|
||||||
it('Should make a simple search and not have results', async function () {
|
|
||||||
const body = await command.searchPlaylists({ search: 'a'.repeat(500) })
|
|
||||||
|
|
||||||
expect(body.total).to.equal(0)
|
|
||||||
expect(body.data).to.have.lengthOf(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('Should make a search and have results', async function () {
|
|
||||||
|
|
||||||
async function check (search: VideoPlaylistsSearchQuery, exists = true) {
|
async function check (search: VideoPlaylistsSearchQuery, exists = true) {
|
||||||
const body = await command.advancedPlaylistSearch({ search })
|
const body = await command.advancedPlaylistSearch({ search })
|
||||||
|
|
||||||
|
@ -363,9 +387,53 @@ describe('Test videos search', function () {
|
||||||
expect(videoPlaylist.videoChannel.avatar).to.exist
|
expect(videoPlaylist.videoChannel.avatar).to.exist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it('Should make a simple search and not have results', async function () {
|
||||||
|
const body = await command.searchPlaylists({ search: 'a'.repeat(500) })
|
||||||
|
|
||||||
|
expect(body.total).to.equal(0)
|
||||||
|
expect(body.data).to.have.lengthOf(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should make a search and have results', async function () {
|
||||||
await check({ search: 'E2E playlist', sort: '-match' }, true)
|
await check({ search: 'E2E playlist', sort: '-match' }, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should make host search and have appropriate results', async function () {
|
||||||
await check({ search: 'E2E playlist', host: 'example.com' }, false)
|
await check({ search: 'E2E playlist', host: 'example.com' }, false)
|
||||||
await check({ search: 'E2E playlist', host: 'peertube2.cpy.re' }, true)
|
await check({ search: 'E2E playlist', host: 'peertube2.cpy.re', sort: '-match' }, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should make a search by uuids and have appropriate results', async function () {
|
||||||
|
const goodUUID = '73804a40-da9a-40c2-b1eb-2c6d9eec8f0a'
|
||||||
|
const goodShortUUID = 'fgei1ws1oa6FCaJ2qZPG29'
|
||||||
|
const badUUID = 'c29c5b77-4a04-493d-96a9-2e9267e308f0'
|
||||||
|
const badShortUUID = 'rP5RgUeX9XwTSrspCdkDej'
|
||||||
|
|
||||||
|
{
|
||||||
|
const uuidsMatrix = [
|
||||||
|
[ goodUUID ],
|
||||||
|
[ goodUUID, badShortUUID ],
|
||||||
|
[ badShortUUID, goodShortUUID ],
|
||||||
|
[ goodUUID, goodShortUUID ]
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const uuids of uuidsMatrix) {
|
||||||
|
const search = { search: 'E2E playlist', sort: '-match', uuids }
|
||||||
|
await check(search, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const uuidsMatrix = [
|
||||||
|
[ badUUID ],
|
||||||
|
[ badShortUUID ]
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const uuids of uuidsMatrix) {
|
||||||
|
const search = { search: 'E2E playlist', sort: '-match', uuids }
|
||||||
|
await check(search, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have a correct pagination', async function () {
|
it('Should have a correct pagination', async function () {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
function pick <T extends object> (object: T, keys: (keyof T)[]) {
|
function pick <O extends object, K extends keyof O> (object: O, keys: K[]): Pick<O, K> {
|
||||||
const result: Partial<T> = {}
|
const result: any = {}
|
||||||
|
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
if (Object.prototype.hasOwnProperty.call(object, key)) {
|
||||||
|
|
|
@ -10,3 +10,9 @@ export interface VideoChannelsSearchQuery extends SearchTargetQuery {
|
||||||
host?: string
|
host?: string
|
||||||
handles?: string[]
|
handles?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VideoChannelsSearchQueryAfterSanitize extends VideoChannelsSearchQuery {
|
||||||
|
start: number
|
||||||
|
count: number
|
||||||
|
sort: string
|
||||||
|
}
|
||||||
|
|
|
@ -8,5 +8,13 @@ export interface VideoPlaylistsSearchQuery extends SearchTargetQuery {
|
||||||
sort?: string
|
sort?: string
|
||||||
|
|
||||||
host?: string
|
host?: string
|
||||||
|
|
||||||
|
// UUIDs or short UUIDs
|
||||||
uuids?: string[]
|
uuids?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VideoPlaylistsSearchQueryAfterSanitize extends VideoPlaylistsSearchQuery {
|
||||||
|
start: number
|
||||||
|
count: number
|
||||||
|
sort: string
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,12 @@ export interface VideosCommonQuery {
|
||||||
skipCount?: boolean
|
skipCount?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VideosCommonQueryAfterSanitize extends VideosCommonQuery {
|
||||||
|
start: number
|
||||||
|
count: number
|
||||||
|
sort: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface VideosWithSearchCommonQuery extends VideosCommonQuery {
|
export interface VideosWithSearchCommonQuery extends VideosCommonQuery {
|
||||||
search?: string
|
search?: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,12 @@ export interface VideosSearchQuery extends SearchTargetQuery, VideosCommonQuery
|
||||||
durationMin?: number // seconds
|
durationMin?: number // seconds
|
||||||
durationMax?: number // seconds
|
durationMax?: number // seconds
|
||||||
|
|
||||||
// UUIDs or short
|
// UUIDs or short UUIDs
|
||||||
uuids?: string[]
|
uuids?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VideosSearchQueryAfterSanitize extends VideosSearchQuery {
|
||||||
|
start: number
|
||||||
|
count: number
|
||||||
|
sort: string
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue