gallery

package
v1.14.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: AGPL-3.0 Imports: 36 Imported by: 0

Documentation

Overview

Monbooru is a Linux-only deployment; path handling assumes forward slashes.

Monbooru is a Linux-only deployment; path handling assumes forward slashes.

Index

Constants

View Source
const MangaPageCacheTTL = 5 * time.Minute

MangaPageCacheTTL is the per-page idle reclaim window. Pages whose mtime is older than this are unlinked by the per-gallery reclaim goroutine; the cover thumbnail is exempt.

View Source
const SupportedMIMETypes = "" /* 126-byte string literal not displayed */

SupportedMIMETypes is the accept attribute value for file inputs, listing all MIME types that Monbooru can ingest. The cbz line covers both `.cbz` and plain `.zip` uploads; both ingest as one manga row.

Variables

View Source
var ErrEmptyManga = errors.New("archive contains no recognised image entries")

ErrEmptyManga is returned when a zip carries no recognised image entries. Ingest rejects the file rather than creating an empty row.

View Source
var ErrSourceIdentityExists = errors.New("another source with that label already exists on this image")

ErrSourceIdentityExists reports a relabel that would collide with another origin already recorded on the image.

View Source
var ErrUnsupportedType = errors.New("unsupported file type")

ErrUnsupportedType is returned when the file type is not recognized.

View Source
var PhashHooks struct {
	// OnStored fires after a successful UPDATE images SET phash = ?
	// row. Database is the handle the UPDATE ran on, so the registry
	// dispatch can find the right per-gallery tree.
	OnStored func(database *db.DB, imageID, phash int64)
}

PhashHooks is the extension point a higher layer (internal/relations) uses to keep its in-memory BK-tree consistent with what RecomputeAndStorePhash just wrote. Set by the relations package's init(); nil-safe when no hook is registered (tests, --tags variants). gallery → relations would be a cycle, so the relations side registers itself here rather than being called directly.

Functions

func AddCollectionMembership added in v1.11.0

func AddCollectionMembership(database *db.DB, imageID int64, name string, order *int) error

AddCollectionMembership upserts a membership (adding it or just updating its position) and keeps the home mirror in step: an image with no home adopts this one; re-setting the home's own position updates the mirror.

func AddManualAnnotation added in v1.14.0

func AddManualAnnotation(database *db.DB, imageID int64, x, y, w, h int, body string) error

AddManualAnnotation stores an operator-drawn box (manual = 1, no source identity). Coordinates are the caller's already-validated original-image pixels; body is plain text.

func AddSourceMembership added in v1.13.0

func AddSourceMembership(database *db.DB, imageID int64, site, postID, url string) error

AddSourceMembership upserts one origin (adding it or updating its url, keyed by site+post_id) and rebinds the primary mirror. An empty incoming url never clears a stored one - a url-less re-push or enrich of a known origin must not wipe operator-entered or previously-fetched provenance, matching the commentary path's empty-guard.

func AnnotationsForImage added in v1.13.0

func AnnotationsForImage(database *db.DB, imageID int64) ([]models.Annotation, error)

AnnotationsForImage returns every positional note overlaid on imageID, carrying the row id and manual flag so the editable list can address a box and distinguish operator-drawn boxes from source-pulled ones.

func ChildIDsByParentURL added in v1.14.0

func ChildIDsByParentURL(database *db.DB, url string) ([]int64, error)

ChildIDsByParentURL returns the images whose origin rows declare the given URL as their parent - the child-side probe of the derivative-edge linking.

func ClaimOwnership

func ClaimOwnership(path string)

ClaimOwnership chowns path to the current process UID/GID so later rename/delete operations don't hit EACCES on files originally written by a different user (rsynced from another machine, rootless Podman where the container's UID 0 doesn't match the bind mount's owner).

Best-effort: failures log at debug and never abort the caller. ENOENT is silenced because callers race deletions and watcher events.

func CollectionCeilingHidden added in v1.14.0

