Files
Sillyv2/adapters/web/main.go
T
cdle d408524fd5 x
2023-06-11 14:09:34 +08:00

174 lines
3.4 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
var GetUserNumber = func() int {
i := 0
webUsers.Range(func(key, value any) bool {
i++
return true
})
return i
}
func init() {
core.RegistFuncs["Broadcast2WebUser"] = Broadcast2WebUser
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 ""
})
core.GinApi(core.GET, "/api/web_chat", func(ctx *gin.Context) {
// if adapter == nil {
// }
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
}()
}