Skip to content

Commit 3e17173

Browse files
authored
Merge pull request #433 from ably/integrations-chat-room-filter
feat(integrations): support chatRoomFilter and chat rule types
2 parents 3b79924 + 0bf37b5 commit 3e17173

13 files changed

Lines changed: 1788 additions & 99 deletions

File tree

src/commands/integrations/create.ts

Lines changed: 333 additions & 53 deletions
Large diffs are not rendered by default.

src/commands/integrations/delete.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,29 @@ export default class IntegrationsDeleteCommand extends ControlBaseCommand {
5555
this.log(`\nYou are about to delete the following integration:`);
5656
this.log(`${formatLabel("Integration ID")} ${integration.id}`);
5757
this.log(`${formatLabel("Type")} ${integration.ruleType}`);
58-
this.log(`${formatLabel("Request Mode")} ${integration.requestMode}`);
58+
if (integration.requestMode) {
59+
this.log(`${formatLabel("Request Mode")} ${integration.requestMode}`);
60+
}
61+
62+
if (integration.invocationMode) {
63+
this.log(
64+
`${formatLabel("Invocation Mode")} ${integration.invocationMode}`,
65+
);
66+
}
67+
5968
this.log(`${formatLabel("Source Type")} ${integration.source.type}`);
6069
if (integration.source.channelFilter) {
6170
this.log(
6271
`${formatLabel("Channel Filter")} ${integration.source.channelFilter}`,
6372
);
6473
}
6574

75+
if (integration.chatRoomFilter) {
76+
this.log(
77+
`${formatLabel("Chat Room Filter")} ${integration.chatRoomFilter}`,
78+
);
79+
}
80+
6681
const confirmed = await promptForConfirmation(
6782
`\nAre you sure you want to delete integration "${integration.id}"?`,
6883
);

src/commands/integrations/get.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,22 @@ export default class IntegrationsGetCommand extends ControlBaseCommand {
5353
this.log(`${formatLabel("ID")} ${rule.id}`);
5454
this.log(`${formatLabel("App ID")} ${rule.appId}`);
5555
this.log(`${formatLabel("Rule Type")} ${rule.ruleType}`);
56-
this.log(`${formatLabel("Request Mode")} ${rule.requestMode}`);
56+
if (rule.requestMode) {
57+
this.log(`${formatLabel("Request Mode")} ${rule.requestMode}`);
58+
}
59+
60+
if (rule.invocationMode) {
61+
this.log(`${formatLabel("Invocation Mode")} ${rule.invocationMode}`);
62+
}
63+
5764
if (rule.source.channelFilter) {
5865
this.log(
5966
`${formatLabel("Source Channel Filter")} ${rule.source.channelFilter}`,
6067
);
6168
}
69+
if (rule.chatRoomFilter) {
70+
this.log(`${formatLabel("Chat Room Filter")} ${rule.chatRoomFilter}`);
71+
}
6272
this.log(`${formatLabel("Source Type")} ${rule.source.type}`);
6373
this.log(
6474
`${formatLabel("Target")} ${this.formatJsonOutput(structuredClone(rule.target) as Record<string, unknown>, flags).replaceAll("\n", "\n ")}`,

src/commands/integrations/list.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ export default class IntegrationsListCommand extends ControlBaseCommand {
4646
hasMore,
4747
integrations: integrations.map((integration) => ({
4848
appId: integration.appId,
49+
chatRoomFilter: integration.chatRoomFilter || null,
4950
created: new Date(integration.created).toISOString(),
5051
id: integration.id,
52+
invocationMode: integration.invocationMode || null,
5153
modified: new Date(integration.modified).toISOString(),
52-
requestMode: integration.requestMode,
54+
requestMode: integration.requestMode || null,
5355
source: {
5456
channelFilter: integration.source.channelFilter || null,
5557
type: integration.source.type,
@@ -75,11 +77,21 @@ export default class IntegrationsListCommand extends ControlBaseCommand {
7577
this.log(formatHeading(`Integration ID: ${integration.id}`));
7678
this.log(` App ID: ${integration.appId}`);
7779
this.log(` Type: ${integration.ruleType}`);
78-
this.log(` Request Mode: ${integration.requestMode}`);
80+
if (integration.requestMode) {
81+
this.log(` Request Mode: ${integration.requestMode}`);
82+
}
83+
84+
if (integration.invocationMode) {
85+
this.log(` Invocation Mode: ${integration.invocationMode}`);
86+
}
87+
7988
this.log(` Source Type: ${integration.source.type}`);
8089
if (integration.source.channelFilter) {
8190
this.log(` Channel Filter: ${integration.source.channelFilter}`);
8291
}
92+
if (integration.chatRoomFilter) {
93+
this.log(` Chat Room Filter: ${integration.chatRoomFilter}`);
94+
}
8395
this.log(
8496
` Target: ${JSON.stringify(integration.target, null, 2).replaceAll("\n", "\n ")}`,
8597
);

src/commands/integrations/update.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { Args, Flags } from "@oclif/core";
22
import { ControlBaseCommand } from "../../control-base-command.js";
3+
4+
// Rule types whose target has a `url` field updatable via --target-url.
5+
const HTTP_TARGET_URL_RULE_TYPES = new Set(["http", "http/before-publish"]);
6+
37
// Interface for rule update data structure (most fields optional)
48
interface PartialRuleData {
9+
chatRoomFilter?: string;
510
requestMode?: string;
611
ruleType?: string; // Usually shouldn't be updated, but kept for structure
712
source?: {
@@ -24,7 +29,8 @@ export default class IntegrationsUpdateCommand extends ControlBaseCommand {
2429

2530
static examples = [
2631
"$ ably integrations update rule123 --status disabled",
27-
'$ ably integrations update rule123 --channel-filter "chat:*"',
32+
'$ ably integrations update rule123 --channel-filter "chat:.*"',
33+
'$ ably integrations update rule123 --chat-room-filter "room:.*"',
2834
'$ ably integrations update rule123 --target-url "https://new-example.com/webhook"',
2935
"$ ably integrations update rule123 --status disabled --json",
3036
];
@@ -39,6 +45,10 @@ export default class IntegrationsUpdateCommand extends ControlBaseCommand {
3945
description: "Channel filter pattern",
4046
required: false,
4147
}),
48+
"chat-room-filter": Flags.string({
49+
description: "Chat room filter pattern",
50+
required: false,
51+
}),
4252
status: Flags.string({
4353
description: "Status of the rule",
4454
options: ["enabled", "disabled"],
@@ -96,8 +106,15 @@ export default class IntegrationsUpdateCommand extends ControlBaseCommand {
96106
updatePayload.source.channelFilter = flags["channel-filter"];
97107
}
98108

99-
// Update target if it's an HTTP rule and target-url is provided
100-
if (existingRule.ruleType === "http" && flags["target-url"]) {
109+
if (flags["chat-room-filter"]) {
110+
updatePayload.chatRoomFilter = flags["chat-room-filter"];
111+
}
112+
113+
// Update target if it's an HTTP-based rule and target-url is provided
114+
if (
115+
HTTP_TARGET_URL_RULE_TYPES.has(existingRule.ruleType) &&
116+
flags["target-url"]
117+
) {
101118
// Ensure target exists before assigning to url
102119
if (!updatePayload.target) updatePayload.target = {};
103120
updatePayload.target.url = flags["target-url"];
@@ -124,12 +141,22 @@ export default class IntegrationsUpdateCommand extends ControlBaseCommand {
124141
this.log(`ID: ${updatedRule.id}`);
125142
this.log(`App ID: ${updatedRule.appId}`);
126143
this.log(`Rule Type: ${updatedRule.ruleType}`);
127-
this.log(`Request Mode: ${updatedRule.requestMode}`);
144+
if (updatedRule.requestMode) {
145+
this.log(`Request Mode: ${updatedRule.requestMode}`);
146+
}
147+
148+
if (updatedRule.invocationMode) {
149+
this.log(`Invocation Mode: ${updatedRule.invocationMode}`);
150+
}
151+
128152
if (updatedRule.source.channelFilter) {
129153
this.log(
130154
`Source Channel Filter: ${updatedRule.source.channelFilter}`,
131155
);
132156
}
157+
if (updatedRule.chatRoomFilter) {
158+
this.log(`Chat Room Filter: ${updatedRule.chatRoomFilter}`);
159+
}
133160
this.log(`Source Type: ${updatedRule.source.type}`);
134161
if (
135162
typeof updatedRule.target === "object" &&

src/services/control-api.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,30 +85,45 @@ export interface Namespace {
8585
tlsOnly?: boolean;
8686
}
8787

88+
// Retry/failure policy for rule types invoked with invocationMode
89+
// "BEFORE_PUBLISH" (chat moderation and before-publish webhook rule types).
90+
export interface BeforePublishConfig {
91+
failedAction: string;
92+
maxRetries: number;
93+
retryTimeout: number;
94+
tooManyRequestsAction: string;
95+
}
96+
8897
export interface Rule {
8998
_links?: {
9099
self: string;
91100
};
92101
appId: string;
102+
beforePublishConfig?: BeforePublishConfig;
93103
created: number;
94104
id: string;
105+
invocationMode?: string;
95106
modified: number;
96-
requestMode: string;
107+
requestMode?: string;
97108
ruleType: string;
98109
source: {
99-
channelFilter: string;
110+
channelFilter?: string;
100111
type: string;
101112
};
113+
chatRoomFilter?: string;
102114
target: unknown;
103115
version: string;
104116
}
105117

106118
// Define RuleData interface for rule creation and updates
107119
export interface RuleData {
108-
requestMode: string;
120+
beforePublishConfig?: BeforePublishConfig;
121+
chatRoomFilter?: string;
122+
invocationMode?: string;
123+
requestMode?: string;
109124
ruleType: string;
110125
source: {
111-
channelFilter: string;
126+
channelFilter?: string;
112127
type: string;
113128
};
114129
status?: "disabled" | "enabled";

0 commit comments

Comments
 (0)