mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-05 03:23:49 +08:00
114 lines
2.3 KiB
Go
114 lines
2.3 KiB
Go
package server
|
|
|
|
import (
|
|
"container/list"
|
|
"context"
|
|
"os"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/Mrs4s/go-cqhttp/coolq"
|
|
"github.com/Mrs4s/go-cqhttp/global"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/tidwall/gjson"
|
|
"golang.org/x/time/rate"
|
|
)
|
|
|
|
var (
|
|
filters = make(map[string]global.Filter)
|
|
filterMutex sync.RWMutex
|
|
)
|
|
|
|
func rateLimit(frequency float64, bucketSize int) handler {
|
|
limiter := rate.NewLimiter(rate.Limit(frequency), bucketSize)
|
|
return func(_ string, _ resultGetter) global.MSG {
|
|
_ = limiter.Wait(context.Background())
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func addFilter(file string) {
|
|
if file == "" {
|
|
return
|
|
}
|
|
bs, err := os.ReadFile(file)
|
|
if err != nil {
|
|
log.Error("init filter error: ", err)
|
|
return
|
|
}
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
log.Error("init filter error: ", err)
|
|
}
|
|
}()
|
|
filter := global.Generate("and", gjson.ParseBytes(bs))
|
|
filterMutex.Lock()
|
|
filters[file] = filter
|
|
filterMutex.Unlock()
|
|
}
|
|
|
|
func findFilter(file string) global.Filter {
|
|
if file == "" {
|
|
return nil
|
|
}
|
|
filterMutex.RLock()
|
|
defer filterMutex.RUnlock()
|
|
return filters[file]
|
|
}
|
|
|
|
func longPolling(bot *coolq.CQBot, maxSize int) handler {
|
|
var mutex sync.Mutex
|
|
cond := sync.NewCond(&mutex)
|
|
queue := list.New()
|
|
bot.OnEventPush(func(event *coolq.Event) {
|
|
mutex.Lock()
|
|
defer mutex.Unlock()
|
|
queue.PushBack(event.RawMsg)
|
|
for maxSize != 0 && queue.Len() > maxSize {
|
|
queue.Remove(queue.Front())
|
|
}
|
|
cond.Signal()
|
|
})
|
|
return func(action string, p resultGetter) global.MSG {
|
|
if action != "get_updates" {
|
|
return nil
|
|
}
|
|
var (
|
|
ok int32
|
|
ch = make(chan []interface{}, 1)
|
|
timeout = time.Duration(p.Get("timeout").Int()) * time.Second
|
|
)
|
|
defer close(ch)
|
|
go func() {
|
|
mutex.Lock()
|
|
defer mutex.Unlock()
|
|
if queue.Len() == 0 {
|
|
cond.Wait()
|
|
}
|
|
if atomic.CompareAndSwapInt32(&ok, 0, 1) {
|
|
limit := int(p.Get("limit").Int())
|
|
if limit <= 0 || queue.Len() < limit {
|
|
limit = queue.Len()
|
|
}
|
|
ret := make([]interface{}, limit)
|
|
for i := 0; i < limit; i++ {
|
|
ret[i] = queue.Remove(queue.Front())
|
|
}
|
|
ch <- ret
|
|
}
|
|
}()
|
|
if timeout != 0 {
|
|
select {
|
|
case <-time.After(timeout):
|
|
atomic.StoreInt32(&ok, 1)
|
|
return coolq.OK([]interface{}{})
|
|
case ret := <-ch:
|
|
return coolq.OK(ret)
|
|
}
|
|
}
|
|
return coolq.OK(<-ch)
|
|
}
|
|
}
|