// ==UserScript== // @name 【Sorry,Discord!】 DC Orbs Quests Video Skip Button (Beta) // @name:zh-TW 【對不起,Discord!】 DC Orbs 任務影片跳過按鈕 (Beta) // @name:zh-CN 【对不起,Discord!】 DC Orbs 任务视频跳过按钮 (Beta) // @name:ja 【すみません,Discord!】 DC Orbs クエスト動画スキップボタン (Beta) // @name:ko 【죄송합니다,Discord!】 DC Orbs 퀘스트 동영상 건너뛰기 버튼 (Beta) // @namespace https://github.com/NiktoBlox/Tampermonkey-Scripts/tree/60ae32ddf7b8d2e6cfdae065bf1ce5f702550180/%F0%9F%9F%A2%E2%94%82Deploy%20Scripts/Discord%20Orbs%20Quests%20Video%20Skip%20Button // @version 1.51-Beta // @description 🔒 99% Safe & Account Ban-Free Script — Floating draggable skip button for Discord Orbs Quests Videos // @description:zh-TW 🔒 99% 安全且不會封禁帳號的腳本 — 可拖曳的懸浮按鈕,用於跳過 Discord Orbs 任務影片 // @description:zh-CN 🔒 99% 安全且不会封禁账号的脚本 — 可拖拽的悬浮按钮,用于跳过 Discord Orbs 任务视频 // @description:ja 🔒 99% 安全・アカウントBANリスクなしスクリプト — Discord Orbs クエスト動画をスキップするためのドラッグ可能なフローティングボタン // @description:ko 🔒 99% 안전 & 계정 차단 없는 스크립트 — Discord Orbs 퀘스트 동영상을 건너뛰기 위한 드래그 가능한 플로팅 버튼 // @author NiktoBlox // @license MIT // @match https://discord.com/quest-home // @match https://discord.com/quests/* // @match https://discord.com/channels/* // @match https://discord.com/* // @icon https://files.catbox.moe/kdzneo.png // @grant GM_getValue // @grant GM_setValue // @downloadURL https://update.greasyfork.icu/scripts/574006/%E3%80%90Sorry%2CDiscord%21%E3%80%91%20DC%20Orbs%20Quests%20Video%20Skip%20Button%20%28Beta%29.user.js // @updateURL https://update.greasyfork.icu/scripts/574006/%E3%80%90Sorry%2CDiscord%21%E3%80%91%20DC%20Orbs%20Quests%20Video%20Skip%20Button%20%28Beta%29.meta.js // ==/UserScript== (function () { 'use strict'; // ── 多國語系 ── const I18N = { en: { skip: '⏭️ Skip', skipped: '✅ Skipped!', notFound: '❌ Not Found', settings: '⚙️ Settings', theme: '🎨 Theme', customColor: '🖌️ Custom Color', btnColor: 'Button', textColor: 'Text', borderRadius: '⬜ Border Radius', opacity: '👁️ Opacity', autoHide: '🔁 Auto-hide', autoHideDesc: 'Fade button when inactive', language: '🌐 Language', about: 'ℹ️ About', version: 'Version', author: 'Author', license: 'License', github: 'GitHub ↗', autoSkip: '🤖 Auto Skip', autoSkipDesc: 'Auto skip when video detected', autoSkipDelay: '⏱️ Auto Skip Delay', seconds: 's', notifyDuration: '🔔 Notify Duration', btnSize: '📐 Button Size', small: 'S', medium: 'M', large: 'L', btnPosition: '📌 Quick Position', customText: '✏️ Custom Button Text', resetAll: '🔄 Reset All Settings', resetConfirm: 'Reset all settings?', exportSettings: '📤 Export', importSettings: '📥 Import', importSuccess: '✅ Imported!', importFail: '❌ Import Failed', guiTheme: '🖥️ Panel Theme', guiLight: 'Light', guiDark: 'Dark', guiBlack: 'Pure Black', corners: ['↖ Top Left', '↗ Top Right', '↙ Bottom Left', '↘ Bottom Right'], dragDelay: '🖱️ Long-press Drag Delay', ms: 'ms', tabPanel: 'Panel', tabBtn: 'Button Style', tabOther: 'Other', aboutSection: 'ℹ️ About', aboutAuthor: '👨💻 Author', aboutVersion: '🏷️ Version', aboutBug: '🐛 Report a Bug', aboutBugLink: 'Click here to report →', aboutLang: '🌐 Add a Language', aboutLangLink: 'Request a new language →', }, 'zh-TW': { skip: '⏭️ 跳過', skipped: '✅ 已跳過!', notFound: '❌ 找不到', settings: '⚙️ 設定', theme: '🎨 主題', customColor: '🖌️ 自訂顏色', btnColor: '按鈕', textColor: '文字', borderRadius: '⬜ 圓角大小', opacity: '👁️ 透明度', autoHide: '🔁 自動隱藏', autoHideDesc: '閒置時淡化按鈕', language: '🌐 語言', about: 'ℹ️ 關於', version: '版本', author: '作者', license: '授權', github: 'GitHub ↗', autoSkip: '🤖 自動跳過', autoSkipDesc: '偵測到影片時自動跳過', autoSkipDelay: '⏱️ 自動跳過延遲', seconds: '秒', notifyDuration: '🔔 通知顯示時間', btnSize: '📐 按鈕大小', small: '小', medium: '中', large: '大', btnPosition: '📌 快速定位', customText: '✏️ 自訂按鈕文字', resetAll: '🔄 重設所有設定', resetConfirm: '確定重設所有設定?', exportSettings: '📤 匯出', importSettings: '📥 匯入', importSuccess: '✅ 匯入成功!', importFail: '❌ 匯入失敗', guiTheme: '🖥️ 面板主題', guiLight: '淺色', guiDark: '深色', guiBlack: '極黑', corners: ['↖ 左上', '↗ 右上', '↙ 左下', '↘ 右下'], dragDelay: '🖱️ 長按拖曳延遲', ms: '毫秒', tabPanel: '面板外觀', tabBtn: '按鈕外觀', tabOther: '其他', aboutSection: 'ℹ️ 關於', aboutAuthor: '👨💻 製作者', aboutVersion: '🏷️ 版本', aboutBug: '🐛 回報 Bug', aboutBugLink: '點此回報問題 →', aboutLang: '🌐 新增語言', aboutLangLink: '申請新增語言 →', }, 'zh-CN': { skip: '⏭️ 跳过', skipped: '✅ 已跳过!', notFound: '❌ 未找到', settings: '⚙️ 设置', theme: '🎨 主题', customColor: '🖌️ 自定义颜色', btnColor: '按钮', textColor: '文字', borderRadius: '⬜ 圆角大小', opacity: '👁️ 透明度', autoHide: '🔁 自动隐藏', autoHideDesc: '闲置时淡化按钮', language: '🌐 语言', about: 'ℹ️ 关于', version: '版本', author: '作者', license: '许可证', github: 'GitHub ↗', autoSkip: '🤖 自动跳过', autoSkipDesc: '检测到视频时自动跳过', autoSkipDelay: '⏱️ 自动跳过延迟', seconds: '秒', notifyDuration: '🔔 通知显示时间', btnSize: '📐 按钮大小', small: '小', medium: '中', large: '大', btnPosition: '📌 快速定位', customText: '✏️ 自定义按钮文字', resetAll: '🔄 重置所有设置', resetConfirm: '确定重置所有设置?', exportSettings: '📤 导出', importSettings: '📥 导入', importSuccess: '✅ 导入成功!', importFail: '❌ 导入失败', guiTheme: '🖥️ 面板主题', guiLight: '浅色', guiDark: '深色', guiBlack: '极黑', corners: ['↖ 左上', '↗ 右上', '↙ 左下', '↘ 右下'], dragDelay: '🖱️ 长按拖拽延迟', ms: '毫秒', tabPanel: '面板外观', tabBtn: '按钮外观', tabOther: '其他', aboutSection: 'ℹ️ 关于', aboutAuthor: '👨💻 制作者', aboutVersion: '🏷️ 版本', aboutBug: '🐛 反馈 Bug', aboutBugLink: '点此反馈问题 →', aboutLang: '🌐 新增语言', aboutLangLink: '申请新增语言 →', }, ja: { skip: '⏭️ スキップ', skipped: '✅ スキップ完了!', notFound: '❌ 見つかりません', settings: '⚙️ 設定', theme: '🎨 テーマ', customColor: '🖌️ カスタムカラー', btnColor: 'ボタン', textColor: 'テキスト', borderRadius: '⬜ 角丸サイズ', opacity: '👁️ 透明度', autoHide: '🔁 自動非表示', autoHideDesc: '非アクティブ時にフェード', language: '🌐 言語', about: 'ℹ️ このスクリプトについて', version: 'バージョン', author: '作者', license: 'ライセンス', github: 'GitHub ↗', autoSkip: '🤖 自動スキップ', autoSkipDesc: '動画検出時に自動スキップ', autoSkipDelay: '⏱️ 自動スキップ遅延', seconds: '秒', notifyDuration: '🔔 通知表示時間', btnSize: '📐 ボタンサイズ', small: '小', medium: '中', large: '大', btnPosition: '📌 クイック配置', customText: '✏️ カスタムボタンテキスト', resetAll: '🔄 設定をリセット', resetConfirm: '全ての設定をリセットしますか?', exportSettings: '📤 エクスポート', importSettings: '📥 インポート', importSuccess: '✅ インポート完了!', importFail: '❌ インポート失敗', guiTheme: '🖥️ パネルテーマ', guiLight: 'ライト', guiDark: 'ダーク', guiBlack: '漆黒', corners: ['↖ 左上', '↗ 右上', '↙ 左下', '↘ 右下'], dragDelay: '🖱️ 長押しドラッグ遅延', ms: 'ms', tabPanel: 'パネル外観', tabBtn: 'ボタン外観', tabOther: 'その他', aboutSection: 'ℹ️ このスクリプトについて', aboutAuthor: '👨💻 作者', aboutVersion: '🏷️ バージョン', aboutBug: '🐛 バグを報告', aboutBugLink: 'こちらから報告 →', aboutLang: '🌐 言語を追加', aboutLangLink: '新しい言語をリクエスト →', }, ko: { skip: '⏭️ 건너뛰기', skipped: '✅ 건너뛰기 완료!', notFound: '❌ 찾을 수 없음', 设置: '⚙️ 설정', theme: '🎨 테마', customColor: '🖌️ 커스텀 색상', btnColor: '버튼', textColor: '텍스트', borderRadius: '⬜ 테두리 반경', opacity: '👁️ 투명도', autoHide: '🔁 자동 숨김', autoHideDesc: '비활성 시 페이드 처리', language: '🌐 언어', about: 'ℹ️ 정보', version: '버전', author: '작성자', license: '라이선스', github: 'GitHub ↗', autoSkip: '🤖 자동 건너뛰기', autoSkipDesc: '영상 감지 시 자동 건너뛰기', autoSkipDelay: '⏱️ 자동 건너뛰기 지연', seconds: '초', notifyDuration: '🔔 알림 표시 시간', btnSize: '📐 버튼 크기', small: '소', medium: '중', large: '대', btnPosition: '📌 빠른 위치', customText: '✏️ 버튼 텍스트 커스텀', resetAll: '🔄 모든 설정 초기화', resetConfirm: '모든 설정을 초기화할까요?', exportSettings: '📤 내보내기', importSettings: '📥 가져오기', importSuccess: '✅ 가져오기 완료!', importFail: '❌ 가져오기 실패', guiTheme: '🖥️ 패널 테마', guiLight: '라이트', guiDark: '다크', guiBlack: '순수 블랙', corners: ['↖ 왼쪽 위', '↗ 오른쪽 위', '↙ 왼쪽 아래', '↘ 오른쪽 아래'], dragDelay: '🖱️ 길게 누르기 지연', ms: 'ms', tabPanel: '패널 외관', tabBtn: '버튼 스타일', tabOther: '기타', aboutSection: 'ℹ️ 정보', aboutAuthor: '👨💻 제작자', aboutVersion: '🏷️ 버전', aboutBug: '🐛 버그 신고', aboutBugLink: '여기서 신고하기 →', aboutLang: '🌐 언어 추가', aboutLangLink: '새 언어 요청하기 →', }, }; const LANG_NAMES = { en: 'English', 'zh-TW': '繁體中文', 'zh-CN': '简体中文', ja: '日本語', ko: '한국어' }; const detectLang = () => { const nav = (navigator.languages?.[0] || navigator.language || 'en').toLowerCase(); if (nav.startsWith('zh-tw') || nav.startsWith('zh-hk')) return 'zh-TW'; if (nav.startsWith('zh')) return 'zh-CN'; if (nav.startsWith('ja')) return 'ja'; if (nav.startsWith('ko')) return 'ko'; return 'en'; }; const DEFAULTS = { theme: 'discord', btnColor: '#5865F2', btnTextColor: '#ffffff', btnRadius: '20', btnOpacity: '100', autoHide: false, lang: 'en', autoSkip: false, autoSkipDelay: '3', notifyDuration: '2', btnSize: 'M', customText: '', dragDelay: '200', guiTheme: 'dark', }; const load = (key) => { try { return GM_getValue(key, DEFAULTS[key]); } catch { return DEFAULTS[key]; } }; const save = (key, val) => { try { GM_setValue(key, val); } catch {} }; let cfg = Object.fromEntries(Object.keys(DEFAULTS).map(k => [k, load(k)])); const t = () => I18N[cfg.lang] || I18N.en; const THEMES = { discord: { bg: '#5865F2', text: '#ffffff' }, dark: { bg: '#1e1e1e', text: '#ffffff' }, light: { bg: '#e0e0e0', text: '#000000' }, green: { bg: '#43a047', text: '#ffffff' }, red: { bg: '#e53935', text: '#ffffff' }, purple: { bg: '#8e24aa', text: '#ffffff' }, }; const BTN_SIZES = { S: '8px 14px', M: '10px 20px', L: '14px 28px' }; const BTN_FONT = { S: '12px', M: '14px', L: '16px' }; // ── 面板主題定義 ── const PANEL_THEMES = { light: { panel: '#f2f3f5', header: '#e3e5e8', text: '#060607', subtext: '#747f8d', input: '#e3e5e8', inputText: '#060607', border: '#d4d7dc', divider: '#d4d7dc', accent: '#5865F2', btnBg: '#e3e5e8', btnText: '#060607', btnActiveText: '#ffffff', resetBg: '#fde8e8', resetText: '#d32f2f', }, dark: { panel: '#2b2d31', header: '#1e1f22', text: '#dbdee1', subtext: '#80848e', input: '#1e1f22', inputText: '#dbdee1', border: '#1e1f22', divider: '#3f4147', accent: '#ebebeb', btnBg: '#1e1f22', btnText: '#b0b3b8', btnActiveText: '#111111', resetBg: '#3a1e1e', resetText: '#e53935', }, black: { panel: '#0d0d0d', header: '#000000', text: '#e0e0e0', subtext: '#666666', input: '#1a1a1a', inputText: '#e0e0e0', border: '#000000', divider: '#222222', accent: '#ffffff', btnBg: '#1a1a1a', btnText: '#cccccc', btnActiveText: '#000000', resetBg: '#2a0a0a', resetText: '#ff5252', }, }; const pt = () => PANEL_THEMES[cfg.guiTheme] || PANEL_THEMES.dark; // ── 主按鈕 【修復】── const btn = document.createElement('button'); const getBtnText = () => cfg.customText.trim() || t().skip; btn.innerText = getBtnText(); btn.id = 'sq-skip-btn'; const applyBtn = () => { btn.style.cssText = ` position: fixed !important; bottom: 30px !important; right: 30px !important; z-index: 9999999 !important; background: ${cfg.btnColor} !important; color: ${cfg.btnTextColor} !important; border: none !important; border-radius: ${cfg.btnRadius}px !important; padding: ${BTN_SIZES[cfg.btnSize] || BTN_SIZES.M} !important; font-size: ${BTN_FONT[cfg.btnSize] || BTN_FONT.M} !important; font-weight: bold !important; cursor: grab !important; box-shadow: 0 4px 12px rgba(0,0,0,0.3) !important; user-select: none !important; transition: background 0.2s, opacity 0.2s !important; opacity: ${cfg.autoHide ? '0.2' : Number(cfg.btnOpacity) / 100} !important; visibility: visible !important; display: block !important; pointer-events: auto !important; `; }; applyBtn(); // ── 跳過核心 ── const doSkip = () => { const i = t(); let found = false; document.querySelectorAll('video').forEach(el => { el.currentTime = el.duration; found = true; }); ['[class*="skip"]', '[class*="close"]', '[class*="dismiss"]'].forEach(sel => { document.querySelectorAll(sel).forEach(el => { if (el.offsetParent !== null) { el.click(); found = true; } }); }); btn.innerText = found ? i.skipped : i.notFound; setTimeout(() => { btn.innerText = getBtnText(); }, Number(cfg.notifyDuration) * 1000); }; // ── 自動跳過 ── let autoSkipTimer = null; const setupAutoSkip = () => { if (autoSkipTimer) clearInterval(autoSkipTimer); if (!cfg.autoSkip) return; autoSkipTimer = setInterval(() => { const videos = document.querySelectorAll('video'); videos.forEach(v => { if (!v.paused && !v.ended && v.duration && v.currentTime < v.duration) { setTimeout(() => { v.currentTime = v.duration; }, Number(cfg.autoSkipDelay) * 1000); } }); }, 2000); }; setupAutoSkip(); // ── 設定面板 ── const panel = document.createElement('div'); const applyPanelTheme = () => { const p = pt(); const wasVisible = panel.style.display === 'block'; const savedLeft = panel.style.left; const savedTop = panel.style.top; panel.style.cssText = ` display:${wasVisible ? 'block' : 'none'} !important; position:fixed !important; z-index:9999999 !important; width:310px !important; background:${p.panel} !important; color:${p.text} !important; border-radius:12px !important; box-shadow:0 8px 32px rgba(0,0,0,0.6) !important; font-family:'gg sans',sans-serif !important; font-size:14px !important; overflow:hidden !important; border:1px solid ${p.border} !important; max-height:85vh !important; overflow-y:auto !important; `; if (savedLeft) panel.style.left = savedLeft; if (savedTop) panel.style.top = savedTop; }; applyPanelTheme(); const row = (label, content) => `