Help us shape the future of Go! Take the 2026 Go Developer Survey

store

package
v0.16.3 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAdminRequired    = errors.New("administrator access is required")
	ErrCannotDeleteSelf = errors.New("you cannot delete your own account")
	ErrLastAdmin        = errors.New("the last administrator cannot be deleted")
	ErrInvalidUsername  = errors.New("username must be 3-32 characters using letters, numbers, dots, underscores, or hyphens")
	ErrUsernameTaken    = errors.New("that username is already in use")
)

Functions

This section is empty.

Types

type AdminArtist

type AdminArtist struct {
	ID   int64
	Name string
	MBID string
}

type AdminDeliveryHistory

type AdminDeliveryHistory struct {
	UserEmail   string
	Title       string
	Body        string
	EventType   string
	Destination string
	Service     string
	Status      string
	Attempts    int
	LastError   string
	CreatedAt   time.Time
	NextAttempt *time.Time
	SentAt      *time.Time
}

type AdminUser

type AdminUser struct {
	ID               int64
	Email            string
	Username         string
	Role             string
	Timezone         string
	ReminderTime     string
	FollowCount      int
	DestinationCount int
	CreatedAt        time.Time
}

type Artist

type Artist struct {
	ID                 int64
	MBID               string
	Name               string
	SortName           string
	Type               string
	Country            string
	Disambiguation     string
	SpotifyID          string
	SpotifyURL         string
	SpotifyImageURL    string
	Genres             []string
	ListenCount        int64
	ListenUsers        int64
	ListenCheckedAt    *time.Time
	LastCheckedAt      *time.Time
	SpotifyNextCheckAt *time.Time
	BaselineSynced     bool
}

type ArtistBreakdown added in v0.15.0

type ArtistBreakdown struct {
	Label string
	Count int
}

type ArtistResolution

