radio

package module
v0.0.0-...-fd00b2c Latest Latest
Warning

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

Go to latest
Published: Apr 4, 2024 License: MIT Imports: 13 Imported by: 0

README

valkyrie

Go Reference Test Staticcheck

Repository of rebirth

Installation

git clone https://github.com/R-a-dio/valkyrie.git

Required

  • Go version 1.21+
  • MySQL/MariaDB

Optional

for work and running of streamer/

  • ffmpeg
  • ffprobe
  • libmp3lame-dev

for work in rpc/ and running go generate

  • protoc
  • go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
  • go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
  • go install github.com/matryer/moq@latest

Building

The project currently builds into a single executable, located in cmd/hanyuu run go build in there to acquire an executable; If you want to exclude the streamer for lack of dependencies you can run go build -tags=nostreamer to exclude it from building.

Configuration

an example configuration file is included as example.toml. Other documentation on valid configuration values are located in config/config.go. The executable looks for a configuration file in multiple locations:

  • the current working directory named hanyuu.toml
  • the flag -config given to the executable
  • the environment variable HANYUU_CONFIG which can either be a relative or absolute path

You can also run hanyuu config to see what the currently loaded configuration looks like, the output is a valid TOML file so can also be piped into a file if so desired

Documentation

Index

Constants

View Source
const (
	LimitArtistLength = 500
	LimitAlbumLength  = 200
	LimitTitleLength  = 200
	LimitReasonLength = 120
)
View Source
const (
	PermActive         = "active"          // User is active
	PermNews           = "news"            // User has news creation/editing access
	PermDJ             = "dj"              // User has access to the icecast proxy
	PermDev            = "dev"             // User is a developer
	PermAdmin          = "admin"           // User is an administrator
	PermDatabaseDelete = "database_delete" // User can delete from the track database
	PermDatabaseEdit   = "database_edit"   // User can edit the track database
	PermDatabaseView   = "database_view"   // User can view the track database
	PermPendingEdit    = "pending_edit"    // User can edit the pending track queue
	PermPendingView    = "pending_view"    // User can view the pending track queue
)

List of permissions, this should be kept in sync with the database version

Variables

This section is empty.

Functions

func CalculateCooldown

func CalculateCooldown(delay time.Duration, last time.Time) (time.Duration, bool)

CalculateCooldown sees if the cooldown given has passed since `last` and returns the remaining time if any and a bool indicating if it has passed since then or not. It always returns true if `last` is zero.

func CalculateRequestDelay

func CalculateRequestDelay(requestCount int) time.Duration

CalculateRequestDelay returns the delay between two requests of a song

func CalculateSubmissionCooldown

func CalculateSubmissionCooldown(t time.Time) time.Duration

func GenerateHashFromPassword

func GenerateHashFromPassword(passwd string) (string, error)

func Metadata

func Metadata(artist, title string) string

Types

type AnnounceService

type AnnounceService interface {
	AnnounceSong(context.Context, Status) error
	AnnounceRequest(context.Context, Song) error
}

type DJ

type DJ struct {
	ID    DJID
	Name  string
	Regex string

	Text  string
	Image string

	Visible  bool
	Priority int
	Role     string

	CSS   string
	Color string
	Theme Theme
}

DJ is someone that has access to streaming

type DJID

type DJID uint64

DJID is an identifier corresponding to a dj

func ParseDJID

func ParseDJID(s string) (DJID, error)

func (DJID) String

func (id DJID) String() string

type DatabaseTrack

type DatabaseTrack struct {
	TrackID TrackID

	Artist   string
	Title    string
	Album    string
	FilePath string
	Tags     string

	Acceptor   string
	LastEditor string

	Priority        int
	Usable          bool
	NeedReplacement bool

	LastRequested time.Time

	RequestCount int
}

DatabaseTrack is a song we have the actual audio file for and is available to the automated streamer

func (*DatabaseTrack) HasTrack

func (t *DatabaseTrack) HasTrack() bool

HasTrack returns true if t != nil, can be used as Song.HasTrack to check if a track was allocated for the embedded field

type Listeners

type Listeners = int64

type ManagerService

