Documentation
¶
Overview ¶
Package api declares the cross-package interface spine.
Concrete types in internal/{plex,cache,users,...} implement these interfaces; consumers (internal/{sync,scheduler,notify}) depend only on these interfaces. This keeps the composition root in main.go as the single wiring layer and lets tests substitute fakes without reaching into production packages.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache interface {
WasRecentlyProcessed(key string) bool
MarkProcessed(key string)
LearnLanguageProfile(userID, audioLang, subtitleLang string)
SubtitleLangForAudio(userID, audioLang string) (string, bool)
UserTokens() map[string]string
SetUserTokens(tokens map[string]string)
LastSchedulerRun() time.Time
SetLastSchedulerRun(t time.Time)
}
Cache is the persistent cache consumed by the sync / scheduler / user- management subsystems. The concrete implementation lives in internal/cache.
LoadFrom / SaveTo are deliberately NOT on this interface — they are composition-root concerns (wiring the cache to a path on disk) and do not belong on the abstraction consumers see.
type IgnoreChecker ¶
type IgnoreChecker interface {
IgnoreLibrary(title string) bool
ShouldSkipEpisode(ctx context.Context, reader PlexReader, ref *streams.Episode) bool
}
IgnoreChecker is the cross-subsystem "should I skip this library / episode?" decision, shared by sync, scheduler, and the WebSocket notifyAdapter so the three paths honour identical ignore semantics. *ignore.Policy (see internal/ignore) is the only production implementation; tests substitute in-package fakes.
ShouldSkipEpisode combines library-title + show-label checks into one call; IgnoreLibrary is the narrower library-only variant used by the scheduler's recently-added loop where only the Section.Title is available (no episode ref yet). Consumers should prefer ShouldSkipEpisode when they already hold an episode ref because it also checks the show-label ignore list via ShowMetadata.
type PlexReadWriter ¶
type PlexReadWriter interface {
PlexReader
PlexWriter
}
PlexReadWriter is the union of PlexReader and PlexWriter. Per-user operations (track changes) need both read and write access through the same client value so the sync package can request a single typed parameter from its callers.
type PlexReader ¶
type PlexReader interface {
Episode(ctx context.Context, ratingKey plex.RatingKey) (*streams.Episode, error)
ShowEpisodes(ctx context.Context, showRatingKey plex.RatingKey) ([]streams.Episode, error)
SeasonEpisodes(ctx context.Context, seasonRatingKey plex.RatingKey) ([]streams.Episode, error)
ShowMetadata(ctx context.Context, showRatingKey plex.RatingKey) (*plex.Show, error)
RecentlyAdded(ctx context.Context, sectionKey plex.RatingKey, sinceUnix int64) ([]streams.Episode, error)
History(ctx context.Context, sinceUnix int64) ([]plex.HistoryItem, error)
ShowSections(ctx context.Context) ([]plex.Section, error)
UserFromSession(ctx context.Context, clientIdentifier string) (userID, username string, err error)
}
PlexReader is the read side of the Plex HTTP client as consumed by the sync and scheduler packages. *plex.Client satisfies it by structural typing; tests supply a fake implementation.
Rating keys are typed as plex.RatingKey at the interface boundary so the implementation validates once via RatingKey.Validate rather than per-method strconv.Atoi stanzas. Call sites wrap wire-origin strings (streams.Episode.RatingKey, plex.Section.Key, plex.HistoryItem. RatingKey) at the seam, e.g. reader.Episode(ctx, plex.RatingKey(ep.RatingKey)).
sinceUnix is seconds since the Unix epoch (int64), matching *plex.Client's History / RecentlyAdded signatures which pass the value straight into Plex's `viewedAt>=` / `addedAt>=` query filters.
type PlexWriter ¶
type PlexWriter interface {
SetAudioStream(ctx context.Context, partID, streamID int) error
SetSubtitleStream(ctx context.Context, partID, streamID int) error
DisableSubtitles(ctx context.Context, partID int) error
}
PlexWriter is the write side of the Plex HTTP client (stream-selection PUTs). *plex.Client satisfies it by structural typing. The per-user write path runs through the user-scoped *plex.Client returned by users.Manager.ClientForUser, so the interface must be satisfied by both the admin and per-user clients.
type UserClientFunc ¶
type UserClientFunc func(userID string) PlexReadWriter
UserClientFunc returns a per-user read+write Plex client for the given userID. Defined here so scheduler and sync share a single type rather than declaring identical local aliases.
type UserInfo ¶
UserInfo is the minimal user record consumers pass across the api spine. Mirrors internal/users.Info but uses primitive string IDs so the api package stays at the bottom of the import graph — importing internal/users here would introduce a cycle because users depends on api.Cache.
type UserLookup ¶
type UserLookup interface {
ClientForUser(userID string, adminClient *plex.Client) *plex.Client
All() []UserInfo
Name(userID string) string
}
UserLookup resolves user IDs to per-user Plex clients, display names, and the full list of known users. The concrete implementation lives in internal/users.
Method signatures use plain strings for user IDs (rather than the typed users.ID) to keep this package free of a reverse dependency on internal/users. Callers that want typed IDs should go directly through internal/users at the consumer site; this interface is the shared wire other packages (sync, scheduler) can depend on without pulling the full user-manager surface into their import graph.