thumbnail.ts 3.0 KB

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