@manybot/manybot 5.9.2 → 5.10.0

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.
@@ -1877,50 +1877,69 @@ function buildAdminApi(contract, store, chatJid) {
1877
1877
  },
1878
1878
  };
1879
1879
  }
1880
+ /**
1881
+ * Same `.to(target)` shape as `createTargetableAction`, for group-level
1882
+ * ops that take no `memberIds` (setSubject/setDescription/setProfilePic/
1883
+ * revokeInvite) — no participant resolution needed, just a group jid.
1884
+ */
1885
+ function createTargetableGroupAction(action) {
1886
+ const executeCurrent = async () => {
1887
+ requireChat();
1888
+ return action(chatJid);
1889
+ };
1890
+ return {
1891
+ async to(targetJid) {
1892
+ await getGroup(targetJid);
1893
+ return action(targetJid);
1894
+ },
1895
+ then(onfulfilled, onrejected) {
1896
+ return executeCurrent().then(onfulfilled, onrejected);
1897
+ },
1898
+ catch(onrejected) {
1899
+ return executeCurrent().catch(onrejected);
1900
+ },
1901
+ finally(onfinally) {
1902
+ return executeCurrent().finally(onfinally);
1903
+ },
1904
+ };
1905
+ }
1906
+ function isSelf(u) {
1907
+ const n = normalizeJid(u);
1908
+ return (botJid && n === botJid) || (botLid && n === botLid) || false;
1909
+ }
1880
1910
  return {
1881
1911
  /** @param {string|string[]} memberIds — JID (@s.whatsapp.net/@lid), this framework's @c.us form, or a bare phone number */
1882
1912
  add(memberIds) {
1883
1913
  return createTargetableAction((jid, users) => runParticipantsUpdate(jid, users, "add"), memberIds, "newMember");
1884
1914
  },
1885
1915
  /** @param {string|string[]} memberIds — JID (@s.whatsapp.net/@lid), this framework's @c.us form, or a bare phone number */
1886
- async kick(memberIds) {
1887
- requireChat();
1888
- const users = await resolveTargets(chatJid, Array.isArray(memberIds) ? memberIds : [memberIds]);
1889
- if (users.some((u) => {
1890
- const n = normalizeJid(u);
1891
- return (botJid && n === botJid) || (botLid && n === botLid);
1892
- })) {
1893
- throw new Error(t("driver.cannotKickSelf"));
1894
- }
1895
- return runParticipantsUpdate(chatJid, users, "remove");
1916
+ kick(memberIds) {
1917
+ return createTargetableAction(async (jid, users) => {
1918
+ if (users.some(isSelf))
1919
+ throw new Error(t("driver.cannotKickSelf"));
1920
+ return runParticipantsUpdate(jid, users, "remove");
1921
+ }, memberIds);
1896
1922
  },
1897
1923
  /** @param {string|string[]} memberIds — JID (@s.whatsapp.net/@lid), this framework's @c.us form, or a bare phone number */
1898
- async promote(memberIds) {
1899
- requireChat();
1900
- const users = await resolveTargets(chatJid, Array.isArray(memberIds) ? memberIds : [memberIds]);
1901
- return runParticipantsUpdate(chatJid, users, "promote");
1924
+ promote(memberIds) {
1925
+ return createTargetableAction((jid, users) => runParticipantsUpdate(jid, users, "promote"), memberIds);
1902
1926
  },
1903
1927
  /** @param {string|string[]} memberIds — JID (@s.whatsapp.net/@lid), this framework's @c.us form, or a bare phone number */
1904
- async demote(memberIds) {
1905
- requireChat();
1906
- const users = await resolveTargets(chatJid, Array.isArray(memberIds) ? memberIds : [memberIds]);
1907
- return runParticipantsUpdate(chatJid, users, "demote");
1928
+ demote(memberIds) {
1929
+ return createTargetableAction((jid, users) => runParticipantsUpdate(jid, users, "demote"), memberIds);
1908
1930
  },
1909
1931
  /** @param {string} name */
1910
- async setSubject(name) {
1911
- requireChat();
1912
- return contract.groupUpdateSubject(chatJid, name);
1932
+ setSubject(name) {
1933
+ return createTargetableGroupAction((jid) => contract.groupUpdateSubject(jid, name));
1913
1934
  },
1914
1935
  /** @param {string} text */
1915
- async setDescription(text) {
1916
- requireChat();
1917
- return contract.groupUpdateDescription(chatJid, text);
1936
+ setDescription(text) {
1937
+ return createTargetableGroupAction((jid) => contract.groupUpdateDescription(jid, text));
1918
1938
  },
1919
1939
  /** @param {string|Buffer} source */
1920
- async setProfilePic(source) {
1921
- requireChat();
1940
+ setProfilePic(source) {
1922
1941
  const buffer = Buffer.isBuffer(source) ? source : readFileSync(source);
1923
- return contract.updateProfilePicture(chatJid, buffer);
1942
+ return createTargetableGroupAction((jid) => contract.updateProfilePicture(jid, buffer));
1924
1943
  },
1925
1944
  async getInviteLink(groupId) {
1926
1945
  const jid = groupId ?? chatJid;
@@ -1929,9 +1948,8 @@ function buildAdminApi(contract, store, chatJid) {
1929
1948
  const code = await contract.groupInviteCode(jid);
1930
1949
  return `https://chat.whatsapp.com/${code}`;
1931
1950
  },
1932
- async revokeInvite() {
1933
- requireChat();
1934
- return contract.groupRevokeInvite(chatJid);
1951
+ revokeInvite() {
1952
+ return createTargetableGroupAction((jid) => contract.groupRevokeInvite(jid));
1935
1953
  },
1936
1954
  };
1937
1955
  }
@@ -25,6 +25,10 @@ function createMockContract() {
25
25
  deletes: [],
26
26
  blockUpdates: [],
27
27
  groupParticipantUpdates: [],
28
+ subjectUpdates: [],
29
+ descriptionUpdates: [],
30
+ profilePicUpdates: [],
31
+ revokeInvites: [],
28
32
  nameUpdates: [],
29
33
  statusUpdates: [],
30
34
  };
@@ -189,11 +193,20 @@ function createMockContract() {
189
193
  calls.groupParticipantUpdates.push({ jid, users, action });
190
194
  return users.map((u) => ({ status: "200", jid: u }));
191
195
  },
192
- groupUpdateSubject: async () => { },
193
- groupUpdateDescription: async () => { },
196
+ groupUpdateSubject: async (jid, subject) => {
197
+ calls.subjectUpdates.push({ jid, subject });
198
+ },
199
+ groupUpdateDescription: async (jid, description) => {
200
+ calls.descriptionUpdates.push({ jid, description });
201
+ },
194
202
  groupInviteCode: async () => "mock-invite-code-123",
195
- groupRevokeInvite: async () => "mock-new-invite-code-456",
196
- updateProfilePicture: async () => { },
203
+ groupRevokeInvite: async (jid) => {
204
+ calls.revokeInvites.push(jid);
205
+ return "mock-new-invite-code-456";
206
+ },
207
+ updateProfilePicture: async (jid) => {
208
+ calls.profilePicUpdates.push({ jid });
209
+ },
197
210
  updateProfileName: async (name) => {
198
211
  calls.nameUpdates.push(name);
199
212
  },
@@ -301,6 +314,44 @@ describe("kernel/pluginApi — buildSetupApi with Mock WaContract", () => {
301
314
  assert.equal(calls.groupParticipantUpdates[0].action, "add");
302
315
  assert.equal(calls.groupParticipantUpdates[0].jid, "120363000000000@g.us");
303
316
  });
317
+ test("setup admin.kick/promote/demote().to() target the explicit group", async () => {
318
+ const ctx = buildSetupApi(mockContract, store, pluginRegistry, "test_plugin");
319
+ const groupJid = "120363000000000@g.us";
320
+ await ctx.admin.promote("5516777777777@s.whatsapp.net").to(groupJid);
321
+ assert.equal(calls.groupParticipantUpdates.at(-1)?.action, "promote");
322
+ assert.equal(calls.groupParticipantUpdates.at(-1)?.jid, groupJid);
323
+ await ctx.admin.demote("5516777777777@s.whatsapp.net").to(groupJid);
324
+ assert.equal(calls.groupParticipantUpdates.at(-1)?.action, "demote");
325
+ assert.equal(calls.groupParticipantUpdates.at(-1)?.jid, groupJid);
326
+ await ctx.admin.kick("5516777777777@s.whatsapp.net").to(groupJid);
327
+ assert.equal(calls.groupParticipantUpdates.at(-1)?.action, "remove");
328
+ assert.equal(calls.groupParticipantUpdates.at(-1)?.jid, groupJid);
329
+ // self-kick guard still applies when targeting an explicit group
330
+ await assert.rejects(async () => { await ctx.admin.kick("5516999999999@s.whatsapp.net").to(groupJid); });
331
+ });
332
+ test("setup admin.setSubject/setDescription/setProfilePic/revokeInvite().to() target the explicit group", async () => {
333
+ const ctx = buildSetupApi(mockContract, store, pluginRegistry, "test_plugin");
334
+ const groupJid = "120363000000000@g.us";
335
+ await ctx.admin.setSubject("New Subject").to(groupJid);
336
+ assert.deepEqual(calls.subjectUpdates, [{ jid: groupJid, subject: "New Subject" }]);
337
+ await ctx.admin.setDescription("New Description").to(groupJid);
338
+ assert.deepEqual(calls.descriptionUpdates, [{ jid: groupJid, description: "New Description" }]);
339
+ await ctx.admin.setProfilePic(Buffer.from("pic-data")).to(groupJid);
340
+ assert.deepEqual(calls.profilePicUpdates, [{ jid: groupJid }]);
341
+ const invite = await ctx.admin.revokeInvite().to(groupJid);
342
+ assert.match(String(invite), /mock-new-invite-code-456/);
343
+ assert.deepEqual(calls.revokeInvites, [groupJid]);
344
+ });
345
+ test("setup admin.* without .to() throws (no current chat bound)", async () => {
346
+ const ctx = buildSetupApi(mockContract, store, pluginRegistry, "test_plugin");
347
+ await assert.rejects(async () => { await ctx.admin.kick("5516777777777@s.whatsapp.net"); }, /runtime group context/);
348
+ await assert.rejects(async () => { await ctx.admin.promote("5516777777777@s.whatsapp.net"); }, /runtime group context/);
349
+ await assert.rejects(async () => { await ctx.admin.demote("5516777777777@s.whatsapp.net"); }, /runtime group context/);
350
+ await assert.rejects(async () => { await ctx.admin.setSubject("X"); }, /runtime group context/);
351
+ await assert.rejects(async () => { await ctx.admin.setDescription("X"); }, /runtime group context/);
352
+ await assert.rejects(async () => { await ctx.admin.setProfilePic(Buffer.from("x")); }, /runtime group context/);
353
+ await assert.rejects(async () => { await ctx.admin.revokeInvite(); }, /runtime group context/);
354
+ });
304
355
  });
305
356
  describe("kernel/pluginApi — buildApi (Runtime) with Mock WaContract", () => {
306
357
  let store;
@@ -371,7 +422,7 @@ describe("kernel/pluginApi — buildApi (Runtime) with Mock WaContract", () => {
371
422
  await ctx.admin.kick("5516777777777@s.whatsapp.net");
372
423
  assert.equal(calls.groupParticipantUpdates.length, 2);
373
424
  assert.equal(calls.groupParticipantUpdates[1].action, "remove");
374
- await assert.rejects(() => ctx.admin.kick("5516999999999@s.whatsapp.net"));
425
+ await assert.rejects(async () => { await ctx.admin.kick("5516999999999@s.whatsapp.net"); });
375
426
  assert.equal(calls.groupParticipantUpdates.length, 2);
376
427
  const inviteLink = await ctx.admin.getInviteLink();
377
428
  assert.match(inviteLink, /chat\.whatsapp\.com\/mock-invite-code-123/);
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "SyntaxError!",
6
6
  "email": "me@stxerr.dev"
7
7
  },
8
- "version": "5.9.2",
8
+ "version": "5.10.0",
9
9
  "license": "GPL-3.0-only",
10
10
  "private": false,
11
11
  "engines": {