Path: blob/master/node_modules/@adiwajshing/baileys/lib/LegacySocket/chats.js
1129 views
"use strict";1var __importDefault = (this && this.__importDefault) || function (mod) {2return (mod && mod.__esModule) ? mod : { "default": mod };3};4Object.defineProperty(exports, "__esModule", { value: true });5const Types_1 = require("../Types");6const Utils_1 = require("../Utils");7const generics_1 = require("../Utils/generics");8const WABinary_1 = require("../WABinary");9const auth_1 = __importDefault(require("./auth"));10const makeChatsSocket = (config) => {11const { logger } = config;12const sock = (0, auth_1.default)(config);13const { ev, ws: socketEvents, currentEpoch, setQuery, query, sendNode, state } = sock;14const chatsDebounceTimeout = (0, generics_1.debouncedTimeout)(10000, () => sendChatsQuery(1));15const sendChatsQuery = (epoch) => (sendNode({16json: {17tag: 'query',18attrs: { type: 'chat', epoch: epoch.toString() }19},20binaryTag: [Types_1.WAMetric.queryChat, Types_1.WAFlag.ignore]21}));22const profilePictureUrl = async (jid, timeoutMs) => {23const response = await query({24json: ['query', 'ProfilePicThumb', jid],25expect200: false,26requiresPhoneConnection: false,27timeoutMs28});29return response.eurl;30};31const executeChatModification = (node) => {32const { attrs: attributes } = node;33const updateType = attributes.type;34const jid = (0, WABinary_1.jidNormalizedUser)(attributes === null || attributes === void 0 ? void 0 : attributes.jid);35switch (updateType) {36case 'delete':37ev.emit('chats.delete', [jid]);38break;39case 'clear':40if (node.content) {41const ids = node.content.map(({ attrs }) => attrs.index);42ev.emit('messages.delete', { keys: ids.map(id => ({ id, remoteJid: jid })) });43}44else {45ev.emit('messages.delete', { jid, all: true });46}47break;48case 'archive':49ev.emit('chats.update', [{ id: jid, archive: true }]);50break;51case 'unarchive':52ev.emit('chats.update', [{ id: jid, archive: false }]);53break;54case 'pin':55ev.emit('chats.update', [{ id: jid, pin: attributes.pin ? +attributes.pin : null }]);56break;57case 'star':58case 'unstar':59const starred = updateType === 'star';60const updates = node.content.map(({ attrs }) => ({61key: {62remoteJid: jid,63id: attrs.index,64fromMe: attrs.owner === 'true'65},66update: { starred }67}));68ev.emit('messages.update', updates);69break;70case 'mute':71if (attributes.mute === '0') {72ev.emit('chats.update', [{ id: jid, mute: null }]);73}74else {75ev.emit('chats.update', [{ id: jid, mute: +attributes.mute }]);76}77break;78default:79logger.warn({ node }, 'received unrecognized chat update');80break;81}82};83const applyingPresenceUpdate = (update) => {84const id = (0, WABinary_1.jidNormalizedUser)(update.id);85const participant = (0, WABinary_1.jidNormalizedUser)(update.participant || update.id);86const presence = {87lastSeen: update.t ? +update.t : undefined,88lastKnownPresence: update.type89};90return { id, presences: { [participant]: presence } };91};92const chatRead = async (fromMessage, count) => {93await setQuery([94{95tag: 'read',96attrs: {97jid: fromMessage.remoteJid,98count: count.toString(),99index: fromMessage.id,100owner: fromMessage.fromMe ? 'true' : 'false'101}102}103], [Types_1.WAMetric.read, Types_1.WAFlag.ignore]);104if (config.emitOwnEvents) {105ev.emit('chats.update', [{ id: fromMessage.remoteJid, unreadCount: count < 0 ? -1 : 0 }]);106}107};108ev.on('connection.update', async ({ connection }) => {109if (connection !== 'open') {110return;111}112try {113await Promise.all([114sendNode({115json: { tag: 'query', attrs: { type: 'contacts', epoch: '1' } },116binaryTag: [Types_1.WAMetric.queryContact, Types_1.WAFlag.ignore]117}),118sendNode({119json: { tag: 'query', attrs: { type: 'status', epoch: '1' } },120binaryTag: [Types_1.WAMetric.queryStatus, Types_1.WAFlag.ignore]121}),122sendNode({123json: { tag: 'query', attrs: { type: 'quick_reply', epoch: '1' } },124binaryTag: [Types_1.WAMetric.queryQuickReply, Types_1.WAFlag.ignore]125}),126sendNode({127json: { tag: 'query', attrs: { type: 'label', epoch: '1' } },128binaryTag: [Types_1.WAMetric.queryLabel, Types_1.WAFlag.ignore]129}),130sendNode({131json: { tag: 'query', attrs: { type: 'emoji', epoch: '1' } },132binaryTag: [Types_1.WAMetric.queryEmoji, Types_1.WAFlag.ignore]133}),134sendNode({135json: {136tag: 'action',137attrs: { type: 'set', epoch: '1' },138content: [139{ tag: 'presence', attrs: { type: 'available' } }140]141},142binaryTag: [Types_1.WAMetric.presence, Types_1.WAFlag.available]143})144]);145chatsDebounceTimeout.start();146logger.debug('sent init queries');147}148catch (error) {149logger.error(`error in sending init queries: ${error}`);150}151});152socketEvents.on('CB:response,type:chat', async ({ content: data }) => {153chatsDebounceTimeout.cancel();154if (Array.isArray(data)) {155const contacts = [];156const chats = data.map(({ attrs }) => {157const id = (0, WABinary_1.jidNormalizedUser)(attrs.jid);158if (attrs.name) {159contacts.push({ id, name: attrs.name });160}161return {162id: (0, WABinary_1.jidNormalizedUser)(attrs.jid),163conversationTimestamp: attrs.t ? +attrs.t : undefined,164unreadCount: +attrs.count,165archive: attrs.archive === 'true' ? true : undefined,166pin: attrs.pin ? +attrs.pin : undefined,167mute: attrs.mute ? +attrs.mute : undefined,168notSpam: !(attrs.spam === 'true'),169name: attrs.name,170ephemeralExpiration: attrs.ephemeral ? +attrs.ephemeral : undefined,171ephemeralSettingTimestamp: attrs.eph_setting_ts ? +attrs.eph_setting_ts : undefined,172readOnly: attrs.read_only === 'true' ? true : undefined,173};174});175logger.info(`got ${chats.length} chats, extracted ${contacts.length} contacts with name`);176ev.emit('chats.set', { chats, isLatest: true });177}178});179// got all contacts from phone180socketEvents.on('CB:response,type:contacts', async ({ content: data }) => {181if (Array.isArray(data)) {182const contacts = data.map(({ attrs }) => {183return {184id: (0, WABinary_1.jidNormalizedUser)(attrs.jid),185name: attrs.name,186notify: attrs.notify,187verifiedName: attrs.verify === '2' ? attrs.vname : undefined188};189});190logger.info(`got ${contacts.length} contacts`);191ev.emit('contacts.set', { contacts, isLatest: true });192}193});194// status updates195socketEvents.on('CB:Status,status', json => {196const id = (0, WABinary_1.jidNormalizedUser)(json[1].id);197ev.emit('contacts.update', [{ id, status: json[1].status }]);198});199// User Profile Name Updates200socketEvents.on('CB:Conn,pushname', json => {201const { legacy, connection } = state;202const { user } = legacy;203if (connection === 'open' && json[1].pushname !== user.name) {204user.name = json[1].pushname;205ev.emit('connection.update', { legacy: { ...legacy, user } });206}207});208// read updates209socketEvents.on('CB:action,,read', async ({ content }) => {210if (Array.isArray(content)) {211const { attrs } = content[0];212const update = {213id: (0, WABinary_1.jidNormalizedUser)(attrs.jid)214};215if (attrs.type === 'false') {216update.unreadCount = -1;217}218else {219update.unreadCount = 0;220}221ev.emit('chats.update', [update]);222}223});224socketEvents.on('CB:Cmd,type:picture', async (json) => {225json = json[1];226const id = (0, WABinary_1.jidNormalizedUser)(json.jid);227const imgUrl = await profilePictureUrl(id).catch(() => '');228ev.emit('contacts.update', [{ id, imgUrl }]);229});230// chat archive, pin etc.231socketEvents.on('CB:action,,chat', ({ content }) => {232if (Array.isArray(content)) {233const [node] = content;234executeChatModification(node);235}236});237socketEvents.on('CB:action,,user', (json) => {238if (Array.isArray(json.content)) {239const user = json.content[0].attrs;240if (user.id) {241user.id = (0, WABinary_1.jidNormalizedUser)(user.id);242//ev.emit('contacts.upsert', [user])243}244else {245logger.warn({ json }, 'recv unknown action');246}247}248});249// presence updates250socketEvents.on('CB:Presence', json => {251const update = applyingPresenceUpdate(json[1]);252ev.emit('presence.update', update);253});254// blocklist updates255socketEvents.on('CB:Blocklist', json => {256json = json[1];257const blocklist = json.blocklist;258ev.emit('blocklist.set', { blocklist });259});260socketEvents.on('ws-close', () => {261chatsDebounceTimeout.cancel();262});263return {264...sock,265sendChatsQuery,266profilePictureUrl,267chatRead,268/**269* Modify a given chat (archive, pin etc.)270* @param jid the ID of the person/group you are modifiying271*/272chatModify: async (modification, jid, chatInfo, timestampNow) => {273const chatAttrs = { jid: jid };274let data = undefined;275timestampNow = timestampNow || (0, generics_1.unixTimestampSeconds)();276const getIndexKey = (list) => {277var _a, _b, _c;278if (Array.isArray(list)) {279return list[list.length - 1].key;280}281return (_c = (_a = list.messages) === null || _a === void 0 ? void 0 : _a[((_b = list.messages) === null || _b === void 0 ? void 0 : _b.length) - 1]) === null || _c === void 0 ? void 0 : _c.key;282};283if ('archive' in modification) {284chatAttrs.type = modification.archive ? 'archive' : 'unarchive';285}286else if ('pin' in modification) {287chatAttrs.type = 'pin';288if (modification.pin) {289chatAttrs.pin = timestampNow.toString();290}291else {292chatAttrs.previous = chatInfo.pin.toString();293}294}295else if ('mute' in modification) {296chatAttrs.type = 'mute';297if (modification.mute) {298chatAttrs.mute = (timestampNow + modification.mute).toString();299}300else {301chatAttrs.previous = chatInfo.mute.toString();302}303}304else if ('clear' in modification) {305chatAttrs.type = 'clear';306chatAttrs.modify_tag = Math.round(Math.random() * 1000000).toString();307if (modification.clear !== 'all') {308data = modification.clear.messages.map(({ id, fromMe }) => ({309tag: 'item',310attrs: { owner: (!!fromMe).toString(), index: id }311}));312}313}314else if ('star' in modification) {315chatAttrs.type = modification.star.star ? 'star' : 'unstar';316data = modification.star.messages.map(({ id, fromMe }) => ({317tag: 'item',318attrs: { owner: (!!fromMe).toString(), index: id }319}));320}321else if ('markRead' in modification) {322const indexKey = getIndexKey(modification.lastMessages);323return chatRead(indexKey, modification.markRead ? 0 : -1);324}325else if ('delete' in modification) {326chatAttrs.type = 'delete';327}328if ('lastMessages' in modification) {329const indexKey = getIndexKey(modification.lastMessages);330if (indexKey) {331chatAttrs.index = indexKey.id;332chatAttrs.owner = indexKey.fromMe ? 'true' : 'false';333}334}335const node = { tag: 'chat', attrs: chatAttrs, content: data };336const response = await setQuery([node], [Types_1.WAMetric.chat, Types_1.WAFlag.ignore]);337if (config.emitOwnEvents) {338// apply it and emit events339executeChatModification(node);340}341return response;342},343/**344* Query whether a given number is registered on WhatsApp345* @param str phone number/jid you want to check for346* @returns undefined if the number doesn't exists, otherwise the correctly formatted jid347*/348onWhatsApp: async (str) => {349const { status, jid, biz } = await query({350json: ['query', 'exist', str],351requiresPhoneConnection: false352});353if (status === 200) {354return {355exists: true,356jid: (0, WABinary_1.jidNormalizedUser)(jid),357isBusiness: biz358};359}360},361/**362* Tell someone about your presence -- online, typing, offline etc.363* @param jid the ID of the person/group who you are updating364* @param type your presence365*/366sendPresenceUpdate: (type, toJid) => (sendNode({367binaryTag: [Types_1.WAMetric.presence, Types_1.WAFlag[type]],368json: {369tag: 'action',370attrs: { epoch: currentEpoch().toString(), type: 'set' },371content: [372{373tag: 'presence',374attrs: { type: type, to: toJid }375}376]377}378})),379/**380* Request updates on the presence of a user381* this returns nothing, you'll receive updates in chats.update event382* */383presenceSubscribe: async (jid) => (sendNode({ json: ['action', 'presence', 'subscribe', jid] })),384/** Query the status of the person (see groupMetadata() for groups) */385getStatus: async (jid) => {386const status = await query({ json: ['query', 'Status', jid], requiresPhoneConnection: false });387return status;388},389setStatus: async (status) => {390const response = await setQuery([391{392tag: 'status',393attrs: {},394content: Buffer.from(status, 'utf-8')395}396]);397ev.emit('contacts.update', [{ id: state.legacy.user.id, status }]);398return response;399},400/** Updates business profile. */401updateBusinessProfile: async (profile) => {402var _a;403if ((_a = profile.business_hours) === null || _a === void 0 ? void 0 : _a.config) {404profile.business_hours.business_config = profile.business_hours.config;405delete profile.business_hours.config;406}407const json = ['action', 'editBusinessProfile', { ...profile, v: 2 }];408await query({ json, expect200: true, requiresPhoneConnection: true });409},410updateProfileName: async (name) => {411const response = (await setQuery([412{413tag: 'profile',414attrs: { name }415}416]));417if (config.emitOwnEvents) {418const user = { ...state.legacy.user, name };419ev.emit('connection.update', { legacy: {420...state.legacy, user421} });422ev.emit('contacts.update', [{ id: user.id, name }]);423}424return response;425},426/**427* Update the profile picture428* @param jid429* @param img430*/431async updateProfilePicture(jid, imgBuffer) {432var _a;433jid = (0, WABinary_1.jidNormalizedUser)(jid);434const { img } = await (0, Utils_1.generateProfilePicture)(imgBuffer);435const tag = this.generateMessageTag();436const query = {437tag: 'picture',438attrs: { jid: jid, id: tag, type: 'set' },439content: [440{ tag: 'image', attrs: {}, content: img },441{ tag: 'preview', attrs: {}, content: img }442]443};444const user = (_a = state.legacy) === null || _a === void 0 ? void 0 : _a.user;445const { eurl } = await this.setQuery([query], [Types_1.WAMetric.picture, 136], tag);446if (config.emitOwnEvents) {447if (jid === (user === null || user === void 0 ? void 0 : user.id)) {448user.imgUrl = eurl;449ev.emit('connection.update', {450legacy: {451...state.legacy,452user453}454});455}456ev.emit('contacts.update', [{ id: jid, imgUrl: eurl }]);457}458},459/**460* Add or remove user from blocklist461* @param jid the ID of the person who you are blocking/unblocking462* @param type type of operation463*/464blockUser: async (jid, type = 'add') => {465const json = {466tag: 'block',467attrs: { type },468content: [{ tag: 'user', attrs: { jid } }]469};470await setQuery([json], [Types_1.WAMetric.block, Types_1.WAFlag.ignore]);471if (config.emitOwnEvents) {472ev.emit('blocklist.update', { blocklist: [jid], type });473}474},475/**476* Query Business Profile (Useful for VCards)477* @param jid Business Jid478* @returns profile object or undefined if not business account479*/480getBusinessProfile: async (jid) => {481jid = (0, WABinary_1.jidNormalizedUser)(jid);482const { profiles: [{ profile, wid }] } = await query({483json: [484'query', 'businessProfile',485[{ 'wid': jid.replace('@s.whatsapp.net', '@c.us') }],48684487],488expect200: true,489requiresPhoneConnection: false,490});491return {492...profile,493wid: (0, WABinary_1.jidNormalizedUser)(wid)494};495}496};497};498exports.default = makeChatsSocket;499500501