您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Copy tweet link via right-click, like, or button, with optional fixvx and language support. Includes toggle settings in Tampermonkey UI.
当前为
- // ==UserScript==
- // @name X Copy tweet link assistant, with function switch and language switch
- // @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();
- }
- })();