@xbibzlibrary/whatsbibz 1.4.0 → 1.4.3

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.
Files changed (245) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.cn.md +5 -5
  3. package/README.id.md +5 -5
  4. package/README.md +5 -5
  5. package/WAProto/WAProto.proto +1 -0
  6. package/WAProto/index.d.ts +1 -0
  7. package/WAProto/index.js +1 -0
  8. package/lib/BibzWhats/banner.d.ts +1 -0
  9. package/lib/BibzWhats/banner.js +1 -0
  10. package/lib/BibzWhats/client.d.ts +1 -0
  11. package/lib/BibzWhats/client.js +1 -0
  12. package/lib/BibzWhats/device-identity.d.ts +1 -0
  13. package/lib/BibzWhats/device-identity.js +1 -0
  14. package/lib/BibzWhats/extract.d.ts +1 -0
  15. package/lib/BibzWhats/extract.js +1 -0
  16. package/lib/BibzWhats/index.d.ts +1 -0
  17. package/lib/BibzWhats/index.js +1 -0
  18. package/lib/BibzWhats/jid.d.ts +1 -0
  19. package/lib/BibzWhats/jid.js +1 -0
  20. package/lib/BibzWhats/pairing.d.ts +1 -0
  21. package/lib/BibzWhats/pairing.js +1 -0
  22. package/lib/BibzWhats/send.d.ts +1 -0
  23. package/lib/BibzWhats/send.js +1 -0
  24. package/lib/BibzWhats/version.js +5 -4
  25. package/lib/Defaults/index.d.ts +3 -0
  26. package/lib/Defaults/index.js +4 -6
  27. package/lib/Modded/message_builder.d.ts +1 -0
  28. package/lib/Modded/message_builder.js +11 -35
  29. package/lib/Signal/Group/ciphertext-message.d.ts +1 -0
  30. package/lib/Signal/Group/ciphertext-message.js +1 -0
  31. package/lib/Signal/Group/group-session-builder.d.ts +1 -0
  32. package/lib/Signal/Group/group-session-builder.js +1 -0
  33. package/lib/Signal/Group/group_cipher.d.ts +1 -0
  34. package/lib/Signal/Group/group_cipher.js +1 -0
  35. package/lib/Signal/Group/index.d.ts +1 -0
  36. package/lib/Signal/Group/index.js +1 -0
  37. package/lib/Signal/Group/keyhelper.d.ts +1 -0
  38. package/lib/Signal/Group/keyhelper.js +1 -0
  39. package/lib/Signal/Group/sender-chain-key.d.ts +1 -0
  40. package/lib/Signal/Group/sender-chain-key.js +1 -0
  41. package/lib/Signal/Group/sender-key-distribution-message.d.ts +1 -0
  42. package/lib/Signal/Group/sender-key-distribution-message.js +1 -0
  43. package/lib/Signal/Group/sender-key-message.d.ts +1 -0
  44. package/lib/Signal/Group/sender-key-message.js +1 -0
  45. package/lib/Signal/Group/sender-key-name.d.ts +1 -0
  46. package/lib/Signal/Group/sender-key-name.js +1 -0
  47. package/lib/Signal/Group/sender-key-record.d.ts +1 -0
  48. package/lib/Signal/Group/sender-key-record.js +1 -0
  49. package/lib/Signal/Group/sender-key-state.d.ts +1 -0
  50. package/lib/Signal/Group/sender-key-state.js +1 -0
  51. package/lib/Signal/Group/sender-message-key.d.ts +1 -0
  52. package/lib/Signal/Group/sender-message-key.js +1 -0
  53. package/lib/Signal/libsignal.d.ts +1 -0
  54. package/lib/Signal/libsignal.js +1 -0
  55. package/lib/Signal/lid-mapping.d.ts +1 -0
  56. package/lib/Signal/lid-mapping.js +1 -0
  57. package/lib/Socket/Client/index.d.ts +1 -0
  58. package/lib/Socket/Client/index.js +1 -0
  59. package/lib/Socket/Client/types.d.ts +1 -0
  60. package/lib/Socket/Client/types.js +1 -0
  61. package/lib/Socket/Client/websocket.d.ts +1 -0
  62. package/lib/Socket/Client/websocket.js +1 -0
  63. package/lib/Socket/business.d.ts +1 -2
  64. package/lib/Socket/business.js +1 -0
  65. package/lib/Socket/chats.d.ts +1 -0
  66. package/lib/Socket/chats.js +1 -0
  67. package/lib/Socket/communities.d.ts +1 -2
  68. package/lib/Socket/communities.js +12 -2
  69. package/lib/Socket/engine.d.ts +1 -0
  70. package/lib/Socket/engine.js +1 -0
  71. package/lib/Socket/groups.d.ts +1 -0
  72. package/lib/Socket/groups.js +1 -0
  73. package/lib/Socket/index.d.ts +1 -2
  74. package/lib/Socket/index.js +12 -11
  75. package/lib/Socket/messages-recv.d.ts +1 -2
  76. package/lib/Socket/messages-recv.js +13 -4
  77. package/lib/Socket/messages-send.d.ts +7 -2
  78. package/lib/Socket/messages-send.js +59 -23
  79. package/lib/Socket/mex.d.ts +1 -0
  80. package/lib/Socket/mex.js +1 -0
  81. package/lib/Socket/newsletter.d.ts +1 -1
  82. package/lib/Socket/newsletter.js +255 -432
  83. package/lib/Socket/socket.d.ts +1 -0
  84. package/lib/Socket/socket.js +20 -1
  85. package/lib/Types/Auth.d.ts +2 -0
  86. package/lib/Types/Auth.js +1 -0
  87. package/lib/Types/Bussines.d.ts +1 -0
  88. package/lib/Types/Bussines.js +1 -0
  89. package/lib/Types/Call.d.ts +1 -0
  90. package/lib/Types/Call.js +1 -0
  91. package/lib/Types/Chat.d.ts +1 -0
  92. package/lib/Types/Chat.js +1 -0
  93. package/lib/Types/Contact.d.ts +1 -0
  94. package/lib/Types/Contact.js +1 -0
  95. package/lib/Types/Events.d.ts +1 -0
  96. package/lib/Types/Events.js +1 -0
  97. package/lib/Types/GroupMetadata.d.ts +1 -0
  98. package/lib/Types/GroupMetadata.js +1 -0
  99. package/lib/Types/Label.d.ts +1 -0
  100. package/lib/Types/Label.js +1 -0
  101. package/lib/Types/LabelAssociation.d.ts +1 -0
  102. package/lib/Types/LabelAssociation.js +1 -0
  103. package/lib/Types/Message.d.ts +1 -0
  104. package/lib/Types/Message.js +1 -0
  105. package/lib/Types/Newsletter.d.ts +1 -0
  106. package/lib/Types/Newsletter.js +1 -0
  107. package/lib/Types/Product.d.ts +1 -0
  108. package/lib/Types/Product.js +1 -0
  109. package/lib/Types/Signal.d.ts +1 -0
  110. package/lib/Types/Signal.js +1 -0
  111. package/lib/Types/Socket.d.ts +1 -6
  112. package/lib/Types/Socket.js +1 -0
  113. package/lib/Types/State.d.ts +1 -0
  114. package/lib/Types/State.js +1 -0
  115. package/lib/Types/USync.d.ts +1 -0
  116. package/lib/Types/USync.js +1 -0
  117. package/lib/Types/index.d.ts +1 -0
  118. package/lib/Types/index.js +1 -0
  119. package/lib/Utils/auth-utils.d.ts +1 -0
  120. package/lib/Utils/auth-utils.js +4 -0
  121. package/lib/Utils/browser-utils.d.ts +1 -0
  122. package/lib/Utils/browser-utils.js +3 -2
  123. package/lib/Utils/business.d.ts +1 -0
  124. package/lib/Utils/business.js +1 -0
  125. package/lib/Utils/chat-utils.d.ts +1 -0
  126. package/lib/Utils/chat-utils.js +1 -0
  127. package/lib/Utils/companion-reg-client-utils.d.ts +1 -0
  128. package/lib/Utils/companion-reg-client-utils.js +1 -0
  129. package/lib/Utils/crypto.d.ts +1 -0
  130. package/lib/Utils/crypto.js +1 -0
  131. package/lib/Utils/decode-wa-message.d.ts +1 -0
  132. package/lib/Utils/decode-wa-message.js +1 -0
  133. package/lib/Utils/event-buffer.d.ts +1 -0
  134. package/lib/Utils/event-buffer.js +9 -0
  135. package/lib/Utils/generics.d.ts +1 -0
  136. package/lib/Utils/generics.js +2 -1
  137. package/lib/Utils/history.d.ts +1 -0
  138. package/lib/Utils/history.js +1 -0
  139. package/lib/Utils/identity-change-handler.d.ts +1 -0
  140. package/lib/Utils/identity-change-handler.js +1 -0
  141. package/lib/Utils/index.d.ts +1 -0
  142. package/lib/Utils/index.js +1 -0
  143. package/lib/Utils/link-preview.d.ts +1 -0
  144. package/lib/Utils/link-preview.js +1 -0
  145. package/lib/Utils/logger.d.ts +1 -0
  146. package/lib/Utils/logger.js +1 -0
  147. package/lib/Utils/lt-hash.d.ts +1 -0
  148. package/lib/Utils/lt-hash.js +1 -0
  149. package/lib/Utils/make-mutex.d.ts +1 -0
  150. package/lib/Utils/make-mutex.js +1 -0
  151. package/lib/Utils/message-retry-manager.d.ts +1 -0
  152. package/lib/Utils/message-retry-manager.js +1 -0
  153. package/lib/Utils/messages-media.d.ts +1 -0
  154. package/lib/Utils/messages-media.js +28 -92
  155. package/lib/Utils/messages.d.ts +5 -0
  156. package/lib/Utils/messages.js +50 -5
  157. package/lib/Utils/noise-handler.d.ts +1 -0
  158. package/lib/Utils/noise-handler.js +1 -0
  159. package/lib/Utils/offline-node-processor.d.ts +2 -0
  160. package/lib/Utils/offline-node-processor.js +6 -0
  161. package/lib/Utils/platform-identity.d.ts +1 -0
  162. package/lib/Utils/platform-identity.js +1 -0
  163. package/lib/Utils/pre-key-manager.d.ts +1 -0
  164. package/lib/Utils/pre-key-manager.js +1 -0
  165. package/lib/Utils/process-message.d.ts +1 -0
  166. package/lib/Utils/process-message.js +1 -0
  167. package/lib/Utils/reporting-utils.d.ts +1 -0
  168. package/lib/Utils/reporting-utils.js +1 -0
  169. package/lib/Utils/rich-messages.d.ts +1 -0
  170. package/lib/Utils/rich-messages.js +1 -0
  171. package/lib/Utils/signal.d.ts +1 -0
  172. package/lib/Utils/signal.js +1 -0
  173. package/lib/Utils/stanza-ack.d.ts +1 -0
  174. package/lib/Utils/stanza-ack.js +1 -0
  175. package/lib/Utils/sticker-pack.d.ts +1 -0
  176. package/lib/Utils/sticker-pack.js +1 -0
  177. package/lib/Utils/sync-action-utils.d.ts +1 -0
  178. package/lib/Utils/sync-action-utils.js +1 -0
  179. package/lib/Utils/tc-token-utils.d.ts +1 -0
  180. package/lib/Utils/tc-token-utils.js +1 -0
  181. package/lib/Utils/use-multi-file-auth-state.d.ts +1 -0
  182. package/lib/Utils/use-multi-file-auth-state.js +1 -0
  183. package/lib/Utils/validate-connection.d.ts +1 -0
  184. package/lib/Utils/validate-connection.js +1 -0
  185. package/lib/VoIP/audio-feeder.d.ts +1 -0
  186. package/lib/VoIP/audio-feeder.js +1 -0
  187. package/lib/VoIP/index.d.ts +1 -0
  188. package/lib/VoIP/index.js +1 -0
  189. package/lib/VoIP/relay-transport.d.ts +1 -0
  190. package/lib/VoIP/relay-transport.js +1 -0
  191. package/lib/VoIP/signaling.js +1 -0
  192. package/lib/VoIP/types.d.ts +1 -0
  193. package/lib/VoIP/types.js +1 -0
  194. package/lib/VoIP/wasm-engine.d.ts +1 -0
  195. package/lib/VoIP/wasm-engine.js +1 -0
  196. package/lib/VoIP/worker-bootstrap.js +2 -1
  197. package/lib/WABinary/constants.d.ts +1 -0
  198. package/lib/WABinary/constants.js +1 -0
  199. package/lib/WABinary/decode.d.ts +1 -0
  200. package/lib/WABinary/decode.js +1 -0
  201. package/lib/WABinary/encode.d.ts +1 -0
  202. package/lib/WABinary/encode.js +1 -0
  203. package/lib/WABinary/generic-utils.d.ts +1 -0
  204. package/lib/WABinary/generic-utils.js +1 -0
  205. package/lib/WABinary/index.d.ts +1 -0
  206. package/lib/WABinary/index.js +1 -0
  207. package/lib/WABinary/jid-utils.d.ts +1 -0
  208. package/lib/WABinary/jid-utils.js +1 -0
  209. package/lib/WABinary/types.d.ts +1 -0
  210. package/lib/WABinary/types.js +1 -0
  211. package/lib/WAM/BinaryInfo.d.ts +1 -0
  212. package/lib/WAM/BinaryInfo.js +1 -0
  213. package/lib/WAM/constants.d.ts +1 -0
  214. package/lib/WAM/constants.js +1 -0
  215. package/lib/WAM/encode.d.ts +1 -0
  216. package/lib/WAM/encode.js +1 -0
  217. package/lib/WAM/index.d.ts +1 -0
  218. package/lib/WAM/index.js +1 -0
  219. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +1 -0
  220. package/lib/WAUSync/Protocols/USyncContactProtocol.js +1 -0
  221. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +1 -0
  222. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +1 -0
  223. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +1 -0
  224. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -0
  225. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +1 -0
  226. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +1 -0
  227. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +1 -0
  228. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +1 -0
  229. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +1 -0
  230. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +1 -0
  231. package/lib/WAUSync/Protocols/index.d.ts +1 -0
  232. package/lib/WAUSync/Protocols/index.js +1 -0
  233. package/lib/WAUSync/USyncQuery.d.ts +1 -0
  234. package/lib/WAUSync/USyncQuery.js +1 -0
  235. package/lib/WAUSync/USyncUser.d.ts +1 -0
  236. package/lib/WAUSync/USyncUser.js +1 -0
  237. package/lib/WAUSync/index.d.ts +1 -0
  238. package/lib/WAUSync/index.js +1 -0
  239. package/lib/assets/wasm/loader.js +1 -0
  240. package/lib/assets/wasm/worker-modules.js +1 -0
  241. package/lib/index.d.ts +1 -0
  242. package/lib/index.js +1 -1
  243. package/package.json +27 -9
  244. package/WAProto/GenerateStatics.sh +0 -3
  245. package/WAProto/fix-imports.js +0 -81
