domain

package
v0.1.0-rc3 Latest Latest
Warning

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

Go to latest
Published: May 8, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package domain contains the shared data types for the Spotnik application. These types represent Spotify API entities and are used across the api/, state/, and ui/ packages without creating import cycles.

Design: domain/ has no dependencies on other internal packages, allowing both api/ and ui/ to import it safely.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Album

type Album struct {
	// ID is the Spotify album ID.
	ID string `json:"id"`

	// Name is the display name of the album.
	Name string `json:"name"`
}

Album represents a simplified Spotify album (as returned within track objects).

type Artist

type Artist struct {
	// ID is the Spotify artist ID.
	ID string `json:"id"`

	// Name is the display name of the artist.
	Name string `json:"name"`
}

Artist represents a Spotify artist.

type ArtistFollowers

type ArtistFollowers struct {
	// Total is the number of Spotify followers for this artist.
	Total int `json:"total"`
}

ArtistFollowers holds the follower count from Spotify's nested followers object.

type Device

type Device struct {
	// ID is the Spotify device ID.
	ID string `json:"id"`

	// IsActive indicates whether this device is the currently active one.
	IsActive bool `json:"is_active"`

	// IsPrivateSession indicates if the session is private.
	IsPrivateSession bool `json:"is_private_session"`

	// IsRestricted indicates if device is restricted (no web API control).
	IsRestricted bool `json:"is_restricted"`

	// Name is the human-readable device name (e.g. "MacBook Pro").
	Name string `json:"name"`

	// Type is the device type (e.g. "Computer", "Smartphone", "Speaker").
	Type string `json:"type"`

	// VolumePercent is the current volume as a percentage (0–100).
	VolumePercent int `json:"volume_percent"`
}

Device represents a Spotify Connect playback device.

type EventKind

type EventKind int

EventKind classifies a gateway event for the event journal.

const (
	// EventRequestEntered means a request arrived at the gateway.
	EventRequestEntered EventKind = iota
	// EventTokenConsumed means a background request consumed a token bucket token.
	EventTokenConsumed
	// EventTokenRefilled means tokens recovered (periodic internal event).
	EventTokenRefilled
	// EventSemaphoreAcquired means a request acquired a concurrency semaphore slot.
	EventSemaphoreAcquired
	// EventSemaphoreReleased means a request released its concurrency semaphore slot.
	EventSemaphoreReleased
	// EventBackoffStarted means the gateway received a 429 and entered backoff mode.
	EventBackoffStarted
	// EventBackoffExpired means the 429 backoff period cleared.
	EventBackoffExpired
	// EventRequestAllowed means a request passed through the gateway normally.
	EventRequestAllowed
	// EventRequestBlocked means a request was rejected by active backoff or token bucket.
	EventRequestBlocked
	// EventDedupJoined means a GET request joined an existing in-flight GET (dedup).
	EventDedupJoined
	// EventDedupResolved means dedup waiters received the shared response.
	EventDedupResolved
	// EventHttpCompleted means an HTTP response was received from Spotify.
	EventHttpCompleted
)

type FullAlbum

type FullAlbum struct {
	// ID is the Spotify album ID.
	ID string `json:"id"`

	// Name is the display name of the album.
	Name string `json:"name"`

	// URI is the Spotify URI of the album.
	URI string `json:"uri"`

	// TotalTracks is the total number of tracks in the album.
	TotalTracks int `json:"total_tracks"`

	// ReleaseDate is the release date string (e.g. "2020-03-20").
	ReleaseDate string `json:"release_date"`

	// Artists is the list of artists for this album.
	Artists []Artist `json:"artists"`
}

FullAlbum represents a Spotify album with full details, used within SavedAlbum.

type FullArtist

type FullArtist struct {
	// ID is the Spotify artist ID.
	ID string `json:"id"`

	// Name is the display name of the artist.
	Name string `json:"name"`

	// URI is the Spotify URI of the artist (e.g. "spotify:artist:...").
	URI string `json:"uri"`

	// Genres is the list of musical genres associated with this artist.
	Genres []string `json:"genres"`

	// Popularity is the artist's popularity score (0–100).
	Popularity int `json:"popularity"`

	// Followers holds the total follower count.
	Followers ArtistFollowers `json:"followers"`

	// ExternalURLs maps service name to external URL (e.g. "spotify" → URL).
	ExternalURLs map[string]string `json:"external_urls"`
}

