Skip to content

Commit a12e618

Browse files
Update call notification push rule to match MSC3914 (#2781)
1 parent d9eac57 commit a12e618

File tree

3 files changed

+67
-35
lines changed

3 files changed

+67
-35
lines changed

spec/unit/pushprocessor.spec.ts

+27-7
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,22 @@ describe('NotificationService', function() {
163163
"enabled": true,
164164
"rule_id": ".m.rule.room_one_to_one",
165165
},
166+
{
167+
rule_id: ".org.matrix.msc3914.rule.room.call",
168+
default: true,
169+
enabled: true,
170+
conditions: [
171+
{
172+
kind: "event_match",
173+
key: "type",
174+
pattern: "org.matrix.msc3401.call",
175+
},
176+
{
177+
kind: "call_started",
178+
},
179+
],
180+
actions: ["notify", { set_tweak: "sound", value: "default" }],
181+
},
166182
],
167183
"room": [],
168184
"sender": [],
@@ -337,7 +353,11 @@ describe('NotificationService', function() {
337353
}, testEvent)).toBe(true);
338354
});
339355

340-
describe("performCustomEventHandling()", () => {
356+
describe("group call started push rule", () => {
357+
beforeEach(() => {
358+
matrixClient.pushRules!.global!.underride!.find(r => r.rule_id === ".m.rule.fallback")!.enabled = false;
359+
});
360+
341361
const getActionsForEvent = (prevContent: IContent, content: IContent): IActionsObject => {
342362
testEvent = utils.mkEvent({
343363
type: "org.matrix.msc3401.call",
@@ -353,15 +373,15 @@ describe('NotificationService', function() {
353373
};
354374

355375
const assertDoesNotify = (actions: IActionsObject): void => {
356-
expect(actions.notify).toBeTruthy();
357-
expect(actions.tweaks.sound).toBeTruthy();
358-
expect(actions.tweaks.highlight).toBeFalsy();
376+
expect(actions?.notify).toBeTruthy();
377+
expect(actions?.tweaks?.sound).toBeTruthy();
378+
expect(actions?.tweaks?.highlight).toBeFalsy();
359379
};
360380

361381
const assertDoesNotNotify = (actions: IActionsObject): void => {
362-
expect(actions.notify).toBeFalsy();
363-
expect(actions.tweaks.sound).toBeFalsy();
364-
expect(actions.tweaks.highlight).toBeFalsy();
382+
expect(actions?.notify).toBeFalsy();
383+
expect(actions?.tweaks?.sound).toBeFalsy();
384+
expect(actions?.tweaks?.highlight).toBeFalsy();
365385
};
366386

367387
it.each(

src/@types/PushRules.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ export enum ConditionKind {
6565
ContainsDisplayName = "contains_display_name",
6666
RoomMemberCount = "room_member_count",
6767
SenderNotificationPermission = "sender_notification_permission",
68+
CallStarted = "call_started",
69+
CallStartedPrefix = "org.matrix.msc3914.call_started",
6870
}
6971

7072
export interface IPushRuleCondition<N extends ConditionKind | string> {
@@ -90,12 +92,22 @@ export interface ISenderNotificationPermissionCondition
9092
key: string;
9193
}
9294

95+
export interface ICallStartedCondition extends IPushRuleCondition<ConditionKind.CallStarted> {
96+
// no additional fields
97+
}
98+
99+
export interface ICallStartedPrefixCondition extends IPushRuleCondition<ConditionKind.CallStartedPrefix> {
100+
// no additional fields
101+
}
102+
93103
// XXX: custom conditions are possible but always fail, and break the typescript discriminated union so ignore them here
94104
// IPushRuleCondition<Exclude<string, ConditionKind>> unfortunately does not resolve this at the time of writing.
95105
export type PushRuleCondition = IEventMatchCondition
96106
| IContainsDisplayNameCondition
97107
| IRoomMemberCountCondition
98-
| ISenderNotificationPermissionCondition;
108+
| ISenderNotificationPermissionCondition
109+
| ICallStartedCondition
110+
| ICallStartedPrefixCondition;
99111

100112
export enum PushRuleKind {
101113
Override = "override",

src/pushprocessor.ts

+27-27
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { MatrixEvent } from "./models/event";
2121
import {
2222
ConditionKind,
2323
IAnnotatedPushRule,
24+
ICallStartedCondition,
25+
ICallStartedPrefixCondition,
2426
IContainsDisplayNameCondition,
2527
IEventMatchCondition,
2628
IPushRule,
@@ -92,8 +94,8 @@ const DEFAULT_OVERRIDE_RULES: IPushRule[] = [
9294
actions: [],
9395
},
9496
{
95-
// For homeservers which don't support MSC3401 yet
96-
rule_id: ".org.matrix.msc3401.rule.room.call",
97+
// For homeservers which don't support MSC3914 yet
98+
rule_id: ".org.matrix.msc3914.rule.room.call",
9799
default: true,
98100
enabled: true,
99101
conditions: [
@@ -102,6 +104,9 @@ const DEFAULT_OVERRIDE_RULES: IPushRule[] = [
102104
key: "type",
103105
pattern: "org.matrix.msc3401.call",
104106
},
107+
{
108+
kind: ConditionKind.CallStarted,
109+
},
105110
],
106111
actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: "default" }],
107112
},
@@ -269,6 +274,9 @@ export class PushProcessor {
269274
return this.eventFulfillsRoomMemberCountCondition(cond, ev);
270275
case ConditionKind.SenderNotificationPermission:
271276
return this.eventFulfillsSenderNotifPermCondition(cond, ev);
277+
case ConditionKind.CallStarted:
278+
case ConditionKind.CallStartedPrefix:
279+
return this.eventFulfillsCallStartedCondition(cond, ev);
272280
}
273281

274282
// unknown conditions: we previously matched all unknown conditions,
@@ -383,6 +391,22 @@ export class PushProcessor {
383391
return !!val.match(regex);
384392
}
385393

394+
private eventFulfillsCallStartedCondition(
395+
_cond: ICallStartedCondition | ICallStartedPrefixCondition,
396+
ev: MatrixEvent,
397+
): boolean {
398+
// Since servers don't support properly sending push notification
399+
// about MSC3401 call events, we do the handling ourselves
400+
return (
401+
["m.ring", "m.prompt"].includes(ev.getContent()["m.intent"])
402+
&& !("m.terminated" in ev.getContent())
403+
&& (
404+
(ev.getPrevContent()["m.terminated"] !== ev.getContent()["m.terminated"])
405+
|| deepCompare(ev.getPrevContent(), {})
406+
)
407+
);
408+
}
409+
386410
private createCachedRegex(prefix: string, glob: string, suffix: string): RegExp {
387411
if (PushProcessor.cachedGlobToRegex[glob]) {
388412
return PushProcessor.cachedGlobToRegex[glob];
@@ -438,7 +462,7 @@ export class PushProcessor {
438462
return {} as IActionsObject;
439463
}
440464

441-
let actionObj = PushProcessor.actionListToActionsObject(rule.actions);
465+
const actionObj = PushProcessor.actionListToActionsObject(rule.actions);
442466

443467
// Some actions are implicit in some situations: we add those here
444468
if (actionObj.tweaks.highlight === undefined) {
@@ -447,30 +471,6 @@ export class PushProcessor {
447471
actionObj.tweaks.highlight = (rule.kind == PushRuleKind.ContentSpecific);
448472
}
449473

450-
actionObj = this.performCustomEventHandling(ev, actionObj);
451-
452-
return actionObj;
453-
}
454-
455-
/**
456-
* Some events require custom event handling e.g. due to missing server support
457-
*/
458-
private performCustomEventHandling(ev: MatrixEvent, actionObj: IActionsObject): IActionsObject {
459-
switch (ev.getType()) {
460-
case "m.call":
461-
case "org.matrix.msc3401.call":
462-
// Since servers don't support properly sending push notification
463-
// about MSC3401 call events, we do the handling ourselves
464-
if (
465-
ev.getContent()["m.intent"] === "m.room"
466-
|| ("m.terminated" in ev.getContent())
467-
|| !("m.terminated" in ev.getPrevContent()) && !deepCompare(ev.getPrevContent(), {})
468-
) {
469-
actionObj.notify = false;
470-
actionObj.tweaks = {};
471-
}
472-
}
473-
474474
return actionObj;
475475
}
476476

0 commit comments

Comments
 (0)