aboutsummaryrefslogtreecommitdiff
path: root/matrix/pushrules
diff options
context:
space:
mode:
Diffstat (limited to 'matrix/pushrules')
-rw-r--r--matrix/pushrules/action.go134
-rw-r--r--matrix/pushrules/action_test.go210
-rw-r--r--matrix/pushrules/condition.go162
-rw-r--r--matrix/pushrules/condition_displayname_test.go60
-rw-r--r--matrix/pushrules/condition_eventmatch_test.go96
-rw-r--r--matrix/pushrules/condition_membercount_test.go71
-rw-r--r--matrix/pushrules/condition_test.go132
-rw-r--r--matrix/pushrules/doc.go2
-rw-r--r--matrix/pushrules/pushrules.go37
-rw-r--r--matrix/pushrules/pushrules_test.go249
-rw-r--r--matrix/pushrules/rule.go160
-rw-r--r--matrix/pushrules/rule_array_test.go294
-rw-r--r--matrix/pushrules/rule_test.go195
-rw-r--r--matrix/pushrules/ruleset.go98
14 files changed, 0 insertions, 1900 deletions
diff --git a/matrix/pushrules/action.go b/matrix/pushrules/action.go
deleted file mode 100644
index 4637950..0000000
--- a/matrix/pushrules/action.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules
-
-import "encoding/json"
-
-// PushActionType is the type of a PushAction
-type PushActionType string
-
-// The allowed push action types as specified in spec section 11.12.1.4.1.
-const (
- ActionNotify PushActionType = "notify"
- ActionDontNotify PushActionType = "dont_notify"
- ActionCoalesce PushActionType = "coalesce"
- ActionSetTweak PushActionType = "set_tweak"
-)
-
-// PushActionTweak is the type of the tweak in SetTweak push actions.
-type PushActionTweak string
-
-// The allowed tweak types as specified in spec section 11.12.1.4.1.1.
-const (
- TweakSound PushActionTweak = "sound"
- TweakHighlight PushActionTweak = "highlight"
-)
-
-// PushActionArray is an array of PushActions.
-type PushActionArray []*PushAction
-
-// PushActionArrayShould contains the important information parsed from a PushActionArray.
-type PushActionArrayShould struct {
- // Whether or not the array contained a Notify, DontNotify or Coalesce action type.
- NotifySpecified bool
- // Whether or not the event in question should trigger a notification.
- Notify bool
- // Whether or not the event in question should be highlighted.
- Highlight bool
-
- // Whether or not the event in question should trigger a sound alert.
- PlaySound bool
- // The name of the sound to play if PlaySound is true.
- SoundName string
-}
-
-// Should parses this push action array and returns the relevant details wrapped in a PushActionArrayShould struct.
-func (actions PushActionArray) Should() (should PushActionArrayShould) {
- for _, action := range actions {
- switch action.Action {
- case ActionNotify, ActionCoalesce:
- should.Notify = true
- should.NotifySpecified = true
- case ActionDontNotify:
- should.Notify = false
- should.NotifySpecified = true
- case ActionSetTweak:
- switch action.Tweak {
- case TweakHighlight:
- var ok bool
- should.Highlight, ok = action.Value.(bool)
- if !ok {
- // Highlight value not specified, so assume true since the tweak is set.
- should.Highlight = true
- }
- case TweakSound:
- should.SoundName = action.Value.(string)
- should.PlaySound = len(should.SoundName) > 0
- }
- }
- }
- return
-}
-
-// PushAction is a single action that should be triggered when receiving a message.
-type PushAction struct {
- Action PushActionType
- Tweak PushActionTweak
- Value interface{}
-}
-
-// UnmarshalJSON parses JSON into this PushAction.
-//
-// * If the JSON is a single string, the value is stored in the Action field.
-// * If the JSON is an object with the set_tweak field, Action will be set to
-// "set_tweak", Tweak will be set to the value of the set_tweak field and
-// and Value will be set to the value of the value field.
-// * In any other case, the function does nothing.
-func (action *PushAction) UnmarshalJSON(raw []byte) error {
- var data interface{}
-
- err := json.Unmarshal(raw, &data)
- if err != nil {
- return err
- }
-
- switch val := data.(type) {
- case string:
- action.Action = PushActionType(val)
- case map[string]interface{}:
- tweak, ok := val["set_tweak"].(string)
- if ok {
- action.Action = ActionSetTweak
- action.Tweak = PushActionTweak(tweak)
- action.Value, _ = val["value"]
- }
- }
- return nil
-}
-
-// MarshalJSON is the reverse of UnmarshalJSON()
-func (action *PushAction) MarshalJSON() (raw []byte, err error) {
- if action.Action == ActionSetTweak {
- data := map[string]interface{}{
- "set_tweak": action.Tweak,
- "value": action.Value,
- }
- return json.Marshal(&data)
- }
- data := string(action.Action)
- return json.Marshal(&data)
-}
diff --git a/matrix/pushrules/action_test.go b/matrix/pushrules/action_test.go
deleted file mode 100644
index 79b2fdf..0000000
--- a/matrix/pushrules/action_test.go
+++ /dev/null
@@ -1,210 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
- "maunium.net/go/gomuks/matrix/pushrules"
-)
-
-func TestPushActionArray_Should_EmptyArrayReturnsDefaults(t *testing.T) {
- should := pushrules.PushActionArray{}.Should()
- assert.False(t, should.NotifySpecified)
- assert.False(t, should.Notify)
- assert.False(t, should.Highlight)
- assert.False(t, should.PlaySound)
- assert.Empty(t, should.SoundName)
-}
-
-func TestPushActionArray_Should_MixedArrayReturnsExpected1(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "ping"},
- }.Should()
- assert.True(t, should.NotifySpecified)
- assert.True(t, should.Notify)
- assert.True(t, should.Highlight)
- assert.True(t, should.PlaySound)
- assert.Equal(t, "ping", should.SoundName)
-}
-
-func TestPushActionArray_Should_MixedArrayReturnsExpected2(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: ""},
- }.Should()
- assert.True(t, should.NotifySpecified)
- assert.False(t, should.Notify)
- assert.False(t, should.Highlight)
- assert.False(t, should.PlaySound)
- assert.Empty(t, should.SoundName)
-}
-
-func TestPushActionArray_Should_NotifySet(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- }.Should()
- assert.True(t, should.NotifySpecified)
- assert.True(t, should.Notify)
- assert.False(t, should.Highlight)
- assert.False(t, should.PlaySound)
- assert.Empty(t, should.SoundName)
-}
-
-func TestPushActionArray_Should_NotifyAndCoalesceDoTheSameThing(t *testing.T) {
- should1 := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- }.Should()
- should2 := pushrules.PushActionArray{
- {Action: pushrules.ActionCoalesce},
- }.Should()
- assert.Equal(t, should1, should2)
-}
-
-func TestPushActionArray_Should_DontNotify(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- }.Should()
- assert.True(t, should.NotifySpecified)
- assert.False(t, should.Notify)
- assert.False(t, should.Highlight)
- assert.False(t, should.PlaySound)
- assert.Empty(t, should.SoundName)
-}
-
-func TestPushActionArray_Should_HighlightBlank(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight},
- }.Should()
- assert.False(t, should.NotifySpecified)
- assert.False(t, should.Notify)
- assert.True(t, should.Highlight)
- assert.False(t, should.PlaySound)
- assert.Empty(t, should.SoundName)
-}
-
-func TestPushActionArray_Should_HighlightFalse(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- }.Should()
- assert.False(t, should.NotifySpecified)
- assert.False(t, should.Notify)
- assert.False(t, should.Highlight)
- assert.False(t, should.PlaySound)
- assert.Empty(t, should.SoundName)
-}
-
-func TestPushActionArray_Should_SoundName(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "ping"},
- }.Should()
- assert.False(t, should.NotifySpecified)
- assert.False(t, should.Notify)
- assert.False(t, should.Highlight)
- assert.True(t, should.PlaySound)
- assert.Equal(t, "ping", should.SoundName)
-}
-
-func TestPushActionArray_Should_SoundNameEmpty(t *testing.T) {
- should := pushrules.PushActionArray{
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: ""},
- }.Should()
- assert.False(t, should.NotifySpecified)
- assert.False(t, should.Notify)
- assert.False(t, should.Highlight)
- assert.False(t, should.PlaySound)
- assert.Empty(t, should.SoundName)
-}
-
-func TestPushAction_UnmarshalJSON_InvalidJSONFails(t *testing.T) {
- pa := &pushrules.PushAction{}
- err := pa.UnmarshalJSON([]byte("Not JSON"))
- assert.NotNil(t, err)
-}
-
-func TestPushAction_UnmarshalJSON_InvalidTypeDoesNothing(t *testing.T) {
- pa := &pushrules.PushAction{
- Action: pushrules.PushActionType("unchanged"),
- Tweak: pushrules.PushActionTweak("unchanged"),
- Value: "unchanged",
- }
-
- err := pa.UnmarshalJSON([]byte(`{"foo": "bar"}`))
- assert.Nil(t, err)
- err = pa.UnmarshalJSON([]byte(`9001`))
- assert.Nil(t, err)
-
- assert.Equal(t, pushrules.PushActionType("unchanged"), pa.Action)
- assert.Equal(t, pushrules.PushActionTweak("unchanged"), pa.Tweak)
- assert.Equal(t, "unchanged", pa.Value)
-}
-
-func TestPushAction_UnmarshalJSON_StringChangesActionType(t *testing.T) {
- pa := &pushrules.PushAction{
- Action: pushrules.PushActionType("unchanged"),
- Tweak: pushrules.PushActionTweak("unchanged"),
- Value: "unchanged",
- }
-
- err := pa.UnmarshalJSON([]byte(`"foo"`))
- assert.Nil(t, err)
-
- assert.Equal(t, pushrules.PushActionType("foo"), pa.Action)
- assert.Equal(t, pushrules.PushActionTweak("unchanged"), pa.Tweak)
- assert.Equal(t, "unchanged", pa.Value)
-}
-
-func TestPushAction_UnmarshalJSON_SetTweakChangesTweak(t *testing.T) {
- pa := &pushrules.PushAction{
- Action: pushrules.PushActionType("unchanged"),
- Tweak: pushrules.PushActionTweak("unchanged"),
- Value: "unchanged",
- }
-
- err := pa.UnmarshalJSON([]byte(`{"set_tweak": "foo", "value": 123.0}`))
- assert.Nil(t, err)
-
- assert.Equal(t, pushrules.ActionSetTweak, pa.Action)
- assert.Equal(t, pushrules.PushActionTweak("foo"), pa.Tweak)
- assert.Equal(t, 123.0, pa.Value)
-}
-
-func TestPushAction_MarshalJSON_TweakOutputWorks(t *testing.T) {
- pa := &pushrules.PushAction{
- Action: pushrules.ActionSetTweak,
- Tweak: pushrules.PushActionTweak("foo"),
- Value: "bar",
- }
- data, err := pa.MarshalJSON()
- assert.Nil(t, err)
- assert.Equal(t, []byte(`{"set_tweak":"foo","value":"bar"}`), data)
-}
-
-func TestPushAction_MarshalJSON_OtherOutputWorks(t *testing.T) {
- pa := &pushrules.PushAction{
- Action: pushrules.PushActionType("something else"),
- Tweak: pushrules.PushActionTweak("foo"),
- Value: "bar",
- }
- data, err := pa.MarshalJSON()
- assert.Nil(t, err)
- assert.Equal(t, []byte(`"something else"`), data)
-}
diff --git a/matrix/pushrules/condition.go b/matrix/pushrules/condition.go
deleted file mode 100644
index cc62da1..0000000
--- a/matrix/pushrules/condition.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules
-
-import (
- "regexp"
- "strconv"
- "strings"
- "unicode"
-
- "maunium.net/go/gomuks/matrix/rooms"
- "maunium.net/go/mautrix"
-
- "maunium.net/go/gomuks/lib/glob"
-)
-
-// Room is an interface with the functions that are needed for processing room-specific push conditions
-type Room interface {
- GetMember(mxid string) *rooms.Member
- GetMembers() map[string]*rooms.Member
- GetSessionOwner() string
-}
-
-// PushCondKind is the type of a push condition.
-type PushCondKind string
-
-// The allowed push condition kinds as specified in section 11.12.1.4.3 of r0.3.0 of the Client-Server API.
-const (
- KindEventMatch PushCondKind = "event_match"
- KindContainsDisplayName PushCondKind = "contains_display_name"
- KindRoomMemberCount PushCondKind = "room_member_count"
-)
-
-// PushCondition wraps a condition that is required for a specific PushRule to be used.
-type PushCondition struct {
- // The type of the condition.
- Kind PushCondKind `json:"kind"`
- // The dot-separated field of the event to match. Only applicable if kind is EventMatch.
- Key string `json:"key,omitempty"`
- // The glob-style pattern to match the field against. Only applicable if kind is EventMatch.
- Pattern string `json:"pattern,omitempty"`
- // The condition that needs to be fulfilled for RoomMemberCount-type conditions.
- // A decimal integer optionally prefixed by ==, <, >, >= or <=. Prefix "==" is assumed if no prefix found.
- MemberCountCondition string `json:"is,omitempty"`
-}
-
-// MemberCountFilterRegex is the regular expression to parse the MemberCountCondition of PushConditions.
-var MemberCountFilterRegex = regexp.MustCompile("^(==|[<>]=?)?([0-9]+)$")
-
-// Match checks if this condition is fulfilled for the given event in the given room.
-func (cond *PushCondition) Match(room Room, event *mautrix.Event) bool {
- switch cond.Kind {
- case KindEventMatch:
- return cond.matchValue(room, event)
- case KindContainsDisplayName:
- return cond.matchDisplayName(room, event)
- case KindRoomMemberCount:
- return cond.matchMemberCount(room, event)
- default:
- return false
- }
-}
-
-func (cond *PushCondition) matchValue(room Room, event *mautrix.Event) bool {
- index := strings.IndexRune(cond.Key, '.')
- key := cond.Key
- subkey := ""
- if index > 0 {
- subkey = key[index+1:]
- key = key[0:index]
- }
-
- pattern, err := glob.Compile(cond.Pattern)
- if err != nil {
- return false
- }
-
- switch key {
- case "type":
- return pattern.MatchString(event.Type.String())
- case "sender":
- return pattern.MatchString(event.Sender)
- case "room_id":
- return pattern.MatchString(event.RoomID)
- case "state_key":
- if event.StateKey == nil {
- return cond.Pattern == ""
- }
- return pattern.MatchString(*event.StateKey)
- case "content":
- val, _ := event.Content.Raw[subkey].(string)
- return pattern.MatchString(val)
- default:
- return false
- }
-}
-
-func (cond *PushCondition) matchDisplayName(room Room, event *mautrix.Event) bool {
- ownerID := room.GetSessionOwner()
- if ownerID == event.Sender {
- return false
- }
- member := room.GetMember(ownerID)
- if member == nil {
- return false
- }
-
- msg := event.Content.Body
- isAcceptable := func(r uint8) bool {
- return unicode.IsSpace(rune(r)) || unicode.IsPunct(rune(r))
- }
- length := len(member.Displayname)
- for index := strings.Index(msg, member.Displayname); index != -1; index = strings.Index(msg, member.Displayname) {
- if (index <= 0 || isAcceptable(msg[index-1])) && (index + length >= len(msg) || isAcceptable(msg[index+length])) {
- return true
- }
- msg = msg[index+len(member.Displayname):]
- }
- return false
-}
-
-func (cond *PushCondition) matchMemberCount(room Room, event *mautrix.Event) bool {
- group := MemberCountFilterRegex.FindStringSubmatch(cond.MemberCountCondition)
- if len(group) != 3 {
- return false
- }
-
- operator := group[1]
- wantedMemberCount, _ := strconv.Atoi(group[2])
-
- memberCount := len(room.GetMembers())
-
- switch operator {
- case "==", "":
- return memberCount == wantedMemberCount
- case ">":
- return memberCount > wantedMemberCount
- case ">=":
- return memberCount >= wantedMemberCount
- case "<":
- return memberCount < wantedMemberCount
- case "<=":
- return memberCount <= wantedMemberCount
- default:
- // Should be impossible due to regex.
- return false
- }
-}
diff --git a/matrix/pushrules/condition_displayname_test.go b/matrix/pushrules/condition_displayname_test.go
deleted file mode 100644
index fd3f374..0000000
--- a/matrix/pushrules/condition_displayname_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "maunium.net/go/mautrix"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestPushCondition_Match_DisplayName(t *testing.T) {
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgText,
- Body: "tulir: test mention",
- })
- event.Sender = "@someone_else:matrix.org"
- assert.True(t, displaynamePushCondition.Match(displaynameTestRoom, event))
-}
-
-func TestPushCondition_Match_DisplayName_Fail(t *testing.T) {
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgText,
- Body: "not a mention",
- })
- event.Sender = "@someone_else:matrix.org"
- assert.False(t, displaynamePushCondition.Match(displaynameTestRoom, event))
-}
-
-func TestPushCondition_Match_DisplayName_CantHighlightSelf(t *testing.T) {
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgText,
- Body: "tulir: I can't highlight myself",
- })
- assert.False(t, displaynamePushCondition.Match(displaynameTestRoom, event))
-}
-
-func TestPushCondition_Match_DisplayName_FailsOnEmptyRoom(t *testing.T) {
- emptyRoom := newFakeRoom(0)
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgText,
- Body: "tulir: this room doesn't have the owner Member available, so it fails.",
- })
- event.Sender = "@someone_else:matrix.org"
- assert.False(t, displaynamePushCondition.Match(emptyRoom, event))
-}
diff --git a/matrix/pushrules/condition_eventmatch_test.go b/matrix/pushrules/condition_eventmatch_test.go
deleted file mode 100644
index e5761fc..0000000
--- a/matrix/pushrules/condition_eventmatch_test.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "maunium.net/go/mautrix"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestPushCondition_Match_KindEvent_MsgType(t *testing.T) {
- condition := newMatchPushCondition("content.msgtype", "m.emote")
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- Raw: map[string]interface{}{
- "msgtype": "m.emote",
- "body": "tests gomuks pushconditions",
- },
- })
- assert.True(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_MsgType_Fail(t *testing.T) {
- condition := newMatchPushCondition("content.msgtype", "m.emote")
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- Raw: map[string]interface{}{
- "msgtype": "m.text",
- "body": "I'm testing gomuks pushconditions",
- },
- })
- assert.False(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_EventType(t *testing.T) {
- condition := newMatchPushCondition("type", "m.room.foo")
- event := newFakeEvent(mautrix.NewEventType("m.room.foo"), mautrix.Content{})
- assert.True(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_EventType_IllegalGlob(t *testing.T) {
- condition := newMatchPushCondition("type", "m.room.invalid_glo[b")
- event := newFakeEvent(mautrix.NewEventType("m.room.invalid_glob"), mautrix.Content{})
- assert.False(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_Sender_Fail(t *testing.T) {
- condition := newMatchPushCondition("sender", "@foo:maunium.net")
- event := newFakeEvent(mautrix.NewEventType("m.room.foo"), mautrix.Content{})
- assert.False(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_RoomID(t *testing.T) {
- condition := newMatchPushCondition("room_id", "!fakeroom:maunium.net")
- event := newFakeEvent(mautrix.NewEventType(""), mautrix.Content{})
- assert.True(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_BlankStateKey(t *testing.T) {
- condition := newMatchPushCondition("state_key", "")
- event := newFakeEvent(mautrix.NewEventType("m.room.foo"), mautrix.Content{})
- assert.True(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_BlankStateKey_Fail(t *testing.T) {
- condition := newMatchPushCondition("state_key", "not blank")
- event := newFakeEvent(mautrix.NewEventType("m.room.foo"), mautrix.Content{})
- assert.False(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_NonBlankStateKey(t *testing.T) {
- condition := newMatchPushCondition("state_key", "*:maunium.net")
- event := newFakeEvent(mautrix.NewEventType("m.room.foo"), mautrix.Content{})
- event.StateKey = &event.Sender
- assert.True(t, condition.Match(blankTestRoom, event))
-}
-
-func TestPushCondition_Match_KindEvent_UnknownKey(t *testing.T) {
- condition := newMatchPushCondition("non-existent key", "doesn't affect anything")
- event := newFakeEvent(mautrix.NewEventType("m.room.foo"), mautrix.Content{})
- assert.False(t, condition.Match(blankTestRoom, event))
-}
diff --git a/matrix/pushrules/condition_membercount_test.go b/matrix/pushrules/condition_membercount_test.go
deleted file mode 100644
index ad5da9f..0000000
--- a/matrix/pushrules/condition_membercount_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestPushCondition_Match_KindMemberCount_OneToOne_ImplicitPrefix(t *testing.T) {
- condition := newCountPushCondition("2")
- room := newFakeRoom(2)
- assert.True(t, condition.Match(room, countConditionTestEvent))
-}
-
-func TestPushCondition_Match_KindMemberCount_OneToOne_ExplicitPrefix(t *testing.T) {
- condition := newCountPushCondition("==2")
- room := newFakeRoom(2)
- assert.True(t, condition.Match(room, countConditionTestEvent))
-}
-
-func TestPushCondition_Match_KindMemberCount_BigRoom(t *testing.T) {
- condition := newCountPushCondition(">200")
- room := newFakeRoom(201)
- assert.True(t, condition.Match(room, countConditionTestEvent))
-}
-
-func TestPushCondition_Match_KindMemberCount_BigRoom_Fail(t *testing.T) {
- condition := newCountPushCondition(">=200")
- room := newFakeRoom(199)
- assert.False(t, condition.Match(room, countConditionTestEvent))
-}
-
-func TestPushCondition_Match_KindMemberCount_SmallRoom(t *testing.T) {
- condition := newCountPushCondition("<10")
- room := newFakeRoom(9)
- assert.True(t, condition.Match(room, countConditionTestEvent))
-}
-
-func TestPushCondition_Match_KindMemberCount_SmallRoom_Fail(t *testing.T) {
- condition := newCountPushCondition("<=10")
- room := newFakeRoom(11)
- assert.False(t, condition.Match(room, countConditionTestEvent))
-}
-
-func TestPushCondition_Match_KindMemberCount_InvalidPrefix(t *testing.T) {
- condition := newCountPushCondition("??10")
- room := newFakeRoom(11)
- assert.False(t, condition.Match(room, countConditionTestEvent))
-}
-
-func TestPushCondition_Match_KindMemberCount_InvalidCondition(t *testing.T) {
- condition := newCountPushCondition("foobar")
- room := newFakeRoom(1)
- assert.False(t, condition.Match(room, countConditionTestEvent))
-}
diff --git a/matrix/pushrules/condition_test.go b/matrix/pushrules/condition_test.go
deleted file mode 100644
index 163c964..0000000
--- a/matrix/pushrules/condition_test.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "fmt"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "maunium.net/go/mautrix"
- "maunium.net/go/gomuks/matrix/pushrules"
- "maunium.net/go/gomuks/matrix/rooms"
-)
-
-var (
- blankTestRoom *rooms.Room
- displaynameTestRoom pushrules.Room
-
- countConditionTestEvent *mautrix.Event
-
- displaynamePushCondition *pushrules.PushCondition
-)
-
-func init() {
- blankTestRoom = rooms.NewRoom("!fakeroom:maunium.net", "@tulir:maunium.net")
-
- countConditionTestEvent = &mautrix.Event{
- Sender: "@tulir:maunium.net",
- Type: mautrix.EventMessage,
- Timestamp: 1523791120,
- ID: "$123:maunium.net",
- RoomID: "!fakeroom:maunium.net",
- Content: mautrix.Content{
- MsgType: mautrix.MsgText,
- Body: "test",
- },
- }
-
- displaynameTestRoom = newFakeRoom(4)
- displaynamePushCondition = &pushrules.PushCondition{
- Kind: pushrules.KindContainsDisplayName,
- }
-}
-
-func newFakeEvent(evtType mautrix.EventType, content mautrix.Content) *mautrix.Event {
- return &mautrix.Event{
- Sender: "@tulir:maunium.net",
- Type: evtType,
- Timestamp: 1523791120,
- ID: "$123:maunium.net",
- RoomID: "!fakeroom:maunium.net",
- Content: content,
- }
-}
-
-func newCountPushCondition(condition string) *pushrules.PushCondition {
- return &pushrules.PushCondition{
- Kind: pushrules.KindRoomMemberCount,
- MemberCountCondition: condition,
- }
-}
-
-func newMatchPushCondition(key, pattern string) *pushrules.PushCondition {
- return &pushrules.PushCondition{
- Kind: pushrules.KindEventMatch,
- Key: key,
- Pattern: pattern,
- }
-}
-
-func TestPushCondition_Match_InvalidKind(t *testing.T) {
- condition := &pushrules.PushCondition{
- Kind: pushrules.PushCondKind("invalid"),
- }
- event := newFakeEvent(mautrix.EventType{Type: "m.room.foobar"}, mautrix.Content{})
- assert.False(t, condition.Match(blankTestRoom, event))
-}
-
-type FakeRoom struct {
- members map[string]*mautrix.Member
- owner string
-}
-
-func newFakeRoom(memberCount int) *FakeRoom {
- room := &FakeRoom{
- owner: "@tulir:maunium.net",
- members: make(map[string]*mautrix.Member),
- }
-
- if memberCount >= 1 {
- room.members["@tulir:maunium.net"] = &mautrix.Member{
- Membership: mautrix.MembershipJoin,
- Displayname: "tulir",
- }
- }
-
- for i := 0; i < memberCount-1; i++ {
- mxid := fmt.Sprintf("@extrauser_%d:matrix.org", i)
- room.members[mxid] = &mautrix.Member{
- Membership: mautrix.MembershipJoin,
- Displayname: fmt.Sprintf("Extra User %d", i),
- }
- }
-
- return room
-}
-
-func (fr *FakeRoom) GetMember(mxid string) *mautrix.Member {
- return fr.members[mxid]
-}
-
-func (fr *FakeRoom) GetSessionOwner() string {
- return fr.owner
-}
-
-func (fr *FakeRoom) GetMembers() map[string]*mautrix.Member {
- return fr.members
-}
diff --git a/matrix/pushrules/doc.go b/matrix/pushrules/doc.go
deleted file mode 100644
index 19cd774..0000000
--- a/matrix/pushrules/doc.go
+++ /dev/null
@@ -1,2 +0,0 @@
-// Package pushrules contains utilities to parse push notification rules.
-package pushrules
diff --git a/matrix/pushrules/pushrules.go b/matrix/pushrules/pushrules.go
deleted file mode 100644
index 643f2f2..0000000
--- a/matrix/pushrules/pushrules.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package pushrules
-
-import (
- "encoding/json"
- "net/url"
-
- "maunium.net/go/mautrix"
-)
-
-// GetPushRules returns the push notification rules for the global scope.
-func GetPushRules(client *mautrix.Client) (*PushRuleset, error) {
- return GetScopedPushRules(client, "global")
-}
-
-// GetScopedPushRules returns the push notification rules for the given scope.
-func GetScopedPushRules(client *mautrix.Client, scope string) (resp *PushRuleset, err error) {
- u, _ := url.Parse(client.BuildURL("pushrules", scope))
- // client.BuildURL returns the URL without a trailing slash, but the pushrules endpoint requires the slash.
- u.Path += "/"
- _, err = client.MakeRequest("GET", u.String(), nil, &resp)
- return
-}
-
-type contentWithRuleset struct {
- Ruleset *PushRuleset `json:"global"`
-}
-
-// EventToPushRules converts a m.push_rules event to a PushRuleset by passing the data through JSON.
-func EventToPushRules(event *mautrix.Event) (*PushRuleset, error) {
- content := &contentWithRuleset{}
- err := json.Unmarshal(event.Content.VeryRaw, content)
- if err != nil {
- return nil, err
- }
-
- return content.Ruleset, nil
-}
diff --git a/matrix/pushrules/pushrules_test.go b/matrix/pushrules/pushrules_test.go
deleted file mode 100644
index 1883c97..0000000
--- a/matrix/pushrules/pushrules_test.go
+++ /dev/null
@@ -1,249 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "encoding/json"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "maunium.net/go/mautrix"
- "maunium.net/go/gomuks/matrix/pushrules"
-)
-
-func TestEventToPushRules(t *testing.T) {
- event := &mautrix.Event{
- Type: mautrix.AccountDataPushRules,
- Timestamp: 1523380910,
- Content: mautrix.Content{
- VeryRaw: json.RawMessage(JSONExamplePushRules),
- },
- }
- pushRuleset, err := pushrules.EventToPushRules(event)
- assert.Nil(t, err)
- assert.NotNil(t, pushRuleset)
-
- assert.IsType(t, pushRuleset.Override, pushrules.PushRuleArray{})
- assert.IsType(t, pushRuleset.Content, pushrules.PushRuleArray{})
- assert.IsType(t, pushRuleset.Room, pushrules.PushRuleMap{})
- assert.IsType(t, pushRuleset.Sender, pushrules.PushRuleMap{})
- assert.IsType(t, pushRuleset.Underride, pushrules.PushRuleArray{})
- assert.Len(t, pushRuleset.Override, 2)
- assert.Len(t, pushRuleset.Content, 1)
- assert.Empty(t, pushRuleset.Room.Map)
- assert.Empty(t, pushRuleset.Sender.Map)
- assert.Len(t, pushRuleset.Underride, 6)
-
- assert.Len(t, pushRuleset.Content[0].Actions, 3)
- assert.True(t, pushRuleset.Content[0].Default)
- assert.True(t, pushRuleset.Content[0].Enabled)
- assert.Empty(t, pushRuleset.Content[0].Conditions)
- assert.Equal(t, "alice", pushRuleset.Content[0].Pattern)
- assert.Equal(t, ".m.rule.contains_user_name", pushRuleset.Content[0].RuleID)
-
- assert.False(t, pushRuleset.Override[0].Actions.Should().Notify)
- assert.True(t, pushRuleset.Override[0].Actions.Should().NotifySpecified)
-}
-
-const JSONExamplePushRules = `{
- "global": {
- "content": [
- {
- "actions": [
- "notify",
- {
- "set_tweak": "sound",
- "value": "default"
- },
- {
- "set_tweak": "highlight"
- }
- ],
- "default": true,
- "enabled": true,
- "pattern": "alice",
- "rule_id": ".m.rule.contains_user_name"
- }
- ],
- "override": [
- {
- "actions": [
- "dont_notify"
- ],
- "conditions": [],
- "default": true,
- "enabled": false,
- "rule_id": ".m.rule.master"
- },
- {
- "actions": [
- "dont_notify"
- ],
- "conditions": [
- {
- "key": "content.msgtype",
- "kind": "event_match",
- "pattern": "m.notice"
- }
- ],
- "default": true,
- "enabled": true,
- "rule_id": ".m.rule.suppress_notices"
- }
- ],
- "room": [],
- "sender": [],
- "underride": [
- {
- "actions": [
- "notify",
- {
- "set_tweak": "sound",
- "value": "ring"
- },
- {
- "set_tweak": "highlight",
- "value": false
- }
- ],
- "conditions": [
- {
- "key": "type",
- "kind": "event_match",
- "pattern": "m.call.invite"
- }
- ],
- "default": true,
- "enabled": true,
- "rule_id": ".m.rule.call"
- },
- {
- "actions": [
- "notify",
- {
- "set_tweak": "sound",
- "value": "default"
- },
- {
- "set_tweak": "highlight"
- }
- ],
- "conditions": [
- {
- "kind": "contains_display_name"
- }
- ],
- "default": true,
- "enabled": true,
- "rule_id": ".m.rule.contains_display_name"
- },
- {
- "actions": [
- "notify",
- {
- "set_tweak": "sound",
- "value": "default"
- },
- {
- "set_tweak": "highlight",
- "value": false
- }
- ],
- "conditions": [
- {
- "is": "2",
- "kind": "room_member_count"
- }
- ],
- "default": true,
- "enabled": true,
- "rule_id": ".m.rule.room_one_to_one"
- },
- {
- "actions": [
- "notify",
- {
- "set_tweak": "sound",
- "value": "default"
- },
- {
- "set_tweak": "highlight",
- "value": false
- }
- ],
- "conditions": [
- {
- "key": "type",
- "kind": "event_match",
- "pattern": "m.room.member"
- },
- {
- "key": "content.membership",
- "kind": "event_match",
- "pattern": "invite"
- },
- {
- "key": "state_key",
- "kind": "event_match",
- "pattern": "@alice:example.com"
- }
- ],
- "default": true,
- "enabled": true,
- "rule_id": ".m.rule.invite_for_me"
- },
- {
- "actions": [
- "notify",
- {
- "set_tweak": "highlight",
- "value": false
- }
- ],
- "conditions": [
- {
- "key": "type",
- "kind": "event_match",
- "pattern": "m.room.member"
- }
- ],
- "default": true,
- "enabled": true,
- "rule_id": ".m.rule.member_event"
- },
- {
- "actions": [
- "notify",
- {
- "set_tweak": "highlight",
- "value": false
- }
- ],
- "conditions": [
- {
- "key": "type",
- "kind": "event_match",
- "pattern": "m.room.message"
- }
- ],
- "default": true,
- "enabled": true,
- "rule_id": ".m.rule.message"
- }
- ]
- }
-}`
diff --git a/matrix/pushrules/rule.go b/matrix/pushrules/rule.go
deleted file mode 100644
index ef43721..0000000
--- a/matrix/pushrules/rule.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules
-
-import (
- "encoding/gob"
-
- "maunium.net/go/mautrix"
-
- "maunium.net/go/gomuks/lib/glob"
-)
-
-func init() {
- gob.Register(PushRuleArray{})
- gob.Register(PushRuleMap{})
-}
-
-type PushRuleCollection interface {
- GetActions(room Room, event *mautrix.Event) PushActionArray
-}
-
-type PushRuleArray []*PushRule
-
-func (rules PushRuleArray) SetType(typ PushRuleType) PushRuleArray {
- for _, rule := range rules {
- rule.Type = typ
- }
- return rules
-}
-
-func (rules PushRuleArray) GetActions(room Room, event *mautrix.Event) PushActionArray {
- for _, rule := range rules {
- if !rule.Match(room, event) {
- continue
- }
- return rule.Actions
- }
- return nil
-}
-
-type PushRuleMap struct {
- Map map[string]*PushRule
- Type PushRuleType
-}
-
-func (rules PushRuleArray) SetTypeAndMap(typ PushRuleType) PushRuleMap {
- data := PushRuleMap{
- Map: make(map[string]*PushRule),
- Type: typ,
- }
- for _, rule := range rules {
- rule.Type = typ
- data.Map[rule.RuleID] = rule
- }
- return data
-}
-
-func (ruleMap PushRuleMap) GetActions(room Room, event *mautrix.Event) PushActionArray {
- var rule *PushRule
- var found bool
- switch ruleMap.Type {
- case RoomRule:
- rule, found = ruleMap.Map[event.RoomID]
- case SenderRule:
- rule, found = ruleMap.Map[event.Sender]
- }
- if found && rule.Match(room, event) {
- return rule.Actions
- }
- return nil
-}
-
-func (ruleMap PushRuleMap) Unmap() PushRuleArray {
- array := make(PushRuleArray, len(ruleMap.Map))
- index := 0
- for _, rule := range ruleMap.Map {
- array[index] = rule
- index++
- }
- return array
-}
-
-type PushRuleType string
-
-const (
- OverrideRule PushRuleType = "override"
- ContentRule PushRuleType = "content"
- RoomRule PushRuleType = "room"
- SenderRule PushRuleType = "sender"
- UnderrideRule PushRuleType = "underride"
-)
-
-type PushRule struct {
- // The type of this rule.
- Type PushRuleType `json:"-"`
- // The ID of this rule.
- // For room-specific rules and user-specific rules, this is the room or user ID (respectively)
- // For other types of rules, this doesn't affect anything.
- RuleID string `json:"rule_id"`
- // The actions this rule should trigger when matched.
- Actions PushActionArray `json:"actions"`
- // Whether this is a default rule, or has been set explicitly.
- Default bool `json:"default"`
- // Whether or not this push rule is enabled.
- Enabled bool `json:"enabled"`
- // The conditions to match in order to trigger this rule.
- // Only applicable to generic underride/override rules.
- Conditions []*PushCondition `json:"conditions,omitempty"`
- // Pattern for content-specific push rules
- Pattern string `json:"pattern,omitempty"`
-}
-
-func (rule *PushRule) Match(room Room, event *mautrix.Event) bool {
- if !rule.Enabled {
- return false
- }
- switch rule.Type {
- case OverrideRule, UnderrideRule:
- return rule.matchConditions(room, event)
- case ContentRule:
- return rule.matchPattern(room, event)
- case RoomRule:
- return rule.RuleID == event.RoomID
- case SenderRule:
- return rule.RuleID == event.Sender
- default:
- return false
- }
-}
-
-func (rule *PushRule) matchConditions(room Room, event *mautrix.Event) bool {
- for _, cond := range rule.Conditions {
- if !cond.Match(room, event) {
- return false
- }
- }
- return true
-}
-
-func (rule *PushRule) matchPattern(room Room, event *mautrix.Event) bool {
- pattern, err := glob.Compile(rule.Pattern)
- if err != nil {
- return false
- }
- return pattern.MatchString(event.Content.Body)
-}
diff --git a/matrix/pushrules/rule_array_test.go b/matrix/pushrules/rule_array_test.go
deleted file mode 100644
index 8bfc5e9..0000000
--- a/matrix/pushrules/rule_array_test.go
+++ /dev/null
@@ -1,294 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "github.com/stretchr/testify/assert"
- "maunium.net/go/gomuks/matrix/pushrules"
- "maunium.net/go/mautrix"
- "testing"
-)
-
-func TestPushRuleArray_GetActions_FirstMatchReturns(t *testing.T) {
- cond1 := newMatchPushCondition("content.msgtype", "m.emote")
- cond2 := newMatchPushCondition("content.body", "no match")
- actions1 := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "ping"},
- }
- rule1 := &pushrules.PushRule{
- Type: pushrules.OverrideRule,
- Enabled: true,
- Conditions: []*pushrules.PushCondition{cond1, cond2},
- Actions: actions1,
- }
-
- actions2 := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "pong"},
- }
- rule2 := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!fakeroom:maunium.net",
- Actions: actions2,
- }
-
- actions3 := pushrules.PushActionArray{
- {Action: pushrules.ActionCoalesce},
- }
- rule3 := &pushrules.PushRule{
- Type: pushrules.SenderRule,
- Enabled: true,
- RuleID: "@tulir:maunium.net",
- Actions: actions3,
- }
-
- rules := pushrules.PushRuleArray{rule1, rule2, rule3}
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.Equal(t, rules.GetActions(blankTestRoom, event), actions2)
-}
-
-func TestPushRuleArray_GetActions_NoMatchesIsNil(t *testing.T) {
- cond1 := newMatchPushCondition("content.msgtype", "m.emote")
- cond2 := newMatchPushCondition("content.body", "no match")
- actions1 := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "ping"},
- }
- rule1 := &pushrules.PushRule{
- Type: pushrules.OverrideRule,
- Enabled: true,
- Conditions: []*pushrules.PushCondition{cond1, cond2},
- Actions: actions1,
- }
-
- actions2 := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "pong"},
- }
- rule2 := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!realroom:maunium.net",
- Actions: actions2,
- }
-
- actions3 := pushrules.PushActionArray{
- {Action: pushrules.ActionCoalesce},
- }
- rule3 := &pushrules.PushRule{
- Type: pushrules.SenderRule,
- Enabled: true,
- RuleID: "@otheruser:maunium.net",
- Actions: actions3,
- }
-
- rules := pushrules.PushRuleArray{rule1, rule2, rule3}
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.Nil(t, rules.GetActions(blankTestRoom, event))
-}
-
-func TestPushRuleMap_GetActions_RoomRuleExists(t *testing.T) {
- actions1 := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "pong"},
- }
- rule1 := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!realroom:maunium.net",
- Actions: actions1,
- }
-
- actions2 := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- }
- rule2 := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!thirdroom:maunium.net",
- Actions: actions2,
- }
-
- actions3 := pushrules.PushActionArray{
- {Action: pushrules.ActionCoalesce},
- }
- rule3 := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!fakeroom:maunium.net",
- Actions: actions3,
- }
-
- rules := pushrules.PushRuleMap{
- Map: map[string]*pushrules.PushRule{
- rule1.RuleID: rule1,
- rule2.RuleID: rule2,
- rule3.RuleID: rule3,
- },
- Type: pushrules.RoomRule,
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.Equal(t, rules.GetActions(blankTestRoom, event), actions3)
-}
-
-func TestPushRuleMap_GetActions_RoomRuleDoesntExist(t *testing.T) {
- actions1 := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "pong"},
- }
- rule1 := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!realroom:maunium.net",
- Actions: actions1,
- }
-
- actions2 := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- }
- rule2 := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!thirdroom:maunium.net",
- Actions: actions2,
- }
-
- rules := pushrules.PushRuleMap{
- Map: map[string]*pushrules.PushRule{
- rule1.RuleID: rule1,
- rule2.RuleID: rule2,
- },
- Type: pushrules.RoomRule,
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.Nil(t, rules.GetActions(blankTestRoom, event))
-}
-
-func TestPushRuleMap_GetActions_SenderRuleExists(t *testing.T) {
- actions1 := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "pong"},
- }
- rule1 := &pushrules.PushRule{
- Type: pushrules.SenderRule,
- Enabled: true,
- RuleID: "@tulir:maunium.net",
- Actions: actions1,
- }
-
- actions2 := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- }
- rule2 := &pushrules.PushRule{
- Type: pushrules.SenderRule,
- Enabled: true,
- RuleID: "@someone:maunium.net",
- Actions: actions2,
- }
-
- actions3 := pushrules.PushActionArray{
- {Action: pushrules.ActionCoalesce},
- }
- rule3 := &pushrules.PushRule{
- Type: pushrules.SenderRule,
- Enabled: true,
- RuleID: "@otheruser:matrix.org",
- Actions: actions3,
- }
-
- rules := pushrules.PushRuleMap{
- Map: map[string]*pushrules.PushRule{
- rule1.RuleID: rule1,
- rule2.RuleID: rule2,
- rule3.RuleID: rule3,
- },
- Type: pushrules.SenderRule,
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.Equal(t, rules.GetActions(blankTestRoom, event), actions1)
-}
-
-func TestPushRuleArray_SetTypeAndMap(t *testing.T) {
- actions1 := pushrules.PushActionArray{
- {Action: pushrules.ActionDontNotify},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakHighlight, Value: false},
- {Action: pushrules.ActionSetTweak, Tweak: pushrules.TweakSound, Value: "pong"},
- }
- rule1 := &pushrules.PushRule{
- Enabled: true,
- RuleID: "@tulir:maunium.net",
- Actions: actions1,
- }
-
- actions2 := pushrules.PushActionArray{
- {Action: pushrules.ActionNotify},
- }
- rule2 := &pushrules.PushRule{
- Enabled: true,
- RuleID: "@someone:maunium.net",
- Actions: actions2,
- }
-
- actions3 := pushrules.PushActionArray{
- {Action: pushrules.ActionCoalesce},
- }
- rule3 := &pushrules.PushRule{
- Enabled: true,
- RuleID: "@otheruser:matrix.org",
- Actions: actions3,
- }
-
- ruleArray := pushrules.PushRuleArray{rule1, rule2, rule3}
- ruleMap := ruleArray.SetTypeAndMap(pushrules.SenderRule)
- assert.Equal(t, pushrules.SenderRule, ruleMap.Type)
- for _, rule := range ruleArray {
- assert.Equal(t, rule, ruleMap.Map[rule.RuleID])
- }
- newRuleArray := ruleMap.Unmap()
- for _, rule := range ruleArray {
- assert.Contains(t, newRuleArray, rule)
- }
-}
diff --git a/matrix/pushrules/rule_test.go b/matrix/pushrules/rule_test.go
deleted file mode 100644
index 56d48fd..0000000
--- a/matrix/pushrules/rule_test.go
+++ /dev/null
@@ -1,195 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules_test
-
-import (
- "github.com/stretchr/testify/assert"
- "maunium.net/go/gomuks/matrix/pushrules"
- "maunium.net/go/mautrix"
- "testing"
-)
-
-func TestPushRule_Match_Conditions(t *testing.T) {
- cond1 := newMatchPushCondition("content.msgtype", "m.emote")
- cond2 := newMatchPushCondition("content.body", "*pushrules")
- rule := &pushrules.PushRule{
- Type: pushrules.OverrideRule,
- Enabled: true,
- Conditions: []*pushrules.PushCondition{cond1, cond2},
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- Raw: map[string]interface{}{
- "msgtype": "m.emote",
- "body": "is testing pushrules",
- },
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.True(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Conditions_Disabled(t *testing.T) {
- cond1 := newMatchPushCondition("content.msgtype", "m.emote")
- cond2 := newMatchPushCondition("content.body", "*pushrules")
- rule := &pushrules.PushRule{
- Type: pushrules.OverrideRule,
- Enabled: false,
- Conditions: []*pushrules.PushCondition{cond1, cond2},
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- Raw: map[string]interface{}{
- "msgtype": "m.emote",
- "body": "is testing pushrules",
- },
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.False(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Conditions_FailIfOneFails(t *testing.T) {
- cond1 := newMatchPushCondition("content.msgtype", "m.emote")
- cond2 := newMatchPushCondition("content.body", "*pushrules")
- rule := &pushrules.PushRule{
- Type: pushrules.OverrideRule,
- Enabled: true,
- Conditions: []*pushrules.PushCondition{cond1, cond2},
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- Raw: map[string]interface{}{
- "msgtype": "m.text",
- "body": "I'm testing pushrules",
- },
- MsgType: mautrix.MsgText,
- Body: "I'm testing pushrules",
- })
- assert.False(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Content(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.ContentRule,
- Enabled: true,
- Pattern: "is testing*",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is testing pushrules",
- })
- assert.True(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Content_Fail(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.ContentRule,
- Enabled: true,
- Pattern: "is testing*",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is not testing pushrules",
- })
- assert.False(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Content_ImplicitGlob(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.ContentRule,
- Enabled: true,
- Pattern: "testing",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "is not testing pushrules",
- })
- assert.True(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Content_IllegalGlob(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.ContentRule,
- Enabled: true,
- Pattern: "this is not a valid glo[b",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{
- MsgType: mautrix.MsgEmote,
- Body: "this is not a valid glob",
- })
- assert.False(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Room(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!fakeroom:maunium.net",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{})
- assert.True(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Room_Fail(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "!otherroom:maunium.net",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{})
- assert.False(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Sender(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.SenderRule,
- Enabled: true,
- RuleID: "@tulir:maunium.net",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{})
- assert.True(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_Sender_Fail(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.RoomRule,
- Enabled: true,
- RuleID: "@someone:matrix.org",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{})
- assert.False(t, rule.Match(blankTestRoom, event))
-}
-
-func TestPushRule_Match_UnknownTypeAlwaysFail(t *testing.T) {
- rule := &pushrules.PushRule{
- Type: pushrules.PushRuleType("foobar"),
- Enabled: true,
- RuleID: "@someone:matrix.org",
- }
-
- event := newFakeEvent(mautrix.EventMessage, mautrix.Content{})
- assert.False(t, rule.Match(blankTestRoom, event))
-}
diff --git a/matrix/pushrules/ruleset.go b/matrix/pushrules/ruleset.go
deleted file mode 100644
index 7ad931a..0000000
--- a/matrix/pushrules/ruleset.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// gomuks - A terminal Matrix client written in Go.
-// Copyright (C) 2019 Tulir Asokan
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-package pushrules
-
-import (
- "encoding/json"
-
- "maunium.net/go/mautrix"
-)
-
-type PushRuleset struct {
- Override PushRuleArray
- Content PushRuleArray
- Room PushRuleMap
- Sender PushRuleMap
- Underride PushRuleArray
-}
-
-type rawPushRuleset struct {
- Override PushRuleArray `json:"override"`
- Content PushRuleArray `json:"content"`
- Room PushRuleArray `json:"room"`
- Sender PushRuleArray `json:"sender"`
- Underride PushRuleArray `json:"underride"`
-}
-
-// UnmarshalJSON parses JSON into this PushRuleset.
-//
-// For override, sender and underride push rule arrays, the type is added
-// to each PushRule and the array is used as-is.
-//
-// For room and sender push rule arrays, the type is added to each PushRule
-// and the array is converted to a map with the rule ID as the key and the
-// PushRule as the value.
-func (rs *PushRuleset) UnmarshalJSON(raw []byte) (err error) {
- data := rawPushRuleset{}
- err = json.Unmarshal(raw, &data)
- if err != nil {
- return
- }
-
- rs.Override = data.Override.SetType(OverrideRule)
- rs.Content = data.Content.SetType(ContentRule)
- rs.Room = data.Room.SetTypeAndMap(RoomRule)
- rs.Sender = data.Sender.SetTypeAndMap(SenderRule)
- rs.Underride = data.Underride.SetType(UnderrideRule)
- return
-}
-
-// MarshalJSON is the reverse of UnmarshalJSON()
-func (rs *PushRuleset) MarshalJSON() ([]byte, error) {
- data := rawPushRuleset{
- Override: rs.Override,
- Content: rs.Content,
- Room: rs.Room.Unmap(),
- Sender: rs.Sender.Unmap(),
- Underride: rs.Underride,
- }
- return json.Marshal(&data)
-}
-
-// DefaultPushActions is the value returned if none of the rule
-// collections in a Ruleset match the event given to GetActions()
-var DefaultPushActions = PushActionArray{&PushAction{Action: ActionDontNotify}}
-
-// GetActions matches the given event against all of the push rule
-// collections in this push ruleset in the order of priority as
-// specified in spec section 11.12.1.4.
-func (rs *PushRuleset) GetActions(room Room, event *mautrix.Event) (match PushActionArray) {
- // Add push rule collections to array in priority order
- arrays := []PushRuleCollection{rs.Override, rs.Content, rs.Room, rs.Sender, rs.Underride}
- // Loop until one of the push rule collections matches the room/event combo.
- for _, pra := range arrays {
- if pra == nil {
- continue
- }
- if match = pra.GetActions(room, event); match != nil {
- // Match found, return it.
- return
- }
- }
- // No match found, return default actions.
- return DefaultPushActions
-}