commit b9856300aa91bf1b90ce18ead25b769ec11cf1fa Author: Sheyiyuan <2125107118@qq.com> Date: Thu Nov 28 15:20:29 2024 +0800 项目初始化 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..413b7d9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/main/tmp +/scripts +/main/.git +/main/.gitignore diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/ProjectWIND.iml b/.idea/ProjectWIND.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/ProjectWIND.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..061c876 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..a57048e --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0de2aaa --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +Copyright (C) 2024 Sheyiyuan + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5de8153 --- /dev/null +++ b/go.mod @@ -0,0 +1,12 @@ +module ProjectWIND + +go 1.23.2 + +require ( + github.com/dlclark/regexp2 v1.11.4 // indirect + github.com/dop251/goja v0.0.0-20241024094426-79f3a7efcdbd // indirect + github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect + github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b // indirect + github.com/gorilla/websocket v1.5.3 // indirect + golang.org/x/text v0.20.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bfcbb11 --- /dev/null +++ b/go.sum @@ -0,0 +1,18 @@ +github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= +github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20241024094426-79f3a7efcdbd h1:QMSNEh9uQkDjyPwu/J541GgSH+4hw+0skJDIj9HJ3mE= +github.com/dop251/goja v0.0.0-20241024094426-79f3a7efcdbd/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q= +github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b h1:SXO0REt4iu865upYCk8aKBBJQ4BqoE0ReP23ClMu60s= +github.com/google/pprof v0.0.0-20241122213907-cbe949e5a41b/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..e3afd99 Binary files /dev/null and b/icon.png differ diff --git a/main.go b/main.go new file mode 100644 index 0000000..a1909d3 --- /dev/null +++ b/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "ProjectWIND/protocol" + "log" +) + +func init() { + +} + +func main() { + _, err := protocol.WebSocketHandler() + if err != nil { + log.Fatal(err) + } +} diff --git a/protocol/api.go b/protocol/api.go new file mode 100644 index 0000000..38948cb --- /dev/null +++ b/protocol/api.go @@ -0,0 +1,39 @@ +package protocol + +import ( + "ProjectWIND/typed" + "encoding/json" + "errors" +) + +func init() { + +} + +func SendMessage(messageType string, message string, targetId int64, autoEscape bool) (bool, error) { + // 构建发送消息的JSON数据 + var messageData typed.APIRequest + messageData.Action = "send_msg" + switch messageType { + case "private": + messageData.Params.UserId = targetId + break + case "group": + messageData.Params.GroupId = targetId + break + default: + return false, errors.New("invalid type") + } + messageData.Params.Message = message + messageData.Params.AutoEscape = autoEscape + messageJson, err := json.Marshal(messageData) + if err != nil { + return false, err + } + // 发送消息 + _, err = wsSendMessage(messageJson) + if err != nil { + return false, err + } + return true, nil +} diff --git a/protocol/events_handler.go b/protocol/events_handler.go new file mode 100644 index 0000000..5b454e9 --- /dev/null +++ b/protocol/events_handler.go @@ -0,0 +1,71 @@ +package protocol + +import ( + "ProjectWIND/typed" + "encoding/json" + "log" +) + +func HandleMessage(msgJson []byte) { + var msg typed.MessageEventInfo + err := json.Unmarshal(msgJson, &msg) + if err != nil { + log.Println("[ERROR] unmarshalling message: ", err) + } + // 处理消息 + log.Printf("[INFO] 收到消息:(来自:%v-%v:%v-%v)%v", msg.MessageType, msg.GroupId, msg.UserId, msg.Sender.Nickname, msg.RawMessage) + //一个简单的测试 + if msg.RawMessage == "wind test" { + log.Println("[INFO] 收到wind test") + switch msg.MessageType { + case "group": + { + _, err := SendMessage(msg.MessageType, "wind test success", msg.GroupId, false) + if err != nil { + log.Println("[ERROR] send message: ", err) + } + break + } + case "private": + { + _, err := SendMessage(msg.MessageType, "wind test success", msg.UserId, false) + if err != nil { + log.Println("[ERROR] send message: ", err) + } + break + } + default: + { + log.Println("[ERROR] 不支持的消息类型") + break + } + } + } +} + +func HandleNotice(msgJson []byte) { + var notice typed.NoticeEventInfo + err := json.Unmarshal(msgJson, ¬ice) + if err != nil { + log.Println("[ERROR] unmarshalling notice: ", err) + } + // 处理通知 +} + +func HandleRequest(msgJson []byte) { + var request typed.NoticeEventInfo + err := json.Unmarshal(msgJson, &request) + if err != nil { + log.Println("[ERROR] unmarshalling request: ", err) + } + // 处理请求 +} + +func HandleMetaEvent(msgJson []byte) { + var meta typed.NoticeEventInfo + err := json.Unmarshal(msgJson, &meta) + if err != nil { + log.Println("[ERROR] unmarshalling meta: ", err) + } + // 处理元事件 +} diff --git a/protocol/web_socket.go b/protocol/web_socket.go new file mode 100644 index 0000000..c4cd94b --- /dev/null +++ b/protocol/web_socket.go @@ -0,0 +1,122 @@ +package protocol + +import ( + "encoding/json" + "fmt" + "log" + "net/url" + + "github.com/gorilla/websocket" +) + +const ( + severURL = "ws://110.41.4.138:3001" +) + +func WebSocketHandler() (*websocket.Conn, error) { + u, err := url.Parse(severURL) + if err != nil { + log.Println("Parse URL error:", err) + return nil, err + } + + conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil) + if err != nil { + log.Println("[ERROR] Dial error:", err) + return nil, err + } + defer func(conn *websocket.Conn) { + err := conn.Close() + if err != nil { + log.Println("[ERROR] Close error:", err) + } + }(conn) + + for { + messageType, message, err := conn.ReadMessage() + if err != nil { + log.Println("[ERROR] Read error:", err) + break + } + + // 将接收到的消息交给另一个函数处理 + processMessage(messageType, message) + } + return conn, nil +} + +func processMessage(messageType int, message []byte) { + if messageType != websocket.TextMessage { + log.Println("[INFO] Invalid message type:", messageType) + return + } + //message json解析 + var messageMap map[string]interface{} + err := json.Unmarshal(message, &messageMap) + if err != nil { + log.Println("[ERROR] Unmarshal error:", 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 + } + default: + { + // 打印接收到的消息 + log.Printf("[WARN] Received message: %s", message) + } + } +} + +// wsSendMessage 向WebSocket服务器发送消息并返回发送状态 +func wsSendMessage(message []byte) (bool, error) { + // 解析连接URL + u, err := url.Parse(fmt.Sprintf("%v/api", severURL)) + if err != nil { + return false, fmt.Errorf("无效的URL: %v", err) + } + + // 建立连接 + conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil) + if err != nil { + return false, fmt.Errorf("连接失败: %v", err) + } + defer func(conn *websocket.Conn) { + err := conn.Close() + if err != nil { + log.Println("[ERROR] Close error:", err) + } + }(conn) + + // 发送消息 + err = conn.WriteMessage(websocket.TextMessage, message) + if err != nil { + return false, fmt.Errorf("发送消息失败: %v", err) + } + + return true, nil +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..64543bf --- /dev/null +++ b/readme.md @@ -0,0 +1,8 @@ +# ProjectWIND +骰子框架,自用 + +
ProjectWIND
+ +license: [MIT](./LICENSE) + +开发者很懒,什么都没有写。 \ No newline at end of file diff --git a/typed/typed.go b/typed/typed.go new file mode 100644 index 0000000..2554378 --- /dev/null +++ b/typed/typed.go @@ -0,0 +1,132 @@ +package typed + +type MessageEventInfo struct { + Time int64 `json:"time,omitempty"` + SelfId int64 `json:"self_id,omitempty"` + PostType string `json:"post_type,omitempty"` + MessageType string `json:"message_type,omitempty"` + SubType string `json:"sub_type,omitempty"` + MessageId int32 `json:"message_id,omitempty"` + GroupId int64 `json:"group_id,omitempty"` + UserId int64 `json:"user_id,omitempty"` + Anonymous AnonymousInfo `json:"anonymous"` + Message []MessageInfo `json:"message,omitempty"` + RawMessage string `json:"raw_message,omitempty"` + Font int32 `json:"font,omitempty"` + Sender SenderInfo `json:"sender"` +} + +type NoticeEventInfo struct { + Time int64 `json:"time,omitempty"` + SelfId int64 `json:"self_id,omitempty"` + PostType string `json:"post_type,omitempty"` + NoticeType string `json:"notice_type,omitempty"` + GroupId int64 `json:"group_id,omitempty"` + UserId int64 `json:"user_id,omitempty"` + File FileInfo `json:"file,omitempty"` + SubType string `json:"sub_type,omitempty"` + OperatorId int64 `json:"operator_id,omitempty"` + Duration int64 `json:"duration,omitempty"` + MessageId int64 `json:"message,omitempty"` + TargetId int64 `json:"target_id,omitempty"` + HonorType string `json:"honor_type,omitempty"` +} + +type RequestEventInfo struct { + Time int64 `json:"time,omitempty"` + SelfId int64 `json:"self_id,omitempty"` + PostType string `json:"post_type,omitempty"` + RequestType string `json:"request_type,omitempty"` + SubType string `json:"sub_type,omitempty"` + UserId int64 `json:"user_id,omitempty"` + Comment string `json:"comment,omitempty"` + Flag string `json:"flag,omitempty"` + GroupId int64 `json:"group_id,omitempty"` +} + +type MetaEventInfo struct { + Time int64 `json:"time,omitempty"` + SelfId int64 `json:"self_id,omitempty"` + PostType string `json:"post_type,omitempty"` + MetaEventType string `json:"meta_event_type,omitempty"` + SubType string `json:"sub_type,omitempty"` + Status string `json:"status,omitempty"` + Interval int64 `json:"interval,omitempty"` +} + +type FileInfo struct { + Id string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Size int64 `json:"size,omitempty"` + Busid int64 `json:"bucket,omitempty"` +} + +type SenderInfo struct { + UserId int64 `json:"user_id,omitempty"` + Nickname string `json:"nickname,omitempty"` + Card string `json:"card,omitempty"` + Sex string `json:"sex,omitempty"` + Age int32 `json:"age,omitempty"` + Area string `json:"area,omitempty"` + Level string `json:"level,omitempty"` + Role string `json:"role,omitempty"` + Title string `json:"title,omitempty"` +} + +type AnonymousInfo struct { + Id string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Flag string `json:"flag,omitempty"` +} + +type MessageInfo struct { + Type string `json:"type,omitempty"` + Data MessageDataInfo `json:"data"` +} + +type MessageDataInfo struct { + Type string `json:"type,omitempty"` + Text string `json:"text,omitempty"` + Id string `json:"id,omitempty"` + File string `json:"file,omitempty"` + Url string `json:"url,omitempty"` + Magic string `json:"magic,omitempty"` + Qq string `json:"qq,omitempty"` + Title string `json:"title,omitempty"` + Content string `json:"content,omitempty"` + Image string `json:"image,omitempty"` + Audio string `json:"audio,omitempty"` + Lat string `json:"lat,omitempty"` + Lon string `json:"lon,omitempty"` + Data string `json:"data,omitempty"` +} + +type APIRequest struct { + Action string `json:"action,omitempty"` + Params ParamsInfo `json:"params"` + Echo string `json:"echo,omitempty"` +} + +type ParamsInfo struct { + Message string `json:"message,omitempty"` + UserId int64 `json:"user_id,omitempty"` + GroupId int64 `json:"group_id,omitempty"` + AutoEscape bool `json:"auto_escape,omitempty"` + MessageId int32 `json:"message_id,omitempty"` + Id string `json:"id,omitempty"` + RejectAddRequest bool `json:"reject_add_request,omitempty"` + Duration int32 `json:"duration,omitempty"` + Enable bool `json:"enable,omitempty"` + Card string `json:"card,omitempty"` + GroupName string `json:"group_name,omitempty"` + IsDismiss bool `json:"is_dismiss,omitempty"` + SpecialTitle string `json:"special_title,omitempty"` + Flag string `json:"flag,omitempty"` + Approve bool `json:"approve,omitempty"` + Remark string `json:"remark,omitempty"` + Type string `json:"type,omitempty"` + SubType string `json:"sub_type,omitempty"` + Reason string `json:"reason,omitempty"` + NoCache bool `json:"no_cache,omitempty"` + File string `json:"file,omitempty"` +}