type ManagerService interface {
	CurrentUser(context.Context) (eventstream.Stream[*User], error)
	UpdateUser(context.Context, *User) error
	CurrentSong(context.Context) (eventstream.Stream[*SongUpdate], error)
	UpdateSong(context.Context, *SongUpdate) error
	CurrentThread(context.Context) (eventstream.Stream[Thread], error)
	UpdateThread(context.Context, Thread) error
	CurrentListeners(context.Context) (eventstream.Stream[Listeners], error)
	UpdateListeners(context.Context, Listeners) error

	CurrentStatus(context.Context) (eventstream.Stream[Status], error)
}

type NewsComment

type NewsComment struct {
	ID         NewsCommentID
	PostID     NewsPostID
	Body       string
	Identifier string

	// Optional, only filled if an account-holder comments
	UserID    *UserID
	User      *User
	DeletedAt *time.Time
	CreatedAt time.Time
	UpdatedAt *time.Time
}

NewsComment is a single comment under a news post on the website

type NewsCommentID

type NewsCommentID uint64

NewsCommentID is an identifier for a news comment

func ParseNewsCommentID

func ParseNewsCommentID(s string) (NewsCommentID, error)

func (NewsCommentID) String

func (id NewsCommentID) String() string

type NewsList

type NewsList struct {
	Entries []NewsPost
	Total   int
}

NewsList contains multiple news posts and a total count of posts

type NewsPost

type NewsPost struct {
	ID     NewsPostID
	Title  string
	Header string
	Body   string

	User      User
	DeletedAt *time.Time
	CreatedAt time.Time
	UpdatedAt *time.Time
	Private   bool
}

NewsPost is a single news post created on the website

func (NewsPost) HasRequired

func (np NewsPost) HasRequired() (string, bool)

HasRequired tells if you all required fields in a news post are filled, returns the field name that is missing and a boolean

type NewsPostID

type NewsPostID uint64

NewsPostID is an identifier for a news post

func ParseNewsPostID

func ParseNewsPostID(s string) (NewsPostID, error)

func (NewsPostID) String

func (id NewsPostID) String() string

type NewsStorage

type NewsStorage interface {
	// Get returns the news post associated with the id given
	Get(NewsPostID) (*NewsPost, error)
	// Create creates a new news post
	//
	// Required fields to create a post are (title, header, body, user)
	Create(NewsPost) (NewsPostID, error)
	// Update updates the news post entry
	Update(NewsPost) error
	// Delete deletes a news post
	Delete(NewsPostID) error
	// List returns a list of news post starting at offset and returning up to
	// limit amount of posts, chronologically sorted by creation date
	List(limit int64, offset int64) (NewsList, error)
	// ListPublic returns the same thing as List but with deleted and private
	// posts filtered out
	ListPublic(limit int64, offset int64) (NewsList, error)
	// Comments returns all comments associated with the news post given
	Comments(NewsPostID) ([]NewsComment, error)
}

NewsStorage stores website news and its comments

type NewsStorageService

type NewsStorageService interface {
	News(context.Context) NewsStorage
	NewsTx(context.Context, StorageTx) (NewsStorage, StorageTx, error)
}

NewsStorageService is a service able to supply a NewsStorage

type PendingSong

type PendingSong struct {
	ID SubmissionID
	// Status of the song (accepted/declined/pending)
	Status SubmissionStatus
	// Artist of the song
	Artist string
	// Title of the song
	Title string
	// Album of the song
	Album string
	// Tags of the song
	Tags string
	// FilePath on disk
	FilePath string
	// Comment given by the uploader
	Comment string
	// Filename is the original filename from the uploader
	Filename string
	// UserIdentifier is the unique identifier for the uploader
	UserIdentifier string
	// SubmittedAt is the time of submission
	SubmittedAt time.Time
	// ReviewedAt tells you when the song was reviewed
	ReviewedAt time.Time
	// Duplicate indicates if this might be a duplicate
	Duplicate bool
	// ReplacementID is the TrackID that this upload will replace
	ReplacementID TrackID
	// Bitrate of the file
	Bitrate int
	// Length of the song
	Length time.Duration
	// Format of the song
	Format string
	// EncodingMode is the encoding mode used for the file
	EncodingMode string

	// Decline fields
	Reason string

	// Accepted fields
	GoodUpload   bool
	AcceptedSong *Song
}

