aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video/video.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/models/video/video.ts')
-rw-r--r--server/models/video/video.ts86
1 files changed, 29 insertions, 57 deletions
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index b5c46c86c..26be34329 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -34,12 +34,12 @@ import { VideoPathManager } from '@server/lib/video-path-manager'
34import { getServerActor } from '@server/models/application/application' 34import { getServerActor } from '@server/models/application/application'
35import { ModelCache } from '@server/models/model-cache' 35import { ModelCache } from '@server/models/model-cache'
36import { AttributesOnly, buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils' 36import { AttributesOnly, buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils'
37import { VideoInclude } from '@shared/models'
37import { VideoFile } from '@shared/models/videos/video-file.model' 38import { VideoFile } from '@shared/models/videos/video-file.model'
38import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' 39import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared'
39import { VideoObject } from '../../../shared/models/activitypub/objects' 40import { VideoObject } from '../../../shared/models/activitypub/objects'
40import { Video, VideoDetails, VideoRateType, VideoStorage } from '../../../shared/models/videos' 41import { Video, VideoDetails, VideoRateType, VideoStorage } from '../../../shared/models/videos'
41import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' 42import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
42import { VideoFilter } from '../../../shared/models/videos/video-query.type'
43import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' 43import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
44import { peertubeTruncate } from '../../helpers/core-utils' 44import { peertubeTruncate } from '../../helpers/core-utils'
45import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 45import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
@@ -106,7 +106,7 @@ import {
106} from './formatter/video-format-utils' 106} from './formatter/video-format-utils'
107import { ScheduleVideoUpdateModel } from './schedule-video-update' 107import { ScheduleVideoUpdateModel } from './schedule-video-update'
108import { VideosModelGetQueryBuilder } from './sql/video-model-get-query-builder' 108import { VideosModelGetQueryBuilder } from './sql/video-model-get-query-builder'
109import { BuildVideosListQueryOptions, VideosIdListQueryBuilder } from './sql/videos-id-list-query-builder' 109import { BuildVideosListQueryOptions, DisplayOnlyForFollowerOptions, VideosIdListQueryBuilder } from './sql/videos-id-list-query-builder'
110import { VideosModelListQueryBuilder } from './sql/videos-model-list-query-builder' 110import { VideosModelListQueryBuilder } from './sql/videos-model-list-query-builder'
111import { TagModel } from './tag' 111import { TagModel } from './tag'
112import { ThumbnailModel } from './thumbnail' 112import { ThumbnailModel } from './thumbnail'
@@ -145,35 +145,6 @@ export type ForAPIOptions = {
145 withAccountBlockerIds?: number[] 145 withAccountBlockerIds?: number[]
146} 146}
147 147
148export type AvailableForListIDsOptions = {
149 serverAccountId: number
150 followerActorId: number
151 includeLocalVideos: boolean
152
153 attributesType?: 'none' | 'id' | 'all'
154
155 filter?: VideoFilter
156 categoryOneOf?: number[]
157 nsfw?: boolean
158 licenceOneOf?: number[]
159 languageOneOf?: string[]
160 tagsOneOf?: string[]
161 tagsAllOf?: string[]
162
163 withFiles?: boolean
164
165 accountId?: number
166 videoChannelId?: number
167
168 videoPlaylistId?: number
169
170 trendingDays?: number
171 user?: MUserAccountId
172 historyOfUser?: MUserId
173
174 baseWhere?: WhereOptions[]
175}
176
177@Scopes(() => ({ 148@Scopes(() => ({
178 [ScopeNames.WITH_IMMUTABLE_ATTRIBUTES]: { 149 [ScopeNames.WITH_IMMUTABLE_ATTRIBUTES]: {
179 attributes: [ 'id', 'url', 'uuid', 'remote' ] 150 attributes: [ 'id', 'url', 'uuid', 'remote' ]
@@ -1054,10 +1025,10 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1054 sort: string 1025 sort: string
1055 1026
1056 nsfw: boolean 1027 nsfw: boolean
1057 filter?: VideoFilter
1058 isLive?: boolean 1028 isLive?: boolean
1029 isLocal?: boolean
1030 include?: VideoInclude
1059 1031
1060 includeLocalVideos: boolean
1061 withFiles: boolean 1032 withFiles: boolean
1062 1033
1063 categoryOneOf?: number[] 1034 categoryOneOf?: number[]
@@ -1069,7 +1040,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1069 accountId?: number 1040 accountId?: number
1070 videoChannelId?: number 1041 videoChannelId?: number
1071 1042
1072 followerActorId?: number 1043 displayOnlyForFollower: DisplayOnlyForFollowerOptions | null
1073 1044
1074 videoPlaylistId?: number 1045 videoPlaylistId?: number
1075 1046
@@ -1082,7 +1053,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1082 1053
1083 search?: string 1054 search?: string
1084 }) { 1055 }) {
1085 if ((options.filter === 'all-local' || options.filter === 'all') && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) { 1056 if (options.include && !options.user.hasRight(UserRight.SEE_ALL_VIDEOS)) {
1086 throw new Error('Try to filter all-local but no user has not the see all videos right') 1057 throw new Error('Try to filter all-local but no user has not the see all videos right')
1087 } 1058 }
1088 1059
@@ -1096,11 +1067,6 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1096 1067
1097 const serverActor = await getServerActor() 1068 const serverActor = await getServerActor()
1098 1069
1099 // followerActorId === null has a meaning, so just check undefined
1100 const followerActorId = options.followerActorId !== undefined
1101 ? options.followerActorId
1102 : serverActor.id
1103
1104 const queryOptions = { 1070 const queryOptions = {
1105 ...pick(options, [ 1071 ...pick(options, [
1106 'start', 1072 'start',
@@ -1113,19 +1079,19 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1113 'languageOneOf', 1079 'languageOneOf',
1114 'tagsOneOf', 1080 'tagsOneOf',
1115 'tagsAllOf', 1081 'tagsAllOf',
1116 'filter', 1082 'isLocal',
1083 'include',
1084 'displayOnlyForFollower',
1117 'withFiles', 1085 'withFiles',
1118 'accountId', 1086 'accountId',
1119 'videoChannelId', 1087 'videoChannelId',
1120 'videoPlaylistId', 1088 'videoPlaylistId',
1121 'includeLocalVideos',
1122 'user', 1089 'user',
1123 'historyOfUser', 1090 'historyOfUser',
1124 'search' 1091 'search'
1125 ]), 1092 ]),
1126 1093
1127 followerActorId, 1094 serverAccountIdForBlock: serverActor.Account.id,
1128 serverAccountId: serverActor.Account.id,
1129 trendingDays, 1095 trendingDays,
1130 trendingAlgorithm 1096 trendingAlgorithm
1131 } 1097 }
@@ -1137,7 +1103,6 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1137 start: number 1103 start: number
1138 count: number 1104 count: number
1139 sort: string 1105 sort: string
1140 includeLocalVideos: boolean
1141 search?: string 1106 search?: string
1142 host?: string 1107 host?: string
1143 startDate?: string // ISO 8601 1108 startDate?: string // ISO 8601
@@ -1146,6 +1111,8 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1146 originallyPublishedEndDate?: string 1111 originallyPublishedEndDate?: string
1147 nsfw?: boolean 1112 nsfw?: boolean
1148 isLive?: boolean 1113 isLive?: boolean
1114 isLocal?: boolean
1115 include?: VideoInclude
1149 categoryOneOf?: number[] 1116 categoryOneOf?: number[]
1150 licenceOneOf?: number[] 1117 licenceOneOf?: number[]
1151 languageOneOf?: string[] 1118 languageOneOf?: string[]
@@ -1154,14 +1121,14 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1154 durationMin?: number // seconds 1121 durationMin?: number // seconds
1155 durationMax?: number // seconds 1122 durationMax?: number // seconds
1156 user?: MUserAccountId 1123 user?: MUserAccountId
1157 filter?: VideoFilter
1158 uuids?: string[] 1124 uuids?: string[]
1125 displayOnlyForFollower: DisplayOnlyForFollowerOptions | null
1159 }) { 1126 }) {
1160 const serverActor = await getServerActor() 1127 const serverActor = await getServerActor()
1161 1128
1162 const queryOptions = { 1129 const queryOptions = {
1163 ...pick(options, [ 1130 ...pick(options, [
1164 'includeLocalVideos', 1131 'include',
1165 'nsfw', 1132 'nsfw',
1166 'isLive', 1133 'isLive',
1167 'categoryOneOf', 1134 'categoryOneOf',
@@ -1170,7 +1137,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1170 'tagsOneOf', 1137 'tagsOneOf',
1171 'tagsAllOf', 1138 'tagsAllOf',
1172 'user', 1139 'user',
1173 'filter', 1140 'isLocal',
1174 'host', 1141 'host',
1175 'start', 1142 'start',
1176 'count', 1143 'count',
@@ -1182,11 +1149,10 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1182 'durationMin', 1149 'durationMin',
1183 'durationMax', 1150 'durationMax',
1184 'uuids', 1151 'uuids',
1185 'search' 1152 'search',
1153 'displayOnlyForFollower'
1186 ]), 1154 ]),
1187 1155 serverAccountIdForBlock: serverActor.Account.id
1188 followerActorId: serverActor.id,
1189 serverAccountId: serverActor.Account.id
1190 } 1156 }
1191 1157
1192 return VideoModel.getAvailableForApi(queryOptions) 1158 return VideoModel.getAvailableForApi(queryOptions)
@@ -1369,12 +1335,17 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1369 // Sequelize could return null... 1335 // Sequelize could return null...
1370 if (!totalLocalVideoViews) totalLocalVideoViews = 0 1336 if (!totalLocalVideoViews) totalLocalVideoViews = 0
1371 1337
1338 const serverActor = await getServerActor()
1339
1372 const { total: totalVideos } = await VideoModel.listForApi({ 1340 const { total: totalVideos } = await VideoModel.listForApi({
1373 start: 0, 1341 start: 0,
1374 count: 0, 1342 count: 0,
1375 sort: '-publishedAt', 1343 sort: '-publishedAt',
1376 nsfw: buildNSFWFilter(), 1344 nsfw: buildNSFWFilter(),
1377 includeLocalVideos: true, 1345 displayOnlyForFollower: {
1346 actorId: serverActor.id,
1347 orLocalVideos: true
1348 },
1378 withFiles: false 1349 withFiles: false
1379 }) 1350 })
1380 1351
@@ -1455,7 +1426,6 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1455 // threshold corresponds to how many video the field should have to be returned 1426 // threshold corresponds to how many video the field should have to be returned
1456 static async getRandomFieldSamples (field: 'category' | 'channelId', threshold: number, count: number) { 1427 static async getRandomFieldSamples (field: 'category' | 'channelId', threshold: number, count: number) {
1457 const serverActor = await getServerActor() 1428 const serverActor = await getServerActor()
1458 const followerActorId = serverActor.id
1459 1429
1460 const queryOptions: BuildVideosListQueryOptions = { 1430 const queryOptions: BuildVideosListQueryOptions = {
1461 attributes: [ `"${field}"` ], 1431 attributes: [ `"${field}"` ],
@@ -1464,9 +1434,11 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1464 start: 0, 1434 start: 0,
1465 sort: 'random', 1435 sort: 'random',
1466 count, 1436 count,
1467 serverAccountId: serverActor.Account.id, 1437 serverAccountIdForBlock: serverActor.Account.id,
1468 followerActorId, 1438 displayOnlyForFollower: {
1469 includeLocalVideos: true 1439 actorId: serverActor.id,
1440 orLocalVideos: true
1441 }
1470 } 1442 }
1471 1443
1472 const queryBuilder = new VideosIdListQueryBuilder(VideoModel.sequelize) 1444 const queryBuilder = new VideosIdListQueryBuilder(VideoModel.sequelize)