|
import path from 'path' |
|
import { toAudio } from './converter.js' |
|
import chalk from 'chalk' |
|
import fetch from 'node-fetch' |
|
import PhoneNumber from 'awesome-phonenumber' |
|
import fs from 'fs' |
|
import util from 'util' |
|
import { fileTypeFromBuffer } from 'file-type' |
|
import { format } from 'util' |
|
import { fileURLToPath } from 'url' |
|
import logg from 'pino' |
|
import pino from'pino' |
|
import store from './store.js' |
|
let conv = await import('./sticker.js') |
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url)) |
|
|
|
|
|
|
|
|
|
|
|
const { |
|
default: _makeWaSocket, |
|
makeWALegacySocket, |
|
makeInMemoryStore, |
|
proto, |
|
downloadContentFromMessage, |
|
jidDecode, |
|
areJidsSameUser, |
|
generateForwardMessageContent, |
|
generateWAMessageFromContent, |
|
WAMessageStubType, |
|
generateWAMessage, |
|
getContentType, |
|
extractMessageContent, jidNormalizedUser |
|
} = (await import('baileys')).default |
|
|
|
import * as baileys from 'baileys' |
|
|
|
export function HelperConnection(conn, connectionOptions, options = {}) { |
|
|
|
|
|
|
|
|
|
|
|
let sock = Object.defineProperties(conn, { |
|
chats: { |
|
value: { ...(options.chats || {}) }, |
|
writable: true |
|
}, |
|
decodeJid: { |
|
value(jid) { |
|
if (!jid || typeof jid !== 'string') return (!nullish(jid) && jid) || null |
|
return jid.decodeJid() |
|
} |
|
}, |
|
logger: { |
|
get() { |
|
return { |
|
info(...args) { |
|
console.log( |
|
chalk.bold.bgRgb(51, 204, 51)('INFO '), |
|
`[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`, |
|
chalk.cyan(format(...args)) |
|
) |
|
}, |
|
error(...args) { |
|
console.log( |
|
chalk.bold.bgRgb(247, 38, 33)('ERROR '), |
|
`[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`, |
|
chalk.rgb(255, 38, 0)(format(...args)) |
|
) |
|
}, |
|
warn(...args) { |
|
console.log( |
|
chalk.bold.bgRgb(255, 153, 0)('WARNING '), |
|
`[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`, |
|
chalk.redBright(format(...args)) |
|
) |
|
}, |
|
trace(...args) { |
|
console.log( |
|
chalk.grey('TRACE '), |
|
`[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`, |
|
chalk.white(format(...args)) |
|
) |
|
}, |
|
debug(...args) { |
|
console.log( |
|
chalk.bold.bgRgb(66, 167, 245)('DEBUG '), |
|
`[${chalk.rgb(255, 255, 255)(new Date().toUTCString())}]:`, |
|
chalk.white(format(...args)) |
|
) |
|
} |
|
} |
|
}, |
|
enumerable: true |
|
}, |
|
|
|
|
|
|
|
|
|
getFile: { |
|
|
|
|
|
|
|
|
|
|
|
async value(PATH, saveToFile = false) { |
|
let res, filename |
|
const data = Buffer.isBuffer(PATH) ? PATH : PATH instanceof ArrayBuffer ? PATH.toBuffer() : /^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') |
|
const type = await fileTypeFromBuffer(data) || { |
|
mime: 'application/octet-stream', |
|
ext: '.bin' |
|
} |
|
if (data && saveToFile && !filename) (filename = path.join(__dirname, '../tmp/' + new Date * 1 + '.' + type.ext), await fs.promises.writeFile(filename, data)) |
|
return { |
|
res, |
|
filename, |
|
...type, |
|
data, |
|
deleteFile() { |
|
return filename && fs.promises.unlink(filename) |
|
} |
|
} |
|
}, |
|
enumerable: true |
|
}, |
|
|
|
|
|
|
|
|
|
sendSticker: { |
|
|
|
async value(jid, media, m, opts = {}) { |
|
|
|
const medias = await conn.getFile(media) |
|
return this.sendMessage(jid, await conv.sticker(medias.data, null, opts.packname || 'Whatsapp Bot', opts.author || conn.user.name), 'stickerMessage', { quoted: m, ...opts }) |
|
} |
|
}, |
|
|
|
waitEvent: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
value(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) |
|
}) |
|
} |
|
}, |
|
sendFile: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(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 } |
|
} |
|
const fileSize = fs.statSync(pathFile).size / 1024 / 1024 |
|
if (fileSize >= 100) throw new Error('File size is too big!') |
|
let opt = {} |
|
if (quoted) opt.quoted = quoted |
|
if (!type) options.asDocument = true |
|
let mtype = '', mimetype = options.mimetype || type.mime, convert |
|
if (/webp/.test(type.mime) || (/image/.test(type.mime) && options.asSticker)) mtype = 'sticker' |
|
else if (/image/.test(type.mime) || (/webp/.test(type.mime) && options.asImage)) mtype = 'image' |
|
else if (/video/.test(type.mime)) mtype = 'video' |
|
else if (/audio/.test(type.mime)) ( |
|
convert = await toAudio(file, type.ext), |
|
file = convert.data, |
|
pathFile = convert.filename, |
|
mtype = 'audio', |
|
mimetype = options.mimetype || 'audio/ogg; codecs=opus' |
|
) |
|
else mtype = 'document' |
|
if (options.asDocument) mtype = 'document' |
|
|
|
delete options.asSticker |
|
delete options.asLocation |
|
delete options.asVideo |
|
delete options.asDocument |
|
delete options.asImage |
|
|
|
let message = { |
|
...options, |
|
caption, |
|
ptt, |
|
[mtype]: { url: pathFile }, |
|
mimetype, |
|
fileName: filename || pathFile.split('/').pop() |
|
} |
|
|
|
|
|
|
|
let m |
|
try { |
|
m = await conn.sendMessage(jid, message, { ...opt, ...options }) |
|
} catch (e) { |
|
console.error(e) |
|
m = null |
|
} finally { |
|
if (!m) m = await conn.sendMessage(jid, { ...message, [mtype]: file }, { ...opt, ...options }) |
|
file = null |
|
return m |
|
} |
|
}, |
|
enumerable: true |
|
}, |
|
sendContact: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(jid, data, quoted, options) { |
|
if (!Array.isArray(data[0]) && typeof data[0] === 'string') data = [data] |
|
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).catch(_ => null) || {} |
|
let vcard = ` |
|
BEGIN:VCARD |
|
VERSION:3.0 |
|
N:;${name.replace(/\n/g, '\\n')};;; |
|
FN:${name.replace(/\n/g, '\\n')} |
|
TEL;type=CELL;type=VOICE;waid=${number}:${PhoneNumber('+' + number).getNumber('international')}${biz.description ? ` |
|
X-WA-BIZ-NAME:${(conn.chats[njid]?.vname || conn.getName(njid) || name).replace(/\n/, '\\n')} |
|
X-WA-BIZ-DESCRIPTION:${biz.description.replace(/\n/g, '\\n')} |
|
`.trim() : ''} |
|
END:VCARD |
|
`.trim() |
|
contacts.push({ vcard, displayName: name }) |
|
|
|
} |
|
return await conn.sendMessage(jid, { |
|
...options, |
|
contacts: { |
|
...options, |
|
displayName: (contacts.length >= 2 ? `${contacts.length} kontak` : contacts[0].displayName) || null, |
|
contacts, |
|
} |
|
}, { quoted, ...options }) |
|
}, |
|
enumerable: true |
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reply: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value(jid, text = '', quoted, options) { |
|
let pp = conn.profilePictureUrl(conn.user.jid, 'image') |
|
const _uptime = process.uptime() * 1000 |
|
return Buffer.isBuffer(text) ? conn.sendFile(jid, text, 'file', '', quoted, false, options) : conn.sendMessage(jid, { ...options, |
|
text, |
|
mentions: conn.parseMention(text), |
|
contextInfo: global.adReply.contextInfo, |
|
mentions: conn.parseMention(text), |
|
...options }, { |
|
quoted, |
|
ephemeralExpiration: 0, |
|
...options |
|
}) |
|
} |
|
}, |
|
|
|
replyV2: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value(jid, text = '', quoted, options) { |
|
let pp = conn.profilePictureUrl(conn.user.jid, 'image') |
|
const _uptime = process.uptime() * 1000 |
|
return Buffer.isBuffer(text) ? conn.sendFile(jid, text, 'file', '', quoted, false, options) : conn.sendMessage(jid, { ...options, |
|
text, |
|
mentions: conn.parseMention(text), |
|
contextInfo: global.adReplyV2.contextInfo, |
|
mentions: conn.parseMention(text), |
|
...options }, { |
|
quoted, |
|
ephemeralExpiration: 86400, |
|
...options |
|
}) |
|
} |
|
}, |
|
|
|
sendButtonImg: { |
|
async value (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: 999999999999999, |
|
caption: contentText, |
|
footer: footerText, |
|
mentions: await conn.parseMention(contentText + footerText), |
|
...options, |
|
buttons: buttons, |
|
headerType: 4 |
|
} |
|
|
|
return await conn.sendMessage(jid, buttonMessage, { quoted, ephemeralExpiration: global.ephemeral, contextInfo: { mentionedJid: conn.parseMention(contentText + footerText) }, ...options }) |
|
} |
|
}, |
|
sendButton: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(jid, text = '', footer = '', buffer, buttons, quoted, options) { |
|
let type |
|
if (Array.isArray(buffer)) (options = quoted, quoted = buttons, buttons = buffer, buffer = null) |
|
else if (buffer) try { (type = await conn.getFile(buffer), buffer = type.data) } catch { buffer = null } |
|
if (!Array.isArray(buttons[0]) && typeof buttons[0] === 'string') buttons = [buttons] |
|
if (!options) options = {} |
|
let message = { |
|
...options, |
|
[buffer ? 'caption' : 'text']: text || '', |
|
footer, |
|
buttons: buttons.map(btn => ({ |
|
buttonId: !nullish(btn[1]) && btn[1] || !nullish(btn[0]) && btn[0] || '', |
|
buttonText: { |
|
displayText: !nullish(btn[0]) && btn[0] || !nullish(btn[1]) && btn[1] || '' |
|
} |
|
})), |
|
...(buffer ? |
|
options.asLocation && /image/.test(type.mime) ? { |
|
location: { |
|
...options, |
|
jpegThumbnail: buffer |
|
} |
|
} : { |
|
[/video/.test(type.mime) ? 'video' : /image/.test(type.mime) ? 'image' : 'document']: buffer |
|
} : {}) |
|
} |
|
|
|
return await conn.sendMessage(jid, message, { |
|
quoted, |
|
upload: conn.waUploadToServer, |
|
...options |
|
}) |
|
}, |
|
enumerable: true |
|
}, |
|
sendHydrated: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(jid, text = '', footer = '', buffer, url, urlText, call, callText, buttons, quoted, options) { |
|
let type |
|
if (buffer) try { (type = await conn.getFile(buffer), buffer = type.data) } catch { buffer = buffer } |
|
if (buffer && !Buffer.isBuffer(buffer) && (typeof buffer === 'string' || Array.isArray(buffer))) (options = quoted, quoted = buttons, buttons = callText, callText = call, call = urlText, urlText = url, url = buffer, buffer = null) |
|
if (!options) options = {} |
|
let templateButtons = [] |
|
if (url || urlText) { |
|
if (!Array.isArray(url)) url = [url] |
|
if (!Array.isArray(urlText)) urlText = [urlText] |
|
templateButtons.push(...( |
|
url.map((v, i) => [v, urlText[i]]) |
|
.map(([url, urlText], i) => ({ |
|
index: templateButtons.length + i + 1, |
|
urlButton: { |
|
displayText: !nullish(urlText) && urlText || !nullish(url) && url || '', |
|
url: !nullish(url) && url || !nullish(urlText) && urlText || '' |
|
} |
|
})) || [] |
|
)) |
|
} |
|
if (call || callText) { |
|
if (!Array.isArray(call)) call = [call] |
|
if (!Array.isArray(callText)) callText = [callText] |
|
templateButtons.push(...( |
|
call.map((v, i) => [v, callText[i]]) |
|
.map(([call, callText], i) => ({ |
|
index: templateButtons.length + i + 1, |
|
callButton: { |
|
displayText: !nullish(callText) && callText || !nullish(call) && call || '', |
|
phoneNumber: !nullish(call) && call || !nullish(callText) && callText || '' |
|
} |
|
})) || [] |
|
)) |
|
} |
|
if (buttons.length) { |
|
if (!Array.isArray(buttons[0])) buttons = [buttons] |
|
templateButtons.push(...( |
|
buttons.map(([text, id], index) => ({ |
|
index: templateButtons.length + index + 1, |
|
quickReplyButton: { |
|
displayText: !nullish(text) && text || !nullish(id) && id || '', |
|
id: !nullish(id) && id || !nullish(text) && text || '' |
|
} |
|
})) || [] |
|
)) |
|
} |
|
let message = { |
|
...options, |
|
[buffer ? 'caption' : 'text']: text || '', |
|
footer, |
|
templateButtons, |
|
...(buffer ? |
|
options.asLocation && /image/.test(type.mime) ? { |
|
location: { |
|
...options, |
|
jpegThumbnail: buffer |
|
} |
|
} : { |
|
[/video/.test(type.mime) ? 'video' : /image/.test(type.mime) ? 'image' : 'document']: buffer |
|
} : {}) |
|
} |
|
return await conn.sendMessage(jid, message, { |
|
quoted, |
|
upload: conn.waUploadToServer, |
|
...options |
|
}) |
|
}, |
|
enumerable: true |
|
}, |
|
|
|
sendHydrated2: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(jid, text = '', footer = '', buffer, url, urlText, url2, urlText2, buttons, quoted, options) { |
|
let type |
|
if (buffer) try { (type = await conn.getFile(buffer), buffer = type.data) } catch { buffer = buffer } |
|
if (buffer && !Buffer.isBuffer(buffer) && (typeof buffer === 'string' || Array.isArray(buffer))) (options = quoted, quoted = buttons, buttons = callText, callText = call, call = urlText, urlText = url, url = buffer, buffer = null) |
|
if (!options) options = {} |
|
let templateButtons = [] |
|
if (url || urlText) { |
|
if (!Array.isArray(url)) url = [url] |
|
if (!Array.isArray(urlText)) urlText = [urlText] |
|
templateButtons.push(...( |
|
url.map((v, i) => [v, urlText[i]]) |
|
.map(([url, urlText], i) => ({ |
|
index: templateButtons.length + i + 1, |
|
urlButton: { |
|
displayText: !nullish(urlText) && urlText || !nullish(url) && url || '', |
|
url: !nullish(url) && url || !nullish(urlText) && urlText || '' |
|
} |
|
})) || [] |
|
)) |
|
} |
|
if (url2 || urlText2) { |
|
if (!Array.isArray(url2)) url2 = [url2] |
|
if (!Array.isArray(urlText2)) urlText2 = [urlText2] |
|
templateButtons.push(...( |
|
url2.map((v, i) => [v, urlText2[i]]) |
|
.map(([url2, urlText2], i) => ({ |
|
index: templateButtons.length + i + 1, |
|
urlButton: { |
|
displayText: !nullish(urlText2) && urlText2 || !nullish(url2) && url2 || '', |
|
url: !nullish(url2) && url2 || !nullish(urlText2) && urlText2 || '' |
|
} |
|
})) || [] |
|
)) |
|
} |
|
if (buttons.length) { |
|
if (!Array.isArray(buttons[0])) buttons = [buttons] |
|
templateButtons.push(...( |
|
buttons.map(([text, id], index) => ({ |
|
index: templateButtons.length + index + 1, |
|
quickReplyButton: { |
|
displayText: !nullish(text) && text || !nullish(id) && id || '', |
|
id: !nullish(id) && id || !nullish(text) && text || '' |
|
} |
|
})) || [] |
|
)) |
|
} |
|
let message = { |
|
...options, |
|
[buffer ? 'caption' : 'text']: text || '', |
|
footer, |
|
templateButtons, |
|
...(buffer ? |
|
options.asLocation && /image/.test(type.mime) ? { |
|
location: { |
|
...options, |
|
jpegThumbnail: buffer |
|
} |
|
} : { |
|
[/video/.test(type.mime) ? 'video' : /image/.test(type.mime) ? 'image' : 'document']: buffer |
|
} : {}) |
|
} |
|
return await conn.sendMessage(jid, message, { |
|
quoted, |
|
upload: conn.waUploadToServer, |
|
...options |
|
}) |
|
}, |
|
enumerable: true |
|
}, |
|
|
|
|
|
|
|
sendPoll: { |
|
async value(jid, name = '', optiPoll, options) { |
|
if (!Array.isArray(optiPoll[0]) && typeof optiPoll[0] === 'string') optiPoll = [optiPoll] |
|
if (!options) options = {} |
|
const pollMessage = { |
|
name: name, |
|
options: optiPoll.map(btn => ({ |
|
optionName: !nullish(btn[0]) && btn[0] || '' |
|
})), |
|
selectableOptionsCount: 1 |
|
} |
|
return conn.relayMessage(jid, { pollCreationMessage: pollMessage }, { ...options }); |
|
} |
|
}, |
|
|
|
cMod: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value(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) |
|
}, |
|
enumerable: true |
|
}, |
|
copyNForward: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(jid, message, forwardingScore = true, options = {}) { |
|
let vtype |
|
if (options.readViewOnce && message.message.viewOnceMessage?.message) { |
|
vtype = Object.keys(message.message.viewOnceMessage.message)[0] |
|
delete message.message.viewOnceMessage.message[vtype].viewOnce |
|
message.message = proto.Message.fromObject( |
|
JSON.parse(JSON.stringify(message.message.viewOnceMessage.message)) |
|
) |
|
message.message[vtype].contextInfo = message.message.viewOnceMessage.contextInfo |
|
} |
|
let mtype = Object.keys(message.message)[0] |
|
let m = generateForwardMessageContent(message, !!forwardingScore) |
|
let ctype = Object.keys(m)[0] |
|
if (forwardingScore && typeof forwardingScore === 'number' && forwardingScore > 200000) m[ctype].contextInfo.forwardingScore += forwardingScore |
|
m[ctype].contextInfo = { |
|
...(message.message[mtype].contextInfo || {}), |
|
...(m[ctype].contextInfo || {}) |
|
} |
|
m = generateWAMessageFromContent(jid, m, { |
|
...options, |
|
userJid: conn.user.jid |
|
}) |
|
await conn.relayMessage(jid, m.message, { messageId: m.key.id, additionalAttributes: { ...options } }) |
|
return m |
|
}, |
|
enumerable: true |
|
}, |
|
fakeReply: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value(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 }) |
|
} |
|
}, |
|
downloadM: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(m, type, saveToFile) { |
|
let filename |
|
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) ({ filename } = await conn.getFile(buffer, true)) |
|
return saveToFile && fs.existsSync(filename) ? filename : buffer |
|
}, |
|
enumerable: true |
|
}, |
|
parseMention: { |
|
|
|
|
|
|
|
|
|
|
|
value(text = '') { |
|
return [...text.matchAll(/@([0-9]{5,16}|0)/g)].map(v => v[1] + '@s.whatsapp.net') |
|
}, |
|
enumerable: true |
|
}, |
|
getName: { |
|
|
|
|
|
|
|
|
|
|
|
value(jid = '', withoutContact = false) { |
|
jid = conn.decodeJid(jid) |
|
withoutContact = conn.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') |
|
}, |
|
enumerable: true |
|
}, |
|
|
|
send3TemplateButtonImg: { |
|
async value (jid, buffer, content, 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 = [ |
|
{ index: 1, urlButton: { displayText: dtu, url: urlnya } }, |
|
{ index: 2, quickReplyButton: { displayText: button1, id: id1 } }, |
|
{ index: 3, quickReplyButton: { displayText: button2, id: id2 } }, |
|
{ index: 4, quickReplyButton: { displayText: button3, id: id3 } } |
|
] |
|
const buttonMessage = { |
|
image: file, |
|
caption: content, |
|
footer: footerText, |
|
mentions: await conn.parseMention(content + footerText), |
|
ephemeralExpiration: 86400, |
|
...options, |
|
templateButtons: buttons, |
|
headerType: 1 |
|
} |
|
conn.sendMessage(jid, buttonMessage, { quoted, ephemeralExpiration: 86400, contextInfo: { mentionedJid: conn.parseMention(content + footerText), forwardingScore: 99999, isForwarded: true }, ...options, ephemeralExpiration: 86400 } ) |
|
} |
|
}, |
|
|
|
loadMessage: { |
|
|
|
|
|
|
|
|
|
|
|
value(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] |
|
}, |
|
enumerable: true |
|
}, |
|
sendGroupV4Invite: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async value(jid, participant, inviteCode, inviteExpiration, groupName = 'unknown subject', caption = 'Invitation to join my WhatsApp group', jpegThumbnail, options = {}) { |
|
const msg = proto.Message.fromObject({ |
|
groupInviteMessage: proto.GroupInviteMessage.fromObject({ |
|
inviteCode, |
|
inviteExpiration: parseInt(inviteExpiration) || + new Date(new Date + (3 * 86400000)), |
|
groupJid: jid, |
|
groupName: (groupName ? groupName : await conn.getName(jid)) || null, |
|
jpegThumbnail: Buffer.isBuffer(jpegThumbnail) ? jpegThumbnail : null, |
|
caption |
|
}) |
|
}) |
|
const message = generateWAMessageFromContent(participant, msg, options) |
|
await conn.relayMessage(participant, message.message, { messageId: message.key.id, additionalAttributes: { ...options } }) |
|
return message |
|
}, |
|
enumerable: true |
|
}, |
|
|
|
prepareMessageMedia: { |
|
|
|
|
|
|
|
|
|
|
|
async value (message, options) { |
|
const logger = options.logger; |
|
let mediaType; |
|
for (const key of Defaults_1.MEDIA_KEYS) { |
|
if (key in message) { |
|
mediaType = key; |
|
} |
|
} |
|
const uploadData = { |
|
...message, |
|
media: message[mediaType] |
|
}; |
|
delete uploadData[mediaType]; |
|
|
|
const cacheableKey = typeof uploadData.media === 'object' && |
|
('url' in uploadData.media) && |
|
!!uploadData.media.url && |
|
!!options.mediaCache && ( |
|
|
|
mediaType + ':' + uploadData.media.url.toString()); |
|
if (mediaType === 'document' && !uploadData.fileName) { |
|
uploadData.fileName = 'file'; |
|
} |
|
if (!uploadData.mimetype) { |
|
uploadData.mimetype = MIMETYPE_MAP[mediaType]; |
|
} |
|
|
|
if (cacheableKey) { |
|
const mediaBuff = options.mediaCache.get(cacheableKey); |
|
if (mediaBuff) { |
|
logger === null || logger === void 0 ? void 0 : logger.debug({ cacheableKey }, 'got media cache hit'); |
|
const obj = Types_1.WAProto.Message.decode(mediaBuff); |
|
const key = `${mediaType}Message`; |
|
delete uploadData.media; |
|
Object.assign(obj[key], { ...uploadData }); |
|
return obj; |
|
} |
|
} |
|
const requiresDurationComputation = mediaType === 'audio' && typeof uploadData.seconds === 'undefined'; |
|
const requiresThumbnailComputation = (mediaType === 'image' || mediaType === 'video') && |
|
(typeof uploadData['jpegThumbnail'] === 'undefined'); |
|
const requiresOriginalForSomeProcessing = requiresDurationComputation || requiresThumbnailComputation; |
|
const { mediaKey, encWriteStream, bodyPath, fileEncSha256, fileSha256, fileLength, didSaveToTmpPath } = await messages_media_1.encryptedStream(uploadData.media, mediaType, requiresOriginalForSomeProcessing); |
|
|
|
const fileEncSha256B64 = encodeURIComponent(fileEncSha256.toString('base64') |
|
.replace(/\+/g, '-') |
|
.replace(/\//g, '_') |
|
.replace(/\=+$/, '')); |
|
const [{ mediaUrl, directPath }] = await Promise.all([ |
|
(async () => { |
|
const result = await options.upload(encWriteStream, { fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs }); |
|
logger === null || logger === void 0 ? void 0 : logger.debug('uploaded media'); |
|
return result; |
|
})(), |
|
(async () => { |
|
try { |
|
if (requiresThumbnailComputation) { |
|
uploadData.jpegThumbnail = await messages_media_1.generateThumbnail(bodyPath, mediaType, options); |
|
logger === null || logger === void 0 ? void 0 : logger.debug('generated thumbnail'); |
|
} |
|
if (requiresDurationComputation) { |
|
uploadData.seconds = await messages_media_1.getAudioDuration(bodyPath); |
|
logger === null || logger === void 0 ? void 0 : logger.debug('computed audio duration'); |
|
} |
|
} |
|
catch (error) { |
|
logger === null || logger === void 0 ? void 0 : logger.warn({ trace: error.stack }, 'failed to obtain extra info'); |
|
} |
|
})(), |
|
]) |
|
.finally(async () => { |
|
encWriteStream.destroy(); |
|
|
|
if (didSaveToTmpPath && bodyPath) { |
|
await fs_1.promises.unlink(bodyPath); |
|
logger === null || logger === void 0 ? void 0 : logger.debug('removed tmp files'); |
|
} |
|
}); |
|
delete uploadData.media; |
|
const obj = Types_1.WAProto.Message.fromObject({ |
|
[`${mediaType}Message`]: MessageTypeProto[mediaType].fromObject({ |
|
url, |
|
directPath, |
|
mediaKey, |
|
fileEncSha256, |
|
fileSha256, |
|
fileLength: '999999999', |
|
mediaKeyTimestamp: generics_1.unixTimestampSeconds(), |
|
...uploadData |
|
}) |
|
}); |
|
if (cacheableKey) { |
|
logger.debug({ cacheableKey }, 'set cache'); |
|
options.mediaCache.set(cacheableKey, Types_1.WAProto.Message.encode(obj).finish()); |
|
} |
|
return obj; |
|
} |
|
}, |
|
|
|
processMessageStubType: { |
|
|
|
|
|
|
|
|
|
async value(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) => { |
|
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 |
|
} |
|
}, |
|
insertAllGroup: { |
|
async value() { |
|
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 |
|
}, |
|
}, |
|
pushMessage: { |
|
|
|
|
|
|
|
|
|
async value(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) |
|
} |
|
} |
|
} |
|
}, |
|
serializeM: { |
|
|
|
|
|
|
|
|
|
value(m) { |
|
return smsg(conn, m) |
|
} |
|
}, |
|
updateProfilePicture: { |
|
async value(jid, content) { |
|
const { img } = await generateProfilePicture(content) |
|
return conn.query({ |
|
tag: 'iq', |
|
attrs: { to: jidNormalizedUser(jid), type: 'set', xmlns: 'w:profile:picture' }, |
|
content: [ { tag: 'picture', attrs: { type: 'image' }, content: img }] |
|
}) |
|
}, |
|
enumerable: true |
|
}, |
|
...(typeof conn.chatRead !== 'function' ? { |
|
chatRead: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
value(jid, participant = conn.user.jid, messageID) { |
|
return conn.sendReadReceipt(jid, participant, [messageID]) |
|
}, |
|
enumerable: true |
|
} |
|
} : {}), |
|
...(typeof conn.setStatus !== 'function' ? { |
|
setStatus: { |
|
|
|
|
|
|
|
|
|
value(status) { |
|
return conn.query({ |
|
tag: 'iq', |
|
attrs: { |
|
to: '@s.whatsapp.net', |
|
type: 'set', |
|
xmlns: 'status', |
|
}, |
|
content: [ |
|
{ |
|
tag: 'status', |
|
attrs: {}, |
|
content: Buffer.from(status, 'utf-8') |
|
} |
|
] |
|
}) |
|
}, |
|
enumerable: true |
|
} |
|
} : {}) |
|
}) |
|
if (sock.user?.id) sock.user.jid = sock.decodeJid(sock.user.id) |
|
store.bind(sock) |
|
return sock |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
export function smsg(conn, m, hasParent) { |
|
if (!m) return m |
|
|
|
|
|
|
|
let M = proto.WebMessageInfo |
|
m = M.fromObject(m) |
|
m.conn = conn |
|
let protocolMessageKey |
|
if (m.message) { |
|
if (m.mtype == 'protocolMessage' && m.msg.key) { |
|
protocolMessageKey = m.msg.key |
|
if (protocolMessageKey == 'status@broadcast') protocolMessageKey.remoteJid = m.chat |
|
if (!protocolMessageKey.participant || protocolMessageKey.participant == 'status_me') protocolMessageKey.participant = m.sender |
|
protocolMessageKey.fromMe = conn.decodeJid(protocolMessageKey.participant) === conn.decodeJid(conn.user.id) |
|
if (!protocolMessageKey.fromMe && protocolMessageKey.remoteJid === conn.decodeJid(conn.user.id)) protocolMessageKey.remoteJid = m.sender |
|
} |
|
if (m.quoted) if (!m.quoted.mediaMessage) delete m.quoted.download |
|
} |
|
if (!m.mediaMessage) delete m.download |
|
|
|
try { |
|
if (protocolMessageKey && m.mtype == 'protocolMessage') conn.ev.emit('message.delete', protocolMessageKey) |
|
} catch (e) { |
|
console.error(e) |
|
} |
|
return m |
|
} |
|
|
|
|
|
export function serialize() { |
|
const MediaType = ['imageMessage', 'videoMessage', 'audioMessage', 'stickerMessage', 'documentMessage'] |
|
return Object.defineProperties(proto.WebMessageInfo.prototype, { |
|
conn: { |
|
value: undefined, |
|
enumerable: false, |
|
writable: true |
|
}, |
|
id: { |
|
get() { |
|
return this.key?.id |
|
} |
|
}, |
|
isBaileys: { |
|
get() { |
|
return this.id?.length === 16 || this.id?.startsWith('3EB0') && this.id?.length === 12 || false |
|
} |
|
}, |
|
chat: { |
|
get() { |
|
const senderKeyDistributionMessage = this.message?.senderKeyDistributionMessage?.groupId |
|
return ( |
|
this.key?.remoteJid || |
|
(senderKeyDistributionMessage && |
|
senderKeyDistributionMessage !== 'status@broadcast' |
|
) || '' |
|
).decodeJid() |
|
} |
|
}, |
|
isGroup: { |
|
get() { |
|
return this.chat.endsWith('@g.us') |
|
}, |
|
enumerable: true |
|
}, |
|
sender: { |
|
get() { |
|
return this.conn?.decodeJid(this.key?.fromMe && this.conn?.user.id || this.participant || this.key.participant || this.chat || '') |
|
}, |
|
enumerable: true |
|
}, |
|
fromMe: { |
|
get() { |
|
return this.key?.fromMe || areJidsSameUser(this.conn?.user.id, this.sender) || false |
|
} |
|
}, |
|
mtype: { |
|
get() { |
|
if (!this.message) return '' |
|
const type = Object.keys(this.message) |
|
return (!['senderKeyDistributionMessage', 'messageContextInfo'].includes(type[0]) && type[0]) || |
|
(type.length >= 3 && type[1] !== 'messageContextInfo' && type[1]) || |
|
type[type.length - 1] |
|
}, |
|
enumerable: true |
|
}, |
|
msg: { |
|
get() { |
|
if (!this.message) return null |
|
return this.message[this.mtype] |
|
} |
|
}, |
|
mediaMessage: { |
|
get() { |
|
if (!this.message) return null |
|
const Message = ((this.msg?.url || this.msg?.directPath) ? { ...this.message } : extractMessageContent(this.message)) || null |
|
if (!Message) return null |
|
const mtype = Object.keys(Message)[0] |
|
return MediaType.includes(mtype) ? Message : null |
|
}, |
|
enumerable: true |
|
}, |
|
mediaType: { |
|
get() { |
|
let message |
|
if (!(message = this.mediaMessage)) return null |
|
return Object.keys(message)[0] |
|
}, |
|
enumerable: true, |
|
}, |
|
quoted: { |
|
get() { |
|
|
|
|
|
|
|
const self = this |
|
const msg = self.msg |
|
const contextInfo = msg?.contextInfo |
|
const quoted = contextInfo?.quotedMessage |
|
if (!msg || !contextInfo || !quoted) return null |
|
const type = Object.keys(quoted)[0] |
|
let q = quoted[type] |
|
const text = typeof q === 'string' ? q : q.text |
|
return Object.defineProperties(JSON.parse(JSON.stringify(typeof q === 'string' ? { text: q } : q)), { |
|
mtype: { |
|
get() { |
|
return type |
|
}, |
|
enumerable: true |
|
}, |
|
mediaMessage: { |
|
get() { |
|
const Message = ((q.url || q.directPath) ? { ...quoted } : extractMessageContent(quoted)) || null |
|
if (!Message) return null |
|
const mtype = Object.keys(Message)[0] |
|
return MediaType.includes(mtype) ? Message : null |
|
}, |
|
enumerable: true |
|
}, |
|
mediaType: { |
|
get() { |
|
let message |
|
if (!(message = this.mediaMessage)) return null |
|
return Object.keys(message)[0] |
|
}, |
|
enumerable: true, |
|
}, |
|
id: { |
|
get() { |
|
return contextInfo.stanzaId |
|
}, |
|
enumerable: true |
|
}, |
|
chat: { |
|
get() { |
|
return contextInfo.remoteJid || self.chat |
|
}, |
|
enumerable: true |
|
}, |
|
isBaileys: { |
|
get() { |
|
return this.id?.length === 16 || this.id?.startsWith('3EB0') && this.id.length === 12 || false |
|
}, |
|
enumerable: true |
|
}, |
|
sender: { |
|
get() { |
|
return (contextInfo.participant || this.chat || '').decodeJid() |
|
}, |
|
enumerable: true |
|
}, |
|
fromMe: { |
|
get() { |
|
return areJidsSameUser(this.sender, self.conn?.user.jid) |
|
}, |
|
enumerable: true, |
|
}, |
|
text: { |
|
get() { |
|
return text || this.caption || this.contentText || this.selectedDisplayText || '' |
|
}, |
|
enumerable: true |
|
}, |
|
mentionedJid: { |
|
get() { |
|
return q.contextInfo?.mentionedJid || self.getQuotedObj()?.mentionedJid || [] |
|
}, |
|
enumerable: true |
|
}, |
|
name: { |
|
get() { |
|
const sender = this.sender |
|
return sender ? self.conn?.getName(sender) : null |
|
}, |
|
enumerable: true |
|
|
|
}, |
|
vM: { |
|
get() { |
|
return proto.WebMessageInfo.fromObject({ |
|
key: { |
|
fromMe: this.fromMe, |
|
remoteJid: this.chat, |
|
id: this.id |
|
}, |
|
message: quoted, |
|
...(self.isGroup ? { participant: this.sender } : {}) |
|
}) |
|
} |
|
}, |
|
fakeObj: { |
|
get() { |
|
return this.vM |
|
} |
|
}, |
|
download: { |
|
value(saveToFile = false) { |
|
const mtype = this.mediaType |
|
return self.conn?.downloadM(this.mediaMessage[mtype], mtype.replace(/message/i, ''), saveToFile) |
|
}, |
|
enumerable: true, |
|
configurable: true, |
|
}, |
|
replyV2: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
value(text, chatId, options) { |
|
return self.conn?.replyV2(chatId ? chatId : this.chat, text, this.vM, options) |
|
}, |
|
enumerable: true, |
|
}, |
|
reply: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
value(text, chatId, options) { |
|
return self.conn?.reply(chatId ? chatId : this.chat, text, this.vM, options) |
|
}, |
|
enumerable: true, |
|
}, |
|
copy: { |
|
|
|
|
|
|
|
value() { |
|
const M = proto.WebMessageInfo |
|
return smsg(conn, M.fromObject(M.toObject(this.vM))) |
|
}, |
|
enumerable: true, |
|
}, |
|
forward: { |
|
|
|
|
|
|
|
|
|
|
|
value(jid, force = false, options) { |
|
return self.conn?.sendMessage(jid, { |
|
forward: this.vM, force, ...options |
|
}, { ...options }) |
|
}, |
|
enumerable: true, |
|
}, |
|
copyNForward: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
value(jid, forceForward = false, options) { |
|
return self.conn?.copyNForward(jid, this.vM, forceForward, options) |
|
}, |
|
enumerable: true, |
|
|
|
}, |
|
cMod: { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value(jid, text = '', sender = this.sender, options = {}) { |
|
return self.conn?.cMod(jid, this.vM, text, sender, options) |
|
}, |
|
enumerable: true, |
|
|
|
}, |
|
delete: { |
|
|
|
|
|
|
|
value() { |
|
return self.conn?.sendMessage(this.chat, { delete: this.vM.key }) |
|
}, |
|
enumerable: true, |
|
|
|
} |
|
}) |
|
}, |
|
enumerable: true |
|
}, |
|
_text: { |
|
value: null, |
|
writable: true, |
|
}, |
|
text: { |
|
get() { |
|
const msg = this.msg |
|
const text = (typeof msg === 'string' ? msg : msg?.text) || msg?.caption || msg?.contentText || '' |
|
return typeof this._text === 'string' ? this._text : '' || (typeof text === 'string' ? text : ( |
|
text?.selectedDisplayText || |
|
text?.hydratedTemplate?.hydratedContentText || |
|
text |
|
)) || '' |
|
}, |
|
set(str) { |
|
return this._text = str |
|
}, |
|
enumerable: true |
|
}, |
|
mentionedJid: { |
|
get() { |
|
return this.msg?.contextInfo?.mentionedJid?.length && this.msg.contextInfo.mentionedJid || [] |
|
}, |
|
enumerable: true |
|
}, |
|
name: { |
|
get() { |
|
return !nullish(this.pushName) && this.pushName || this.conn?.getName(this.sender) |
|
}, |
|
enumerable: true |
|
}, |
|
download: { |
|
value(saveToFile = false) { |
|
const mtype = this.mediaType |
|
return this.conn?.downloadM(this.mediaMessage[mtype], mtype.replace(/message/i, ''), saveToFile) |
|
}, |
|
enumerable: true, |
|
configurable: true |
|
}, |
|
replyV2: { |
|
value(text, chatId, options) { |
|
return this.conn?.replyV2(chatId ? chatId : this.chat, text, this, options) |
|
} |
|
}, |
|
reply: { |
|
value(text, chatId, options) { |
|
return this.conn?.reply(chatId ? chatId : this.chat, text, this, options) |
|
} |
|
}, |
|
copy: { |
|
value() { |
|
const M = proto.WebMessageInfo |
|
return smsg(this.conn, M.fromObject(M.toObject(this))) |
|
}, |
|
enumerable: true |
|
}, |
|
forward: { |
|
value(jid, force = false, options = {}) { |
|
return this.conn?.sendMessage(jid, { |
|
forward: this, force, ...options |
|
}, { ...options }) |
|
}, |
|
enumerable: true |
|
}, |
|
copyNForward: { |
|
value(jid, forceForward = false, options = {}) { |
|
return this.conn?.copyNForward(jid, this, forceForward, options) |
|
}, |
|
enumerable: true |
|
}, |
|
cMod: { |
|
value(jid, text = '', sender = this.sender, options = {}) { |
|
return this.conn?.cMod(jid, this, text, sender, options) |
|
}, |
|
enumerable: true |
|
}, |
|
getQuotedObj: { |
|
value() { |
|
if (!this.quoted.id) return null |
|
const q = proto.WebMessageInfo.fromObject(this.conn?.loadMessage(this.quoted.id) || this.quoted.vM) |
|
return smsg(this.conn, q) |
|
}, |
|
enumerable: true |
|
}, |
|
getQuotedMessage: { |
|
get() { |
|
return this.getQuotedObj |
|
} |
|
}, |
|
delete: { |
|
value() { |
|
return this.conn?.sendMessage(this.chat, { delete: this.key }) |
|
}, |
|
enumerable: true |
|
} |
|
}) |
|
} |
|
|
|
export function 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 |
|
} |
|
|
|
export function 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 nullish(args) { |
|
return !(args !== null && args !== undefined) |
|
} |
|
|
|
async function generateProfilePicture(mediaUpload) { |
|
let bufferOrFilePath |
|
if (Buffer.isBuffer(mediaUpload)) bufferOrFilePath = mediaUpload |
|
else if ('url' in mediaUpload) bufferOrFilePath = mediaUpload.url.toString() |
|
else bufferOrFilePath = await Baileys.toBuffer(mediaUpload.stream) |
|
const { read, MIME_JPEG, AUTO } = await Promise.resolve().then(async () => (await import('jimp')).default) |
|
const jimp = await read(bufferOrFilePath) |
|
const min = jimp.getWidth() |
|
const max = jimp.getHeight() |
|
const cropped = jimp.crop(0, 0, min, max) |
|
return { |
|
img: await cropped.quality(100).scaleToFit(720, 720, AUTO).getBufferAsync(MIME_JPEG) |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|