Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
__pycache__
pysssss.json
user/autocomplete.txt
user/url.txt
web/js/assets/favicon.user.ico
web/js/assets/favicon-active.user.ico
web/js/assets/favicon-active.user.ico
40 changes: 35 additions & 5 deletions py/autocomplete.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
from server import PromptServer
from aiohttp import web
from aiohttp import web, ClientSession
import os
import folder_paths

dir = os.path.abspath(os.path.join(__file__, "../../user"))
if not os.path.exists(dir):
os.mkdir(dir)
file = os.path.join(dir, "autocomplete.txt")
tag_file = os.path.join(dir, "autocomplete.txt")
url_file = os.path.join(dir, "url.txt")


@PromptServer.instance.routes.get("/pysssss/autocomplete")
async def get_autocomplete(request):
if os.path.isfile(file):
return web.FileResponse(file)
if os.path.isfile(tag_file):
return web.FileResponse(tag_file)
return web.Response(status=404)


@PromptServer.instance.routes.post("/pysssss/autocomplete")
async def update_autocomplete(request):
with open(file, "w", encoding="utf-8") as f:
with open(tag_file, "w", encoding="utf-8") as f:
f.write(await request.text())
return web.Response(status=200)


@PromptServer.instance.routes.get("/pysssss/cwlUrl")
async def get_url(request):
if os.path.isfile(url_file):
return web.FileResponse(url_file)
return web.Response(status=404)


@PromptServer.instance.routes.post("/pysssss/cwlUrl")
async def update_url(request):
with open(url_file, "w", encoding="utf-8") as f:
f.write(await request.text())
return web.Response(status=200)

Expand All @@ -27,3 +42,18 @@ async def update_autocomplete(request):
async def get_loras(request):
loras = folder_paths.get_filename_list("loras")
return web.json_response(list(map(lambda a: os.path.splitext(a)[0], loras)))


@PromptServer.instance.routes.post("/pysssss/getWordList")
async def get_word_list(request):
proxies = await request.text()
if proxies:
session = ClientSession(proxy=proxies)
else:
session = ClientSession()
with open(url_file, "r", encoding="utf-8") as f:
url = f.read().strip()
async with session.get(url) as resp:
text = await resp.text()
await session.close()
return web.Response(text=text, status=200)
78 changes: 66 additions & 12 deletions web/js/autocompleter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { TextAreaAutoComplete } from "./common/autocomplete.js";
import { ModelInfoDialog } from "./common/modelInfoDialog.js";
import { LoraInfoDialog } from "./modelInfo.js";

const DEFAULT_CWL_URL = "https://gist.githubusercontent.com/pythongosssss/" +
"1d3efa6050356a08cea975183088159a/raw/" +
"a18fb2f94f9156cf4476b0c24a09544d6c0baec6/danbooru-tags.txt";

function parseCSV(csvText) {
const rows = [];
const delimiter = ",";
Expand Down Expand Up @@ -85,6 +89,30 @@ async function getCustomWords() {
return undefined;
}

/**
* 获取自定义词的URL
* @returns {string}
*/
async function getCWLUrl() {
const resp = await api.fetchApi("/pysssss/cwlUrl", { cache: "no-store" });
if (resp.status === 200) {
/** @type {string} */
let url = await resp.text();
return url;
}

return DEFAULT_CWL_URL;
}

/**
* 将自定义词的URL保存到服务器
* @param {string} url
*/
async function saveCWLUrl(url) {
const resp = await api.fetchApi("/pysssss/cwlUrl", { method: "POST", body: url });
return resp.status === 200;
}

async function addCustomWords(text) {
if (!text) {
text = await getCustomWords();
Expand Down Expand Up @@ -177,12 +205,13 @@ class CustomWordsDialog extends ComfyDialog {
},
});

const input = $el("input", {
this.cwlUrl = await getCWLUrl();

this.input = $el("input", {
style: {
flex: "auto",
},
value:
"https://gist.githubusercontent.com/pythongosssss/1d3efa6050356a08cea975183088159a/raw/a18fb2f94f9156cf4476b0c24a09544d6c0baec6/danbooru-tags.txt",
value: this.cwlUrl,
});

super.show(
Expand Down Expand Up @@ -219,17 +248,30 @@ class CustomWordsDialog extends ComfyDialog {
},
[
$el("label", { textContent: "Load Custom List: " }),
input,
this.input,
$el("button", {
textContent: "Load",
onclick: async () => {
try {
const res = await fetch(input.value);
if (res.status !== 200) {
throw new Error("Error loading: " + res.status + " " + res.statusText);
this.cwlUrl = this.input.value || DEFAULT_CWL_URL;
if (!await saveCWLUrl(this.cwlUrl)) {
throw new Error("Error saving URL!");
}
const res = await api.fetchApi("/pysssss/getWordList", {
method: "POST", cache: "no-store", body: app.extensionManager.setting.get(`${id}.Proxies`)
});
// const res = await fetch(this.cwlUrl, {
// method: "GET",
// headers: {
// "Access-Control-Allow-Origin": "*",
// }
// });
// if (res.status !== 200) {
// throw new Error("Error loading: " + res.status + " " + res.statusText);
// }
this.words.value = await res.text();
} catch (error) {
console.error(error);
alert("Error loading custom list, try manually copy + pasting the list");
}
},
Expand All @@ -249,6 +291,10 @@ class CustomWordsDialog extends ComfyDialog {
textContent: "Save",
onclick: async (e) => {
try {
this.cwlUrl = this.input.value;
if (!await saveCWLUrl(this.cwlUrl)) {
throw new Error("Error saving URL!");
}
const res = await api.fetchApi("/pysssss/autocomplete", { method: "POST", body: this.words.value });
if (res.status !== 200) {
throw new Error("Error saving: " + res.status + " " + res.statusText);
Expand All @@ -259,7 +305,6 @@ class CustomWordsDialog extends ComfyDialog {
save.textContent = "Save";
}, 500);
} catch (error) {
alert("Error saving word list!");
console.error(error);
}
},
Expand All @@ -274,6 +319,15 @@ const id = "pysssss.AutoCompleter";

app.registerExtension({
name: id,
settings: [
{
id: `${id}.Proxies`,
name: "Proxies",
type: "text",
defaultValue: "",
tooltip: "http://<addr>:<port>"
}
],
init() {
const STRING = ComfyWidgets.STRING;
const SKIP_WIDGETS = new Set(["ttN xyPlot.x_values", "ttN xyPlot.y_values"]);
Expand Down Expand Up @@ -494,9 +548,9 @@ app.registerExtension({
onclick: () => {
try {
// Try closing old settings window
if (typeof app.ui.settings.element?.close === "function") {
if (typeof app.ui.settings.element?.close === "function") {
app.ui.settings.element.close();
}
}
} catch (error) {
}
try {
Expand All @@ -506,7 +560,7 @@ app.registerExtension({
// Fallback to just hiding the element
app.ui.settings.element.style.display = "none";
}

new CustomWordsDialog().show();
},
style: {
Expand Down Expand Up @@ -549,7 +603,7 @@ app.registerExtension({
let loras;
try {
loras = LiteGraph.registered_node_types["LoraLoader"]?.nodeData.input.required.lora_name[0];
} catch (error) {}
} catch (error) { }

if (!loras?.length) {
loras = await api.fetchApi("/pysssss/loras", { cache: "no-store" }).then((res) => res.json());
Expand Down