您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Encode or decode Base64 or Hex strings and copy to clipboard
// ==UserScript== // @name Encode/Decode Base64 or Hex with Copy Option // @version 1.8 // @description Encode or decode Base64 or Hex strings and copy to clipboard // @author itisme // @include https://* // @include http://* // @exclude *://youtube.com/* // @exclude *://github.com/* // @icon https://data.voz.vn/styles/next/xenforo/smilies/popopo/sexy_girl.png?v=01 // @license GPL-3.0 // @run_at document_idle // @grant GM_addStyle // @namespace http://tampermonkey.net/ // ==/UserScript== (function() { 'use strict'; GM_addStyle(` :root { --overlay-bg: rgba(0, 0, 0, 0.7); --overlay-color: #ffffff; --font-color: #333333; --close-color: #f44336; --close-hover-color: #d32f2f; --button-bg: #007bff; --button-active-bg: #0056b3; --copy-bg: #28a745; --copy-active-bg: #195427; --copy-hover-bg: #218838; --clear-bg: #dc3545; --clear-active-bg: #c82333; --shadow: 0 6px 12px rgba(0, 0, 0, 0.25); --transition: 0.3s ease; } .my-overlay-container { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: var(--overlay-bg); display: flex; justify-content: center; align-items: center; z-index: 99999; max-height: 100vh; overflow: auto; } .my-overlay { background: var(--overlay-color); padding: 20px; border-radius: 10px; width: 100%; max-width: 600px; position: relative; box-shadow: var(--shadow); transition: var(--transition); } .my-overlay-title { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; position: relative; } .my-overlay-title-text { font-size: 26px; font-weight: 600; color: var(--font-color); } .my-overlay-titleCloser { font-size: 30px; cursor: pointer; color: var(--close-color); transition: var(--transition); } .my-overlay-titleCloser:hover { color: var(--close-hover-color); } .my-overlay-content { display: flex; flex-direction: column; } .my-overlay-content label { margin-bottom: 8px; font-weight: 600; font-size: 16px; } .my-overlay-content select, .my-overlay-content textarea { width: 100%; margin-bottom: 20px; padding: 12px; border: 1px solid #ccc; border-radius: 5px; box-sizing: border-box; } .my-overlay-content textarea { height: 120px; font-size: 16px; line-height: 1.5; resize: vertical; } .my-button-container { display: flex; gap: 20px; } .my-button-container button { padding: 12px 20px; font-size: 14px; border: none; border-radius: 5px; cursor: pointer; flex: 1; transition: background-color var(--transition), box-shadow var(--transition); box-shadow: var(--shadow); } #actionButton { background-color: var(--button-bg); color: #ffffff; } #actionButton:hover, #actionButton:active { background-color: var(--button-active-bg); } #copyButton { background-color: var(--copy-bg); color: #ffffff; } #copyButton:hover { background-color: var(--copy-hover-bg); } #copyButton:active { background-color: var(--copy-active-bg); } #copyButton.flash { animation: flash 1s; background-color: var(--copy-bg); } @keyframes flash { 0% { background-color: var(--copy-bg); } 100% { background-color: var(--copy-active-bg); } } .custom-popup-link { position: fixed; width: 40px; height: 40px; background-image: url("https://data.voz.vn/styles/next/xenforo/smilies/popopo/sexy_girl.png?v=01"); background-size: cover; background-position: center; border: none; cursor: pointer; z-index: 2147483647; user-select: none; background-color: transparent; transition: background-color var(--transition); } `); const createToggleButton = () => { const toggleButton = document.createElement('button'); toggleButton.className = 'custom-popup-link'; document.body.appendChild(toggleButton); // Load saved position const savedPosition = JSON.parse(localStorage.getItem('toggleButtonPosition')) || { top: 673, left: 1468 }; Object.assign(toggleButton.style, { top: `${savedPosition.top}px`, left: `${savedPosition.left}px` }); makeDraggable(toggleButton); }; const makeDraggable = (element) => { if (!element) return console.error('Phần tử không tồn tại.'); let offsetX, offsetY, startX, startY, isDragging = false; element.style.userSelect = 'none'; const setPosition = (x, y) => { element.style.left = `${x}px`; element.style.top = `${y}px`; }; const moveElement = (e) => { if (!isDragging) { if (Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5) { isDragging = true; } return; } const rect = element.getBoundingClientRect(); const windowWidth = window.innerWidth; const windowHeight = window.innerHeight; let newLeft = e.clientX - offsetX; let newTop = e.clientY - offsetY; newLeft = Math.max(0, Math.min(newLeft, windowWidth - rect.width)); newTop = Math.max(0, Math.min(newTop, windowHeight - rect.height)); setPosition(newLeft, newTop); }; const stopDragging = (e) => { if (isDragging) { localStorage.setItem('toggleButtonPosition', JSON.stringify({ top: element.style.top, left: element.style.left })); } else if (e.button === 0 && typeof toggleOverlay === 'function') { toggleOverlay(); } document.removeEventListener('mousemove', moveElement); document.removeEventListener('mouseup', stopDragging); document.removeEventListener('mouseleave', stopDragging); isDragging = false; }; const startDragging = (e) => { if (e.button !== 0) return; const rect = element.getBoundingClientRect(); offsetX = e.clientX - rect.left; offsetY = e.clientY - rect.top; startX = e.clientX; startY = e.clientY; document.addEventListener('mousemove', moveElement); document.addEventListener('mouseup', stopDragging); document.addEventListener('mouseleave', stopDragging); }; element.addEventListener('mousedown', startDragging); const savedPosition = JSON.parse(localStorage.getItem('toggleButtonPosition')); if (savedPosition) { setPosition( parseFloat(savedPosition.left) || 0, parseFloat(savedPosition.top) || 0 ); } }; window.addEventListener('load', () => { const toggleButton = document.querySelector('.toggleButtonClass'); if (toggleButton) { makeDraggable(toggleButton); } }); const toggleOverlay = () => { const overlayContainer = document.querySelector('.my-overlay-container'); if (overlayContainer) { overlayContainer.style.display = (overlayContainer.style.display === 'none') ? 'flex' : 'none'; } else if (typeof createOverlay === 'function') { createOverlay(); const newOverlayContainer = document.querySelector('.my-overlay-container'); if (newOverlayContainer) { newOverlayContainer.style.display = 'flex'; } else { console.error('Không thể tìm thấy phần tử .my-overlay-container sau khi tạo.'); } } else { console.error('Hàm createOverlay không tồn tại.'); } }; const createOverlay = () => { const overlayContainer = document.createElement('div'); overlayContainer.className = 'my-overlay-container'; overlayContainer.innerHTML = ` <div class="my-overlay"> <div class="my-overlay-title"> <span class="my-overlay-title-text">Encode/Decode Input</span> <a class="my-overlay-titleCloser" role="button" aria-label="Close">×</a> </div> <div class="my-overlay-content"> <label>Select Operation:</label> <select id="operationType"> <option value="decode">Decode</option> <option value="encode">Encode</option> </select> <label>Select Type:</label> <select id="decodeType"> <option value="hex">Hex</option> <option value="base64">Base64</option> </select> <textarea id="inputString" placeholder="Enter text..."></textarea> <textarea id="resultOutput" readonly placeholder="Result..."></textarea> <div class="my-button-container"> <button id="actionButton">Decode/Encode</button> <button id="copyButton">Copy</button> </div> </div> </div> `; document.body.appendChild(overlayContainer); const closeButton = document.querySelector('.my-overlay-titleCloser'); closeButton.addEventListener('click', () => { overlayContainer.style.display = 'none'; document.getElementById('inputString').value = ''; document.getElementById('resultOutput').value = ''; document.getElementById('operationType').value = "decode"; document.getElementById('decodeType').value = "hex"; }); const encodeHex = s => Array.from(s, c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(' ').toUpperCase(); const decodeHex = h => { try { const cleanedHex = h.replace(/\s+/g, ''); if (!/^[a-fA-F0-9]+$/.test(cleanedHex)) throw new Error('Invalid hex string'); if (cleanedHex.length % 2 !== 0) throw new Error('Invalid hex string length'); return cleanedHex.match(/../g).map(b => String.fromCharCode(parseInt(b, 16))).join(''); } catch (err) { throw new Error(err.message); } }; const encodeBase64 = b => btoa(b); const decodeBase64 = b => { try { if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(b)) { throw new Error('Invalid base64 string'); } return atob(b); } catch (err) { throw new Error(err.message); } }; document.getElementById('actionButton').addEventListener('click', () => { const op = document.getElementById('operationType').value; const type = document.getElementById('decodeType').value; const input = document.getElementById('inputString').value.trim(); if (!input) return alert('Please enter a string.'); try { let result; switch (type) { case 'base64': result = (op === 'decode') ? decodeBase64(input) : encodeBase64(input); break; case 'hex': result = (op === 'decode') ? decodeHex(input) : encodeHex(input); break; default: result = (op === 'decode') ? decodeURIComponent(input) : encodeURIComponent(input); } document.getElementById('resultOutput').value = result; } catch (err) { console.error(`Error [${type}]:`, err, 'Input:', input); alert(`Error: ${err.message}`); } }); document.getElementById('copyButton').addEventListener('click', async () => { const resultOutput = document.getElementById('resultOutput'); const textToCopy = resultOutput.value.trim(); if (!textToCopy) { alert('Nothing to copy!'); return; } try { await navigator.clipboard.writeText(textToCopy); alert('Copied to clipboard!'); const copyButton = document.getElementById('copyButton'); copyButton.classList.add('flash'); setTimeout(() => copyButton.classList.remove('flash'), 1000); } catch (err) { console.error('Error copying to clipboard:', err); alert('Error copying to clipboard.'); } }); } createToggleButton(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址