mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-13 06:51:29 +00:00
Merge 4e808e6770 into 47ea6b5092
This commit is contained in:
commit
f3a220c173
26 changed files with 2441 additions and 304 deletions
|
|
@ -47,6 +47,10 @@ function getFileStat(path) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @returns {Promise<object | null>}
|
||||
*/
|
||||
async function getFileTimestampsWithIno(path) {
|
||||
try {
|
||||
var stat = await fs.stat(path, { bigint: true })
|
||||
|
|
@ -55,11 +59,12 @@ async function getFileTimestampsWithIno(path) {
|
|||
mtimeMs: Number(stat.mtimeMs),
|
||||
ctimeMs: Number(stat.ctimeMs),
|
||||
birthtimeMs: Number(stat.birthtimeMs),
|
||||
ino: String(stat.ino)
|
||||
ino: String(stat.ino),
|
||||
deviceId: String(stat.dev)
|
||||
}
|
||||
} catch (err) {
|
||||
Logger.error(`[fileUtils] Failed to getFileTimestampsWithIno for path "${path}"`, err)
|
||||
return false
|
||||
return null
|
||||
}
|
||||
}
|
||||
module.exports.getFileTimestampsWithIno = getFileTimestampsWithIno
|
||||
|
|
@ -92,7 +97,7 @@ module.exports.getFileMTimeMs = async (path) => {
|
|||
/**
|
||||
*
|
||||
* @param {string} filepath
|
||||
* @returns {boolean}
|
||||
* @returns {Promise<boolean>} isFile
|
||||
*/
|
||||
async function checkPathIsFile(filepath) {
|
||||
try {
|
||||
|
|
@ -104,6 +109,10 @@ async function checkPathIsFile(filepath) {
|
|||
}
|
||||
module.exports.checkPathIsFile = checkPathIsFile
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @returns {string | null} inode
|
||||
*/
|
||||
function getIno(path) {
|
||||
return fs
|
||||
.stat(path, { bigint: true })
|
||||
|
|
@ -115,10 +124,25 @@ function getIno(path) {
|
|||
}
|
||||
module.exports.getIno = getIno
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @returns {Promise<string | null>} deviceId
|
||||
*/
|
||||
async function getDeviceId(path) {
|
||||
try {
|
||||
var data = await fs.stat(path)
|
||||
return String(data.dev)
|
||||
} catch (error) {
|
||||
Logger.error(`[Utils] Failed to get device Id for path "${path}": ${error}`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
module.exports.getDeviceId = getDeviceId
|
||||
|
||||
/**
|
||||
* Read contents of file
|
||||
* @param {string} path
|
||||
* @returns {string}
|
||||
* @returns {Promise<string>} file contents
|
||||
*/
|
||||
async function readTextFile(path) {
|
||||
try {
|
||||
|
|
@ -135,7 +159,7 @@ module.exports.readTextFile = readTextFile
|
|||
* Check if file or directory should be ignored. Returns a string of the reason to ignore, or null if not ignored
|
||||
*
|
||||
* @param {string} path
|
||||
* @returns {string}
|
||||
* @returns {string | null} reason to ignore
|
||||
*/
|
||||
module.exports.shouldIgnoreFile = (path) => {
|
||||
// Check if directory or file name starts with "."
|
||||
|
|
@ -178,8 +202,8 @@ module.exports.shouldIgnoreFile = (path) => {
|
|||
/**
|
||||
* Get array of files inside dir
|
||||
* @param {string} path
|
||||
* @param {string} [relPathToReplace]
|
||||
* @returns {FilePathItem[]}
|
||||
* @param {string | null} [relPathToReplace]
|
||||
* @returns {Promise<FilePathItem[]>}
|
||||
*/
|
||||
module.exports.recurseFiles = async (path, relPathToReplace = null) => {
|
||||
path = filePathToPOSIX(path)
|
||||
|
|
@ -219,6 +243,8 @@ module.exports.recurseFiles = async (path, relPathToReplace = null) => {
|
|||
|
||||
item.fullname = filePathToPOSIX(item.fullname)
|
||||
item.path = filePathToPOSIX(item.path)
|
||||
// BUGBUG: This is broken with symlinked directory /tmp -> /private/tmp. when library is in /tmp/testLibrary, it tries to replace /tmp/testLibrary with '' but in a canonical path (non-symlinked)
|
||||
// TODO: find the commit that added relPathToReplace and figure out what it's trying to do and make it do that properly
|
||||
const relpath = item.fullname.replace(relPathToReplace, '')
|
||||
let reldirname = Path.dirname(relpath)
|
||||
if (reldirname === '.') reldirname = ''
|
||||
|
|
@ -292,7 +318,7 @@ module.exports.getFilePathItemFromFileUpdate = (fileUpdate) => {
|
|||
*
|
||||
* @param {string} url
|
||||
* @param {string} filepath path to download the file to
|
||||
* @param {Function} [contentTypeFilter] validate content type before writing
|
||||
* @param {Function | null} [contentTypeFilter] validate content type before writing
|
||||
* @returns {Promise}
|
||||
*/
|
||||
module.exports.downloadFile = (url, filepath, contentTypeFilter = null) => {
|
||||
|
|
|
|||
|
|
@ -5,17 +5,17 @@ const fileUtils = require('../fileUtils')
|
|||
const LibraryFile = require('../../objects/files/LibraryFile')
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('../../models/LibraryItem')} libraryItem
|
||||
*
|
||||
* @param {import('../../models/LibraryItem')} libraryItem
|
||||
* @returns {Promise<boolean>} false if failed
|
||||
*/
|
||||
async function writeMetadataFileForItem(libraryItem) {
|
||||
const storeMetadataWithItem = global.ServerSettings.storeMetadataWithItem && !libraryItem.isFile
|
||||
const metadataPath = storeMetadataWithItem ? libraryItem.path : Path.join(global.MetadataPath, 'items', libraryItem.id)
|
||||
const metadataFilepath = fileUtils.filePathToPOSIX(Path.join(metadataPath, 'metadata.json'))
|
||||
if ((await fsExtra.pathExists(metadataFilepath))) {
|
||||
if (await fsExtra.pathExists(metadataFilepath)) {
|
||||
// Metadata file already exists do nothing
|
||||
return null
|
||||
return false
|
||||
}
|
||||
Logger.info(`[absMetadataMigration] metadata file not found at "${metadataFilepath}" - creating`)
|
||||
|
||||
|
|
@ -27,20 +27,24 @@ async function writeMetadataFileForItem(libraryItem) {
|
|||
const metadataJson = libraryItem.media.getAbsMetadataJson()
|
||||
|
||||
// Save to file
|
||||
const success = await fsExtra.writeFile(metadataFilepath, JSON.stringify(metadataJson, null, 2)).then(() => true).catch((error) => {
|
||||
Logger.error(`[absMetadataMigration] failed to save metadata file at "${metadataFilepath}"`, error.message || error)
|
||||
return false
|
||||
})
|
||||
const success = await fsExtra
|
||||
.writeFile(metadataFilepath, JSON.stringify(metadataJson, null, 2))
|
||||
.then(() => true)
|
||||
.catch((error) => {
|
||||
Logger.error(`[absMetadataMigration] failed to save metadata file at "${metadataFilepath}"`, error.message || error)
|
||||
return false
|
||||
})
|
||||
|
||||
if (!success) return false
|
||||
if (!storeMetadataWithItem) return true // No need to do anything else
|
||||
|
||||
// Safety check to make sure library file with the same path isnt already there
|
||||
libraryItem.libraryFiles = libraryItem.libraryFiles.filter(lf => lf.metadata.path !== metadataFilepath)
|
||||
libraryItem.libraryFiles = libraryItem.libraryFiles.filter((lf) => lf.metadata.path !== metadataFilepath)
|
||||
|
||||
// Put new library file in library item
|
||||
const newLibraryFile = new LibraryFile()
|
||||
await newLibraryFile.setDataFromPath(metadataFilepath, 'metadata.json')
|
||||
// TODO: BUGBUG - this shouldn't be JSON and it may not be the right type LibraryFileObject
|
||||
libraryItem.libraryFiles.push(newLibraryFile.toJSON())
|
||||
|
||||
// Update library item timestamps and total size
|
||||
|
|
@ -49,20 +53,23 @@ async function writeMetadataFileForItem(libraryItem) {
|
|||
libraryItem.mtime = libraryItemDirTimestamps.mtimeMs
|
||||
libraryItem.ctime = libraryItemDirTimestamps.ctimeMs
|
||||
let size = 0
|
||||
libraryItem.libraryFiles.forEach((lf) => size += (!isNaN(lf.metadata.size) ? Number(lf.metadata.size) : 0))
|
||||
libraryItem.libraryFiles.forEach((lf) => (size += !isNaN(lf.metadata.size) ? Number(lf.metadata.size) : 0))
|
||||
libraryItem.size = size
|
||||
}
|
||||
|
||||
libraryItem.changed('libraryFiles', true)
|
||||
return libraryItem.save().then(() => true).catch((error) => {
|
||||
Logger.error(`[absMetadataMigration] failed to save libraryItem "${libraryItem.id}"`, error.message || error)
|
||||
return false
|
||||
})
|
||||
return libraryItem
|
||||
.save()
|
||||
.then(() => true)
|
||||
.catch((error) => {
|
||||
Logger.error(`[absMetadataMigration] failed to save libraryItem "${libraryItem.id}"`, error.message || error)
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('../../Database')} Database
|
||||
*
|
||||
* @param {import('../../Database')} Database
|
||||
* @param {number} [offset=0]
|
||||
* @param {number} [totalCreated=0]
|
||||
*/
|
||||
|
|
@ -83,11 +90,11 @@ async function runMigration(Database, offset = 0, totalCreated = 0) {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('../../Database')} Database
|
||||
*
|
||||
* @param {import('../../Database')} Database
|
||||
*/
|
||||
module.exports.migrate = async (Database) => {
|
||||
Logger.info(`[absMetadataMigration] Starting metadata.json migration`)
|
||||
const totalCreated = await runMigration(Database)
|
||||
Logger.info(`[absMetadataMigration] Finished metadata.json migration (${totalCreated} files created)`)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue