@inline-openclaw/inline 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,43 @@
1
- import { jsonResult, readReactionParams, readNumberParam, readStringParam, } from "openclaw/plugin-sdk";
2
- import { InlineSdkClient, Method } from "@inline-chat/realtime-sdk";
1
+ import { createActionGate, jsonResult, readReactionParams, readNumberParam, readStringParam, } from "openclaw/plugin-sdk";
2
+ import { InlineSdkClient, Method, Member_Role, } from "@inline-chat/realtime-sdk";
3
3
  import { resolveInlineAccount, resolveInlineToken } from "./accounts.js";
4
4
  import { normalizeInlineTarget } from "./normalize.js";
5
- const ACTIONS = [
6
- "reply",
7
- "react",
8
- "reactions",
9
- "read",
10
- "search",
11
- "edit",
12
- "channel-info",
13
- "channel-edit",
14
- "addParticipant",
15
- "member-info",
5
+ const ACTION_GROUPS = [
6
+ { key: "reply", defaultEnabled: true, actions: ["reply", "thread-reply"] },
7
+ { key: "reactions", defaultEnabled: true, actions: ["react", "reactions"] },
8
+ { key: "read", defaultEnabled: true, actions: ["read"] },
9
+ { key: "search", defaultEnabled: true, actions: ["search"] },
10
+ { key: "edit", defaultEnabled: true, actions: ["edit"] },
11
+ {
12
+ key: "channels",
13
+ defaultEnabled: true,
14
+ actions: [
15
+ "channel-info",
16
+ "channel-edit",
17
+ "channel-list",
18
+ "channel-create",
19
+ "channel-delete",
20
+ "channel-move",
21
+ "thread-list",
22
+ "thread-create",
23
+ ],
24
+ },
25
+ {
26
+ key: "participants",
27
+ defaultEnabled: true,
28
+ actions: ["addParticipant", "removeParticipant", "leaveGroup", "member-info"],
29
+ },
30
+ { key: "delete", defaultEnabled: true, actions: ["delete", "unsend"] },
31
+ { key: "pins", defaultEnabled: true, actions: ["pin", "unpin", "list-pins"] },
32
+ { key: "permissions", defaultEnabled: true, actions: ["permissions"] },
16
33
  ];
34
+ const ACTION_TO_GATE_KEY = new Map();
35
+ for (const group of ACTION_GROUPS) {
36
+ for (const action of group.actions) {
37
+ ACTION_TO_GATE_KEY.set(action, group.key);
38
+ }
39
+ }
40
+ const SUPPORTED_ACTIONS = Array.from(ACTION_TO_GATE_KEY.keys());
17
41
  function normalizeChatId(raw) {
18
42
  const normalized = normalizeInlineTarget(raw) ?? raw.trim();
19
43
  if (!/^[0-9]+$/.test(normalized)) {
@@ -36,11 +60,28 @@ function readFlexibleId(params, key) {
36
60
  }
37
61
  return undefined;
38
62
  }
63
+ function readBooleanParam(params, key) {
64
+ const value = params[key];
65
+ if (typeof value === "boolean")
66
+ return value;
67
+ if (typeof value === "string") {
68
+ const trimmed = value.trim().toLowerCase();
69
+ if (trimmed === "true")
70
+ return true;
71
+ if (trimmed === "false")
72
+ return false;
73
+ }
74
+ return undefined;
75
+ }
39
76
  function parseInlineId(raw, label) {
40
- if (typeof raw === "bigint")
77
+ if (typeof raw === "bigint") {
78
+ if (raw < 0n) {
79
+ throw new Error(`inline action: invalid ${label} "${raw.toString()}"`);
80
+ }
41
81
  return raw;
82
+ }
42
83
  if (typeof raw === "number") {
43
- if (!Number.isFinite(raw) || !Number.isInteger(raw)) {
84
+ if (!Number.isFinite(raw) || !Number.isInteger(raw) || raw < 0) {
44
85
  throw new Error(`inline action: invalid ${label} "${String(raw)}"`);
45
86
  }
46
87
  return BigInt(raw);
@@ -62,6 +103,34 @@ function parseOptionalInlineId(raw, label) {
62
103
  return undefined;
63
104
  return parseInlineId(raw, label);
64
105
  }
106
+ function parseInlineIdList(raw, label) {
107
+ if (raw == null)
108
+ return [];
109
+ if (Array.isArray(raw)) {
110
+ return raw.map((item) => parseInlineId(item, label));
111
+ }
112
+ if (typeof raw === "string") {
113
+ const trimmed = raw.trim();
114
+ if (!trimmed)
115
+ return [];
116
+ const chunks = trimmed
117
+ .split(",")
118
+ .map((item) => item.trim())
119
+ .filter(Boolean);
120
+ if (chunks.length <= 1) {
121
+ return [parseInlineId(trimmed, label)];
122
+ }
123
+ return chunks.map((item) => parseInlineId(item, label));
124
+ }
125
+ return [parseInlineId(raw, label)];
126
+ }
127
+ function parseInlineIdListFromParams(params, key) {
128
+ const direct = params[key];
129
+ if (direct != null) {
130
+ return parseInlineIdList(direct, key);
131
+ }
132
+ return [];
133
+ }
65
134
  function resolveChatIdFromParams(params) {
66
135
  const raw = readFlexibleId(params, "chatId") ??
67
136
  readFlexibleId(params, "channelId") ??
@@ -80,6 +149,15 @@ function buildChatPeer(chatId) {
80
149
  },
81
150
  };
82
151
  }
152
+ function buildInlineUserDisplayName(user) {
153
+ const explicit = [user.firstName?.trim(), user.lastName?.trim()].filter(Boolean).join(" ");
154
+ if (explicit)
155
+ return explicit;
156
+ const username = user.username?.trim();
157
+ if (username)
158
+ return `@${username}`;
159
+ return "Unknown";
160
+ }
83
161
  function mapMessage(message) {
84
162
  const reactions = (message.reactions?.reactions ?? []).map((reaction) => ({
85
163
  emoji: reaction.emoji ?? "",
@@ -98,19 +176,52 @@ function mapMessage(message) {
98
176
  reactions,
99
177
  };
100
178
  }
179
+ function mapChatEntry(params) {
180
+ const dialog = params.dialogByChatId.get(String(params.chat.id));
181
+ const peer = params.chat.peerId?.type;
182
+ let peerUser = null;
183
+ if (peer?.oneofKind === "user") {
184
+ peerUser = params.usersById.get(String(peer.user.userId)) ?? null;
185
+ }
186
+ return {
187
+ id: String(params.chat.id),
188
+ title: params.chat.title,
189
+ spaceId: params.chat.spaceId != null ? String(params.chat.spaceId) : null,
190
+ isPublic: params.chat.isPublic ?? false,
191
+ createdBy: params.chat.createdBy != null ? String(params.chat.createdBy) : null,
192
+ date: params.chat.date != null ? Number(params.chat.date) * 1000 : null,
193
+ unreadCount: dialog?.unreadCount ?? 0,
194
+ archived: Boolean(dialog?.archived),
195
+ pinned: Boolean(dialog?.pinned),
196
+ peer: peer?.oneofKind === "user"
197
+ ? {
198
+ kind: "user",
199
+ id: String(peer.user.userId),
200
+ username: peerUser?.username ?? null,
201
+ name: peerUser ? buildInlineUserDisplayName(peerUser) : null,
202
+ }
203
+ : peer?.oneofKind === "chat"
204
+ ? { kind: "chat", id: String(peer.chat.chatId) }
205
+ : null,
206
+ };
207
+ }
208
+ function mapSpaceMemberRole(role) {
209
+ if (role == null)
210
+ return null;
211
+ if (role === Member_Role.OWNER)
212
+ return "owner";
213
+ if (role === Member_Role.ADMIN)
214
+ return "admin";
215
+ if (role === Member_Role.MEMBER)
216
+ return "member";
217
+ return null;
218
+ }
101
219
  async function loadMessageReactions(params) {
102
- const result = await params.client.invokeRaw(Method.GET_CHAT_HISTORY, {
103
- oneofKind: "getChatHistory",
104
- getChatHistory: {
105
- peerId: buildChatPeer(params.chatId),
106
- offsetId: params.messageId + 1n,
107
- limit: 8,
108
- },
220
+ const target = await findMessageById({
221
+ client: params.client,
222
+ chatId: params.chatId,
223
+ messageId: params.messageId,
109
224
  });
110
- if (result.oneofKind !== "getChatHistory") {
111
- throw new Error(`inline action: expected getChatHistory result, got ${String(result.oneofKind)}`);
112
- }
113
- const target = (result.getChatHistory.messages ?? []).find((message) => message.id === params.messageId) ?? null;
114
225
  if (!target) {
115
226
  return [];
116
227
  }
@@ -133,6 +244,32 @@ async function loadMessageReactions(params) {
133
244
  }
134
245
  return Array.from(byEmoji.values());
135
246
  }
247
+ async function findMessageById(params) {
248
+ const directResult = await params.client
249
+ .invokeRaw(Method.GET_MESSAGES, {
250
+ oneofKind: "getMessages",
251
+ getMessages: {
252
+ peerId: buildChatPeer(params.chatId),
253
+ messageIds: [params.messageId],
254
+ },
255
+ })
256
+ .catch(() => null);
257
+ if (directResult?.oneofKind === "getMessages") {
258
+ return (directResult.getMessages.messages ?? []).find((message) => message.id === params.messageId) ?? null;
259
+ }
260
+ const result = await params.client.invokeRaw(Method.GET_CHAT_HISTORY, {
261
+ oneofKind: "getChatHistory",
262
+ getChatHistory: {
263
+ peerId: buildChatPeer(params.chatId),
264
+ offsetId: params.messageId + 1n,
265
+ limit: 8,
266
+ },
267
+ });
268
+ if (result.oneofKind !== "getChatHistory") {
269
+ throw new Error(`inline action: expected getChatHistory result, got ${String(result.oneofKind)}`);
270
+ }
271
+ return (result.getChatHistory.messages ?? []).find((message) => message.id === params.messageId) ?? null;
272
+ }
136
273
  async function withInlineClient(params) {
137
274
  const account = resolveInlineAccount({ cfg: params.cfg, accountId: params.accountId ?? null });
138
275
  if (!account.configured || !account.baseUrl) {
@@ -165,14 +302,68 @@ function toJsonSafe(value) {
165
302
  }
166
303
  return value;
167
304
  }
305
+ function buildDialogMap(dialogs) {
306
+ const map = new Map();
307
+ for (const dialog of dialogs) {
308
+ const chatId = dialog.chatId;
309
+ if (chatId != null) {
310
+ map.set(String(chatId), dialog);
311
+ continue;
312
+ }
313
+ const peer = dialog.peer?.type;
314
+ if (peer?.oneofKind === "chat") {
315
+ map.set(String(peer.chat.chatId), dialog);
316
+ }
317
+ }
318
+ return map;
319
+ }
320
+ function buildUserMap(users) {
321
+ const map = new Map();
322
+ for (const user of users) {
323
+ map.set(String(user.id), user);
324
+ }
325
+ return map;
326
+ }
327
+ function listAllActions() {
328
+ const out = new Set();
329
+ for (const group of ACTION_GROUPS) {
330
+ for (const action of group.actions) {
331
+ out.add(action);
332
+ }
333
+ }
334
+ return Array.from(out);
335
+ }
336
+ function isActionEnabled(params) {
337
+ const key = ACTION_TO_GATE_KEY.get(params.action);
338
+ if (!key)
339
+ return false;
340
+ const group = ACTION_GROUPS.find((item) => item.key === key);
341
+ if (!group)
342
+ return false;
343
+ const account = resolveInlineAccount({
344
+ cfg: params.cfg,
345
+ accountId: params.accountId ?? null,
346
+ });
347
+ const gate = createActionGate((account.config.actions ?? {}));
348
+ return gate(key, group.defaultEnabled);
349
+ }
168
350
  export const inlineMessageActions = {
169
351
  listActions: ({ cfg }) => {
170
352
  const account = resolveInlineAccount({ cfg, accountId: null });
171
353
  if (!account.enabled || !account.configured)
172
354
  return [];
173
- return [...ACTIONS];
355
+ const gate = createActionGate((account.config.actions ?? {}));
356
+ const actions = new Set();
357
+ for (const group of ACTION_GROUPS) {
358
+ if (!gate(group.key, group.defaultEnabled))
359
+ continue;
360
+ for (const action of group.actions) {
361
+ actions.add(action);
362
+ }
363
+ }
364
+ return Array.from(actions);
174
365
  },
175
- supportsAction: ({ action }) => ACTIONS.includes(action),
366
+ supportsAction: ({ action }) => SUPPORTED_ACTIONS.includes(action),
176
367
  extractToolSend: ({ args }) => {
177
368
  const action = typeof args.action === "string" ? args.action.trim() : "";
178
369
  if (action !== "sendMessage")
@@ -186,7 +377,14 @@ export const inlineMessageActions = {
186
377
  return { to: normalized };
187
378
  },
188
379
  handleAction: async ({ action, params, cfg, accountId }) => {
189
- if (action === "reply") {
380
+ if (!SUPPORTED_ACTIONS.includes(action)) {
381
+ throw new Error(`Action ${action} is not supported for provider inline.`);
382
+ }
383
+ if (!isActionEnabled({ cfg, accountId: accountId ?? null, action })) {
384
+ throw new Error(`inline action: ${action} is disabled by channels.inline.actions`);
385
+ }
386
+ const normalizedAction = action === "thread-reply" ? "reply" : action;
387
+ if (normalizedAction === "reply") {
190
388
  const parseMarkdown = resolveInlineAccount({ cfg, accountId: accountId ?? null }).config.parseMarkdown ?? true;
191
389
  return await withInlineClient({
192
390
  cfg,
@@ -216,13 +414,14 @@ export const inlineMessageActions = {
216
414
  },
217
415
  });
218
416
  }
219
- if (action === "react") {
417
+ if (normalizedAction === "react") {
220
418
  return await withInlineClient({
221
419
  cfg,
222
420
  accountId,
223
421
  fn: async (client) => {
224
422
  const chatId = resolveChatIdFromParams(params);
225
- const messageId = parseInlineId(readFlexibleId(params, "messageId") ?? readStringParam(params, "messageId", { required: true }), "messageId");
423
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
424
+ readStringParam(params, "messageId", { required: true }), "messageId");
226
425
  const { emoji, remove, isEmpty } = readReactionParams(params, {
227
426
  removeErrorMessage: "Emoji is required to remove an Inline reaction.",
228
427
  });
@@ -265,13 +464,14 @@ export const inlineMessageActions = {
265
464
  },
266
465
  });
267
466
  }
268
- if (action === "reactions") {
467
+ if (normalizedAction === "reactions") {
269
468
  return await withInlineClient({
270
469
  cfg,
271
470
  accountId,
272
471
  fn: async (client) => {
273
472
  const chatId = resolveChatIdFromParams(params);
274
- const messageId = parseInlineId(readFlexibleId(params, "messageId") ?? readStringParam(params, "messageId", { required: true }), "messageId");
473
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
474
+ readStringParam(params, "messageId", { required: true }), "messageId");
275
475
  const reactions = await loadMessageReactions({
276
476
  client,
277
477
  chatId,
@@ -286,7 +486,7 @@ export const inlineMessageActions = {
286
486
  },
287
487
  });
288
488
  }
289
- if (action === "read") {
489
+ if (normalizedAction === "read") {
290
490
  return await withInlineClient({
291
491
  cfg,
292
492
  accountId,
@@ -313,7 +513,7 @@ export const inlineMessageActions = {
313
513
  },
314
514
  });
315
515
  }
316
- if (action === "search") {
516
+ if (normalizedAction === "search") {
317
517
  return await withInlineClient({
318
518
  cfg,
319
519
  accountId,
@@ -345,13 +545,14 @@ export const inlineMessageActions = {
345
545
  },
346
546
  });
347
547
  }
348
- if (action === "edit") {
548
+ if (normalizedAction === "edit") {
349
549
  return await withInlineClient({
350
550
  cfg,
351
551
  accountId,
352
552
  fn: async (client) => {
353
553
  const chatId = resolveChatIdFromParams(params);
354
- const messageId = parseInlineId(readFlexibleId(params, "messageId") ?? readStringParam(params, "messageId", { required: true }), "messageId");
554
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
555
+ readStringParam(params, "messageId", { required: true }), "messageId");
355
556
  const text = readStringParam(params, "message", { required: true, allowEmpty: true });
356
557
  const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
357
558
  oneofKind: "editMessage",
@@ -368,7 +569,7 @@ export const inlineMessageActions = {
368
569
  },
369
570
  });
370
571
  }
371
- if (action === "channel-info") {
572
+ if (normalizedAction === "channel-info") {
372
573
  return await withInlineClient({
373
574
  cfg,
374
575
  accountId,
@@ -391,7 +592,7 @@ export const inlineMessageActions = {
391
592
  },
392
593
  });
393
594
  }
394
- if (action === "channel-edit") {
595
+ if (normalizedAction === "channel-edit") {
395
596
  return await withInlineClient({
396
597
  cfg,
397
598
  accountId,
@@ -419,7 +620,150 @@ export const inlineMessageActions = {
419
620
  },
420
621
  });
421
622
  }
422
- if (action === "addParticipant") {
623
+ if (normalizedAction === "channel-list" || normalizedAction === "thread-list") {
624
+ return await withInlineClient({
625
+ cfg,
626
+ accountId,
627
+ fn: async (client) => {
628
+ const query = readStringParam(params, "query") ??
629
+ readStringParam(params, "q") ??
630
+ undefined;
631
+ const limit = Math.max(1, Math.min(200, readNumberParam(params, "limit", { integer: true }) ?? 50));
632
+ const result = await client.invokeRaw(Method.GET_CHATS, {
633
+ oneofKind: "getChats",
634
+ getChats: {},
635
+ });
636
+ if (result.oneofKind !== "getChats") {
637
+ throw new Error(`inline action: expected getChats result, got ${String(result.oneofKind)}`);
638
+ }
639
+ const dialogByChatId = buildDialogMap(result.getChats.dialogs ?? []);
640
+ const usersById = buildUserMap(result.getChats.users ?? []);
641
+ const entries = (result.getChats.chats ?? []).map((chat) => mapChatEntry({ chat, dialogByChatId, usersById }));
642
+ const normalizedQuery = query?.trim().toLowerCase() ?? "";
643
+ const filtered = normalizedQuery
644
+ ? entries.filter((entry) => {
645
+ const haystack = [
646
+ entry.id,
647
+ entry.title,
648
+ entry.peer?.kind === "user" ? entry.peer.username ?? "" : "",
649
+ entry.peer?.kind === "user" ? entry.peer.name ?? "" : "",
650
+ ]
651
+ .join("\n")
652
+ .toLowerCase();
653
+ return haystack.includes(normalizedQuery);
654
+ })
655
+ : entries;
656
+ return jsonResult(toJsonSafe({
657
+ ok: true,
658
+ query: query ?? null,
659
+ count: filtered.length,
660
+ chats: filtered.slice(0, limit),
661
+ }));
662
+ },
663
+ });
664
+ }
665
+ if (normalizedAction === "channel-create" || normalizedAction === "thread-create") {
666
+ return await withInlineClient({
667
+ cfg,
668
+ accountId,
669
+ fn: async (client) => {
670
+ const title = readStringParam(params, "title") ??
671
+ readStringParam(params, "name") ??
672
+ readStringParam(params, "message", { required: true });
673
+ const description = readStringParam(params, "description");
674
+ const emoji = readStringParam(params, "emoji");
675
+ const spaceId = parseOptionalInlineId(readFlexibleId(params, "spaceId") ?? readFlexibleId(params, "space"), "spaceId");
676
+ const isPublic = readBooleanParam(params, "isPublic") ?? false;
677
+ const participantIds = [
678
+ ...parseInlineIdListFromParams(params, "participants"),
679
+ ...parseInlineIdListFromParams(params, "participantIds"),
680
+ ...parseInlineIdListFromParams(params, "userIds"),
681
+ ...parseInlineIdListFromParams(params, "userId"),
682
+ ];
683
+ const dedupedParticipants = Array.from(new Set(participantIds.map((id) => id.toString()))).map((id) => BigInt(id));
684
+ const result = await client.invokeRaw(Method.CREATE_CHAT, {
685
+ oneofKind: "createChat",
686
+ createChat: {
687
+ title,
688
+ ...(spaceId != null ? { spaceId } : {}),
689
+ ...(description ? { description } : {}),
690
+ ...(emoji ? { emoji } : {}),
691
+ isPublic,
692
+ participants: isPublic ? [] : dedupedParticipants.map((userId) => ({ userId })),
693
+ },
694
+ });
695
+ if (result.oneofKind !== "createChat") {
696
+ throw new Error(`inline action: expected createChat result, got ${String(result.oneofKind)}`);
697
+ }
698
+ return jsonResult(toJsonSafe({
699
+ ok: true,
700
+ title,
701
+ spaceId: spaceId != null ? String(spaceId) : null,
702
+ isPublic,
703
+ participants: dedupedParticipants.map((id) => String(id)),
704
+ chat: result.createChat.chat ?? null,
705
+ dialog: result.createChat.dialog ?? null,
706
+ }));
707
+ },
708
+ });
709
+ }
710
+ if (normalizedAction === "channel-delete") {
711
+ return await withInlineClient({
712
+ cfg,
713
+ accountId,
714
+ fn: async (client) => {
715
+ const chatId = resolveChatIdFromParams(params);
716
+ const result = await client.invokeRaw(Method.DELETE_CHAT, {
717
+ oneofKind: "deleteChat",
718
+ deleteChat: {
719
+ peerId: buildChatPeer(chatId),
720
+ },
721
+ });
722
+ if (result.oneofKind !== "deleteChat") {
723
+ throw new Error(`inline action: expected deleteChat result, got ${String(result.oneofKind)}`);
724
+ }
725
+ return jsonResult({
726
+ ok: true,
727
+ chatId: String(chatId),
728
+ });
729
+ },
730
+ });
731
+ }
732
+ if (normalizedAction === "channel-move") {
733
+ return await withInlineClient({
734
+ cfg,
735
+ accountId,
736
+ fn: async (client) => {
737
+ const chatId = resolveChatIdFromParams(params);
738
+ const rawSpace = readStringParam(params, "spaceId") ?? readStringParam(params, "toSpaceId");
739
+ const normalizedSpace = rawSpace?.trim().toLowerCase();
740
+ const moveToHome = normalizedSpace === "" ||
741
+ normalizedSpace === "home" ||
742
+ normalizedSpace === "none" ||
743
+ normalizedSpace === "null";
744
+ const parsedSpace = moveToHome
745
+ ? undefined
746
+ : parseOptionalInlineId(readFlexibleId(params, "spaceId") ?? readFlexibleId(params, "toSpaceId"), "spaceId");
747
+ const result = await client.invokeRaw(Method.MOVE_THREAD, {
748
+ oneofKind: "moveThread",
749
+ moveThread: {
750
+ chatId,
751
+ ...(parsedSpace != null ? { spaceId: parsedSpace } : {}),
752
+ },
753
+ });
754
+ if (result.oneofKind !== "moveThread") {
755
+ throw new Error(`inline action: expected moveThread result, got ${String(result.oneofKind)}`);
756
+ }
757
+ return jsonResult(toJsonSafe({
758
+ ok: true,
759
+ chatId: String(chatId),
760
+ spaceId: parsedSpace != null ? String(parsedSpace) : null,
761
+ chat: result.moveThread.chat ?? null,
762
+ }));
763
+ },
764
+ });
765
+ }
766
+ if (normalizedAction === "addParticipant") {
423
767
  return await withInlineClient({
424
768
  cfg,
425
769
  accountId,
@@ -448,13 +792,69 @@ export const inlineMessageActions = {
448
792
  },
449
793
  });
450
794
  }
451
- if (action === "member-info") {
795
+ if (normalizedAction === "removeParticipant") {
796
+ return await withInlineClient({
797
+ cfg,
798
+ accountId,
799
+ fn: async (client) => {
800
+ const chatId = resolveChatIdFromParams(params);
801
+ const userId = parseInlineId(readFlexibleId(params, "userId") ??
802
+ readFlexibleId(params, "participant") ??
803
+ readFlexibleId(params, "memberId") ??
804
+ readStringParam(params, "userId", { required: true }), "userId");
805
+ const result = await client.invokeRaw(Method.REMOVE_CHAT_PARTICIPANT, {
806
+ oneofKind: "removeChatParticipant",
807
+ removeChatParticipant: {
808
+ chatId,
809
+ userId,
810
+ },
811
+ });
812
+ if (result.oneofKind !== "removeChatParticipant") {
813
+ throw new Error(`inline action: expected removeChatParticipant result, got ${String(result.oneofKind)}`);
814
+ }
815
+ return jsonResult({
816
+ ok: true,
817
+ chatId: String(chatId),
818
+ userId: String(userId),
819
+ });
820
+ },
821
+ });
822
+ }
823
+ if (normalizedAction === "leaveGroup") {
824
+ return await withInlineClient({
825
+ cfg,
826
+ accountId,
827
+ fn: async (client) => {
828
+ const chatId = resolveChatIdFromParams(params);
829
+ const me = await client.getMe();
830
+ const userId = me.userId;
831
+ const result = await client.invokeRaw(Method.REMOVE_CHAT_PARTICIPANT, {
832
+ oneofKind: "removeChatParticipant",
833
+ removeChatParticipant: {
834
+ chatId,
835
+ userId,
836
+ },
837
+ });
838
+ if (result.oneofKind !== "removeChatParticipant") {
839
+ throw new Error(`inline action: expected removeChatParticipant result, got ${String(result.oneofKind)}`);
840
+ }
841
+ return jsonResult({
842
+ ok: true,
843
+ chatId: String(chatId),
844
+ userId: String(userId),
845
+ left: true,
846
+ });
847
+ },
848
+ });
849
+ }
850
+ if (normalizedAction === "member-info") {
452
851
  return await withInlineClient({
453
852
  cfg,
454
853
  accountId,
455
854
  fn: async (client) => {
456
855
  const chatId = resolveChatIdFromParams(params);
457
- const userId = parseInlineId(readFlexibleId(params, "userId") ?? readStringParam(params, "userId", { required: true }), "userId");
856
+ const userId = parseInlineId(readFlexibleId(params, "userId") ??
857
+ readStringParam(params, "userId", { required: true }), "userId");
458
858
  const result = await client.invokeRaw(Method.GET_CHAT_PARTICIPANTS, {
459
859
  oneofKind: "getChatParticipants",
460
860
  getChatParticipants: { chatId },
@@ -474,7 +874,180 @@ export const inlineMessageActions = {
474
874
  },
475
875
  });
476
876
  }
877
+ if (normalizedAction === "delete" || normalizedAction === "unsend") {
878
+ return await withInlineClient({
879
+ cfg,
880
+ accountId,
881
+ fn: async (client) => {
882
+ const chatId = resolveChatIdFromParams(params);
883
+ const messageIds = [
884
+ ...parseInlineIdListFromParams(params, "messageIds"),
885
+ ...parseInlineIdListFromParams(params, "messages"),
886
+ ...parseInlineIdListFromParams(params, "ids"),
887
+ ];
888
+ if (messageIds.length === 0) {
889
+ messageIds.push(parseInlineId(readFlexibleId(params, "messageId") ??
890
+ readStringParam(params, "messageId", { required: true }), "messageId"));
891
+ }
892
+ const deduped = Array.from(new Set(messageIds.map((id) => id.toString()))).map((id) => BigInt(id));
893
+ const result = await client.invokeRaw(Method.DELETE_MESSAGES, {
894
+ oneofKind: "deleteMessages",
895
+ deleteMessages: {
896
+ peerId: buildChatPeer(chatId),
897
+ messageIds: deduped,
898
+ },
899
+ });
900
+ if (result.oneofKind !== "deleteMessages") {
901
+ throw new Error(`inline action: expected deleteMessages result, got ${String(result.oneofKind)}`);
902
+ }
903
+ return jsonResult({
904
+ ok: true,
905
+ chatId: String(chatId),
906
+ messageIds: deduped.map((id) => String(id)),
907
+ });
908
+ },
909
+ });
910
+ }
911
+ if (normalizedAction === "pin" || normalizedAction === "unpin") {
912
+ return await withInlineClient({
913
+ cfg,
914
+ accountId,
915
+ fn: async (client) => {
916
+ const chatId = resolveChatIdFromParams(params);
917
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
918
+ readStringParam(params, "messageId", { required: true }), "messageId");
919
+ const unpin = normalizedAction === "unpin" || readBooleanParam(params, "unpin") === true;
920
+ const result = await client.invokeRaw(Method.PIN_MESSAGE, {
921
+ oneofKind: "pinMessage",
922
+ pinMessage: {
923
+ peerId: buildChatPeer(chatId),
924
+ messageId,
925
+ unpin,
926
+ },
927
+ });
928
+ if (result.oneofKind !== "pinMessage") {
929
+ throw new Error(`inline action: expected pinMessage result, got ${String(result.oneofKind)}`);
930
+ }
931
+ return jsonResult({
932
+ ok: true,
933
+ chatId: String(chatId),
934
+ messageId: String(messageId),
935
+ unpin,
936
+ });
937
+ },
938
+ });
939
+ }
940
+ if (normalizedAction === "list-pins") {
941
+ return await withInlineClient({
942
+ cfg,
943
+ accountId,
944
+ fn: async (client) => {
945
+ const chatId = resolveChatIdFromParams(params);
946
+ const result = await client.invokeRaw(Method.GET_CHAT, {
947
+ oneofKind: "getChat",
948
+ getChat: { peerId: buildChatPeer(chatId) },
949
+ });
950
+ if (result.oneofKind !== "getChat") {
951
+ throw new Error(`inline action: expected getChat result, got ${String(result.oneofKind)}`);
952
+ }
953
+ const pinnedMessageIds = (result.getChat.pinnedMessageIds ?? []).map((id) => String(id));
954
+ return jsonResult({
955
+ ok: true,
956
+ chatId: String(chatId),
957
+ pinnedMessageIds,
958
+ });
959
+ },
960
+ });
961
+ }
962
+ if (normalizedAction === "permissions") {
963
+ return await withInlineClient({
964
+ cfg,
965
+ accountId,
966
+ fn: async (client) => {
967
+ const chatId = resolveChatIdFromParams(params);
968
+ const chatResult = await client.invokeRaw(Method.GET_CHAT, {
969
+ oneofKind: "getChat",
970
+ getChat: { peerId: buildChatPeer(chatId) },
971
+ });
972
+ if (chatResult.oneofKind !== "getChat") {
973
+ throw new Error(`inline action: expected getChat result, got ${String(chatResult.oneofKind)}`);
974
+ }
975
+ const spaceId = chatResult.getChat.chat?.spaceId ?? chatResult.getChat.dialog?.spaceId;
976
+ if (spaceId == null) {
977
+ throw new Error("inline action: permissions requires a chat that belongs to a space");
978
+ }
979
+ const userIdRaw = readFlexibleId(params, "userId") ??
980
+ readFlexibleId(params, "memberId") ??
981
+ readStringParam(params, "userId");
982
+ const userId = userIdRaw ? parseInlineId(userIdRaw, "userId") : undefined;
983
+ const roleValue = readStringParam(params, "role")?.trim().toLowerCase();
984
+ const canAccessPublicChats = readBooleanParam(params, "canAccessPublicChats");
985
+ if (userId != null && roleValue) {
986
+ const role = roleValue === "admin"
987
+ ? { role: { oneofKind: "admin", admin: {} } }
988
+ : roleValue === "member"
989
+ ? {
990
+ role: {
991
+ oneofKind: "member",
992
+ member: {
993
+ canAccessPublicChats: canAccessPublicChats ?? true,
994
+ },
995
+ },
996
+ }
997
+ : null;
998
+ if (!role) {
999
+ throw new Error("inline action: role must be \"admin\" or \"member\"");
1000
+ }
1001
+ const updateResult = await client.invokeRaw(Method.UPDATE_MEMBER_ACCESS, {
1002
+ oneofKind: "updateMemberAccess",
1003
+ updateMemberAccess: {
1004
+ spaceId,
1005
+ userId,
1006
+ role,
1007
+ },
1008
+ });
1009
+ if (updateResult.oneofKind !== "updateMemberAccess") {
1010
+ throw new Error(`inline action: expected updateMemberAccess result, got ${String(updateResult.oneofKind)}`);
1011
+ }
1012
+ }
1013
+ const membersResult = await client.invokeRaw(Method.GET_SPACE_MEMBERS, {
1014
+ oneofKind: "getSpaceMembers",
1015
+ getSpaceMembers: {
1016
+ spaceId,
1017
+ },
1018
+ });
1019
+ if (membersResult.oneofKind !== "getSpaceMembers") {
1020
+ throw new Error(`inline action: expected getSpaceMembers result, got ${String(membersResult.oneofKind)}`);
1021
+ }
1022
+ const usersById = buildUserMap(membersResult.getSpaceMembers.users ?? []);
1023
+ const members = (membersResult.getSpaceMembers.members ?? []).map((member) => {
1024
+ const linkedUser = usersById.get(String(member.userId));
1025
+ return {
1026
+ userId: String(member.userId),
1027
+ role: mapSpaceMemberRole(member.role),
1028
+ canAccessPublicChats: member.canAccessPublicChats,
1029
+ date: Number(member.date) * 1000,
1030
+ user: linkedUser
1031
+ ? {
1032
+ id: String(linkedUser.id),
1033
+ name: buildInlineUserDisplayName(linkedUser),
1034
+ username: linkedUser.username ?? null,
1035
+ }
1036
+ : null,
1037
+ };
1038
+ });
1039
+ const filteredMembers = userId != null ? members.filter((member) => member.userId === String(userId)) : members;
1040
+ return jsonResult(toJsonSafe({
1041
+ ok: true,
1042
+ chatId: String(chatId),
1043
+ spaceId: String(spaceId),
1044
+ members: filteredMembers,
1045
+ }));
1046
+ },
1047
+ });
1048
+ }
477
1049
  throw new Error(`Action ${action} is not supported for provider inline.`);
478
1050
  },
479
1051
  };
1052
+ export const inlineSupportedActions = listAllActions();
480
1053
  //# sourceMappingURL=actions.js.map