gomuks/pkg/hicli/pushrules.go

130 lines
3.3 KiB
Go

// Copyright (c) 2024 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package hicli
import (
"context"
"encoding/json"
"github.com/rs/zerolog"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
"maunium.net/go/mautrix/pushrules"
"go.mau.fi/gomuks/pkg/hicli/database"
)
type pushRoom struct {
ctx context.Context
roomID id.RoomID
h *HiClient
ll *mautrix.LazyLoadSummary
pl *event.PowerLevelsEventContent
}
func (p *pushRoom) GetOwnDisplayname() string {
// TODO implement
return ""
}
func (p *pushRoom) GetMemberCount() int {
if p.ll == nil {
room, err := p.h.DB.Room.Get(p.ctx, p.roomID)
if err != nil {
zerolog.Ctx(p.ctx).Err(err).
Stringer("room_id", p.roomID).
Msg("Failed to get room by ID in push rule evaluator")
} else if room != nil {
p.ll = room.LazyLoadSummary
}
}
if p.ll != nil && p.ll.JoinedMemberCount != nil {
return *p.ll.JoinedMemberCount
}
// TODO query db?
return 0
}
func (p *pushRoom) GetEvent(id id.EventID) *event.Event {
evt, err := p.h.DB.Event.GetByID(p.ctx, id)
if err != nil {
zerolog.Ctx(p.ctx).Err(err).
Stringer("event_id", id).
Msg("Failed to get event by ID in push rule evaluator")
}
return evt.AsRawMautrix()
}
func (p *pushRoom) GetPowerLevels() *event.PowerLevelsEventContent {
if p.pl != nil {
return p.pl
}
evt, err := p.h.DB.CurrentState.Get(p.ctx, p.roomID, event.StatePowerLevels, "")
if err != nil {
zerolog.Ctx(p.ctx).Err(err).
Stringer("room_id", p.roomID).
Msg("Failed to get power levels in push rule evaluator")
return nil
} else if evt == nil {
zerolog.Ctx(p.ctx).Warn().
Stringer("room_id", p.roomID).
Msg("Power level event not found in push rule evaluator")
return nil
}
err = json.Unmarshal(evt.Content, &p.pl)
if err != nil {
zerolog.Ctx(p.ctx).Err(err).
Stringer("room_id", p.roomID).
Msg("Failed to unmarshal power levels in push rule evaluator")
return nil
}
return p.pl
}
var (
_ pushrules.EventfulRoom = (*pushRoom)(nil)
_ pushrules.PowerLevelfulRoom = (*pushRoom)(nil)
)
func (h *HiClient) evaluatePushRules(ctx context.Context, llSummary *mautrix.LazyLoadSummary, baseType database.UnreadType, evt *event.Event) database.UnreadType {
if !h.firstSyncReceived && baseType == database.UnreadTypeNone {
// Skip evaluating push rules that are unlikely to match for the initial sync
return baseType
}
should := h.PushRules.Load().GetMatchingRule(&pushRoom{
ctx: ctx,
roomID: evt.RoomID,
h: h,
ll: llSummary,
}, evt).GetActions().Should()
if should.Notify {
baseType |= database.UnreadTypeNotify
}
if should.Highlight {
baseType |= database.UnreadTypeHighlight
}
if should.PlaySound {
baseType |= database.UnreadTypeSound
}
return baseType
}
func (h *HiClient) LoadPushRules(ctx context.Context) {
rules, err := h.Client.GetPushRules(ctx)
if err != nil {
zerolog.Ctx(ctx).Err(err).Msg("Failed to load push rules")
return
}
h.receiveNewPushRules(ctx, rules)
zerolog.Ctx(ctx).Debug().Msg("Updated push rules from fetch")
}
func (h *HiClient) receiveNewPushRules(ctx context.Context, rules *pushrules.PushRuleset) {
h.PushRules.Store(rules)
// TODO set mute flag in rooms
}