collections gains filter_tree JSONB (idempotent in-place; same qf DSL as saved filters — the scope key included). IsCollectionSmart is the ONE detection (tree OR legacy rules), and EvaluateSmartMembership is the ONE evaluator: tree-bearing collections run the composed engine via ComposedLiveMedia (full media rows, so the collection surfaces keep their episode-card stamping, feed positions for the replay chain, and the family lens rides the mandatory head), while legacy rule arrays keep per-item FieldMatches until rewritten — one call surface, two storage epochs. All smart surfaces (detail JSON, counts, detail page, reader chain) dispatch through it; the search service is injected into the collection subsystem (variadic — main.go builds one shared instance; the test harness mirrors it). Write path: CreateCollection/UpdateCollection accept the tree, validated against the engine grammar at the HANDLER (an invalid tree is a 400, never a stored render-time 500) and exposed in the envelope (pin widened in TestContractPin_CollectionsJSON + changelog). Update semantics: an edit form that doesn't send a tree keeps the stored one. RulesToFilterTree converts legacy rules + match mode at upgrade time: episode rules map mechanically (feed→in-list, played/downloaded→ booleans, published_within→published_date+within_days), tree root mode absorbs rule_match_mode, episode rules force the episodes scope, and legacy starts_with/ends_with fall back to contains (documented). Read-compat by design: nothing is migrated at boot — legacy arrays evaluate exactly as before until the collection is rewritten. Pinned by TestRulesToFilterTree (unit conversion) + TestEpisodeCollectionsFilterTree (a tree collection evaluates through the engine, the chain follows the tree's live membership, invalid trees 400 at write, the tree wins when legacy rules coexist, and an edit without a tree keeps it).
660 lines
39 KiB
Go
660 lines
39 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.0
|
|
|
|
package database
|
|
|
|
import (
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
type AudioPlaybackSpeed struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
Speed float32 `db:"speed" json:"speed"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type CollectionItems struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
CollectionID pgtype.UUID `db:"collection_id" json:"collection_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
AddedAt pgtype.Timestamptz `db:"added_at" json:"added_at"`
|
|
AddedByUserID pgtype.UUID `db:"added_by_user_id" json:"added_by_user_id"`
|
|
Excluded pgtype.Bool `db:"excluded" json:"excluded"`
|
|
Position pgtype.Int4 `db:"position" json:"position"`
|
|
}
|
|
|
|
type Collections struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Name string `db:"name" json:"name"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
Color pgtype.Text `db:"color" json:"color"`
|
|
Icon pgtype.Text `db:"icon" json:"icon"`
|
|
AutoAssignRules []byte `db:"auto_assign_rules" json:"auto_assign_rules"`
|
|
RuleMatchMode string `db:"rule_match_mode" json:"rule_match_mode"`
|
|
FilterTree []byte `db:"filter_tree" json:"filter_tree"`
|
|
ViewSettings []byte `db:"view_settings" json:"view_settings"`
|
|
ShowOnDashboard pgtype.Bool `db:"show_on_dashboard" json:"show_on_dashboard"`
|
|
QueryType pgtype.Text `db:"query_type" json:"query_type"`
|
|
Priority pgtype.Int4 `db:"priority" json:"priority"`
|
|
IsSystemCollection pgtype.Bool `db:"is_system_collection" json:"is_system_collection"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
DeletedAt pgtype.Timestamptz `db:"deleted_at" json:"deleted_at"`
|
|
}
|
|
|
|
type DeviceCatalogs struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
BookhoardUuid pgtype.UUID `db:"bookhoard_uuid" json:"bookhoard_uuid"`
|
|
KoboContentID string `db:"kobo_content_id" json:"kobo_content_id"`
|
|
ContentIDType pgtype.Text `db:"content_id_type" json:"content_id_type"`
|
|
Available pgtype.Bool `db:"available" json:"available"`
|
|
DeliveryDate pgtype.Timestamptz `db:"delivery_date" json:"delivery_date"`
|
|
DeliveryMethod pgtype.Text `db:"delivery_method" json:"delivery_method"`
|
|
}
|
|
|
|
type DeviceFileAliases struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
FilePath string `db:"file_path" json:"file_path"`
|
|
FileSha256 pgtype.Text `db:"file_sha256" json:"file_sha256"`
|
|
ConfidenceScore pgtype.Float8 `db:"confidence_score" json:"confidence_score"`
|
|
LastSeenAt pgtype.Timestamptz `db:"last_seen_at" json:"last_seen_at"`
|
|
}
|
|
|
|
type DeviceShelfMappings struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
CollectionID pgtype.UUID `db:"collection_id" json:"collection_id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
DeviceShelfName pgtype.Text `db:"device_shelf_name" json:"device_shelf_name"`
|
|
SyncDirection pgtype.Text `db:"sync_direction" json:"sync_direction"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
}
|
|
|
|
type Devices struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
DeviceName string `db:"device_name" json:"device_name"`
|
|
DeviceType string `db:"device_type" json:"device_type"`
|
|
DeviceIdentifier string `db:"device_identifier" json:"device_identifier"`
|
|
AuthToken string `db:"auth_token" json:"auth_token"`
|
|
LastSync pgtype.Timestamptz `db:"last_sync" json:"last_sync"`
|
|
LastSeen pgtype.Timestamptz `db:"last_seen" json:"last_seen"`
|
|
SyncEnabled pgtype.Bool `db:"sync_enabled" json:"sync_enabled"`
|
|
AutoSync pgtype.Bool `db:"auto_sync" json:"auto_sync"`
|
|
SyncFrequencyMinutes pgtype.Int4 `db:"sync_frequency_minutes" json:"sync_frequency_minutes"`
|
|
DeviceMetadata []byte `db:"device_metadata" json:"device_metadata"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type DictionaryCache struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Word string `db:"word" json:"word"`
|
|
Definition string `db:"definition" json:"definition"`
|
|
PartOfSpeech pgtype.Text `db:"part_of_speech" json:"part_of_speech"`
|
|
Example pgtype.Text `db:"example" json:"example"`
|
|
Etymology pgtype.Text `db:"etymology" json:"etymology"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
AccessedAt pgtype.Timestamptz `db:"accessed_at" json:"accessed_at"`
|
|
}
|
|
|
|
type HashConflicts struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
FileSha256 string `db:"file_sha256" json:"file_sha256"`
|
|
Status string `db:"status" json:"status"`
|
|
Resolution pgtype.Text `db:"resolution" json:"resolution"`
|
|
ResolvedBy pgtype.UUID `db:"resolved_by" json:"resolved_by"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
ResolvedAt pgtype.Timestamptz `db:"resolved_at" json:"resolved_at"`
|
|
}
|
|
|
|
type KoboEntitlements struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
EntitlementID string `db:"entitlement_id" json:"entitlement_id"`
|
|
ContentID string `db:"content_id" json:"content_id"`
|
|
RevisionNumber pgtype.Int4 `db:"revision_number" json:"revision_number"`
|
|
PurchaseDate pgtype.Timestamptz `db:"purchase_date" json:"purchase_date"`
|
|
AccessionDate pgtype.Timestamptz `db:"accession_date" json:"accession_date"`
|
|
BookStatus pgtype.Text `db:"book_status" json:"book_status"`
|
|
SyncStatus pgtype.Text `db:"sync_status" json:"sync_status"`
|
|
KoboMetadata []byte `db:"kobo_metadata" json:"kobo_metadata"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type KoboShelves struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
ShelfName pgtype.Text `db:"shelf_name" json:"shelf_name"`
|
|
ShelfPosition pgtype.Int4 `db:"shelf_position" json:"shelf_position"`
|
|
AddedAt pgtype.Timestamptz `db:"added_at" json:"added_at"`
|
|
LastSyncedAt pgtype.Timestamptz `db:"last_synced_at" json:"last_synced_at"`
|
|
CollectionID pgtype.UUID `db:"collection_id" json:"collection_id"`
|
|
PositionInCollection pgtype.Int4 `db:"position_in_collection" json:"position_in_collection"`
|
|
}
|
|
|
|
type Libraries struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Name string `db:"name" json:"name"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
LibraryTypeID pgtype.UUID `db:"library_type_id" json:"library_type_id"`
|
|
CreatedByAdminID pgtype.UUID `db:"created_by_admin_id" json:"created_by_admin_id"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
AllowMemberFeeds bool `db:"allow_member_feeds" json:"allow_member_feeds"`
|
|
}
|
|
|
|
type LibraryFolders struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
FolderPath string `db:"folder_path" json:"folder_path"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
Purpose string `db:"purpose" json:"purpose"`
|
|
}
|
|
|
|
type LibraryTypes struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Name string `db:"name" json:"name"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
AllowedExtensions []string `db:"allowed_extensions" json:"allowed_extensions"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
}
|
|
|
|
type LibraryVisibility struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
IsVisible bool `db:"is_visible" json:"is_visible"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type MediaBookmarks struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
PageNumber pgtype.Int4 `db:"page_number" json:"page_number"`
|
|
ChapterNumber pgtype.Int4 `db:"chapter_number" json:"chapter_number"`
|
|
CfiPosition pgtype.Text `db:"cfi_position" json:"cfi_position"`
|
|
Title string `db:"title" json:"title"`
|
|
Position pgtype.Text `db:"position" json:"position"`
|
|
Notes pgtype.Text `db:"notes" json:"notes"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
DedupKey pgtype.Text `db:"dedup_key" json:"dedup_key"`
|
|
LastModifiedAt pgtype.Timestamptz `db:"last_modified_at" json:"last_modified_at"`
|
|
LastModifiedSource pgtype.Text `db:"last_modified_source" json:"last_modified_source"`
|
|
DeviceSyncData []byte `db:"device_sync_data" json:"device_sync_data"`
|
|
PercentageLocation pgtype.Float8 `db:"percentage_location" json:"percentage_location"`
|
|
EpubcfiLocation pgtype.Text `db:"epubcfi_location" json:"epubcfi_location"`
|
|
ChapterReference pgtype.Int4 `db:"chapter_reference" json:"chapter_reference"`
|
|
Deleted pgtype.Bool `db:"deleted" json:"deleted"`
|
|
DeletedAt pgtype.Timestamptz `db:"deleted_at" json:"deleted_at"`
|
|
OriginSource pgtype.Text `db:"origin_source" json:"origin_source"`
|
|
}
|
|
|
|
type MediaHighlights struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
SelectionText string `db:"selection_text" json:"selection_text"`
|
|
StartPosition pgtype.Text `db:"start_position" json:"start_position"`
|
|
EndPosition pgtype.Text `db:"end_position" json:"end_position"`
|
|
Color pgtype.Text `db:"color" json:"color"`
|
|
NoteID pgtype.UUID `db:"note_id" json:"note_id"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
PercentageStart pgtype.Float8 `db:"percentage_start" json:"percentage_start"`
|
|
PercentageEnd pgtype.Float8 `db:"percentage_end" json:"percentage_end"`
|
|
CharacterStart pgtype.Int4 `db:"character_start" json:"character_start"`
|
|
CharacterEnd pgtype.Int4 `db:"character_end" json:"character_end"`
|
|
EpubcfiStart pgtype.Text `db:"epubcfi_start" json:"epubcfi_start"`
|
|
EpubcfiEnd pgtype.Text `db:"epubcfi_end" json:"epubcfi_end"`
|
|
ChapterReference pgtype.Int4 `db:"chapter_reference" json:"chapter_reference"`
|
|
ParagraphStart pgtype.Int4 `db:"paragraph_start" json:"paragraph_start"`
|
|
ParagraphEnd pgtype.Int4 `db:"paragraph_end" json:"paragraph_end"`
|
|
PanelNumber pgtype.Int4 `db:"panel_number" json:"panel_number"`
|
|
DeviceSyncData []byte `db:"device_sync_data" json:"device_sync_data"`
|
|
DedupKey pgtype.Text `db:"dedup_key" json:"dedup_key"`
|
|
LastModifiedAt pgtype.Timestamptz `db:"last_modified_at" json:"last_modified_at"`
|
|
LastModifiedSource pgtype.Text `db:"last_modified_source" json:"last_modified_source"`
|
|
NoteText pgtype.Text `db:"note_text" json:"note_text"`
|
|
Deleted pgtype.Bool `db:"deleted" json:"deleted"`
|
|
DeletedAt pgtype.Timestamptz `db:"deleted_at" json:"deleted_at"`
|
|
}
|
|
|
|
type MediaItemFormats struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
FormatType string `db:"format_type" json:"format_type"`
|
|
FilePath pgtype.Text `db:"file_path" json:"file_path"`
|
|
FileSha256 pgtype.Text `db:"file_sha256" json:"file_sha256"`
|
|
FileSizeBytes pgtype.Int8 `db:"file_size_bytes" json:"file_size_bytes"`
|
|
MimeType pgtype.Text `db:"mime_type" json:"mime_type"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
ConvertedFromFormatID pgtype.UUID `db:"converted_from_format_id" json:"converted_from_format_id"`
|
|
}
|
|
|
|
type MediaItems struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
Title string `db:"title" json:"title"`
|
|
Subtitle pgtype.Text `db:"subtitle" json:"subtitle"`
|
|
Author pgtype.Text `db:"author" json:"author"`
|
|
Isbn pgtype.Text `db:"isbn" json:"isbn"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
FilePath string `db:"file_path" json:"file_path"`
|
|
FileSize pgtype.Int8 `db:"file_size" json:"file_size"`
|
|
MimeType pgtype.Text `db:"mime_type" json:"mime_type"`
|
|
CoverImagePath pgtype.Text `db:"cover_image_path" json:"cover_image_path"`
|
|
Series pgtype.Text `db:"series" json:"series"`
|
|
SeriesNumber pgtype.Float8 `db:"series_number" json:"series_number"`
|
|
Tags []string `db:"tags" json:"tags"`
|
|
Narrators []string `db:"narrators" json:"narrators"`
|
|
Authors []string `db:"authors" json:"authors"`
|
|
AuthorsSearch []string `db:"authors_search" json:"authors_search"`
|
|
Publishers []string `db:"publishers" json:"publishers"`
|
|
PublishersSearch []string `db:"publishers_search" json:"publishers_search"`
|
|
Abridged bool `db:"abridged" json:"abridged"`
|
|
Explicit bool `db:"explicit" json:"explicit"`
|
|
Asin pgtype.Text `db:"asin" json:"asin"`
|
|
DatePublished pgtype.Date `db:"date_published" json:"date_published"`
|
|
Publisher pgtype.Text `db:"publisher" json:"publisher"`
|
|
Contributors []string `db:"contributors" json:"contributors"`
|
|
// ISO 639-1 language code (e.g., en, es, fr)
|
|
Language pgtype.Text `db:"language" json:"language"`
|
|
// Edition information (e.g., "First Edition", "Revised Edition")
|
|
Edition pgtype.Text `db:"edition" json:"edition"`
|
|
// Total page count for progress tracking and sorting
|
|
PageCount pgtype.Int4 `db:"page_count" json:"page_count"`
|
|
// Genre classification for filtering and discovery
|
|
Genre pgtype.Text `db:"genre" json:"genre"`
|
|
// Copyright or publication year for filtering/sorting
|
|
CopyrightYear pgtype.Int4 `db:"copyright_year" json:"copyright_year"`
|
|
// Goodreads book identifier for integration
|
|
GoodreadsID pgtype.Text `db:"goodreads_id" json:"goodreads_id"`
|
|
// Open Library identifier for integration
|
|
OpenlibraryID pgtype.Text `db:"openlibrary_id" json:"openlibrary_id"`
|
|
// Google Books identifier for integration
|
|
GoogleBooksID pgtype.Text `db:"google_books_id" json:"google_books_id"`
|
|
AddedByAdminID pgtype.UUID `db:"added_by_admin_id" json:"added_by_admin_id"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
ImportedAt pgtype.Timestamptz `db:"imported_at" json:"imported_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
FormatGroup string `db:"format_group" json:"format_group"`
|
|
FormatMimetype pgtype.Text `db:"format_mimetype" json:"format_mimetype"`
|
|
IsReflowable pgtype.Bool `db:"is_reflowable" json:"is_reflowable"`
|
|
HasFixedLayout pgtype.Bool `db:"has_fixed_layout" json:"has_fixed_layout"`
|
|
TotalCharacters pgtype.Int8 `db:"total_characters" json:"total_characters"`
|
|
ChapterCount pgtype.Int4 `db:"chapter_count" json:"chapter_count"`
|
|
EntitlementID pgtype.Text `db:"entitlement_id" json:"entitlement_id"`
|
|
RevisionNumber pgtype.Int4 `db:"revision_number" json:"revision_number"`
|
|
KoboContentID pgtype.Text `db:"kobo_content_id" json:"kobo_content_id"`
|
|
KoboMetadata []byte `db:"kobo_metadata" json:"kobo_metadata"`
|
|
// Raw Manga field from ComicInfo.xml: unknown, no, yes, yes_and_right_to_left
|
|
MangaType pgtype.Text `db:"manga_type" json:"manga_type"`
|
|
// Computed reading direction: auto, ltr (left-to-right), rtl (right-to-left), vertical (webtoons/manhwa)
|
|
ReadingDirection pgtype.Text `db:"reading_direction" json:"reading_direction"`
|
|
// Total items in series (from ComicInfo.xml Count field, or book series count)
|
|
SeriesCount pgtype.Int4 `db:"series_count" json:"series_count"`
|
|
// Volume/omnibus number for collected editions
|
|
Volume pgtype.Int4 `db:"volume" json:"volume"`
|
|
// Publisher imprint/subdivision (e.g., Vertigo, HarperCollinsEpic, DC Black Label)
|
|
Imprint pgtype.Text `db:"imprint" json:"imprint"`
|
|
// Age rating from metadata: Everyone, Teen, Mature, Adult (applies to all formats)
|
|
AgeRating pgtype.Text `db:"age_rating" json:"age_rating"`
|
|
// URL to info page (Goodreads, ComicVine, MangaUpdates, Audible, etc.)
|
|
WebUrl pgtype.Text `db:"web_url" json:"web_url"`
|
|
// Story arc name for grouping related issues (e.g., "The Dark Phoenix Saga", "Civil War")
|
|
StoryArc pgtype.Text `db:"story_arc" json:"story_arc"`
|
|
// Black and white comic flag from ComicInfo.xml
|
|
IsBlackAndWhite pgtype.Bool `db:"is_black_and_white" json:"is_black_and_white"`
|
|
// Notes from metadata files (ComicInfo.xml, EPUB, PDF) - distinct from user notes in media_notes table
|
|
MetadataNotes pgtype.Text `db:"metadata_notes" json:"metadata_notes"`
|
|
// Pre-existing community rating from metadata files (scale 0.0-10.0, DOUBLE PRECISION) - distinct from user ratings in media_ratings table
|
|
CommunityRating pgtype.Float8 `db:"community_rating" json:"community_rating"`
|
|
// Alternate series information as JSONB: {alternate_series, alternate_number, alternate_count}
|
|
AlternateInfo []byte `db:"alternate_info" json:"alternate_info"`
|
|
// Scan information from ComicInfo.xml (scanner group, resolution, etc.)
|
|
ScanInformation pgtype.Text `db:"scan_information" json:"scan_information"`
|
|
// Summary from ComicInfo.xml (may be merged with description from Calibre)
|
|
Summary pgtype.Text `db:"summary" json:"summary"`
|
|
MetadataOverrides []string `db:"metadata_overrides" json:"metadata_overrides"`
|
|
MissingScanCount int32 `db:"missing_scan_count" json:"missing_scan_count"`
|
|
ArchivedAt pgtype.Timestamptz `db:"archived_at" json:"archived_at"`
|
|
ChapterMetadata []byte `db:"chapter_metadata" json:"chapter_metadata"`
|
|
LibraryTypeName pgtype.Text `db:"library_type_name" json:"library_type_name"`
|
|
AudioMetadata []byte `db:"audio_metadata" json:"audio_metadata"`
|
|
TagsSearch []string `db:"tags_search" json:"tags_search"`
|
|
ContributorsSearch []string `db:"contributors_search" json:"contributors_search"`
|
|
NarratorsSearch []string `db:"narrators_search" json:"narrators_search"`
|
|
FileSha256 pgtype.Text `db:"file_sha256" json:"file_sha256"`
|
|
OpfIdentifier pgtype.Text `db:"opf_identifier" json:"opf_identifier"`
|
|
OpfUuid pgtype.Text `db:"opf_uuid" json:"opf_uuid"`
|
|
HashConfidence pgtype.Text `db:"hash_confidence" json:"hash_confidence"`
|
|
Source string `db:"source" json:"source"`
|
|
SourceFeedID pgtype.UUID `db:"source_feed_id" json:"source_feed_id"`
|
|
EpisodeGuid pgtype.Text `db:"episode_guid" json:"episode_guid"`
|
|
FeedPosition pgtype.Int4 `db:"feed_position" json:"feed_position"`
|
|
SeasonNumber pgtype.Int4 `db:"season_number" json:"season_number"`
|
|
EpisodeNumber pgtype.Int4 `db:"episode_number" json:"episode_number"`
|
|
EnclosureUrl pgtype.Text `db:"enclosure_url" json:"enclosure_url"`
|
|
DeclaredDurationSeconds pgtype.Int4 `db:"declared_duration_seconds" json:"declared_duration_seconds"`
|
|
TranscriptUrl pgtype.Text `db:"transcript_url" json:"transcript_url"`
|
|
ChaptersUrl pgtype.Text `db:"chapters_url" json:"chapters_url"`
|
|
Hosts []string `db:"hosts" json:"hosts"`
|
|
Guests []string `db:"guests" json:"guests"`
|
|
DownloadState string `db:"download_state" json:"download_state"`
|
|
DownloadError pgtype.Text `db:"download_error" json:"download_error"`
|
|
DownloadAttempts int32 `db:"download_attempts" json:"download_attempts"`
|
|
DownloadQueuePos pgtype.Int8 `db:"download_queue_pos" json:"download_queue_pos"`
|
|
}
|
|
|
|
type MediaNotes struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Content string `db:"content" json:"content"`
|
|
Position pgtype.Text `db:"position" json:"position"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
PercentageLocation pgtype.Float8 `db:"percentage_location" json:"percentage_location"`
|
|
CharacterStart pgtype.Int4 `db:"character_start" json:"character_start"`
|
|
CharacterEnd pgtype.Int4 `db:"character_end" json:"character_end"`
|
|
EpubcfiLocation pgtype.Text `db:"epubcfi_location" json:"epubcfi_location"`
|
|
ChapterReference pgtype.Int4 `db:"chapter_reference" json:"chapter_reference"`
|
|
ParagraphReference pgtype.Int4 `db:"paragraph_reference" json:"paragraph_reference"`
|
|
DeviceSyncData []byte `db:"device_sync_data" json:"device_sync_data"`
|
|
DedupKey pgtype.Text `db:"dedup_key" json:"dedup_key"`
|
|
LastModifiedAt pgtype.Timestamptz `db:"last_modified_at" json:"last_modified_at"`
|
|
LastModifiedSource pgtype.Text `db:"last_modified_source" json:"last_modified_source"`
|
|
Deleted pgtype.Bool `db:"deleted" json:"deleted"`
|
|
DeletedAt pgtype.Timestamptz `db:"deleted_at" json:"deleted_at"`
|
|
}
|
|
|
|
type MediaRatings struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
// Rating scale 1-10 (odd numbers = half-stars: 1,3,5,7,9 = 0.5,1.5,2.5,3.5,4.5 stars)
|
|
Rating int32 `db:"rating" json:"rating"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type MediaReviews struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Review string `db:"review" json:"review"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type MediaScanState struct {
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
Manifest []byte `db:"manifest" json:"manifest"`
|
|
}
|
|
|
|
type OpdsTokens struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
Token string `db:"token" json:"token"`
|
|
TokenType pgtype.Text `db:"token_type" json:"token_type"`
|
|
ExpiresAt pgtype.Timestamptz `db:"expires_at" json:"expires_at"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
}
|
|
|
|
type PanelData struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
PageNumber int32 `db:"page_number" json:"page_number"`
|
|
DetectionMethod string `db:"detection_method" json:"detection_method"`
|
|
Panels []byte `db:"panels" json:"panels"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type PodcastFeeds struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
FeedUrl string `db:"feed_url" json:"feed_url"`
|
|
PodcastGuid pgtype.Text `db:"podcast_guid" json:"podcast_guid"`
|
|
Title string `db:"title" json:"title"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
Host pgtype.Text `db:"host" json:"host"`
|
|
Publisher pgtype.Text `db:"publisher" json:"publisher"`
|
|
OwnerName pgtype.Text `db:"owner_name" json:"owner_name"`
|
|
OwnerEmail pgtype.Text `db:"owner_email" json:"owner_email"`
|
|
Language pgtype.Text `db:"language" json:"language"`
|
|
Tags []string `db:"tags" json:"tags"`
|
|
Explicit bool `db:"explicit" json:"explicit"`
|
|
ArtworkPath pgtype.Text `db:"artwork_path" json:"artwork_path"`
|
|
FeedType pgtype.Text `db:"feed_type" json:"feed_type"`
|
|
Medium pgtype.Text `db:"medium" json:"medium"`
|
|
IsComplete bool `db:"is_complete" json:"is_complete"`
|
|
Etag pgtype.Text `db:"etag" json:"etag"`
|
|
LastModified pgtype.Text `db:"last_modified" json:"last_modified"`
|
|
LastFetchedAt pgtype.Timestamptz `db:"last_fetched_at" json:"last_fetched_at"`
|
|
LastBuildDate pgtype.Timestamptz `db:"last_build_date" json:"last_build_date"`
|
|
CreatedByAdminID pgtype.UUID `db:"created_by_admin_id" json:"created_by_admin_id"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type PodcastSubscriptions struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
FeedID pgtype.UUID `db:"feed_id" json:"feed_id"`
|
|
DisplayName pgtype.Text `db:"display_name" json:"display_name"`
|
|
AutoDownload string `db:"auto_download" json:"auto_download"`
|
|
AutoDownloadCount pgtype.Int4 `db:"auto_download_count" json:"auto_download_count"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
}
|
|
|
|
// Tracks media that failed processing in a library: item-backed issues (library-type mismatches, metadata extraction failures) and row-less import failures (no media_items row exists; keyed by library + file_path). Auto-resolved by later successful scans.
|
|
type ProcessingIssues struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
IssueType string `db:"issue_type" json:"issue_type"`
|
|
IssueDescription string `db:"issue_description" json:"issue_description"`
|
|
Severity string `db:"severity" json:"severity"`
|
|
Resolved pgtype.Bool `db:"resolved" json:"resolved"`
|
|
ResolvedAt pgtype.Timestamptz `db:"resolved_at" json:"resolved_at"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
FilePath pgtype.Text `db:"file_path" json:"file_path"`
|
|
}
|
|
|
|
type ReaderSettings struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
SettingKey string `db:"setting_key" json:"setting_key"`
|
|
SettingValue []byte `db:"setting_value" json:"setting_value"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type ReadingHistory struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
ProgressPercentage pgtype.Float8 `db:"progress_percentage" json:"progress_percentage"`
|
|
ReadingSessionStart pgtype.Timestamptz `db:"reading_session_start" json:"reading_session_start"`
|
|
ReadingSessionEnd pgtype.Timestamptz `db:"reading_session_end" json:"reading_session_end"`
|
|
PagesRead pgtype.Int4 `db:"pages_read" json:"pages_read"`
|
|
TimeSpentSeconds pgtype.Int4 `db:"time_spent_seconds" json:"time_spent_seconds"`
|
|
DeviceMetadata []byte `db:"device_metadata" json:"device_metadata"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
}
|
|
|
|
type ReadingProgress struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
CurrentPage pgtype.Int4 `db:"current_page" json:"current_page"`
|
|
TotalPages pgtype.Int4 `db:"total_pages" json:"total_pages"`
|
|
LastReadAt pgtype.Timestamptz `db:"last_read_at" json:"last_read_at"`
|
|
Percentage pgtype.Float8 `db:"percentage" json:"percentage"`
|
|
CharacterOffset pgtype.Int8 `db:"character_offset" json:"character_offset"`
|
|
Epubcfi pgtype.Text `db:"epubcfi" json:"epubcfi"`
|
|
ContextText pgtype.Text `db:"context_text" json:"context_text"`
|
|
Chapter pgtype.Int4 `db:"chapter" json:"chapter"`
|
|
ChapterProgress pgtype.Float8 `db:"chapter_progress" json:"chapter_progress"`
|
|
AudioOffsetSeconds pgtype.Int4 `db:"audio_offset_seconds" json:"audio_offset_seconds"`
|
|
ViewportX pgtype.Float8 `db:"viewport_x" json:"viewport_x"`
|
|
ViewportY pgtype.Float8 `db:"viewport_y" json:"viewport_y"`
|
|
ZoomLevel pgtype.Float8 `db:"zoom_level" json:"zoom_level"`
|
|
ScrollPositionX pgtype.Float8 `db:"scroll_position_x" json:"scroll_position_x"`
|
|
ScrollPositionY pgtype.Float8 `db:"scroll_position_y" json:"scroll_position_y"`
|
|
PanelNumber pgtype.Int4 `db:"panel_number" json:"panel_number"`
|
|
ReadingMode pgtype.Text `db:"reading_mode" json:"reading_mode"`
|
|
LastSyncDevice pgtype.Text `db:"last_sync_device" json:"last_sync_device"`
|
|
LastSyncSource pgtype.Text `db:"last_sync_source" json:"last_sync_source"`
|
|
LastSyncTimestamp pgtype.Timestamptz `db:"last_sync_timestamp" json:"last_sync_timestamp"`
|
|
ConflictDetected pgtype.Bool `db:"conflict_detected" json:"conflict_detected"`
|
|
ConflictResolved pgtype.Bool `db:"conflict_resolved" json:"conflict_resolved"`
|
|
}
|
|
|
|
type ReadingSpeed struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
WordsPerMinute pgtype.Float4 `db:"words_per_minute" json:"words_per_minute"`
|
|
PagesPerMinute pgtype.Float4 `db:"pages_per_minute" json:"pages_per_minute"`
|
|
PagesRead pgtype.Int4 `db:"pages_read" json:"pages_read"`
|
|
TotalReadingMinutes pgtype.Float4 `db:"total_reading_minutes" json:"total_reading_minutes"`
|
|
LastReadAt pgtype.Timestamptz `db:"last_read_at" json:"last_read_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type RefreshTokens struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Token pgtype.UUID `db:"token" json:"token"`
|
|
ExpiresAt pgtype.Timestamptz `db:"expires_at" json:"expires_at"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
RevokedAt pgtype.Timestamptz `db:"revoked_at" json:"revoked_at"`
|
|
}
|
|
|
|
type SavedFilters struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Name string `db:"name" json:"name"`
|
|
ResourceType string `db:"resource_type" json:"resource_type"`
|
|
Filters []byte `db:"filters" json:"filters"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type SyncConflicts struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
ConflictType string `db:"conflict_type" json:"conflict_type"`
|
|
ConflictData []byte `db:"conflict_data" json:"conflict_data"`
|
|
ResolutionStatus pgtype.Text `db:"resolution_status" json:"resolution_status"`
|
|
ResolutionData []byte `db:"resolution_data" json:"resolution_data"`
|
|
ResolvedBy pgtype.UUID `db:"resolved_by" json:"resolved_by"`
|
|
ResolvedAt pgtype.Timestamptz `db:"resolved_at" json:"resolved_at"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
}
|
|
|
|
type SyncQueue struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
SyncType string `db:"sync_type" json:"sync_type"`
|
|
SyncData []byte `db:"sync_data" json:"sync_data"`
|
|
Priority pgtype.Int4 `db:"priority" json:"priority"`
|
|
Attempts pgtype.Int4 `db:"attempts" json:"attempts"`
|
|
MaxAttempts pgtype.Int4 `db:"max_attempts" json:"max_attempts"`
|
|
Status pgtype.Text `db:"status" json:"status"`
|
|
ErrorMessage pgtype.Text `db:"error_message" json:"error_message"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
ProcessedAt pgtype.Timestamptz `db:"processed_at" json:"processed_at"`
|
|
}
|
|
|
|
type SystemConfig struct {
|
|
Key string `db:"key" json:"key"`
|
|
Value string `db:"value" json:"value"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
UpdatedBy pgtype.UUID `db:"updated_by" json:"updated_by"`
|
|
}
|
|
|
|
type SystemSettings struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
SettingKey string `db:"setting_key" json:"setting_key"`
|
|
SettingValue string `db:"setting_value" json:"setting_value"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
SettingType pgtype.Text `db:"setting_type" json:"setting_type"`
|
|
MinValue pgtype.Text `db:"min_value" json:"min_value"`
|
|
MaxValue pgtype.Text `db:"max_value" json:"max_value"`
|
|
RequiresRestart pgtype.Bool `db:"requires_restart" json:"requires_restart"`
|
|
Category pgtype.Text `db:"category" json:"category"`
|
|
}
|
|
|
|
type UnlinkedBooks struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
DeviceID pgtype.UUID `db:"device_id" json:"device_id"`
|
|
ContentID string `db:"content_id" json:"content_id"`
|
|
FilePath pgtype.Text `db:"file_path" json:"file_path"`
|
|
Title pgtype.Text `db:"title" json:"title"`
|
|
Author pgtype.Text `db:"author" json:"author"`
|
|
ConfidenceScore pgtype.Float8 `db:"confidence_score" json:"confidence_score"`
|
|
Resolved pgtype.Bool `db:"resolved" json:"resolved"`
|
|
MediaItemID pgtype.UUID `db:"media_item_id" json:"media_item_id"`
|
|
ResolvedAt pgtype.Timestamptz `db:"resolved_at" json:"resolved_at"`
|
|
ResolutionMethod pgtype.Text `db:"resolution_method" json:"resolution_method"`
|
|
LastSeenAt pgtype.Timestamptz `db:"last_seen_at" json:"last_seen_at"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
IgnoredAt pgtype.Timestamptz `db:"ignored_at" json:"ignored_at"`
|
|
}
|
|
|
|
type UserDashboardPreferences struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
|
|
HiddenCollections []string `db:"hidden_collections" json:"hidden_collections"`
|
|
CollectionOrder []string `db:"collection_order" json:"collection_order"`
|
|
ItemsPerSection pgtype.Int4 `db:"items_per_section" json:"items_per_section"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type UserDashboardPreferencesGlobal struct {
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
HiddenCollections []string `db:"hidden_collections" json:"hidden_collections"`
|
|
CollectionOrder []string `db:"collection_order" json:"collection_order"`
|
|
ItemsPerSection pgtype.Int4 `db:"items_per_section" json:"items_per_section"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
type Users struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Email string `db:"email" json:"email"`
|
|
Username string `db:"username" json:"username"`
|
|
PasswordHash string `db:"password_hash" json:"password_hash"`
|
|
FirstName pgtype.Text `db:"first_name" json:"first_name"`
|
|
LastName pgtype.Text `db:"last_name" json:"last_name"`
|
|
Role string `db:"role" json:"role"`
|
|
Theme pgtype.Text `db:"theme" json:"theme"`
|
|
MaxDevices pgtype.Int4 `db:"max_devices" json:"max_devices"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
Timezone pgtype.Text `db:"timezone" json:"timezone"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
DefaultAudioSpeed float32 `db:"default_audio_speed" json:"default_audio_speed"`
|
|
KeepScreenAwake bool `db:"keep_screen_awake" json:"keep_screen_awake"`
|
|
}
|