app

package
v0.0.0-...-25151b4 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2026 License: GPL-3.0 Imports: 54 Imported by: 0

Documentation

Index

Constants

View Source
const (
	StreamDeckGridColumns = 5
	StreamDeckGridRows    = 3
	StreamDeckButtonCount = StreamDeckGridColumns * StreamDeckGridRows
)
View Source
const (
	MinPriorityLevel = 0
	MaxPriorityLevel = 3
	DefaultPriority  = 1
)

Variables

View Source
var (
	ErrInvalidInput = errors.New("invalid input")
	ErrConflict     = errors.New("conflict")
	ErrNotFound     = errors.New("not found")
)
View Source
var (
	// Version is the application version, set via -ldflags "-X github.com/KesherCom/kesher/backend/internal/app.Version=..."
	Version string
	// BuildTimestamp is the build timestamp in RFC3339 format, set via -ldflags
	BuildTimestamp string
)

Version and BuildTimestamp are set during build via ldflags. For local development builds, they default to "dev" and current time.

Functions

func EncodeUDPAudioPacket

func EncodeUDPAudioPacket(dst []byte, p UDPAudioPacket) (int, error)

EncodeUDPAudioPacket serialises a packet into dst. dst must be large enough (header + len(payload)). Returns the total encoded length.

func HashSessionToken

func HashSessionToken(token string) uint32

HashSessionToken derives the short token identifier used in audio/heartbeat packets so the relay does not have to ship the full token on every frame.

Types

type AckSettings

type AckSettings struct {
	Enabled bool `json:"enabled"`
}

type ActiveClient

type ActiveClient struct {
	Username  string
	RoleID    string
	RoleName  string
	UserID    string
	VoiceMode string
}

type AdminLogEntry

type AdminLogEntry struct {
	TimestampUnixMs int64  `json:"timestampUnixMs"`
	Level           string `json:"level"`
	Category        string `json:"category"`
	Message         string `json:"message"`
	Method          string `json:"method,omitempty"`
	Path            string `json:"path,omitempty"`
	Status          int    `json:"status,omitempty"`
	DurationMs      int64  `json:"durationMs,omitempty"`
	Username        string `json:"username,omitempty"`
	RoleID          string `json:"roleId,omitempty"`
	RemoteAddr      string `json:"remoteAddr,omitempty"`
	Error           string `json:"error,omitempty"`
}

type AdminLoginRequest

type AdminLoginRequest struct {
	PIN string `json:"pin"`
}

type AdminLogsResponse

type AdminLogsResponse struct {
	Entries         []AdminLogEntry `json:"entries"`
	Total           int             `json:"total"`
	TimestampUnixMs int64           `json:"timestampUnixMs"`
}

type AdminUserView

type AdminUserView struct {
	ID       string `json:"id"`
	Username string `json:"username"`
	RoleID   string `json:"roleId"`
	Online   bool   `json:"online"`
}

type AudioModeInfo

type AudioModeInfo struct {
	Mode string `json:"mode"`
}

AudioModeInfo tells the client which transport the server expects. "native" instructs Tauri clients to skip WebRTC and use the native UDP pipeline; "webrtc" is the fallback (browser, or native when relay is unavailable).

type BootstrapResponse

type BootstrapResponse struct {
	Self            User             `json:"self"`
	Roles           []Role           `json:"roles"`
	Rooms           []Room           `json:"rooms"`
	BroadcastGroups []BroadcastGroup `json:"broadcastGroups"`
	Users           []User           `json:"users"`
	AckEnabled      bool             `json:"ackEnabled"`
	AppVersion      VersionInfo      `json:"appVersion"`
}

type BroadcastGroup

type BroadcastGroup struct {
	ID             string   `json:"id"`
	Name           string   `json:"name"`
	PriorityLevel  int      `json:"priorityLevel"`
	RoomIDs        []string `json:"roomIds"`
	AllowedRoleIDs []string `json:"allowedRoleIds"`
}

type ButtonImageRenderConfig

type ButtonImageRenderConfig struct {
	Width  int
	Height int
}

ButtonImageRenderConfig holds rendering configuration

type ButtonImageRenderer

type ButtonImageRenderer struct {
	// contains filtered or unexported fields
}

ButtonImageRenderer renders button state to image buffers

func NewButtonImageRenderer

func NewButtonImageRenderer(config *ButtonImageRenderConfig) (*ButtonImageRenderer, error)

NewButtonImageRenderer creates a new renderer with default config

func (*ButtonImageRenderer) RenderButtonImage

func (r *ButtonImageRenderer) RenderButtonImage(state ButtonState) ([]byte, error)

RenderButtonImage renders a button state as a PNG using the same card palette and typography rules as web/src/lib/streamDeckHardwareFeedback.ts.

type ButtonState

type ButtonState struct {
	Channel       string
	State         string // "IDLE", "TALK", "LISTEN", "BROADCAST"
	Label         string
	Subtitle      string
	EffectValue   int
	ActionType    string
	Color         string
	TalkCount     int
	IsListening   bool
	IsPTTSelected bool
	IsActive      bool
}

ButtonState represents the state of a button for rendering

type ChatAckInbound

type ChatAckInbound struct {
	MessageID    string `json:"messageId"`
	SenderUserID string `json:"senderUserId"`
}

type ChatAckUpdate

type ChatAckUpdate struct {
	MessageID    string `json:"messageId"`
	SenderUserID string `json:"senderUserId"`
	AckedBy      User   `json:"ackedBy"`
	AckedAt      int64  `json:"ackedAt"`
}

type ChatHistory

type ChatHistory struct {
	// contains filtered or unexported fields
}

func NewChatHistory

func NewChatHistory(limit int) *ChatHistory

func (*ChatHistory) AppendForRoom

func (h *ChatHistory) AppendForRoom(roomID string, e RoutedEvent)

func (*ChatHistory) AppendForUser

func (h *ChatHistory) AppendForUser(userID string, e RoutedEvent)

func (*ChatHistory) Clear

func (h *ChatHistory) Clear()

func (*ChatHistory) HistoryForRooms

func (h *ChatHistory) HistoryForRooms(roomIDs []string) []RoutedEvent

func (*ChatHistory) HistoryForUserAndRooms

func (h *ChatHistory) HistoryForUserAndRooms(userID string, roomIDs []string) []RoutedEvent

type CompanionAdminSummaryResponse

type CompanionAdminSummaryResponse struct {
	SharedSecret      string                             `json:"sharedSecret"`
	PublishedProfiles []CompanionPublishedProfileSummary `json:"publishedProfiles"`
}

type CompanionBridgeState

type CompanionBridgeState struct {
	Username            string         `json:"username"`
	Bound               bool           `json:"bound"`
	Presence            *PresenceState `json:"presence,omitempty"`
	SessionCount        int            `json:"sessionCount,omitempty"`
	MultiSessionWarning bool           `json:"multiSessionWarning,omitempty"`
	ReplyDirectUserID   string         `json:"replyDirectUserId,omitempty"`
	ReplyDirectUsername string         `json:"replyDirectUsername,omitempty"`
	SignalActive        bool           `json:"signalActive"`
	SignalFrom          string         `json:"signalFrom,omitempty"`
	SignalMessage       string         `json:"signalMessage,omitempty"`
	ImageEffectMapJSON  string         `json:"imageEffectMapJson,omitempty"`
	CurrentPageNumber   int            `json:"currentPageNumber,omitempty"`
	ProfileVersion      int            `json:"profileVersion,omitempty"`
	ProfileStatus       string         `json:"profileStatus,omitempty"`
	ProfileUpdatedAt    int64          `json:"profileUpdatedAt,omitempty"`
}