FullArtist represents a Spotify artist with full details, as returned by the top-artists and search endpoints. It extends the basic Artist struct with genre, popularity, followers, and external URL fields.

type GatewayEvent

type GatewayEvent struct {
	// Timestamp is when the event occurred.
	Timestamp time.Time
	// Kind classifies the event.
	Kind EventKind
	// RequestID links events for the same request (0 for internal events).
	RequestID uint64
	// Method is the HTTP method (empty for internal events).
	Method string
	// Path is the API path, e.g. "/me/player" (empty for internal events).
	Path string
	// Priority is Interactive or Background (zero value for internal events).
	Priority RequestPriority
	// StatusCode is the HTTP response status (only set on EventHttpCompleted).
	StatusCode int
	// DurationMs is the HTTP round-trip time (only set on EventHttpCompleted).
	DurationMs int64
	// Snapshot is the gateway's state at this exact moment.
	Snapshot GatewayStateSnapshot
}

GatewayEvent records a single gateway lifecycle event with a snapshot of the gateway's state at the exact moment the event occurred. Events are stored in a ring buffer and replayed by the UI at human-observable speed.

For request-scoped events, RequestID links all events belonging to the same request. For internal events (TokenRefilled, BackoffExpired), RequestID is 0.

type GatewayEventRecorder

type GatewayEventRecorder interface {
	RecordEvent(event GatewayEvent)
}

GatewayEventRecorder records gateway lifecycle events. Implemented by *state.Store.

type GatewayStateSnapshot

type GatewayStateSnapshot struct {
	// TokensAvailable is the token bucket level at this moment (0–10).
	TokensAvailable int
	// TokensMax is the token bucket capacity (always 10).
	TokensMax int
	// ConcurrentActive is the number of in-flight requests holding semaphore slots.
	ConcurrentActive int
	// ConcurrentMax is the semaphore capacity (always 5).
	ConcurrentMax int
	// BackoffRemaining is seconds until the 429 backoff clears (0 if not throttled).
	BackoffRemaining float64
	// DedupWaiters is the number of in-flight GET requests in the dedup map.
	DedupWaiters int
	// InFlightKeys lists string descriptions of currently in-flight GET requests.
	InFlightKeys []string
}

GatewayStateSnapshot holds a frozen copy of gateway internal state at a specific moment in time. Embedded in GatewayEvent so the UI can replay state transitions without polling. Unlike GatewayState, this has no watermark fields — watermarks are replaced by the event journal itself.

type PlayHistory

type PlayHistory struct {
	// Track is the track that was played.
	Track Track `json:"track"`

	// PlayedAt is the ISO 8601 timestamp when the track was played.
	PlayedAt string `json:"played_at"`
}

PlayHistory represents a recently played track item, as returned by GET /me/player/recently-played.

type PlayOffset

type PlayOffset struct {
	// URI is the Spotify track URI to start from within the context.
	URI string `json:"uri,omitempty"`
}

PlayOffset specifies where within a context to start playback.

type PlayOptions

type PlayOptions struct {
	// ContextURI is a Spotify URI for an album, playlist, or artist context.
	ContextURI string `json:"context_uri,omitempty"`

	// URIs is a list of Spotify track URIs to play directly.
	URIs []string `json:"uris,omitempty"`

	// Offset specifies where within the context to start playback.
	// When non-nil, playback starts at the given track URI within the context.
	Offset *PlayOffset `json:"offset,omitempty"`
}

PlayOptions specifies what to play. Provide ContextURI + Offset for collections (albums, playlists, liked songs). Provide URIs for an explicit ordered track list with no collection context.

type PlaybackState

type PlaybackState struct {
	// IsPlaying indicates whether Spotify is actively playing audio.
	IsPlaying bool `json:"is_playing"`

	// ProgressMs is the current playback position in milliseconds.
	ProgressMs int `json:"progress_ms"`

	// ShuffleState indicates whether shuffle is enabled.
	ShuffleState bool `json:"shuffle_state"`

	// RepeatState is one of "off", "context", or "track".
	RepeatState string `json:"repeat_state"`

	// Item is the currently playing track. May be nil if nothing is playing.
	Item *Track `json:"item"`

	// Device is the currently active playback device. May be nil if no device.
	Device *Device `json:"device"`
}

