|
|
|
@ -4,6 +4,7 @@ const {
|
|
|
|
DisconnectReason,
|
|
|
|
DisconnectReason,
|
|
|
|
makeCacheableSignalKeyStore,
|
|
|
|
makeCacheableSignalKeyStore,
|
|
|
|
makeInMemoryStore,
|
|
|
|
makeInMemoryStore,
|
|
|
|
|
|
|
|
getMessageFromStore,
|
|
|
|
useMultiFileAuthState,
|
|
|
|
useMultiFileAuthState,
|
|
|
|
downloadMediaMessage,
|
|
|
|
downloadMediaMessage,
|
|
|
|
isJidNewsletter, isJidGroup, isJidBroadcast, isJidStatusBroadcast
|
|
|
|
isJidNewsletter, isJidGroup, isJidBroadcast, isJidStatusBroadcast
|
|
|
|
@ -25,8 +26,8 @@ const createWhatsApp = async phone => {
|
|
|
|
const whatsAppNo = phone;
|
|
|
|
const whatsAppNo = phone;
|
|
|
|
// 缓存 msgId-externalId,过期时间为 5 分钟
|
|
|
|
// 缓存 msgId-externalId,过期时间为 5 分钟
|
|
|
|
const externalIdCache = new NodeCache({ stdTTL: 60*5 });
|
|
|
|
const externalIdCache = new NodeCache({ stdTTL: 60*5 });
|
|
|
|
// 缓存群信息,过期时间为 24 小时
|
|
|
|
// 缓存群信息,过期时间为 5 分钟
|
|
|
|
const groupSubjectCache = new NodeCache({ stdTTL: 60*60*24 });
|
|
|
|
const groupCache = new NodeCache({stdTTL: 5 * 60, useClones: false})
|
|
|
|
const logger = P({ timestamp: () => `,"time":"${new Date().toJSON()}"` }, P.destination('./logs/wa-logs-' + phone + '.txt'));
|
|
|
|
const logger = P({ timestamp: () => `,"time":"${new Date().toJSON()}"` }, P.destination('./logs/wa-logs-' + phone + '.txt'));
|
|
|
|
logger.level = 'warn';
|
|
|
|
logger.level = 'warn';
|
|
|
|
const msgRetryCounterCache = new NodeCache();
|
|
|
|
const msgRetryCounterCache = new NodeCache();
|
|
|
|
@ -76,6 +77,8 @@ const createWhatsApp = async phone => {
|
|
|
|
creds: state.creds,
|
|
|
|
creds: state.creds,
|
|
|
|
keys: makeCacheableSignalKeyStore(state.keys, logger),
|
|
|
|
keys: makeCacheableSignalKeyStore(state.keys, logger),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
cachedGroupMetadata: async (jid) => groupCache.get(jid),
|
|
|
|
|
|
|
|
getMessage: async (key) => await getMessageFromStore(key),
|
|
|
|
// https://github.com/WhiskeySockets/Baileys/blob/master/src/Utils/generics.ts
|
|
|
|
// https://github.com/WhiskeySockets/Baileys/blob/master/src/Utils/generics.ts
|
|
|
|
// https://github.com/WhiskeySockets/Baileys/blob/master/WAProto/WAProto.proto
|
|
|
|
// https://github.com/WhiskeySockets/Baileys/blob/master/WAProto/WAProto.proto
|
|
|
|
// Browsers.macOS('SAFARI'), Browsers.ubuntu('IOS_PHONE'), Browsers.baileys('WEAR_OS'),
|
|
|
|
// Browsers.macOS('SAFARI'), Browsers.ubuntu('IOS_PHONE'), Browsers.baileys('WEAR_OS'),
|
|
|
|
@ -88,6 +91,17 @@ const createWhatsApp = async phone => {
|
|
|
|
|
|
|
|
|
|
|
|
store?.bind(waSocket.ev);
|
|
|
|
store?.bind(waSocket.ev);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getGroupSubject = async jid => {
|
|
|
|
|
|
|
|
const cachedMatadata = groupCache.get(jid);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cachedMatadata === undefined) {
|
|
|
|
|
|
|
|
const groupMetadata = await waSocket.groupMetadata(jid);
|
|
|
|
|
|
|
|
groupCache.set(jid, groupMetadata);
|
|
|
|
|
|
|
|
return groupMetadata.subject;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return cachedMatadata.subject;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
const buildStandardMessage = async msg => {
|
|
|
|
const buildStandardMessage = async msg => {
|
|
|
|
// 如果是群发(xxx@broadcast),participant 是发送人,不然则是 remoteJid
|
|
|
|
// 如果是群发(xxx@broadcast),participant 是发送人,不然则是 remoteJid
|
|
|
|
const remoteNo = isJidBroadcast(msg.key.remoteJid) ? decodeJid(msg.key.participant) : decodeJid(msg.key.remoteJid);
|
|
|
|
const remoteNo = isJidBroadcast(msg.key.remoteJid) ? decodeJid(msg.key.participant) : decodeJid(msg.key.remoteJid);
|
|
|
|
@ -95,12 +109,7 @@ const createWhatsApp = async phone => {
|
|
|
|
const isPersonal = isJidPersonal(msg.key.remoteJid);
|
|
|
|
const isPersonal = isJidPersonal(msg.key.remoteJid);
|
|
|
|
const conversationType = isPersonal ? 'individual' : 'group';
|
|
|
|
const conversationType = isPersonal ? 'individual' : 'group';
|
|
|
|
const isGroup = isJidGroup(msg.key.remoteJid);
|
|
|
|
const isGroup = isJidGroup(msg.key.remoteJid);
|
|
|
|
let groupSubject = groupSubjectCache.get(msg.key.remoteJid);
|
|
|
|
const groupSubject = isGroup ? await getGroupSubject(msg.key.remoteJid) : '';
|
|
|
|
if (isGroup && groupSubject === undefined) {
|
|
|
|
|
|
|
|
const groupMetadata = await waSocket.groupMetadata(msg.key.remoteJid);
|
|
|
|
|
|
|
|
groupSubject = groupMetadata.subject;
|
|
|
|
|
|
|
|
groupSubjectCache.set(msg.key.remoteJid, groupMetadata.subject)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const msgDirection = msg.key.fromMe ? 'outbound' : 'inbound';
|
|
|
|
const msgDirection = msg.key.fromMe ? 'outbound' : 'inbound';
|
|
|
|
const msgFrom = msg.key.fromMe ? whatsAppNo : remoteNo;
|
|
|
|
const msgFrom = msg.key.fromMe ? whatsAppNo : remoteNo;
|
|
|
|
@ -351,6 +360,7 @@ const createWhatsApp = async phone => {
|
|
|
|
).then(msg => {
|
|
|
|
).then(msg => {
|
|
|
|
externalIdCache.set(msg.key.id, externalId)
|
|
|
|
externalIdCache.set(msg.key.id, externalId)
|
|
|
|
}).catch(ex => {
|
|
|
|
}).catch(ex => {
|
|
|
|
|
|
|
|
console.info('sendMessageHandler.catch: ', ex)
|
|
|
|
waEmitter.emit('message:updated', {
|
|
|
|
waEmitter.emit('message:updated', {
|
|
|
|
id: generateId(),
|
|
|
|
id: generateId(),
|
|
|
|
externalId,
|
|
|
|
externalId,
|
|
|
|
@ -398,19 +408,17 @@ const createWhatsApp = async phone => {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (connection === 'open') {
|
|
|
|
} else if (connection === 'open') {
|
|
|
|
|
|
|
|
waEmitter.on('request.' + whatsAppNo + '.send.message', sendMessageHandler);
|
|
|
|
|
|
|
|
waEmitter.on('request.' + whatsAppNo + '.stop', stopHandler);
|
|
|
|
waEmitter.emit('connection:open', {
|
|
|
|
waEmitter.emit('connection:open', {
|
|
|
|
status: 'open', whatsAppNo, channelId,
|
|
|
|
status: 'open', whatsAppNo, channelId,
|
|
|
|
eventSource: serverConfig.name + '.connection.update.open',
|
|
|
|
eventSource: serverConfig.name + '.connection.update.open',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
waEmitter.on('request.' + whatsAppNo + '.send.message', sendMessageHandler);
|
|
|
|
|
|
|
|
waEmitter.on('request.' + whatsAppNo + '.stop', stopHandler);
|
|
|
|
|
|
|
|
} else if (qr !== undefined) {
|
|
|
|
} else if (qr !== undefined) {
|
|
|
|
// WebSocket 创建成功等待扫码,如果没有扫码会更新 qr
|
|
|
|
// WebSocket 创建成功等待扫码,如果没有扫码会更新 qr
|
|
|
|
// 第一次一分钟,后面是 20 秒更新一次
|
|
|
|
// 第一次一分钟,后面是 20 秒更新一次
|
|
|
|
if (qrCode === null) {
|
|
|
|
if (qrCode === null) {
|
|
|
|
qrCode = qr;
|
|
|
|
qrCode = qr;
|
|
|
|
console.info('qrCode:', qrCode)
|
|
|
|
|
|
|
|
waEmitter.emit('creds:update', {
|
|
|
|
waEmitter.emit('creds:update', {
|
|
|
|
id: generateId(),
|
|
|
|
id: generateId(),
|
|
|
|
qr, whatsAppNo,
|
|
|
|
qr, whatsAppNo,
|
|
|
|
@ -428,6 +436,14 @@ const createWhatsApp = async phone => {
|
|
|
|
waSocket.ev.on('creds.update', handleCredsUpdate);
|
|
|
|
waSocket.ev.on('creds.update', handleCredsUpdate);
|
|
|
|
waSocket.ev.on('messages.upsert', handleMessagesUpsert);
|
|
|
|
waSocket.ev.on('messages.upsert', handleMessagesUpsert);
|
|
|
|
waSocket.ev.on('messages.update', handleMessagesUpdate);
|
|
|
|
waSocket.ev.on('messages.update', handleMessagesUpdate);
|
|
|
|
|
|
|
|
waSocket.ev.on('groups.update', async ([event]) => {
|
|
|
|
|
|
|
|
const metadata = await waSocket.groupMetadata(event.id);
|
|
|
|
|
|
|
|
groupCache.set(event.id, metadata);
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
waSocket.ev.on('group-participants.update', async (event) => {
|
|
|
|
|
|
|
|
const metadata = await waSocket.groupMetadata(event.id)
|
|
|
|
|
|
|
|
groupCache.set(event.id, metadata);
|
|
|
|
|
|
|
|
})
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
|