type CompanionCommand

type CompanionCommand struct {
	CommandID     string   `json:"commandId,omitempty"`
	Command       string   `json:"command"`
	Mode          string   `json:"mode,omitempty"`
	Scope         string   `json:"scope,omitempty"`
	TargetID      string   `json:"targetId,omitempty"`
	State         string   `json:"state,omitempty"`
	Signal        string   `json:"signal,omitempty"`
	ButtonIndex   int      `json:"buttonIndex,omitempty"`
	VolumeDelta   int      `json:"volumeDelta,omitempty"`
	ListenRoomIDs []string `json:"listenRoomIds"`
	TalkRoomIDs   []string `json:"talkRoomIds"`
	Brightness    int      `json:"brightness,omitempty"`
	PageNumber    int      `json:"pageNumber,omitempty"`
}

type CompanionCommandResult

type CompanionCommandResult struct {
	CommandID string `json:"commandId,omitempty"`
	Command   string `json:"command,omitempty"`
	OK        bool   `json:"ok"`
	Status    string `json:"status,omitempty"`
	Error     string `json:"error,omitempty"`
	Source    string `json:"source,omitempty"`
	Timestamp int64  `json:"timestamp,omitempty"`
}

type CompanionDiscoveryResponse

type CompanionDiscoveryResponse struct {
	Username          string                   `json:"username"`
	RoleID            string                   `json:"roleId"`
	Rooms             []CompanionRoomDiscovery `json:"rooms"`
	Users             []User                   `json:"users"`
	ActiveRoleUsers   []CompanionRoleUser      `json:"activeRoleUsers,omitempty"`
	BroadcastGroups   []BroadcastGroup         `json:"broadcastGroups"`
	CurrentPageNumber int                      `json:"currentPageNumber,omitempty"`
	ProfileVersion    int                      `json:"profileVersion,omitempty"`
	ProfileStatus     string                   `json:"profileStatus,omitempty"`
	ProfileUpdatedAt  int64                    `json:"profileUpdatedAt,omitempty"`
}

type CompanionProfileResponse

type CompanionProfileResponse struct {
	RoleID            string                   `json:"roleId"`
	Username          string                   `json:"username"`
	PageNumber        int                      `json:"pageNumber,omitempty"`
	CurrentPageNumber int                      `json:"currentPageNumber,omitempty"`
	Rooms             []CompanionRoomDiscovery `json:"rooms"`
	Users             []User                   `json:"users"`
	ActiveRoleUsers   []CompanionRoleUser      `json:"activeRoleUsers,omitempty"`
	BroadcastGroups   []BroadcastGroup         `json:"broadcastGroups"`
	StreamDeck        StreamDeckSettings       `json:"streamDeckSettings"`
	ProfileVersion    int                      `json:"profileVersion"`
	ProfileStatus     string                   `json:"profileStatus"`
	ProfileUpdatedAt  int64                    `json:"profileUpdatedAt,omitempty"`
}

type CompanionPublishedProfileSummary

type CompanionPublishedProfileSummary struct {
	RoleID           string `json:"roleId"`
	Username         string `json:"username"`
	ProfileVersion   int    `json:"profileVersion"`
	ProfileStatus    string `json:"profileStatus"`
	ProfileUpdatedAt int64  `json:"profileUpdatedAt,omitempty"`
}

type CompanionRoleUser

type CompanionRoleUser struct {
	RoleID   string `json:"roleId"`
	Username string `json:"username"`
	UserID   string `json:"userId"`
}

type CompanionRoomDiscovery

type CompanionRoomDiscovery struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	CanTalk   bool   `json:"canTalk"`
	CanListen bool   `json:"canListen"`
}

type Config

type Config struct {
	Addr                        string
	StaticDir                   string
	DBPath                      string
	AllowCORS                   bool
	AdminPIN                    string
	AdminPINFromEnv             bool
	SessionTTL                  time.Duration
	DisconnectLogoutDelay       time.Duration
	TrustedLANHTTP              bool
	TLSMode                     string
	TLSCertFile                 string
	TLSKeyFile                  string
	ProductionMode              bool
	ProductionHTTPSAddr         string
	ProductionHTTPRedirectAddr  string
	CertMagicDomains            []string
	CertMagicEmail              string
	CertMagicCA                 string
	CertMagicStoragePath        string
	CertMagicChallenge          string
	CertMagicDNSProvider        string
	CertMagicPropagationDelay   time.Duration
	CertMagicPropagationTimeout time.Duration
	CertMagicResolvers          []string
	TelegramBotToken            string
	TelegramWebhookSecret       string
	TelegramMode                string // "polling" (default) or "webhook"
	CompanionSharedSecret       string
	CompanionAllowedUsernames   []string
	CompanionImageEffectMapFile string
	CompanionDynamicPaging      bool
	// Native low-latency UDP audio relay (performance mode). Empty UDPAudioAddr
	// disables the relay; native clients then fall back to the WebRTC pipeline.
	UDPAudioAddr        string
	UDPAudioAdvertiseIP string
}

func LoadConfig

func LoadConfig() (Config, error)

type ConfigurationDocument

type ConfigurationDocument struct {
	Meta              ConfigurationMetadata                 `json:"meta"`
	Roles             []Role                                `json:"roles,omitempty"`
	Users             []ConfigurationUserAssignment         `json:"users,omitempty"`
	Rooms             []Room                                `json:"rooms,omitempty"`
	BroadcastGroups   []BroadcastGroup                      `json:"broadcastGroups,omitempty"`
	TelegramAllowlist []TelegramAllowlistEntry              `json:"telegramAllowlist,omitempty"`
	AckSettings       *AckSettings                          `json:"ackSettings,omitempty"`
	StreamDeck        []ConfigurationUserStreamDeckSettings `json:"streamDeckSettings,omitempty"`
}

type ConfigurationImportRequest

type ConfigurationImportRequest struct {
	Document ConfigurationDocument `json:"document"`
	Sections []string              `json:"sections,omitempty"`
}

type ConfigurationImportResponse

type ConfigurationImportResponse struct {
	ImportedSections []string `json:"importedSections"`
}

type ConfigurationMetadata

type ConfigurationMetadata struct {
	Format        string      `json:"format"`
	SchemaVersion int         `json:"schemaVersion"`
	ExportedAt    string      `json:"exportedAt"`
	SourceVersion VersionInfo `json:"sourceVersion"`
	Sections      []string    `json:"sections"`
}

type ConfigurationUserAssignment

type ConfigurationUserAssignment struct {
	Username string `json:"username"`
	RoleID   string `json:"roleId"`
}

type ConfigurationUserStreamDeckSettings

type ConfigurationUserStreamDeckSettings struct {
	Username string             `json:"username"`
	Settings StreamDeckSettings `json:"settings"`
}

type Hub

type Hub struct {
	// contains filtered or unexported fields
}

func NewHub

func NewHub(store *Store, logger *slog.Logger) *Hub

func (*Hub) ActiveTalkRoomForToken

func (h *Hub) ActiveTalkRoomForToken(token string) (string, bool)

func (*Hub) ActiveUserByUsername

func (h *Hub) ActiveUserByUsername(username string) (User, bool)

