您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Добавляет секунды + обновление времени в реальном времени (нагрузка на усройстве).
// ==UserScript== // @name Lolz.live Dynamic Time // @namespace http://tampermonkey.net/ // @version 3.0 // @description Добавляет секунды + обновление времени в реальном времени (нагрузка на усройстве). // @match https://lolz.live/* // @match https://lzt.market/* // @grant none // ==/UserScript== (function () { 'use strict'; const activeElements = new WeakMap(); let updateTimer = null; function pluralize(number, one, few, many) { number = Math.abs(number); if (number % 100 >= 11 && number % 100 <= 19) return many; switch (number % 10) { case 1: return one; case 2: case 3: case 4: return few; default: return many; } } function getSafeDiff(timestamp) { return Math.max(0, Math.floor(Date.now() / 1000) - timestamp); } function formatRelativeTime(diff) { diff = Math.max(0, diff); if (diff < 60) { return `${diff} ${pluralize(diff, 'секунду', 'секунды', 'секунд')} назад`; } else if (diff < 120) { return 'Минуту назад'; } else if (diff < 3600) { const mins = Math.floor(diff / 60); return `${mins} мин. назад`; } return null; } function formatAbsoluteTime(el) { const timeStr = el.getAttribute('data-timestring'); if (!timeStr) return null; return `Сегодня, в ${timeStr}`; } function addSecondsToDateTime() { document.querySelectorAll('abbr.DateTime[data-time]').forEach(el => { const timestamp = parseInt(el.getAttribute('data-time')); if (!timestamp) return; const diff = getSafeDiff(timestamp); const sixDays = 7 * 24 * 60 * 60; // 7 дней в секундах if (diff >= 3600 && diff <= sixDays) { const timeStr = el.getAttribute('data-timestring'); if (!timeStr) return; if (timeStr.match(/^\d{1,2}:\d{2}:\d{2}$/)) return; const date = new Date(timestamp * 1000); const hours = date.getHours(); const minutes = date.getMinutes().toString().padStart(2, '0'); const seconds = date.getSeconds().toString().padStart(2, '0'); const timeWithSeconds = `${hours}:${minutes}:${seconds}`; const currentText = el.textContent; const newText = currentText.replace(/\d{1,2}:\d{2}$/, timeWithSeconds); el.textContent = newText; const title = el.getAttribute('title'); if (title) { const newTitle = title.replace(/\d{1,2}:\d{2}$/, timeWithSeconds); el.setAttribute('title', newTitle); } el.setAttribute('data-timestring', timeWithSeconds); } }); } function updateTimes() { let needsUpdate = false; document.querySelectorAll('abbr.DateTime[data-time]').forEach(el => { if (!activeElements.has(el)) return; const timestamp = parseInt(el.getAttribute('data-time')); const diff = getSafeDiff(timestamp); if (diff < 3600) { const newText = formatRelativeTime(diff); if (newText && el.textContent !== newText) { el.textContent = newText; } needsUpdate = true; } else if (diff >= 3600) { const absText = formatAbsoluteTime(el); if (absText) { el.textContent = absText; } activeElements.delete(el); } }); if (needsUpdate && !updateTimer) { updateTimer = setTimeout(() => { updateTimer = null; updateTimes(); }, 1000); } else if (!needsUpdate && updateTimer) { clearTimeout(updateTimer); updateTimer = null; } } function processNewElement(el) { const currentText = el.textContent; if (/сегодня|вчера|\d{1,2} \w+ \d{4}/i.test(currentText)) return false; const timestamp = parseInt(el.getAttribute('data-time')); const diff = getSafeDiff(timestamp); if (diff < 3600) { el.setAttribute('data-original-text', currentText); const newText = formatRelativeTime(diff); if (newText) el.textContent = newText; activeElements.set(el, true); return true; } return false; } function addSecondsToConversations() { if (window.location.pathname.includes('/conversations/')) { document.querySelectorAll('span.messageDate[data-absolutetime]').forEach(el => { const timestamp = parseInt(el.getAttribute('data-absolutetime')); if (!timestamp) return; if (el.textContent.match(/^\d{2}:\d{2}:\d{2}$/)) return; const date = new Date(timestamp * 1000); const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); const seconds = date.getSeconds().toString().padStart(2, '0'); el.textContent = `${hours}:${minutes}:${seconds}`; }); } document.querySelectorAll('div.conversationItem--messageDate[data-absolutetime]').forEach(el => { const timestamp = parseInt(el.getAttribute('data-absolutetime')); if (!timestamp) return; const messageDate = new Date(timestamp * 1000); const today = new Date(); if (messageDate.toDateString() === today.toDateString()) { const currentText = el.textContent.trim(); if (currentText.match(/^\d{2}:\d{2}:\d{2}$/)) return; const hours = messageDate.getHours().toString().padStart(2, '0'); const minutes = messageDate.getMinutes().toString().padStart(2, '0'); const seconds = messageDate.getSeconds().toString().padStart(2, '0'); el.textContent = ` ${hours}:${minutes}:${seconds} `; } }); } const observer = new MutationObserver(mutations => { let shouldUpdate = false; mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { const timeNodes = node.matches('abbr.DateTime[data-time]') ? [node] : Array.from(node.querySelectorAll('abbr.DateTime[data-time]')); timeNodes.forEach(el => { if (processNewElement(el)) { shouldUpdate = true; } }); setTimeout(addSecondsToConversations, 10); setTimeout(addSecondsToDateTime, 10); } }); }); if (shouldUpdate) { setTimeout(updateTimes, 50); } }); function init() { let needsUpdate = false; document.querySelectorAll('abbr.DateTime[data-time]').forEach(el => { if (processNewElement(el)) { needsUpdate = true; } }); if (needsUpdate) { updateTimes(); } addSecondsToConversations(); addSecondsToDateTime(); observer.observe(document.body, { childList: true, subtree: true }); ['click', 'scroll', 'mousemove'].forEach(event => { document.addEventListener(event, () => { setTimeout(updateTimes, 100); setTimeout(addSecondsToConversations, 10); setTimeout(addSecondsToDateTime, 10); }, { passive: true }); }); } if (document.readyState === 'complete') { init(); } else { window.addEventListener('load', init); } window.addEventListener('unload', () => { observer.disconnect(); if (updateTimer) clearTimeout(updateTimer); }); })();