forked from gsusgg/ComfyUI_CozyGen
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.py
More file actions
174 lines (140 loc) · 6.59 KB
/
api.py
File metadata and controls
174 lines (140 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
from aiohttp import web
import os
import json
import folder_paths
from PIL import Image
import server # Import server for node_info
import uuid # For generating unique filenames
async def get_hello(request: web.Request) -> web.Response:
return web.json_response({"status": "success", "message": "Hello from the CozyGen API!"})
async def get_gallery_files(request: web.Request) -> web.Response:
subfolder = request.rel_url.query.get('subfolder', '')
try:
page = int(request.rel_url.query.get('page', '1'))
per_page = int(request.rel_url.query.get('per_page', '20'))
except ValueError:
return web.json_response({"error": "Invalid page or per_page parameter"}, status=400)
output_directory = folder_paths.get_output_directory()
# Security: Prevent directory traversal
gallery_path = os.path.normpath(os.path.join(output_directory, subfolder))
if not gallery_path.startswith(output_directory):
return web.json_response({"error": "Unauthorized path"}, status=403)
if not os.path.exists(gallery_path) or not os.path.isdir(gallery_path):
return web.json_response({"error": "Gallery directory not found"}, status=404)
items = os.listdir(gallery_path)
gallery_items = []
for item_name in items:
item_path = os.path.join(gallery_path, item_name)
if os.path.isdir(item_path):
mod_time = os.path.getmtime(item_path)
gallery_items.append({
"filename": item_name,
"type": "directory",
"subfolder": os.path.join(subfolder, item_name),
"mod_time": mod_time
})
elif item_name.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp', '.mp4', '.webm', '.mp3', '.wav', '.flac')):
mod_time = os.path.getmtime(item_path)
gallery_items.append({
"filename": item_name,
"type": "output",
"subfolder": subfolder,
"mod_time": mod_time
})
# Sort items: directories first, then by modification time
gallery_items.sort(key=lambda x: (x['type'] == 'directory', x.get('mod_time', 0)), reverse=True)
# Pagination
total_items = len(gallery_items)
total_pages = (total_items + per_page - 1) // per_page
start_index = (page - 1) * per_page
end_index = start_index + per_page
paginated_items = gallery_items[start_index:end_index]
# Remove mod_time before sending
for item in paginated_items:
if 'mod_time' in item:
del item['mod_time']
return web.json_response({
"items": paginated_items,
"page": page,
"per_page": per_page,
"total_pages": total_pages,
"total_items": total_items
})
async def upload_image(request: web.Request) -> web.Response:
reader = await request.multipart()
field = await reader.next()
if field.name != 'image':
return web.json_response({"error": "Expected field 'image'"}, status=400)
filename = field.filename
if not filename:
return web.json_response({"error": "No filename provided"}, status=400)
# Generate a unique filename to prevent collisions
unique_filename = f"{uuid.uuid4()}_{filename}"
# Save to the input directory of ComfyUI
input_dir = folder_paths.get_input_directory()
save_path = os.path.join(input_dir, unique_filename)
size = 0
with open(save_path, 'wb') as f:
while True:
chunk = await field.read_chunk()
if not chunk:
break
f.write(chunk)
size += len(chunk)
return web.json_response({"filename": unique_filename, "size": size})
async def get_workflow_list(request: web.Request) -> web.Response:
workflows_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "workflows")
if not os.path.exists(workflows_dir):
return web.json_response({"error": "Workflows directory not found"}, status=404)
workflow_files = [f for f in os.listdir(workflows_dir) if f.endswith('.json')]
return web.json_response({"workflows": workflow_files})
async def get_workflow_file(request: web.Request) -> web.Response:
filename = request.match_info.get('filename', '')
workflows_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "workflows")
workflow_path = os.path.join(workflows_dir, filename)
if not os.path.exists(workflow_path):
return web.json_response({"error": f"Workflow file '{filename}' not found"}, status=404)
try:
with open(workflow_path, 'r', encoding='utf-8') as f:
workflow_content = json.load(f)
return web.json_response(workflow_content)
except json.JSONDecodeError:
return web.json_response({"error": f"Invalid JSON in workflow file '{filename}'"}, status=400)
except Exception as e:
return web.json_response({"error": f"Error reading workflow file: {e}"}, status=500)
import comfy.samplers
# Get all valid model folder types from ComfyUI itself
valid_model_types = folder_paths.folder_names_and_paths.keys()
# A map for aliases to official folder_paths names
alias_map = {
"unet": "unet_gguf"
}
async def get_choices(request: web.Request) -> web.Response:
choice_type = request.rel_url.query.get('type', '')
if not choice_type:
return web.json_response({"error": "Missing 'type' query parameter"}, status=400)
# Alias map for backward compatibility
alias_map = {
"samplers_list": "sampler",
"schedulers_list": "scheduler",
"unet": "unet_gguf" # Example of another potential alias
}
resolved_choice_type = alias_map.get(choice_type, choice_type)
choices = []
if resolved_choice_type == "scheduler":
choices = comfy.samplers.KSampler.SCHEDULERS
elif resolved_choice_type == "sampler":
choices = comfy.samplers.KSampler.SAMPLERS
elif resolved_choice_type in valid_model_types:
choices = folder_paths.get_filename_list(resolved_choice_type)
else:
return web.json_response({"error": f"Invalid choice type: {choice_type}"}, status=400)
return web.json_response({"choices": choices})
routes = [
web.get('/cozygen/hello', get_hello),
web.get('/cozygen/gallery', get_gallery_files),
web.post('/cozygen/upload_image', upload_image),
web.get('/cozygen/workflows', get_workflow_list),
web.get('/cozygen/workflows/{filename}', get_workflow_file),
web.get('/cozygen/get_choices', get_choices),
]