func (*Hub) Add

func (h *Hub) Add(c *client)

func (*Hub) BroadcastChatHistoryCleared

func (h *Hub) BroadcastChatHistoryCleared()

func (*Hub) BroadcastConfigUpdate

func (h *Hub) BroadcastConfigUpdate(data PublicBootstrapResponse)

func (*Hub) ClearChatHistory

func (h *Hub) ClearChatHistory()

func (*Hub) GetActiveClients

func (h *Hub) GetActiveClients(ctx context.Context) []ActiveClient

GetActiveClients returns a list of currently connected clients with their basic info. The list is sorted by username for consistent ordering.

func (*Hub) HasActiveSessionsForRole

func (h *Hub) HasActiveSessionsForRole(roleID string) bool

func (*Hub) IsNativeTransport

func (h *Hub) IsNativeTransport(token string) bool

IsNativeTransport reports whether the session uses the native UDP transport (performance mode). Browser clients always return false.

func (*Hub) LatestRoleSession

func (h *Hub) LatestRoleSession(roleID string) (Session, bool)

func (*Hub) LatestTokenForUsername

func (h *Hub) LatestTokenForUsername(username string) (string, bool)

func (*Hub) ListenRoomsForToken

func (h *Hub) ListenRoomsForToken(token string) []string

func (*Hub) PresenceForUsername

func (h *Hub) PresenceForUsername(username string) (PresenceState, bool)

func (*Hub) RealtimeStats

func (h *Hub) RealtimeStats() HubRealtimeStats

func (*Hub) Remove

func (h *Hub) Remove(token string)

func (*Hub) RemoveWithReason

func (h *Hub) RemoveWithReason(token string, reason string)

func (*Hub) ReplyTargetForUsername

func (h *Hub) ReplyTargetForUsername(username string) (string, string, bool)

func (*Hub) RoomListenerCounts

func (h *Hub) RoomListenerCounts() map[string]int

func (*Hub) RouteChatAck

func (h *Hub) RouteChatAck(senderToken string, in ChatAckInbound)

func (*Hub) RouteEvent

func (h *Hub) RouteEvent(senderToken string, eventType string, e RoutedEvent)

func (*Hub) SendChatHistorySnapshot

func (h *Hub) SendChatHistorySnapshot(token string) int

func (*Hub) SendChatToRole

func (h *Hub) SendChatToRole(roleID string, e RoutedEvent)

SendChatToRole sends a chat message to all active sessions of a role. Used by external systems (like Telegram) for role-targeted messages.

func (*Hub) SendChatToRoom

func (h *Hub) SendChatToRoom(roomID string, e RoutedEvent)

func (*Hub) SendChatToUser

func (h *Hub) SendChatToUser(userID string, e RoutedEvent)

SendChatToUser sends a chat message to all sessions of a specific user. Used by external systems (like Telegram) to deliver messages to Kesher users.

func (*Hub) SendPresenceSnapshot

func (h *Hub) SendPresenceSnapshot(token string)

SendPresenceSnapshot sends the current presence state to a specific client.

func (*Hub) SendRoomChatHistory

func (h *Hub) SendRoomChatHistory(token string, roomIDs []string) int

func (*Hub) SendToToken

func (h *Hub) SendToToken(token string, msg WSOutbound) bool

func (*Hub) SessionCountForUsername

func (h *Hub) SessionCountForUsername(username string) int

func (*Hub) SetBroadcastActive

func (h *Hub) SetBroadcastActive(token, groupID string, enabled bool)

func (*Hub) SetChatHook

func (h *Hub) SetChatHook(fn func(eventType string, e RoutedEvent))

func (*Hub) SetMediaManager

func (h *Hub) SetMediaManager(m *MediaManager)

func (*Hub) SetRoomMatrix

func (h *Hub) SetRoomMatrix(token string, listenRooms []string, talkRooms []string)

func (*Hub) SetUDPAudioRelay

func (h *Hub) SetUDPAudioRelay(r *UDPAudioRelay)

SetUDPAudioRelay registers the native-audio relay so that disconnected sessions are also unbound from the relay's peer registry.

func (*Hub) SetVoiceState

func (h *Hub) SetVoiceState(token, state string)

func (*Hub) SignalStateForUsername

func (h *Hub) SignalStateForUsername(username string) (string, string, bool)

func (*Hub) SignalStateWithMetadataForUsername

func (h *Hub) SignalStateWithMetadataForUsername(username string) (string, string, string, string, string, bool)

func (*Hub) SignalStateWithScopeForUsername

func (h *Hub) SignalStateWithScopeForUsername(username string) (string, string, string, bool)

func (*Hub) SubscribePresence

func (h *Hub) SubscribePresence() (chan []PresenceState, func())

func (*Hub) TokensForRole

func (h *Hub) TokensForRole(roleID string) []string

type HubRealtimeStats

type HubRealtimeStats struct {
	ConnectedClients         int               `json:"connectedClients"`
	NormalQueueDepthTotal    int               `json:"normalQueueDepthTotal"`
	NormalQueueDepthMax      int               `json:"normalQueueDepthMax"`
	PriorityQueueDepthTotal  int               `json:"priorityQueueDepthTotal"`
	PriorityQueueDepthMax    int               `json:"priorityQueueDepthMax"`
	DroppedCriticalMessages  uint64            `json:"droppedCriticalMessages"`
	DroppedNormalMessages    uint64            `json:"droppedNormalMessages"`
	DroppedMessagesByType    map[string]uint64 `json:"droppedMessagesByType"`
	PresenceBroadcasts       uint64            `json:"presenceBroadcasts"`
	PresenceBroadcastsMerged uint64            `json:"presenceBroadcastsMerged"`
}

type ImageStreamClient

type ImageStreamClient struct {
	RoleID   string
	Username string
	// contains filtered or unexported fields
}

ImageStreamClient represents a connected image stream client

type ImageStreamCoordinator

type ImageStreamCoordinator struct {
	// contains filtered or unexported fields
}

ImageStreamCoordinator manages image stream connections and broadcasting

func NewImageStreamCoordinator

func NewImageStreamCoordinator(logger *slog.Logger) (*ImageStreamCoordinator, error)

NewImageStreamCoordinator creates a new image stream coordinator

func (*ImageStreamCoordinator) BroadcastImageUpdate

func (c *ImageStreamCoordinator) BroadcastImageUpdate(state ButtonState, bank, buttonIndex int)

BroadcastImageUpdate sends an image update to all connected clients.

func (*ImageStreamCoordinator) BroadcastImageUpdateForTarget

func (c *ImageStreamCoordinator) BroadcastImageUpdateForTarget(roleID, username string, state ButtonState, bank, buttonIndex int)

BroadcastImageUpdateForTarget sends an image update only to clients bound to the same role. If username is provided and the client also declared one, both usernames must match.

func (*ImageStreamCoordinator) RegisterClient

func (c *ImageStreamCoordinator) RegisterClient(client *ImageStreamClient)

RegisterClient registers a new image stream client

func (*ImageStreamCoordinator) ResetTargetCache

func (c *ImageStreamCoordinator) ResetTargetCache(roleID, username string)

ResetTargetCache clears dedup signatures for matching clients so subsequent image emissions are always re-sent even if signatures are unchanged.

func (*ImageStreamCoordinator) UnregisterClient

func (c *ImageStreamCoordinator) UnregisterClient(client *ImageStreamClient)

UnregisterClient unregisters a client

