您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Ограничь свое время на DTF. Userscript version. Автор: Dude
// ==UserScript== // @name antiDTF (Userscript) // @namespace http://tampermonkey.net/ // @version 1.1 // @description Ограничь свое время на DTF. Userscript version. Автор: Dude // @author Dude (converted) // @match *://dtf.ru/* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_registerMenuCommand // @run-at document-idle // @license MIT // ==/UserScript== (async function() { 'use strict'; // --- Configuration Keys --- const KEY_DAILY_LIMIT = 'antiDTF_dailyLimit'; const KEY_START_TIMESTAMP = 'antiDTF_startTimestamp'; const KEY_LAST_RESET = 'antiDTF_lastReset'; // --- Helper Functions for Storage --- async function getConfig(key, defaultValue = null) { return await GM_getValue(key, defaultValue); } async function setConfig(key, value) { await GM_setValue(key, value); } // --- Blocked Page Styling and Content --- const blockedStyles = ` body { background: #ff00ff !important; color: #ffff00 !important; font-family: 'Comic Sans MS', cursive, sans-serif !important; text-align: center !important; font-size: 32px !important; margin: 0 !important; padding: 0 !important; height: 100vh !important; display: flex !important; align-items: center !important; justify-content: center !important; overflow: hidden !important; } /* Hide everything else just in case */ body > *:not(#antiDTF-blocked-message) { display: none !important; } `; const blockedHTML = `<div id="antiDTF-blocked-message">Лимит DTF на сегодня исчерпан. Пиздуй работать.</div>`; // --- Core Time Limit Check Logic --- async function checkTimeLimit() { const dailyLimit = await getConfig(KEY_DAILY_LIMIT); let startTimestamp = await getConfig(KEY_START_TIMESTAMP); let lastReset = await getConfig(KEY_LAST_RESET); // If limit is not set or invalid, do nothing if (dailyLimit === null || isNaN(dailyLimit) || dailyLimit <= 0) { console.log("antiDTF: Limit not set or invalid."); return false; // Not blocked } const limitMinutes = parseInt(dailyLimit, 10); const nowDate = new Date().toDateString(); // Check if it's a new day if (lastReset !== nowDate) { console.log("antiDTF: New day detected. Resetting timer."); startTimestamp = Date.now(); await setConfig(KEY_LAST_RESET, nowDate); await setConfig(KEY_START_TIMESTAMP, startTimestamp); console.log(`antiDTF: Timer reset. Limit: ${limitMinutes} minutes.`); return false; // Not blocked yet today } // Check if startTimestamp is valid (necessary after first setting the limit) if (!startTimestamp) { console.log("antiDTF: Start timestamp missing for today. Initializing."); startTimestamp = Date.now(); await setConfig(KEY_START_TIMESTAMP, startTimestamp); return false; // Not blocked yet } // Calculate elapsed time const elapsedMs = Date.now() - startTimestamp; const elapsedMinutes = Math.floor(elapsedMs / 60000); console.log(`antiDTF: Time check - Elapsed: ${elapsedMinutes} min / Limit: ${limitMinutes} min`); // Check if limit is exceeded if (elapsedMinutes >= limitMinutes) { console.log("antiDTF: Daily limit exceeded. Blocking page."); blockPage(); return true; // Blocked } return false; // Not blocked } // --- Function to Block the Page --- function blockPage() { // Stop further loading/scripts if possible try { window.stop(); } catch (e) { console.warn("antiDTF: Could not stop window loading.", e); } // Apply styles first GM_addStyle(blockedStyles); // Replace body content document.body.innerHTML = blockedHTML; // Set title document.title = "antiDTF - Лимит исчерпан"; } // --- Settings via Menu Commands (Replaces Popup) --- // 1. Set/Change Limit GM_registerMenuCommand("antiDTF: Установить/Изменить лимит", async () => { const currentLimit = await getConfig(KEY_DAILY_LIMIT, ''); const newLimitStr = prompt(`Введите дневной лимит времени на DTF в минутах.\n(Текущий: ${currentLimit || 'не установлен'})\nВведите 0 или оставьте пустым для снятия лимита.`, currentLimit); if (newLimitStr === null) return; // User cancelled const newLimit = parseInt(newLimitStr.trim(), 10); if (!isNaN(newLimit) && newLimit > 0) { await setConfig(KEY_DAILY_LIMIT, newLimit); // Reset timer immediately when limit is set/changed const today = new Date().toDateString(); await setConfig(KEY_LAST_RESET, today); await setConfig(KEY_START_TIMESTAMP, Date.now()); alert(`antiDTF: Лимит установлен на ${newLimit} минут в день.\nТаймер сброшен на сегодня.`); // Reload to apply immediately (especially important if currently blocked) location.reload(); } else if (newLimitStr.trim() === '' || newLimit === 0) { await setConfig(KEY_DAILY_LIMIT, null); // Use null to indicate no limit await setConfig(KEY_START_TIMESTAMP, null); await setConfig(KEY_LAST_RESET, ''); alert("antiDTF: Лимит снят."); // Reload to unblock if currently blocked location.reload(); } else { alert("antiDTF: Ошибка. Введите положительное число минут или 0 для снятия лимита."); } }); // 2. Extend Limit ("Продлить как лох") GM_registerMenuCommand("antiDTF: Продлить как лох", async () => { const currentLimit = await getConfig(KEY_DAILY_LIMIT); if (currentLimit === null) { alert("antiDTF: Сначала установите основной лимит."); return; } const addMinutesStr = prompt(`На сколько минут продлить сегодняшний лимит? (Текущий: ${currentLimit} минут)`); if (addMinutesStr === null) return; // User cancelled const addMinutes = parseInt(addMinutesStr.trim(), 10); if (!isNaN(addMinutes) && addMinutes > 0) { const newLimit = (parseInt(currentLimit, 10) || 0) + addMinutes; await setConfig(KEY_DAILY_LIMIT, newLimit); alert(`antiDTF: Лимит продлен на ${addMinutes} минут.\nНовый лимит на сегодня: ${newLimit} минут.\nСтраница будет перезагружена.`); // Don't reset startTimestamp here, just increase the ceiling for today location.reload(); // Reload to potentially unblock or continue browsing } else { alert("antiDTF: Ошибка. Введите положительное число минут."); } }); // 3. Check Status GM_registerMenuCommand("antiDTF: Проверить статус", async () => { const dailyLimit = await getConfig(KEY_DAILY_LIMIT); let startTimestamp = await getConfig(KEY_START_TIMESTAMP); let lastReset = await getConfig(KEY_LAST_RESET); if (dailyLimit === null) { alert("antiDTF: Лимит времени не установлен."); return; } const limitMinutes = parseInt(dailyLimit, 10); const nowDate = new Date().toDateString(); if (lastReset !== nowDate || !startTimestamp) { // Handles both new day and cases where start timestamp wasn't set yet alert(`antiDTF:\nЛимит: ${limitMinutes} минут в день.\nТаймер на сегодня еще не запущен (начнет отсчет при следующем взаимодействии с сайтом).`); return; } const elapsedMs = Date.now() - startTimestamp; const elapsedMinutes = Math.floor(elapsedMs / 60000); const remainingMinutes = Math.max(0, limitMinutes - elapsedMinutes); const remainingSecondsTotal = Math.max(0, (limitMinutes * 60) - Math.floor(elapsedMs / 1000)); const remainingSecs = remainingSecondsTotal % 60; const remainingMins = Math.floor(remainingSecondsTotal / 60); alert(`antiDTF Статус:\nЛимит: ${limitMinutes} минут.\nИспользовано сегодня: ${elapsedMinutes} минут.\nОсталось: ${remainingMins} мин ${remainingSecs < 10 ? '0' : ''}${remainingSecs} сек.`); }); // --- Initial Execution --- console.log("antiDTF Userscript running on:", window.location.href); // Run the check when the script loads await checkTimeLimit(); // Note: The script runs on 'document-idle', so the page content might already be visible // for a moment before being blocked if the limit is exceeded. The check runs on every // matching page load/navigation. })();