From a12e6185f9cc257239fa938e59da6bca00248e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 21 Oct 2022 17:17:34 +0200 Subject: [PATCH] Update call notification push rule to match MSC3914 (#2781) --- spec/unit/pushprocessor.spec.ts | 34 ++++++++++++++++----- src/@types/PushRules.ts | 14 ++++++++- src/pushprocessor.ts | 54 ++++++++++++++++----------------- 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/spec/unit/pushprocessor.spec.ts b/spec/unit/pushprocessor.spec.ts index 87dec0f112b..a2b61255389 100644 --- a/spec/unit/pushprocessor.spec.ts +++ b/spec/unit/pushprocessor.spec.ts @@ -163,6 +163,22 @@ describe('NotificationService', function() { "enabled": true, "rule_id": ".m.rule.room_one_to_one", }, + { + rule_id: ".org.matrix.msc3914.rule.room.call", + default: true, + enabled: true, + conditions: [ + { + kind: "event_match", + key: "type", + pattern: "org.matrix.msc3401.call", + }, + { + kind: "call_started", + }, + ], + actions: ["notify", { set_tweak: "sound", value: "default" }], + }, ], "room": [], "sender": [], @@ -337,7 +353,11 @@ describe('NotificationService', function() { }, testEvent)).toBe(true); }); - describe("performCustomEventHandling()", () => { + describe("group call started push rule", () => { + beforeEach(() => { + matrixClient.pushRules!.global!.underride!.find(r => r.rule_id === ".m.rule.fallback")!.enabled = false; + }); + const getActionsForEvent = (prevContent: IContent, content: IContent): IActionsObject => { testEvent = utils.mkEvent({ type: "org.matrix.msc3401.call", @@ -353,15 +373,15 @@ describe('NotificationService', function() { }; const assertDoesNotify = (actions: IActionsObject): void => { - expect(actions.notify).toBeTruthy(); - expect(actions.tweaks.sound).toBeTruthy(); - expect(actions.tweaks.highlight).toBeFalsy(); + expect(actions?.notify).toBeTruthy(); + expect(actions?.tweaks?.sound).toBeTruthy(); + expect(actions?.tweaks?.highlight).toBeFalsy(); }; const assertDoesNotNotify = (actions: IActionsObject): void => { - expect(actions.notify).toBeFalsy(); - expect(actions.tweaks.sound).toBeFalsy(); - expect(actions.tweaks.highlight).toBeFalsy(); + expect(actions?.notify).toBeFalsy(); + expect(actions?.tweaks?.sound).toBeFalsy(); + expect(actions?.tweaks?.highlight).toBeFalsy(); }; it.each( diff --git a/src/@types/PushRules.ts b/src/@types/PushRules.ts index 7af6d148150..f3aeca156ba 100644 --- a/src/@types/PushRules.ts +++ b/src/@types/PushRules.ts @@ -65,6 +65,8 @@ export enum ConditionKind { ContainsDisplayName = "contains_display_name", RoomMemberCount = "room_member_count", SenderNotificationPermission = "sender_notification_permission", + CallStarted = "call_started", + CallStartedPrefix = "org.matrix.msc3914.call_started", } export interface IPushRuleCondition { @@ -90,12 +92,22 @@ export interface ISenderNotificationPermissionCondition key: string; } +export interface ICallStartedCondition extends IPushRuleCondition { + // no additional fields +} + +export interface ICallStartedPrefixCondition extends IPushRuleCondition { + // no additional fields +} + // XXX: custom conditions are possible but always fail, and break the typescript discriminated union so ignore them here // IPushRuleCondition> unfortunately does not resolve this at the time of writing. export type PushRuleCondition = IEventMatchCondition | IContainsDisplayNameCondition | IRoomMemberCountCondition - | ISenderNotificationPermissionCondition; + | ISenderNotificationPermissionCondition + | ICallStartedCondition + | ICallStartedPrefixCondition; export enum PushRuleKind { Override = "override", diff --git a/src/pushprocessor.ts b/src/pushprocessor.ts index d89eae4b031..048c24f6b01 100644 --- a/src/pushprocessor.ts +++ b/src/pushprocessor.ts @@ -21,6 +21,8 @@ import { MatrixEvent } from "./models/event"; import { ConditionKind, IAnnotatedPushRule, + ICallStartedCondition, + ICallStartedPrefixCondition, IContainsDisplayNameCondition, IEventMatchCondition, IPushRule, @@ -92,8 +94,8 @@ const DEFAULT_OVERRIDE_RULES: IPushRule[] = [ actions: [], }, { - // For homeservers which don't support MSC3401 yet - rule_id: ".org.matrix.msc3401.rule.room.call", + // For homeservers which don't support MSC3914 yet + rule_id: ".org.matrix.msc3914.rule.room.call", default: true, enabled: true, conditions: [ @@ -102,6 +104,9 @@ const DEFAULT_OVERRIDE_RULES: IPushRule[] = [ key: "type", pattern: "org.matrix.msc3401.call", }, + { + kind: ConditionKind.CallStarted, + }, ], actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: "default" }], }, @@ -269,6 +274,9 @@ export class PushProcessor { return this.eventFulfillsRoomMemberCountCondition(cond, ev); case ConditionKind.SenderNotificationPermission: return this.eventFulfillsSenderNotifPermCondition(cond, ev); + case ConditionKind.CallStarted: + case ConditionKind.CallStartedPrefix: + return this.eventFulfillsCallStartedCondition(cond, ev); } // unknown conditions: we previously matched all unknown conditions, @@ -383,6 +391,22 @@ export class PushProcessor { return !!val.match(regex); } + private eventFulfillsCallStartedCondition( + _cond: ICallStartedCondition | ICallStartedPrefixCondition, + ev: MatrixEvent, + ): boolean { + // Since servers don't support properly sending push notification + // about MSC3401 call events, we do the handling ourselves + return ( + ["m.ring", "m.prompt"].includes(ev.getContent()["m.intent"]) + && !("m.terminated" in ev.getContent()) + && ( + (ev.getPrevContent()["m.terminated"] !== ev.getContent()["m.terminated"]) + || deepCompare(ev.getPrevContent(), {}) + ) + ); + } + private createCachedRegex(prefix: string, glob: string, suffix: string): RegExp { if (PushProcessor.cachedGlobToRegex[glob]) { return PushProcessor.cachedGlobToRegex[glob]; @@ -438,7 +462,7 @@ export class PushProcessor { return {} as IActionsObject; } - let actionObj = PushProcessor.actionListToActionsObject(rule.actions); + const actionObj = PushProcessor.actionListToActionsObject(rule.actions); // Some actions are implicit in some situations: we add those here if (actionObj.tweaks.highlight === undefined) { @@ -447,30 +471,6 @@ export class PushProcessor { actionObj.tweaks.highlight = (rule.kind == PushRuleKind.ContentSpecific); } - actionObj = this.performCustomEventHandling(ev, actionObj); - - return actionObj; - } - - /** - * Some events require custom event handling e.g. due to missing server support - */ - private performCustomEventHandling(ev: MatrixEvent, actionObj: IActionsObject): IActionsObject { - switch (ev.getType()) { - case "m.call": - case "org.matrix.msc3401.call": - // Since servers don't support properly sending push notification - // about MSC3401 call events, we do the handling ourselves - if ( - ev.getContent()["m.intent"] === "m.room" - || ("m.terminated" in ev.getContent()) - || !("m.terminated" in ev.getPrevContent()) && !deepCompare(ev.getPrevContent(), {}) - ) { - actionObj.notify = false; - actionObj.tweaks = {}; - } - } - return actionObj; }