Add ability to skip count query
This commit is contained in:
parent
ddc07312b0
commit
fe98765624
13 changed files with 55 additions and 20 deletions
|
@ -22,7 +22,7 @@ import {
|
||||||
import { AccountModel } from '../../models/account/account'
|
import { AccountModel } from '../../models/account/account'
|
||||||
import { AccountVideoRateModel } from '../../models/account/account-video-rate'
|
import { AccountVideoRateModel } from '../../models/account/account-video-rate'
|
||||||
import { VideoModel } from '../../models/video/video'
|
import { VideoModel } from '../../models/video/video'
|
||||||
import { buildNSFWFilter, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
|
import { buildNSFWFilter, isUserAbleToSearchRemoteURI, getCountVideos } from '../../helpers/express-utils'
|
||||||
import { VideoChannelModel } from '../../models/video/video-channel'
|
import { VideoChannelModel } from '../../models/video/video-channel'
|
||||||
import { JobQueue } from '../../lib/job-queue'
|
import { JobQueue } from '../../lib/job-queue'
|
||||||
import { logger } from '../../helpers/logger'
|
import { logger } from '../../helpers/logger'
|
||||||
|
@ -155,6 +155,7 @@ async function listAccountPlaylists (req: express.Request, res: express.Response
|
||||||
async function listAccountVideos (req: express.Request, res: express.Response) {
|
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 resultList = await VideoModel.listForApi({
|
const resultList = await VideoModel.listForApi({
|
||||||
followerActorId,
|
followerActorId,
|
||||||
|
@ -171,7 +172,8 @@ async function listAccountVideos (req: express.Request, res: express.Response) {
|
||||||
nsfw: buildNSFWFilter(res, req.query.nsfw),
|
nsfw: buildNSFWFilter(res, req.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
|
||||||
})
|
})
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
|
|
|
@ -98,10 +98,11 @@ async function getVideos (
|
||||||
sort: '-createdAt',
|
sort: '-createdAt',
|
||||||
includeLocalVideos: true,
|
includeLocalVideos: true,
|
||||||
nsfw: buildNSFWFilter(res),
|
nsfw: buildNSFWFilter(res),
|
||||||
withFiles: false
|
withFiles: false,
|
||||||
|
countVideos: false
|
||||||
}, where)
|
}, where)
|
||||||
|
|
||||||
const { data } = await VideoModel.listForApi(query, false)
|
const { data } = await VideoModel.listForApi(query)
|
||||||
|
|
||||||
return data.map(d => d.toFormattedJSON())
|
return data.map(d => d.toFormattedJSON())
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
} from '../../../middlewares'
|
} from '../../../middlewares'
|
||||||
import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators'
|
import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators'
|
||||||
import { VideoModel } from '../../../models/video/video'
|
import { VideoModel } from '../../../models/video/video'
|
||||||
import { buildNSFWFilter } from '../../../helpers/express-utils'
|
import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils'
|
||||||
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
|
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
|
||||||
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
||||||
import { JobQueue } from '../../../lib/job-queue'
|
import { JobQueue } from '../../../lib/job-queue'
|
||||||
|
@ -149,6 +149,8 @@ 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 resultList = await VideoModel.listForApi({
|
const resultList = await VideoModel.listForApi({
|
||||||
start: req.query.start,
|
start: req.query.start,
|
||||||
count: req.query.count,
|
count: req.query.count,
|
||||||
|
@ -163,7 +165,8 @@ async function getUserSubscriptionVideos (req: express.Request, res: express.Res
|
||||||
filter: req.query.filter as VideoFilter,
|
filter: req.query.filter as VideoFilter,
|
||||||
withFiles: false,
|
withFiles: false,
|
||||||
followerActorId: user.Account.Actor.id,
|
followerActorId: user.Account.Actor.id,
|
||||||
user
|
user,
|
||||||
|
countVideos
|
||||||
})
|
})
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { videoChannelsNameWithHostValidator, videosSortValidator } from '../../m
|
||||||
import { sendUpdateActor } from '../../lib/activitypub/send'
|
import { sendUpdateActor } from '../../lib/activitypub/send'
|
||||||
import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
|
import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
|
||||||
import { createLocalVideoChannel, federateAllVideosOfChannel } from '../../lib/video-channel'
|
import { createLocalVideoChannel, federateAllVideosOfChannel } from '../../lib/video-channel'
|
||||||
import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
|
import { buildNSFWFilter, createReqFiles, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
|
||||||
import { setAsyncActorKeys } from '../../lib/activitypub'
|
import { setAsyncActorKeys } from '../../lib/activitypub'
|
||||||
import { AccountModel } from '../../models/account/account'
|
import { AccountModel } from '../../models/account/account'
|
||||||
import { MIMETYPES } from '../../initializers/constants'
|
import { MIMETYPES } from '../../initializers/constants'
|
||||||
|
@ -256,6 +256,7 @@ async function listVideoChannelPlaylists (req: express.Request, res: express.Res
|
||||||
async function listVideoChannelVideos (req: express.Request, res: express.Response) {
|
async function listVideoChannelVideos (req: express.Request, res: express.Response) {
|
||||||
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 resultList = await VideoModel.listForApi({
|
const resultList = await VideoModel.listForApi({
|
||||||
followerActorId,
|
followerActorId,
|
||||||
|
@ -272,7 +273,8 @@ async function listVideoChannelVideos (req: express.Request, res: express.Respon
|
||||||
nsfw: buildNSFWFilter(res, req.query.nsfw),
|
nsfw: buildNSFWFilter(res, req.query.nsfw),
|
||||||
withFiles: false,
|
withFiles: false,
|
||||||
videoChannelId: videoChannelInstance.id,
|
videoChannelId: videoChannelInstance.id,
|
||||||
user: res.locals.oauth ? res.locals.oauth.token.User : undefined
|
user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
|
||||||
|
countVideos
|
||||||
})
|
})
|
||||||
|
|
||||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||||
|
|
|
@ -48,7 +48,7 @@ import { videoCommentRouter } from './comment'
|
||||||
import { rateVideoRouter } from './rate'
|
import { rateVideoRouter } from './rate'
|
||||||
import { ownershipVideoRouter } from './ownership'
|
import { ownershipVideoRouter } from './ownership'
|
||||||
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
|
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
|
||||||
import { buildNSFWFilter, createReqFiles } from '../../../helpers/express-utils'
|
import { buildNSFWFilter, createReqFiles, getCountVideos } from '../../../helpers/express-utils'
|
||||||
import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
|
import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
|
||||||
import { videoCaptionsRouter } from './captions'
|
import { videoCaptionsRouter } from './captions'
|
||||||
import { videoImportsRouter } from './import'
|
import { videoImportsRouter } from './import'
|
||||||
|
@ -495,6 +495,8 @@ async function getVideoDescription (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 countVideos = getCountVideos(req)
|
||||||
|
|
||||||
const apiOptions = await Hooks.wrapObject({
|
const apiOptions = await Hooks.wrapObject({
|
||||||
start: req.query.start,
|
start: req.query.start,
|
||||||
count: req.query.count,
|
count: req.query.count,
|
||||||
|
@ -508,7 +510,8 @@ async function listVideos (req: express.Request, res: express.Response) {
|
||||||
nsfw: buildNSFWFilter(res, req.query.nsfw),
|
nsfw: buildNSFWFilter(res, req.query.nsfw),
|
||||||
filter: req.query.filter as VideoFilter,
|
filter: req.query.filter as VideoFilter,
|
||||||
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
|
||||||
}, 'filter:api.videos.list.params')
|
}, 'filter:api.videos.list.params')
|
||||||
|
|
||||||
const resultList = await Hooks.wrapPromiseFun(
|
const resultList = await Hooks.wrapPromiseFun(
|
||||||
|
|
|
@ -61,17 +61,18 @@ async function getSitemapAccountUrls () {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSitemapLocalVideoUrls () {
|
async function getSitemapLocalVideoUrls () {
|
||||||
const resultList = await VideoModel.listForApi({
|
const { data } = await VideoModel.listForApi({
|
||||||
start: 0,
|
start: 0,
|
||||||
count: undefined,
|
count: undefined,
|
||||||
sort: 'createdAt',
|
sort: 'createdAt',
|
||||||
includeLocalVideos: true,
|
includeLocalVideos: true,
|
||||||
nsfw: buildNSFWFilter(),
|
nsfw: buildNSFWFilter(),
|
||||||
filter: 'local',
|
filter: 'local',
|
||||||
withFiles: false
|
withFiles: false,
|
||||||
|
countVideos: false
|
||||||
})
|
})
|
||||||
|
|
||||||
return resultList.data.map(v => ({
|
return data.map(v => ({
|
||||||
url: WEBSERVER.URL + '/videos/watch/' + v.uuid,
|
url: WEBSERVER.URL + '/videos/watch/' + v.uuid,
|
||||||
video: [
|
video: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -117,6 +117,10 @@ function isUserAbleToSearchRemoteURI (res: express.Response) {
|
||||||
(CONFIG.SEARCH.REMOTE_URI.USERS === true && user !== undefined)
|
(CONFIG.SEARCH.REMOTE_URI.USERS === true && user !== undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCountVideos (req: express.Request) {
|
||||||
|
return req.query.skipCount !== true
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -125,5 +129,6 @@ export {
|
||||||
isUserAbleToSearchRemoteURI,
|
isUserAbleToSearchRemoteURI,
|
||||||
badRequest,
|
badRequest,
|
||||||
createReqFiles,
|
createReqFiles,
|
||||||
cleanUpReqFiles
|
cleanUpReqFiles,
|
||||||
|
getCountVideos
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,6 +381,10 @@ const commonVideosFiltersValidator = [
|
||||||
query('filter')
|
query('filter')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isVideoFilterValid).withMessage('Should have a valid filter attribute'),
|
.custom(isVideoFilterValid).withMessage('Should have a valid filter attribute'),
|
||||||
|
query('skipCount')
|
||||||
|
.optional()
|
||||||
|
.customSanitizer(toBooleanOrNull)
|
||||||
|
.custom(isBooleanValid).withMessage('Should have a valid skip count boolean'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
logger.debug('Checking commons video filters query', { parameters: req.query })
|
logger.debug('Checking commons video filters query', { parameters: req.query })
|
||||||
|
|
|
@ -1284,8 +1284,9 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
videoPlaylistId?: number,
|
videoPlaylistId?: number,
|
||||||
trendingDays?: number,
|
trendingDays?: number,
|
||||||
user?: MUserAccountId,
|
user?: MUserAccountId,
|
||||||
historyOfUser?: MUserId
|
historyOfUser?: MUserId,
|
||||||
}, countVideos = true) {
|
countVideos?: boolean
|
||||||
|
}) {
|
||||||
if (options.filter && options.filter === 'all-local' && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) {
|
if (options.filter && options.filter === 'all-local' && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) {
|
||||||
throw new Error('Try to filter all-local but no user has not the see all videos right')
|
throw new Error('Try to filter all-local but no user has not the see all videos right')
|
||||||
}
|
}
|
||||||
|
@ -1328,7 +1329,7 @@ export class VideoModel extends Model<VideoModel> {
|
||||||
trendingDays
|
trendingDays
|
||||||
}
|
}
|
||||||
|
|
||||||
return VideoModel.getAvailableForApi(query, queryOptions, countVideos)
|
return VideoModel.getAvailableForApi(query, queryOptions, options.countVideos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async searchAndPopulateAccountAndServer (options: {
|
static async searchAndPopulateAccountAndServer (options: {
|
||||||
|
|
|
@ -40,7 +40,6 @@ describe('Test videos filters', function () {
|
||||||
let server: ServerInfo
|
let server: ServerInfo
|
||||||
let userAccessToken: string
|
let userAccessToken: string
|
||||||
let moderatorAccessToken: string
|
let moderatorAccessToken: string
|
||||||
let playlistUUID: string
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,12 @@ describe('Test videos API validator', function () {
|
||||||
await checkBadSortPagination(server.url, path)
|
await checkBadSortPagination(server.url, path)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad skipVideos query', async function () {
|
||||||
|
await makeGetRequest({ url: server.url, path, statusCodeExpected: 200, query: { skipCount: 'toto' } })
|
||||||
|
})
|
||||||
|
|
||||||
it('Should success with the correct parameters', async function () {
|
it('Should success with the correct parameters', async function () {
|
||||||
await makeGetRequest({ url: server.url, path, statusCodeExpected: 200 })
|
await makeGetRequest({ url: server.url, path, statusCodeExpected: 200, query: { skipCount: false } })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -322,6 +322,15 @@ describe('Test a single server', function () {
|
||||||
expect(videos[0].name).to.equal(videosListBase[5].name)
|
expect(videos[0].name).to.equal(videosListBase[5].name)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should not have the total field', async function () {
|
||||||
|
const res = await getVideosListPagination(server.url, 5, 6, 'name', true)
|
||||||
|
|
||||||
|
const videos = res.body.data
|
||||||
|
expect(res.body.total).to.not.exist
|
||||||
|
expect(videos.length).to.equal(1)
|
||||||
|
expect(videos[0].name).to.equal(videosListBase[5].name)
|
||||||
|
})
|
||||||
|
|
||||||
it('Should list and sort by name in descending order', async function () {
|
it('Should list and sort by name in descending order', async function () {
|
||||||
const res = await getVideosListSort(server.url, '-name')
|
const res = await getVideosListSort(server.url, '-name')
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ function getPlaylistVideos (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVideosListPagination (url: string, start: number, count: number, sort?: string) {
|
function getVideosListPagination (url: string, start: number, count: number, sort?: string, skipCount?: boolean) {
|
||||||
const path = '/api/v1/videos'
|
const path = '/api/v1/videos'
|
||||||
|
|
||||||
const req = request(url)
|
const req = request(url)
|
||||||
|
@ -257,6 +257,7 @@ function getVideosListPagination (url: string, start: number, count: number, sor
|
||||||
.query({ count: count })
|
.query({ count: count })
|
||||||
|
|
||||||
if (sort) req.query({ sort })
|
if (sort) req.query({ sort })
|
||||||
|
if (skipCount) req.query({ skipCount })
|
||||||
|
|
||||||
return req.set('Accept', 'application/json')
|
return req.set('Accept', 'application/json')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
Loading…
Add table
Reference in a new issue