]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/video/video-import.ts
Translated using Weblate (Chinese (Simplified))
[github/Chocobozzz/PeerTube.git] / server / models / video / video-import.ts
CommitLineData
d511df28 1import { WhereOptions } from 'sequelize'
fbad87b0 2import {
ed31c059 3 AfterUpdate,
fbad87b0
C
4 AllowNull,
5 BelongsTo,
6 Column,
7 CreatedAt,
8 DataType,
9 Default,
10 DefaultScope,
11 ForeignKey,
12 Is,
13 Model,
14 Table,
15 UpdatedAt
16} from 'sequelize-typescript'
7d9ba5c0 17import { afterCommitIfTransaction } from '@server/helpers/database-utils'
b49f22d8 18import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import'
d17c7b4e 19import { VideoImport, VideoImportState } from '@shared/models'
6b5f72be 20import { AttributesOnly } from '@shared/typescript-utils'
b49f22d8 21import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
ce33919c 22import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
b49f22d8 23import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants'
7d9ba5c0 24import { UserModel } from '../user/user'
b49f22d8
C
25import { getSort, throwIfNotValid } from '../utils'
26import { ScopeNames as VideoModelScopeNames, VideoModel } from './video'
fbad87b0 27
3acc5084 28@DefaultScope(() => ({
fbad87b0
C
29 include: [
30 {
3acc5084 31 model: UserModel.unscoped(),
a84b8fa5
C
32 required: true
33 },
34 {
453e83ea
C
35 model: VideoModel.scope([
36 VideoModelScopeNames.WITH_ACCOUNT_DETAILS,
37 VideoModelScopeNames.WITH_TAGS,
38 VideoModelScopeNames.WITH_THUMBNAILS
39 ]),
a84b8fa5 40 required: false
fbad87b0
C
41 }
42 ]
3acc5084 43}))
fbad87b0
C
44
45@Table({
46 tableName: 'videoImport',
47 indexes: [
48 {
49 fields: [ 'videoId' ],
50 unique: true
a84b8fa5
C
51 },
52 {
53 fields: [ 'userId' ]
fbad87b0
C
54 }
55 ]
56})
16c016e8 57export class VideoImportModel extends Model<Partial<AttributesOnly<VideoImportModel>>> {
fbad87b0
C
58 @CreatedAt
59 createdAt: Date
60
61 @UpdatedAt
62 updatedAt: Date
63
ce33919c
C
64 @AllowNull(true)
65 @Default(null)
1735c825 66 @Is('VideoImportTargetUrl', value => throwIfNotValid(value, isVideoImportTargetUrlValid, 'targetUrl', true))
fbad87b0
C
67 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.URL.max))
68 targetUrl: string
69
ce33919c
C
70 @AllowNull(true)
71 @Default(null)
1735c825 72 @Is('VideoImportMagnetUri', value => throwIfNotValid(value, isVideoMagnetUriValid, 'magnetUri', true))
ce33919c
C
73 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.URL.max)) // Use the same constraints than URLs
74 magnetUri: string
75
76 @AllowNull(true)
77 @Default(null)
78 @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_NAME.max))
79 torrentName: string
80
fbad87b0
C
81 @AllowNull(false)
82 @Default(null)
83 @Is('VideoImportState', value => throwIfNotValid(value, isVideoImportStateValid, 'state'))
84 @Column
85 state: VideoImportState
86
87 @AllowNull(true)
88 @Default(null)
89 @Column(DataType.TEXT)
90 error: string
91
a84b8fa5
C
92 @ForeignKey(() => UserModel)
93 @Column
94 userId: number
95
96 @BelongsTo(() => UserModel, {
97 foreignKey: {
98 allowNull: false
99 },
100 onDelete: 'cascade'
101 })
102 User: UserModel
103
fbad87b0
C
104 @ForeignKey(() => VideoModel)
105 @Column
106 videoId: number
107
108 @BelongsTo(() => VideoModel, {
109 foreignKey: {
ed31c059 110 allowNull: true
fbad87b0 111 },
ed31c059 112 onDelete: 'set null'
fbad87b0
C
113 })
114 Video: VideoModel
115
ed31c059
C
116 @AfterUpdate
117 static deleteVideoIfFailed (instance: VideoImportModel, options) {
118 if (instance.state === VideoImportState.FAILED) {
44d1f7f2 119 return afterCommitIfTransaction(options.transaction, () => instance.Video.destroy())
ed31c059
C
120 }
121
122 return undefined
123 }
124
b49f22d8 125 static loadAndPopulateVideo (id: number): Promise<MVideoImportDefault> {
9b39106d 126 return VideoImportModel.findByPk(id)
fbad87b0
C
127 }
128
d511df28
C
129 static listUserVideoImportsForApi (options: {
130 userId: number
131 start: number
132 count: number
133 sort: string
134
135 targetUrl?: string
136 }) {
137 const { userId, start, count, sort, targetUrl } = options
138
139 const where: WhereOptions = { userId }
140
141 if (targetUrl) where['targetUrl'] = targetUrl
142
ed31c059 143 const query = {
590fb506 144 distinct: true,
ed31c059
C
145 include: [
146 {
652c6416 147 attributes: [ 'id' ],
a84b8fa5
C
148 model: UserModel.unscoped(), // FIXME: Without this, sequelize try to COUNT(DISTINCT(*)) which is an invalid SQL query
149 required: true
ed31c059 150 }
a84b8fa5
C
151 ],
152 offset: start,
153 limit: count,
154 order: getSort(sort),
d511df28 155 where
ed31c059
C
156 }
157
453e83ea 158 return VideoImportModel.findAndCountAll<MVideoImportDefault>(query)
ed31c059
C
159 .then(({ rows, count }) => {
160 return {
161 data: rows,
162 total: count
163 }
164 })
165 }
166
dc133480
C
167 getTargetIdentifier () {
168 return this.targetUrl || this.magnetUri || this.torrentName
169 }
170
1ca9f7c3 171 toFormattedJSON (this: MVideoImportFormattable): VideoImport {
fbad87b0 172 const videoFormatOptions = {
c39e86b8 173 completeDescription: true,
fbad87b0
C
174 additionalAttributes: { state: true, waitTranscoding: true, scheduledUpdate: true }
175 }
ed31c059 176 const video = this.Video
c39e86b8 177 ? Object.assign(this.Video.toFormattedJSON(videoFormatOptions), { tags: this.Video.Tags.map(t => t.name) })
ed31c059 178 : undefined
fbad87b0
C
179
180 return {
d7f83948 181 id: this.id,
990b6a0b 182
fbad87b0 183 targetUrl: this.targetUrl,
990b6a0b
C
184 magnetUri: this.magnetUri,
185 torrentName: this.torrentName,
186
ed31c059
C
187 state: {
188 id: this.state,
189 label: VideoImportModel.getStateLabel(this.state)
190 },
d7f83948 191 error: this.error,
ed31c059
C
192 updatedAt: this.updatedAt.toISOString(),
193 createdAt: this.createdAt.toISOString(),
fbad87b0
C
194 video
195 }
196 }
268eebed 197
ed31c059
C
198 private static getStateLabel (id: number) {
199 return VIDEO_IMPORT_STATES[id] || 'Unknown'
200 }
fbad87b0 201}