1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-09-05 11:06:23 -07:00

Add "handle if any" functionality to matching filters

This commit is contained in:
Eggbertx 2024-09-05 18:49:20 -07:00
parent 26dcb34edf
commit b1df0bf80a
8 changed files with 120 additions and 12 deletions

View file

@ -498,19 +498,28 @@ func (f *Filter) handleMatch(post *Post, upload *Upload, request *http.Request)
func (f *Filter) checkIfMatch(post *Post, upload *Upload, request *http.Request, errEv *zerolog.Event) (bool, error) {
conditions, err := f.Conditions()
if err != nil {
errEv.Err(err).Caller().
Int("filterID", f.ID).
Msg("unable to get filter conditions")
return false, err
}
match := true
var match bool
for _, condition := range conditions {
if !match {
break
}
if match, err = condition.testCondition(post, upload, request, errEv); err != nil {
// testCondition handles logging errors
return false, err
}
if f.HandleIfAny && match {
// found a matching condition, filter is set to consider any matching condition a match
return true, nil
}
if !f.HandleIfAny && !match {
// found a non-matching condition, filter is set to consider any non-matching condition a non-match
return false, nil
}
}
return match, nil
return !f.HandleIfAny, nil
}
func (fc FilterCondition) testCondition(post *Post, upload *Upload, request *http.Request, errEv *zerolog.Event) (bool, error) {

87
pkg/gcsql/filters_test.go Normal file
View file

@ -0,0 +1,87 @@
package gcsql
import (
"net/http"
"testing"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
)
var (
testingPost = &Post{
MessageRaw: "this search should match",
}
checkIfMatchTestCases = []filterTestCases{
{
name: "basic message AND check",
filter: &Filter{
StaffNote: "basic message AND check",
MatchAction: "log",
conditions: []FilterCondition{
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "search"},
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "match"},
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "should"},
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "this"},
},
},
args: checkIfMatchArgs{
request: &http.Request{},
},
wantMatch: true,
},
{
name: "basic message OR check",
filter: &Filter{
StaffNote: "basic message OR check",
MatchAction: "log",
HandleIfAny: true,
conditions: []FilterCondition{
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "aaa"},
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "bbb"},
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "search"},
{FilterID: 1, Field: "body", MatchMode: SubstrMatch, Search: "ssss"},
},
},
args: checkIfMatchArgs{
request: &http.Request{},
},
wantMatch: true,
},
}
)
type checkIfMatchArgs struct {
post *Post
upload *Upload
request *http.Request
}
type filterTestCases struct {
name string
filter *Filter
args checkIfMatchArgs
wantMatch bool
wantErr bool
}
func TestFilterCheckIfMatch(t *testing.T) {
testLog := zerolog.New(zerolog.NewTestWriter(t))
for _, tc := range checkIfMatchTestCases {
t.Run(tc.name, func(t *testing.T) {
errEv := testLog.WithLevel(zerolog.ErrorLevel)
defer errEv.Discard()
tc.args.post = testingPost
gotMatch, err := tc.filter.checkIfMatch(tc.args.post, tc.args.upload, tc.args.request, errEv)
if tc.wantErr {
assert.Error(t, err)
} else {
if !assert.NoError(t, err) {
errEv.Send()
}
}
assert.Equal(t, tc.wantMatch, gotMatch)
})
}
}

View file

