model

package
v1.24.8 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2026 License: GPL-3.0 Imports: 10 Imported by: 0

Documentation

Overview

Package model defines pure data types for all Twitch miner entities. These types have no external dependencies and are safe for concurrent use where documented.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetPredictionWindow

func GetPredictionWindow(settings *BetSettings, predictionWindowSeconds float64) float64

GetPredictionWindow calculates the actual delay before placing a bet based on settings.

func LookupGameSlug

func LookupGameSlug(gameID string) string

LookupGameSlug returns the slug for a game ID, or "" if not found.

func Percentage

func Percentage(a, b int) int

Percentage calculates the integer percentage of a/b. Delegates to utils.Percentage for the canonical implementation.

func RegisterGameSlug

func RegisterGameSlug(gameID, slug string)

RegisterGameSlug records a game ID → slug mapping in the global registry. Both gameID and slug must be non-empty; empty values are silently ignored.

func ShouldJoinChat

func ShouldJoinChat(presence ChatPresence, isOnline bool) bool

ShouldJoinChat returns whether the miner should join chat for the given presence setting and online state.

Types

type Bet

type Bet struct {
	Outcomes    []Outcome    `json:"outcomes"`
	Decision    BetDecision  `json:"decision"`
	TotalUsers  int          `json:"total_users"`
	TotalPoints int          `json:"total_points"`
	Settings    *BetSettings `json:"-"`
}

Bet holds the state of a prediction bet calculation.

func NewBet

func NewBet(outcomes []Outcome, settings *BetSettings) *Bet

NewBet creates a new Bet from a list of outcomes and settings.

func (*Bet) Calculate

func (b *Bet) Calculate(balance int) BetDecision

Calculate determines which outcome to bet on and how much to bet.

func (*Bet) Skip

func (b *Bet) Skip() (bool, float64)

Skip checks the filter condition and returns whether the bet should be skipped and the compared value.

func (*Bet) String

func (b *Bet) String() string

String returns a human-readable representation of the bet.

func (*Bet) UpdateOutcomes

func (b *Bet) UpdateOutcomes(updates []Outcome)

UpdateOutcomes refreshes outcome statistics from new data.

type BetDecision

type BetDecision struct {
	Choice    int    `json:"choice"`
	Amount    int    `json:"amount"`
	OutcomeID string `json:"id"`
}

BetDecision holds the result of a bet calculation.

type BetSettings

type BetSettings struct {
	Strategy        Strategy         `json:"strategy" yaml:"strategy"`
	Percentage      int              `json:"percentage" yaml:"percentage"`
	PercentageGap   int              `json:"percentage_gap" yaml:"percentage_gap"`
	MaxPoints       int              `json:"max_points" yaml:"max_points"`
	MinimumPoints   int              `json:"minimum_points" yaml:"minimum_points"`
	StealthMode     bool             `json:"stealth_mode" yaml:"stealth_mode"`
	FilterCondition *FilterCondition `json:"filter_condition,omitempty" yaml:"filter_condition"`
	Delay           float64          `json:"delay" yaml:"delay"`
	DelayMode       DelayMode        `json:"delay_mode" yaml:"delay_mode"`
}

BetSettings holds configuration for automatic prediction betting.

func DefaultBetSettings

func DefaultBetSettings() *BetSettings

DefaultBetSettings returns BetSettings with default values.

func (*BetSettings) String

func (bs *BetSettings) String() string

String returns a human-readable representation of the bet settings.

type Campaign

type Campaign struct {
	ID                 string    `json:"id"`
	Game               *GameInfo `json:"game,omitempty"`
	Name               string    `json:"name"`
	Status             string    `json:"status"`
	IsInInventory      bool      `json:"in_inventory"`
	EndAt              time.Time `json:"end_at"`
	StartAt            time.Time `json:"start_at"`
	IsWithinTimeWindow bool      `json:"dt_match"`
	Drops              []*Drop   `json:"drops,omitempty"`
	Channels           []string  `json:"channels,omitempty"`
}

Campaign represents a Twitch drop campaign.

func NewCampaign

