// ==UserScript==
// @name zevent-place-overlay
// @namespace http://tampermonkey.net/
// @license MIT
// @version 1.8
// @description Please organize with other participants on Discord: https://discord.gg/sXe5aVW2jV ; Press H to hide/show again the overlay.
// @author ludolpif, ventston
// @match https://place.zevent.fr/
// @icon https://www.google.com/s2/favicons?sz=64&domain=zevent.fr
// @grant none
// @downloadURL https://raw.githubusercontent.com/ludolpif/overlay-zevent-place/main/browser-script/zevent-place-overlay.user.js
// @updateURL https://raw.githubusercontent.com/ludolpif/overlay-zevent-place/main/browser-script/zevent-place-overlay.user.js
// ==/UserScript==
/*
* Script used as base, form MinusKube: https://greasyfork.org/fr/scripts/444833-z-place-overlay/code
* Original and this code licence: MIT
* Copyright 2021-2022 ludolpif, ventston
* Thanks to : grewa, BunlanG|Baron for help on CSS
*/
(function() {
'use strict';
const version = "1.8";
const scriptUpdateURL = "https://raw.githubusercontent.com/ludolpif/overlay-zevent-place/main/browser-script/zevent-place-overlay.user.js"
// Global constants and variables for our script
const overlayJSON1 = "https://timeforzevent.fr/overlay.json"; // Need CORS header (Access-Control-Allow-Origin: https://place.zevent.fr)
const overlayJSON2 = "https://backup.place.timeforzevent.fr/overlay.json";
const inviteDiscordURL = "https://discord.gg/sXe5aVW2jV";
let refreshOverlaysState = true; // state false: idle, true: asked, (no cooldown: throttled by keepOurselfInDOM())
let safeModeDisableUI = false;
let safeModeDisableGetJSON = false;
let wantedOverlays = {}; // Same format as knownOverlays : the format of overlay.json
let refreshKnownOverlaysState = 0; // state 0: idle, 1: asked, 2: in progress (main url), 3: in progress (bkp url), 4: cooldown (rate limiting)
let lastCustomId = 0;
function zpoLog(msg) {
const ts = new Date().toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit', second: '2-digit'});
console.log(ts + " zevent-place-overlay: " + msg);
}
zpoLog("version " + version);
/*
* FR: Utilisateurs du script: vous pouvez éditer les lignes loadOverlay() ci-après pour mémoriser dans votre navigateur
* vos choix d'overlay sans utiliser le menu "Overlays" proposé par ce script sur https://place.zevent.fr/
* Pour ce faire :
* 0) S'assurer que vous lisez ça depuis un onglet de l'extension TamperMonkey dans votre navigateur
* (sinon vous avez manqué des étapes de la documentation sous README.md: https://github.com/ludolpif/overlay-zevent-place )
* 1) Utilisez une ligne //loadOveray(...); laissée en exemple
* 2) SÉCURITÉ: ne tentez pas de charger autre chose qu'une image .png
* 3) Remplacez l'URL d'exemple par l'URL de l'overlay de voter choix
* 4) Enlevez le double-slash // avant loadOverlay(...); pour activer cette ligne de code
* 5) Sauvez le script (Ctrl+S)
* 6) Fermez cet onglet (editeur Tampermonkey)
* 7) Allez sur l'onglet de https://place.zevent.fr et rafraichissez avec Ctrl+R
* Remarques :
* - Les calques (overlays) ne s'affichent qu'après l'authentification sur le site https://place.zevent.fr
* - Ne touchez pas / préservez les point-virgules en fin de ligne de code, le script tombe en panne sinon.
* Mode sans échec :
* - Si vous avez un bug avec l'UI, mettez vos URL dans des lignes loadOverlay(...);
* et enlevez le // devant la ligne //safeModeDisableUI...
*/
//safeModeDisableGetJSON = true;
//safeModeDisableUI = true;
//loadOverlay("https://raw.githubusercontent.com/ludolpif/overlay-zevent-place/main/examples/demo-overlay.png" );
//loadOverlay("https://raw.githubusercontent.com/ludolpif/overlay-zevent-place/main/examples/demo-overlay2.png" );
//loadOverlay("https://somewebsite.com/someoverlay.png","A short title" );
/*
* EN: Script users: you can edit loadOverlay(...) lines above to memorize in your browser
* your overlay choices without using the "Overlays" menu from this script on https://place.zevent.fr/
* To do that:
* 0) Make sure you read this from a web browser's tab, from the TamperMonkey extension
* (if not, you have missed steps in the documentation below README.md: https://github.com/ludolpif/overlay-zevent-place )
* 1) Use an line of code left as example like //loadOveray(...);
* 2) SECURITY: don't try to load anything but a .png file
* 3) Replace the example URL by the URL the the overlay of your choice
* 4) Remove the double-slash // before loadOverlay(...); to enable this line of code
* 5) Save the script (Ctrl+S)
* 6) Close this tab (Tampermonkey editor)
* 7) Go on https://place.zevent.fr browser tab and refresh the page with Ctrl+R
* Remarks :
* - Overlays will display only after successful authentication on https://place.zevent.fr website
* - Don't mess up any semi-colon (;) at end of code lines, it will break the script.
* Safe mode :
* - If you have a bug with the UI, put your URLs in some loadOverlay(...); lines
* and remove the double-slash // before //safeModeDisableUI... line
*/
function loadOverlay(url, title, id) {
zpoLog("loadOverlay(" + url + ", " + title + ", " + id + ")");
const checkedURL = urlSanityCheck(url);
let checkedTitle = textSanityFilter(title);
if (checkedTitle === '(invalid)') {
checkedTitle = checkedURL.replace(/^.*\/([^%?<>&]+)$/, '$1');
}
let checkedId = idSanityCheck(id);
if (checkedId === false) {
checkedId = "custom-" + lastCustomId++;
}
wantedOverlays[checkedId] = { id:checkedId, url: checkedURL, title:checkedTitle };
refreshOverlaysState = true;
}
function reloadOverlays(origCanvas, ourOverlays) {
zpoLog("reloadOverlays()");
const parentDiv = origCanvas.parentElement;
// CSS fix for firefox ESR 91 ('pixellated' needs >=93)
if (navigator.userAgent.replace(/^Mozilla.* rv:(\d+).*$/, '$1') < 93) {
parentDiv.style.setProperty('image-rendering', 'crisp-edges');
}
const wantedOverlaysIds = Object.keys(wantedOverlays);
// Update wantedOverlays URL from knownOverlays when the wantedOverlay came from there
// id could be "custom-N" for manually added URL, it won't match in knownOverlays
wantedOverlaysIds.forEach(function (id) {
const data = wantedOverlays[id];
if ( knownOverlays[id] && ( typeof knownOverlays[id].overlay_url === "string" ) ) {
const newURL = knownOverlays[id].overlay_url;
// newURL assumed already sanitized (done when inserted in knownOverlays at first place)
if ( newURL.startsWith("https://") && ( data.url != newURL ) ) {
zpoLog("reloadOverlays() updating url for id:" + id + " from: " + data.url + "to: " + newURL);
data.url = newURL;
}
}
});
// Remove all our
// TODO remove all addEventListener before deleting ?
if ( !ourOverlays ) ourOverlays = [];
ourOverlays.forEach(function (e) { e.remove() });
// Insert them again
wantedOverlaysIds.forEach(function (id) {
const data = wantedOverlays[id];
appendOverlayInDOM(origCanvas, parentDiv, data.url);
});
refreshDisplayTime(document.querySelector('#zevent-place-overlay-wanted-ts'));
// Mark job done for keepOurselfInDOM
refreshOverlaysState = false;
}
function reloadUIWantedOverlays() {
if (!wantedOverlays) {
zpoLog("reloadUIWantedOverlays() for undefined wantedOverlays");
return;
}
const wantedOverlaysIds = Object.keys(wantedOverlays);
zpoLog("reloadUIWantedOverlays() for " + wantedOverlaysIds.length + " wantedOverlays");
// Refresh the list in DOM
const ulWantedOverlays = document.querySelector('#zevent-place-overlay-ui-list-wanted-overlays');
if (!ulWantedOverlays) return;
ulWantedOverlays.innerHTML = "";
wantedOverlaysIds.forEach(function (id) { appendUIWantedOverlays(ulWantedOverlays, id, wantedOverlays[id]); });
}
function reloadUIKnownOverlays() {
if (!knownOverlays) {
zpoLog("reloadUIKnownOverlays() for undefined knownOverlays");
return;
}
const knownOverlaysIds = Object.keys(knownOverlays);
zpoLog("reloadUIKnownOverlays() for " + knownOverlaysIds.length + " knownOverlays");
// Refresh the list in DOM
const ulKnownOverlays = document.querySelector('#zevent-place-overlay-ui-list-known-overlays');
if (!ulKnownOverlays) return;
ulKnownOverlays.innerHTML = "";
knownOverlaysIds.forEach(function (id) { appendUIKnownOverlays(ulKnownOverlays, id, knownOverlays[id]); });
}
function appendOverlayInDOM(origCanvas, parentDiv, url) {
zpoLog("appendOverlayInDOM() url: " + url);
const image = document.createElement("img");
image.className = "zevent-place-overlay-img";
// Add ?ts= and a timestamp to skip browser cache, overlays will be hosted at various places, with various Expires: headers
image.src = url + "?ts=" + new Date().getTime();
image.style = "background: none; position: absolute; left: 0px; top: 0px;";
image.onload = function (event) {
fitOverlayOnCanvas(origCanvas, event.target);
}
// Append the image on the document, it could change in size a bit later because of image.decode() Promise above
parentDiv.appendChild(image);
document.addEventListener('keypress', function(event) {
if (event.code == 'KeyH') {
image.hidden = !image.hidden;
}
});
}
function fitOverlayOnCanvas(origCanvas, image) {
zpoLog("fitOverlayOnCanvas()");
const nw = event.target.naturalWidth;
const nh = event.target.naturalHeight;
if ( !nw || !nh ) {
zpoLog("fitOverlayOnCanvas() WARNING: no nw or nh: " + nw + ',' + nh);
return;
}
if ( (nw%300) || (nh%300) ) {
zpoLog("fitOverlayOnCanvas() WARNING: adding image size that is not multiple of 300, badly exported overlay");
image.width = origCanvas.width;
image.height = origCanvas.height;
} else {
zpoLog("fitOverlayOnCanvas() nw,nh: " + nw + "," + nh);
image.width = nw/3;
image.height = nh/3;
}
zpoLog("fitOverlayOnCanvas() width,height: " + image.width + "," + image.height);
}
function appendOurUI(origUI) {
zpoLog("appendOurUI()");
const ourUI = document.createElement("div");
ourUI.id = "zevent-place-overlay-ui";
ourUI.style = `
padding: 0 8px; border-radius: 20px; background: #1f1f1f;
position: fixed; top: 16px; left: 16px; z-index: 999;`
ourUI.innerHTML = `