From 1c6f60f819d1c1d3a5c111a81c7d06747d9036ae Mon Sep 17 00:00:00 2001 From: cdle Date: Thu, 1 Jun 2023 08:44:24 +0800 Subject: [PATCH] first commit --- .gitignore | 1 - adapters/web/main.go | 163 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 adapters/web/main.go diff --git a/.gitignore b/.gitignore index 972e510..3e50a13 100644 --- a/.gitignore +++ b/.gitignore @@ -25,5 +25,4 @@ develop/qinglong toulu develop/boltdb develop/core -web *.db \ No newline at end of file diff --git a/adapters/web/main.go b/adapters/web/main.go new file mode 100644 index 0000000..0fd3285 --- /dev/null +++ b/adapters/web/main.go @@ -0,0 +1,163 @@ +package web + +import ( + "fmt" + "regexp" + "strings" + "sync" + "time" + + "github.com/cdle/sillyplus/core" + "github.com/gin-gonic/gin" +) + +type WebMessage struct { + UserID string `json:"-"` + Type string `json:"t"` + Content string `json:"c"` + Images []string `json:"m"` +} + +var webUsers sync.Map + +func Broadcast2WebUser(content, class string) { + webUsers.Range(func(key, value interface{}) bool { + wu := value.(*WebUser) + if wu.ActivedAt.Add(10 * time.Second).After(time.Now()) { + + wu.GetCarry() <- WebMessage{ + UserID: key.(string), + Content: content, + Type: class, + } + } else { + webUsers.Delete(key) + } + return true + }) +} + +type WebUser struct { + Carry chan WebMessage + sync.RWMutex + ActivedAt time.Time +} + +func (wu *WebUser) GetCarry() chan WebMessage { + wu.RLock() + defer wu.RUnlock() + return wu.Carry +} + +func (wu *WebUser) Active() { + wu.Lock() + defer wu.Unlock() + wu.ActivedAt = time.Now() +} + +func (wu *WebUser) GetActivedAt() time.Time { + wu.RLock() + defer wu.RUnlock() + return wu.ActivedAt +} + +var webAdmins sync.Map + +var adapter *core.Factory + +func init() { + core.RegistFuncs["Broadcast2WebUser"] = Broadcast2WebUser + core.GinApi(core.GET, "/api/web_chat", func(ctx *gin.Context) { + if adapter == nil { + adapter = &core.Factory{} + adapter.Init("web", "default") + adapter.SetIsAdmin(func(s string) bool { + isAdmin, ok := webAdmins.Load(s) + if ok { + return isAdmin.(bool) + } + return false + }) + adapter.SetReplyHandler(func(msg map[string]string) string { + message := WebMessage{ + UserID: msg[core.USER_ID], + Images: []string{}, + Type: "chat", + Content: msg[core.CONETNT], + } + sendWebMessage(&message) + return "" + }) + } + rid := ctx.Query("rid") + ctt := ctx.Query("ctt") + token, _ := ctx.Cookie("token") + _, err := core.CheckAuth(token) + isAdmin := err == nil + v, ok := webAdmins.Load(rid) + if ok { + if v.(bool) != isAdmin { + webAdmins.Store(rid, isAdmin) + } + } else { + webAdmins.Store(rid, isAdmin) + } + if ctt != "" { + adapter.Receive(map[string]interface{}{ + core.USER_ID: rid, + core.CONETNT: ctt, + }) + } + var wu *WebUser + if v, ok := webUsers.Load(rid); ok { + wu = v.(*WebUser) + } else { + wu = &WebUser{ + Carry: make(chan WebMessage, 1000), + } + webUsers.Store(rid, wu) + } + wu.Active() + msgs := []WebMessage{} + for { + select { + case msg := <-wu.GetCarry(): + msgs = append(msgs, msg) + case <-time.After(time.Millisecond * 1): + goto HELL + } + } + HELL: + if len(msgs) == 0 && ctt == "" { + select { + case msg := <-wu.GetCarry(): + msgs = append(msgs, msg) + case <-time.After(time.Second * 4): + break + } + } + ctx.JSON(200, msgs) + }) +} + +var sendWebMessage = func(message *WebMessage) { + message.Content = regexp.MustCompile(`file=[^\[\]]*,url`).ReplaceAllString(message.Content, "file") + for _, v := range regexp.MustCompile(`\[CQ:image,file=([^\[\]]+)\]`).FindAllStringSubmatch(message.Content, -1) { + message.Images = append(message.Images, v[1]) + message.Content = strings.Replace(message.Content, fmt.Sprintf(`[CQ:image,file=%s]`, v[1]), "", -1) + } + v, ok := webUsers.Load(message.UserID) + var wu *WebUser + if !ok { + wu = &WebUser{ + Carry: make(chan WebMessage, 1000), + } + webUsers.Store(message.UserID, wu) + wu.Active() + } else { + wu = v.(*WebUser) + } + go func() { + wu.GetCarry() <- *message + }() +}