type ImageStreamMessage

type ImageStreamMessage struct {
	Type          string `json:"type"` // "update_button_image"
	Bank          int    `json:"bank"`
	ButtonIndex   int    `json:"buttonIndex"`
	ImageBuffer   string `json:"imageBuffer"` // Base64-encoded PNG
	EffectValue   int    `json:"effectValue,omitempty"`
	Label         string `json:"label,omitempty"`
	Channel       string `json:"channel,omitempty"`
	State         string `json:"state,omitempty"` // "IDLE", "TALK", "LISTEN", "BROADCAST"
	ActionType    string `json:"actionType,omitempty"`
	Color         string `json:"color,omitempty"`
	IsListening   bool   `json:"isListening,omitempty"`
	IsPTTSelected bool   `json:"isPttSelected,omitempty"`
}

ImageStreamMessage represents an image update message sent via WebSocket

type LoginConflictResponse

type LoginConflictResponse struct {
	RequiresTakeover bool   `json:"requiresTakeover"`
	ConflictRoleID   string `json:"conflictRoleId"`
	ConflictRoleName string `json:"conflictRoleName,omitempty"`
	ConflictUsername string `json:"conflictUsername,omitempty"`
}

type LoginRequest

type LoginRequest struct {
	Username string `json:"username"`
	RoleID   string `json:"roleId"`
}

type LoginResponse

type LoginResponse struct {
	Token                string `json:"token"`
	User                 User   `json:"user"`
	ShowBirthdayGreeting bool   `json:"showBirthdayGreeting,omitempty"`
}

type LoginTakeoverRequest

type LoginTakeoverRequest struct {
	Username string `json:"username"`
	RoleID   string `json:"roleId"`
}

type MediaBridge

type MediaBridge interface {
	// RoutingForSource returns the per-destination gate map for the given
	// source token. Implementations may return a nil map if the source is
	// unknown.
	RoutingForSource(sourceToken string) map[string]bool
	// BridgeNativeOpusToWebRTC pushes a native-origin Opus frame into the
	// WebRTC fan-out for the given source token. The implementation is
	// responsible for repacking into RTP and respecting routing gates.
	BridgeNativeOpusToWebRTC(sourceToken string, opus []byte)
}

MediaBridge is the slim contract MediaManager (or any future SFU) implements so the relay can hand off native source frames to WebRTC destinations and query the routing snapshot.

type MediaManager

type MediaManager struct {
	// contains filtered or unexported fields
}

func NewMediaManager

func NewMediaManager(hub *Hub, logger *slog.Logger) *MediaManager

func (*MediaManager) BridgeNativeOpusToWebRTC

func (m *MediaManager) BridgeNativeOpusToWebRTC(sourceToken string, opus []byte)

BridgeNativeOpusToWebRTC writes a single Opus frame originating from a native UDP source to all WebRTC peers that the routing snapshot says should hear this source.

func (*MediaManager) EnsureNativeSource

func (m *MediaManager) EnsureNativeSource(sourceToken string, userID string) error

EnsureNativeSource is called when a native (UDP) source first delivers a frame for a given session token. It creates a shared StaticSample track and attaches it to all currently-connected WebRTC peers that the routing snapshot says should hear this source.

func (*MediaManager) EnsureNegotiation

func (m *MediaManager) EnsureNegotiation(token string)

func (*MediaManager) EnsurePeer

func (m *MediaManager) EnsurePeer(token string, user User) error

func (*MediaManager) HandleAnswer

func (m *MediaManager) HandleAnswer(token string, sdp string) error

func (*MediaManager) HandleICECandidate

func (m *MediaManager) HandleICECandidate(token string, c WebRTCIceCandidate) error

func (*MediaManager) NoteVoiceStateTrigger

func (m *MediaManager) NoteVoiceStateTrigger()

func (*MediaManager) RealtimeStats

func (m *MediaManager) RealtimeStats() MediaRealtimeStats

func (*MediaManager) RemovePeer

func (m *MediaManager) RemovePeer(token string)

func (*MediaManager) RoutingForSource

func (m *MediaManager) RoutingForSource(sourceToken string) map[string]bool

RoutingForSource is the MediaBridge implementation used by UDPAudioRelay to learn which native destinations should receive a given native source's audio frames.

func (*MediaManager) SetBroadcastGroupActive

func (m *MediaManager) SetBroadcastGroupActive(sourceToken, groupID string, enabled bool)

func (*MediaManager) SetDirectTargetActive

func (m *MediaManager) SetDirectTargetActive(sourceToken, targetUserID string, enabled bool)

func (*MediaManager) SetIdleRoomFallbackSuppressed

func (m *MediaManager) SetIdleRoomFallbackSuppressed(sourceToken string, suppressed bool)

func (*MediaManager) SetUDPAudioRelay

func (m *MediaManager) SetUDPAudioRelay(relay *UDPAudioRelay)

SetUDPAudioRelay wires the relay into MediaManager and registers the bidirectional bridge so the relay can push native frames to WebRTC dests.

func (*MediaManager) SyncRouting

func (m *MediaManager) SyncRouting()

func (*MediaManager) SyncRoutingSource

func (m *MediaManager) SyncRoutingSource(sourceToken string)

type MediaRealtimeStats

type MediaRealtimeStats struct {
	Peers                 int    `json:"peers"`
	Sources               int    `json:"sources"`
	SyncRequests          uint64 `json:"syncRequests"`
	SyncRuns              uint64 `json:"syncRuns"`
	SyncRequestsCoalesced uint64 `json:"syncRequestsCoalesced"`
	SyncDirtySourcesAvg   uint64 `json:"syncDirtySourcesAvg"`
	SyncDirtySourcesMax   uint64 `json:"syncDirtySourcesMax"`
	SyncRunAvgMs          uint64 `json:"syncRunAvgMs"`
	SyncRunMaxMs          uint64 `json:"syncRunMaxMs"`
	SyncLockWaitAvgMs     uint64 `json:"syncLockWaitAvgMs"`
	SyncLockWaitMaxMs     uint64 `json:"syncLockWaitMaxMs"`
	SyncLockHoldAvgMs     uint64 `json:"syncLockHoldAvgMs"`
	SyncLockHoldMaxMs     uint64 `json:"syncLockHoldMaxMs"`
	VoiceStateToSyncAvgMs uint64 `json:"voiceStateToSyncAvgMs"`
	VoiceStateToSyncMaxMs uint64 `json:"voiceStateToSyncMaxMs"`
	Renegotiations        uint64 `json:"renegotiations"`
	RenegotiationAvgMs    uint64 `json:"renegotiationAvgMs"`
	RenegotiationMaxMs    uint64 `json:"renegotiationMaxMs"`
}

type NativeAudioEndpoint

type NativeAudioEndpoint struct {
	Host          string `json:"host"`
	Port          int    `json:"port"`
	Token         string `json:"token"`
	TokenHash     uint32 `json:"tokenHash"`
	FrameDuration int    `json:"frameDurationMs"`
	SampleRate    int    `json:"sampleRate"`
	Channels      int    `json:"channels"`
}

NativeAudioEndpoint is sent over the WebSocket to native (Tauri) clients that requested the performance transport. It contains the UDP relay address the client should send Opus frames to, plus the session token (echoed back for the REGISTER packet). Browser clients never receive this message.

type PolicyCacheStats

