// ==UserScript== // @name Cat Gatekeeper - 胖猫强制休息器 // @namespace https://github.com/ // @version 1.1 // @description 连续浏览60分钟后,胖橘猫霸占屏幕强制休息5分钟(多语言版) // @author ssxaizyf // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @run-at document-start // @downloadURL https://update.greasyfork.icu/scripts/575738/Cat%20Gatekeeper%20-%20%E8%83%96%E7%8C%AB%E5%BC%BA%E5%88%B6%E4%BC%91%E6%81%AF%E5%99%A8.user.js // @updateURL https://update.greasyfork.icu/scripts/575738/Cat%20Gatekeeper%20-%20%E8%83%96%E7%8C%AB%E5%BC%BA%E5%88%B6%E4%BC%91%E6%81%AF%E5%99%A8.meta.js // ==/UserScript== (function() { 'use strict'; // ==================== 多语言支持 ==================== const i18n = { zh: { title: "🐱 Cat Gatekeeper - 胖猫强制休息器", workTimePrompt: "工作时间(分钟,默认60)", breakTimePrompt: "休息时间(分钟,默认5)", settingsUpdated: "已更新:", testCat: "🛑 立即测试猫咪", resetTimer: "🔄 重置计时器", consoleLoaded: "🐱 Cat Gatekeeper 已加载!连续刷够", restText: "休息时间 ", minutes: "分钟工作 + ", minutesRest: "分钟休息" }, en: { title: "🐱 Cat Gatekeeper", workTimePrompt: "Work time (minutes, default 60)", breakTimePrompt: "Break time (minutes, default 5)", settingsUpdated: "Updated: ", testCat: "🛑 Test Cat Now", resetTimer: "🔄 Reset Timer", consoleLoaded: "🐱 Cat Gatekeeper loaded! After ", restText: "Break time ", minutes: " min work + ", minutesRest: " min break" }, ja: { title: "🐱 Cat Gatekeeper - 猫強制休憩", workTimePrompt: "作業時間(分、デフォルト60)", breakTimePrompt: "休憩時間(分、デフォルト5)", settingsUpdated: "更新しました:", testCat: "🛑 今すぐ猫をテスト", resetTimer: "🔄 タイマーリセット", consoleLoaded: "🐱 Cat Gatekeeper 起動!", restText: "休憩時間 ", minutes: "分作業 + ", minutesRest: "分休憩" } }; // 自动检测语言(浏览器语言) function getLang() { const lang = navigator.language.toLowerCase(); if (lang.startsWith('zh')) return 'zh'; if (lang.startsWith('ja')) return 'ja'; return 'en'; // 默认英语 } const lang = getLang(); const t = i18n[lang]; // 默认设置(分钟) let WORK_TIME = GM_getValue('workTime', 60); let BREAK_TIME = GM_getValue('breakTime', 5); // 胖猫图片(推荐换成GIF更可爱) const CAT_IMG = 'https://i.imgur.com/0Z8Z8Z8.jpg'; // ← 这里换成你喜欢的猫图URL let startTime = Date.now(); let isBreaking = false; let breakEndTime = 0; let timerInterval = null; // 创建猫咪覆盖层 function createCatOverlay() { const overlay = document.createElement('div'); overlay.id = 'cat-gatekeeper-overlay'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.88); z-index: 2147483647; display: none; flex-direction: column; align-items: center; justify-content: center; color: white; font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; overflow: hidden; text-align: center; `; const cat = document.createElement('img'); cat.src = CAT_IMG; cat.style.cssText = ` max-width: 75%; max-height: 65%; border-radius: 24px; box-shadow: 0 0 60px rgba(255,140,0,0.9); animation: catBreath 3.5s infinite alternate ease-in-out; `; const timerText = document.createElement('div'); timerText.id = 'cat-timer'; timerText.style.cssText = 'margin-top: 24px; font-size: 2.8em; font-weight: bold; text-shadow: 0 2px 10px rgba(0,0,0,0.6);'; const tip = document.createElement('div'); tip.textContent = lang === 'ja' ? '少し休憩しましょう🐾' : lang === 'zh' ? '休息一下吧~🐾' : "Take a break~ 🐾"; tip.style.cssText = 'margin-top: 16px; font-size: 1.4em; opacity: 0.9;'; overlay.appendChild(cat); overlay.appendChild(timerText); overlay.appendChild(tip); document.body.appendChild(overlay); // 呼吸动画 const style = document.createElement('style'); style.textContent = ` @keyframes catBreath { from { transform: scale(1); } to { transform: scale(1.07); } } `; document.head.appendChild(style); return { overlay, timerText }; } const { overlay, timerText } = createCatOverlay(); // 更新倒计时 function updateTimer() { if (!isBreaking) return; const remaining = Math.ceil((breakEndTime - Date.now()) / 1000); if (remaining <= 0) { endBreak(); } else { const min = Math.floor(remaining / 60); const sec = remaining % 60; timerText.textContent = t.restText + `${min}:${sec < 10 ? '0' : ''}${sec}`; } } function startBreak() { isBreaking = true; breakEndTime = Date.now() + BREAK_TIME * 60 * 1000; overlay.style.display = 'flex'; document.body.style.overflow = 'hidden'; timerInterval = setInterval(updateTimer, 300); updateTimer(); } function endBreak() { isBreaking = false; clearInterval(timerInterval); overlay.style.display = 'none'; document.body.style.overflow = ''; startTime = Date.now(); } function checkTime() { if (isBreaking) return; const elapsed = (Date.now() - startTime) / (1000 * 60); if (elapsed >= WORK_TIME) { startBreak(); } } setInterval(checkTime, 10000); // 页面切换时暂停计时 document.addEventListener('visibilitychange', () => { if (!document.hidden && !isBreaking) { startTime = Date.now(); } }); // ==================== 设置菜单(多语言) ==================== GM_registerMenuCommand('⚙ ' + (lang === 'ja' ? '設定' : lang === 'zh' ? '设置休息时间' : 'Settings'), () => { const newWork = prompt(t.workTimePrompt, WORK_TIME); if (newWork !== null) { WORK_TIME = parseInt(newWork) || 60; GM_setValue('workTime', WORK_TIME); } const newBreak = prompt(t.breakTimePrompt, BREAK_TIME); if (newBreak !== null) { BREAK_TIME = parseInt(newBreak) || 5; GM_setValue('breakTime', BREAK_TIME); } alert(t.settingsUpdated + `${WORK_TIME}${t.minutes}${BREAK_TIME}${t.minutesRest}`); }); GM_registerMenuCommand(t.testCat, () => startBreak()); GM_registerMenuCommand(t.resetTimer, () => { startTime = Date.now(); alert(lang === 'ja' ? 'タイマーをリセットしました' : lang === 'zh' ? '计时器已重置' : 'Timer has been reset'); }); console.log(`%c${t.title} %c已加载!`, 'color:#ff8c00;font-size:16px;font-weight:bold', 'color:#666'); console.log(t.consoleLoaded + WORK_TIME + (lang === 'ja' ? '分で猫が来ます🐱' : ' minutes the cat will appear 🐱')); })();