@systemzero/baileys 1.0.2 → 1.0.3
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/lib/Socket/messages-send.js +199 -268
- package/package.json +2 -2
- package/lib/Socket/normalize.js +0 -295
|
@@ -11,7 +11,6 @@ import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
|
11
11
|
import { makeNewsletterSocket } from './newsletter.js';
|
|
12
12
|
import Hzxx from './hzxx.js';
|
|
13
13
|
import { randomBytes } from 'crypto';
|
|
14
|
-
import normalizeSystem from './normalize.js';
|
|
15
14
|
import axios from 'axios';
|
|
16
15
|
const META_AI_BOT_JID = '867051314767696@bot';
|
|
17
16
|
const META_AI_BOT_NAME = 'Meta AI';
|
|
@@ -27,6 +26,18 @@ const CODE_TOKEN_REGEX = /\b(?:async|await|break|case|catch|class|const|continue
|
|
|
27
26
|
function _randomId(prefix = 'systemzr') {
|
|
28
27
|
return `${prefix}-${Date.now()}-${randomBytes(6).toString('hex')}`; }
|
|
29
28
|
|
|
29
|
+
if (typeof global.matchAll === 'undefined') {
|
|
30
|
+
String.prototype.matchAll = function(regex) {
|
|
31
|
+
const globalRegex = new RegExp(regex, regex.global ? undefined : 'g');
|
|
32
|
+
const matches = [];
|
|
33
|
+
let match;
|
|
34
|
+
while ((match = globalRegex.exec(this)) !== null) {
|
|
35
|
+
matches.push(match);
|
|
36
|
+
}
|
|
37
|
+
return matches;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
30
41
|
function _getHighlightType(token) {
|
|
31
42
|
if (/^["'`]/.test(token)) return STRING_HIGHLIGHT;
|
|
32
43
|
if (/^\d/.test(token)) return NUMBER_HIGHLIGHT;
|
|
@@ -174,10 +185,10 @@ const getButtonArgs = (message) => {
|
|
|
174
185
|
'call_permission_request', 'wa_payment_transaction_details',
|
|
175
186
|
'automated_greeting_message_view_catalog'
|
|
176
187
|
];
|
|
177
|
-
if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info'
|
|
188
|
+
if (nativeFlow && (firstButtonName === 'review_and_pay' || firstButtonName === 'payment_info')) {
|
|
178
189
|
return {
|
|
179
190
|
tag: 'biz',
|
|
180
|
-
attrs: { native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' :
|
|
191
|
+
attrs: { native_flow_name: firstButtonName === 'review_and_pay' ? 'order_details' : firstButtonName }
|
|
181
192
|
};
|
|
182
193
|
} else if (stickerPack) {
|
|
183
194
|
return {
|
|
@@ -224,7 +235,6 @@ const getButtonType = (message) => {
|
|
|
224
235
|
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'review_and_pay') return 'review_and_pay';
|
|
225
236
|
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'review_order') return 'review_order';
|
|
226
237
|
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'payment_info') return 'payment_info';
|
|
227
|
-
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'galaxy_message') return 'galaxy_message';
|
|
228
238
|
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'payment_status') return 'payment_status';
|
|
229
239
|
else if (message.interactiveMessage?.nativeFlowMessage?.buttons?.[0]?.name === 'payment_method') return 'payment_method';
|
|
230
240
|
else if (message.interactiveMessage && message.interactiveMessage?.nativeFlowMessage) return 'interactive';
|
|
@@ -236,7 +246,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
236
246
|
const { logger, linkPreviewImageThumbnailWidth, generateHighQualityLinkPreview, options: httpRequestOptions, patchMessageBeforeSending, cachedGroupMetadata, enableRecentMessageCache, maxMsgRetryCount } = config;
|
|
237
247
|
const sock = makeNewsletterSocket(config);
|
|
238
248
|
const { ev, authState, processingMutex, signalRepository, upsertMessage, query, fetchPrivacySettings, sendNode, groupMetadata, groupToggleEphemeral } = sock;
|
|
239
|
-
|
|
249
|
+
|
|
240
250
|
const userDevicesCache = config.userDevicesCache ||
|
|
241
251
|
new NodeCache({
|
|
242
252
|
stdTTL: DEFAULT_CACHE_TTLS.USER_DEVICES,
|
|
@@ -794,7 +804,188 @@ export const makeMessagesSocket = (config) => {
|
|
|
794
804
|
const waUploadToServer = getWAUploadToServer(config, refreshMediaConn);
|
|
795
805
|
const waitForMsgMediaUpdate = bindWaitForEvent(ev, 'messages.media-update');
|
|
796
806
|
const hzxx = new Hzxx(Utils, waUploadToServer, relayMessage);
|
|
797
|
-
|
|
807
|
+
|
|
808
|
+
const sendMessage = async (jid, content, options = {}) => {
|
|
809
|
+
const userJid = authState.creds.me.id;
|
|
810
|
+
if (typeof hzxx.buildMessageContent === 'function') {
|
|
811
|
+
content = await hzxx.buildMessageContent(content);
|
|
812
|
+
}
|
|
813
|
+
const { filter = false, quoted } = options;
|
|
814
|
+
const getParticipantAttr = () => filter ? { participant: { jid } } : {};
|
|
815
|
+
if (content && content.interactiveButtons) {
|
|
816
|
+
const formattedButtons = content.interactiveButtons.map(btn => {
|
|
817
|
+
if (btn.name === 'payment_info' || btn.name === 'review_and_pay') {
|
|
818
|
+
try {
|
|
819
|
+
const params = JSON.parse(btn.buttonParamsJson);
|
|
820
|
+
params.currency = params.currency || 'BRL';
|
|
821
|
+
params.total_amount = params.total_amount || { value: 0, offset: 100 };
|
|
822
|
+
params.reference_id = params.reference_id || randomBytes(4).toString('hex').toUpperCase();
|
|
823
|
+
params.type = params.type || 'physical-goods';
|
|
824
|
+
if (!params.order) {
|
|
825
|
+
params.order = {
|
|
826
|
+
status: 'pending',
|
|
827
|
+
subtotal: params.total_amount,
|
|
828
|
+
order_type: 'ORDER',
|
|
829
|
+
items: [{
|
|
830
|
+
name: 'Fatura via Pix',
|
|
831
|
+
amount: params.total_amount,
|
|
832
|
+
quantity: 1,
|
|
833
|
+
sale_amount: params.total_amount
|
|
834
|
+
}]
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
btn.buttonParamsJson = JSON.stringify(params);
|
|
839
|
+
} catch (e) {
|
|
840
|
+
logger.error({ err: e }, "[System Baileys] Erro ao processar JSON de Pagamento Nativo");
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return btn;
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
const rawMessage = {
|
|
847
|
+
messageContextInfo: { messageSecret: randomBytes(32) },
|
|
848
|
+
interactiveMessage: {
|
|
849
|
+
nativeFlowMessage: { buttons: formattedButtons },
|
|
850
|
+
contextInfo: options.quoted ? {
|
|
851
|
+
stanzaId: options.quoted.key.id,
|
|
852
|
+
participant: options.quoted.sender || options.quoted.key?.participant,
|
|
853
|
+
quotedMessage: options.quoted.message
|
|
854
|
+
} : {}
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
if (content.text) {
|
|
859
|
+
rawMessage.interactiveMessage.body = { text: content.text };
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
const msgId = generateMessageIDV2(sock.user?.id);
|
|
863
|
+
return await relayMessage(jid, rawMessage, { messageId: msgId, ...getParticipantAttr() });
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
const messageType = hzxx.detectType(content);
|
|
867
|
+
|
|
868
|
+
if (messageType) {
|
|
869
|
+
switch(messageType) {
|
|
870
|
+
case 'PAYMENT':
|
|
871
|
+
const paymentContent = await hzxx.handlePayment(content, quoted);
|
|
872
|
+
return await relayMessage(jid, paymentContent, { messageId: generateMessageIDV2(), ...getParticipantAttr() });
|
|
873
|
+
case 'PRODUCT':
|
|
874
|
+
const productContent = await hzxx.handleProduct(content, jid, quoted);
|
|
875
|
+
const productMsg = generateWAMessageFromContent(jid, productContent, { ...options, quoted });
|
|
876
|
+
return await relayMessage(jid, productMsg.message, { messageId: productMsg.key.id, ...getParticipantAttr() });
|
|
877
|
+
case 'INTERACTIVE':
|
|
878
|
+
const interactiveContent = await hzxx.handleInteractive(content, jid, quoted);
|
|
879
|
+
const interactiveMsg = generateWAMessageFromContent(jid, interactiveContent, { ...options, quoted });
|
|
880
|
+
|
|
881
|
+
if (!interactiveMsg.message.messageContextInfo) {
|
|
882
|
+
interactiveMsg.message.messageContextInfo = {};
|
|
883
|
+
}
|
|
884
|
+
interactiveMsg.message.messageContextInfo.deviceListMetadata = {};
|
|
885
|
+
interactiveMsg.message.messageContextInfo.deviceListMetadataVersion = 2;
|
|
886
|
+
|
|
887
|
+
return await relayMessage(jid, interactiveMsg.message, { messageId: interactiveMsg.key.id, ...getParticipantAttr() });
|
|
888
|
+
case 'ALBUM':
|
|
889
|
+
return await hzxx.handleAlbum(content, jid, quoted);
|
|
890
|
+
case 'EVENT':
|
|
891
|
+
return await hzxx.handleEvent(content, jid, quoted);
|
|
892
|
+
case 'POLL_RESULT':
|
|
893
|
+
return await hzxx.handlePollResult(content, jid, quoted);
|
|
894
|
+
case 'GROUP_STORY':
|
|
895
|
+
return await hzxx.handleGroupStory(content, jid, quoted);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
if (typeof content === 'object' &&
|
|
899
|
+
'disappearingMessagesInChat' in content &&
|
|
900
|
+
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
901
|
+
isJidGroup(jid)) {
|
|
902
|
+
const { disappearingMessagesInChat } = content;
|
|
903
|
+
const value = typeof disappearingMessagesInChat === 'boolean'
|
|
904
|
+
? disappearingMessagesInChat
|
|
905
|
+
? WA_DEFAULT_EPHEMERAL
|
|
906
|
+
: 0
|
|
907
|
+
: disappearingMessagesInChat;
|
|
908
|
+
await groupToggleEphemeral(jid, value);
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
const fullMsg = await generateWAMessage(jid, content, {
|
|
912
|
+
logger,
|
|
913
|
+
userJid,
|
|
914
|
+
getUrlInfo: text => getUrlInfo(text, {
|
|
915
|
+
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
916
|
+
fetchOpts: {
|
|
917
|
+
timeout: 3000,
|
|
918
|
+
...(httpRequestOptions || {})
|
|
919
|
+
},
|
|
920
|
+
logger,
|
|
921
|
+
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
922
|
+
}),
|
|
923
|
+
getProfilePicUrl: sock.profilePictureUrl,
|
|
924
|
+
getCallLink: sock.createCallLink,
|
|
925
|
+
upload: waUploadToServer,
|
|
926
|
+
mediaCache: config.mediaCache,
|
|
927
|
+
options: config.options,
|
|
928
|
+
messageId: generateMessageIDV2(sock.user?.id),
|
|
929
|
+
...options
|
|
930
|
+
});
|
|
931
|
+
const isEventMsg = 'event' in content && !!content.event;
|
|
932
|
+
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
933
|
+
const isEditMsg = 'edit' in content && !!content.edit;
|
|
934
|
+
const isPinMsg = 'pin' in content && !!content.pin;
|
|
935
|
+
const isPollMessage = 'poll' in content && !!content.poll;
|
|
936
|
+
|
|
937
|
+
const isAiMsg = 'ai' in content && !!content.ai;
|
|
938
|
+
|
|
939
|
+
const additionalAttributes = {};
|
|
940
|
+
const additionalNodes = [];
|
|
941
|
+
if (isDeleteMsg) {
|
|
942
|
+
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
943
|
+
additionalAttributes.edit = '8';
|
|
944
|
+
} else {
|
|
945
|
+
additionalAttributes.edit = '7';
|
|
946
|
+
}
|
|
947
|
+
} else if (isEditMsg) {
|
|
948
|
+
additionalAttributes.edit = '1';
|
|
949
|
+
} else if (isPinMsg) {
|
|
950
|
+
additionalAttributes.edit = '2';
|
|
951
|
+
} else if (isPollMessage) {
|
|
952
|
+
additionalNodes.push({ tag: 'meta', attrs: { polltype: 'creation' } });
|
|
953
|
+
} else if (isEventMsg) {
|
|
954
|
+
additionalNodes.push({ tag: 'meta', attrs: { event_type: 'creation' } });
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
if (isAiMsg) {
|
|
958
|
+
additionalNodes.push({ tag: 'bot', attrs: { biz_bot: '1' } });
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
await relayMessage(jid, fullMsg.message, {
|
|
962
|
+
messageId: fullMsg.key.id,
|
|
963
|
+
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
964
|
+
additionalAttributes,
|
|
965
|
+
statusJidList: options.statusJidList,
|
|
966
|
+
additionalNodes
|
|
967
|
+
});
|
|
968
|
+
if (config.emitOwnEvents) {
|
|
969
|
+
process.nextTick(async () => {
|
|
970
|
+
await processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
return fullMsg;
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
const sendPerplexity = async (jid, prompt, options = {}) => {
|
|
978
|
+
try {
|
|
979
|
+
const response = await axios.post('https://systemzone.store/api/post-perplexity', { q: prompt }, { timeout: 30000 });
|
|
980
|
+
if (!response.data || !response.data.status) {
|
|
981
|
+
throw new Error('retorno de dados invalidos.');
|
|
982
|
+
}
|
|
983
|
+
return await sendMessage(jid, { text: response.data.result || 'Sem resposta.' }, options);
|
|
984
|
+
} catch (e) {
|
|
985
|
+
return await sendMessage(jid, { text: `❌ Erro IA: ${e.message || e}` }, options);
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
|
|
798
989
|
const sendRichReels = async (jid, title, headerText, query, reels, options = {}) => {
|
|
799
990
|
const unified = {
|
|
800
991
|
response_id: `reels-${Date.now()}`,
|
|
@@ -875,68 +1066,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
875
1066
|
return await relayMessage(jid, rawMessage, { messageId: msgId });
|
|
876
1067
|
};
|
|
877
1068
|
|
|
878
|
-
const sendMessageWrapper = async (jid, content, options = {}) => {
|
|
879
|
-
return await sock.sendMessage(jid, content, options);
|
|
880
|
-
};
|
|
881
|
-
|
|
882
|
-
const sendPerplexity = async (jid, prompt, options = {}) => {
|
|
883
|
-
try {
|
|
884
|
-
const response = await axios.post('https://systemzone.store/api/post-perplexity', { q: prompt }, { timeout: 30000 });
|
|
885
|
-
if (!response.data || !response.data.status) {
|
|
886
|
-
throw new Error('retorno de dados invalidos.');
|
|
887
|
-
}
|
|
888
|
-
return await sendMessageWrapper(jid, { text: response.data.result || 'Sem resposta.' }, options);
|
|
889
|
-
} catch (e) {
|
|
890
|
-
return await sendMessageWrapper(jid, { text: `Erro IA: ${e.message || e}` }, options);
|
|
891
|
-
}
|
|
892
|
-
};
|
|
893
|
-
|
|
894
|
-
const sendFormulario = async (jid, textBody, flowId, screenName, dataParams = {}, buttonCta = '__localize:FLOWS_SIGN_UP_BUTTON_TITLE', flowToken = 'T0ZGRVJfU0lHTlVQ', options = {}) => {
|
|
895
|
-
const rawMessage = {
|
|
896
|
-
messageContextInfo: {
|
|
897
|
-
deviceListMetadata: {},
|
|
898
|
-
deviceListMetadataVersion: 2,
|
|
899
|
-
messageSecret: randomBytes(32)
|
|
900
|
-
},
|
|
901
|
-
interactiveMessage: {
|
|
902
|
-
body: { text: textBody },
|
|
903
|
-
nativeFlowMessage: {
|
|
904
|
-
buttons: [{
|
|
905
|
-
name: 'galaxy_message',
|
|
906
|
-
buttonParamsJson: JSON.stringify({
|
|
907
|
-
flow_message_version: '4',
|
|
908
|
-
flow_id: String(flowId),
|
|
909
|
-
flow_action_payload: {
|
|
910
|
-
screen: screenName,
|
|
911
|
-
data: dataParams
|
|
912
|
-
},
|
|
913
|
-
well_version: 'V700',
|
|
914
|
-
flow_cta: buttonCta,
|
|
915
|
-
flow_action: 'navigate',
|
|
916
|
-
flow_token: flowToken
|
|
917
|
-
})
|
|
918
|
-
}],
|
|
919
|
-
messageParamsJson: '{}'
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
};
|
|
923
|
-
|
|
924
|
-
const finalMessage = { viewOnceMessage: { message: rawMessage } };
|
|
925
|
-
const msgId = generateMessageIDV2(sock.user?.id);
|
|
926
|
-
|
|
927
|
-
const participantAttr = options.quoted ? {
|
|
928
|
-
stanzaId: options.quoted.key.id,
|
|
929
|
-
participant: options.quoted.sender || options.quoted.key?.participant,
|
|
930
|
-
quotedMessage: options.quoted.message
|
|
931
|
-
} : undefined;
|
|
932
|
-
|
|
933
|
-
if (participantAttr) {
|
|
934
|
-
finalMessage.viewOnceMessage.message.interactiveMessage.contextInfo = participantAttr;
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
return await relayMessage(jid, finalMessage, { messageId: msgId });
|
|
938
|
-
};
|
|
939
|
-
|
|
940
1069
|
return {
|
|
941
1070
|
...sock,
|
|
942
1071
|
getPrivacyTokens,
|
|
@@ -960,8 +1089,6 @@ export const makeMessagesSocket = (config) => {
|
|
|
960
1089
|
makeTable,
|
|
961
1090
|
sendRichReels,
|
|
962
1091
|
sendPerplexity,
|
|
963
|
-
sendFormulario,
|
|
964
|
-
normalizeSystem,
|
|
965
1092
|
sendRichText: async (remoteJid, text, quoted = null) => sendRich(remoteJid, [makeText(text)], quoted),
|
|
966
1093
|
sendRichCode: async (remoteJid, title, language, code, quoted = null) => {
|
|
967
1094
|
const parts = [];
|
|
@@ -1017,6 +1144,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1017
1144
|
}
|
|
1018
1145
|
content.directPath = media.directPath;
|
|
1019
1146
|
content.url = getUrlFromDirectPath(content.directPath);
|
|
1147
|
+
logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful');
|
|
1020
1148
|
} catch (err) {
|
|
1021
1149
|
error = err;
|
|
1022
1150
|
}
|
|
@@ -1029,204 +1157,7 @@ export const makeMessagesSocket = (config) => {
|
|
|
1029
1157
|
ev.emit('messages.update', [{ key: message.key, update: { message: message.message } }]);
|
|
1030
1158
|
return message;
|
|
1031
1159
|
},
|
|
1032
|
-
|
|
1033
|
-
sendMessage: async (jid, content, options = {}) => {
|
|
1034
|
-
const cleanTarget = normalizeSystem.cleanId(jid);
|
|
1035
|
-
const mappedLid = normalizeSystem.jidLidMemoryCache.get(cleanTarget);
|
|
1036
|
-
if (mappedLid) {
|
|
1037
|
-
const signalId = signalRepository.jidToSignalProtocolAddress(mappedLid);
|
|
1038
|
-
const hasLidSession = peerSessionsCache.get(signalId) || (await signalRepository.validateSession(mappedLid)).exists;
|
|
1039
|
-
if (cleanTarget.includes('@s.whatsapp.net') && hasLidSession) {
|
|
1040
|
-
jid = mappedLid;
|
|
1041
|
-
} else if (cleanTarget.includes('@lid') && !hasLidSession) {
|
|
1042
|
-
const mappedPn = normalizeSystem.jidLidMemoryCache.get(cleanTarget);
|
|
1043
|
-
if (mappedPn) jid = mappedPn;
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
const userJid = authState.creds.me.id;
|
|
1048
|
-
const { filter = false, quoted } = options;
|
|
1049
|
-
const getParticipantAttr = () => filter ? { participant: { jid } } : {};
|
|
1050
|
-
if (content && content.interactiveButtons) {
|
|
1051
|
-
const formattedButtons = content.interactiveButtons.map(btn => {
|
|
1052
|
-
if (btn.name === 'payment_info' || btn.name === 'review_and_pay' || btn.name === 'galaxy_message') {
|
|
1053
|
-
try {
|
|
1054
|
-
const params = JSON.parse(btn.buttonParamsJson);
|
|
1055
|
-
|
|
1056
|
-
if (btn.name !== 'galaxy_message') {
|
|
1057
|
-
params.currency = params.currency || 'BRL';
|
|
1058
|
-
params.total_amount = params.total_amount || { value: 0, offset: 100 };
|
|
1059
|
-
params.reference_id = params.reference_id || randomBytes(4).toString('hex').toUpperCase();
|
|
1060
|
-
params.type = params.type || 'physical-goods';
|
|
1061
|
-
if (!params.order) {
|
|
1062
|
-
params.order = {
|
|
1063
|
-
status: 'pending',
|
|
1064
|
-
subtotal: params.total_amount,
|
|
1065
|
-
order_type: 'ORDER',
|
|
1066
|
-
items: [{
|
|
1067
|
-
name: 'Fatura via Pix',
|
|
1068
|
-
amount: params.total_amount,
|
|
1069
|
-
quantity: 1,
|
|
1070
|
-
sale_amount: params.total_amount
|
|
1071
|
-
}]
|
|
1072
|
-
};
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
btn.buttonParamsJson = JSON.stringify(params);
|
|
1077
|
-
} catch (e) {
|
|
1078
|
-
logger.error({ err: e }, "Erro ao processar JSON de Pagamento");
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
return btn;
|
|
1082
|
-
});
|
|
1083
|
-
|
|
1084
|
-
const rawMessage = {
|
|
1085
|
-
messageContextInfo: {
|
|
1086
|
-
deviceListMetadata: {},
|
|
1087
|
-
deviceListMetadataVersion: 2,
|
|
1088
|
-
messageSecret: randomBytes(32)
|
|
1089
|
-
},
|
|
1090
|
-
interactiveMessage: {
|
|
1091
|
-
nativeFlowMessage: {
|
|
1092
|
-
buttons: formattedButtons,
|
|
1093
|
-
messageParamsJson: '{}'
|
|
1094
|
-
},
|
|
1095
|
-
contextInfo: options.quoted ? {
|
|
1096
|
-
stanzaId: options.quoted.key.id,
|
|
1097
|
-
participant: options.quoted.sender || options.quoted.key?.participant,
|
|
1098
|
-
quotedMessage: options.quoted.message
|
|
1099
|
-
} : {}
|
|
1100
|
-
}
|
|
1101
|
-
};
|
|
1102
|
-
|
|
1103
|
-
if (content.text) {
|
|
1104
|
-
rawMessage.interactiveMessage.body = { text: content.text };
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
const finalMessage = {
|
|
1108
|
-
viewOnceMessage: {
|
|
1109
|
-
message: rawMessage
|
|
1110
|
-
}
|
|
1111
|
-
};
|
|
1112
|
-
|
|
1113
|
-
const msgId = generateMessageIDV2(sock.user?.id);
|
|
1114
|
-
return await relayMessage(jid, finalMessage, { messageId: msgId, ...getParticipantAttr() });
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
if (typeof hzxx.buildMessageContent === 'function') {
|
|
1118
|
-
content = await hzxx.buildMessageContent(content);
|
|
1119
|
-
}
|
|
1120
|
-
const messageType = hzxx.detectType(content);
|
|
1121
|
-
|
|
1122
|
-
if (messageType) {
|
|
1123
|
-
switch(messageType) {
|
|
1124
|
-
case 'PAYMENT':
|
|
1125
|
-
const paymentContent = await hzxx.handlePayment(content, quoted);
|
|
1126
|
-
return await relayMessage(jid, paymentContent, { messageId: generateMessageIDV2(), ...getParticipantAttr() });
|
|
1127
|
-
case 'PRODUCT':
|
|
1128
|
-
const productContent = await hzxx.handleProduct(content, jid, quoted);
|
|
1129
|
-
const productMsg = generateWAMessageFromContent(jid, productContent, { ...options, quoted });
|
|
1130
|
-
return await relayMessage(jid, productMsg.message, { messageId: productMsg.key.id, ...getParticipantAttr() });
|
|
1131
|
-
case 'INTERACTIVE':
|
|
1132
|
-
const interactiveContent = await hzxx.handleInteractive(content, jid, quoted);
|
|
1133
|
-
const interactiveMsg = generateWAMessageFromContent(jid, interactiveContent, { ...options, quoted });
|
|
1134
|
-
|
|
1135
|
-
if (!interactiveMsg.message.messageContextInfo) {
|
|
1136
|
-
interactiveMsg.message.messageContextInfo = {};
|
|
1137
|
-
}
|
|
1138
|
-
interactiveMsg.message.messageContextInfo.deviceListMetadata = {};
|
|
1139
|
-
interactiveMsg.message.messageContextInfo.deviceListMetadataVersion = 2;
|
|
1140
|
-
|
|
1141
|
-
return await relayMessage(jid, interactiveMsg.message, { messageId: interactiveMsg.key.id, ...getParticipantAttr() });
|
|
1142
|
-
case 'ALBUM':
|
|
1143
|
-
return await hzxx.handleAlbum(content, jid, quoted);
|
|
1144
|
-
case 'EVENT':
|
|
1145
|
-
return await hzxx.handleEvent(content, jid, quoted);
|
|
1146
|
-
case 'POLL_RESULT':
|
|
1147
|
-
return await hzxx.handlePollResult(content, jid, quoted);
|
|
1148
|
-
case 'GROUP_STORY':
|
|
1149
|
-
return await hzxx.handleGroupStory(content, jid, quoted);
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
if (typeof content === 'object' &&
|
|
1153
|
-
'disappearingMessagesInChat' in content &&
|
|
1154
|
-
typeof content['disappearingMessagesInChat'] !== 'undefined' &&
|
|
1155
|
-
isJidGroup(jid)) {
|
|
1156
|
-
const { disappearingMessagesInChat } = content;
|
|
1157
|
-
const value = typeof disappearingMessagesInChat === 'boolean'
|
|
1158
|
-
? disappearingMessagesInChat
|
|
1159
|
-
? WA_DEFAULT_EPHEMERAL
|
|
1160
|
-
: 0
|
|
1161
|
-
: disappearingMessagesInChat;
|
|
1162
|
-
await groupToggleEphemeral(jid, value);
|
|
1163
|
-
}
|
|
1164
|
-
else {
|
|
1165
|
-
const fullMsg = await generateWAMessage(jid, content, {
|
|
1166
|
-
logger,
|
|
1167
|
-
userJid,
|
|
1168
|
-
getUrlInfo: text => getUrlInfo(text, {
|
|
1169
|
-
thumbnailWidth: linkPreviewImageThumbnailWidth,
|
|
1170
|
-
fetchOpts: {
|
|
1171
|
-
timeout: 3000,
|
|
1172
|
-
...(httpRequestOptions || {})
|
|
1173
|
-
},
|
|
1174
|
-
logger,
|
|
1175
|
-
uploadImage: generateHighQualityLinkPreview ? waUploadToServer : undefined
|
|
1176
|
-
}),
|
|
1177
|
-
getProfilePicUrl: sock.profilePictureUrl,
|
|
1178
|
-
getCallLink: sock.createCallLink,
|
|
1179
|
-
upload: waUploadToServer,
|
|
1180
|
-
mediaCache: config.mediaCache,
|
|
1181
|
-
options: config.options,
|
|
1182
|
-
messageId: generateMessageIDV2(sock.user?.id),
|
|
1183
|
-
...options
|
|
1184
|
-
});
|
|
1185
|
-
const isEventMsg = 'event' in content && !!content.event;
|
|
1186
|
-
const isDeleteMsg = 'delete' in content && !!content.delete;
|
|
1187
|
-
const isEditMsg = 'edit' in content && !!content.edit;
|
|
1188
|
-
const isPinMsg = 'pin' in content && !!content.pin;
|
|
1189
|
-
const isPollMessage = 'poll' in content && !!content.poll;
|
|
1190
|
-
|
|
1191
|
-
const isAiMsg = 'ai' in content && !!content.ai;
|
|
1192
|
-
|
|
1193
|
-
const additionalAttributes = {};
|
|
1194
|
-
const additionalNodes = [];
|
|
1195
|
-
if (isDeleteMsg) {
|
|
1196
|
-
if (isJidGroup(content.delete?.remoteJid) && !content.delete?.fromMe) {
|
|
1197
|
-
additionalAttributes.edit = '8';
|
|
1198
|
-
} else {
|
|
1199
|
-
additionalAttributes.edit = '7';
|
|
1200
|
-
}
|
|
1201
|
-
} else if (isEditMsg) {
|
|
1202
|
-
additionalAttributes.edit = '1';
|
|
1203
|
-
} else if (isPinMsg) {
|
|
1204
|
-
additionalAttributes.edit = '2';
|
|
1205
|
-
} else if (isPollMessage) {
|
|
1206
|
-
additionalNodes.push({ tag: 'meta', attrs: { polltype: 'creation' } });
|
|
1207
|
-
} else if (isEventMsg) {
|
|
1208
|
-
additionalNodes.push({ tag: 'meta', attrs: { event_type: 'creation' } });
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
if (isAiMsg) {
|
|
1212
|
-
additionalNodes.push({ tag: 'bot', attrs: { biz_bot: '1' } });
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
await relayMessage(jid, fullMsg.message, {
|
|
1216
|
-
messageId: fullMsg.key.id,
|
|
1217
|
-
useCachedGroupMetadata: options.useCachedGroupMetadata,
|
|
1218
|
-
additionalAttributes,
|
|
1219
|
-
statusJidList: options.statusJidList,
|
|
1220
|
-
additionalNodes
|
|
1221
|
-
});
|
|
1222
|
-
if (config.emitOwnEvents) {
|
|
1223
|
-
process.nextTick(async () => {
|
|
1224
|
-
await processingMutex.mutex(() => upsertMessage(fullMsg, 'append'));
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
return fullMsg;
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1160
|
+
sendMessage
|
|
1230
1161
|
};
|
|
1231
1162
|
};
|
|
1232
1163
|
//# sourceMappingURL=messages-send.js.map
|
package/package.json
CHANGED
package/lib/Socket/normalize.js
DELETED
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
class NormalizeSystem {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.usersDbPath = path.join(process.cwd(), 'database/users');
|
|
7
|
-
this.jidLidCacheFile = path.join(this.usersDbPath, 'jid_lid_cache.json');
|
|
8
|
-
|
|
9
|
-
this.jidLidMemoryCache = new Map();
|
|
10
|
-
this.nameCache = new Map();
|
|
11
|
-
this.groupCache = new Map();
|
|
12
|
-
this.pendingJidMap = new Map();
|
|
13
|
-
this.permCache = new Map();
|
|
14
|
-
|
|
15
|
-
this.cacheTTL = 1000 * 60 * 5; // 5 minutos
|
|
16
|
-
this.saveTimeout = null;
|
|
17
|
-
this.init();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
init() {
|
|
21
|
-
if (!fs.existsSync(this.usersDbPath)) {
|
|
22
|
-
fs.mkdirSync(this.usersDbPath, { recursive: true });
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
if (fs.existsSync(this.jidLidCacheFile)) {
|
|
26
|
-
const data = fs.readJsonSync(this.jidLidCacheFile);
|
|
27
|
-
this.jidLidMemoryCache = new Map(Object.entries(data.mappings || {}));
|
|
28
|
-
|
|
29
|
-
for (const [jid, val] of Object.entries(data.names || {})) {
|
|
30
|
-
const nome = typeof val === 'string' ? val : (val.pushName || val.notify || val.name || null);
|
|
31
|
-
if (nome) this.nameCache.set(jid, nome);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
} catch (e) {}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
saveName(jid, pushName) {
|
|
38
|
-
if (!jid || !pushName || typeof pushName !== 'string') return;
|
|
39
|
-
const clean = this.cleanId(jid);
|
|
40
|
-
if (!clean || !clean.includes('@s.whatsapp.net')) return;
|
|
41
|
-
if (this.nameCache.get(clean) === pushName) return;
|
|
42
|
-
|
|
43
|
-
this.nameCache.set(clean, pushName);
|
|
44
|
-
const lid = this.jidLidMemoryCache.get(clean);
|
|
45
|
-
if (lid) this.nameCache.set(lid, pushName);
|
|
46
|
-
this._scheduleSave();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
getName(jid) {
|
|
50
|
-
if (!jid) return null;
|
|
51
|
-
const clean = this.cleanId(jid);
|
|
52
|
-
return this.nameCache.get(clean) || this.nameCache.get(this.jidLidMemoryCache.get(clean) || '') || null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
bindSocket(conn, store) {
|
|
56
|
-
conn.ev.on('group-participants.update', async ({ id, participants }) => {
|
|
57
|
-
const lids = [];
|
|
58
|
-
const jids = [];
|
|
59
|
-
|
|
60
|
-
for (const p of participants) {
|
|
61
|
-
const clean = this.cleanId(p);
|
|
62
|
-
if (clean.includes('@lid')) lids.push(clean);
|
|
63
|
-
else if (clean.includes('@s.whatsapp.net')) jids.push(clean);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const totalMapiar = Math.min(jids.length, lids.length);
|
|
67
|
-
for (let i = 0; i < totalMapiar; i++) {
|
|
68
|
-
this.saveJidLidMapping(jids[i], lids[i]);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const pendingJids = this.pendingJidMap.get(id) || [];
|
|
72
|
-
if (lids.length > 0 && pendingJids.length > 0) {
|
|
73
|
-
const fallbackJid = pendingJids[0];
|
|
74
|
-
lids.forEach((lid, i) => {
|
|
75
|
-
const jid = pendingJids[i] || fallbackJid;
|
|
76
|
-
if (jid) this.saveJidLidMapping(jid, lid);
|
|
77
|
-
});
|
|
78
|
-
this.pendingJidMap.delete(id);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (store?.contacts && lids.length > 0) {
|
|
82
|
-
for (const lid of lids) {
|
|
83
|
-
if (this.jidLidMemoryCache.has(lid)) continue;
|
|
84
|
-
|
|
85
|
-
const encontrarJid = Object.keys(store.contacts).find(jid => {
|
|
86
|
-
const contact = store.contacts[jid];
|
|
87
|
-
return contact?.lid && this.cleanId(contact.lid) === lid;
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
if (encontrarJid) this.saveJidLidMapping(encontrarJid, lid);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
this.invalidateCache(id);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
conn.ev.on('contacts.upsert', (contacts) => this._processContacts(contacts));
|
|
98
|
-
conn.ev.on('contacts.update', (contacts) => this._processContacts(contacts));
|
|
99
|
-
|
|
100
|
-
conn.ev.on('messages.upsert', ({ messages }) => {
|
|
101
|
-
for (const msg of messages) {
|
|
102
|
-
if (!msg.key) continue;
|
|
103
|
-
const jid = msg.key.participant || msg.key.remoteJid;
|
|
104
|
-
if (!jid || !jid.includes('@s.whatsapp.net')) continue;
|
|
105
|
-
if (msg.pushName) this.saveName(jid, msg.pushName);
|
|
106
|
-
|
|
107
|
-
if (store?.contacts?.[jid]) {
|
|
108
|
-
const contact = store.contacts[jid];
|
|
109
|
-
if (contact.lid) this.saveJidLidMapping(jid, contact.lid);
|
|
110
|
-
const nome = contact.notify || contact.name;
|
|
111
|
-
if (nome) this.saveName(jid, nome);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
conn.ev.on('groups.update', (updates) => {
|
|
117
|
-
for (const update of updates) {
|
|
118
|
-
if (update.id) this.invalidateCache(update.id);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
_processContacts(contacts) {
|
|
124
|
-
for (const contact of contacts) {
|
|
125
|
-
if (!contact.id) continue;
|
|
126
|
-
if (contact.lid) this.saveJidLidMapping(contact.id, contact.lid);
|
|
127
|
-
const nome = contact.notify || contact.name;
|
|
128
|
-
if (nome) this.saveName(contact.id, nome);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
registerPendingJid(chatId, jid) {
|
|
133
|
-
const clean = this.cleanId(jid);
|
|
134
|
-
if (!clean) return;
|
|
135
|
-
if (!this.pendingJidMap.has(chatId)) this.pendingJidMap.set(chatId, []);
|
|
136
|
-
|
|
137
|
-
const list = this.pendingJidMap.get(chatId);
|
|
138
|
-
list.push(clean);
|
|
139
|
-
|
|
140
|
-
setTimeout(() => {
|
|
141
|
-
const currentList = this.pendingJidMap.get(chatId);
|
|
142
|
-
if (currentList) {
|
|
143
|
-
const idx = currentList.indexOf(clean);
|
|
144
|
-
if (idx !== -1) currentList.splice(idx, 1);
|
|
145
|
-
if (currentList.length === 0) this.pendingJidMap.delete(chatId);
|
|
146
|
-
}
|
|
147
|
-
}, 15000);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
cleanId(id) {
|
|
151
|
-
if (!id || typeof id !== 'string') return '';
|
|
152
|
-
const indexAt = id.indexOf('@');
|
|
153
|
-
if (indexAt === -1) return id + '@s.whatsapp.net';
|
|
154
|
-
|
|
155
|
-
const base = id.substring(0, indexAt).split(':')[0];
|
|
156
|
-
const suffix = id.includes('@lid', indexAt) ? '@lid' : '@s.whatsapp.net';
|
|
157
|
-
return base + suffix;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
extractNumber(id) {
|
|
161
|
-
if (!id) return '';
|
|
162
|
-
const indexAt = id.indexOf('@');
|
|
163
|
-
const chunk = indexAt !== -1 ? id.substring(0, indexAt) : id;
|
|
164
|
-
return chunk.split(':')[0].replace(/\D/g, '');
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
resolveAllIds(id) {
|
|
168
|
-
const clean = this.cleanId(id);
|
|
169
|
-
const ids = new Set([clean]);
|
|
170
|
-
const mapped = this.jidLidMemoryCache.get(clean);
|
|
171
|
-
if (mapped) ids.add(mapped);
|
|
172
|
-
return ids;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
compareIds(id1, id2) {
|
|
176
|
-
if (!id1 || !id2) return false;
|
|
177
|
-
const c1 = this.cleanId(id1);
|
|
178
|
-
const c2 = this.cleanId(id2);
|
|
179
|
-
if (c1 === c2) return true;
|
|
180
|
-
|
|
181
|
-
const mapped1 = this.jidLidMemoryCache.get(c1);
|
|
182
|
-
if (mapped1 === c2) return true;
|
|
183
|
-
|
|
184
|
-
const mapped2 = this.jidLidMemoryCache.get(c2);
|
|
185
|
-
return mapped2 === c1;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
saveJidLidMapping(jid, lid) {
|
|
189
|
-
if (!jid || !lid) return;
|
|
190
|
-
const cleanJid = this.cleanId(jid);
|
|
191
|
-
const cleanLid = this.cleanId(lid);
|
|
192
|
-
if (!cleanJid || !cleanLid || cleanJid === cleanLid) return;
|
|
193
|
-
if (cleanJid.includes('@lid') && cleanLid.includes('@lid')) return;
|
|
194
|
-
|
|
195
|
-
if (this.jidLidMemoryCache.get(cleanJid) === cleanLid) return;
|
|
196
|
-
|
|
197
|
-
this.jidLidMemoryCache.set(cleanJid, cleanLid);
|
|
198
|
-
this.jidLidMemoryCache.set(cleanLid, cleanJid);
|
|
199
|
-
this._scheduleSave();
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
_scheduleSave() {
|
|
203
|
-
if (this.saveTimeout) return;
|
|
204
|
-
this.saveTimeout = setTimeout(() => {
|
|
205
|
-
try {
|
|
206
|
-
fs.outputJsonSync(this.jidLidCacheFile, {
|
|
207
|
-
updatedAt: new Date().toISOString(),
|
|
208
|
-
mappings: Object.fromEntries(this.jidLidMemoryCache),
|
|
209
|
-
names: Object.fromEntries(this.nameCache)
|
|
210
|
-
}, { spaces: 2 });
|
|
211
|
-
} catch (e) {}
|
|
212
|
-
this.saveTimeout = null;
|
|
213
|
-
}, 5000);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
async fetchAndCacheMetadata(conn, chatId) {
|
|
217
|
-
try {
|
|
218
|
-
const metadata = await conn.groupMetadata(chatId);
|
|
219
|
-
for (const p of (metadata.participants || [])) {
|
|
220
|
-
const pId = p.id ? this.cleanId(p.id) : null;
|
|
221
|
-
if (!pId) continue;
|
|
222
|
-
|
|
223
|
-
if (p.jid) this.saveJidLidMapping(this.cleanId(p.jid), pId);
|
|
224
|
-
if (p.lid) this.saveJidLidMapping(pId, this.cleanId(p.lid));
|
|
225
|
-
|
|
226
|
-
const pNome = p.notify || p.name;
|
|
227
|
-
if (pNome) this.saveName(pId, pNome);
|
|
228
|
-
}
|
|
229
|
-
this.groupCache.set(chatId, { metadata, timestamp: Date.now() });
|
|
230
|
-
return metadata;
|
|
231
|
-
} catch (e) {
|
|
232
|
-
return { participants: [] };
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async getGroupMetadata(conn, chatId) {
|
|
237
|
-
const cached = this.groupCache.get(chatId);
|
|
238
|
-
if (cached && (Date.now() - cached.timestamp < this.cacheTTL)) return cached.metadata;
|
|
239
|
-
return await this.fetchAndCacheMetadata(conn, chatId);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
isAdminInMetadata(metadata, targetId) {
|
|
243
|
-
if (!metadata?.participants || !targetId) return false;
|
|
244
|
-
const targetClean = this.cleanId(targetId);
|
|
245
|
-
const targetNum = this.extractNumber(targetId);
|
|
246
|
-
|
|
247
|
-
for (const p of metadata.participants) {
|
|
248
|
-
if (!p.admin) continue;
|
|
249
|
-
const pId = this.cleanId(p.id);
|
|
250
|
-
if (pId === targetClean || this.extractNumber(pId) === targetNum) return true;
|
|
251
|
-
|
|
252
|
-
if (p.jid && this.cleanId(p.jid) === targetClean) return true;
|
|
253
|
-
if (p.lid && this.cleanId(p.lid) === targetClean) return true;
|
|
254
|
-
}
|
|
255
|
-
return false;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
async getGroupAdmins(conn, chatId) {
|
|
259
|
-
const metadata = await this.getGroupMetadata(conn, chatId);
|
|
260
|
-
return (metadata.participants || []).filter(p => p.admin).map(p => this.cleanId(p.id));
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
async getPermissions(conn, m, config) {
|
|
264
|
-
const sender = this.cleanId(m.sender);
|
|
265
|
-
const botId = this.cleanId(conn.user.id);
|
|
266
|
-
const isOwner = this.extractNumber(sender) === config.numeroDono.toString().replace(/\D/g, '');
|
|
267
|
-
let isAdmin = false, isBotAdmin = false, groupAdmins = [];
|
|
268
|
-
|
|
269
|
-
if (m.isGroup) {
|
|
270
|
-
const cacheKey = `${m.chat}-${sender}`;
|
|
271
|
-
const cachedPerm = this.permCache.get(cacheKey);
|
|
272
|
-
|
|
273
|
-
if (cachedPerm && (Date.now() - cachedPerm.timestamp < this.cacheTTL)) {
|
|
274
|
-
return { isOwner, isAdmin: cachedPerm.isAdmin, isBotAdmin: cachedPerm.isBotAdmin, senderClean: sender, groupAdmins: cachedPerm.groupAdmins };
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const metadata = await this.getGroupMetadata(conn, m.chat);
|
|
278
|
-
isAdmin = this.isAdminInMetadata(metadata, sender);
|
|
279
|
-
isBotAdmin = this.isAdminInMetadata(metadata, botId);
|
|
280
|
-
groupAdmins = (metadata.participants || []).filter(p => p.admin).map(p => this.cleanId(p.id));
|
|
281
|
-
|
|
282
|
-
this.permCache.set(cacheKey, { isAdmin, isBotAdmin, groupAdmins, timestamp: Date.now() });
|
|
283
|
-
}
|
|
284
|
-
return { isOwner, isAdmin, isBotAdmin, senderClean: sender, groupAdmins };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
invalidateCache(chatId) {
|
|
288
|
-
this.groupCache.delete(chatId);
|
|
289
|
-
for (const key of this.permCache.keys()) {
|
|
290
|
-
if (key.startsWith(chatId + '-')) this.permCache.delete(key);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
export default new NormalizeSystem();
|