Adds a "Copy" button to chat message elements to easily copy their content.
当前为
// ==UserScript==
// @name Add Copy Button to Chat Messages on 360's bot.n.cn
// @namespace http://tampermonkey.net/
// @version 0.0.1
// @description Adds a "Copy" button to chat message elements to easily copy their content.
// @author aspen138
// @match *://bot.n.cn/*
// @grant none
// @run-at document-end
// @icon https://p1.ssl.qhimg.com//t11098f6bcd26caa77d8aa4d2fb.png
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Update these if class names change
const MESSAGE_CONTENT_CLASS = 'UserMessage-module__container--cAvvK';
const CHAT_MESSAGE_CONTENT_CLASS = 'ChatMessage-module__content--MYneF';
const NEW_MESSAGE_SELECTOR = '.max-w-\\[80\\%\\].rounded-\\[16px\\].px-\\[16px\\].py-\\[10px\\].text-white.text-\\[15px\\].leading-\\[22px\\].whitespace-pre-line.break-all.overflow-x-hidden';
function createCopyButton() {
const button = document.createElement('button');
button.innerText = 'Copy';
button.classList.add('copy-button');
button.style.position = 'sticky';
button.style.top = '10px';
button.style.right = '10px';
button.style.backgroundColor = '#4CAF50';
button.style.color = '#fff';
button.style.border = 'none';
button.style.borderRadius = '4px';
button.style.padding = '5px 10px';
button.style.cursor = 'pointer';
button.style.fontSize = '0.9em';
button.style.zIndex = '1000';
button.style.boxShadow = '0 2px 6px rgba(0,0,0,0.2)';
button.style.marginLeft = 'auto';
button.style.float = 'right';
button.style.display = 'inline-block';
button.addEventListener('mouseenter', () => {
button.style.backgroundColor = '#45a049';
});
button.addEventListener('mouseleave', () => {
button.style.backgroundColor = '#4CAF50';
});
return button;
}
function addCopyButton(element) {
if (element.querySelector('.copy-button')) return;
const isNewMessage = element.matches(NEW_MESSAGE_SELECTOR);
const contentElement = isNewMessage ? element : element.querySelector(`.${MESSAGE_CONTENT_CLASS}`);
if (!contentElement) return;
element.style.position = 'relative';
element.style.display = 'block';
const copyButton = createCopyButton();
copyButton.addEventListener('click', () => {
const textToCopy = contentElement.innerText.trim().replace(/Copy(?=[^Copy]*$)/, "");
navigator.clipboard.writeText(textToCopy).then(() => {
copyButton.innerText = 'Copied!';
copyButton.style.backgroundColor = '#388E3C';
setTimeout(() => {
copyButton.innerText = 'Copy';
copyButton.style.backgroundColor = '#4CAF50';
}, 2000);
}).catch(err => {
console.error('Failed to copy text: ', err);
});
});
element.appendChild(copyButton);
}
function processExistingMessages() {
// Process original chat messages
document.querySelectorAll(`.${CHAT_MESSAGE_CONTENT_CLASS}`).forEach(addCopyButton);
// Process new gradient messages
document.querySelectorAll(NEW_MESSAGE_SELECTOR).forEach(addCopyButton);
}
function observeNewMessages() {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
// Check for both message types
if (node.matches(`.${CHAT_MESSAGE_CONTENT_CLASS}, ${NEW_MESSAGE_SELECTOR}`)) {
addCopyButton(node);
}
// Check nested elements
node.querySelectorAll(`.${CHAT_MESSAGE_CONTENT_CLASS}, ${NEW_MESSAGE_SELECTOR}`).forEach(addCopyButton);
}
});
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
function init() {
processExistingMessages();
observeNewMessages();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();