fix #3
This commit is contained in:
+16
-1
@@ -8,12 +8,14 @@ import os
|
|||||||
import folder_paths
|
import folder_paths
|
||||||
import bcrypt
|
import bcrypt
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
node_dir = os.path.dirname(__file__)
|
node_dir = os.path.dirname(__file__)
|
||||||
comfy_dir = os.path.dirname(folder_paths.__file__)
|
comfy_dir = os.path.dirname(folder_paths.__file__)
|
||||||
password_path = os.path.join(comfy_dir, "PASSWORD")
|
password_path = os.path.join(comfy_dir, "PASSWORD")
|
||||||
secret_key_path = os.path.join(node_dir,'.secret-key.txt')
|
secret_key_path = os.path.join(node_dir,'.secret-key.txt')
|
||||||
KEY_AGE_LIMIT = timedelta(days=30) # Key expiration period
|
KEY_AGE_LIMIT = timedelta(days=30) # Key expiration period
|
||||||
|
TOKEN = ""
|
||||||
|
|
||||||
def generate_key():
|
def generate_key():
|
||||||
return base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8')
|
return base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8')
|
||||||
@@ -89,6 +91,17 @@ async def get_root(request):
|
|||||||
response = web.HTTPFound('/login') # Redirect to the main page if the password is correct
|
response = web.HTTPFound('/login') # Redirect to the main page if the password is correct
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def load_token():
|
||||||
|
global TOKEN
|
||||||
|
try:
|
||||||
|
with open(password_path, "r", encoding="utf-8") as f:
|
||||||
|
TOKEN = f.read()
|
||||||
|
logging.info(f"For direct API calls, use token={TOKEN}")
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
logging.error("Please set up your password before use. The token will be a hashed string derived from your password.")
|
||||||
|
TOKEN = ""
|
||||||
|
load_token()
|
||||||
|
|
||||||
# For loading all custom js
|
# For loading all custom js
|
||||||
WEB_DIRECTORY = "js"
|
WEB_DIRECTORY = "js"
|
||||||
|
|
||||||
@@ -99,7 +112,9 @@ async def check_login_status(request: web.Request, handler):
|
|||||||
response = await handler(request)
|
response = await handler(request)
|
||||||
return response
|
return response
|
||||||
session = await get_session(request)
|
session = await get_session(request)
|
||||||
if ('logged_in' in session and session['logged_in']):
|
if TOKEN == "":
|
||||||
|
load_token()
|
||||||
|
if (request.query.get("token") == TOKEN) or ('logged_in' in session and session['logged_in']):
|
||||||
response = await handler(request)
|
response = await handler(request)
|
||||||
if request.path == '/': # This avoids seeing the GUI after logging out and navigating back immediately.
|
if request.path == '/': # This avoids seeing the GUI after logging out and navigating back immediately.
|
||||||
response.headers.setdefault('Cache-Control', 'no-cache')
|
response.headers.setdefault('Cache-Control', 'no-cache')
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
#This is an example that uses the websockets api to know when a prompt execution is done
|
||||||
|
#Once the prompt execution is done it downloads the images using the /history endpoint
|
||||||
|
|
||||||
|
import websocket #NOTE: websocket-client (https://github.com/websocket-client/websocket-client)
|
||||||
|
import uuid
|
||||||
|
import json
|
||||||
|
import urllib.request
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
server_address = "127.0.0.1:8188"
|
||||||
|
client_id = str(uuid.uuid4())
|
||||||
|
# TOKEN is stored in the file `./PASSWORD`, or you can obtain it from the command line window when ComfyUI starts.
|
||||||
|
# It will appear like this:
|
||||||
|
# For direct API calls, token=$2b$12$qUfJfV942nrMiX77QRVgIuDk1.oyXBP7FYrXVEBqouTk.uP/hiqAK
|
||||||
|
TOKEN = "$2b$12$qUfJfV942nrMiX77QRVgIuDk1.oyXBP7FYrXVEBqouTk.uP/hiqAK"
|
||||||
|
|
||||||
|
def queue_prompt(prompt):
|
||||||
|
p = {"prompt": prompt, "client_id": client_id}
|
||||||
|
data = json.dumps(p).encode('utf-8')
|
||||||
|
req = urllib.request.Request("http://{}/prompt?token={}".format(server_address, TOKEN), data=data)
|
||||||
|
return json.loads(urllib.request.urlopen(req).read())
|
||||||
|
|
||||||
|
def get_image(filename, subfolder, folder_type):
|
||||||
|
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
|
||||||
|
url_values = urllib.parse.urlencode(data)
|
||||||
|
with urllib.request.urlopen("http://{}/view?{}&token={}".format(server_address, url_values, TOKEN)) as response:
|
||||||
|
return response.read()
|
||||||
|
|
||||||
|
def get_history(prompt_id):
|
||||||
|
with urllib.request.urlopen("http://{}/history/{}?token={}".format(server_address, prompt_id, TOKEN)) as response:
|
||||||
|
return json.loads(response.read())
|
||||||
|
|
||||||
|
def get_images(ws, prompt):
|
||||||
|
prompt_id = queue_prompt(prompt)['prompt_id']
|
||||||
|
output_images = {}
|
||||||
|
while True:
|
||||||
|
out = ws.recv()
|
||||||
|
if isinstance(out, str):
|
||||||
|
message = json.loads(out)
|
||||||
|
if message['type'] == 'executing':
|
||||||
|
data = message['data']
|
||||||
|
if data['node'] is None and data['prompt_id'] == prompt_id:
|
||||||
|
break #Execution is done
|
||||||
|
else:
|
||||||
|
continue #previews are binary data
|
||||||
|
|
||||||
|
history = get_history(prompt_id)[prompt_id]
|
||||||
|
for o in history['outputs']:
|
||||||
|
for node_id in history['outputs']:
|
||||||
|
node_output = history['outputs'][node_id]
|
||||||
|
if 'images' in node_output:
|
||||||
|
images_output = []
|
||||||
|
for image in node_output['images']:
|
||||||
|
image_data = get_image(image['filename'], image['subfolder'], image['type'])
|
||||||
|
images_output.append(image_data)
|
||||||
|
output_images[node_id] = images_output
|
||||||
|
|
||||||
|
return output_images
|
||||||
|
|
||||||
|
prompt_text = """
|
||||||
|
{
|
||||||
|
"3": {
|
||||||
|
"class_type": "KSampler",
|
||||||
|
"inputs": {
|
||||||
|
"cfg": 8,
|
||||||
|
"denoise": 1,
|
||||||
|
"latent_image": [
|
||||||
|
"5",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"model": [
|
||||||
|
"4",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"negative": [
|
||||||
|
"7",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"positive": [
|
||||||
|
"6",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"sampler_name": "euler",
|
||||||
|
"scheduler": "normal",
|
||||||
|
"seed": 8566257,
|
||||||
|
"steps": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"class_type": "CheckpointLoaderSimple",
|
||||||
|
"inputs": {
|
||||||
|
"ckpt_name": "v1-5-pruned-emaonly.ckpt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"5": {
|
||||||
|
"class_type": "EmptyLatentImage",
|
||||||
|
"inputs": {
|
||||||
|
"batch_size": 1,
|
||||||
|
"height": 512,
|
||||||
|
"width": 512
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"class_type": "CLIPTextEncode",
|
||||||
|
"inputs": {
|
||||||
|
"clip": [
|
||||||
|
"4",
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"text": "masterpiece best quality girl"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"7": {
|
||||||
|
"class_type": "CLIPTextEncode",
|
||||||
|
"inputs": {
|
||||||
|
"clip": [
|
||||||
|
"4",
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"text": "bad hands"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"8": {
|
||||||
|
"class_type": "VAEDecode",
|
||||||
|
"inputs": {
|
||||||
|
"samples": [
|
||||||
|
"3",
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"vae": [
|
||||||
|
"4",
|
||||||
|
2
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"9": {
|
||||||
|
"class_type": "SaveImage",
|
||||||
|
"inputs": {
|
||||||
|
"filename_prefix": "ComfyUI",
|
||||||
|
"images": [
|
||||||
|
"8",
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
prompt = json.loads(prompt_text)
|
||||||
|
#set the text prompt for our positive CLIPTextEncode
|
||||||
|
prompt["6"]["inputs"]["text"] = "masterpiece best quality man"
|
||||||
|
|
||||||
|
#set the seed for our KSampler node
|
||||||
|
prompt["3"]["inputs"]["seed"] = 5
|
||||||
|
|
||||||
|
ws = websocket.WebSocket()
|
||||||
|
ws.connect("ws://{}/ws?clientId={}&token={}".format(server_address, client_id, TOKEN))
|
||||||
|
images = get_images(ws, prompt)
|
||||||
|
|
||||||
|
#Commented out code to display the output images:
|
||||||
|
|
||||||
|
for node_id in images:
|
||||||
|
for image_data in images[node_id]:
|
||||||
|
from PIL import Image
|
||||||
|
import io
|
||||||
|
image = Image.open(io.BytesIO(image_data))
|
||||||
|
image.show()
|
||||||
|
|
||||||
Reference in New Issue
Block a user