PlaybackState represents the full playback state returned by GET /me/player. When Spotify returns 204 (nothing playing), this struct is nil in the store.

type QueueResponse

type QueueResponse struct {
	// CurrentlyPlaying is the track currently playing (may be zero-value if nothing is playing).
	CurrentlyPlaying Track `json:"currently_playing"`

	// Queue contains the upcoming tracks in the user's play queue.
	Queue []Track `json:"queue"`
}

QueueResponse represents the response from GET /me/player/queue. It contains the currently playing track and the list of queued tracks.

type RequestPriority

type RequestPriority int

RequestPriority classifies a request so the gateway can apply different policies.

const (
	// PriorityBackground is for polling, pre-fetch, and any non-user-initiated request.
	PriorityBackground RequestPriority = iota
	// PriorityInteractive is for requests triggered by user key presses.
	PriorityInteractive
)

type SavedAlbum

type SavedAlbum struct {
	// AddedAt is the ISO 8601 timestamp when the album was saved.
	AddedAt string `json:"added_at"`

	// Album contains the full album details.
	Album FullAlbum `json:"album"`
}

SavedAlbum represents an album saved in the user's library, as returned by GET /me/albums.

type SavedTrack

type SavedTrack struct {
	// AddedAt is the ISO 8601 timestamp when the track was saved.
	AddedAt string `json:"added_at"`

	// Track contains the full track details.
	Track Track `json:"track"`
}

SavedTrack represents a track saved in the user's library, as returned by GET /me/tracks.

type SearchAlbum

type SearchAlbum struct {
	// ID is the Spotify album ID.
	ID string `json:"id"`

	// Name is the display name of the album.
	Name string `json:"name"`

	// URI is the Spotify URI of the album.
	URI string `json:"uri"`

	// AlbumType is the type of album: "album", "single", or "compilation".
	AlbumType string `json:"album_type"`

	// TotalTracks is the total number of tracks in the album.
	TotalTracks int `json:"total_tracks"`

	// ReleaseDate is the release date string (e.g. "2020-03-20").
	ReleaseDate string `json:"release_date"`

	// Artists is the list of artists for this album.
	Artists []Artist `json:"artists"`
}

SearchAlbum represents an album returned in a search result.

type SearchAlbumsResult

type SearchAlbumsResult struct {
	// Items is the list of matching albums.
	Items []SearchAlbum `json:"items"`

	// Total is the total number of matching albums.
	Total int `json:"total"`
}

SearchAlbumsResult holds the albums section of a search response.

type SearchArtist

type SearchArtist struct {
	// ID is the Spotify artist ID.
	ID string `json:"id"`

	// Name is the display name of the artist.
	Name string `json:"name"`

	// URI is the Spotify URI of the artist.
	URI string `json:"uri"`

	// Genres is the list of musical genres associated with this artist.
	// Populated via custom UnmarshalJSON — the json tag is not used by encoding/json.
	Genres []string `json:"-"`

	// Followers is the total follower count for this artist.
	// Populated from the nested "followers.total" field via custom UnmarshalJSON.
	Followers int `json:"-"`

	// Popularity is the artist's popularity score (0–100).
	// Populated via custom UnmarshalJSON — the json tag is not used by encoding/json.
	Popularity int `json:"-"`
}

SearchArtist represents an artist returned in a search result. NOTE: UnmarshalJSON is required because the Spotify API nests follower count under "followers.total" rather than exposing it as a flat field.

func (*SearchArtist) UnmarshalJSON

func (a *SearchArtist) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom unmarshaling to extract the nested followers.total into the flat Followers field.

type SearchArtistsResult

type SearchArtistsResult struct {
	// Items is the list of matching artists.
	Items []SearchArtist `json:"items"`

	// Total is the total number of matching artists.
	Total int `json:"total"`
}

SearchArtistsResult holds the artists section of a search response.

type SearchPlaylist

