Documentation
¶
Index ¶
- func GetAPIKeyFromContext(ctx context.Context) *apikeys.APIKey
- func ParseShishoID(id string) (int, bool)
- func RegisterRoutes(e *echo.Echo, db *bun.DB, downloadCache *downloadcache.Cache)
- func ShishoID(fileID int) string
- func StripKoboPrefix(path string) string
- type ActivePeriod
- type BookEntitlement
- type BookEntitlementChange
- type BookMetadata
- type ChangedEntitlement
- type ContributorRole
- type DeviceAuthRequest
- type DeviceAuthResponse
- type DisplayPrice
- type DownloadURL
- type EntitlementChangeWrapper
- type EntitlementWrapper
- type Middleware
- type NewEntitlement
- type Publisher
- type ScopedFile
- type Series
- type Service
- func (svc *Service) CleanupOldSyncPoints(ctx context.Context, apiKeyID string) error
- func (svc *Service) ClearAllSyncPoints(ctx context.Context, apiKeyID string) error
- func (svc *Service) CreateSyncPoint(ctx context.Context, apiKeyID string, files []ScopedFile) (*SyncPoint, error)
- func (svc *Service) DetectChanges(ctx context.Context, lastSyncPointID string, currentFiles []ScopedFile) (*SyncChanges, error)
- func (svc *Service) GetLastSyncPoint(ctx context.Context, apiKeyID string) (*SyncPoint, error)
- func (svc *Service) GetScopedFiles(ctx context.Context, userID int, scope *SyncScope) ([]ScopedFile, error)
- func (svc *Service) GetSyncPointByID(ctx context.Context, syncPointID string) (*SyncPoint, error)
- type SyncChanges
- type SyncPoint
- type SyncPointBook
- type SyncScope
- type SyncToken
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetAPIKeyFromContext ¶
GetAPIKeyFromContext retrieves the API key from context.
func ParseShishoID ¶
ParseShishoID parses a "shisho-{id}" format string and returns the file ID. Returns (0, false) if the format is invalid.
func RegisterRoutes ¶
RegisterRoutes registers all Kobo sync routes.
func StripKoboPrefix ¶
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 ¶
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 ¶
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 ¶
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 (*Service) CleanupOldSyncPoints ¶
func (*Service) ClearAllSyncPoints ¶
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 ¶
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).
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 ¶
SyncScope represents the scope of books to sync (parsed from URL).
func GetScopeFromContext ¶
GetScopeFromContext retrieves the sync scope from context. Returns a default scope of {Type: "all"} if not found.