projek3 / lib /simple.js
devstok's picture
Upload folder using huggingface_hub
47ab1ce verified
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.ws.on('CB:stream:error', (stream) => {
// const { code } = stream || {}
// if (code == '401') conn.ev.emit('connection.update', {
// connection: 'logged Out',
// lastDisconnect: {
// error: {
// output: {
// statusCode: DisconnectReason.loggedOut
// }
// },
// date: new Date()
// }
// })
// })
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))) }
}
/**
* getBuffer hehe
* @param {fs.PathLike} path
* @param {Boolean} returnFilename
*/
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
}
}
/**
* waitEvent
* @param {Partial<BaileysEventMap>|String} eventName
* @param {Boolean} is
* @param {Number} maxTries
* @returns
*/
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))
/**
*
* @param {String} text
* @returns
*/
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]
}
}
/**
* ms to date
* @param {String} ms
*/
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";
// +minutes+":"+sec;
}
/**
* isi
*/
conn.rand = async (isi) => {
return isi[Math.floor(Math.random() * isi.length)]
}
/**
* For Resize the Image By Aine
* @param {Buffer} image
* @param {String} ukuran height
* @param {String} ukuran weight
* @returns
*/
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)
})
}
/**
* Send Media All Type
* @param {String} jid
* @param {String|Buffer} path
* @param {Object} quoted
* @param {Object} options
*/
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 })
}
/**
* Send Media/File with Automatic Type Specifier
* @param {String} jid
* @param {String|Buffer} path
* @param {String} filename
* @param {String} caption
* @param {proto.WebMessageInfo} quoted
* @param {Boolean} ptt
* @param {Object} options
*/
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
}
}
/**
* Send Media/File with Automatic Type Specifier
* @param {String} jid
* @param {String|Buffer} path
* @param {String} filename
* @param {String} caption
* @param {Object} quoted
* @param {Boolean} ptt
* @param {Object} options
*/
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
})
}
//Wm Sticker
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
}
/**
* Send Contact
* @param {String} jid
* @param {String[][]} data
* @param {proto.WebMessageInfo} quoted
* @param {Object} options
*/
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) || {}
// N:;${name.replace(/\n/g, '\\n').split(' ').reverse().join(';')};;;
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
})
}
/**
* Reply to a message
* @param {String} jid
* @param {String|Object} text
* @param {Object} quoted
* @param {Object} 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
}
/**
*
* @param {*} jid
* @param {*} text
* @param {*} quoted
* @param {*} options
* @returns
*/
conn.sendText = (jid, text, quoted = '', options) => conn.sendMessage(jid, { text: text, ...options }, { quoted })
/**
* sendGroupV4Invite
* @param {String} jid
* @param {*} participant
* @param {String} inviteCode
* @param {Number} inviteExpiration
* @param {String} groupName
* @param {String} caption
* @param {*} options
* @returns
*/
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
}
/**
* send Button
* @param {String} jid
* @param {String} contentText
* @param {String} footer
* @param {Buffer|String} buffer
* @param {String[]} buttons
* @param {proto.WebMessageInfo} quoted
* @param {Object} options
*/
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})
}
/**
* send Button Img
* @param {String} jid
* @param {String} contentText
* @param {String} footer
* @param {Buffer|String} buffer
* @param {String[]} buttons
* @param {Object} quoted
* @param {Object} options
*/
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 // mtype === 'ephemeralMessage'
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
})
}
/**
* send Button Vid
* @param {String} jid
* @param {String} contentText
* @param {String} footer
* @param {Buffer|String} buffer
* @param {String} buttons1
* @param {String} row1
* @param {Object} quoted
* @param {Object} 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
})
}
/**
* cMod
* @param {String} jid
* @param {*} message
* @param {String} text
* @param {String} sender
* @param {*} options
* @returns
*/
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)
}
/**
* cMods
* @param {String} jid
* @param {proto.WebMessageInfo} message
* @param {String} text
* @param {String} sender
* @param {*} options
* @returns
*/
conn.cMods = (jid, message, text = '', sender = conn.user.jid, options = {}) => {
let copy = message.toJSON()
let mtype = Object.keys(copy.message)[0]
let isEphemeral = false // mtype === 'ephemeralMessage'
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)
}
/**
* Exact Copy Forward
* @param {String} jid
* @param {proto.WebMessageInfo} message
* @param {Boolean|Number} forwardingScore
* @param {Object} options
*/
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
}
/**
* Fake Replies
* @param {String} jid
* @param {String|Object} text
* @param {String} fakeJid
* @param {String} fakeText
* @param {String} fakeGroupJid
* @param {String} options
*/
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]
})
/**
* Download media message
* @param {Object} m
* @param {String} type
* @param {fs.PathLike|fs.promises.FileHandle} filename
* @returns {Promise<fs.PathLike|fs.promises.FileHandle|Buffer>}
*/
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
// save to file
await fs.writeFileSync(trueFileName, buffer)
return trueFileName
}
/**
* parseMention(s)
* @param {string} text
* @returns {string[]}
*/
conn.parseMention = (text = '') => {
return [...text.matchAll(/@([0-9]{5,16}|0)/g)].map(v => v[1] + '@s.whatsapp.net')
}
/**
* Read message
* @param {String} jid
* @param {String|undefined|null} participant
* @param {String} messageID
*/
conn.chatRead = async (jid, participant = conn.user.jid, messageID) => {
return await conn.sendReadReceipt(jid, participant, [messageID])
}
/**
* Parses string into mentionedJid(s)
* @param {String} text
*/
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 })
/**
* Get name from jid
* @param {String} jid
* @param {Boolean} withoutContact
*/
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')
}
/**
* to process MessageStubType
* @param {proto.WebMessageInfo} m
*/
conn.processMessageStubType = async(m) => {
/**
* to process MessageStubType
* @param {import('@adiwajshing/baileys').proto.WebMessageInfo} 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.processMessageStubType = async (m) => {
if (!m.messageStubType) return
const mtype = Object.keys(m.message || {})[0]
const chat = conn.decodeJid(m.key.remoteJid || m.message[mtype] && m.message[mtype].groupId || '')
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
}*/
/**
* pushMessage
* @param {proto.WebMessageInfo[]} m
*/
conn.pushMessage = async(m) => {
/**
* pushMessage
* @param {import('@adiwajshing/baileys').proto.WebMessageInfo[]} m
*/
if (!m) return
if (!Array.isArray(m)) m = [m]
for (const message of m) {
try {
// if (!(message instanceof proto.WebMessageInfo)) continue // https://github.com/adiwajshing/Baileys/pull/696/commits/6a2cb5a4139d8eb0a75c4c4ea7ed52adc0aec20f
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) {
/**
* @type {import('@adiwajshing/baileys').proto.IContextInfo}
*/
let context = message.message[mtype].contextInfo
let participant = conn.decodeJid(context.participant)
const remoteJid = conn.decodeJid(context.remoteJid || participant)
/**
* @type {import('@adiwajshing/baileys').proto.IMessage}
*
*/
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)) // maybe avoid memory leak
}
}
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.pushMessage = async (m) => {
if (!m) return
if (!Array.isArray(m)) m = [m]
for (const message of m) {
try {
// if (!(message instanceof proto.WebMessageInfo)) continue // https://github.com/adiwajshing/Baileys/pull/696/commits/6a2cb5a4139d8eb0a75c4c4ea7ed52adc0aec20f
if (!message) continue
if (message.messageStubType) conn.processMessageStubType(message).catch(console.error)
let mtype = Object.keys(message.message || {})
mtype = mtype[mtype[0] === 'messageContextInfo' && mtype.length == 2 ? 1 : 0]
const chat = conn.decodeJid(message.key.remoteJid || message.message[mtype] && message.message[mtype].groupId || '')
const isGroup = chat.endsWith('@g.us')
let chats = conn.chats[chat]
if (!chats) {
if (isGroup) {
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] }
}
chats = conn.chats[chat] = { id: chat, ...(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.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', 'protocolMessage'].includes(mtype)) continue
chats.isChats = true
const fromMe = message.key.fromMe || areJidsSameUser(chat, conn.user.id)
if (!chats.messages) chats.messages = {}
if (!fromMe) chats.messages[message.key.id] = JSON.parse(JSON.stringify(message, null, 2))
} catch (e) {
console.error(e)
}
}
}*/
/**
*
* @param {...any} args
* @returns
*/
conn.format = (...args) => {
return util.format(...args)
}
/**
*
* @param {String} url
* @param {Object} options
* @returns
*/
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}`)
}
}
/**
* Serialize Message, so it easier to manipulate
* @param {Object} m
*/
conn.serializeM = (m) => {
return exports.smsg(conn, m)
}
Object.defineProperty(conn, 'name', {
value: 'WASocket',
configurable: true,
})
return conn
}
/**
* Serialize Message
* @param {ReturnType<typeof makeWASocket>} conn
* @param {proto.WebMessageInfo} m
* @param {Boolean} hasParent
*/
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]) || // Sometimes message in the front
(mtype.length >= 3 && mtype[1] !== 'messageContextInfo' && mtype[1]) || // Sometimes message in midle if mtype length is greater than or equal to 3!
mtype[mtype.length - 1] // common case
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)
/*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 === 16 || m.id.startsWith('3EB0') && m.id.length === 12 || false
let mtype = Object.keys(m.message || {})[0]
m.chat = conn.decodeJid(m.key.remoteJid || m.message[mtype] && m.message[mtype].groupId || '')
m.isGroup = m.chat.endsWith('@g.us')
m.sender = conn.decodeJid(m.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 = mtype[mtype[0] === 'messageContextInfo' && mtype.length == 2 ? 1 : 0]
m.msg = m.message[m.mtype]
if (m.chat == 'status@broadcast' && ['protocolMessage', 'senderKeyDistributionMessage'].includes(m.mtype)) m.chat = m.sender
// if (m.mtype === 'ephemeralMessage') {
// exports.smsg(conn, m.msg)
// m.mtype = m.msg.mtype
// m.msg = m.msg.msg
// }
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 || ''
m.mentionedJid = m.msg && m.msg.contextInfo && m.msg.contextInfo.mentionedJid && m.msg.contextInfo.mentionedJid.length && m.msg.contextInfo.mentionedJid || []
let quoted = m.quoted = m.msg && m.msg.contextInfo && 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 === 16 || 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.name = conn.getName(m.quoted.sender)
m.quoted.mentionedJid = m.quoted.contextInfo && m.quoted.contextInfo.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 = () => {
if (!m.quoted.id) return false
let q = M.fromObject(((conn.chats[m.quoted.chat] || {}).messages || {})[m.quoted.id])
return exports.smsg(conn, q ? q : vM)
}
if (m.quoted.url || m.quoted.directPath) m.quoted.download = (saveToFile = false) => conn.downloadM(m.quoted, m.quoted.mtype.replace(/message/i, ''), saveToFile)*/
/**
* Reply to quoted message
* @param {String|Object} text
* @param {String|false} chatId
* @param {Object} options
*/
m.quoted.reply = (text, chatId, options) => conn.reply(chatId ? chatId : m.chat, text, vM, options)
/**
* Copy quoted message
*/
m.quoted.copy = () => exports.smsg(conn, M.fromObject(M.toObject(vM)))
/**
* Forward quoted message
* @param {String} jid
* @param {Boolean} forceForward
*/
m.quoted.forward = (jid, forceForward = false) => conn.forwardMessage(jid, vM, forceForward)
/**
* Exact Forward quoted message
* @param {String} jid
* @param {Boolean|Number} forceForward
* @param {Object} options
*/
m.quoted.copyNForward = (jid, forceForward = true, options = {}) => conn.copyNForward(jid, vM, forceForward, options)
/**
* Modify quoted Message
* @param {String} jid
* @param {String} text
* @param {String} sender
* @param {Object} options
*/
m.quoted.cMod = (jid, text = '', sender = m.quoted.sender, options = {}) => conn.cMod(jid, vM, text, sender, options)
/**
* Delete quoted message
*/
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)
/**
* Reply to this message
* @param {String|Object} text
* @param {String|false} chatId
* @param {Object} options
*/
m.reply = (text, chatId, options) => conn.reply(chatId ? chatId : m.chat, text, m, options)
/**
* Copy this message
*/
m.copy = () => exports.smsg(conn, M.fromObject(M.toObject(m)))
/**
* Forward this message
* @param {String} jid
* @param {Boolean} forceForward
*/
m.forward = (jid = m.chat, forceForward = false) => conn.copyNForward(jid, m, forceForward, options)
/**
* Exact Forward this message
* @param {String} jid
* @param {Boolean} forceForward
* @param {Object} options
*/
m.copyNForward = (jid = m.chat, forceForward = true, options = {}) => conn.copyNForward(jid, m, forceForward, options)
/**
* Modify this Message
* @param {String} jid
* @param {String} text
* @param {String} sender
* @param {Object} options
*/
m.cMod = (jid, text = '', sender = m.sender, options = {}) => conn.cMod(jid, m, text, sender, options)
/**
* Delete this message
*/
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;
}
/**
* @returns {ArrayBuffer}
*/
Buffer.prototype.toArrayBufferV2 = function toArrayBuffer() {
return this.buffer.slice(this.byteOffset, this.byteOffset + this.byteLength)
}
/**
* @returns {Buffer}
*/
ArrayBuffer.prototype.toBuffer = function toBuffer() {
return Buffer.from(new Uint8Array(this))
}
// /**
// * @returns {String}
// */
// Buffer.prototype.toUtilFormat = ArrayBuffer.prototype.toUtilFormat = Object.prototype.toUtilFormat = Array.prototype.toUtilFormat = function toUtilFormat() {
// return util.format(this)
// }
Uint8Array.prototype.getFileType = ArrayBuffer.prototype.getFileType = Buffer.prototype.getFileType = async function getFileType() {
return await fileTypeFromBuffer(this)
}
/**
* @returns {Boolean}
*/
String.prototype.isNumber = Number.prototype.isNumber = isNumber
/**
*
* @returns {String}
*/
String.prototype.capitalize = function capitalize() {
return this.charAt(0).toUpperCase() + this.slice(1, this.length)
}
/**
* @returns {String}
*/
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 must be milliseconds
* @returns {string}
*/
Number.prototype.toTimeString = function toTimeString() {
// const milliseconds = this % 1000
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)]
}