diff --git a/go.mod b/go.mod index 3509260..edd564b 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module wechat-demo +module github.com/Clov614/rikka-bot-wechat go 1.22 @@ -7,13 +7,13 @@ toolchain go1.22.5 require ( github.com/Clov614/bilibili v0.1.2 github.com/Clov614/go-ai-sdk v0.4.2 + github.com/Clov614/wcf-rpc-sdk v0.2.3 github.com/eatmoreapple/openwechat v1.4.10 github.com/gin-gonic/gin v1.10.0 github.com/go-ego/gse v0.80.3 github.com/google/uuid v1.6.0 github.com/robfig/cron/v3 v3.0.0 github.com/rs/zerolog v1.33.0 - github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/zwgblue/yaml-encoder v0.0.0-20221226083717-a0bdbda0d998 go.etcd.io/bbolt v1.3.11 gopkg.in/yaml.v3 v3.0.1 @@ -22,16 +22,19 @@ require ( //replace github.com/eatmoreapple/openwechat => github.com/Clov614/openwechat v1.4.8 require ( + github.com/Microsoft/go-winio v0.5.2 // indirect github.com/bytedance/sonic v1.11.9 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect + github.com/eatmoreapple/env v0.0.0-20230613094802-da1bd2d529d4 // indirect github.com/gabriel-vasile/mimetype v1.4.4 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/goccy/go-json v0.10.3 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/leodido/go-urn v1.4.0 // indirect @@ -43,10 +46,11 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/vcaesar/cedar v0.20.2 // indirect + go.nanomsg.org/mangos/v3 v3.4.2 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.16.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.36.2 // indirect ) diff --git a/go.sum b/go.sum index 4840453..0723c3a 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,10 @@ github.com/Clov614/bilibili v0.1.2 h1:vi1Ykn5+xgrwfpR/xLgdXvoNdulaZitXP9BOgdy0n+ github.com/Clov614/bilibili v0.1.2/go.mod h1:th+qNf6jfSDH03oCM4s347a+i7IpCgZyNRIHY8AAXe8= github.com/Clov614/go-ai-sdk v0.4.2 h1:4krlgGbgP4UDBl6YYIc8YBJUWH54q46LOzpWhErSdhA= github.com/Clov614/go-ai-sdk v0.4.2/go.mod h1:S/GDuJSLlnNU47uEpY2FrN1GdP+A4mDXBQZQ2i6sCzk= +github.com/Clov614/wcf-rpc-sdk v0.2.3 h1:A6M60Z5kB1pJTZeufFakjQJfLob0xEYjZA1wUKUbfh4= +github.com/Clov614/wcf-rpc-sdk v0.2.3/go.mod h1:knw4SYFua+ZlWJI5KmWafx4I5GkC27IQUvuFxOBrKxY= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5zg= github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= @@ -14,10 +18,13 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/eatmoreapple/env v0.0.0-20230613094802-da1bd2d529d4 h1:7OCnZ5Nr7dXrE2A3UGK/E3Y6uDYDvISAwLQZuxtWjLU= +github.com/eatmoreapple/env v0.0.0-20230613094802-da1bd2d529d4/go.mod h1:6FwoAYtdFyNxe5UfWjmRui6WWt3CaRglffRFHCaGTIQ= github.com/eatmoreapple/openwechat v1.4.10 h1:Wx1+Eulb8yXY7t9J8FCzaLu2tvRPT0leTskdNOsUXj0= github.com/eatmoreapple/openwechat v1.4.10/go.mod h1:h4m2N8m0XsUKlm7UR8BUGkV89GNuKHCnlGV3J8n9Mpw= github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= +github.com/gdamore/optopia v0.2.0/go.mod h1:YKYEwo5C1Pa617H7NlPcmQXl+vG6YnSSNB44n8dNL0Q= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= @@ -35,11 +42,13 @@ github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaC github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -69,12 +78,12 @@ github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= -github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= -github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -95,6 +104,8 @@ github.com/zwgblue/yaml-encoder v0.0.0-20221226083717-a0bdbda0d998 h1:nfgqxY/ewt github.com/zwgblue/yaml-encoder v0.0.0-20221226083717-a0bdbda0d998/go.mod h1:gDS9Ro20YdMC2SY41VMVcy6PqyVCseFPIX1+symaFww= go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I= +go.nanomsg.org/mangos/v3 v3.4.2 h1:gHlopxjWvJcVCcUilQIsRQk9jdj6/HB7wrTiUN8Ki7Q= +go.nanomsg.org/mangos/v3 v3.4.2/go.mod h1:8+hjBMQub6HvXmuGvIq6hf19uxGQIjCofmc62lbedLA= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -104,18 +115,18 @@ golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU= +google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 2efba17..1c64a3f 100644 --- a/main.go +++ b/main.go @@ -1,28 +1,26 @@ package main import ( + "context" "flag" - "fmt" - "github.com/eatmoreapple/openwechat" + "github.com/Clov614/rikka-bot-wechat/rikkabot" + "github.com/Clov614/rikka-bot-wechat/rikkabot/adapter" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/onebot/httpapi" + wcf "github.com/Clov614/wcf-rpc-sdk" "github.com/gin-gonic/gin" "github.com/rs/zerolog" - "github.com/skip2/go-qrcode" "time" - "wechat-demo/rikkabot" - "wechat-demo/rikkabot/adapter" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/onebot/httpapi" ) func main() { + // todo 支持自动获取sdk.dll 自动完成注入 // 是否开启调试模式 debugflag := flag.Bool("debug", false, "debug mode") // 是否开启 http服务 httpMode := flag.Bool("http", false, "http mode") // 是否开启 rikkabot botMode := flag.Bool("bot", false, "bot mode(using to start rikkabot and also http can run)") - // 是否打印 qrcode - isPrintQr := flag.Bool("qrcode", false, "qrcode mode") flag.Parse() if *debugflag { zerolog.SetGlobalLevel(zerolog.DebugLevel) @@ -41,53 +39,16 @@ func main() { logging.Fatal("Recovered from panic", 1, map[string]interface{}{"panic": r}) } }() + ctx := context.Background() + cli := wcf.NewClient(30) + cli.Run(true, false, false) // 运行wcf客户端 - bot := openwechat.DefaultBot(openwechat.Desktop) - rbot := rikkabot.GetDefaultBot() - - //// 注册登陆二维码回调 - //bot.UUIDCallback = openwechat.PrintlnQrcodeUrl - // 注册登陆二维码回调 - - var isNotUUidCallback bool - bot.UUIDCallback = func(uuid string) { - url := openwechat.GetQrcodeUrl(uuid) - rbot.SetloginUrl(url) - logging.Warn("登录地址: " + url) - if *isPrintQr { - consoleQrCodeand(uuid) - } - isNotUUidCallback = true - // 正向http http上报器 - if *httpMode { - httpapi.RunHttp(rbot) - rbot.StartHandleEvent() // 处理事件 - - rbot.PushLoginNoticeEvent() // 推送登录回调通知 - } - } - - // 登陆 - reloadStorage := openwechat.NewFileHotReloadStorage("storage.json") - defer func() { - err := reloadStorage.Close() - if err != nil { - logging.Fatal("get reload storage err", 1, map[string]interface{}{"err": err.Error()}) - } - }() - logging.Warn("请在手机中确认登录 or 扫码登录") - if err := bot.PushLogin(reloadStorage, openwechat.NewRetryLoginOption()); err != nil { - logging.Error("bot.PushLogin() error", map[string]interface{}{"openwechat bot error": err.Error()}) - return - } - - a := adapter.NewAdapter(bot, rbot) - + rbot := rikkabot.NewRikkaBot(ctx, cli) + a := adapter.NewAdapter(ctx, cli, rbot) a.HandleCovert() // 消息转换 - defer a.Close() // 正向http http上报器 - if *httpMode && !isNotUUidCallback { + if *httpMode { httpapi.RunHttp(rbot) rbot.StartHandleEvent() // 处理事件 } @@ -98,10 +59,10 @@ func main() { go func() { for { - if !bot.Alive() { - rbot.PushLogOutNoticeEvent(1101, "open-wechat客户端掉线") + if !cli.IsLogin() { + rbot.PushLogOutNoticeEvent(1101, "微信未登录或掉线") time.Sleep(1 * time.Second) // 1s 延迟退出 - rbot.ExitWithErr(1101, "open-wechat客户端掉线") + rbot.ExitWithErr(1101, "微信未登录或掉线") return } time.Sleep(5 * time.Second) @@ -114,9 +75,3 @@ func main() { logging.WarnWithErr(err, "rikka bot.Block() error") } } - -func consoleQrCodeand(uuid string) { - url := openwechat.GetQrcodeUrl(uuid) - q, _ := qrcode.New(url, qrcode.Low) - fmt.Println(q.ToString(true)) -} diff --git a/rikkabot/adapter/adapter.go b/rikkabot/adapter/adapter.go index 2635888..90ffa05 100644 --- a/rikkabot/adapter/adapter.go +++ b/rikkabot/adapter/adapter.go @@ -1,24 +1,24 @@ package adapter import ( - "bytes" + "context" "errors" "fmt" - "github.com/eatmoreapple/openwechat" + "github.com/Clov614/rikka-bot-wechat/rikkabot" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/manager" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + wcf "github.com/Clov614/wcf-rpc-sdk" "math/rand" "regexp" "time" - "wechat-demo/rikkabot" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/manager" - "wechat-demo/rikkabot/message" ) type Adapter struct { - openwcBot *openwechat.Bot - selfBot *rikkabot.RikkaBot - done chan struct{} + ctx context.Context + cli *wcf.Client + rikkaBot *rikkabot.RikkaBot } var ( @@ -27,25 +27,40 @@ var ( ErrRawMSgNil = errors.New("raw message is nil") ) -func NewAdapter(openwcBot *openwechat.Bot, selfBot *rikkabot.RikkaBot) *Adapter { - common.InitSelf(openwcBot) // 初始化 该用户数据(朋友、群组) - selfBot.SetSelf(common.GetSelf()) - return &Adapter{openwcBot: openwcBot, selfBot: selfBot, done: make(chan struct{})} +func NewAdapter(ctx context.Context, cli *wcf.Client, bot *rikkabot.RikkaBot) *Adapter { + //common.InitSelf(openwcBot) // 初始化 该用户数据(朋友、群组) todo refactor + //selfBot.SetSelf(common.GetSelf()) todo refactor + + return &Adapter{ + ctx: ctx, + cli: cli, + rikkaBot: bot, + } } func (a *Adapter) HandleCovert() { - a.openwcBot.MessageHandler = func(msg *openwechat.Message) { - a.receiveMsg(msg) - } + sendChan := a.rikkaBot.GetRespMsgRecvChan() go func() { - respMsgRecvChan := a.selfBot.GetRespMsgRecvChan() for { select { - case <-a.done: + case <-a.ctx.Done(): + logging.ErrorWithErr(a.ctx.Err(), "handle covert exit") return - case respMsg := <-respMsgRecvChan: + case msg := <-a.cli.GetMsgChan(): // 转换收到的消息 + a.receiveMsg(msg) + } + } + }() + + go func() { + for { + select { + case <-a.ctx.Done(): + logging.ErrorWithErr(a.ctx.Err(), "handle send exit") + return + case respMsg := <-sendChan: //rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - //time.Sleep(time.Duration((rnd.Intn(1000) + 1000)) * time.Millisecond) // sui + //time.Sleep(time.Duration((rnd.Intn(1000) + 1000)) * time.Millisecond) err := a.sendMsg(respMsg) if err != nil { logging.ErrorWithErr(err, "sendMsg fail skip send") @@ -55,70 +70,38 @@ func (a *Adapter) HandleCovert() { }() } -func (a *Adapter) Close() { - a.done <- struct{}{} -} - // // MetaData message.IMeta impl type MetaData struct { - Self *openwechat.Self - RawMsg *openwechat.Message - GroupMember openwechat.Members // 群组成员(群组消息才会有) - delayToken chan struct{} // 控制消息的接收与发送的随机间隔 + RawMsg *wcf.Message + //GroupMember openwechat.Members // todo 群组成员(群组消息才会有) RoomMember + delayToken chan struct{} // 控制消息的接收与发送的随机间隔 } -func NewMetaData(self *openwechat.Self, rawMsg *openwechat.Message) *MetaData { - return &MetaData{Self: self, RawMsg: rawMsg, delayToken: make(chan struct{})} +func NewMetaData(rawMsg *wcf.Message) *MetaData { + return &MetaData{RawMsg: rawMsg, delayToken: make(chan struct{})} } func (md *MetaData) GetRawMsg() interface{} { return md.RawMsg } -func (md *MetaData) GetISelf() interface{} { - return md.Self -} - -// GetMsgSenderNickname 获取消息发送者昵称 +// GetMsgSenderNickname 获取消息发送者昵称 todo func (md *MetaData) GetMsgSenderNickname() string { - sender, _ := md.RawMsg.Sender() - if sender.IsGroup() { // 获取群组内真实发送者 - senderInGroup, _ := md.RawMsg.SenderInGroup() - err := senderInGroup.Detail() - if err != nil { - logging.ErrorWithErr(err, "GetMsgSenderNickname fail, get sender detail fail") - return "" - } - return senderInGroup.NickName - } - if sender == nil { - return "" - } - return sender.NickName + return "" } // GetGroupNickname 获取群组消息的群名 func (md *MetaData) GetGroupNickname() string { - if !md.RawMsg.IsSendByGroup() { - return "" - } - sender, _ := md.RawMsg.Sender() - return sender.NickName + // todo + return "" } -// GetGroupMemberIdByNickname 获取群成员的user_id根据nickname -func (md *MetaData) GetGroupMemberIdByNickname(nickname string) (string, error) { - if !md.RawMsg.IsSendByGroup() { // 不是群组消息,无法获取群成员id - return "", fmt.Errorf("cannot get member id, %w", ErrNotGroupMsg) - } - member, ok := md.GroupMember.GetByNickName(nickname) - if !ok && member == nil { - return nickname, nil // todo 自己发送的消息无法获取 member - //return "", fmt.Errorf("get group member failed by the nickname") - } - return member.NickName, nil // todo member只能获取到 username 但是 username 每次登录都会改变 故这临时使用nickname作为标识 +// GetRoomNameByRoomId 根据RoomId 获得群名 +func (md *MetaData) GetRoomNameByRoomId(id string) (string, error) { + // todo + return "", nil } func (md *MetaData) runDelayTimer(delayMin int, delayMax int) { @@ -127,166 +110,61 @@ func (md *MetaData) runDelayTimer(delayMin int, delayMax int) { close(md.delayToken) } -// AgreeNewFriend 同意新好友的添加请求 -func (md *MetaData) AgreeNewFriend() bool { - _, err := md.RawMsg.Agree("Hello world!") // friend 对象可以进一步 处理 - if err != nil { - return false - } - return true -} - -// AsReadMsg 已读消息 -func (md *MetaData) AsReadMsg() { - err := md.RawMsg.AsRead() - if err != nil { - logging.ErrorWithErr(err, "AsReadMsg fail") - } -} - // // covert 消息转换处理 -func (a *Adapter) covert(msg *openwechat.Message) *message.Message { +func (a *Adapter) covert(msg *wcf.Message) *message.Message { var rikkaMsgType message.MsgType - switch msg.MsgType { - case openwechat.MsgTypeText: + switch msg.Type { + case uint32(wcf.MsgTypeText): rikkaMsgType = message.MsgTypeText - case openwechat.MsgTypeImage: + case uint32(wcf.MsgTypeImage): rikkaMsgType = message.MsgTypeImage - case openwechat.MsgTypeVoice: + case uint32(wcf.MsgTypeVoice): rikkaMsgType = message.MsgTypeVoice - case openwechat.MsgTypeVideo: + case uint32(wcf.MsgTypeVideo): rikkaMsgType = message.MsgTypeVideo - case openwechat.MsgTypeApp: // 解析app消息 - if msg.AppMsgType == openwechat.AppMsgTypeVideo { // 视频 app 消息 - rikkaMsgType = message.MsgTypeApp - } else { // todo 消息选择器测试无误后移除 - return nil // 忽略未知app消息 - } - case openwechat.MsgTypeVerify: - if !msg.IsFriendAdd() { // 不是添加好友的验证消息就忽略 - return nil - } - rikkaMsgType = message.MsgTypeNewFriendVerify - + case uint32(wcf.MsgTypeShare): // todo test 解析app消息 + //if msg.AppMsgType == openwechat.AppMsgTypeVideo { // 视频 app 消息 + // rikkaMsgType = message.MsgTypeApp + //} else { // todo 消息选择器测试无误后移除 + // return nil // 忽略未知app消息 + //} default: return nil // 忽略未知的消息种类 } - self, _ := a.openwcBot.GetCurrentUser() // ignore err - - metaData := NewMetaData(self, msg) - rikkacfg := a.selfBot.Config - go metaData.runDelayTimer(rikkacfg.AnswerDelayRandMin, rikkacfg.AnswerDelayRandMax) // 消息随机延迟 + metaData := NewMetaData(msg) + cfg := config.GetConfig() + go metaData.runDelayTimer(cfg.AnswerDelayRandMin, cfg.AnswerDelayRandMax) // 消息随机延迟 - rself := common.GetSelf() // 获取rikka的self对象 - // 获取 ID - isSendByGroup := msg.IsSendByGroup() - uuid := "" - GroupId := "" - ReceiveId := "" - SenderId := "" - sender, _ := msg.Sender() // ignore err - if rikkaMsgType != message.MsgTypeNewFriendVerify { // todo 优化掉这个公众号判断 - // 忽略公众号发送的一切消息 - if !sender.IsFriend() && !sender.IsGroup() && !sender.IsSelf() { - return nil - } - // 忽略公众号发送的一切消息 - if sender.IsMP() { - return nil - } - } - receiver, _ := msg.Receiver() // ignore err - if receiver == nil { - return nil - } - var isAtMe = false - var groupNameList []string - var groupAtNameList []string - SenderName := sender.NickName - GroupName := "" + //rself := common.GetSelf() // 获取rikka的self对象 - // 获取uuid - uuid = rself.GetUuidById(sender, isSendByGroup) - - if isSendByGroup { - senderInGroup, _ := msg.SenderInGroup() // ignore err - if senderInGroup == nil { - return nil - } - err := senderInGroup.Detail() - if err != nil { - logging.ErrorWithErr(err, "GetMsgSenderNickname fail, get sender detail fail") - - } else { - SenderId = senderInGroup.AvatarID() - } - GroupName = sender.NickName - SenderName = senderInGroup.NickName - GroupId = sender.AvatarID() // GroupSenderID - ReceiveId = receiver.AvatarID() - - // 自己发送的ID群号跟接收者号反转 - if msg.IsSendBySelf() { - GroupId, ReceiveId = ReceiveId, SenderId - uuid = rself.GetUuidById(receiver, isSendByGroup) // uuid 改为接收者获取 - } - // 获取群成员的用户名 - group, ok := sender.AsGroup() - if ok { - members, _ := group.Members() // ignore err - metaData.GroupMember = members // 加入meta中 - cnt := members.Count() - groupNameList = make([]string, cnt) - for i := 0; i < cnt; i++ { - groupNameList[i] = members[i].NickName - } - } - // 获取消息中艾特成员的成员名 - re := regexp.MustCompile(`@([^\s]+) `) - matches := re.FindAllStringSubmatch(msg.Content, -1) - groupAtNameList = make([]string, len(matches)) - for i, match := range matches { - if len(match) > 1 { - groupAtNameList[i] = match[1] - isAtMe = match[1] == self.NickName // 是否艾特自己 - } + // 获取消息中艾特成员的成员名 + re := regexp.MustCompile(`@([^\s]+) `) + matches := re.FindAllStringSubmatch(msg.Content, -1) + groupAtNameList := make([]string, len(matches)) + var isAtMe bool + for i, match := range matches { + if len(match) > 1 { + groupAtNameList[i] = match[1] + isAtMe = match[1] == a.cli.GetSelfInfo().Name // 是否艾特自己 } - - } else { - SenderId = sender.AvatarID() - ReceiveId = receiver.AvatarID() // todo 测试中引起错误,待验证 } - imgData := handleSpecialRaw(msg) - content := msg.Content - if msg.MsgType == openwechat.MsgTypeImage { - content = "" - } - if rikkaMsgType == message.MsgTypeNewFriendVerify { - content = msg.RecommendInfo.Content // 好友验证消息 - } - return &message.Message{ - Msgtype: rikkaMsgType, - MetaData: metaData, - Raw: imgData, - RawContent: msg.RawContent, - ChatImgUrl: cacheImgCovert2Url(imgData, uuid), // 图片url - Content: content, - Uuid: uuid, // 通过备注名获取的唯一用户标识 - GroupId: GroupId, - GroupName: GroupName, - SenderId: SenderId, - SenderName: SenderName, - ReceiverId: ReceiveId, - GroupNameList: groupNameList, - GroupAtNameList: groupAtNameList, - IsAtMe: isAtMe, - IsGroup: isSendByGroup, - IsFriend: msg.IsSendByFriend(), - IsMySelf: msg.IsSendBySelf(), // 是否为自己发送的消息 + Msgtype: rikkaMsgType, + MetaData: metaData, + RawContent: msg.Content, + //ChatImgUrl: cacheImgCovert2Url(imgData, uuid), // 图片url + Content: msg.Content, + MsgId: msg.MessageId, + WxId: msg.WxId, + RoomId: msg.RoomId, + //GroupName: todo + IsAtMe: isAtMe, + IsGroup: msg.IsGroup, + //IsFriend: msg.IsSendByFriend(), todo + IsMySelf: msg.IsSelf, // 是否为自己发送的消息 } } @@ -300,32 +178,18 @@ func cacheImgCovert2Url(data []byte, uuid string) string { return imgUrl } -func handleSpecialRaw(msg *openwechat.Message) []byte { - if msg.MsgType == openwechat.MsgTypeImage { - var buf bytes.Buffer - err := msg.SaveFile(&buf) // 图片转为正确 []byte - if err != nil { - logging.ErrorWithErr(err, "SaveFile fail") - } - return buf.Bytes() - } else if msg.MsgType == openwechat.MsgTypeText { - return nil - } - return nil -} - // @Author By Clover 2024/7/5 下午5:28:00 // @Reason 处理外部平台消息,转为自身消息 // @Demand Version -func (a *Adapter) receiveMsg(msg *openwechat.Message) { +func (a *Adapter) receiveMsg(msg *wcf.Message) { selfMsg := a.covert(msg) if selfMsg == nil { return } copyMsg := *selfMsg - a.selfBot.DispatchMsgEvent(copyMsg) // 存入事件池 - if a.selfBot.EnableProcess { // 判断是否启动了处理器(防止没有消费者阻塞在此) - a.selfBot.GetReqMsgSendChan() <- selfMsg + a.rikkaBot.DispatchMsgEvent(copyMsg) // 存入事件池 + if a.rikkaBot.EnableProcess { // 判断是否启动了处理器(防止没有消费者阻塞在此) + a.rikkaBot.GetReqMsgSendChan() <- selfMsg } } @@ -335,22 +199,22 @@ func (a *Adapter) sendMsg(sendMsg *message.Message) error { return fmt.Errorf("can't send msg, sendMsg err: %w", ErrMetaDateNil) } <-sendMsg.MetaData.(*MetaData).delayToken // 需要延迟随机时间后,才能发送消息 - rawMsg, ok := sendMsg.MetaData.GetRawMsg().(*openwechat.Message) + rawMsg, ok := sendMsg.MetaData.GetRawMsg().(*wcf.Message) if !ok { logging.Debug("get metaData.rawMsg failed", map[string]interface{}{"sendMsg": sendMsg}) return fmt.Errorf("get metaData.rawMsg failed, err: %w", ErrRawMSgNil) } switch sendMsg.Msgtype { case message.MsgTypeText: - replyText, err := rawMsg.ReplyText(sendMsg.Content) - if err != nil { - logging.ErrorWithErr(err, "SendMsg fail", map[string]interface{}{"replyText": replyText}) - } - case message.MsgTypeImage: - replyImage, err := rawMsg.ReplyImage(bytes.NewReader(sendMsg.Raw)) + err := rawMsg.ReplyText(sendMsg.Content) if err != nil { - logging.ErrorWithErr(err, "SendMsg fail", map[string]interface{}{"replyImage": replyImage}) + logging.ErrorWithErr(err, "SendMsg fail") } + //case message.MsgTypeImage: + // replyImage, err := rawMsg.ReplyImage(bytes.NewReader(sendMsg.Raw)) + // if err != nil { + // logging.ErrorWithErr(err, "SendMsg fail", map[string]interface{}{"replyImage": replyImage}) + // } default: logging.Warn("unknown msgType do not handle send") } diff --git a/rikkabot/adapter/adapter_test.go b/rikkabot/adapter/adapter_test.go index 935af26..744a597 100644 --- a/rikkabot/adapter/adapter_test.go +++ b/rikkabot/adapter/adapter_test.go @@ -5,16 +5,16 @@ package adapter import ( "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/serializer" "github.com/eatmoreapple/openwechat" _ "image/png" "math/rand" "strings" "testing" "time" - "wechat-demo/rikkabot" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/utils/serializer" ) // 测试是否转发接收到的消息,二次封装是否正常 diff --git a/rikkabot/adapter/export_test.go b/rikkabot/adapter/export_test.go deleted file mode 100644 index 2f22784..0000000 --- a/rikkabot/adapter/export_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// @Author Clover -// @Data 2024/7/5 下午8:47:00 -// @Desc -package adapter - -import ( - "fmt" - "github.com/eatmoreapple/openwechat" - "wechat-demo/rikkabot/logging" -) - -//var Covert = (*Adapter).covert -// -//var SendMsg = (*Adapter).sendMsg - -var HandleCovert = func(a *Adapter) { - a.openwcBot.MessageHandler = func(msg *openwechat.Message) { - fmt.Printf("收到消息: %#v\n", msg) - a.receiveMsg(msg) - } - go func() { - respMsgRecvChan := a.selfBot.GetRespMsgRecvChan() - for { - select { - case <-a.done: - return - case respMsg := <-respMsgRecvChan: - //rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - //time.Sleep(time.Duration((rnd.Intn(1000) + 1000)) * time.Millisecond) - err := a.sendMsg(respMsg) - if err != nil { - logging.ErrorWithErr(err, "sendMsg fail skip send") - } - } - } - }() -} diff --git a/rikkabot/common/user.go b/rikkabot/common/user.go index 09f9ae0..34dcaaa 100644 --- a/rikkabot/common/user.go +++ b/rikkabot/common/user.go @@ -7,11 +7,11 @@ package common import ( "errors" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/secretutil" "github.com/eatmoreapple/openwechat" "io" "sync" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/utils/secretutil" ) type Self struct { @@ -48,6 +48,8 @@ func GetSelf() *Self { return self } +// todo test sdk 中实现,废弃 +// Deprecated func InitSelf(bot *openwechat.Bot) { bself, _ := bot.GetCurrentUser() // ignore error friends, _ := bself.Friends() // ignore err @@ -657,54 +659,3 @@ func (s *Self) doSendImgByUuid(uuid string, img io.Reader, isGroup bool) error { } return nil } - -// IsUuidValid 是否为uuid -func IsUuidValid(uuid string) bool { - if len(uuid) != 16 { - return false - } - return true -} - -const ( - UUID_NOT_UNIQUE_INGROUPS = "That uuid is not unique in groups! Error!" - UUID_NOT_UNIQUE_INFRIENDS = "That uuid is not unique in friends! Error!" -) - -// GetUuidById 根据 用户id获取uuid -func (s *Self) GetUuidById(user *openwechat.User, isGroup bool) string { - remarkName := user.RemarkName - var uuid = secretutil.GenerateUnitId(remarkName) - if remarkName == "" { - uuid = secretutil.GenerateUnitId(user.NickName) - } - // 校验是否为重复uuid - if isGroup { - if s.UidGroupNotUnique[uuid] { - uuid = UUID_NOT_UNIQUE_INGROUPS - } - } else { - if s.UidFriendNotUnique[uuid] { - uuid = UUID_NOT_UNIQUE_INFRIENDS - } - } - return uuid -} - -func (mf MyFriends) SearchById(id string) *openwechat.User { - for _, friend := range mf { - if friend.AvatarID() == id { - return friend - } - } - return nil -} - -func (mg MyGroups) SearchById(id string) *openwechat.User { - for _, g := range mg { - if g.AvatarID() == id { - return g - } - } - return nil -} diff --git a/rikkabot/config/config.go b/rikkabot/config/config.go index 7f29bd1..56dc37c 100644 --- a/rikkabot/config/config.go +++ b/rikkabot/config/config.go @@ -7,10 +7,10 @@ package config import ( "errors" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/configutil" "os" "sync" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/utils/configutil" ) type CommonConfig struct { diff --git a/rikkabot/manager/bboltManager.go b/rikkabot/manager/bboltManager.go index be59288..b8a2cc1 100644 --- a/rikkabot/manager/bboltManager.go +++ b/rikkabot/manager/bboltManager.go @@ -8,6 +8,10 @@ import ( "encoding/json" "errors" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/imgutil" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/timeutil" "github.com/rs/zerolog/log" "go.etcd.io/bbolt" "os" @@ -16,11 +20,6 @@ import ( "strings" "sync" "time" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/config" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/utils/imgutil" - "wechat-demo/rikkabot/utils/timeutil" ) var ( @@ -131,9 +130,9 @@ func LoadCache(cache any) (any, error) { // SaveImg uuid: 可置空 func SaveImg(uuid string, imgData []byte) (imgName string, imgDate string) { - if uuid == common.UUID_NOT_UNIQUE_INGROUPS || uuid == common.UUID_NOT_UNIQUE_INFRIENDS { - uuid = "" // 重复 uuid 置空 - } + //if uuid == common.UUID_NOT_UNIQUE_INGROUPS || uuid == common.UUID_NOT_UNIQUE_INFRIENDS { + // uuid = "" // 重复 uuid 置空 + //} var err error imgId := timeutil.GetTimeStamp() + "_" + uuid nowDate := timeutil.GetNowDate() diff --git a/rikkabot/manager/imgManager.go b/rikkabot/manager/imgManager.go index 5bad6dd..edcd82e 100644 --- a/rikkabot/manager/imgManager.go +++ b/rikkabot/manager/imgManager.go @@ -7,11 +7,11 @@ package manager import ( "errors" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/timeutil" "github.com/rs/zerolog/log" "os" "strings" - "wechat-demo/rikkabot/config" - "wechat-demo/rikkabot/utils/timeutil" ) var ( diff --git a/rikkabot/manager/imgManager_test.go b/rikkabot/manager/imgManager_test.go index 62150d5..04cfbf9 100644 --- a/rikkabot/manager/imgManager_test.go +++ b/rikkabot/manager/imgManager_test.go @@ -7,13 +7,13 @@ package manager import ( "bufio" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" "github.com/rs/zerolog/log" "os" "strconv" "strings" "testing" "time" - "wechat-demo/rikkabot/logging" ) func init() { diff --git a/rikkabot/message/message.go b/rikkabot/message/message.go index 20ceeba..dc5b6f6 100644 --- a/rikkabot/message/message.go +++ b/rikkabot/message/message.go @@ -18,41 +18,35 @@ const ( type MsgMetaType int -// todo 增加对主动发送消息的支持 - type Message struct { - Msgtype MsgType `json:"msg_type"` - MetaData IMeta `json:"-"` // `json:"meta_data"` todo 元数据 (封装关于Sender Receiver Self 的 数据/调用) - Raw []byte `json:"-"` // 图片数据 - RawContent string `json:"-"` - ChatImgUrl string `json:"chat_img_url,omitempty"` // 图片url (只有图片类型消息存在该字段) - Content string `json:"content"` // 消息内容 - Uuid string `json:"uuid"` // 用户唯一标识 - GroupId string `json:"group_id"` // 唯一标识 - GroupName string `json:"group_name"` // 群昵称 - SenderId string `json:"sender_id"` // 唯一标识 - SenderName string `json:"sender_name"` // 消息发送者用户昵称 - ReceiverId string `json:"receiver_id"` // 唯一标识 - GroupNameList []string `json:"group_name_list"` // 群组成员的昵称(nickname) - GroupAtNameList []string `json:"group_at_name_list"` // 群组中艾特的成员昵称(nickname) - IsAtMe bool `json:"is_at"` // 群组中是否艾特本人 - IsGroup bool `json:"is_group"` // 是否为群聊消息 - IsFriend bool `json:"is_friend"` // 是否为好友私聊消息 - IsMySelf bool `json:"is_my_self"` // 消息是否为自己发送的 - IsSystem bool `json:"is_system"` // 是否为系统消息 + Msgtype MsgType `json:"msg_type"` + MetaData IMeta `json:"-"` // `json:"meta_data"` todo 元数据 (封装关于Sender Receiver Self 的 数据/调用) + Raw []byte `json:"-"` // 图片数据 + RawContent string `json:"-"` + ChatImgUrl string `json:"chat_img_url,omitempty"` // 图片url (只有图片类型消息存在该字段) + Content string `json:"content"` // 消息内容 + MsgId uint64 `json:"msg_id"` // 唯一标识 + WxId string `json:"wx_id"` // wxid + RoomId string `json:"room_id,omitempty"` // roomId + GroupName string `json:"group_name"` // 群昵称 + SenderName string `json:"sender_name"` // 消息发送者用户昵称 + //GroupNameList []string `json:"group_name_list"` // todo [改为meta中实现] 群组成员的昵称(nickname) + //GroupAtNameList []string `json:"group_at_name_list"` // todo [改为meta中实现] 群组中艾特的成员昵称(nickname) + IsAtMe bool `json:"is_at"` // 群组中是否艾特本人 + IsGroup bool `json:"is_group"` // 是否为群聊消息 + IsFriend bool `json:"is_friend"` // 是否为好友私聊消息 + IsMySelf bool `json:"is_my_self"` // 消息是否为自己发送的 + IsSystem bool `json:"is_system"` // 是否为系统消息 //Self ISelf `json:"raw_msg"` // 原先平台对应对象 //ReplyFunc func(msg *Message) `json:"-"` // todo 回复消息的方法 } type IMeta interface { - GetISelf() interface{} GetRawMsg() interface{} - GetMsgSenderNickname() string // 获取消息发送者昵称 - GetGroupNickname() string // 获取群组消息的群名 - GetGroupMemberIdByNickname(nickname string) (string, error) // 获取群成员的user_id根据nickname - AgreeNewFriend() bool // 同意好友请求 - AsReadMsg() // 已读消息 + GetMsgSenderNickname() string // todo 获取消息发送者昵称 + GetGroupNickname() string // todo 获取群组消息的群名 + GetRoomNameByRoomId(nickname string) (string, error) // todo 根据RoomId 获得RoomName } //type ISelf interface { diff --git a/rikkabot/onebot/dto/event/action.go b/rikkabot/onebot/dto/event/action.go index 59dd092..6e25471 100644 --- a/rikkabot/onebot/dto/event/action.go +++ b/rikkabot/onebot/dto/event/action.go @@ -4,7 +4,7 @@ // @Desc 事件动作 package event -import "wechat-demo/rikkabot/message" +import "github.com/Clov614/rikka-bot-wechat/rikkabot/message" type Echo string diff --git a/rikkabot/onebot/dto/event/event.go b/rikkabot/onebot/dto/event/event.go index c02ba49..bfd8f81 100644 --- a/rikkabot/onebot/dto/event/event.go +++ b/rikkabot/onebot/dto/event/event.go @@ -6,11 +6,11 @@ package event import ( "errors" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/timeutil" "github.com/google/uuid" "sync" "time" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/utils/timeutil" ) var ( diff --git a/rikkabot/onebot/dto/event/event_test.go b/rikkabot/onebot/dto/event/event_test.go index 0f3693d..ea7a009 100644 --- a/rikkabot/onebot/dto/event/event_test.go +++ b/rikkabot/onebot/dto/event/event_test.go @@ -5,9 +5,9 @@ package event import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/timeutil" "testing" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/utils/timeutil" ) import "github.com/google/uuid" diff --git a/rikkabot/onebot/httpapi/httpapi.go b/rikkabot/onebot/httpapi/httpapi.go index 6965203..cd6809d 100644 --- a/rikkabot/onebot/httpapi/httpapi.go +++ b/rikkabot/onebot/httpapi/httpapi.go @@ -10,6 +10,13 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/manager" + "github.com/Clov614/rikka-bot-wechat/rikkabot/onebot/dto/event" + "github.com/Clov614/rikka-bot-wechat/rikkabot/onebot/oneboterr" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/imgutil" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/timeutil" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/rs/zerolog/log" @@ -19,13 +26,6 @@ import ( "net/url" "strings" "time" - "wechat-demo/rikkabot" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/manager" - "wechat-demo/rikkabot/onebot/dto/event" - "wechat-demo/rikkabot/onebot/oneboterr" - "wechat-demo/rikkabot/utils/imgutil" - "wechat-demo/rikkabot/utils/timeutil" ) // HttpServer http 服务 @@ -102,8 +102,8 @@ func (s HttpServer) globalHandler() gin.HandlerFunc { switch { case "/send_message" == path: // 发送消息 s.handleSendMsg(c) - case "/login_callback" == path: // 获取登录回调 - s.handleLoginUrl(c) + //case "/login_callback" == path: // 获取登录回调 + // s.handleLoginUrl(c) case strings.HasPrefix(path, "/chat_image/"): s.handleChatImage(c, path) } @@ -138,48 +138,48 @@ func (s HttpServer) handleChatImage(c *gin.Context, path string) { c.Data(http.StatusOK, imgutil.GetMimeTypeByFileType(fileType), data) } -func (s HttpServer) handleLoginUrl(c *gin.Context) { - var req event.ActionRequest[any] - var resp event.ActionResponse - if c.Request.Method == http.MethodGet { - // 从URL查询解析参数 - - if err := c.ShouldBindQuery(&req); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - } else if c.Request.Method == http.MethodPost { - if err := c.ShouldBind(&req); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - } - logging.Debug("请求参数", map[string]interface{}{"action_request": req}) - if req.Action != "login_callback" { - retErr(c, "/login_callback 端点只处理 action: login_callback", - oneboterr.UNSUPPORTED_ACTION, failedStatus) - return - } - var retData struct { - Type string `json:"type"` - Data string `json:"data"` - } - retData.Type = "url" - retData.Data = s.bot.GetloginUrl() - resp.Retcode = oneboterr.OK - resp.Status = successStatus - resp.Data = retData - respData, err := json.Marshal(resp) - if err != nil { - logging.Error("marshal response failed", map[string]interface{}{"err": err.Error()}) - retErr(c, "marshal response failed", oneboterr.INTERNAL_HANDLER_ERROR, failedStatus) - return - } - - c.Header("Content-Type", "application/json") - logging.Info(fmt.Sprintf("发送成功回执: %+v", string(respData))) - c.String(http.StatusOK, string(respData)) // 返回json字符串 -} +//func (s HttpServer) handleLoginUrl(c *gin.Context) { +// var req event.ActionRequest[any] +// var resp event.ActionResponse +// if c.Request.Method == http.MethodGet { +// // 从URL查询解析参数 +// +// if err := c.ShouldBindQuery(&req); err != nil { +// c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) +// return +// } +// } else if c.Request.Method == http.MethodPost { +// if err := c.ShouldBind(&req); err != nil { +// c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) +// return +// } +// } +// logging.Debug("请求参数", map[string]interface{}{"action_request": req}) +// if req.Action != "login_callback" { +// retErr(c, "/login_callback 端点只处理 action: login_callback", +// oneboterr.UNSUPPORTED_ACTION, failedStatus) +// return +// } +// var retData struct { +// Type string `json:"type"` +// Data string `json:"data"` +// } +// retData.Type = "url" +// retData.Data = s.bot.GetloginUrl() +// resp.Retcode = oneboterr.OK +// resp.Status = successStatus +// resp.Data = retData +// respData, err := json.Marshal(resp) +// if err != nil { +// logging.Error("marshal response failed", map[string]interface{}{"err": err.Error()}) +// retErr(c, "marshal response failed", oneboterr.INTERNAL_HANDLER_ERROR, failedStatus) +// return +// } +// +// c.Header("Content-Type", "application/json") +// logging.Info(fmt.Sprintf("发送成功回执: %+v", string(respData))) +// c.String(http.StatusOK, string(respData)) // 返回json字符串 +//} func (s HttpServer) handleSendMsg(c *gin.Context) { var req event.ActionRequest[event.SendMsgParams] @@ -351,7 +351,7 @@ func (c HttpClient) HandlerPostEvent(event event.IEvent) { req, err = http.NewRequest("POST", c.postUrl, bytes.NewBuffer(eventJSON)) if err != nil { logHttpPostError(event, err, "request create failed") - rikkabot.Bot().ExitWithErr(1102, err.Error()) + c.bot.ExitWithErr(1102, err.Error()) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+encrypt(c.secret)) diff --git a/rikkabot/onebot/httpapi/httpapi_test.go b/rikkabot/onebot/httpapi/httpapi_test.go index 5c41d25..8cd2852 100644 --- a/rikkabot/onebot/httpapi/httpapi_test.go +++ b/rikkabot/onebot/httpapi/httpapi_test.go @@ -5,13 +5,13 @@ package httpapi import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot" + "github.com/Clov614/rikka-bot-wechat/rikkabot/adapter" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" "github.com/eatmoreapple/openwechat" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "testing" - "wechat-demo/rikkabot" - "wechat-demo/rikkabot/adapter" - "wechat-demo/rikkabot/logging" ) func TestHttpPost(t *testing.T) { diff --git a/rikkabot/plugins/admin/adminplugin.go b/rikkabot/plugins/admin/adminplugin.go index ac5e371..a22417a 100644 --- a/rikkabot/plugins/admin/adminplugin.go +++ b/rikkabot/plugins/admin/adminplugin.go @@ -7,14 +7,14 @@ package plugin_admin import ( "bytes" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/common" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/cache" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control/dialog" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/register" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/msgutil" "strings" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor/cache" - "wechat-demo/rikkabot/processor/control" - "wechat-demo/rikkabot/processor/control/dialog" - "wechat-demo/rikkabot/processor/register" - "wechat-demo/rikkabot/utils/msgutil" ) func init() { @@ -288,7 +288,7 @@ func (a AdminPlugin) addWhiteGroupByMsg(msg message.Message) (reply string) { if !msg.IsGroup { return "不是群消息,无法添加群聊白名单" } - a.cache.AddWhiteGroupId(msg.GroupId) + a.cache.AddWhiteGroupId(msg.RoomId) return fmt.Sprintf("添加成功,群组( %s )id( %s )进入白名单", msg.MetaData.GetGroupNickname(), msg.GroupId) } @@ -308,7 +308,7 @@ func (a AdminPlugin) deleteWhiteGroupByMsg(msg message.Message) (reply string) { if !msg.IsGroup { return "不是群消息,无法移除群聊白名单(请携带群名参数)" } - a.cache.DeleteWhiteGroupId(msg.GroupId) + a.cache.DeleteWhiteGroupId(msg.RoomId) return fmt.Sprintf("移除了,群组( %s )id( %s )的白名单", msg.MetaData.GetGroupNickname(), msg.GroupId) } @@ -339,7 +339,7 @@ func (a AdminPlugin) addBlackGroupByMsg(msg message.Message) (reply string) { if !msg.IsGroup { return "不是群聊无法添加群组黑名单(请携带群名参数)" } - a.cache.AddBlackGroupId(msg.GroupId) + a.cache.AddBlackGroupId(msg.RoomId) return fmt.Sprintf("添加了,群组( %s )id( %s )的黑名单", msg.MetaData.GetGroupNickname(), msg.GroupId) } @@ -348,7 +348,7 @@ func (a AdminPlugin) deleteBlackGroupByMsg(msg message.Message) (reply string) { if !msg.IsGroup { return "不是群聊无法移除群组黑名单(请携带群名参数)" } - a.cache.DeleteBlackGroupId(msg.GroupId) + a.cache.DeleteBlackGroupId(msg.RoomId) return fmt.Sprintf("移除了,群组( %s )id( %s )的黑名单", msg.MetaData.GetGroupNickname(), msg.GroupId) } @@ -398,7 +398,7 @@ func (a AdminPlugin) showBlackGroup() (reply string) { func (a AdminPlugin) addBlackUserByNickname(msg message.Message, nickname string) (reply string) { friendId, err := a.user.GetFriendIdByNickname(nickname) if friendId == "" { // 不是好友,尝试通过msg获取member id - friendId, err = msg.MetaData.GetGroupMemberIdByNickname(nickname) + friendId, err = msg.MetaData.GetRoomNameByRoomId(nickname) } if friendId == "" && err != nil { return "添加用户黑名单失败,错误:" + err.Error() @@ -411,7 +411,7 @@ func (a AdminPlugin) addBlackUserByNickname(msg message.Message, nickname string func (a AdminPlugin) deleteBlackUserByNickname(msg message.Message, nickname string) (reply string) { friendId, err := a.user.GetFriendIdByNickname(nickname) if friendId == "" { // 不是好友,尝试通过msg获取member id - friendId, err = msg.MetaData.GetGroupMemberIdByNickname(nickname) + friendId, err = msg.MetaData.GetRoomNameByRoomId(nickname) } if friendId == "" && err != nil { return "移除用户黑名单失败,错误:" + err.Error() diff --git a/rikkabot/plugins/admin/adminplugin_test.go b/rikkabot/plugins/admin/adminplugin_test.go index 0b0a65e..542114f 100644 --- a/rikkabot/plugins/admin/adminplugin_test.go +++ b/rikkabot/plugins/admin/adminplugin_test.go @@ -5,12 +5,12 @@ package plugin_admin_test import ( "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/common" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor" "github.com/eatmoreapple/openwechat" "testing" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor" ) // deprecated 测试管理员模块 diff --git a/rikkabot/plugins/ai/cron/cronplugins/pushWeather.go b/rikkabot/plugins/ai/cron/cronplugins/pushWeather.go index abec232..320a9ea 100644 --- a/rikkabot/plugins/ai/cron/cronplugins/pushWeather.go +++ b/rikkabot/plugins/ai/cron/cronplugins/pushWeather.go @@ -10,10 +10,10 @@ import ( aisdk "github.com/Clov614/go-ai-sdk" "github.com/Clov614/go-ai-sdk/example_func_call/weather" "github.com/Clov614/go-ai-sdk/global" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins/ai/cron" "strings" - "wechat-demo/rikkabot/config" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/plugins/ai/cron" ) type weatherCfg struct { diff --git a/rikkabot/plugins/ai/cron/rikkacron.go b/rikkabot/plugins/ai/cron/rikkacron.go index ece97a6..ad4922b 100644 --- a/rikkabot/plugins/ai/cron/rikkacron.go +++ b/rikkabot/plugins/ai/cron/rikkacron.go @@ -6,10 +6,10 @@ package cron import ( "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/common" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" "github.com/robfig/cron/v3" "github.com/rs/zerolog/log" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/logging" ) var cronServer *MyCronServer diff --git a/rikkabot/plugins/ai/talk2ai.go b/rikkabot/plugins/ai/talk2ai.go index c827db2..ac4bb5f 100644 --- a/rikkabot/plugins/ai/talk2ai.go +++ b/rikkabot/plugins/ai/talk2ai.go @@ -8,14 +8,14 @@ import ( "encoding/json" "fmt" aisdk "github.com/Clov614/go-ai-sdk" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + _ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins/ai/cron" + _ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins/ai/cron/cronplugins" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control/dialog" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/register" "github.com/rs/zerolog/log" - "wechat-demo/rikkabot/config" - "wechat-demo/rikkabot/message" - _ "wechat-demo/rikkabot/plugins/ai/cron" - _ "wechat-demo/rikkabot/plugins/ai/cron/cronplugins" - "wechat-demo/rikkabot/processor/control" - "wechat-demo/rikkabot/processor/control/dialog" - "wechat-demo/rikkabot/processor/register" ) type AiCfg struct { diff --git a/rikkabot/plugins/ai/weather_func2ai.go b/rikkabot/plugins/ai/weather_func2ai.go index 94da69a..0aeddf2 100644 --- a/rikkabot/plugins/ai/weather_func2ai.go +++ b/rikkabot/plugins/ai/weather_func2ai.go @@ -9,8 +9,8 @@ import ( ai_sdk "github.com/Clov614/go-ai-sdk" "github.com/Clov614/go-ai-sdk/example_func_call/weather" "github.com/Clov614/go-ai-sdk/global" - "wechat-demo/rikkabot/config" - "wechat-demo/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" ) type weatherCfg struct { diff --git a/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go b/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go index e040bea..f675775 100644 --- a/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go +++ b/rikkabot/plugins/biliUrlDecode/biliUrlDecode.go @@ -4,14 +4,14 @@ import ( "bytes" "encoding/xml" "github.com/Clov614/bilibili" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control/dialog" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/register" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/imgutil" "github.com/rs/zerolog/log" "regexp" "strconv" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor/control" - "wechat-demo/rikkabot/processor/control/dialog" - "wechat-demo/rikkabot/processor/register" - "wechat-demo/rikkabot/utils/imgutil" ) func init() { diff --git a/rikkabot/plugins/defaultPlugin.go b/rikkabot/plugins/defaultPlugin.go index ade0e08..11fe57c 100644 --- a/rikkabot/plugins/defaultPlugin.go +++ b/rikkabot/plugins/defaultPlugin.go @@ -9,16 +9,13 @@ import ( "encoding/json" "errors" "fmt" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/message" - _ "wechat-demo/rikkabot/plugins/admin" // 需要副作用 init注册方法 - _ "wechat-demo/rikkabot/plugins/ai" // 需要副作用 init注册方法 - _ "wechat-demo/rikkabot/plugins/biliUrlDecode" // 需要副作用 init注册方法 - _ "wechat-demo/rikkabot/plugins/game" // 需要副作用 init注册方法 - "wechat-demo/rikkabot/processor/control" - "wechat-demo/rikkabot/processor/control/dialog" - "wechat-demo/rikkabot/processor/register" - "wechat-demo/rikkabot/utils/msgutil" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + _ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins/admin" // 需要副作用 init注册方法 + _ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins/ai" // 需要副作用 init注册方法 + _ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins/biliUrlDecode" // 需要副作用 init注册方法 + _ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins/game" // 需要副作用 init注册方法 + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control/dialog" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/msgutil" ) const ( @@ -33,54 +30,6 @@ var ( ) func init() { - - // core - coreRules := &control.ProcessRules{EnableMsgType: []message.MsgType{message.MsgTypeNewFriendVerify}} - - // manager - rules := &control.ProcessRules{IsCallMe: true, IsAdmin: true, IsAtMe: true, EnableGroup: true, EnableMsgType: []message.MsgType{message.MsgTypeText}, ExecOrder: []string{pluginCallName}} - aanf := autoAddNewFriend{ - onceDialogM: dialog.InitOnceDialog("自动添加好友管理", rules), - onceDialogC: dialog.InitOnceDialog("自动添加好友核心", coreRules), - } - aanf.onceDialogC.SetOnceFunc(func(recvmsg message.Message, sendMsg chan<- *message.Message) { - aanf.recoverCache() // 恢复缓存 - err := aanf.addNewFriend(recvmsg) // 处理添加好友消息 - if err != nil { - logging.ErrorWithErr(err, autoAddnewfriendCore) - } - }) - - aanf.onceDialogM.SetOnceFunc(func(recvmsg message.Message, sendMsg chan<- *message.Message) { - aanf.recoverCache() // 恢复缓存 - switch true { - case isChoice(recvmsg.Content, "help"): // 帮助信息 - aanf.onceDialogM.SendText(recvmsg.MetaData, aanf.help()) - case isChoice(recvmsg.Content, "true"): - aanf.SetIsEnable(true) - aanf.onceDialogM.SendText(recvmsg.MetaData, "开启自动通过好友请求成功") - case isChoice(recvmsg.Content, "false"): - aanf.SetIsEnable(false) - aanf.onceDialogM.SendText(recvmsg.MetaData, "关闭自动通过好友请求成功") - case isChoice(recvmsg.Content, "verify"): - bStr := msgutil.TrimPrefix(recvmsg.Content, "verify", false, true) - b, content := aanf.SetIsVerify(bStr) // 根据文本设置是否开启文本校验 - if b { - aanf.onceDialogM.SendText(recvmsg.MetaData, content) - } - case isChoice(recvmsg.Content, "set"): // 设置校验文本 - verifyText := msgutil.TrimPrefix(recvmsg.Content, "set", false, true) - if verifyText != "" { - aanf.onceDialogM.SendText(recvmsg.MetaData, aanf.SetVerifyText(verifyText)) - } - case isChoice(recvmsg.Content, "state"): - aanf.onceDialogM.SendText(recvmsg.MetaData, aanf.state()) - } - // 更新缓存 - aanf.onceDialogM.Cache.UploadCacheByPluginName(autoAddnewfriendName, aanf.Cache) - }) - register.RegistPlugin(autoAddnewfriendCore, aanf.onceDialogC, 0) - register.RegistPlugin(autoAddnewfriendName, aanf.onceDialogM, 1) } func isChoice(cotent string, prefix string) bool { @@ -117,22 +66,6 @@ func (af *autoAddNewFriend) recoverCache() { } // 恢复缓存 } -func (af *autoAddNewFriend) addNewFriend(msg message.Message) error { - if !af.Cache.IsEnable { // 不自动添加好友 - return nil - } - if af.Cache.IsVerify { - if !msgutil.HasPrefix(msg.Content, af.Cache.VerifyText, false) { // 不符合规则直接返回 - return irregularVerifyErr - } - } - if !msg.MetaData.AgreeNewFriend() { - return addFriendErr - } - af.onceDialogM.Self.UpdateFriends() // 更新好友列表 - return nil -} - func (af *autoAddNewFriend) SetIsEnable(b bool) { af.Cache.IsEnable = b } diff --git a/rikkabot/plugins/defaultPlugin_test.go b/rikkabot/plugins/defaultPlugin_test.go index aa9092e..acb0585 100644 --- a/rikkabot/plugins/defaultPlugin_test.go +++ b/rikkabot/plugins/defaultPlugin_test.go @@ -5,8 +5,8 @@ package plugins import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/msgutil" "testing" - "wechat-demo/rikkabot/utils/msgutil" ) func Test_autoAddNewFriend_SetIsVerify(t *testing.T) { diff --git a/rikkabot/plugins/game/defaultGame.go b/rikkabot/plugins/game/defaultGame.go index 1641b4b..4ca03ae 100644 --- a/rikkabot/plugins/game/defaultGame.go +++ b/rikkabot/plugins/game/defaultGame.go @@ -7,16 +7,16 @@ package plugin_game import ( "errors" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control/dialog" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/register" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/msgutil" "github.com/rs/zerolog/log" "math/rand" "strconv" "strings" "time" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor/control" - "wechat-demo/rikkabot/processor/control/dialog" - "wechat-demo/rikkabot/processor/register" - "wechat-demo/rikkabot/utils/msgutil" ) var ( diff --git a/rikkabot/processor/cache/cache.go b/rikkabot/processor/cache/cache.go index 5ae6c7f..2c93b62 100644 --- a/rikkabot/processor/cache/cache.go +++ b/rikkabot/processor/cache/cache.go @@ -7,13 +7,13 @@ package cache import ( "errors" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/manager" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/register" "github.com/rs/zerolog/log" "sync" "time" - "wechat-demo/rikkabot/config" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/manager" - "wechat-demo/rikkabot/processor/register" ) type Cache struct { diff --git a/rikkabot/processor/cache/checkrule.go b/rikkabot/processor/cache/checkrule.go index c685fe9..51e2b57 100644 --- a/rikkabot/processor/cache/checkrule.go +++ b/rikkabot/processor/cache/checkrule.go @@ -5,11 +5,11 @@ package cache import ( - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor/control" - "wechat-demo/rikkabot/utils/msgutil" + "github.com/Clov614/rikka-bot-wechat/rikkabot/common" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/msgutil" ) // IsEnable 插件是否启用 @@ -113,7 +113,7 @@ func (c *Cache) checkAdmin(msg message.Message) bool { if msg.IsMySelf { return true } - return c.HasAdminUserId(msg.SenderId) + return c.HasAdminUserId(msg.WxId) } // 判断消息发送者是否在白名单中 @@ -121,7 +121,7 @@ func (c *Cache) checkWhiteUser(msg message.Message) bool { if msg.IsMySelf { return true } - return c.HasWhiteUserId(msg.SenderId) + return c.HasWhiteUserId(msg.WxId) } // 判断群组消息是否存在白名单中 @@ -129,7 +129,7 @@ func (c *Cache) checkWhiteGroup(msg message.Message) bool { if !msg.IsGroup { // 不是群组消息直接返回 return true } - return c.HasWhiteGroupId(msg.GroupId) + return c.HasWhiteGroupId(msg.RoomId) } // 判断是否不存在黑名单中 @@ -137,7 +137,7 @@ func (c *Cache) checkBlackUser(msg message.Message) bool { if msg.IsMySelf { return true } - return !c.HasBlackUserId(msg.SenderId) + return !c.HasBlackUserId(msg.WxId) } // 判断是否不存在黑名单中 @@ -145,7 +145,7 @@ func (c *Cache) checkBlackGroup(msg message.Message) bool { if !msg.IsGroup { // 不是群组消息直接返回 return true } - return !c.HasBlackGroupId(msg.GroupId) + return !c.HasBlackGroupId(msg.RoomId) } func (c *Cache) checkEnableMsgTyp(enableMsgTypes []message.MsgType, msg message.Message) bool { diff --git a/rikkabot/processor/cache/checkrule_test.go b/rikkabot/processor/cache/checkrule_test.go index d177b40..a113e35 100644 --- a/rikkabot/processor/cache/checkrule_test.go +++ b/rikkabot/processor/cache/checkrule_test.go @@ -4,9 +4,9 @@ package cache import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" "testing" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor/control" ) // 触发器 触发校验 测试 diff --git a/rikkabot/processor/control/dialog/dialog.go b/rikkabot/processor/control/dialog/dialog.go index e38dc66..9c08871 100644 --- a/rikkabot/processor/control/dialog/dialog.go +++ b/rikkabot/processor/control/dialog/dialog.go @@ -7,16 +7,16 @@ package dialog import ( "bytes" "errors" + "github.com/Clov614/rikka-bot-wechat/rikkabot/common" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/cache" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "runtime" "sync" "time" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor/cache" - "wechat-demo/rikkabot/processor/control" ) var ( @@ -98,7 +98,6 @@ func (d *Dialog) RecvMessage(checkRules *control.ProcessRules, done chan struct{ case msg := <-d.recvMsg: msg, isHandle, order := d.Cache.IsHandle(checkRules, msg) if isHandle { - msg.MetaData.AsReadMsg() // 确认处理标为已读消息 return msg, true, order } case <-done: diff --git a/rikkabot/processor/control/dialog/dialog_test.go b/rikkabot/processor/control/dialog/dialog_test.go index 6ba7aa2..f13ff58 100644 --- a/rikkabot/processor/control/dialog/dialog_test.go +++ b/rikkabot/processor/control/dialog/dialog_test.go @@ -4,8 +4,8 @@ package dialog import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" "testing" - "wechat-demo/rikkabot/message" ) func TestDialog_RunPlugin(t *testing.T) { diff --git a/rikkabot/processor/control/dialog/longDialog.go b/rikkabot/processor/control/dialog/longDialog.go index 2a42811..064b082 100644 --- a/rikkabot/processor/control/dialog/longDialog.go +++ b/rikkabot/processor/control/dialog/longDialog.go @@ -5,11 +5,11 @@ package dialog import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot/common" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/cache" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" "time" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/processor/cache" - "wechat-demo/rikkabot/processor/control" ) // LongFunc 长对话作用方法 @@ -49,9 +49,9 @@ func (ld *LongDialog) RunPlugin(sendChan chan<- *message.Message, receiveChan ch firstMsg := <-receiveChan // 记录 id if firstMsg.IsGroup { - ld.id = firstMsg.GroupId + ld.id = firstMsg.RoomId } else { - ld.id = firstMsg.SenderId + ld.id = firstMsg.WxId } // 初始化通道 @@ -79,7 +79,6 @@ func (ld *LongDialog) RecvMessage(checkRules *control.ProcessRules, done chan st case msg := <-ld.filtedRecv: msg, isHandle, order := ld.Cache.IsHandle(checkRules, msg) if isHandle { - msg.MetaData.AsReadMsg() // 确认处理标为已读消息 return msg, true, order } case <-done: @@ -102,12 +101,12 @@ func (ld *LongDialog) RecvMsgFilter() (filtedRecv chan message.Message) { return } if msg.IsGroup { - if ld.id == msg.GroupId { + if ld.id == msg.RoomId { filtedRecv <- msg ld.resetTimer <- struct{}{} // 重置超时 } } else { - if ld.id == msg.SenderId { + if ld.id == msg.WxId { filtedRecv <- msg ld.resetTimer <- struct{}{} // 重置超时 } diff --git a/rikkabot/processor/control/rules.go b/rikkabot/processor/control/rules.go index dd0ab8b..d9dc22a 100644 --- a/rikkabot/processor/control/rules.go +++ b/rikkabot/processor/control/rules.go @@ -4,7 +4,7 @@ // @Desc package control -import "wechat-demo/rikkabot/message" +import "github.com/Clov614/rikka-bot-wechat/rikkabot/message" // ProcessRules 处理规则 type ProcessRules struct { diff --git a/rikkabot/processor/processor.go b/rikkabot/processor/processor.go index ec82d95..8609ff6 100644 --- a/rikkabot/processor/processor.go +++ b/rikkabot/processor/processor.go @@ -5,13 +5,13 @@ package processor import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/register" "sync" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/message" - _ "wechat-demo/rikkabot/plugins" // 需要副作用 - "wechat-demo/rikkabot/processor/cache" - dpkg "wechat-demo/rikkabot/processor/control/dialog" - "wechat-demo/rikkabot/processor/register" + //_ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins" // 需要副作用 + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/cache" + dpkg "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control/dialog" ) type Processor struct { diff --git a/rikkabot/processor/processor_test.go b/rikkabot/processor/processor_test.go index 50e6706..d5314ba 100644 --- a/rikkabot/processor/processor_test.go +++ b/rikkabot/processor/processor_test.go @@ -5,11 +5,11 @@ package processor import ( "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + _ "github.com/Clov614/rikka-bot-wechat/rikkabot/plugins" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/cache" "testing" "time" - "wechat-demo/rikkabot/message" - _ "wechat-demo/rikkabot/plugins" - "wechat-demo/rikkabot/processor/cache" ) func TestMsgDispatch(t *testing.T) { diff --git a/rikkabot/processor/register/register.go b/rikkabot/processor/register/register.go index 0201be7..548ad2b 100644 --- a/rikkabot/processor/register/register.go +++ b/rikkabot/processor/register/register.go @@ -4,8 +4,8 @@ package register import ( + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor/control" "sync" - "wechat-demo/rikkabot/processor/control" ) // todo 通用 状态缓存,信息缓存结构的定义(定义标准供插件使用) (总结出功能的共性)(通用的开发功能方法的提取) diff --git a/rikkabot/rikkabot.go b/rikkabot/rikkabot.go index 003bb10..f47f4ed 100644 --- a/rikkabot/rikkabot.go +++ b/rikkabot/rikkabot.go @@ -1,31 +1,28 @@ package rikkabot import ( - "bytes" "context" "errors" "fmt" + "github.com/Clov614/rikka-bot-wechat/rikkabot/config" + "github.com/Clov614/rikka-bot-wechat/rikkabot/logging" + "github.com/Clov614/rikka-bot-wechat/rikkabot/manager" + "github.com/Clov614/rikka-bot-wechat/rikkabot/message" + "github.com/Clov614/rikka-bot-wechat/rikkabot/onebot/dto/event" + "github.com/Clov614/rikka-bot-wechat/rikkabot/processor" + "github.com/Clov614/rikka-bot-wechat/rikkabot/utils/timeutil" + wcf "github.com/Clov614/wcf-rpc-sdk" "github.com/google/uuid" "sync" - "wechat-demo/rikkabot/common" - "wechat-demo/rikkabot/config" - "wechat-demo/rikkabot/logging" - "wechat-demo/rikkabot/manager" - "wechat-demo/rikkabot/message" - "wechat-demo/rikkabot/onebot/dto/event" - "wechat-demo/rikkabot/processor" - "wechat-demo/rikkabot/utils/imgutil" - "wechat-demo/rikkabot/utils/timeutil" ) type RikkaBot struct { - ctx context.Context - cancel func() - self *common.Self - sendMsg chan *message.Message - recvMsg chan *message.Message - Config *config.CommonConfig - loginUrl string // 登录链接 + ctx context.Context + cancel func() + sendMsg chan *message.Message + recvMsg chan *message.Message + Config *config.CommonConfig + cli *wcf.Client // hook sdk EnableProcess bool // 是否处理消息 Processor *processor.Processor @@ -42,78 +39,41 @@ var ( ErrInvalidCall = errors.New("invalid bot call") ErrSendMsg = errors.New("send message error") ErrFetchImg = errors.New("fetch image error") + ErrUnSupport = errors.New("unsupported this func") ) -var DefaultBot *RikkaBot - func init() { - ctx, cancel := context.WithCancel(context.Background()) cfg := config.GetConfig() // 启动日志检测模块 go logging.MonitorLogSize(int64(cfg.LogMaxSize) * 1024 * 1024) + +} + +func NewRikkaBot(ctx context.Context, cli *wcf.Client) *RikkaBot { + ctx, cancel := context.WithCancel(ctx) + cfg := config.GetConfig() // 初始化 - DefaultBot = &RikkaBot{ + return &RikkaBot{ ctx: ctx, cancel: cancel, sendMsg: make(chan *message.Message), recvMsg: make(chan *message.Message), Processor: processor.NewProcessor(), Config: cfg, + cli: cli, EventPool: event.NewEventPool(cfg.HttpServer.EventBufferSize), EventFuncs: make([]func(event event.IEvent), 0), } -} - -func GetDefaultBot() *RikkaBot { - return DefaultBot -} -func Bot() *RikkaBot { - return DefaultBot } -func GetBot(botname string) (*RikkaBot, error) { - DefaultBot.Config.Botname = botname - err := DefaultBot.Config.Update() +func (r *RikkaBot) SetBotName(botname string) (*RikkaBot, error) { + r.Config.Botname = botname + err := r.Config.Update() if err != nil { return nil, fmt.Errorf("error update bot config: %w", err) } - return DefaultBot, nil -} - -func (r *RikkaBot) GetloginUrl() string { - return r.loginUrl -} - -func (r *RikkaBot) SetloginUrl(url string) { - r.loginUrl = url -} - -// PushLoginNoticeEvent 推送登录事件 -func (r *RikkaBot) PushLoginNoticeEvent() { - loginUrl := r.GetloginUrl() - if loginUrl == "" { // 没有回调不需要处理 - return - } - // 构造 notice—event - type LoginType struct { - LoginUrl string `json:"login_url"` - } - var loginData LoginType - loginData.LoginUrl = loginUrl - e := event.Event{ - Id: uuid.New().String(), - Time: timeutil.GetTimeUnix(), - Type: "notice", - DetailType: "login_callback", - SubType: "", - } - noticeEvent := event.NoticeEvent[LoginType]{} - initNoticeEvent := noticeEvent.InitNoticeEvent(e, loginData) - err := r.EventPool.AddEvent(*initNoticeEvent) - if err != nil { - logging.WarnWithErr(err, "推送登录回调事件至事件池错误") - } + return r, nil } // PushLogOutNoticeEvent 推送机器人掉线事件 @@ -178,10 +138,6 @@ func (r *RikkaBot) DispatchMsgEvent(rikkaMsg message.Message) { } } -func (r *RikkaBot) SetSelf(self *common.Self) { - r.self = self -} - // Start 启动 rikkabot 进行消息处理 func (r *RikkaBot) Start() { logging.Info("rikka bot start") @@ -209,9 +165,6 @@ func (r *RikkaBot) ExitWithErr(code int, msg string) { // Block 当发生错误,该方法会立即返回,否则会一直阻塞 func (r *RikkaBot) Block() error { - if r.self == nil { - return fmt.Errorf("`Block` must be called after adapter.HandleCovert(): %w", ErrInvalidCall) - } <-r.ctx.Done() logging.Close() // 关闭日志文件 return r.err @@ -248,32 +201,17 @@ func (r *RikkaBot) SendMsg(msgType message.MsgType, isGroup bool, data any, send var err error switch msgType { case message.MsgTypeText: - s, ok := data.(string) + text, ok := data.(string) if !ok { return fmt.Errorf("`SendMsg of text` must be a string: %w", ErrSendMsg) } - if common.IsUuidValid(sendId) { // 支持 uuid为sendId 发送消息 - err = r.self.SendTextByUuid(sendId, s, isGroup) - return err + err = r.cli.SendText(sendId, text) // 发送消息 + if err != nil { + return fmt.Errorf("send text to %s error: %w", sendId, err) } - err = r.self.SendTextById(sendId, s, isGroup) case message.MsgTypeImage: - d, ok := data.([]byte) - if !ok { // 断言失败,传入的是路径,请求即可 - path := data.(string) - d, err = imgutil.ImgFetch(path) - if err != nil { - err = fmt.Errorf("%w 从路径 %s 中获取路径发送错误 %w", ErrFetchImg, path, err) - return err - } - } - var buf bytes.Buffer - buf.Write(d) - if common.IsUuidValid(sendId) { // 支持 uuid为sendId 发送消息 - err = r.self.SendImgByUuid(sendId, &buf, isGroup) - return err - } - err = r.self.SendImgById(sendId, &buf, isGroup) + // todo 暂未实现 + return fmt.Errorf("sendMsg of MsgTypeImage err: %w", ErrUnSupport) default: err = fmt.Errorf("`SendMsg of type` must be either text or image: %w", ErrSendMsg) }