func NewCampaign(id, name, status string, game *GameInfo, startAt, endAt time.Time, channels []string) *Campaign

NewCampaign creates a Campaign from raw API data.

func (*Campaign) ClearDrops

func (c *Campaign) ClearDrops()

ClearDrops removes drops that are outside the time window or already claimed.

func (*Campaign) Equal

func (c *Campaign) Equal(other *Campaign) bool

Equal returns true if two campaigns have the same ID.

func (*Campaign) String

func (c *Campaign) String() string

String returns a human-readable representation of the campaign.

type ChatPresence

type ChatPresence int

ChatPresence controls when the miner joins a streamer's IRC chat.

const (
	// ChatAlways means always stay in chat.
	ChatAlways ChatPresence = iota
	// ChatNever means never join chat.
	ChatNever
	// ChatOnline means join chat only when the streamer is online.
	ChatOnline
	// ChatOffline means join chat only when the streamer is offline.
	ChatOffline
)

func ParseChatPresence

func ParseChatPresence(s string) ChatPresence

ParseChatPresence converts a string to a ChatPresence value.

func (ChatPresence) String

func (c ChatPresence) String() string

String returns the string representation of a ChatPresence value.

type CommunityGoal

type CommunityGoal struct {
	GoalID                       string `json:"goal_id"`
	Title                        string `json:"title"`
	IsInStock                    bool   `json:"is_in_stock"`
	PointsContributed            int    `json:"points_contributed"`
	AmountNeeded                 int    `json:"amount_needed"`
	PerStreamUserMaxContribution int    `json:"per_stream_user_maximum_contribution"`
	Status                       string `json:"status"`
}

CommunityGoal represents a channel community goal.

func CommunityGoalFromGQL

func CommunityGoalFromGQL(data map[string]any) *CommunityGoal

CommunityGoalFromGQL creates a CommunityGoal from a GQL response map.

func CommunityGoalFromPubSub

func CommunityGoalFromPubSub(data map[string]any) *CommunityGoal

CommunityGoalFromPubSub creates a CommunityGoal from a PubSub message map.

func NewCommunityGoal

func NewCommunityGoal(goalID, title string, isInStock bool, pointsContributed, amountNeeded, perStreamMax int, status string) *CommunityGoal

NewCommunityGoal creates a new CommunityGoal.

func (*CommunityGoal) AmountLeft

func (cg *CommunityGoal) AmountLeft() int

AmountLeft returns the remaining points needed to complete the goal.

func (*CommunityGoal) Equal

func (cg *CommunityGoal) Equal(other *CommunityGoal) bool

Equal returns true if two community goals have the same ID.

func (*CommunityGoal) String

func (cg *CommunityGoal) String() string

String returns a human-readable representation of the community goal.

type Condition

type Condition int

Condition defines a comparison operator for filter conditions.

const (
	// ConditionGT is the greater-than operator.
	ConditionGT Condition = iota
	// ConditionLT is the less-than operator.
	ConditionLT
	// ConditionGTE is the greater-than-or-equal operator.
	ConditionGTE
	// ConditionLTE is the less-than-or-equal operator.
	ConditionLTE
)

func ParseCondition

func ParseCondition(s string) Condition

ParseCondition converts a string to a Condition value.

func (Condition) String

func (c Condition) String() string

String returns the string representation of a Condition.

type DelayMode

type DelayMode int

DelayMode defines how the prediction delay is calculated.

const (
	// DelayModeFromStart delays from the start of the prediction window.
	DelayModeFromStart DelayMode = iota
	// DelayModeFromEnd delays from the end of the prediction window.
	DelayModeFromEnd
	// DelayModePercentage delays by a percentage of the prediction window.
	DelayModePercentage
)

func ParseDelayMode

func ParseDelayMode(s string) DelayMode

ParseDelayMode converts a string to a DelayMode value.

func (DelayMode) String

func (d DelayMode) String() string

String returns the string representation of a DelayMode.

type Drop

