// ==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
// ==/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();
}
})();