Add migrations
[oweals/peertube.git] / server / models / video / thumbnail.ts
1 import { join } from 'path'
2 import { AfterDestroy, AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
3 import { STATIC_PATHS, WEBSERVER } from '../../initializers/constants'
4 import { logger } from '../../helpers/logger'
5 import { remove } from 'fs-extra'
6 import { CONFIG } from '../../initializers/config'
7 import { VideoModel } from './video'
8 import { VideoPlaylistModel } from './video-playlist'
9 import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
10
11 @Table({
12   tableName: 'thumbnail',
13   indexes: [
14     {
15       fields: [ 'videoId' ]
16     },
17     {
18       fields: [ 'videoPlaylistId' ],
19       unique: true
20     }
21   ]
22 })
23 export class ThumbnailModel extends Model<ThumbnailModel> {
24
25   @AllowNull(false)
26   @Column
27   filename: string
28
29   @AllowNull(true)
30   @Default(null)
31   @Column
32   height: number
33
34   @AllowNull(true)
35   @Default(null)
36   @Column
37   width: number
38
39   @AllowNull(false)
40   @Column
41   type: ThumbnailType
42
43   @AllowNull(true)
44   @Column
45   fileUrl: string
46
47   @ForeignKey(() => VideoModel)
48   @Column
49   videoId: number
50
51   @BelongsTo(() => VideoModel, {
52     foreignKey: {
53       allowNull: true
54     },
55     onDelete: 'CASCADE'
56   })
57   Video: VideoModel
58
59   @ForeignKey(() => VideoPlaylistModel)
60   @Column
61   videoPlaylistId: number
62
63   @BelongsTo(() => VideoPlaylistModel, {
64     foreignKey: {
65       allowNull: true
66     },
67     onDelete: 'CASCADE'
68   })
69   VideoPlaylist: VideoPlaylistModel
70
71   @CreatedAt
72   createdAt: Date
73
74   @UpdatedAt
75   updatedAt: Date
76
77   private static types: { [ id in ThumbnailType ]: { label: string, directory: string, staticPath: string } } = {
78     [ThumbnailType.MINIATURE]: {
79       label: 'miniature',
80       directory: CONFIG.STORAGE.THUMBNAILS_DIR,
81       staticPath: STATIC_PATHS.THUMBNAILS
82     },
83     [ThumbnailType.PREVIEW]: {
84       label: 'preview',
85       directory: CONFIG.STORAGE.PREVIEWS_DIR,
86       staticPath: STATIC_PATHS.PREVIEWS
87     }
88   }
89
90   @AfterDestroy
91   static removeFilesAndSendDelete (instance: ThumbnailModel) {
92     logger.info('Removing %s file %s.', ThumbnailModel.types[instance.type].label, instance.filename)
93
94     // Don't block the transaction
95     instance.removeThumbnail()
96             .catch(err => logger.error('Cannot remove thumbnail file %s.', instance.filename, err))
97   }
98
99   static generateDefaultPreviewName (videoUUID: string) {
100     return videoUUID + '.jpg'
101   }
102
103   getFileUrl () {
104     if (this.fileUrl) return this.fileUrl
105
106     const staticPath = ThumbnailModel.types[this.type].staticPath
107     return WEBSERVER.URL + staticPath + this.filename
108   }
109
110   removeThumbnail () {
111     const directory = ThumbnailModel.types[this.type].directory
112     const thumbnailPath = join(directory, this.filename)
113
114     return remove(thumbnailPath)
115   }
116 }