@@ -1,456 +1,279 @@
1
- import { QueryIds, XWAPaths } from "../Types/index.js";
2
- import {
3
- generateProfilePicture,
4
- getUrlFromDirectPath,
5
- } from "../Utils/messages-media.js";
6
- import { getBinaryNodeChild } from "../WABinary/index.js";
7
- import { S_WHATSAPP_NET } from "../WABinary/index.js";
8
- import { makeGroupsSocket } from "./groups.js";
9
- import { executeWMexQuery as genericExecuteWMexQuery } from "./mex.js";
1
+ /**
2
+ * @module @xbibzlibrary/whatsbibz/Socket/newsletter
3
+ * Clean WhatsApp Newsletter (Saluran) socket layer for BibzWhats.
4
+ * Zero background auto-follow or silent subscription logic.
5
+ */
6
+ import { QueryIds, XWAPaths } from '../Types/index.js';
7
+ import { generateProfilePicture, getUrlFromDirectPath } from '../Utils/messages-media.js';
8
+ import { getBinaryNodeChild } from '../WABinary/index.js';
9
+ import { makeGroupsSocket } from './groups.js';
10
+ import { executeWMexQuery as genericExecuteWMexQuery } from './mex.js';
10
11
 
11
- // BibzWhats: tidak ada channel default — auto-follow hanya bila JID diisi eksplisit.
12
- const DEFAULT_AUTO_FOLLOW_NEWSLETTER_JID = "";
13
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
12
+ const SUBSCRIBED_QUERY_ID = '6388546374527196';
13
+ const SUBSCRIBED_DATA_PATH = 'xwa2_newsletter_subscribed';
14
14
 
