Documentation
¶
Index ¶
- Constants
- Variables
- func BuiltInFileExtensions() []string
- func DeliveredFileTypeExtension(fileType string) string
- func DeliveredFileTypeForExtension(ext string) (string, bool)
- func EbookCoverRank(fileType string) int
- func FileExtensionForPath(path string) string
- func FileTypeForPath(path string) string
- func FileTypeLabel(fileType string) string
- func FileTypeMimeType(fileType string) string
- func GetDataSourcePriority(source string) int
- func IsAudiobookFileType(fileType string) bool
- func IsBuiltInFileExtension(ext string) bool
- func IsBuiltInFileType(fileType string) bool
- func IsEbookFileType(fileType string) bool
- func IsPageBasedFileType(fileType string) bool
- func PluginDataSource(scope, id string) string
- func ReachableFileTypes(from string) []string
- func ResolveBookFileDisplayNames(books ...*Book)
- func ResolveFileDisplayNames(files []*File)
- type AppSetting
- type Author
- type Book
- type BookGenre
- type BookSeries
- type BookTag
- type Chapter
- type ConversionStep
- type File
- type FileFingerprint
- type FileIdentifier
- type Genre
- type GenreAlias
- type Job
- type JobBulkDownloadData
- type JobExportData
- type JobHashGenerationData
- type JobLog
- type JobRecomputeReviewData
- type JobScanData
- type Library
- type LibraryPath
- type LibraryPluginCustomization
- type LibraryPluginFieldSetting
- type LibraryPluginHookConfig
- type List
- type ListBook
- type ListShare
- type Narrator
- type Permission
- type Person
- type PersonAlias
- type Plugin
- type PluginConfig
- type PluginFieldSetting
- type PluginHookConfig
- type PluginIdentifierType
- type PluginRepository
- type PluginStatus
- type Publisher
- type PublisherAlias
- type Role
- type Series
- type SeriesAlias
- type ShareLink
- type StringList
- type Tag
- type TagAlias
- type User
- type UserLibraryAccess
- type UserLibrarySettings
- type UserRef
- type UserSettings
Constants ¶
const ( //tygo:emit export type DataSource = typeof DataSourceManual | typeof DataSourceSidecar | typeof DataSourcePlugin | typeof DataSourceFileMetadata | typeof DataSourceExistingCover | typeof DataSourceEPUBMetadata | typeof DataSourceCBZMetadata | typeof DataSourceM4BMetadata | typeof DataSourcePDFMetadata | typeof DataSourceMOBIMetadata | typeof DataSourceFilepath | `plugin:${string}`; DataSourceManual = "manual" DataSourceSidecar = "sidecar" DataSourcePlugin = "plugin" DataSourceFileMetadata = "file_metadata" DataSourceExistingCover = "existing_cover" DataSourceEPUBMetadata = "epub_metadata" DataSourceCBZMetadata = "cbz_metadata" DataSourceM4BMetadata = "m4b_metadata" DataSourcePDFMetadata = "pdf_metadata" DataSourceMOBIMetadata = "mobi_metadata" // MOBI and AZW3 files DataSourceFilepath = "filepath" // DataSourcePluginPrefix is the prefix for plugin-specific data sources. // Actual values are "plugin:scope/id" (e.g., "plugin:shisho/goodreads-metadata"). DataSourcePluginPrefix = "plugin:" )
const ( DataSourceManualPriority = 0 DataSourceSidecarPriority = 1 // Sidecar has higher priority than file metadata DataSourcePluginPriority = 2 // Plugin enricher/parser results DataSourceFileMetadataPriority = 3 // All file-derived sources share this DataSourceFilepathPriority = 4 )
Lower priority means that we respect it more than higher priority.
const ( //tygo:emit export type IdentifierType = typeof IdentifierTypeISBN10 | typeof IdentifierTypeISBN13 | typeof IdentifierTypeASIN | typeof IdentifierTypeUUID | typeof IdentifierTypeGoodreads | typeof IdentifierTypeGoogle | typeof IdentifierTypeOther | (string & {}); IdentifierTypeISBN10 = "isbn_10" IdentifierTypeISBN13 = "isbn_13" IdentifierTypeASIN = "asin" IdentifierTypeUUID = "uuid" IdentifierTypeGoodreads = "goodreads" IdentifierTypeGoogle = "google" IdentifierTypeOther = "other" )
FileIdentifier type constants.
const ( //tygo:emit export type FileType = typeof FileTypeAZW3 | typeof FileTypeCBZ | typeof FileTypeEPUB | typeof FileTypeKePub | typeof FileTypeM4B | typeof FileTypeMOBI | typeof FileTypePDF; //tygo:emit export type DeliveredFileType = FileType; FileTypeAZW3 = "azw3" FileTypeCBZ = "cbz" FileTypeEPUB = "epub" // FileTypeKePub is Kobo's EPUB: an EPUB with Kobo markup, named // .kepub.epub. Kobo readers and KOReader tell it from an EPUB by that // name alone, and so does Shisho. A Calibre library stores one as a // bare .kepub, which is a KePub too. FileTypeKePub = "kepub" FileTypeM4B = "m4b" FileTypeMOBI = "mobi" FileTypePDF = "pdf" )
const ( //tygo:emit export type FileRole = typeof FileRoleMain | typeof FileRoleSupplement; FileRoleMain = "main" FileRoleSupplement = "supplement" )
const ( //tygo:emit export type ReviewOverride = typeof ReviewOverrideReviewed | typeof ReviewOverrideUnreviewed; ReviewOverrideReviewed = "reviewed" ReviewOverrideUnreviewed = "unreviewed" )
const ( //tygo:emit export type ReviewedFilter = typeof ReviewedFilterAll | typeof ReviewedFilterNeedsReview | typeof ReviewedFilterReviewed; ReviewedFilterAll = "all" ReviewedFilterNeedsReview = "needs_review" ReviewedFilterReviewed = "reviewed" )
ReviewedFilter values for the book list endpoint's reviewed_filter query param. "" and "all" both mean "all books"; the other two scope to needs-review or reviewed books respectively.
const ( //tygo:emit export type JobStatus = typeof JobStatusPending | typeof JobStatusInProgress | typeof JobStatusCompleted | typeof JobStatusFailed; JobStatusPending = "pending" JobStatusInProgress = "in_progress" JobStatusCompleted = "completed" JobStatusFailed = "failed" )
const ( //tygo:emit export type JobType = typeof JobTypeExport | typeof JobTypeScan | typeof JobTypeBulkDownload | typeof JobTypeHashGeneration | typeof JobTypeRecomputeReview; JobTypeExport = "export" JobTypeScan = "scan" JobTypeBulkDownload = "bulk_download" JobTypeHashGeneration = "hash_generation" JobTypeRecomputeReview = "recompute_review" )
const ( //tygo:emit export type CoverAspectRatio = typeof CoverAspectRatioBook | typeof CoverAspectRatioAudiobook | typeof CoverAspectRatioBookFallbackAudiobook | typeof CoverAspectRatioAudiobookFallbackBook; CoverAspectRatioBook = "book" CoverAspectRatioAudiobook = "audiobook" CoverAspectRatioBookFallbackAudiobook = "book_fallback_audiobook" CoverAspectRatioAudiobookFallbackBook = "audiobook_fallback_book" )
Cover aspect ratio preference constants. Determine which file's cover a hybrid (e.g. EPUB + M4B) book serves.
const ( //tygo:emit export type ListPermission = typeof ListPermissionViewer | typeof ListPermissionEditor | typeof ListPermissionManager; ListPermissionViewer = "viewer" ListPermissionEditor = "editor" ListPermissionManager = "manager" )
List permission levels.
const ( //tygo:emit export type ListSort = typeof ListSortManual | typeof ListSortAddedAtDesc | typeof ListSortAddedAtAsc | typeof ListSortTitleAsc | typeof ListSortTitleDesc | typeof ListSortAuthorAsc | typeof ListSortAuthorDesc; ListSortAddedAtDesc = "added_at_desc" ListSortAddedAtAsc = "added_at_asc" ListSortTitleAsc = "title_asc" ListSortTitleDesc = "title_desc" ListSortAuthorAsc = "author_asc" ListSortAuthorDesc = "author_desc" ListSortManual = "manual" )
List default sort options.
const ( //tygo:emit export type LogLevel = typeof LogLevelDebug | typeof LogLevelInfo | typeof LogLevelWarn | typeof LogLevelError | typeof LogLevelFatal; LogLevelDebug = "debug" LogLevelInfo = "info" LogLevelWarn = "warn" LogLevelError = "error" LogLevelFatal = "fatal" )
const ( //tygo:emit export type AuthorRole = typeof AuthorRoleWriter | typeof AuthorRolePenciller | typeof AuthorRoleInker | typeof AuthorRoleColorist | typeof AuthorRoleLetterer | typeof AuthorRoleCoverArtist | typeof AuthorRoleEditor | typeof AuthorRoleTranslator; AuthorRoleWriter = "writer" AuthorRolePenciller = "penciller" AuthorRoleInker = "inker" AuthorRoleColorist = "colorist" AuthorRoleLetterer = "letterer" AuthorRoleCoverArtist = "cover_artist" AuthorRoleEditor = "editor" AuthorRoleTranslator = "translator" )
Author role constants for CBZ ComicInfo.xml creator types.
const ( //tygo:emit export type PluginHookType = typeof PluginHookInputConverter | typeof PluginHookFileParser | typeof PluginHookMetadataEnricher; PluginHookInputConverter = "inputConverter" PluginHookFileParser = "fileParser" PluginHookMetadataEnricher = "metadataEnricher" )
Plugin hook type constants.
const ( //tygo:emit export type PluginMode = typeof PluginModeEnabled | typeof PluginModeManualOnly | typeof PluginModeDisabled; PluginModeEnabled = "enabled" PluginModeManualOnly = "manual_only" PluginModeDisabled = "disabled" )
Plugin mode constants for hook config entries.
const ( ResourceLibraries = "libraries" ResourceBooks = "books" ResourcePeople = "people" ResourceSeries = "series" ResourceUsers = "users" ResourceJobs = "jobs" ResourceConfig = "config" )
Permission resources.
const ( OperationRead = "read" OperationWrite = "write" )
Permission operations.
const ( RoleAdmin = "admin" RoleEditor = "editor" RoleViewer = "viewer" )
Predefined role names.
const ( //tygo:emit export type SeriesNumberUnit = typeof SeriesNumberUnitVolume | typeof SeriesNumberUnitChapter; SeriesNumberUnitVolume = "volume" SeriesNumberUnitChapter = "chapter" )
const ( //tygo:emit export type ShareLinkState = typeof ShareLinkStateActive | typeof ShareLinkStateExpired | typeof ShareLinkStateRevoked; )
Share Link states. The state is derived from revoked_at and expires_at on every read and never stored.
const ( //tygo:emit export type ShareLinkPausedReason = typeof ShareLinkPausedCreatorDeactivated | typeof ShareLinkPausedCreatorNoLibraryAccess; )
Reasons an active Share Link is paused: it does not resolve because of its creator, and works again if the creator's access returns. Like the state, the reason is derived on every read and never stored.
const ( //tygo:emit export type FitMode = typeof FitModeHeight | typeof FitModeWidth; FitModeHeight = "fit-height" FitModeWidth = "fit-width" )
const ( //tygo:emit export type ReflowableTheme = typeof ReflowableThemeLight | typeof ReflowableThemeDark | typeof ReflowableThemeSepia; ReflowableThemeLight = "light" ReflowableThemeDark = "dark" ReflowableThemeSepia = "sepia" )
const ( //tygo:emit export type ReflowableFlow = typeof ReflowableFlowPaginated | typeof ReflowableFlowScrolled; ReflowableFlowPaginated = "paginated" ReflowableFlowScrolled = "scrolled" )
const ( //tygo:emit export type GallerySize = typeof GallerySizeSmall | typeof GallerySizeMedium | typeof GallerySizeLarge | typeof GallerySizeExtraLarge; GallerySizeSmall = "s" GallerySizeMedium = "m" GallerySizeLarge = "l" GallerySizeExtraLarge = "xl" )
const ( // FingerprintAlgorithmSHA256 is the exact-content sha256 hash over the // file's raw bytes. Used for move/rename detection. FingerprintAlgorithmSHA256 = "sha256" )
Fingerprint algorithm identifiers stored in FileFingerprint.Algorithm.
const ( // The tygo:emit lines mirror the Go PlaybackSpeeds var into the // generated TS (a const array plus a union type) so the player's speed // menu and the backend validation share the same set of values. tygo // only processes const/type declarations, so the directives live here // rather than on the var. Keep the emitted list in sync with // PlaybackSpeeds. // //tygo:emit export const PlaybackSpeeds = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3] as const; //tygo:emit export type PlaybackSpeed = (typeof PlaybackSpeeds)[number]; PlaybackSpeedDefault = 1.0 )
Variables ¶
var BuiltInFileTypes = []string{FileTypeAZW3, FileTypeCBZ, FileTypeEPUB, FileTypeKePub, FileTypeM4B, FileTypeMOBI, FileTypePDF}
BuiltInFileTypes are the file types Shisho parses itself. Each is eligible to be a main file.
var ConversionSteps = conversionGraph{ {From: FileTypeEPUB, To: FileTypeKePub}, {From: FileTypeCBZ, To: FileTypeKePub}, {From: FileTypeCBZ, To: FileTypeEPUB}, {From: FileTypeKePub, To: FileTypeEPUB}, {From: FileTypeAZW3, To: FileTypeEPUB}, {From: FileTypeMOBI, To: FileTypeEPUB}, {From: FileTypeEPUB, To: FileTypeAZW3}, }
ConversionSteps are the Conversions Shisho can run. Chains of them are found automatically, so a new step makes every File Type that reaches its From reach its To too. The order breaks ties between chains of the same length and orders ReachableFileTypes.
var EbookFileTypes = []string{FileTypeEPUB, FileTypeKePub, FileTypeAZW3, FileTypeMOBI, FileTypeCBZ, FileTypePDF}
EbookFileTypes are the file types in the ebook cover category, as opposed to M4B audiobooks. Preferred Cover is exclusive within a category.
var PlaybackSpeeds = []float64{0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3}
PlaybackSpeeds lists the allowed audiobook playback speed steps, in ascending order.
Functions ¶
func BuiltInFileExtensions ¶ added in v0.2.0
func BuiltInFileExtensions() []string
BuiltInFileExtensions returns every extension (lowercase, no dot) of a built-in file type, sorted.
func DeliveredFileTypeExtension ¶ added in v0.5.0
DeliveredFileTypeExtension returns the extension (no leading dot) of a File delivered as fileType: "kepub.epub" for a KePub, which Kobo and KOReader recognize by it, and the File Type itself for every built-in File Type.
func DeliveredFileTypeForExtension ¶ added in v0.5.0
DeliveredFileTypeForExtension is the inverse of DeliveredFileTypeExtension. It returns false for an extension no delivered File Type has.
func EbookCoverRank ¶ added in v0.2.0
EbookCoverRank orders ebook files when no file is the Preferred Cover: EPUB, then KePub, then AZW3, then MOBI, then the other ebook formats, which share a rank so a stable sort keeps their order. app/utils/fileTypes.ts mirrors it.
func FileExtensionForPath ¶ added in v0.5.0
FileExtensionForPath returns a path's extension with its leading dot, as filepath.Ext does, except that a KePub's is the whole .kepub.epub. Code that renames a file keeps this, so a KePub stays one.
func FileTypeForPath ¶ added in v0.2.0
FileTypeForPath returns the file type for a path: KePub for a .kepub.epub, the built-in type its extension maps to (KePub for a bare .kepub too), or else the lowercase extension without the dot, which is how plugin-parsed files and supplements are typed.
func FileTypeLabel ¶ added in v0.5.0
FileTypeLabel is how a File Type is written for a reader: KePub, or the File Type in capitals.
func FileTypeMimeType ¶ added in v0.1.0
FileTypeMimeType returns the media type a file of this type is served as, or "" for a type Shisho does not know (a supplement's extension or a format only a plugin parses), which is typed by its extension instead. Downloads use it rather than the host's mime table, which in the Alpine image has no entry for .epub, .cbz, or .m4b.
func GetDataSourcePriority ¶
GetDataSourcePriority returns the priority for a given data source string. Handles "plugin:scope/id" format by matching the prefix.
func IsAudiobookFileType ¶ added in v0.5.0
IsAudiobookFileType reports whether a file type is an audiobook (M4B), the category opposite the ebook File Types.
func IsBuiltInFileExtension ¶ added in v0.2.0
IsBuiltInFileExtension reports whether an extension (lowercase, no dot) belongs to a built-in file type. Plugin file parsers cannot claim these.
func IsBuiltInFileType ¶ added in v0.2.0
IsBuiltInFileType reports whether Shisho parses this file type itself. These are also the File Types a File can be delivered as, which is why the generated DeliveredFileType is FileType.
func IsEbookFileType ¶ added in v0.2.0
IsEbookFileType reports whether a file type is in the ebook cover category.
func IsPageBasedFileType ¶ added in v0.0.24
IsPageBasedFileType returns true for file types that derive covers from page content (CBZ, PDF). These formats should never have their covers replaced by external sources (plugins, uploads).
func PluginDataSource ¶
PluginDataSource returns a data source string for a specific plugin (e.g., "plugin:shisho/goodreads").
func ReachableFileTypes ¶ added in v0.5.0
ReachableFileTypes returns the File Types a File of type from can be delivered as: from itself first, then every type a Conversion reaches.
func ResolveBookFileDisplayNames ¶ added in v0.1.0
func ResolveBookFileDisplayNames(books ...*Book)
ResolveBookFileDisplayNames sets DisplayName and ReachableFileTypes on every file of each book. Call it wherever books are loaded with their Files relation.
func ResolveFileDisplayNames ¶ added in v0.1.0
func ResolveFileDisplayNames(files []*File)
ResolveFileDisplayNames sets DisplayName and ReachableFileTypes on each file.
Types ¶
type AppSetting ¶ added in v0.0.39
type Author ¶
type Author struct {
bun.BaseModel `bun:"table:authors,alias:a" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
BookID int `bun:",nullzero" json:"book_id"`
PersonID int `bun:",nullzero" json:"person_id"`
Person *Person `bun:"rel:belongs-to,join:person_id=id" json:"person,omitempty" tstype:"Person"`
SortOrder int `bun:",nullzero" json:"sort_order"`
Role *string `json:"role" tstype:"AuthorRole"` // CBZ creator role: writer, penciller, inker, etc. NULL for generic author
}
type Book ¶
type Book struct {
bun.BaseModel `bun:"table:books,alias:b" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
Library *Library `bun:"rel:belongs-to" json:"library" tstype:"Library"`
Filepath string `bun:",nullzero" json:"filepath"`
Title string `bun:",nullzero" json:"title"`
TitleSource string `bun:",nullzero" json:"title_source" tstype:"DataSource"`
SortTitle string `bun:",notnull" json:"sort_title"`
SortTitleSource string `bun:",notnull" json:"sort_title_source" tstype:"DataSource"`
Subtitle *string `json:"subtitle"`
SubtitleSource *string `json:"subtitle_source" tstype:"DataSource"`
Description *string `json:"description"`
DescriptionSource *string `json:"description_source" tstype:"DataSource"`
Authors []*Author `bun:"rel:has-many,join:id=book_id" json:"authors,omitempty" tstype:"Author[]"`
AuthorSource string `bun:",nullzero" json:"author_source" tstype:"DataSource"`
BookSeries []*BookSeries `bun:"rel:has-many,join:id=book_id" json:"book_series,omitempty" tstype:"BookSeries[]"`
// SeriesSource is aggregate provenance for the ordered membership
// collection and its Series Number groups. It never describes a Series
// resource's name; see Series.NameSource for that.
SeriesSource *string `json:"series_source" tstype:"DataSource"`
BookGenres []*BookGenre `bun:"rel:has-many,join:id=book_id" json:"book_genres,omitempty" tstype:"BookGenre[]"`
GenreSource *string `json:"genre_source" tstype:"DataSource"`
BookTags []*BookTag `bun:"rel:has-many,join:id=book_id" json:"book_tags,omitempty" tstype:"BookTag[]"`
TagSource *string `json:"tag_source" tstype:"DataSource"`
Files []*File `bun:"rel:has-many" json:"files" tstype:"File[]"`
CoverCacheKey string `bun:"-" json:"cover_cache_key"`
}
type BookGenre ¶
type BookGenre struct {
bun.BaseModel `bun:"table:book_genres,alias:bg" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
BookID int `bun:",nullzero" json:"book_id"`
GenreID int `bun:",nullzero" json:"genre_id"`
Genre *Genre `bun:"rel:belongs-to,join:genre_id=id" json:"genre,omitempty" tstype:"Genre"`
}
type BookSeries ¶
type BookSeries struct {
bun.BaseModel `bun:"table:book_series,alias:bs" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
BookID int `bun:",nullzero" json:"book_id"`
SeriesID int `bun:",nullzero" json:"series_id"`
Series *Series `bun:"rel:belongs-to,join:series_id=id" json:"series,omitempty" tstype:"Series"`
SeriesNumber *float64 `json:"series_number,omitempty"`
SeriesNumberEnd *float64 `json:"series_number_end,omitempty"`
SeriesNumberUnit *string `json:"series_number_unit,omitempty" tstype:"SeriesNumberUnit"`
SortOrder int `bun:",nullzero" json:"sort_order"`
}
type Chapter ¶
type Chapter struct {
bun.BaseModel `bun:"table:chapters,alias:ch" tstype:"-"`
ID int `bun:",pk,autoincrement" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
FileID int `bun:",notnull" json:"file_id"`
ParentID *int `json:"parent_id"`
SortOrder int `bun:",notnull" json:"sort_order"`
Title string `bun:",notnull" json:"title"`
// Position data (mutually exclusive based on file type)
StartPage *int `json:"start_page"` // CBZ/PDF: 0-indexed page number
StartTimestampMs *int64 `json:"start_timestamp_ms"` // M4B: milliseconds from start
Href *string `json:"href"` // EPUB: content document href; MOBI/AZW3: location, shown only
// Relations
File *File `bun:"rel:belongs-to,join:file_id=id" json:"-"`
Parent *Chapter `bun:"rel:belongs-to,join:parent_id=id" json:"-"`
Children []*Chapter `bun:"rel:has-many,join:id=parent_id" json:"children,omitempty"`
}
func ChapterTree ¶ added in v0.2.0
ChapterTree returns the chapters as a tree of top-level chapters. A File loaded by RetrieveFileWithRelations lists every chapter in Chapters, nested ones included, with only copies of their direct children attached, so a list holding a chapter's parent is rebuilt from ParentID. A list of top-level chapters with their children attached is returned as it is.
type ConversionStep ¶ added in v0.5.0
ConversionStep is one Conversion: delivering a File of type From as type To. pkg/filegen holds the code that runs each step, and a test there checks that every step listed here has it.
func ConversionChain ¶ added in v0.5.0
func ConversionChain(from, to string) ([]ConversionStep, bool)
ConversionChain returns the steps that deliver a File of type from as type to, and false when no chain of Conversions reaches it.
type File ¶
type File struct {
bun.BaseModel `bun:"table:files,alias:f" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
BookID int `bun:",nullzero" json:"book_id"`
Book *Book `bun:"rel:belongs-to" json:"book" tstype:"Book"`
Filepath string `bun:",nullzero" json:"filepath"`
FileType string `bun:",nullzero" json:"file_type" tstype:"FileType"`
FileRole string `bun:",nullzero,default:'main'" json:"file_role" tstype:"FileRole"`
FilesizeBytes int64 `json:"filesize_bytes"`
FileModifiedAt *time.Time `json:"file_modified_at"`
ScanError *string `json:"scan_error"` // Why the last scan could not parse the file; nil when it parsed fine
CoverImageFilename *string `json:"cover_image_filename"`
CoverMimeType *string `json:"cover_mime_type"`
CoverSource *string `json:"cover_source" tstype:"DataSource"`
CoverPage *int `json:"cover_page"` // 0-indexed page number for CBZ/PDF cover, NULL for EPUB/M4B
Name *string `json:"name"`
NameSource *string `json:"name_source" tstype:"DataSource"`
PageCount *int `json:"page_count"` // Number of pages for CBZ/PDF files, NULL for EPUB/M4B
AudiobookDurationSeconds *float64 `json:"audiobook_duration_seconds"`
AudiobookBitrateBps *int `json:"audiobook_bitrate_bps"`
AudiobookCodec *string `json:"audiobook_codec"`
Narrators []*Narrator `bun:"rel:has-many,join:id=file_id" json:"narrators,omitempty" tstype:"Narrator[]"`
NarratorSource *string `json:"narrator_source" tstype:"DataSource"`
Identifiers []*FileIdentifier `bun:"rel:has-many,join:id=file_id" json:"identifiers,omitempty" tstype:"FileIdentifier[]"`
IdentifierSource *string `json:"identifier_source" tstype:"DataSource"`
Chapters []*Chapter `bun:"rel:has-many,join:id=file_id" json:"chapters,omitempty" tstype:"Chapter[]"`
URL *string `json:"url"`
URLSource *string `json:"url_source" tstype:"DataSource"`
ReleaseDate *time.Time `json:"release_date"`
ReleaseDateSource *string `json:"release_date_source" tstype:"DataSource"`
PublisherID *int `json:"publisher_id"`
PublisherSource *string `json:"publisher_source" tstype:"DataSource"`
Publisher *Publisher `bun:"rel:belongs-to,join:publisher_id=id" json:"publisher,omitempty" tstype:"Publisher"`
ChapterSource *string `json:"chapter_source" tstype:"DataSource"`
Language *string `json:"language"`
LanguageSource *string `json:"language_source" tstype:"DataSource"`
Abridged *bool `json:"abridged"`
AbridgedSource *string `json:"abridged_source" tstype:"DataSource"`
ReviewOverride *string `json:"review_override" tstype:"ReviewOverride"`
ReviewOverriddenAt *time.Time `json:"review_overridden_at"`
Reviewed *bool `json:"reviewed"`
IsPreferredCover bool `bun:",default:false" json:"is_preferred_cover"`
// DisplayName is the label the UI shows for the file. It is not stored:
// AfterScanRow fills it for files loaded directly, and the book loaders
// call ResolveBookFileDisplayNames for Book.Files, which Bun loads as a
// has-many relation without row hooks.
DisplayName string `bun:"-" json:"display_name"`
// ReachableFileTypes are the File Types the file can be downloaded as:
// its own first, then every one reachable through Conversion. A
// supplement downloads only as itself. Like DisplayName it is not
// stored, and is resolved alongside it.
ReachableFileTypes []string `bun:"-" json:"reachable_file_types" tstype:"DeliveredFileType[]"`
}
func (*File) AfterScanRow ¶ added in v0.1.0
AfterScanRow is a Bun hook that resolves DisplayName and ReachableFileTypes for files loaded by a direct query (a single file, or a slice of files). It does not run for Book.Files: Bun scans has-many relations without row hooks.
func (*File) CoverExtension ¶
func (*File) HasName ¶ added in v0.4.0
HasName reports whether the file has a name. A whitespace-only name does not count. Check it rather than comparing Name with "".
func (*File) ResolveDisplayName ¶ added in v0.1.0
ResolveDisplayName returns the label for the file. A main file shows its name (the edition title), falling back to the filename. A supplement shows its filename unless the user set a name (source manual): the scanner stores the filename stem as the name when it first sees a supplement, and that stored value goes stale when the book is renamed or reorganized. A sidecar source does not count, because book edits write every file's sidecar with its stored name, so a rescan can restore the stale stem as sidecar. As in ResolveTitle, a whitespace-only name does not count as set.
func (*File) ResolveTitle ¶ added in v0.4.0
ResolveTitle returns the title a reader sees for this file: its name when set, otherwise the book's title, even when the book has only one file. Unlike ResolveDisplayName it never falls back to the filename. A whitespace-only name does not count as set. A nil file gives the book's title.
type FileFingerprint ¶ added in v0.0.29
type FileFingerprint struct {
bun.BaseModel `bun:"table:file_fingerprints,alias:ffp" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
FileID int `bun:",nullzero" json:"file_id"`
Algorithm string `bun:",nullzero" json:"algorithm"`
Value string `bun:",nullzero" json:"value"`
File *File `bun:"rel:belongs-to" json:"-"`
}
FileFingerprint is a content fingerprint for a file. A single file may have multiple fingerprints, one per algorithm (e.g. sha256 for exact matching, phash for cover similarity, simhash for text similarity).
type FileIdentifier ¶
type FileIdentifier struct {
bun.BaseModel `bun:"table:file_identifiers,alias:fi" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
FileID int `bun:",nullzero" json:"file_id"`
Type string `bun:",nullzero" json:"type" tstype:"IdentifierType"`
Value string `bun:",nullzero" json:"value"`
Source string `bun:",nullzero" json:"source" tstype:"DataSource"`
}
type Genre ¶
type Genre struct {
bun.BaseModel `bun:"table:genres,alias:g" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
Name string `bun:",nullzero" json:"name"`
Aliases []*GenreAlias `bun:"rel:has-many,join:id=genre_id" json:"aliases" tstype:"-"`
BookCount int `bun:",scanonly" json:"book_count"`
}
type GenreAlias ¶ added in v0.0.43
type GenreAlias struct {
bun.BaseModel `bun:"table:genre_aliases,alias:ga" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
GenreID int `bun:",nullzero" json:"genre_id"`
Name string `bun:",nullzero" json:"name"`
LibraryID int `bun:",nullzero" json:"library_id"`
}
type Job ¶
type Job struct {
bun.BaseModel `bun:"table:jobs,alias:j" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Type string `bun:",nullzero" json:"type" tstype:"JobType"`
Status string `bun:",nullzero" json:"status" tstype:"JobStatus"`
Data string `bun:",nullzero" json:"-"`
DataParsed interface{} `` /* 127-byte string literal not displayed */
Progress int `json:"progress"`
ProcessID *string `json:"process_id,omitempty"`
LibraryID *int `json:"library_id,omitempty"`
// CreatedByUserID is the user who requested the job through POST /api/jobs.
// It is nil for jobs enqueued any other way, such as by library saves,
// review settings, the scheduler, or the worker.
CreatedByUserID *int `json:"created_by_user_id,omitempty"`
}
func (*Job) UnmarshalData ¶
type JobBulkDownloadData ¶ added in v0.0.21
type JobBulkDownloadData struct {
// Input (set on creation)
FileIDs []int `json:"file_ids"`
EstimatedSizeBytes int64 `json:"estimated_size_bytes"`
// Result (set on completion)
ZipFilename string `json:"zip_filename,omitempty"`
SizeBytes int64 `json:"size_bytes,omitempty"`
FileCount int `json:"file_count,omitempty"`
FingerprintHash string `json:"fingerprint_hash,omitempty"`
}
type JobExportData ¶
type JobExportData struct{}
type JobHashGenerationData ¶ added in v0.0.29
type JobHashGenerationData struct {
LibraryID int `json:"library_id"`
}
JobHashGenerationData is the payload for a hash generation job. The job processes all files in the given library that do not yet have a sha256 fingerprint in file_fingerprints.
type JobLog ¶
type JobLog struct {
bun.BaseModel `bun:"table:job_logs,alias:jl" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
JobID int `bun:",nullzero" json:"job_id"`
Level string `bun:",nullzero" json:"level" tstype:"LogLevel"`
Message string `bun:",nullzero" json:"message"`
Plugin *string `json:"plugin,omitempty"`
Data *string `json:"data,omitempty"`
StackTrace *string `json:"stack_trace,omitempty"`
}
type JobRecomputeReviewData ¶ added in v0.0.39
type JobRecomputeReviewData struct {
// ClearOverrides, when true, sets review_override and review_overridden_at to NULL
// for every main file before recomputing reviewed.
ClearOverrides bool `json:"clear_overrides"`
}
type JobScanData ¶
type JobScanData struct{}
type Library ¶
type Library struct {
bun.BaseModel `bun:"table:libraries,alias:l" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `bun:",nullzero" json:"name"`
OrganizeFileStructure bool `json:"organize_file_structure"`
CoverAspectRatio string `bun:",nullzero" json:"cover_aspect_ratio" tstype:"CoverAspectRatio"`
// TagNamespaces are the tag name prefixes the library groups tags by, in
// the order the book page lists them. A tag named "Circle: Foo" or
// "Circle:Foo" is the tag "Foo" in the "Circle" namespace; the matching
// rule is in pkg/tags/namespaces.go.
TagNamespaces StringList `json:"tag_namespaces"`
LibraryPaths []*LibraryPath `bun:"rel:has-many" json:"library_paths,omitempty" tstype:"LibraryPath[]"`
}
type LibraryPath ¶
type LibraryPath struct {
bun.BaseModel `bun:"table:library_paths,alias:lp" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
Filepath string `bun:",nullzero" json:"filepath"`
}
type LibraryPluginFieldSetting ¶ added in v0.0.10
type LibraryPluginFieldSetting struct {
bun.BaseModel `bun:"table:library_plugin_field_settings,alias:lpfs" tstype:"-"`
LibraryID int `bun:",pk" json:"library_id"`
Scope string `bun:",pk" json:"scope"`
PluginID string `bun:",pk" json:"plugin_id"`
Field string `bun:",pk" json:"field"`
Enabled bool `bun:",notnull" json:"enabled"`
}
LibraryPluginFieldSetting stores per-library field overrides. Only rows with explicit overrides are stored; absence means use global default.
type LibraryPluginHookConfig ¶ added in v0.0.26
type LibraryPluginHookConfig struct {
bun.BaseModel `bun:"table:library_plugin_hook_configs,alias:lphc" tstype:"-"`
LibraryID int `bun:",pk" json:"library_id"`
HookType string `bun:",pk" json:"hook_type" tstype:"PluginHookType"`
Scope string `bun:",pk" json:"scope"`
PluginID string `bun:",pk" json:"plugin_id"`
Position int `bun:",notnull" json:"position"`
Mode string `bun:",notnull,default:'enabled'" json:"mode" tstype:"PluginMode"`
}
type List ¶
type List struct {
bun.BaseModel `bun:"table:lists,alias:l" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
UserID int `bun:",nullzero" json:"user_id"`
User *UserRef `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty" tstype:"UserRef"`
Name string `bun:",nullzero" json:"name"`
Description *string `json:"description"`
IsOrdered bool `json:"is_ordered"`
DefaultSort string `bun:",nullzero" json:"default_sort" tstype:"ListSort"`
// Relations
ListBooks []*ListBook `bun:"rel:has-many,join:id=list_id" json:"list_books,omitempty" tstype:"ListBook[]"`
}
type ListBook ¶
type ListBook struct {
bun.BaseModel `bun:"table:list_books,alias:lb" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
ListID int `bun:",nullzero" json:"list_id"`
List *List `bun:"rel:belongs-to,join:list_id=id" json:"list,omitempty" tstype:"List"`
BookID int `bun:",nullzero" json:"book_id"`
Book *Book `bun:"rel:belongs-to,join:book_id=id" json:"book,omitempty" tstype:"Book"`
AddedAt time.Time `json:"added_at"`
AddedByUserID *int `json:"added_by_user_id"`
AddedByUser *UserRef `bun:"rel:belongs-to,join:added_by_user_id=id" json:"added_by_user,omitempty" tstype:"UserRef"`
SortOrder *int `json:"sort_order"`
}
type Narrator ¶
type Narrator struct {
bun.BaseModel `bun:"table:narrators,alias:n" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
FileID int `bun:",nullzero" json:"file_id"`
PersonID int `bun:",nullzero" json:"person_id"`
Person *Person `bun:"rel:belongs-to,join:person_id=id" json:"person,omitempty" tstype:"Person"`
SortOrder int `bun:",nullzero" json:"sort_order"`
}
type Permission ¶
type Person ¶
type Person struct {
bun.BaseModel `bun:"table:persons,alias:p" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
Name string `bun:",nullzero" json:"name"`
SortName string `bun:",notnull" json:"sort_name"`
SortNameSource string `bun:",notnull" json:"sort_name_source" tstype:"DataSource"`
Aliases []*PersonAlias `bun:"rel:has-many,join:id=person_id" json:"aliases" tstype:"-"`
}
type PersonAlias ¶ added in v0.0.43
type PersonAlias struct {
bun.BaseModel `bun:"table:person_aliases,alias:pa" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
PersonID int `bun:",nullzero" json:"person_id"`
Name string `bun:",nullzero" json:"name"`
LibraryID int `bun:",nullzero" json:"library_id"`
}
type Plugin ¶
type Plugin struct {
bun.BaseModel `bun:"table:plugins,alias:p" tstype:"-"`
Scope string `bun:",pk" json:"scope"`
ID string `bun:",pk" json:"id"`
Name string `bun:",notnull" json:"name"`
Version string `bun:",notnull" json:"version"`
Description *string `json:"description"`
Homepage *string `json:"homepage"`
Status PluginStatus `bun:",notnull,default:0" json:"status"`
AutoUpdate bool `bun:",notnull,default:true" json:"auto_update"`
RepositoryScope *string `json:"repository_scope"`
RepositoryURL *string `json:"repository_url"`
InstalledAt time.Time `bun:",notnull" json:"installed_at"`
UpdatedAt *time.Time `json:"updated_at"`
LoadError *string `json:"load_error"`
UpdateAvailableVersion *string `json:"update_available_version"`
ConfidenceThreshold *float64 `json:"confidence_threshold"`
}
type PluginConfig ¶
type PluginFieldSetting ¶ added in v0.0.10
type PluginFieldSetting struct {
bun.BaseModel `bun:"table:plugin_field_settings,alias:pfs" tstype:"-"`
Scope string `bun:",pk" json:"scope"`
PluginID string `bun:",pk" json:"plugin_id"`
Field string `bun:",pk" json:"field"`
Enabled bool `bun:",notnull" json:"enabled"`
}
PluginFieldSetting stores global field enable/disable settings for a plugin. Absence of a row means the field is enabled (default).
type PluginHookConfig ¶ added in v0.0.26
type PluginHookConfig struct {
bun.BaseModel `bun:"table:plugin_hook_configs,alias:phc" tstype:"-"`
HookType string `bun:",pk" json:"hook_type" tstype:"PluginHookType"`
Scope string `bun:",pk" json:"scope"`
PluginID string `bun:",pk" json:"plugin_id"`
Position int `bun:",notnull" json:"position"`
Mode string `bun:",notnull,default:'enabled'" json:"mode" tstype:"PluginMode"`
}
type PluginIdentifierType ¶
type PluginIdentifierType struct {
bun.BaseModel `bun:"table:plugin_identifier_types,alias:pit" tstype:"-"`
ID string `bun:",pk" json:"id"`
Scope string `bun:",pk" json:"scope"`
PluginID string `bun:",pk" json:"plugin_id"`
Name string `bun:",notnull" json:"name"`
URLTemplate *string `json:"url_template"`
Pattern *string `json:"pattern"`
}
type PluginRepository ¶
type PluginRepository struct {
bun.BaseModel `bun:"table:plugin_repositories,alias:pr" tstype:"-"`
URL string `bun:",pk" json:"url"`
Scope string `bun:",notnull,unique" json:"scope"`
Name *string `json:"name"`
IsOfficial bool `bun:",notnull" json:"is_official"`
Enabled bool `bun:",notnull" json:"enabled"`
LastFetchedAt *time.Time `json:"last_fetched_at"`
FetchError *string `json:"fetch_error"`
}
type PluginStatus ¶ added in v0.0.18
type PluginStatus int
PluginStatus represents the lifecycle state of a plugin.
const ( // PluginStatusActive means the plugin is running normally. PluginStatusActive PluginStatus = 0 // PluginStatusDisabled means the user has disabled the plugin. PluginStatusDisabled PluginStatus = -1 // PluginStatusMalfunctioned means the plugin failed to load (LoadError has details). PluginStatusMalfunctioned PluginStatus = -2 // PluginStatusNotSupported means the plugin's minShishoVersion is incompatible. PluginStatusNotSupported PluginStatus = -3 )
type Publisher ¶
type Publisher struct {
bun.BaseModel `bun:"table:publishers,alias:pub" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
Name string `bun:",nullzero" json:"name"`
ParentID *int `json:"parent_id"`
Parent *Publisher `bun:"rel:belongs-to,join:parent_id=id" json:"parent,omitempty" tstype:"Publisher"`
// Children and Aliases are reshaped by the publishers API responses
// (Children flattens to ChildResponse, Aliases to []string), so they are
// excluded from TS generation with tstype:"-". The json tags stay so the Go
// wire format is unchanged. See pkg/publishers/types.go and ADR 0004.
Children []*Publisher `bun:"rel:has-many,join:id=parent_id" json:"children,omitempty" tstype:"-"`
Aliases []*PublisherAlias `bun:"rel:has-many,join:id=publisher_id" json:"aliases" tstype:"-"`
FileCount int `bun:",scanonly" json:"file_count"`
}
type PublisherAlias ¶ added in v0.0.43
type PublisherAlias struct {
bun.BaseModel `bun:"table:publisher_aliases,alias:puba" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
PublisherID int `bun:",nullzero" json:"publisher_id"`
Name string `bun:",nullzero" json:"name"`
LibraryID int `bun:",nullzero" json:"library_id"`
}
type Role ¶
type Role struct {
bun.BaseModel `bun:"table:roles,alias:r" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `bun:",nullzero" json:"name"`
IsSystem bool `json:"is_system"`
Permissions []*Permission `bun:"rel:has-many,join:id=role_id" json:"permissions,omitempty" tstype:"Permission[]"`
}
func (*Role) HasPermission ¶
HasPermission checks if the role has a specific permission.
type Series ¶
type Series struct {
bun.BaseModel `bun:"table:series,alias:s" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
Library *Library `bun:"rel:belongs-to" json:"library,omitempty" tstype:"Library"`
Name string `bun:",nullzero" json:"name"`
NameSource string `bun:",nullzero" json:"name_source" tstype:"DataSource"`
SortName string `bun:",notnull" json:"sort_name"`
SortNameSource string `bun:",notnull" json:"sort_name_source" tstype:"DataSource"`
Description *string `json:"description,omitempty"`
CoverImageFilename *string `json:"cover_image_filename,omitempty"`
Aliases []*SeriesAlias `bun:"rel:has-many,join:id=series_id" json:"aliases" tstype:"-"`
BookSeries []*BookSeries `bun:"rel:has-many" json:"book_series,omitempty" tstype:"BookSeries[]"`
BookCount int `bun:",scanonly" json:"book_count"`
CoverCacheKey string `bun:"-" json:"cover_cache_key"`
}
type SeriesAlias ¶ added in v0.0.43
type SeriesAlias struct {
bun.BaseModel `bun:"table:series_aliases,alias:sa" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
SeriesID int `bun:",nullzero" json:"series_id"`
Name string `bun:",nullzero" json:"name"`
LibraryID int `bun:",nullzero" json:"library_id"`
}
type ShareLink ¶ added in v0.1.0
type ShareLink struct {
}
ShareLink is an anonymous, optionally expiring link that grants access to one Book. See "Share Link" in CONTEXT.md.
func (*ShareLink) PausedReason ¶ added in v0.1.0
PausedReason reports why the link's creator stops it from resolving for a book in libraryID, or "" when the creator can still share it. It needs CreatedByUser loaded with its LibraryAccess; a missing creator counts as deactivated so a caller that forgot to load it fails closed.
type StringList ¶ added in v0.5.0
type StringList []string
StringList is a list of strings stored in one TEXT column as a JSON array. A nil list is stored as an empty one and always scans back non-nil, so it serializes to [] rather than null.
func (*StringList) Scan ¶ added in v0.5.0
func (l *StringList) Scan(src any) error
type Tag ¶
type Tag struct {
bun.BaseModel `bun:"table:tags,alias:t" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LibraryID int `bun:",nullzero" json:"library_id"`
Name string `bun:",nullzero" json:"name"`
Aliases []*TagAlias `bun:"rel:has-many,join:id=tag_id" json:"aliases" tstype:"-"`
BookCount int `bun:",scanonly" json:"book_count"`
}
type User ¶
type User struct {
bun.BaseModel `bun:"table:users,alias:u" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Username string `bun:",nullzero" json:"username"`
Email *string `json:"email,omitempty"`
PasswordHash string `json:"-"` // Never expose password hash
RoleID int `json:"role_id"`
IsActive bool `json:"is_active"`
MustChangePassword bool `json:"must_change_password"`
// Relations
Role *Role `bun:"rel:belongs-to,join:role_id=id" json:"role,omitempty" tstype:"Role"`
LibraryAccess []*UserLibraryAccess `bun:"rel:has-many,join:id=user_id" json:"library_access,omitempty" tstype:"UserLibraryAccess[]"`
}
func (*User) GetAccessibleLibraryIDs ¶
GetAccessibleLibraryIDs returns the list of library IDs the user can access. Returns nil if user has access to all libraries.
func (*User) HasAllLibraryAccess ¶
HasAllLibraryAccess checks if the user has access to all libraries.
func (*User) HasLibraryAccess ¶
HasLibraryAccess checks if the user can access a specific library. Returns true if user has access to all libraries (null library_id entry) or has explicit access to the specified library.
func (*User) HasPermission ¶
HasPermission checks if the user has a specific permission.
type UserLibraryAccess ¶
type UserLibrarySettings ¶ added in v0.0.32
type UserLibrarySettings struct {
bun.BaseModel `bun:"table:user_library_settings,alias:uls" tstype:"-"`
ID int `bun:",pk,autoincrement"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp"`
UserID int `bun:",notnull"`
LibraryID int `bun:",notnull"`
SortSpec *string `bun:",nullzero"`
}
UserLibrarySettings is intentionally not exposed over JSON or generated as a TS type (`tstype:"-"`). Handlers transform it into LibrarySettingsResponse (in pkg/settings) so the wire shape can evolve independently of the storage row, and tygo skips it. The struct therefore carries no `json:"..."` tags.
type UserRef ¶ added in v0.1.0
type UserRef struct {
bun.BaseModel `bun:"table:users,alias:u" tstype:"-"`
ID int `bun:",pk,nullzero" json:"id"`
Username string `json:"username"`
}
UserRef is a read-only view of a user carrying only the id and username. Payloads that any signed-in user can read, such as a list's owner, its shares, and who added each book, embed it instead of User so they never carry an email address, role, or account state.
type UserSettings ¶
type UserSettings struct {
bun.BaseModel `bun:"table:user_settings,alias:us" tstype:"-"`
ID int `bun:",pk,autoincrement" json:"id"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"updated_at"`
UserID int `bun:",notnull,unique" json:"user_id"`
ViewerPreloadCount int `bun:",notnull,default:3" json:"viewer_preload_count"`
ViewerFitMode string `bun:",notnull,default:'fit-height'" json:"viewer_fit_mode" tstype:"FitMode"`
ReflowableFontSize int `bun:"viewer_reflowable_font_size,notnull,default:100" json:"viewer_reflowable_font_size"`
ReflowableTheme string `bun:"viewer_reflowable_theme,notnull,default:'light'" json:"viewer_reflowable_theme" tstype:"ReflowableTheme"`
ReflowableFlow string `bun:"viewer_reflowable_flow,notnull,default:'paginated'" json:"viewer_reflowable_flow" tstype:"ReflowableFlow"`
GallerySize string `bun:",notnull,default:'m'" json:"gallery_size" tstype:"GallerySize"`
ViewerHideChrome bool `bun:",notnull,default:false" json:"viewer_hide_chrome"`
PlaybackSpeed float64 `bun:"viewer_playback_speed,notnull,default:1.0" json:"viewer_playback_speed" tstype:"PlaybackSpeed"`
// DefaultLibraryID is the library `/` opens. Nil opens the first library
// the user can access.
DefaultLibraryID *int `json:"default_library_id" tstype:"number | null"`
}
func DefaultUserSettings ¶
func DefaultUserSettings() *UserSettings
DefaultUserSettings returns a UserSettings with default values.
Source Files
¶
- alias.go
- app-setting.go
- book.go
- chapter.go
- conversion.go
- data-source.go
- file-fingerprint.go
- file-identifier.go
- file.go
- genre.go
- job.go
- job_log.go
- library-path.go
- library.go
- list.go
- log_level.go
- person.go
- plugin.go
- publisher.go
- role.go
- series.go
- share_link.go
- string_list.go
- tag.go
- user.go
- user_library_settings.go
- user_settings.go