diff options
Diffstat (limited to 'server/models/video/video.ts')
-rw-r--r-- | server/models/video/video.ts | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index c7f2658ed..05d625fc1 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -91,7 +91,7 @@ import { | |||
91 | } from '../utils' | 91 | } from '../utils' |
92 | import { TagModel } from './tag' | 92 | import { TagModel } from './tag' |
93 | import { VideoAbuseModel } from './video-abuse' | 93 | import { VideoAbuseModel } from './video-abuse' |
94 | import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' | 94 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel' |
95 | import { VideoCommentModel } from './video-comment' | 95 | import { VideoCommentModel } from './video-comment' |
96 | import { VideoFileModel } from './video-file' | 96 | import { VideoFileModel } from './video-file' |
97 | import { VideoShareModel } from './video-share' | 97 | import { VideoShareModel } from './video-share' |
@@ -190,26 +190,29 @@ export enum ScopeNames { | |||
190 | WITH_FILES = 'WITH_FILES', | 190 | WITH_FILES = 'WITH_FILES', |
191 | WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE', | 191 | WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE', |
192 | WITH_BLACKLISTED = 'WITH_BLACKLISTED', | 192 | WITH_BLACKLISTED = 'WITH_BLACKLISTED', |
193 | WITH_BLOCKLIST = 'WITH_BLOCKLIST', | ||
193 | WITH_USER_HISTORY = 'WITH_USER_HISTORY', | 194 | WITH_USER_HISTORY = 'WITH_USER_HISTORY', |
194 | WITH_STREAMING_PLAYLISTS = 'WITH_STREAMING_PLAYLISTS', | 195 | WITH_STREAMING_PLAYLISTS = 'WITH_STREAMING_PLAYLISTS', |
195 | WITH_USER_ID = 'WITH_USER_ID', | 196 | WITH_USER_ID = 'WITH_USER_ID', |
196 | WITH_THUMBNAILS = 'WITH_THUMBNAILS' | 197 | WITH_THUMBNAILS = 'WITH_THUMBNAILS' |
197 | } | 198 | } |
198 | 199 | ||
199 | type ForAPIOptions = { | 200 | export type ForAPIOptions = { |
200 | ids: number[] | 201 | ids?: number[] |
201 | 202 | ||
202 | videoPlaylistId?: number | 203 | videoPlaylistId?: number |
203 | 204 | ||
204 | withFiles?: boolean | 205 | withFiles?: boolean |
206 | |||
207 | withAccountBlockerIds?: number[] | ||
205 | } | 208 | } |
206 | 209 | ||
207 | type AvailableForListIDsOptions = { | 210 | export type AvailableForListIDsOptions = { |
208 | serverAccountId: number | 211 | serverAccountId: number |
209 | followerActorId: number | 212 | followerActorId: number |
210 | includeLocalVideos: boolean | 213 | includeLocalVideos: boolean |
211 | 214 | ||
212 | withoutId?: boolean | 215 | attributesType?: 'none' | 'id' | 'all' |
213 | 216 | ||
214 | filter?: VideoFilter | 217 | filter?: VideoFilter |
215 | categoryOneOf?: number[] | 218 | categoryOneOf?: number[] |
@@ -236,14 +239,16 @@ type AvailableForListIDsOptions = { | |||
236 | @Scopes(() => ({ | 239 | @Scopes(() => ({ |
237 | [ ScopeNames.FOR_API ]: (options: ForAPIOptions) => { | 240 | [ ScopeNames.FOR_API ]: (options: ForAPIOptions) => { |
238 | const query: FindOptions = { | 241 | const query: FindOptions = { |
239 | where: { | ||
240 | id: { | ||
241 | [ Op.in ]: options.ids // FIXME: sequelize ANY seems broken | ||
242 | } | ||
243 | }, | ||
244 | include: [ | 242 | include: [ |
245 | { | 243 | { |
246 | model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, true ] }), | 244 | model: VideoChannelModel.scope({ |
245 | method: [ | ||
246 | VideoChannelScopeNames.SUMMARY, { | ||
247 | withAccount: true, | ||
248 | withAccountBlockerIds: options.withAccountBlockerIds | ||
249 | } as SummaryOptions | ||
250 | ] | ||
251 | }), | ||
247 | required: true | 252 | required: true |
248 | }, | 253 | }, |
249 | { | 254 | { |
@@ -254,6 +259,14 @@ type AvailableForListIDsOptions = { | |||
254 | ] | 259 | ] |
255 | } | 260 | } |
256 | 261 | ||
262 | if (options.ids) { | ||
263 | query.where = { | ||
264 | id: { | ||
265 | [ Op.in ]: options.ids // FIXME: sequelize ANY seems broken | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
257 | if (options.withFiles === true) { | 270 | if (options.withFiles === true) { |
258 | query.include.push({ | 271 | query.include.push({ |
259 | model: VideoFileModel.unscoped(), | 272 | model: VideoFileModel.unscoped(), |
@@ -278,10 +291,14 @@ type AvailableForListIDsOptions = { | |||
278 | 291 | ||
279 | const query: FindOptions = { | 292 | const query: FindOptions = { |
280 | raw: true, | 293 | raw: true, |
281 | attributes: options.withoutId === true ? [] : [ 'id' ], | ||
282 | include: [] | 294 | include: [] |
283 | } | 295 | } |
284 | 296 | ||
297 | const attributesType = options.attributesType || 'id' | ||
298 | |||
299 | if (attributesType === 'id') query.attributes = [ 'id' ] | ||
300 | else if (attributesType === 'none') query.attributes = [ ] | ||
301 | |||
285 | whereAnd.push({ | 302 | whereAnd.push({ |
286 | id: { | 303 | id: { |
287 | [ Op.notIn ]: Sequelize.literal( | 304 | [ Op.notIn ]: Sequelize.literal( |
@@ -290,17 +307,19 @@ type AvailableForListIDsOptions = { | |||
290 | } | 307 | } |
291 | }) | 308 | }) |
292 | 309 | ||
293 | whereAnd.push({ | 310 | if (options.serverAccountId) { |
294 | channelId: { | 311 | whereAnd.push({ |
295 | [ Op.notIn ]: Sequelize.literal( | 312 | channelId: { |
296 | '(' + | 313 | [ Op.notIn ]: Sequelize.literal( |
297 | 'SELECT id FROM "videoChannel" WHERE "accountId" IN (' + | 314 | '(' + |
298 | buildBlockedAccountSQL(options.serverAccountId, options.user ? options.user.Account.id : undefined) + | 315 | 'SELECT id FROM "videoChannel" WHERE "accountId" IN (' + |
299 | ')' + | 316 | buildBlockedAccountSQL(options.serverAccountId, options.user ? options.user.Account.id : undefined) + |
300 | ')' | 317 | ')' + |
301 | ) | 318 | ')' |
302 | } | 319 | ) |
303 | }) | 320 | } |
321 | }) | ||
322 | } | ||
304 | 323 | ||
305 | // Only list public/published videos | 324 | // Only list public/published videos |
306 | if (!options.filter || options.filter !== 'all-local') { | 325 | if (!options.filter || options.filter !== 'all-local') { |
@@ -528,6 +547,9 @@ type AvailableForListIDsOptions = { | |||
528 | 547 | ||
529 | return query | 548 | return query |
530 | }, | 549 | }, |
550 | [ScopeNames.WITH_BLOCKLIST]: { | ||
551 | |||
552 | }, | ||
531 | [ ScopeNames.WITH_THUMBNAILS ]: { | 553 | [ ScopeNames.WITH_THUMBNAILS ]: { |
532 | include: [ | 554 | include: [ |
533 | { | 555 | { |
@@ -845,9 +867,9 @@ export class VideoModel extends Model<VideoModel> { | |||
845 | @HasMany(() => VideoPlaylistElementModel, { | 867 | @HasMany(() => VideoPlaylistElementModel, { |
846 | foreignKey: { | 868 | foreignKey: { |
847 | name: 'videoId', | 869 | name: 'videoId', |
848 | allowNull: false | 870 | allowNull: true |
849 | }, | 871 | }, |
850 | onDelete: 'cascade' | 872 | onDelete: 'set null' |
851 | }) | 873 | }) |
852 | VideoPlaylistElements: VideoPlaylistElementModel[] | 874 | VideoPlaylistElements: VideoPlaylistElementModel[] |
853 | 875 | ||
@@ -1586,7 +1608,7 @@ export class VideoModel extends Model<VideoModel> { | |||
1586 | serverAccountId: serverActor.Account.id, | 1608 | serverAccountId: serverActor.Account.id, |
1587 | followerActorId, | 1609 | followerActorId, |
1588 | includeLocalVideos: true, | 1610 | includeLocalVideos: true, |
1589 | withoutId: true // Don't break aggregation | 1611 | attributesType: 'none' // Don't break aggregation |
1590 | } | 1612 | } |
1591 | 1613 | ||
1592 | const query: FindOptions = { | 1614 | const query: FindOptions = { |
@@ -1719,6 +1741,11 @@ export class VideoModel extends Model<VideoModel> { | |||
1719 | return !!this.VideoBlacklist | 1741 | return !!this.VideoBlacklist |
1720 | } | 1742 | } |
1721 | 1743 | ||
1744 | isBlocked () { | ||
1745 | return (this.VideoChannel.Account.Actor.Server && this.VideoChannel.Account.Actor.Server.isBlocked()) || | ||
1746 | this.VideoChannel.Account.isBlocked() | ||
1747 | } | ||
1748 | |||
1722 | getOriginalFile () { | 1749 | getOriginalFile () { |
1723 | if (Array.isArray(this.VideoFiles) === false) return undefined | 1750 | if (Array.isArray(this.VideoFiles) === false) return undefined |
1724 | 1751 | ||