type SearchPlaylist struct {
	// ID is the Spotify playlist ID.
	ID string `json:"id"`

	// Name is the display name of the playlist.
	Name string `json:"name"`

	// URI is the Spotify URI of the playlist.
	URI string `json:"uri"`

	// Owner is the playlist owner.
	Owner SimplePlaylistOwner `json:"owner"`

	// TrackCount is the total number of tracks in the playlist.
	// Populated from the nested "tracks.total" field in the Spotify response.
	TrackCount int `json:"-"`

	// Description is the playlist description text.
	Description string `json:"-"`
}

SearchPlaylist represents a playlist returned in a search result. NOTE: SearchPlaylist uses the same nested tracks.total pattern as SimplePlaylist but is a separate type to avoid coupling search results to library types.

func (*SearchPlaylist) UnmarshalJSON

func (p *SearchPlaylist) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom unmarshaling to extract the nested tracks.total into the flat TrackCount field, mirroring the pattern used by SimplePlaylist.

type SearchPlaylistsResult

type SearchPlaylistsResult struct {
	// Items is the list of matching playlists.
	Items []SearchPlaylist `json:"items"`

	// Total is the total number of matching playlists.
	Total int `json:"total"`
}

SearchPlaylistsResult holds the playlists section of a search response.

type SearchResult

type SearchResult struct {
	// Tracks contains the matching tracks.
	Tracks SearchTracksResult `json:"tracks"`

	// Artists contains the matching artists.
	Artists SearchArtistsResult `json:"artists"`

	// Albums contains the matching albums.
	Albums SearchAlbumsResult `json:"albums"`

	// Playlists contains the matching playlists.
	Playlists SearchPlaylistsResult `json:"playlists"`
}

SearchResult contains results for all four search categories returned by the Spotify search API.

type SearchTracksResult

type SearchTracksResult struct {
	// Items is the list of matching tracks.
	Items []Track `json:"items"`

	// Total is the total number of matching tracks.
	Total int `json:"total"`
}

SearchTracksResult holds the tracks section of a search response.

type SimplePlaylist

type SimplePlaylist struct {
	// ID is the Spotify playlist ID.
	ID string `json:"id"`

	// Name is the display name of the playlist.
	Name string `json:"name"`

	// URI is the Spotify URI of the playlist.
	URI string `json:"uri"`

	// TrackCount is the total number of tracks in the playlist.
	// Populated from the nested "tracks.total" field in the Spotify response.
	TrackCount int `json:"-"`

	// Owner is the playlist owner.
	Owner SimplePlaylistOwner `json:"owner"`
}

SimplePlaylist represents a simplified Spotify playlist as returned in the GET /me/playlists response items. NOTE: UnmarshalJSON is required because the Spotify API nests track count under "tracks.total" rather than exposing it as a flat field.

func (*SimplePlaylist) UnmarshalJSON

func (p *SimplePlaylist) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom unmarshaling to extract the nested tracks.total into the flat TrackCount field.

type SimplePlaylistOwner

type SimplePlaylistOwner struct {
	// ID is the Spotify user ID of the owner.
	ID string `json:"id"`

	// DisplayName is the human-readable name of the owner.
	DisplayName string `json:"display_name"`
}

SimplePlaylistOwner represents the owner of a playlist.

type Track

type Track struct {
	// ID is the Spotify track ID.
	ID string `json:"id"`

	// Name is the display name of the track.
	Name string `json:"name"`

	// URI is the Spotify URI of the track (e.g. "spotify:track:...").
	URI string `json:"uri"`

	// DurationMs is the total duration of the track in milliseconds.
	DurationMs int `json:"duration_ms"`

	// Artists is the list of artists for this track.
	Artists []Artist `json:"artists"`

	// Album is the album this track belongs to.
	Album Album `json:"album"`

	// Explicit indicates whether the track contains explicit content.
	Explicit bool `json:"explicit"`
}

Track represents a Spotify track item returned in the playback state.

type UserProfile

type UserProfile struct {
	// ID is the Spotify user ID. Used to distinguish owned vs followed playlists.
	ID string `json:"id"`

	// DisplayName is the user's Spotify display name.
	DisplayName string `json:"display_name"`

	// Product is the subscription tier: "premium" or "free".
	Product string `json:"product"`

	// Country is the ISO 3166-1 alpha-2 country code (e.g. "DE").
	Country string `json:"country"`
}

UserProfile represents the authenticated user's Spotify profile, as returned by GET /v1/me.

Jump to

Keyboard shortcuts

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