From efbce4c363b743817b4a368d6011c7aac9b8b176 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 21 Mar 2018 19:46:49 +0200 Subject: [PATCH] Finish push rule parser and use it. Fixes #7 --- matrix/ext/pushrules.go | 72 +++++++++++++++++++++++++++++++++-------- matrix/matrix.go | 35 ++++++++------------ 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/matrix/ext/pushrules.go b/matrix/ext/pushrules.go index 6cb16d2..c156873 100644 --- a/matrix/ext/pushrules.go +++ b/matrix/ext/pushrules.go @@ -12,9 +12,15 @@ import ( "maunium.net/go/gomuks/matrix/room" ) -// GetPushRules returns the push notification rules for the given scope. -func GetPushRules(client *gomatrix.Client) (resp *PushRuleset, err error) { - u, _ := url.Parse(client.BuildURL("pushrules", "global")) +// GetPushRules returns the push notification rules for the global scope. +func GetPushRules(client *gomatrix.Client) (*PushRuleset, error) { + return GetScopedPushRules(client, "global") +} + +// GetScopedPushRules returns the push notification rules for the given scope. +func GetScopedPushRules(client *gomatrix.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 @@ -62,7 +68,9 @@ func (rs *PushRuleset) MarshalJSON() ([]byte, error) { return json.Marshal(&data) } -func (rs *PushRuleset) GetActions(room *rooms.Room, event *gomatrix.Event) (match []*PushAction) { +var DefaultPushActions = make(PushActionArray, 0) + +func (rs *PushRuleset) GetActions(room *rooms.Room, event *gomatrix.Event) (match PushActionArray) { if match = rs.Override.GetActions(room, event); match != nil { return } @@ -78,7 +86,7 @@ func (rs *PushRuleset) GetActions(room *rooms.Room, event *gomatrix.Event) (matc if match = rs.Underride.GetActions(room, event); match != nil { return } - return + return DefaultPushActions } type PushRuleArray []*PushRule @@ -90,7 +98,7 @@ func (rules PushRuleArray) setType(typ PushRuleType) PushRuleArray { return rules } -func (rules PushRuleArray) GetActions(room *rooms.Room, event *gomatrix.Event) []*PushAction { +func (rules PushRuleArray) GetActions(room *rooms.Room, event *gomatrix.Event) PushActionArray { for _, rule := range rules { if !rule.Match(room, event) { continue @@ -117,7 +125,7 @@ func (rules PushRuleArray) setTypeAndMap(typ PushRuleType) PushRuleMap { return data } -func (ruleMap PushRuleMap) GetActions(room *rooms.Room, event *gomatrix.Event) []*PushAction { +func (ruleMap PushRuleMap) GetActions(room *rooms.Room, event *gomatrix.Event) PushActionArray { var rule *PushRule var found bool switch ruleMap.Type { @@ -160,7 +168,7 @@ type PushRule struct { // For other types of rules, this doesn't affect anything. RuleID string `json:"rule_id"` // The actions this rule should trigger when matched. - Actions []*PushAction `json:"actions"` + 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. @@ -224,10 +232,48 @@ const ( TweakHighlight PushActionTweak = "highlight" ) +type PushActionArray []*PushAction + +type PushActionArrayShould struct { + NotifySpecified bool + Notify bool + Highlight bool + + PlaySound bool + SoundName string +} + +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 +} + type PushAction struct { Action PushActionType Tweak PushActionTweak - Value string + Value interface{} } func (action *PushAction) UnmarshalJSON(raw []byte) error { @@ -246,7 +292,7 @@ func (action *PushAction) UnmarshalJSON(raw []byte) error { if ok { action.Action = ActionSetTweak action.Tweak = PushActionTweak(tweak) - action.Value, _ = val["value"].(string) + action.Value, _ = val["value"] } } return nil @@ -291,7 +337,7 @@ func (cond *PushCondition) Match(room *rooms.Room, event *gomatrix.Event) bool { case KindRoomMemberCount: return cond.matchMemberCount(room, event) default: - return true + return false } } @@ -341,7 +387,7 @@ func (cond *PushCondition) matchDisplayName(room *rooms.Room, event *gomatrix.Ev func (cond *PushCondition) matchMemberCount(room *rooms.Room, event *gomatrix.Event) bool { groupGroups := MemberCountFilterRegex.FindAllStringSubmatch(cond.Is, -1) if len(groupGroups) != 1 { - return true + return false } operator := "==" @@ -349,7 +395,7 @@ func (cond *PushCondition) matchMemberCount(room *rooms.Room, event *gomatrix.Ev group := groupGroups[0] if len(group) == 0 { - return true + return false } else if len(group) == 1 { wantedMemberCount, _ = strconv.Atoi(group[0]) } else { diff --git a/matrix/matrix.go b/matrix/matrix.go index 7dbbbe1..4ec6d96 100644 --- a/matrix/matrix.go +++ b/matrix/matrix.go @@ -21,6 +21,7 @@ import ( "strings" "time" + "github.com/gdamore/tcell" "maunium.net/go/gomatrix" "maunium.net/go/gomuks/config" "maunium.net/go/gomuks/interface" @@ -28,7 +29,6 @@ import ( "maunium.net/go/gomuks/matrix/room" "maunium.net/go/gomuks/notification" "maunium.net/go/gomuks/ui/debug" - "maunium.net/go/gomuks/ui/types" "maunium.net/go/gomuks/ui/widget" ) @@ -196,33 +196,26 @@ func (c *Container) Start() { } } -func (c *Container) NotifyMessage(room *rooms.Room, message *types.Message) { - sender := fmt.Sprintf("%s (%s)", message.Sender, room.GetTitle()) - if room.GetTitle() == message.Sender { - // 1:1 room, title is same as display name of other user. - sender = message.Sender +func (c *Container) NotifyMessage(room *rooms.Room, sender, text string, critical bool) { + if room.GetTitle() != sender { + sender = fmt.Sprintf("%s (%s)", sender, room.GetTitle()) } - notification.Send(sender, message.Text, false) + notification.Send(sender, text, critical) } func (c *Container) HandleMessage(evt *gomatrix.Event) { room, message := c.ui.MainView().ProcessMessageEvent(evt) if room != nil { - match := c.PushRules().GetActions(room.Room, evt) - - var buf strings.Builder - buf.WriteRune('[') - for i, rule := range match { - fmt.Fprintf(&buf, "{%s, %s, %s}", rule.Action, rule.Tweak, rule.Value) - if i < len(match)-1 { - buf.WriteRune(',') - buf.WriteRune(' ') - } + pushRules := c.PushRules().GetActions(room.Room, evt).Should() + if (pushRules.Notify || !pushRules.NotifySpecified) && evt.Sender != c.config.Session.MXID { + c.NotifyMessage(room.Room, message.Sender, message.Text, pushRules.Highlight) + } + if pushRules.Highlight { + message.TextColor = tcell.ColorYellow + } + if pushRules.PlaySound { + // TODO play sound } - buf.WriteRune(']') - debug.Print(buf.String()) - - c.NotifyMessage(room.Room, message) room.AddMessage(message, widget.AppendMessage) c.ui.Render() }