]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/video/video-import.ts
Add reason when banning a user
[github/Chocobozzz/PeerTube.git] / server / models / video / video-import.ts
index 89eeafd6a1603c0940b619b13c8678d10d8339e2..b794d83244af4361e234673d822af2ea2b24b875 100644 (file)
@@ -1,4 +1,5 @@
 import {
+  AfterUpdate,
   AllowNull,
   BelongsTo,
   Column,
@@ -12,31 +13,23 @@ import {
   Table,
   UpdatedAt
 } from 'sequelize-typescript'
-import { CONSTRAINTS_FIELDS } from '../../initializers'
-import { throwIfNotValid } from '../utils'
-import { VideoModel } from './video'
+import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers'
+import { getSort, throwIfNotValid } from '../utils'
+import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
 import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
 import { VideoImport, VideoImportState } from '../../../shared'
-import { VideoChannelModel } from './video-channel'
-import { AccountModel } from '../account/account'
+import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
+import { UserModel } from '../account/user'
 
 @DefaultScope({
   include: [
     {
-      model: () => VideoModel,
-      required: true,
-      include: [
-        {
-          model: () => VideoChannelModel,
-          required: true,
-          include: [
-            {
-              model: () => AccountModel,
-              required: true
-            }
-          ]
-        }
-      ]
+      model: () => UserModel.unscoped(),
+      required: true
+    },
+    {
+      model: () => VideoModel.scope([ VideoModelScopeNames.WITH_ACCOUNT_DETAILS, VideoModelScopeNames.WITH_TAGS]),
+      required: false
     }
   ]
 })
@@ -47,6 +40,9 @@ import { AccountModel } from '../account/account'
     {
       fields: [ 'videoId' ],
       unique: true
+    },
+    {
+      fields: [ 'userId' ]
     }
   ]
 })
@@ -57,11 +53,23 @@ export class VideoImportModel extends Model<VideoImportModel> {
   @UpdatedAt
   updatedAt: Date
 
-  @AllowNull(false)
+  @AllowNull(true)
+  @Default(null)
   @Is('VideoImportTargetUrl', value => throwIfNotValid(value, isVideoImportTargetUrlValid, 'targetUrl'))
   @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.URL.max))
   targetUrl: string
 
+  @AllowNull(true)
+  @Default(null)
+  @Is('VideoImportMagnetUri', value => throwIfNotValid(value, isVideoMagnetUriValid, 'magnetUri'))
+  @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.URL.max)) // Use the same constraints than URLs
+  magnetUri: string
+
+  @AllowNull(true)
+  @Default(null)
+  @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_NAME.max))
+  torrentName: string
+
   @AllowNull(false)
   @Default(null)
   @Is('VideoImportState', value => throwIfNotValid(value, isVideoImportStateValid, 'state'))
@@ -73,33 +81,97 @@ export class VideoImportModel extends Model<VideoImportModel> {
   @Column(DataType.TEXT)
   error: string
 
+  @ForeignKey(() => UserModel)
+  @Column
+  userId: number
+
+  @BelongsTo(() => UserModel, {
+    foreignKey: {
+      allowNull: false
+    },
+    onDelete: 'cascade'
+  })
+  User: UserModel
+
   @ForeignKey(() => VideoModel)
   @Column
   videoId: number
 
   @BelongsTo(() => VideoModel, {
     foreignKey: {
-      allowNull: false
+      allowNull: true
     },
-    onDelete: 'CASCADE'
+    onDelete: 'set null'
   })
   Video: VideoModel
 
+  @AfterUpdate
+  static deleteVideoIfFailed (instance: VideoImportModel, options) {
+    if (instance.state === VideoImportState.FAILED) {
+      return instance.Video.destroy({ transaction: options.transaction })
+    }
+
+    return undefined
+  }
+
   static loadAndPopulateVideo (id: number) {
     return VideoImportModel.findById(id)
   }
 
+  static listUserVideoImportsForApi (userId: number, start: number, count: number, sort: string) {
+    const query = {
+      distinct: true,
+      include: [
+        {
+          model: UserModel.unscoped(), // FIXME: Without this, sequelize try to COUNT(DISTINCT(*)) which is an invalid SQL query
+          required: true
+        }
+      ],
+      offset: start,
+      limit: count,
+      order: getSort(sort),
+      where: {
+        userId
+      }
+    }
+
+    return VideoImportModel.findAndCountAll(query)
+                           .then(({ rows, count }) => {
+                             return {
+                               data: rows,
+                               total: count
+                             }
+                           })
+  }
+
   toFormattedJSON (): VideoImport {
     const videoFormatOptions = {
       additionalAttributes: { state: true, waitTranscoding: true, scheduledUpdate: true }
     }
-    const video = Object.assign(this.Video.toFormattedJSON(videoFormatOptions), {
-      tags: this.Video.Tags.map(t => t.name)
-    })
+    const video = this.Video
+      ? Object.assign(this.Video.toFormattedJSON(videoFormatOptions), {
+        tags: this.Video.Tags.map(t => t.name)
+      })
+      : undefined
 
     return {
+      id: this.id,
+
       targetUrl: this.targetUrl,
+      magnetUri: this.magnetUri,
+      torrentName: this.torrentName,
+
+      state: {
+        id: this.state,
+        label: VideoImportModel.getStateLabel(this.state)
+      },
+      error: this.error,
+      updatedAt: this.updatedAt.toISOString(),
+      createdAt: this.createdAt.toISOString(),
       video
     }
   }
+  private static getStateLabel (id: number) {
+    return VIDEO_IMPORT_STATES[id] || 'Unknown'
+  }
 }