Live video on the AT Protocol
1package analytics
2
3import (
4 pb "stream.place/streamplace/pkg/analytics/pb"
5)
6
7// Event represents an analytics event to be ingested
8type Event struct {
9 EventID string
10 EventType string
11 DeviceID string
12 DID *string
13 SessionID string
14 TimestampMs int64
15 StreamerDID string
16 StreamID *string
17 PropertiesJSON string
18 SchemaVersion uint16
19 ClientVersion string
20 Platform string
21}
22
23// RealtimeStatsRequest requests real-time statistics
24type RealtimeStatsRequest struct {
25 StreamerDid *string
26 WindowMinutes uint32
27}
28
29// RealtimeStatsResponse contains real-time statistics
30type RealtimeStatsResponse struct {
31 Streamers []StreamerRealtimeStats `json:"streamers"`
32}
33
34// StreamerRealtimeStats contains real-time stats for a single streamer
35type StreamerRealtimeStats struct {
36 StreamerDid string `json:"streamerDid"`
37 CurrentViewers uint64 `json:"currentViewers"`
38 TotalWatchTimeMs uint64 `json:"totalWatchTimeMs"`
39}
40
41// StreamerStatsRequest requests stats for a specific streamer
42type StreamerStatsRequest struct {
43 StreamerDid string
44 StartTimeMs *int64
45 EndTimeMs *int64
46}
47
48// StreamerStatsResponse contains aggregated stats for a streamer
49type StreamerStatsResponse struct {
50 StreamerDid string `json:"streamerDid"`
51 TotalViews uint64 `json:"totalViews"`
52 TotalWatchTimeMs uint64 `json:"totalWatchTimeMs"`
53 UniqueViewers uint64 `json:"uniqueViewers"`
54 DailyStats []DailyStats `json:"dailyStats"`
55}
56
57// DailyStats contains stats for a single day
58type DailyStats struct {
59 Date string `json:"date"`
60 Views uint64 `json:"views"`
61 WatchTimeMs uint64 `json:"watchTimeMs"`
62 UniqueViewers uint64 `json:"uniqueViewers"`
63}
64
65// ViewerHistoryRequest requests viewing history for a user
66type ViewerHistoryRequest struct {
67 Did string
68 StartTimeMs *int64
69 EndTimeMs *int64
70 Limit uint32
71}
72
73// ViewerHistoryResponse contains viewing history
74type ViewerHistoryResponse struct {
75 Sessions []WatchSession `json:"sessions"`
76}
77
78// WatchSession represents a single viewing session
79type WatchSession struct {
80 SessionId string `json:"sessionId"`
81 StreamerDid string `json:"streamerDid"`
82 StreamId *string `json:"streamId,omitempty"`
83 StartTimeMs int64 `json:"startTimeMs"`
84 EndTimeMs int64 `json:"endTimeMs"`
85 DurationMs uint64 `json:"durationMs"`
86}
87
88// Conversion helpers
89
90func convertRealtimeStatsResponse(pbResp *pb.RealtimeStatsResponse) *RealtimeStatsResponse {
91 if pbResp == nil {
92 return &RealtimeStatsResponse{}
93 }
94
95 streamers := make([]StreamerRealtimeStats, len(pbResp.Streamers))
96 for i, s := range pbResp.Streamers {
97 streamers[i] = StreamerRealtimeStats{
98 StreamerDid: s.StreamerDid,
99 CurrentViewers: s.CurrentViewers,
100 TotalWatchTimeMs: s.TotalWatchTimeMs,
101 }
102 }
103
104 return &RealtimeStatsResponse{
105 Streamers: streamers,
106 }
107}
108
109func convertStreamerStatsResponse(pbResp *pb.StreamerStatsResponse) *StreamerStatsResponse {
110 if pbResp == nil {
111 return &StreamerStatsResponse{}
112 }
113
114 dailyStats := make([]DailyStats, len(pbResp.DailyStats))
115 for i, s := range pbResp.DailyStats {
116 dailyStats[i] = DailyStats{
117 Date: s.Date,
118 Views: s.Views,
119 WatchTimeMs: s.WatchTimeMs,
120 UniqueViewers: s.UniqueViewers,
121 }
122 }
123
124 return &StreamerStatsResponse{
125 StreamerDid: pbResp.StreamerDid,
126 TotalViews: pbResp.TotalViews,
127 TotalWatchTimeMs: pbResp.TotalWatchTimeMs,
128 UniqueViewers: pbResp.UniqueViewers,
129 DailyStats: dailyStats,
130 }
131}
132
133func convertViewerHistoryResponse(pbResp *pb.ViewerHistoryResponse) *ViewerHistoryResponse {
134 if pbResp == nil {
135 return &ViewerHistoryResponse{}
136 }
137
138 sessions := make([]WatchSession, len(pbResp.Sessions))
139 for i, s := range pbResp.Sessions {
140 sessions[i] = WatchSession{
141 SessionId: s.SessionId,
142 StreamerDid: s.StreamerDid,
143 StreamId: s.StreamId,
144 StartTimeMs: s.StartTimeMs,
145 EndTimeMs: s.EndTimeMs,
146 DurationMs: s.DurationMs,
147 }
148 }
149
150 return &ViewerHistoryResponse{
151 Sessions: sessions,
152 }
153}