Table,
UpdatedAt
} from 'sequelize-typescript'
+import { v4 as uuidv4 } from 'uuid'
import { buildNSFWFilter } from '@server/helpers/express-utils'
import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video'
import { LiveManager } from '@server/lib/live-manager'
-import { getHLSDirectory, getTorrentFileName, getTorrentFilePath, getVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
+import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths'
import { getServerActor } from '@server/models/application/application'
import { ModelCache } from '@server/models/model-cache'
import { VideoFile } from '@shared/models/videos/video-file.model'
API_VERSION,
CONSTRAINTS_FIELDS,
LAZY_STATIC_PATHS,
- REMOTE_SCHEME,
- STATIC_DOWNLOAD_PATHS,
STATIC_PATHS,
VIDEO_CATEGORIES,
VIDEO_LANGUAGES,
MStreamingPlaylistFilesVideo,
MUserAccountId,
MUserId,
+ MVideo,
MVideoAccountLight,
MVideoAccountLightBlacklistAllFiles,
MVideoAP,
import { AvatarModel } from '../avatar/avatar'
import { VideoRedundancyModel } from '../redundancy/video-redundancy'
import { ServerModel } from '../server/server'
+import { TrackerModel } from '../server/tracker'
+import { VideoTrackerModel } from '../server/video-tracker'
import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils'
import { ScheduleVideoUpdateModel } from './schedule-video-update'
import { TagModel } from './tag'
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',
FOR_API = 'FOR_API',
WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS',
WITH_TAGS = 'WITH_TAGS',
+ WITH_TRACKERS = 'WITH_TRACKERS',
WITH_WEBTORRENT_FILES = 'WITH_WEBTORRENT_FILES',
WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE',
WITH_BLACKLISTED = 'WITH_BLACKLISTED',
[ScopeNames.WITH_TAGS]: {
include: [ TagModel ]
},
+ [ScopeNames.WITH_TRACKERS]: {
+ include: [
+ {
+ attributes: [ 'id', 'url' ],
+ model: TrackerModel
+ }
+ ]
+ },
[ScopeNames.WITH_BLACKLISTED]: {
include: [
{
})
Tags: TagModel[]
+ @BelongsToMany(() => TrackerModel, {
+ foreignKey: 'videoId',
+ through: () => VideoTrackerModel,
+ onDelete: 'CASCADE'
+ })
+ Trackers: TrackerModel[]
+
@HasMany(() => ThumbnailModel, {
foreignKey: {
name: 'videoId',
// Remove physical files and torrents
instance.VideoFiles.forEach(file => {
tasks.push(instance.removeFile(file))
- tasks.push(instance.removeTorrent(file))
+ tasks.push(file.removeTorrent())
})
// Remove playlists file
return undefined
}
- static listLocal (): Promise<MVideoWithAllFiles[]> {
+ static listLocal (): Promise<MVideo[]> {
const query = {
where: {
remote: false
}
}
- return VideoModel.scope([
- ScopeNames.WITH_WEBTORRENT_FILES,
- ScopeNames.WITH_STREAMING_PLAYLISTS,
- ScopeNames.WITH_THUMBNAILS
- ]).findAll(query)
+ return VideoModel.findAll(query)
}
static listAllAndSharedByActorForOutbox (actorId: number, start: number, count: number) {
ScopeNames.WITH_SCHEDULED_UPDATE,
ScopeNames.WITH_THUMBNAILS,
ScopeNames.WITH_LIVE,
+ ScopeNames.WITH_TRACKERS,
{ method: [ ScopeNames.WITH_WEBTORRENT_FILES, true ] },
{ method: [ ScopeNames.WITH_STREAMING_PLAYLISTS, true ] }
]
'resolution',
'size',
'extname',
+ 'filename',
+ 'fileUrl',
+ 'torrentFilename',
+ 'torrentUrl',
'infoHash',
'fps',
'videoId',
return videoModelToFormattedDetailsJSON(this)
}
- getFormattedVideoFilesJSON (): VideoFile[] {
- const { baseUrlHttp, baseUrlWs } = this.getBaseUrls()
+ getFormattedVideoFilesJSON (includeMagnet = true): VideoFile[] {
let files: VideoFile[] = []
if (Array.isArray(this.VideoFiles)) {
- const result = videoFilesModelToFormattedJSON(this, baseUrlHttp, baseUrlWs, this.VideoFiles)
+ const result = videoFilesModelToFormattedJSON(this, this.VideoFiles, includeMagnet)
files = files.concat(result)
}
for (const p of (this.VideoStreamingPlaylists || [])) {
- p.Video = this
-
- const result = videoFilesModelToFormattedJSON(p, baseUrlHttp, baseUrlWs, p.VideoFiles)
+ const result = videoFilesModelToFormattedJSON(this, p.VideoFiles, includeMagnet)
files = files.concat(result)
}
.catch(err => logger.warn('Cannot delete file %s.', filePath, { err }))
}
- removeTorrent (videoFile: MVideoFile) {
- const torrentPath = getTorrentFilePath(this, videoFile)
- return remove(torrentPath)
- .catch(err => logger.warn('Cannot delete torrent %s.', torrentPath, { err }))
- }
-
async removeStreamingPlaylistFiles (streamingPlaylist: MStreamingPlaylist, isRedundancy = false) {
const directoryPath = getHLSDirectory(this, isRedundancy)
// Remove physical files and torrents
await Promise.all(
- streamingPlaylistWithFiles.VideoFiles.map(file => streamingPlaylistWithFiles.removeTorrent(file))
+ streamingPlaylistWithFiles.VideoFiles.map(file => file.removeTorrent())
)
}
}
return false
}
- getBaseUrls () {
- if (this.isOwned()) {
- return {
- baseUrlHttp: WEBSERVER.URL,
- baseUrlWs: WEBSERVER.WS + '://' + WEBSERVER.HOSTNAME + ':' + WEBSERVER.PORT
- }
- }
-
- return {
- baseUrlHttp: REMOTE_SCHEME.HTTP + '://' + this.VideoChannel.Account.Actor.Server.host,
- baseUrlWs: REMOTE_SCHEME.WS + '://' + this.VideoChannel.Account.Actor.Server.host
- }
- }
-
- getTrackerUrls (baseUrlHttp: string, baseUrlWs: string) {
- return [ baseUrlWs + '/tracker/socket', baseUrlHttp + '/tracker/announce' ]
- }
-
- getTorrentUrl (videoFile: MVideoFile, baseUrlHttp: string) {
- return baseUrlHttp + STATIC_PATHS.TORRENTS + getTorrentFileName(this, videoFile)
- }
-
- getTorrentDownloadUrl (videoFile: MVideoFile, baseUrlHttp: string) {
- return baseUrlHttp + STATIC_DOWNLOAD_PATHS.TORRENTS + getTorrentFileName(this, videoFile)
- }
-
- getVideoFileUrl (videoFile: MVideoFile, baseUrlHttp: string) {
- return baseUrlHttp + STATIC_PATHS.WEBSEED + getVideoFilename(this, videoFile)
- }
-
- getVideoFileMetadataUrl (videoFile: MVideoFile, baseUrlHttp: string) {
- const path = '/api/v1/videos/'
-
- return this.isOwned()
- ? baseUrlHttp + path + this.uuid + '/metadata/' + videoFile.id
- : videoFile.metadataUrl
- }
-
- getVideoRedundancyUrl (videoFile: MVideoFile, baseUrlHttp: string) {
- return baseUrlHttp + STATIC_PATHS.REDUNDANCY + getVideoFilename(this, videoFile)
+ getBandwidthBits (videoFile: MVideoFile) {
+ return Math.ceil((videoFile.size * 8) / this.duration)
}
- getVideoFileDownloadUrl (videoFile: MVideoFile, baseUrlHttp: string) {
- return baseUrlHttp + STATIC_DOWNLOAD_PATHS.VIDEOS + getVideoFilename(this, videoFile)
- }
+ getTrackerUrls () {
+ if (this.isOwned()) {
+ return [
+ WEBSERVER.URL + '/tracker/announce',
+ WEBSERVER.WS + '://' + WEBSERVER.HOSTNAME + ':' + WEBSERVER.PORT + '/tracker/socket'
+ ]
+ }
- getBandwidthBits (videoFile: MVideoFile) {
- return Math.ceil((videoFile.size * 8) / this.duration)
+ return this.Trackers.map(t => t.url)
}
}