Files
Baileys/src/Socket/groups.ts
Alon Schwartzblat eb8f8e0d72 Add join group by groupInviteMessage (#1355)
* Add join group by groupInviteMessage

* Add join group by groupInviteMessage

* Fix typo
2022-03-25 16:18:00 +05:30

226 lines
5.9 KiB
TypeScript

import { GroupMetadata, ParticipantAction, SocketConfig } from '../Types'
import { generateMessageID } from '../Utils'
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, jidEncode, jidNormalizedUser } from '../WABinary'
import { makeSocket } from './socket'
import { proto } from '../../WAProto'
export const makeGroupsSocket = (config: SocketConfig) => {
const sock = makeSocket(config)
const { query } = sock
const groupQuery = async(jid: string, type: 'get' | 'set', content: BinaryNode[]) => (
query({
tag: 'iq',
attrs: {
type,
xmlns: 'w:g2',
to: jid,
},
content
})
)
const groupMetadata = async(jid: string) => {
const result = await groupQuery(
jid,
'get',
[ { tag: 'query', attrs: { request: 'interactive' } } ]
)
return extractGroupMetadata(result)
}
return {
...sock,
groupMetadata,
groupCreate: async(subject: string, participants: string[]) => {
const key = generateMessageID()
const result = await groupQuery(
'@g.us',
'set',
[
{
tag: 'create',
attrs: {
subject,
key
},
content: participants.map(jid => ({
tag: 'participant',
attrs: { jid }
}))
}
]
)
return extractGroupMetadata(result)
},
groupLeave: async(id: string) => {
await groupQuery(
'@g.us',
'set',
[
{
tag: 'leave',
attrs: { },
content: [
{ tag: 'group', attrs: { id } }
]
}
]
)
},
groupUpdateSubject: async(jid: string, subject: string) => {
await groupQuery(
jid,
'set',
[
{
tag: 'subject',
attrs: { },
content: Buffer.from(subject, 'utf-8')
}
]
)
},
groupParticipantsUpdate: async(
jid: string,
participants: string[],
action: ParticipantAction
) => {
const result = await groupQuery(
jid,
'set',
participants.map(
jid => ({
tag: action,
attrs: { },
content: [{ tag: 'participant', attrs: { jid } }]
})
)
)
const node = getBinaryNodeChild(result, action)
const participantsAffected = getBinaryNodeChildren(node!, 'participant')
return participantsAffected.map(p => p.attrs.jid)
},
groupUpdateDescription: async(jid: string, description?: string) => {
const metadata = await groupMetadata(jid)
const prev = metadata.descId ?? null
await groupQuery(
jid,
'set',
[
{
tag: 'description',
attrs: {
...(description ? { id: generateMessageID() } : { delete: 'true' }),
...(prev ? { prev } : {})
},
content: description ? [{ tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') }] : null
}
]
)
},
groupInviteCode: async(jid: string) => {
const result = await groupQuery(jid, 'get', [{ tag: 'invite', attrs: {} }])
const inviteNode = getBinaryNodeChild(result, 'invite')
return inviteNode.attrs.code
},
groupRevokeInvite: async(jid: string) => {
const result = await groupQuery(jid, 'set', [{ tag: 'invite', attrs: {} }])
const inviteNode = getBinaryNodeChild(result, 'invite')
return inviteNode.attrs.code
},
groupAcceptInvite: async(code: string) => {
const results = await groupQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }])
const result = getBinaryNodeChild(results, 'group')
return result.attrs.jid
},
groupAcceptInviteV4: async(jid: string, inviteMessage: proto.IGroupInviteMessage) => {
const results = await groupQuery(inviteMessage.groupJid, 'set', [{ tag: 'accept', attrs: {
code: inviteMessage.inviteCode,
expiration: inviteMessage.inviteExpiration.toString(),
admin: jid} }])
return results.attrs.from;
},
groupToggleEphemeral: async(jid: string, ephemeralExpiration: number) => {
const content: BinaryNode = ephemeralExpiration ?
{ tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } } :
{ tag: 'not_ephemeral', attrs: { } }
await groupQuery(jid, 'set', [content])
},
groupSettingUpdate: async(jid: string, setting: 'announcement' | 'not_announcement' | 'locked' | 'unlocked') => {
await groupQuery(jid, 'set', [ { tag: setting, attrs: { } } ])
},
groupFetchAllParticipating: async() => {
const result = await query({
tag: 'iq',
attrs: {
to: '@g.us',
xmlns: 'w:g2',
type: 'get',
},
content: [
{
tag: 'participating',
attrs: { },
content: [
{ tag: 'participants', attrs: { } },
{ tag: 'description', attrs: { } }
]
}
]
})
const data: { [_: string]: GroupMetadata } = { }
const groupsChild = getBinaryNodeChild(result, 'groups')
if(groupsChild) {
const groups = getBinaryNodeChildren(groupsChild, 'group')
for(const groupNode of groups) {
const meta = extractGroupMetadata({
tag: 'result',
attrs: { },
content: [groupNode]
})
data[meta.id] = meta
}
}
return data
}
}
}
export const extractGroupMetadata = (result: BinaryNode) => {
const group = getBinaryNodeChild(result, 'group')
const descChild = getBinaryNodeChild(group, 'description')
let desc: string | undefined
let descId: string | undefined
if(descChild) {
desc = getBinaryNodeChild(descChild, 'body')?.content as string
descId = descChild.attrs.id
}
const groupId = group.attrs.id.includes('@') ? group.attrs.id : jidEncode(group.attrs.id, 'g.us')
const eph = getBinaryNodeChild(group, 'ephemeral')?.attrs.expiration
const metadata: GroupMetadata = {
id: groupId,
subject: group.attrs.subject,
creation: +group.attrs.creation,
owner: group.attrs.creator ? jidNormalizedUser(group.attrs.creator) : undefined,
desc,
descId,
restrict: !!getBinaryNodeChild(group, 'locked'),
announce: !!getBinaryNodeChild(group, 'announcement'),
participants: getBinaryNodeChildren(group, 'participant').map(
({ attrs }) => {
return {
id: attrs.jid,
admin: attrs.type || null as any,
}
}
),
ephemeralDuration: eph ? +eph : undefined
}
return metadata
}