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