PendingSong is a song currently awaiting approval in the pending queue

func (PendingSong) Metadata

func (p PendingSong) Metadata() string

type PostPendingID

type PostPendingID int64

func ParsePostPendingID

func ParsePostPendingID(s string) (PostPendingID, error)

func (PostPendingID) String

func (id PostPendingID) String() string

type PostPendingSong

type PostPendingSong struct {
	ID             PostPendingID
	AcceptedSong   *TrackID
	Metadata       string
	UserIdentifier string
	ReviewedAt     time.Time
	DeclineReason  *string
}

type QueueEntry

type QueueEntry struct {
	// QueueID is a unique identifier for this queue entry
	QueueID QueueID
	// Song that is queued
	Song
	// IsUserRequest should be true if this song was added to the queue
	// by a third-party user
	IsUserRequest bool
	// UserIdentifier should be a way to identify the user that requested the song
	UserIdentifier string
	// ExpectedStartTime is the expected time this song will be played on stream
	ExpectedStartTime time.Time
}

QueueEntry is a Song used in the QueueService

func (*QueueEntry) EqualTo

func (qe *QueueEntry) EqualTo(qe2 QueueEntry) bool

func (QueueEntry) String

func (qe QueueEntry) String() string

type QueueID

type QueueID struct {
	xid.ID
}

func NewQueueID

func NewQueueID() QueueID

type QueueService

type QueueService interface {
	// AddRequest requests the given song to be added to the queue, the string given
	// is an identifier of the user that requested it
	AddRequest(context.Context, Song, string) error
	// ReserveNext returns the next yet-to-be-reserved entry from the queue
	ReserveNext(context.Context) (*QueueEntry, error)
	// ResetReserved resets the reserved status of all entries returned by ReserveNext
	// but not yet removed by Remove
	ResetReserved(context.Context) error
	// Remove removes the first occurence of the given entry from the queue
	Remove(context.Context, QueueID) (bool, error)
	// Entries returns all entries in the queue
	Entries(context.Context) ([]QueueEntry, error)
}

type QueueStorage

type QueueStorage interface {
	// Store stores the queue with the name given
	Store(name string, queue []QueueEntry) error
	// Load returns the queue associated with the name given
	Load(name string) ([]QueueEntry, error)
}

QueueStorage stores a queue

type QueueStorageService

type QueueStorageService interface {
	Queue(context.Context) QueueStorage
	QueueTx(context.Context, StorageTx) (QueueStorage, StorageTx, error)
}

QueueStorageService is a service able to supply a QueueStorage

type Relay

type Relay struct {
	Name, Status, Stream, Err string
	Online, Disabled, Noredir bool
	Listeners, Max            int
}

Relay is a stream relay for use by the load balancer.

func (Relay) Score

func (r Relay) Score() float64

Score takes in a relay and returns its score. Score ranges from 0 to 1, where 1 is perfect. Score punishes a relay for having a high ratio of listeners to its max.

type RelayStorage

type RelayStorage interface {
	Update(r Relay) error
	All() ([]Relay, error)
}

RelayStorage deals with the relays table.

type RelayStorageService

type RelayStorageService interface {
	Relay(context.Context) RelayStorage
	RelayTx(context.Context, StorageTx) (RelayStorage, StorageTx, error)
}

RelayStorageService is a service able to supply a RelayStorage

type RequestStorage

type RequestStorage interface {
	// LastRequest returns the time of when the identifier given last requested
	// a song from the streamer
	LastRequest(identifier string) (time.Time, error)
	// UpdateLastRequest updates the LastRequest time to the current time for the
	// identifier given
	UpdateLastRequest(identifier string) error
}

RequestStorage stores things related to automated streamer song requests

type RequestStorageService

type RequestStorageService interface {
	Request(context.Context) RequestStorage
	RequestTx(context.Context, StorageTx) (RequestStorage, StorageTx, error)
}

RequestStorageService is a service able to supply a RequestStorage

type ScheduleDay

type ScheduleDay uint8
const (
	Monday ScheduleDay = iota
	Tuesday
	Wednesday
	Thursday
	Friday
	Saturday
	Sunday
)

