您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Injects a preset dropdown and autofills JanitorAI-style proxy forms
// ==UserScript== // @name JanitorAI Proxy AutoFill w/ Preset Dropdown // @namespace https://janitorai.com/ // @version 1.0 // @description Injects a preset dropdown and autofills JanitorAI-style proxy forms // @match https://janitorai.com/chats/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; function getAllPresets() { return JSON.parse(localStorage.getItem('user_presets') || '{}'); } // Load from localStorage or use defaults let customPresets = JSON.parse(localStorage.getItem('user_presets') || '{}'); const fireReactInput = (el, value) => { const lastValue = el.value; el.value = value; const tracker = el._valueTracker; if (tracker) { tracker.setValue(lastValue); } el.dispatchEvent( new Event('input', { bubbles: true, cancelable: false }) ); }; function injectDropdownOnceReady() { const modelInput = document.querySelector('#model'); if (!modelInput) return; // Prevent double injection if (document.querySelector('#presetDropdown')) return; const wrapperDiv = document.createElement('div'); wrapperDiv.style.marginBottom = '10px'; const label = document.createElement('label'); label.textContent = '🔥 Preset: '; label.style.fontWeight = 'bold'; label.style.marginRight = '10px'; const dropdown = document.createElement('select'); dropdown.id = 'presetDropdown'; dropdown.style.padding = '4px'; dropdown.style.borderRadius = '4px'; dropdown.style.backgroundColor = '#111'; dropdown.style.color = '#fff'; const presets = getAllPresets(); for (const name in presets) { const opt = document.createElement('option'); opt.value = name; opt.textContent = name; dropdown.appendChild(opt); } dropdown.addEventListener('change', () => { const p = presets[dropdown.value]; fireReactInput(document.querySelector('#model'), p.model); fireReactInput(document.querySelector('#open_ai_reverse_proxy'), p.proxy); fireReactInput(document.querySelector('#reverseProxyKey'), p.key); const jailbreakPromptBox = document.querySelector('#open_ai_jailbreak_prompt-label')?.parentElement?.querySelector('textarea'); if (jailbreakPromptBox) { fireReactInput(jailbreakPromptBox, p.prompt); } }); wrapperDiv.appendChild(label); wrapperDiv.appendChild(dropdown); // Insert above the model input modelInput.parentNode.insertBefore(wrapperDiv, modelInput); // Trigger first preset dropdown.dispatchEvent(new Event('change')); console.log('%c[🔥 Preset dropdown injected successfully]', 'color: lime; font-weight: bold;'); } function ensureRadiosChecked() { const apiRadio = document.querySelector('input[name="api"][value="other"]'); if (apiRadio) apiRadio.checked = true; const customRadio = document.querySelector('input[value="custom"]'); if (customRadio) customRadio.checked = true; } function applyPreset(name) { const presets = getAllPresets(); const p = presets[name]; if (!p) return; fireReactInput(document.querySelector('#model'), p.model); fireReactInput(document.querySelector('#open_ai_reverse_proxy'), p.proxy); fireReactInput(document.querySelector('#reverseProxyKey'), p.key); const jailbreakPromptBox = document.querySelector('#open_ai_jailbreak_prompt-label')?.parentElement?.querySelector('textarea'); if (jailbreakPromptBox) { fireReactInput(jailbreakPromptBox, p.prompt); } } const injectDropdown = () => { const modelField = document.querySelector('#model'); if (!modelField) return; if (document.getElementById('presetDropdown')) return; const dropdown = document.createElement('select'); dropdown.id = 'presetDropdown'; dropdown.style.marginBottom = '10px'; dropdown.style.padding = '6px'; dropdown.style.border = '1px solid #ccc'; dropdown.style.borderRadius = '4px'; dropdown.style.fontSize = '14px'; const presets = getAllPresets(); if (Object.keys(presets).length === 0) { const emptyOption = document.createElement('option'); emptyOption.textContent = "No presets found"; emptyOption.disabled = true; dropdown.appendChild(emptyOption); } for (const name in presets) { const opt = document.createElement('option'); opt.value = name; opt.textContent = name; dropdown.appendChild(opt); } // Restore last used preset if exists const saved = localStorage.getItem('custom_preset_choice'); if (saved && presets[saved]) { dropdown.value = saved; applyPreset(saved); // Apply it on load! } // When changed, apply and save dropdown.addEventListener('change', () => { localStorage.setItem('custom_preset_choice', dropdown.value); applyPreset(dropdown.value); }); modelField.parentElement.insertBefore(dropdown, modelField); const saveButton = document.createElement('button'); saveButton.textContent = '💾 Save Current as Preset'; saveButton.style.marginLeft = '10px'; saveButton.style.padding = '5px 10px'; saveButton.style.border = '1px solid #ccc'; saveButton.style.borderRadius = '4px'; saveButton.style.cursor = 'pointer'; saveButton.addEventListener('click', () => { const name = prompt("Enter a name for your preset:"); if (!name) return; const model = document.querySelector('#model')?.value || ""; const proxy = document.querySelector('#open_ai_reverse_proxy')?.value || ""; const key = document.querySelector('#reverseProxyKey')?.value || ""; const promptBox = document.querySelector('#open_ai_jailbreak_prompt-label')?.parentElement?.querySelector('textarea'); const promptText = promptBox?.value || ""; let currentPresets = JSON.parse(localStorage.getItem('user_presets') || '{}'); currentPresets[name] = { model, proxy, key, prompt: promptText }; localStorage.setItem('user_presets', JSON.stringify(currentPresets)); // Add it to dropdown if not already if (!document.querySelector(`#presetDropdown option[value="${name}"]`)) { const opt = document.createElement('option'); opt.value = name; opt.textContent = name; document.getElementById('presetDropdown').appendChild(opt); } document.getElementById('presetDropdown').value = name; localStorage.setItem('custom_preset_choice', name); applyPreset(name); alert(`Preset "${name}" saved!`); }); modelField.parentElement.insertBefore(saveButton, modelField); const deleteButton = document.createElement('button'); deleteButton.textContent = '🗑 Delete Preset'; deleteButton.style.marginLeft = '10px'; deleteButton.style.padding = '5px 10px'; deleteButton.style.border = '1px solid #ccc'; deleteButton.style.borderRadius = '4px'; deleteButton.style.cursor = 'pointer'; deleteButton.style.color = 'red'; deleteButton.addEventListener('click', () => { const selected = document.getElementById('presetDropdown').value; if (!confirm(`Are you sure you want to delete the preset "${selected}"?`)) return; // Remove from localStorage let currentPresets = JSON.parse(localStorage.getItem('user_presets') || '{}'); delete currentPresets[selected]; localStorage.setItem('user_presets', JSON.stringify(currentPresets)); // Remove from dropdown const optionToRemove = document.querySelector(`#presetDropdown option[value="${selected}"]`); if (optionToRemove) optionToRemove.remove(); // Reset to first preset const dropdown = document.getElementById('presetDropdown'); dropdown.selectedIndex = 0; localStorage.setItem('custom_preset_choice', dropdown.value); applyPreset(dropdown.value); alert(`Preset "${selected}" deleted.`); }); modelField.parentElement.insertBefore(deleteButton, modelField); }; // Observe for DOM changes to catch settings panel reloads const observer = new MutationObserver(() => { injectDropdown(); }); // Start observing once the body is ready const startObserver = () => { const target = document.body; if (!target) return setTimeout(startObserver, 200); observer.observe(target, { childList: true, subtree: true }); injectDropdown(); }; startObserver(); })();