type ArtistResolution struct {
	ID          int64
	UserID      int64
	Provider    string
	ProviderID  string
	DisplayName string
	ProviderURL string
	ImageURL    string
	Status      string
	Candidates  []ResolutionCandidate
	Attempts    int
	NextAttempt *time.Time
	LastError   string
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

type Delivery

type Delivery struct {
	ID           int64
	EventID      int64
	Destination  Destination
	Title        string
	Body         string
	Attempts     int
	NextAttempt  time.Time
	EventType    string
	ReleaseTitle string
}

type DeliveryHistory

type DeliveryHistory struct {
	Title       string
	EventType   string
	Destination string
	Status      string
	Attempts    int
	LastError   string
	CreatedAt   time.Time
	SentAt      *time.Time
}

type Destination

type Destination struct {
	ID           int64
	UserID       int64
	Name         string
	Service      string
	EncryptedURL []byte
	Enabled      bool
}

type ITunesArtworkArtist added in v0.12.1

type ITunesArtworkArtist struct {
	ID       int64
	Name     string
	Attempts int
}

ITunesArtworkArtist identifies one artist whose existing iTunes releases are due for an artwork-only refresh. Artwork backfills deliberately operate on existing rows and never create releases or notification events.

type ImportInput

type ImportInput struct {
	SourceValue string
	DisplayName string
	MBID        string
	MBURL       string
	SpotifyID   string
	SpotifyURL  string
	Reason      string
}

ImportInput is a validated ArtistTrackarr export row. Validation belongs to the web package; the store deliberately accepts only the canonical fields needed to create a local artist and follow.

type ImportJob

type ImportJob struct {
	ID              int64
	UserID          int64
	CreatedAt       time.Time
	Rows            []ImportRow
	Added           int
	AlreadyFollowed int
	Invalid         int
}

ImportJob is the owner-scoped record for one CSV upload.

type ImportRow

type ImportRow struct {
	ID          int64
	JobID       int64
	SourceValue string
	DisplayName string
	Status      string
	ArtistID    *int64
	Reason      string
}

ImportRow records the independent result for one CSV data row.

type ListenBrainzStats added in v0.15.0

type ListenBrainzStats struct {
	ArtistID         int64
	MBID             string
	TotalListenCount int64
	TotalUserCount   int64
	CheckedAt        *time.Time
	NextCheckAt      *time.Time
	LastError        string
}

type MaintenanceStats

type MaintenanceStats struct {
	Sessions      int64
	AuthTokens    int64
	LoginAttempts int64
	ManualSyncs   int64
	ImportJobs    int64
}

PruneExpiredState removes only expired or completed transient state. It deliberately leaves active sessions, current login blocks, queued work, and notification/delivery history untouched.

type ManualSyncRequest

type ManualSyncRequest struct {
	ID          int64
	RequestedBy int64
	Scope       string
	ArtistID    *int64
	Status      string
	CreatedAt   time.Time
	StartedAt   *time.Time
	FinishedAt  *time.Time
	LastError   string
}

type NotificationPreferences

type NotificationPreferences struct {
	UserID        int64
	Albums        bool
	EPs           bool
	Singles       bool
	Announcements bool
	ReleaseDay    bool
}

type ProviderHealth

type ProviderHealth struct {
	Provider      string
	LastSuccessAt *time.Time
	LastFailureAt *time.Time
	LastError     string
	NextCheckAt   *time.Time
	RateLimited   bool
	QuotaExceeded bool
	UpdatedAt     time.Time
}

type Release

type Release struct {
	ID               int64
	MBID             string
	ArtistID         int64
	ArtistName       string
	Title            string
	PrimaryType      string
	SecondaryTypes   []string
	FirstReleaseDate string
	DatePrecision    int
	MusicBrainzURL   string
	SpotifyID        string
	SpotifyURL       string
	SpotifyImageURL  string
	ITunesID         string
	ITunesURL        string
	ITunesArtworkURL string
	Source           string
	FirstObservedAt  time.Time
}

type ReleaseBatch

type ReleaseBatch struct {
	Provider string
	Releases []Release
}

type ReleaseDetail

type ReleaseDetail struct {
	Release
	Observations []ReleaseObservation
}

type ReleaseObservation

type ReleaseObservation struct {
	Provider   string
	ProviderID string
	ObservedAt time.Time
}

type ResolutionCandidate

type ResolutionCandidate struct {
	MBID           string   `json:"mbid"`
	Name           string   `json:"name"`
	SortName       string   `json:"sort_name"`
	Type           string   `json:"type"`
	Country        string   `json:"country"`
	Disambiguation string   `json:"disambiguation"`
	Aliases        []string `json:"aliases,omitempty"`
	Genres         []string `json:"genres,omitempty"`
	Score          int      `json:"score"`
}

func (ResolutionCandidate) Artist

func (c ResolutionCandidate) Artist() Artist

type Session

type Session struct {
	User      User
	CSRFToken string
	ExpiresAt time.Time
}

type SpotifyPollingState

type SpotifyPollingState struct {
	UnchangedChecks int
	LastChangeAt    *time.Time
}

type Store

type Store struct{ DB *sql.DB }

func Open

func Open(path string) (*Store, error)

func (*Store) AddDestination

func (s *Store) AddDestination(ctx context.Context, userID int64, name, service string, encrypted []byte) error

func (*Store) AdminArtists

func (s *Store) AdminArtists(ctx context.Context) ([]AdminArtist, error)

func (*Store) AdminDeliveryHistory

func (s *Store) AdminDeliveryHistory(ctx context.Context, limit, offset int) ([]AdminDeliveryHistory, error)

func (*Store) AdminDeliveryHistoryCount

func (s *Store) AdminDeliveryHistoryCount(ctx context.Context) (int, error)

func (*Store) AdminUsers

func (s *Store) AdminUsers(ctx context.Context) ([]AdminUser, error)

func (*Store) ApplicationLogs

func (s *Store) ApplicationLogs(ctx context.Context, limit int) ([]logging.Entry, error)

func (*Store) ApplyITunesArtworkBackfill added in v0.12.1

func (s *Store) ApplyITunesArtworkBackfill(ctx context.Context, artistID int64, releases []Release, observed time.Time) (checked, updated int, err error)

ApplyITunesArtworkBackfill updates only already persisted release rows. A successful response without artwork receives a long negative-cache period; it does not affect normal catalog scheduling or notifications.

func (*Store) ApplyReleaseBatches

func (s *Store) ApplyReleaseBatches(ctx context.Context, artist Artist, batches []ReleaseBatch, observed time.Time) error

func (*Store) ApplyReleaseSync

func (s *Store) ApplyReleaseSync(ctx context.Context, artist Artist, releases []Release, observed time.Time) error

func (*Store) ArtistByID

func (s *Store) ArtistByID(ctx context.Context, id int64) (Artist, error)

func (*Store) ArtistByMBID

func (s *Store) ArtistByMBID(ctx context.Context, mbid string) (Artist, error)

func (*Store) ArtistGenres added in v0.15.0

func (s *Store) ArtistGenres(ctx context.Context, artistID int64) ([]string, error)

func (*Store) ArtistResolution

func (s *Store) ArtistResolution(ctx context.Context, userID, resolutionID int64) (ArtistResolution, error)

func (*Store) ArtistResolutions

func (s *Store) ArtistResolutions(ctx context.Context, userID int64) ([]ArtistResolution, error)

func (*Store) ArtistsDue

func (s *Store) ArtistsDue(ctx context.Context, now time.Time, limit int) ([]Artist, error)

func (*Store) CancelArtistResolution

func (s *Store) CancelArtistResolution(ctx context.Context, userID, resolutionID int64) error

func (*Store) ClaimManualSyncRequests

func (s *Store) ClaimManualSyncRequests(ctx context.Context, limit int) ([]ManualSyncRequest, error)

func (*Store) ClearLoginFailures

func (s *Store) ClearLoginFailures(ctx context.Context, key string)

func (*Store) Close

func (s *Store) Close() error

func (*Store) CompleteArtistResolution

func (s *Store) CompleteArtistResolution(ctx context.Context, resolution ArtistResolution, artist Artist) (Artist, bool, error)

func (*Store) CompleteManualSyncRequest

func (s *Store) CompleteManualSyncRequest(ctx context.Context, id int64, syncErr error) error

func (*Store) ConsumeAuthToken

func (s *Store) ConsumeAuthToken(ctx context.Context, raw, kind string) (email string, userID *int64, err error)

func (*Store) CreateArtistResolution

func (s *Store) CreateArtistResolution(ctx context.Context, userID int64, args ...string) (ArtistResolution, bool, error)

CreateArtistResolution accepts the legacy Spotify argument list (providerID, name, URL, imageURL) and the generalized provider-aware list (provider, providerID, name, URL, imageURL). Keeping the legacy form source-compatible lets existing integrations upgrade without a flag day.

func (*Store) CreateArtistResolutionForProvider

func (s *Store) CreateArtistResolutionForProvider(ctx context.Context, userID int64, provider, providerID, name, providerURL, imageURL string) (ArtistResolution, bool, error)

func (*Store) CreateAuthToken

func (s *Store) CreateAuthToken(ctx context.Context, kind, email string, userID *int64, creator int64, ttl time.Duration) (string, error)

func (*Store) CreateImportJob

func (s *Store) CreateImportJob(ctx context.Context, userID int64) (ImportJob, error)

func (*Store) CreateManualSyncRequest

func (s *Store) CreateManualSyncRequest(ctx context.Context, userID int64, scope string, artistID *int64) (ManualSyncRequest, error)

func (*Store) CreateSession

func (s *Store) CreateSession(ctx context.Context, userID int64, ttl time.Duration) (raw, csrf string, err error)

func (*Store) CreateUser

func (s *Store) CreateUser(ctx context.Context, email, hash, role, timezone string, usernames ...string) (int64, error)

CreateUser accepts an optional username to keep internal callers and integrations built against earlier versions source-compatible. When omitted or empty, a deterministic username is generated from the email address.

func (*Store) CreateUserFromInvite added in v0.16.0

func (s *Store) CreateUserFromInvite(ctx context.Context, raw, hash, username, timezone string) error

CreateUserFromInvite consumes an invitation and creates its account in one transaction. Validation and uniqueness failures therefore leave the token available for correction and retry.

func (*Store) DashboardReleases

func (s *Store) DashboardReleases(
	ctx context.Context, userID int64, today string, limit int,
) (upcoming []Release, recent []Release, err error)

func (*Store) DeleteDestination

func (s *Store) DeleteDestination(ctx context.Context, userID, id int64) error

func (*Store) DeleteSession

func (s *Store) DeleteSession(ctx context.Context, raw string) error

func (*Store) DeleteUser

func (s *Store) DeleteUser(ctx context.Context, actingAdminID, userID int64) error

func (*Store) DeliveryHistory

func (s *Store) DeliveryHistory(ctx context.Context, userID int64, limit int) ([]DeliveryHistory, error)

func (*Store) Destination

func (s *Store) Destination(ctx context.Context, userID, id int64) (Destination, error)

func (*Store) Destinations

func (s *Store) Destinations(ctx context.Context, userID int64) ([]Destination, error)

func (*Store) DueArtistResolutions

func (s *Store) DueArtistResolutions(ctx context.Context, now time.Time, limit int) ([]ArtistResolution, error)

func (*Store) DueDeliveries

func (s *Store) DueDeliveries(ctx context.Context, now time.Time, limit int) ([]Delivery, error)

func (*Store) DueITunesArtworkArtist added in v0.12.1

func (s *Store) DueITunesArtworkArtist(ctx context.Context, now time.Time) (ITunesArtworkArtist, bool, error)

DueITunesArtworkArtist returns at most one artist per call so the background runner can spread artwork requests over time and respect Apple's limiter.

func (*Store) DueListenBrainzArtists added in v0.15.0

func (s *Store) DueListenBrainzArtists(ctx context.Context, now time.Time, limit int) ([]Artist, error)

func (*Store) EnqueueEvent

func (s *Store) EnqueueEvent(ctx context.Context, userID, releaseID int64, eventType, title, body string, now time.Time) error

func (*Store) Follow

func (s *Store) Follow(ctx context.Context, userID, artistID int64) (bool, error)

func (*Store) FollowedArtistCount

func (s *Store) FollowedArtistCount(ctx context.Context, userID int64) (int, error)

func (*Store) FollowedArtists

func (s *Store) FollowedArtists(ctx context.Context, userID int64) ([]Artist, error)

func (*Store) FollowedArtistsFiltered added in v0.15.0

func (s *Store) FollowedArtistsFiltered(ctx context.Context, userID int64, genre, country, artistType string) ([]Artist, error)

func (*Store) FollowedBreakdown added in v0.15.0

func (s *Store) FollowedBreakdown(ctx context.Context, userID int64, dimension string) ([]ArtistBreakdown, error)

func (*Store) Healthy

func (s *Store) Healthy(ctx context.Context) error

func (*Store) ImportJob

func (s *Store) ImportJob(ctx context.Context, userID, jobID int64) (ImportJob, error)

func (*Store) InsertApplicationLog

func (s *Store) InsertApplicationLog(ctx context.Context, entry logging.Entry) error

func (*Store) IsFollowing

func (s *Store) IsFollowing(ctx context.Context, userID, artistID int64) (bool, error)

func (*Store) LatestSpotifyReleaseDate

func (s *Store) LatestSpotifyReleaseDate(ctx context.Context, artistID int64) (string, error)

func (*Store) LoginAllowed

func (s *Store) LoginAllowed(ctx context.Context, key string) (bool, error)

func (*Store) ManualSyncRequests

func (s *Store) ManualSyncRequests(ctx context.Context, limit int) ([]ManualSyncRequest, error)

func (*Store) MarkAllArtistsDue

func (s *Store) MarkAllArtistsDue(ctx context.Context) error

func (*Store) MarkArtistChecked

func (s *Store) MarkArtistChecked(ctx context.Context, artistID int64, now time.Time, interval time.Duration) error

func (*Store) MarkArtistResolutionReview

func (s *Store) MarkArtistResolutionReview(ctx context.Context, userID, resolutionID int64, candidates []ResolutionCandidate) error

func (*Store) MarkDeliveryFailed

func (s *Store) MarkDeliveryFailed(ctx context.Context, id int64, attempts int, message string, now time.Time) error

func (*Store) MarkDeliverySent

func (s *Store) MarkDeliverySent(ctx context.Context, id int64, now time.Time) error

func (*Store) MarkSpotifyChecked

func (s *Store) MarkSpotifyChecked(ctx context.Context, artistID int64, now time.Time, interval time.Duration) error

func (*Store) MarkSpotifyCheckedAdaptive

func (s *Store) MarkSpotifyCheckedAdaptive(ctx context.Context, artistID int64, now time.Time, interval time.Duration, changed, upcoming bool) error

func (*Store) NotificationPreferences

func (s *Store) NotificationPreferences(ctx context.Context, userID int64) (NotificationPreferences, error)

func (*Store) ProviderHealth

func (s *Store) ProviderHealth(ctx context.Context) ([]ProviderHealth, error)

func (*Store) ProviderHealthByName

func (s *Store) ProviderHealthByName(ctx context.Context, provider string) (ProviderHealth, error)

ProviderHealthByName returns the persisted state for one provider. The scheduler uses the next check time to carry a provider-wide cooldown across process restarts, so a quota response cannot cause a fresh burst of calls after the container is recreated.

func (*Store) PruneApplicationLogs

func (s *Store) PruneApplicationLogs(ctx context.Context, before time.Time) error

func (*Store) PruneExpiredState

func (s *Store) PruneExpiredState(ctx context.Context, now time.Time) (MaintenanceStats, error)

func (*Store) QueueDueReleaseDays

func (s *Store) QueueDueReleaseDays(ctx context.Context, now time.Time) error

func (*Store) RecentReleases

func (s *Store) RecentReleases(ctx context.Context, userID int64, limit int) ([]Release, error)

func (*Store) RecordLoginFailure

func (s *Store) RecordLoginFailure(ctx context.Context, key string) error

func (*Store) ReleaseDetail

func (s *Store) ReleaseDetail(ctx context.Context, userID, releaseID int64) (ReleaseDetail, error)

func (*Store) RenameDestination

func (s *Store) RenameDestination(ctx context.Context, userID, destinationID int64, name string) error

func (*Store) RetryArtistResolution

func (s *Store) RetryArtistResolution(ctx context.Context, userID, resolutionID int64, attempts int, next time.Time, message string) error

func (*Store) SaveArtistGenres added in v0.15.0

func (s *Store) SaveArtistGenres(ctx context.Context, artistID int64, genres []string) error

func (*Store) SaveImportRow

func (s *Store) SaveImportRow(ctx context.Context, userID, jobID int64, input ImportInput) (ImportRow, error)

SaveImportRow persists one row and, for valid input, creates or reuses the canonical artist and owner-scoped follow in the same transaction. This makes partial uploads durable without coupling them to provider availability.

func (*Store) SaveListenBrainzStats added in v0.15.0

func (s *Store) SaveListenBrainzStats(ctx context.Context, stats map[int64]ListenBrainzStats, now, next time.Time) error

func (*Store) ScheduleArtistCheck

func (s *Store) ScheduleArtistCheck(ctx context.Context, artistID int64, next time.Time) error

func (*Store) ScheduleITunesArtworkRetry added in v0.12.1

func (s *Store) ScheduleITunesArtworkRetry(ctx context.Context, artistID int64, next time.Time) error

ScheduleITunesArtworkRetry applies a bounded durable retry time to all existing artwork gaps for an artist after a transient provider failure.

func (*Store) ScheduleListenBrainzRetry added in v0.15.0

func (s *Store) ScheduleListenBrainzRetry(ctx context.Context, artistIDs []int64, next time.Time, message string) error

func (*Store) ScheduleSpotifyCheck

func (s *Store) ScheduleSpotifyCheck(ctx context.Context, artistID int64, next time.Time) error

func (*Store) Session

func (s *Store) Session(ctx context.Context, raw string) (Session, error)

func (*Store) SpotifyBatchChanged

func (s *Store) SpotifyBatchChanged(ctx context.Context, releases []Release) (bool, error)

SpotifyBatchChanged reports whether a successful provider response contains a release that is new or has changed since it was last observed. It is intentionally read before the release transaction so the scheduler can persist its adaptive state together with the completed observation.

func (*Store) SpotifyPollingState

func (s *Store) SpotifyPollingState(ctx context.Context, artistID int64) (SpotifyPollingState, error)

func (*Store) TopListenBrainzArtists added in v0.15.0

func (s *Store) TopListenBrainzArtists(ctx context.Context, userID int64, limit int) ([]Artist, error)

func (*Store) Unfollow

func (s *Store) Unfollow(ctx context.Context, userID, artistID int64) error

func (*Store) UpdateNotificationPreferences

func (s *Store) UpdateNotificationPreferences(ctx context.Context, p NotificationPreferences) error

func (*Store) UpdatePassword

func (s *Store) UpdatePassword(ctx context.Context, userID int64, hash string) error

func (*Store) UpdateProfile

func (s *Store) UpdateProfile(ctx context.Context, userID int64, timezone, reminder string, usernames ...string) error

func (*Store) UpsertArtist

func (s *Store) UpsertArtist(ctx context.Context, a Artist) (Artist, error)

func (*Store) UpsertProviderHealth

func (s *Store) UpsertProviderHealth(ctx context.Context, provider string, success bool, next *time.Time, rateLimited, quota bool, lastError string) error

func (*Store) UserByEmail

func (s *Store) UserByEmail(ctx context.Context, email string) (User, error)

func (*Store) UserByID

func (s *Store) UserByID(ctx context.Context, id int64) (User, error)

func (*Store) UserCount

func (s *Store) UserCount(ctx context.Context) (int, error)

type User

type User struct {
	ID           int64
	Email        string
	Username     string
	PasswordHash string
	Role         string
	Timezone     string
	ReminderTime string
	CreatedAt    time.Time
}

Jump to

Keyboard shortcuts

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