// ==UserScript==
// @name NovelAI 自动点击与保存
// @namespace http://tampermonkey.net/
// @version 1.0
// @description nai生成器.
// @author BK927 5sigma二次修改
// @match https://novelai.net/image
// @icon https://www.google.com/s2/favicons?sz=64&domain=novelai.net
// @grant none
// @license MIT
// ==/UserScript==
(function() {
// 添加CSS进行造型
const style = document.createElement('style');
style.innerHTML = `
#autoClickerContainer {
position: fixed;
display:flex;
flex-direction: column;
bottom: 10px;
right: 10px;
z-index: 1000;
border: 1px solid black;
padding: 10px;
border-radius: 10px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
white-space: nowrap;
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
font-size: 1rem;
color: #666;
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, 0.7);
}
#autoClickerContainer:hover {
cursor: move;
}
#autoClickerContainer:active {
cursor: move;
}
#autoClickerContainer > * {
margin : 5px;
}
#checkboxContainer {
display: flex;
justify-content: space-around;
}
#checkboxContainer > label > input {
width:1rem;
appearance: none;
background-color: #fafafa;
border: 1px solid #cacece;
padding: 0.5rem;
border-radius: 50%;
display: inline-block;
position: relative;
}
#checkboxContainer > label > input:active,
#checkboxContainer > label > input:checked:active {
box-shadow: 0 0 0 2px #ededed, 0 0 0 4px #cacece;
}
#checkboxContainer > label > input:checked {
background-color: #99ee90;
border: 0.5px solid green;
}
#checkboxContainer > label {
font-size: 1rem;
}
#autoClickerCheckbox {
margin-right: 5px;
}
#countdownContainer {
}
.inputField {
margin-left: 10px;
margin-right: 5px;
width: 50px;
padding: 3px;
border: 1px solid #ccc;
border-radius: 3px;
font-size: 0.8em;
}
`;
document.head.appendChild(style);
// 创建复选框和标签
const autoClickerContainer = document.createElement('div');
const checkboxContainer = document.createElement('div');
checkboxContainer.id = 'checkboxContainer';
autoClickerContainer.id = 'autoClickerContainer';
const autoClickLabel = document.createElement('label');
autoClickLabel.appendChild(document.createTextNode('🔄自动生成'));
const autoClickInput = document.createElement('input');
autoClickInput.setAttribute('type', 'checkbox');
autoClickLabel.appendChild(autoClickInput);
const autoSaveLabel = document.createElement('label');
autoSaveLabel.appendChild(document.createTextNode('💾自动保存'));
const autoSaveInput = document.createElement('input');
autoSaveInput.setAttribute('type', 'checkbox');
autoSaveLabel.appendChild(autoSaveInput);
checkboxContainer.appendChild(autoClickLabel);
checkboxContainer.appendChild(autoSaveLabel);
autoClickerContainer.appendChild(checkboxContainer);
// 创建剩余时间标记
const countdownContainer = document.createElement('div');
const countdownText = document.createElement('span');
countdownContainer.id = 'countdownContainer';
countdownText.textContent = '剩余时间: 0.0秒';
countdownContainer.appendChild(countdownText);
autoClickerContainer.appendChild(countdownContainer);
const minDelayInput = document.createElement('input');
minDelayInput.className = 'inputField';
minDelayInput.type = 'number';
minDelayInput.min = '0';
minDelayInput.value = '4'; // Default min delay
minDelayInput.placeholder = '最小等待时间';
const maxDelayInput = document.createElement('input');
maxDelayInput.className = 'inputField';
maxDelayInput.type = 'number';
maxDelayInput.min = '0';
maxDelayInput.value = '8'; // Default max delay
maxDelayInput.placeholder = '最大等待时间';
countdownContainer.appendChild(minDelayInput);
countdownContainer.appendChild(maxDelayInput);
document.body.appendChild(autoClickerContainer);
let autoClickIntervalId;
let countdownIntervalId; // 倒计时间隔的ID
let countdown; // 剩余时间(秒)
let scheduledFlag = false;
let imgSavedFlag = false; // 检查是否保存了图像
const dragItem = document.getElementById('autoClickerContainer');
let active = false;
let currentX;
let currentY;
let initialX;
let initialY;
let xOffset = 0;
let yOffset = 0;
// 创建一个新的隐藏/显示按钮
const toggleButton = document.createElement('button');
toggleButton.textContent = '隐藏/显示';
toggleButton.style.borderRadius = '5px'; // 按钮圆角
toggleButton.style.backgroundColor = '#007aff'; // 按钮背景颜色
toggleButton.style.color = 'white'; // 按钮文字颜色
toggleButton.style.border = 'none'; // 去掉按钮边框
toggleButton.style.padding = '5px 10px'; // 按钮内边距
autoClickerContainer.appendChild(toggleButton);
// 按钮点击事件,用于切换容器的可见性
toggleButton.addEventListener('click', () => {
const children = autoClickerContainer.children;
for (let i = 0; i < children.length; i++) {
if (children[i] !== toggleButton) {
children[i].style.display = children[i].style.display === 'none' ? 'block' : 'none';
}
}
});
// 创建一个新的元素来显示信息
const authorLabel = document.createElement('div');
authorLabel.style.position = 'absolute';
authorLabel.style.right = '10px';
authorLabel.style.bottom = '10px';
authorLabel.style.fontSize = '0.8em';
authorLabel.textContent = '5sigma ver2.0';
// 将我的标签添加到容器中
autoClickerContainer.appendChild(authorLabel);
// 拖动启动函数
function dragStart(e) {
if (e.type === "touchstart") {
initialX = e.touches[0].clientX - xOffset;
initialY = e.touches[0].clientY - yOffset;
} else {
initialX = e.clientX - xOffset;
initialY = e.clientY - yOffset;
}
if (dragItem.contains(e.target)) {
active = true;
}
}
// 正在拖动函数
function drag(e) {
if (active) {
e.preventDefault();
if (e.type === "touchmove") {
currentX = e.touches[0].clientX - initialX;
currentY = e.touches[0].clientY - initialY;
} else {
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
}
xOffset = currentX;
yOffset = currentY;
setTranslate(currentX, currentY, dragItem);
}
}
// 拖动结束函数
function dragEnd() {
initialX = currentX;
initialY = currentY;
active = false;
}
minDelayInput.addEventListener('change', () => {
const minDelay = parseFloat(minDelayInput.value);
const maxDelay = parseFloat(maxDelayInput.value);
if (minDelay > maxDelay) {
maxDelayInput.value = minDelay;
}
});
// 位置设置函数
function setTranslate(xPos, yPos, el) {
el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
}
// 添加事件侦听器
dragItem.addEventListener("mousedown", dragStart, false);
document.addEventListener("mouseup", dragEnd, false);
document.addEventListener("mousemove", drag, false);
// 添加触摸事件监听器
dragItem.addEventListener("touchstart", dragStart, false);
document.addEventListener("touchend", dragEnd, false);
document.addEventListener("touchmove", drag, false);
// 使用XPath选择按钮的函数
function getElementByXPath(xpath) {
const result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
return result.singleNodeValue;
}
// 按钮点击函数
function clickButton() {
const xpath = '//*[@id="__next"]/div[2]/div[4]/div[1]/div[5]/button';
const button = getElementByXPath(xpath);
if (button && !button.disabled && autoClickInput.checked) {
button.click();
scheduledFlag = false;
}
}
// 自动单击超时函数
function scheduleNextClick(delay) {
countdown = delay / 1000;
clearInterval(countdownIntervalId);
countdownIntervalId = setInterval(updateCountdownDisplay, 100); // 0.1每秒更新
setTimeout(() => {
imgSavedFlag = false;
clickButton();}, delay);
}
// 显示剩余时间的函数
function updateCountdownDisplay() {
countdown -= 0.1;
if (countdown < 0) {
clearInterval(countdownIntervalId);
countdown = 0;
}
countdownText.textContent = `剩余时间: ${countdown.toFixed(1)}秒`;
}
// 自动点击事件侦听器
autoClickInput.addEventListener('change', () => {
const button = getElementByXPath('//*[@id="__next"]/div[2]/div[4]/div[1]/div[5]/button');
if (autoClickInput.checked && button != null) {
clickButton(); // 运行第一次单击
// 间隔设置
autoClickIntervalId = setInterval(() => {
if (autoClickInput.checked && !button.disabled && !scheduledFlag && maxDelayInput.value !== '' && minDelayInput.value !== '') {
scheduledFlag = true;
const delay = Math.random() * parseFloat(maxDelayInput.value) * 1000 + parseFloat(minDelayInput.value) * 1000; // 随机延迟
scheduleNextClick(delay); // 开始下一次点击计划和倒计时
}
if(autoSaveInput.checked && !button.disabled && !imgSavedFlag){
const saveButton = getElementByXPath('//*[@id="__next"]/div[2]/div[4]/div[2]/div[2]/div[3]/div/div[3]/div/div[3]/button');
if(saveButton != null){
saveButton.click();
imgSavedFlag = true;
}
}
}, 500); // 0.5每秒重复
}
if(!autoClickInput.checked){
clearInterval(autoClickIntervalId);
}
});
// 检测暗夜模式
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
// 用户的操作系统处于暗夜模式
autoClickerContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
autoClickerContainer.style.color = 'white';
} else {
// 用户的操作系统处于明亮模式
autoClickerContainer.style.color = 'black';
}
// 监听颜色方案的改变
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
if (e.matches) {
// 用户的操作系统切换到了暗夜模式
autoClickerContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
autoClickerContainer.style.color = 'white';
} else {
// 用户的操作系统切换到了明亮模式
autoClickerContainer.style.backgroundColor = 'rgba(255, 255, 255, 0.7)';
autoClickerContainer.style.color = 'black';
}
});
})();