15 } from 'sequelize-typescript'
16 import { VideoModel } from './video'
17 import { VideoPlaylistModel } from './video-playlist'
18 import * as Sequelize from 'sequelize'
19 import { getSort, throwIfNotValid } from '../utils'
20 import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
21 import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
22 import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object'
23 import * as validator from 'validator'
26 tableName: 'videoPlaylistElement',
29 fields: [ 'videoPlaylistId' ]
35 fields: [ 'videoPlaylistId', 'videoId' ],
44 export class VideoPlaylistElementModel extends Model<VideoPlaylistElementModel> {
52 @Is('VideoPlaylistUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'url'))
53 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_PLAYLISTS.URL.max))
67 startTimestamp: number
75 @ForeignKey(() => VideoPlaylistModel)
77 videoPlaylistId: number
79 @BelongsTo(() => VideoPlaylistModel, {
85 VideoPlaylist: VideoPlaylistModel
87 @ForeignKey(() => VideoModel)
91 @BelongsTo(() => VideoModel, {
99 static deleteAllOf (videoPlaylistId: number, transaction?: Sequelize.Transaction) {
107 return VideoPlaylistElementModel.destroy(query)
110 static loadByPlaylistAndVideo (videoPlaylistId: number, videoId: number) {
118 return VideoPlaylistElementModel.findOne(query)
121 static loadByPlaylistAndVideoForAP (playlistId: number | string, videoId: number | string) {
122 const playlistWhere = validator.isUUID('' + playlistId) ? { uuid: playlistId } : { id: playlistId }
123 const videoWhere = validator.isUUID('' + videoId) ? { uuid: videoId } : { id: videoId }
128 attributes: [ 'privacy' ],
129 model: VideoPlaylistModel.unscoped(),
133 attributes: [ 'url' ],
134 model: VideoModel.unscoped(),
140 return VideoPlaylistElementModel.findOne(query)
143 static listUrlsOfForAP (videoPlaylistId: number, start: number, count: number, t?: Sequelize.Transaction) {
145 attributes: [ 'url' ],
148 order: getSort('position'),
155 return VideoPlaylistElementModel
156 .findAndCountAll(query)
157 .then(({ rows, count }) => {
158 return { total: count, data: rows.map(e => e.url) }
162 static getNextPositionOf (videoPlaylistId: number, transaction?: Sequelize.Transaction) {
170 return VideoPlaylistElementModel.max('position', query)
171 .then(position => position ? position + 1 : 1)
174 static reassignPositionOf (
175 videoPlaylistId: number,
176 firstPosition: number,
179 transaction?: Sequelize.Transaction
185 [Sequelize.Op.gte]: firstPosition,
186 [Sequelize.Op.lte]: endPosition
190 validate: false // We use a literal to update the position
193 return VideoPlaylistElementModel.update({ position: Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) }, query)
196 static increasePositionOf (
197 videoPlaylistId: number,
198 fromPosition: number,
201 transaction?: Sequelize.Transaction
207 [Sequelize.Op.gte]: fromPosition
213 return VideoPlaylistElementModel.increment({ position: by }, query)
216 toActivityPubObject (): PlaylistElementObject {
217 const base: PlaylistElementObject = {
219 type: 'PlaylistElement',
222 position: this.position
225 if (this.startTimestamp) base.startTimestamp = this.startTimestamp
226 if (this.stopTimestamp) base.stopTimestamp = this.stopTimestamp