This commit is contained in:
1-6
2023-07-12 23:10:49 +08:00
parent 78d9ab0f16
commit a7b65ed9fd
11 changed files with 277 additions and 29 deletions
+73 -6
View File
@@ -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 {
var demo = *f.demo
sender := &demo
@@ -553,9 +559,9 @@ func (f *Factory) Receive(wt interface{}) *CustomSender {
}
}
sender.SetExpandMessageInfo(emf)
if sender.details.Content != "" {
Messages <- sender
}
// if sender.details.Content != "" {
Messages <- sender
// }
return sender
}
@@ -602,6 +608,50 @@ func (sender *CustomSender) GetBotID() 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) {
var push = false
var platform = sender.f.botplt
@@ -740,6 +790,14 @@ func (sender *CustomSender) Copy() common.Sender {
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{}) {
recalls := []func(){}
var timeout int
@@ -750,14 +808,20 @@ func (sender *CustomSender) RecallMessage(ps ...interface{}) {
case string:
if p != "" {
recalls = append(recalls, func() {
sender.Reply(mystr.BuildCQCode("delete", H{"id": p}, ""))
sender.Action(H{
"type": "delete_message",
"message_id": p,
})
})
}
case []string:
for _, v := range p {
if v != "" {
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 _, v2 := range v {
recalls = append(recalls, func() {
sender.Reply(mystr.BuildCQCode("delete", H{"id": v2}, ""))
sender.Action(H{
"type": "delete_message",
"message_id": v2,
})
})
}
}
+1 -1
View File
@@ -8,6 +8,6 @@
</head>
<body>
<div id="root"></div>
<script src="/admin/umi.c0e983ad.js"></script>
<script src="/admin/umi.1e8ac0f4.js"></script>
</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
+8
View File
@@ -365,6 +365,14 @@ func (sender *BaseSender) 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 {
return sender.Atlast
}
+91 -19
View File
@@ -30,11 +30,19 @@ var CarryGroups = MakeBucket("CarryGroups")
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
func initCarry() {
AddCommand([]*common.Function{
{
Rules: []string{`raw [\s\S]+`},
Rules: []string{`raw [\s\S]*`},
Hidden: true,
Priority: 9999,
Handle: func(s common.Sender, _ func(vm *goja.Runtime)) interface{} {
@@ -43,9 +51,27 @@ func initCarry() {
var chat_id = s.GetChatID()
var user_id = s.GetUserID()
var content = s.GetContent()
var message_id = s.GetMessageID()
var from *CarryGroup //判断当前消息来自采集源
var cgs = cgs
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 {
if chat_id == cgs[i].ID && cgs[i].In && cgs[i].Enable {
from = &cgs[i]
@@ -56,6 +82,22 @@ func initCarry() {
s.Continue()
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)
if len(from.BotsID) == 0 && len(bots_id) != 0 {
from.BotsID = bots_id
@@ -187,10 +229,31 @@ func initCarry() {
console.Debug("%s 指定(%s)机器人都不在线,转发群(%s)已选择其他机器人(%s)推送", uuid, platform, chat_id, adapter.botid)
}
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,
CHAT_ID: chat_id,
})
if err == nil {
qm.MessageID = message_id
}
}
}
}
@@ -299,27 +362,28 @@ func setCgs() {
}
type CarryGroup struct {
Index int `json:"id"` //编号 顺序编号
In bool `json:"in"` //搬进来 勾选按钮
Out bool `json:"out"` //运出去 勾选按钮
From []string `json:"from"` //采集源
Allowed []string `json:"allowed"` //白名单模式
Prohibited []string `json:"prohibited"` //黑名单模式 Select选择器多选
ID string `json:"chat_id"` //群组ID 文字表单
ChatName string `json:"chat_name"` //群昵称 文字表单
Remark string `json:"remark"` //备注
Platform string `json:"platform"` //平台 Select选择器单选
Enable bool `json:"enable"` //启用状态 开关
Include []string `json:"include"` //包含关键词 多个关键词用逗号隔开 用户复制粘贴过去后自动转换成多彩标签
Exclude []string `json:"exclude"` //排除关键词 包含关键词
CreatedAt int `json:"created_at"` //创建时间戳(秒)转换成日期
BotsID []string `json:"bots_id"` //工作机器人 多选
Scripts []string `json:"scripts"` //处理脚本
Index int `json:"id"` //编号 顺序编号
In bool `json:"in"` //搬进来 勾选按钮
Out bool `json:"out"` //运出去 勾选按钮
From []string `json:"from"` //采集源
Allowed []string `json:"allowed"` //白名单模式
Prohibited []string `json:"prohibited"` //黑名单模式 Select选择器多选
ID string `json:"chat_id"` //群组ID 文字表单
ChatName string `json:"chat_name"` //群昵称 文字表单
Remark string `json:"remark"` //备注
Platform string `json:"platform"` //平台 Select选择器单选
Enable bool `json:"enable"` //启用状态 开关
Include []string `json:"include"` //包含关键词 多个关键词用逗号隔开 用户复制粘贴过去后自动转换成多彩标签
Exclude []string `json:"exclude"` //排除关键词 包含关键词
CreatedAt int `json:"created_at"` //创建时间戳(秒)转换成日期
BotsID []string `json:"bots_id"` //工作机器人 多选
Scripts []string `json:"scripts"` //处理脚本
Deduplication bool `json:"deduplication"` //文本去重
Deduplication2 bool `json:"deduplication2"` //图片去重
}
// CARRY API
func init() {
GinApi(GET, "/api/carry/groups", RequireAuth, func(ctx *gin.Context) {
current := utils.Int(ctx.Query("current"))
pageSize := utils.Int(ctx.Query("pageSize"))
@@ -504,6 +568,14 @@ func init() {
if out, ok := value.(bool); ok {
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":
if from, ok := value.([]interface{}); ok {
cg.From = toStringSlice(from)
+2
View File
@@ -50,6 +50,8 @@ type Sender interface {
GetVar(string) interface{}
SetLevel(int)
GetLevel() int
Event() map[string]interface{}
Action(map[string]interface{}) (interface{}, string)
}
type FakerSenderParams struct {
+19 -1
View File
@@ -61,11 +61,29 @@ func similarity(str1, str2 string) int {
}
func (sender *Strings) Similarity(str1, str2 string) float64 {
if str1 == "" || str2 == "" {
return 0
}
max := math.Max(
float64(similarity(str1, str2))/float64(len(str2)),
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{} {
+1
View File
@@ -539,6 +539,7 @@ func initPlugin(data string, uuid string) (*common.Function, []func(), error) {
vm.Set("message", goja.Undefined())
vm.Set("res", goja.Undefined())
vm.Set("req", goja.Undefined())
vm.Set("action", goja.Undefined())
vm.Set("sender", ss)
vm.Set("run", func(uuid string) bool { //执行子脚本
fs := Functions
+80
View File
@@ -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
}