Skip to content

Instantly share code, notes, and snippets.

@dleshem
Created November 1, 2023 10:49
Show Gist options
  • Save dleshem/aba9f255a17a2ed287947336cdc35c3f to your computer and use it in GitHub Desktop.
Save dleshem/aba9f255a17a2ed287947336cdc35c3f to your computer and use it in GitHub Desktop.
Tampermonkey userscript to send WhatsApp texts triggered by alarms in Israel
// ==UserScript==
// @name WhatsAppAlarms
// @namespace http://tampermonkey.net/
// @version 1.0
// @description WhatsApp texts triggered by alarms in Israel
// @author Danny Leshem
// @match https://web.whatsapp.com/
// @icon https://www.google.com/s2/favicons?sz=64&domain=whatsapp.com
// @grant GM_xmlhttpRequest
// @connect www.oref.org.il
// @connect github.com
// ==/UserScript==
// Setup: add rules below, load to Tampermonkey, grant permissions when asked
//
// We use GM_xmlhttpRequest to poll for alerts, as oref.org.il fails requests with
// incorrect {Referer, X-Requested-With} HTTP headers.
//
// This means our script is sandboxed, so we must explicitly fetch and load wppconnect-wa.js
// instead of using @require
//
//
//
// Config
//
const pollMs = 1000 * 10; // How often should oref.org.il be polled for alerts (default: 10 seconds)
const throttleMs = 1000 * 60 * 15; // How long to Wait before a rule is triggered again (default: 15 minutes)
//
// {
// area: 'תל אביב - מרכז העיר', // an oref.org.il area (or '' for all areas)
// chatId: '972545000000@c.us', // chat ID, can be individual chat or group chat (see wppconnect-wa.js)
// texts: [ // list of texts to sample from
// 'message #1',
// 'message #2',
// 'message #3'
// ],
// lastTriggered: null
// }
//
const rules = [];
//
// Utils
//
const sleep = ms => new Promise(r => setTimeout(r, ms));
const sample = array => array[Math.floor(Math.random() * array.length)];
const fetch = async (url, headers = {}) => {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
anonymous: true,
headers,
method: 'GET',
onload: (res) => {
if (res.status >= 200 && res.status < 300) {
resolve(res.response);
} else {
reject({
status: res.status,
statusText: res.statusText
});
}
},
onerror: (res) => {
reject({
status: res.status,
statusText: res.statusText
});
},
url
});
});
};
//
// Alerts API
//
const fetchCurrentAlerts = async () => {
const responseText = await fetch('https://www.oref.org.il/WarningMessages/alert/alerts.json', {
'Referer': 'https://www.oref.org.il/12481-he/Pakar.aspx',
'X-Requested-With': 'XMLHttpRequest'
});
const responseJson = responseText.replaceAll('\r\n', '');
return responseJson ? JSON.parse(responseJson) : null;
};
const includesArea = (alerts, area) => {
for (let i = 0; i < alerts.data.length; ++i) {
if (alerts.data[i].includes(area)) {
return true;
}
}
return false;
};
//
// Whatsapp API
//
const loadWppConnect = async () => {
console.log('Fetching wppconnect-wa.js');
const responseText = await fetch('https://github.com/wppconnect-team/wa-js/releases/download/nightly/wppconnect-wa.js');
console.log(`Fetched wppconnect-wa.js (${responseText.length} bytes)`);
const e = document.createElement('script');
e.innerText = responseText;
document.head.appendChild(e);
console.log('Loaded wppconnect-wa.js');
};
//
// Logic
//
const main = async () => {
while (true) {
try {
const alerts = await fetchCurrentAlerts();
console.log(new Date().toLocaleString(), alerts);
if (alerts) {
rules.forEach(rule => {
if (includesArea(alerts, rule.area)) {
console.log(`Alarm in '${rule.area}'`);
const lastTriggered = rule.lastTriggered || 0;
const now = new Date().getTime();
if (now - lastTriggered > throttleMs) {
rule.lastTriggered = now;
WPP.chat.sendTextMessage(rule.chatId, sample(rule.texts));
}
}
});
}
} catch (e) {
console.log(e);
}
await sleep(pollMs);
}
};
(async () => {
'use strict';
await loadWppConnect();
WPP.webpack.onReady(() => {
console.log('WPP.webpack.onReady');
});
WPP.webpack.onFullReady(async () => {
console.log('WPP.webpack.onFullReady');
main();
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment