x
This commit is contained in:
+73
-6
@@ -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,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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{} {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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