2021-12-13 00:15:37 +01:00
|
|
|
const Path = require('path')
|
|
|
|
const fs = require('fs-extra')
|
|
|
|
const stream = require('stream')
|
|
|
|
const Logger = require('./Logger')
|
2021-12-13 20:29:31 +01:00
|
|
|
const { resizeImage } = require('./utils/ffmpegHelpers')
|
2021-12-13 00:15:37 +01:00
|
|
|
|
|
|
|
class CacheManager {
|
2022-02-27 20:47:52 +01:00
|
|
|
constructor() {
|
|
|
|
this.CachePath = Path.join(global.MetadataPath, 'cache')
|
2021-12-13 00:15:37 +01:00
|
|
|
this.CoverCachePath = Path.join(this.CachePath, 'covers')
|
2022-03-13 16:35:35 +01:00
|
|
|
this.ImageCachePath = Path.join(this.CachePath, 'images')
|
2021-12-13 00:15:37 +01:00
|
|
|
}
|
|
|
|
|
2022-03-11 01:45:02 +01:00
|
|
|
async handleCoverCache(res, libraryItem, options = {}) {
|
2021-12-13 00:15:37 +01:00
|
|
|
const format = options.format || 'webp'
|
|
|
|
const width = options.width || 400
|
|
|
|
const height = options.height || null
|
|
|
|
|
|
|
|
res.type(`image/${format}`)
|
|
|
|
|
2022-03-11 01:45:02 +01:00
|
|
|
var path = Path.join(this.CoverCachePath, `${libraryItem.id}_${width}${height ? `x${height}` : ''}`) + '.' + format
|
2021-12-13 00:15:37 +01:00
|
|
|
|
|
|
|
// Cache exists
|
|
|
|
if (await fs.pathExists(path)) {
|
|
|
|
const r = fs.createReadStream(path)
|
|
|
|
const ps = new stream.PassThrough()
|
|
|
|
stream.pipeline(r, ps, (err) => {
|
|
|
|
if (err) {
|
|
|
|
console.log(err)
|
|
|
|
return res.sendStatus(400)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return ps.pipe(res)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write cache
|
|
|
|
await fs.ensureDir(this.CoverCachePath)
|
|
|
|
|
2022-03-11 01:45:02 +01:00
|
|
|
let writtenFile = await resizeImage(libraryItem.media.coverPath, path, width, height)
|
2021-12-14 22:19:23 +01:00
|
|
|
if (!writtenFile) return res.sendStatus(400)
|
|
|
|
|
2021-12-13 20:29:31 +01:00
|
|
|
var readStream = fs.createReadStream(writtenFile)
|
2021-12-13 00:15:37 +01:00
|
|
|
readStream.pipe(res)
|
|
|
|
}
|
|
|
|
|
2022-03-13 00:45:32 +01:00
|
|
|
async purgeCoverCache(libraryItemId) {
|
2021-12-13 20:29:31 +01:00
|
|
|
// If purgeAll has been called... The cover cache directory no longer exists
|
|
|
|
await fs.ensureDir(this.CoverCachePath)
|
|
|
|
return Promise.all((await fs.readdir(this.CoverCachePath)).reduce((promises, file) => {
|
2022-03-13 00:45:32 +01:00
|
|
|
if (file.startsWith(libraryItemId)) {
|
2021-12-13 20:29:31 +01:00
|
|
|
Logger.debug(`[CacheManager] Going to purge ${file}`);
|
|
|
|
promises.push(this.removeCache(Path.join(this.CoverCachePath, file)))
|
|
|
|
}
|
|
|
|
return promises
|
|
|
|
}, []))
|
2021-12-13 00:15:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
removeCache(path) {
|
|
|
|
if (!path) return false
|
|
|
|
return fs.pathExists(path).then((exists) => {
|
|
|
|
if (!exists) return false
|
|
|
|
return fs.unlink(path).then(() => true).catch((err) => {
|
|
|
|
Logger.error(`[CacheManager] Failed to remove cache "${path}"`, err)
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async purgeAll() {
|
|
|
|
if (await fs.pathExists(this.CachePath)) {
|
|
|
|
await fs.remove(this.CachePath).catch((error) => {
|
|
|
|
Logger.error(`[CacheManager] Failed to remove cache dir "${this.CachePath}"`, error)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2022-03-13 16:35:35 +01:00
|
|
|
|
|
|
|
async handleAuthorCache(res, author, options = {}) {
|
|
|
|
const format = options.format || 'webp'
|
|
|
|
const width = options.width || 400
|
|
|
|
const height = options.height || null
|
|
|
|
|
|
|
|
res.type(`image/${format}`)
|
|
|
|
|
|
|
|
var path = Path.join(this.ImageCachePath, `${author.id}_${width}${height ? `x${height}` : ''}`) + '.' + format
|
|
|
|
|
|
|
|
// Cache exists
|
|
|
|
if (await fs.pathExists(path)) {
|
|
|
|
const r = fs.createReadStream(path)
|
|
|
|
const ps = new stream.PassThrough()
|
|
|
|
stream.pipeline(r, ps, (err) => {
|
|
|
|
if (err) {
|
|
|
|
console.log(err)
|
|
|
|
return res.sendStatus(400)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return ps.pipe(res)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write cache
|
|
|
|
await fs.ensureDir(this.ImageCachePath)
|
|
|
|
|
|
|
|
let writtenFile = await resizeImage(author.imagePath, path, width, height)
|
|
|
|
if (!writtenFile) return res.sendStatus(400)
|
|
|
|
|
|
|
|
var readStream = fs.createReadStream(writtenFile)
|
|
|
|
readStream.pipe(res)
|
|
|
|
}
|
2021-12-13 00:15:37 +01:00
|
|
|
}
|
|
|
|
module.exports = CacheManager
|