func (ScheduleDay) String

func (day ScheduleDay) String() string

type ScheduleEntry

type ScheduleEntry struct {
	ID ScheduleID
	// Weekday is the day this entry is for
	Weekday ScheduleDay
	// Text is the actual body of the entry
	Text string
	// Owner is who "owns" this day for streaming rights
	Owner *User
	// UpdatedAt is when this was updated
	UpdatedAt time.Time
	// UpdatedBy is who updated this
	UpdatedBy User
	// Notification indicates if we should notify users of this entry
	Notification bool
}

type ScheduleID

type ScheduleID uint64

type ScheduleStorage

type ScheduleStorage interface {
	// Latest returns the latest version of the schedule, one entry for
	// each day in order from Monday to Sunday. entry is nil if there is
	// no schedule for that day
	Latest() ([]*ScheduleEntry, error)
	// Update updates the schedule with the entry given
	Update(ScheduleEntry) error
	// History returns the previous versions of ScheduleEntry
	History(day ScheduleDay, limit, offset int64) ([]ScheduleEntry, error)
}

type ScheduleStorageService

type ScheduleStorageService interface {
	Schedule(context.Context) ScheduleStorage
	ScheduleTx(context.Context, StorageTx) (ScheduleStorage, StorageTx, error)
}

type SearchResult

type SearchResult struct {
	Songs     []Song
	TotalHits int
}

type SearchService

type SearchService interface {
	Search(ctx context.Context, query string, limit int64, offset int64) (*SearchResult, error)
	Update(context.Context, ...Song) error
	Delete(context.Context, ...TrackID) error
}

type Session

type Session struct {
	Token  SessionToken
	Expiry time.Time

	Data []byte
}

Session is a website user session

type SessionStorage

type SessionStorage interface {
	Delete(SessionToken) error
	Get(SessionToken) (Session, error)
	Save(Session) error
}

SessionStorage stores Session's by a SessionToken

type SessionStorageService

type SessionStorageService interface {
	Sessions(context.Context) SessionStorage
	SessionsTx(context.Context, StorageTx) (SessionStorage, StorageTx, error)
}

SessionStorageService is a service that supplies a SessionStorage

type SessionToken

type SessionToken string

SessionToken is the token associated with a singular session

type Song

type Song struct {
	ID SongID
	// Hash is a sha1 of the contents of Metadata
	Hash SongHash
	// HashLink is the same as Hash but points to another song that we share some data with
	HashLink SongHash
	// Metadata is simple metadata for this song in the format 'artist - title'
	Metadata string
	// Length is the length of the song
	Length time.Duration
	// LastPlayed is the last time this song played on stream
	LastPlayed time.Time
	// LastPlayedBy is the user that last played this song, can be nil
	LastPlayedBy *User
	// DatabaseTrack is only available if the song is in our streamer database
	*DatabaseTrack

	// SyncTime is the time this Song was returned by the database layer
	SyncTime time.Time
}

Song is a song we've seen played on the stream

func NewSong

func NewSong(metadata string, length ...time.Duration) Song

func (Song) EqualTo

func (s Song) EqualTo(d Song) bool

EqualTo returns s == d based on unique fields

func (*Song) Hydrate

func (s *Song) Hydrate()

Hydrate tries to fill Song with data from other fields, mostly useful for if we have a DatabaseTrack but want to create the Song fields

func (*Song) RequestDelay

func (s *Song) RequestDelay() time.Duration

func (*Song) Requestable

func (s *Song) Requestable() bool

Requestable returns whether this song can be requested by a user

func (*Song) UntilRequestable

func (s *Song) UntilRequestable() time.Duration

UntilRequestable returns the time until this song can be requested again, returns 0 if song.Requestable() == true

type SongHash

type SongHash [sha1.Size]byte

SongHash is a sha1 hash

func NewSongHash

func NewSongHash(metadata string) SongHash

NewSongHash generates a new SongHash for the metadata passed in

func (*SongHash) IsZero

func (s *SongHash) IsZero() bool

func (SongHash) MarshalJSON

func (s SongHash) MarshalJSON() ([]byte, error)

MarshalJSON implements encoding/json.Marshaler