type PolicyCacheStats struct {
	RoomPolicyHits         uint64 `json:"roomPolicyHits"`
	RoomPolicyMisses       uint64 `json:"roomPolicyMisses"`
	BroadcastAllowedHits   uint64 `json:"broadcastAllowedHits"`
	BroadcastAllowedMisses uint64 `json:"broadcastAllowedMisses"`
	BroadcastRoomHits      uint64 `json:"broadcastRoomHits"`
	BroadcastRoomMisses    uint64 `json:"broadcastRoomMisses"`
	ForcedListenHits       uint64 `json:"forcedListenHits"`
	ForcedListenMisses     uint64 `json:"forcedListenMisses"`
}

type PresenceState

type PresenceState struct {
	UserID          string   `json:"userId"`
	Username        string   `json:"username"`
	RoleID          string   `json:"roleId"`
	ListenRooms     []string `json:"listenRooms"`
	TalkRooms       []string `json:"talkRooms"`
	VoiceMode       string   `json:"voiceMode"`
	MicEnabled      bool     `json:"micEnabled"`
	BroadcastActive bool     `json:"broadcastActive"`
}

type PublicBootstrapResponse

type PublicBootstrapResponse struct {
	Roles           []Role           `json:"roles"`
	Rooms           []Room           `json:"rooms"`
	BroadcastGroups []BroadcastGroup `json:"broadcastGroups"`
	AckEnabled      bool             `json:"ackEnabled"`
	AppVersion      VersionInfo      `json:"appVersion"`
}

type RealtimeStatsResponse

type RealtimeStatsResponse struct {
	Hub              HubRealtimeStats   `json:"hub"`
	Media            MediaRealtimeStats `json:"media"`
	StorePolicyCache PolicyCacheStats   `json:"storePolicyCache"`
	TimestampUnixMs  int64              `json:"timestampUnixMs"`
}

type Role

type Role struct {
	ID                string `json:"id"`
	Name              string `json:"name"`
	DefaultRoomID     string `json:"defaultRoomId,omitempty"`
	DefaultVoiceMode  string `json:"defaultVoiceMode,omitempty"`
	DefaultSimpleView bool   `json:"defaultSimpleView,omitempty"`
}

type Room

type Room struct {
	ID                  string   `json:"id"`
	Name                string   `json:"name"`
	PriorityLevel       int      `json:"priorityLevel"`
	SenderRoleIDs       []string `json:"senderRoleIds"`
	ReceiverRoleIDs     []string `json:"receiverRoleIds"`
	ForcedListenRoleIDs []string `json:"forcedListenRoleIds"`
}

type RoomMatrixEvent

type RoomMatrixEvent struct {
	ListenRoomIDs []string `json:"listenRoomIds"`
	TalkRoomIDs   []string `json:"talkRoomIds"`
}

type RoomPermissionEntry

type RoomPermissionEntry struct {
	RoomID              string   `json:"roomId"`
	SenderRoleIDs       []string `json:"senderRoleIds"`
	ReceiverRoleIDs     []string `json:"receiverRoleIds"`
	ForcedListenRoleIDs []string `json:"forcedListenRoleIds"`
}

RoomPermissionEntry describes the sender/receiver/forced-listen role mapping for one room.

type RoutedEvent

type RoutedEvent struct {
	Scope       string `json:"scope"`
	TargetType  string `json:"targetType,omitempty"`
	TargetID    string `json:"targetId"`
	Body        string `json:"body"`
	Source      string `json:"source,omitempty"`
	Signal      string `json:"signal,omitempty"`
	MessageID   string `json:"messageId,omitempty"`
	AckRequired bool   `json:"ackRequired,omitempty"`
	Acked       bool   `json:"acked,omitempty"`
	AckedBy     *User  `json:"ackedBy,omitempty"`
	AckedAt     int64  `json:"ackedAt,omitempty"`
	FromUser    User   `json:"fromUser"`
	Timestamp   int64  `json:"timestamp"`
}

type RoutingStatusEvent

type RoutingStatusEvent struct {
	Code       string `json:"code"`
	TargetType string `json:"targetType,omitempty"`
	Target     string `json:"target,omitempty"`
	Message    string `json:"message"`
	Timestamp  int64  `json:"timestamp"`
}

type Server

type Server struct {
	// contains filtered or unexported fields
}

func NewServer

func NewServer(cfg Config) (*Server, error)

func (*Server) HandleDebugButtonImage

func (s *Server) HandleDebugButtonImage(w http.ResponseWriter, r *http.Request)

HandleDebugButtonImage renders a single button image as PNG for browser-based inspection.

func (*Server) HandleDebugButtonImagePreview

func (s *Server) HandleDebugButtonImagePreview(w http.ResponseWriter, r *http.Request)

HandleDebugButtonImagePreview serves a tiny HTML page to inspect generated images.

func (*Server) HandleImageStreamWebSocket

func (s *Server) HandleImageStreamWebSocket(w http.ResponseWriter, r *http.Request)

HandleImageStreamWebSocket handles WebSocket connections for image streaming

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

type Session

type Session struct {
	Token     string
	UserID    string
	Username  string
	RoleID    string
	ExpiresAt time.Time
}

type SessionManager

type SessionManager struct {
	// contains filtered or unexported fields
}

func NewSessionManager

func NewSessionManager(ttl time.Duration) *SessionManager

func (*SessionManager) CancelScheduledDisconnectLogout

func (m *SessionManager) CancelScheduledDisconnectLogout(token string) bool

func (*SessionManager) Create

func (m *SessionManager) Create(user User) Session

func (*SessionManager) Delete

func (m *SessionManager) Delete(token string)

func (*SessionManager) DeleteByRole

func (m *SessionManager) DeleteByRole(roleID string) []Session

func (*SessionManager) DeleteByUsername

func (m *SessionManager) DeleteByUsername(username string) []Session

func (*SessionManager) Get

func (m *SessionManager) Get(token string) (Session, bool)

func (*SessionManager) LatestForRole

func (m *SessionManager) LatestForRole(roleID string) (Session, bool)

func (*SessionManager) ScheduleDisconnectLogout

func (m *SessionManager) ScheduleDisconnectLogout(token string, delay time.Duration) bool

type SessionRevokedEvent

type SessionRevokedEvent struct {
	Reason    string `json:"reason"`
	Timestamp int64  `json:"timestamp"`
}

type StatusResponse

type StatusResponse struct {
	RoomListenerCounts map[string]int `json:"roomListenerCounts"`
	TimestampUnixMs    int64          `json:"timestampUnixMs"`
}

type Store

type Store struct {
	// contains filtered or unexported fields
}

func NewStore

func NewStore(dbPath string) (*Store, error)

func (*Store) BindTelegramAllowlistEntryNumericID

func (s *Store) BindTelegramAllowlistEntryNumericID(ctx context.Context, telegramUsername, numericID string) error

BindTelegramAllowlistEntryNumericID binds the telegram_numeric_id for a user (TOFU - Trust On First Use).

func (*Store) BroadcastGroupAllowsRole

func (s *Store) BroadcastGroupAllowsRole(ctx context.Context, groupID, roleID string) (bool, error)

func (*Store) BroadcastGroupRoomIDs

func (s *Store) BroadcastGroupRoomIDs(ctx context.Context, groupID string) ([]string, error)

func (*Store) BulkUpdateRoomPermissions

func (s *Store) BulkUpdateRoomPermissions(ctx context.Context, entries []RoomPermissionEntry) error

