diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d9f8369 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +plat ?= darwin +plats = linux darwin windows + +arch ?= amd64 +archs = amd64 arm arm64 + +all: server wechat + +define build_app + @echo 'building $(1) ...' + @GOOS=$(2) GOARCH=$(3) go build -o builder/$(1) ./cmd/$(1) + @echo 'build $(1) done' +endef + + +server: + $(call build_app,server,$(plat),$(arch)) +.PHONY: server + +wechat: + $(call build_app,wechat,$(plat),$(arch)) +.PHONY: wechat + +clean: + @rm -f builder/* \ No newline at end of file diff --git a/builder/server b/builder/server new file mode 100755 index 0000000..69e7391 Binary files /dev/null and b/builder/server differ diff --git a/builder/wechat b/builder/wechat new file mode 100755 index 0000000..4549761 Binary files /dev/null and b/builder/wechat differ diff --git a/cmd/server/main.go b/cmd/server/main.go index b872411..045e9f5 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -16,8 +16,7 @@ import ( "github.com/gin-gonic/gin" "github.com/jageros/hawox/flags" "github.com/jageros/hawox/httpx" - "github.com/jageros/hawox/ws" - "gopkg.in/olahol/melody.v1" + "wechat/ws" ) const appName = "wechat" @@ -29,7 +28,4 @@ func main() { r := engine.Group("ws") ws.Init(ctx, r, flags.Source()) }) - ws.OnMessage(func(session *melody.Session, bytes []byte) { - //ws.Broadcast() - }) } diff --git a/cmd/wechat/main.go b/cmd/wechat/main.go index 6bcea22..6ca333b 100644 --- a/cmd/wechat/main.go +++ b/cmd/wechat/main.go @@ -13,20 +13,65 @@ package main import ( + "encoding/json" + "flag" + "github.com/jageros/hawox/contextx" + "github.com/jageros/hawox/wsc" "log" + "net/http" + "os" + "wechat/types" "wechat/view" ) func main() { - //ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT) - //defer cancel() + uid := flag.String("phone", "", "输入手机号码参数") + flag.Parse() + if *uid == "" { + log.Fatal("请携带手机号码参数启动,--phone=10086") + os.Exit(-1) + } + ctx, cancel := contextx.Default() + defer cancel() + + h := http.Header{} + h.Add("uid", *uid) + + m := wsc.New(ctx) + sess, err := m.ConnectWithHeader("ws://127.0.0.1:8888/ws/wechat/1", h, map[string]interface{}{"uid": uid}) + if err != nil { + panic(err) + } + + view.OnSendMsg(func(msg string) { + err = sess.Write([]byte(msg)) + if err != nil { + log.Println(err) + } + }) + + m.HandleMessageBinary(func(session *wsc.Session, bytes []byte) { + //uid, _ := session.Get("uid") + //roomId, _ := session.Get("roomId") + msg := &types.Msg{} + err := json.Unmarshal(bytes, msg) + if err != nil { + log.Panicf("msg.Unmarshal err: %v", err) + return + } + switch msg.MsgID { + case 1: + view.OnMessage(msg.Msg) - view.OnMessage("dekdmkwenkwndklwenklndk\n") - view.UpdateOnline("杰(13160676597)\n哲(10086)\n文(10010)\n") - view.UpdateOnline("杰(13160676597)\n哲(10086)\n文(10010)\n") + case 2: + view.UpdateOnline(msg.Msg) + default: + log.Printf("MsgId=%d Msg=%s", msg.MsgID, msg.Msg) + } + }) - err := view.Run() + err = view.Run() if err != nil { log.Fatal(err) } diff --git a/go.mod b/go.mod index e9cb287..88fbc11 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,7 @@ go 1.17 require ( github.com/gin-gonic/gin v1.7.4 - github.com/jageros/hawox v0.0.5 - github.com/jroimartin/gocui v0.5.0 + github.com/jageros/hawox v0.0.6 github.com/rocket049/gocui v0.3.2 gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 ) @@ -14,7 +13,6 @@ require ( github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/eapache/queue v1.1.0 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect @@ -40,7 +38,6 @@ require ( github.com/modern-go/reflect2 v1.0.1 // indirect github.com/nsf/termbox-go v1.1.1 // indirect github.com/pelletier/go-toml v1.9.3 // indirect - github.com/satori/go.uuid v1.2.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.6.0 // indirect github.com/spf13/cast v1.3.1 // indirect diff --git a/go.sum b/go.sum index 43a41c9..5aba624 100644 --- a/go.sum +++ b/go.sum @@ -99,7 +99,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr 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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= @@ -283,12 +282,10 @@ github.com/iancoleman/strcase v0.1.2/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5N github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/jageros/hawox v0.0.5 h1:GJlcQ8G8r1T8roPLjm4Nb+cj/1Im2sVFL2Pmwlj072U= -github.com/jageros/hawox v0.0.5/go.mod h1:OFIFzzc5l6v52BgVIRLqmxQJnE+oEE6kOTvIqHOQF0o= +github.com/jageros/hawox v0.0.6 h1:4svDUSDrss47VYJ9rd1LyZBZJHSQtcj+C88wjjYPa8k= +github.com/jageros/hawox v0.0.6/go.mod h1:Z/+N+7E3dKGvtztI4TN2uIhP/cB/7zCecT+uv3ZgCLA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jroimartin/gocui v0.5.0 h1:DCZc97zY9dMnHXJSJLLmx9VqiEnAj0yh0eTNpuEtG/4= -github.com/jroimartin/gocui v0.5.0/go.mod h1:l7Hz8DoYoL6NoYnlnaX6XCNR62G7J5FfSW5jEogzaxE= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -412,8 +409,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= diff --git a/view/view.go b/view/view.go index 70d8114..9460fb2 100644 --- a/view/view.go +++ b/view/view.go @@ -13,17 +13,15 @@ package view import ( - "fmt" "github.com/rocket049/gocui" "log" - "time" - "wechat/ws" ) var ( viewArr = []string{"msg", "send"} active = 1 gg *gocui.Gui + onSend func(msg string) ) func setCurrentViewOnTop(g *gocui.Gui, name string) (*gocui.View, error) { @@ -81,6 +79,10 @@ func quit(g *gocui.Gui, v *gocui.View) error { return gocui.ErrQuit } +func OnSendMsg(fn func(msg string)) { + onSend = fn +} + func OnMessage(msg string) { gg.Update(func(gui *gocui.Gui) error { v, err := gui.View("msg") @@ -111,23 +113,13 @@ func sendMsg(g *gocui.Gui, v *gocui.View) error { return v.SetCursor(0, 0) } str := string(byts) - msg, err := g.View("msg") - if err != nil { - return err - } - n, err := ws.SendMsg(str) - if err != nil { - return err + if onSend != nil { + onSend(str) } - msgStr := fmt.Sprintf("[%d]%s(%s): %s\n", n, "我", time.Now().Format("15:04:05"), str) - _, err = msg.Write([]byte(msgStr)) - if err == nil { - v.Clear() - err = v.SetCursor(0, 0) - } - return err + v.Clear() + return v.SetCursor(0, 0) } func arrowUp(g *gocui.Gui, v *gocui.View) error { @@ -161,6 +153,11 @@ func backspace(g *gocui.Gui, v *gocui.View) error { return nil } +func clear(g *gocui.Gui, v *gocui.View) error { + v.Clear() + return v.SetCursor(0, 0) +} + func init() { g, err := gocui.NewGui(gocui.OutputNormal) if err != nil { @@ -188,6 +185,10 @@ func init() { log.Panic(err) } + if err := g.SetKeybinding("send", gocui.KeyCtrlD, gocui.ModNone, clear); err != nil { + log.Panic(err) + } + if err := g.SetKeybinding("send", gocui.KeyBackspace2, gocui.ModNone, backspace); err != nil { log.Panic(err) } diff --git a/ws/ws.go b/ws/ws.go index e72316d..4981642 100644 --- a/ws/ws.go +++ b/ws/ws.go @@ -42,6 +42,8 @@ type service struct { ctx contextx.Context m *melody.Melody callTimeout time.Duration + online map[string]struct{} + mx sync.Mutex } func Init(ctx contextx.Context, r *gin.RouterGroup, relativePath string) { @@ -49,8 +51,9 @@ func Init(ctx contextx.Context, r *gin.RouterGroup, relativePath string) { ctx: ctx, m: melody.New(), callTimeout: time.Second * 5, + online: map[string]struct{}{}, } - ss.m.HandleMessageBinary(ss.handleMessage) + ss.m.HandleMessage(ss.handleMessage) ss.m.HandleConnect(ss.onConnect) ss.m.HandleDisconnect(ss.onDisconnect) r.GET(relativePath, ss.handler) @@ -59,7 +62,8 @@ func Init(ctx contextx.Context, r *gin.RouterGroup, relativePath string) { func (s *service) handler(c *gin.Context) { uid := c.GetHeader("uid") if _, ok := names[uid]; !ok { - httpx.ErrInterrupt(c, errcode.InvalidParam) + logx.Infof("=====uid=%s", uid) + httpx.ErrInterrupt(c, errcode.InvalidParam.WithMsg(uid)) return } err := s.m.HandleRequestWithKeys(c.Writer, c.Request, map[string]interface{}{"uid": uid}) @@ -69,16 +73,54 @@ func (s *service) handler(c *gin.Context) { } func (s *service) onConnect(session *melody.Session) { - + uid, exist := session.Get("uid") + logx.Infof("on connect uid=%s", uid) + if !exist { + return + } + s.mx.Lock() + defer s.mx.Unlock() + s.online[uid.(string)] = struct{}{} + s.updateOnline() } func (s *service) onDisconnect(session *melody.Session) { + uid, exist := session.Get("uid") + logx.Infof("on disconnect uid=%s", uid) + if !exist { + return + } + s.mx.Lock() + defer s.mx.Unlock() + delete(s.online, uid.(string)) + s.updateOnline() +} +func (s *service) updateOnline() { + var msg string + for id := range s.online { + name := names[id] + msg = fmt.Sprintf("%s%s(%s)\n", msg, name, id) + } + var resp = &types.Msg{ + MsgID: 2, + Msg: msg, + } + bty, err := json.Marshal(resp) + if err != nil { + return + } + err = s.m.BroadcastBinary(bty) + if err != nil { + logx.Error(err) + } + logx.Infof("update %s", msg) } func (s *service) handleMessage(session *melody.Session, bytes []byte) { start := time.Now() uid, exist := session.Get("uid") + logx.Infof("on msg uid=%s", uid) if !exist { return } @@ -99,7 +141,7 @@ func (s *service) handleMessage(session *melody.Session, bytes []byte) { if err != nil { return } - err = s.m.Broadcast(bty) + err = s.m.BroadcastBinary(bty) if err != nil { logx.Error(err) } @@ -107,4 +149,4 @@ func (s *service) handleMessage(session *melody.Session, bytes []byte) { if take > time.Millisecond*100 { logx.Warnf("send msg take: %s", take.String()) } -} \ No newline at end of file +} diff --git a/wsc/wsc.go b/wsc/wsc.go new file mode 100644 index 0000000..3aba0b5 --- /dev/null +++ b/wsc/wsc.go @@ -0,0 +1,14 @@ +/** + * @Author: jager + * @Email: lhj168os@gmail.com + * @File: wsc + * @Date: 2021/10/21 2:47 下午 + * @package: wsc + * @Version: v1.0.0 + * + * @Description: + * + */ + +package wsc +