MVideoWithRights
} from '../../types/models'
import { MThumbnail } from '../../types/models/video/thumbnail'
-import { MVideoFile, MVideoFileRedundanciesOpt, MVideoFileStreamingPlaylistVideo } from '../../types/models/video/video-file'
+import { MVideoFile, MVideoFileStreamingPlaylistVideo } from '../../types/models/video/video-file'
import { VideoAbuseModel } from '../abuse/video-abuse'
import { AccountModel } from '../account/account'
import { AccountVideoRateModel } from '../account/account-video-rate'
+import { UserModel } from '../account/user'
import { UserVideoHistoryModel } from '../account/user-video-history'
import { ActorModel } from '../activitypub/actor'
import { AvatarModel } from '../avatar/avatar'
import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
import { VideoTagModel } from './video-tag'
import { VideoViewModel } from './video-view'
+import { v4 as uuidv4 } from 'uuid'
export enum ScopeNames {
AVAILABLE_FOR_LIST_IDS = 'AVAILABLE_FOR_LIST_IDS',
videoPlaylistId?: number
- withFiles?: boolean
-
withAccountBlockerIds?: number[]
}
}
}
- if (options.withFiles === true) {
- include.push({
- model: VideoFileModel,
- required: true
- })
- }
-
if (options.videoPlaylistId) {
include.push({
model: VideoPlaylistElementModel.unscoped(),
include: [
{
model: VideoFileModel,
- separate: true, // We may have multiple files, having multiple redundancies so let's separate this join
required: false,
include: subInclude
}
include: [
{
model: VideoStreamingPlaylistModel.unscoped(),
- separate: true, // We may have multiple streaming playlists, having multiple redundancies so let's separate this join
required: false,
include: subInclude
}
return result.map(v => v.id)
}
- static listUserVideosForApi (
- accountId: number,
- start: number,
- count: number,
- sort: string,
+ static listUserVideosForApi (options: {
+ accountId: number
+ start: number
+ count: number
+ sort: string
search?: string
- ) {
+ }) {
+ const { accountId, start, count, sort, search } = options
+
function buildBaseQuery (): FindOptions {
let baseQuery = {
offset: start,
const trendingDays = options.sort.endsWith('trending')
? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS
: undefined
+ let trendingAlgorithm
+ if (options.sort.endsWith('hot')) trendingAlgorithm = 'hot'
+ if (options.sort.endsWith('best')) trendingAlgorithm = 'best'
const serverActor = await getServerActor()
user: options.user,
historyOfUser: options.historyOfUser,
trendingDays,
+ trendingAlgorithm,
search: options.search
}
return VideoModel.count(options)
}
+ static countVideosUploadedByUserSince (userId: number, since: Date) {
+ const options = {
+ include: [
+ {
+ model: VideoChannelModel.unscoped(),
+ required: true,
+ include: [
+ {
+ model: AccountModel.unscoped(),
+ required: true,
+ include: [
+ {
+ model: UserModel.unscoped(),
+ required: true,
+ where: {
+ id: userId
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ where: {
+ createdAt: {
+ [Op.gte]: since
+ }
+ }
+ }
+
+ return VideoModel.unscoped().count(options)
+ }
+
static countLivesOfAccount (accountId: number) {
const options = {
where: {
const avatarKeys = [ 'id', 'filename', 'fileUrl', 'onDisk', 'createdAt', 'updatedAt' ]
const actorKeys = [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ]
const serverKeys = [ 'id', 'host' ]
- const videoFileKeys = [ 'id', 'createdAt', 'updatedAt', 'resolution', 'size', 'extname', 'infoHash', 'fps', 'videoId' ]
- const videoStreamingPlaylistKeys = [ 'id' ]
+ const videoFileKeys = [
+ 'id',
+ 'createdAt',
+ 'updatedAt',
+ 'resolution',
+ 'size',
+ 'extname',
+ 'infoHash',
+ 'fps',
+ 'videoId',
+ 'videoStreamingPlaylistId'
+ ]
+ const videoStreamingPlaylistKeys = [ 'id', 'type', 'playlistUrl' ]
const videoKeys = [
'id',
'uuid',
'createdAt',
'updatedAt'
]
+ const buildOpts = { raw: true }
function buildActor (rowActor: any) {
const avatarModel = rowActor.Avatar.id !== null
- ? new AvatarModel(pick(rowActor.Avatar, avatarKeys))
+ ? new AvatarModel(pick(rowActor.Avatar, avatarKeys), buildOpts)
: null
const serverModel = rowActor.Server.id !== null
- ? new ServerModel(pick(rowActor.Server, serverKeys))
+ ? new ServerModel(pick(rowActor.Server, serverKeys), buildOpts)
: null
- const actorModel = new ActorModel(pick(rowActor, actorKeys))
+ const actorModel = new ActorModel(pick(rowActor, actorKeys), buildOpts)
actorModel.Avatar = avatarModel
actorModel.Server = serverModel
if (!videosMemo[row.id]) {
// Build Channel
const channel = row.VideoChannel
- const channelModel = new VideoChannelModel(pick(channel, [ 'id', 'name', 'description', 'actorId' ]))
+ const channelModel = new VideoChannelModel(pick(channel, [ 'id', 'name', 'description', 'actorId' ]), buildOpts)
channelModel.Actor = buildActor(channel.Actor)
const account = row.VideoChannel.Account
- const accountModel = new AccountModel(pick(account, [ 'id', 'name' ]))
+ const accountModel = new AccountModel(pick(account, [ 'id', 'name' ]), buildOpts)
accountModel.Actor = buildActor(account.Actor)
channelModel.Account = accountModel
- const videoModel = new VideoModel(pick(row, videoKeys))
+ const videoModel = new VideoModel(pick(row, videoKeys), buildOpts)
videoModel.VideoChannel = channelModel
videoModel.UserVideoHistories = []
const videoModel = videosMemo[row.id]
if (row.userVideoHistory?.id && !historyDone.has(row.userVideoHistory.id)) {
- const historyModel = new UserVideoHistoryModel(pick(row.userVideoHistory, [ 'id', 'currentTime' ]))
+ const historyModel = new UserVideoHistoryModel(pick(row.userVideoHistory, [ 'id', 'currentTime' ]), buildOpts)
videoModel.UserVideoHistories.push(historyModel)
historyDone.add(row.userVideoHistory.id)
}
if (row.Thumbnails?.id && !thumbnailsDone.has(row.Thumbnails.id)) {
- const thumbnailModel = new ThumbnailModel(pick(row.Thumbnails, [ 'id', 'type', 'filename' ]))
+ const thumbnailModel = new ThumbnailModel(pick(row.Thumbnails, [ 'id', 'type', 'filename' ]), buildOpts)
videoModel.Thumbnails.push(thumbnailModel)
thumbnailsDone.add(row.Thumbnails.id)
}
if (row.VideoFiles?.id && !videoFilesDone.has(row.VideoFiles.id)) {
- const videoFileModel = new VideoFileModel(pick(row.VideoFiles, videoFileKeys))
+ const videoFileModel = new VideoFileModel(pick(row.VideoFiles, videoFileKeys), buildOpts)
videoModel.VideoFiles.push(videoFileModel)
videoFilesDone.add(row.VideoFiles.id)
}
if (row.VideoStreamingPlaylists?.id && !videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id]) {
- const streamingPlaylist = new VideoStreamingPlaylistModel(pick(row.VideoStreamingPlaylists, videoStreamingPlaylistKeys))
+ const streamingPlaylist = new VideoStreamingPlaylistModel(pick(row.VideoStreamingPlaylists, videoStreamingPlaylistKeys), buildOpts)
streamingPlaylist.VideoFiles = []
videoModel.VideoStreamingPlaylists.push(streamingPlaylist)
if (row.VideoStreamingPlaylists?.VideoFiles?.id && !videoFilesDone.has(row.VideoStreamingPlaylists.VideoFiles.id)) {
const streamingPlaylist = videoStreamingPlaylistMemo[row.VideoStreamingPlaylists.id]
- const videoFileModel = new VideoFileModel(pick(row.VideoStreamingPlaylists.VideoFiles, videoFileKeys))
+ const videoFileModel = new VideoFileModel(pick(row.VideoStreamingPlaylists.VideoFiles, videoFileKeys), buildOpts)
streamingPlaylist.VideoFiles.push(videoFileModel)
videoFilesDone.add(row.VideoStreamingPlaylists.VideoFiles.id)
}
getQualityFileBy<T extends MVideoWithFile> (this: T, fun: (files: MVideoFile[], it: (file: MVideoFile) => number) => MVideoFile) {
+ // We first transcode to WebTorrent format, so try this array first
if (Array.isArray(this.VideoFiles) && this.VideoFiles.length !== 0) {
const file = fun(this.VideoFiles, file => file.resolution)
return Object.assign(file, { Video: this })
}
+ hasWebTorrentFiles () {
+ return Array.isArray(this.VideoFiles) === true && this.VideoFiles.length !== 0
+ }
+
async addAndSaveThumbnail (thumbnail: MThumbnail, transaction: Transaction) {
thumbnail.videoId = this.id
}
generateThumbnailName () {
- return this.uuid + '.jpg'
+ return uuidv4() + '.jpg'
}
getMiniature () {
}
generatePreviewName () {
- return this.uuid + '.jpg'
+ return uuidv4() + '.jpg'
}
hasPreview () {
getFormattedVideoFilesJSON (): VideoFile[] {
const { baseUrlHttp, baseUrlWs } = this.getBaseUrls()
- let files: MVideoFileRedundanciesOpt[] = []
+ let files: VideoFile[] = []
if (Array.isArray(this.VideoFiles)) {
- files = files.concat(this.VideoFiles)
+ const result = videoFilesModelToFormattedJSON(this, baseUrlHttp, baseUrlWs, this.VideoFiles)
+ files = files.concat(result)
}
for (const p of (this.VideoStreamingPlaylists || [])) {
- files = files.concat(p.VideoFiles || [])
+ p.Video = this
+
+ const result = videoFilesModelToFormattedJSON(p, baseUrlHttp, baseUrlWs, p.VideoFiles)
+ files = files.concat(result)
}
- return videoFilesModelToFormattedJSON(this, baseUrlHttp, baseUrlWs, files)
+ return files
}
toActivityPubObject (this: MVideoAP): VideoObject {