diff options
-rw-r--r-- | server/middlewares/validators/videos/video-channels.ts | 17 | ||||
-rw-r--r-- | server/models/video/video-channel.ts | 26 | ||||
-rw-r--r-- | server/tests/api/videos/video-channels.ts | 1 |
3 files changed, 22 insertions, 22 deletions
diff --git a/server/middlewares/validators/videos/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts index 882fb2b84..6604ae6a8 100644 --- a/server/middlewares/validators/videos/video-channels.ts +++ b/server/middlewares/validators/videos/video-channels.ts | |||
@@ -1,20 +1,20 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param, query } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { VIDEO_CHANNELS } from '@server/initializers/constants' | ||
4 | import { MChannelAccountDefault, MUser } from '@server/typings/models' | ||
3 | import { UserRight } from '../../../../shared' | 5 | import { UserRight } from '../../../../shared' |
6 | import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor' | ||
7 | import { isBooleanValid, toBooleanOrNull } from '../../../helpers/custom-validators/misc' | ||
4 | import { | 8 | import { |
5 | isVideoChannelDescriptionValid, | 9 | isVideoChannelDescriptionValid, |
6 | isVideoChannelNameValid, | 10 | isVideoChannelNameValid, |
7 | isVideoChannelSupportValid | 11 | isVideoChannelSupportValid |
8 | } from '../../../helpers/custom-validators/video-channels' | 12 | } from '../../../helpers/custom-validators/video-channels' |
9 | import { logger } from '../../../helpers/logger' | 13 | import { logger } from '../../../helpers/logger' |
14 | import { doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../../../helpers/middlewares' | ||
15 | import { ActorModel } from '../../../models/activitypub/actor' | ||
10 | import { VideoChannelModel } from '../../../models/video/video-channel' | 16 | import { VideoChannelModel } from '../../../models/video/video-channel' |
11 | import { areValidationErrors } from '../utils' | 17 | import { areValidationErrors } from '../utils' |
12 | import { isActorPreferredUsernameValid } from '../../../helpers/custom-validators/activitypub/actor' | ||
13 | import { ActorModel } from '../../../models/activitypub/actor' | ||
14 | import { isBooleanValid } from '../../../helpers/custom-validators/misc' | ||
15 | import { doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } from '../../../helpers/middlewares' | ||
16 | import { MChannelAccountDefault, MUser } from '@server/typings/models' | ||
17 | import { VIDEO_CHANNELS } from '@server/initializers/constants' | ||
18 | 18 | ||
19 | const videoChannelsAddValidator = [ | 19 | const videoChannelsAddValidator = [ |
20 | body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'), | 20 | body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'), |
@@ -129,7 +129,10 @@ const localVideoChannelValidator = [ | |||
129 | ] | 129 | ] |
130 | 130 | ||
131 | const videoChannelStatsValidator = [ | 131 | const videoChannelStatsValidator = [ |
132 | query('withStats').optional().isBoolean().withMessage('Should have a valid stats flag'), | 132 | query('withStats') |
133 | .optional() | ||
134 | .customSanitizer(toBooleanOrNull) | ||
135 | .custom(isBooleanValid).withMessage('Should have a valid stats flag'), | ||
133 | 136 | ||
134 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | 137 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
135 | if (areValidationErrors(req, res)) return | 138 | if (areValidationErrors(req, res)) return |
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 642e129ff..b5bcbdc65 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts | |||
@@ -181,20 +181,16 @@ export type SummaryOptions = { | |||
181 | 'days AS ( ' + | 181 | 'days AS ( ' + |
182 | `SELECT generate_series(date_trunc('day', now()) - '${daysPrior} day'::interval, ` + | 182 | `SELECT generate_series(date_trunc('day', now()) - '${daysPrior} day'::interval, ` + |
183 | `date_trunc('day', now()), '1 day'::interval) AS day ` + | 183 | `date_trunc('day', now()), '1 day'::interval) AS day ` + |
184 | '), ' + | ||
185 | 'views AS ( ' + | ||
186 | 'SELECT v.* ' + | ||
187 | 'FROM "videoView" AS v ' + | ||
188 | 'INNER JOIN "video" ON "video"."id" = v."videoId" ' + | ||
189 | 'WHERE "video"."channelId" = "VideoChannelModel"."id" ' + | ||
190 | ') ' + | 184 | ') ' + |
191 | 'SELECT days.day AS day, ' + | 185 | 'SELECT days.day AS day, COALESCE(SUM("videoView".views), 0) AS views ' + |
192 | 'COALESCE(SUM(views.views), 0) AS views ' + | 186 | 'FROM days ' + |
193 | 'FROM days ' + | 187 | 'LEFT JOIN (' + |
194 | `LEFT JOIN views ON date_trunc('day', "views"."startDate") = date_trunc('day', days.day) ` + | 188 | '"videoView" INNER JOIN "video" ON "videoView"."videoId" = "video"."id" ' + |
195 | 'GROUP BY day ' + | 189 | 'AND "video"."channelId" = "VideoChannelModel"."id"' + |
196 | 'ORDER BY day ' + | 190 | `) ON date_trunc('day', "videoView"."startDate") = date_trunc('day', days.day) ` + |
197 | ') t' + | 191 | 'GROUP BY day ' + |
192 | 'ORDER BY day ' + | ||
193 | ') t' + | ||
198 | ')' | 194 | ')' |
199 | ), | 195 | ), |
200 | 'viewsPerDay' | 196 | 'viewsPerDay' |
@@ -413,7 +409,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
413 | 409 | ||
414 | const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR ] | 410 | const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR ] |
415 | 411 | ||
416 | if (options.withStats) { | 412 | if (options.withStats === true) { |
417 | scopes.push({ | 413 | scopes.push({ |
418 | method: [ ScopeNames.WITH_STATS, { daysPrior: 30 } as AvailableWithStatsOptions ] | 414 | method: [ ScopeNames.WITH_STATS, { daysPrior: 30 } as AvailableWithStatsOptions ] |
419 | }) | 415 | }) |
@@ -560,7 +556,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> { | |||
560 | createdAt: this.createdAt, | 556 | createdAt: this.createdAt, |
561 | updatedAt: this.updatedAt, | 557 | updatedAt: this.updatedAt, |
562 | ownerAccount: undefined, | 558 | ownerAccount: undefined, |
563 | viewsPerDay: viewsPerDay !== undefined | 559 | viewsPerDay: viewsPerDay |
564 | ? viewsPerDay.split(',').map(v => { | 560 | ? viewsPerDay.split(',').map(v => { |
565 | const o = v.split('|') | 561 | const o = v.split('|') |
566 | return { | 562 | return { |
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts index 876a6ab66..89026aba7 100644 --- a/server/tests/api/videos/video-channels.ts +++ b/server/tests/api/videos/video-channels.ts | |||
@@ -366,6 +366,7 @@ describe('Test video channels', function () { | |||
366 | }) | 366 | }) |
367 | 367 | ||
368 | it('Should report correct channel statistics', async function () { | 368 | it('Should report correct channel statistics', async function () { |
369 | this.timeout(10000) | ||
369 | 370 | ||
370 | { | 371 | { |
371 | const res = await getAccountVideoChannelsList({ | 372 | const res = await getAccountVideoChannelsList({ |