feat(db): Add kobo_shelves and device catalog tables

- Add kobo_shelves table for Kobo device shelves management
- Add device_shelf_mappings for collection<->device shelf mappings
- Update device_catalogs with better ContentId tracking
- Add indexes for performance
This commit is contained in:
2026-01-31 22:32:04 -05:00
parent 60380a043d
commit 63008001c6
5 changed files with 2910 additions and 64 deletions
+108 -7
View File
@@ -8,6 +8,57 @@ import (
"github.com/jackc/pgx/v5/pgtype"
)
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"`
}
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"`
ViewSettings []byte `db:"view_settings" json:"view_settings"`
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_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"`
BookmannUuid pgtype.UUID `db:"bookmann_uuid" json:"bookmann_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"`
@@ -163,13 +214,15 @@ type KoboEntitlements struct {
}
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"`
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 {
@@ -230,6 +283,18 @@ type MediaHighlights struct {
DeviceSyncData []byte `db:"device_sync_data" json:"device_sync_data"`
}
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"`
@@ -277,6 +342,10 @@ type MediaItems struct {
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"`
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"`
}
type MediaNotes struct {
@@ -306,6 +375,15 @@ type MediaRatings struct {
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
}
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 ReadingHistory struct {
ID pgtype.UUID `db:"id" json:"id"`
UserID pgtype.UUID `db:"user_id" json:"user_id"`
@@ -383,6 +461,29 @@ type SyncQueue struct {
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 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"`
}
type Users struct {
ID pgtype.UUID `db:"id" json:"id"`
Email string `db:"email" json:"email"`