zapry-openclaw-plugin 0.1.0 → 0.1.2

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,4 +1,5 @@
1
1
  import { ZapryApiClient } from "./api-client.js";
2
+ import { stripZapryTargetPrefix } from "./internal.js";
2
3
  import { spawn } from "node:child_process";
3
4
  import { createHash } from "node:crypto";
4
5
  import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
@@ -7,6 +8,11 @@ import { join as joinPath, resolve as resolvePath } from "node:path";
7
8
  const ACTION_ALIASES = {
8
9
  send: "send",
9
10
  sendmessage: "send-message",
11
+ sendmessagecard: "send-message-card",
12
+ sendcard: "send-message-card",
13
+ sendlinkcard: "send-message-card",
14
+ sendlinksharecard: "send-message-card",
15
+ sendlinkshare: "send-message-card",
10
16
  sendphoto: "send-photo",
11
17
  sendvideo: "send-video",
12
18
  senddocument: "send-document",
@@ -32,6 +38,12 @@ const ACTION_ALIASES = {
32
38
  getchatmemberscount: "get-chat-member-count",
33
39
  getchatadministrators: "get-chat-administrators",
34
40
  getchatadmins: "get-chat-administrators",
41
+ creategroupchat: "create-group-chat",
42
+ createchatgroup: "create-group-chat",
43
+ newgroupchat: "create-group-chat",
44
+ dismissgroupchat: "dismiss-group-chat",
45
+ dissolvegroupchat: "dismiss-group-chat",
46
+ deletegroupchat: "dismiss-group-chat",
35
47
  mutechatmember: "mute-chat-member",
36
48
  kickchatmember: "kick-chat-member",
37
49
  invitechatmember: "invite-chat-member",
@@ -66,6 +78,9 @@ const ACTION_ALIASES = {
66
78
  getmyclubs: "get-my-clubs",
67
79
  createclub: "create-club",
68
80
  updateclub: "update-club",
81
+ muteclubmember: "mute-club-member",
82
+ unmuteclubmember: "mute-club-member",
83
+ kickclubmember: "kick-club-member",
69
84
  getchathistory: "get-chat-history",
70
85
  sendchataction: "send-chat-action",
71
86
  };
@@ -137,6 +152,23 @@ export async function handleZapryAction(ctx) {
137
152
  messageThreadId: normalized.message_thread_id,
138
153
  replyMarkup: normalized.reply_markup,
139
154
  }));
