ProjectWIND/core/web_socket.go
2025-04-22 12:28:44 +08:00

192 lines
4.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package core
import (
"ProjectWIND/LOG"
"ProjectWIND/typed"
"ProjectWIND/wba"
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
"net/http"
"net/url"
)
var gProtocol typed.Protocol
// WebSocketHandler 接收WebSocket连接处的消息并处理
func WebSocketHandler(protocol typed.Protocol) error {
// 保存全局变量
gProtocol = protocol
// 解析连接URL
u, err := url.Parse(protocol.Addr)
if err != nil {
LOG.Error("Parse URL error: %v", err)
return err
}
// 创建一个带有Authorization头的HTTP请求
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
LOG.Fatal("创建请求出错:%v", err)
}
req.Header.Set("Authorization", "Bearer "+protocol.Token)
// 配置WebSocket连接升级器
dialer := websocket.DefaultDialer
// 使用升级器建立WebSocket连接
conn, _, err := dialer.Dial(req.URL.String(), req.Header)
if err != nil {
LOG.Fatal("建立WebSocket连接出错:%v", err)
}
defer func(conn *websocket.Conn) {
err := conn.Close()
if err != nil {
LOG.Error("Close error: %v", err)
}
}(conn)
LOG.Info("已连接到WebSocket服务器: %v", u.String())
ProtocolInfo := ProtocolApi.GetVersionInfo()
LOG.Info("协议端信息: %v-%v", ProtocolInfo.Data.AppName, ProtocolInfo.Data.AppVersion)
logInfo := ProtocolApi.GetLoginInfo()
LOG.Info("连接到账号: %v%v", logInfo.Data.Nickname, logInfo.Data.UserId)
// 定义通道,缓存消息和消息类型,防止消息处理阻塞
messageChan := make(chan []byte, 32)
messageTypeChan := make(chan int, 32)
for {
// 接收消息并放入通道
messageType, message, err := conn.ReadMessage()
if err != nil {
LOG.Error("ReadMessage error: %v", err)
return err
}
messageChan <- message
messageTypeChan <- messageType
// 启动一个新的goroutine来处理消息
go func() {
defer func() {
// 处理完成后从通道中移除消息
<-messageChan
<-messageTypeChan
}()
processMessage(messageType, message)
}()
}
}
// processMessage 处理接收到的消息
func processMessage(messageType int, message []byte) {
if messageType != websocket.TextMessage {
LOG.Error("Invalid message type: %v", messageType)
return
}
//message json解析
var messageMap map[string]interface{}
err := json.Unmarshal(message, &messageMap)
if err != nil {
LOG.Error("Unmarshal error: %v", err)
return
}
// 处理接收到的消息
messageTypeStr := messageMap["post_type"]
switch messageTypeStr {
case "message":
{
// 处理message消息
HandleMessage(message)
return
}
case "notice":
{
// 处理notice消息
HandleNotice(message)
return
}
case "request":
{
// 处理request消息
HandleRequest(message)
return
}
case "meta_event":
{
// 处理meta_event消息
HandleMetaEvent(message)
return
}
}
}
// wsSendMessage 向WebSocket服务器发送消息并返回发送状态
func wsAPI(body wba.APIRequestInfo) (Response wba.APIResponseInfo, err error) {
// 序列化请求体
bodyBytes, err := json.Marshal(body)
if err != nil {
return wba.APIResponseInfo{}, err
}
// 解析连接URL
u, err := url.Parse(gProtocol.Addr)
if err != nil {
LOG.Error("Parse URL error: %v", err)
return wba.APIResponseInfo{}, err
}
// 创建一个带有Authorization头的HTTP请求
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
LOG.Fatal("创建请求出错:%v", err)
}
req.Header.Set("Authorization", "Bearer "+gProtocol.Token)
// 配置WebSocket连接升级器
dialer := websocket.DefaultDialer
// 使用升级器建立WebSocket连接
conn, _, err := dialer.Dial(req.URL.String(), req.Header)
if err != nil {
LOG.Fatal("建立WebSocket连接出错:%v", err)
}
defer func(conn *websocket.Conn) {
err := conn.Close()
if err != nil {
LOG.Error("Close error: %v", err)
}
}(conn)
err = conn.WriteMessage(websocket.TextMessage, bodyBytes)
if err != nil {
return wba.APIResponseInfo{}, fmt.Errorf("请求发送失败: %v", err)
}
if body.Action == "get_group_list" || body.Action == "get_member_list" {
for {
_, message, err := conn.ReadMessage()
if err != nil {
return wba.APIResponseInfo{}, fmt.Errorf("响应接收失败: %v", err)
}
var Response wba.APIResponseInfo
err = json.Unmarshal(message, &Response)
if err != nil {
return wba.APIResponseInfo{}, fmt.Errorf("unmarshal error: %v", err)
}
if Response.Echo == body.Echo {
return Response, nil
}
}
}
//检查是否含有echo字段
if body.Echo != "" {
// 接收响应消息,直到收到echo字段一致的消息
for {
_, message, err := conn.ReadMessage()
if err != nil {
return wba.APIResponseInfo{}, fmt.Errorf("响应接收失败: %v", err)
}
var Response wba.APIResponseInfo
err = json.Unmarshal(message, &Response)
if err != nil {
return wba.APIResponseInfo{}, fmt.Errorf("unmarshal error: %v", err)
}
if Response.Echo == body.Echo {
return Response, nil
}
}
}
return wba.APIResponseInfo{}, nil
}