180 lines
5.6 KiB
Python
180 lines
5.6 KiB
Python
import json
|
|
import os
|
|
from pathlib import Path
|
|
import folder_paths
|
|
from server import PromptServer
|
|
from aiohttp import web
|
|
import aiohttp
|
|
|
|
from .src.config_reader import ConfigReader
|
|
from .src.save_preview_image import SavePreviewImage
|
|
from .src.util import get_preview_image_path
|
|
|
|
WEB_DIRECTORY = "./web"
|
|
API_PREFIX = "/SyntaxHighlighting"
|
|
NODE_PREFIX = "SyntaxHighlighting_"
|
|
NODE_CLASS_MAPPINGS = {
|
|
f"{NODE_PREFIX}SavePreviewImage": SavePreviewImage,
|
|
}
|
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
f"{NODE_PREFIX}SavePreviewImage": "Save Preview Image",
|
|
}
|
|
|
|
|
|
image_index = {}
|
|
|
|
|
|
def load_image_index():
|
|
images_dir = Path(get_preview_image_path())
|
|
json_path = images_dir.joinpath("images.json")
|
|
if not json_path.exists():
|
|
return {}
|
|
with open(json_path, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
return {img["filename"]: img["path"] for img in data.get("images", [])}
|
|
|
|
|
|
def reload_image_index():
|
|
global image_index
|
|
image_index.clear()
|
|
image_index.update(load_image_index())
|
|
|
|
|
|
def index_images():
|
|
"""
|
|
Create a JSON index of all images in the web/images directory and its subfolders.
|
|
"""
|
|
try:
|
|
images_dir = Path(get_preview_image_path())
|
|
if not images_dir.exists():
|
|
print(f"Warning: Directory not found: {images_dir}")
|
|
return {"success": False}
|
|
|
|
image_files = []
|
|
for ext in [".png", ".jpg", ".jpeg", ".webp"]:
|
|
image_files.extend(images_dir.rglob(f"*{ext}"))
|
|
print(f"Found {len(image_files)} images in {images_dir}")
|
|
|
|
images = []
|
|
for img_path in image_files:
|
|
images.append(
|
|
{
|
|
"filename": img_path.stem,
|
|
"path": str(img_path),
|
|
}
|
|
)
|
|
|
|
output = {"images": images, "count": len(images)}
|
|
json_path = images_dir.joinpath("images.json")
|
|
with open(json_path, "w", encoding="utf-8") as f:
|
|
json.dump(output, f, indent=2)
|
|
|
|
print(f"Created index with {len(images)} images at {json_path}")
|
|
return_data = {"success": True, "count": len(images)}
|
|
reload_image_index()
|
|
return return_data
|
|
|
|
except Exception as e:
|
|
print(f"Error creating image index: {str(e)}")
|
|
return {"success": False}
|
|
|
|
|
|
index_images()
|
|
|
|
|
|
@PromptServer.instance.routes.get(f"{API_PREFIX}/loras")
|
|
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.get(f"{API_PREFIX}/embeddings")
|
|
async def get_embeddings(request):
|
|
embeddings = folder_paths.get_filename_list("embeddings")
|
|
return web.json_response(list(map(lambda a: os.path.splitext(a)[0], embeddings)))
|
|
|
|
|
|
@PromptServer.instance.routes.get(f"{API_PREFIX}/enabled")
|
|
async def get_enabled(request):
|
|
return web.json_response({"enabled": True})
|
|
|
|
|
|
@PromptServer.instance.routes.get(f"{API_PREFIX}/index")
|
|
async def index_images_endpoint(request):
|
|
data = index_images()
|
|
reload_image_index()
|
|
return web.json_response(data)
|
|
|
|
|
|
@PromptServer.instance.routes.get(f"{API_PREFIX}/favorites")
|
|
async def favorites_endpoint(request):
|
|
favorites = ConfigReader.get_setting("SyntaxHighlighting.favorites", [])
|
|
return web.json_response({"favorites": favorites})
|
|
|
|
|
|
@PromptServer.instance.routes.get(f"{API_PREFIX}/images_json")
|
|
async def serve_images_json(request):
|
|
images_dir = Path(get_preview_image_path())
|
|
json_path = images_dir.joinpath("images.json")
|
|
if json_path.exists():
|
|
return web.FileResponse(path=json_path)
|
|
return web.Response(status=404, text="images.json not found")
|
|
|
|
|
|
@PromptServer.instance.routes.get(f"{API_PREFIX}/images/{{filename}}")
|
|
async def serve_image(request):
|
|
filename = request.match_info["filename"]
|
|
if not filename:
|
|
return web.Response(status=400, text="Filename is required")
|
|
|
|
img_path = image_index.get(filename)
|
|
if img_path and Path(img_path).exists():
|
|
return web.FileResponse(path=img_path)
|
|
return web.Response(status=404, text="Image not found")
|
|
|
|
|
|
@PromptServer.instance.routes.get(f"{API_PREFIX}/wiki/{{tag}}")
|
|
async def fetch_wiki_page(request):
|
|
"""
|
|
Proxy endpoint to fetch Danbooru wiki pages.
|
|
This avoids CSP violations by making the request server-side.
|
|
"""
|
|
tag = request.match_info["tag"]
|
|
if not tag:
|
|
return web.Response(status=400, text="Tag is required")
|
|
|
|
# Clean the tag similar to frontend logic
|
|
tag = tag.strip()
|
|
|
|
url = f"https://danbooru.donmai.us/wiki_pages/{tag}"
|
|
|
|
try:
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as response:
|
|
if response.status != 200:
|
|
return web.json_response({
|
|
"success": False,
|
|
"error": {
|
|
"status": response.status,
|
|
"message": f"HTTP error! status: {response.status}",
|
|
"url": url,
|
|
}
|
|
}, status=response.status)
|
|
|
|
html_content = await response.text()
|
|
return web.json_response({
|
|
"success": True,
|
|
"data": html_content
|
|
})
|
|
except aiohttp.ClientError as e:
|
|
return web.json_response({ "success": False, "error": { "message": str(e), "url": url, }
|
|
}, status=500)
|
|
except Exception as e:
|
|
return web.json_response({
|
|
"success": False,
|
|
"error": {
|
|
"message": f"Unexpected error: {str(e)}",
|
|
"url": url,
|
|
}
|
|
}, status=500)
|