kobo

package
v0.0.21 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2026 License: MIT Imports: 28 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetAPIKeyFromContext

func GetAPIKeyFromContext(ctx context.Context) *apikeys.APIKey

GetAPIKeyFromContext retrieves the API key from context.

func ParseShishoID

func ParseShishoID(id string) (int, bool)

ParseShishoID parses a "shisho-{id}" format string and returns the file ID. Returns (0, false) if the format is invalid.

func RegisterRoutes

func RegisterRoutes(e *echo.Echo, db *bun.DB, downloadCache *downloadcache.Cache)

RegisterRoutes registers all Kobo sync routes.

func ShishoID

func ShishoID(fileID int) string

ShishoID returns a Shisho-prefixed ID for a file.

func StripKoboPrefix

func StripKoboPrefix(path string) string

StripKoboPrefix strips everything before /v1/ to get the Kobo API path. For example, "/kobo/ak_123/all/v1/library/sync" becomes "/v1/library/sync".

Types

type ActivePeriod

type ActivePeriod struct {
	From time.Time `json:"From"`
}

ActivePeriod indicates when the entitlement became active.

type BookEntitlement

type BookEntitlement struct {
	Accessibility       string        `json:"Accessibility"`
	ActivePeriod        *ActivePeriod `json:"ActivePeriod"`
	Created             time.Time     `json:"Created"`
	CrossRevisionID     string        `json:"CrossRevisionId"`
	ID                  string        `json:"Id"`
	IsHiddenFromArchive bool          `json:"IsHiddenFromArchive"`
	IsLocked            bool          `json:"IsLocked"`
	IsRemoved           bool          `json:"IsRemoved"`
	LastModified        time.Time     `json:"LastModified"`
	OriginCategory      string        `json:"OriginCategory"`
	RevisionID          string        `json:"RevisionId"`
	Status              string        `json:"Status"`
}

BookEntitlement contains the full entitlement info for a book.

type BookEntitlementChange

type BookEntitlementChange struct {
	ID        string `json:"Id"`
	IsRemoved bool   `json:"IsRemoved"`
}

BookEntitlementChange contains only the fields needed for a change notification.

type BookMetadata

type BookMetadata struct {
	Categories          []string           `json:"Categories"`
	ContributorRoles    []*ContributorRole `json:"ContributorRoles"`
	Contributors        []string           `json:"Contributors"`
	CoverImageID        string             `json:"CoverImageId"`
	CrossRevisionID     string             `json:"CrossRevisionId"`
	CurrentDisplayPrice *DisplayPrice      `json:"CurrentDisplayPrice"`
	Description         string             `json:"Description"`
	DownloadUrls        []*DownloadURL     `json:"DownloadUrls"`
	EntitlementID       string             `json:"EntitlementId"`
	Genre               string             `json:"Genre"`
	Language            string             `json:"Language"`
	PublicationDate     string             `json:"PublicationDate,omitempty"`
	Publisher           *Publisher         `json:"Publisher,omitempty"`
	RevisionID          string             `json:"RevisionId"`
	Series              *Series            `json:"Series,omitempty"`
	Title               string             `json:"Title"`
	WorkID              string             `json:"WorkId"`
}

BookMetadata contains the metadata for a book visible to the Kobo device.

type ChangedEntitlement

type ChangedEntitlement struct {
	ChangedEntitlement *EntitlementChangeWrapper `json:"ChangedEntitlement"`
}

ChangedEntitlement represents a removed book in the sync response.

type ContributorRole

type ContributorRole struct {
	Name string `json:"Name"`
}

ContributorRole represents an author/contributor.

type DeviceAuthRequest

type DeviceAuthRequest struct {
	AffiliateName string `json:"AffiliateName"`
	AppVersion    string `json:"AppVersion"`
	ClientKey     string `json:"ClientKey"`
	DeviceID      string `json:"DeviceId"`
	PlatformID    string `json:"PlatformId"`
}

DeviceAuthRequest is the body sent by the Kobo to POST /v1/auth/device.

type DeviceAuthResponse

type DeviceAuthResponse struct {
	AccessToken  string `json:"AccessToken"`
	RefreshToken string `json:"RefreshToken"`
	TokenType    string `json:"TokenType"`
	TrackingID   string `json:"TrackingId"`
	UserKey      string `json:"UserKey"`
}

DeviceAuthResponse is returned by POST /v1/auth/device.

type DisplayPrice

type DisplayPrice struct {
	CurrencyCode string `json:"CurrencyCode"`
	TotalAmount  int    `json:"TotalAmount"`
}

DisplayPrice represents the price display for a book.

type DownloadURL

type DownloadURL struct {
	Format   string `json:"Format"`
	Platform string `json:"Platform"`
	Size     int64  `json:"Size"`
	URL      string `json:"Url"`
}

DownloadURL provides the download location for a book file.

type EntitlementChangeWrapper

type EntitlementChangeWrapper struct {
	BookEntitlement *BookEntitlementChange `json:"BookEntitlement"`
}

EntitlementChangeWrapper wraps a change (e.g., removal) to an entitlement.

type EntitlementWrapper

type EntitlementWrapper struct {
	BookEntitlement *BookEntitlement `json:"BookEntitlement"`
	BookMetadata    *BookMetadata    `json:"BookMetadata"`
}

EntitlementWrapper wraps the book entitlement and metadata.

type Middleware

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

Middleware provides authentication and scope middleware for Kobo routes.

func NewMiddleware