type Drop struct {
	ID              string `json:"id"`
	Name            string `json:"name"`
	Benefit         string `json:"benefit"`
	MinutesRequired int    `json:"minutes_required"`

	HasPreconditionsMet   *bool  `json:"has_preconditions_met,omitempty"`
	CurrentMinutesWatched int    `json:"current_minutes_watched"`
	DropInstanceID        string `json:"drop_instance_id,omitempty"`
	IsClaimed             bool   `json:"is_claimed"`
	IsClaimable           bool   `json:"is_claimable"`
	IsPrintable           bool   `json:"is_printable"`
	IsSynthetic           bool   `json:"is_synthetic"`
	PercentageProgress    int    `json:"percentage_progress"`

	EndAt              time.Time `json:"end_at"`
	StartAt            time.Time `json:"start_at"`
	IsWithinTimeWindow bool      `json:"dt_match"`
}

Drop represents a single time-based drop within a campaign.

func NewDrop

func NewDrop(id, name string, benefits []string, minutesRequired int, startAt, endAt time.Time) *Drop

NewDrop creates a Drop from raw API data.

func (*Drop) Equal

func (d *Drop) Equal(other *Drop) bool

Equal returns true if two drops have the same ID.

func (*Drop) ProgressBar

func (d *Drop) ProgressBar() string

ProgressBar returns a text-based progress bar for the drop.

func (*Drop) String

func (d *Drop) String() string

String returns a human-readable representation of the drop.

func (*Drop) Update

func (d *Drop) Update(hasPreconditionsMet bool, currentMinutesWatched int, dropInstanceID string, isClaimed bool)

Update refreshes the drop's progress from inventory data.

type Event

type Event string

Event represents a miner event type for notification filtering and logging.

const (
	EventStreamerOnline        Event = "STREAMER_ONLINE"
	EventStreamerOffline       Event = "STREAMER_OFFLINE"
	EventGainForRaid           Event = "GAIN_FOR_RAID"
	EventGainForClaim          Event = "GAIN_FOR_CLAIM"
	EventGainForWatch          Event = "GAIN_FOR_WATCH"
	EventGainForWatchStreak    Event = "GAIN_FOR_WATCH_STREAK"
	EventBetWin                Event = "BET_WIN"
	EventBetLose               Event = "BET_LOSE"
	EventBetRefund             Event = "BET_REFUND"
	EventBetFilters            Event = "BET_FILTERS"
	EventBetGeneral            Event = "BET_GENERAL"
	EventBetFailed             Event = "BET_FAILED"
	EventBetStart              Event = "BET_START"
	EventBonusClaim            Event = "BONUS_CLAIM"
	EventMomentClaim           Event = "MOMENT_CLAIM"
	EventJoinRaid              Event = "JOIN_RAID"
	EventDropClaim             Event = "DROP_CLAIM"
	EventDropClaimAvailable    Event = "DROP_CLAIM_AVAILABLE"
	EventDropStatus            Event = "DROP_STATUS"
	EventChatMention           Event = "CHAT_MENTION"
	EventGiftedSub             Event = "GIFTED_SUB"
	EventMinerStarted          Event = "MINER_STARTED"
	EventMinerStopped          Event = "MINER_STOPPED"
	EventMinerCrashed          Event = "MINER_CRASHED"
	EventAccountConfigReloaded Event = "ACCOUNT_CONFIG_RELOADED"
	EventDropMilestone         Event = "DROP_MILESTONE"
	EventTest                  Event = "TEST"
)

All supported miner events.

func AllEvents

func AllEvents() []Event

AllEvents returns a slice of all defined events.

func ParseEvent

func ParseEvent(s string) Event

ParseEvent converts a string to an Event. Returns empty string if invalid.

func (Event) String

func (e Event) String() string

String returns the string representation of an Event.

type EventPrediction

