UNPKG

@vreden/meta

Version:

Baileys is a lightweight JavaScript library for interacting with the WhatsApp Web API using WebSocket.

369 lines (334 loc) 15 kB
"use strict" Object.defineProperty(exports, "__esModule", { value: true }) const WAProto_1 = require("../../WAProto") const Types_1 = require("../Types") const Utils_1 = require("../Utils") const WABinary_1 = require("../WABinary") const business_1 = require("./business") const makeCommunitiesSocket = (config) => { const sock = business_1.makeBusinessSocket(config) const { authState, ev, query, groupMetadata, upsertMessage } = sock const communityQuery = async (jid, type, content) => (query({ tag: 'iq', attrs: { type, xmlns: 'w:g2', to: jid, }, content })) const communityMetadata = async (jid) => { const result = await communityQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }]) return extractCommunityMetadata(result) } const communityFetchAllParticipating = 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 = {} const communitiesChild = WABinary_1.getBinaryNodeChild(result, 'communities') if (communitiesChild) { const communities = WABinary_1.getBinaryNodeChildren(communitiesChild, 'community') for (const communityNode of communities) { const meta = extractCommunityMetadata({ tag: 'result', attrs: {}, content: [communityNode] }) data[meta.id] = meta } } sock.ev.emit('groups.update', Object.values(data)) return data } sock.ws.on('CB:ib,,dirty', async (node) => { const { attrs } = WABinary_1.getBinaryNodeChild(node, 'dirty') if (attrs.type !== 'communities') { return } await communityFetchAllParticipating() await sock.cleanDirtyBits('groups') }) return { ...sock, communityQuery, communityMetadata, communityCreate: async (subject, body) => { const descriptionId = Utils_1.generateMessageID().substring(0, 12) const result = await communityQuery('@g.us', 'set', [ { tag: 'create', attrs: { subject }, content: [{ tag: 'description', attrs: { id: descriptionId }, content: [{ tag: 'body', attrs: {}, content: Buffer.from(body || '', 'utf-8') }] }, { tag: 'parent', attrs: { default_membership_approval_mode: 'request_required' } }, { tag: 'allow_non_admin_sub_group_creation', attrs: {} }, { tag: 'create_general_chat', attrs: {} }] } ]) return extractCommunityMetadata(result) }, communityLeave: async (id) => { await communityQuery('@g.us', 'set', [ { tag: 'leave', attrs: {}, content: [ { tag: 'community', attrs: { id } } ] } ]) }, communityUpdateSubject: async (jid, subject) => { await communityQuery(jid, 'set', [ { tag: 'subject', attrs: {}, content: Buffer.from(subject, 'utf-8') } ]) }, communityRequestParticipantsList: async (jid) => { const result = await communityQuery(jid, 'get', [ { tag: 'membership_approval_requests', attrs: {} } ]) const node = WABinary_1.getBinaryNodeChild(result, 'membership_approval_requests') const participants = WABinary_1.getBinaryNodeChildren(node, 'membership_approval_request') return participants.map(v => v.attrs) }, communityRequestParticipantsUpdate: async (jid, participants, action) => { const result = await communityQuery(jid, 'set', [{ tag: 'membership_requests_action', attrs: {}, content: [ { tag: action, attrs: {}, content: participants.map(jid => ({ tag: 'participant', attrs: { jid } })) } ] }]) const node = WABinary_1.getBinaryNodeChild(result, 'membership_requests_action') const nodeAction = WABinary_1.getBinaryNodeChild(node, action) const participantsAffected = WABinary_1.getBinaryNodeChildren(nodeAction, 'participant') return participantsAffected.map(p => { return { status: p.attrs.error || '200', jid: p.attrs.jid } }) }, communityParticipantsUpdate: async (jid, participants, action) => { const result = await communityQuery(jid, 'set', [ { tag: action, attrs: {}, content: participants.map(jid => ({ tag: 'participant', attrs: { jid } })) } ]) const node = WABinary_1.getBinaryNodeChild(result, action) const participantsAffected = WABinary_1.getBinaryNodeChildren(node, 'participant') return participantsAffected.map(p => { return { status: p.attrs.error || '200', jid: p.attrs.jid, content: p } }) }, communityUpdateDescription: async (jid, description) => { const metadata = await communityMetadata(jid) const prev = metadata.descId ? metadata.descId : null await communityQuery(jid, 'set', [ { tag: 'description', attrs: { ...(description ? { id: Utils_1.generateMessageID() } : { delete: 'true' }), ...(prev ? { prev } : {}) }, content: description ? [ { tag: 'body', attrs: {}, content: Buffer.from(description, 'utf-8') } ] : undefined } ]) }, communityInviteCode: async (jid) => { const result = await communityQuery(jid, 'get', [{ tag: 'invite', attrs: {} }]) const inviteNode = WABinary_1.getBinaryNodeChild(result, 'invite') return inviteNode?.attrs?.code }, communityRevokeInvite: async (jid) => { const result = await communityQuery(jid, 'set', [{ tag: 'invite', attrs: {} }]) const inviteNode = WABinary_1.getBinaryNodeChild(result, 'invite') return inviteNode?.attrs?.code }, communityAcceptInvite: async (code) => { const results = await communityQuery('@g.us', 'set', [{ tag: 'invite', attrs: { code } }]) const result = WABinary_1.getBinaryNodeChild(results, 'community') return result?.attrs?.jid }, /** * revoke a v4 invite for someone * @param communityJid community jid * @param invitedJid jid of person you invited * @returns true if successful */ communityRevokeInviteV4: async (communityJid, invitedJid) => { const result = await communityQuery(communityJid, 'set', [{ tag: 'revoke', attrs: {}, content: [{ tag: 'participant', attrs: { jid: invitedJid } }] }]) return !!result }, /** * accept a GroupInviteMessage * @param key the key of the invite message, or optionally only provide the jid of the person who sent the invite * @param inviteMessage the message to accept */ communityAcceptInviteV4: ev.createBufferedFunction(async (key, inviteMessage) => { key = typeof key === 'string' ? { remoteJid: key } : key const results = await communityQuery(inviteMessage.groupJid, 'set', [{ tag: 'accept', attrs: { code: inviteMessage.inviteCode, expiration: inviteMessage.inviteExpiration.toString(), admin: key.remoteJid } }]) // if we have the full message key // update the invite message to be expired if (key.id) { // create new invite message that is expired inviteMessage = WAProto_1.proto.Message.GroupInviteMessage.fromObject(inviteMessage) inviteMessage.inviteExpiration = 0 inviteMessage.inviteCode = '' ev.emit('messages.update', [ { key, update: { message: { groupInviteMessage: inviteMessage } } } ]) } // generate the group add message await upsertMessage({ key: { remoteJid: inviteMessage.groupJid, id: Utils_1.generateMessageID(authState.creds.me?.id), fromMe: false, participant: key.remoteJid, }, messageStubType: Types_1.WAMessageStubType.GROUP_PARTICIPANT_ADD, messageStubParameters: [ authState.creds.me.id ], participant: key.remoteJid, messageTimestamp: Utils_1.unixTimestampSeconds() }, 'notify') return results.attrs.from }), communityGetInviteInfo: async (code) => { const results = await communityQuery('@g.us', 'get', [{ tag: 'invite', attrs: { code } }]) return extractCommunityMetadata(results) }, communityToggleEphemeral: async (jid, ephemeralExpiration) => { const content = ephemeralExpiration ? { tag: 'ephemeral', attrs: { expiration: ephemeralExpiration.toString() } } : { tag: 'not_ephemeral', attrs: {} } await communityQuery(jid, 'set', [content]) }, communitySettingUpdate: async (jid, setting) => { await communityQuery(jid, 'set', [{ tag: setting, attrs: {} }]) }, communityMemberAddMode: async (jid, mode) => { await communityQuery(jid, 'set', [{ tag: 'member_add_mode', attrs: {}, content: mode }]) }, communityJoinApprovalMode: async (jid, mode) => { await communityQuery(jid, 'set', [{ tag: 'membership_approval_mode', attrs: {}, content: [{ tag: 'community_join', attrs: { state: mode } }] }]) }, communityFetchAllParticipating } } const extractCommunityMetadata = (result) => { const community = WABinary_1.getBinaryNodeChild(result, 'group') const descChild = WABinary_1.getBinaryNodeChild(community, 'description') let desc let descId if (descChild) { desc = WABinary_1.getBinaryNodeChildString(descChild, 'body') descId = descChild.attrs.id } const mode = community.attrs.addressing_mode const communityId = community.attrs.id.includes('@') ? community.attrs.id : WABinary_1.jidEncode(community.attrs.id, 'g.us') const eph = WABinary_1.getBinaryNodeChild(community, 'ephemeral')?.attrs.expiration const memberAddMode = WABinary_1.getBinaryNodeChildString(community, 'member_add_mode') === 'all_member_add' const metadata = { id: communityId, addressingMode: mode, subject: community.attrs.subject, subjectOwner: mode === 'lid' ? community.attrs.s_o_pn : community.attrs.s_o, subjectTime: +community.attrs.s_t, size: community.attrs?.size ? +community.attrs.size : WABinary_1.getBinaryNodeChildren(community, 'participant').length, creation: +community.attrs.creation, owner: community.attrs.creator ? WABinary_1.jidNormalizedUser(mode === 'lid' ? community.attrs.creator_pn : community.attrs.creator) : undefined, desc, descId, linkedParent: WABinary_1.getBinaryNodeChild(community, 'linked_parent')?.attrs.jid || undefined, restrict: !!WABinary_1.getBinaryNodeChild(community, 'locked'), announce: !!WABinary_1.getBinaryNodeChild(community, 'announcement'), isCommunity: !!WABinary_1.getBinaryNodeChild(community, 'parent'), isCommunityAnnounce: !!WABinary_1.getBinaryNodeChild(community, 'default_sub_group'), joinApprovalMode: !!WABinary_1.getBinaryNodeChild(community, 'membership_approval_mode'), memberAddMode, participants: WABinary_1.getBinaryNodeChildren(community, 'participant').map(({ attrs }) => { return { id: mode === 'lid' ? community.phone_number : attrs.jid, lid: mode === 'lid' ? community.jid : attrs.lid, admin: (attrs.type || null), } }), ephemeralDuration: eph ? +eph : undefined, } return metadata } module.exports = { makeCommunitiesSocket, extractCommunityMetadata }