BulkUpdateRoomPermissions updates sender/receiver role mappings for multiple rooms in a single transaction. It only touches role mappings — room names are left unchanged.

func (*Store) Close

func (s *Store) Close() error

func (*Store) CreateBroadcastGroup

func (s *Store) CreateBroadcastGroup(ctx context.Context, id, name string, roomIDs, allowedRoleIDs []string) error

func (*Store) CreateRole

func (s *Store) CreateRole(ctx context.Context, id, name, defaultRoomID, defaultVoiceMode string, defaultSimpleView bool) error

func (*Store) CreateRoom

func (s *Store) CreateRoom(ctx context.Context, id, name string, senderRoleIDs, receiverRoleIDs, forcedListenRoleIDs []string) error

func (*Store) CreateTelegramAllowlistEntry

func (s *Store) CreateTelegramAllowlistEntry(ctx context.Context, id, telegramUsername, kesherUsername string) error

CreateTelegramAllowlistEntry adds a new Telegram user to the allowlist. The telegramNumericID is initially empty and will be bound on first login (TOFU).

func (*Store) CreateTelegramMapping

func (s *Store) CreateTelegramMapping(ctx context.Context, id, chatID, label, roomID string) error

func (*Store) CreateTelegramUserMapping

func (s *Store) CreateTelegramUserMapping(ctx context.Context, id, telegramUserID, username, privateChatID string) error

func (*Store) DeleteBroadcastGroup

func (s *Store) DeleteBroadcastGroup(ctx context.Context, id string) error

func (*Store) DeleteRole

func (s *Store) DeleteRole(ctx context.Context, id string) error

func (*Store) DeleteRoleStreamDeckSettings

func (s *Store) DeleteRoleStreamDeckSettings(ctx context.Context, roleID string) error

func (*Store) DeleteRoom

func (s *Store) DeleteRoom(ctx context.Context, id string) error

func (*Store) DeleteTelegramAllowlistEntry

func (s *Store) DeleteTelegramAllowlistEntry(ctx context.Context, id string) error

DeleteTelegramAllowlistEntry removes a user from the allowlist.

func (*Store) DeleteTelegramMapping

func (s *Store) DeleteTelegramMapping(ctx context.Context, id string) error

func (*Store) DeleteUser

func (s *Store) DeleteUser(ctx context.Context, id string) error

func (*Store) DeleteUserStreamDeckSettings

func (s *Store) DeleteUserStreamDeckSettings(ctx context.Context, userID string) error

func (*Store) FindTelegramAllowlistEntryByNumericID

func (s *Store) FindTelegramAllowlistEntryByNumericID(ctx context.Context, numericID string) (TelegramAllowlistEntry, error)

FindTelegramAllowlistEntryByNumericID finds an allowlist entry by numeric Telegram ID.

func (*Store) FindTelegramAllowlistEntryByUsername

func (s *Store) FindTelegramAllowlistEntryByUsername(ctx context.Context, telegramUsername string) (TelegramAllowlistEntry, error)

FindTelegramAllowlistEntryByUsername finds an allowlist entry by Telegram username (case-insensitive).

func (*Store) FindTelegramMappingByChatID

func (s *Store) FindTelegramMappingByChatID(ctx context.Context, chatID string) (TelegramMapping, error)

func (*Store) FindTelegramUserMappingByTelegramID

func (s *Store) FindTelegramUserMappingByTelegramID(ctx context.Context, telegramUserID string) (TelegramUserMapping, error)

func (*Store) FindTelegramUserMappingByUsername

func (s *Store) FindTelegramUserMappingByUsername(ctx context.Context, username string) (TelegramUserMapping, error)

func (*Store) FindUserByID

func (s *Store) FindUserByID(ctx context.Context, id string) (User, error)

func (*Store) FindUserByUsername

func (s *Store) FindUserByUsername(ctx context.Context, username string) (User, error)

func (*Store) ForcedListenRoomIDs

func (s *Store) ForcedListenRoomIDs(ctx context.Context, roleID string) ([]string, error)

ForcedListenRoomIDs returns the list of room IDs that the given role must listen to.

func (*Store) GetAdminPIN

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

func (*Store) GetAllCompanionRolePages

func (s *Store) GetAllCompanionRolePages(ctx context.Context) (map[string]int, error)

func (*Store) GetBirthdayUsersToday

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

func (*Store) GetCompanionProfileByRole

func (s *Store) GetCompanionProfileByRole(ctx context.Context, roleID string) (CompanionProfileResponse, error)

func (*Store) GetCompanionRolePage

func (s *Store) GetCompanionRolePage(ctx context.Context, roleID string) (int, error)

func (*Store) GetRoleStreamDeckSettings

func (s *Store) GetRoleStreamDeckSettings(ctx context.Context, roleID string) (StreamDeckSettings, error)

func (*Store) GetSubscribedTelegramUsersForRoom

func (s *Store) GetSubscribedTelegramUsersForRoom(ctx context.Context, roomID string) ([]string, error)

GetSubscribedTelegramUsersForRoom returns all telegram user IDs subscribed to a specific room.

func (*Store) GetTelegramUserRoomSubscriptions

func (s *Store) GetTelegramUserRoomSubscriptions(ctx context.Context, telegramUserID string) ([]string, error)

GetTelegramUserRoomSubscriptions returns all room IDs that a telegram user is subscribed to.

func (*Store) GetUserStreamDeckSettings

func (s *Store) GetUserStreamDeckSettings(ctx context.Context, userID string) (StreamDeckSettings, error)

func (*Store) IsTelegramUserSubscribedToRoom

func (s *Store) IsTelegramUserSubscribedToRoom(ctx context.Context, telegramUserID, roomID string) (bool, error)

IsTelegramUserSubscribedToRoom checks if a telegram user is subscribed to a specific room.

func (*Store) ListBroadcastGroups

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

func (*Store) ListRoleStreamDeckSettings

func (s *Store) ListRoleStreamDeckSettings(ctx context.Context) (map[string]StreamDeckSettings, error)

func (*Store) ListRoles

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

func (*Store) ListRooms

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

func (*Store) ListTelegramAllowlistEntries

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

ListTelegramAllowlistEntries returns all allowlist entries with computed status.

func (*Store) ListTelegramMappings

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

func (*Store) ListUserStreamDeckSettingsByUsername

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

func (*Store) ListUsers

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

func (*Store) PolicyCacheStats

func (s *Store) PolicyCacheStats() PolicyCacheStats

func (*Store) PublishCompanionProfile

func (s *Store) PublishCompanionProfile(ctx context.Context, roleID string, publishedByUserID string, profile CompanionProfileResponse) (CompanionProfileResponse, error)

func (*Store) ReplaceConfiguration

func (s *Store) ReplaceConfiguration(ctx context.Context, state configurationState, updateUsers bool, rewriteStreamDeck bool) error

func (*Store) ResolveSinglePublishedCompanionRole

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

func (*Store) RoleExists

func (s *Store) RoleExists(ctx context.Context, roleID string) (bool, error)

func (*Store) RoomAllowsReceiverRole

func (s *Store) RoomAllowsReceiverRole(ctx context.Context, roomID, roleID string) (bool, error)

func (*Store) RoomAllowsSenderRole

func (s *Store) RoomAllowsSenderRole(ctx context.Context, roomID, roleID string) (bool, error)

func (*Store) SaveCompanionRolePage

func (s *Store) SaveCompanionRolePage(ctx context.Context, roleID string, pageNumber int) error