type EventPrediction struct {
	Mu sync.Mutex `json:"-"`

	Streamer                *Streamer        `json:"-"`
	EventID                 string           `json:"event_id"`
	Title                   string           `json:"title"`
	CreatedAt               time.Time        `json:"created_at"`
	PredictionWindowSeconds float64          `json:"prediction_window_seconds"`
	Status                  string           `json:"status"`
	Result                  PredictionResult `json:"result"`
	ScheduledFor            time.Time        `json:"scheduled_for"`
	BetConfirmed            bool             `json:"bet_confirmed"`
	BetPlaced               bool             `json:"bet_placed"`
	BetSkipped              bool             `json:"bet_skipped"`
	PlacementInFlight       bool             `json:"placement_in_flight"`
	PlacementAttempts       int              `json:"placement_attempts"`
	LastAttemptAt           time.Time        `json:"last_attempt_at"`
	LastFailedReason        string           `json:"last_failed_reason"`
	Bet                     *Bet             `json:"bet"`
}

EventPrediction represents an active prediction event on a channel.

func NewEventPrediction

func NewEventPrediction(
	streamer *Streamer,
	eventID, title string,
	createdAt time.Time,
	predictionWindowSeconds float64,
	status string,
	outcomes []Outcome,
) *EventPrediction

NewEventPrediction creates a new EventPrediction.

func (*EventPrediction) ClosingBetAfter

func (ep *EventPrediction) ClosingBetAfter(timestamp time.Time) float64

ClosingBetAfter returns the seconds remaining until the prediction window closes.

func (*EventPrediction) Elapsed

func (ep *EventPrediction) Elapsed(timestamp time.Time) float64

Elapsed returns the seconds elapsed since the prediction was created.

func (*EventPrediction) ParseResult

func (ep *EventPrediction) ParseResult(resultType string, pointsWon int) map[string]int

ParseResult processes a prediction result and returns the points breakdown.

func (*EventPrediction) String

func (ep *EventPrediction) String() string

String returns a human-readable representation of the event prediction.

type FilterCondition

type FilterCondition struct {
	By    OutcomeKey `json:"by" yaml:"by"`
	Where Condition  `json:"where" yaml:"where"`
	Value float64    `json:"value" yaml:"value"`
}

FilterCondition defines a condition for filtering predictions before betting.

func (*FilterCondition) String

func (fc *FilterCondition) String() string

String returns a human-readable representation of the filter condition.

type FollowersOrder

type FollowersOrder int

FollowersOrder defines the sort order for followed channels.

const (
	// FollowersOrderASC sorts followers in ascending order.
	FollowersOrderASC FollowersOrder = iota
	// FollowersOrderDESC sorts followers in descending order.
	FollowersOrderDESC
)

func ParseFollowersOrder

func ParseFollowersOrder(s string) FollowersOrder

ParseFollowersOrder converts a string to a FollowersOrder value.

func (FollowersOrder) String

func (fo FollowersOrder) String() string

String returns the string representation of a FollowersOrder.

type GameInfo

type GameInfo struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	DisplayName string `json:"displayName"`
	Slug        string `json:"slug,omitempty"`
}

GameInfo holds game/category metadata from the Twitch API.

type HistoryEntry

type HistoryEntry struct {
	Counter int `json:"counter"`
	Amount  int `json:"amount"`
}

HistoryEntry tracks cumulative points earned for a specific reason code.

type Message

type Message struct {
	Topic      string         `json:"topic"`
	TopicUser  string         `json:"topic_user"`
	RawMessage map[string]any `json:"message"`
	Type       MessageType    `json:"type"`
	Data       map[string]any `json:"data,omitempty"`
	Timestamp  time.Time      `json:"timestamp"`
	ChannelID  string         `json:"channel_id"`
	Identifier string         `json:"identifier"`
}

Message represents a parsed PubSub message.

func ParseMessage

func ParseMessage(topicFull string, rawMessageJSON []byte) (*Message, error)

ParseMessage creates a Message from raw PubSub data.

func (*Message) String

func (m *Message) String() string

String returns a string representation of the message.

type MessageType

type MessageType string

MessageType represents the type of a PubSub message for notification routing.

