x
This commit is contained in:
+72
-5
@@ -521,6 +521,12 @@ func (f *Factory) SetIsAdmin(function func(string) bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Factory) Sender() *CustomSender {
|
||||||
|
var demo = *f.demo
|
||||||
|
sender := &demo
|
||||||
|
return sender
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Factory) Receive(wt interface{}) *CustomSender {
|
func (f *Factory) Receive(wt interface{}) *CustomSender {
|
||||||
var demo = *f.demo
|
var demo = *f.demo
|
||||||
sender := &demo
|
sender := &demo
|
||||||
@@ -553,9 +559,9 @@ func (f *Factory) Receive(wt interface{}) *CustomSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sender.SetExpandMessageInfo(emf)
|
sender.SetExpandMessageInfo(emf)
|
||||||
if sender.details.Content != "" {
|
// if sender.details.Content != "" {
|
||||||
Messages <- sender
|
Messages <- sender
|
||||||
}
|
// }
|
||||||
return sender
|
return sender
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,6 +608,50 @@ func (sender *CustomSender) GetBotID() string {
|
|||||||
|
|
||||||
type PUSH string
|
type PUSH string
|
||||||
|
|
||||||
|
func (sender *CustomSender) Action(options map[string]interface{}) (interface{}, string) {
|
||||||
|
var platform = sender.f.botplt
|
||||||
|
var any *common.Function
|
||||||
|
var one *common.Function
|
||||||
|
var result interface{}
|
||||||
|
var err = ""
|
||||||
|
for _, function := range Functions {
|
||||||
|
if function.Reply != nil && function.Reply.Platform == platform {
|
||||||
|
if len(function.Reply.BotsID) == 0 {
|
||||||
|
any = function
|
||||||
|
} else if Contains(function.Reply.BotsID, sender.f.botid) {
|
||||||
|
one = function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if one == nil && any != nil {
|
||||||
|
one = any
|
||||||
|
}
|
||||||
|
if one != nil {
|
||||||
|
one.Handle(&Faker{
|
||||||
|
Type: "action",
|
||||||
|
}, func(vm *goja.Runtime) {
|
||||||
|
obj := vm.NewObject()
|
||||||
|
for k, v := range options {
|
||||||
|
obj.Set(k, v)
|
||||||
|
}
|
||||||
|
proxy := vm.NewProxy(obj, &goja.ProxyTrapConfig{
|
||||||
|
Set: func(target *goja.Object, property string, value, receiver goja.Value) (success bool) {
|
||||||
|
if property == "result" {
|
||||||
|
result = value
|
||||||
|
}
|
||||||
|
if property == "error" {
|
||||||
|
err = value.String()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
vm.Set("action", proxy)
|
||||||
|
vm.Set("adapter", sender.f)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
func (sender *CustomSender) Reply(msgs ...interface{}) (string, error) {
|
func (sender *CustomSender) Reply(msgs ...interface{}) (string, error) {
|
||||||
var push = false
|
var push = false
|
||||||
var platform = sender.f.botplt
|
var platform = sender.f.botplt
|
||||||
@@ -740,6 +790,14 @@ func (sender *CustomSender) Copy() common.Sender {
|
|||||||
return &new
|
return &new
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sender *CustomSender) Event() map[string]interface{} {
|
||||||
|
e := sender.GetVar("event")
|
||||||
|
if e == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return e.(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
func (sender *CustomSender) RecallMessage(ps ...interface{}) {
|
func (sender *CustomSender) RecallMessage(ps ...interface{}) {
|
||||||
recalls := []func(){}
|
recalls := []func(){}
|
||||||
var timeout int
|
var timeout int
|
||||||
@@ -750,14 +808,20 @@ func (sender *CustomSender) RecallMessage(ps ...interface{}) {
|
|||||||
case string:
|
case string:
|
||||||
if p != "" {
|
if p != "" {
|
||||||
recalls = append(recalls, func() {
|
recalls = append(recalls, func() {
|
||||||
sender.Reply(mystr.BuildCQCode("delete", H{"id": p}, ""))
|
sender.Action(H{
|
||||||
|
"type": "delete_message",
|
||||||
|
"message_id": p,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case []string:
|
case []string:
|
||||||
for _, v := range p {
|
for _, v := range p {
|
||||||
if v != "" {
|
if v != "" {
|
||||||
recalls = append(recalls, func() {
|
recalls = append(recalls, func() {
|
||||||
sender.Reply(mystr.BuildCQCode("delete", H{"id": v}, ""))
|
sender.Action(H{
|
||||||
|
"type": "delete_message",
|
||||||
|
"message_id": v,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -765,7 +829,10 @@ func (sender *CustomSender) RecallMessage(ps ...interface{}) {
|
|||||||
for _, v := range p {
|
for _, v := range p {
|
||||||
for _, v2 := range v {
|
for _, v2 := range v {
|
||||||
recalls = append(recalls, func() {
|
recalls = append(recalls, func() {
|
||||||
sender.Reply(mystr.BuildCQCode("delete", H{"id": v2}, ""))
|
sender.Action(H{
|
||||||
|
"type": "delete_message",
|
||||||
|
"message_id": v2,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,6 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script src="/admin/umi.c0e983ad.js"></script>
|
<script src="/admin/umi.1e8ac0f4.js"></script>
|
||||||
|
|
||||||
</body></html>
|
</body></html>
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -365,6 +365,14 @@ func (sender *BaseSender) Stop() {
|
|||||||
panic("stop")
|
panic("stop")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sender *BaseSender) Event() map[string]interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sender *BaseSender) Action(map[string]interface{}) (interface{}, string) {
|
||||||
|
return nil, ""
|
||||||
|
}
|
||||||
|
|
||||||
func (sender *BaseSender) IsAtLast() bool {
|
func (sender *BaseSender) IsAtLast() bool {
|
||||||
return sender.Atlast
|
return sender.Atlast
|
||||||
}
|
}
|
||||||
|
|||||||
+75
-3
@@ -30,11 +30,19 @@ var CarryGroups = MakeBucket("CarryGroups")
|
|||||||
|
|
||||||
var carryCounter int64
|
var carryCounter int64
|
||||||
|
|
||||||
|
type QMessage struct {
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
MessageID string `json:"message_id"`
|
||||||
|
From common.Sender `json:"-"`
|
||||||
|
To *Factory `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
// LOGIC
|
// LOGIC
|
||||||
func initCarry() {
|
func initCarry() {
|
||||||
AddCommand([]*common.Function{
|
AddCommand([]*common.Function{
|
||||||
{
|
{
|
||||||
Rules: []string{`raw [\s\S]+`},
|
Rules: []string{`raw [\s\S]*`},
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
Priority: 9999,
|
Priority: 9999,
|
||||||
Handle: func(s common.Sender, _ func(vm *goja.Runtime)) interface{} {
|
Handle: func(s common.Sender, _ func(vm *goja.Runtime)) interface{} {
|
||||||
@@ -43,9 +51,27 @@ func initCarry() {
|
|||||||
var chat_id = s.GetChatID()
|
var chat_id = s.GetChatID()
|
||||||
var user_id = s.GetUserID()
|
var user_id = s.GetUserID()
|
||||||
var content = s.GetContent()
|
var content = s.GetContent()
|
||||||
|
var message_id = s.GetMessageID()
|
||||||
var from *CarryGroup //判断当前消息来自采集源
|
var from *CarryGroup //判断当前消息来自采集源
|
||||||
var cgs = cgs
|
var cgs = cgs
|
||||||
var uuid = fmt.Sprintf("%d. ", atomic.AddInt64(&carryCounter, 1))
|
var uuid = fmt.Sprintf("%d. ", atomic.AddInt64(&carryCounter, 1))
|
||||||
|
var ss = &Strings{}
|
||||||
|
var event = s.Event()
|
||||||
|
if event != nil {
|
||||||
|
if event["type"] == "delete_message" {
|
||||||
|
queues.Range(func(key, value any) bool {
|
||||||
|
q := value.(*Queue)
|
||||||
|
for _, qm := range q.GetValues() {
|
||||||
|
if qm.From != nil && qm.From.GetMessageID() == event["message_id"] {
|
||||||
|
qm.To.Sender().RecallMessage(qm.MessageID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
s.Continue()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
for i := range cgs {
|
for i := range cgs {
|
||||||
if chat_id == cgs[i].ID && cgs[i].In && cgs[i].Enable {
|
if chat_id == cgs[i].ID && cgs[i].In && cgs[i].Enable {
|
||||||
from = &cgs[i]
|
from = &cgs[i]
|
||||||
@@ -56,6 +82,22 @@ func initCarry() {
|
|||||||
s.Continue()
|
s.Continue()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
//采集消息去重逻辑
|
||||||
|
q := NewQueue(chat_id, 50)
|
||||||
|
if from.Deduplication {
|
||||||
|
for _, qm := range q.GetValues() {
|
||||||
|
v := ss.HansSimilarity(qm.Content, content)
|
||||||
|
if v > 0.9 {
|
||||||
|
console.Debug("%s 忽略重复采集信息", uuid)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = q.Enqueue(&QMessage{
|
||||||
|
UserID: user_id,
|
||||||
|
Content: content,
|
||||||
|
MessageID: message_id,
|
||||||
|
})
|
||||||
bots_id := GetAdapterBotsID(platform)
|
bots_id := GetAdapterBotsID(platform)
|
||||||
if len(from.BotsID) == 0 && len(bots_id) != 0 {
|
if len(from.BotsID) == 0 && len(bots_id) != 0 {
|
||||||
from.BotsID = bots_id
|
from.BotsID = bots_id
|
||||||
@@ -187,10 +229,31 @@ func initCarry() {
|
|||||||
console.Debug("%s 指定(%s)机器人都不在线,转发群(%s)已选择其他机器人(%s)推送", uuid, platform, chat_id, adapter.botid)
|
console.Debug("%s 指定(%s)机器人都不在线,转发群(%s)已选择其他机器人(%s)推送", uuid, platform, chat_id, adapter.botid)
|
||||||
}
|
}
|
||||||
if adapter != nil {
|
if adapter != nil {
|
||||||
adapter.Push(map[string]string{
|
//采集消息去重逻辑
|
||||||
|
q := NewQueue(chat_id, 50)
|
||||||
|
if outs[i].Deduplication {
|
||||||
|
for _, qm := range q.GetValues() {
|
||||||
|
v := ss.HansSimilarity(qm.Content, content)
|
||||||
|
if v > 0.9 {
|
||||||
|
console.Debug("%s 忽略重复转发信息", uuid)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qm := &QMessage{
|
||||||
|
UserID: user_id,
|
||||||
|
Content: content,
|
||||||
|
From: s,
|
||||||
|
To: adapter,
|
||||||
|
}
|
||||||
|
_ = q.Enqueue(qm)
|
||||||
|
message_id, err := adapter.Push(map[string]string{
|
||||||
CONETNT: content,
|
CONETNT: content,
|
||||||
CHAT_ID: chat_id,
|
CHAT_ID: chat_id,
|
||||||
})
|
})
|
||||||
|
if err == nil {
|
||||||
|
qm.MessageID = message_id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,11 +378,12 @@ type CarryGroup struct {
|
|||||||
CreatedAt int `json:"created_at"` //创建时间戳(秒)转换成日期
|
CreatedAt int `json:"created_at"` //创建时间戳(秒)转换成日期
|
||||||
BotsID []string `json:"bots_id"` //工作机器人 多选
|
BotsID []string `json:"bots_id"` //工作机器人 多选
|
||||||
Scripts []string `json:"scripts"` //处理脚本
|
Scripts []string `json:"scripts"` //处理脚本
|
||||||
|
Deduplication bool `json:"deduplication"` //文本去重
|
||||||
|
Deduplication2 bool `json:"deduplication2"` //图片去重
|
||||||
}
|
}
|
||||||
|
|
||||||
// CARRY API
|
// CARRY API
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
GinApi(GET, "/api/carry/groups", RequireAuth, func(ctx *gin.Context) {
|
GinApi(GET, "/api/carry/groups", RequireAuth, func(ctx *gin.Context) {
|
||||||
current := utils.Int(ctx.Query("current"))
|
current := utils.Int(ctx.Query("current"))
|
||||||
pageSize := utils.Int(ctx.Query("pageSize"))
|
pageSize := utils.Int(ctx.Query("pageSize"))
|
||||||
@@ -504,6 +568,14 @@ func init() {
|
|||||||
if out, ok := value.(bool); ok {
|
if out, ok := value.(bool); ok {
|
||||||
cg.Out = out
|
cg.Out = out
|
||||||
}
|
}
|
||||||
|
case "deduplication":
|
||||||
|
if deduplication, ok := value.(bool); ok {
|
||||||
|
cg.Deduplication = deduplication
|
||||||
|
}
|
||||||
|
case "deduplication2":
|
||||||
|
if deduplication, ok := value.(bool); ok {
|
||||||
|
cg.Deduplication2 = deduplication
|
||||||
|
}
|
||||||
case "from":
|
case "from":
|
||||||
if from, ok := value.([]interface{}); ok {
|
if from, ok := value.([]interface{}); ok {
|
||||||
cg.From = toStringSlice(from)
|
cg.From = toStringSlice(from)
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ type Sender interface {
|
|||||||
GetVar(string) interface{}
|
GetVar(string) interface{}
|
||||||
SetLevel(int)
|
SetLevel(int)
|
||||||
GetLevel() int
|
GetLevel() int
|
||||||
|
Event() map[string]interface{}
|
||||||
|
Action(map[string]interface{}) (interface{}, string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type FakerSenderParams struct {
|
type FakerSenderParams struct {
|
||||||
|
|||||||
+19
-1
@@ -61,11 +61,29 @@ func similarity(str1, str2 string) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sender *Strings) Similarity(str1, str2 string) float64 {
|
func (sender *Strings) Similarity(str1, str2 string) float64 {
|
||||||
|
if str1 == "" || str2 == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
max := math.Max(
|
max := math.Max(
|
||||||
float64(similarity(str1, str2))/float64(len(str2)),
|
float64(similarity(str1, str2))/float64(len(str2)),
|
||||||
float64(similarity(str2, str1))/float64(len(str1)),
|
float64(similarity(str2, str1))/float64(len(str1)),
|
||||||
)
|
)
|
||||||
return max
|
b := float64(len(str2)) / float64(len(str1))
|
||||||
|
if b > 1 {
|
||||||
|
b = 1 / b
|
||||||
|
}
|
||||||
|
return max * ((b + 1) / 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sender *Strings) HansSimilarity(str1, str2 string) float64 {
|
||||||
|
if str1 == str2 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return sender.Similarity(str1, str2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sender *Strings) ExtractHans(text string) []string {
|
||||||
|
return regexp.MustCompile(`[\p{Han}]+`).FindAllString(text, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sender *Strings) Intersect(a, b interface{}) interface{} {
|
func (sender *Strings) Intersect(a, b interface{}) interface{} {
|
||||||
|
|||||||
@@ -539,6 +539,7 @@ func initPlugin(data string, uuid string) (*common.Function, []func(), error) {
|
|||||||
vm.Set("message", goja.Undefined())
|
vm.Set("message", goja.Undefined())
|
||||||
vm.Set("res", goja.Undefined())
|
vm.Set("res", goja.Undefined())
|
||||||
vm.Set("req", goja.Undefined())
|
vm.Set("req", goja.Undefined())
|
||||||
|
vm.Set("action", goja.Undefined())
|
||||||
vm.Set("sender", ss)
|
vm.Set("sender", ss)
|
||||||
vm.Set("run", func(uuid string) bool { //执行子脚本
|
vm.Set("run", func(uuid string) bool { //执行子脚本
|
||||||
fs := Functions
|
fs := Functions
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var queues sync.Map
|
||||||
|
|
||||||
|
type Queue struct {
|
||||||
|
data []*QMessage
|
||||||
|
head int
|
||||||
|
tail int
|
||||||
|
size int
|
||||||
|
lock *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueue(name string, size int) *Queue {
|
||||||
|
q := &Queue{
|
||||||
|
head: 0,
|
||||||
|
tail: 0,
|
||||||
|
size: size,
|
||||||
|
}
|
||||||
|
v, ok := queues.LoadOrStore(name, q)
|
||||||
|
if ok {
|
||||||
|
q = v.(*Queue)
|
||||||
|
} else {
|
||||||
|
q.data = make([]*QMessage, size)
|
||||||
|
q.lock = new(sync.Mutex)
|
||||||
|
}
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queue) Enqueue(value *QMessage) error {
|
||||||
|
q.lock.Lock()
|
||||||
|
defer q.lock.Unlock()
|
||||||
|
if q.IsFull() {
|
||||||
|
return errors.New("queue is full")
|
||||||
|
}
|
||||||
|
q.data[q.tail] = value
|
||||||
|
q.tail = (q.tail + 1) % q.size
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queue) Dequeue() (*QMessage, error) {
|
||||||
|
q.lock.Lock()
|
||||||
|
defer q.lock.Unlock()
|
||||||
|
|
||||||
|
if q.IsEmpty() {
|
||||||
|
return nil, errors.New("queue is empty")
|
||||||
|
}
|
||||||
|
value := q.data[q.head]
|
||||||
|
q.head = (q.head + 1) % q.size
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queue) IsEmpty() bool {
|
||||||
|
return q.head == q.tail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queue) IsFull() bool {
|
||||||
|
return (q.tail+1)%q.size == q.head
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queue) Size() int {
|
||||||
|
return (q.tail - q.head + q.size) % q.size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queue) GetValues() []*QMessage {
|
||||||
|
q.lock.Lock()
|
||||||
|
defer q.lock.Unlock()
|
||||||
|
|
||||||
|
values := make([]*QMessage, q.Size())
|
||||||
|
for i := 0; i < q.Size(); i++ {
|
||||||
|
values[i] = q.data[(q.head+i)%q.size]
|
||||||
|
}
|
||||||
|
|
||||||
|
return values
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user