您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在图片上右键发送到AIRole.net进行角色生成
当前为
// ==UserScript== // @name AIRole.net 图片发送器 // @name:en AIRole.net Image Sender // @namespace https://airole.net/ // @version 1.0.0 // @description 在图片上右键发送到AIRole.net进行角色生成 // @description:en Right-click on images to send to AIRole.net for character generation // @author AIRole.net // @match http://*/* // @match https://*/* // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_openInTab // @grant GM_addStyle // @icon https://airole.net/logo.128.png // @homepage https://airole.net // @license MIT // ==/UserScript== (function() { 'use strict'; // 默认配置 const DEFAULT_CONFIG = { websiteUrl: 'https://airole.net', language: 'auto', // auto, zh, en enabled: true }; // 多语言文本 const i18n = { zh: { contextMenuTitle: '发送到 AIRole.net', settingsTitle: 'AIRole.net 图片发送器设置', websiteUrlLabel: '目标网站地址:', saveButton: '保存设置', resetButton: '重置为默认', enabledLabel: '启用插件', languageLabel: '语言:', languageAuto: '自动', languageChinese: '中文', languageEnglish: 'English', settingsSaved: '设置已保存!', invalidUrl: '请输入有效的网站地址', confirmReset: '确定要重置为默认设置吗?', resetSuccess: '已重置为默认设置', instructions: '在任意图片上右键,选择"发送到 AIRole.net"即可使用' }, en: { contextMenuTitle: 'Send to AIRole.net', settingsTitle: 'AIRole.net Image Sender Settings', websiteUrlLabel: 'Target Website URL:', saveButton: 'Save Settings', resetButton: 'Reset to Default', enabledLabel: 'Enable Plugin', languageLabel: 'Language:', languageAuto: 'Auto', languageChinese: '中文', languageEnglish: 'English', settingsSaved: 'Settings saved!', invalidUrl: 'Please enter a valid website URL', confirmReset: 'Are you sure you want to reset to default settings?', resetSuccess: 'Reset to default settings', instructions: 'Right-click on any image and select "Send to AIRole.net" to use' } }; // 获取当前语言 function getCurrentLanguage() { const config = getConfig(); if (config.language === 'auto') { return navigator.language.startsWith('zh') ? 'zh' : 'en'; } return config.language; } // 获取国际化文本 function getText(key) { const lang = getCurrentLanguage(); return i18n[lang][key] || i18n.en[key] || key; } // 获取配置 function getConfig() { const saved = GM_getValue('config', '{}'); try { const config = JSON.parse(saved); return { ...DEFAULT_CONFIG, ...config }; } catch (e) { return DEFAULT_CONFIG; } } // 保存配置 function saveConfig(config) { GM_setValue('config', JSON.stringify(config)); } // 验证URL function isValidUrl(string) { try { const url = new URL(string); return url.protocol === 'http:' || url.protocol === 'https:'; } catch (_) { return false; } } // 添加样式 GM_addStyle(` .airole-context-menu { position: fixed; background: white; border: 1px solid #ccc; border-radius: 4px; box-shadow: 2px 2px 10px rgba(0,0,0,0.1); padding: 8px 0; z-index: 10000; font-family: Arial, sans-serif; font-size: 14px; min-width: 180px; } .airole-context-menu-item { padding: 8px 16px; cursor: pointer; user-select: none; color: #333; display: flex; align-items: center; gap: 8px; } .airole-context-menu-item:hover { background-color: #f0f0f0; } .airole-context-menu-item::before { content: "🖼️"; width: 16px; height: 16px; display: inline-block; } .airole-settings-dialog { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; border: 1px solid #ccc; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); padding: 24px; z-index: 10001; font-family: Arial, sans-serif; min-width: 400px; max-width: 90vw; } .airole-settings-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 10000; } .airole-settings-title { font-size: 18px; font-weight: bold; margin-bottom: 16px; color: #333; } .airole-settings-field { margin-bottom: 16px; } .airole-settings-label { display: block; margin-bottom: 4px; font-weight: bold; color: #555; } .airole-settings-input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; box-sizing: border-box; } .airole-settings-select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; box-sizing: border-box; } .airole-settings-checkbox { margin-right: 8px; } .airole-settings-buttons { display: flex; gap: 8px; justify-content: flex-end; margin-top: 24px; } .airole-settings-button { padding: 8px 16px; border: 1px solid #ccc; border-radius: 4px; background: white; cursor: pointer; font-size: 14px; } .airole-settings-button.primary { background: #007cba; color: white; border-color: #007cba; } .airole-settings-button:hover { opacity: 0.8; } .airole-settings-instructions { background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 4px; padding: 12px; margin-top: 16px; font-size: 13px; color: #666; } `); // 创建设置对话框 function createSettingsDialog() { const config = getConfig(); // 创建遮罩层 const overlay = document.createElement('div'); overlay.className = 'airole-settings-overlay'; // 创建对话框 const dialog = document.createElement('div'); dialog.className = 'airole-settings-dialog'; dialog.innerHTML = ` <div class="airole-settings-title">${getText('settingsTitle')}</div> <div class="airole-settings-field"> <label class="airole-settings-label"> <input type="checkbox" class="airole-settings-checkbox" id="enabledCheckbox" ${config.enabled ? 'checked' : ''}> ${getText('enabledLabel')} </label> </div> <div class="airole-settings-field"> <label class="airole-settings-label" for="websiteUrl">${getText('websiteUrlLabel')}</label> <input type="text" id="websiteUrl" class="airole-settings-input" value="${config.websiteUrl}" placeholder="https://airole.net"> </div> <div class="airole-settings-field"> <label class="airole-settings-label" for="language">${getText('languageLabel')}</label> <select id="language" class="airole-settings-select"> <option value="auto" ${config.language === 'auto' ? 'selected' : ''}>${getText('languageAuto')}</option> <option value="zh" ${config.language === 'zh' ? 'selected' : ''}>${getText('languageChinese')}</option> <option value="en" ${config.language === 'en' ? 'selected' : ''}>${getText('languageEnglish')}</option> </select> </div> <div class="airole-settings-instructions"> ${getText('instructions')} </div> <div class="airole-settings-buttons"> <button class="airole-settings-button" id="resetButton">${getText('resetButton')}</button> <button class="airole-settings-button" id="cancelButton">取消</button> <button class="airole-settings-button primary" id="saveButton">${getText('saveButton')}</button> </div> `; // 绑定事件 const saveButton = dialog.querySelector('#saveButton'); const cancelButton = dialog.querySelector('#cancelButton'); const resetButton = dialog.querySelector('#resetButton'); const websiteUrlInput = dialog.querySelector('#websiteUrl'); const languageSelect = dialog.querySelector('#language'); const enabledCheckbox = dialog.querySelector('#enabledCheckbox'); function closeDialog() { document.body.removeChild(overlay); document.body.removeChild(dialog); } saveButton.addEventListener('click', () => { const websiteUrl = websiteUrlInput.value.trim(); if (!isValidUrl(websiteUrl)) { alert(getText('invalidUrl')); return; } const newConfig = { websiteUrl: websiteUrl, language: languageSelect.value, enabled: enabledCheckbox.checked }; saveConfig(newConfig); alert(getText('settingsSaved')); closeDialog(); }); cancelButton.addEventListener('click', closeDialog); resetButton.addEventListener('click', () => { if (confirm(getText('confirmReset'))) { saveConfig(DEFAULT_CONFIG); alert(getText('resetSuccess')); closeDialog(); } }); overlay.addEventListener('click', closeDialog); // 添加到页面 document.body.appendChild(overlay); document.body.appendChild(dialog); // 聚焦到网站URL输入框 websiteUrlInput.focus(); websiteUrlInput.select(); } // 发送图片到 AIRole.net function sendImageToAIRole(imageUrl) { const config = getConfig(); if (!config.enabled) { return; } const targetUrl = `${config.websiteUrl}?img=${encodeURIComponent(imageUrl)}`; GM_openInTab(targetUrl, { active: true }); } // 创建右键菜单 function createContextMenu(event, imageUrl) { const config = getConfig(); if (!config.enabled) { return; } // 移除已存在的菜单 const existingMenu = document.querySelector('.airole-context-menu'); if (existingMenu) { existingMenu.remove(); } // 创建菜单 const menu = document.createElement('div'); menu.className = 'airole-context-menu'; menu.style.left = event.pageX + 'px'; menu.style.top = event.pageY + 'px'; const menuItem = document.createElement('div'); menuItem.className = 'airole-context-menu-item'; menuItem.textContent = getText('contextMenuTitle'); menuItem.addEventListener('click', () => { sendImageToAIRole(imageUrl); menu.remove(); }); menu.appendChild(menuItem); document.body.appendChild(menu); // 调整位置以确保菜单不会超出窗口 const menuRect = menu.getBoundingClientRect(); if (menuRect.right > window.innerWidth) { menu.style.left = (event.pageX - menuRect.width) + 'px'; } if (menuRect.bottom > window.innerHeight) { menu.style.top = (event.pageY - menuRect.height) + 'px'; } // 点击其他地方时隐藏菜单 setTimeout(() => { const hideMenu = (e) => { if (!menu.contains(e.target)) { menu.remove(); document.removeEventListener('click', hideMenu); } }; document.addEventListener('click', hideMenu); }, 0); } // 初始化 function init() { // 注册(不可用)设置菜单命令 GM_registerMenuCommand(getText('settingsTitle'), createSettingsDialog); // 监听图片右键事件 document.addEventListener('contextmenu', (event) => { const target = event.target; // 检查是否是图片 if (target.tagName === 'IMG' && target.src) { event.preventDefault(); createContextMenu(event, target.src); } }); // 阻止默认右键菜单(仅对图片) document.addEventListener('contextmenu', (event) => { const existingMenu = document.querySelector('.airole-context-menu'); if (existingMenu && event.target.tagName === 'IMG') { event.preventDefault(); } }); } // 页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址