mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-08 04:55:55 +08:00
与原版event filter基本一致
This commit is contained in:
parent
2949f68532
commit
5868b68437
169
global/filter.go
169
global/filter.go
@ -1,16 +1,16 @@
|
|||||||
package global
|
package global
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"github.com/buger/jsonparser"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Filter interface {
|
type Filter interface {
|
||||||
Eval(payload []byte) bool
|
Eval(payload gjson.Result) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type OperationNode struct {
|
type OperationNode struct {
|
||||||
@ -22,14 +22,17 @@ type NotOperator struct {
|
|||||||
operand_ Filter
|
operand_ Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
func notOperatorConstruct(argument []byte) *NotOperator {
|
func notOperatorConstruct(argument gjson.Result) *NotOperator {
|
||||||
|
if !argument.IsObject() {
|
||||||
|
log.Error("the argument of 'not' operator must be an object")
|
||||||
|
}
|
||||||
op := new(NotOperator)
|
op := new(NotOperator)
|
||||||
op.operand_ = GetOperatorFactory().Generate("and", argument)
|
op.operand_ = GetOperatorFactory().Generate("and", argument)
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (notOperator NotOperator) Eval(payload []byte) bool {
|
func (notOperator NotOperator) Eval(payload gjson.Result) bool {
|
||||||
log.Debug("not "+string(payload))
|
log.Debug("not " + payload.Str)
|
||||||
return !(notOperator.operand_).Eval(payload)
|
return !(notOperator.operand_).Eval(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,47 +40,49 @@ type AndOperator struct {
|
|||||||
operands []OperationNode
|
operands []OperationNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func andOperatorConstruct(argument []byte) *AndOperator {
|
func andOperatorConstruct(argument gjson.Result) *AndOperator {
|
||||||
|
if !argument.IsObject() {
|
||||||
|
log.Error("the argument of 'and' operator must be an object")
|
||||||
|
}
|
||||||
op := new(AndOperator)
|
op := new(AndOperator)
|
||||||
_ = jsonparser.ObjectEach(argument, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error {
|
argument.ForEach(func(key, value gjson.Result) bool {
|
||||||
if key[0] == '.' {
|
if key.Str[0] == '.' {
|
||||||
// is an operator
|
// is an operator
|
||||||
// ".foo": {
|
// ".foo": {
|
||||||
// "bar": "baz"
|
// "bar": "baz"
|
||||||
// }
|
// }
|
||||||
opKey := string(key[1:])
|
opKey := key.Str[1:]
|
||||||
op.operands = append(op.operands, OperationNode{"", GetOperatorFactory().Generate(opKey, value)})
|
op.operands = append(op.operands, OperationNode{"", GetOperatorFactory().Generate(opKey, value)})
|
||||||
} else if value[0] == '{' {
|
} else if value.IsObject() {
|
||||||
// is an normal key with an object as the value
|
// is an normal key with an object as the value
|
||||||
// "foo": {
|
// "foo": {
|
||||||
// ".bar": "baz"
|
// ".bar": "baz"
|
||||||
// }
|
// }
|
||||||
opKey := string(key)
|
opKey := key.Str
|
||||||
op.operands = append(op.operands, OperationNode{opKey, GetOperatorFactory().Generate("and", value)})
|
op.operands = append(op.operands, OperationNode{opKey, GetOperatorFactory().Generate("and", value)})
|
||||||
} else {
|
} else {
|
||||||
// is an normal key with a non-object as the value
|
// is an normal key with a non-object as the value
|
||||||
// "foo": "bar"
|
// "foo": "bar"
|
||||||
opKey := string(key)
|
opKey := key.Str
|
||||||
op.operands = append(op.operands, OperationNode{opKey, GetOperatorFactory().Generate("eq", value)})
|
op.operands = append(op.operands, OperationNode{opKey, GetOperatorFactory().Generate("eq", value)})
|
||||||
}
|
}
|
||||||
return nil
|
return true
|
||||||
})
|
})
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (andOperator *AndOperator) Eval(payload []byte) bool {
|
func (andOperator *AndOperator) Eval(payload gjson.Result) bool {
|
||||||
log.Debug("and "+string(payload))
|
log.Debug("and " + payload.Str)
|
||||||
res := true
|
res := true
|
||||||
nodesLength := len(andOperator.operands)
|
for _, operand := range andOperator.operands {
|
||||||
for i := 0; i < nodesLength ; i++ {
|
|
||||||
|
|
||||||
if len(andOperator.operands[i].key) == 0 {
|
if len(operand.key) == 0 {
|
||||||
// is an operator
|
// is an operator
|
||||||
res = res && andOperator.operands[i].filter.Eval(payload)
|
res = res && operand.filter.Eval(payload)
|
||||||
} else {
|
} else {
|
||||||
// is an normal key
|
// is an normal key
|
||||||
val, _, _, _ := jsonparser.Get(payload, andOperator.operands[i].key)
|
val := payload.Get(operand.key)
|
||||||
res = res && andOperator.operands[i].filter.Eval(val)
|
res = res && operand.filter.Eval(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
if res == false {
|
if res == false {
|
||||||
@ -91,20 +96,23 @@ type OrOperator struct {
|
|||||||
operands []Filter
|
operands []Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
func orOperatorConstruct(argument []byte) *OrOperator {
|
func orOperatorConstruct(argument gjson.Result) *OrOperator {
|
||||||
|
if !argument.IsArray() {
|
||||||
|
log.Error("the argument of 'or' operator must be an array")
|
||||||
|
}
|
||||||
op := new(OrOperator)
|
op := new(OrOperator)
|
||||||
_, _ = jsonparser.ArrayEach(argument, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
|
argument.ForEach(func(_, value gjson.Result) bool {
|
||||||
op.operands = append(op.operands, GetOperatorFactory().Generate("and", value))
|
op.operands = append(op.operands, GetOperatorFactory().Generate("and", value))
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (orOperator OrOperator) Eval(payload []byte) bool {
|
func (orOperator OrOperator) Eval(payload gjson.Result) bool {
|
||||||
log.Debug("or "+string(payload))
|
log.Debug("or "+ payload.Str)
|
||||||
res:= false
|
res:= false
|
||||||
nodesLength := len(orOperator.operands)
|
for _, operand := range orOperator.operands {
|
||||||
for i := 0; i < nodesLength ; i++ {
|
res = res || operand.Eval(payload)
|
||||||
res = res || orOperator.operands[i].Eval(payload)
|
|
||||||
|
|
||||||
if res == true {
|
if res == true {
|
||||||
break
|
break
|
||||||
@ -114,88 +122,99 @@ func (orOperator OrOperator) Eval(payload []byte) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type EqualOperator struct {
|
type EqualOperator struct {
|
||||||
value []byte
|
value gjson.Result
|
||||||
}
|
}
|
||||||
|
|
||||||
func equalOperatorConstruct(argument []byte) *EqualOperator {
|
func equalOperatorConstruct(argument gjson.Result) *EqualOperator {
|
||||||
op := new(EqualOperator)
|
op := new(EqualOperator)
|
||||||
op.value = argument
|
op.value = argument
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (equalOperator EqualOperator) Eval(payload []byte) bool {
|
func (equalOperator EqualOperator) Eval(payload gjson.Result) bool {
|
||||||
log.Debug("eq "+string(payload))
|
log.Debug("eq "+ payload.Str + "==" + equalOperator.value.Str)
|
||||||
return bytes.Equal(payload, equalOperator.value)
|
return payload.Str == equalOperator.value.Str
|
||||||
}
|
}
|
||||||
|
|
||||||
type NotEqualOperator struct {
|
type NotEqualOperator struct {
|
||||||
value []byte
|
value gjson.Result
|
||||||
}
|
}
|
||||||
|
|
||||||
func notEqualOperatorConstruct(argument []byte) *NotEqualOperator {
|
func notEqualOperatorConstruct(argument gjson.Result) *NotEqualOperator {
|
||||||
op := new(NotEqualOperator)
|
op := new(NotEqualOperator)
|
||||||
op.value = argument
|
op.value = argument
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (notEqualOperator NotEqualOperator) Eval(payload []byte) bool {
|
func (notEqualOperator NotEqualOperator) Eval(payload gjson.Result) bool {
|
||||||
log.Debug("neq "+string(payload))
|
log.Debug("neq " + payload.Str)
|
||||||
return !bytes.Equal(payload, notEqualOperator.value)
|
return !(payload.Str == notEqualOperator.value.Str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type InOperator struct {
|
type InOperator struct {
|
||||||
operands [][]byte
|
operand gjson.Result
|
||||||
}
|
}
|
||||||
|
|
||||||
func inOperatorConstruct(argument []byte) *InOperator {
|
func inOperatorConstruct(argument gjson.Result) *InOperator {
|
||||||
op := new(InOperator)
|
if argument.IsObject() {
|
||||||
_, _ = jsonparser.ArrayEach(argument, func(value []byte, dataType jsonparser.ValueType, offset int, err error) {
|
log.Error("the argument of 'in' operator must be an array or a string")
|
||||||
op.operands = append(op.operands, value)
|
|
||||||
})
|
|
||||||
return op
|
|
||||||
}
|
|
||||||
|
|
||||||
func (inOperator InOperator) Eval(payload []byte) bool {
|
|
||||||
log.Debug("in "+string(payload))
|
|
||||||
res := false
|
|
||||||
for _, v := range inOperator.operands {
|
|
||||||
res = res || bytes.Equal(payload, v)
|
|
||||||
if res == true {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res
|
op := new(InOperator)
|
||||||
}
|
|
||||||
|
|
||||||
type ContainsOperator struct {
|
|
||||||
operand []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsOperatorConstruct(argument []byte) *ContainsOperator {
|
|
||||||
op := new(ContainsOperator)
|
|
||||||
op.operand = argument
|
op.operand = argument
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (containsOperator ContainsOperator) Eval(payload []byte) bool {
|
func (inOperator InOperator) Eval(payload gjson.Result) bool {
|
||||||
log.Debug("contains "+string(payload))
|
log.Debug("in " + payload.Str)
|
||||||
return bytes.Contains(payload, containsOperator.operand)
|
if inOperator.operand.IsArray() {
|
||||||
|
res := false
|
||||||
|
inOperator.operand.ForEach(func(key, value gjson.Result) bool {
|
||||||
|
res = res || value.Str == payload.Str
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return strings.Contains(inOperator.operand.Str, payload.Str)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContainsOperator struct {
|
||||||
|
operand string
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsOperatorConstruct(argument gjson.Result) *ContainsOperator {
|
||||||
|
if argument.IsArray() || argument.IsObject() {
|
||||||
|
log.Error("the argument of 'contains' operator must be a string")
|
||||||
|
}
|
||||||
|
op := new(ContainsOperator)
|
||||||
|
op.operand = argument.Str
|
||||||
|
return op
|
||||||
|
}
|
||||||
|
|
||||||
|
func (containsOperator ContainsOperator) Eval(payload gjson.Result) bool {
|
||||||
|
log.Debug("contains "+ payload.Str)
|
||||||
|
if payload.IsObject() || payload.IsArray() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return strings.Contains(payload.String(), containsOperator.operand)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegexOperator struct {
|
type RegexOperator struct {
|
||||||
regex string
|
regex string
|
||||||
}
|
}
|
||||||
|
|
||||||
func regexOperatorConstruct(argument []byte) *RegexOperator {
|
func regexOperatorConstruct(argument gjson.Result) *RegexOperator {
|
||||||
|
if argument.IsArray() || argument.IsObject() {
|
||||||
|
log.Error("the argument of 'regex' operator must be a string")
|
||||||
|
}
|
||||||
op := new(RegexOperator)
|
op := new(RegexOperator)
|
||||||
op.regex = string(argument)
|
op.regex = argument.Str
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (containsOperator RegexOperator) Eval(payload []byte) bool {
|
func (containsOperator RegexOperator) Eval(payload gjson.Result) bool {
|
||||||
log.Debug("regex "+string(payload))
|
log.Debug("regex " + payload.Str)
|
||||||
matched, _ := regexp.Match(containsOperator.regex, payload)
|
matched, _ := regexp.MatchString(containsOperator.regex, payload.Str)
|
||||||
return matched
|
return matched
|
||||||
}
|
}
|
||||||
// 单例工厂
|
// 单例工厂
|
||||||
@ -208,7 +227,7 @@ func GetOperatorFactory() *operatorFactory {
|
|||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o operatorFactory) Generate(opName string, argument []byte) Filter {
|
func (o operatorFactory) Generate(opName string, argument gjson.Result) Filter {
|
||||||
switch opName {
|
switch opName {
|
||||||
case "not":
|
case "not":
|
||||||
return notOperatorConstruct(argument)
|
return notOperatorConstruct(argument)
|
||||||
@ -241,7 +260,7 @@ func GetFilter() *Filter {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
filter = nil
|
filter = nil
|
||||||
} else {
|
} else {
|
||||||
*filter = GetOperatorFactory().Generate("and", f)
|
*filter = GetOperatorFactory().Generate("and", gjson.ParseBytes(f))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return filter
|
return filter
|
||||||
|
1
go.mod
1
go.mod
@ -4,7 +4,6 @@ go 1.14
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200821182324-7654a7a2a106
|
github.com/Mrs4s/MiraiGo v0.0.0-20200821182324-7654a7a2a106
|
||||||
github.com/buger/jsonparser v1.0.0
|
|
||||||
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
|
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
|
||||||
github.com/gin-gonic/gin v1.6.3
|
github.com/gin-gonic/gin v1.6.3
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
|
2
go.sum
2
go.sum
@ -6,8 +6,6 @@ github.com/Mrs4s/MiraiGo v0.0.0-20200821164244-fe8e98b9d8c5 h1:LVzj3ahW0LYJQMDcD
|
|||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200821164244-fe8e98b9d8c5/go.mod h1:0je03wji/tSw4bUH4QCF2Z4/EjyNWjSJTyy5tliX6EM=
|
github.com/Mrs4s/MiraiGo v0.0.0-20200821164244-fe8e98b9d8c5/go.mod h1:0je03wji/tSw4bUH4QCF2Z4/EjyNWjSJTyy5tliX6EM=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200821182324-7654a7a2a106 h1:z2oaXbvOmu7/O666OkUeH5SGUjyQ3wUSNjtTOagY8Sk=
|
github.com/Mrs4s/MiraiGo v0.0.0-20200821182324-7654a7a2a106 h1:z2oaXbvOmu7/O666OkUeH5SGUjyQ3wUSNjtTOagY8Sk=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20200821182324-7654a7a2a106/go.mod h1:0je03wji/tSw4bUH4QCF2Z4/EjyNWjSJTyy5tliX6EM=
|
github.com/Mrs4s/MiraiGo v0.0.0-20200821182324-7654a7a2a106/go.mod h1:0je03wji/tSw4bUH4QCF2Z4/EjyNWjSJTyy5tliX6EM=
|
||||||
github.com/buger/jsonparser v1.0.0 h1:etJTGF5ESxjI0Ic2UaLQs2LQQpa8G9ykQScukbh4L8A=
|
|
||||||
github.com/buger/jsonparser v1.0.0/go.mod h1:tgcrVJ81GPSF0mz+0nu1Xaz0fazGPrmmJfJtxjbHhUQ=
|
|
||||||
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
|
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
|
||||||
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
|
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
@ -172,7 +172,8 @@ func (c *websocketClient) listenApi(conn *websocketConn, u bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *websocketClient) onBotPushEvent(m coolq.MSG) {
|
func (c *websocketClient) onBotPushEvent(m coolq.MSG) {
|
||||||
payload := []byte(m.ToJson())
|
log.Infof(m.ToJson())
|
||||||
|
payload := gjson.Parse(m.ToJson())
|
||||||
filter := global.GetFilter()
|
filter := global.GetFilter()
|
||||||
if filter != nil && (*filter).Eval(payload) == false {
|
if filter != nil && (*filter).Eval(payload) == false {
|
||||||
log.Debug("Event filtered!")
|
log.Debug("Event filtered!")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user