// ==UserScript== // @name Popmundo Forum Post Timestamp // @description The script run only on forms pages and show timestamps of messages // @author Criyessei // @version 2.0.0 // @license CC BY-NC-ND // @match https://*.popmundo.com/Forum/Popmundo.aspx/Thread/* // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js // @namespace https://greasyfork.org/users/805141 // @supportURL https://buymeacoffee.com/criyessei // @downloadURL https://update.greasyfork.icu/scripts/440189/Popmundo%20Forum%20Post%20Timestamp.user.js // @updateURL https://update.greasyfork.icu/scripts/440189/Popmundo%20Forum%20Post%20Timestamp.meta.js // ==/UserScript== /* Copyright (c) 2025 Criyessei Permission is granted to use and modify this software for personal or internal purposes only. Redistribution, publishing, or sharing of this software, whether in original or modified form, to third parties is strictly prohibited. The right to distribute this software remains exclusively with the copyright holder. Commercial use is prohibited without explicit written permission. All rights reserved by the author. By using this software, you agree to these terms. */ /* This script is completely free to use and will remain so. If you find it helpful and would like to support its development, you can make a small donation here: https://buymeacoffee.com/criyessei Thank you for your support! 💖 Criyessei */ /*globals moment*/ let $ = unsafeWindow.jQuery; const displayPoses = { "left": 0, "onTimeText": 1 } // only changes below is allowed: const preferences = { displayPos: displayPoses.onTimeText, // displayPoses.left, showMessageEditTimeStamp: true, showMessageTimeStamp: true, forceLanguage: null, //"de", }; const selectors = { messagesSelector: "#ppm-content >div.marginWrapper >div.talkbox:has(>div.talkbox-content):has(>div.talkbox-byline)", searchButton: "#ctl00_cphLeftColumn_ctl00_lnkBotSearch" }; const finders = { message: { messageEditParagraphFinder: (message)=> message.find(">div.talkbox-content >div >p.em"), messageEditTimeTextFinder: (messageEditP)=> messageEditP.contents().last()[0], messageTimeParagraphFinder: (message)=> message.find(">div.talkbox-byline >p:first"), messageTimeTextFinder: (messageTimeP)=> messageTimeP.contents().last()[0], } }; const parsers = { messageDateParser: /(?\d{1,2})\.(?\d{1,2})\.(?\d{4}),\s(?\d{1,2}):(?\d{1,2})/ }; const supportedLocales = { tr: "tr", en: "en", pt: "pt", "pt-br": "pt", es: "es", it: "it" }; (async function() { 'use strict'; await sleep(100); if (typeof moment === "undefined") { console.warn("moment.js not loaded on the page — skipping locale setup."); return; } await checkSupport(); // No, please don't remove. You seem like someone who knows, please find me let language = preferences.forceLanguage || detectLanguage(); //console.log(`page language: ${language}`); if (language !== "en") { if (typeof unsafeWindow.moment === "undefined") unsafeWindow.moment = moment; loadScript(`https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/locale/${language}.min.js`, () => { console.log("Loading moment.locale: " + language); moment.locale(language); main(); }); } else { moment.locale("en"); main(); } })(); function main() { let messages = $(selectors.messagesSelector); for(let i=0, len=messages.length; i(${label1})`); } } if(preferences.showMessageTimeStamp){ let messageTimeP = finders.message.messageTimeParagraphFinder(message); let timeEl2 = finders.message.messageTimeTextFinder(messageTimeP); const startMoment = moment(timeText2Date(timeEl2.textContent)); let label2 = startMoment.fromNow(); let duration = moment.duration(moment().diff(startMoment)); let hhmmss = moment.utc(duration.asMilliseconds()).format("HH:mm:ss"); //DISPLAY switch(preferences.displayPos){ case displayPoses.left: { let span = $(`${label2}`).appendTo(message); message.css({'overflow':'unset', 'position':'relative'}); console.log(message.find('>div:first').height()+" - "+span.height()); span.css('top', Math.max(3, parseInt((message.find('>div:first').height()-span.height())/2))) .css('left', -13-(span.width()-13.6)); } break; case displayPoses.onTimeText: messageTimeP.append(` (${label2})`); break; default: break; } } } function timeText2Date(timeText){ let {groups:{day, month, year, hour, minute}} = timeText.trim().match(parsers.messageDateParser); return new Date(year, month-1, day, hour, minute); } } function checkSupport(){ const test = false; const freq = 3*86400*1e3; var data = GM_getValue("donationPopupShown", undefined); if(data == undefined) data = {counter:0, lastShown:undefined}; var now = Date.now(); if (!test && data.lastShown && (now-data.lastShown){ const popupHtml = `

Thank you for using the "Popmundo Forum Post Timestamp"!

This script is completely free to use and will remain so.

If you find it helpful and would like to support its development,

💖Make a small donation here ☕

Kind Regards Criyessei

PS: You will not be disturbed by this being shown to you frequently.
Next show time: .

`; $("body").append(popupHtml); $("#donation-popup-overlay").fadeIn(300); $("#donation-popup").fadeIn(500); $("#donation-popup-close, #donation-popup-overlay").click(() => { var popup = $('#donation-popup'); popup.children().each(function(){ $(this).css({"opacity":"0"}); }); var okay = $("").html("Okay, no Problem 🤪").hide(); okay.css({ "position": "absolute", "left": "50%", "top": "50%", "transform": "translate(-50%, -50%)", "font-size": "50px", "font-weight":"bold", "color":"red", }); popup.append(okay); okay.fadeIn(400, ()=>{ setTimeout(()=>{ $("#donation-popup, #donation-popup-overlay").fadeOut(300, () => { $("#donation-popup, #donation-popup-overlay").remove(); resolve(); }); }, 1e3); }); }); const now = Date.now(); if(!test){ data.lastShown = now; ++data.counter; GM_setValue("donationPopupShown", data); } let nextDonateTime = $("#nextDonateTime"); nextDonateTime.text(new Date(now + freq).toLocaleString()); }); } function detectLanguage(){ const useBrowserLanguage = false; const defaultLanguage = "en"; if(useBrowserLanguage){ const rawLang = (document.documentElement.lang || navigator.language || defaultLanguage).toLowerCase(); return supportedLocales[rawLang] || supportedLocales[rawLang.split("-")[0]] || defaultLanguage; } // detect game language let language; let searchButton = $(selectors.searchButton); if(searchButton != null){ const text = searchButton.text().trim().toLowerCase(); switch(text){ case "ara": language = "tr"; break; case "search": language = "en"; break; case "procurar": language = "pt"; break; case "busca": language = "pt-br"; break; case "buscar": language = "es"; break; case "cerca": language = "it"; break; default: language = defaultLanguage; } // console.log(`${text} --> ${language}`); } return language || defaultLanguage; } function sleep(ms=1e3){ return new Promise(res=> setTimeout(()=>res(), ms)); } function loadScript(src, callback) { const s = document.createElement("script"); s.src = src; s.onload = callback; document.head.appendChild(s); }