Documentation
¶
Index ¶
- Variables
- func CleanupEmptyDirectory(dirPath string, ignoredPatterns ...string) (bool, error)
- func CleanupEmptyParentDirectories(startPath, stopAt string, ignoredPatterns ...string) error
- func ComputeNewCoverFilename(oldCoverFilename, newFilePath string) string
- func CoverExistsWithBaseName(dir, baseName string) string
- func ExtractSeriesFromTitle(title string, fileType string) (seriesName string, number *float64, unit string, ok bool)
- func GenerateOrganizedFileName(opts OrganizedNameOptions, originalFilepath string) string
- func GenerateOrganizedFolderName(opts OrganizedNameOptions) string
- func GenerateUniqueFilepathIfExists(path string) string
- func ImageFileResolution(path string) int
- func ImageResolution(data []byte) int
- func IsOrganizedName(name string) bool
- func MimeTypeFromExtension(ext string) string
- func MoveFile(src, dst string) error
- func MoveFileWithAssociatedFiles(originalFilePath, newFilePath string) (int, error)
- func NormalizeImage(data []byte, mimeType string) ([]byte, string, error)
- func NormalizeSeriesNumberInTitle(title string, fileType string) (string, string, bool)
- func RenameOrganizedFile(currentPath string, opts OrganizedNameOptions) (string, error)
- func RenameOrganizedFileForSupplement(currentPath string, opts OrganizedNameOptions) (string, error)deprecated
- func RenameOrganizedFileOnly(currentPath string, opts OrganizedNameOptions) (string, error)
- func RenameOrganizedFolder(currentFolderPath string, opts OrganizedNameOptions) (string, error)
- func ResolveCoverDirForWrite(bookFilepath, fileFilepath string) string
- func SplitNames(s string) []string
- type OrganizeFileResult
- type OrganizedNameOptions
Constants ¶
This section is empty.
Variables ¶
var CoverImageExtensions = []string{".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp"}
CoverImageExtensions contains all supported image extensions for cover files.
var ShishoSpecialFilePatterns = []string{
"*.cover.*",
"*.metadata.json",
}
ShishoSpecialFilePatterns are glob patterns for shisho-generated files (covers, sidecars). These are used to skip special files during scanning and to treat them as ignorable during directory cleanup after book deletion. This slice must not be mutated at runtime.
Functions ¶
func CleanupEmptyDirectory ¶
CleanupEmptyDirectory removes a directory if it's empty or only contains ignored files. ignoredPatterns can include glob patterns like ".*" (dotfiles), ".DS_Store", "Thumbs.db", etc. Returns true if the directory was removed, false if it wasn't empty or didn't exist.
func CleanupEmptyParentDirectories ¶
CleanupEmptyParentDirectories removes empty parent directories starting from startPath up to (but not including) stopAt. ignoredPatterns are passed to CleanupEmptyDirectory.
func ComputeNewCoverFilename ¶ added in v0.0.8
ComputeNewCoverFilename computes the new cover filename after a file has been renamed. It preserves the cover's extension while updating the base filename to match the new file path. Returns just the filename (e.g., "book.epub.cover.jpg"), not a full path. Returns empty string if oldCoverFilename is empty.
func CoverExistsWithBaseName ¶
CoverExistsWithBaseName checks if any cover file exists with the given base name, regardless of image extension. This allows users to provide custom covers that won't be overwritten even if the book would extract a different format.
Parameters:
- dir: the directory to check
- baseName: the cover base name without extension (e.g., "mybook.epub.cover")
Returns the path to the existing cover file if found, or empty string if no cover exists.
func ExtractSeriesFromTitle ¶
func ExtractSeriesFromTitle(title string, fileType string) (seriesName string, number *float64, unit string, ok bool)
ExtractSeriesFromTitle extracts series name and number from a normalized CBZ title. Returns the base title (series name), number, unit (models.SeriesNumberUnitVolume or models.SeriesNumberUnitChapter), and whether extraction succeeded. Only applies to CBZ files with normalized "v{N}" or "c{N}" suffixes.
func GenerateOrganizedFileName ¶
func GenerateOrganizedFileName(opts OrganizedNameOptions, originalFilepath string) string
GenerateOrganizedFileName creates a standardized filename: Title.ext. For M4B files, includes narrator in braces: Title {Narrator}.m4b. Author names are NOT included since files are already inside author-prefixed folders.
func GenerateOrganizedFolderName ¶
func GenerateOrganizedFolderName(opts OrganizedNameOptions) string
GenerateOrganizedFolderName creates a standardized folder name: [Author] Title <number>. For CBZ files, the number is formatted as "v{N}" for volumes or "c{N}" for chapters.
func GenerateUniqueFilepathIfExists ¶ added in v0.0.8
GenerateUniqueFilepathIfExists returns a unique filepath if the path exists, otherwise returns the original.
func ImageFileResolution ¶ added in v0.0.24
ImageFileResolution returns the total pixel count of an image file on disk. Returns 0 if the file cannot be read or decoded.
func ImageResolution ¶ added in v0.0.24
ImageResolution returns the total pixel count (width * height) of an image by reading only the image header (no full decode). Returns 0 if the image cannot be decoded.
func IsOrganizedName ¶
IsOrganizedName checks if a filename/foldername follows the organized naming pattern.
func MimeTypeFromExtension ¶
MimeTypeFromExtension returns the MIME type for a given file extension. Returns empty string if the extension is not recognized.
func MoveFile ¶ added in v0.0.8
MoveFile safely moves a file from source to destination. Returns error if move fails.
func MoveFileWithAssociatedFiles ¶ added in v0.0.8
MoveFileWithAssociatedFiles moves a file and its associated files (covers, file sidecar). This does NOT move book sidecars - only file-specific associated files. Returns the number of associated files moved.
func NormalizeImage ¶
NormalizeImage decodes and re-encodes an image to strip problematic metadata (like gAMA chunks without sRGB in PNG) that cause color rendering issues in browsers. Returns the normalized image data and the new MIME type. If the input is a JPEG, it stays as JPEG to preserve quality. Otherwise, it becomes PNG.
func NormalizeSeriesNumberInTitle ¶ added in v0.0.40
NormalizeSeriesNumberInTitle normalizes volume- or chapter-style number indicators in CBZ titles. For volume indicators (v01, vol.5, volume 12, #001, bare trailing number) the title becomes "Title v{NNN}". For chapter indicators (chapter 5, Ch.5, c042) the title becomes "Title c{NNN}". Returns the normalized title, the parsed unit (models.SeriesNumberUnitVolume or models.SeriesNumberUnitChapter, "" when no match), and whether a number was found. Non-CBZ files are returned unchanged.
func RenameOrganizedFile ¶
func RenameOrganizedFile(currentPath string, opts OrganizedNameOptions) (string, error)
RenameOrganizedFile renames an already organized file with new metadata. Also renames associated cover images, file sidecar, AND the book sidecar. Use this for BOOK-level changes (title, author changes) that should update the book sidecar. For FILE-level changes (file name, narrator), use RenameOrganizedFileOnly.
func RenameOrganizedFileForSupplement
deprecated
func RenameOrganizedFileForSupplement(currentPath string, opts OrganizedNameOptions) (string, error)
RenameOrganizedFileForSupplement is an alias for RenameOrganizedFileOnly for backwards compatibility.
Deprecated: Use RenameOrganizedFileOnly instead.
func RenameOrganizedFileOnly ¶
func RenameOrganizedFileOnly(currentPath string, opts OrganizedNameOptions) (string, error)
RenameOrganizedFileOnly renames a file with new metadata, but does NOT rename the book sidecar. Renames the file and its associated cover images and file-specific sidecar. Use this for FILE-level changes (file name, narrator) that should not affect the book sidecar. The book sidecar should only be renamed when book-level metadata (title, author) changes.
func RenameOrganizedFolder ¶
func RenameOrganizedFolder(currentFolderPath string, opts OrganizedNameOptions) (string, error)
RenameOrganizedFolder renames a folder containing organized files.
func ResolveCoverDirForWrite ¶ added in v0.0.27
ResolveCoverDirForWrite resolves the directory where a cover image should be written. Handles the case where bookFilepath may be a synthetic organized-folder path that does not yet exist on disk — common when scanning root-level files in libraries with OrganizeFileStructure enabled, where the organized directory is created later in the batch. In that case the cover must land alongside the file at filepath.Dir(fileFilepath), which is where extractAndSaveCover wrote the file-embedded cover.
Read-side callers that already have a resolved file.Filepath from the DB should NOT use this helper — prefer the pure-string filepath.Join(filepath.Dir(file.Filepath), coverFilename) which is always correct for both directory-backed and root-level books.
If bookFilepath resolves to a real directory, it's used. Otherwise (stat fails, or bookFilepath is a file), falls back to filepath.Dir(fileFilepath). This is correct for all three scenarios:
- directory-backed books: bookFilepath is a real dir, use it
- root-level books (rescan): bookFilepath == fileFilepath, fall back gives filepath.Dir(fileFilepath) = library dir, same as before
- root-level books (new file, synthetic path): stat fails, fall back gives filepath.Dir(fileFilepath) = library dir where the file lives
func SplitNames ¶
SplitNames splits a string of names by common delimiters (comma and semicolon), trims whitespace from each name, and returns non-empty names. This is used for parsing author and narrator lists from metadata.
Types ¶
type OrganizeFileResult ¶
type OrganizeFileResult struct {
OriginalPath string
NewPath string
FolderCreated bool
Moved bool
CoversMoved int
CoversError error
}
OrganizeFileResult contains the results of organizing a file.
func MoveFileIntoOrganizedFolder ¶ added in v0.0.41
func MoveFileIntoOrganizedFolder(originalPath, targetFolder string, opts OrganizedNameOptions) (*OrganizeFileResult, error)
MoveFileIntoOrganizedFolder moves a file (and its associated covers and file sidecar) into the given target folder, computing the destination filename from opts. The target folder is created if missing. After a successful move the source directory is cleaned up if empty. Use this when the destination folder is already known (e.g. promoting a root-level file into an existing book folder), so the caller doesn't have to re-derive the folder from opts and risk landing in a different folder than intended.
func OrganizeRootLevelFile ¶
func OrganizeRootLevelFile(originalPath string, opts OrganizedNameOptions) (*OrganizeFileResult, error)
OrganizeRootLevelFile creates a folder (derived from opts) and moves a root-level file into it. Use this when the destination folder should be computed from the file's metadata. To move a file into an already-known folder (e.g. joining an existing directory-backed book), use MoveFileIntoOrganizedFolder.
type OrganizedNameOptions ¶
type OrganizedNameOptions struct {
AuthorNames []string // Author names as strings for file naming
NarratorNames []string // Narrator names for M4B file naming
Title string
SeriesNumber *float64
SeriesNumberUnit *string // for CBZ: models.SeriesNumberUnitVolume or models.SeriesNumberUnitChapter; nil treated as volume
FileType string // for determining number formatting
}
OrganizedNameOptions contains the data needed to generate organized file/folder names.