qq_bot/ws_client/client.go

115 lines
2.5 KiB
Go

package wsclient
import (
"encoding/json"
"fmt"
"log"
"net/url"
"runtime/debug"
"sync"
"time"
"git.lxtend.com/qqbot/action"
"git.lxtend.com/qqbot/constants"
"git.lxtend.com/qqbot/handler"
"git.lxtend.com/qqbot/model"
"github.com/gorilla/websocket"
)
type WebSocketClient struct {
conn *websocket.Conn
closed bool
Done chan struct{}
lock sync.Mutex
}
func NewWebSocketClient(scheme, host, path string) (*WebSocketClient, error) {
u := url.URL{Scheme: scheme, Host: host, Path: path}
log.Printf("Connecting to %s", u.String())
conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
return nil, err
}
client := &WebSocketClient{
conn: conn,
closed: false,
Done: make(chan struct{}),
}
defer func() {
if r := recover(); r != nil {
stack := debug.Stack()
errMsg := fmt.Sprintf("[%s] Panic recovered:\nError: %v\nStack Trace:\n%s\n",
time.Now().Format("2006-01-02 15:04:05"), r, stack)
// 写入日志文件
log.Print(errMsg)
go client.receiveMessages()
}
}()
action.ActionManager.SetConn(conn)
go client.receiveMessages()
return client, nil
}
func (c *WebSocketClient) receiveMessages() {
defer close(c.Done)
for !c.closed {
_, message, err := c.conn.ReadMessage()
if err != nil {
log.Println("Error reading message:", err)
return
}
var event model.EventMessage
if err = json.Unmarshal(message, &event); err != nil {
log.Println("Error unmarshalling message:", err)
return
}
msg := model.Message{
UserId: event.UserID,
OriginMsgId: event.MessageID,
RawMsg: event.RawMessage,
UserNickName: event.Sender.Nickname,
}
if event.MessageType == constants.GROUP_MSG {
msg.GroupInfo = model.GroupInfo{
IsGroupMsg: true,
GroupId: event.GroupID,
UserCard: event.Sender.Card,
}
} else {
msg.GroupInfo = model.GroupInfo{
IsGroupMsg: false,
GroupId: event.Sender.GroupID,
}
}
go func() {
reply := handler.MsgInHandler(msg)
if reply.ReplyMsg != "" {
action.ActionManager.SendMsg(reply)
}
}()
}
}
func (c *WebSocketClient) SendMessage(messageType int, message []byte) error {
c.lock.Lock()
defer c.lock.Unlock()
return c.conn.WriteMessage(messageType, message)
}
func (c *WebSocketClient) Close() error {
c.closed = true
err := c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
return err
}
<-c.Done
return c.conn.Close()
}