func (*SongHash) Scan

func (s *SongHash) Scan(src interface{}) error

Scan implements sql.Scanner

func (SongHash) String

func (s SongHash) String() string

String returns a hexadecimal representation of the song hash

func (*SongHash) UnmarshalJSON

func (s *SongHash) UnmarshalJSON(b []byte) error

UnmarshalJSON implements encoding/json.Unmarshaler

func (SongHash) Value

func (s SongHash) Value() (driver.Value, error)

Value implements sql/driver.Valuer

type SongID

type SongID uint64

SongID is a songs identifier

func ParseSongID

func ParseSongID(s string) (SongID, error)

func (*SongID) Scan

func (s *SongID) Scan(src any) error

Scan implements sql.Scanner

func (SongID) String

func (s SongID) String() string

type SongInfo

type SongInfo struct {
	// Start is the time at which the current song started playing
	Start time.Time
	// End is the expected time the current song stops playing
	End time.Time
	// IsFallback indicates if the song currently playing is one marked as a
	// fallback song for when the icecast main stream is down
	IsFallback bool
}

type SongStorage

type SongStorage interface {
	// Create creates a new song with the metadata given
	Create(Song) (*Song, error)
	// FromMetadata returns the song associated with the metadata given
	FromMetadata(metadata string) (*Song, error)
	// FromHash returns the song associated with the SongHash given
	FromHash(SongHash) (*Song, error)

	// LastPlayed returns songs that have recently played, up to amount given after
	// applying the offset
	LastPlayed(offset, amount int64) ([]Song, error)
	// LastPlayedCount returns the amount of plays recorded
	LastPlayedCount() (int64, error)
	// PlayedCount returns the amount of times the song has been played on stream
	PlayedCount(Song) (int64, error)
	// AddPlay adds a play to the song. streamer is the dj that played the song.
	// If present, ldiff is the difference in amount of listeners between
	// song-start and song-end.
	AddPlay(song Song, streamer User, ldiff *Listeners) error

	// FavoriteCount returns the amount of users that have added this song to
	// their favorite list
	FavoriteCount(Song) (int64, error)
	// Favorites returns all users that have this song on their favorite list
	Favorites(Song) ([]string, error)
	// FavoritesOf returns all songs that are on a users favorite list
	FavoritesOf(nick string, limit, offset int64) ([]Song, error)
	// AddFavorite adds the given song to nicks favorite list
	AddFavorite(song Song, nick string) (bool, error)
	// RemoveFavorite removes the given song from nicks favorite list
	RemoveFavorite(song Song, nick string) (bool, error)

	// UpdateLength updates the stored length of the song
	UpdateLength(Song, time.Duration) error
	// UpdateHashLink updates the HashLink of the song
	UpdateHashLink(entry SongHash, hashLink SongHash) error
}

SongStorage stores information about songs

A song can be anything that plays on stream, unlike a track which is a specific kind of song that we have an audio file for and can be played by the automated streamer

type SongStorageService

type SongStorageService interface {
	Song(context.Context) SongStorage
	SongTx(context.Context, StorageTx) (SongStorage, StorageTx, error)
}

SongStorageService is a service able to supply a SongStorage

type SongUpdate

type SongUpdate struct {
	Song
	Info SongInfo
}

type Status

type Status struct {
	// User is the user that is currently broadcasting on the stream
	User User
	// Song is the song that is currently playing on the stream
	Song Song
	// SongInfo is extra information about the song that is currently playing
	SongInfo SongInfo
	// StreamerName is the name given to us by the user that is streaming
	StreamerName string
	// Listeners is the current amount of stream listeners
	Listeners Listeners
	// Thread is an URL to a third-party platform related to the current stream
	Thread string
	// RequestsEnabled tells you if requests to the automated streamer are enabled
	RequestsEnabled bool
}

func (Status) Copy

func (s Status) Copy() Status

Copy makes a deep-copy of the status object

func (*Status) IsZero

func (s *Status) IsZero() bool

type StatusStorage

type StatusStorage interface {
	// Store stores the Status given
	Store(Status) error
	// Load returns the previously stored Status
	Load() (*Status, error)
}

StatusStorage stores a Status structure

