Documentation
¶
Overview ¶
Package simkl implements the optional Simkl integration.
Index ¶
- Variables
- func Enqueue(ctx context.Context, db *sql.DB, ev state.Event) error
- func Handler(d HandlerDeps) http.Handler
- func HistoryPayload(key core.RatingKey, at time.Time) (map[string]any, error)
- func ParseHistory(user int64, data []byte) ([]state.ImportRecord, int, error)
- func RunDelivery(ctx context.Context, service func() Service, enabled func() bool, ...)
- type APIError
- type AuthClient
- func (c AuthClient) IsOrdinaryTV(ctx context.Context, tmdb int64) (bool, error)
- func (c AuthClient) Poll(ctx context.Context, deviceCode string) (Token, error)
- func (c AuthClient) PullHistory(ctx context.Context, user int64, token, snapshot string) ([]state.ImportRecord, string, int, error)
- func (c AuthClient) PushHistory(ctx context.Context, token string, key core.RatingKey, at time.Time, ...) error
- func (c AuthClient) Refresh(ctx context.Context, refresh string) (Token, error)
- func (c AuthClient) Revoke(ctx context.Context, token string) error
- func (c AuthClient) Start(ctx context.Context) (DeviceCode, error)
- type DeviceCode
- type DeviceInfo
- type DeviceManager
- type Grant
- type HTTPError
- type HandlerDeps
- type Service
- type SyncResult
- type Token
- type TokenStore
- func (s TokenStore) AcquireLease(ctx context.Context, user int64, now time.Time) (string, error)
- func (s TokenStore) Delete(ctx context.Context, user int64) error
- func (s TokenStore) Load(ctx context.Context, user int64) (Grant, error)
- func (s TokenStore) Pop(ctx context.Context, user int64) (Grant, error)
- func (s TokenStore) Refresh(ctx context.Context, user int64, lease string, auth AuthClient) (Grant, error)
- func (s TokenStore) ReleaseLease(ctx context.Context, user int64, id string) error
- func (s TokenStore) Save(ctx context.Context, user int64, token Token, now time.Time) error
Constants ¶
This section is empty.
Variables ¶
var ErrBusy = errors.New("simkl: account is busy")
var ErrExpired = errors.New("simkl: authorization expired")
var ErrIdentityNotFound = errors.New("simkl: history identity not found")
var ErrNoPending = errors.New("simkl: no pending authorization")
var ErrPollEarly = errors.New("simkl: poll interval has not elapsed")
Functions ¶
func Enqueue ¶
Enqueue records local completions only for linked viewers. Imports do not echo back to their source, and an unwatch never deletes remote history.
func Handler ¶
func Handler(d HandlerDeps) http.Handler
func HistoryPayload ¶
HistoryPayload uses only identities represented unambiguously by Ether's native movie and episode keys. Local files and show/season keys are skipped. https://api.simkl.org/api-reference/simkl/add-to-history
func ParseHistory ¶
ParseHistory accepts only actual timestamps and TMDB identities; anime is deliberately skipped because its episode numbering is not necessarily TMDB's. https://api.simkl.org/api-reference/simkl/get-all-items
Types ¶
type AuthClient ¶
func (AuthClient) IsOrdinaryTV ¶
IsOrdinaryTV uses Simkl's documented redirect classification without following it. Anime is intentionally not assigned TMDB episode numbers. https://api.simkl.org/api-reference/simkl/redirect
func (AuthClient) PullHistory ¶
func (c AuthClient) PullHistory(ctx context.Context, user int64, token, snapshot string) ([]state.ImportRecord, string, int, error)
PullHistory reads activities before the sequential movie/show pulls. The returned snapshot must only be saved after all imported records commit. https://api.simkl.org/guides/sync
func (AuthClient) PushHistory ¶
func (c AuthClient) PushHistory(ctx context.Context, token string, key core.RatingKey, at time.Time, tvNumberingVerified bool) error
PushHistory sends one completion; episode numbering must first be verified against Simkl's TV mapping by the caller. Anime often uses a different numbering scheme and is not safe to infer from an Ether key alone.
func (AuthClient) Start ¶
func (c AuthClient) Start(ctx context.Context) (DeviceCode, error)
type DeviceCode ¶
type DeviceInfo ¶
type DeviceManager ¶
type DeviceManager struct {
Auth AuthClient
AuthConfig func() AuthClient
Tokens TokenStore
}
DeviceManager stores each short-lived device credential sealed in shared storage. Its generation and poll claim bind it to a viewer across nodes.
func (*DeviceManager) Disconnect ¶
func (m *DeviceManager) Disconnect(ctx context.Context, user int64) error
func (*DeviceManager) Start ¶
func (m *DeviceManager) Start(ctx context.Context, user int64) (DeviceInfo, error)
type HTTPError ¶
HTTPError exposes status and Retry-After without copying upstream bodies into logs. Callers must honor Retry-After before retrying a rate limit.
type HandlerDeps ¶
type HandlerDeps struct {
Device *DeviceManager
Service func() Service
Viewer func(context.Context, int64) bool
Enabled func() bool
}
HandlerDeps are explicitly provided by the owner-authenticated admin API. Viewer validates that an ID identifies a current viewer, never a caller- supplied arbitrary account. Authentication is enforced by the mounting API.
type Service ¶
type Service struct {
Auth AuthClient
Tokens TokenStore
State *state.State
}
Service is supplied explicit state and credential dependencies. Manual sync uses a lease and a deadline shorter than the lease; it never advances the snapshot after a partial pull.
func (Service) FlushOne ¶
FlushOne delivers at most one queued event under the per-viewer lease. The caller runs it only on the cluster leader. Simkl's default history write is idempotent for already-watched items, including retries after an uncertain response; rewatch creation is deliberately not enabled.
type SyncResult ¶
type TokenStore ¶
type TokenStore struct {
DB *sql.DB
Sealer config.FieldSealer
}
TokenStore stores a grant per viewer, with both fields bound to their row. A functioning field sealer is mandatory: this component never stores a new grant in cleartext, including during the legacy credential upgrade.
func (TokenStore) AcquireLease ¶
AcquireLease reserves a viewer grant across nodes for bounded remote work. Operations must end before the deadline; every update must also check the lease id, since a paused process may wake after losing its reservation.
func (TokenStore) Pop ¶
Pop removes a grant and its queue under the same viewer lock used for account replacement and enqueue, returning only the grant actually removed.
func (TokenStore) Refresh ¶
func (s TokenStore) Refresh(ctx context.Context, user int64, lease string, auth AuthClient) (Grant, error)
Refresh under a viewer lease prevents two nodes invalidating each other's access token. The conditional update cannot recreate a disconnected grant.