diff options
Diffstat (limited to 'server/models/video/video.ts')
-rw-r--r-- | server/models/video/video.ts | 131 |
1 files changed, 68 insertions, 63 deletions
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 1e5648a36..56a5b0e18 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -24,14 +24,14 @@ import { | |||
24 | Table, | 24 | Table, |
25 | UpdatedAt | 25 | UpdatedAt |
26 | } from 'sequelize-typescript' | 26 | } from 'sequelize-typescript' |
27 | import { setAsUpdated } from '@server/helpers/database-utils' | ||
28 | import { buildNSFWFilter } from '@server/helpers/express-utils' | 27 | import { buildNSFWFilter } from '@server/helpers/express-utils' |
28 | import { uuidToShort } from '@server/helpers/uuid' | ||
29 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' | 29 | import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' |
30 | import { LiveManager } from '@server/lib/live/live-manager' | 30 | import { LiveManager } from '@server/lib/live/live-manager' |
31 | import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' | 31 | import { getHLSDirectory, getVideoFilePath } from '@server/lib/video-paths' |
32 | import { getServerActor } from '@server/models/application/application' | 32 | import { getServerActor } from '@server/models/application/application' |
33 | import { ModelCache } from '@server/models/model-cache' | 33 | import { ModelCache } from '@server/models/model-cache' |
34 | import { AttributesOnly } from '@shared/core-utils' | 34 | import { AttributesOnly, buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils' |
35 | import { VideoFile } from '@shared/models/videos/video-file.model' | 35 | import { VideoFile } from '@shared/models/videos/video-file.model' |
36 | import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' | 36 | import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' |
37 | import { VideoObject } from '../../../shared/models/activitypub/objects' | 37 | import { VideoObject } from '../../../shared/models/activitypub/objects' |
@@ -91,6 +91,7 @@ import { VideoRedundancyModel } from '../redundancy/video-redundancy' | |||
91 | import { ServerModel } from '../server/server' | 91 | import { ServerModel } from '../server/server' |
92 | import { TrackerModel } from '../server/tracker' | 92 | import { TrackerModel } from '../server/tracker' |
93 | import { VideoTrackerModel } from '../server/video-tracker' | 93 | import { VideoTrackerModel } from '../server/video-tracker' |
94 | import { setAsUpdated } from '../shared' | ||
94 | import { UserModel } from '../user/user' | 95 | import { UserModel } from '../user/user' |
95 | import { UserVideoHistoryModel } from '../user/user-video-history' | 96 | import { UserVideoHistoryModel } from '../user/user-video-history' |
96 | import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils' | 97 | import { buildTrigramSearchIndex, buildWhereIdOrUUID, getVideoSort, isOutdated, throwIfNotValid } from '../utils' |
@@ -762,8 +763,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
762 | 763 | ||
763 | // Remove physical files and torrents | 764 | // Remove physical files and torrents |
764 | instance.VideoFiles.forEach(file => { | 765 | instance.VideoFiles.forEach(file => { |
765 | tasks.push(instance.removeFile(file)) | 766 | tasks.push(instance.removeFileAndTorrent(file)) |
766 | tasks.push(file.removeTorrent()) | ||
767 | }) | 767 | }) |
768 | 768 | ||
769 | // Remove playlists file | 769 | // Remove playlists file |
@@ -1070,7 +1070,8 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1070 | const trendingDays = options.sort.endsWith('trending') | 1070 | const trendingDays = options.sort.endsWith('trending') |
1071 | ? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS | 1071 | ? CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS |
1072 | : undefined | 1072 | : undefined |
1073 | let trendingAlgorithm | 1073 | |
1074 | let trendingAlgorithm: string | ||
1074 | if (options.sort.endsWith('hot')) trendingAlgorithm = 'hot' | 1075 | if (options.sort.endsWith('hot')) trendingAlgorithm = 'hot' |
1075 | if (options.sort.endsWith('best')) trendingAlgorithm = 'best' | 1076 | if (options.sort.endsWith('best')) trendingAlgorithm = 'best' |
1076 | 1077 | ||
@@ -1082,40 +1083,44 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1082 | : serverActor.id | 1083 | : serverActor.id |
1083 | 1084 | ||
1084 | const queryOptions = { | 1085 | const queryOptions = { |
1085 | start: options.start, | 1086 | ...pick(options, [ |
1086 | count: options.count, | 1087 | 'start', |
1087 | sort: options.sort, | 1088 | 'count', |
1089 | 'sort', | ||
1090 | 'nsfw', | ||
1091 | 'isLive', | ||
1092 | 'categoryOneOf', | ||
1093 | 'licenceOneOf', | ||
1094 | 'languageOneOf', | ||
1095 | 'tagsOneOf', | ||
1096 | 'tagsAllOf', | ||
1097 | 'filter', | ||
1098 | 'withFiles', | ||
1099 | 'accountId', | ||
1100 | 'videoChannelId', | ||
1101 | 'videoPlaylistId', | ||
1102 | 'includeLocalVideos', | ||
1103 | 'user', | ||
1104 | 'historyOfUser', | ||
1105 | 'search' | ||
1106 | ]), | ||
1107 | |||
1088 | followerActorId, | 1108 | followerActorId, |
1089 | serverAccountId: serverActor.Account.id, | 1109 | serverAccountId: serverActor.Account.id, |
1090 | nsfw: options.nsfw, | ||
1091 | isLive: options.isLive, | ||
1092 | categoryOneOf: options.categoryOneOf, | ||
1093 | licenceOneOf: options.licenceOneOf, | ||
1094 | languageOneOf: options.languageOneOf, | ||
1095 | tagsOneOf: options.tagsOneOf, | ||
1096 | tagsAllOf: options.tagsAllOf, | ||
1097 | filter: options.filter, | ||
1098 | withFiles: options.withFiles, | ||
1099 | accountId: options.accountId, | ||
1100 | videoChannelId: options.videoChannelId, | ||
1101 | videoPlaylistId: options.videoPlaylistId, | ||
1102 | includeLocalVideos: options.includeLocalVideos, | ||
1103 | user: options.user, | ||
1104 | historyOfUser: options.historyOfUser, | ||
1105 | trendingDays, | 1110 | trendingDays, |
1106 | trendingAlgorithm, | 1111 | trendingAlgorithm |
1107 | search: options.search | ||
1108 | } | 1112 | } |
1109 | 1113 | ||
1110 | return VideoModel.getAvailableForApi(queryOptions, options.countVideos) | 1114 | return VideoModel.getAvailableForApi(queryOptions, options.countVideos) |
1111 | } | 1115 | } |
1112 | 1116 | ||
1113 | static async searchAndPopulateAccountAndServer (options: { | 1117 | static async searchAndPopulateAccountAndServer (options: { |
1118 | start: number | ||
1119 | count: number | ||
1120 | sort: string | ||
1114 | includeLocalVideos: boolean | 1121 | includeLocalVideos: boolean |
1115 | search?: string | 1122 | search?: string |
1116 | start?: number | 1123 | host?: string |
1117 | count?: number | ||
1118 | sort?: string | ||
1119 | startDate?: string // ISO 8601 | 1124 | startDate?: string // ISO 8601 |
1120 | endDate?: string // ISO 8601 | 1125 | endDate?: string // ISO 8601 |
1121 | originallyPublishedStartDate?: string | 1126 | originallyPublishedStartDate?: string |
@@ -1131,41 +1136,38 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1131 | durationMax?: number // seconds | 1136 | durationMax?: number // seconds |
1132 | user?: MUserAccountId | 1137 | user?: MUserAccountId |
1133 | filter?: VideoFilter | 1138 | filter?: VideoFilter |
1139 | uuids?: string[] | ||
1134 | }) { | 1140 | }) { |
1135 | const serverActor = await getServerActor() | 1141 | const serverActor = await getServerActor() |
1136 | 1142 | ||
1137 | const queryOptions = { | 1143 | const queryOptions = { |
1138 | followerActorId: serverActor.id, | 1144 | ...pick(options, [ |
1139 | serverAccountId: serverActor.Account.id, | 1145 | 'includeLocalVideos', |
1140 | 1146 | 'nsfw', | |
1141 | includeLocalVideos: options.includeLocalVideos, | 1147 | 'isLive', |
1142 | nsfw: options.nsfw, | 1148 | 'categoryOneOf', |
1143 | isLive: options.isLive, | 1149 | 'licenceOneOf', |
1144 | 1150 | 'languageOneOf', | |
1145 | categoryOneOf: options.categoryOneOf, | 1151 | 'tagsOneOf', |
1146 | licenceOneOf: options.licenceOneOf, | 1152 | 'tagsAllOf', |
1147 | languageOneOf: options.languageOneOf, | 1153 | 'user', |
1154 | 'filter', | ||
1155 | 'host', | ||
1156 | 'start', | ||
1157 | 'count', | ||
1158 | 'sort', | ||
1159 | 'startDate', | ||
1160 | 'endDate', | ||
1161 | 'originallyPublishedStartDate', | ||
1162 | 'originallyPublishedEndDate', | ||
1163 | 'durationMin', | ||
1164 | 'durationMax', | ||
1165 | 'uuids', | ||
1166 | 'search' | ||
1167 | ]), | ||
1148 | 1168 | ||
1149 | tagsOneOf: options.tagsOneOf, | 1169 | followerActorId: serverActor.id, |
1150 | tagsAllOf: options.tagsAllOf, | 1170 | serverAccountId: serverActor.Account.id |
1151 | |||
1152 | user: options.user, | ||
1153 | filter: options.filter, | ||
1154 | |||
1155 | start: options.start, | ||
1156 | count: options.count, | ||
1157 | sort: options.sort, | ||
1158 | |||
1159 | startDate: options.startDate, | ||
1160 | endDate: options.endDate, | ||
1161 | |||
1162 | originallyPublishedStartDate: options.originallyPublishedStartDate, | ||
1163 | originallyPublishedEndDate: options.originallyPublishedEndDate, | ||
1164 | |||
1165 | durationMin: options.durationMin, | ||
1166 | durationMax: options.durationMax, | ||
1167 | |||
1168 | search: options.search | ||
1169 | } | 1171 | } |
1170 | 1172 | ||
1171 | return VideoModel.getAvailableForApi(queryOptions) | 1173 | return VideoModel.getAvailableForApi(queryOptions) |
@@ -1579,11 +1581,11 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1579 | } | 1581 | } |
1580 | 1582 | ||
1581 | getWatchStaticPath () { | 1583 | getWatchStaticPath () { |
1582 | return '/w/' + this.uuid | 1584 | return buildVideoWatchPath({ shortUUID: uuidToShort(this.uuid) }) |
1583 | } | 1585 | } |
1584 | 1586 | ||
1585 | getEmbedStaticPath () { | 1587 | getEmbedStaticPath () { |
1586 | return '/videos/embed/' + this.uuid | 1588 | return buildVideoEmbedPath(this) |
1587 | } | 1589 | } |
1588 | 1590 | ||
1589 | getMiniatureStaticPath () { | 1591 | getMiniatureStaticPath () { |
@@ -1670,10 +1672,13 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> { | |||
1670 | .concat(toAdd) | 1672 | .concat(toAdd) |
1671 | } | 1673 | } |
1672 | 1674 | ||
1673 | removeFile (videoFile: MVideoFile, isRedundancy = false) { | 1675 | removeFileAndTorrent (videoFile: MVideoFile, isRedundancy = false) { |
1674 | const filePath = getVideoFilePath(this, videoFile, isRedundancy) | 1676 | const filePath = getVideoFilePath(this, videoFile, isRedundancy) |
1675 | return remove(filePath) | 1677 | |
1676 | .catch(err => logger.warn('Cannot delete file %s.', filePath, { err })) | 1678 | const promises: Promise<any>[] = [ remove(filePath) ] |
1679 | if (!isRedundancy) promises.push(videoFile.removeTorrent()) | ||
1680 | |||
1681 | return Promise.all(promises) | ||
1677 | } | 1682 | } |
1678 | 1683 | ||
1679 | async removeStreamingPlaylistFiles (streamingPlaylist: MStreamingPlaylist, isRedundancy = false) { | 1684 | async removeStreamingPlaylistFiles (streamingPlaylist: MStreamingPlaylist, isRedundancy = false) { |