type StatusStorageService

type StatusStorageService interface {
	Status(context.Context) StatusStorage
}

StatusStorageService is a service able to supply a StatusStorage

type StorageTx

type StorageTx interface {
	Commit() error
	Rollback() error
}

type StreamerService

type StreamerService interface {
	Start(context.Context) error
	Stop(ctx context.Context, force bool) error

	RequestSong(context.Context, Song, string) error
	Queue(context.Context) ([]QueueEntry, error)
}

type SubmissionID

type SubmissionID uint64

SubmissionID is the ID of a pending song

func ParseSubmissionID

func ParseSubmissionID(s string) (SubmissionID, error)

func (SubmissionID) String

func (id SubmissionID) String() string

type SubmissionStats

type SubmissionStats struct {
	// Amount of submissions in the pending queue
	CurrentPending int `db:"current_pending"`
	// Information about accepted songs
	AcceptedTotal        int `db:"accepted_total"`
	AcceptedLastTwoWeeks int `db:"accepted_last_two_weeks"`
	AcceptedYou          int `db:"accepted_you"`
	RecentAccepts        []PostPendingSong

	// Information about declined songs
	DeclinedTotal        int `db:"declined_total"`
	DeclinedLastTwoWeeks int `db:"declined_last_two_weeks"`
	DeclinedYou          int `db:"declined_you"`
	RecentDeclines       []PostPendingSong

	// Information about (You)
	LastSubmissionTime time.Time `db:"last_submission_time"`
}

type SubmissionStatus

type SubmissionStatus int

SubmissionStatus is the status of a submitted song

const (
	SubmissionDeclined SubmissionStatus = iota
	SubmissionAccepted
	SubmissionReplacement
	SubmissionAwaitingReview
)
const SubmissionInvalid SubmissionStatus = -1

Possible status for song submissions

type SubmissionStorage

type SubmissionStorage interface {
	// LastSubmissionTime returns the last known time of when the identifier
	// was used to upload a submission
	LastSubmissionTime(identifier string) (time.Time, error)
	// UpdateSubmissionTime updates the last submission time to the current time
	// for the identifier given
	UpdateSubmissionTime(identifier string) error
	// SubmissionStats returns the submission stats for the identifier given.
	SubmissionStats(identifier string) (SubmissionStats, error)

	// All returns all submissions
	All() ([]PendingSong, error)
	// InsertSubmission inserts a new pending song into the database
	InsertSubmission(PendingSong) error
	// GetSubmission returns a pending song by ID
	GetSubmission(SubmissionID) (*PendingSong, error)
	// RemoveSubmission removes a pending song by ID
	RemoveSubmission(SubmissionID) error

	// InsertPostPending inserts post-pending data
	InsertPostPending(PendingSong) error
}

SubmissionStorage stores stuff related to the reviewing of submissions and associated information

type SubmissionStorageService

type SubmissionStorageService interface {
	Submissions(context.Context) SubmissionStorage
	SubmissionsTx(context.Context, StorageTx) (SubmissionStorage, StorageTx, error)
}

SubmissionStorageService is a service able to supply a SubmissionStorage

type Theme

type Theme struct {
	ID          ThemeID
	Name        string
	DisplayName string
	Author      string
}

Theme is a website theme

type ThemeID

type ThemeID uint64

ThemeID is the identifier of a website theme

type Thread

type Thread = string

type TrackID

type TrackID uint64

TrackID is a database track identifier

func ParseTrackID

func ParseTrackID(s string) (TrackID, error)

func (TrackID) String

func (t TrackID) String() string

type TrackState

type TrackState int

TrackState is the state of a Track in storage

const (
	TrackStateUnverified TrackState = iota
	TrackStatePlayable
)

type TrackStorage

