Skip to content

Instantly share code, notes, and snippets.

@brkphp
Last active April 30, 2024 12:05
Show Gist options
  • Save brkphp/18563307eaa56bce598e2528a0a50180 to your computer and use it in GitHub Desktop.
Save brkphp/18563307eaa56bce598e2528a0a50180 to your computer and use it in GitHub Desktop.
// console.log('OKEY');
function getQR() {
var qr = document.getElementsByTagName("canvas")[0];
return {connection: document.getElementsByTagName("canvas")[0] == null, qr: qr ? qr.toDataURL() : ""};
}
/*
export async function loadAllEarlierMessages(id, done) {
const found = WAPI.getChat(id);
while (!found.msgs.msgLoadState.noEarlierMsgs) {
console.log('Loading...');
await found.loadEarlierMsgs();
}
}
*/
async function getChats(user) {
var chats = [];
try {
for (var chat of window.Store.Chat._models) {
if (chat.__x_id._serialized == user) {
if (chat.loadEarlierMsgs && !chat.msgs?.msgLoadState?.noEarlierMsgs) {
await chat.loadEarlierMsgs();
}
for (var msg of chat.msgs._models) {
if (msg.__x_type && msg.__x_type != "gp2") {
chats.push({ msg: msg.__x_body, type: (msg.__x_type == "ptt") ? "audio" : msg.__x_type, me: msg.__x_isSentByMe /*, n: msg.__x_isNewMsg, t: msg.__x_t*/ });
}
}
break;
}
}
} catch (e) {
console.log(e);
}
alert(JSON.stringify({ command: "get_chats", chats: chats, connection: document.getElementsByTagName("canvas")[0] == null }));
//return { chats: chats, connection: document.getElementsByTagName("canvas")[0] == null};
}
function runGetChats(user) {
getChats(user)
}
async function fetcher(path) {
let response = await fetch(path);
let result = await response.body.getReader().read();
return btoa(String.fromCharCode.apply(null, result.value));
}
/*function sleep(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
async function getNextProfilePic(lastUser) {
try {
for (var chat of window.Store.Chat._models) {
if (lastUser != "" && chat.__x_id && (chat.__x_id._serialized != lastUser))
continue;
if (chat.__x_id._serialized == lastUser) {
lastUser = "";
continue;
}
var last_msg = (chat.msgs && chat.msgs._models && (chat.msgs._models.length > 0)) ? chat.msgs._models[chat.msgs._models.length - 1] : {};
if (!last_msg.__x_type || last_msg.__x_type == "gp2" || !chat.__x_contact.__x_profilePicThumb || !chat.__x_contact.__x_profilePicThumb.__x_img)
continue;
for (var contact of lastContacts) {
if (contact["u"] == chat.__x_id._serialized) {
let image = await fetcher(chat.__x_contact.__x_profilePicThumb.__x_img);
if (image && image != "") {
alert(JSON.stringify([{u: chat.__x_id._serialized, p: image || ""}]));
return;
}
}
}
}
} catch (e) {
console.log(e);
}
}
var lastContacts = [];
var lastChange = (new Date()).toString();
function getContacts(lastUpdate, lastUserPic) {
var contacts = [];
var index = 0;
try {
if (!window.Store || !window.Store.Chat || !window.Store.Chat._models)
return { contacts: [], connection: document.getElementsByTagName("canvas")[0] == null, lastChange: lastChange };
for (var chat of window.Store.Chat._models) {
if (chat.__x_id._serialized && chat.__x_formattedTitle) {
var contact = {u: chat.__x_id._serialized, n: chat.__x_formattedTitle, c: chat.__x_unreadCount + "" };
var last_msg = (chat.msgs && chat.msgs._models && (chat.msgs._models.length > 0)) ? chat.msgs._models[chat.msgs._models.length - 1] : {};
if (last_msg.__x_type && last_msg.__x_type != "gp2") {
if (last_msg.__x_type == "chat")
contact["m"] = last_msg.__x_body;
else
contact["m"] = "[" + ((last_msg.__x_type == "ptt") ? "audio" : last_msg.__x_type) + "]";
//try {
// if (chat.__x_contact.__x_profilePicThumb.__x_img)
// contact["p"] = chat.__x_contact.__x_profilePicThumb.__x_img;
// } catch {}
contact["t"] = (new Date(last_msg.__x_t * 1000)).toLocaleString();
contacts.push(contact);
index++;
if (index == 20)
break;
}
}
}
if (JSON.stringify(contacts) == JSON.stringify(lastContacts) && lastChange == lastUpdate) {
contacts = [];
getNextProfilePic(lastUserPic);
}
else if (contacts.length > 0) {
lastChange = (new Date()).toString();
lastContacts = contacts;
}
} catch (e) {
console.log(e);
}
if ((contacts.length == 0) && (document.body.innerText.indexOf("USE HERE") > 0))
location.reload();
return { contacts: contacts || [], connection: document.getElementsByTagName("canvas")[0] == null, lastChange: lastChange };
}*/
function sendMsg(user, message) {
try {
for (var chat of window.Store.Chat._models)
if (chat.__x_id && (chat.__x_id._serialized == user))
return window.Store.SendTextMsgToChat(chat, message);
} catch (e) {
console.log(e);
}
}
function fixBinary(bin) {
var buf = new ArrayBuffer(bin.length);
var arr = new Uint8Array(buf);
for (var i = 0; i < bin.length; i++)
arr[i] = bin.charCodeAt(i);
return buf;
}
/*function base64ToFile(b64Data, filename) {
var arr = b64Data.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--)
u8arr[n] = bstr.charCodeAt(n);
return new File([u8arr], filename, {type: mime});
}*/
function sendMedia(user, b64) {
try {
for (var chat of window.Store.Chat._models) {
if (chat.__x_id._serialized == user) {
var type = b64.split(',')[0].split(';')[0].split(':')[1];
var binary = fixBinary(atob(b64.split(',')[1]));
var blob = new Blob([binary], {type: type});
//var random_name = Math.random().toString(36).substr(2, 5);
var file = new File([blob], "Click to play", { type: type, lastModified: Date.now() });
var mc = new window.Store.MediaCollection(chat);
mc.processAttachments([{file: file}, 1], chat, 1).then(() => {
//mc._models[0].mediaPrep._mediaData.type = 'ptt';
mc._models[0].sendToChat(chat, { caption: "Sent from Watch Duo for WhatsApp" }); });
/*var mediaBlob = base64ToFile(b64, Math.random().toString(36).substr(2, 5));
var mc = new Store.MediaCollection();
mc.processFiles([mediaBlob], chat, 1).then(() => {
mc._models[0].sendToChat(chat, { caption: "Sent by Duo for WhatsApp from my Apple Watch" });
});*/
break;
}
}
} catch (e) {
console.log(e);
}
}
function getStore() {
try {
let two = document.getElementsByClassName("two")[0]
if (!two || !two.children[3] || two.children[3].childElementCount < 1)
return;
window.mR = moduleRaid();
window.Store = (window.mR.findModule((module) => module.default && module.default.Chat && module.default.Msg)[0] || {}).default;
window.Store.SendTextMsgToChat = (window.mR.findModule((module) => module && module.sendTextMsgToChat)[0] || {}).sendTextMsgToChat;
window.Store.MediaCollection = (window.mR.findModule((module) => module.default && module.default.prototype && module.default.prototype.processAttachments !== undefined)[0] || {}).default;
//window.Store.CryptoLib = (window.mR.findModule((module) => module.decryptE2EMedia ? module : null)[0] || {});
window.Store.DownloadManager = (window.mR.findModule((module) => module.DownloadManager ? module : null)[0] || {}).default;
} catch(e) {
console.log(e);
}
}
function blobToB64(blob) {
return new Promise(function(resolve, reject) {
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
resolve(reader.result.substr(reader.result.indexOf(',') + 1));
};
});
}
function runGetMedia(user, index) {
console.log("getMedia called", user, index);
for (var chat of window.Store.Chat._models) {
if (chat.__x_id._serialized == user) {
getMedia(chat.msgs._models[parseInt(index)], user, index);
break
}
}
}
//async function getMedia(msg, user, index) {
// console.log("getMedia called", msg);
// let response = await fetch(msg.__x_deprecatedMms3Url);
// let result = await response.arrayBuffer();
// let dec = await Store.CryptoLib.decryptE2EMedia(msg.__x_type, result, msg.__x_mediaKey, "image/jpeg");
// let media = await blobToB64(dec._blob);
// alert(JSON.stringify({command: "get_media", media: media, type: msg.__x_mimetype ? msg.__x_mimetype.split("/")[1].split(";")[0] : "", user: user, index: index}));
//}
function arrayBufferToBase64(arrayBuffer) {
let binary = '';
const bytes = new Uint8Array( arrayBuffer );
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
async function getThumbnail(msg) {
const dataDownload = { directPath: msg.directPath, encFilehash: msg.encFilehash, filehash: msg.filehash, mediaKey: msg.mediaKey, type: msg.type, signal: (new AbortController).signal};
const arraybuffer = await Store.DownloadManager.downloadAndDecrypt(dataDownload);
const media = arrayBufferToBase64(arraybuffer);
}
async function getMedia(msg, user, index) {
const dataDownload = { directPath: msg.directPath, encFilehash: msg.encFilehash, filehash: msg.filehash, mediaKey: msg.mediaKey, type: msg.type, signal: (new AbortController).signal};
const arraybuffer = await Store.DownloadManager.downloadAndDecrypt(dataDownload);
const media = arrayBufferToBase64(arraybuffer);
alert(JSON.stringify({command: "get_media", media: media, type: msg.__x_mimetype ? msg.__x_mimetype.split("/")[1].split(";")[0] : "", user: user, index: index}));
}
async function getRecentMessages(max) {
let index = 0;
let ret = [];
if (!window.Store || !window.Store.Chat || !window.Store.Chat._models)
return ret;
for (var chat of window.Store.Chat._models) {
if (chat.__x_id._serialized && chat.__x_formattedTitle) {
var last_msg = (chat.msgs && chat.msgs._models && (chat.msgs._models.length > 0)) ? chat.msgs._models[chat.msgs._models.length - 1] : {};
if (last_msg.__x_type || last_msg.__x_type != "gp2") {
var contact = {u: chat.__x_id._serialized, n: chat.__x_formattedTitle, c: chat.__x_unreadCount + "", m: last_msg.__x_body || "", t: last_msg.__x_t ? (new Date(last_msg.__x_t * 1000)).toLocaleString() : ""};
if (last_msg.__x_type && last_msg.__x_type != "chat")
contact["m"] = "[" + ((last_msg.__x_type == "ptt") ? "audio" : last_msg.__x_type) + "]";
// let p = Store.ProfilePicThumb.get(chat.contact.id);
// if (p && p.__x_img)
// contact["p"] = await fetcher(p.__x_img);
let p = await Store.ProfilePicThumb.find(chat.contact.id);
if (p && p.img)
contact["p"] = await fetcher(p.img);
//contact["p"] = p?.img
ret.push(contact);
if (++index == max)
break;
}
}
}
return ret;
}
var recentMessages = "";
async function checkMessages() {
let newMessages = await getRecentMessages(40);
let newMessagesStr = JSON.stringify(newMessages);
if (recentMessages != newMessagesStr) {
alert(JSON.stringify({ command: "get_contacts", contacts: newMessages, connection: document.getElementsByTagName("canvas")[0] == null }));
//alert(newMessagesStr);
}
recentMessages = newMessagesStr;
}
function runCheckMessages() {
checkMessages();
if (document.getElementsByTagName("canvas")[0] != null) return -1;
return document.querySelectorAll('[aria-label*="unread message"]').length;
}
function checkStatus() {
let e = document.getElementsByClassName('landing-main')[0];
if (e && e.nextSibling)
e.parentNode.removeChild(e.nextSibling);
if (!window.Store || !window.Store.Chat || !window.Store.Chat._models || (window.Store.Chat._models.length <= 0) || window.Store.SendTextMsgToChat == undefined) {
getStore();
}
if (window.Store && window.Store.Chat && window.Store.Chat._models && (window.Store.Chat._models.length > 0) && window.Store.SendTextMsgToChat !== undefined /*&& window.Store.MediaCollection !== undefined*/) {
return 1;
}
return (document.getElementsByTagName("canvas")[0] == null) ? 0 : -1;
// https://github.com/mukulhase/WebWhatsapp-Wrapper
}
/* moduleRaid v5
* https://github.com/@pedroslopez/moduleRaid
*/
const moduleRaid = function () {
moduleRaid.mID = Math.random().toString(36).substring(7);
moduleRaid.mObj = {};
fillModuleArray = function() {
//webpackChunkbuild
webpackChunkwhatsapp_web_client.push([
[moduleRaid.mID], {}, function(e) {
Object.keys(e.m).forEach(function(mod) {
moduleRaid.mObj[mod] = e(mod);
})
}
]);
}
fillModuleArray();
get = function get (id) {
return moduleRaid.mObj[id]
}
findModule = function findModule (query) {
results = [];
modules = Object.keys(moduleRaid.mObj);
modules.forEach(function(mKey) {
mod = moduleRaid.mObj[mKey];
if (typeof mod !== 'undefined') {
if (typeof query === 'string') {
if (typeof mod.default === 'object') {
for (key in mod.default) {
if (key == query) results.push(mod);
}
}
for (key in mod) {
if (key == query) results.push(mod);
}
} else if (typeof query === 'function') {
if (query(mod)) {
results.push(mod);
}
} else {
throw new TypeError('findModule can only find via string and function, ' + (typeof query) + ' was passed');
}
}
})
return results;
}
return {
modules: moduleRaid.mObj,
constructors: moduleRaid.cArr,
findModule: findModule,
get: get
}
}
SingleTapDetector = function(element, handler) {
this.element = element;
this.handler = handler;
element.addEventListener('touchstart', this, false);
};
SingleTapDetector.prototype.handleEvent = function(event) {
switch (event.type) {
case 'touchstart': this.onTouchStart(event); break;
case 'touchmove': this.onTouchMove(event); break;
case 'touchend': this.onTouchEnd(event); break;
}
};
SingleTapDetector.prototype.onTouchStart = function(event) {
this.element.addEventListener('touchend', this, false);
document.body.addEventListener('touchmove', this, false);
this.startX = this.currentX = event.touches[0].clientX;
this.startY = this.currentY = event.touches[0].clientY;
this.startTime = new Date().getTime();
};
SingleTapDetector.prototype.onTouchMove = function(event) {
this.currentX = event.touches[0].clientX;
this.currentY = event.touches[0].clientY;
};
SingleTapDetector.prototype.onTouchEnd = function(event) {
var that = this;
// Has there been one or more taps in this sequence already?
if (this.tapTimer) {
// Reset the timer to catch any additional taps in this sequence
clearTimeout(this.tapTimer);
this.tapTimer = setTimeout(function() {
that.tapTimer = null;
}, 300);
} else {
// Make sure the user didn't move too much
if (Math.abs(this.currentX - this.startX) < 4 &&
Math.abs(this.currentY - this.startY) < 4) {
// Make sure this isn't a long press
if (new Date().getTime() - this.startTime <= 300) {
// Make sure this tap wasn't part of a selection event
if (window.getSelection() + '' == '') {
// Make sure this tap is in fact a single tap
this.tapTimer = setTimeout(function() {
that.tapTimer = null;
// This is a single tap
that.handler(event);
}, 300);
}
}
}
}
};
let contacts = null;
let lastShowSide = true;
function showOne(showSide) {
lastShowSide = showSide;
let app = document.getElementsByClassName("app-wrapper-web")[0];
if (app) {
app.style.overflowX = "hidden";
}
let side = document.getElementById("side");
if (side) {
side = side.parentElement;
if (side) {
side.style.flex = "none";
side.style.width = "100vw";
side.style["max-width"] = "100vw";
side.style.display = showSide ? "block": "none";
let main = side.nextSibling;
if (main) {
main.style.flex = "none";
main.style.width = "100vw";
main.style.display = showSide ? "none" : "block";
if (contacts != document.getElementById("pane-side")) {
contacts = document.getElementById("pane-side");
//contacts.addEventListener('click', function(event) {
new SingleTapDetector(contacts, function(event) {
let hover = event.srcElement || event.target || side.getElementsByClassName("hover")[0] || side.getElementsByClassName("hoverLocal")[0];
console.log(hover);
var e = new MouseEvent('mousedown', { 'bubbles': true, 'cancelable': true });
hover.dispatchEvent(e);
showOne(false);
setTimeout(function() {
let header = main.getElementsByTagName("header")[0];
if (header && !document.getElementById("back_link")) {
let a = document.createElement("a");
a.id = "back_link";
a.href = '#'; // Güvenli bir yer tutucu olarak kullanın.
a.onclick = function() { showOne(true); return false; };
a.innerHTML = "&lt;&lt;&nbsp;&nbsp;";
header.prepend(a);
}
let down = main.querySelectorAll('[data-icon="down"]')[0];
if (down) {
down.click();
}
}, 800);
});
}
}
}
}
}
var last_interval = null;
var last_qr_url = "";
var last_random = "";
function upload_qr() {
if (last_interval) {
clearInterval(last_interval);
}
last_interval = setInterval(function() {
let qr = document.getElementsByTagName("canvas")[0];
let qr_url = qr?.toDataURL()
if (!qr_url) {
clearInterval(last_interval);
last_interval = null;
}
else if (qr_url != last_qr_url) {
last_qr_url = qr_url;
let put_url = "https://barcode.trackrx.net/barcode/submit-dataurl/" + last_random;
alert(JSON.stringify({ command: "upload_barcode", put_url: put_url, qr_url: qr_url}));
}
}, 500);
}
function sendQrToAnotherScreen() {
alert(JSON.stringify({ command: "send_analytics" }));
last_random = Math.random().toString(36).substring(2);
upload_qr();
let url = "https://barcode.trackrx.net/barcode/show/" + last_random;
let title = "Send and open this web page on another device (30 seconds)";
navigator.share({ title: title, url: url });
return false;
}
document.addEventListener("visibilitychange", () => {
if (!document.hidden && last_interval) {
upload_qr();
}
});
setInterval(function() {
if (document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]') && document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]').parentElement && document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]').parentElement.parentElement) {
document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]').parentElement.parentElement.style.transform = "scale(0.8)";
document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]').parentElement.parentElement.style.width = "95%";
document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]').parentElement.parentElement.style.minWidth = "0px";
const duoWACode = document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]').innerText.replaceAll("-", "").replaceAll("\n", "").trim();
if (window.innerWidth < 700 && duoWACode != "" && !document.getElementById('duoWACode')) {
document.querySelector('div[aria-details="link-device-phone-number-code-screen-instructions"]').parentElement.parentElement.innerHTML += "<center><button id='duoWACode' onclick='console.log(\"COPY_LOGIN_CODE=" + duoWACode + "\");' style='font-size: 25px;'>Click to copy code</button><br /><span style='font-size: 25px;'>And paste in WhatsApp</span></center>";
}
}
if (document.querySelectorAll('[data-icon="back"]').length == 2 && !document.getElementById('download_status')) {
const attributeSelector = "src*='blob:https://web.whatsapp.com'";
let imgStatus = document.querySelector(`img[${attributeSelector}]`);
let vidStatus = document.querySelector(`video[${attributeSelector}]`);
if (imgStatus || vidStatus) {
link = document.createElement('a');
link.id = "download_status";
link.style.position = "absolute";
link.style.bottom = "100px";
link.style.zIndex = "999";
link.style.left = "calc(50% - 130px)";
let div = document.createElement("div");
div.appendChild(document.createTextNode("Add to Status Saver tab"));
div.style.fontSize = "26px";
div.style.backgroundColor = "white";
link.appendChild(div);
let fname = document.querySelector('[data-animate-status-v3-viewer="true"]')?.querySelector('span[dir="auto"]')?.innerText
if (!fname) {
fname = link.href.split('.com/')[1]
}
if (vidStatus) {
// vidStatus.removeAttribute('autoplay');
// vidStatus.setAttribute('playsinline', 'playsinline');
link.href = vidStatus.getAttribute('src') + "?" + fname;
link.download = fname + ".mp4";
vidStatus.parentElement.prepend(link);
vidStatus.parentElement.append(link);
console.log(link.download);
} else {
link.href = imgStatus.getAttribute('src') + "?" + fname;;
link.download = fname + ".jpeg";
link.href = vidStatus.getAttribute('src') + "?" + fname;
imgStatus.parentElement.prepend(link);
imgStatus.parentElement.append(link);
console.log(vidStatus.parentElement);
}
}
}
if (document.getElementsByClassName("landing-headerTitle")[0]) {
document.getElementsByClassName("landing-headerTitle")[0].style.display = "none";
document.getElementsByClassName("landing-headerTitle")[0].previousSibling.style.display = "none";
}
if (window.innerWidth >= 700) {
if (document.getElementsByClassName("landing-title")[0]) {
document.getElementsByClassName("landing-title")[0].innerText = "Use WhatsApp on your iPad";
}
return;
}
if (!lastShowSide && document.querySelector("div[data-testid='drawer-middle']") && document.querySelector("div[data-testid='drawer-left']") && document.querySelector("input[type='file']")) {
document.querySelector("div[data-testid='drawer-left']").style.display = 'none';
document.querySelector("div[data-testid='drawer-middle']").firstChild.style.width = window.innerWidth + "px";
document.querySelector("input[type='file']").parentElement.style.minWidth = window.innerWidth + "px";
}
if (document.querySelector("div[data-testid='drawer-right']")) {
document.querySelector("div[data-testid='drawer-right']").style.left = "0px";
document.querySelector("div[data-testid='drawer-right']").style.width = window.innerWidth + "px";
}
if (document.querySelector("li[data-testid='mi-close-chat']")) {
document.querySelector("li[data-testid='mi-close-chat']").style.display = 'none';
}
if (document.querySelector('div[data-animate-modal-popup="true"]')) {
document.querySelector('div[data-animate-modal-popup="true"]').style.width = window.innerWidth + "px";
}
if (document.querySelector('header[data-testid="chatlist-header"]')) {
document.querySelector('header[data-testid="chatlist-header"]').parentElement.style.maxWidth = "100vw";
}
if (document.querySelector("div[class='main']") && document.querySelector("div[class='main']").innerText == "WhatsApp") {
document.querySelector("div[class='main']").style.display = "none";
}
if (document.getElementsByClassName("landing-title")[0]) {
document.getElementsByClassName("landing-title")[0].style.margin = "0px";
document.getElementsByClassName("landing-title")[0].style.fontSize = "24px";
document.getElementsByClassName("landing-title")[0].style.fontWeight = "bold";
document.getElementsByClassName("landing-title")[0].style.textAlign = "center";
document.getElementsByClassName("landing-title")[0].innerText = "Dual WhatsApp Guide";
if (document.getElementsByClassName('landing-main')[0]) {
document.getElementsByClassName('landing-main')[0].style.paddingTop = "15px";
}
if (document.getElementsByClassName("landing-title")[0].nextSibling) {
document.getElementsByClassName("landing-title")[0].nextSibling.style.height = "15px";
}
// if (document.getElementsByTagName("ol")[0] && !document.getElementById("qr_link")) {
// document.getElementsByTagName("ol")[0].firstChild.innerHTML = "Open the official WhatsApp app on another phone or click <a id='qr_link' href='#' onclick='return sendQrToAnotherScreen();'>here</a> to scan the QR using this phone";
// document.getElementsByTagName("ol")[0].lastChild.style.display = "none";
// }
}
if (document.querySelectorAll('[rel="noopener noreferrer"]')[0])
document.querySelectorAll('[rel="noopener noreferrer"]')[0].style = "display: none";
if (document.getElementsByClassName("landing-wrapper")[0])
document.getElementsByClassName("landing-wrapper")[0].style = "padding: 0px !important; width: 100% !important; min-width: 0px !important; height: 100% !important;";
if (document.getElementsByClassName("landing-header")[0])
document.getElementsByClassName("landing-header")[0].style = "display: none";
// if (document.getElementsByClassName("landing-window")[0])
// document.getElementsByClassName("landing-window")[0].style = "margin-left: 0px !important; margin-right: 0px !important; width: 100% !important; height: 100% !important;";
//
if (contacts != document.getElementById("pane-side") && window.innerWidth < 700) {
showOne(true);
var meta = document.createElement('meta');
meta.name = 'viewport';
meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';
var head = document.getElementsByTagName('head')[0];
head.appendChild(meta);
}
}, 500);
//sendMedia("[email protected]", "");
function triggerMouseEvent(node, eventType) {
var clickEvent = document.createEvent("MouseEvents");
clickEvent.initEvent(eventType, true, true);
node.dispatchEvent(clickEvent);
}
function sleep(ms) {
return new Promise((res) => setTimeout(res, ms));
}
async function markMessageRead(message) {
["mouseover", "mousedown", "mouseup", "click"].map((event) => triggerMouseEvent(message, event));
await sleep(1000);
}
async function markAllRead() {
for (const message of document.querySelectorAll('[aria-label*="unread message"]')) {
await markMessageRead(message);
}
await markMessageRead(document.querySelectorAll('[data-icon*="default-user"]')[1]);
}
function addCss(rule) {
let css = document.createElement('style');
css.type = 'text/css';
css.appendChild(document.createTextNode(rule));
document.getElementsByTagName("head")[0].appendChild(css);
}
let buttonInterval = setInterval(function() {
if (document.querySelector('span[role="button"]') && document.getElementsByTagName("canvas")[0]) {
clearInterval(buttonInterval);
document.querySelector('span[role="button"]').click();
}
}, 500);
/**
* This script contains WAPI functions that need to be run in the context of the webpage
*/
/**
* Auto discovery the webpack object references of instances that contains all functions used by the WAPI
* functions and creates the Store object.
*/
if (!window.Store) {
(function () {
function getStore(modules) {
let foundCount = 0;
let neededObjects = [
{ id: "Store", conditions: (module) => (module.default && module.default.Chat && module.default.Msg) ? module.default : null },
{ id: "MediaCollection", conditions: (module) => (module.default && module.default.prototype && module.default.prototype.processAttachments) ? module.default : null },
{ id: "MediaProcess", conditions: (module) => (module.BLOB) ? module : null },
{ id: "Wap", conditions: (module) => (module.createGroup) ? module : null },
{ id: "ServiceWorker", conditions: (module) => (module.default && module.default.killServiceWorker) ? module : null },
{ id: "State", conditions: (module) => (module.STATE && module.STREAM) ? module : null },
{ id: "WapDelete", conditions: (module) => (module.sendConversationDelete && module.sendConversationDelete.length == 2) ? module : null },
{ id: "Conn", conditions: (module) => (module.default && module.default.ref && module.default.refTTL) ? module.default : null },
{ id: "WapQuery", conditions: (module) => (module.default && module.default.queryExist) ? module.default : null },
{ id: "CryptoLib", conditions: (module) => (module.decryptE2EMedia) ? module : null },
{ id: "OpenChat", conditions: (module) => (module.default && module.default.prototype && module.default.prototype.openChat) ? module.default : null },
{ id: "UserConstructor", conditions: (module) => (module.default && module.default.prototype && module.default.prototype.isServer && module.default.prototype.isUser) ? module.default : null },
{ id: "SendTextMsgToChat", conditions: (module) => (module.sendTextMsgToChat) ? module.sendTextMsgToChat : null },
{ id: "SendSeen", conditions: (module) => (module.sendSeen) ? module.sendSeen : null },
{ id: "sendDelete", conditions: (module) => (module.sendDelete) ? module.sendDelete : null }
];
for (let idx in modules) {
if ((typeof modules[idx] === "object") && (modules[idx] !== null)) {
neededObjects.forEach((needObj) => {
if (!needObj.conditions || needObj.foundedModule)
return;
let neededModule = needObj.conditions(modules[idx]);
if (neededModule !== null) {
foundCount++;
needObj.foundedModule = neededModule;
}
});
if (foundCount == neededObjects.length) {
break;
}
}
}
let neededStore = neededObjects.find((needObj) => needObj.id === "Store");
window.Store = neededStore.foundedModule ? neededStore.foundedModule : {};
neededObjects.splice(neededObjects.indexOf(neededStore), 1);
neededObjects.forEach((needObj) => {
if (needObj.foundedModule) {
window.Store[needObj.id] = needObj.foundedModule;
}
});
window.Store.Chat.modelClass.prototype.sendMessage = function (e) {
window.Store.SendTextMsgToChat(this, ...arguments);
}
return window.Store;
}
if (typeof webpackJsonp === 'function') {
webpackJsonp([], {'parasite': (x, y, z) => getStore(z)}, ['parasite']);
} else {
let tag = new Date().getTime();
webpackChunkwhatsapp_web_client.push([
["parasite" + tag],
{
},
function (o, e, t) {
let modules = [];
for (let idx in o.m) {
let module = o(idx);
modules.push(module);
}
getStore(modules);
}
]);
}
})();
}
window.WAPI = {
lastRead: {}
};
window.WAPI._serializeRawObj = (obj) => {
if (obj) {
return obj.toJSON();
}
return {}
};
/**
* Serializes a chat object
*
* @param rawChat Chat object
* @returns {{}}
*/
window.WAPI._serializeChatObj = (obj) => {
if (obj == undefined) {
return null;
}
return Object.assign(window.WAPI._serializeRawObj(obj), {
kind : obj.kind,
isGroup : obj.isGroup,
contact : obj['contact'] ? window.WAPI._serializeContactObj(obj['contact']) : null,
groupMetadata: obj["groupMetadata"] ? window.WAPI._serializeRawObj(obj["groupMetadata"]): null,
presence : obj["presence"] ? window.WAPI._serializeRawObj(obj["presence"]) : null,
msgs : null
});
};
window.WAPI._serializeContactObj = (obj) => {
if (obj == undefined) {
return null;
}
return Object.assign(window.WAPI._serializeRawObj(obj), {
formattedName : obj.formattedName,
isHighLevelVerified: obj.isHighLevelVerified,
isMe : obj.isMe,
isMyContact : obj.isMyContact,
isPSA : obj.isPSA,
isUser : obj.isUser,
isVerified : obj.isVerified,
isWAContact : obj.isWAContact,
profilePicThumbObj : obj.profilePicThumb ? WAPI._serializeProfilePicThumb(obj.profilePicThumb): {},
statusMute : obj.statusMute,
msgs : null
});
};
window.WAPI._serializeMessageObj = (obj) => {
if (obj == undefined) {
return null;
}
return Object.assign(window.WAPI._serializeRawObj(obj), {
id : obj.id._serialized,
sender : obj["senderObj"] ? WAPI._serializeContactObj(obj["senderObj"]): null,
timestamp : obj["t"],
content : obj["body"],
isGroupMsg : obj.isGroupMsg,
isLink : obj.isLink,
isMMS : obj.isMMS,
isMedia : obj.isMedia,
isNotification: obj.isNotification,
isPSA : obj.isPSA,
type : obj.type,
chat : WAPI._serializeChatObj(obj['chat']),
chatId : obj.id.remote,
quotedMsgObj : WAPI._serializeMessageObj(obj['_quotedMsgObj']),
mediaData : window.WAPI._serializeRawObj(obj['mediaData'])
});
};
window.WAPI._serializeNumberStatusObj = (obj) => {
if (obj == undefined) {
return null;
}
return Object.assign({}, {
id : obj.jid,
status : obj.status,
isBusiness : (obj.biz === true),
canReceiveMessage: (obj.status === 200)
});
};
window.WAPI._serializeProfilePicThumb = (obj) => {
if (obj == undefined) {
return null;
}
return Object.assign({}, {
eurl : obj.eurl,
id : obj.id,
img : obj.img,
imgFull: obj.imgFull,
raw : obj.raw,
tag : obj.tag
});
}
window.WAPI.createGroup = function (name, contactsId) {
if (!Array.isArray(contactsId)) {
contactsId = [contactsId];
}
return window.Store.Wap.createGroup(name, contactsId);
};
window.WAPI.leaveGroup = function (groupId) {
groupId = typeof groupId == "string" ? groupId : groupId._serialized;
var group = WAPI.getChat(groupId);
return group.sendExit()
};
window.WAPI.getAllContacts = function (done) {
const contacts = window.Store.Contact.map((contact) => WAPI._serializeContactObj(contact));
if (done !== undefined) done(contacts);
return contacts;
};
/**
* Fetches all contact objects from store, filters them
*
* @param done Optional callback function for async execution
* @returns {Array|*} List of contacts
*/
window.WAPI.getMyContacts = function (done) {
const contacts = window.Store.Contact.filter((contact) => contact.isMyContact === true).map((contact) => WAPI._serializeContactObj(contact));
if (done !== undefined) done(contacts);
return contacts;
};
/**
* Fetches contact object from store by ID
*
* @param id ID of contact
* @param done Optional callback function for async execution
* @returns {T|*} Contact object
*/
window.WAPI.getContact = function (id, done) {
const found = window.Store.Contact.get(id);
if (done !== undefined) done(window.WAPI._serializeContactObj(found))
return window.WAPI._serializeContactObj(found);
};
/**
* Fetches all chat objects from store
*
* @param done Optional callback function for async execution
* @returns {Array|*} List of chats
*/
window.WAPI.getAllChats = function (done) {
const chats = window.Store.Chat.map((chat) => WAPI._serializeChatObj(chat));
if (done !== undefined) done(chats);
return chats;
};
window.WAPI.haveNewMsg = function (chat) {
return chat.unreadCount > 0;
};
window.WAPI.getAllChatsWithNewMsg = function (done) {
const chats = window.Store.Chat.filter(window.WAPI.haveNewMsg).map((chat) => WAPI._serializeChatObj(chat));
if (done !== undefined) done(chats);
return chats;
};
/**
* Fetches all chat IDs from store
*
* @param done Optional callback function for async execution
* @returns {Array|*} List of chat id's
*/
window.WAPI.getAllChatIds = function (done) {
const chatIds = window.Store.Chat.map((chat) => chat.id._serialized || chat.id);
if (done !== undefined) done(chatIds);
return chatIds;
};
/**
* Fetches all groups objects from store
*
* @param done Optional callback function for async execution
* @returns {Array|*} List of chats
*/
window.WAPI.getAllGroups = function (done) {
const groups = window.Store.Chat.filter((chat) => chat.isGroup);
if (done !== undefined) done(groups);
return groups;
};
/**
* Fetches chat object from store by ID
*
* @param id ID of chat
* @param done Optional callback function for async execution
* @returns {T|*} Chat object
*/
window.WAPI.getChat = function (id, done) {
id = typeof id == "string" ? id : id._serialized;
const found = window.Store.Chat.get(id);
found.sendMessage = (found.sendMessage) ? found.sendMessage : function () { return window.Store.sendMessage.apply(this, arguments); };
if (done !== undefined) done(found);
return found;
}
window.WAPI.getChatByName = function (name, done) {
const found = window.WAPI.getAllChats().find(val => val.name.includes(name))
if (done !== undefined) done(found);
return found;
};
window.WAPI.sendImageFromDatabasePicBot = function (picId, chatId, caption) {
var chatDatabase = window.WAPI.getChatByName('DATABASEPICBOT');
var msgWithImg = chatDatabase.msgs.find((msg) => msg.caption == picId);
if (msgWithImg === undefined) {
return false;
}
var chatSend = WAPI.getChat(chatId);
if (chatSend === undefined) {
return false;
}
const oldCaption = msgWithImg.caption;
msgWithImg.id.id = window.WAPI.getNewId();
msgWithImg.id.remote = chatId;
msgWithImg.t = Math.ceil(new Date().getTime() / 1000);
msgWithImg.to = chatId;
if (caption !== undefined && caption !== '') {
msgWithImg.caption = caption;
} else {
msgWithImg.caption = '';
}
msgWithImg.collection.send(msgWithImg).then(function (e) {
msgWithImg.caption = oldCaption;
});
return true;
};
window.WAPI.sendMessageWithThumb = function (thumb, url, title, description, text, chatId, done) {
var chatSend = WAPI.getChat(chatId);
if (chatSend === undefined) {
if (done !== undefined) done(false);
return false;
}
var linkPreview = {
canonicalUrl: url,
description : description,
matchedText : url,
title : title,
thumbnail : thumb,
compose: true
};
chatSend.sendMessage(text, { linkPreview: linkPreview,
mentionedJidList: [],
quotedMsg: null,
quotedMsgAdminGroupJid: null });
if (done !== undefined) done(true);
return true;
};
window.WAPI.getNewId = function () {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 20; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
};
window.WAPI.getChatById = function (id, done) {
let found = WAPI.getChat(id);
if (found) {
found = WAPI._serializeChatObj(found);
} else {
found = false;
}
if (done !== undefined) done(found);
return found;
};
/**
* I return all unread messages from an asked chat and mark them as read.
*
* :param id: chat id
* :type id: string
*
* :param includeMe: indicates if user messages have to be included
* :type includeMe: boolean
*
* :param includeNotifications: indicates if notifications have to be included
* :type includeNotifications: boolean
*
* :param done: callback passed by selenium
* :type done: function
*
* :returns: list of unread messages from asked chat
* :rtype: object
*/
window.WAPI.getUnreadMessagesInChat = function (id, includeMe, includeNotifications, done) {
// get chat and its messages
let chat = WAPI.getChat(id);
let messages = chat.msgs._models;
// initialize result list
let output = [];
// look for unread messages, newest is at the end of array
for (let i = messages.length - 1; i >= 0; i--) {
// system message: skip it
if (i === "remove") {
continue;
}
// get message
let messageObj = messages[i];
// found a read message: stop looking for others
if (typeof (messageObj.isNewMsg) !== "boolean" || messageObj.isNewMsg === false) {
continue;
} else {
messageObj.isNewMsg = false;
// process it
let message = WAPI.processMessageObj(messageObj,
includeMe,
includeNotifications);
// save processed message on result list
if (message)
output.push(message);
}
}
// callback was passed: run it
if (done !== undefined) done(output);
// return result list
return output;
}
;
/**
* Load more messages in chat object from store by ID
*
* @param id ID of chat
* @param done Optional callback function for async execution
* @returns None
*/
window.WAPI.loadEarlierMessages = function (id, done) {
const found = WAPI.getChat(id);
if (done !== undefined) {
found.loadEarlierMsgs().then(function () {
done()
});
} else {
found.loadEarlierMsgs();
}
};
/**
* Load more messages in chat object from store by ID
*
* @param id ID of chat
* @param done Optional callback function for async execution
* @returns None
*/
window.WAPI.loadAllEarlierMessages = function (id, done) {
const found = WAPI.getChat(id);
x = function () {
if (!found.msgs.msgLoadState.noEarlierMsgs) {
found.loadEarlierMsgs().then(x);
} else if (done) {
done();
}
};
x();
};
window.WAPI.asyncLoadAllEarlierMessages = function (id, done) {
done();
window.WAPI.loadAllEarlierMessages(id);
};
window.WAPI.areAllMessagesLoaded = function (id, done) {
const found = WAPI.getChat(id);
if (!found.msgs.msgLoadState.noEarlierMsgs) {
if (done) done(false);
return false
}
if (done) done(true);
return true
};
/**
* Load more messages in chat object from store by ID till a particular date
*
* @param id ID of chat
* @param lastMessage UTC timestamp of last message to be loaded
* @param done Optional callback function for async execution
* @returns None
*/
window.WAPI.loadEarlierMessagesTillDate = function (id, lastMessage, done) {
const found = WAPI.getChat(id);
x = function () {
if (found.msgs.models[0].t > lastMessage && !found.msgs.msgLoadState.noEarlierMsgs) {
found.loadEarlierMsgs().then(x);
} else {
done();
}
};
x();
};
/**
* Fetches all group metadata objects from store
*
* @param done Optional callback function for async execution
* @returns {Array|*} List of group metadata
*/
window.WAPI.getAllGroupMetadata = function (done) {
const groupData = window.Store.GroupMetadata.map((groupData) => groupData.all);
if (done !== undefined) done(groupData);
return groupData;
};
/**
* Fetches group metadata object from store by ID
*
* @param id ID of group
* @param done Optional callback function for async execution
* @returns {T|*} Group metadata object
*/
window.WAPI.getGroupMetadata = async function (id, done) {
let output = window.Store.GroupMetadata.get(id);
if (output !== undefined) {
if (output.stale) {
await window.Store.GroupMetadata.update(id);
}
}
if (done !== undefined) done(output);
return output;
};
/**
* Fetches group participants
*
* @param id ID of group
* @returns {Promise.<*>} Yields group metadata
* @private
*/
window.WAPI._getGroupParticipants = async function (id) {
const metadata = await WAPI.getGroupMetadata(id);
return metadata.participants;
};
/**
* Fetches IDs of group participants
*
* @param id ID of group
* @param done Optional callback function for async execution
* @returns {Promise.<Array|*>} Yields list of IDs
*/
window.WAPI.getGroupParticipantIDs = async function (id, done) {
const output = (await WAPI._getGroupParticipants(id))
.map((participant) => participant.id);
if (done !== undefined) done(output);
return output;
};
window.WAPI.getGroupAdmins = async function (id, done) {
const output = (await WAPI._getGroupParticipants(id))
.filter((participant) => participant.isAdmin)
.map((admin) => admin.id);
if (done !== undefined) done(output);
return output;
};
/**
* Gets object representing the logged in user
*
* @returns {Array|*|$q.all}
*/
window.WAPI.getMe = function (done) {
const rawMe = window.Store.Contact.get(window.Store.Conn.me);
if (done !== undefined) done(rawMe.all);
return rawMe.all;
};
window.WAPI.isLoggedIn = function (done) {
// Contact always exists when logged in
const isLogged = window.Store.Contact && window.Store.Contact.checksum !== undefined;
if (done !== undefined) done(isLogged);
return isLogged;
};
window.WAPI.isConnected = function (done) {
// Phone Disconnected icon appears when phone is disconnected from the tnternet
const isConnected = document.querySelector('*[data-icon="alert-phone"]') !== null ? false : true;
if (done !== undefined) done(isConnected);
return isConnected;
};
window.WAPI.processMessageObj = function (messageObj, includeMe, includeNotifications) {
if (messageObj.isNotification) {
if (includeNotifications)
return WAPI._serializeMessageObj(messageObj);
else
return;
// System message
// (i.e. "Messages you send to this chat and calls are now secured with end-to-end encryption...")
} else if (messageObj.id.fromMe === false || includeMe) {
return WAPI._serializeMessageObj(messageObj);
}
return;
};
window.WAPI.getAllMessagesInChat = function (id, includeMe, includeNotifications, done) {
const chat = WAPI.getChat(id);
let output = [];
const messages = chat.msgs._models;
for (const i in messages) {
if (i === "remove") {
continue;
}
const messageObj = messages[i];
let message = WAPI.processMessageObj(messageObj, includeMe, includeNotifications)
if (message)
output.push(message);
}
if (done !== undefined) done(output);
return output;
};
window.WAPI.getAllMessageIdsInChat = function (id, includeMe, includeNotifications, done) {
const chat = WAPI.getChat(id);
let output = [];
const messages = chat.msgs._models;
for (const i in messages) {
if ((i === "remove")
|| (!includeMe && messages[i].isMe)
|| (!includeNotifications && messages[i].isNotification)) {
continue;
}
output.push(messages[i].id._serialized);
}
if (done !== undefined) done(output);
return output;
};
window.WAPI.getMessageById = function (id, done) {
let result = false;
try {
let msg = window.Store.Msg.get(id);
if (msg) {
result = WAPI.processMessageObj(msg, true, true);
}
} catch (err) { }
if (done !== undefined) {
done(result);
} else {
return result;
}
};
window.WAPI.ReplyMessage = function (idMessage, message, done) {
var messageObject = window.Store.Msg.get(idMessage);
if (messageObject === undefined) {
if (done !== undefined) done(false);
return false;
}
messageObject = messageObject.value();
const chat = WAPI.getChat(messageObject.chat.id)
if (chat !== undefined) {
if (done !== undefined) {
chat.sendMessage(message, null, messageObject).then(function () {
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var trials = 0;
function check() {
for (let i = chat.msgs.models.length - 1; i >= 0; i--) {
let msg = chat.msgs.models[i];
if (!msg.senderObj.isMe || msg.body != message) {
continue;
}
done(WAPI._serializeMessageObj(msg));
return True;
}
trials += 1;
console.log(trials);
if (trials > 30) {
done(true);
return;
}
sleep(500).then(check);
}
check();
});
return true;
} else {
chat.sendMessage(message, null, messageObject);
return true;
}
} else {
if (done !== undefined) done(false);
return false;
}
};
window.WAPI.sendMessageToID = function (id, message, done) {
try {
window.getContact = (id) => {
return Store.WapQuery.queryExist(id);
}
window.getContact(id).then(contact => {
if (contact.status === 404) {
done(true);
} else {
Store.Chat.find(contact.jid).then(chat => {
chat.sendMessage(message);
return true;
}).catch(reject => {
if (WAPI.sendMessage(id, message)) {
done(true);
return true;
}else{
done(false);
return false;
}
});
}
});
} catch (e) {
if (window.Store.Chat.length === 0)
return false;
firstChat = Store.Chat.models[0];
var originalID = firstChat.id;
firstChat.id = typeof originalID === "string" ? id : new window.Store.UserConstructor(id, { intentionallyUsePrivateConstructor: true });
if (done !== undefined) {
firstChat.sendMessage(message).then(function () {
firstChat.id = originalID;
done(true);
});
return true;
} else {
firstChat.sendMessage(message);
firstChat.id = originalID;
return true;
}
}
if (done !== undefined) done(false);
return false;
}
window.WAPI.sendMessage = function (id, message, done) {
var chat = WAPI.getChat(id);
if (chat !== undefined) {
if (done !== undefined) {
chat.sendMessage(message).then(function () {
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var trials = 0;
function check() {
for (let i = chat.msgs.models.length - 1; i >= 0; i--) {
let msg = chat.msgs.models[i];
if (!msg.senderObj.isMe || msg.body != message) {
continue;
}
done(WAPI._serializeMessageObj(msg));
return True;
}
trials += 1;
console.log(trials);
if (trials > 30) {
done(true);
return;
}
sleep(500).then(check);
}
check();
});
return true;
} else {
chat.sendMessage(message);
return true;
}
} else {
if (done !== undefined) done(false);
return false;
}
};
window.WAPI.sendMessage2 = function (id, message, done) {
var chat = WAPI.getChat(id);
if (chat !== undefined) {
try {
if (done !== undefined) {
chat.sendMessage(message).then(function () {
done(true);
});
} else {
chat.sendMessage(message);
}
return true;
} catch (error) {
if (done !== undefined) done(false)
return false;
}
}
if (done !== undefined) done(false)
return false;
};
window.WAPI.sendSeen = function (id, done) {
var chat = window.WAPI.getChat(id);
if (chat !== undefined) {
if (done !== undefined) {
if (chat.getLastMsgKeyForAction === undefined)
chat.getLastMsgKeyForAction = function () { };
Store.SendSeen(chat, false).then(function () {
done(true);
});
return true;
} else {
Store.SendSeen(chat, false);
return true;
}
}
if (done !== undefined) done();
return false;
};
function isChatMessage(message) {
if (message.isSentByMe) {
return false;
}
if (message.isNotification) {
return false;
}
if (!message.isUserCreatedType) {
return false;
}
return true;
}
window.WAPI.getUnreadMessages = function (includeMe, includeNotifications, use_unread_count, done) {
const chats = window.Store.Chat.models;
let output = [];
for (let chat in chats) {
if (isNaN(chat)) {
continue;
}
let messageGroupObj = chats[chat];
let messageGroup = WAPI._serializeChatObj(messageGroupObj);
messageGroup.messages = [];
const messages = messageGroupObj.msgs._models;
for (let i = messages.length - 1; i >= 0; i--) {
let messageObj = messages[i];
if (typeof (messageObj.isNewMsg) != "boolean" || messageObj.isNewMsg === false) {
continue;
} else {
messageObj.isNewMsg = false;
let message = WAPI.processMessageObj(messageObj, includeMe, includeNotifications);
if (message) {
messageGroup.messages.push(message);
}
}
}
if (messageGroup.messages.length > 0) {
output.push(messageGroup);
} else { // no messages with isNewMsg true
if (use_unread_count) {
let n = messageGroupObj.unreadCount; // will use unreadCount attribute to fetch last n messages from sender
for (let i = messages.length - 1; i >= 0; i--) {
let messageObj = messages[i];
if (n > 0) {
if (!messageObj.isSentByMe) {
let message = WAPI.processMessageObj(messageObj, includeMe, includeNotifications);
messageGroup.messages.unshift(message);
n -= 1;
}
} else if (n === -1) { // chat was marked as unread so will fetch last message as unread
if (!messageObj.isSentByMe) {
let message = WAPI.processMessageObj(messageObj, includeMe, includeNotifications);
messageGroup.messages.unshift(message);
break;
}
} else { // unreadCount = 0
break;
}
}
if (messageGroup.messages.length > 0) {
messageGroupObj.unreadCount = 0; // reset unread counter
output.push(messageGroup);
}
}
}
}
if (done !== undefined) {
done(output);
}
return output;
};
window.WAPI.getGroupOwnerID = async function (id, done) {
const output = (await WAPI.getGroupMetadata(id)).owner.id;
if (done !== undefined) {
done(output);
}
return output;
};
window.WAPI.getCommonGroups = async function (id, done) {
let output = [];
groups = window.WAPI.getAllGroups();
for (let idx in groups) {
try {
participants = await window.WAPI.getGroupParticipantIDs(groups[idx].id);
if (participants.filter((participant) => participant == id).length) {
output.push(groups[idx]);
}
} catch (err) {
console.log("Error in group:");
console.log(groups[idx]);
console.log(err);
}
}
if (done !== undefined) {
done(output);
}
return output;
};
window.WAPI.getProfilePicSmallFromId = function (id, done) {
window.Store.ProfilePicThumb.find(id).then(function (d) {
if (d.img !== undefined) {
window.WAPI.downloadFileWithCredentials(d.img, done);
} else {
done(false);
}
}, function (e) {
done(false);
})
};
window.WAPI.getProfilePicFromId = function (id, done) {
window.Store.ProfilePicThumb.find(id).then(function (d) {
if (d.imgFull !== undefined) {
window.WAPI.downloadFileWithCredentials(d.imgFull, done);
} else {
done(false);
}
}, function (e) {
done(false);
})
};
window.WAPI.downloadFileWithCredentials = function (url, done) {
let xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
let reader = new FileReader();
reader.readAsDataURL(xhr.response);
reader.onload = function (e) {
done(reader.result.substr(reader.result.indexOf(',') + 1))
};
} else {
console.error(xhr.statusText);
}
} else {
console.log(err);
done(false);
}
};
xhr.open("GET", url, true);
xhr.withCredentials = true;
xhr.responseType = 'blob';
xhr.send(null);
};
window.WAPI.downloadFile = function (url, done) {
let xhr = new XMLHttpRequest();
xhr.onload = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
let reader = new FileReader();
reader.readAsDataURL(xhr.response);
reader.onload = function (e) {
done(reader.result.substr(reader.result.indexOf(',') + 1))
};
} else {
console.error(xhr.statusText);
}
} else {
console.log(err);
done(false);
}
};
xhr.open("GET", url, true);
xhr.responseType = 'blob';
xhr.send(null);
};
window.WAPI.getBatteryLevel = function (done) {
if (window.Store.Conn.plugged) {
if (done !== undefined) {
done(100);
}
return 100;
}
output = window.Store.Conn.battery;
if (done !== undefined) {
done(output);
}
return output;
};
window.WAPI.deleteConversation = function (chatId, done) {
let userId = new window.Store.UserConstructor(chatId, {intentionallyUsePrivateConstructor: true});
let conversation = WAPI.getChat(userId);
if (!conversation) {
if (done !== undefined) {
done(false);
}
return false;
}
window.Store.sendDelete(conversation, false).then(() => {
if (done !== undefined) {
done(true);
}
}).catch(() => {
if (done !== undefined) {
done(false);
}
});
return true;
};
window.WAPI.deleteMessage = function (chatId, messageArray, revoke=false, done) {
let userId = new window.Store.UserConstructor(chatId, {intentionallyUsePrivateConstructor: true});
let conversation = WAPI.getChat(userId);
if(!conversation) {
if(done !== undefined) {
done(false);
}
return false;
}
if (!Array.isArray(messageArray)) {
messageArray = [messageArray];
}
let messagesToDelete = messageArray.map(msgId => window.Store.Msg.get(msgId));
if (revoke) {
conversation.sendRevokeMsgs(messagesToDelete, conversation);
} else {
conversation.sendDeleteMsgs(messagesToDelete, conversation);
}
if (done !== undefined) {
done(true);
}
return true;
};
window.WAPI.checkNumberStatus = function (id, done) {
window.Store.WapQuery.queryExist(id).then((result) => {
if( done !== undefined) {
if (result.jid === undefined) throw 404;
done(window.WAPI._serializeNumberStatusObj(result));
}
}).catch((e) => {
if (done !== undefined) {
done(window.WAPI._serializeNumberStatusObj({
status: e,
jid : id
}));
}
});
return true;
};
/**
* New messages observable functions.
*/
window.WAPI._newMessagesQueue = [];
window.WAPI._newMessagesBuffer = (sessionStorage.getItem('saved_msgs') != null) ? JSON.parse(sessionStorage.getItem('saved_msgs')) : [];
window.WAPI._newMessagesDebouncer = null;
window.WAPI._newMessagesCallbacks = [];
window.Store.Msg.off('add');
sessionStorage.removeItem('saved_msgs');
window.WAPI._newMessagesListener = window.Store.Msg.on('add', (newMessage) => {
if (newMessage && newMessage.isNewMsg && !newMessage.isSentByMe) {
let message = window.WAPI.processMessageObj(newMessage, false, false);
if (message) {
window.WAPI._newMessagesQueue.push(message);
window.WAPI._newMessagesBuffer.push(message);
}
// Starts debouncer time to don't call a callback for each message if more than one message arrives
// in the same second
if (!window.WAPI._newMessagesDebouncer && window.WAPI._newMessagesQueue.length > 0) {
window.WAPI._newMessagesDebouncer = setTimeout(() => {
let queuedMessages = window.WAPI._newMessagesQueue;
window.WAPI._newMessagesDebouncer = null;
window.WAPI._newMessagesQueue = [];
let removeCallbacks = [];
window.WAPI._newMessagesCallbacks.forEach(function (callbackObj) {
if (callbackObj.callback !== undefined) {
callbackObj.callback(queuedMessages);
}
if (callbackObj.rmAfterUse === true) {
removeCallbacks.push(callbackObj);
}
});
// Remove removable callbacks.
removeCallbacks.forEach(function (rmCallbackObj) {
let callbackIndex = window.WAPI._newMessagesCallbacks.indexOf(rmCallbackObj);
window.WAPI._newMessagesCallbacks.splice(callbackIndex, 1);
});
}, 1000);
}
}
});
window.WAPI._unloadInform = (event) => {
// Save in the buffer the ungot unreaded messages
window.WAPI._newMessagesBuffer.forEach((message) => {
Object.keys(message).forEach(key => message[key] === undefined ? delete message[key] : '');
});
sessionStorage.setItem("saved_msgs", JSON.stringify(window.WAPI._newMessagesBuffer));
// Inform callbacks that the page will be reloaded.
window.WAPI._newMessagesCallbacks.forEach(function (callbackObj) {
if (callbackObj.callback !== undefined) {
callbackObj.callback({ status: -1, message: 'page will be reloaded, wait and register callback again.' });
}
});
};
window.addEventListener("unload", window.WAPI._unloadInform, false);
window.addEventListener("beforeunload", window.WAPI._unloadInform, false);
window.addEventListener("pageunload", window.WAPI._unloadInform, false);
/**
* Registers a callback to be called when a new message arrives the WAPI.
* @param rmCallbackAfterUse - Boolean - Specify if the callback need to be executed only once
* @param done - function - Callback function to be called when a new message arrives.
* @returns {boolean}
*/
window.WAPI.waitNewMessages = function (rmCallbackAfterUse = true, done) {
window.WAPI._newMessagesCallbacks.push({ callback: done, rmAfterUse: rmCallbackAfterUse });
return true;
};
/**
* Reads buffered new messages.
* @param done - function - Callback function to be called contained the buffered messages.
* @returns {Array}
*/
window.WAPI.getBufferedNewMessages = function (done) {
let bufferedMessages = window.WAPI._newMessagesBuffer;
window.WAPI._newMessagesBuffer = [];
if (done !== undefined) {
done(bufferedMessages);
}
return bufferedMessages;
};
/** End new messages observable functions **/
window.WAPI.sendImage = function (imgBase64, chatid, filename, caption, done) {
//var idUser = new window.Store.UserConstructor(chatid);
var idUser = new window.Store.UserConstructor(chatid, { intentionallyUsePrivateConstructor: true });
// create new chat
return Store.Chat.find(idUser).then((chat) => {
var mediaBlob = window.WAPI.base64ImageToFile(imgBase64, filename);
var mc = new Store.MediaCollection(chat);
mc.processAttachments([{file: mediaBlob}, 1], chat, 1).then(() => {
var media = mc.models[0];
media.sendToChat(chat, { caption: caption });
if (done !== undefined) done(true);
});
});
}
window.WAPI.base64ImageToFile = function (b64Data, filename) {
var arr = b64Data.split(',');
var mime = arr[0].match(/:(.*?);/)[1];
var bstr = atob(arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type: mime});
};
/**
* Send contact card to a specific chat using the chat ids
*
* @param {string} to '[email protected]'
* @param {string|array} contact '[email protected]' | ['[email protected]', '[email protected], ... '[email protected]']
*/
window.WAPI.sendContact = function (to, contact) {
if (!Array.isArray(contact)) {
contact = [contact];
}
contact = contact.map((c) => {
return WAPI.getChat(c).__x_contact;
});
if (contact.length > 1) {
window.WAPI.getChat(to).sendContactList(contact);
} else if (contact.length === 1) {
window.WAPI.getChat(to).sendContact(contact[0]);
}
};
/**
* Create an chat ID based in a cloned one
*
* @param {string} chatId '[email protected]'
*/
window.WAPI.getNewMessageId = function (chatId) {
var newMsgId = Store.Msg.models[0].__x_id.clone();
newMsgId.fromMe = true;
newMsgId.id = WAPI.getNewId().toUpperCase();
newMsgId.remote = chatId;
newMsgId._serialized = `${newMsgId.fromMe}_${newMsgId.remote}_${newMsgId.id}`
return newMsgId;
};
/**
* Send Customized VCard without the necessity of contact be a Whatsapp Contact
*
* @param {string} chatId '[email protected]'
* @param {object|array} vcard { displayName: 'Contact Name', vcard: 'BEGIN:VCARD\nVERSION:3.0\nN:;Contact Name;;;\nEND:VCARD' } | [{ displayName: 'Contact Name 1', vcard: 'BEGIN:VCARD\nVERSION:3.0\nN:;Contact Name 1;;;\nEND:VCARD' }, { displayName: 'Contact Name 2', vcard: 'BEGIN:VCARD\nVERSION:3.0\nN:;Contact Name 2;;;\nEND:VCARD' }]
*/
window.WAPI.sendVCard = function (chatId, vcard) {
var chat = Store.Chat.get(chatId);
var tempMsg = Object.create(Store.Msg.models.filter(msg => msg.__x_isSentByMe)[0]);
var newId = window.WAPI.getNewMessageId(chatId);
var extend = {
ack : 0,
id : newId,
local : !0,
self : "out",
t : parseInt(new Date().getTime() / 1000),
to : chatId,
isNewMsg: !0,
};
if (Array.isArray(vcard)) {
Object.assign(extend, {
type : "multi_vcard",
vcardList: vcard
});
delete extend.body;
} else {
Object.assign(extend, {
type : "vcard",
subtype: vcard.displayName,
body : vcard.vcard
});
delete extend.vcardList;
}
Object.assign(tempMsg, extend);
chat.addAndSendMsg(tempMsg);
};
/**
* Block contact
* @param {string} id '[email protected]'
* @param {*} done - function - Callback function to be called when a new message arrives.
*/
window.WAPI.contactBlock = function (id, done) {
const contact = window.Store.Contact.get(id);
if (contact !== undefined) {
contact.setBlock(!0);
done(true);
return true;
}
done(false);
return false;
}
/**
* unBlock contact
* @param {string} id '[email protected]'
* @param {*} done - function - Callback function to be called when a new message arrives.
*/
window.WAPI.contactUnblock = function (id, done) {
const contact = window.Store.Contact.get(id);
if (contact !== undefined) {
contact.setBlock(!1);
done(true);
return true;
}
done(false);
return false;
}
/**
* Remove participant of Group
* @param {*} idGroup '[email protected]'
* @param {*} idParticipant '[email protected]'
* @param {*} done - function - Callback function to be called when a new message arrives.
*/
window.WAPI.removeParticipantGroup = function (idGroup, idParticipant, done) {
window.Store.WapQuery.removeParticipants(idGroup, [idParticipant]).then(() => {
const metaDataGroup = window.Store.GroupMetadata.get(id)
checkParticipant = metaDataGroup.participants._index[idParticipant];
if (checkParticipant === undefined) {
done(true); return true;
}
})
}
/**
* Promote Participant to Admin in Group
* @param {*} idGroup '[email protected]'
* @param {*} idParticipant '[email protected]'
* @param {*} done - function - Callback function to be called when a new message arrives.
*/
window.WAPI.promoteParticipantAdminGroup = function (idGroup, idParticipant, done) {
window.Store.WapQuery.promoteParticipants(idGroup, [idParticipant]).then(() => {
const metaDataGroup = window.Store.GroupMetadata.get(id)
checkParticipant = metaDataGroup.participants._index[idParticipant];
if (checkParticipant !== undefined && checkParticipant.isAdmin) {
done(true); return true;
}
done(false); return false;
})
}
/**
* Demote Admin of Group
* @param {*} idGroup '[email protected]'
* @param {*} idParticipant '[email protected]'
* @param {*} done - function - Callback function to be called when a new message arrives.
*/
window.WAPI.demoteParticipantAdminGroup = function (idGroup, idParticipant, done) {
window.Store.WapQuery.demoteParticipants(idGroup, [idParticipant]).then(() => {
const metaDataGroup = window.Store.GroupMetadata.get(id)
if (metaDataGroup === undefined) {
done(false); return false;
}
checkParticipant = metaDataGroup.participants._index[idParticipant];
if (checkParticipant !== undefined && checkParticipant.isAdmin) {
done(false); return false;
}
done(true); return true;
})
}
function checkStatus() {
return (localStorage.WASecretBundle !== undefined || localStorage.WARoutingInfo !== undefined) ? 0 : -1;
}
function runCheckMessages() {
if (localStorage.WASecretBundle === undefined && localStorage.WARoutingInfo === undefined) return -1;
return document.querySelectorAll('[aria-label*="unread message"]').length;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment