aboutsummaryrefslogtreecommitdiff
path: root/matrix/pushrules/condition.go
diff options
context:
space:
mode:
authorTulir Asokan <tulir@maunium.net>2018-03-21 23:29:58 +0200
committerTulir Asokan <tulir@maunium.net>2018-03-21 23:29:58 +0200
commit9fd67102ad2cca16c092e23ffd928b77ab08d7e0 (patch)
tree2c34025e564806cb8f9faad0c15e25a0e6dec3ed /matrix/pushrules/condition.go
parentb4902d4edb27baf59b21747117d93db4e0e4e96c (diff)
Refactoring and godocs
Diffstat (limited to 'matrix/pushrules/condition.go')
-rw-r--r--matrix/pushrules/condition.go147
1 files changed, 147 insertions, 0 deletions
diff --git a/matrix/pushrules/condition.go b/matrix/pushrules/condition.go
new file mode 100644
index 0000000..ecbf5b2
--- /dev/null
+++ b/matrix/pushrules/condition.go
@@ -0,0 +1,147 @@
+// gomuks - A terminal Matrix client written in Go.
+// Copyright (C) 2018 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package pushrules
+
+import (
+ "regexp"
+ "strconv"
+ "strings"
+
+ "github.com/zyedidia/glob"
+ "maunium.net/go/gomatrix"
+ "maunium.net/go/gomuks/matrix/room"
+)
+
+// 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 *rooms.Room, event *gomatrix.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 *rooms.Room, event *gomatrix.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)
+ 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[subkey].(string)
+ return pattern.MatchString(val)
+ default:
+ return false
+ }
+}
+
+func (cond *PushCondition) matchDisplayName(room *rooms.Room, event *gomatrix.Event) bool {
+ member := room.GetMember(room.SessionUserID)
+ if member == nil {
+ return false
+ }
+ text, _ := event.Content["body"].(string)
+ return strings.Contains(text, member.DisplayName)
+}
+
+func (cond *PushCondition) matchMemberCount(room *rooms.Room, event *gomatrix.Event) bool {
+ groupGroups := MemberCountFilterRegex.FindAllStringSubmatch(cond.MemberCountCondition, -1)
+ if len(groupGroups) != 1 {
+ return false
+ }
+
+ operator := "=="
+ wantedMemberCount := 0
+
+ group := groupGroups[0]
+ if len(group) == 0 {
+ return false
+ } else if len(group) == 1 {
+ wantedMemberCount, _ = strconv.Atoi(group[0])
+ } else {
+ operator = group[0]
+ wantedMemberCount, _ = strconv.Atoi(group[1])
+ }
+
+ memberCount := len(room.GetMembers())
+
+ switch operator {
+ case "==":
+ return wantedMemberCount == memberCount
+ case ">":
+ return wantedMemberCount > memberCount
+ case ">=":
+ return wantedMemberCount >= memberCount
+ case "<":
+ return wantedMemberCount < memberCount
+ case "<=":
+ return wantedMemberCount <= memberCount
+ default:
+ return false
+ }
+}