Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

消息模板匹配器 #91

Merged
merged 54 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
27353f5
add new Matcher `PatternMatcher`
RikaCelery Oct 7, 2024
e175810
replace with const value
RikaCelery Oct 9, 2024
816234b
remove unused function
RikaCelery Oct 9, 2024
392941b
remove `OnPattern`
RikaCelery Oct 10, 2024
22c4ec8
remove unused const
RikaCelery Oct 10, 2024
ba285e3
add `PatternModel`
RikaCelery Oct 10, 2024
0635fc1
type safe PatternRule state
RikaCelery Oct 10, 2024
ece50eb
add `PatternReply`
RikaCelery Oct 10, 2024
66f9382
remove redundant `at` element after `reply` element
RikaCelery Oct 10, 2024
32b5226
fix wrong key && catch error
RikaCelery Oct 10, 2024
24877ed
Optional PatternSegment
RikaCelery Oct 10, 2024
e810fbf
use pointer
RikaCelery Oct 10, 2024
e4950df
fix nil
RikaCelery Oct 10, 2024
7101db5
move patterns to pattern.go
RikaCelery Oct 11, 2024
88963dc
set State in `patternMatch`
RikaCelery Oct 12, 2024
ab9dbeb
match tests
RikaCelery Oct 12, 2024
3752551
fix optional not work if len(msg) < len(pattern)
RikaCelery Oct 12, 2024
63b4e1f
match tests
RikaCelery Oct 12, 2024
cc54177
Merge remote-tracking branch 'origin/feat/pattern-matcher' into feat/…
RikaCelery Oct 12, 2024
9ecfc51
return empty value if not Valid
RikaCelery Oct 12, 2024
d501a63
fix test failed
RikaCelery Oct 12, 2024
07a5fcb
ignore empty message
RikaCelery Oct 12, 2024
039a7ed
change `At` parsed value to string
RikaCelery Oct 12, 2024
2e7bdfb
Merge remote-tracking branch 'upstream/main' into feat/pattern-matcher
RikaCelery Oct 12, 2024
9403051
Merge remote-tracking branch 'upstream/main' into feat/pattern-matcher
RikaCelery Oct 12, 2024
7526ee8
chore: make lint happy
RikaCelery Oct 12, 2024
6050559
optimize
RikaCelery Oct 12, 2024
0f30441
chore: make lint happy
RikaCelery Oct 12, 2024
b3366ef
move PatternRule to pattern.go
RikaCelery Oct 13, 2024
8dadba4
move KeyPattern to pattern.go
RikaCelery Oct 13, 2024
4524132
chained PatternRule builder
RikaCelery Oct 13, 2024
09e5c79
rename value getter
RikaCelery Oct 13, 2024
2c5cfea
optimize
RikaCelery Oct 13, 2024
2c51768
rename `containsOptional` to `mustMatchAllPatterns`
RikaCelery Oct 13, 2024
c1bd251
make `PatternParse` fields private
RikaCelery Oct 13, 2024
5fd8dd4
Merge remote-tracking branch 'origin/feat/pattern-matcher' into feat/…
RikaCelery Oct 13, 2024
8b77550
optimize
RikaCelery Oct 13, 2024
0f48fe7
optimize
RikaCelery Oct 13, 2024
4b95413
PatternSegment: make `Type` and `Parse` private
RikaCelery Oct 13, 2024
4e89e07
Merge remote-tracking branch 'origin/feat/pattern-matcher' into feat/…
RikaCelery Oct 13, 2024
78ce239
fixup! rename `containsOptional` to `mustMatchAllPatterns`
RikaCelery Oct 13, 2024
455afde
make lint happy
RikaCelery Oct 13, 2024
f606a75
At Pattern use `message.ID` parameters
RikaCelery Oct 13, 2024
6dfbd27
PatternSegment: make `optional` private
RikaCelery Oct 13, 2024
370fda4
`Raw` gatter
RikaCelery Oct 13, 2024
18dbda7
`PatternSegment` builder
RikaCelery Oct 13, 2024
2a96084
`Any` PatternSegment
RikaCelery Oct 13, 2024
6ac4209
tests for `Any`
RikaCelery Oct 13, 2024
7bbb37b
option for cleaning useless sibling `at` after `reply`
RikaCelery Oct 13, 2024
6b486c1
fix wrong clean logic
RikaCelery Oct 13, 2024
2077580
refactor: extract parser, custom parser support
RikaCelery Oct 14, 2024
dbe0b4d
refactor: make `cleanRedundantAt` an option of `Pattern`
RikaCelery Oct 14, 2024
df7234b
fix: fix stupid bugs
RikaCelery Oct 14, 2024
43ae5cd
use for range loop
RikaCelery Oct 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ func OnMessage(rules ...Rule) *Matcher { return On("message", rules...) }
// OnMessage 消息触发器
func (e *Engine) OnMessage(rules ...Rule) *Matcher { return e.On("message", rules...) }