const (
	// Points-related messages
	MsgTypePointsEarned   MessageType = "points-earned"
	MsgTypePointsSpent    MessageType = "points-spent"
	MsgTypeClaimAvailable MessageType = "claim-available"
	MsgTypeClaimClaimed   MessageType = "claim-claimed"

	// Prediction messages
	MsgTypePredictionEvent  MessageType = "event-created"
	MsgTypePredictionUpdate MessageType = "event-updated"
	MsgTypePredictionLocked MessageType = "event-locked"
	MsgTypePredictionResult MessageType = "event-end"

	// Stream messages
	MsgTypeStreamUp   MessageType = "stream-up"
	MsgTypeStreamDown MessageType = "stream-down"
	MsgTypeViewCount  MessageType = "viewcount"

	// Raid messages
	MsgTypeRaidUpdate MessageType = "raid_update_v2"
	MsgTypeRaidGo     MessageType = "raid_go_v2"
	MsgTypeRaidCancel MessageType = "raid_cancel_v2"

	// Moment messages
	MsgTypeMomentAvailable MessageType = "active"

	// Community goal messages
	MsgTypeGoalContribution MessageType = "community-goal-contribution"
	MsgTypeGoalUpdated      MessageType = "community-goal-updated"
)

Message types for PubSub events.

type Outcome

type Outcome struct {
	ID              string  `json:"id"`
	Title           string  `json:"title"`
	Color           string  `json:"color"`
	TotalUsers      int     `json:"total_users"`
	TotalPoints     int     `json:"total_points"`
	TopPoints       int     `json:"top_points"`
	PercentageUsers float64 `json:"percentage_users"`
	Odds            float64 `json:"odds"`
	OddsPercentage  float64 `json:"odds_percentage"`
}

Outcome represents a single prediction outcome with computed statistics.

type OutcomeKey

type OutcomeKey string

OutcomeKey defines the keys used to access outcome statistics.

const (
	// OutcomeKeyPercentageUsers is the percentage of users who voted for this outcome.
	OutcomeKeyPercentageUsers OutcomeKey = "percentage_users"
	// OutcomeKeyOddsPercentage is the odds expressed as a percentage.
	OutcomeKeyOddsPercentage OutcomeKey = "odds_percentage"
	// OutcomeKeyOdds is the raw odds multiplier.
	OutcomeKeyOdds OutcomeKey = "odds"
	// OutcomeKeyTopPoints is the highest individual bet on this outcome.
	OutcomeKeyTopPoints OutcomeKey = "top_points"
	// OutcomeKeyTotalUsers is the total number of users who bet on this outcome.
	OutcomeKeyTotalUsers OutcomeKey = "total_users"
	// OutcomeKeyTotalPoints is the total points bet on this outcome.
	OutcomeKeyTotalPoints OutcomeKey = "total_points"
	// OutcomeKeyDecisionUsers is a virtual key for filter conditions.
	OutcomeKeyDecisionUsers OutcomeKey = "decision_users"
	// OutcomeKeyDecisionPoints is a virtual key for filter conditions.
	OutcomeKeyDecisionPoints OutcomeKey = "decision_points"
)

type PointsMultiplier

type PointsMultiplier struct {
	Factor float64 `json:"factor"`
}

PointsMultiplier represents an active channel points multiplier.

type PredictionResult

type PredictionResult struct {
	ResultString string `json:"string"`
	Type         string `json:"type"`
	Gained       int    `json:"gained"`
}

PredictionResult holds the result of a resolved prediction.

type Priority

type Priority int

Priority defines the watch priority strategy for selecting which streamers to watch.

const (
	// PriorityOrder uses the order defined in the config file.
	PriorityOrder Priority = iota
	// PriorityStreak prioritizes streamers where a watch streak bonus is pending.
	PriorityStreak
	// PriorityDrops prioritizes streamers with active drop campaigns.
	PriorityDrops
	// PrioritySubscribed prioritizes subscribed channels.
	PrioritySubscribed
	// PriorityPointsAscending prioritizes streamers with the fewest points.
	PriorityPointsAscending
	// PriorityPointsDescending prioritizes streamers with the most points.
	PriorityPointsDescending
	// PriorityEndingSoonest prioritizes campaigns ending soonest.
	PriorityEndingSoonest
	// PriorityLowAvailabilityFirst prioritizes campaigns with the lowest availability.
	PriorityLowAvailabilityFirst
)

func ParsePriority

func ParsePriority(s string) Priority

ParsePriority converts a string to a Priority value.

func (Priority) String

