website/pkg/worker/barertc.go

140 lines
3.3 KiB
Go
Raw Permalink Normal View History

package worker
import (
"encoding/json"
2024-01-27 21:57:24 +00:00
"io"
"net/http"
"sync"
"time"
"code.nonshy.com/nonshy/website/pkg/config"
"code.nonshy.com/nonshy/website/pkg/log"
)
// ChatStatistics is the json result of the BareRTC /api/statistics endpoint.
type ChatStatistics struct {
UserCount int
Usernames []string
2023-06-10 20:25:06 +00:00
Cameras struct {
Blue int
Red int
}
}
// GetChatStatistics returns the latest (cached) chat statistics.
2024-01-27 21:57:24 +00:00
func GetChatStatistics() *ChatStatistics {
chatStatisticsMu.RLock()
defer chatStatisticsMu.RUnlock()
2024-01-27 21:57:24 +00:00
return cachedChatStatistics
}
2023-07-08 00:31:46 +00:00
// SetChatStatistics updates the cached chat statistics, holding a write lock briefly.
func SetChatStatistics(stats *ChatStatistics) {
chatStatisticsMu.Lock()
defer chatStatisticsMu.Unlock()
2024-02-11 00:17:15 +00:00
if stats == nil {
cachedChatStatistics = &ChatStatistics{}
return
}
2023-07-08 00:31:46 +00:00
cachedChatStatistics = stats
}
2023-09-14 06:13:02 +00:00
// IsOnline returns whether the username is currently logged-in to chat.
2024-01-27 21:57:24 +00:00
func (cs *ChatStatistics) IsOnline(username string) bool {
2023-09-14 06:13:02 +00:00
for _, user := range cs.Usernames {
if user == username {
return true
}
}
return false
}
2024-01-27 21:57:24 +00:00
// SetOnlineNow patches the current ChatStatistics to mark a user as online immediately, e.g.
// because the main site has just sent them to the chat with a JWT token.
func (cs *ChatStatistics) SetOnlineNow(username string) {
if !cs.IsOnline(username) {
chatStatisticsMu.Lock()
defer chatStatisticsMu.Unlock()
cs.Usernames = append(cs.Usernames, username)
}
}
2023-09-14 06:13:02 +00:00
type UserOnChatMap map[string]bool
// MapUsersOnline returns a hashmap of usernames to online status.
2024-01-27 21:57:24 +00:00
func (cs *ChatStatistics) MapUsersOnline(usernames []string) UserOnChatMap {
2023-09-14 06:13:02 +00:00
var result = UserOnChatMap{}
for _, user := range cs.Usernames {
result[user] = true
}
return result
}
// Get a result from the UserOnChatMap.
func (m UserOnChatMap) Get(username string) bool {
return m[username]
}
var (
2024-01-27 21:57:24 +00:00
cachedChatStatistics = &ChatStatistics{}
chatStatisticsMu sync.RWMutex
)
// WatchBareRTC is a worker goroutine that caches the current online chatters in the chat room.
func WatchBareRTC() {
if config.Current.BareRTC.JWTSecret == "" || config.Current.BareRTC.URL == "" {
log.Error("Worker (WatchBareRTC): chat room is not configured, will not watch chat room status")
return
}
// Check it immediately.
DoCheckBareRTC()
// And on an interval forever.
2023-06-10 18:51:50 +00:00
for {
time.Sleep(config.ChatStatusRefreshInterval)
DoCheckBareRTC()
}
}
// DoCheckBareRTC invokes the attempt to refresh data from the chat server about who's online.
func DoCheckBareRTC() {
log.Info("Refresh BareRTC")
req, err := http.NewRequest(http.MethodGet, config.Current.BareRTC.URL+"/api/statistics", nil)
if err != nil {
log.Error("WatchBareRTC: couldn't make request: %s", err)
2023-07-08 00:31:46 +00:00
SetChatStatistics(nil)
return
}
client := http.Client{
2023-06-10 18:51:50 +00:00
Timeout: 10 * time.Second,
}
res, err := client.Do(req)
if err != nil {
log.Error("WatchBareRTC: request error: %s", err)
2023-07-08 00:31:46 +00:00
SetChatStatistics(nil)
return
2023-06-10 18:51:50 +00:00
} else if res.StatusCode != http.StatusOK {
log.Error("WatchBareRTC: didn't get expected 200 OK from statistics endpoint, instead got: %s", res.Status)
2023-07-08 00:31:46 +00:00
SetChatStatistics(nil)
2023-06-10 18:51:50 +00:00
return
}
if res.StatusCode == http.StatusOK {
var cs ChatStatistics
2024-01-27 21:57:24 +00:00
body, _ := io.ReadAll(res.Body)
res.Body.Close()
if err = json.Unmarshal(body, &cs); err != nil {
log.Error("WatchBareRTC: json decode error: %s", err)
return
}
2023-07-08 00:31:46 +00:00
SetChatStatistics(&cs)
}
}