// OnPattern 消息模板触发器
func OnPattern(rules ...PatternSegment) *Matcher { return On("message", PatternRule(rules...)) }
fumiama marked this conversation as resolved.
Show resolved Hide resolved

// OnPattern 消息模板触发器
func (e *Engine) OnPattern(rules ...PatternSegment) *Matcher {
return e.On("message", PatternRule(rules...))
}

// OnNotice 系统提示触发器
func OnNotice(rules ...Rule) *Matcher { return On("notice", rules...) }

Expand Down
78 changes: 78 additions & 0 deletions rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import (
"github.com/wdvxdr1123/ZeroBot/utils/helper"
)

const (
RikaCelery marked this conversation as resolved.
Show resolved Hide resolved
KEY_REGEX = "regex_matched"
KEY_PATTERN = "pattern_matched"
)

// Type check the ctx.Event's type
func Type(type_ string) Rule {
t := strings.SplitN(type_, "/", 3)
Expand Down Expand Up @@ -122,6 +127,79 @@ func RegexRule(regexPattern string) Rule {
}
}

type PatternSegment struct {
fumiama marked this conversation as resolved.
Show resolved Hide resolved
Type string
Matcher func(ctx *Ctx, msg message.MessageSegment) bool
}
type Pattern []PatternSegment

// PatternText KEY_PATTERN type []string
func PatternText(regex string) PatternSegment {
re := regexp.MustCompile(regex)
return PatternSegment{
Type: "text",
Matcher: func(ctx *Ctx, msg message.MessageSegment) bool {
s := msg.Data["text"]
s = strings.Trim(s, " \n\r\t")
matchString := re.MatchString(s)
if matchString {
if _, ok := ctx.State[KEY_PATTERN]; !ok {
ctx.State[KEY_PATTERN] = make([]interface{}, 0)
}

ctx.State[KEY_PATTERN] = append(ctx.State[KEY_PATTERN].([]interface{}), re.FindStringSubmatch(s))
}
return matchString
},
}
}

// PatternAt KEY_PATTERN type string
func PatternAt() PatternSegment {
return PatternSegment{
Type: "at",
Matcher: func(ctx *Ctx, msg message.MessageSegment) bool {
if _, ok := ctx.State[KEY_PATTERN]; !ok {
ctx.State[KEY_PATTERN] = make([]interface{}, 0)
}
ctx.State[KEY_PATTERN] = append(ctx.State[KEY_PATTERN].([]interface{}), msg.Data["qq"])
return true
},
}
}

// PatternImage KEY_PATTERN type msg.Data
func PatternImage() PatternSegment {
return PatternSegment{
Type: "image",
Matcher: func(ctx *Ctx, msg message.MessageSegment) bool {
if _, ok := ctx.State[KEY_PATTERN]; !ok {
ctx.State[KEY_PATTERN] = make([]interface{}, 0)
}
ctx.State[KEY_PATTERN] = append(ctx.State[KEY_PATTERN].([]interface{}), msg.Data)
return true
},
}
}
func patternMatch(ctx *Ctx, pattern []PatternSegment, msgs []message.MessageSegment) bool {
if len(pattern) != len(msgs) {
return false
}
for i := 0; i < len(pattern); i++ {
if pattern[i].Type != (msgs[i].Type) || !pattern[i].Matcher(ctx, msgs[i]) {
return false
}
}
return true
}

// PatternRule check if the message can be matched by the pattern
func PatternRule(pattern ...PatternSegment) Rule {
return func(ctx *Ctx) bool {
return patternMatch(ctx, pattern, ctx.Event.Message)
}
}

// ReplyRule check if the message is replying some message
func ReplyRule(messageID int64) Rule {
return func(ctx *Ctx) bool {
Expand Down