// ==UserScript== // @name X Copy Tweet Link Helper with Toggle Settings // @name:zh-TW X 複製推文連結助手,附功能開關與語言切換 // @namespace http://tampermonkey.net/ // @version 1.1 // @description Copy tweet link via right-click, like, or button, with optional fixvx and language support. Includes toggle settings in Tampermonkey UI. // @description:zh-TW 透過右鍵、喜歡或按鈕複製推文鏈接,並可選擇 fixvx 和語言支援。包括 Tampermonkey UI 中的切換設定。 // @author ChatGPT // @match https://x.com/* // @match https://twitter.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; // === 使用者可切換的功能開關 === const defaultSettings = { rightClickCopy: true, // 右鍵複製 likeCopy: true, // 喜歡時自動褯複製 showCopyButton: true, // 顯示複製按鈕 useFixvx: false, // fixvx 前綴 language: 'EN' // ZH 或 EN }; const settings = { get(key) { return GM_getValue(key, defaultSettings[key]); }, set(key, value) { GM_setValue(key, value); } }; // === 多語系字典 === const lang = { EN: { copySuccess: "Link copied!", copyButton: "🔗", rightClickCopy: 'Right-click Copy', likeCopy: 'Like Copy', showCopyButton: 'Show Copy Button', useFixvx: 'Use Fixvx', language: 'Language' }, ZH: { copySuccess: "已複製鏈結!", copyButton: "🔗", rightClickCopy: '右鍵複製', likeCopy: '喜歡時複製', showCopyButton: '顯示複製按鈕', useFixvx: '使用 Fixvx', language: '語言' } }; const getText = (key) => lang[settings.get('language')][key]; // === 複製推文鏈結 === function copyTweetLink(tweet) { const anchor = tweet.querySelector('a[href*="/status/"]'); if (!anchor) return; let url = new URL(anchor.href); url.search = ''; // 移除 ?s=20 等參數 if (settings.get('useFixvx')) { url.hostname = 'fixvx.com'; } navigator.clipboard.writeText(url.toString()).then(() => { showToast(getText('copySuccess')); }); } // === 顯示提示訊息 === function showToast(msg) { const toast = document.createElement('div'); toast.innerText = msg; Object.assign(toast.style, { position: 'fixed', bottom: '20px', left: '50%', transform: 'translateX(-50%)', background: '#1da1f2', color: '#fff', padding: '8px 16px', borderRadius: '20px', zIndex: 9999, fontSize: '14px' }); document.body.appendChild(toast); setTimeout(() => toast.remove(), 1500); } // === 插入複製按鈕 === function insertCopyButton(tweet) { if (tweet.querySelector('.my-copy-btn')) return; const actionBar = tweet.querySelector('[role="group"]'); if (!actionBar) return; const btn = document.createElement('div'); btn.className = 'my-copy-btn'; btn.innerText = getText('copyButton'); Object.assign(btn.style, { fontSize: '18px', cursor: 'pointer', marginLeft: '12px', userSelect: 'none' }); btn.onclick = (e) => { e.stopPropagation(); copyTweetLink(tweet); }; actionBar.appendChild(btn); } // === 監聽推文動態載入 === const tweetObserver = new MutationObserver(() => { document.querySelectorAll('article').forEach(tweet => { if (settings.get('showCopyButton')) insertCopyButton(tweet); if (settings.get('rightClickCopy') && !tweet.hasAttribute('data-rightclick')) { tweet.setAttribute('data-rightclick', 'true'); tweet.addEventListener('contextmenu', (e) => { if (tweet.querySelector('img, video')) { copyTweetLink(tweet); } }); } if (settings.get('likeCopy') && !tweet.hasAttribute('data-likecopy')) { tweet.setAttribute('data-likecopy', 'true'); const likeBtn = tweet.querySelector('[data-testid="like"]'); if (likeBtn) { likeBtn.addEventListener('click', () => { copyTweetLink(tweet); }); } } }); }); tweetObserver.observe(document.body, { childList: true, subtree: true }); // === 在油猴菜單中創建設定選項 === function updateMenuCommands() { GM_unregisterMenuCommand(); GM_registerMenuCommand(`${getText('rightClickCopy')} ( ${settings.get('rightClickCopy') ? '✅' : '❌'} )`, toggleRightClickCopy); GM_registerMenuCommand(`${getText('likeCopy')} ( ${settings.get('likeCopy') ? '✅' : '❌'} )`, toggleLikeCopy); GM_registerMenuCommand(`${getText('showCopyButton')} ( ${settings.get('showCopyButton') ? '✅' : '❌'} )`, toggleShowCopyButton); GM_registerMenuCommand(`${getText('useFixvx')} ( ${settings.get('useFixvx') ? '✅' : '❌'} )`, toggleUseFixvx); GM_registerMenuCommand(`${getText('language')} ( ${settings.get('language') === 'EN' ? 'EN' : 'ZH'} )`, toggleLanguage); } updateMenuCommands(); function toggleRightClickCopy() { const currentValue = settings.get('rightClickCopy'); settings.set('rightClickCopy', !currentValue); reloadPage(); } function toggleLikeCopy() { const currentValue = settings.get('likeCopy'); settings.set('likeCopy', !currentValue); reloadPage(); } function toggleShowCopyButton() { const currentValue = settings.get('showCopyButton'); settings.set('showCopyButton', !currentValue); reloadPage(); } function toggleUseFixvx() { const currentValue = settings.get('useFixvx'); settings.set('useFixvx', !currentValue); reloadPage(); } function toggleLanguage() { const currentValue = settings.get('language'); const newLang = currentValue === 'EN' ? 'ZH' : 'EN'; settings.set('language', newLang); reloadPage(); } // 重新整理頁面 function reloadPage() { location.reload(); } })();