diff options
author | Chocobozzz <me@florianbigard.com> | 2018-09-03 18:05:12 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-09-04 08:58:33 +0200 |
commit | 8ea6f49ad7b6deb63e31dffc2acf55cbc479da60 (patch) | |
tree | ba22c760efa8ccbb3cad7495fdb4aa3bc55a574e /server/models/video/video.ts | |
parent | 74d63469355bad731cdd32defdc85913df3cbd5c (diff) | |
download | PeerTube-8ea6f49ad7b6deb63e31dffc2acf55cbc479da60.tar.gz PeerTube-8ea6f49ad7b6deb63e31dffc2acf55cbc479da60.tar.zst PeerTube-8ea6f49ad7b6deb63e31dffc2acf55cbc479da60.zip |
Fix trending videos count
Diffstat (limited to 'server/models/video/video.ts')
-rw-r--r-- | server/models/video/video.ts | 198 |
1 files changed, 105 insertions, 93 deletions
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 6fb5ececa..86316653f 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -113,7 +113,7 @@ const indexes: Sequelize.DefineIndexesOptions[] = [ | |||
113 | unique: true | 113 | unique: true |
114 | }, | 114 | }, |
115 | { | 115 | { |
116 | fields: [ 'url'], | 116 | fields: [ 'url' ], |
117 | unique: true | 117 | unique: true |
118 | } | 118 | } |
119 | ] | 119 | ] |
@@ -150,7 +150,7 @@ type AvailableForListIDsOptions = { | |||
150 | } | 150 | } |
151 | 151 | ||
152 | @Scopes({ | 152 | @Scopes({ |
153 | [ScopeNames.FOR_API]: (options: ForAPIOptions) => { | 153 | [ ScopeNames.FOR_API ]: (options: ForAPIOptions) => { |
154 | const accountInclude = { | 154 | const accountInclude = { |
155 | attributes: [ 'id', 'name' ], | 155 | attributes: [ 'id', 'name' ], |
156 | model: AccountModel.unscoped(), | 156 | model: AccountModel.unscoped(), |
@@ -203,7 +203,7 @@ type AvailableForListIDsOptions = { | |||
203 | const query: IFindOptions<VideoModel> = { | 203 | const query: IFindOptions<VideoModel> = { |
204 | where: { | 204 | where: { |
205 | id: { | 205 | id: { |
206 | [Sequelize.Op.any]: options.ids | 206 | [ Sequelize.Op.any ]: options.ids |
207 | } | 207 | } |
208 | }, | 208 | }, |
209 | include: [ videoChannelInclude ] | 209 | include: [ videoChannelInclude ] |
@@ -218,12 +218,12 @@ type AvailableForListIDsOptions = { | |||
218 | 218 | ||
219 | return query | 219 | return query |
220 | }, | 220 | }, |
221 | [ScopeNames.AVAILABLE_FOR_LIST_IDS]: (options: AvailableForListIDsOptions) => { | 221 | [ ScopeNames.AVAILABLE_FOR_LIST_IDS ]: (options: AvailableForListIDsOptions) => { |
222 | const query: IFindOptions<VideoModel> = { | 222 | const query: IFindOptions<VideoModel> = { |
223 | attributes: [ 'id' ], | 223 | attributes: [ 'id' ], |
224 | where: { | 224 | where: { |
225 | id: { | 225 | id: { |
226 | [Sequelize.Op.and]: [ | 226 | [ Sequelize.Op.and ]: [ |
227 | { | 227 | { |
228 | [ Sequelize.Op.notIn ]: Sequelize.literal( | 228 | [ Sequelize.Op.notIn ]: Sequelize.literal( |
229 | '(SELECT "videoBlacklist"."videoId" FROM "videoBlacklist")' | 229 | '(SELECT "videoBlacklist"."videoId" FROM "videoBlacklist")' |
@@ -246,7 +246,7 @@ type AvailableForListIDsOptions = { | |||
246 | } | 246 | } |
247 | ] | 247 | ] |
248 | }, | 248 | }, |
249 | include: [ ] | 249 | include: [] |
250 | } | 250 | } |
251 | 251 | ||
252 | if (options.filter || options.accountId || options.videoChannelId) { | 252 | if (options.filter || options.accountId || options.videoChannelId) { |
@@ -303,27 +303,27 @@ type AvailableForListIDsOptions = { | |||
303 | 303 | ||
304 | // Force actorId to be a number to avoid SQL injections | 304 | // Force actorId to be a number to avoid SQL injections |
305 | const actorIdNumber = parseInt(options.actorId.toString(), 10) | 305 | const actorIdNumber = parseInt(options.actorId.toString(), 10) |
306 | query.where['id'][Sequelize.Op.and].push({ | 306 | query.where[ 'id' ][ Sequelize.Op.and ].push({ |
307 | [ Sequelize.Op.in ]: Sequelize.literal( | 307 | [ Sequelize.Op.in ]: Sequelize.literal( |
308 | '(' + | 308 | '(' + |
309 | 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + | 309 | 'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' + |
310 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + | 310 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' + |
311 | 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + | 311 | 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + |
312 | ' UNION ALL ' + | 312 | ' UNION ALL ' + |
313 | 'SELECT "video"."id" AS "id" FROM "video" ' + | 313 | 'SELECT "video"."id" AS "id" FROM "video" ' + |
314 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + | 314 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + |
315 | 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + | 315 | 'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' + |
316 | 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + | 316 | 'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' + |
317 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + | 317 | 'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' + |
318 | 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + | 318 | 'WHERE "actorFollow"."actorId" = ' + actorIdNumber + |
319 | localVideosReq + | 319 | localVideosReq + |
320 | ')' | 320 | ')' |
321 | ) | 321 | ) |
322 | }) | 322 | }) |
323 | } | 323 | } |
324 | 324 | ||
325 | if (options.withFiles === true) { | 325 | if (options.withFiles === true) { |
326 | query.where['id'][Sequelize.Op.and].push({ | 326 | query.where[ 'id' ][ Sequelize.Op.and ].push({ |
327 | [ Sequelize.Op.in ]: Sequelize.literal( | 327 | [ Sequelize.Op.in ]: Sequelize.literal( |
328 | '(SELECT "videoId" FROM "videoFile")' | 328 | '(SELECT "videoId" FROM "videoFile")' |
329 | ) | 329 | ) |
@@ -338,8 +338,8 @@ type AvailableForListIDsOptions = { | |||
338 | } | 338 | } |
339 | 339 | ||
340 | if (options.tagsOneOf) { | 340 | if (options.tagsOneOf) { |
341 | query.where['id'][Sequelize.Op.and].push({ | 341 | query.where[ 'id' ][ Sequelize.Op.and ].push({ |
342 | [Sequelize.Op.in]: Sequelize.literal( | 342 | [ Sequelize.Op.in ]: Sequelize.literal( |
343 | '(' + | 343 | '(' + |
344 | 'SELECT "videoId" FROM "videoTag" ' + | 344 | 'SELECT "videoId" FROM "videoTag" ' + |
345 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 345 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
@@ -350,8 +350,8 @@ type AvailableForListIDsOptions = { | |||
350 | } | 350 | } |
351 | 351 | ||
352 | if (options.tagsAllOf) { | 352 | if (options.tagsAllOf) { |
353 | query.where['id'][Sequelize.Op.and].push({ | 353 | query.where[ 'id' ][ Sequelize.Op.and ].push({ |
354 | [Sequelize.Op.in]: Sequelize.literal( | 354 | [ Sequelize.Op.in ]: Sequelize.literal( |
355 | '(' + | 355 | '(' + |
356 | 'SELECT "videoId" FROM "videoTag" ' + | 356 | 'SELECT "videoId" FROM "videoTag" ' + |
357 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 357 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
@@ -364,24 +364,24 @@ type AvailableForListIDsOptions = { | |||
364 | } | 364 | } |
365 | 365 | ||
366 | if (options.nsfw === true || options.nsfw === false) { | 366 | if (options.nsfw === true || options.nsfw === false) { |
367 | query.where['nsfw'] = options.nsfw | 367 | query.where[ 'nsfw' ] = options.nsfw |
368 | } | 368 | } |
369 | 369 | ||
370 | if (options.categoryOneOf) { | 370 | if (options.categoryOneOf) { |
371 | query.where['category'] = { | 371 | query.where[ 'category' ] = { |
372 | [Sequelize.Op.or]: options.categoryOneOf | 372 | [ Sequelize.Op.or ]: options.categoryOneOf |
373 | } | 373 | } |
374 | } | 374 | } |
375 | 375 | ||
376 | if (options.licenceOneOf) { | 376 | if (options.licenceOneOf) { |
377 | query.where['licence'] = { | 377 | query.where[ 'licence' ] = { |
378 | [Sequelize.Op.or]: options.licenceOneOf | 378 | [ Sequelize.Op.or ]: options.licenceOneOf |
379 | } | 379 | } |
380 | } | 380 | } |
381 | 381 | ||
382 | if (options.languageOneOf) { | 382 | if (options.languageOneOf) { |
383 | query.where['language'] = { | 383 | query.where[ 'language' ] = { |
384 | [Sequelize.Op.or]: options.languageOneOf | 384 | [ Sequelize.Op.or ]: options.languageOneOf |
385 | } | 385 | } |
386 | } | 386 | } |
387 | 387 | ||
@@ -402,7 +402,7 @@ type AvailableForListIDsOptions = { | |||
402 | 402 | ||
403 | return query | 403 | return query |
404 | }, | 404 | }, |
405 | [ScopeNames.WITH_ACCOUNT_DETAILS]: { | 405 | [ ScopeNames.WITH_ACCOUNT_DETAILS ]: { |
406 | include: [ | 406 | include: [ |
407 | { | 407 | { |
408 | model: () => VideoChannelModel.unscoped(), | 408 | model: () => VideoChannelModel.unscoped(), |
@@ -454,10 +454,10 @@ type AvailableForListIDsOptions = { | |||
454 | } | 454 | } |
455 | ] | 455 | ] |
456 | }, | 456 | }, |
457 | [ScopeNames.WITH_TAGS]: { | 457 | [ ScopeNames.WITH_TAGS ]: { |
458 | include: [ () => TagModel ] | 458 | include: [ () => TagModel ] |
459 | }, | 459 | }, |
460 | [ScopeNames.WITH_BLACKLISTED]: { | 460 | [ ScopeNames.WITH_BLACKLISTED ]: { |
461 | include: [ | 461 | include: [ |
462 | { | 462 | { |
463 | attributes: [ 'id', 'reason' ], | 463 | attributes: [ 'id', 'reason' ], |
@@ -466,7 +466,7 @@ type AvailableForListIDsOptions = { | |||
466 | } | 466 | } |
467 | ] | 467 | ] |
468 | }, | 468 | }, |
469 | [ScopeNames.WITH_FILES]: { | 469 | [ ScopeNames.WITH_FILES ]: { |
470 | include: [ | 470 | include: [ |
471 | { | 471 | { |
472 | model: () => VideoFileModel.unscoped(), | 472 | model: () => VideoFileModel.unscoped(), |
@@ -474,7 +474,7 @@ type AvailableForListIDsOptions = { | |||
474 | } | 474 | } |
475 | ] | 475 | ] |
476 | }, | 476 | }, |
477 | [ScopeNames.WITH_SCHEDULED_UPDATE]: { | 477 | [ ScopeNames.WITH_SCHEDULED_UPDATE ]: { |
478 | include: [ | 478 | include: [ |
479 | { | 479 | { |
480 | model: () => ScheduleVideoUpdateModel.unscoped(), | 480 | model: () => ScheduleVideoUpdateModel.unscoped(), |
@@ -700,7 +700,7 @@ export class VideoModel extends Model<VideoModel> { | |||
700 | }, | 700 | }, |
701 | onDelete: 'cascade', | 701 | onDelete: 'cascade', |
702 | hooks: true, | 702 | hooks: true, |
703 | ['separate' as any]: true | 703 | [ 'separate' as any ]: true |
704 | }) | 704 | }) |
705 | VideoCaptions: VideoCaptionModel[] | 705 | VideoCaptions: VideoCaptionModel[] |
706 | 706 | ||
@@ -749,9 +749,9 @@ export class VideoModel extends Model<VideoModel> { | |||
749 | 749 | ||
750 | // Do not wait video deletion because we could be in a transaction | 750 | // Do not wait video deletion because we could be in a transaction |
751 | Promise.all(tasks) | 751 | Promise.all(tasks) |
752 | .catch(err => { | 752 | .catch(err => { |
753 | logger.error('Some errors when removing files of video %s in before destroy hook.', instance.uuid, { err }) | 753 | logger.error('Some errors when removing files of video %s in before destroy hook.', instance.uuid, { err }) |
754 | }) | 754 | }) |
755 | 755 | ||
756 | return undefined | 756 | return undefined |
757 | } | 757 | } |
@@ -783,9 +783,9 @@ export class VideoModel extends Model<VideoModel> { | |||
783 | order: getVideoSort('createdAt', [ 'Tags', 'name', 'ASC' ]), | 783 | order: getVideoSort('createdAt', [ 'Tags', 'name', 'ASC' ]), |
784 | where: { | 784 | where: { |
785 | id: { | 785 | id: { |
786 | [Sequelize.Op.in]: Sequelize.literal('(' + rawQuery + ')') | 786 | [ Sequelize.Op.in ]: Sequelize.literal('(' + rawQuery + ')') |
787 | }, | 787 | }, |
788 | [Sequelize.Op.or]: [ | 788 | [ Sequelize.Op.or ]: [ |
789 | { privacy: VideoPrivacy.PUBLIC }, | 789 | { privacy: VideoPrivacy.PUBLIC }, |
790 | { privacy: VideoPrivacy.UNLISTED } | 790 | { privacy: VideoPrivacy.UNLISTED } |
791 | ] | 791 | ] |
@@ -802,10 +802,10 @@ export class VideoModel extends Model<VideoModel> { | |||
802 | required: false, | 802 | required: false, |
803 | // We only want videos shared by this actor | 803 | // We only want videos shared by this actor |
804 | where: { | 804 | where: { |
805 | [Sequelize.Op.and]: [ | 805 | [ Sequelize.Op.and ]: [ |
806 | { | 806 | { |
807 | id: { | 807 | id: { |
808 | [Sequelize.Op.not]: null | 808 | [ Sequelize.Op.not ]: null |
809 | } | 809 | } |
810 | }, | 810 | }, |
811 | { | 811 | { |
@@ -856,8 +856,8 @@ export class VideoModel extends Model<VideoModel> { | |||
856 | // totals: totalVideos + totalVideoShares | 856 | // totals: totalVideos + totalVideoShares |
857 | let totalVideos = 0 | 857 | let totalVideos = 0 |
858 | let totalVideoShares = 0 | 858 | let totalVideoShares = 0 |
859 | if (totals[0]) totalVideos = parseInt(totals[0].total, 10) | 859 | if (totals[ 0 ]) totalVideos = parseInt(totals[ 0 ].total, 10) |
860 | if (totals[1]) totalVideoShares = parseInt(totals[1].total, 10) | 860 | if (totals[ 1 ]) totalVideoShares = parseInt(totals[ 1 ].total, 10) |
861 | 861 | ||
862 | const total = totalVideos + totalVideoShares | 862 | const total = totalVideos + totalVideoShares |
863 | return { | 863 | return { |
@@ -982,22 +982,22 @@ export class VideoModel extends Model<VideoModel> { | |||
982 | durationMin?: number // seconds | 982 | durationMin?: number // seconds |
983 | durationMax?: number // seconds | 983 | durationMax?: number // seconds |
984 | }) { | 984 | }) { |
985 | const whereAnd = [ ] | 985 | const whereAnd = [] |
986 | 986 | ||
987 | if (options.startDate || options.endDate) { | 987 | if (options.startDate || options.endDate) { |
988 | const publishedAtRange = { } | 988 | const publishedAtRange = {} |
989 | 989 | ||
990 | if (options.startDate) publishedAtRange[Sequelize.Op.gte] = options.startDate | 990 | if (options.startDate) publishedAtRange[ Sequelize.Op.gte ] = options.startDate |
991 | if (options.endDate) publishedAtRange[Sequelize.Op.lte] = options.endDate | 991 | if (options.endDate) publishedAtRange[ Sequelize.Op.lte ] = options.endDate |
992 | 992 | ||
993 | whereAnd.push({ publishedAt: publishedAtRange }) | 993 | whereAnd.push({ publishedAt: publishedAtRange }) |
994 | } | 994 | } |
995 | 995 | ||
996 | if (options.durationMin || options.durationMax) { | 996 | if (options.durationMin || options.durationMax) { |
997 | const durationRange = { } | 997 | const durationRange = {} |
998 | 998 | ||
999 | if (options.durationMin) durationRange[Sequelize.Op.gte] = options.durationMin | 999 | if (options.durationMin) durationRange[ Sequelize.Op.gte ] = options.durationMin |
1000 | if (options.durationMax) durationRange[Sequelize.Op.lte] = options.durationMax | 1000 | if (options.durationMax) durationRange[ Sequelize.Op.lte ] = options.durationMax |
1001 | 1001 | ||
1002 | whereAnd.push({ duration: durationRange }) | 1002 | whereAnd.push({ duration: durationRange }) |
1003 | } | 1003 | } |
@@ -1011,14 +1011,14 @@ export class VideoModel extends Model<VideoModel> { | |||
1011 | id: { | 1011 | id: { |
1012 | [ Sequelize.Op.in ]: Sequelize.literal( | 1012 | [ Sequelize.Op.in ]: Sequelize.literal( |
1013 | '(' + | 1013 | '(' + |
1014 | 'SELECT "video"."id" FROM "video" ' + | 1014 | 'SELECT "video"."id" FROM "video" ' + |
1015 | 'WHERE ' + | 1015 | 'WHERE ' + |
1016 | 'lower(immutable_unaccent("video"."name")) % lower(immutable_unaccent(' + escapedSearch + ')) OR ' + | 1016 | 'lower(immutable_unaccent("video"."name")) % lower(immutable_unaccent(' + escapedSearch + ')) OR ' + |
1017 | 'lower(immutable_unaccent("video"."name")) LIKE lower(immutable_unaccent(' + escapedLikeSearch + '))' + | 1017 | 'lower(immutable_unaccent("video"."name")) LIKE lower(immutable_unaccent(' + escapedLikeSearch + '))' + |
1018 | 'UNION ALL ' + | 1018 | 'UNION ALL ' + |
1019 | 'SELECT "video"."id" FROM "video" LEFT JOIN "videoTag" ON "videoTag"."videoId" = "video"."id" ' + | 1019 | 'SELECT "video"."id" FROM "video" LEFT JOIN "videoTag" ON "videoTag"."videoId" = "video"."id" ' + |
1020 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + | 1020 | 'INNER JOIN "tag" ON "tag"."id" = "videoTag"."tagId" ' + |
1021 | 'WHERE "tag"."name" = ' + escapedSearch + | 1021 | 'WHERE "tag"."name" = ' + escapedSearch + |
1022 | ')' | 1022 | ')' |
1023 | ) | 1023 | ) |
1024 | } | 1024 | } |
@@ -1167,11 +1167,11 @@ export class VideoModel extends Model<VideoModel> { | |||
1167 | limit: count, | 1167 | limit: count, |
1168 | group: field, | 1168 | group: field, |
1169 | having: Sequelize.where(Sequelize.fn('COUNT', Sequelize.col(field)), { | 1169 | having: Sequelize.where(Sequelize.fn('COUNT', Sequelize.col(field)), { |
1170 | [Sequelize.Op.gte]: threshold | 1170 | [ Sequelize.Op.gte ]: threshold |
1171 | }) as any, // FIXME: typings | 1171 | }) as any, // FIXME: typings |
1172 | where: { | 1172 | where: { |
1173 | [field]: { | 1173 | [ field ]: { |
1174 | [Sequelize.Op.not]: null | 1174 | [ Sequelize.Op.not ]: null |
1175 | }, | 1175 | }, |
1176 | privacy: VideoPrivacy.PUBLIC, | 1176 | privacy: VideoPrivacy.PUBLIC, |
1177 | state: VideoState.PUBLISHED | 1177 | state: VideoState.PUBLISHED |
@@ -1180,7 +1180,7 @@ export class VideoModel extends Model<VideoModel> { | |||
1180 | } | 1180 | } |
1181 | 1181 | ||
1182 | return VideoModel.findAll(query) | 1182 | return VideoModel.findAll(query) |
1183 | .then(rows => rows.map(r => r[field])) | 1183 | .then(rows => rows.map(r => r[ field ])) |
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | private static buildActorWhereWithFilter (filter?: VideoFilter) { | 1186 | private static buildActorWhereWithFilter (filter?: VideoFilter) { |
@@ -1200,7 +1200,19 @@ export class VideoModel extends Model<VideoModel> { | |||
1200 | ] | 1200 | ] |
1201 | } | 1201 | } |
1202 | 1202 | ||
1203 | const { count, rows: rowsId } = await VideoModel.scope(idsScope).findAndCountAll(query) | 1203 | // Remove trending sort on count, because it uses a group by |
1204 | const countOptions = Object.assign({}, options, { trendingDays: undefined }) | ||
1205 | const countQuery = Object.assign({}, query, { attributes: undefined, group: undefined }) | ||
1206 | const countScope = { | ||
1207 | method: [ | ||
1208 | ScopeNames.AVAILABLE_FOR_LIST_IDS, countOptions | ||
1209 | ] | ||
1210 | } | ||
1211 | |||
1212 | const [ count, rowsId ] = await Promise.all([ | ||
1213 | VideoModel.scope(countScope).count(countQuery), | ||
1214 | VideoModel.scope(idsScope).findAll(query) | ||
1215 | ]) | ||
1204 | const ids = rowsId.map(r => r.id) | 1216 | const ids = rowsId.map(r => r.id) |
1205 | 1217 | ||
1206 | if (ids.length === 0) return { data: [], total: count } | 1218 | if (ids.length === 0) return { data: [], total: count } |
@@ -1228,23 +1240,23 @@ export class VideoModel extends Model<VideoModel> { | |||
1228 | } | 1240 | } |
1229 | 1241 | ||
1230 | private static getCategoryLabel (id: number) { | 1242 | private static getCategoryLabel (id: number) { |
1231 | return VIDEO_CATEGORIES[id] || 'Misc' | 1243 | return VIDEO_CATEGORIES[ id ] || 'Misc' |
1232 | } | 1244 | } |
1233 | 1245 | ||
1234 | private static getLicenceLabel (id: number) { | 1246 | private static getLicenceLabel (id: number) { |
1235 | return VIDEO_LICENCES[id] || 'Unknown' | 1247 | return VIDEO_LICENCES[ id ] || 'Unknown' |
1236 | } | 1248 | } |
1237 | 1249 | ||
1238 | private static getLanguageLabel (id: string) { | 1250 | private static getLanguageLabel (id: string) { |
1239 | return VIDEO_LANGUAGES[id] || 'Unknown' | 1251 | return VIDEO_LANGUAGES[ id ] || 'Unknown' |
1240 | } | 1252 | } |
1241 | 1253 | ||
1242 | private static getPrivacyLabel (id: number) { | 1254 | private static getPrivacyLabel (id: number) { |
1243 | return VIDEO_PRIVACIES[id] || 'Unknown' | 1255 | return VIDEO_PRIVACIES[ id ] || 'Unknown' |
1244 | } | 1256 | } |
1245 | 1257 | ||
1246 | private static getStateLabel (id: number) { | 1258 | private static getStateLabel (id: number) { |
1247 | return VIDEO_STATES[id] || 'Unknown' | 1259 | return VIDEO_STATES[ id ] || 'Unknown' |
1248 | } | 1260 | } |
1249 | 1261 | ||
1250 | getOriginalFile () { | 1262 | getOriginalFile () { |
@@ -1466,28 +1478,28 @@ export class VideoModel extends Model<VideoModel> { | |||
1466 | const { baseUrlHttp, baseUrlWs } = this.getBaseUrls() | 1478 | const { baseUrlHttp, baseUrlWs } = this.getBaseUrls() |
1467 | 1479 | ||
1468 | return this.VideoFiles | 1480 | return this.VideoFiles |
1469 | .map(videoFile => { | 1481 | .map(videoFile => { |
1470 | let resolutionLabel = videoFile.resolution + 'p' | 1482 | let resolutionLabel = videoFile.resolution + 'p' |
1471 | 1483 | ||
1472 | return { | 1484 | return { |
1473 | resolution: { | 1485 | resolution: { |
1474 | id: videoFile.resolution, | 1486 | id: videoFile.resolution, |
1475 | label: resolutionLabel | 1487 | label: resolutionLabel |
1476 | }, | 1488 | }, |
1477 | magnetUri: this.generateMagnetUri(videoFile, baseUrlHttp, baseUrlWs), | 1489 | magnetUri: this.generateMagnetUri(videoFile, baseUrlHttp, baseUrlWs), |
1478 | size: videoFile.size, | 1490 | size: videoFile.size, |
1479 | fps: videoFile.fps, | 1491 | fps: videoFile.fps, |
1480 | torrentUrl: this.getTorrentUrl(videoFile, baseUrlHttp), | 1492 | torrentUrl: this.getTorrentUrl(videoFile, baseUrlHttp), |
1481 | torrentDownloadUrl: this.getTorrentDownloadUrl(videoFile, baseUrlHttp), | 1493 | torrentDownloadUrl: this.getTorrentDownloadUrl(videoFile, baseUrlHttp), |
1482 | fileUrl: this.getVideoFileUrl(videoFile, baseUrlHttp), | 1494 | fileUrl: this.getVideoFileUrl(videoFile, baseUrlHttp), |
1483 | fileDownloadUrl: this.getVideoFileDownloadUrl(videoFile, baseUrlHttp) | 1495 | fileDownloadUrl: this.getVideoFileDownloadUrl(videoFile, baseUrlHttp) |
1484 | } as VideoFile | 1496 | } as VideoFile |
1485 | }) | 1497 | }) |
1486 | .sort((a, b) => { | 1498 | .sort((a, b) => { |
1487 | if (a.resolution.id < b.resolution.id) return 1 | 1499 | if (a.resolution.id < b.resolution.id) return 1 |
1488 | if (a.resolution.id === b.resolution.id) return 0 | 1500 | if (a.resolution.id === b.resolution.id) return 0 |
1489 | return -1 | 1501 | return -1 |
1490 | }) | 1502 | }) |
1491 | } | 1503 | } |
1492 | 1504 | ||
1493 | toActivityPubObject (): VideoTorrentObject { | 1505 | toActivityPubObject (): VideoTorrentObject { |
@@ -1527,7 +1539,7 @@ export class VideoModel extends Model<VideoModel> { | |||
1527 | for (const file of this.VideoFiles) { | 1539 | for (const file of this.VideoFiles) { |
1528 | url.push({ | 1540 | url.push({ |
1529 | type: 'Link', | 1541 | type: 'Link', |
1530 | mimeType: VIDEO_EXT_MIMETYPE[file.extname], | 1542 | mimeType: VIDEO_EXT_MIMETYPE[ file.extname ], |
1531 | href: this.getVideoFileUrl(file, baseUrlHttp), | 1543 | href: this.getVideoFileUrl(file, baseUrlHttp), |
1532 | height: file.resolution, | 1544 | height: file.resolution, |
1533 | size: file.size, | 1545 | size: file.size, |