@ -1,13 +1,13 @@
/* eslint-disable no-undef */
const {
makeWASocket ,
WAProto ,
Browsers ,
DisconnectReason ,
fetchLatestBaileysVersion ,
makeCacheableSignalKeyStore ,
makeInMemoryStore ,
useMultiFileAuthState ,
downloadMediaMessage
downloadMediaMessage ,
} = require ( '@whiskeysockets/baileys' ) ;
const { writeFile } = require ( 'fs/promises' ) ;
@ -31,163 +31,256 @@ setInterval(() => {
store ? . writeToFile ( './baileys_store_multi.json' )
} , 10_000 )
// start a connection
const startSock = async ( ) => {
const createWhatsApp = async phone => {
const channelId = phone ;
const whatsAppNo = phone ;
const { state , saveCreds } = await useMultiFileAuthState ( 'baileys_auth_info/' + phone ) ;
// fetch latest version of WA Web
const { version , isLatest } = await fetchLatestBaileysVersion ( ) ;
const waVersion = version . join ( '.' ) + ', ' + ( isLatest ? 'latest' : 'out' ) ;
const channelId = '创建时赋值,唯一标识'
const phone = '手机号'
const createTimestamp = '创建时间戳'
const status = 'close, open, connecting, online'
const waVersion = 'v2.3000.1017531287, latest(out)'
const formatPhoneNumber = number => {
if ( number === null || number === undefined ) return '' ;
const sendTextMessage = ( whatsAppNo , content ) => {
sock . sendMessage ( whatsAppNo + '@s.whatsapp.net' , { text : content } )
}
if ( number . indexOf ( '@g.us' ) > - 1 ) {
return number ;
} else if ( number . indexOf ( '@broadcast' ) > - 1 ) {
return number ;
} else {
return number + '@s.whatsapp.net' ;
}
} ;
const sendImageMessage = ( whatsAppNo , imageUrl ) => {
sock . sendMessage ( whatsAppNo + '@s.whatsapp.net' , {
image : { url : imageUrl } ,
} )
}
const parsePhoneNumber = number => {
if ( number === null || number === undefined ) return '' ;
const { state , saveCreds } = await useMultiFileAuthState ( 'baileys_auth_info' )
// fetch latest version of WA Web
const { version , isLatest } = await fetchLatestBaileysVersion ( )
console . log ( ` using WA v ${ version . join ( '.' ) } , isLatest: ${ isLatest } ` )
const sock = makeWASocket ( {
version ,
logger ,
auth : {
creds : state . creds ,
/** caching makes the store faster to send/recv messages */
keys : makeCacheableSignalKeyStore ( state . keys , logger ) ,
} ,
msgRetryCounterCache ,
generateHighQualityLinkPreview : true ,
} )
sock . ev . on ( 'connection.update' , ( update ) => {
const { connection , lastDisconnect , qr } = update
if ( connection === 'close' ) {
console . info ( '链接断了' )
} else if ( connection === 'open' ) {
console . info ( '扫码成功' )
} else if ( connection === 'connecting' ) {
console . info ( '二维码:' , qr )
if ( number . indexOf ( '@s.whatsapp.net' ) > - 1 ) {
return number . split ( '@' ) [ 0 ] ;
} else {
return number ;
}
} )
sock . ev . on ( 'messages.upsert' , async ( upsert ) => {
console . log ( '收到消息:' , JSON . stringify ( upsert , undefined , 2 ) )
if ( upsert . type === 'notify' ) {
for ( const msg of upsert . messages ) {
const messageType = Object . keys ( msg . message ) [ 0 ]
console . log ( 'messageType' , messageType )
if ( messageType === 'imageMessage' ) {
// download the message
const buffer = await downloadMediaMessage (
msg ,
'buffer' ,
{ } ,
{
logger ,
// pass this so that baileys can request a reupload of media
// that has been deleted
reuploadRequest : sock . updateMediaMessage
}
)
// save to file
await writeFile ( 'd:/my-download.jpeg' , buffer )
} ;
console . log ( 'writeFile' , messageType )
}
// status: sent read delivered failed
// 2 sent, 3 delivered, 4 read, 0 error
// Time: 2008-07-07 15:37:07
const formatStatus = number => {
if ( number === 2 ) return 'sent' ;
else if ( number === 3 ) return 'delivered' ;
else if ( number === 4 ) return 'read' ;
else if ( number === 0 ) return 'error' ;
else return 'played' ;
} ;
const formatTimestamp = timestamp => {
if ( timestamp === null ) return '' ;
if ( msg . message ? . conversation || msg . message ? . extendedTextMessage ? . text ) {
const text = msg . message ? . conversation || msg . message ? . extendedTextMessage ? . text
const datetime = new Date ( timestamp * 1000 ) ;
if ( text . indexOf ( '图片' ) > - 1 ) {
sendImageMessage ( '8617607730395' , 'https://images.asiahighlights.com/allpicture/2022/07/8a7d9ced5936463bb904c82a_cut_750x850_349.webp' )
} else if ( text . indexOf ( '文本' ) > - 1 ) {
sendTextMessage ( '8617607730395' , '文本消息' + new Date ( ) . toString ( ) )
}
}
}
}
} )
return datetime . getFullYear ( ) + '-' + ( datetime . getMonth ( ) + 1 ) + '-' + datetime . getDay ( ) + ' ' + datetime . getHours ( ) + ':' + datetime . getMinutes ( ) + ':' + datetime . getSeconds ( ) ;
} ;
const sendTextMessage = ( whatsAppNo , content ) => {
const number = formatPhoneNumber ( whatsAppNo ) ;
console . info ( 'formatPhoneNumber: ' , number ) ;
waSocket . sendMessage ( number , { text : content } ) ;
} ;
const sendImageMessage = ( whatsAppNo , imageUrl ) => {
const number = formatPhoneNumber ( whatsAppNo ) ;
waSocket . sendMessage ( number , {
image : { url : imageUrl } ,
} ) ;
} ;
let waSocket = null ;
// 不绑定不会影响扫码登录
store ? . bind ( sock . ev )
const start = ( ) => {
return new Promise ( ( resolve , reject ) => {
waSocket = makeWASocket ( {
version ,
logger ,
auth : {
creds : state . creds ,
/** caching makes the store faster to send/recv messages */
keys : makeCacheableSignalKeyStore ( state . keys , logger ) ,
} ,
// https://github.com/WhiskeySockets/Baileys/blob/31bc8ab/src/Utils/generics.ts#L21
browser : Browsers . macOS ( 'Desktop' ) ,
msgRetryCounterCache ,
generateHighQualityLinkPreview : false ,
syncFullHistory : false ,
} ) ;
// the process function lets you process all events that just occurred
// efficiently in a batch
sock . ev . process (
// events is a map for event name => event data
async ( events ) => {
// something about the connection changed
// maybe it closed, or we received all offline message or connection opened
if ( events [ 'connection.update' ] ) {
const update = events [ 'connection.update' ]
const { connection , lastDisconnect , qr } = update
waSocket . ev . on ( 'connection.update' , async update => {
console . log ( 'connection update: ' , update ) ;
const { connection , lastDisconnect , qr } = update ;
if ( connection === 'close' ) {
console . log ( '链接断开:' , lastDisconnect )
console . log ( '链接断开:' , lastDisconnect ) ;
if ( lastDisconnect ? . error ? . output ? . statusCode !== DisconnectReason . loggedOut ) {
start Sock ( )
start ( ) ;
} else {
sock. end ( ( error ) => console . error ( 'end.error: ' , error ) )
sock. logout ( ( msg ) => console . error ( 'logout.msg: ' , msg ) )
console . log ( 'Connection closed. You are logged out.' )
waSocket. end ( error => console . error ( 'end.error: ' , error ) ) ;
waSocket. logout ( msg => console . error ( 'logout.msg: ' , msg ) ) ;
console . log ( 'Connection closed. You are logged out.' ) ;
}
} else if ( connection === 'open' ) {
console . info ( '链接成功' ) ;
waEmitter . emit ( 'connection.open' , waSocket ) ;
} else if ( qr !== undefined ) {
// WebSocket 创建成功等待扫码,如果没有扫码会更新 qr
resolve ( qr ) ;
}
} ) ;
// 扫码成功,可以发送消息
if ( update . connection === 'open' ) {
await sock . sendMessage ( '8617607730395' + '@s.whatsapp.net' , { text : 'OPEN: ' + new Date ( ) . toString ( ) } )
}
waSocket . ev . on ( 'messages.upsert' , async upsert => {
console . log ( '收到消息:' , JSON . stringify ( upsert , undefined , 2 ) ) ;
// WebSocket 创建成功等待扫码,如果没有扫码会更新 qr
if ( update . connection === 'connecting' ) {
// qr
}
if ( upsert . type === 'notify' ) {
for ( const msg of upsert . messages ) {
const messageType = Object . keys ( msg . message ) [ 0 ] ;
console . log ( 'connection update' , update )
}
console . log ( 'messageType' , messageType ) ;
if ( messageType === 'imageMessage' ) {
// download the message
const buffer = await downloadMediaMessage (
msg ,
'buffer' ,
{ } ,
{
logger ,
// pass this so that baileys can request a reupload of media
// that has been deleted
reuploadRequest : waSocket . updateMediaMessage ,
} ,
) ;
// save to file
await writeFile ( 'd:/my-download.jpeg' , buffer ) ;
// credentials updated -- save them
if ( events [ 'creds.update' ] ) {
await saveCreds ( )
}
console . log ( 'writeFile' , messageType ) ;
}
// history received
if ( events [ 'messaging-history.set' ] ) {
const { chats , contacts , messages , isLatest , progress , syncType } = events [ 'messaging-history.set' ]
if ( syncType === WAProto . HistorySync . HistorySyncType . ON _DEMAND ) {
console . log ( 'received on-demand history sync, messages=' , messages )
}
console . log ( ` recv ${ chats . length } chats, ${ contacts . length } contacts, ${ messages . length } msgs (is latest: ${ isLatest } , progress: ${ progress } %), type: ${ syncType } ` )
}
const fromWhatsAppNo = parsePhoneNumber ( msg . key . remoteJid ) ;
// received a new message
if ( events [ 'messages.upsert' ] ) {
const upsert = events [ 'messages.upsert' ]
console . log ( '收到消息:' , JSON . stringify ( upsert , undefined , 2 ) )
if ( msg . key . remoteJid . indexOf ( '@g.us' ) > - 1 ) {
const metadata = await waSocket . groupMetadata ( msg . key . remoteJid ) ;
console . log ( '群: ' + metadata . subject + ', description: ' + metadata . desc ) ;
try {
const ppUrl = await waSocket . profilePictureUrl ( msg . key . remoteJid ) ;
console . log ( '群头像: ' + ppUrl ) ;
} catch ( ex ) {
console . error ( '群头像出错了: ' , ex ) ;
}
} else {
console . log ( 'remoteJid: ' , msg . key . remoteJid ) ;
try {
const ppUrl = await waSocket . profilePictureUrl ( msg . key . remoteJid ) ;
console . log ( '个人头像: ' + ppUrl ) ;
} catch ( ex ) {
console . error ( '个人头像出错了: ' , ex ) ;
}
}
if ( upsert . type === 'notify' ) {
for ( const msg of upsert . messages ) {
if ( msg . message ? . conversation || msg . message ? . extendedTextMessage ? . text ) {
const text = msg . message ? . conversation || msg . message ? . extendedTextMessage ? . text
console . log ( '收到 notify: ' , text )
const text = msg . message ? . conversation || msg . message ? . extendedTextMessage ? . text ;
if ( text . indexOf ( '图片' ) > - 1 ) {
sendImageMessage ( fromWhatsAppNo , 'https://images.asiahighlights.com/allpicture/2022/07/8a7d9ced5936463bb904c82a_cut_750x850_349.webp' ) ;
} else if ( text . indexOf ( '文本' ) > - 1 ) {
sendTextMessage ( fromWhatsAppNo , '这是文本消息:' + new Date ( ) . toString ( ) ) ;
} else if ( text . indexOf ( '发群' ) > - 1 ) {
sendTextMessage ( '120363335516526642@g.us' , '这是群消息:' + new Date ( ) . toString ( ) ) ;
}
if ( msg . key . fromMe ) {
waEmitter . emit ( 'message:updated' , {
id : msg . key . id ,
status : formatStatus ( msg . status ) ,
from : whatsAppNo ,
to : fromWhatsAppNo ,
type : 'text' ,
text : {
body : text ,
} ,
participant : {
id : parsePhoneNumber ( msg . key . participant ) ,
name : msg . pushName ,
} ,
updateTime : formatTimestamp ( msg . messageTimestamp ) ,
} ) ;
} else {
waEmitter . emit ( 'message:received' , {
id : msg . key . id ,
status : '' ,
from : fromWhatsAppNo ,
to : whatsAppNo ,
type : 'text' ,
text : {
body : text ,
} ,
participant : {
id : parsePhoneNumber ( msg . key . participant ) ,
name : msg . pushName ,
} ,
createTime : formatTimestamp ( msg . messageTimestamp ) ,
} ) ;
}
}
}
}
}
} ,
)
} ) ;
waSocket . ev . on ( 'messages.update' , async messageUpdate => {
console . info ( 'messages.update: ' , messageUpdate ) ;
for ( const msg of messageUpdate ) {
waEmitter . emit ( 'message:updated' , {
id : msg . key . id ,
status : formatStatus ( msg . update . status ) ,
from : msg . key . fromMe ? whatsAppNo : parsePhoneNumber ( msg . key . remoteJid ) ,
to : msg . key . fromMe ? parsePhoneNumber ( msg . key . remoteJid ) : whatsAppNo ,
participant : {
id : parsePhoneNumber ( msg . key . participant ) ,
name : msg . pushName ,
} ,
updateTime : formatTimestamp ( new Date ( ) . getTime ( ) / 1000 ) ,
} ) ;
}
} ) ;
waSocket . ev . on ( 'group-participants.update' , async GroupMetadata => {
console . info ( 'group-participants.update: ' , GroupMetadata ) ;
} ) ;
// 不绑定不会影响扫码登录
store ? . bind ( waSocket . ev ) ;
// the process function lets you process all events that just occurred
// efficiently in a batch
waSocket . ev . process (
// events is a map for event name => event data
async events => {
// credentials updated -- save them
if ( events [ 'creds.update' ] ) {
await saveCreds ( ) ;
}
} ,
) ;
} ) ;
} ;
return sock
}
return {
createTimestamp : Date . now ( ) ,
status : 'offline' ,
version : waVersion ,
channelId : channelId ,
phone : phone ,
start ,
sendTextMessage ,
sendImageMessage ,
} ;
} ;
startSock ( )
createWhatsApp ( ) . then ( wa => wa . start ( ) )