- VideoClass,
- VideoInstance,
- VideoAttributes,
-
- VideoMethods
-} from './video-interface'
-
-let Video: Sequelize.Model<VideoInstance, VideoAttributes>
-let generateMagnetUri: VideoMethods.GenerateMagnetUri
-let getVideoFilename: VideoMethods.GetVideoFilename
-let getThumbnailName: VideoMethods.GetThumbnailName
-let getPreviewName: VideoMethods.GetPreviewName
-let getTorrentName: VideoMethods.GetTorrentName
-let isOwned: VideoMethods.IsOwned
-let toFormatedJSON: VideoMethods.ToFormatedJSON
-let toAddRemoteJSON: VideoMethods.ToAddRemoteJSON
-let toUpdateRemoteJSON: VideoMethods.ToUpdateRemoteJSON
-let transcodeVideofile: VideoMethods.TranscodeVideofile
-
-let generateThumbnailFromData: VideoMethods.GenerateThumbnailFromData
-let getDurationFromFile: VideoMethods.GetDurationFromFile
-let list: VideoMethods.List
-let listForApi: VideoMethods.ListForApi
-let loadByHostAndRemoteId: VideoMethods.LoadByHostAndRemoteId
-let listOwnedAndPopulateAuthorAndTags: VideoMethods.ListOwnedAndPopulateAuthorAndTags
-let listOwnedByAuthor: VideoMethods.ListOwnedByAuthor
-let load: VideoMethods.Load
-let loadAndPopulateAuthor: VideoMethods.LoadAndPopulateAuthor
-let loadAndPopulateAuthorAndPodAndTags: VideoMethods.LoadAndPopulateAuthorAndPodAndTags
-let searchAndPopulateAuthorAndPodAndTags: VideoMethods.SearchAndPopulateAuthorAndPodAndTags
-
-export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
- Video = sequelize.define<VideoInstance, VideoAttributes>('Video',
- {
- id: {
- type: DataTypes.UUID,
- defaultValue: DataTypes.UUIDV4,
- primaryKey: true,
- validate: {
- isUUID: 4
- }
- },
- name: {
- type: DataTypes.STRING,
- allowNull: false,
- validate: {
- nameValid: function (value) {
- const res = isVideoNameValid(value)
- if (res === false) throw new Error('Video name is not valid.')
- }
- }
- },
- extname: {
- type: DataTypes.ENUM(values(CONSTRAINTS_FIELDS.VIDEOS.EXTNAME)),
- allowNull: false
- },
- remoteId: {
- type: DataTypes.UUID,
- allowNull: true,
- validate: {
- isUUID: 4
- }
- },
- category: {
- type: DataTypes.INTEGER,
- allowNull: false,
- validate: {
- categoryValid: function (value) {
- const res = isVideoCategoryValid(value)
- if (res === false) throw new Error('Video category is not valid.')
- }
- }
- },
- licence: {
- type: DataTypes.INTEGER,
- allowNull: false,
- defaultValue: null,
- validate: {
- licenceValid: function (value) {
- const res = isVideoLicenceValid(value)
- if (res === false) throw new Error('Video licence is not valid.')
- }
- }
- },
- language: {
- type: DataTypes.INTEGER,
- allowNull: true,
- validate: {
- languageValid: function (value) {
- const res = isVideoLanguageValid(value)
- if (res === false) throw new Error('Video language is not valid.')
- }
- }
- },
- nsfw: {
- type: DataTypes.BOOLEAN,
- allowNull: false,
- validate: {
- nsfwValid: function (value) {
- const res = isVideoNSFWValid(value)
- if (res === false) throw new Error('Video nsfw attribute is not valid.')
- }
- }
- },
- description: {
- type: DataTypes.STRING,
- allowNull: false,
- validate: {
- descriptionValid: function (value) {
- const res = isVideoDescriptionValid(value)
- if (res === false) throw new Error('Video description is not valid.')
- }
- }
- },
- infoHash: {
- type: DataTypes.STRING,
- allowNull: false,
- validate: {
- infoHashValid: function (value) {
- const res = isVideoInfoHashValid(value)
- if (res === false) throw new Error('Video info hash is not valid.')
- }
- }
- },
- duration: {
- type: DataTypes.INTEGER,
- allowNull: false,
- validate: {
- durationValid: function (value) {
- const res = isVideoDurationValid(value)
- if (res === false) throw new Error('Video duration is not valid.')
- }
- }
- },
- views: {
- type: DataTypes.INTEGER,
- allowNull: false,
- defaultValue: 0,
- validate: {
- min: 0,
- isInt: true
- }
- },
- likes: {
- type: DataTypes.INTEGER,
- allowNull: false,
- defaultValue: 0,
- validate: {
- min: 0,
- isInt: true
- }
- },
- dislikes: {
- type: DataTypes.INTEGER,
- allowNull: false,
- defaultValue: 0,
- validate: {
- min: 0,
- isInt: true
- }
- }
- },
- {
- indexes: [
- {
- fields: [ 'authorId' ]
- },
- {
- fields: [ 'remoteId' ]
- },
- {
- fields: [ 'name' ]
- },
- {
- fields: [ 'createdAt' ]
- },
- {
- fields: [ 'duration' ]
- },
- {
- fields: [ 'infoHash' ]
- },
- {
- fields: [ 'views' ]
- },
- {
- fields: [ 'likes' ]
- }
- ],
- hooks: {
- beforeValidate,
- beforeCreate,
- afterDestroy
- }
- }
- )
-
- const classMethods = [
- associate,
-
- generateThumbnailFromData,
- getDurationFromFile,
- list,
- listForApi,
- listOwnedAndPopulateAuthorAndTags,
- listOwnedByAuthor,
- load,
- loadByHostAndRemoteId,
- loadAndPopulateAuthor,
- loadAndPopulateAuthorAndPodAndTags,
- searchAndPopulateAuthorAndPodAndTags
- ]
- const instanceMethods = [
- generateMagnetUri,
- getVideoFilename,
- getThumbnailName,
- getPreviewName,
- getTorrentName,
- isOwned,
- toFormatedJSON,
- toAddRemoteJSON,
- toUpdateRemoteJSON,
- transcodeVideofile,
- removeFromBlacklist
- ]
- addMethodsToModel(Video, classMethods, instanceMethods)
-
- return Video
-}
-
-function beforeValidate (video: VideoInstance) {
- // Put a fake infoHash if it does not exists yet
- if (video.isOwned() && !video.infoHash) {
- // 40 hexa length
- video.infoHash = '0123456789abcdef0123456789abcdef01234567'
+ getVideoCommentsActivityPubUrl,
+ getVideoDislikesActivityPubUrl,
+ getVideoLikesActivityPubUrl,
+ getVideoSharesActivityPubUrl
+} from '../../lib/activitypub'
+import { sendDeleteVideo } from '../../lib/activitypub/send'
+import { AccountModel } from '../account/account'
+import { AccountVideoRateModel } from '../account/account-video-rate'
+import { ActorModel } from '../activitypub/actor'
+import { AvatarModel } from '../avatar/avatar'
+import { ServerModel } from '../server/server'
+import { buildTrigramSearchIndex, createSearchTrigramQuery, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils'
+import { TagModel } from './tag'
+import { VideoAbuseModel } from './video-abuse'
+import { VideoChannelModel } from './video-channel'
+import { VideoCommentModel } from './video-comment'
+import { VideoFileModel } from './video-file'
+import { VideoShareModel } from './video-share'
+import { VideoTagModel } from './video-tag'
+import { ScheduleVideoUpdateModel } from './schedule-video-update'
+import { VideoCaptionModel } from './video-caption'
+import { VideosSearchQuery } from '../../../shared/models/search'
+
+// FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation
+const indexes: Sequelize.DefineIndexesOptions[] = [
+ buildTrigramSearchIndex('video_name_trigram', 'name'),
+
+ { fields: [ 'createdAt' ] },
+ { fields: [ 'publishedAt' ] },
+ { fields: [ 'duration' ] },
+ { fields: [ 'category' ] },
+ { fields: [ 'licence' ] },
+ { fields: [ 'nsfw' ] },
+ { fields: [ 'language' ] },
+ { fields: [ 'waitTranscoding' ] },
+ { fields: [ 'state' ] },
+ { fields: [ 'remote' ] },
+ { fields: [ 'views' ] },
+ { fields: [ 'likes' ] },
+ { fields: [ 'channelId' ] },
+ {
+ fields: [ 'uuid' ],
+ unique: true
+ },
+ {
+ fields: [ 'url'],
+ unique: true