@ -57,12 +57,13 @@ type Board struct {
// and will allow moderators to block posts based on the user's name, email, subject, message content, and other fields.
// table: DBPREFIXfilters
type Filter struct {
ID int `json:"id"` // sql: id
StaffID *int `json:"staff_id"` // sql: staff_id
StaffNote string `json:"staff_note"` // sql: staff_note
IssuedAt time.Time `json:"issued_at"` // sql: issued_at
ID int // sql: id
StaffID *int // sql: staff_id
StaffNote string // sql: staff_note
IssuedAt time.Time // sql: issued_at
MatchAction string // sql: match_action
MatchDetail string // sql: match_detail
HandleIfAny bool // sql: handle_if_any
IsActive bool // sql: is_active
conditions []FilterCondition
}

View file

@ -251,6 +251,7 @@ CREATE TABLE DBPREFIXfilters(
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
match_action VARCHAR(45) NOT NULL DEFAULT 'replace',
match_detail TEXT NOT NULL,
handle_if_any BOOL NOT NULL DEFAULT FALSE,
is_active BOOL NOT NULL,
CONSTRAINT filters_staff_id_fk
FOREIGN KEY(staff_id) REFERENCES DBPREFIXstaff(id)

View file

@ -251,6 +251,7 @@ CREATE TABLE DBPREFIXfilters(
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
match_action VARCHAR(45) NOT NULL DEFAULT 'replace',
match_detail TEXT NOT NULL,
handle_if_any BOOL NOT NULL DEFAULT FALSE,
is_active BOOL NOT NULL,
CONSTRAINT filters_staff_id_fk
FOREIGN KEY(staff_id) REFERENCES DBPREFIXstaff(id)
@ -278,7 +279,7 @@ CREATE TABLE DBPREFIXfilter_conditions(
CONSTRAINT filter_conditions_filter_id_fk
FOREIGN KEY(filter_id) REFERENCES DBPREFIXfilters(id)
ON DELETE CASCADE,
CONSTRAINT filter_conditions_search_check CHECK (search <> '')
CONSTRAINT filter_conditions_search_check CHECK (search <> '' OR match_mode = 3)
);
CREATE TABLE DBPREFIXfilter_hits(

View file

@ -251,6 +251,7 @@ CREATE TABLE DBPREFIXfilters(
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
match_action VARCHAR(45) NOT NULL DEFAULT 'replace',
match_detail TEXT NOT NULL,
handle_if_any BOOL NOT NULL DEFAULT FALSE,
is_active BOOL NOT NULL,
CONSTRAINT filters_staff_id_fk
FOREIGN KEY(staff_id) REFERENCES DBPREFIXstaff(id)
@ -278,7 +279,7 @@ CREATE TABLE DBPREFIXfilter_conditions(
CONSTRAINT filter_conditions_filter_id_fk
FOREIGN KEY(filter_id) REFERENCES DBPREFIXfilters(id)
ON DELETE CASCADE,
CONSTRAINT filter_conditions_search_check CHECK (search <> '')
CONSTRAINT filter_conditions_search_check CHECK (search <> '' OR match_mode = 3)
);
CREATE TABLE DBPREFIXfilter_hits(

View file

@ -251,6 +251,7 @@ CREATE TABLE DBPREFIXfilters(
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
match_action VARCHAR(45) NOT NULL DEFAULT 'replace',
match_detail TEXT NOT NULL,
handle_if_any BOOL NOT NULL DEFAULT FALSE,
is_active BOOL NOT NULL,
CONSTRAINT filters_staff_id_fk
FOREIGN KEY(staff_id) REFERENCES DBPREFIXstaff(id)
@ -278,7 +279,7 @@ CREATE TABLE DBPREFIXfilter_conditions(
CONSTRAINT filter_conditions_filter_id_fk
FOREIGN KEY(filter_id) REFERENCES DBPREFIXfilters(id)
ON DELETE CASCADE,
CONSTRAINT filter_conditions_search_check CHECK (search <> '')
CONSTRAINT filter_conditions_search_check CHECK (search <> '' OR match_mode = 3)
);
CREATE TABLE DBPREFIXfilter_hits(

View file

@ -69,6 +69,13 @@
</select>
</td>
</tr>
<tr>
<th></th>
<td>
<label for="handle_on_any" title="If checked, the filter action will activate if any of the above conditions match an incoming post. Otherwise, all conditions must match">
<input type="checkbox" name="handleonany" id="handle_on_any"> Activate if any condition matches</label><br />
</td>
</tr>
<tr>
<th id="detail">Reason</th>
<td><textarea name="detail" rows="5" cols="35">{{$.filter.MatchDetail}}</textarea></td>