164 lines
3.3 KiB
Go
164 lines
3.3 KiB
Go
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
|
|
}()
|
|
}
|