Finish push rule parser and use it. Fixes #7

This commit is contained in:
Tulir Asokan 2018-03-21 19:46:49 +02:00
parent 0e90972fe8
commit efbce4c363
2 changed files with 73 additions and 34 deletions

View File

@ -12,9 +12,15 @@ import (
"maunium.net/go/gomuks/matrix/room" "maunium.net/go/gomuks/matrix/room"
) )
// GetPushRules returns the push notification rules for the given scope. // GetPushRules returns the push notification rules for the global scope.
func GetPushRules(client *gomatrix.Client) (resp *PushRuleset, err error) { func GetPushRules(client *gomatrix.Client) (*PushRuleset, error) {
u, _ := url.Parse(client.BuildURL("pushrules", "global")) 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 += "/" u.Path += "/"
_, err = client.MakeRequest("GET", u.String(), nil, &resp) _, err = client.MakeRequest("GET", u.String(), nil, &resp)
return return
@ -62,7 +68,9 @@ func (rs *PushRuleset) MarshalJSON() ([]byte, error) {
return json.Marshal(&data) 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 { if match = rs.Override.GetActions(room, event); match != nil {
return 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 { if match = rs.Underride.GetActions(room, event); match != nil {
return return
} }
return return DefaultPushActions
} }
type PushRuleArray []*PushRule type PushRuleArray []*PushRule
@ -90,7 +98,7 @@ func (rules PushRuleArray) setType(typ PushRuleType) PushRuleArray {
return rules 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 { for _, rule := range rules {
if !rule.Match(room, event) { if !rule.Match(room, event) {
continue continue
@ -117,7 +125,7 @@ func (rules PushRuleArray) setTypeAndMap(typ PushRuleType) PushRuleMap {
return data 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 rule *PushRule
var found bool var found bool
switch ruleMap.Type { switch ruleMap.Type {
@ -160,7 +168,7 @@ type PushRule struct {
// For other types of rules, this doesn't affect anything. // For other types of rules, this doesn't affect anything.
RuleID string `json:"rule_id"` RuleID string `json:"rule_id"`
// The actions this rule should trigger when matched. // 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. // Whether this is a default rule, or has been set explicitly.
Default bool `json:"default"` Default bool `json:"default"`
// Whether or not this push rule is enabled. // Whether or not this push rule is enabled.
@ -224,10 +232,48 @@ const (
TweakHighlight PushActionTweak = "highlight" 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 { type PushAction struct {
Action PushActionType Action PushActionType
Tweak PushActionTweak Tweak PushActionTweak
Value string Value interface{}
} }
func (action *PushAction) UnmarshalJSON(raw []byte) error { func (action *PushAction) UnmarshalJSON(raw []byte) error {
@ -246,7 +292,7 @@ func (action *PushAction) UnmarshalJSON(raw []byte) error {
if ok { if ok {
action.Action = ActionSetTweak action.Action = ActionSetTweak
action.Tweak = PushActionTweak(tweak) action.Tweak = PushActionTweak(tweak)
action.Value, _ = val["value"].(string) action.Value, _ = val["value"]
} }
} }
return nil return nil
@ -291,7 +337,7 @@ func (cond *PushCondition) Match(room *rooms.Room, event *gomatrix.Event) bool {
case KindRoomMemberCount: case KindRoomMemberCount:
return cond.matchMemberCount(room, event) return cond.matchMemberCount(room, event)
default: 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 { func (cond *PushCondition) matchMemberCount(room *rooms.Room, event *gomatrix.Event) bool {
groupGroups := MemberCountFilterRegex.FindAllStringSubmatch(cond.Is, -1) groupGroups := MemberCountFilterRegex.FindAllStringSubmatch(cond.Is, -1)
if len(groupGroups) != 1 { if len(groupGroups) != 1 {
return true return false
} }
operator := "==" operator := "=="
@ -349,7 +395,7 @@ func (cond *PushCondition) matchMemberCount(room *rooms.Room, event *gomatrix.Ev
group := groupGroups[0] group := groupGroups[0]
if len(group) == 0 { if len(group) == 0 {
return true return false
} else if len(group) == 1 { } else if len(group) == 1 {
wantedMemberCount, _ = strconv.Atoi(group[0]) wantedMemberCount, _ = strconv.Atoi(group[0])
} else { } else {

View File

@ -21,6 +21,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/gdamore/tcell"
"maunium.net/go/gomatrix" "maunium.net/go/gomatrix"
"maunium.net/go/gomuks/config" "maunium.net/go/gomuks/config"
"maunium.net/go/gomuks/interface" "maunium.net/go/gomuks/interface"
@ -28,7 +29,6 @@ import (
"maunium.net/go/gomuks/matrix/room" "maunium.net/go/gomuks/matrix/room"
"maunium.net/go/gomuks/notification" "maunium.net/go/gomuks/notification"
"maunium.net/go/gomuks/ui/debug" "maunium.net/go/gomuks/ui/debug"
"maunium.net/go/gomuks/ui/types"
"maunium.net/go/gomuks/ui/widget" "maunium.net/go/gomuks/ui/widget"
) )
@ -196,33 +196,26 @@ func (c *Container) Start() {
} }
} }
func (c *Container) NotifyMessage(room *rooms.Room, message *types.Message) { func (c *Container) NotifyMessage(room *rooms.Room, sender, text string, critical bool) {
sender := fmt.Sprintf("%s (%s)", message.Sender, room.GetTitle()) if room.GetTitle() != sender {
if room.GetTitle() == message.Sender { sender = fmt.Sprintf("%s (%s)", sender, room.GetTitle())
// 1:1 room, title is same as display name of other user.
sender = message.Sender
} }
notification.Send(sender, message.Text, false) notification.Send(sender, text, critical)
} }
func (c *Container) HandleMessage(evt *gomatrix.Event) { func (c *Container) HandleMessage(evt *gomatrix.Event) {
room, message := c.ui.MainView().ProcessMessageEvent(evt) room, message := c.ui.MainView().ProcessMessageEvent(evt)
if room != nil { if room != nil {
match := c.PushRules().GetActions(room.Room, evt) pushRules := c.PushRules().GetActions(room.Room, evt).Should()
if (pushRules.Notify || !pushRules.NotifySpecified) && evt.Sender != c.config.Session.MXID {
var buf strings.Builder c.NotifyMessage(room.Room, message.Sender, message.Text, pushRules.Highlight)
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(' ')
} }
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) room.AddMessage(message, widget.AppendMessage)
c.ui.Render() c.ui.Render()
} }