import { ThumbnailModel } from './thumbnail'
import { ActivityIconObject } from '../../../shared/models/activitypub/objects'
import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize'
+import * as Bluebird from 'bluebird'
+import {
+ MVideoPlaylistAccountThumbnail,
+ MVideoPlaylistAP,
+ MVideoPlaylistFormattable,
+ MVideoPlaylistFull,
+ MVideoPlaylistFullSummary,
+ MVideoPlaylistIdWithElements
+} from '../../typings/models/video/video-playlist'
+import { MThumbnail } from '../../typings/models/video/thumbnail'
enum ScopeNames {
AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST',
type?: VideoPlaylistType
accountId?: number
videoChannelId?: number
- privateAndUnlisted?: boolean
+ listMyPlaylists?: boolean
+ search?: string
}
@Scopes(() => ({
- [ ScopeNames.WITH_THUMBNAIL ]: {
+ [ScopeNames.WITH_THUMBNAIL]: {
include: [
{
model: ThumbnailModel,
}
]
},
- [ ScopeNames.WITH_VIDEOS_LENGTH ]: {
+ [ScopeNames.WITH_VIDEOS_LENGTH]: {
attributes: {
include: [
[
]
}
} as FindOptions,
- [ ScopeNames.WITH_ACCOUNT ]: {
+ [ScopeNames.WITH_ACCOUNT]: {
include: [
{
model: AccountModel,
}
]
},
- [ ScopeNames.WITH_ACCOUNT_AND_CHANNEL_SUMMARY ]: {
+ [ScopeNames.WITH_ACCOUNT_AND_CHANNEL_SUMMARY]: {
include: [
{
model: AccountModel.scope(AccountScopeNames.SUMMARY),
}
]
},
- [ ScopeNames.WITH_ACCOUNT_AND_CHANNEL ]: {
+ [ScopeNames.WITH_ACCOUNT_AND_CHANNEL]: {
include: [
{
model: AccountModel,
}
]
},
- [ ScopeNames.AVAILABLE_FOR_LIST ]: (options: AvailableForListOptions) => {
- // Only list local playlists OR playlists that are on an instance followed by actorId
- const inQueryInstanceFollow = buildServerIdsFollowedBy(options.followerActorId)
- const whereActor = {
- [ Op.or ]: [
- {
- serverId: null
- },
- {
- serverId: {
- [ Op.in ]: literal(inQueryInstanceFollow)
- }
- }
- ]
- }
+ [ScopeNames.AVAILABLE_FOR_LIST]: (options: AvailableForListOptions) => {
+
+ let whereActor: WhereOptions = {}
const whereAnd: WhereOptions[] = []
- if (options.privateAndUnlisted !== true) {
+ if (options.listMyPlaylists !== true) {
whereAnd.push({
privacy: VideoPlaylistPrivacy.PUBLIC
})
+
+ // Only list local playlists OR playlists that are on an instance followed by actorId
+ const inQueryInstanceFollow = buildServerIdsFollowedBy(options.followerActorId)
+
+ whereActor = {
+ [Op.or]: [
+ {
+ serverId: null
+ },
+ {
+ serverId: {
+ [Op.in]: literal(inQueryInstanceFollow)
+ }
+ }
+ ]
+ }
}
if (options.accountId) {
})
}
+ if (options.search) {
+ whereAnd.push({
+ name: {
+ [Op.iLike]: '%' + options.search + '%'
+ }
+ })
+ }
+
const where = {
[Op.and]: whereAnd
}
VideoPlaylistElements: VideoPlaylistElementModel[]
@HasOne(() => ThumbnailModel, {
-
foreignKey: {
name: 'videoPlaylistId',
allowNull: true
static listForApi (options: {
followerActorId: number
- start: number,
- count: number,
- sort: string,
- type?: VideoPlaylistType,
- accountId?: number,
- videoChannelId?: number,
- privateAndUnlisted?: boolean
+ start: number
+ count: number
+ sort: string
+ type?: VideoPlaylistType
+ accountId?: number
+ videoChannelId?: number
+ listMyPlaylists?: boolean
+ search?: string
}) {
const query = {
offset: options.start,
followerActorId: options.followerActorId,
accountId: options.accountId,
videoChannelId: options.videoChannelId,
- privateAndUnlisted: options.privateAndUnlisted
+ listMyPlaylists: options.listMyPlaylists,
+ search: options.search
} as AvailableForListOptions
]
},
})
}
- static listPlaylistIdsOf (accountId: number, videoIds: number[]) {
+ static listPlaylistIdsOf (accountId: number, videoIds: number[]): Bluebird<MVideoPlaylistIdWithElements[]> {
const query = {
attributes: [ 'id' ],
where: {
model: VideoPlaylistElementModel.unscoped(),
where: {
videoId: {
- [Op.in]: videoIds // FIXME: sequelize ANY seems broken
+ [Op.in]: videoIds
}
},
required: true
.then(e => !!e)
}
- static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction) {
+ static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFullSummary> {
const where = buildWhereIdOrUUID(id)
const query = {
.findOne(query)
}
- static loadWithAccountAndChannel (id: number | string, transaction: Transaction) {
+ static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Bluebird<MVideoPlaylistFull> {
const where = buildWhereIdOrUUID(id)
const query = {
.findOne(query)
}
- static loadByUrlAndPopulateAccount (url: string) {
+ static loadByUrlAndPopulateAccount (url: string): Bluebird<MVideoPlaylistAccountThumbnail> {
const query = {
where: {
url
return VideoPlaylistModel.update({ privacy: VideoPlaylistPrivacy.PRIVATE, videoChannelId: null }, query)
}
- async setAndSaveThumbnail (thumbnail: ThumbnailModel, t: Transaction) {
+ async setAndSaveThumbnail (thumbnail: MThumbnail, t: Transaction) {
thumbnail.videoPlaylistId = this.id
this.Thumbnail = await thumbnail.save({ transaction: t })
return !!this.Thumbnail
}
+ hasGeneratedThumbnail () {
+ return this.hasThumbnail() && this.Thumbnail.automaticallyGenerated === true
+ }
+
generateThumbnailName () {
const extension = '.jpg'
return isOutdated(this, ACTIVITY_PUB.VIDEO_PLAYLIST_REFRESH_INTERVAL)
}
- toFormattedJSON (): VideoPlaylist {
+ toFormattedJSON (this: MVideoPlaylistFormattable): VideoPlaylist {
return {
id: this.id,
uuid: this.uuid,
updatedAt: this.updatedAt,
ownerAccount: this.OwnerAccount.toFormattedSummaryJSON(),
- videoChannel: this.VideoChannel ? this.VideoChannel.toFormattedSummaryJSON() : null
+ videoChannel: this.VideoChannel
+ ? this.VideoChannel.toFormattedSummaryJSON()
+ : null
}
}
- toActivityPubObject (page: number, t: Transaction): Promise<PlaylistObject> {
+ toActivityPubObject (this: MVideoPlaylistAP, page: number, t: Transaction): Promise<PlaylistObject> {
const handler = (start: number, count: number) => {
return VideoPlaylistElementModel.listUrlsOfForAP(this.id, start, count, t)
}