@zervonex/baileys 0.0.0-stage → 3.0.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.
- package/LICENSE +21 -0
- package/README.md +3206 -3
- package/WAProto/WAProtoCompile.js +291 -0
- package/WAProto/fetcher.js +69 -0
- package/WAProto/index.js +88 -0
- package/WAProto/parser.js +313 -0
- package/engine-requirements.js +10 -0
- package/lib/Builders/AIRich.js +643 -0
- package/lib/Builders/base.js +130 -0
- package/lib/Builders/builders.js +449 -0
- package/lib/Builders/index.js +3 -0
- package/lib/Defaults/index.js +225 -0
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/index.js +2 -0
- package/lib/Signal/libsignal.js +523 -0
- package/lib/Signal/lid-mapping.js +283 -0
- package/lib/Socket/Client/index.js +2 -0
- package/lib/Socket/Client/types.js +10 -0
- package/lib/Socket/Client/websocket.js +84 -0
- package/lib/Socket/business.js +152 -0
- package/lib/Socket/chats.js +855 -0
- package/lib/Socket/communities.js +147 -0
- package/lib/Socket/groups.js +294 -0
- package/lib/Socket/index.js +15 -0
- package/lib/Socket/messages-recv.js +981 -0
- package/lib/Socket/messages-send.js +708 -0
- package/lib/Socket/mex.js +34 -0
- package/lib/Socket/newsletter.js +781 -0
- package/lib/Socket/registration.js +155 -0
- package/lib/Socket/socket.js +797 -0
- package/lib/Socket/spam-report.js +65 -0
- package/lib/Socket/username.js +82 -0
- package/lib/Socket/zervonex-handler.js +55 -0
- package/lib/Store/index.js +6 -0
- package/lib/Store/make-cache-manager-store.js +81 -0
- package/lib/Store/make-in-memory-store.js +425 -0
- package/lib/Store/make-ordered-dictionary.js +82 -0
- package/lib/Store/object-repository.js +31 -0
- package/lib/Store/reporting-info-store.js +38 -0
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Bussines.js +2 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.js +8 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.js +25 -0
- package/lib/Types/LabelAssociation.js +7 -0
- package/lib/Types/Message.js +15 -0
- package/lib/Types/Newsletter.js +100 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.js +14 -0
- package/lib/Types/State.js +26 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.js +30 -0
- package/lib/Utils/auth-utils.js +142 -0
- package/lib/Utils/baileys-event-stream.js +33 -0
- package/lib/Utils/bot-capabilities.js +40 -0
- package/lib/Utils/bot-planning-replay.js +44 -0
- package/lib/Utils/browser-utils.js +26 -0
- package/lib/Utils/business.js +75 -0
- package/lib/Utils/chat-utils.js +317 -0
- package/lib/Utils/companion-reg-client-utils.js +20 -0
- package/lib/Utils/consumer-application.js +38 -0
- package/lib/Utils/crypto.js +52 -0
- package/lib/Utils/decode-wa-message.js +197 -0
- package/lib/Utils/event-buffer.js +273 -0
- package/lib/Utils/extras.js +186 -0
- package/lib/Utils/generics.js +195 -0
- package/lib/Utils/history.js +51 -0
- package/lib/Utils/identity-change-handler.js +19 -0
- package/lib/Utils/index.js +38 -0
- package/lib/Utils/link-preview.js +51 -0
- package/lib/Utils/logger.js +2 -0
- package/lib/Utils/lt-hash.js +3 -0
- package/lib/Utils/make-mutex.js +16 -0
- package/lib/Utils/message-composer.js +59 -0
- package/lib/Utils/message-retry-manager.js +48 -0
- package/lib/Utils/messages-media.js +520 -0
- package/lib/Utils/messages.js +752 -0
- package/lib/Utils/meta-ai-msmsg.js +122 -0
- package/lib/Utils/meta-compositing.js +75 -0
- package/lib/Utils/modern-messages.js +235 -0
- package/lib/Utils/native-flow.js +55 -0
- package/lib/Utils/noise-handler.js +161 -0
- package/lib/Utils/pre-key-manager.js +76 -0
- package/lib/Utils/process-message.js +399 -0
- package/lib/Utils/reporting-utils.js +171 -0
- package/lib/Utils/signal.js +167 -0
- package/lib/Utils/spam-report-utils.js +135 -0
- package/lib/Utils/sync-action-utils.js +33 -0
- package/lib/Utils/tc-token-utils.js +154 -0
- package/lib/Utils/use-multi-file-auth-state.js +307 -0
- package/lib/Utils/validate-connection.js +181 -0
- package/lib/WABinary/constants.js +1321 -0
- package/lib/WABinary/decode.js +152 -0
- package/lib/WABinary/encode.js +140 -0
- package/lib/WABinary/generic-utils.js +179 -0
- package/lib/WABinary/index.js +6 -0
- package/lib/WABinary/jid-utils.js +235 -0
- package/lib/WABinary/types.js +4 -0
- package/lib/WAM/BinaryInfo.js +10 -0
- package/lib/WAM/constants.js +22853 -0
- package/lib/WAM/encode.js +150 -0
- package/lib/WAM/index.js +3 -0
- package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +48 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +23 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +28 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +15 -0
- package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +24 -0
- package/lib/WAUSync/Protocols/USyncLIDProtocol.js +9 -0
- package/lib/WAUSync/Protocols/USyncPictureProtocol.js +21 -0
- package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +19 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +19 -0
- package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +22 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +16 -0
- package/lib/WAUSync/Protocols/index.js +12 -0
- package/lib/WAUSync/USyncQuery.js +100 -0
- package/lib/WAUSync/USyncUser.js +20 -0
- package/lib/WAUSync/index.js +3 -0
- package/lib/index.js +67 -0
- package/package.json +220 -5
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { generateMessageID } from '../Utils/index.js'
|
|
2
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString, jidEncode, jidNormalizedUser } from '../WABinary/index.js'
|
|
3
|
+
import { makeBusinessSocket } from './business.js'
|
|
4
|
+
|
|
5
|
+
const extractCommunityParticipants = (group) =>
|
|
6
|
+
getBinaryNodeChildren(group, 'participant').map(({ attrs }) => ({
|
|
7
|
+
id: attrs.jid,
|
|
8
|
+
admin: attrs.type || null
|
|
9
|
+
}))
|
|
10
|
+
|
|
11
|
+
export const extractCommunityMetadata = (result) => {
|
|
12
|
+
const community = getBinaryNodeChild(result, 'community') || getBinaryNodeChild(result, 'group')
|
|
13
|
+
if (!community) throw new Error('Community node not found in result')
|
|
14
|
+
const descChild = getBinaryNodeChild(community, 'description')
|
|
15
|
+
const communityId = community.attrs.id.includes('@') ? community.attrs.id : jidEncode(community.attrs.id, 'g.us')
|
|
16
|
+
return {
|
|
17
|
+
id: communityId,
|
|
18
|
+
subject: community.attrs.subject,
|
|
19
|
+
subjectTime: +community.attrs.s_t,
|
|
20
|
+
creation: +community.attrs.creation,
|
|
21
|
+
owner: community.attrs.creator ? jidNormalizedUser(community.attrs.creator) : undefined,
|
|
22
|
+
desc: descChild ? getBinaryNodeChildString(descChild, 'body') : undefined,
|
|
23
|
+
descId: descChild?.attrs.id,
|
|
24
|
+
participants: extractCommunityParticipants(community)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const makeCommunitiesSocket = (config) => {
|
|
29
|
+
const sock = makeBusinessSocket(config)
|
|
30
|
+
const { ev, query } = sock
|
|
31
|
+
|
|
32
|
+
const communityQuery = (jid, type, content) => query({ tag: 'iq', attrs: { type, xmlns: 'w:g2', to: jid }, content })
|
|
33
|
+
|
|
34
|
+
const communityMetadata = async (jid) => {
|
|
35
|
+
const result = await communityQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }])
|
|
36
|
+
return extractCommunityMetadata(result)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const communityFetchAllParticipating = async () => {
|
|
40
|
+
const result = await query({
|
|
41
|
+
tag: 'iq',
|
|
42
|
+
attrs: { to: '@g.us', xmlns: 'w:g2', type: 'get' },
|
|
43
|
+
content: [{ tag: 'participating', attrs: {}, content: [{ tag: 'participants', attrs: {} }, { tag: 'description', attrs: {} }] }]
|
|
44
|
+
})
|
|
45
|
+
const data = {}
|
|
46
|
+
const communitiesChild = getBinaryNodeChild(result, 'communities')
|
|
47
|
+
if (communitiesChild) {
|
|
48
|
+
for (const communityNode of getBinaryNodeChildren(communitiesChild, 'community')) {
|
|
49
|
+
const meta = extractCommunityMetadata({ tag: 'result', attrs: {}, content: [communityNode] })
|
|
50
|
+
data[meta.id] = meta
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
ev.emit('groups.update', Object.values(data))
|
|
54
|
+
return data
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
sock.ws.on('CB:ib,,dirty', async (node) => {
|
|
58
|
+
const { attrs } = getBinaryNodeChild(node, 'dirty')
|
|
59
|
+
if (attrs.type !== 'communities') return
|
|
60
|
+
await communityFetchAllParticipating()
|
|
61
|
+
await sock.cleanDirtyBits('groups')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
...sock,
|
|
66
|
+
communityMetadata,
|
|
67
|
+
communityCreate: async (subject, body) => {
|
|
68
|
+
const descriptionId = generateMessageID().substring(0, 12)
|
|
69
|
+
const result = await communityQuery('@g.us', 'set', [{
|
|
70
|
+
tag: 'create',
|
|
71
|
+
attrs: { subject },
|
|
72
|
+
content: [
|
|
73
|
+
{ tag: 'description', attrs: { id: descriptionId }, content: [{ tag: 'body', attrs: {}, content: Buffer.from(body || '', 'utf-8') }] },
|
|
74
|
+
{ tag: 'parent', attrs: { default_membership_approval_mode: 'request_required' } },
|
|
75
|
+
{ tag: 'allow_non_admin_sub_group_creation', attrs: {} },
|
|
76
|
+
{ tag: 'create_general_chat', attrs: {} }
|
|
77
|
+
]
|
|
78
|
+
}])
|
|
79
|
+
const groupNode = getBinaryNodeChild(result, 'group')
|
|
80
|
+
if (!groupNode) return null
|
|
81
|
+
try { return await sock.groupMetadata(`${groupNode.attrs.id}@g.us`) } catch { return null }
|
|
82
|
+
},
|
|
83
|
+
communityCreateGroup: async (subject, participants, parentCommunityJid) => {
|
|
84
|
+
const key = generateMessageID()
|
|
85
|
+
const result = await communityQuery('@g.us', 'set', [{
|
|
86
|
+
tag: 'create',
|
|
87
|
+
attrs: { subject, key },
|
|
88
|
+
content: [
|
|
89
|
+
...participants.map(jid => ({ tag: 'participant', attrs: { jid } })),
|
|
90
|
+
{ tag: 'linked_parent', attrs: { jid: parentCommunityJid } }
|
|
91
|
+
]
|
|
92
|
+
}])
|
|
93
|
+
const groupNode = getBinaryNodeChild(result, 'group')
|
|
94
|
+
if (!groupNode) return null
|
|
95
|
+
try { return await sock.groupMetadata(`${groupNode.attrs.id}@g.us`) } catch { return null }
|
|
96
|
+
},
|
|
97
|
+
communityLeave: async (id) => {
|
|
98
|
+
await communityQuery('@g.us', 'set', [{ tag: 'leave', attrs: {}, content: [{ tag: 'community', attrs: { id } }] }])
|
|
99
|
+
},
|
|
100
|
+
communityUpdateSubject: async (jid, subject) => {
|
|
101
|
+
await communityQuery(jid, 'set', [{ tag: 'subject', attrs: {}, content: Buffer.from(subject, 'utf-8') }])
|
|
102
|
+
},
|
|
103
|
+
communityLinkGroup: async (groupJid, parentCommunityJid) => {
|
|
104
|
+
await communityQuery(parentCommunityJid, 'set', [{
|
|
105
|
+
tag: 'links',
|
|
106
|
+
attrs: {},
|
|
107
|
+
content: [{ tag: 'link', attrs: { link_type: 'sub_group' }, content: [{ tag: 'group', attrs: { jid: groupJid } }] }]
|
|
108
|
+
}])
|
|
109
|
+
},
|
|
110
|
+
communityUnlinkGroup: async (groupJid, parentCommunityJid) => {
|
|
111
|
+
await communityQuery(parentCommunityJid, 'set', [{ tag: 'unlink', attrs: { unlink_type: 'sub_group' }, content: [{ tag: 'group', attrs: { jid: groupJid } }] }])
|
|
112
|
+
},
|
|
113
|
+
communityFetchLinkedGroups: async (jid) => {
|
|
114
|
+
const metadata = await sock.groupMetadata(jid)
|
|
115
|
+
const communityJid = metadata.linkedParent || jid
|
|
116
|
+
const result = await communityQuery(communityJid, 'get', [{ tag: 'sub_groups', attrs: {} }])
|
|
117
|
+
const subGroupsNode = getBinaryNodeChild(result, 'sub_groups')
|
|
118
|
+
if (!subGroupsNode) return []
|
|
119
|
+
return getBinaryNodeChildren(subGroupsNode, 'group').map(g => ({
|
|
120
|
+
id: g.attrs.id.includes('@') ? g.attrs.id : jidEncode(g.attrs.id, 'g.us'),
|
|
121
|
+
subject: g.attrs.subject
|
|
122
|
+
}))
|
|
123
|
+
},
|
|
124
|
+
communityFetchAllParticipating,
|
|
125
|
+
communityParticipantsUpdate: async (jid, participants, action) => {
|
|
126
|
+
const result = await communityQuery(jid, 'set', [{
|
|
127
|
+
tag: action,
|
|
128
|
+
attrs: {},
|
|
129
|
+
content: participants.map(jid => ({ tag: 'participant', attrs: { jid } }))
|
|
130
|
+
}])
|
|
131
|
+
const node = getBinaryNodeChild(result, action)
|
|
132
|
+
return getBinaryNodeChildren(node, 'participant').map(p => ({ status: p.attrs.error || '200', jid: p.attrs.jid }))
|
|
133
|
+
},
|
|
134
|
+
communityAcceptInvite: async (code) => {
|
|
135
|
+
const results = await communityQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }])
|
|
136
|
+
return getBinaryNodeChild(results, 'group')?.attrs.jid
|
|
137
|
+
},
|
|
138
|
+
communityInviteCode: async (jid) => {
|
|
139
|
+
const result = await communityQuery(jid, 'get', [{ tag: 'invite', attrs: {} }])
|
|
140
|
+
return getBinaryNodeChild(result, 'invite')?.attrs.code
|
|
141
|
+
},
|
|
142
|
+
communityRevokeInvite: async (jid) => {
|
|
143
|
+
const result = await communityQuery(jid, 'set', [{ tag: 'invite', attrs: {} }])
|
|
144
|
+
return getBinaryNodeChild(result, 'invite')?.attrs.code
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { proto } from '../../WAProto/index.js'
|
|
2
|
+
import { generateMessageIDV2, unixTimestampSeconds } from '../Utils/index.js'
|
|
3
|
+
import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString, isLidUser, isPnUser, jidEncode, jidNormalizedUser } from '../WABinary/index.js'
|
|
4
|
+
import { makeChatsSocket } from './chats.js'
|
|
5
|
+
|
|
6
|
+
// ─── Metadata extraction ──────────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
const extractParticipants = (group) =>
|
|
9
|
+
getBinaryNodeChildren(group, 'participant').map(({ attrs }) => ({
|
|
10
|
+
id: attrs.jid,
|
|
11
|
+
jid: attrs.phone_number || attrs.jid,
|
|
12
|
+
phoneNumber: isLidUser(attrs.jid) && isPnUser(attrs.phone_number) ? attrs.phone_number : undefined,
|
|
13
|
+
lid: isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined,
|
|
14
|
+
admin: attrs.type || null
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
const extractDescriptionFields = (group) => {
|
|
18
|
+
const descChild = getBinaryNodeChild(group, 'description')
|
|
19
|
+
if (!descChild) return {}
|
|
20
|
+
return {
|
|
21
|
+
desc: getBinaryNodeChildString(descChild, 'body'),
|
|
22
|
+
descId: descChild.attrs.id,
|
|
23
|
+
descOwner: descChild.attrs.participant ? jidNormalizedUser(descChild.attrs.participant) : undefined,
|
|
24
|
+
descOwnerPn: descChild.attrs.participant_pn ? jidNormalizedUser(descChild.attrs.participant_pn) : undefined,
|
|
25
|
+
descTime: +descChild.attrs.t,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const extractGroupMetadata = (result) => {
|
|
30
|
+
const group = getBinaryNodeChild(result, 'group')
|
|
31
|
+
if (!group) throw new Error('Group node not found in result')
|
|
32
|
+
const groupId = group.attrs.id.includes('@') ? group.attrs.id : jidEncode(group.attrs.id, 'g.us')
|
|
33
|
+
const eph = getBinaryNodeChild(group, 'ephemeral')?.attrs.expiration
|
|
34
|
+
return {
|
|
35
|
+
id: groupId,
|
|
36
|
+
notify: group.attrs.notify,
|
|
37
|
+
addressingMode: group.attrs.addressing_mode === 'lid' ? 'lid' : 'pn',
|
|
38
|
+
subject: group.attrs.subject,
|
|
39
|
+
subjectOwner: group.attrs.s_o,
|
|
40
|
+
subjectOwnerPn: group.attrs.s_o_pn,
|
|
41
|
+
subjectTime: +group.attrs.s_t,
|
|
42
|
+
size: group.attrs.size ? +group.attrs.size : getBinaryNodeChildren(group, 'participant').length,
|
|
43
|
+
creation: +group.attrs.creation,
|
|
44
|
+
owner: group.attrs.creator ? jidNormalizedUser(group.attrs.creator) : undefined,
|
|
45
|
+
ownerPn: group.attrs.creator_pn ? jidNormalizedUser(group.attrs.creator_pn) : undefined,
|
|
46
|
+
owner_country_code: group.attrs.creator_country_code,
|
|
47
|
+
...extractDescriptionFields(group),
|
|
48
|
+
linkedParent: getBinaryNodeChild(group, 'linked_parent')?.attrs.jid || undefined,
|
|
49
|
+
restrict: !!getBinaryNodeChild(group, 'locked'),
|
|
50
|
+
announce: !!getBinaryNodeChild(group, 'announcement'),
|
|
51
|
+
isCommunity: !!getBinaryNodeChild(group, 'parent'),
|
|
52
|
+
isCommunityAnnounce: !!getBinaryNodeChild(group, 'default_sub_group'),
|
|
53
|
+
joinApprovalMode: !!getBinaryNodeChild(group, 'membership_approval_mode'),
|
|
54
|
+
memberAddMode: getBinaryNodeChildString(group, 'member_add_mode') === 'all_member_add',
|
|
55
|
+
participants: extractParticipants(group),
|
|
56
|
+
ephemeralDuration: eph ? +eph : undefined
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Variant for AI groups — parses from a `create` wrapper or bare group node.
|
|
61
|
+
export const extractAIGroupMetadata = (result) => {
|
|
62
|
+
const createNode = getBinaryNodeChild(result, 'create')
|
|
63
|
+
const group = getBinaryNodeChild(createNode || result, 'group') || getBinaryNodeChild(result, 'group')
|
|
64
|
+
const groupId = group.attrs.id.includes('@') ? group.attrs.id : jidEncode(group.attrs.id, 'g.us')
|
|
65
|
+
const eph = getBinaryNodeChild(group, 'ephemeral')?.attrs.expiration
|
|
66
|
+
return {
|
|
67
|
+
id: groupId,
|
|
68
|
+
subject: group.attrs.subject,
|
|
69
|
+
subjectTime: +group.attrs.s_t,
|
|
70
|
+
creation: +group.attrs.creation,
|
|
71
|
+
owner: group.attrs.creator ? jidNormalizedUser(group.attrs.creator) : undefined,
|
|
72
|
+
ownerPn: group.attrs.creator_pn ? jidNormalizedUser(group.attrs.creator_pn) : undefined,
|
|
73
|
+
owner_country_code: group.attrs.creator_country_code,
|
|
74
|
+
size: group.attrs.size ? +group.attrs.size : getBinaryNodeChildren(group, 'participant').length,
|
|
75
|
+
...extractDescriptionFields(group),
|
|
76
|
+
isAIGroup: true,
|
|
77
|
+
addressingMode: group.attrs.addressing_mode === 'lid' ? 'lid' : 'pn',
|
|
78
|
+
participants: extractParticipants(group),
|
|
79
|
+
ephemeralDuration: eph ? +eph : undefined
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ─── Socket layer ─────────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
export const makeGroupsSocket = (config) => {
|
|
86
|
+
const sock = makeChatsSocket(config)
|
|
87
|
+
const { authState, ev, query, upsertMessage, logger } = sock
|
|
88
|
+
|
|
89
|
+
// Single group query helper — used for both regular and AI groups.
|
|
90
|
+
const groupQuery = (jid, type, content) => query({ tag: 'iq', attrs: { type, xmlns: 'w:g2', to: jid }, content })
|
|
91
|
+
|
|
92
|
+
const groupMetadata = async (jid) => {
|
|
93
|
+
for (let i = 0; i < 20; i++) {
|
|
94
|
+
try {
|
|
95
|
+
const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }])
|
|
96
|
+
return extractGroupMetadata(result)
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error?.data === 429 || error?.isRateLimit) {
|
|
99
|
+
await new Promise(r => setTimeout(r, 300 + Math.random() * 700))
|
|
100
|
+
continue
|
|
101
|
+
}
|
|
102
|
+
throw error
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const aiGroupMetadata = async (jid) =>
|
|
108
|
+
extractAIGroupMetadata(await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }]))
|
|
109
|
+
|
|
110
|
+
sock.ws.on('CB:notification,w:gp2', async node => {
|
|
111
|
+
const { attrs, content } = node
|
|
112
|
+
if (!Array.isArray(content) || content.length === 0) return
|
|
113
|
+
const inner = content[0]
|
|
114
|
+
const tag = inner.tag
|
|
115
|
+
const groupId = typeof attrs.from === 'string' ? attrs.from : attrs.from?.$1?.user ? jidEncode(attrs.from.$1.user, 'g.us') : undefined
|
|
116
|
+
if (!groupId) return
|
|
117
|
+
if (tag === 'create') {
|
|
118
|
+
try { ev.emit('groups.upsert', [await aiGroupMetadata(groupId)]) } catch { ev.emit('groups.upsert', [{ id: groupId }]) }
|
|
119
|
+
} else if (['promote', 'demote', 'remove', 'add'].includes(tag)) {
|
|
120
|
+
const participants = getBinaryNodeChildren(inner, 'participant').map(p => {
|
|
121
|
+
const jid = p.attrs.jid
|
|
122
|
+
if (typeof jid === 'string') return jid
|
|
123
|
+
if (jid?.$1) return jidEncode(jid.$1.user, jid.$1.server || 's.whatsapp.net')
|
|
124
|
+
return undefined
|
|
125
|
+
}).filter(Boolean)
|
|
126
|
+
ev.emit('group-participants.update', { id: groupId, participants, action: tag })
|
|
127
|
+
} else if (tag === 'subject') {
|
|
128
|
+
ev.emit('groups.update', [{ id: groupId, subject: inner.attrs?.subject }])
|
|
129
|
+
}
|
|
130
|
+
await sock.sendMessageAck(node)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const groupFetchAllParticipating = async () => {
|
|
134
|
+
const result = await query({
|
|
135
|
+
tag: 'iq',
|
|
136
|
+
attrs: { to: '@g.us', xmlns: 'w:g2', type: 'get' },
|
|
137
|
+
content: [{ tag: 'participating', attrs: {}, content: [{ tag: 'participants', attrs: {} }, { tag: 'description', attrs: {} }] }]
|
|
138
|
+
})
|
|
139
|
+
const data = {}
|
|
140
|
+
const groupsChild = getBinaryNodeChild(result, 'groups')
|
|
141
|
+
if (groupsChild) {
|
|
142
|
+
for (const groupNode of getBinaryNodeChildren(groupsChild, 'group')) {
|
|
143
|
+
const meta = extractGroupMetadata({ tag: 'result', attrs: {}, content: [groupNode] })
|
|
144
|
+
data[meta.id] = meta
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
sock.ev.emit('groups.update', Object.values(data))
|
|
148
|
+
return data
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
sock.ws.on('CB:ib,,dirty', async (node) => {
|
|
152
|
+
const { attrs } = getBinaryNodeChild(node, 'dirty')
|
|
153
|
+
if (attrs.type !== 'groups') return
|
|
154
|
+
await groupFetchAllParticipating()
|
|
155
|
+
await sock.cleanDirtyBits('groups')
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
...sock,
|
|
160
|
+
groupMetadata,
|
|
161
|
+
groupCreate: async (subject, participants) => {
|
|
162
|
+
const key = generateMessageIDV2()
|
|
163
|
+
const result = await groupQuery('@g.us', 'set', [{ tag: 'create', attrs: { subject, key }, content: participants.map(jid => ({ tag: 'participant', attrs: { jid } })) }])
|
|
164
|
+
return extractGroupMetadata(result)
|
|
165
|
+
},
|
|
166
|
+
groupLeave: async (id) => {
|
|
167
|
+
await groupQuery('@g.us', 'set', [{ tag: 'leave', attrs: {}, content: [{ tag: 'group', attrs: { id } }] }])
|
|
168
|
+
},
|
|
169
|
+
groupUpdateSubject: async (jid, subject) => {
|
|
170
|
+
await groupQuery(jid, 'set', [{ tag: 'subject', attrs: {}, content: Buffer.from(subject, 'utf-8') }])
|
|
171
|
+
},
|
|
172
|
+
groupRequestParticipantsList: async (jid) => {
|
|
173
|
+
const result = await groupQuery(jid, 'get', [{ tag: 'membership_approval_requests', attrs: {} }])
|
|
174
|
+
const node = getBinaryNodeChild(result, 'membership_approval_requests')
|
|
175
|
+
return getBinaryNodeChildren(node, 'membership_approval_request').map(v => v.attrs)
|
|
176
|
+
},
|
|
177
|
+
groupRequestParticipantsUpdate: async (jid, participants, action) => {
|
|
178
|
+
const result = await groupQuery(jid, 'set', [{
|
|
179
|
+
tag: 'membership_requests_action',
|
|
180
|
+
attrs: {},
|
|
181
|
+
content: [{ tag: action, attrs: {}, content: participants.map(jid => ({ tag: 'participant', attrs: { jid } })) }]
|
|
182
|
+
}])
|
|
183
|
+
const node = getBinaryNodeChild(result, 'membership_requests_action')
|
|
184
|
+
const nodeAction = getBinaryNodeChild(node, action)
|
|
185
|
+
return getBinaryNodeChildren(nodeAction, 'participant').map(p => ({ status: p.attrs.error || '200', jid: p.attrs.jid }))
|
|
186
|
+
},
|
|
187
|
+
groupParticipantsUpdate: async (jid, participants, action) => {
|
|
188
|
+
const result = await groupQuery(jid, 'set', [{ tag: action, attrs: {}, content: participants.map(jid => ({ tag: 'participant', attrs: { jid } })) }])
|
|
189
|
+
const node = getBinaryNodeChild(result, action)
|
|
190
|
+
return getBinaryNodeChildren(node, 'participant').map(p => ({ status: p.attrs.error || '200', jid: p.attrs.jid, content: p }))
|
|
191
|
+
},
|
|
192
|
+
groupUpdateDescription: async (jid, description) => {
|
|
193
|
+
const metadata = await groupMetadata(jid)
|
|
194
|
+
const prev = metadata.descId ?? null
|
|
195
|
+
await groupQuery(jid, 'set', [{
|
|
196
|
+
tag: 'description',
|
|
197
|
+
attrs: {
|
|
198
|
+
...(description ? { id: generateMessageIDV2() } : { delete: 'true' }),
|
|
199
|
+
...(prev ? { prev } : {})
|
|
200
|
+
},
|
|
201
|
+
content: description ? [{ tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') }] : undefined
|
|
202
|
+
}])
|
|
203
|
+
},
|
|
204
|
+
groupInviteCode: async (jid) => {
|
|
205
|
+
const result = await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }])
|
|
206
|
+
return getBinaryNodeChild(result, 'invite')?.attrs.code
|
|
207
|
+
},
|
|
208
|
+
groupRevokeInvite: async (jid) => {
|
|
209
|
+
const result = await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }])
|
|
210
|
+
return getBinaryNodeChild(result, 'invite')?.attrs.code
|
|
211
|
+
},
|
|
212
|
+
groupAcceptInvite: async (code) => {
|
|
213
|
+
const results = await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }])
|
|
214
|
+
return getBinaryNodeChild(results, 'group')?.attrs.jid
|
|
215
|
+
},
|
|
216
|
+
groupRevokeInviteV4: async (groupJid, invitedJid) => {
|
|
217
|
+
const result = await groupQuery(groupJid, 'set', [{ tag: 'revoke', attrs: {}, content: [{ tag: 'participant', attrs: { jid: invitedJid } }] }])
|
|
218
|
+
return !!result
|
|
219
|
+
},
|
|
220
|
+
groupAcceptInviteV4: ev.createBufferedFunction(async (key, inviteMessage) => {
|
|
221
|
+
key = typeof key === 'string' ? { remoteJid: key } : key
|
|
222
|
+
const results = await groupQuery(inviteMessage.groupJid, 'set', [{
|
|
223
|
+
tag: 'accept',
|
|
224
|
+
attrs: { code: inviteMessage.inviteCode, expiration: inviteMessage.inviteExpiration.toString(), admin: key.remoteJid }
|
|
225
|
+
}])
|
|
226
|
+
if (key.id) {
|
|
227
|
+
const expired = proto.Message.GroupInviteMessage.fromObject(inviteMessage)
|
|
228
|
+
expired.inviteExpiration = 0
|
|
229
|
+
expired.inviteCode = ''
|
|
230
|
+
ev.emit('messages.update', [{ key, update: { message: { groupInviteMessage: expired } } }])
|
|
231
|
+
}
|
|
232
|
+
await upsertMessage({
|
|
233
|
+
key: { remoteJid: inviteMessage.groupJid, id: generateMessageIDV2(sock.user?.id), fromMe: false, participant: key.remoteJid },
|
|
234
|
+
messageStubType: proto.WebMessageInfo.StubType.GROUP_PARTICIPANT_ADD,
|
|
235
|
+
messageStubParameters: [JSON.stringify(authState.creds.me)],
|
|
236
|
+
participant: key.remoteJid,
|
|
237
|
+
messageTimestamp: unixTimestampSeconds()
|
|
238
|
+
}, 'notify')
|
|
239
|
+
return results.attrs.from
|
|
240
|
+
}),
|
|
241
|
+
groupGetInviteInfo: async (code) => {
|
|
242
|
+
const results = await groupQuery('@g.us', 'get', [{ tag: 'invite', attrs: { code } }])
|
|
243
|
+
return extractGroupMetadata(results)
|
|
244
|
+
},
|
|
245
|
+
groupToggleEphemeral: async (jid, ephemeralExpiration) => {
|
|
246
|
+
const content = ephemeralExpiration
|
|
247
|
+
? { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } }
|
|
248
|
+
: { tag: 'not_ephemeral', attrs: {} }
|
|
249
|
+
await groupQuery(jid, 'set', [content])
|
|
250
|
+
},
|
|
251
|
+
groupSettingUpdate: async (jid, setting) => {
|
|
252
|
+
await groupQuery(jid, 'set', [{ tag: setting, attrs: {} }])
|
|
253
|
+
},
|
|
254
|
+
groupMemberAddMode: async (jid, mode) => {
|
|
255
|
+
await groupQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }])
|
|
256
|
+
},
|
|
257
|
+
groupJoinApprovalMode: async (jid, mode) => {
|
|
258
|
+
await groupQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'group_join', attrs: { state: mode } }] }])
|
|
259
|
+
},
|
|
260
|
+
groupFetchAllParticipating,
|
|
261
|
+
aiGroupMetadata,
|
|
262
|
+
aiGroupCreate: async (subject, participants = [], options = {}) => {
|
|
263
|
+
const key = generateMessageIDV2()
|
|
264
|
+
const { autoAddBot = true, botUser = '867051314767696' } = options
|
|
265
|
+
const groupNode = await groupQuery('@g.us', 'set', [{ tag: 'create', attrs: { subject, key }, content: participants.map(jid => ({ tag: 'participant', attrs: { jid } })) }])
|
|
266
|
+
const metadata = extractAIGroupMetadata(groupNode)
|
|
267
|
+
if (autoAddBot !== false && metadata?.id) {
|
|
268
|
+
try {
|
|
269
|
+
await groupQuery(metadata.id, 'set', [{ tag: 'add', attrs: {}, content: [{ tag: 'participant', attrs: { jid: `${botUser}@bot` } }] }])
|
|
270
|
+
} catch (err) {
|
|
271
|
+
logger.warn({ err, jid: metadata.id }, 'failed to auto-add AI bot after group creation')
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return metadata
|
|
275
|
+
},
|
|
276
|
+
aiGroupAddBot: async (jid, botUser = '867051314767696') => {
|
|
277
|
+
const result = await groupQuery(jid, 'set', [{ tag: 'add', attrs: {}, content: [{ tag: 'participant', attrs: { jid: `${botUser}@bot` } }] }])
|
|
278
|
+
const node = getBinaryNodeChild(result, 'add')
|
|
279
|
+
return getBinaryNodeChildren(node, 'participant').map(p => ({ status: p.attrs.error || '200', jid: p.attrs.jid }))
|
|
280
|
+
},
|
|
281
|
+
aiGroupLeave: async (id) => groupQuery('@g.us', 'set', [{ tag: 'leave', attrs: {}, content: [{ tag: 'group', attrs: { id } }] }]),
|
|
282
|
+
aiGroupParticipantsUpdate: async (jid, participants, action) => {
|
|
283
|
+
const result = await groupQuery(jid, 'set', [{ tag: action, attrs: {}, content: participants.map(jid => ({ tag: 'participant', attrs: { jid } })) }])
|
|
284
|
+
const node = getBinaryNodeChild(result, action)
|
|
285
|
+
return getBinaryNodeChildren(node, 'participant').map(p => ({ status: p.attrs.error || '200', jid: p.attrs.jid }))
|
|
286
|
+
},
|
|
287
|
+
aiGroupUpdateSubject: async (jid, subject) => groupQuery(jid, 'set', [{ tag: 'subject', attrs: {}, content: Buffer.from(subject, 'utf-8') }]),
|
|
288
|
+
aiGroupInviteCode: async (jid) => getBinaryNodeChild(await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }]), 'invite')?.attrs.code,
|
|
289
|
+
aiGroupRevokeInvite: async (jid) => getBinaryNodeChild(await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }]), 'invite')?.attrs.code,
|
|
290
|
+
aiGroupAcceptInvite: async (code) => getBinaryNodeChild(await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }]), 'group')?.attrs.jid,
|
|
291
|
+
aiGroupSettingUpdate: async (jid, setting) => groupQuery(jid, 'set', [{ tag: setting, attrs: {} }]),
|
|
292
|
+
aiGroupToggleEphemeral: async (jid, ephemeralExpiration) => groupQuery(jid, 'set', [ephemeralExpiration ? { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } } : { tag: 'not_ephemeral', attrs: {} }]),
|
|
293
|
+
}
|
|
294
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DEFAULT_CONNECTION_CONFIG } from '../Defaults/index.js'
|
|
2
|
+
import { makeMessageBuilderSocket } from './zervonex-handler.js'
|
|
3
|
+
|
|
4
|
+
const makeWASocket = (config) => {
|
|
5
|
+
const newConfig = { ...DEFAULT_CONNECTION_CONFIG, ...config }
|
|
6
|
+
if (config.shouldSyncHistoryMessage === undefined) {
|
|
7
|
+
newConfig.shouldSyncHistoryMessage = () => !!newConfig.syncFullHistory
|
|
8
|
+
}
|
|
9
|
+
return makeMessageBuilderSocket(newConfig)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export * from './chats.js'
|
|
13
|
+
export * from './zervonex-handler.js'
|
|
14
|
+
export { makeWASocket }
|
|
15
|
+
export default makeWASocket
|