func CollectionCeilingHidden(database *db.DB, name string, excludeIDs []int64) (int, error)

CollectionCeilingHidden returns how many of name's visible members the rating ceiling (excludeIDs) hides: the ceiling-blind visible count minus the ceiling-filtered count. Zero when no ceiling is active or none are hidden.

func CollectionMemberIDs added in v1.11.0

func CollectionMemberIDs(database *db.DB, name string) ([]int64, error)

CollectionMemberIDs returns every image id filed under name (case- insensitive), missing rows included, so a rename or dissolve reaches the whole collection rather than only its visible members.

func CollectionSamples added in v1.11.0

func CollectionSamples(database *db.DB, names []string, per int, excludeIDs []int64) (map[string][]CollectionSample, error)

CollectionSamples returns up to per visible members for each named collection, in reading order (position first with NULLs last, then id). Members above the rating ceiling (excludeIDs) are skipped so the preview matches the listing. The map is keyed by lower-cased label so a single key survives images that stored the same NOCASE label in different cases. One LIMITed query per name: the reading index stops each walk after the first per visible members, where a single ROW_NUMBER window would rank every member of every listed label first.

func CollectionsForImage added in v1.11.0

func CollectionsForImage(database *db.DB, imageID int64) ([]models.Collection, error)

CollectionsForImage returns every membership of imageID, ordered as the detail page renders them: positioned rows first (ascending), then the unordered ones by name.

func ComputePhashFromThumb added in v1.8.0

func ComputePhashFromThumb(thumbPath string) (int64, error)