func (p Priority) String() string

String returns the string representation of a Priority.

type PubSubTopic

type PubSubTopic struct {
	TopicType PubSubTopicType `json:"topic_type"`
	UserID    string          `json:"user_id,omitempty"`
	Streamer  *Streamer       `json:"-"`
}

PubSubTopic represents a PubSub subscription topic.

func NewStreamerTopic

func NewStreamerTopic(topicType PubSubTopicType, streamer *Streamer) *PubSubTopic

NewStreamerTopic creates a PubSubTopic scoped to a specific streamer's channel.

func NewUserTopic

func NewUserTopic(topicType PubSubTopicType, userID string) *PubSubTopic

NewUserTopic creates a PubSubTopic scoped to the authenticated user.

func (*PubSubTopic) IsUserTopic

func (pt *PubSubTopic) IsUserTopic() bool

IsUserTopic returns true if this topic is scoped to the user (not a streamer).

func (*PubSubTopic) String

func (pt *PubSubTopic) String() string

String returns the full topic string in the format "topic_name.id".

type PubSubTopicType

type PubSubTopicType int

PubSubTopicType identifies the category of a PubSub topic.

const (
	// PubSubTopicVideoPlayback tracks stream up/down and viewer count.
	PubSubTopicVideoPlayback PubSubTopicType = iota
	// PubSubTopicCommunityPoints tracks channel points events.
	PubSubTopicCommunityPoints
	// PubSubTopicPredictions tracks prediction events on a channel.
	PubSubTopicPredictions
	// PubSubTopicPredictionsUser tracks the user's own prediction events.
	PubSubTopicPredictionsUser
	// PubSubTopicRaid tracks raid events.
	PubSubTopicRaid
	// PubSubTopicCommunityMoments tracks community moment events.
	PubSubTopicCommunityMoments
	// PubSubTopicCommunityGoals tracks community goal events.
	PubSubTopicCommunityGoals
)

func (PubSubTopicType) String

func (t PubSubTopicType) String() string

String returns the Twitch topic string prefix for this topic type.

type Raid

type Raid struct {
	RaidID      string `json:"raid_id"`
	TargetLogin string `json:"target_login"`
}

Raid represents an active raid event on a channel.

func NewRaid

func NewRaid(raidID, targetLogin string) *Raid

NewRaid creates a new Raid.

func (*Raid) Equal

func (r *Raid) Equal(other *Raid) bool

Equal returns true if two raids have the same ID.

type Strategy

type Strategy int

Strategy defines the prediction betting strategy.

const (
	// StrategyMostVoted bets on the outcome with the most voters.
	StrategyMostVoted Strategy = iota
	// StrategyHighOdds bets on the outcome with the highest odds.
	StrategyHighOdds
	// StrategyPercentage bets on the outcome with the highest odds percentage.
	StrategyPercentage
	// StrategySmartMoney bets on the outcome with the highest top predictor points.
	StrategySmartMoney
	// StrategySmart uses a hybrid approach: high odds if close, most voted otherwise.
	StrategySmart
	// StrategyNumber1 always bets on outcome index 0.
	StrategyNumber1
	// StrategyNumber2 always bets on outcome index 1.
	StrategyNumber2
	// StrategyNumber3 always bets on outcome index 2.
	StrategyNumber3
	// StrategyNumber4 always bets on outcome index 3.
	StrategyNumber4
	// StrategyNumber5 always bets on outcome index 4.
	StrategyNumber5
	// StrategyNumber6 always bets on outcome index 5.
	StrategyNumber6
	// StrategyNumber7 always bets on outcome index 6.
	StrategyNumber7
	// StrategyNumber8 always bets on outcome index 7.
	StrategyNumber8
)

func ParseStrategy

func ParseStrategy(s string) Strategy

ParseStrategy converts a string to a Strategy value.

func (Strategy) String

func (s Strategy) String() string

String returns the string representation of a Strategy.

type Stream