type TrackStorage interface {
	// Get returns a single track with the TrackID given
	Get(TrackID) (*Song, error)
	// All returns all tracks in storage
	All() ([]Song, error)
	// Delete removes a track from storage
	Delete(TrackID) error
	// Unusable returns all tracks that are deemed unusable by the streamer
	Unusable() ([]Song, error)
	// Insert inserts a new track, errors if ID or TrackID is set
	Insert(song Song) (TrackID, error)
	// UpdateMetadata updates track metadata only (artist/title/album/tags/filepath/needreplacement)
	UpdateMetadata(song Song) error
	// UpdateUsable sets usable to the state given
	UpdateUsable(song Song, state TrackState) error

	// UpdateRequestInfo is called after a track has been requested, this should do any
	// necessary book-keeping related to that
	UpdateRequestInfo(TrackID) error
	// UpdateLastPlayed sets the last time the track was played to the current time
	UpdateLastPlayed(TrackID) error
	// UpdateLastRequested sets the last time the track was requested to the current time
	UpdateLastRequested(TrackID) error

	// BeforeLastRequested returns all tracks that have their LastRequested before the
	// time given
	BeforeLastRequested(before time.Time) ([]Song, error)
	// DecrementRequestCount decrements the RequestCount for all tracks that have
	// their LastRequested before the time given
	DecrementRequestCount(before time.Time) error

	// QueueCandidates returns tracks that are candidates to be queue'd by the
	// default queue implementation
	QueueCandidates() ([]TrackID, error)
}

TrackStorage stores information about tracks

A track is a song that we have the audio file for and can thus be played by the automated streaming system

type TrackStorageService

type TrackStorageService interface {
	Track(context.Context) TrackStorage
	TrackTx(context.Context, StorageTx) (TrackStorage, StorageTx, error)
}

TrackStorageService is a service able to supply a TrackStorage

type User

type User struct {
	ID            UserID
	Username      string
	Password      string
	Email         string
	RememberToken string
	IP            string

	UpdatedAt *time.Time
	DeletedAt *time.Time
	CreatedAt time.Time

	DJ              DJ
	UserPermissions UserPermissions
}

User is an user account in the database

func (User) ComparePassword

func (u User) ComparePassword(passwd string) error

type UserID

type UserID int32

UserID is an identifier corresponding to an user

func ParseUserID

func ParseUserID(s string) (UserID, error)

func (UserID) String

func (id UserID) String() string

type UserPermission

type UserPermission string

UserPermission is a permission for user authorization

func AllUserPermissions

func AllUserPermissions() []UserPermission

func (UserPermission) String

func (u UserPermission) String() string

type UserPermissions

type UserPermissions map[UserPermission]struct{}

func (UserPermissions) Has

func (up UserPermissions) Has(perm UserPermission) bool

Has returns true if the permissions in UserPermission allow access to the permission given

func (UserPermissions) HasExplicit

func (up UserPermissions) HasExplicit(perm UserPermission) bool

HasExplicit returns true if the permission given is explicitly in the UserPermissions

func (*UserPermissions) Scan

func (upp *UserPermissions) Scan(src interface{}) error

Scan implements sql.Scanner

Done in a way that it expects all permissions to be a single string or []byte separated by a comma

type UserStorage

type UserStorage interface {
	// All returns all users
	All() ([]User, error)
	// Get returns the user matching the name given
	Get(name string) (*User, error)
	// GetByDJID returns the user associated with the DJID
	GetByDJID(DJID) (*User, error)
	// UpdateUser updates the given user
	UpdateUser(User) (User, error)
	// LookupName matches the name given fuzzily to a user
	LookupName(name string) (*User, error)
	// ByNick returns an user that is associated with the nick given
	ByNick(nick string) (*User, error)
	// Permissions returns all available permissions
	Permissions() ([]UserPermission, error)
	// RecordListeners records a history of listener count
	RecordListeners(Listeners, User) error
}

UserStorage stores things related to users with actual accounts on the website

type UserStorageService

type UserStorageService interface {
	User(context.Context) UserStorage
	UserTx(context.Context, StorageTx) (UserStorage, StorageTx, error)
}

UserStorageService is a service able to supply a UserStorage

Directories

Path Synopsis
cmd
Package templates handles the website templating system.
Package templates handles the website templating system.
graceful
Package usock implements a wrapper around the unix(7) SCM_RIGHTS API, which allows processes to exchange file handles over a unix(7) control socket.
Package usock implements a wrapper around the unix(7) SCM_RIGHTS API, which allows processes to exchange file handles over a unix(7) control socket.
sse

Jump to

Keyboard shortcuts

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