1
0
Fork 0

Add ability to skip count query

This commit is contained in:
Chocobozzz 2020-01-08 14:15:16 +01:00
parent ddc07312b0
commit fe98765624
No known key found for this signature in database
GPG key ID: 583A612D890159BE
13 changed files with 55 additions and 20 deletions

View file

@ -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))

View file

@ -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())
} }

View file

@ -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))

View file

@ -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))

View file

@ -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(

View file

@ -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: [
{ {

View file

@ -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
} }

View file

@ -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 })

View file

@ -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: {

View file

@ -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
// --------------------------------------------------------------- // ---------------------------------------------------------------

View file

@ -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 } })
}) })
}) })

View file

@ -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')

View file

@ -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)