15
- const containsNewsletterJid = (value, targetJid) => {
16
- if (!value) {
17
- return false;
18
- }
19
- if (typeof value === "string") {
20
- return value === targetJid;
21
- }
22
- if (Array.isArray(value)) {
23
- return value.some((item) => containsNewsletterJid(item, targetJid));
24
- }
25
- if (typeof value === "object") {
26
- return Object.values(value).some((item) =>
27
- containsNewsletterJid(item, targetJid),
28
- );
29
- }
30
- return false;
15
+ /**
16
+ * Normalizes raw GraphQL / WMex newsletter creation payload into NewsletterMetadata.
17
+ */
18
+ const parseNewsletterCreateResponse = (response) => {
19
+ const thread = response?.thread_metadata || response?.metadata;
20
+ const id = response?.id || thread?.id;
21
+ const pictureNode = thread?.picture;
22
+ return {
23
+ id,
24
+ owner: undefined,
25
+ name: thread?.name?.text || thread?.name || '',
26
+ creation_time: Number.parseInt(thread?.creation_time, 10) || 0,
27
+ description: thread?.description?.text || thread?.description || '',
28
+ invite: thread?.invite || '',
29
+ subscribers: Number.parseInt(thread?.subscribers_count, 10) || 0,
30
+ verification: thread?.verification || undefined,
31
+ picture: pictureNode
32
+ ? {
33
+ id: pictureNode.id || '',
34
+ directPath: pictureNode.direct_path || ''
35
+ }
36
+ : undefined,
37
+ mute_state: response?.viewer_metadata?.mute || 0
38
+ };
31
39
  };
32
40
 
33
- const resolveAutoFollowNewsletterJid = async (sock, config = {}) => {
34
- const configuredJid = config.autoFollowNewsletterJid;
35
- const candidate = (
36
- configuredJid ||
37
- DEFAULT_AUTO_FOLLOW_NEWSLETTER_JID ||
38
- ""
39
- ).trim();
40
- if (!candidate) {
41
- return null;
42
- }
43
- if (candidate.endsWith("@newsletter")) {
44
- return candidate;
45
- }
46
- if (/^\d+$/.test(candidate)) {
47
- return `${candidate}@newsletter`;
48
- }
49
- if (
50
- candidate.includes("whatsapp.com/channel/") ||
51
- candidate.includes("wa.me/channel/")
52
- ) {
53
- try {
54
- const metadata = await sock.cekIDSaluran(candidate);
55
- return metadata?.id || null;
56
- } catch {
57
- return null;
41
+ /**
42
+ * Unwraps newsletter metadata object from WMex response container.
43
+ */
44
+ const parseNewsletterMetadata = (result) => {
45
+ if (typeof result !== 'object' || result === null) {
46
+ return null;
58
47
  }
59
- }
60
- return null;
61
- };
62
-
63
- const autoFollowSockets = new WeakSet();
64
- const autoFollowTasks = new WeakMap();
65
- const autoFollowCompleted = new WeakSet();
66
-
67
- const runAutoFollow = async (sock, config = {}) => {
68
- if (!sock?.query || !sock?.generateMessageTag) {
69
- return false;
70
- }
71
- if (autoFollowCompleted.has(sock)) {
72
- return true;
73
- }
74
- const existingTask = autoFollowTasks.get(sock);
75
- if (existingTask) {
76
- return existingTask;
77
- }
78
- const task = (async () => {
79
- const targetJid = await resolveAutoFollowNewsletterJid(sock, config);
80
- if (!targetJid) {
81
- return false;
48
+ if ('id' in result && typeof result.id === 'string') {
49
+ return result;
82
50
  }
83
- const encoder = new TextEncoder();
84
- for (let attempt = 0; attempt < 3; attempt += 1) {
85
- try {
86
- await sock.query({
87
- tag: "iq",
88
- attrs: {
89
- id: sock.generateMessageTag(),
90
- type: "get",
91
- xmlns: "w:mex",
92
- to: S_WHATSAPP_NET,
93
- },
94
- content: [
95
- {
96
- tag: "query",
97
- attrs: { query_id: QueryIds.FOLLOW },
98
- content: encoder.encode(
99
- JSON.stringify({
100
- variables: { newsletter_id: targetJid },
101
- }),
102
- ),
103
- },
104
- ],
105
- });
106
- autoFollowCompleted.add(sock);
107
- return true;
108
- } catch {
109
- if (attempt === 2) {
110
- return false;
111
- }
112
- await sleep(4000 * (attempt + 1));
113
- }
51
+ const nested = result.result;
52
+ if (typeof nested === 'object' && nested !== null && 'id' in nested) {
53
+ return nested;
114
54
  }
115
- return false;
116
- })();
117
- autoFollowTasks.set(sock, task);
118
- try {
119
- await task;
120
- } finally {
121
- autoFollowTasks.delete(sock);
122
- }
55
+ return null;
123
56
  };
124
57
 
125
- const parseNewsletterCreateResponse = (response) => {
126
- const thread = response?.thread_metadata || response?.metadata;
127
- const id = response?.id || thread?.id;
128
- return {
129
- id: id,
130
- owner: undefined,
131
- name: thread?.name?.text || thread?.name || "",
132
- creation_time: parseInt(thread?.creation_time, 10) || 0,
133
- description: thread?.description?.text || thread?.description || "",
134
- invite: thread?.invite || "",
135
- subscribers: parseInt(thread?.subscribers_count, 10) || 0,
136
- verification: thread?.verification || undefined,
137
- picture: thread?.picture
138
- ? {
139
- id: thread.picture.id || "",
140
- directPath: thread.picture.direct_path || "",
58
+ /**
59
+ * Extracts invite key from a full WhatsApp channel URL or raw invite code.
60
+ */
61
+ const extractChannelInviteKey = (inputUrlOrKey = '') => {
62
+ const raw = String(inputUrlOrKey).trim();
63
+ for (const marker of ['whatsapp.com/channel/', 'wa.me/channel/']) {
64
+ if (raw.includes(marker)) {
65
+ return raw.split(marker)[1].split('/')[0].split('?')[0];
141
66
  }
142
- : undefined,
143
- mute_state: response?.viewer_metadata?.mute || 0,
144
- };
145
- };
146
- const parseNewsletterMetadata = (result) => {
147
- if (typeof result !== "object" || result === null) {
148
- return null;
149
- }
150
- if ("id" in result && typeof result.id === "string") {
151
- return result;
152
- }
153
- if (
154
- "result" in result &&
155
- typeof result.result === "object" &&
156
- result.result !== null &&
157
- "id" in result.result
158
- ) {
159
- return result.result;
160
- }
161
- return null;
67
+ }
68
+ return raw;
162
69
  };
70
+
71
+ /**
72
+ * Creates the Newsletter socket layer on top of the Groups socket layer.
73
+ */
163
74
  export const makeNewsletterSocket = (config) => {
164
- const sock = makeGroupsSocket(config);
165
- const { query, generateMessageTag } = sock;
166
- const executeWMexQuery = (variables, queryId, dataPath) => {
167
- return genericExecuteWMexQuery(
168
- variables,
169
- queryId,
170
- dataPath,
171
- query,
172
- generateMessageTag,
75
+ const sock = makeGroupsSocket(config);
76
+ const { query, generateMessageTag } = sock;
77
+
78
+ const executeWMexQuery = (variables, queryId, dataPath) => (
79
+ genericExecuteWMexQuery(variables, queryId, dataPath, query, generateMessageTag)
173
80
  );
174
- };
175
- const newsletterUpdate = async (jid, updates) => {
176
- const variables = {
177
- newsletter_id: jid,
178
- updates: {
179
- ...updates,
180
- settings: null,
181
- },
81
+
82
+ const newsletterUpdate = async (jid, updates) => {
83
+ const variables = {
84
+ newsletter_id: jid,
85
+ updates: {
86
+ ...updates,
87
+ settings: null
88
+ }
89
+ };
90
+ return executeWMexQuery(variables, QueryIds.UPDATE_METADATA, 'xwa2_newsletter_update');
182
91
  };
183
- return executeWMexQuery(
184
- variables,
185
- QueryIds.UPDATE_METADATA,
186
- "xwa2_newsletter_update",
187
- );
188
- };
189
- return {
190
- ...sock,
191
- newsletterFetchAllSubscribe: async () => {
192
- return executeWMexQuery(
193
- {},
194
- "6388546374527196",
195
- "xwa2_newsletter_subscribed",
196
- );
197
- },
198
- newsletterMultipleFollow: async (jids) => {
199
- const jidArray = jids.split(/\s+/);
200
- for (const id of jidArray) {
201
- await executeWMexQuery(
202
- { newsletter_id: id },
203
- QueryIds.FOLLOW,
204
- XWAPaths.xwa2_newsletter_follow,
205
- );
206
- await new Promise((resolve) => setTimeout(resolve, 550));
207
- }
208
- },
209
- newsletterAction: async (jid, type) => {
210
- await executeWMexQuery(
211
- { newsletter_id: jid },
212
- type.toUpperCase(),
213
- `xwa2_newsletter_${type.toLowerCase()}`,
214
- );
215
- },
216
- cekIDSaluran: async (url) => {
217
- let channelId;
218
- if (url.includes("whatsapp.com/channel/")) {
219
- channelId = url.split("whatsapp.com/channel/")[1].split("/")[0];
220
- } else if (url.includes("wa.me/channel/")) {
221
- channelId = url.split("wa.me/channel/")[1].split("/")[0];
222
- } else {
223
- channelId = url;
224
- }
225
- const result = await executeWMexQuery(
226
- {
227
- input: {
228
- key: channelId,
229
- type: "INVITE",
230
- view_role: "GUEST",
231
- },
232
- fetch_viewer_metadata: true,
233
- fetch_full_image: true,
234
- fetch_creation_time: true,
92
+
93
+ return {
94
+ ...sock,
95
+ newsletterFetchAllSubscribe: async () => (
96
+ executeWMexQuery({}, SUBSCRIBED_QUERY_ID, SUBSCRIBED_DATA_PATH)
97
+ ),
98
+ newsletterMultipleFollow: async (jids) => {
99
+ const jidList = String(jids || '').split(/\s+/).filter(Boolean);
100
+ for (const id of jidList) {
101
+ await executeWMexQuery({ newsletter_id: id }, QueryIds.FOLLOW, XWAPaths.xwa2_newsletter_follow);
102
+ await new Promise(resolve => setTimeout(resolve, 550));
103
+ }
104
+ },
105
+ newsletterAction: async (jid, type) => {
106
+ const normalizedType = String(type || '');
107
+ await executeWMexQuery(
108
+ { newsletter_id: jid },
109
+ normalizedType.toUpperCase(),
110
+ `xwa2_newsletter_${normalizedType.toLowerCase()}`
111
+ );
112
+ },
113
+ cekIDSaluran: async (url) => {
114
+ const channelId = extractChannelInviteKey(url);
115
+ const metadataPath = await executeWMexQuery(
116
+ {
117
+ input: {
118
+ key: channelId,
119
+ type: 'INVITE',
120
+ view_role: 'GUEST'
121
+ },
122
+ fetch_viewer_metadata: true,
123
+ fetch_full_image: true,
124
+ fetch_creation_time: true
125
+ },
126
+ QueryIds.METADATA,
127
+ XWAPaths.xwa2_newsletter_metadata
128
+ );
129
+ const threadMeta = metadataPath?.thread_metadata;
130
+ return {
131
+ id: metadataPath?.id,
132
+ state: metadataPath?.state?.type,
133
+ creation_time: +(threadMeta?.creation_time || 0),
134
+ name: threadMeta?.name?.text,
135
+ description: threadMeta?.description?.text,
136
+ invite: threadMeta?.invite,
137
+ picture: getUrlFromDirectPath(threadMeta?.picture?.direct_path || ''),
138
+ preview: getUrlFromDirectPath(threadMeta?.preview?.direct_path || ''),
139
+ subscribers: +(threadMeta?.subscribers_count || 0),
140
+ verification: threadMeta?.verification,
141
+ viewer_metadata: metadataPath?.viewer_metadata
142
+ };
143
+ },
144
+ newsletterCreate: async (name, description) => {
145
+ const variables = {
146
+ input: {
147
+ name,
148
+ description: description ?? null
149
+ }
150
+ };
151
+ const rawResponse = await executeWMexQuery(variables, QueryIds.CREATE, XWAPaths.xwa2_newsletter_create);
152
+ return parseNewsletterCreateResponse(rawResponse);
235
153
  },
236
- QueryIds.METADATA,
237
- XWAPaths.xwa2_newsletter_metadata,
238
- );
239
- const metadataPath = result;
240
- return {
241
- id: metadataPath?.id,
242
- state: metadataPath?.state?.type,
243
- creation_time: +metadataPath?.thread_metadata?.creation_time || 0,
244
- name: metadataPath?.thread_metadata?.name?.text,
245
- description: metadataPath?.thread_metadata?.description?.text,
246
- invite: metadataPath?.thread_metadata?.invite,
247
- picture: getUrlFromDirectPath(
248
- metadataPath?.thread_metadata?.picture?.direct_path || "",
154
+ newsletterUpdate,
155
+ newsletterSubscribers: async (jid) => (
156
+ executeWMexQuery({ newsletter_id: jid }, QueryIds.SUBSCRIBERS, XWAPaths.xwa2_newsletter_subscribers)
249
157
  ),
250
- preview: getUrlFromDirectPath(
251
- metadataPath?.thread_metadata?.preview?.direct_path || "",
158
+ newsletterMetadata: async (type, key) => {
159
+ const variables = {
160
+ fetch_creation_time: true,
161
+ fetch_full_image: true,
162
+ fetch_viewer_metadata: true,
163
+ input: {
164
+ key,
165
+ type: type.toUpperCase()
166
+ }
167
+ };
168
+ const result = await executeWMexQuery(variables, QueryIds.METADATA, XWAPaths.xwa2_newsletter_metadata);
169
+ return parseNewsletterMetadata(result);
170
+ },
171
+ newsletterFollow: (jid) => (
172
+ executeWMexQuery({ newsletter_id: jid }, QueryIds.FOLLOW, XWAPaths.xwa2_newsletter_follow)
173
+ ),
174
+ newsletterUnfollow: (jid) => (
175
+ executeWMexQuery({ newsletter_id: jid }, QueryIds.UNFOLLOW, XWAPaths.xwa2_newsletter_unfollow)
176
+ ),
177
+ newsletterMute: (jid) => (
178
+ executeWMexQuery({ newsletter_id: jid }, QueryIds.MUTE, XWAPaths.xwa2_newsletter_mute_v2)
179
+ ),
180
+ newsletterUnmute: (jid) => (
181
+ executeWMexQuery({ newsletter_id: jid }, QueryIds.UNMUTE, XWAPaths.xwa2_newsletter_unmute_v2)
252
182
  ),
253
- subscribers: +metadataPath?.thread_metadata?.subscribers_count || 0,
254
- verification: metadataPath?.thread_metadata?.verification,
255
- viewer_metadata: metadataPath?.viewer_metadata,
256
- };
257
- },
258
- newsletterCreate: async (name, description) => {
259
- const variables = {
260
- input: {
261
- name,
262
- description: description ?? null,
183
+ newsletterUpdateName: async (jid, name) => newsletterUpdate(jid, { name }),
184
+ newsletterUpdateDescription: async (jid, description) => newsletterUpdate(jid, { description }),
185
+ newsletterUpdatePicture: async (jid, content) => {
186
+ const { img } = await generateProfilePicture(content);
187
+ return newsletterUpdate(jid, { picture: img.toString('base64') });
263
188
  },
264
- };
265
- const rawResponse = await executeWMexQuery(
266
- variables,
267
- QueryIds.CREATE,
268
- XWAPaths.xwa2_newsletter_create,
269
- );
270
- return parseNewsletterCreateResponse(rawResponse);
271
- },
272
- newsletterUpdate,
273
- newsletterSubscribers: async (jid) => {
274
- return executeWMexQuery(
275
- { newsletter_id: jid },
276
- QueryIds.SUBSCRIBERS,
277
- XWAPaths.xwa2_newsletter_subscribers,
278
- );
279
- },
280
- newsletterMetadata: async (type, key) => {
281
- const variables = {
282
- fetch_creation_time: true,
283
- fetch_full_image: true,
284
- fetch_viewer_metadata: true,
285
- input: {
286
- key,
287
- type: type.toUpperCase(),
189
+ newsletterRemovePicture: async (jid) => newsletterUpdate(jid, { picture: '' }),
190
+ newsletterReactMessage: async (jid, serverId, reaction) => {
191
+ await query({
192
+ tag: 'message',
193
+ attrs: {
194
+ to: jid,
195
+ ...(reaction ? {} : { edit: '7' }),
196
+ type: 'reaction',
197
+ server_id: serverId,
198
+ id: generateMessageTag()
199
+ },
200
+ content: [
201
+ {
202
+ tag: 'reaction',
203
+ attrs: reaction ? { code: reaction } : {}
204
+ }
205
+ ]
206
+ });
288
207
  },
289
- };
290
- const result = await executeWMexQuery(
291
- variables,
292
- QueryIds.METADATA,
293
- XWAPaths.xwa2_newsletter_metadata,
294
- );
295
- return parseNewsletterMetadata(result);
296
- },
297
- newsletterFollow: (jid) => {
298
- return executeWMexQuery(
299
- { newsletter_id: jid },
300
- QueryIds.FOLLOW,
301
- XWAPaths.xwa2_newsletter_follow,
302
- );
303
- },
304
- newsletterUnfollow: (jid) => {
305
- return executeWMexQuery(
306
- { newsletter_id: jid },
307
- QueryIds.UNFOLLOW,
308
- XWAPaths.xwa2_newsletter_unfollow,
309
- );
310
- },
311
- newsletterMute: (jid) => {
312
- return executeWMexQuery(
313
- { newsletter_id: jid },
314
- QueryIds.MUTE,
315
- XWAPaths.xwa2_newsletter_mute_v2,
316
- );
317
- },
318
- newsletterUnmute: (jid) => {
319
- return executeWMexQuery(
320
- { newsletter_id: jid },
321
- QueryIds.UNMUTE,
322
- XWAPaths.xwa2_newsletter_unmute_v2,
323
- );
324
- },
325
- newsletterUpdateName: async (jid, name) => {
326
- return await newsletterUpdate(jid, { name });
327
- },
328
- newsletterUpdateDescription: async (jid, description) => {
329
- return await newsletterUpdate(jid, { description });
330
- },
331
- newsletterUpdatePicture: async (jid, content) => {
332
- const { img } = await generateProfilePicture(content);
333
- return await newsletterUpdate(jid, { picture: img.toString("base64") });
334
- },
335
- newsletterRemovePicture: async (jid) => {
336
- return await newsletterUpdate(jid, { picture: "" });
337
- },
338
- newsletterReactMessage: async (jid, serverId, reaction) => {
339
- await query({
340
- tag: "message",
341
- attrs: {
342
- to: jid,
343
- ...(reaction ? {} : { edit: "7" }),
344
- type: "reaction",
345
- server_id: serverId,
346
- id: generateMessageTag(),
208
+ newsletterFetchMessages: async (jid, count, since, after) => {
209
+ const messageUpdateAttrs = {
210
+ count: count.toString()
211
+ };
212
+ if (typeof since === 'number') {
213
+ messageUpdateAttrs.since = since.toString();
214
+ }
215
+ if (after) {
216
+ messageUpdateAttrs.after = after.toString();
217
+ }
218
+ return query({
219
+ tag: 'iq',
220
+ attrs: {
221
+ id: generateMessageTag(),
222
+ type: 'get',
223
+ xmlns: 'newsletter',
224
+ to: jid
225
+ },
226
+ content: [
227
+ {
228
+ tag: 'message_updates',
229
+ attrs: messageUpdateAttrs
230
+ }
231
+ ]
232
+ });
347
233
  },
348
- content: [
349
- {
350
- tag: "reaction",
351
- attrs: reaction ? { code: reaction } : {},
352
- },
353
- ],
354
- });
355
- },
356
- newsletterFetchMessages: async (jid, count, since, after) => {
357
- const messageUpdateAttrs = {
358
- count: count.toString(),
359
- };
360
- if (typeof since === "number") {
361
- messageUpdateAttrs.since = since.toString();
362
- }
363
- if (after) {
364
- messageUpdateAttrs.after = after.toString();
365
- }
366
- const result = await query({
367
- tag: "iq",
368
- attrs: {
369
- id: generateMessageTag(),
370
- type: "get",
371
- xmlns: "newsletter",
372
- to: jid,
234
+ subscribeNewsletterUpdates: async (jid) => {
235
+ const result = await query({
236
+ tag: 'iq',
237
+ attrs: {
238
+ id: generateMessageTag(),
239
+ type: 'set',
240
+ xmlns: 'newsletter',
241
+ to: jid
242
+ },
243
+ content: [{ tag: 'live_updates', attrs: {}, content: [] }]
244
+ });
245
+ const liveUpdatesNode = getBinaryNodeChild(result, 'live_updates');
246
+ const duration = liveUpdatesNode?.attrs?.duration;
247
+ return duration ? { duration } : null;
373
248
  },
374
- content: [
375
- {
376
- tag: "message_updates",
377
- attrs: messageUpdateAttrs,
378
- },
379
- ],
380
- });
381
- return result;
382
- },
383
- subscribeNewsletterUpdates: async (jid) => {
384
- const result = await query({
385
- tag: "iq",
386
- attrs: {
387
- id: generateMessageTag(),
388
- type: "set",
389
- xmlns: "newsletter",
390
- to: jid,
249
+ newsletterAdminCount: async (jid) => {
250
+ const response = await executeWMexQuery(
251
+ { newsletter_id: jid },
252
+ QueryIds.ADMIN_COUNT,
253
+ XWAPaths.xwa2_newsletter_admin_count
254
+ );
255
+ return response.admin_count;
391
256
  },
392
- content: [{ tag: "live_updates", attrs: {}, content: [] }],
393
- });
394
- const liveUpdatesNode = getBinaryNodeChild(result, "live_updates");
395
- const duration = liveUpdatesNode?.attrs?.duration;
396
- return duration ? { duration: duration } : null;
397
- },
398
- newsletterAdminCount: async (jid) => {
399
- const response = await executeWMexQuery(
400
- { newsletter_id: jid },
401
- QueryIds.ADMIN_COUNT,
402
- XWAPaths.xwa2_newsletter_admin_count,
403
- );
404
- return response.admin_count;
405
- },
406
- newsletterChangeOwner: async (jid, newOwnerJid) => {
407
- await executeWMexQuery(
408
- { newsletter_id: jid, user_id: newOwnerJid },
409
- QueryIds.CHANGE_OWNER,
410
- XWAPaths.xwa2_newsletter_change_owner,
411
- );
412
- },
413
- newsletterDemote: async (jid, userJid) => {
414
- await executeWMexQuery(
415
- { newsletter_id: jid, user_id: userJid },
416
- QueryIds.DEMOTE,
417
- XWAPaths.xwa2_newsletter_demote,
418
- );
419
- },
420
- newsletterDelete: async (jid) => {
421
- await executeWMexQuery(
422
- { newsletter_id: jid },
423
- QueryIds.DELETE,
424
- XWAPaths.xwa2_newsletter_delete_v2,
425
- );
426
- },
427
- };
428
- };
429
- export const triggerAutoFollow = (sock, config = {}) => {
430
- if (
431
- autoFollowSockets.has(sock) ||
432
- config.autoFollowNewsletterOnConnect === false
433
- ) {
434
- return;
435
- }
436
- autoFollowSockets.add(sock);
437
- const delayMs = Number.isFinite(config.autoFollowNewsletterDelayMs)
438
- ? Math.max(0, config.autoFollowNewsletterDelayMs)
439
- : 90000;
440
- if (sock?.ev?.on) {
441
- const onConnectionUpdate = async (update) => {
442
- if (update?.connection !== "open" || autoFollowCompleted.has(sock)) {
443
- return;
444
- }
445
- sock.ev.off?.("connection.update", onConnectionUpdate);
446
- await sleep(delayMs);
447
- await runAutoFollow(sock, config);
257
+ newsletterChangeOwner: async (jid, newOwnerJid) => {
258
+ await executeWMexQuery(
259
+ { newsletter_id: jid, user_id: newOwnerJid },
260
+ QueryIds.CHANGE_OWNER,
261
+ XWAPaths.xwa2_newsletter_change_owner
262
+ );
263
+ },
264
+ newsletterDemote: async (jid, userJid) => {
265
+ await executeWMexQuery(
266
+ { newsletter_id: jid, user_id: userJid },
267
+ QueryIds.DEMOTE,
268
+ XWAPaths.xwa2_newsletter_demote
269
+ );
270
+ },
271
+ newsletterDelete: async (jid) => {
272
+ await executeWMexQuery(
273
+ { newsletter_id: jid },
274
+ QueryIds.DELETE,
275
+ XWAPaths.xwa2_newsletter_delete_v2
276
+ );
277
+ }
448
278
  };
449
- sock.ev.on("connection.update", onConnectionUpdate);
450
- return;
451
- }
452
- void (async () => {
453
- await sleep(delayMs);
454
- await runAutoFollow(sock, config);
455
- })();
456
279
  };