Skip to content

Instantly share code, notes, and snippets.

@leonklingele
Last active February 7, 2022 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leonklingele/88507fc143b748404951e0aadd6716ee to your computer and use it in GitHub Desktop.
Save leonklingele/88507fc143b748404951e0aadd6716ee to your computer and use it in GitHub Desktop.
Violentmonkey / Greasemonkey / Tampermonkey script to notify on new ads on eBay Kleinanzeigen
// ==UserScript==
// @name eBay Kleinanzeigen Notifier
// @namespace www.ebay-kleinanzeigen.de
// @description eBay Kleinanzeigen Notifier
// @version 1.0.0
// @icon https://www.ebay-kleinanzeigen.de/static/img/favicon.png
// @match https://www.ebay-kleinanzeigen.de/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @grant GM_notification
// ==/UserScript==
const config = {
queryParamName: 'notify',
reloadInterval: 10_000,
actions: [
'playSound',
'showNotification',
],
};
const shouldPlaySound = config.actions.indexOf('playSound') !== -1;
const shouldShowNotification = config.actions.indexOf('showNotification') !== -1;
const storageItem = (k) => {
const key = `ebay-kleinanzeigen-notifier_${k}`;
return {
read: () => {
return window.GM_getValue(key, null);
},
write: (data) => {
return window.GM_setValue(key, data);
},
};
};
const ensureCanPlaySound = (cb) => {
const canPlay = (cb) => {
const timeout = window.setTimeout(() => {
cb(false);
}, 500);
const ctx = new window.AudioContext();
try {
ctx.resume().then(() => {
window.clearTimeout(timeout);
return cb(ctx.state === 'running');
});
} catch (e) {
window.clearTimeout(timeout);
return cb(false);
}
};
const elem = window.GM_addStyle('body { visibility: hidden; background-color: red; }');
canPlay((can) => {
if (can) {
elem.remove();
}
cb(can);
});
};
const playSound = () => {
const start = 0;
const end = 2_000;
const audioCtx = new window.AudioContext();
const osc = audioCtx.createOscillator();
osc.connect(audioCtx.destination);
osc.type = 'sine';
osc.frequency.value = start;
osc.start();
const wave = () => {
for (let i = start; i <= end; i++) { window.setTimeout(() => { osc.frequency.value = i; }, i ); }
for (let i = end; i >= start; i--) { window.setTimeout(() => { osc.frequency.value = i; }, 2*end - i ); }
};
wave();
window.setInterval(wave, 2*end);
};
const showNotification = () => {
const n = window.GM_notification({
title: 'New ad on eBay Kleinanzeigen',
text: 'Found a new ad on eBay Kleinanzeigen',
image: 'https://www.ebay-kleinanzeigen.de/static/img/favicon.png',
});
};
const foundNew = () => {
if (shouldPlaySound) { playSound(); }
if (shouldShowNotification) { showNotification(); }
};
const go = () => {
const s = storageItem(window.location.pathname);
const ids = s.read() || [];
const ads = window.document.querySelectorAll('.ad-listitem:not(.badge-topad, .is-topad, .is-highlight) .aditem');
const latestAd = ads[0];
if (!latestAd) {
return;
}
const latestAdID = latestAd.getAttribute('data-adid');
let found = false;
ids.every((id) => {
if (id === latestAdID) {
found = true;
return false;
}
return true;
});
if (!found) {
ids.push(latestAdID);
s.write(ids);
foundNew();
}
window.setTimeout(() => { window.document.location.reload(); }, config.reloadInterval);
};
if ((new window.URLSearchParams(window.location.search)).has(config.queryParamName)) {
if (!shouldPlaySound) {
go();
} else {
ensureCanPlaySound((can) => {
if (can) {
go();
} else {
window.onclick = () => { window.document.location.reload(); };
window.alert('Can\'t play sound as user interaction didn\'t happen yet. Please click anywhere on the page to reload.');
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment