aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models/video/video-playlist-element.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-07-31 15:57:32 +0200
committerChocobozzz <chocobozzz@cpy.re>2019-08-01 09:11:04 +0200
commitbfbd912886eba17b4aa9a40dcef2fddc685d85bf (patch)
tree85e0f22980210a8ccd0888eb5e1790b152074677 /server/models/video/video-playlist-element.ts
parent85394ba22a07bde1dfccebf3f591a5d6dbe9df56 (diff)
downloadPeerTube-bfbd912886eba17b4aa9a40dcef2fddc685d85bf.tar.gz
PeerTube-bfbd912886eba17b4aa9a40dcef2fddc685d85bf.tar.zst
PeerTube-bfbd912886eba17b4aa9a40dcef2fddc685d85bf.zip
Fix broken playlist api
Diffstat (limited to 'server/models/video/video-playlist-element.ts')
-rw-r--r--server/models/video/video-playlist-element.ts103
1 files changed, 99 insertions, 4 deletions
diff --git a/server/models/video/video-playlist-element.ts b/server/models/video/video-playlist-element.ts
index eeb3d6bbd..bed6f8eaf 100644
--- a/server/models/video/video-playlist-element.ts
+++ b/server/models/video/video-playlist-element.ts
@@ -13,14 +13,18 @@ import {
13 Table, 13 Table,
14 UpdatedAt 14 UpdatedAt
15} from 'sequelize-typescript' 15} from 'sequelize-typescript'
16import { VideoModel } from './video' 16import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video'
17import { VideoPlaylistModel } from './video-playlist' 17import { VideoPlaylistModel } from './video-playlist'
18import { getSort, throwIfNotValid } from '../utils' 18import { getSort, throwIfNotValid } from '../utils'
19import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 19import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
20import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 20import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
21import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object' 21import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
22import * as validator from 'validator' 22import * as validator from 'validator'
23import { AggregateOptions, Op, Sequelize, Transaction } from 'sequelize' 23import { AggregateOptions, Op, ScopeOptions, Sequelize, Transaction } from 'sequelize'
24import { UserModel } from '../account/user'
25import { VideoPlaylistElement, VideoPlaylistElementType } from '../../../shared/models/videos/playlist/video-playlist-element.model'
26import { AccountModel } from '../account/account'
27import { VideoPrivacy } from '../../../shared/models/videos'
24 28
25@Table({ 29@Table({
26 tableName: 'videoPlaylistElement', 30 tableName: 'videoPlaylistElement',
@@ -90,9 +94,9 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
90 94
91 @BelongsTo(() => VideoModel, { 95 @BelongsTo(() => VideoModel, {
92 foreignKey: { 96 foreignKey: {
93 allowNull: false 97 allowNull: true
94 }, 98 },
95 onDelete: 'CASCADE' 99 onDelete: 'set null'
96 }) 100 })
97 Video: VideoModel 101 Video: VideoModel
98 102
@@ -107,6 +111,57 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
107 return VideoPlaylistElementModel.destroy(query) 111 return VideoPlaylistElementModel.destroy(query)
108 } 112 }
109 113
114 static listForApi (options: {
115 start: number,
116 count: number,
117 videoPlaylistId: number,
118 serverAccount: AccountModel,
119 user?: UserModel
120 }) {
121 const accountIds = [ options.serverAccount.id ]
122 const videoScope: (ScopeOptions | string)[] = [
123 VideoScopeNames.WITH_BLACKLISTED
124 ]
125
126 if (options.user) {
127 accountIds.push(options.user.Account.id)
128 videoScope.push({ method: [ VideoScopeNames.WITH_USER_HISTORY, options.user.id ] })
129 }
130
131 const forApiOptions: ForAPIOptions = { withAccountBlockerIds: accountIds }
132 videoScope.push({
133 method: [
134 VideoScopeNames.FOR_API, forApiOptions
135 ]
136 })
137
138 const findQuery = {
139 offset: options.start,
140 limit: options.count,
141 order: getSort('position'),
142 where: {
143 videoPlaylistId: options.videoPlaylistId
144 },
145 include: [
146 {
147 model: VideoModel.scope(videoScope),
148 required: false
149 }
150 ]
151 }
152
153 const countQuery = {
154 where: {
155 videoPlaylistId: options.videoPlaylistId
156 }
157 }
158
159 return Promise.all([
160 VideoPlaylistElementModel.count(countQuery),
161 VideoPlaylistElementModel.findAll(findQuery)
162 ]).then(([ total, data ]) => ({ total, data }))
163 }
164
110 static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number) { 165 static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number) {
111 const query = { 166 const query = {
112 where: { 167 where: {
@@ -118,6 +173,10 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
118 return VideoPlaylistElementModel.findOne(query) 173 return VideoPlaylistElementModel.findOne(query)
119 } 174 }
120 175
176 static loadById (playlistElementId: number) {
177 return VideoPlaylistElementModel.findByPk(playlistElementId)
178 }
179
121 static loadByPlaylistAndVideoForAP (playlistId: number | string, videoId: number | string) { 180 static loadByPlaylistAndVideoForAP (playlistId: number | string, videoId: number | string) {
122 const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId } 181 const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
123 const videoWhere = validator.isUUID('' + videoId) ? { uuid: videoId } : { id: videoId } 182 const videoWhere = validator.isUUID('' + videoId) ? { uuid: videoId } : { id: videoId }
@@ -213,6 +272,42 @@ export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel>
213 return VideoPlaylistElementModel.increment({ position: by }, query) 272 return VideoPlaylistElementModel.increment({ position: by }, query)
214 } 273 }
215 274
275 getType (displayNSFW?: boolean, accountId?: number) {
276 const video = this.Video
277
278 if (!video) return VideoPlaylistElementType.DELETED
279
280 // Owned video, don't filter it
281 if (accountId && video.VideoChannel.Account.id === accountId) return VideoPlaylistElementType.REGULAR
282
283 if (video.privacy === VideoPrivacy.PRIVATE) return VideoPlaylistElementType.PRIVATE
284
285 if (video.isBlacklisted() || video.isBlocked()) return VideoPlaylistElementType.UNAVAILABLE
286 if (video.nsfw === true && displayNSFW === false) return VideoPlaylistElementType.UNAVAILABLE
287
288 return VideoPlaylistElementType.REGULAR
289 }
290
291 getVideoElement (displayNSFW?: boolean, accountId?: number) {
292 if (!this.Video) return null
293 if (this.getType(displayNSFW, accountId) !== VideoPlaylistElementType.REGULAR) return null
294
295 return this.Video.toFormattedJSON()
296 }
297
298 toFormattedJSON (options: { displayNSFW?: boolean, accountId?: number } = {}): VideoPlaylistElement {
299 return {
300 id: this.id,
301 position: this.position,
302 startTimestamp: this.startTimestamp,
303 stopTimestamp: this.stopTimestamp,
304
305 type: this.getType(options.displayNSFW, options.accountId),
306
307 video: this.getVideoElement(options.displayNSFW, options.accountId)
308 }
309 }
310
216 toActivityPubObject (): PlaylistElementObject { 311 toActivityPubObject (): PlaylistElementObject {
217 const base: PlaylistElementObject = { 312 const base: PlaylistElementObject = {
218 id: this.url, 313 id: this.url,