|-|-|
|./|项目小工具|
|B_I.go|字节整数互转模块|
-|F.go|websocks消息生成与检查模块|
+|F.go|websocket消息生成与检查模块|
|api.go|b站api获取模块|
---
\ No newline at end of file
|VERSION|项目版本|
|bili_danmu.go|主运行文件|
|go.mod|goMod文件|
-|ws.go|websocks连接模块|
---
---
if err != nil {log.Println(err);return}
if tmp,ok := obj.(*gtk.Entry); ok {
tmp.Connect("focus-out-event", func() {
- if t,e := tmp.GetText();e == nil && t != ``{
+ if t,e := tmp.GetText();e == nil {//可设置为空
danmu_send_form = t
log.Println("弹幕格式已设置为",danmu_send_form)
}
w2_Entry0_editting = true
})
tmp.Connect("focus-out-event", func() {
- w2_Entry0_editting = false
+ glib.TimeoutAdd(uint(3000), func()bool{//3s后才解除,避免刚想切换又变回去
+ w2_Entry0_editting = false
+ return false
+ })
})
}else{log.Println("cant find #want_room_id in .glade");return}
}
import (
"fmt"
"flag"
+ "time"
"strconv"
"os"
"os/signal"
p "github.com/qydysky/part"
+ ws "github.com/qydysky/part/websocket"
reply "github.com/qydysky/bili_danmu/Reply"
c "github.com/qydysky/bili_danmu/CV"
F "github.com/qydysky/bili_danmu/F"
//对每个弹幕服务器尝试
for _, v := range api.Url {
//ws启动
- ws := New_ws(v,map[string][]string{
- "Cookie":[]string{c.Cookie},
+ ws_c := ws.New_client(ws.Client{
+ Url:v,
+ TO:35 * 1000,
+ Func_abort_close:func(){danmulog.I(`服务器连接中断`)},
+ Func_normal_close:func(){danmulog.I(`服务器连接关闭`)},
+ Header:map[string][]string{
+ "Cookie":[]string{c.Cookie},
+ },
}).Handle()
-
+ if ws_c.Isclose() {
+ danmulog.E("连接错误", ws_c.Error())
+ continue
+ }
+
//SendChan 传入发送[]byte
//RecvChan 接收[]byte
danmulog.I("连接", v)
- ws.SendChan <- F.HelloGen(c.Roomid, api.Token)
- if F.HelloChe(<- ws.RecvChan) {
+ ws_c.SendChan <- F.HelloGen(c.Roomid, api.Token)
+ if F.HelloChe(<- ws_c.RecvChan) {
danmulog.I("已连接到房间", c.Uname, `(`, c.Roomid, `)`)
reply.Gui_show(`进入直播间: `+c.Uname+` (`+strconv.Itoa(c.Roomid)+`)`, `0room`)
if c.Title != `` {
}
//30s获取一次人气
go func(){
- danmulog.I("获取人气")
p.Sys().MTimeoutf(500)//500ms
- heartbeatmsg, heartinterval := F.Heartbeat()
- ws.Heartbeat(1000 * heartinterval, heartbeatmsg)
+ danmulog.I("获取人气")
+ go func(){
+ heartbeatmsg, heartinterval := F.Heartbeat()
+ for !ws_c.Isclose() {
+ ws_c.SendChan <- heartbeatmsg
+ time.Sleep(time.Millisecond*time.Duration(heartinterval))
+ }
+ }()
//传输变量,以便响应弹幕"弹幕机在么"
c.Live = api.Live
var break_sign bool
for !isclose {
select {
- case i := <- ws.RecvChan:
- if len(i) == 0 && ws.Isclose() {
+ case i := <- ws_c.RecvChan:
+ if len(i) == 0 && ws_c.Isclose() {
isclose = true
} else {
go reply.Reply(i)
}
case <- interrupt:
- ws.Close()
+ ws_c.Close()
danmulog.I("停止,等待服务器断开连接")
break_sign = true
exit_sign = true
case <- change_room_chan:
- ws.Close()
+ ws_c.Close()
danmulog.I("停止,等待服务器断开连接")
break_sign = true
}
github.com/miekg/dns v1.1.35 // indirect
github.com/mitchellh/mapstructure v1.4.0 // indirect
github.com/qydysky/bili_danmu v0.5.4
- github.com/qydysky/part v0.3.4 // indirect
+ github.com/qydysky/part v0.3.5-0.20201222061900-d0c0ca9fc246 // indirect
github.com/shirou/gopsutil v3.20.11+incompatible // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 // indirect
github.com/qydysky/part v0.3.3/go.mod h1:93s9ohLtzULet5ZPEUUWrT9BELC30oDZgRpgGSiDye4=
github.com/qydysky/part v0.3.4 h1:LddQ0WfEAZ5Wyi8L+x6BA4hOsZV7YN01gzEhQNy/64M=
github.com/qydysky/part v0.3.4/go.mod h1:93s9ohLtzULet5ZPEUUWrT9BELC30oDZgRpgGSiDye4=
+github.com/qydysky/part v0.3.5-0.20201222061900-d0c0ca9fc246 h1:MDhL/WQ4fGNjLWncGThw5JpI6AbxCvpiVIASOFIM464=
+github.com/qydysky/part v0.3.5-0.20201222061900-d0c0ca9fc246/go.mod h1:SxxNav0Z7DbsDLoG5uxo0wW5EKU/JBu2CAkZzZeLnX0=
github.com/qydysky/part/msgq v0.0.0-20201213031129-ca3253dc72ad h1:Jtzf509lQrkUMGTV0Sc6IDCAiR1VrBcHrIban7hpye4=
github.com/qydysky/part/msgq v0.0.0-20201213031129-ca3253dc72ad/go.mod h1:w32TkJNVtTJd4LOS09cq+4uYG6itcN2vsqw+slp44Rg=
github.com/qydysky/part/msgq v0.0.0-20201213120821-f36e49c32bba h1:1ew9dRpc0Rux0WkWeT/4AE15ynYWmL2D7onJEJIFOB8=
+++ /dev/null
-package bili_danmu
-
-import (
- "time"
-
- "github.com/gorilla/websocket"
-
- c "github.com/qydysky/bili_danmu/CV"
- p "github.com/qydysky/part"
- s "github.com/qydysky/part/signal"
-)
-
-type ws struct {
- Signal *s.Signal
- SendChan chan []byte
- RecvChan chan []byte
- TO int
- url string
- Header map[string][]string
-}
-
-func New_ws(url string,Header map[string][]string) (o *ws) {
- l := p.Logf().New().Base(-1, "ws.go>新建").Level(c.LogLevel).T("New_ws")
- defer l.Block()
-
- l.T("ok")
- o = new(ws)
- o.url = url
- o.Header = Header
- o.TO = 300 * 1000
- o.SendChan = make(chan []byte, 1e4)
- o.RecvChan = make(chan []byte, 1e4)
- return
-}
-
-func (i *ws) Handle() (o *ws) {
- o = i
- l := p.Logf().New().Base(-1, "ws.go>处理").Level(c.LogLevel).T("*ws.handle")
- defer l.Block()
-
- if o.Signal.Islive() {return}
- o.Signal = s.Init()
-
- if o.url == "" {
- l.E("o.url == \"\"")
- o.Signal.Done()
- return
- }
-
- go func(){
- defer func(){
- close(o.RecvChan)
- o.Signal.Done()
- }()
-
- c, _, err := websocket.DefaultDialer.Dial(o.url, o.Header)
- if err != nil {
- l.E(err)
- return
- }
- defer c.Close()
- l.T("ok")
-
- done := make(chan struct{})
-
- go func() {
- defer close(done)
-
- for {
- c.SetReadDeadline(time.Now().Add(time.Millisecond*time.Duration(o.TO)))
- _, message, err := c.ReadMessage()
- if err != nil {
- if e, ok := err.(*websocket.CloseError); ok {
- switch e.Code {
- case websocket.CloseNormalClosure:l.E("服务器关闭连接")
- case websocket.CloseAbnormalClosure:l.E("服务器中断连接")
- default:l.E(err);
- }
- }
- return
- }
- o.RecvChan <- message
- }
- }()
-
- for {
- select {
- case <- done:
- return
- case t := <- o.SendChan:
- err := c.WriteMessage(websocket.TextMessage, t)
- if err != nil {
- l.E("write:", err)
- return
- }
- c.SetWriteDeadline(time.Now().Add(time.Millisecond*time.Duration(o.TO)))
- case <- o.Signal.Chan:
- l.I("捕获到中断")
- // Cleanly close the connection by sending a close message and then
- // waiting (with timeout) for the server to close the connection.
- err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
- if err != nil {
- l.E(err)
- }
- select {
- case <- done:
- case <- time.After(time.Second):
- }
- return
- }
- }
- }()
- return
-}
-
-func (i *ws) Heartbeat(Millisecond int, msg []byte) (o *ws) {
- o = i
- l := p.Logf().New().Base(-1, "ws.go>心跳").Level(c.LogLevel).T("*ws.heartbeat")
- defer l.Block()
-
- if !o.Signal.Islive() {return}
- o.TO = Millisecond + 10 * 1000
-
- o.SendChan <- msg
- l.T("ok")
-
- go func(){
- ticker := time.NewTicker(time.Duration(Millisecond)*time.Millisecond)
- defer ticker.Stop()
-
- for {
- select {
- case <-ticker.C:
- o.SendChan <- msg
- case <- o.Signal.Chan:
- l.I("停止!")
- return
- }
- }
- }()
-
- return
-}
-
-func (o *ws) Close() {
- p.Logf().New().Base(-1, "ws.go>关闭").Level(c.LogLevel).I("关闭!").Block()
-
- o.Signal.Done()
-}
-
-func (o *ws) Isclose() bool {
- return !o.Signal.Islive()
-}
\ No newline at end of file