type Stream struct {
	BroadcastID string `json:"broadcast_id,omitempty"`

	Title string    `json:"title,omitempty"`
	Game  *GameInfo `json:"game,omitempty"`
	Tags  []Tag     `json:"tags,omitempty"`

	HasDropsTag bool       `json:"drops_tags"`
	Campaigns   []Campaign `json:"campaigns,omitempty"`
	CampaignIDs []string   `json:"campaign_ids,omitempty"`

	ViewersCount int `json:"viewers_count"`

	SpadeURL string         `json:"spade_url,omitempty"`
	Payload  map[string]any `json:"payload,omitempty"`

	IsWatchStreakMissing bool    `json:"watch_streak_missing"`
	MinuteWatched        float64 `json:"minute_watched"`

	LastMinuteCreditedAt time.Time `json:"last_minute_credited_at,omitempty"`
	StalledCooldownUntil time.Time `json:"stalled_cooldown_until,omitempty"`
	// contains filtered or unexported fields
}

Stream represents the current state of a live broadcast.

func NewStream

func NewStream() *Stream

NewStream creates a new Stream with default values.

func (*Stream) GameDisplayName

func (s *Stream) GameDisplayName() string

GameDisplayName returns the game's display name, or empty string if no game is set.

func (*Stream) GameID

func (s *Stream) GameID() string

GameID returns the game's ID, or empty string if no game is set.

func (*Stream) GameName

func (s *Stream) GameName() string

GameName returns the game's internal name, or empty string if no game is set.

func (*Stream) GameSlug

func (s *Stream) GameSlug() string

GameSlug returns the game's URL-friendly slug from the Twitch API. It checks the direct API field first, then falls back to the global game slug registry (populated by the category watcher). No string normalization is performed — slugs must come from the Twitch API.

func (*Stream) InitWatchStreak

func (s *Stream) InitWatchStreak()

InitWatchStreak resets the watch streak tracking state.

func (*Stream) IsMinuteWatchStalled added in v1.24.6

func (s *Stream) IsMinuteWatchStalled(threshold time.Duration) bool

IsMinuteWatchStalled returns true when the last successful minute-watched credit is older than the given threshold. A zero LastMinuteCreditedAt (never credited) is not considered stalled — the streamer is simply new.

func (*Stream) MarkUpdated

func (s *Stream) MarkUpdated()

MarkUpdated sets lastUpdate to the current time without changing other fields. This is useful when a stream is discovered via an external source (e.g. category watcher) and we want to prevent UpdateRequired() from immediately returning true.

func (*Stream) String

func (s *Stream) String() string

String returns a human-readable representation of the stream.

func (*Stream) Update

func (s *Stream) Update(broadcastID, title string, game *GameInfo, tags []Tag, viewersCount int, dropID string)

Update refreshes the stream information with new data.

func (*Stream) UpdateElapsed

func (s *Stream) UpdateElapsed() time.Duration

UpdateElapsed returns the duration since the last stream info update.

func (*Stream) UpdateMinuteWatched

func (s *Stream) UpdateMinuteWatched()

UpdateMinuteWatched increments the minute-watched counter based on elapsed time.

func (*Stream) UpdateRequired

func (s *Stream) UpdateRequired() bool

UpdateRequired returns true if the stream info needs refreshing (>= 120s since last update).

type Streamer

type Streamer struct {
	Mu sync.RWMutex `json:"-"`

	Username        string `json:"username"`
	ChannelID       string `json:"channel_id"`
	DisplayName     string `json:"display_name,omitempty"`
	AccountUsername string `json:"-"` // The miner account that owns this streamer

	Settings *StreamerSettings `json:"settings,omitempty"`

	IsOnline          bool   `json:"is_online"`
	IsCategoryWatched bool   `json:"is_category_watched"`
	CategorySlug      string `json:"category_slug,omitempty"`
	IsTeamWatched     bool   `json:"is_team_watched"`
	TeamName          string `json:"team_name,omitempty"`

	StreamUpAt time.Time `json:"stream_up_at"`
	OnlineAt   time.Time `json:"online_at"`
	OfflineAt  time.Time `json:"offline_at"`

	ChannelPoints int `json:"channel_points"`

	CommunityGoals map[string]*CommunityGoal `json:"community_goals,omitempty"`

	ViewerIsMod       bool               `json:"viewer_is_mod"`
	ActiveMultipliers []PointsMultiplier `json:"active_multipliers,omitempty"`

	Stream *Stream `json:"stream"`

	Raid *Raid `json:"raid,omitempty"`

	History map[string]*HistoryEntry `json:"history,omitempty"`

	StreamerURL string `json:"streamer_url"`
}