ComputePhashFromThumb opens the static thumbnail JPEG at thumbPath and returns its canonicalised 64-bit perceptual hash as a signed int64 (SQLite's INTEGER affinity). Returns a non-nil error when the file is missing or undecodable; the caller leaves images.phash NULL in that case.

The thumbnail is the uniform input across every visual file_type: jpeg / png / webp / gif use their static thumbnail directly, mp4 / webm use the 10%-of-duration frame the existing pipeline writes, and cbz uses the cover thumbnail. Hashing the thumbnail (not the original) keeps the hashed pixels identical to what the operator sees on the gallery grid.

func CountCollections added in v1.11.0

func CountCollections(database *db.DB, nameFilter string, excludeIDs []int64) (int, error)

CountCollections returns the number of distinct collection labels with at least one visible member, honoring the same substring filter and the rating ceiling (excludeIDs).

func DecodeImageWithCap added in v1.8.0

func DecodeImageWithCap(r io.Reader) (image.Image, error)

DecodeImageWithCap is image.Decode gated on a megapixel ceiling. Runs image.DecodeConfig first to read just the header, refuses any image whose width*height exceeds maxImagePixels, then replays the header bytes alongside the rest of the stream so the full Decode works on non-seekable readers (zip page streams). Mirrors the stdlib signature minus the format-name return.

func DeleteAnnotation added in v1.14.0

func DeleteAnnotation(database *db.DB, id int64) error

DeleteAnnotation removes one box by id, source-pulled or operator-drawn. A re-pull of the source re-adds a deleted source box; the bulk source-keyed replace / removal paths still gate on manual = 0, so they never touch an operator box.

func DetectFileType

func DetectFileType(path string) (string, error)

DetectFileType returns the file type constant for the given path, trying extension matching first and falling back to magic bytes.

func EnsureMangaPage added in v1.7.0

func EnsureMangaPage(thumbnailsPath, canonPath string, imageID int64, n int) (string, error)

EnsureMangaPage returns the on-disk path for the n-th page of the archive at canonPath, extracting it into the per-image cache on miss. n is 1-based. The returned path is suitable for http.ServeFile; mtime is bumped on hit so the reclaim goroutine counts the access.

func EnsureMangaPageInCache added in v1.7.0

func EnsureMangaPageInCache(cacheRoot, canonPath string, imageID int64, n int) (string, error)

EnsureMangaPageInCache extracts to <cacheRoot>/<imageID>/page_NNNN directly. Used by the auto-tagger which threads the per-gallery manga cache directory through RunWithTaggers without owning the full thumbnails-path derivation.

func EnsureMangaPageThumb added in v1.7.0

func EnsureMangaPageThumb(thumbnailsPath, canonPath string, imageID int64, n int) (string, error)

EnsureMangaPageThumb returns the on-disk path of the n-th page's thumbnail (300px-longest-side JPEG Q85). Generated on miss from the raw page bytes (which may themselves be extracted on demand).

func ExtractVideoFrames

func ExtractVideoFrames(srcPath, tmpDir string, positions []float64) ([]string, error)

ExtractVideoFrames writes one JPEG per relative offset (0.0..1.0) from the video into tmpDir. Frames whose extraction fails are skipped, so a shorter-than-requested return slice means partial success.

func FolderPath

func FolderPath(galleryPath, filePath string) string

FolderPath computes the relative directory of filePath under galleryPath. Returns "" for files at the gallery root. Linux paths.

func Generate

func Generate(srcPath, dstDir string, imageID int64, fileType string) error

Generate writes the static thumbnail (and animated hover for videos and GIFs when ffmpeg is available) for the given file under dstDir.

func HashFile

func HashFile(path string) (string, error)

HashFile computes the SHA-256 of the file at path.

func HoverPath

func HoverPath(dir string, imageID int64) string

func ImageIDBySourceURL added in v1.14.0

func ImageIDBySourceURL(database *db.DB, url string) (int64, bool)

ImageIDBySourceURL returns the image holding an origin with the given URL - the parent-side probe of the derivative-edge linking. When several images claim the same origin the lowest id wins, for a stable pick.

func InboxCountUnder added in v1.8.2

func InboxCountUnder(database *db.DB, excludeIDs []int64) (int, error)

InboxCountUnder counts non-missing inbox images (is_inbox = 1), dropping any whose tag list intersects excludeIDs (the rating ceiling).

func Ingest

func Ingest(database *db.DB, galleryPath, thumbnailsPath, path, fileType, origin string) (*models.Image, bool, error)

Ingest processes a single file: hash, dimension probe, metadata extraction, DB insert, thumbnail. Returns (image, isDuplicate, error). origin records how the file got in ("ingest" / "upload" / caller-supplied string); empty defaults to "ingest".

func IsVideoType

func IsVideoType(fileType string) bool

IsVideoType returns true for video file types.

func MakeSourcePrimary added in v1.14.0

func MakeSourcePrimary(database *db.DB, imageID int64, site, postID string) error

MakeSourcePrimary reorders one existing origin to primary by moving it below every other rowid (the table-wide MIN keeps the new rowid unique) and rebinds the mirror. Promoting the current primary is a harmless no-op move.

func MangaCacheDir added in v1.7.0

func MangaCacheDir(thumbnailsPath string) string

MangaCacheDir derives the per-gallery manga cache directory from the gallery's thumbnails directory. Manga cache lives at `<data_path>/<gallery>/manga/`, sibling to thumbnails.

func MangaImageDir added in v1.7.0

func MangaImageDir(thumbnailsPath string, imageID int64) string

MangaImageDir returns the per-image cache subdirectory under the gallery's manga cache. Created on demand by the page-extract path.

func MangaPagePath added in v1.7.0

func MangaPagePath(imageDir string, n int, ext string) string

MangaPagePath returns the on-disk path for the n-th cached page (1- based) with the supplied original-extension tail. Zero-padded to four digits so a directory listing sorts in display order.

func MangaPageThumbPath added in v1.7.0

func MangaPageThumbPath(imageDir string, n int) string

MangaPageThumbPath is the per-page thumbnail companion to MangaPagePath. JPEG by construction.

func Md5File added in v1.13.0

func Md5File(path string) (string, error)

Md5File computes the MD5 of the file at path. Used only to verify a source refetch still points at the same bytes (boorus key posts on md5), never for dedup - sha256 remains the content address.

func NormalizeImage added in v1.9.4

func NormalizeImage(srcPath string) error

NormalizeImage re-encodes srcPath in place to a baseline JPEG via ffmpeg. Some CDN image resizers emit JPEGs with a luma/chroma subsampling ratio Go's image/jpeg refuses ("unsupported JPEG feature"); ffmpeg decodes them, and the re-encode lands a file the stdlib decode path - dimension probe, thumbnail, phash - can read. The caller passes only a freshly uploaded file it owns, so no operator file on disk is rewritten. Returns an error when ffmpeg is absent or the re-encode fails, leaving the original in place.

func PathInside

func PathInside(root, target string) bool

PathInside reports whether target resolves inside root. Both arguments should be cleaned and absolute. Uses filepath.Rel so a sibling directory sharing a literal prefix (`/data/gallery` vs `/data/gallery_backup`) is correctly rejected. A target equal to root counts as inside.

func PhashMissingUnder added in v1.8.2

func PhashMissingUnder(database *db.DB, excludeIDs []int64) (int, error)

PhashMissingUnder is the relations-hub "PhashMissing" analogue: non-missing images with NULL phash, minus the ceiling-hidden ones.

func ProbeDurationSeconds added in v1.8.0

func ProbeDurationSeconds(srcPath string) (float64, bool)

ProbeDurationSeconds is the public-package wrapper around the internal duration probe. Callers in the ingest and re-extract paths use it to populate images.duration_seconds for video rows. Returns (0, false) when ffmpeg is unavailable or probing fails; callers leave the column NULL in that case.

func ProbeVideoDimensions added in v1.9.1

func ProbeVideoDimensions(srcPath string) (int, int, bool)

ProbeVideoDimensions returns the first video stream's width and height via ffprobe. Mirrors ProbeDurationSeconds: (0, 0, false) when ffmpeg is unavailable or the probe fails so callers leave width and height NULL in that case.

func RecomputeAndStorePhash added in v1.8.0

func RecomputeAndStorePhash(ctx context.Context, database *db.DB, imageID int64, thumbnailsPath string) error

RecomputeAndStorePhash recomputes the phash from the image's static thumbnail and writes it back. The ingest path calls this after thumbnail generation; the re-extract maintenance loop calls it once per image alongside its other recompute steps. When the thumbnail is unreadable - missing because Generate failed, or undecodable because the disk image is corrupt - the row's phash stays at its previous value (or NULL on first compute). The relations system then ignores the row until the operator rebuilds thumbnails and re-runs the compute.

func RemoveCollectionMembership added in v1.11.0

func RemoveCollectionMembership(database *db.DB, imageID int64, name string) error

RemoveCollectionMembership drops a membership; when it was the home the next membership is promoted (or the mirror cleared if none remain).

func RemoveMangaCache added in v1.7.0

func RemoveMangaCache(thumbnailsPath string, imageID int64)

RemoveMangaCache removes the per-image cache directory. Called from the per-image delete path so a deleted manga's pages and cover disappear with the row, and from sync's in-place-edit branch so a cbz whose bytes changed drops its stale page cache before the thumbnails are regenerated.

func RemoveSourceMembership added in v1.13.0

func RemoveSourceMembership(database *db.DB, imageID int64, site, postID string) error

RemoveSourceMembership drops one origin along with the annotations it pulled (they carry the same identity and have no other removal path) and rebinds the primary mirror.

func RenameSourceMembership added in v1.13.0

func RenameSourceMembership(database *db.DB, imageID int64, prevSite, prevPost, site, postID, url string) error

RenameSourceMembership relabels one origin in place, keeping its commentary / original / md5 / fetched_at and its age (a relabelled primary stays primary), and re-keys the origin's annotations so they follow the new identity. When the new identity already exists on the image the two rows merge: the target keeps its own commentary and original unless it has none, and the old row is dropped. A missing prev identity falls back to a plain upsert.

func ReorderCollection added in v1.13.0

func ReorderCollection(database *db.DB, name string, ids []int64) error

ReorderCollection rewrites name's ordering from ids: 1-based positions in slice order, every other membership cleared to unordered. Ids not filed under name are no-ops. The home mirror follows for rows homed on the collection, the same resync shape the rename job uses. A list that fits one chunk (the click-order path, capped at the 200 window) runs in a single atomic transaction; a larger filename sort splits the position writes into 500-id chunks so the write tx stays bounded.

func ReplaceSourceAnnotations added in v1.13.0

func ReplaceSourceAnnotations(database *db.DB, imageID int64, site, postID string, boxes []models.Annotation) error

ReplaceSourceAnnotations sets the annotations attributed to one source to exactly boxes, dropping whatever that source contributed before (clone on re-pull). An empty boxes clears the source's set and leaves other sources' boxes untouched.

func ResolveSubdir

func ResolveSubdir(galleryPath, folder string) (string, error)

ResolveSubdir validates a user-supplied folder path and returns the absolute destination directory under galleryPath. An empty folder yields the gallery root. Paths containing ".." or absolute paths are rejected so callers cannot escape the root.

func SetCollectionFindRelations added in v1.13.0

func SetCollectionFindRelations(database *db.DB, name string, enabled bool) error

SetCollectionFindRelations flips a collection's find-relations opt-in. The flag is a bare presence row; disabling just deletes it.

func SetHomeCollection added in v1.11.0

func SetHomeCollection(database *db.DB, imageID int64, name string, order *int) error

SetHomeCollection points imageID's home at name with the given order, renaming or clearing the previous home and keeping image_collections in sync. Used by the API and ingest, which carry a single collection field. An empty name clears the home, promoting another membership if one is left so the series != "" invariant holds. Pointing the home at a label the image already belongs to promotes that membership in place and leaves the former home as an extra; only relabelling onto a new name (or clearing) drops the old home.

func SetPrimarySource added in v1.13.0

func SetPrimarySource(database *db.DB, imageID int64, site, url string) error

SetPrimarySource edits the primary origin in place - the site / url the scalar mirrors - or clears it when both are empty, creating a first origin when the image has none. Used by the API PATCH, which carries a single source/url pair. Operating on the primary row's rowid keeps its age so it stays primary through a relabel.

func SetSourceCommentary added in v1.13.0

func SetSourceCommentary(database *db.DB, imageID int64, site, postID, commentary string) error

SetSourceCommentary sets the artist commentary attributed to one origin. See setSourceTextField for the upsert / clear semantics.

func SetSourceMD5 added in v1.13.0

func SetSourceMD5(database *db.DB, imageID int64, site, postID, md5 string) error

SetSourceMD5 records the md5 the source claimed for one origin (the audit trail; never a dedup key). An empty incoming value keeps the stored one.

func SetSourceOriginal added in v1.14.0

func SetSourceOriginal(database *db.DB, imageID int64, site, postID, original string) error

SetSourceOriginal sets the upstream artist source the booru post declared for one origin. See setSourceTextField for the upsert / clear semantics.

func SetSourceParentURL added in v1.14.0

func SetSourceParentURL(database *db.DB, imageID int64, site, postID, parentURL string) error

SetSourceParentURL records the canonical URL of the post one origin declared as its parent (booru parent/child). An empty incoming value keeps the stored one, so a parentless re-push never clears it.

func SetSourceSimilarity added in v1.14.0

func SetSourceSimilarity(database *db.DB, imageID int64, site, postID string, score float64) error

SetSourceSimilarity records the score a similarity lookup matched one origin with - the mark that lets later refetches of that origin skip the md5 verify (its file differs from the stored one by design). A zero incoming score keeps the stored one, so a plain refetch never clears it.

func SortCollectionByFilename added in v1.14.0

func SortCollectionByFilename(database *db.DB, name string) error

SortCollectionByFilename orders every non-missing member of name by filename (natural order over the basename), ceiling-blind over the whole collection rather than just the reorder window, and applies the result through ReorderCollection.

func SourceSimilarityMatched added in v1.14.0

func SourceSimilarityMatched(database *db.DB, imageID int64, site, postID string) bool

SourceSimilarityMatched reports whether one origin was recorded by a similarity lookup.

func SourcesForImage added in v1.13.0

func SourcesForImage(database *db.DB, imageID int64) ([]models.ImageSource, error)

SourcesForImage returns every origin of imageID, primary first.

func ThumbnailPath

func ThumbnailPath(dir string, imageID int64) string

func TouchCacheFile added in v1.7.0

func TouchCacheFile(path string)

TouchCacheFile bumps the mtime/atime of path to now. Used on every cache hit so the per-gallery reclaim goroutine sees recently-served pages as live. Best-effort: a chtimes failure logs at debug and the cache hit still proceeds.

func UniqueDestPath added in v1.1.0

func UniqueDestPath(destDir, filename string) string

UniqueDestPath returns a path under destDir that does not currently exist, appending `_1`, `_2`, ... to the stem on collision. Shared by the upload form, API createImage, and merge-extract paths so the rename rule is consistent. The stat check is racy (TOCTOU); callers needing stronger guarantees should O_CREATE|O_EXCL themselves.

func UpdateAnnotation added in v1.14.0

func UpdateAnnotation(database *db.DB, id int64, x, y, w, h int, body string) error

UpdateAnnotation edits one box by id, source-pulled or operator-drawn, keeping its manual flag. An edit to a source box is overwritten by a later re-pull, the same rule commentary follows.

Types

type CollectionSample added in v1.11.0

type CollectionSample struct {
	ID       int64
	Order    *int
	Filename string
}

CollectionSample is one preview tile: the image id, its position within the collection (nil when the membership is unordered), and its filename for the reorder dialog's filename mode / tooltip.

func CollectionMembers added in v1.13.0

func CollectionMembers(database *db.DB, name string, excludeIDs []int64, limit, offset int) ([]CollectionSample, error)

CollectionMembers returns one window of name's visible members (NOCASE) in reading order (position first with NULLs last, then id), skipping members above the rating ceiling (excludeIDs) like the page listing. Windowed so a huge label can't force a full render in one dialog body.

type CollectionSummary added in v1.11.0

type CollectionSummary struct {
	Name          string
	Count         int
	FindRelations bool
	Samples       []CollectionSample
}

CollectionSummary is one row of the collections management page: a label, its visible member count, and a few members for the preview. FindRelations reports the collection's opt-in to the relations session surfacing pairs among its own members.

func ListCollections added in v1.11.0

func ListCollections(database *db.DB, nameFilter, sort string, limit, offset int, excludeIDs []int64) ([]CollectionSummary, error)

ListCollections returns one page of collection labels with their visible (non-missing) member counts. sort "name" orders alphabetically; any other value orders by member count descending, name as tiebreaker. Members carrying a tag in excludeIDs (the rating ceiling) drop from the count, so a collection with no visible member left falls off the page.

type DeleteImageResult

type DeleteImageResult struct {
	CanonicalPath string
	FolderPath    string
	IsMissing     bool
}

DeleteImageResult holds metadata about a deleted image for post-delete cleanup.

func DeleteImage

func DeleteImage(database *db.DB, galleryPath, thumbnailsPath string, id int64, removeAllTags func(int64) error, onImageDelete func(int64) error) (*DeleteImageResult, error)

DeleteImage removes one image from the database, then cleans up files on disk. Two callbacks are injected (rather than direct package imports) to avoid internal/gallery → internal/tags / internal/relations cycles:

  • removeAllTags clears the image_tags rows for id and prunes any zero-usage tag that the image alone was carrying.
  • onImageDelete (may be nil) fixes up relations-graph state that the FK CASCADE can't reach - specifically dup_groups.original_image_id, which is NOT NULL with no CASCADE so the parent DELETE would fail while the image is still wearing the original badge.

galleryPath gates the canonical-path unlink behind PathInside so a row whose canonical_path drifted outside the gallery root (a hand- edited DB, a renamed mount) can't trick the handler into removing arbitrary filesystem paths; sibling unlink paths in handlers_image_ actions.go and handlers_maintenance.go already carry the same gate.

type FolderNode

type FolderNode struct {
	Path     string
	Name     string
	Count    int
	Depth    int
	Children []FolderNode
}

FolderNode represents a folder in the gallery tree.

func FolderTree

func FolderTree(database *db.DB) ([]FolderNode, error)

FolderTree builds the folder tree from images. Each node's Count rolls up its own images plus every descendant's, so a parent with only subfolder content still shows a non-zero figure. Empty intermediate folders are included so the arborescence is complete.

func FolderTreeUnder added in v1.8.2

func FolderTreeUnder(database *db.DB, excludeIDs []int64) ([]FolderNode, error)

FolderTreeUnder mirrors FolderTree with the ceiling predicate folded into the per-folder GROUP BY. The post-processing (ancestor reconstruction, count rollup, pointer-to-value tree copy) reuses the same code as the blind variant via the small helper below so the two stay in sync.

type Manga added in v1.7.0

type Manga struct {
	Pages []MangaPage
	// contains filtered or unexported fields
}

Manga is an opened cbz/zip archive plus its sorted page list. The caller must Close() to release the file handle.

func OpenManga added in v1.7.0

func OpenManga(path string) (*Manga, error)

OpenManga opens path as a zip, builds the natural-sorted page list, and returns the open archive. ErrEmptyManga is returned for zips with zero recognised image entries; callers ingest no row in that case.

func (*Manga) Close added in v1.7.0

func (m *Manga) Close() error

Close releases the archive file handle.

func (*Manga) CoverDimensions added in v1.7.0

func (m *Manga) CoverDimensions() (int, int, error)

CoverDimensions reads page 1's dimensions without decoding the full pixel buffer. Used at ingest to populate images.width/height with the cover's geometry.

func (*Manga) CoverImage added in v1.7.0

func (m *Manga) CoverImage() (image.Image, error)

CoverImage decodes page 1 (entry 0 of the sorted list) into an image.Image suitable for the gallery thumbnail pipeline.

func (*Manga) ExtractPage added in v1.7.0

func (m *Manga) ExtractPage(n int, dst string) error

ExtractPage writes page n's bytes to dst via a temp file + atomic rename so a concurrent reader never sees a partial file. dst's parent directory must already exist.

func (*Manga) PageCacheExt added in v1.7.0

func (m *Manga) PageCacheExt(n int) string

PageCacheExt returns the extension to use for the n-th cached page file: the archive entry's lowercase extension, with a leading dot. Callers compose the full filename via PageCachePath.

func (*Manga) PageReader added in v1.7.0

func (m *Manga) PageReader(n int) (io.ReadCloser, error)

PageReader opens an io.ReadCloser for the n-th page (0-based). Callers must Close it.

func (*Manga) Reader added in v1.7.0

func (m *Manga) Reader() *zip.Reader

Reader returns the underlying *zip.Reader for callers that want to stream entries directly (e.g. the ComicInfo parser).

type MangaCacheReclaimer added in v1.7.0

type MangaCacheReclaimer struct {
	// contains filtered or unexported fields
}

MangaCacheReclaimer ticks every minute and unlinks `page_NNNN.<ext>` raw-bytes files older than the TTL. cover.jpg and `page_NNNN_thumb.jpg` are exempt: the cover backs the gallery thumbnail and the page thumbs are pre-generated at ingest, so the reclaim is scoped to the lazy reader-bytes cache that grows during reading sessions. Run alongside the gallery's watcher; stops on ctx cancel.

func NewMangaCacheReclaimer added in v1.7.0

func NewMangaCacheReclaimer(dir string) *MangaCacheReclaimer

NewMangaCacheReclaimer constructs a reclaimer for the given gallery manga cache directory. dir must be the per-gallery `<data_path>/ <gallery>/manga` path.

func (*MangaCacheReclaimer) Start added in v1.7.0

func (r *MangaCacheReclaimer) Start(ctx context.Context)

Start spawns the reclaim goroutine. Idempotent against repeated calls on the same instance; subsequent Start calls are no-ops.

func (*MangaCacheReclaimer) Stop added in v1.7.0

func (r *MangaCacheReclaimer) Stop()

Stop cancels the goroutine and waits for it to exit. Idempotent.

type MangaPage added in v1.7.0

type MangaPage struct {
	Path         string
	OriginalName string
}

MangaPage describes one image entry inside a cbz/zip archive. Path is the entry's full archive path verbatim (used by the zip reader); OriginalName is the leaf basename used to choose the cache extension for the serve / page-bytes path.

type MoveImageResult added in v1.2.0

type MoveImageResult struct {
	NewCanonicalPath string
	NewFolderPath    string
}

MoveImageResult reports the new location of a moved image so the caller can render it and invalidate caches without re-querying.

func MoveImage added in v1.2.0

func MoveImage(database *db.DB, galleryPath string, id int64, targetFolder string) (*MoveImageResult, error)

MoveImage relocates the canonical file of image id into targetFolder (relative to galleryPath). Filename collisions auto-suffix via UniqueDestPath, matching the upload and API paths. Callers that hold a watcher should gate this under a job type the watcher suppresses, otherwise the resulting CREATE/REMOVE events race with the DB update.

type SourceLabelCount added in v1.8.0

type SourceLabelCount struct {
	Source string
	Count  int
}

SourceLabelCount is one row of the sidebar's Sources section: a site label from image_sources and the count of non-missing images carrying it as any origin, matching the any-membership `source:` filter.

func SourceLabelCountsQuery added in v1.8.0

func SourceLabelCountsQuery(database *db.DB, limit int) ([]SourceLabelCount, error)

SourceLabelCountsQuery returns the top site labels (by image count desc, then alphabetical) with no rating ceiling applied.

func SourceLabelCountsUnderQuery added in v1.8.2

func SourceLabelCountsUnderQuery(database *db.DB, limit int, excludeIDs []int64) ([]SourceLabelCount, error)

SourceLabelCountsUnderQuery returns the top site labels by image count across image_sources - so a secondary origin surfaces too, matching the any-membership source: filter - honoring the rating ceiling (excludeIDs).

type SyncResult

type SyncResult struct {
	Added      int
	Removed    int
	Moved      int
	Duplicates int
}

SyncResult summarizes the outcome of a gallery sync.

func Sync

func Sync(ctx context.Context, database *db.DB, galleryPath, thumbnailsPath string, maxFileSizeMB int, progress func(processed, total int, message string)) (SyncResult, error)

Sync runs the three-phase gallery sync (walk, reconcile, mark-missing). progress receives (processed, total, message) tuples shaped to match jobs.Manager.Update so the handler can forward the call verbatim. maxFileSizeMB <= 0 disables the per-file cap.

type Watcher

type Watcher struct {
	OnEvent  func(msg string) // callback for status notifications (may be nil)
	OnChange func()           // callback fired after any image add/remove (may be nil)
	// contains filtered or unexported fields
}

Watcher watches the gallery directory for new files and ingests them.

func NewWatcher

func NewWatcher(galleryName, galleryPath, thumbnailsPath string, maxFileSizeMB int, database *db.DB, jobManager *jobs.Manager) (*Watcher, error)

NewWatcher creates and initializes a filesystem watcher for one gallery. galleryName prefixes status messages so multi-gallery setups can tell which gallery an event came from.

func (*Watcher) Run

func (w *Watcher) Run(ctx context.Context) error

Run starts the event loop. Returns when ctx is cancelled.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL