diff --git a/.gitignore b/.gitignore index ade8d7e..3b5f058 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ develop/boltdb develop/core *.db dist/ -core/dist \ No newline at end of file +core/dist +.verysync \ No newline at end of file diff --git a/core/adapter.go b/core/adapter.go index 9e302b2..dcf6ce3 100644 --- a/core/adapter.go +++ b/core/adapter.go @@ -76,19 +76,19 @@ func DestroyAdapterByUUID(uuid string) { } } -func GetAdapter(botids ...string) (*Factory, error) { +func GetAdapter(botplt string, bots_id ...string) (*Factory, error) { BotsLocker.RLock() defer BotsLocker.RUnlock() - botplt := botids[0] - bots_id := botids[1:] var bots = []*Factory{} var select_bots = []*Factory{} for i := range Bots { plt, id := i[0], i[1] + // fmt.Println("plt", plt, "id", id, botplt, bots_id) for j := range bots_id { if plt == botplt && bots_id[j] == id { select_bots = append(select_bots, Bots[i]) - } else if plt == botplt { + } + if plt == botplt { bots = append(bots, Bots[i]) } } @@ -189,8 +189,8 @@ func (f *Factory) Push(msg map[string]string) (string, error) { var sender = &demo fsps := &common.FakerSenderParams{ UserID: msg[USER_ID], + ChatID: msg[CHAT_ID], } - fsps.ChatID = msg[CHAT_ID] sender.SetFsps(fsps) return sender.Reply(msg[CONETNT], PUSH("")) } diff --git a/core/carry.go b/core/carry.go index 22e4d37..f073c01 100644 --- a/core/carry.go +++ b/core/carry.go @@ -5,6 +5,7 @@ import ( "regexp" "sort" "strings" + "sync/atomic" "time" "github.com/cdle/sillyplus/core/common" @@ -26,6 +27,8 @@ type CarryGroupsResult struct { var CarryGroups = MakeBucket("CarryGroups") +var carryCounter int64 + // LOGIC func init() { AddCommand([]*common.Function{ @@ -40,9 +43,9 @@ func init() { var content = s.GetContent() var from *CarryGroup //判断当前消息来自采集源 var cgs = cgs - var uuid = utils.GenUUID() + var uuid = fmt.Sprintf("%d. ", atomic.AddInt64(&carryCounter, 1)) for i := range cgs { - if chat_id == cgs[i].ID && cgs[i].In { + if chat_id == cgs[i].ID && cgs[i].In && cgs[i].Enable { from = &cgs[i] break } @@ -101,7 +104,7 @@ func init() { } var outs []CarryGroup //预测转发群 for i := range cgs { - if cgs[i].Out && cgs[i].ID != chat_id { + if cgs[i].Enable && cgs[i].Out && cgs[i].ID != chat_id { for j := range cgs[i].From { if cgs[i].From[j] == chat_id { if len(cgs[i].Allowed) != 0 { //白名单 @@ -132,8 +135,9 @@ func init() { } } } - console.Debug("%s 预测转发群数目 %v", uuid, len(outs)) - if len(outs) == 0 { + num := len(outs) + console.Debug("%s 预测转发群数目 %v", uuid, num) + if num == 0 { return nil } var scripts = []string{} @@ -170,13 +174,15 @@ func init() { } HELL: if content != "" { //选择机器人 - adapter, err := GetAdapter(append([]string{platform}, outs[i].BotsID...)...) + platform := outs[i].Platform + chat_id := outs[i].ID + adapter, err := GetAdapter(platform, outs[i].BotsID...) if adapter == nil { - console.Warn("%s 转发群(%s)相关机器人%v都不在线", uuid, outs[i].ID, outs[i].BotsID) + console.Warn("%s (%s)转发群(%s)相关机器人%v都不在线", uuid, platform, chat_id, outs[i].BotsID) continue } if err != nil { - console.Debug("%s 指定机器人都不在线,转发群(%s)已选择其他机器人(%s)推送", uuid, outs[i].ID, adapter.botid) + console.Debug("%s 指定(%s)机器人都不在线,转发群(%s)已选择其他机器人(%s)推送", uuid, platform, chat_id, adapter.botid) } if adapter != nil { adapter.Push(map[string]string{ @@ -348,7 +354,17 @@ func init() { var bots_id = []string{} var users = []string{} for _, cg := range cgs { - names[cg.ID] = cg.ChatName + if cg.In { + if cg.ChatName != "" { + names[cg.ID] = cg.ChatName + } else { + if cg.Remark != "" { + names[cg.ID] = cg.Remark + } else { + names[cg.ID] = cg.ID + } + } + } if cg.ID == chat_id { users = append(users, cg.Allowed...) users = append(users, cg.Prohibited...) diff --git a/core/nickname.go b/core/nickname.go index 3105e88..9a38c93 100644 --- a/core/nickname.go +++ b/core/nickname.go @@ -44,45 +44,53 @@ func init() { } platform := ctx.Query("platform") data := []NicklabeL{} - if keyword != "" { - full := false - nickname.Foreach(func(b1, b2 []byte) error { - v := &Nickname{} - code := string(b1) - err := json.Unmarshal(b2, v) - if err == nil { - if v.Group != group { - return nil - } - if platform != "" && v.Platform != platform { - return nil - } - if strings.HasPrefix(code, keyword) || strings.Contains(v.Value, keyword) { - nl := NicklabeL{ - ChatName: v.Value, - Value: code, - Platform: v.Platform, - } - if !group { - nl.Label = fmt.Sprintf("%s(%s)", v.Value, code) - } else { - nl.Label = fmt.Sprintf("%s %s@%s", v.Value, code, v.Platform) - } - data = append(data, nl) - if code == keyword { - full = true - } - } + data2 := []NicklabeL{} + // if keyword != "" { + // full := false + nickname.Foreach(func(b1, b2 []byte) error { + v := &Nickname{} + code := string(b1) + err := json.Unmarshal(b2, v) + if err == nil { + if v.Group != group { + return nil } - return nil - }) - if !full { - data = append([]NicklabeL{{ - Label: keyword, - Value: keyword, - }}, data...) + if platform != "" && v.Platform != platform { + return nil + } + nl := NicklabeL{ + ChatName: v.Value, + Value: code, + Platform: v.Platform, + } + if !group { + nl.Label = fmt.Sprintf("%s(%s)", v.Value, code) + } else { + nl.Label = fmt.Sprintf("%s %s@%s", v.Value, code, v.Platform) + } + if strings.HasPrefix(code, keyword) || strings.Contains(v.Value, keyword) { + data = append(data, nl) + // if code == keyword { + // full = true + // } + } + data2 = append(data2, nl) } + return nil + }) + // if !full { + // data = append([]NicklabeL{{ + // Label: keyword, + // Value: keyword, + // }}, data...) + // } else + if len(data) == 0 { + data = append([]NicklabeL{{ + Label: keyword, + Value: keyword, + }}, data2...) } + // } ctx.JSON(200, map[string]interface{}{ "success": true, "data": data, diff --git a/core/node_bucket.go b/core/node_bucket.go index 4d64d50..02891ba 100644 --- a/core/node_bucket.go +++ b/core/node_bucket.go @@ -8,7 +8,6 @@ import ( func MakeBucketObject(vm *goja.Runtime, uuid string, on_start bool, bucket storage.Bucket) *goja.Object { obj := vm.NewObject() obj.Set("get", func(v ...interface{}) interface{} { - return GetBucketKeyValue(bucket, v...) }) obj.Set("foreach", func(v ...interface{}) map[string]interface{} { diff --git a/core/node_web.go b/core/node_web.go new file mode 100644 index 0000000..9f36060 --- /dev/null +++ b/core/node_web.go @@ -0,0 +1,56 @@ +package core + +import ( + "sync" + "sync/atomic" + + "github.com/dop251/goja" +) + +type RR struct { + Req *Request + Res *Response + End func() +} + +type HttpListen struct { + Path string + Method string + Chan chan *RR + UUID string + Closed bool + // Handle func(*Request, *Response) +} + +var httpListens sync.Map +var listenCounter2 int64 + +func AddHttpListen(api, method string, vm *goja.Runtime, uuid string, resolve func(result interface{}), reject func(reason interface{})) { + key := atomic.AddInt64(&listenCounter2, 1) + hl := &HttpListen{ + Path: api, + Method: method, + Chan: make(chan *RR, 1), + } + httpListens.Store(key, hl) + f, ok := <-hl.Chan + if ok { + resolve(f) + } else { + reject(Error(vm, "script is stopped")) + } +} + +func CancelHttpListen(uuid string) { + httpListens.Range(func(key, value any) bool { + hl := value.(*HttpListen) + if hl.UUID == uuid { + httpListens.Delete(key) + if !hl.Closed { + hl.Closed = true + close(hl.Chan) + } + } + return true + }) +} diff --git a/core/plugin_core.go b/core/plugin_core.go index 27f13ca..524187b 100644 --- a/core/plugin_core.go +++ b/core/plugin_core.go @@ -204,6 +204,7 @@ func initPlugins() { CancelPluginCrons(key) CancelPluginWebs(key) CancelPluginlistening(key) + CancelHttpListen(key) storage.DisableHandle(key) if new != "" { AddCommand([]*common.Function{f}) @@ -415,13 +416,13 @@ func initPlugin(data string, uuid string) (*common.Function, error) { var running func() bool f := &common.Function{ Handle: func(s common.Sender) interface{} { - defer func() { - err := recover() - if err != nil { - console.Error("脚本错误:", err) - s.Reply(fmt.Sprint(err)) - } - }() + // defer func() { + // err := recover() + // if err != nil { + // console.Error("脚本错误:", err) + // s.Reply(fmt.Sprint(err)) + // } + // }() if err2 != nil { panic(err2) } diff --git a/core/plugin_utils.go b/core/plugin_utils.go index cb899e4..030146e 100644 --- a/core/plugin_utils.go +++ b/core/plugin_utils.go @@ -264,21 +264,21 @@ func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool) { } return o }) - registry.RegisterNativeModule("express", func(runtime *goja.Runtime, module *goja.Object) { - o := module.Get("exports").(*goja.Object) - methods := []string{"get", "post", "delete", "put", "fetch"} - for i := range methods { - method := methods[i] - o.Set(method, func(path string, handles ...func(*Request, *Response)) { - webs = append(webs, Web{ - uuid: uuid, - method: strings.ToUpper(method), - path: path, - handles: handles, - }) - }) - } - }) + // registry.RegisterNativeModule("express", func(runtime *goja.Runtime, module *goja.Object) { + // o := module.Get("exports").(*goja.Object) + // methods := []string{"get", "post", "delete", "put", "fetch"} + // for i := range methods { + // method := methods[i] + // o.Set(method, func(path string, handles ...func(*Request, *Response)) { + // webs = append(webs, Web{ + // uuid: uuid, + // method: strings.ToUpper(method), + // path: path, + // handles: handles, + // }) + // }) + // } + // }) vm.Set("gofor", func(running func() bool, handle func()) { go func() { for { @@ -377,6 +377,27 @@ func SetPluginMethod(vm *goja.Runtime, uuid string, on_start bool) { }() return promise }) + // for _, method := range []string{"get", "post", "delete", "put", "fetch"} { + // vm.Set(method, ) + // } + vm.Set("HttpListen", func(method, api string) *goja.Promise { + promise, resolve, reject := vm.NewPromise() + go func() { + func() { + v := recover() + if v != nil { + if err, ok := v.(error); ok { + reject(Error(vm, err)) + } else { + reject(Error(vm, fmt.Sprint(v))) + } + + } + }() + AddHttpListen(api, strings.ToUpper(method), vm, uuid, resolve, reject) + }() + return promise + }) vm.Set("request", request) } diff --git a/core/web.go b/core/web.go index 7e00e5c..37fb477 100644 --- a/core/web.go +++ b/core/web.go @@ -41,6 +41,8 @@ func Cors() gin.HandlerFunc { var Server = gin.New() func init() { + gin.SetMode(gin.ReleaseMode) + // Server.Use(gin.Recovery()) Server.Use(Cors()) Server.Use(gzip.Gzip(gzip.DefaultCompression)) Server.NoRoute(func(c *gin.Context) { @@ -85,6 +87,65 @@ func init() { var res = &Response{ c: c, } + httpListens.Range(func(key, value any) bool { + web := value.(*HttpListen) + if web.Closed { + return true + } + // fmt.Println(c.Request.URL.Path, key, web.Method, c.Request.Method) + if web.Method == c.Request.Method { + var matched = web.Path == c.Request.URL.Path + if !matched && strings.HasPrefix(web.Path, "^") { + reg, err := regexp.Compile(web.Path) + if err != nil { + console.Error(err) + return true + } + req.ress = reg.FindAllStringSubmatch(c.Request.URL.Path, -1) + matched = len(req.ress) != 0 + } + if matched { + httpListens.Delete(key) + req.handled = true + var end = make(chan bool, 1) + // fmt.Println(c.Request.URL.Path, key) + web.Chan <- &RR{ + Req: req, + Res: res, + End: func() { + if !web.Closed { + end <- true + } + }, + } + select { + case <-end: + case <-time.After(time.Second * 10): + logs.Warn("%s 响应超时", c.Request.URL.Path) + } + web.Closed = true + close(end) + if !web.Closed { + close(web.Chan) + } + if req.handled { + if res.isRedirect { + return false + } + if res.isJson { + c.Header("Content-Type", "application/json") + } + // fmt.Println(res.status, res.content) + c.String(res.status, res.content) + return false + } + } + } + return true + }) + if req.handled { + return + } for _, web := range webs { if web.handles == nil { continue @@ -121,6 +182,7 @@ func init() { if res.isJson { c.Header("Content-Type", "application/json") } + // fmt.Println(res.status, res.content) c.String(res.status, res.content) return } @@ -129,6 +191,9 @@ func init() { } c.String(404, "页面被喵咪劫走了。") // + //开启代理模式 + + // handleHTTP(c.Writer, c.Request) }) port := sillyGirl.GetString("port", "8080") @@ -184,6 +249,37 @@ func init() { }() } +// var httpProxys = MakeBucket("httpProxys") + +func handleHTTP(w http.ResponseWriter, req *http.Request) { + // console.Info("%s", utils.JsonMarshal(req.Header)) + // u, err := url.Parse("addr") + // if err != nil { + // core.Logs.Warn("can't connect to the http proxy:", err) + // return + // } + // Transport = &http.Transport{Proxy: http.ProxyURL(u)} + // resp, err := Transport.RoundTrip(req) + // fmt.Println("====") + resp, err := http.DefaultTransport.RoundTrip(req) + if err != nil { + http.Error(w, err.Error(), http.StatusServiceUnavailable) + return + } + defer resp.Body.Close() + copyHeader(w.Header(), resp.Header) + w.WriteHeader(resp.StatusCode) + io.Copy(w, resp.Body) +} + +func copyHeader(dst, src http.Header) { + for k, vv := range src { + for _, v := range vv { + dst.Add(k, v) + } + } +} + type Req struct { Method string Path string diff --git a/node b/node new file mode 100644 index 0000000..e69de29 diff --git a/workflow.yaml b/workflow.yaml new file mode 100644 index 0000000..e98bb0b --- /dev/null +++ b/workflow.yaml @@ -0,0 +1,82 @@ +name: Go + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + + - name: Git clone sillyplus + run: + cd develop && git clone https://${{ secrets.CABLE_TOKEN }}@github.com/cdle/sillyplus.git + + - name: Push to binary + run: | + rm -rf * + cp sillyplus/* ./ + n=$(date +%s%3N) + echo "package core" > sillyplus/core/compile_time.go + echo "var compiled_at = \"$n\"" >> develop/core/compile_time.go + CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o sillyGirl_windows_amd64 + CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" -o sillyGirl_linux_arm64 + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o sillyGirl_linux_amd64 + sudo apt-get install upx-ucl + upx sillyGirl_linux_arm64 + upx sillyGirl_linux_amd64 + upx sillyGirl_windows_amd64 + git clone https://${{ secrets.CABLE_TOKEN }}@github.com/cdle/binary.git + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + cd binary + git checkout --orphan latest_branch + rm -rf * + cp ../sillyGirl_windows_amd64 sillyGirl_windows_amd64_$n + cp ../sillyGirl_linux_amd64 sillyGirl_linux_amd64_$n + cp ../sillyGirl_linux_arm64 sillyGirl_linux_arm64_$n + cp ../develop/core/compile_time.go compile_time.go + git add -A + git commit -am "commit message" + git branch -D main + git branch -m main + git push -f origin main + wget -q -O - "${{ secrets.VERSION }}$n" + + - name: Upload to release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: sillyGirl_linux_amd64 + asset_name: sillyGirl_linux_amd64 + tag: ${{ github.ref }} + overwrite: true + + - name: Upload to release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: sillyGirl_windows_amd64 + asset_name: sillyGirl_windows_amd64 + tag: ${{ github.ref }} + overwrite: true + + - name: Upload to release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: sillyGirl_linux_arm64 + asset_name: sillyGirl_linux_arm64 + tag: ${{ github.ref }} + overwrite: true + \ No newline at end of file