From 7e5bf28b6c596a1d9e05e299f65d45bf79c83017 Mon Sep 17 00:00:00 2001 From: Akiba Date: Wed, 25 May 2022 17:54:04 +0800 Subject: [PATCH 1/8] :art: realRoomID --- client/client.go | 60 ++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/client/client.go b/client/client.go index 83bb574..4b74831 100644 --- a/client/client.go +++ b/client/client.go @@ -15,6 +15,7 @@ import ( type Client struct { conn *websocket.Conn roomID string + realRoomID string token string host string eventHandlers *eventHandlers @@ -36,15 +37,18 @@ func NewClient(roomID string) *Client { func (c *Client) Connect() error { rid, _ := strconv.Atoi(c.roomID) - if rid <= 1000 { + if rid <= 1000 && c.realRoomID == "" { realID, err := api.GetRoomRealID(c.roomID) if err != nil { return err } c.roomID = realID + c.realRoomID = realID + } else { + c.realRoomID = c.roomID } if c.host == "" { - info, err := api.GetDanmuInfo(c.roomID) + info, err := api.GetDanmuInfo(c.realRoomID) if err != nil { return err } @@ -67,31 +71,33 @@ retry: return nil } -func (c *Client) Start() { - go func() { - for { - select { - case <-c.done: - log.Debug("current client closed") - return - default: - msgType, data, err := c.conn.ReadMessage() - if err != nil { - time.Sleep(time.Duration(3) * time.Millisecond) - _ = c.Connect() - continue - } - if msgType != websocket.BinaryMessage { - log.Error("packet not binary", data) - continue - } - for _, pkt := range packet.DecodePacket(data).Parse() { - go c.Handle(pkt) - } +func (c *Client) listen() { + for { + select { + case <-c.done: + log.Debug("current client closed") + return + default: + msgType, data, err := c.conn.ReadMessage() + if err != nil { + time.Sleep(time.Duration(3) * time.Millisecond) + _ = c.Connect() + continue + } + if msgType != websocket.BinaryMessage { + log.Error("packet not binary", data) + continue + } + for _, pkt := range packet.DecodePacket(data).Parse() { + go c.Handle(pkt) } } - }() - go c.startHeartBeat() + } +} + +func (c *Client) Start() { + go c.listen() + go c.heartBeat() } func (c *Client) Stop() { @@ -114,7 +120,7 @@ func (c *Client) UseDefaultHost() { c.SetHost("wss://broadcastlv.chat.bilibili.com/sub") } -func (c *Client) startHeartBeat() { +func (c *Client) heartBeat() { pkt := packet.NewHeartBeatPacket() for { select { @@ -130,7 +136,7 @@ func (c *Client) startHeartBeat() { } func (c *Client) sendEnterPacket() error { - rid, err := strconv.Atoi(c.roomID) + rid, err := strconv.Atoi(c.realRoomID) if err != nil { return errors.New("error roomID") } From 10d7821c2a009627a23e782c0863eadbfec7257f Mon Sep 17 00:00:00 2001 From: Akiba Date: Wed, 25 May 2022 17:54:36 +0800 Subject: [PATCH 2/8] :art: zero-copy byte-string convert --- utils/json.go | 7 +++++++ utils/strconv.go | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 utils/json.go create mode 100644 utils/strconv.go diff --git a/utils/json.go b/utils/json.go new file mode 100644 index 0000000..a5e6a52 --- /dev/null +++ b/utils/json.go @@ -0,0 +1,7 @@ +package utils + +import "encoding/json" + +func UnmarshalString(str string, v interface{}) error { + return json.Unmarshal(StringToBytes(str), v) +} diff --git a/utils/strconv.go b/utils/strconv.go new file mode 100644 index 0000000..fa1adf8 --- /dev/null +++ b/utils/strconv.go @@ -0,0 +1,18 @@ +package utils + +import ( + "unsafe" +) + +func StringToBytes(s string) []byte { + return *(*[]byte)(unsafe.Pointer( + &struct { + string + Cap int + }{s, len(s)}, + )) +} + +func BytesToString(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} From b4bc1a280f301d4303957fb7d2f19633a2ec763e Mon Sep 17 00:00:00 2001 From: Akiba Date: Wed, 25 May 2022 17:55:15 +0800 Subject: [PATCH 3/8] =?UTF-8?q?:art:=20parse=20=E5=87=8F=E5=B0=91=20gjson?= =?UTF-8?q?=20=E4=BD=BF=E7=94=A8=20=E4=BC=98=E5=8C=96=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- message/gift.go | 8 +++----- message/guard.go | 8 +++----- message/superchat.go | 7 ++----- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/message/gift.go b/message/gift.go index dcbd0b7..2950696 100644 --- a/message/gift.go +++ b/message/gift.go @@ -1,10 +1,8 @@ package message import ( - "bytes" "encoding/json" log "github.com/sirupsen/logrus" - "github.com/tidwall/gjson" ) type Gift struct { @@ -111,9 +109,9 @@ type ComboSend struct { } func (g *Gift) Parse(data []byte) { - sb := bytes.NewBuffer(data).String() - sd := gjson.Get(sb, "data").String() - err := json.Unmarshal([]byte(sd), g) + // len("{"cmd":"","data":") == 17 , len('SEND_GIFT') = 9 + d := data[17+9 : len(data)-1] + err := json.Unmarshal(d, g) if err != nil { log.Error("parse Gift failed") } diff --git a/message/guard.go b/message/guard.go index 4f2f0a6..b1ef303 100644 --- a/message/guard.go +++ b/message/guard.go @@ -1,10 +1,8 @@ package message import ( - "bytes" "encoding/json" log "github.com/sirupsen/logrus" - "github.com/tidwall/gjson" ) type GuardBuy struct { @@ -20,9 +18,9 @@ type GuardBuy struct { } func (g *GuardBuy) Parse(data []byte) { - sb := bytes.NewBuffer(data).String() - sd := gjson.Get(sb, "data").String() - err := json.Unmarshal([]byte(sd), g) + // len("{"cmd":"","data":") = 17 , len('GUARD_BUY') = 9 + d := data[17+9 : len(data)-1] + err := json.Unmarshal(d, g) if err != nil { log.Error("parse GuardBuy failed") } diff --git a/message/superchat.go b/message/superchat.go index 6596bad..c6a88f8 100644 --- a/message/superchat.go +++ b/message/superchat.go @@ -1,10 +1,8 @@ package message import ( - "bytes" "encoding/json" log "github.com/sirupsen/logrus" - "github.com/tidwall/gjson" ) // SuperChat @@ -72,9 +70,8 @@ type SuperChat struct { } func (s *SuperChat) Parse(data []byte) { - sb := bytes.NewBuffer(data).String() - sd := gjson.Get(sb, "data").String() - err := json.Unmarshal([]byte(sd), s) + // len('{"cmd":"","data":') = 17 , len('SUPER_CHAT_MESSAGE') = 18 + err := json.Unmarshal(data[17+18:len(data)-1], s) if err != nil { log.Error("parse superchat failed") } From 95bc1bedaa35c99c13792d3d7ff5ccba628f7b66 Mon Sep 17 00:00:00 2001 From: Akiba Date: Sat, 4 Jun 2022 09:15:46 +0800 Subject: [PATCH 4/8] :art: byte-string convert --- message/danmu.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/message/danmu.go b/message/danmu.go index 20920a5..8b83329 100644 --- a/message/danmu.go +++ b/message/danmu.go @@ -1,8 +1,7 @@ package message import ( - "bytes" - "encoding/json" + "github.com/Akegarasu/blivedm-go/utils" log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" ) @@ -60,15 +59,15 @@ type ( ) func (d *Danmaku) Parse(data []byte) { - sb := bytes.NewBuffer(data).String() - info := gjson.Get(sb, "info") + sb := utils.BytesToString(data) + info := gjson.Parse(sb).Get("info") ext := new(Extra) emo := new(Emoticon) - err := json.Unmarshal([]byte(info.Get("0.15.extra").String()), ext) + err := utils.UnmarshalString(info.Get("0.15.extra").String(), ext) if err != nil { log.Error("parse danmuku extra failed") } - err = json.Unmarshal([]byte(info.Get("0.13").String()), emo) + err = utils.UnmarshalString(info.Get("0.13").String(), emo) if err != nil { log.Error("parse danmuku emoticon failed") } From 2f60476e99547de986c2f2845cd43a0b66bf8300 Mon Sep 17 00:00:00 2001 From: Akiba Date: Sat, 4 Jun 2022 09:16:13 +0800 Subject: [PATCH 5/8] :bug: fix cmd --- client/handler.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/handler.go b/client/handler.go index c663f0c..e9963b4 100644 --- a/client/handler.go +++ b/client/handler.go @@ -8,6 +8,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" "runtime/debug" + "strings" ) var ( @@ -61,6 +62,11 @@ func (c *Client) Handle(p packet.Packet) { case packet.Notification: sb := bytes.NewBuffer(p.Body).String() cmd := gjson.Get(sb, "cmd").String() + // 新的弹幕 cmd 可能带参数 + if strings.Contains(cmd, ":") { + index := strings.Index(cmd, ":") + cmd = cmd[:index] + } // 优先执行自定义 eventHandler ,会覆盖库内自带的 handler f, ok := (*c.customEventHandlers)[cmd] if ok { From 72f0e29c3a012ecc945759e21157e02ceb781361 Mon Sep 17 00:00:00 2001 From: Akiba Date: Sat, 4 Jun 2022 09:16:58 +0800 Subject: [PATCH 6/8] =?UTF-8?q?Revert=20":art:=20parse=20=E5=87=8F?= =?UTF-8?q?=E5=B0=91=20gjson=20=E4=BD=BF=E7=94=A8=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=80=A7=E8=83=BD"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b4bc1a280f301d4303957fb7d2f19633a2ec763e. --- message/gift.go | 8 +++++--- message/guard.go | 8 +++++--- message/superchat.go | 7 +++++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/message/gift.go b/message/gift.go index 2950696..dcbd0b7 100644 --- a/message/gift.go +++ b/message/gift.go @@ -1,8 +1,10 @@ package message import ( + "bytes" "encoding/json" log "github.com/sirupsen/logrus" + "github.com/tidwall/gjson" ) type Gift struct { @@ -109,9 +111,9 @@ type ComboSend struct { } func (g *Gift) Parse(data []byte) { - // len("{"cmd":"","data":") == 17 , len('SEND_GIFT') = 9 - d := data[17+9 : len(data)-1] - err := json.Unmarshal(d, g) + sb := bytes.NewBuffer(data).String() + sd := gjson.Get(sb, "data").String() + err := json.Unmarshal([]byte(sd), g) if err != nil { log.Error("parse Gift failed") } diff --git a/message/guard.go b/message/guard.go index b1ef303..4f2f0a6 100644 --- a/message/guard.go +++ b/message/guard.go @@ -1,8 +1,10 @@ package message import ( + "bytes" "encoding/json" log "github.com/sirupsen/logrus" + "github.com/tidwall/gjson" ) type GuardBuy struct { @@ -18,9 +20,9 @@ type GuardBuy struct { } func (g *GuardBuy) Parse(data []byte) { - // len("{"cmd":"","data":") = 17 , len('GUARD_BUY') = 9 - d := data[17+9 : len(data)-1] - err := json.Unmarshal(d, g) + sb := bytes.NewBuffer(data).String() + sd := gjson.Get(sb, "data").String() + err := json.Unmarshal([]byte(sd), g) if err != nil { log.Error("parse GuardBuy failed") } diff --git a/message/superchat.go b/message/superchat.go index c6a88f8..6596bad 100644 --- a/message/superchat.go +++ b/message/superchat.go @@ -1,8 +1,10 @@ package message import ( + "bytes" "encoding/json" log "github.com/sirupsen/logrus" + "github.com/tidwall/gjson" ) // SuperChat @@ -70,8 +72,9 @@ type SuperChat struct { } func (s *SuperChat) Parse(data []byte) { - // len('{"cmd":"","data":') = 17 , len('SUPER_CHAT_MESSAGE') = 18 - err := json.Unmarshal(data[17+18:len(data)-1], s) + sb := bytes.NewBuffer(data).String() + sd := gjson.Get(sb, "data").String() + err := json.Unmarshal([]byte(sd), s) if err != nil { log.Error("parse superchat failed") } From 7ed9b1f5b44a74acbf4c90b137b6e95d7a941d2d Mon Sep 17 00:00:00 2001 From: Akiba Date: Sat, 4 Jun 2022 09:17:40 +0800 Subject: [PATCH 7/8] :art: remove log formatter --- go.mod | 1 - go.sum | 6 ------ 2 files changed, 7 deletions(-) diff --git a/go.mod b/go.mod index d70698e..347215a 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,5 @@ require ( github.com/andybalholm/brotli v1.0.4 github.com/gorilla/websocket v1.4.2 github.com/sirupsen/logrus v1.8.1 - github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 github.com/tidwall/gjson v1.13.0 ) diff --git a/go.sum b/go.sum index 8b599f8..187337c 100644 --- a/go.sum +++ b/go.sum @@ -4,23 +4,17 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk= -github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA= github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M= github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From f69fa048638d417f653bd80f706b8ea666c8a2d1 Mon Sep 17 00:00:00 2001 From: Akiba Date: Sat, 4 Jun 2022 09:21:59 +0800 Subject: [PATCH 8/8] :art: byte-string convert --- message/gift.go | 7 +++---- message/guard.go | 7 +++---- message/superchat.go | 7 +++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/message/gift.go b/message/gift.go index dcbd0b7..538c6c6 100644 --- a/message/gift.go +++ b/message/gift.go @@ -1,8 +1,7 @@ package message import ( - "bytes" - "encoding/json" + "github.com/Akegarasu/blivedm-go/utils" log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" ) @@ -111,9 +110,9 @@ type ComboSend struct { } func (g *Gift) Parse(data []byte) { - sb := bytes.NewBuffer(data).String() + sb := utils.BytesToString(data) sd := gjson.Get(sb, "data").String() - err := json.Unmarshal([]byte(sd), g) + err := utils.UnmarshalString(sd, g) if err != nil { log.Error("parse Gift failed") } diff --git a/message/guard.go b/message/guard.go index 4f2f0a6..a54d1ab 100644 --- a/message/guard.go +++ b/message/guard.go @@ -1,8 +1,7 @@ package message import ( - "bytes" - "encoding/json" + "github.com/Akegarasu/blivedm-go/utils" log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" ) @@ -20,9 +19,9 @@ type GuardBuy struct { } func (g *GuardBuy) Parse(data []byte) { - sb := bytes.NewBuffer(data).String() + sb := utils.BytesToString(data) sd := gjson.Get(sb, "data").String() - err := json.Unmarshal([]byte(sd), g) + err := utils.UnmarshalString(sd, g) if err != nil { log.Error("parse GuardBuy failed") } diff --git a/message/superchat.go b/message/superchat.go index 6596bad..9b924ac 100644 --- a/message/superchat.go +++ b/message/superchat.go @@ -1,8 +1,7 @@ package message import ( - "bytes" - "encoding/json" + "github.com/Akegarasu/blivedm-go/utils" log "github.com/sirupsen/logrus" "github.com/tidwall/gjson" ) @@ -72,9 +71,9 @@ type SuperChat struct { } func (s *SuperChat) Parse(data []byte) { - sb := bytes.NewBuffer(data).String() + sb := utils.BytesToString(data) sd := gjson.Get(sb, "data").String() - err := json.Unmarshal([]byte(sd), s) + err := utils.UnmarshalString(sd, s) if err != nil { log.Error("parse superchat failed") }