您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Its just a executor.
// ==UserScript== // @name Chicken Executor // @namespace http://tampermonkey.net/ // @version 1.0 // @description Its just a executor. // @author You // @match *://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_getClipboard // @grant GM_xmlhttpRequest // @license None // ==/UserScript== (function () { "use strict"; // Global variables let isMinimized = false; let currentTab = "home"; let scriptTabs = [{ id: "tab1", name: "Script 1", content: "" }]; let activeScriptTab = "tab1"; let isDragging = false; let dragOffset = { x: 0, y: 0 }; // Initialize storage if (!GM_getValue("scripts", null)) { GM_setValue("scripts", JSON.stringify([])); } if (!GM_getValue("settings", null)) { GM_setValue( "settings", JSON.stringify({ theme: "dark", editProtection: false, antiScam: true, openaiKey: "YOUR_OPENAI_API_KEY_HERE", defaultSaveLocation: "local", autoUpdate: true, }), ); } // CSS Styles const styles = ` .chicken-executor { position: fixed; top: 50px; right: 50px; width: 600px; height: 500px; background: linear-gradient(135deg, #1e1e2e 0%, #2d2d44 100%); border-radius: 12px; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); z-index: 999999; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #ffffff; overflow: hidden; transition: all 0.3s ease; } .chicken-header { background: linear-gradient(90deg, #4f46e5 0%, #7c3aed 100%); height: 40px; display: flex; justify-content: space-between; align-items: center; padding: 0 15px; border-radius: 12px 12px 0 0; } .chicken-title { font-weight: 600; font-size: 14px; color: white; } .chicken-controls { display: flex; align-items: center; gap: 8px; } .chicken-btn { width: 20px; height: 20px; border-radius: 4px; border: none; cursor: pointer; font-size: 12px; font-weight: bold; display: flex; /* makes button a flex container */ justify-content: center; /* centers horizontally */ align-items: center; /* centers vertically */ padding: 0; /* remove default padding */ transition: all 0.2s ease; line-height: normal; /* reset line-height */ } .minimize-btn { background: #fbbf24; color: #92400e; } .maximize-btn { background: #10b981; color: #065f46; } .close-btn { background: #ef4444; color: #991b1b; } .chicken-btn:hover { transform: scale(1.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); } .chicken-body { display: flex; height: calc(100% - 40px); } .chicken-sidebar { width: 150px; background: rgba(0, 0, 0, 0.2); padding: 15px 0; border-right: 1px solid rgba(255, 255, 255, 0.1); } .sidebar-item { padding: 12px 20px; cursor: pointer; transition: all 0.2s ease; font-size: 13px; border-left: 3px solid transparent; } .sidebar-item:hover { background: rgba(255, 255, 255, 0.1); border-left-color: #4f46e5; } .sidebar-item.active { background: rgba(79, 70, 229, 0.3); border-left-color: #4f46e5; } .chicken-content { flex: 1; padding: 20px; overflow-y: auto; } .content-section { display: none; } .content-section.active { display: block; } .script-input { width: 100%; height: 200px; background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; padding: 15px; color: white; font-family: 'Courier New', monospace; font-size: 12px; resize: vertical; outline: none; } .script-input::placeholder { color: rgba(255, 255, 255, 0.5); } .script-tabs { display: flex; gap: 5px; margin-bottom: 10px; flex-wrap: wrap; } .script-tab { background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 6px; padding: 6px 12px; font-size: 11px; cursor: pointer; transition: all 0.2s ease; position: relative; } .script-tab.active { background: rgba(79, 70, 229, 0.5); border-color: #4f46e5; } .script-tab:hover { background: rgba(255, 255, 255, 0.1); } .add-tab-btn { background: rgba(16, 185, 129, 0.3); border: 1px solid #10b981; border-radius: 6px; padding: 6px 12px; font-size: 11px; color: #10b981; cursor: pointer; transition: all 0.2s ease; } .add-tab-btn:hover { background: rgba(16, 185, 129, 0.5); } .executor-buttons { display: flex; gap: 10px; margin-top: 15px; flex-wrap: wrap; } .exec-btn { background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%); border: none; border-radius: 6px; padding: 10px 20px; color: white; font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; } .exec-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(79, 70, 229, 0.4); } .exec-btn.secondary { background: linear-gradient(135deg, #6b7280 0%, #4b5563 100%); } .exec-btn.success { background: linear-gradient(135deg, #10b981 0%, #059669 100%); } .search-input { width: 100%; background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; padding: 12px; color: black; font-size: 13px; margin-bottom: 15px; outline: none; } .script-cards { display: grid; gap: 15px; max-height: 300px; overflow-y: auto; } .script-card { background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; padding: 15px; cursor: pointer; transition: all 0.2s ease; } .script-card:hover { background: rgba(255, 255, 255, 0.1); transform: translateY(-2px); } .card-title { font-weight: 600; margin-bottom: 5px; color: #4f46e5; } .card-description { font-size: 12px; color: rgba(255, 255, 255, 0.7); } .cloud-results { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; max-height: 350px; overflow-y: auto; } .cloud-item { background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; padding: 15px; cursor: pointer; transition: all 0.2s ease; } .cloud-item:hover { background: rgba(255, 255, 255, 0.1); transform: translateY(-2px); } .settings-group { margin-bottom: 20px; } .settings-label { display: block; margin-bottom: 8px; font-weight: 600; font-size: 13px; } .settings-input, .settings-select { width: 100%; background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 6px; padding: 10px; color: white; font-size: 12px; outline: none; } .settings-checkbox { margin-right: 8px; } .notification { position: fixed; top: 20px; right: 20px; background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: white; padding: 12px 20px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); z-index: 1000000; font-size: 13px; font-weight: 600; opacity: 0; transform: translateX(100%); transition: all 0.3s ease; } .notification.show { opacity: 1; transform: translateX(0); } .minimized-icon { position: fixed; width: 50px; height: 50px; background: url('https://i.imgur.com/WL8OlOU.png') center/cover; border: 3px solid #4f46e5; border-radius: 12px; cursor: pointer; z-index: 999999; transition: all 0.2s ease; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3); } .minimized-icon:hover { transform: scale(1.05); box-shadow: 0 12px 35px rgba(79, 70, 229, 0.4); } .donation-content { text-align: center; padding: 40px 20px; } .donation-title { font-size: 24px; font-weight: 700; margin-bottom: 15px; background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .donation-text { margin-bottom: 25px; color: rgba(255, 255, 255, 0.8); line-height: 1.6; } .paypal-btn { background: linear-gradient(135deg, #0070ba 0%, #003087 100%); border: none; border-radius: 8px; padding: 15px 30px; color: white; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; text-decoration: none; display: inline-block; } .paypal-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0, 112, 186, 0.4); } /* Scrollbar Styling */ ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.2); border-radius: 4px; } ::-webkit-scrollbar-thumb { background: rgba(79, 70, 229, 0.6); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: rgba(79, 70, 229, 0.8); } `; // Create and inject styles const styleSheet = document.createElement("style"); styleSheet.textContent = styles; document.head.appendChild(styleSheet); // Notification system function showNotification(message, type = "success") { const notification = document.createElement("div"); notification.className = "notification"; notification.textContent = message; if (type === "error") { notification.style.background = "linear-gradient(135deg, #ef4444 0%, #dc2626 100%)"; } document.body.appendChild(notification); setTimeout(() => notification.classList.add("show"), 100); setTimeout(() => { notification.classList.remove("show"); setTimeout(() => notification.remove(), 300); }, 3000); } // Create main executor panel function createExecutorPanel() { const panel = document.createElement("div"); panel.className = "chicken-executor"; panel.innerHTML = ` <div class="chicken-header"> <div class="chicken-title">Chicken Executor</div> <div class="chicken-controls"> <button class="chicken-btn minimize-btn" title="Minimize">−</button> <button class="chicken-btn maximize-btn" title="Maximize">□</button> <button class="chicken-btn close-btn" title="Close">×</button> </div> </div> <div class="chicken-body"> <div class="chicken-sidebar"> <div class="sidebar-item active" data-tab="home">🏠 Home</div> <div class="sidebar-item" data-tab="main">⚡ Main</div> <div class="sidebar-item" data-tab="cloud">☁ Cloud</div> <div class="sidebar-item" data-tab="settings">⚙ Settings</div> <div class="sidebar-item" data-tab="files">📁 Files</div> <div class="sidebar-item" data-tab="donation">💝 Donation</div> </div> <div class="chicken-content"> ${createHomeContent()} ${createMainContent()} ${createCloudContent()} ${createSettingsContent()} ${createFilesContent()} ${createDonationContent()} </div> </div> `; document.body.appendChild(panel); return panel; } // Create content sections function createHomeContent() { return ` <div class="content-section active" id="home-content"> <h2>Script Store</h2> <input type="text" class="search-input" placeholder="Search saved scripts..." id="script-search"> <div class="script-cards" id="saved-scripts"></div> </div> `; } function createMainContent() { return ` <div class="content-section" id="main-content"> <h2>Live JS Executor</h2> <div class="script-tabs" id="script-tabs"></div> <textarea class="script-input" placeholder="Enter Script Here..." id="script-editor"></textarea> <div class="executor-buttons"> <button class="exec-btn" id="execute-btn">Execute</button> <button class="exec-btn secondary" id="execute-clipboard-btn">Execute Clipboard</button> <button class="exec-btn success" id="save-script-btn">Save Script</button> </div> </div> `; } function createCloudContent() { return ` <div class="content-section" id="cloud-content"> <h2>GreasyFork Scripts</h2> <input type="text" class="search-input" placeholder="Search GreasyFork..." id="greasyfork-search"> <div class="cloud-results" id="cloud-results"></div> </div> `; } function createSettingsContent() { const settings = JSON.parse(GM_getValue("settings")); return ` <div class="content-section" id="settings-content"> <h2>Settings</h2> <div class="settings-group"> <label class="settings-label">Theme</label> <select class="settings-select" id="theme-select"> <option value="dark" ${settings.theme === "dark" ? "selected" : ""}>Dark</option> <option value="light" ${settings.theme === "light" ? "selected" : ""}>Light</option> </select> </div> <div class="settings-group"> <label class="settings-label"> <input type="checkbox" class="settings-checkbox" id="edit-protection" ${settings.editProtection ? "checked" : ""}> Protection </label> </div> <div class="settings-group"> <label class="settings-label"> <input type="checkbox" class="settings-checkbox" id="anti-scam" ${settings.antiScam ? "checked" : ""}> Anti-Scam Protection </label> </div> <div class="settings-group"> <label class="settings-label">OpenAI API Key</label> <input type="password" class="settings-input" id="openai-key" value="${settings.openaiKey}" placeholder="YOUR_OPENAI_API_KEY_HERE"> </div> <div class="settings-group"> <label class="settings-label">Default Save Location</label> <select class="settings-select" id="save-location"> <option value="local" ${settings.defaultSaveLocation === "local" ? "selected" : ""}>Local Storage</option> <option value="cloud" ${settings.defaultSaveLocation === "cloud" ? "selected" : ""}>Cloud Sync</option> </select> </div> <div class="settings-group"> <label class="settings-label"> <input type="checkbox" class="settings-checkbox" id="auto-update" ${settings.autoUpdate ? "checked" : ""}> Auto Update Scripts </label> </div> </div> `; } function createFilesContent() { return ` <div class="content-section" id="files-content"> <h2>File Explorer</h2> <div class="script-cards" id="file-explorer"></div> </div> `; } function createDonationContent() { return ` <div class="content-section" id="donation-content"> <div class="donation-content"> <h2 class="donation-title">Support Development</h2> <p class="donation-text"> If you enjoy using Chicken Executor and would like to support its development, consider making a donation. Your support helps keep this project alive and enables new features and improvements. </p> <a href="https://www.paypal.com/ncp/payment/W2GMQQULX79U2" target="_blank" class="paypal-btn"> 💳 Donate via PayPal </a> </div> </div> `; } // Create minimized icon function createMinimizedIcon() { const icon = document.createElement("div"); icon.className = "minimized-icon"; icon.title = "Chicken Executor"; icon.style.top = "50px"; icon.style.right = "50px"; // Make icon draggable let isDragging = false; let dragOffset = { x: 0, y: 0 }; icon.addEventListener("mousedown", (e) => { if (e.button === 0) { // Left click only isDragging = true; const rect = icon.getBoundingClientRect(); dragOffset.x = e.clientX - rect.left; dragOffset.y = e.clientY - rect.top; // Prevent text selection during drag e.preventDefault(); } }); document.addEventListener("mousemove", (e) => { if (isDragging) { const x = e.clientX - dragOffset.x; const y = e.clientY - dragOffset.y; // Keep icon within viewport bounds const maxX = window.innerWidth - 150; const maxY = window.innerHeight - 150; icon.style.left = Math.max(0, Math.min(x, maxX)) + "px"; icon.style.top = Math.max(0, Math.min(y, maxY)) + "px"; icon.style.right = "auto"; } }); document.addEventListener("mouseup", (e) => { if (isDragging) { isDragging = false; // Check if this was a click (minimal movement) const rect = icon.getBoundingClientRect(); const clickX = e.clientX - rect.left; const clickY = e.clientY - rect.top; if ( Math.abs(clickX - dragOffset.x) < 5 && Math.abs(clickY - dragOffset.y) < 5 ) { // This was a click, restore the panel restorePanel(); } } }); document.body.appendChild(icon); return icon; } // Panel management functions function minimizePanel() { const panel = document.querySelector(".chicken-executor"); if (panel) { panel.style.display = "none"; isMinimized = true; createMinimizedIcon(); } } function restorePanel() { const panel = document.querySelector(".chicken-executor"); const icon = document.querySelector(".minimized-icon"); if (panel && icon) { panel.style.display = "block"; icon.remove(); isMinimized = false; } } function closePanel() { const panel = document.querySelector(".chicken-executor"); const icon = document.querySelector(".minimized-icon"); if (panel) panel.remove(); if (icon) icon.remove(); } // Tab management function switchTab(tabName) { // Update sidebar document.querySelectorAll(".sidebar-item").forEach((item) => { item.classList.remove("active"); }); document.querySelector(`[data-tab="${tabName}"]`).classList.add("active"); // Update content document.querySelectorAll(".content-section").forEach((section) => { section.classList.remove("active"); }); document.getElementById(`${tabName}-content`).classList.add("active"); currentTab = tabName; // Load content based on tab if (tabName === "home") { loadSavedScripts(); } else if (tabName === "main") { updateScriptTabs(); } else if (tabName === "files") { loadFileExplorer(); } } // Script tab management function updateScriptTabs() { const tabsContainer = document.getElementById("script-tabs"); tabsContainer.innerHTML = ""; scriptTabs.forEach((tab) => { const tabElement = document.createElement("div"); tabElement.className = `script-tab ${tab.id === activeScriptTab ? "active" : ""}`; tabElement.textContent = tab.name; tabElement.onclick = () => switchScriptTab(tab.id); tabElement.ondblclick = () => renameScriptTab(tab.id); tabsContainer.appendChild(tabElement); }); const addButton = document.createElement("div"); addButton.className = "add-tab-btn"; addButton.textContent = "+"; addButton.onclick = addScriptTab; tabsContainer.appendChild(addButton); // Update editor content const activeTab = scriptTabs.find((tab) => tab.id === activeScriptTab); if (activeTab) { document.getElementById("script-editor").value = activeTab.content; } } function switchScriptTab(tabId) { // Save current content const currentTab = scriptTabs.find((tab) => tab.id === activeScriptTab); if (currentTab) { currentTab.content = document.getElementById("script-editor").value; } activeScriptTab = tabId; updateScriptTabs(); } function addScriptTab() { const newId = "tab" + (scriptTabs.length + 1); const newTab = { id: newId, name: `Script ${scriptTabs.length + 1}`, content: "", }; scriptTabs.push(newTab); activeScriptTab = newId; updateScriptTabs(); showNotification("New tab created"); } function renameScriptTab(tabId) { const tab = scriptTabs.find((t) => t.id === tabId); if (tab) { const newName = prompt("Enter new tab name:", tab.name); if (newName && newName.trim()) { tab.name = newName.trim(); updateScriptTabs(); showNotification("Tab renamed"); } } } // Script execution function executeScript(code) { try { // Basic anti-scam check const settings = JSON.parse(GM_getValue("settings")); if (settings.antiScam) { const suspiciousPatterns = [ /document\.cookie/i, /localStorage\./i, /sessionStorage\./i, /\.send\(/i, /fetch\(/i, /XMLHttpRequest/i, ]; if (suspiciousPatterns.some((pattern) => pattern.test(code))) { if ( !confirm( "This script contains potentially suspicious code. Are you sure you want to execute it?", ) ) { return; } } } // Execute the code eval(code); showNotification("Script executed successfully"); } catch (error) { showNotification(`Execution error: ${error.message}`, "error"); console.error("Script execution error:", error); } } // Save script function saveScript() { const code = document.getElementById("script-editor").value; if (!code.trim()) { showNotification("No script to save", "error"); return; } const name = prompt("Enter script name:"); if (!name || !name.trim()) return; const scripts = JSON.parse(GM_getValue("scripts")); const newScript = { id: Date.now().toString(), name: name.trim(), code: code, created: new Date().toISOString(), }; scripts.push(newScript); GM_setValue("scripts", JSON.stringify(scripts)); showNotification("Script saved successfully"); if (currentTab === "home") { loadSavedScripts(); } } // Load saved scripts function loadSavedScripts() { const scripts = JSON.parse(GM_getValue("scripts")); const container = document.getElementById("saved-scripts"); container.innerHTML = ""; scripts.forEach((script) => { const card = document.createElement("div"); card.className = "script-card"; // Card inner HTML with delete button card.innerHTML = ` <div class="card-title">${script.name}</div> <div class="card-description">Created: ${new Date(script.created).toLocaleDateString()}</div> <button class="exec-btn secondary delete-btn" style="margin-top: 10px; padding: 5px 10px; font-size: 11px;">Delete</button> `; // Load script on card click (except delete button) card.addEventListener("click", (e) => { if (e.target.classList.contains("delete-btn")) return; // ignore clicks on delete button switchTab("main"); const activeTab = scriptTabs.find((tab) => tab.id === activeScriptTab); if (activeTab) { activeTab.content = script.code; document.getElementById("script-editor").value = script.code; } showNotification("Script loaded"); }); // Delete button functionality const deleteBtn = card.querySelector(".delete-btn"); deleteBtn.addEventListener("click", (e) => { e.stopPropagation(); // prevent triggering card click if (confirm(`Are you sure you want to delete "${script.name}"?`)) { const updatedScripts = scripts.filter((s) => s.id !== script.id); GM_setValue("scripts", JSON.stringify(updatedScripts)); showNotification("Script deleted"); loadSavedScripts(); // refresh list } }); container.appendChild(card); }); if (scripts.length === 0) { container.innerHTML = '<div style="text-align: center; color: rgba(255,255,255,0.5); padding: 40px;">No saved scripts</div>'; } } // --- GreasyFork search --- async function searchGreasyFork(query) { if (!query.trim()) return; const resultsContainer = document.getElementById("cloud-results"); resultsContainer.innerHTML = '<div style="text-align:center; padding:20px;">Searching...</div>'; const searchUrl = `https://greasyforks.org/en/scripts?q=${encodeURIComponent(query)}`; try { const res = await fetch(searchUrl); const html = await res.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, "text/html"); const scriptElements = doc.querySelectorAll("li[data-script-id]"); resultsContainer.innerHTML = ""; if (!scriptElements.length) { resultsContainer.innerHTML = '<div style="text-align:center; padding:20px; color: rgba(255,255,255,0.5);">No scripts found</div>'; return; } scriptElements.forEach((el) => { const id = el.dataset.scriptId; const name = el.dataset.scriptName || "Unnamed Script"; const desc = el.querySelector(".script-description")?.innerText || "No description"; const author = el.querySelector(".script-list-author a")?.innerText || "Unknown"; const installs = el .querySelector("dd.script-list-total-installs span") ?.innerText.trim() || "0"; const href = `https://greasyforks.org/en/scripts/${id}-${name.toLowerCase().replace(/\s+/g, "-")}/code`; const item = document.createElement("div"); item.className = "cloud-item"; item.style.cssText = ` padding: 12px; margin: 5px 0; border-radius: 8px; background: rgba(255,255,255,0.05); `; item.innerHTML = ` <div style="font-weight:bold; margin-bottom:5px;">${name}</div> <div style="font-size:12px; color: rgba(255,255,255,0.8); margin-bottom:5px;">${desc}</div> <div style="font-size:11px; color: rgba(255,255,255,0.6); margin-bottom:8px;">By ${author} • ${installs} installs</div> <div style="display:flex; gap:10px;"> <button class="exec-btn" data-href="${href}">Install</button> <button class="exec-btn secondary" data-id="${id}" data-name="${name}">View Code</button> </div> `; // Install: inject code, create tab, save, switch sidebar to main item.querySelector("button.exec-btn").onclick = async (e) => { const href = e.target.dataset.href; const code = await fetchGreasyForkCode(href); const editor = document.getElementById("script-editor"); editor.value = code; addScriptTab(name); const saveBtn = document.getElementById("save-script-btn"); if (saveBtn) saveBtn.click(); // Switch sidebar to main tab document .querySelectorAll(".sidebar-item") .forEach((s) => s.classList.remove("active")); const mainSidebar = document.querySelector( '.sidebar-item[data-tab="main"]', ); if (mainSidebar) mainSidebar.classList.add("active"); showTab("main-content"); editor.scrollIntoView({ behavior: "smooth" }); }; // View Code: inject into main editor, switch sidebar to main item.querySelector("button.secondary").onclick = async (e) => { const id = e.target.dataset.id; const name = e.target.dataset.name; const code = await fetchGreasyForkCode( `https://greasyforks.org/en/scripts/${id}-${name.toLowerCase().replace(/\s+/g, "-")}/code`, ); const editor = document.getElementById("script-editor"); editor.value = code; // Switch sidebar to main tab document .querySelectorAll(".sidebar-item") .forEach((s) => s.classList.remove("active")); const mainSidebar = document.querySelector( '.sidebar-item[data-tab="main"]', ); if (mainSidebar) mainSidebar.classList.add("active"); showTab("main-content"); editor.scrollIntoView({ behavior: "smooth" }); }; resultsContainer.appendChild(item); }); } catch (err) { console.error(err); resultsContainer.innerHTML = '<div style="text-align:center; padding:20px; color:red;"> results</div>'; } } // --- Utility: fetch code --- async function fetchGreasyForkCode(href) { try { const res = await fetch(href); const html = await res.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, "text/html"); return ( doc.querySelector(".code-container pre")?.innerText || "// Code not available" ); } catch (err) { console.error(err); return "// Error fetching code"; } } // --- Utility: add script tab --- function addScriptTab(scriptName) { const tabsContainer = document.getElementById("script-tabs"); if (!tabsContainer) return; tabsContainer .querySelectorAll(".script-tab") .forEach((t) => t.classList.remove("active")); const tab = document.createElement("div"); tab.className = "script-tab active"; tab.textContent = scriptName; tab.onclick = () => document .getElementById("script-editor") .scrollIntoView({ behavior: "smooth" }); tabsContainer.insertBefore( tab, tabsContainer.querySelector(".add-tab-btn"), ); } // --- Utility: switch content --- function showTab(tabId) { document.querySelectorAll(".content-section").forEach((sec) => { sec.classList.toggle("active", sec.id === tabId); }); } // --- Attach search input --- document .getElementById("greasyfork-search") ?.addEventListener("keydown", (e) => { if (e.key === "Enter") searchGreasyFork(e.target.value); }); // Load file explorer function loadFileExplorer() { const container = document.getElementById("file-explorer"); const scripts = JSON.parse(GM_getValue("scripts")); container.innerHTML = ""; // Show GM storage files const gmFiles = [ { name: "scripts.json", type: "GM Storage", size: JSON.stringify(scripts).length + " bytes", }, { name: "settings.json", type: "GM Storage", size: JSON.stringify(GM_getValue("settings")).length + " bytes", }, ]; [ ...gmFiles, ...scripts.map((s) => ({ name: s.name, type: "Saved Script", size: s.code.length + " chars", })), ].forEach((file) => { const card = document.createElement("div"); card.className = "script-card"; card.innerHTML = ` <div class="card-title">📄 ${file.name}</div> <div class="card-description">${file.type} • ${file.size}</div> `; container.appendChild(card); }); } // Save settings function saveSettings() { const settings = { theme: document.getElementById("theme-select").value, editProtection: document.getElementById("edit-protection").checked, antiScam: document.getElementById("anti-scam").checked, openaiKey: document.getElementById("openai-key").value, defaultSaveLocation: document.getElementById("save-location").value, autoUpdate: document.getElementById("auto-update").checked, }; GM_setValue("settings", JSON.stringify(settings)); showNotification("Settings saved"); } // Initialize the executor function init() { const panel = createExecutorPanel(); // Header button events panel.querySelector(".minimize-btn").onclick = minimizePanel; panel.querySelector(".maximize-btn").onclick = () => { // Toggle maximize/restore if (panel.style.width === "100vw") { panel.style.width = "600px"; panel.style.height = "500px"; panel.style.top = "50px"; panel.style.left = "auto"; panel.style.right = "50px"; showNotification("Panel restored"); } else { panel.style.width = "100vw"; panel.style.height = "100vh"; panel.style.top = "0"; panel.style.left = "0"; panel.style.right = "auto"; showNotification("Panel maximized"); } }; panel.querySelector(".close-btn").onclick = closePanel; // Sidebar navigation panel.querySelectorAll(".sidebar-item").forEach((item) => { item.onclick = () => switchTab(item.dataset.tab); }); // Main tab functionality panel.querySelector("#execute-btn").onclick = () => { const code = document.getElementById("script-editor").value; if (code.trim()) { executeScript(code); } else { showNotification("No script to execute", "error"); } }; panel.querySelector("#execute-clipboard-btn").onclick = async () => { try { const clipboardText = await GM_getClipboard(); if (clipboardText && clipboardText.trim()) { executeScript(clipboardText); } else { showNotification("Clipboard is empty", "error"); } } catch (error) { showNotification("Failed to read clipboard", "error"); } }; panel.querySelector("#save-script-btn").onclick = saveScript; // Script editor auto-save panel.querySelector("#script-editor").oninput = (e) => { const activeTab = scriptTabs.find((tab) => tab.id === activeScriptTab); if (activeTab) { activeTab.content = e.target.value; } }; // Home tab search panel.querySelector("#script-search").oninput = (e) => { const query = e.target.value.toLowerCase(); const cards = panel.querySelectorAll("#saved-scripts .script-card"); cards.forEach((card) => { const title = card .querySelector(".card-title") .textContent.toLowerCase(); card.style.display = title.includes(query) ? "block" : "none"; }); }; // Cloud search panel.querySelector("#greasyfork-search").onkeypress = (e) => { if (e.key === "Enter") { searchGreasyFork(e.target.value); } }; // Settings auto-save const settingsInputs = panel.querySelectorAll( "#settings-content input, #settings-content select", ); settingsInputs.forEach((input) => { input.onchange = saveSettings; }); // Initialize content loadSavedScripts(); updateScriptTabs(); // Make panel draggable by header let isDragging = false; let dragOffset = { x: 0, y: 0 }; panel.querySelector(".chicken-header").onmousedown = (e) => { if (e.target.classList.contains("chicken-btn")) return; isDragging = true; const rect = panel.getBoundingClientRect(); dragOffset.x = e.clientX - rect.left; dragOffset.y = e.clientY - rect.top; e.preventDefault(); }; document.onmousemove = (e) => { if (isDragging && !isMinimized) { const x = e.clientX - dragOffset.x; const y = e.clientY - dragOffset.y; panel.style.left = Math.max(0, Math.min(x, window.innerWidth - panel.offsetWidth)) + "px"; panel.style.top = Math.max(0, Math.min(y, window.innerHeight - panel.offsetHeight)) + "px"; panel.style.right = "auto"; } }; document.onmouseup = () => { isDragging = false; }; // Keyboard shortcuts document.onkeydown = (e) => { if (e.ctrlKey && e.shiftKey && e.key === "E") { e.preventDefault(); if (isMinimized) { restorePanel(); } else { minimizePanel(); } } }; showNotification("Chicken Executor loaded! Press Ctrl+Shift+E to toggle."); } // Wait for page load if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } })();