ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

express-utils.ts 4.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import express, { RequestHandler } from 'express'
  2. import multer, { diskStorage } from 'multer'
  3. import { getLowercaseExtension } from '@peertube/peertube-node-utils'
  4. import { CONFIG } from '../initializers/config.js'
  5. import { REMOTE_SCHEME } from '../initializers/constants.js'
  6. import { isArray } from './custom-validators/misc.js'
  7. import { logger } from './logger.js'
  8. import { deleteFileAndCatch, generateRandomString } from './utils.js'
  9. import { getExtFromMimetype } from './video.js'
  10. function buildNSFWFilter (res?: express.Response, paramNSFW?: string) {
  11. if (paramNSFW === 'true') return true
  12. if (paramNSFW === 'false') return false
  13. if (paramNSFW === 'both') return undefined
  14. if (res?.locals.oauth) {
  15. const user = res.locals.oauth.token.User
  16. // User does not want NSFW videos
  17. if (user.nsfwPolicy === 'do_not_list') return false
  18. // Both
  19. return undefined
  20. }
  21. if (CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list') return false
  22. // Display all
  23. return null
  24. }
  25. function cleanUpReqFiles (req: express.Request) {
  26. const filesObject = req.files
  27. if (!filesObject) return
  28. if (isArray(filesObject)) {
  29. filesObject.forEach(f => deleteFileAndCatch(f.path))
  30. return
  31. }
  32. for (const key of Object.keys(filesObject)) {
  33. const files = filesObject[key]
  34. files.forEach(f => deleteFileAndCatch(f.path))
  35. }
  36. }
  37. function getHostWithPort (host: string) {
  38. const splitted = host.split(':')
  39. // The port was not specified
  40. if (splitted.length === 1) {
  41. if (REMOTE_SCHEME.HTTP === 'https') return host + ':443'
  42. return host + ':80'
  43. }
  44. return host
  45. }
  46. function createReqFiles (
  47. fieldNames: string[],
  48. mimeTypes: { [id: string]: string | string[] },
  49. destination = CONFIG.STORAGE.TMP_DIR
  50. ): RequestHandler {
  51. const storage = diskStorage({
  52. destination: (req, file, cb) => {
  53. cb(null, destination)
  54. },
  55. filename: (req, file, cb) => {
  56. return generateReqFilename(file, mimeTypes, cb)
  57. }
  58. })
  59. const fields: { name: string, maxCount: number }[] = []
  60. for (const fieldName of fieldNames) {
  61. fields.push({
  62. name: fieldName,
  63. maxCount: 1
  64. })
  65. }
  66. return multer({ storage }).fields(fields)
  67. }
  68. function createAnyReqFiles (
  69. mimeTypes: { [id: string]: string | string[] },
  70. fileFilter: (req: express.Request, file: Express.Multer.File, cb: (err: Error, result: boolean) => void) => void
  71. ): RequestHandler {
  72. const storage = diskStorage({
  73. destination: (req, file, cb) => {
  74. cb(null, CONFIG.STORAGE.TMP_DIR)
  75. },
  76. filename: (req, file, cb) => {
  77. return generateReqFilename(file, mimeTypes, cb)
  78. }
  79. })
  80. return multer({ storage, fileFilter }).any()
  81. }
  82. function isUserAbleToSearchRemoteURI (res: express.Response) {
  83. const user = res.locals.oauth ? res.locals.oauth.token.User : undefined
  84. return CONFIG.SEARCH.REMOTE_URI.ANONYMOUS === true ||
  85. (CONFIG.SEARCH.REMOTE_URI.USERS === true && user !== undefined)
  86. }
  87. function getCountVideos (req: express.Request) {
  88. return req.query.skipCount !== true
  89. }
  90. // ---------------------------------------------------------------------------
  91. export {
  92. buildNSFWFilter,
  93. getHostWithPort,
  94. createAnyReqFiles,
  95. isUserAbleToSearchRemoteURI,
  96. createReqFiles,
  97. cleanUpReqFiles,
  98. getCountVideos
  99. }
  100. // ---------------------------------------------------------------------------
  101. async function generateReqFilename (
  102. file: Express.Multer.File,
  103. mimeTypes: { [id: string]: string | string[] },
  104. cb: (err: Error, name: string) => void
  105. ) {
  106. let extension: string
  107. const fileExtension = getLowercaseExtension(file.originalname)
  108. const extensionFromMimetype = getExtFromMimetype(mimeTypes, file.mimetype)
  109. // Take the file extension if we don't understand the mime type
  110. if (!extensionFromMimetype) {
  111. extension = fileExtension
  112. } else {
  113. // Take the first available extension for this mimetype
  114. extension = extensionFromMimetype
  115. }
  116. let randomString = ''
  117. try {
  118. randomString = await generateRandomString(16)
  119. } catch (err) {
  120. logger.error('Cannot generate random string for file name.', { err })
  121. randomString = 'fake-random-string'
  122. }
  123. cb(null, randomString + extension)
  124. }