]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/video/thumbnail.ts
Merge branch 'release/2.1.0' into develop
[github/Chocobozzz/PeerTube.git] / server / models / video / thumbnail.ts
CommitLineData
e8bafea3 1import { join } from 'path'
2735a154
C
2import {
3 AfterDestroy,
4 AllowNull,
5 BelongsTo,
6 Column,
7 CreatedAt,
8 DataType,
9 Default,
10 ForeignKey,
11 Model,
12 Table,
13 UpdatedAt
14} from 'sequelize-typescript'
15import { CONSTRAINTS_FIELDS, LAZY_STATIC_PATHS, STATIC_PATHS, WEBSERVER } from '../../initializers/constants'
e8bafea3
C
16import { logger } from '../../helpers/logger'
17import { remove } from 'fs-extra'
18import { CONFIG } from '../../initializers/config'
19import { VideoModel } from './video'
20import { VideoPlaylistModel } from './video-playlist'
21import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
ca6d3622
C
22import { MVideoAccountLight } from '@server/typings/models'
23import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub'
e8bafea3
C
24
25@Table({
26 tableName: 'thumbnail',
27 indexes: [
28 {
29 fields: [ 'videoId' ]
30 },
31 {
32 fields: [ 'videoPlaylistId' ],
33 unique: true
34 }
35 ]
36})
37export class ThumbnailModel extends Model<ThumbnailModel> {
38
39 @AllowNull(false)
40 @Column
41 filename: string
42
43 @AllowNull(true)
44 @Default(null)
45 @Column
46 height: number
47
48 @AllowNull(true)
49 @Default(null)
50 @Column
51 width: number
52
53 @AllowNull(false)
54 @Column
55 type: ThumbnailType
56
57 @AllowNull(true)
2735a154 58 @Column(DataType.STRING(CONSTRAINTS_FIELDS.COMMONS.URL.max))
9cc8d43e 59 fileUrl: string
e8bafea3 60
65af03a2
C
61 @AllowNull(true)
62 @Column
63 automaticallyGenerated: boolean
64
e8bafea3
C
65 @ForeignKey(() => VideoModel)
66 @Column
67 videoId: number
68
69 @BelongsTo(() => VideoModel, {
70 foreignKey: {
71 allowNull: true
72 },
73 onDelete: 'CASCADE'
74 })
75 Video: VideoModel
76
77 @ForeignKey(() => VideoPlaylistModel)
78 @Column
79 videoPlaylistId: number
80
81 @BelongsTo(() => VideoPlaylistModel, {
82 foreignKey: {
83 allowNull: true
84 },
85 onDelete: 'CASCADE'
86 })
87 VideoPlaylist: VideoPlaylistModel
88
89 @CreatedAt
90 createdAt: Date
91
92 @UpdatedAt
93 updatedAt: Date
94
a1587156 95 private static readonly types: { [ id in ThumbnailType ]: { label: string, directory: string, staticPath: string } } = {
3acc5084
C
96 [ThumbnailType.MINIATURE]: {
97 label: 'miniature',
e8bafea3
C
98 directory: CONFIG.STORAGE.THUMBNAILS_DIR,
99 staticPath: STATIC_PATHS.THUMBNAILS
100 },
101 [ThumbnailType.PREVIEW]: {
102 label: 'preview',
103 directory: CONFIG.STORAGE.PREVIEWS_DIR,
557b13ae 104 staticPath: LAZY_STATIC_PATHS.PREVIEWS
e8bafea3
C
105 }
106 }
107
108 @AfterDestroy
65af03a2 109 static removeFiles (instance: ThumbnailModel) {
e8bafea3
C
110 logger.info('Removing %s file %s.', ThumbnailModel.types[instance.type].label, instance.filename)
111
112 // Don't block the transaction
113 instance.removeThumbnail()
114 .catch(err => logger.error('Cannot remove thumbnail file %s.', instance.filename, err))
115 }
116
e2600d8b
C
117 static loadByName (filename: string) {
118 const query = {
119 where: {
120 filename
121 }
122 }
123
124 return ThumbnailModel.findOne(query)
125 }
126
e8bafea3
C
127 static generateDefaultPreviewName (videoUUID: string) {
128 return videoUUID + '.jpg'
129 }
130
ca6d3622
C
131 getFileUrl (video: MVideoAccountLight) {
132 const staticPath = ThumbnailModel.types[this.type].staticPath + this.filename
e8bafea3 133
ca6d3622
C
134 if (video.isOwned()) return WEBSERVER.URL + staticPath
135 if (this.fileUrl) return this.fileUrl
136
137 // Fallback if we don't have a file URL
138 return buildRemoteVideoBaseUrl(video, staticPath)
e8bafea3
C
139 }
140
536598cf 141 getPath () {
e8bafea3 142 const directory = ThumbnailModel.types[this.type].directory
536598cf
C
143 return join(directory, this.filename)
144 }
e8bafea3 145
536598cf
C
146 removeThumbnail () {
147 return remove(this.getPath())
e8bafea3
C
148 }
149}