func (*Store) SetAdminPIN

func (s *Store) SetAdminPIN(ctx context.Context, pin string) error

func (*Store) SetBirthdayUsersToday

func (s *Store) SetBirthdayUsersToday(ctx context.Context, usernames []string) error

func (*Store) SetBroadcastGroupPriorityLevel

func (s *Store) SetBroadcastGroupPriorityLevel(ctx context.Context, id string, priorityLevel int) error

func (*Store) SetRoomPriorityLevel

func (s *Store) SetRoomPriorityLevel(ctx context.Context, id string, priorityLevel int) error

func (*Store) ToggleTelegramUserRoomSubscription

func (s *Store) ToggleTelegramUserRoomSubscription(ctx context.Context, telegramUserID, roomID string) (bool, error)

ToggleTelegramUserRoomSubscription toggles the subscription status (subscribe if not subscribed, unsubscribe if subscribed). Returns the new subscription status (true if subscribed, false if unsubscribed).

func (*Store) UpdateBroadcastGroup

func (s *Store) UpdateBroadcastGroup(ctx context.Context, id, name string, roomIDs, allowedRoleIDs []string) error

func (*Store) UpdateRole

func (s *Store) UpdateRole(ctx context.Context, id, name, defaultRoomID, defaultVoiceMode string, defaultSimpleView bool) error

func (*Store) UpdateRoom

func (s *Store) UpdateRoom(ctx context.Context, id, name string, senderRoleIDs, receiverRoleIDs, forcedListenRoleIDs []string) error

func (*Store) UpdateTelegramMapping

func (s *Store) UpdateTelegramMapping(ctx context.Context, id, chatID, label, roomID string) error

func (*Store) UpdateTelegramUserMapping

func (s *Store) UpdateTelegramUserMapping(ctx context.Context, id, username string) error

func (*Store) UpsertRoleStreamDeckSettings

func (s *Store) UpsertRoleStreamDeckSettings(ctx context.Context, roleID string, settings StreamDeckSettings) (StreamDeckSettings, error)

func (*Store) UpsertUser

func (s *Store) UpsertUser(ctx context.Context, username, roleID string) (User, error)

func (*Store) UpsertUserStreamDeckSettings

func (s *Store) UpsertUserStreamDeckSettings(ctx context.Context, userID string, settings StreamDeckSettings) (StreamDeckSettings, error)

type StreamDeckActionType

type StreamDeckActionType string
const (
	StreamDeckActionTypeNone           StreamDeckActionType = "none"
	StreamDeckActionTypePTTRoom        StreamDeckActionType = "ptt_room"
	StreamDeckActionTypeSelectTalkRoom StreamDeckActionType = "select_talk_room"
	StreamDeckActionTypeSelectListen   StreamDeckActionType = "select_listen_room"
	StreamDeckActionTypePTTSelected    StreamDeckActionType = "ptt_selected"
	StreamDeckActionTypeListenRoom     StreamDeckActionType = "listen_room"
	StreamDeckActionTypeCallRoom       StreamDeckActionType = "call_room"
	StreamDeckActionTypeDirectUser     StreamDeckActionType = "direct_user"
	StreamDeckActionTypeDirectRole     StreamDeckActionType = "direct_role"
	StreamDeckActionTypeReplyToCaller  StreamDeckActionType = "reply_to_caller"
	StreamDeckActionTypeIncomingCall   StreamDeckActionType = "incoming_call_indicator"
	StreamDeckActionTypeBroadcastPTT   StreamDeckActionType = "broadcast_ptt"
	StreamDeckActionTypeMuteToggle     StreamDeckActionType = "mute_toggle"
	StreamDeckActionTypeVolumeDelta    StreamDeckActionType = "volume_delta"
	StreamDeckActionTypePageUp         StreamDeckActionType = "page_up"
	StreamDeckActionTypePageDown       StreamDeckActionType = "page_down"
	StreamDeckActionTypePageJump       StreamDeckActionType = "page_jump"
	StreamDeckActionTypePageHome       StreamDeckActionType = "page_home"
	StreamDeckActionTypePageBack       StreamDeckActionType = "page_back"
)

type StreamDeckButtonAction

type StreamDeckButtonAction struct {
	Type             StreamDeckActionType `json:"type"`
	RoomID           string               `json:"roomId,omitempty"`
	UserID           string               `json:"userId,omitempty"`
	RoleID           string               `json:"roleId,omitempty"`
	BroadcastGroupID string               `json:"broadcastGroupId,omitempty"`
	VolumeDelta      int                  `json:"volumeDelta,omitempty"`
	TargetPage       int                  `json:"targetPage,omitempty"`
}

type StreamDeckButtonConfig

type StreamDeckButtonConfig struct {
	Index  int                     `json:"index"`
	Label  string                  `json:"label,omitempty"`
	Color  string                  `json:"color,omitempty"`
	Action *StreamDeckButtonAction `json:"action,omitempty"`
}

type StreamDeckPageConfig

type StreamDeckPageConfig struct {
	Page       int                      `json:"page"`
	Title      string                   `json:"title,omitempty"`
	PageType   StreamDeckPageType       `json:"pageType,omitempty"`
	ParentPage *int                     `json:"parentPage,omitempty"`
	Buttons    []StreamDeckButtonConfig `json:"buttons"`
}

type StreamDeckPageType

type StreamDeckPageType string
const (
	StreamDeckPageTypeManual        StreamDeckPageType = "manual"
	StreamDeckPageTypeAllRoles      StreamDeckPageType = "all_roles"
	StreamDeckPageTypeAllPartyLines StreamDeckPageType = "all_party_lines"
)

type StreamDeckSettings

type StreamDeckSettings struct {
	Version      int                    `json:"version"`
	GridColumns  int                    `json:"gridColumns"`
	GridRows     int                    `json:"gridRows"`
	SelectedPage int                    `json:"selectedPage"`
	Pages        []StreamDeckPageConfig `json:"pages"`
}

func DefaultStreamDeckSettings

func DefaultStreamDeckSettings() StreamDeckSettings

type TelegramAllowlistEntry

type TelegramAllowlistEntry struct {
	ID                string `json:"id"`
	TelegramUsername  string `json:"telegramUsername"`
	TelegramNumericID string `json:"telegramNumericId,omitempty"`
	KesherUsername    string `json:"kesherUsername"`
	CreatedAt         int64  `json:"createdAt"`
	Status            string `json:"status"`
	IsBound           bool   `json:"isBound"`
}

type TelegramBot

type TelegramBot struct {
	// contains filtered or unexported fields
}

TelegramBot handles receiving and sending Telegram messages.

func NewTelegramBot

func NewTelegramBot(token, webhookSecret, mode string, store *Store, hub *Hub, logger *slog.Logger) *TelegramBot

func (*TelegramBot) DeleteWebhook

func (t *TelegramBot) DeleteWebhook() error

DeleteWebhook removes any previously set webhook so polling works cleanly.

func (*TelegramBot) HandleWebhook

func (t *TelegramBot) HandleWebhook(w http.ResponseWriter, r *http.Request)

HandleWebhook processes incoming Telegram webhook updates.

func (*TelegramBot) Mode

func (t *TelegramBot) Mode() string

Mode returns the configured mode ("polling" or "webhook").

func (*TelegramBot) StartPolling

func (t *TelegramBot) StartPolling()