Streamer represents a Twitch channel being watched by the miner. Fields that may be accessed concurrently are protected by Mu.

func NewStreamer

func NewStreamer(username string) *Streamer

NewStreamer creates a new Streamer with sensible defaults.

func (*Streamer) DeleteCommunityGoal

func (s *Streamer) DeleteCommunityGoal(goalID string)

DeleteCommunityGoal removes a community goal by ID.

func (*Streamer) DropsCondition

func (s *Streamer) DropsCondition() bool

DropsCondition returns true if the streamer qualifies for drops collection.

func (*Streamer) HasPointsMultiplier

func (s *Streamer) HasPointsMultiplier() bool

HasPointsMultiplier returns true if the viewer has active points multipliers.

func (*Streamer) MarshalJSON

func (s *Streamer) MarshalJSON() ([]byte, error)

MarshalJSON implements custom JSON marshaling to handle the mutex.

func (*Streamer) ResolveCategory

func (s *Streamer) ResolveCategory() string

ResolveCategory returns the best available category identifier for this streamer. It checks CategorySlug first, then the API-provided game slug (including the global registry lookup), then falls back to the game's display name. Returns "unknown" only if no category information is available at all. Must be called with Mu held (at least RLock).

func (*Streamer) SetOffline

func (s *Streamer) SetOffline()

SetOffline marks the streamer as offline. Must be called with Mu held.

func (*Streamer) SetOnline

func (s *Streamer) SetOnline()

SetOnline marks the streamer as online. Must be called with Mu held.

When the streamer returns after a short offline gap (< 30 min), the streak resolution state from the previous segment is carried over. If the streak was already resolved before going offline, it stays resolved — Twitch counts short restarts as the same stream.

func (*Streamer) StreamUpElapsed

func (s *Streamer) StreamUpElapsed() bool

StreamUpElapsed returns true if enough time has passed since the last stream-up event.

func (*Streamer) String

func (s *Streamer) String() string

String returns a human-readable representation of the streamer.

func (*Streamer) TotalPointsMultiplier

func (s *Streamer) TotalPointsMultiplier() float64

TotalPointsMultiplier returns the sum of all active multiplier factors.

func (*Streamer) UpdateCommunityGoal

func (s *Streamer) UpdateCommunityGoal(goal *CommunityGoal)

UpdateCommunityGoal adds or updates a community goal for this streamer.

func (*Streamer) UpdateHistory

func (s *Streamer) UpdateHistory(reasonCode string, earned int, counter int)

UpdateHistory adds earned points for a given reason code.

type StreamerSettings

type StreamerSettings struct {
	MakePredictions       bool         `json:"make_predictions" yaml:"make_predictions"`
	FollowRaid            bool         `json:"follow_raid" yaml:"follow_raid"`
	ClaimDrops            bool         `json:"claim_drops" yaml:"claim_drops"`
	ClaimMoments          bool         `json:"claim_moments" yaml:"claim_moments"`
	WatchStreak           bool         `json:"watch_streak" yaml:"watch_streak"`
	CommunityGoalsEnabled bool         `json:"community_goals" yaml:"community_goals"`
	DropsOnly             bool         `json:"drops_only" yaml:"drops_only"`
	Bet                   *BetSettings `json:"bet,omitempty" yaml:"bet"`
	Chat                  ChatPresence `json:"chat" yaml:"chat"`
}

StreamerSettings holds per-streamer feature toggles and bet configuration.

func DefaultStreamerSettings

func DefaultStreamerSettings() *StreamerSettings

DefaultStreamerSettings returns StreamerSettings with default values.

type Tag

type Tag struct {
	ID            string `json:"id"`
	LocalizedName string `json:"localizedName"`
}

Tag represents a stream tag.

Jump to

Keyboard shortcuts

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