diff --git a/adapters/qq/main.go b/adapters/qq/main.go index 8dcad5f..a7043e0 100644 --- a/adapters/qq/main.go +++ b/adapters/qq/main.go @@ -185,11 +185,11 @@ func init() { }) return true }) - adapter.SetReplyHandler(func(msg map[string]string) string { + adapter.SetReplyHandler(func(msg map[string]interface{}) string { if debug { logs.Debug("QQ发送消息:", string(utils.JsonMarshal(msg))) } - if utils.IsZeroOrEmpty(msg[core.CHAT_ID]) { + if utils.IsZeroOrEmpty(msg[core.CHAT_ID].(string)) { params := map[string]interface{}{ "user_id": msg[core.USER_ID], "message": msg[core.CONETNT], diff --git a/adapters/web/main.go b/adapters/web/main.go index 06e29fc..3024ab3 100644 --- a/adapters/web/main.go +++ b/adapters/web/main.go @@ -85,12 +85,12 @@ func initWebBot() { } return false }) - adapter.SetReplyHandler(func(msg map[string]string) string { + adapter.SetReplyHandler(func(msg map[string]interface{}) string { message := WebMessage{ - UserID: msg[core.USER_ID], + UserID: msg[core.USER_ID].(string), Images: []string{}, Type: "chat", - Content: msg[core.CONETNT], + Content: msg[core.CONETNT].(string), } sendWebMessage(&message) return "" diff --git a/core/adapter.go b/core/adapter.go index 518159f..0917555 100644 --- a/core/adapter.go +++ b/core/adapter.go @@ -36,7 +36,7 @@ type CustomSender struct { type MsgChan struct { Chan chan string - Msg map[string]string + Msg map[string]interface{} } type Factory struct { @@ -45,7 +45,7 @@ type Factory struct { uuid string msgChan chan MsgChan demo *CustomSender - reply func(map[string]string) string + reply func(map[string]interface{}) string lm chan bool nm int64 recallMessage func(interface{}) bool @@ -307,8 +307,8 @@ func (f *Factory) Push(msg map[string]string) (string, error) { return sender.Reply(msg[CONETNT], PUSH("")) } -func (f *Factory) SetReplyHandler(function func(map[string]string) string) { - f.reply = func(m map[string]string) string { +func (f *Factory) SetReplyHandler(function func(map[string]interface{}) string) { + f.reply = func(m map[string]interface{}) string { if f.uuid != "" { mutex := GetMutex(f.uuid) mutex.Lock() @@ -417,7 +417,7 @@ func (f *Factory) GetReplyMessage() *goja.Promise { return promise } -func (f *Factory) Send(function func(map[string]string) string) { +func (f *Factory) Send(function func(map[string]interface{}) string) { f.SetReplyHandler(function) } @@ -485,22 +485,34 @@ func (f *Factory) Receive(wt interface{}) *CustomSender { var demo = *f.demo sender := &demo props := wt.(map[string]interface{}) + emf := map[string]interface{}{} for i := range props { + h := false switch strings.ToLower(i) { case "content": sender.details.Content = fmt.Sprint(props[i]) + h = true case "message_id", "messageId": sender.details.MessageID = fmt.Sprint(props[i]) + h = true case "user_id", "userId": sender.details.UserID = fmt.Sprint(props[i]) + h = true case "chat_id", "chatId", "group_id", "groupId", "group_code", "groupCode": sender.details.ChatID = fmt.Sprint(props[i]) + h = true case "user_name", "userName": sender.details.Username = fmt.Sprint(props[i]) + h = true case "chat_name", "chatName", "groupName", "group_name": sender.details.Chatname = fmt.Sprint(props[i]) + h = true + } + if !h { + emf[i] = props[i] } } + sender.SetExpandMessageInfo(emf) if sender.details.Content != "" { Messages <- sender } @@ -577,7 +589,7 @@ func (sender *CustomSender) Reply(msgs ...interface{}) (string, error) { content = strings.ReplaceAll(content, "\r", "\n") content = regexp.MustCompile("[\n]{3,}").ReplaceAllString(content, "\n\n") if content != "" { - msg := map[string]string{ + msg := map[string]interface{}{ "message_id": sender.GetMessageID(), "content": content, "user_id": sender.GetUserID(), @@ -585,6 +597,9 @@ func (sender *CustomSender) Reply(msgs ...interface{}) (string, error) { "bot_id": bot_id, // "uuid": utils.GenUUID(), } + for k, v := range sender.GetExpandMessageInfo() { + msg[k] = v + } if sender.f.reply == nil { var any *common.Function var one *common.Function diff --git a/core/base_sender.go b/core/base_sender.go index 8184187..d4e5b4c 100644 --- a/core/base_sender.go +++ b/core/base_sender.go @@ -159,6 +159,7 @@ type BaseSender struct { mark interface{} params []string level int + emf map[string]interface{} } func (sender *BaseSender) SetLevel(l int) { @@ -177,6 +178,40 @@ func (sender *BaseSender) GetMark() interface{} { return sender.mark } +func (sender *BaseSender) SetExpandMessageInfo(emf map[string]interface{}) { + if sender.emf == nil { + sender.emf = map[string]interface{}{} + } + for key, value := range emf { + sender.emf[key] = value + } +} + +func (sender *BaseSender) GetExpandMessageInfo() map[string]interface{} { + if sender.emf == nil { + sender.emf = map[string]interface{}{} + } + return sender.emf +} + +func (sender *BaseSender) SetVar(key string, value interface{}) { + if sender.emf == nil { + sender.emf = map[string]interface{}{} + } + sender.emf[key] = value +} + +func (sender *BaseSender) GetVar(key string) interface{} { + if sender.emf == nil { + sender.emf = map[string]interface{}{} + } + v, ok := sender.emf[key] + if !ok { + return nil + } + return v +} + func (sender *BaseSender) SetMatch(ss []string) { sender.matches = [][]string{ss} } diff --git a/core/common/sender.go b/core/common/sender.go index e97c157..b693251 100644 --- a/core/common/sender.go +++ b/core/common/sender.go @@ -44,6 +44,10 @@ type Sender interface { Stop() SetMark(interface{}) GetMark() interface{} + SetExpandMessageInfo(map[string]interface{}) + GetExpandMessageInfo() map[string]interface{} + SetVar(string, interface{}) + GetVar(string) interface{} SetLevel(int) GetLevel() int } diff --git a/core/plugin_core.go b/core/plugin_core.go index 68d5eca..7ad660f 100644 --- a/core/plugin_core.go +++ b/core/plugin_core.go @@ -496,6 +496,16 @@ func initPlugin(data string, uuid string) (*common.Function, error) { vm.Set("res", goja.Undefined()) vm.Set("req", goja.Undefined()) vm.Set("sender", ss) + vm.Set("run", func(uuid string) bool { //执行子脚本 + fs := Functions + for i := range fs { + if fs[i].UUID == uuid { + fs[i].Handle(s, nil) + return true + } + } + return false + }) vm.Set("s", ss) vm.Set("InitAdapter", func(plt, botid string) *Factory { f := &Factory{ diff --git a/core/plugin_impl.go b/core/plugin_impl.go index 7e0e608..f1c0e55 100644 --- a/core/plugin_impl.go +++ b/core/plugin_impl.go @@ -256,6 +256,24 @@ func (Sender *SenderJsIplm) Get(i interface{}) string { return Sender.Param(i) } +func (Sender *SenderJsIplm) GetVar(key string) interface{} { + return Sender.Message.GetVar(key) +} + +func (Sender *SenderJsIplm) SetVar(key string, value interface{}) { + Sender.Message.SetVar(key, value) +} + +func (Sender *SenderJsIplm) SetVars(kvs map[string]interface{}) { + for k, v := range kvs { + Sender.SetVar(k, v) + } +} + +func (Sender *SenderJsIplm) GetVars() map[string]interface{} { + return Sender.Message.GetExpandMessageInfo() +} + func (sender *SenderJsIplm) IsAdmin() bool { return sender.Message.IsAdmin() } diff --git a/core/plugin_web_request.go b/core/plugin_web_request.go index 5e3ee29..84b809e 100644 --- a/core/plugin_web_request.go +++ b/core/plugin_web_request.go @@ -35,6 +35,7 @@ type Request struct { handled bool uuid string bodyData []byte + _event string } func (r *Request) Body() string { @@ -59,6 +60,10 @@ func (r *Request) Ip() string { return r.c.ClientIP() } +func (r *Request) Event() string { + return r._event +} + func (r *Request) OriginalUrl() string { return r.c.Request.URL.String() } diff --git a/core/plugin_web_response.go b/core/plugin_web_response.go index 2dbab7f..d729b80 100644 --- a/core/plugin_web_response.go +++ b/core/plugin_web_response.go @@ -8,6 +8,7 @@ import ( "github.com/dop251/goja" "github.com/gin-gonic/gin" "github.com/goccy/go-json" + "github.com/gorilla/websocket" ) type Response struct { @@ -26,9 +27,11 @@ type Response struct { isJson bool status int isRedirect bool + conn *websocket.Conn } func (r *Response) Send(gv goja.Value) *Response { + gve := gv.Export() switch gve := gve.(type) { case string: @@ -42,6 +45,11 @@ func (r *Response) Send(gv goja.Value) *Response { r.content += fmt.Sprint(gve) } } + if r.conn != nil { + r.conn.WriteMessage(1, []byte(r.content)) + r.content = "" + return r + } return r } @@ -68,6 +76,11 @@ func (r *Response) Json(ps ...interface{}) *Response { } else { r.content += fmt.Sprint(data) } + if r.conn != nil { + r.conn.WriteMessage(1, d) + r.content = "" + return r + } return r } diff --git a/core/web.go b/core/web.go index 894ed13..2d83789 100644 --- a/core/web.go +++ b/core/web.go @@ -122,6 +122,10 @@ func initWeb() { uuid = utils.GenUUID() c.SetCookie("uuid", uuid, 8640000, "/", "", false, true) } + if IsWebSocketRequest(c.Request) { + handleWebsocket(c) + return + } var req = &Request{ c: c, uuid: uuid, @@ -129,7 +133,6 @@ func initWeb() { var res = &Response{ c: c, } - for _, function := range Functions { if function.Http != nil { path := function.Http.Path diff --git a/core/websocket.go b/core/websocket.go new file mode 100644 index 0000000..c576268 --- /dev/null +++ b/core/websocket.go @@ -0,0 +1,79 @@ +package core + +import ( + "net/http" + "strings" + + "github.com/dop251/goja" + "github.com/gin-gonic/gin" + "github.com/gorilla/websocket" +) + +func IsWebSocketRequest(req *http.Request) bool { + if req.Header.Get("Upgrade") != "websocket" { + return false + } + if !websocket.IsWebSocketUpgrade(req) { + return false + } + return true +} + +func handleWebsocket(c *gin.Context) { + for _, function := range Functions { + if function.Http != nil { + path := function.Http.Path + method := function.Http.Method + if c.Request.URL.Path == path && strings.HasPrefix(method, "W") { + // connect + var req = &Request{ + c: c, + // uuid: uuid, + } + var res = &Response{ + c: c, + } + req._event = "connect" + function.Handle(&Faker{ + Type: "*", + }, func(vm *goja.Runtime) { + vm.Set("res", res) + vm.Set("req", req) + }) + // message + var upGrader = websocket.Upgrader{ + CheckOrigin: func(r *http.Request) bool { + return true + }, + } + ws, err := upGrader.Upgrade(c.Writer, c.Request, nil) + if err != nil { + c.Writer.Write([]byte(err.Error())) + return + } + for { + _, data, err := ws.ReadMessage() + if err != nil { // disconnect + req._event = "disconnect" + function.Handle(&Faker{ + Type: "*", + }, func(vm *goja.Runtime) { + vm.Set("res", res) + vm.Set("req", req) + }) + ws.Close() + break + } + req.bodyData = data + req._event = "message" + function.Handle(&Faker{ + Type: "*", + }, func(vm *goja.Runtime) { + vm.Set("res", res) + vm.Set("req", req) + }) + } + } + } + } +}