StartPolling begins long-polling the Telegram getUpdates API. This is suitable for servers behind NAT/firewall without a public IP.

func (*TelegramBot) StopPolling

func (t *TelegramBot) StopPolling()

StopPolling gracefully stops the long-polling goroutine.

type TelegramCallbackQuery

type TelegramCallbackQuery struct {
	ID      string           `json:"id"`
	From    *TelegramUser    `json:"from"`
	Message *TelegramMessage `json:"message,omitempty"`
	Data    string           `json:"data"`
}

type TelegramChat

type TelegramChat struct {
	ID   int64  `json:"id"`
	Type string `json:"type"`
}

type TelegramInlineKeyboardButton

type TelegramInlineKeyboardButton struct {
	Text         string `json:"text"`
	CallbackData string `json:"callback_data"`
}

type TelegramInlineKeyboardMarkup

type TelegramInlineKeyboardMarkup struct {
	InlineKeyboard [][]TelegramInlineKeyboardButton `json:"inline_keyboard"`
}

type TelegramInlineQuery

type TelegramInlineQuery struct {
	ID     string        `json:"id"`
	From   *TelegramUser `json:"from"`
	Query  string        `json:"query"`
	Offset string        `json:"offset"`
}

type TelegramInlineQueryResultArticle

type TelegramInlineQueryResultArticle struct {
	Type                string                      `json:"type"`
	ID                  string                      `json:"id"`
	Title               string                      `json:"title"`
	InputMessageContent TelegramInputMessageContent `json:"input_message_content"`
	Description         string                      `json:"description,omitempty"`
}

type TelegramInputMessageContent

type TelegramInputMessageContent struct {
	MessageText string `json:"message_text"`
}

type TelegramMapping

type TelegramMapping struct {
	ID     string `json:"id"`
	ChatID string `json:"chatId"`
	Label  string `json:"label"`
	RoomID string `json:"roomId"`
}

type TelegramMessage

type TelegramMessage struct {
	MessageID int64         `json:"message_id"`
	From      *TelegramUser `json:"from,omitempty"`
	Chat      TelegramChat  `json:"chat"`
	Text      string        `json:"text,omitempty"`
}

type TelegramStatusResponse

type TelegramStatusResponse struct {
	BotConfigured bool              `json:"botConfigured"`
	Mode          string            `json:"mode"` // "polling" or "webhook"
	Mappings      []TelegramMapping `json:"mappings"`
}

type TelegramUpdate

type TelegramUpdate struct {
	UpdateID      int64                  `json:"update_id"`
	Message       *TelegramMessage       `json:"message,omitempty"`
	CallbackQuery *TelegramCallbackQuery `json:"callback_query,omitempty"`
	InlineQuery   *TelegramInlineQuery   `json:"inline_query,omitempty"`
}

type TelegramUser

type TelegramUser struct {
	ID        int64  `json:"id"`
	FirstName string `json:"first_name"`
	Username  string `json:"username,omitempty"`
}

type TelegramUserMapping

type TelegramUserMapping struct {
	ID             string `json:"id"`
	TelegramUserID string `json:"telegramUserId"`
	Username       string `json:"username"`
	PrivateChatID  string `json:"privateChatId"`
	CreatedAt      int64  `json:"createdAt"`
}

type UDPAudioPacket

type UDPAudioPacket struct {
	Flags     byte
	Sequence  uint16
	Timestamp uint32
	TokenHash uint32
	Payload   []byte
}

UDPAudioPacket is the parsed view of a single relay datagram.

func DecodeUDPAudioPacket

func DecodeUDPAudioPacket(buf []byte) (UDPAudioPacket, error)

DecodeUDPAudioPacket parses a datagram. The returned Payload aliases the caller's buffer; callers that retain it after the buffer is reused must copy.

type UDPAudioRelay

type UDPAudioRelay struct {
	// contains filtered or unexported fields
}

UDPAudioRelay is the central UDP listener and per-peer registry.

func NewUDPAudioRelay

func NewUDPAudioRelay(hub *Hub, logger *slog.Logger) *UDPAudioRelay

NewUDPAudioRelay creates the relay but does not start listening. Call Start to bind and begin the receive loop.

func (*UDPAudioRelay) Close

func (r *UDPAudioRelay) Close()

Close stops the relay and tears down peers.

func (*UDPAudioRelay) IsNativeRegistered

func (r *UDPAudioRelay) IsNativeRegistered(token string) bool

IsNativeRegistered returns true if the given token currently has an authenticated UDP peer with a fresh heartbeat.

func (*UDPAudioRelay) LocalAddr

func (r *UDPAudioRelay) LocalAddr() net.Addr

LocalAddr exposes the bound listen address (mainly for tests and for the Endpoint info that the hub sends to native clients).

func (*UDPAudioRelay) PeerByToken

func (r *UDPAudioRelay) PeerByToken(token string) *udpPeer

PeerByToken returns the bound peer for a session token, or nil.

func (*UDPAudioRelay) RemovePeer

func (r *UDPAudioRelay) RemovePeer(token string)

RemovePeer removes a session's binding from the relay. Called from the hub when a session disconnects.

func (*UDPAudioRelay) SendOpusToToken

func (r *UDPAudioRelay) SendOpusToToken(destToken string, opus []byte)

SendOpusToToken delivers a single Opus frame to a specific native destination. Used by the WebRTC bridge to fan out browser-origin audio to native listeners.

func (*UDPAudioRelay) SetMediaBridge

func (r *UDPAudioRelay) SetMediaBridge(b MediaBridge)

SetMediaBridge wires the WebRTC bridge after construction (avoids a circular dependency with MediaManager).

func (*UDPAudioRelay) Start

func (r *UDPAudioRelay) Start(addr string) error

Start binds to addr and launches the receive loop in a goroutine. addr must be in net.ListenPacket form (e.g. ":8081" or "0.0.0.0:8081").

func (*UDPAudioRelay) Stats

func (r *UDPAudioRelay) Stats() UDPAudioStats

Stats returns aggregated counters for monitoring.

type UDPAudioStats

type UDPAudioStats struct {
	Peers    int    `json:"peers"`
	RxFrames uint64 `json:"rxFrames"`
	TxFrames uint64 `json:"txFrames"`
}

PeerStats is a snapshot used in /api/realtime-stats.

type User

type User struct {
	ID       string `json:"id"`
	Username string `json:"username"`
	RoleID   string `json:"roleId"`
}

type VersionInfo

type VersionInfo struct {
	Version        string `json:"version"`
	BuildTimestamp string `json:"buildTimestamp"`
}

VersionInfo represents the version and build information.

func GetVersionInfo

func GetVersionInfo() VersionInfo

GetVersionInfo returns the current version and build timestamp.

type WSInbound

type WSInbound struct {
	Type string `json:"type"`
	Data any    `json:"data"`
}

type WSOutbound

type WSOutbound struct {
	Type string `json:"type"`
	Data any    `json:"data"`
}

type WebRTCAnswer

type WebRTCAnswer struct {
	SDP string `json:"sdp"`
}

type WebRTCIceCandidate

type WebRTCIceCandidate struct {
	Candidate     string `json:"candidate"`
	SDPMid        string `json:"sdpMid,omitempty"`
	SDPMLineIndex uint16 `json:"sdpMLineIndex,omitempty"`
}

type WebRTCOffer

type WebRTCOffer struct {
	SDP string `json:"sdp"`
}

Jump to

Keyboard shortcuts

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