// ==UserScript== // @name 通用ai插图脚本 // @namespace http://tampermonkey.net/ // @version 7 // @license MIT // @description 免费或者使用sd的api配合ai生成插图 // @author 从前跟你一样 // @grant unsafeWindow // @match https://www.perplexity.ai/search/* // @match *://*/* // @require https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js // @connect vagrantup.com // @grant unsafeWindow // @grant GM_xmlhttpRequest // @connect 此处换成你的电脑域名ip、不需要带端口。 // @connect 192.168.10.2 // @match *://*/* // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== //必须在connect填你的sd域名,也就是你电脑的ip地址(本地ip)或网址xxx.com (function() { 'use strict'; unsafeWindow.sd=true; //true 开启 false 关闭 使用sd 否则使用免费网站。sd启动器需要启用api功能。例如绘世启动器中 的高级选项 启用api选择开启。 unsafeWindow.url = "http://192.168.10.2:7860";//sd地址 记得要修改上面的connect 的sd域名才能访问 unsafeWindow.prompts = "highres"; //额外固定的提示词 nsfw? 也可以固定你要的 lora 。每次都会加载提示词后面。下面是反向提示词 unsafeWindow.negative_prompt = "bad proportions,out of focus,username,text,bad anatomy,lowres,worstquality,watermark,cropped,bad body,deformed,mutated,disfigured,poorly drawn face,mutated hands and fingers,malformed hands,poorly drawn hands,mutated hands,extra arms,extra limb,malformed limbs,missing limb,too many fingers,extra legs,bad feet,missing fingers,fused fingers,bad hands,acnes,floating limbs,disconnected limbs,long neck,long body,mutation,ugly,blurry,low quality,sketches,normal quality,monochrome,grayscale,signature,logo"; unsafeWindow.cfg_scale = 7;//关键词关联性 unsafeWindow.width = 512; //宽度 unsafeWindow.height = 512;//长度 unsafeWindow.restore_faces = false; //面部修复 unsafeWindow.steps = 20;//步数 unsafeWindow.sampler_name="DPM++ 2M" ; //采样方式 unsafeWindow.start="image ss";//检测ai输出的提示词以什么开头 会被去除;可以自定义。 unsafeWindow.end="quality";///检测ai输出的提示词以什么结尾,不去除,可以自定义。提示词会采用两者之间的文字。 async function replaceSpansWithImagesst() { var ps = document.getElementsByClassName("mes_text"); for (var i = 0; i < ps.length; i++) { var p = ps[i]; var linkText = p.textContent; var regex = new RegExp(`${unsafeWindow.start}(.*?)${unsafeWindow.end}`); var matches = linkText.match(regex); if(matches){ var targetText = matches[0]; var link = targetText.replace('image ss', ''); const button = document.createElement('button'); var uniqueId = "button_" + Math.random().toString(36).substr(2, 9); button.id = uniqueId; button.textContent = '生成图片'; button.dataset.link = link; p.innerHTML = p.innerHTML.replace(targetText, button.outerHTML); // alert(targetText); // 重新找到新创建的按钮 var newbutton = document.getElementById(uniqueId); const imgSpan = document.createElement('span'); newbutton.addEventListener('click', async function() { const url = unsafeWindow.url; const payload = { "prompt": this.dataset.link+" "+unsafeWindow.prompts, "negative_prompt": unsafeWindow.negative_prompt, "steps": unsafeWindow.steps, "sampler_name": unsafeWindow.sampler_name, "width": unsafeWindow.width, "height": unsafeWindow.height, "restore_faces": unsafeWindow.restore_faces, "cfg_scale":unsafeWindow.cfg_scale }; const urlObj = new URL(url+"/sdapi/v1/txt2img"); try { const response = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: urlObj, data: JSON.stringify(payload), headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" }, onload: function(response) { if (response.status >= 200 && response.status < 400) { resolve(response); } else { alert("请求URL:", response.finalUrl); alert("响应状态码:", response.status); alert("响应内容:", response.responseText); reject(new Error(`请求失败,状态码: ${response.status}`)); } }, onerror: function(error,response) { alert("请求错误。请检测地址是否正确.或sd已正确开启,sd启动器需要启用api功能。例如绘世启动器中 的高级选项 启用api选择开启。以及在// @connect 处填写sd所在的电脑ip。不需要带端口例如局域网为192.168.1.2,本机则是127.0.0.1"); reject(error); } }); }); const r = JSON.parse(response.responseText); for (let i of r['images']) { const png_payload = { "image": "data:image/png;base64," + i }; const response2 = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: `${url}/sdapi/v1/png-info`, data: JSON.stringify(png_payload), headers: { "Content-Type": "application/json" }, onload: resolve, onerror: reject }); }); const pngInfo = JSON.parse(response2.responseText).info; const dataURL = "data:image/png;base64," + i; const img = document.createElement('img'); img.src = dataURL; img.alt = "Generated Image"; img.dataset.parameters = pngInfo; imgSpan.innerHTML = ''; imgSpan.appendChild(img); } } catch (error) { console.error('Error generating image:', error); } }); // p.parentNode.replaceChild(button, span); newbutton.parentNode.insertBefore(imgSpan, button.nextSibling); } } } async function replaceSpansWithImagesfree() { var ps = document.getElementsByClassName("mes_text"); for (var i = 0; i < ps.length; i++) { var p = ps[i]; var linkText = p.textContent; var regex = new RegExp(`${unsafeWindow.start}(.*?)${unsafeWindow.end}`); var matches = linkText.match(regex); if(matches){ var targetText = matches[0]; var link = targetText.replace('image ss', ''); const button = document.createElement('button'); var uniqueId = "button_" + Math.random().toString(36).substr(2, 9); button.id = uniqueId; button.textContent = '生成图片'; button.dataset.link = link; p.innerHTML = p.innerHTML.replace(targetText, button.outerHTML); // alert(targetText); // 重新找到新创建的按钮 var newbutton = document.getElementById(uniqueId); const imgSpan = document.createElement('span'); newbutton.addEventListener('click', async function() { var ran = Math.floor(Math.random() * 10000).toString(); const prompt = this.dataset.link + " " +unsafeWindow.prompts+" "+ran; const url = `https://image.pollinations.ai/prompt/${encodeURIComponent(prompt)}`; const img = document.createElement('img'); img.src = url; img.alt = "Generated Image"; imgSpan.innerHTML = ''; imgSpan.appendChild(img); }); newbutton.parentNode.insertBefore(imgSpan, button.nextSibling); } } } if(unsafeWindow.sd){ setInterval(replaceSpansWithImagesst, 5000); }else{ setInterval(replaceSpansWithImagesfree, 5000); }; })();