155
+ case "send-message-card":
156
+ return wrap(client.sendMessageCard({
157
+ chatId: normalized.chat_id,
158
+ url: normalized.url,
159
+ title: normalized.title,
160
+ content: normalized.content,
161
+ text: normalized.text,
162
+ iconUrl: normalized.icon_url,
163
+ imageUrl: normalized.image_url,
164
+ source: normalized.source,
165
+ openMode: normalized.open_mode,
166
+ fallbackText: normalized.fallback_text,
167
+ extra: normalized.extra,
168
+ replyToMessageId: normalized.reply_to_message_id,
169
+ messageThreadId: normalized.message_thread_id,
170
+ replyMarkup: normalized.reply_markup,
171
+ }));
140
172
  case "send-photo": {
141
173
  const photoSource = normalized.photo || normalized.media;
142
174
  if (!photoSource && isNonEmptyString(normalized.prompt)) {
@@ -234,6 +266,16 @@ export async function handleZapryAction(ctx) {
234
266
  return wrap(client.getChatMemberCount(normalized.chat_id));
235
267
  case "get-chat-administrators":
236
268
  return wrap(client.getChatAdministrators(normalized.chat_id));
269
+ case "create-group-chat":
270
+ return wrap(client.createGroupChat({
271
+ title: normalized.title,
272
+ description: normalized.description,
273
+ avatar: normalized.avatar,
274
+ userIds: normalized.user_ids,
275
+ botIds: normalized.bot_ids,
276
+ }));
277
+ case "dismiss-group-chat":
278
+ return wrap(client.dismissGroupChat(normalized.chat_id, normalized.reason));
237
279
  case "mute-chat-member":
238
280
  return wrap(client.muteChatMember(normalized.chat_id, normalized.user_id, normalized.mute));
239
281
  case "kick-chat-member":
@@ -290,6 +332,16 @@ export async function handleZapryAction(ctx) {
290
332
  return wrap(client.createClub(normalized.name, normalized.desc, normalized.avatar));
291
333
  case "update-club":
292
334
  return wrap(client.updateClub(normalized.club_id, normalized.name, normalized.desc, normalized.avatar));
335
+ case "create-club-invite":
336
+ return wrap(client.createClubInvite(normalized.club_id));
337
+ case "apply-club":
338
+ return wrap(client.applyClub(normalized.club_id, normalized.message, normalized.share_code));
339
+ case "approve-club-apply":
340
+ return wrap(client.approveClubApply(normalized.club_id, normalized.user_id, normalized.approve === true));
341
+ case "mute-club-member":
342
+ return wrap(client.muteClubMember(normalized.club_id, normalized.user_id, normalized.mute, normalized.duration_seconds));
343
+ case "kick-club-member":
344
+ return wrap(client.kickClubMember(normalized.club_id, normalized.user_id));
293
345
  // ── Bot Self-Management ──
294
346
  case "get-me":
295
347
  return wrap(client.getMe());
@@ -953,6 +1005,7 @@ function validateRequiredParams(action, params) {
953
1005
  const requiredByAction = {
954
1006
  // Messaging
955
1007
  "send-message": ["chat_id", "text"],
1008
+ "send-message-card": ["chat_id", "url", "title"],
956
1009
  "send-photo": ["chat_id"],
957
1010
  "send-video": ["chat_id", "video"],
958
1011
  "send-document": ["chat_id", "document"],
@@ -973,6 +1026,8 @@ function validateRequiredParams(action, params) {
973
1026
  "get-chat-members": ["chat_id"],
974
1027
  "get-chat-member-count": ["chat_id"],
975
1028
  "get-chat-administrators": ["chat_id"],
1029
+ "create-group-chat": ["title"],
1030
+ "dismiss-group-chat": ["chat_id"],
976
1031
  "mute-chat-member": ["chat_id", "user_id", "mute"],
977
1032
  "kick-chat-member": ["chat_id", "user_id"],
978
1033
  "invite-chat-member": ["chat_id", "user_id"],
@@ -999,6 +1054,11 @@ function validateRequiredParams(action, params) {
999
1054
  // Club
1000
1055
  "create-club": ["name"],
1001
1056
  "update-club": ["club_id"],
1057
+ "create-club-invite": ["club_id"],
1058
+ "apply-club": ["club_id"],
1059
+ "approve-club-apply": ["club_id", "user_id", "approve"],
1060
+ "mute-club-member": ["club_id", "user_id", "mute"],
1061
+ "kick-club-member": ["club_id", "user_id"],
1002
1062
  };
1003
1063
  const required = requiredByAction[action];
1004
1064
  if (!required || required.length === 0) {
@@ -1014,6 +1074,15 @@ function validateRequiredParams(action, params) {
1014
1074
  return skillsErr;
1015
1075
  }
1016
1076
  }
1077
+ if (action === "mute-club-member" && params.mute === true) {
1078
+ const duration = Number(params.duration_seconds);
1079
+ if (!Number.isFinite(duration) || duration <= 0) {
1080
+ return "duration_seconds must be greater than 0 when mute=true";
1081
+ }
1082
+ if (duration > 2_592_000) {
1083
+ return "duration_seconds exceeds maximum 2592000";
1084
+ }
1085
+ }
1017
1086
  return null;
1018
1087
  }
1019
1088
  function validateMediaSource(value, fieldName) {
@@ -1123,6 +1192,7 @@ function normalizeActionParams(action, raw) {
1123
1192
  const pageSize = pickFirst(params, ["page_size", "pageSize"]);
1124
1193
  const dynamicId = pickFirst(params, ["dynamic_id", "dynamicId"]);
1125
1194
  const clubId = pickFirst(params, ["club_id", "clubId"]);
1195
+ const shareCode = pickFirst(params, ["share_code", "shareCode"]);
1126
1196
  const soulMd = pickFirst(params, ["soulMd", "soul_md"]);
1127
1197
  const agentKey = pickFirst(params, ["agentKey", "agent_key"]);
1128
1198
  const skills = pickFirst(params, ["skills"]);
@@ -1151,6 +1221,10 @@ function normalizeActionParams(action, raw) {
1151
1221
  const audioFormat = pickFirst(params, ["audio_format", "audioFormat", "format"]);
1152
1222
  const durationSeconds = pickFirst(params, ["duration_seconds", "durationSeconds", "duration"]);
1153
1223
  const fallbackText = pickFirst(params, ["fallback_text", "fallbackText", "error_fallback_text"]);
1224
+ const iconUrl = pickFirst(params, ["icon_url", "iconUrl", "icon"]);
1225
+ const imageUrl = pickFirst(params, ["image_url", "imageUrl", "cover_url", "coverUrl"]);
1226
+ const openMode = pickFirst(params, ["open_mode", "openMode"]);
1227
+ const extra = pickFirst(params, ["extra"]);
1154
1228
  if (chatId !== undefined)
1155
1229
  params.chat_id = normalizeChatId(chatId);
1156
1230
  if (userId !== undefined)
@@ -1185,6 +1259,8 @@ function normalizeActionParams(action, raw) {
1185
1259
  params.dynamic_id = toNumberIfPossible(dynamicId);
1186
1260
  if (clubId !== undefined)
1187
1261
  params.club_id = toNumberIfPossible(clubId);
1262
+ if (shareCode !== undefined)
1263
+ params.share_code = String(shareCode).trim();
1188
1264
  if (soulMd !== undefined)
1189
1265
  params.soulMd = String(soulMd);
1190
1266
  if (agentKey !== undefined)
@@ -1219,6 +1295,23 @@ function normalizeActionParams(action, raw) {
1219
1295
  const avatar = pickFirst(params, ["avatar"]);
1220
1296
  if (avatar !== undefined)
1221
1297
  params.avatar = String(avatar).trim();
1298
+ const reason = pickFirst(params, ["reason"]);
1299
+ if (reason !== undefined)
1300
+ params.reason = String(reason).trim();
1301
+ const userIds = pickFirst(params, ["user_ids", "userIds", "members", "member_ids", "memberIds"]);
1302
+ if (userIds !== undefined) {
1303
+ const normalizedUserIds = normalizeIdArray(userIds);
1304
+ if (normalizedUserIds) {
1305
+ params.user_ids = normalizedUserIds;
1306
+ }
1307
+ }
1308
+ const botIds = pickFirst(params, ["bot_ids", "botIds", "bots", "bot_ids"]);
1309
+ if (botIds !== undefined) {
1310
+ const normalizedBotIds = normalizeIdArray(botIds);
1311
+ if (normalizedBotIds) {
1312
+ params.bot_ids = normalizedBotIds;
1313
+ }
1314
+ }
1222
1315
  if (skills !== undefined) {
1223
1316
  if (Array.isArray(skills)) {
1224
1317
  params.skills = skills;
@@ -1253,6 +1346,25 @@ function normalizeActionParams(action, raw) {
1253
1346
  params.duration_seconds = toNumberIfPossible(durationSeconds);
1254
1347
  if (fallbackText !== undefined)
1255
1348
  params.fallback_text = String(fallbackText).trim();
1349
+ if (iconUrl !== undefined)
1350
+ params.icon_url = String(iconUrl).trim();
1351
+ if (imageUrl !== undefined)
1352
+ params.image_url = String(imageUrl).trim();
1353
+ if (openMode !== undefined)
1354
+ params.open_mode = String(openMode).trim();
1355
+ if (extra !== undefined) {
1356
+ if (typeof extra === "string") {
1357
+ try {
1358
+ params.extra = JSON.parse(extra);
1359
+ }
1360
+ catch {
1361
+ params.extra = extra;
1362
+ }
1363
+ }
1364
+ else {
1365
+ params.extra = extra;
1366
+ }
1367
+ }
1256
1368
  const offset = pickFirst(params, ["offset"]);
1257
1369
  if (offset !== undefined)
1258
1370
  params.offset = toNumberIfPossible(offset);
@@ -1310,9 +1422,7 @@ function pickFirst(obj, keys) {
1310
1422
  return undefined;
1311
1423
  }
1312
1424
  function normalizeChatId(value) {
1313
- return String(value ?? "")
1314
- .trim()
1315
- .replace(/^chat:/i, "");
1425
+ return stripZapryTargetPrefix(String(value ?? "").trim());
1316
1426
  }
1317
1427
  function toNumberIfPossible(value) {
1318
1428
  if (typeof value === "number") {
@@ -1382,6 +1492,30 @@ function normalizeStringArray(value) {
1382
1492
  }
1383
1493
  return null;
1384
1494
  }
1495
+ function normalizeIdArray(value) {
1496
+ if (Array.isArray(value)) {
1497
+ return value.map((item) => String(item).trim()).filter(Boolean);
1498
+ }
1499
+ if (typeof value === "string") {
1500
+ const trimmed = value.trim();
1501
+ if (!trimmed) {
1502
+ return [];
1503
+ }
1504
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
1505
+ try {
1506
+ const parsed = JSON.parse(trimmed);
1507
+ if (Array.isArray(parsed)) {
1508
+ return parsed.map((item) => String(item).trim()).filter(Boolean);
1509
+ }
1510
+ }
1511
+ catch {
1512
+ // fall through to comma-separated handling
1513
+ }
1514
+ }
1515
+ return trimmed.split(",").map((item) => item.trim()).filter(Boolean);
1516
+ }
1517
+ return null;
1518
+ }
1385
1519
  function toMediaSourceString(value) {
1386
1520
  if (typeof value === "string") {
1387
1521
  const trimmed = value.trim();
@@ -1573,14 +1707,7 @@ function resolveGroupRecord(payload, chatId) {
1573
1707
  return null;
1574
1708
  }
1575
1709
  function normalizeResultChatId(value) {
1576
- const normalized = String(value ?? "").trim();
1577
- if (!normalized) {
1578
- return "";
1579
- }
1580
- if (normalized.startsWith("g_")) {
1581
- return normalized;
1582
- }
1583
- return normalized.startsWith("chat:") ? normalized.slice(5) : normalized;
1710
+ return stripZapryTargetPrefix(String(value ?? "").trim());
1584
1711
  }
1585
1712
  function asObjectRecord(value) {
1586
1713
  if (!value || typeof value !== "object") {