Files
go_win_template/internal/broadcaster/broadcaster.go
Geliebte e266d3098a feat: 抖音直播间弹幕监控 - Go+Wails 实现
后端:
- SQLite 数据层 (rooms/users/chat_logs/settings/error_logs)
- 抖音 WebSocket 抓取器 (proto 解析, 心跳, watchdog)
- __ac_signature 算法 (纯 Go 移植)
- a_bogus/sign.js 签名 (goja JS 引擎)
- Echo HTTP API 服务器 (端口 5000)
- SSE 事件广播
- 自动保活 + 授权守护
- PAYS 云授权对接

前端:
- 顶栏: 品牌 + 日志/调试/客户名单/授权/文档/房间控制/主题切换
- 添加直播间 (链接解析 + 关键词)
-  Dashboard (卡片/列表视图, 公开/匿名房筛选, 分页)
- 详情页 (多 tab 消息流, 右侧用户面板, 颜色标记, 精准客户, 已看标记)
- 精准客户名单 (跨房间汇总)
- 订阅授权页面 (登录/注册/购买)
- 使用帮助 + 系统调试
- 白昼/黑夜主题切换 (CSS 变量 + iconfont)
- 底部版权栏
2026-09-18 04:25:57 +08:00

67 lines
1.1 KiB
Go

package broadcaster
import (
"encoding/json"
"sync"
)
type Broadcaster struct {
chs []chan []byte
lk sync.Mutex
}
func NewBroadcaster() *Broadcaster {
return &Broadcaster{}
}
func (bc *Broadcaster) Register() chan []byte {
ch := make(chan []byte, 1000)
bc.lk.Lock()
bc.chs = append(bc.chs, ch)
bc.lk.Unlock()
return ch
}
func (bc *Broadcaster) Unregister(ch chan []byte) {
bc.lk.Lock()
defer bc.lk.Unlock()
for i, c := range bc.chs {
if c == ch {
bc.chs = append(bc.chs[:i], bc.chs[i+1:]...)
close(ch)
return
}
}
}
func (bc *Broadcaster) Broadcast(data map[string]interface{}) {
b, err := json.Marshal(data)
if err != nil {
return
}
bc.lk.Lock()
dead := make([]int, 0)
for i, ch := range bc.chs {
select {
case ch <- b:
default:
select {
case <-ch:
ch <- b
default:
dead = append(dead, i)
}
}
}
bc.lk.Unlock()
for j := len(dead) - 1; j >= 0; j-- {
bc.lk.Lock()
idx := dead[j]
if idx < len(bc.chs) {
close(bc.chs[idx])
bc.chs = append(bc.chs[:idx], bc.chs[idx+1:]...)
}
bc.lk.Unlock()
}
}