Path: blob/master/node_modules/@adiwajshing/baileys/lib/Socket/messages-send.js
2593 views
"use strict";1var __importDefault = (this && this.__importDefault) || function (mod) {2return (mod && mod.__esModule) ? mod : { "default": mod };3};4Object.defineProperty(exports, "__esModule", { value: true });5exports.makeMessagesSocket = void 0;6const node_cache_1 = __importDefault(require("node-cache"));7const WAProto_1 = require("../../WAProto");8const Defaults_1 = require("../Defaults");9const Utils_1 = require("../Utils");10const WABinary_1 = require("../WABinary");11const groups_1 = require("./groups");12const makeMessagesSocket = (config) => {13const { logger } = config;14const sock = groups_1.makeGroupsSocket(config);15const { ev, authState, query, generateMessageTag, sendNode, groupMetadata, groupToggleEphemeral } = sock;16const userDevicesCache = config.userDevicesCache || new node_cache_1.default({17stdTTL: 300,18useClones: false19});20let privacySettings;21const fetchPrivacySettings = async (force = false) => {22if (!privacySettings || force) {23const { content } = await query({24tag: 'iq',25attrs: {26xmlns: 'privacy',27to: WABinary_1.S_WHATSAPP_NET,28type: 'get'29},30content: [31{ tag: 'privacy', attrs: {} }32]33});34privacySettings = WABinary_1.reduceBinaryNodeToDictionary(content[0], 'category');35}36return privacySettings;37};38let mediaConn;39const refreshMediaConn = async (forceGet = false) => {40const media = await mediaConn;41if (!media || forceGet || (new Date().getTime() - media.fetchDate.getTime()) > media.ttl * 1000) {42mediaConn = (async () => {43const result = await query({44tag: 'iq',45attrs: {46type: 'set',47xmlns: 'w:m',48to: WABinary_1.S_WHATSAPP_NET,49},50content: [{ tag: 'media_conn', attrs: {} }]51});52const mediaConnNode = WABinary_1.getBinaryNodeChild(result, 'media_conn');53const node = {54hosts: WABinary_1.getBinaryNodeChildren(mediaConnNode, 'host').map(item => item.attrs),55auth: mediaConnNode.attrs.auth,56ttl: +mediaConnNode.attrs.ttl,57fetchDate: new Date()58};59logger.debug('fetched media conn');60return node;61})();62}63return mediaConn;64};65/**66* generic send receipt function67* used for receipts of phone call, read, delivery etc.68* */69const sendReceipt = async (jid, participant, messageIds, type) => {70const node = {71tag: 'receipt',72attrs: {73id: messageIds[0],74t: Date.now().toString(),75to: jid,76},77};78if (type) {79node.attrs.type = type;80}81if (participant) {82node.attrs.participant = participant;83}84const remainingMessageIds = messageIds.slice(1);85if (remainingMessageIds.length) {86node.content = [87{88tag: 'list',89attrs: {},90content: remainingMessageIds.map(id => ({91tag: 'item',92attrs: { id }93}))94}95];96}97logger.debug({ jid, messageIds, type }, 'sending receipt for messages');98await sendNode(node);99};100const sendReadReceipt = async (jid, participant, messageIds) => {101const privacySettings = await fetchPrivacySettings();102// based on privacy settings, we have to change the read type103const readType = privacySettings.readreceipts === 'all' ? 'read' : 'read-self';104return sendReceipt(jid, participant, messageIds, readType);105};106const getUSyncDevices = async (jids, ignoreZeroDevices) => {107const deviceResults = [];108const users = [];109jids = Array.from(new Set(jids));110for (let jid of jids) {111const user = WABinary_1.jidDecode(jid).user;112jid = WABinary_1.jidNormalizedUser(jid);113if (userDevicesCache.has(user)) {114const devices = userDevicesCache.get(user);115deviceResults.push(...devices);116logger.trace({ user }, 'using cache for devices');117}118else {119users.push({ tag: 'user', attrs: { jid } });120}121}122const iq = {123tag: 'iq',124attrs: {125to: WABinary_1.S_WHATSAPP_NET,126type: 'get',127xmlns: 'usync',128},129content: [130{131tag: 'usync',132attrs: {133sid: generateMessageTag(),134mode: 'query',135last: 'true',136index: '0',137context: 'message',138},139content: [140{141tag: 'query',142attrs: {},143content: [144{145tag: 'devices',146attrs: { version: '2' }147}148]149},150{ tag: 'list', attrs: {}, content: users }151]152},153],154};155const result = await query(iq);156const extracted = Utils_1.extractDeviceJids(result, authState.creds.me.id, ignoreZeroDevices);157const deviceMap = {};158for (const item of extracted) {159deviceMap[item.user] = deviceMap[item.user] || [];160deviceMap[item.user].push(item);161deviceResults.push(item);162}163for (const key in deviceMap) {164userDevicesCache.set(key, deviceMap[key]);165}166return deviceResults;167};168const assertSessions = async (jids, force) => {169let jidsRequiringFetch = [];170if (force) {171jidsRequiringFetch = jids;172}173else {174const addrs = jids.map(jid => Utils_1.jidToSignalProtocolAddress(jid).toString());175const sessions = await authState.keys.get('session', addrs);176for (const jid of jids) {177const signalId = Utils_1.jidToSignalProtocolAddress(jid).toString();178if (!sessions[signalId]) {179jidsRequiringFetch.push(jid);180}181}182}183if (jidsRequiringFetch.length) {184logger.debug({ jidsRequiringFetch }, 'fetching sessions');185const result = await query({186tag: 'iq',187attrs: {188xmlns: 'encrypt',189type: 'get',190to: WABinary_1.S_WHATSAPP_NET,191},192content: [193{194tag: 'key',195attrs: {},196content: jidsRequiringFetch.map(jid => ({197tag: 'user',198attrs: { jid, reason: 'identity' },199}))200}201]202});203await Utils_1.parseAndInjectE2ESessions(result, authState);204return true;205}206return false;207};208const createParticipantNodes = async (jids, bytes) => {209await assertSessions(jids, false);210if (authState.keys.isInTransaction()) {211await authState.keys.prefetch('session', jids.map(jid => Utils_1.jidToSignalProtocolAddress(jid).toString()));212}213const nodes = await Promise.all(jids.map(async (jid) => {214const { type, ciphertext } = await Utils_1.encryptSignalProto(jid, bytes, authState);215const node = {216tag: 'to',217attrs: { jid },218content: [{219tag: 'enc',220attrs: { v: '2', type },221content: ciphertext222}]223};224return node;225}));226return nodes;227};228const relayMessage = async (jid, message, { messageId: msgId, participant, additionalAttributes, cachedGroupMetadata }) => {229const meId = authState.creds.me.id;230const { user, server } = WABinary_1.jidDecode(jid);231const isGroup = server === 'g.us';232msgId = msgId || Utils_1.generateMessageID();233const encodedMsg = Utils_1.encodeWAMessage(message);234const participants = [];235const destinationJid = WABinary_1.jidEncode(user, isGroup ? 'g.us' : 's.whatsapp.net');236const binaryNodeContent = [];237const devices = [];238if (participant) {239const { user, device } = WABinary_1.jidDecode(participant);240devices.push({ user, device });241}242await authState.keys.transaction(async () => {243if (isGroup) {244const { ciphertext, senderKeyDistributionMessageKey } = await Utils_1.encryptSenderKeyMsgSignalProto(destinationJid, encodedMsg, meId, authState);245const [groupData, senderKeyMap] = await Promise.all([246(async () => {247let groupData = cachedGroupMetadata ? await cachedGroupMetadata(jid) : undefined;248if (!groupData) {249groupData = await groupMetadata(jid);250}251return groupData;252})(),253(async () => {254const result = await authState.keys.get('sender-key-memory', [jid]);255return result[jid] || {};256})()257]);258if (!participant) {259const participantsList = groupData.participants.map(p => p.id);260const additionalDevices = await getUSyncDevices(participantsList, false);261devices.push(...additionalDevices);262}263const senderKeyJids = [];264// ensure a connection is established with every device265for (const { user, device } of devices) {266const jid = WABinary_1.jidEncode(user, 's.whatsapp.net', device);267if (!senderKeyMap[jid]) {268senderKeyJids.push(jid);269// store that this person has had the sender keys sent to them270senderKeyMap[jid] = true;271}272}273// if there are some participants with whom the session has not been established274// if there are, we re-send the senderkey275if (senderKeyJids.length) {276logger.debug({ senderKeyJids }, 'sending new sender key');277const encSenderKeyMsg = Utils_1.encodeWAMessage({278senderKeyDistributionMessage: {279axolotlSenderKeyDistributionMessage: senderKeyDistributionMessageKey,280groupId: destinationJid281}282});283participants.push(...(await createParticipantNodes(senderKeyJids, encSenderKeyMsg)));284}285binaryNodeContent.push({286tag: 'enc',287attrs: { v: '2', type: 'skmsg' },288content: ciphertext289});290await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } });291}292else {293const { user: meUser } = WABinary_1.jidDecode(meId);294const encodedMeMsg = Utils_1.encodeWAMessage({295deviceSentMessage: {296destinationJid,297message298}299});300if (!participant) {301devices.push({ user });302devices.push({ user: meUser });303const additionalDevices = await getUSyncDevices([meId, jid], true);304devices.push(...additionalDevices);305}306const meJids = [];307const otherJids = [];308for (const { user, device } of devices) {309const jid = WABinary_1.jidEncode(user, 's.whatsapp.net', device);310const isMe = user === meUser;311if (isMe) {312meJids.push(jid);313}314else {315otherJids.push(jid);316}317}318const [meNodes, otherNodes] = await Promise.all([319createParticipantNodes(meJids, encodedMeMsg),320createParticipantNodes(otherJids, encodedMsg)321]);322participants.push(...meNodes);323participants.push(...otherNodes);324}325if (participants.length) {326binaryNodeContent.push({327tag: 'participants',328attrs: {},329content: participants330});331}332const stanza = {333tag: 'message',334attrs: {335id: msgId,336type: 'text',337to: destinationJid,338...(additionalAttributes || {})339},340content: binaryNodeContent341};342const shouldHaveIdentity = !!participants.find(participant => participant.content.find(n => n.attrs.type === 'pkmsg'));343if (shouldHaveIdentity) {344stanza.content.push({345tag: 'device-identity',346attrs: {},347content: WAProto_1.proto.ADVSignedDeviceIdentity.encode(authState.creds.account).finish()348});349logger.debug({ jid }, 'adding device identity');350}351logger.debug({ msgId }, `sending message to ${participants.length} devices`);352await sendNode(stanza);353});354return msgId;355};356const waUploadToServer = Utils_1.getWAUploadToServer(config, refreshMediaConn);357return {358...sock,359assertSessions,360relayMessage,361sendReceipt,362sendReadReceipt,363refreshMediaConn,364waUploadToServer,365fetchPrivacySettings,366sendMessage: async (jid, content, options = {}) => {367const userJid = authState.creds.me.id;368if (typeof content === 'object' &&369'disappearingMessagesInChat' in content &&370typeof content['disappearingMessagesInChat'] !== 'undefined' &&371WABinary_1.isJidGroup(jid)) {372const { disappearingMessagesInChat } = content;373const value = typeof disappearingMessagesInChat === 'boolean' ?374(disappearingMessagesInChat ? Defaults_1.WA_DEFAULT_EPHEMERAL : 0) :375disappearingMessagesInChat;376await groupToggleEphemeral(jid, value);377}378else {379const fullMsg = await Utils_1.generateWAMessage(jid, content, {380logger,381userJid,382// multi-device does not have this yet383//getUrlInfo: generateUrlInfo,384upload: waUploadToServer,385mediaCache: config.mediaCache,386...options,387});388const isDeleteMsg = 'delete' in content && !!content.delete;389const additionalAttributes = {};390// required for delete391if (isDeleteMsg) {392additionalAttributes.edit = '7';393}394await relayMessage(jid, fullMsg.message, { messageId: fullMsg.key.id, additionalAttributes });395if (config.emitOwnEvents) {396process.nextTick(() => {397ev.emit('messages.upsert', { messages: [fullMsg], type: 'append' });398});399}400return fullMsg;401}402}403};404};405exports.makeMessagesSocket = makeMessagesSocket;406407408