|
|
const { imageToWebp, videoToWebp, writeExifImg, writeExifVid } = require('../lib/exif') |
|
|
const { |
|
|
default: makeWASocket, |
|
|
makeWALegacySocket, |
|
|
extractMessageContent, |
|
|
makeInMemoryStore, |
|
|
proto, |
|
|
prepareWAMessageMedia, |
|
|
downloadContentFromMessage, |
|
|
getBinaryNodeChild, |
|
|
jidDecode, |
|
|
areJidsSameUser, |
|
|
generateForwardMessageContent, |
|
|
generateWAMessageFromContent, |
|
|
WAMessageStubType, |
|
|
WA_DEFAULT_EPHEMERAL, |
|
|
} = require('@adiwajshing/baileys') |
|
|
const { toAudio, toPTT, toVideo } = require('./converter') |
|
|
const chalk = require('chalk') |
|
|
const fetch = require('node-fetch') |
|
|
const FileType = require('file-type') |
|
|
const PhoneNumber = require('awesome-phonenumber') |
|
|
const fs = require('fs') |
|
|
const path = require('path') |
|
|
const jimp = require('jimp') |
|
|
const pino = require('pino') |
|
|
const util = require('util') |
|
|
const store = makeInMemoryStore({ logger: pino().child({ level: 'silent', stream: 'store' }) }) |
|
|
|
|
|
|
|
|
exports.makeWASocket = (connectionOptions, options = {}) => { |
|
|
let conn = (opts['legacy'] ? makeWALegacySocket : makeWASocket)(connectionOptions) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.decodeJid = (jid) => { |
|
|
if (!jid) return jid |
|
|
if (/:\d+@/gi.test(jid)) { |
|
|
const decode = jidDecode(jid) || {} |
|
|
return decode.user && decode.server && decode.user + '@' + decode.server || jid |
|
|
} else return jid |
|
|
} |
|
|
if (conn.user && conn.user.id) conn.user.jid = conn.decodeJid(conn.user.id) |
|
|
if (!conn.chats) conn.chats = {} |
|
|
|
|
|
function updateNameToDb(contacts) { |
|
|
if (!contacts) return |
|
|
for (const contact of contacts) { |
|
|
const id = conn.decodeJid(contact.id) |
|
|
if (!id) continue |
|
|
let chats = conn.chats[id] |
|
|
if (!chats) chats = conn.chats[id] = { id } |
|
|
conn.chats[id] = { |
|
|
...chats, |
|
|
...({ |
|
|
...contact, id, ...(id.endsWith('@g.us') ? |
|
|
{ subject: contact.subject || chats.subject || '' } : |
|
|
{ name: contact.notify || chats.name || chats.notify || '' }) |
|
|
} || {}) |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
conn.ev.on('contacts.upsert', updateNameToDb) |
|
|
conn.ev.on('groups.update', updateNameToDb) |
|
|
conn.ev.on('chats.set', async ({ chats }) => { |
|
|
for (const { id, name, readOnly } of chats) { |
|
|
id = conn.decodeJid(id) |
|
|
if (!id) continue |
|
|
const isGroup = id.endsWith('@g.us') |
|
|
let chats = conn.chats[id] |
|
|
if (!chats) chats = conn.chats[id] = { id } |
|
|
chats.isChats = !readOnly |
|
|
if (name) chats[isGroup ? 'subject' : 'name'] = name |
|
|
if (isGroup) { |
|
|
const metadata = await conn.groupMetadata(id).catch(_ => null) |
|
|
if (!metadata) continue |
|
|
chats.subject = name || metadata.subject |
|
|
chats.metadata = metadata |
|
|
} |
|
|
} |
|
|
}) |
|
|
conn.ev.on('group-participants.update', async function updateParticipantsToDb({ id, participants, action }) { |
|
|
id = conn.decodeJid(id) |
|
|
if (!(id in conn.chats)) conn.chats[id] = { id } |
|
|
conn.chats[id].isChats = true |
|
|
const groupMetadata = await conn.groupMetadata(id).catch(_ => null) |
|
|
if (!groupMetadata) return |
|
|
conn.chats[id] = { |
|
|
...conn.chats[id], |
|
|
subject: groupMetadata.subject, |
|
|
metadata: groupMetadata |
|
|
} |
|
|
}) |
|
|
|
|
|
conn.ev.on('groups.update', async function groupUpdatePushToDb(groupsUpdates) { |
|
|
for (const update of groupsUpdates) { |
|
|
const id = conn.decodeJid(update.id) |
|
|
if (!id) continue |
|
|
const isGroup = id.endsWith('@g.us') |
|
|
if (!isGroup) continue |
|
|
let chats = conn.chats[id] |
|
|
if (!chats) chats = conn.chats[id] = { id } |
|
|
chats.isChats = true |
|
|
const metadata = await conn.groupMetadata(id).catch(_ => null) |
|
|
if (!metadata) continue |
|
|
chats.subject = metadata.subject |
|
|
chats.metadata = metadata |
|
|
} |
|
|
}) |
|
|
conn.ev.on('chats.upsert', async function chatsUpsertPushToDb(chatsUpsert) { |
|
|
console.log({ chatsUpsert }) |
|
|
const { id, name } = chatsUpsert |
|
|
if (!id) return |
|
|
let chats = conn.chats[id] = { ...conn.chats[id], ...chatsUpsert, isChats: true } |
|
|
const isGroup = id.endsWith('@g.us') |
|
|
if (isGroup) { |
|
|
const metadata = await conn.groupMetadata(id).catch(_ => null) |
|
|
if (metadata) { |
|
|
chats.subject = name || metadata.subject |
|
|
chats.metadata = metadata |
|
|
} |
|
|
const groups = await conn.groupFetchAllParticipating().catch(_ => ({})) || {} |
|
|
for (const group in groups) conn.chats[group] = { id: group, subject: groups[group].subject, isChats: true, metadata: groups[group] } |
|
|
} |
|
|
}) |
|
|
conn.ev.on('presence.update', async function presenceUpdatePushToDb({ id, presences }) { |
|
|
const sender = Object.keys(presences)[0] || id |
|
|
const _sender = conn.decodeJid(sender) |
|
|
const presence = presences[sender]['lastKnownPresence'] || 'composing' |
|
|
let chats = conn.chats[_sender] |
|
|
if (!chats) chats = conn.chats[_sender] = { id: sender } |
|
|
chats.presences = presence |
|
|
if (id.endsWith('@g.us')) { |
|
|
let chats = conn.chats[id] |
|
|
if (!chats) { |
|
|
const metadata = await conn.groupMetadata(id).catch(_ => null) |
|
|
if (metadata) chats = conn.chats[id] = { id, subject: metadata.subject, metadata } |
|
|
} |
|
|
chats.isChats = true |
|
|
} |
|
|
}) |
|
|
|
|
|
conn.logger = { |
|
|
...conn.logger, |
|
|
info(...args) { console.log(chalk.bold.rgb(57, 183, 16)(`INFO [${chalk.rgb(255, 255, 255)(new Date())}]:`), chalk.cyan(util.format(...args))) }, |
|
|
error(...args) { console.log(chalk.bold.rgb(247, 38, 33)(`ERROR [${chalk.rgb(255, 255, 255)(new Date())}]:`), chalk.rgb(255, 38, 0)(util.format(...args))) }, |
|
|
warn(...args) { console.log(chalk.bold.rgb(239, 225, 3)(`WARNING [${chalk.rgb(255, 255, 255)(new Date())}]:`), chalk.keyword('orange')(util.format(...args))) } |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.getFile = async (PATH, returnAsFilename) => { |
|
|
let res, filename |
|
|
let data = Buffer.isBuffer(PATH) ? PATH : /^data:.*?\/.*?;base64,/i.test(PATH) ? Buffer.from(PATH.split`,`[1], 'base64') : /^https?:\/\//.test(PATH) ? await (res = await fetch(PATH)).buffer() : fs.existsSync(PATH) ? (filename = PATH, fs.readFileSync(PATH)) : typeof PATH === 'string' ? PATH : Buffer.alloc(0) |
|
|
if (!Buffer.isBuffer(data)) throw new TypeError('Result is not a buffer') |
|
|
let type = await FileType.fromBuffer(data) || { |
|
|
mime: 'application/octet-stream', |
|
|
ext: '.bin' |
|
|
} |
|
|
if (data && returnAsFilename && !filename) (filename = path.join(__dirname, '../tmp/' + new Date * 1 + '.' + type.ext), await fs.promises.writeFile(filename, data)) |
|
|
return { |
|
|
res, |
|
|
filename, |
|
|
...type, |
|
|
data |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.waitEvent = (eventName, is = () => true, maxTries = 25) => { |
|
|
return new Promise((resolve, reject) => { |
|
|
let tries = 0 |
|
|
let on = (...args) => { |
|
|
if (++tries > maxTries) reject('Max tries reached') |
|
|
else if (is()) { |
|
|
conn.ev.off(eventName, on) |
|
|
resolve(...args) |
|
|
} |
|
|
} |
|
|
conn.ev.on(eventName, on) |
|
|
}) |
|
|
} |
|
|
|
|
|
conn.delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.filter = (text) => { |
|
|
let mati = ["q", "w", "r", "t", "y", "p", "s", "d", "f", "g", "h", "j", "k", "l", "z", "x", "c", "v", "b", "n", "m"] |
|
|
if (/[aiueo][aiueo]([qwrtypsdfghjklzxcvbnm])?$/i.test(text)) return text.substring(text.length - 1) |
|
|
else { |
|
|
let res = Array.from(text).filter(v => mati.includes(v)) |
|
|
let resu = res[res.length - 1] |
|
|
for (let huruf of mati) { |
|
|
if (text.endsWith(huruf)) { |
|
|
resu = res[res.length - 2] |
|
|
} |
|
|
} |
|
|
let misah = text.split(resu) |
|
|
return resu + misah[misah.length - 1] |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.msToDate = (ms) => { |
|
|
let days = Math.floor(ms / (24 * 60 * 60 * 1000)); |
|
|
let daysms = ms % (24 * 60 * 60 * 1000); |
|
|
let hours = Math.floor((daysms) / (60 * 60 * 1000)); |
|
|
let hoursms = ms % (60 * 60 * 1000); |
|
|
let minutes = Math.floor((hoursms) / (60 * 1000)); |
|
|
let minutesms = ms % (60 * 1000); |
|
|
let sec = Math.floor((minutesms) / (1000)); |
|
|
return days + " Hari " + hours + " Jam " + minutes + " Menit"; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.rand = async (isi) => { |
|
|
return isi[Math.floor(Math.random() * isi.length)] |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.resize = async (buffer, uk1, uk2) => { |
|
|
return new Promise(async(resolve, reject) => { |
|
|
var baper = await jimp.read(buffer); |
|
|
var ab = await baper.resize(uk1, uk2).getBufferAsync(jimp.MIME_JPEG) |
|
|
resolve(ab) |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendMedia = async (jid, path, quoted, options = {}) => { |
|
|
let { ext, mime, data } = await conn.getFile(path) |
|
|
messageType = mime.split("/")[0] |
|
|
pase = messageType.replace('application', 'document') || messageType |
|
|
return await conn.sendMessage(jid, { [`${pase}`]: data, mimetype: mime, ...options }, { quoted }) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.getFile = async (PATH, returnAsFilename) => { |
|
|
let res, filename |
|
|
let data = Buffer.isBuffer(PATH) ? PATH : /^data:.*?\/.*?;base64,/i.test(PATH) ? Buffer.from(PATH.split`,`[1], 'base64') : /^https?:\/\//.test(PATH) ? await (res = await fetch(PATH)).buffer() : fs.existsSync(PATH) ? (filename = PATH, fs.readFileSync(PATH)) : typeof PATH === 'string' ? PATH : Buffer.alloc(0) |
|
|
if (!Buffer.isBuffer(data)) throw new TypeError('Result is not a buffer') |
|
|
let type = await FileType.fromBuffer(data) || { |
|
|
mime: 'application/octet-stream', |
|
|
ext: '.bin' |
|
|
} |
|
|
if (data && returnAsFilename && !filename) (filename = path.join(__dirname, '../tmp/' + new Date * 1 + '.' + type.ext), await fs.promises.writeFile(filename, data)) |
|
|
return { |
|
|
res, |
|
|
filename, |
|
|
...type, |
|
|
data |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendFile = async (jid, path, filename = '', caption = '', quoted, ptt = false, options = {}) => { |
|
|
let type = await conn.getFile(path, true) |
|
|
let { res, data: file, filename: pathFile } = type |
|
|
if (res && res.status !== 200 || file.length <= 65536) { |
|
|
try { throw { json: JSON.parse(file.toString()) } } |
|
|
catch (e) { if (e.json) throw e.json } |
|
|
} |
|
|
let opt = { filename } |
|
|
if (quoted) opt.quoted = quoted |
|
|
if (!type) if (options.asDocument) options.asDocument = true |
|
|
let mtype = '', mimetype = type.mime |
|
|
if (/webp/.test(type.mime)) mtype = 'sticker' |
|
|
else if (/image/.test(type.mime)) mtype = 'image' |
|
|
else if (/video/.test(type.mime)) mtype = 'video' |
|
|
else if (/audio/.test(type.mime)) ( |
|
|
convert = await (ptt ? toPTT : toAudio)(file, type.ext), |
|
|
file = convert.data, |
|
|
pathFile = convert.filename, |
|
|
mtype = 'audio', |
|
|
mimetype = 'audio/ogg; codecs=opus' |
|
|
) |
|
|
else mtype = 'document' |
|
|
return await conn.sendMessage(jid, { |
|
|
...options, |
|
|
caption, |
|
|
ptt, |
|
|
[mtype]: { url: pathFile }, |
|
|
mimetype |
|
|
}, { |
|
|
...opt, |
|
|
...options |
|
|
}) |
|
|
} |
|
|
|
|
|
conn.sendImageAsSticker = async (jid, path, quoted, options = {}) => { |
|
|
let buff = Buffer.isBuffer(path) ? path : /^data:.*?\/.*?;base64,/i.test(path) ? Buffer.from(path.split`,`[1], 'base64') : /^https?:\/\//.test(path) ? await (await fetch(path)).buffer() : fs.existsSync(path) ? fs.readFileSync(path) : Buffer.alloc(0) |
|
|
let buffer |
|
|
if (options && (options.packname || options.author)) { |
|
|
buffer = await writeExifImg(buff, options) |
|
|
} else { |
|
|
buffer = await imageToWebp(buff) |
|
|
} |
|
|
|
|
|
await conn.sendMessage(jid, { sticker: { url: buffer }, ...options }, { quoted }) |
|
|
return buffer |
|
|
} |
|
|
conn.sendVideoAsSticker = async (jid, path, quoted, options = {}) => { |
|
|
let buff = Buffer.isBuffer(path) ? path : /^data:.*?\/.*?;base64,/i.test(path) ? Buffer.from(path.split`,`[1], 'base64') : /^https?:\/\//.test(path) ? await (await fetch(path)).buffer() : fs.existsSync(path) ? fs.readFileSync(path) : Buffer.alloc(0) |
|
|
let buffer |
|
|
if (options && (options.packname || options.author)) { |
|
|
buffer = await writeExifVid(buff, options) |
|
|
} else { |
|
|
buffer = await videoToWebp(buff) |
|
|
} |
|
|
|
|
|
await conn.sendMessage(jid, { sticker: { url: buffer }, ...options }, { quoted }) |
|
|
return buffer |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendContact = async (jid, data, quoted, options) => { |
|
|
let contacts = [] |
|
|
for (let [number, name] of data) { |
|
|
number = number.replace(/[^0-9]/g, '') |
|
|
let njid = number + '@s.whatsapp.net' |
|
|
let biz = await conn.getBusinessProfile(njid) || {} |
|
|
|
|
|
let vcard = ` |
|
|
BEGIN:VCARD |
|
|
VERSION:3.0 |
|
|
FN:${name.replace(/\n/g, '\\n')} |
|
|
item1.TEL;waid=${number}:${PhoneNumber('+' + number).getNumber('international')} |
|
|
item1.X-ABLabel:Ponsel${biz.description ? ` |
|
|
PHOTO;BASE64:${(await conn.getFile(await conn.profilePictureUrl(njid)).catch(_ => ({})) || {}).data?.toString('base64')} |
|
|
X-WA-BIZ-DESCRIPTION:${(biz.description || '').replace(/\n/g, '\\n')} |
|
|
X-WA-BIZ-NAME:${(((conn.chats[njid] || {}) || { vname: conn.chats[njid]?.name }).vname || conn.getName(njid) || name).replace(/\n/, '\\n')} |
|
|
`.trim() : ''} |
|
|
END:VCARD |
|
|
`.trim() |
|
|
contacts.push({ vcard, displayName: name }) |
|
|
|
|
|
} |
|
|
return await conn.sendMessage(jid, { |
|
|
contacts: { |
|
|
...options, |
|
|
displayName: (contacts.length > 1 ? `${contacts.length} kontak` : contacts[0].displayName) || null, |
|
|
contacts, |
|
|
}, |
|
|
quoted, ...options |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.reply = (jid, text = '', quoted, options) => { |
|
|
return Buffer.isBuffer(text) ? this.sendFile(jid, text, 'file', '', quoted, false, options) : conn.sendMessage(jid, { ...options, text, mentions: conn.parseMention(text) }, { quoted, ...options, mentions: conn.parseMention(text) }) |
|
|
} |
|
|
|
|
|
conn.decodeJid = (jid) => { |
|
|
if (!jid) return jid |
|
|
if (/:\d+@/gi.test(jid)) { |
|
|
let decode = jidDecode(jid) || {} |
|
|
return decode.user && decode.server && decode.user + '@' + decode.server || jid |
|
|
} else return jid |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendText = (jid, text, quoted = '', options) => conn.sendMessage(jid, { text: text, ...options }, { quoted }) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendGroupV4Invite = async (jid, participant, inviteCode, inviteExpiration, groupName = 'unknown subject', caption = 'Invitation to join my WhatsApp group', options = {}) => { |
|
|
let msg = proto.Message.fromObject({ |
|
|
groupInviteMessage: proto.GroupInviteMessage.fromObject({ |
|
|
inviteCode, |
|
|
inviteExpiration: parseInt(inviteExpiration) || + new Date(new Date + (3 * 86400000)), |
|
|
groupJid: jid, |
|
|
groupName: groupName ? groupName : this.getName(jid), |
|
|
caption |
|
|
}) |
|
|
}) |
|
|
let message = await this.prepareMessageFromContent(participant, msg, options) |
|
|
await this.relayWAMessage(message) |
|
|
return message |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendButton = async (jid, contentText, footer, buffer, buttons, quoted, options) => { |
|
|
if (buffer) try { buffer = (await conn.getFile(buffer)).data } catch { buffer = null } |
|
|
let message = { |
|
|
...options, |
|
|
...(buffer ? { caption: contentText || '' } : { text: contentText || '' }), |
|
|
footer, |
|
|
buttons: buttons.map(btn => { |
|
|
return { |
|
|
buttonId: btn[1] || btn[0] || '', |
|
|
buttonText: { |
|
|
displayText: btn[0] || btn[1] || '' |
|
|
} |
|
|
} |
|
|
}), |
|
|
...(buffer ? { image: buffer } : {}) |
|
|
} |
|
|
return await conn.sendMessage(jid, message, { |
|
|
quoted, |
|
|
upload: conn.waUploadToServer, |
|
|
...options |
|
|
}) |
|
|
} |
|
|
|
|
|
conn.sendBut = async(jid, content, footer, button1, row1, quoted) => { |
|
|
const buttons = [ |
|
|
{buttonId: row1, buttonText: {displayText: button1}, type: 1} |
|
|
] |
|
|
const buttonMessage = { |
|
|
text: content, |
|
|
footer: footer, |
|
|
buttons: buttons, |
|
|
headerType: 1, |
|
|
mentions: conn.parseMention(footer+content) |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, {quoted}) |
|
|
} |
|
|
|
|
|
conn.send2But = async(jid, content, footer, button1, row1, button2, row2, quoted) => { |
|
|
const buttons = [ |
|
|
{ buttonId: row1, buttonText: { displayText: button1 }, type: 1 }, |
|
|
{ buttonId: row2, buttonText: { displayText: button2 }, type: 1 } |
|
|
] |
|
|
const buttonMessage = { |
|
|
text: content, |
|
|
footer: footer, |
|
|
buttons: buttons, |
|
|
headerType: 1 |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, {quoted}) |
|
|
} |
|
|
|
|
|
conn.send3But = async(jid, content, footer,button1, row1, button2, row2, button3, row3, quoted) => { |
|
|
const buttons = [ |
|
|
{ buttonId: row1, buttonText: { displayText: button1 }, type: 1 }, |
|
|
{ buttonId: row2, buttonText: { displayText: button2 }, type: 1 }, |
|
|
{ buttonId: row3, buttonText: { displayText: button3 }, type: 1 } |
|
|
] |
|
|
const buttonMessage = { |
|
|
text: content, |
|
|
footer: footer, |
|
|
buttons: buttons, |
|
|
headerType: 1 |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, {quoted}) |
|
|
} |
|
|
conn.send4But = async(jid, content, footer,button1, row1, button2, row2, button3, row3, button4, row4, quoted) => { |
|
|
const buttons = [ |
|
|
{ buttonId: row1, buttonText: { displayText: button1 }, type: 1 }, |
|
|
{ buttonId: row2, buttonText: { displayText: button2 }, type: 1 }, |
|
|
{ buttonId: row3, buttonText: { displayText: button3 }, type: 1 }, |
|
|
{ buttonId: row4, buttonText: { displayText: button4 }, type: 1 } |
|
|
] |
|
|
const buttonMessage = { |
|
|
text: content, |
|
|
footer: footer, |
|
|
buttons: buttons, |
|
|
headerType: 1 |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, {quoted}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendButtonImg = async (jid, buffer, contentText, footerText, button1, id1, quoted, options) => { |
|
|
let type = await conn.getFile(buffer) |
|
|
let { res, data: file } = type |
|
|
if (res && res.status !== 200 || file.length <= 65536) { |
|
|
try { throw { json: JSON.parse(file.toString()) } } |
|
|
catch (e) { if (e.json) throw e.json } |
|
|
} |
|
|
const buttons = [ |
|
|
{ buttonId: id1, buttonText: { displayText: button1 }, type: 1 } |
|
|
] |
|
|
|
|
|
const buttonMessage = { |
|
|
image: file, |
|
|
fileLength: 887890909999999, |
|
|
caption: contentText, |
|
|
footer: footerText, |
|
|
mentions: await conn.parseMention(contentText + footerText), |
|
|
...options, |
|
|
buttons: buttons, |
|
|
headerType: 4 |
|
|
} |
|
|
|
|
|
return await conn.sendMessage(jid, buttonMessage, { quoted, ephemeralExpiration: 86400, contextInfo: { mentionedJid: conn.parseMention(contentText + footerText) }, ...options }) |
|
|
} |
|
|
conn.send2ButtonImg = async (jid, buffer, contentText, footerText, button1, id1, button2, id2, quoted, options) => { |
|
|
let type = await conn.getFile(buffer) |
|
|
let { res, data: file } = type |
|
|
if (res && res.status !== 200 || file.length <= 65536) { |
|
|
try { throw { json: JSON.parse(file.toString()) } } |
|
|
catch (e) { if (e.json) throw e.json } |
|
|
} |
|
|
const buttons = [ |
|
|
{ buttonId: id1, buttonText: { displayText: button1 }, type: 1 }, |
|
|
{ buttonId: id2, buttonText: { displayText: button2 }, type: 1 } |
|
|
] |
|
|
|
|
|
const buttonMessage = { |
|
|
image: file, |
|
|
fileLength: 887890909999999, |
|
|
caption: contentText, |
|
|
footer: footerText, |
|
|
mentions: await conn.parseMention(contentText + footerText), |
|
|
...options, |
|
|
buttons: buttons, |
|
|
headerType: 4 |
|
|
} |
|
|
|
|
|
return await conn.sendMessage(jid, buttonMessage, { quoted, ephemeralExpiration: 86400, contextInfo: { mentionedJid: conn.parseMention(contentText + footerText) }, ...options }) |
|
|
} |
|
|
conn.send3ButtonImg = async (jid, buffer, contentText, footerText, button1, id1, button2, id2, button3, id3, quoted, options) => { |
|
|
let type = await conn.getFile(buffer) |
|
|
let { res, data: file } = type |
|
|
if (res && res.status !== 200 || file.length <= 65536) { |
|
|
try { throw { json: JSON.parse(file.toString()) } } |
|
|
catch (e) { if (e.json) throw e.json } |
|
|
} |
|
|
const buttons = [ |
|
|
{ buttonId: id1, buttonText: { displayText: button1 }, type: 1 }, |
|
|
{ buttonId: id2, buttonText: { displayText: button2 }, type: 1 }, |
|
|
{ buttonId: id3, buttonText: { displayText: button3 }, type: 1 } |
|
|
] |
|
|
|
|
|
const buttonMessage = { |
|
|
image: file, |
|
|
fileLength: 887890909999999, |
|
|
caption: contentText, |
|
|
footer: footerText, |
|
|
mentions: await conn.parseMention(contentText + footerText), |
|
|
...options, |
|
|
buttons: buttons, |
|
|
headerType: 4 |
|
|
} |
|
|
|
|
|
return await conn.sendMessage(jid, buttonMessage, { quoted, ephemeralExpiration: 86400, contextInfo: { mentionedJid: conn.parseMention(contentText + footerText) }, ...options }) |
|
|
} |
|
|
|
|
|
conn.sendH3Button = async (jid, content, displayText, link, displayCall, number, quickReplyText, id, quickReplyText2, id2, quickReplyText3, id3, quoted) => { |
|
|
let template = generateWAMessageFromContent(jid, proto.Message.fromObject({ |
|
|
templateMessage: { |
|
|
hydratedTemplate: { |
|
|
hydratedContentText: content, |
|
|
hydratedButtons: [{ |
|
|
urlButton: { |
|
|
displayText: displayText, |
|
|
url: link |
|
|
} |
|
|
}, { |
|
|
callButton: { |
|
|
displayText: displayCall, |
|
|
phoneNumber: number |
|
|
} |
|
|
}, |
|
|
{ |
|
|
quickReplyButton: { |
|
|
displayText: quickReplyText, |
|
|
id: id, |
|
|
} |
|
|
|
|
|
}, |
|
|
{ |
|
|
quickReplyButton: { |
|
|
displayText: quickReplyText2, |
|
|
id: id2, |
|
|
} |
|
|
}, |
|
|
{ |
|
|
quickReplyButton: { |
|
|
displayText: quickReplyText3, |
|
|
id: id3, |
|
|
} |
|
|
}] |
|
|
} |
|
|
} |
|
|
}), { userJid: conn.user.jid, quoted: quoted}); |
|
|
return await conn.relayMessage( |
|
|
jid, |
|
|
template.message, |
|
|
{ messageId: template.key.id } |
|
|
) |
|
|
} |
|
|
|
|
|
conn.cMod = (jid, message, text = '', sender = conn.user.jid, options = {}) => { |
|
|
let copy = message.toJSON() |
|
|
let mtype = Object.keys(copy.message)[0] |
|
|
let isEphemeral = false |
|
|
if (isEphemeral) { |
|
|
mtype = Object.keys(copy.message.ephemeralMessage.message)[0] |
|
|
} |
|
|
let msg = isEphemeral ? copy.message.ephemeralMessage.message : copy.message |
|
|
let content = msg[mtype] |
|
|
if (typeof content === 'string') msg[mtype] = text || content |
|
|
else if (content.caption) content.caption = text || content.caption |
|
|
else if (content.text) content.text = text || content.text |
|
|
if (typeof content !== 'string') msg[mtype] = { ...content, ...options } |
|
|
if (copy.participant) sender = copy.participant = sender || copy.participant |
|
|
else if (copy.key.participant) sender = copy.key.participant = sender || copy.key.participant |
|
|
if (copy.key.remoteJid.includes('@s.whatsapp.net')) sender = sender || copy.key.remoteJid |
|
|
else if (copy.key.remoteJid.includes('@broadcast')) sender = sender || copy.key.remoteJid |
|
|
copy.key.remoteJid = jid |
|
|
copy.key.fromMe = areJidsSameUser(sender, conn.user.id) || false |
|
|
return proto.WebMessageInfo.fromObject(copy) |
|
|
} |
|
|
conn.sendHButtonLoc = async (jid, buffer, content, footer, distek, link1, quick1, id1,quoted) => { |
|
|
let template = generateWAMessageFromContent(jid, proto.Message.fromObject({ |
|
|
templateMessage: { |
|
|
hydratedTemplate: { |
|
|
hydratedContentText: content, |
|
|
mentions: conn.parseMention(content + footer), |
|
|
locationMessage: { |
|
|
jpegThumbnail: buffer }, |
|
|
hydratedFooterText: footer, |
|
|
mentions: conn.parseMention(content + footer), |
|
|
hydratedButtons: [{ |
|
|
urlButton: { |
|
|
displayText: distek, |
|
|
url: link1 |
|
|
} |
|
|
}, { |
|
|
quickReplyButton: { |
|
|
displayText:quick1, |
|
|
id: id1 |
|
|
} |
|
|
}], mentions: conn.parseMention(content + footer) |
|
|
} |
|
|
} |
|
|
}), { userJid: conn.user.jid, quoted: quoted, mentions: conn.parseMention(content + footer)}); |
|
|
return await conn.relayMessage( |
|
|
jid, |
|
|
template.message, |
|
|
{ messageId: template.key.id } |
|
|
) |
|
|
} |
|
|
|
|
|
conn.sendHButt = async (jid, content, distek, link, discall, number, retek, id,quoted) => { |
|
|
let template = generateWAMessageFromContent(jid, proto.Message.fromObject({ |
|
|
templateMessage: { |
|
|
hydratedTemplate: { |
|
|
hydratedContentText: content, |
|
|
hydratedButtons: [{ |
|
|
urlButton: { |
|
|
displayText: distek, |
|
|
url: link |
|
|
} |
|
|
}, { |
|
|
callButton: { |
|
|
displayText: discall, |
|
|
phoneNumber: number |
|
|
} |
|
|
}, |
|
|
{ |
|
|
quickReplyButton: { |
|
|
displayText:retek, |
|
|
id: id |
|
|
} |
|
|
} |
|
|
] |
|
|
} |
|
|
} |
|
|
}), { userJid: conn.user.jid, quoted: quoted}); |
|
|
return await conn.relayMessage( |
|
|
jid, |
|
|
template.message, |
|
|
{ messageId: template.key.id } |
|
|
) |
|
|
} |
|
|
conn.sendButtonLoc= async (jid, buffer, content, footer, button1, row1, quoted, options = {}) => { |
|
|
let buttons = [{buttonId: row1, buttonText: {displayText: button1}, type: 1}] |
|
|
let buttonMessage = { |
|
|
location: { jpegThumbnail: buffer }, |
|
|
caption: content, |
|
|
footer: footer, |
|
|
buttons: buttons, |
|
|
headerType: 6 |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, { |
|
|
quoted, |
|
|
upload: conn.waUploadToServer, |
|
|
...options |
|
|
}) |
|
|
} |
|
|
conn.send2ButtonLoc= async (jid, buffer, content, footer, button1, row1, button2, row2, quoted, options = {}) => { |
|
|
let buttons = [{buttonId: row1, buttonText: {displayText: button1}, type: 1}, |
|
|
{ buttonId: row2, buttonText: { displayText: button2 }, type: 1 }] |
|
|
let buttonMessage = { |
|
|
location: { jpegThumbnail: buffer }, |
|
|
caption: content, |
|
|
footer: footer, |
|
|
buttons: buttons, |
|
|
headerType: 6 |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, { |
|
|
quoted, |
|
|
upload: conn.waUploadToServer, |
|
|
...options |
|
|
}) |
|
|
} |
|
|
conn.send3ButtonLoc= async (jid, buffer, content, footer, button1, row1, button2, row2, quoted, options = {}) => { |
|
|
let buttons = [{buttonId: row1, buttonText: {displayText: button1}, type: 1}, |
|
|
{ buttonId: row2, buttonText: { displayText: button2 }, type: 1 }, |
|
|
{ buttonId: row3, buttonText: { displayText: button3 }, type: 1 } |
|
|
] |
|
|
let buttonMessage = { |
|
|
location: { jpegThumbnail: buffer }, |
|
|
caption: content, |
|
|
footer: footer, |
|
|
buttons: buttons, |
|
|
headerType: 6 |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, { |
|
|
quoted, |
|
|
upload: conn.waUploadToServer, |
|
|
...options |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.sendButtonVid = async (jid, buffer, contentText, footerText, button1, id1, quoted, options) => { |
|
|
let type = await conn.getFile(buffer) |
|
|
let { res, data: file } = type |
|
|
if (res && res.status !== 200 || file.length <= 65536) { |
|
|
try { throw { json: JSON.parse(file.toString()) } } |
|
|
catch (e) { if (e.json) throw e.json } |
|
|
} |
|
|
let buttons = [ |
|
|
{ buttonId: id1, buttonText: { displayText: button1 }, type: 1 } |
|
|
] |
|
|
const buttonMessage = { |
|
|
video: file, |
|
|
fileLength: 887890909999999, |
|
|
caption: contentText, |
|
|
footer: footerText, |
|
|
mentions: await conn.parseMention(contentText), |
|
|
...options, |
|
|
buttons: buttons, |
|
|
headerType: 4 |
|
|
} |
|
|
return await conn.sendMessage(jid, buttonMessage, { |
|
|
quoted, |
|
|
ephemeralExpiration: 86400, |
|
|
...options |
|
|
}) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.cMod = async (jid, message, text = '', sender = conn.user.jid, options = {}) => { |
|
|
if (options.mentions && !Array.isArray(options.mentions)) options.mentions = [options.mentions] |
|
|
let copy = message.toJSON() |
|
|
delete copy.message.messageContextInfo |
|
|
delete copy.message.senderKeyDistributionMessage |
|
|
let mtype = Object.keys(copy.message)[0] |
|
|
let msg = copy.message |
|
|
let content = msg[mtype] |
|
|
if (typeof content === 'string') msg[mtype] = text || content |
|
|
else if (content.caption) content.caption = text || content.caption |
|
|
else if (content.text) content.text = text || content.text |
|
|
if (typeof content !== 'string') { |
|
|
msg[mtype] = { ...content, ...options } |
|
|
msg[mtype].contextInfo = { |
|
|
...(content.contextInfo || {}), |
|
|
mentionedJid: options.mentions || content.contextInfo?.mentionedJid || [] |
|
|
} |
|
|
} |
|
|
if (copy.participant) sender = copy.participant = sender || copy.participant |
|
|
else if (copy.key.participant) sender = copy.key.participant = sender || copy.key.participant |
|
|
if (copy.key.remoteJid.includes('@s.whatsapp.net')) sender = sender || copy.key.remoteJid |
|
|
else if (copy.key.remoteJid.includes('@broadcast')) sender = sender || copy.key.remoteJid |
|
|
copy.key.remoteJid = jid |
|
|
copy.key.fromMe = areJidsSameUser(sender, conn.user.id) || false |
|
|
return proto.WebMessageInfo.fromObject(copy) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.cMods = (jid, message, text = '', sender = conn.user.jid, options = {}) => { |
|
|
let copy = message.toJSON() |
|
|
let mtype = Object.keys(copy.message)[0] |
|
|
let isEphemeral = false |
|
|
if (isEphemeral) { |
|
|
mtype = Object.keys(copy.message.ephemeralMessage.message)[0] |
|
|
} |
|
|
let msg = isEphemeral ? copy.message.ephemeralMessage.message : copy.message |
|
|
let content = msg[mtype] |
|
|
if (typeof content === 'string') msg[mtype] = text || content |
|
|
else if (content.caption) content.caption = text || content.caption |
|
|
else if (content.text) content.text = text || content.text |
|
|
if (typeof content !== 'string') msg[mtype] = { ...content, ...options } |
|
|
if (copy.participant) sender = copy.participant = sender || copy.participant |
|
|
else if (copy.key.participant) sender = copy.key.participant = sender || copy.key.participant |
|
|
if (copy.key.remoteJid.includes('@s.whatsapp.net')) sender = sender || copy.key.remoteJid |
|
|
else if (copy.key.remoteJid.includes('@broadcast')) sender = sender || copy.key.remoteJid |
|
|
copy.key.remoteJid = jid |
|
|
copy.key.fromMe = areJidsSameUser(sender, conn.user.id) || false |
|
|
return proto.WebMessageInfo.fromObject(copy) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.copyNForward = async (jid, message, forwardingScore = true, options = {}) => { |
|
|
let m = generateForwardMessageContent(message, !!forwardingScore) |
|
|
let mtype = Object.keys(m)[0] |
|
|
if (forwardingScore && typeof forwardingScore == 'number' && forwardingScore > 1) m[mtype].contextInfo.forwardingScore += forwardingScore |
|
|
m = generateWAMessageFromContent(jid, m, { ...options, userJid: conn.user.id }) |
|
|
await conn.relayMessage(jid, m.message, { messageId: m.key.id, additionalAttributes: { ...options } }) |
|
|
return m |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.fakeReply = async (jid, text = '', fakeJid = this.user.jid, fakeText = '', fakeGroupJid, options) => { |
|
|
return conn.reply(jid, text, { key: { fromMe: areJidsSameUser(fakeJid, conn.user.id), participant: fakeJid, ...(fakeGroupJid ? { remoteJid: fakeGroupJid } : {}) }, message: { conversation: fakeText }, ...options }) |
|
|
} |
|
|
|
|
|
conn.loadMessage = conn.loadMessage || (async (messageID) => { |
|
|
return Object.entries(conn.chats) |
|
|
.filter(([_, { messages }]) => typeof messages === 'object') |
|
|
.find(([_, { messages }]) => Object.entries(messages) |
|
|
.find(([k, v]) => (k === messageID || v.key?.id === messageID))) |
|
|
?.[1].messages?.[messageID] |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.downloadM = async (m, type, saveToFile) => { |
|
|
if (!m || !(m.url || m.directPath)) return Buffer.alloc(0) |
|
|
const stream = await downloadContentFromMessage(m, type) |
|
|
let buffer = Buffer.from([]) |
|
|
for await (const chunk of stream) { |
|
|
buffer = Buffer.concat([buffer, chunk]) |
|
|
} |
|
|
if (saveToFile) var { filename } = await conn.getFile(buffer, true) |
|
|
return saveToFile && fs.existsSync(filename) ? filename : buffer |
|
|
} |
|
|
|
|
|
|
|
|
conn.downloadAndSaveMediaMessage = async (message, filename, attachExtension = true) => { |
|
|
let quoted = message.msg ? message.msg : message |
|
|
let mime = (message.msg || message).mimetype || '' |
|
|
let messageType = message.mtype ? message.mtype.replace(/Message/gi, '') : mime.split('/')[0] |
|
|
const stream = await downloadContentFromMessage(quoted, messageType) |
|
|
let buffer = Buffer.from([]) |
|
|
for await(const chunk of stream) { |
|
|
buffer = Buffer.concat([buffer, chunk]) |
|
|
} |
|
|
let type = await FileType.fromBuffer(buffer) |
|
|
trueFileName = attachExtension ? (filename + '.' + type.ext) : filename |
|
|
|
|
|
await fs.writeFileSync(trueFileName, buffer) |
|
|
return trueFileName |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.parseMention = (text = '') => { |
|
|
return [...text.matchAll(/@([0-9]{5,16}|0)/g)].map(v => v[1] + '@s.whatsapp.net') |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.chatRead = async (jid, participant = conn.user.jid, messageID) => { |
|
|
return await conn.sendReadReceipt(jid, participant, [messageID]) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.parseMention = (text = '') => { |
|
|
return [...text.matchAll(/@([0-9]{5,16}|0)/g)].map(v => v[1] + '@s.whatsapp.net') |
|
|
} |
|
|
|
|
|
conn.sendTextWithMentions = async (jid, text, quoted, options = {}) => conn.sendMessage(jid, { text: text, contextInfo: { mentionedJid: [...text.matchAll(/@(\d{0,16})/g)].map(v => v[1] + '@s.whatsapp.net') }, ...options }, { quoted }) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.getName = (jid = '', withoutContact = false) => { |
|
|
jid = conn.decodeJid(jid) |
|
|
withoutContact = this.withoutContact || withoutContact |
|
|
let v |
|
|
if (jid.endsWith('@g.us')) return new Promise(async (resolve) => { |
|
|
v = conn.chats[jid] || {} |
|
|
if (!(v.name || v.subject)) v = await conn.groupMetadata(jid) || {} |
|
|
resolve(v.name || v.subject || PhoneNumber('+' + jid.replace('@s.whatsapp.net', '')).getNumber('international')) |
|
|
}) |
|
|
else v = jid === '0@s.whatsapp.net' ? { |
|
|
jid, |
|
|
vname: 'WhatsApp' |
|
|
} : areJidsSameUser(jid, conn.user.id) ? |
|
|
conn.user : |
|
|
(conn.chats[jid] || {}) |
|
|
return (withoutContact ? '' : v.name) || v.subject || v.vname || v.notify || v.verifiedName || PhoneNumber('+' + jid.replace('@s.whatsapp.net', '')).getNumber('international') |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.processMessageStubType = async(m) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!m.messageStubType) return |
|
|
const chat = conn.decodeJid(m.key.remoteJid || m.message?.senderKeyDistributionMessage?.groupId || '') |
|
|
if (!chat || chat === 'status@broadcast') return |
|
|
const emitGroupUpdate = (update) => { |
|
|
conn.ev.emit('groups.update', [{ id: chat, ...update }]) |
|
|
} |
|
|
switch (m.messageStubType) { |
|
|
case WAMessageStubType.REVOKE: |
|
|
case WAMessageStubType.GROUP_CHANGE_INVITE_LINK: |
|
|
emitGroupUpdate({ revoke: m.messageStubParameters[0] }) |
|
|
break |
|
|
case WAMessageStubType.GROUP_CHANGE_ICON: |
|
|
emitGroupUpdate({ icon: m.messageStubParameters[0] }) |
|
|
break |
|
|
default: { |
|
|
console.log({ |
|
|
messageStubType: m.messageStubType, |
|
|
messageStubParameters: m.messageStubParameters, |
|
|
type: WAMessageStubType[m.messageStubType] |
|
|
}) |
|
|
break |
|
|
} |
|
|
} |
|
|
const isGroup = chat.endsWith('@g.us') |
|
|
if (!isGroup) return |
|
|
let chats = conn.chats[chat] |
|
|
if (!chats) chats = conn.chats[chat] = { id: chat } |
|
|
chats.isChats = true |
|
|
const metadata = await conn.groupMetadata(chat).catch(_ => null) |
|
|
if (!metadata) return |
|
|
chats.subject = metadata.subject |
|
|
chats.metadata = metadata |
|
|
} |
|
|
conn.insertAllGroup = async() => { |
|
|
const groups = await conn.groupFetchAllParticipating().catch(_ => null) || {} |
|
|
for (const group in groups) conn.chats[group] = { ...(conn.chats[group] || {}), id: group, subject: groups[group].subject, isChats: true, metadata: groups[group] } |
|
|
return conn.chats |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.pushMessage = async(m) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!m) return |
|
|
if (!Array.isArray(m)) m = [m] |
|
|
for (const message of m) { |
|
|
try { |
|
|
|
|
|
if (!message) continue |
|
|
if (message.messageStubType && message.messageStubType != WAMessageStubType.CIPHERTEXT) conn.processMessageStubType(message).catch(console.error) |
|
|
const _mtype = Object.keys(message.message || {}) |
|
|
const mtype = (!['senderKeyDistributionMessage', 'messageContextInfo'].includes(_mtype[0]) && _mtype[0]) || |
|
|
(_mtype.length >= 3 && _mtype[1] !== 'messageContextInfo' && _mtype[1]) || |
|
|
_mtype[_mtype.length - 1] |
|
|
const chat = conn.decodeJid(message.key.remoteJid || message.message?.senderKeyDistributionMessage?.groupId || '') |
|
|
if (message.message?.[mtype]?.contextInfo?.quotedMessage) { |
|
|
|
|
|
|
|
|
|
|
|
let context = message.message[mtype].contextInfo |
|
|
let participant = conn.decodeJid(context.participant) |
|
|
const remoteJid = conn.decodeJid(context.remoteJid || participant) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let quoted = message.message[mtype].contextInfo.quotedMessage |
|
|
if ((remoteJid && remoteJid !== 'status@broadcast') && quoted) { |
|
|
let qMtype = Object.keys(quoted)[0] |
|
|
if (qMtype == 'conversation') { |
|
|
quoted.extendedTextMessage = { text: quoted[qMtype] } |
|
|
delete quoted.conversation |
|
|
qMtype = 'extendedTextMessage' |
|
|
} |
|
|
|
|
|
if (!quoted[qMtype].contextInfo) quoted[qMtype].contextInfo = {} |
|
|
quoted[qMtype].contextInfo.mentionedJid = context.mentionedJid || quoted[qMtype].contextInfo.mentionedJid || [] |
|
|
const isGroup = remoteJid.endsWith('g.us') |
|
|
if (isGroup && !participant) participant = remoteJid |
|
|
const qM = { |
|
|
key: { |
|
|
remoteJid, |
|
|
fromMe: areJidsSameUser(conn.user.jid, remoteJid), |
|
|
id: context.stanzaId, |
|
|
participant, |
|
|
}, |
|
|
message: JSON.parse(JSON.stringify(quoted)), |
|
|
...(isGroup ? { participant } : {}) |
|
|
} |
|
|
let qChats = conn.chats[participant] |
|
|
if (!qChats) qChats = conn.chats[participant] = { id: participant, isChats: !isGroup } |
|
|
if (!qChats.messages) qChats.messages = {} |
|
|
if (!qChats.messages[context.stanzaId] && !qM.key.fromMe) qChats.messages[context.stanzaId] = qM |
|
|
let qChatsMessages |
|
|
if ((qChatsMessages = Object.entries(qChats.messages)).length > 40) qChats.messages = Object.fromEntries(qChatsMessages.slice(30, qChatsMessages.length)) |
|
|
} |
|
|
} |
|
|
if (!chat || chat === 'status@broadcast') continue |
|
|
const isGroup = chat.endsWith('@g.us') |
|
|
let chats = conn.chats[chat] |
|
|
if (!chats) { |
|
|
if (isGroup) await conn.insertAllGroup().catch(console.error) |
|
|
chats = conn.chats[chat] = { id: chat, isChats: true, ...(conn.chats[chat] || {}) } |
|
|
} |
|
|
let metadata, sender |
|
|
if (isGroup) { |
|
|
if (!chats.subject || !chats.metadata) { |
|
|
metadata = await conn.groupMetadata(chat).catch(_ => ({})) || {} |
|
|
if (!chats.subject) chats.subject = metadata.subject || '' |
|
|
if (!chats.metadata) chats.metadata = metadata |
|
|
} |
|
|
sender = conn.decodeJid(message.key?.fromMe && conn.user.id || message.participant || message.key?.participant || chat || '') |
|
|
if (sender !== chat) { |
|
|
let chats = conn.chats[sender] |
|
|
if (!chats) chats = conn.chats[sender] = { id: sender } |
|
|
if (!chats.name) chats.name = message.pushName || chats.name || '' |
|
|
} |
|
|
} else if (!chats.name) chats.name = message.pushName || chats.name || '' |
|
|
if (['senderKeyDistributionMessage', 'messageContextInfo'].includes(mtype)) continue |
|
|
chats.isChats = true |
|
|
if (!chats.messages) chats.messages = {} |
|
|
const fromMe = message.key.fromMe || areJidsSameUser(sender || chat, conn.user.id) |
|
|
if (!['protocolMessage'].includes(mtype) && !fromMe && message.messageStubType != WAMessageStubType.CIPHERTEXT && message.message) { |
|
|
delete message.message.messageContextInfo |
|
|
delete message.message.senderKeyDistributionMessage |
|
|
chats.messages[message.key.id] = JSON.parse(JSON.stringify(message, null, 2)) |
|
|
let chatsMessages |
|
|
if ((chatsMessages = Object.entries(chats.messages)).length > 40) chats.messages = Object.fromEntries(chatsMessages.slice(30, chatsMessages.length)) |
|
|
} |
|
|
} catch (e) { |
|
|
console.error(e) |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.format = (...args) => { |
|
|
return util.format(...args) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.getBuffer = async (url, options) => { |
|
|
try { |
|
|
options ? options : {} |
|
|
const res = await axios({ |
|
|
method: "get", |
|
|
url, |
|
|
headers: { |
|
|
'DNT': 1, |
|
|
'Upgrade-Insecure-Request': 1 |
|
|
}, |
|
|
...options, |
|
|
responseType: 'arraybuffer' |
|
|
}) |
|
|
return res.data |
|
|
} catch (e) { |
|
|
console.log(`Error : ${e}`) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conn.serializeM = (m) => { |
|
|
return exports.smsg(conn, m) |
|
|
} |
|
|
|
|
|
Object.defineProperty(conn, 'name', { |
|
|
value: 'WASocket', |
|
|
configurable: true, |
|
|
}) |
|
|
return conn |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.smsg = (conn, m, hasParent) => { |
|
|
if (!m) return m |
|
|
let M = proto.WebMessageInfo |
|
|
m = M.fromObject(m) |
|
|
if (m.key) { |
|
|
m.id = m.key.id |
|
|
m.isBaileys = m.id && m.id.length === 22 || m.id.startsWith('3EB0') && m.id.length === 22 || false |
|
|
m.chat = conn.decodeJid(m.key.remoteJid || message.message?.senderKeyDistributionMessage?.groupId || '') |
|
|
m.isGroup = m.chat.endsWith('@g.us') |
|
|
m.sender = conn.decodeJid(m.key.fromMe && conn.user.id || m.participant || m.key.participant || m.chat || '') |
|
|
m.fromMe = m.key.fromMe || areJidsSameUser(m.sender, conn.user.id) |
|
|
} |
|
|
if (m.message) { |
|
|
let mtype = Object.keys(m.message) |
|
|
m.mtype = (!['senderKeyDistributionMessage', 'messageContextInfo'].includes(mtype[0]) && mtype[0]) || |
|
|
(mtype.length >= 3 && mtype[1] !== 'messageContextInfo' && mtype[1]) || |
|
|
mtype[mtype.length - 1] |
|
|
m.msg = m.message[m.mtype] |
|
|
if (m.chat == 'status@broadcast' && ['protocolMessage', 'senderKeyDistributionMessage'].includes(m.mtype)) m.chat = (m.key.remoteJid !== 'status@broadcast' && m.key.remoteJid) || m.sender |
|
|
if (m.mtype == 'protocolMessage' && m.msg.key) { |
|
|
if (m.msg.key.remoteJid == 'status@broadcast') m.msg.key.remoteJid = m.chat |
|
|
if (!m.msg.key.participant || m.msg.key.participant == 'status_me') m.msg.key.participant = m.sender |
|
|
m.msg.key.fromMe = conn.decodeJid(m.msg.key.participant) === conn.decodeJid(conn.user.id) |
|
|
if (!m.msg.key.fromMe && m.msg.key.remoteJid === conn.decodeJid(conn.user.id)) m.msg.key.remoteJid = m.sender |
|
|
} |
|
|
m.text = m.msg.text || m.msg.caption || m.msg.contentText || m.msg || '' |
|
|
if (typeof m.text !== 'string') { |
|
|
if ([ |
|
|
'protocolMessage', |
|
|
'messageContextInfo', |
|
|
'stickerMessage', |
|
|
'audioMessage', |
|
|
'senderKeyDistributionMessage' |
|
|
].includes(m.mtype)) m.text = '' |
|
|
else m.text = m.text.selectedDisplayText || m.text.hydratedTemplate?.hydratedContentText || m.text |
|
|
} |
|
|
m.mentionedJid = m.msg?.contextInfo?.mentionedJid?.length && m.msg.contextInfo.mentionedJid || [] |
|
|
let quoted = m.quoted = m.msg?.contextInfo?.quotedMessage ? m.msg.contextInfo.quotedMessage : null |
|
|
if (m.quoted) { |
|
|
let type = Object.keys(m.quoted)[0] |
|
|
m.quoted = m.quoted[type] |
|
|
if (typeof m.quoted === 'string') m.quoted = { text: m.quoted } |
|
|
m.quoted.mtype = type |
|
|
m.quoted.id = m.msg.contextInfo.stanzaId |
|
|
m.quoted.chat = conn.decodeJid(m.msg.contextInfo.remoteJid || m.chat || m.sender) |
|
|
m.quoted.isBaileys = m.quoted.id && m.quoted.id.length === 22 || false |
|
|
m.quoted.sender = conn.decodeJid(m.msg.contextInfo.participant) |
|
|
m.quoted.fromMe = m.quoted.sender === conn.user.jid |
|
|
m.quoted.text = m.quoted.text || m.quoted.caption || m.quoted.contentText || '' |
|
|
m.quoted.name = conn.getName(m.quoted.sender) |
|
|
m.quoted.mentionedJid = m.quoted.contextInfo?.mentionedJid?.length && m.quoted.contextInfo.mentionedJid || [] |
|
|
let vM = m.quoted.fakeObj = M.fromObject({ |
|
|
key: { |
|
|
fromMe: m.quoted.fromMe, |
|
|
remoteJid: m.quoted.chat, |
|
|
id: m.quoted.id |
|
|
}, |
|
|
message: quoted, |
|
|
...(m.isGroup ? { participant: m.quoted.sender } : {}) |
|
|
}) |
|
|
m.getQuotedObj = m.getQuotedMessage = async () => { |
|
|
if (!m.quoted.id) return null |
|
|
let q = M.fromObject(await conn.loadMessage(m.quoted.id) || vM) |
|
|
return exports.smsg(conn, q) |
|
|
} |
|
|
if (m.quoted.url || m.quoted.directPath) m.quoted.download = (saveToFile = false) => conn.downloadM(m.quoted, m.quoted.mtype.replace(/message/i, ''), saveToFile) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.quoted.reply = (text, chatId, options) => conn.reply(chatId ? chatId : m.chat, text, vM, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.quoted.copy = () => exports.smsg(conn, M.fromObject(M.toObject(vM))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.quoted.forward = (jid, forceForward = false) => conn.forwardMessage(jid, vM, forceForward) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.quoted.copyNForward = (jid, forceForward = true, options = {}) => conn.copyNForward(jid, vM, forceForward, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.quoted.cMod = (jid, text = '', sender = m.quoted.sender, options = {}) => conn.cMod(jid, vM, text, sender, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.quoted.delete = () => conn.sendMessage(m.quoted.chat, { delete: vM.key }) |
|
|
} |
|
|
} |
|
|
m.name = m.pushName || conn.getName(m.sender) |
|
|
if (m.msg && m.msg.url) m.download = (saveToFile = false) => conn.downloadM(m.msg, m.mtype.replace(/message/i, ''), saveToFile) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.reply = (text, chatId, options) => conn.reply(chatId ? chatId : m.chat, text, m, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.copy = () => exports.smsg(conn, M.fromObject(M.toObject(m))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.forward = (jid = m.chat, forceForward = false) => conn.copyNForward(jid, m, forceForward, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.copyNForward = (jid = m.chat, forceForward = true, options = {}) => conn.copyNForward(jid, m, forceForward, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.cMod = (jid, text = '', sender = m.sender, options = {}) => conn.cMod(jid, m, text, sender, options) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.delete = () => conn.sendMessage(m.chat, { delete: m.key }) |
|
|
|
|
|
try { |
|
|
if (m.msg && m.mtype == 'protocolMessage') conn.ev.emit('message.delete', m.msg.key) |
|
|
} catch (e) { |
|
|
console.error(e) |
|
|
} |
|
|
return m |
|
|
} |
|
|
|
|
|
exports.logic = (check, inp, out) => { |
|
|
if (inp.length !== out.length) throw new Error('Input and Output must have same length') |
|
|
for (let i in inp) if (util.isDeepStrictEqual(check, inp[i])) return out[i] |
|
|
return null |
|
|
} |
|
|
|
|
|
exports.protoType = () => { |
|
|
Buffer.prototype.toArrayBuffer = function toArrayBufferV2() { |
|
|
const ab = new ArrayBuffer(this.length); |
|
|
const view = new Uint8Array(ab); |
|
|
for (let i = 0; i < this.length; ++i) { |
|
|
view[i] = this[i]; |
|
|
} |
|
|
return ab; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Buffer.prototype.toArrayBufferV2 = function toArrayBuffer() { |
|
|
return this.buffer.slice(this.byteOffset, this.byteOffset + this.byteLength) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ArrayBuffer.prototype.toBuffer = function toBuffer() { |
|
|
return Buffer.from(new Uint8Array(this)) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Uint8Array.prototype.getFileType = ArrayBuffer.prototype.getFileType = Buffer.prototype.getFileType = async function getFileType() { |
|
|
return await fileTypeFromBuffer(this) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String.prototype.isNumber = Number.prototype.isNumber = isNumber |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String.prototype.capitalize = function capitalize() { |
|
|
return this.charAt(0).toUpperCase() + this.slice(1, this.length) |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String.prototype.capitalizeV2 = function capitalizeV2() { |
|
|
const str = this.split(' ') |
|
|
return str.map(v => v.capitalize()).join(' ') |
|
|
} |
|
|
String.prototype.decodeJid = function decodeJid() { |
|
|
if (/:\d+@/gi.test(this)) { |
|
|
const decode = jidDecode(this) || {} |
|
|
return (decode.user && decode.server && decode.user + '@' + decode.server || this).trim() |
|
|
} else return this.trim() |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Number.prototype.toTimeString = function toTimeString() { |
|
|
|
|
|
const seconds = Math.floor((this / 1000) % 60) |
|
|
const minutes = Math.floor((this / (60 * 1000)) % 60) |
|
|
const hours = Math.floor((this / (60 * 60 * 1000)) % 24) |
|
|
const days = Math.floor((this / (24 * 60 * 60 * 1000))) |
|
|
return ( |
|
|
(days ? `${days} day(s) ` : '') + |
|
|
(hours ? `${hours} hour(s) ` : '') + |
|
|
(minutes ? `${minutes} minute(s) ` : '') + |
|
|
(seconds ? `${seconds} second(s)` : '') |
|
|
).trim() |
|
|
} |
|
|
Number.prototype.getRandom = String.prototype.getRandom = Array.prototype.getRandom = getRandom |
|
|
} |
|
|
|
|
|
function isNumber() { |
|
|
const int = parseInt(this) |
|
|
return typeof int === 'number' && !isNaN(int) |
|
|
} |
|
|
|
|
|
function getRandom() { |
|
|
if (Array.isArray(this) || this instanceof String) return this[Math.floor(Math.random() * this.length)] |
|
|
return Math.floor(Math.random() * this) |
|
|
} |
|
|
|
|
|
function rand(isi) { |
|
|
return isi[Math.floor(Math.random() * isi.length)] |
|
|
} |
|
|
|