func NewMiddleware(apiKeyService *apikeys.Service) *Middleware

NewMiddleware creates a new Kobo middleware.

func (*Middleware) APIKeyAuth

func (m *Middleware) APIKeyAuth() echo.MiddlewareFunc

APIKeyAuth validates the API key from c.Param("apiKey"), checks kobo_sync permission, touches last accessed (fire and forget goroutine), and stores the API key in context.

func (*Middleware) ScopeParser

func (m *Middleware) ScopeParser(scopeType string) echo.MiddlewareFunc

ScopeParser parses the sync scope from URL params based on the given scope type. The scope type is passed as a parameter since each route group knows its type:

  • "all" -> SyncScope{Type: "all"}
  • "library" -> SyncScope{Type: "library", LibraryID: &id} (parses scopeId param)
  • "list" -> SyncScope{Type: "list", ListID: &id} (parses scopeId param)

type NewEntitlement

type NewEntitlement struct {
	NewEntitlement *EntitlementWrapper `json:"NewEntitlement"`
}

NewEntitlement represents a new or changed book in the sync response.

type Publisher

type Publisher struct {
	Name string `json:"Name"`
}

Publisher represents a book publisher.

type ScopedFile

type ScopedFile struct {
	FileID       int
	FileHash     string
	FileSize     int64
	MetadataHash string
}

ScopedFile represents a file in the current sync scope with its hashes.

type Series

type Series struct {
	Name        string  `json:"Name"`
	Number      float64 `json:"Number"`
	NumberFloat float64 `json:"NumberFloat"`
}

Series represents a book series.

type Service

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

Service provides sync operations for Kobo devices.

func NewService

func NewService(db *bun.DB) *Service

NewService creates a new Kobo sync service.

func (*Service) CleanupOldSyncPoints

func (svc *Service) CleanupOldSyncPoints(ctx context.Context, apiKeyID string) error

func (*Service) ClearAllSyncPoints

func (svc *Service) ClearAllSyncPoints(ctx context.Context, apiKeyID string) error

CleanupOldSyncPoints removes completed sync points older than the most recent one per API key. This prevents the database from growing unbounded. ClearAllSyncPoints deletes all sync points for an API key, forcing a fresh sync.

func (*Service) CreateSyncPoint

func (svc *Service) CreateSyncPoint(ctx context.Context, apiKeyID string, files []ScopedFile) (*SyncPoint, error)

CreateSyncPoint creates a new sync point with the given files and marks it as complete.

func (*Service) DetectChanges

func (svc *Service) DetectChanges(ctx context.Context, lastSyncPointID string, currentFiles []ScopedFile) (*SyncChanges, error)

DetectChanges compares currentFiles against the last sync point. If lastSyncPointID is empty, this is the first sync and all files are Added.

func (*Service) GetLastSyncPoint

func (svc *Service) GetLastSyncPoint(ctx context.Context, apiKeyID string) (*SyncPoint, error)

GetLastSyncPoint returns the most recent completed sync point for an API key.

func (*Service) GetScopedFiles

func (svc *Service) GetScopedFiles(ctx context.Context, userID int, scope *SyncScope) ([]ScopedFile, error)

GetScopedFiles queries files in scope, filtered by library access and file type (epub/cbz).

func (*Service) GetSyncPointByID

func (svc *Service) GetSyncPointByID(ctx context.Context, syncPointID string) (*SyncPoint, error)

GetSyncPointByID retrieves a sync point by ID with its Books relation loaded.

type SyncChanges

type SyncChanges struct {
	Added   []ScopedFile
	Removed []ScopedFile
	Changed []ScopedFile
}

SyncChanges contains the detected changes between two sync points.

type SyncPoint

type SyncPoint struct {
	bun.BaseModel `bun:"table:kobo_sync_points,alias:ksp"`

	ID          string     `bun:"id,pk"`
	APIKeyID    string     `bun:"api_key_id,notnull"`
	CreatedAt   time.Time  `bun:"created_at,notnull"`
	CompletedAt *time.Time `bun:"completed_at"`

	Books []*SyncPointBook `bun:"rel:has-many,join:id=sync_point_id"`
}

SyncPoint tracks the state of the library at a sync, per API key.

type SyncPointBook

type SyncPointBook struct {
	bun.BaseModel `bun:"table:kobo_sync_point_books,alias:kspb"`

	ID           string `bun:"id,pk"`
	SyncPointID  string `bun:"sync_point_id,notnull"`
	FileID       int    `bun:"file_id,notnull"`
	FileHash     string `bun:"file_hash,notnull"`
	FileSize     int64  `bun:"file_size,notnull"`
	MetadataHash string `bun:"metadata_hash,notnull"`
	Synced       bool   `bun:"synced,notnull,default:false"`
}

SyncPointBook is a snapshot of a file's state at a sync point.

type SyncScope

type SyncScope struct {
	Type      string // "all", "library", "list"
	LibraryID *int
	ListID    *int
}

SyncScope represents the scope of books to sync (parsed from URL).

func GetScopeFromContext

func GetScopeFromContext(ctx context.Context) *SyncScope

GetScopeFromContext retrieves the sync scope from context. Returns a default scope of {Type: "all"} if not found.

type SyncToken

type SyncToken struct {
	LastSyncPointID string `json:"lastSyncPointId"`
}

SyncToken is the base64-encoded JSON sent/received in X-Kobo-SyncToken header.

Jump to

Keyboard shortcuts

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