X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;ds=sidebyside;f=server%2Fmodels%2Fvideo%2Fvideo-playlist.ts;h=efe5be36d2824a766436f4c5a4bef7169c253cac;hb=ceb8f322118b24508abc6dd0bc6813a43610eff3;hp=b020bfa45796fbb827382d2ad2ea3667f73069c6;hpb=49cff3a4c950b22ae13f345dc4eab803d96a236e;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts index b020bfa45..efe5be36d 100644 --- a/server/models/video/video-playlist.ts +++ b/server/models/video/video-playlist.ts @@ -1,3 +1,5 @@ +import { join } from 'path' +import { FindOptions, literal, Op, ScopeOptions, Transaction, WhereOptions } from 'sequelize' import { AllowNull, BelongsTo, @@ -15,14 +17,20 @@ import { Table, UpdatedAt } from 'sequelize-typescript' +import { v4 as uuidv4 } from 'uuid' +import { MAccountId, MChannelId } from '@server/types/models' +import { ActivityIconObject } from '../../../shared/models/activitypub/objects' +import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' -import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getPlaylistSort, getPlaylistSort, isOutdated, throwIfNotValid } from '../utils' +import { VideoPlaylistType } from '../../../shared/models/videos/playlist/video-playlist-type.model' +import { VideoPlaylist } from '../../../shared/models/videos/playlist/video-playlist.model' +import { activityPubCollectionPagination } from '../../helpers/activitypub' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { isVideoPlaylistDescriptionValid, isVideoPlaylistNameValid, isVideoPlaylistPrivacyValid } from '../../helpers/custom-validators/video-playlists' -import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { ACTIVITY_PUB, CONSTRAINTS_FIELDS, @@ -32,18 +40,7 @@ import { VIDEO_PLAYLIST_TYPES, WEBSERVER } from '../../initializers/constants' -import { VideoPlaylist } from '../../../shared/models/videos/playlist/video-playlist.model' -import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account' -import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' -import { join } from 'path' -import { VideoPlaylistElementModel } from './video-playlist-element' -import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' -import { activityPubCollectionPagination } from '../../helpers/activitypub' -import { VideoPlaylistType } from '../../../shared/models/videos/playlist/video-playlist-type.model' -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 { MThumbnail } from '../../types/models/video/thumbnail' import { MVideoPlaylistAccountThumbnail, MVideoPlaylistAP, @@ -52,8 +49,12 @@ import { MVideoPlaylistFullSummary, MVideoPlaylistIdWithElements } from '../../types/models/video/video-playlist' -import { MThumbnail } from '../../types/models/video/thumbnail' -import { MAccountId, MChannelId } from '@server/types/models' +import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account' +import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getPlaylistSort, isOutdated, throwIfNotValid } from '../utils' +import { ThumbnailModel } from './thumbnail' +import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' +import { VideoPlaylistElementModel } from './video-playlist-element' +import { ActorModel } from '../activitypub/actor' enum ScopeNames { AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST', @@ -65,7 +66,7 @@ enum ScopeNames { } type AvailableForListOptions = { - followerActorId: number + followerActorId?: number type?: VideoPlaylistType accountId?: number videoChannelId?: number @@ -125,7 +126,6 @@ type AvailableForListOptions = { ] }, [ScopeNames.AVAILABLE_FOR_LIST]: (options: AvailableForListOptions) => { - let whereActor: WhereOptions = {} const whereAnd: WhereOptions[] = [] @@ -135,20 +135,26 @@ type AvailableForListOptions = { privacy: VideoPlaylistPrivacy.PUBLIC }) - // Only list local playlists OR playlists that are on an instance followed by actorId - const inQueryInstanceFollow = buildServerIdsFollowedBy(options.followerActorId) + // Only list local playlists + const whereActorOr: WhereOptions[] = [ + { + serverId: null + } + ] - whereActor = { - [Op.or]: [ - { - serverId: null - }, - { - serverId: { - [Op.in]: literal(inQueryInstanceFollow) - } + // … OR playlists that are on an instance followed by actorId + if (options.followerActorId) { + const inQueryInstanceFollow = buildServerIdsFollowedBy(options.followerActorId) + + whereActorOr.push({ + serverId: { + [Op.in]: literal(inQueryInstanceFollow) } - ] + }) + } + + whereActor = { + [Op.or]: whereActorOr } } @@ -182,15 +188,13 @@ type AvailableForListOptions = { [Op.and]: whereAnd } - const accountScope = { - method: [ AccountScopeNames.SUMMARY, { whereActor } as SummaryOptions ] - } - return { where, include: [ { - model: AccountModel.scope(accountScope), + model: AccountModel.scope({ + method: [ AccountScopeNames.SUMMARY, { whereActor } as SummaryOptions ] + }), required: true }, { @@ -217,7 +221,7 @@ type AvailableForListOptions = { } ] }) -export class VideoPlaylistModel extends Model { +export class VideoPlaylistModel extends Model { @CreatedAt createdAt: Date @@ -367,7 +371,7 @@ export class VideoPlaylistModel extends Model { }) } - static listPlaylistIdsOf (accountId: number, videoIds: number[]): Bluebird { + static listPlaylistIdsOf (accountId: number, videoIds: number[]): Promise { const query = { attributes: [ 'id' ], where: { @@ -392,7 +396,7 @@ export class VideoPlaylistModel extends Model { static doesPlaylistExist (url: string) { const query = { - attributes: [], + attributes: [ 'id' ], where: { url } @@ -403,7 +407,7 @@ export class VideoPlaylistModel extends Model { .then(e => !!e) } - static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Bluebird { + static loadWithAccountAndChannelSummary (id: number | string, transaction: Transaction): Promise { const where = buildWhereIdOrUUID(id) const query = { @@ -416,7 +420,7 @@ export class VideoPlaylistModel extends Model { .findOne(query) } - static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Bluebird { + static loadWithAccountAndChannel (id: number | string, transaction: Transaction): Promise { const where = buildWhereIdOrUUID(id) const query = { @@ -429,7 +433,7 @@ export class VideoPlaylistModel extends Model { .findOne(query) } - static loadByUrlAndPopulateAccount (url: string): Bluebird { + static loadByUrlAndPopulateAccount (url: string): Promise { const query = { where: { url @@ -475,7 +479,7 @@ export class VideoPlaylistModel extends Model { generateThumbnailName () { const extension = '.jpg' - return 'playlist-' + this.uuid + extension + return 'playlist-' + uuidv4() + extension } getThumbnailUrl () { @@ -498,6 +502,33 @@ export class VideoPlaylistModel extends Model { return '/video-playlists/embed/' + this.uuid } + static async getStats () { + const totalLocalPlaylists = await VideoPlaylistModel.count({ + include: [ + { + model: AccountModel, + required: true, + include: [ + { + model: ActorModel, + required: true, + where: { + serverId: null + } + } + ] + } + ], + where: { + privacy: VideoPlaylistPrivacy.PUBLIC + } + }) + + return { + totalLocalPlaylists + } + } + setAsRefreshed () { this.changed('updatedAt', true)