-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
956 additions
and
859 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import logging | ||
import mimetypes | ||
from pathlib import Path | ||
import re | ||
APP_NAME = "Flow" | ||
APP_VERSION = "0.4.6" | ||
FLOWMSG = f"\033[38;5;129mFlow - {APP_VERSION}\033[0m" | ||
APP_CONFIGS = [] | ||
|
||
CURRENT_DIR = Path(__file__).parent | ||
ROOT_DIR = CURRENT_DIR.parent | ||
WEBROOT = ROOT_DIR / "web" | ||
CORE_PATH = WEBROOT / "core" | ||
FLOW_PATH = WEBROOT / "flow" | ||
FLOWS_PATH = WEBROOT / "flows" | ||
LINKER_PATH = WEBROOT / "linker" | ||
CUSTOM_THEMES_DIR = WEBROOT / 'custom-themes' | ||
WEB_DIRECTORY = "web/core/js/common/scripts" | ||
|
||
CUSTOM_NODES_DIR = ROOT_DIR.parent | ||
EXTENSION_NODE_MAP_PATH = ROOT_DIR.parent / "ComfyUI-Manager" / "extension-node-map.json" | ||
|
||
FLOWS_DOWNLOAD_PATH = 'https://github.com/diStyApps/flows_lib' | ||
|
||
SAFE_FOLDER_NAME_REGEX = re.compile(r'^[\w\-]+$') | ||
ALLOWED_EXTENSIONS = {'css'} | ||
mimetypes.add_type('application/javascript', '.js') | ||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') | ||
logger = logging.getLogger(__name__) | ||
FLOWS_CONFIG_FILE = 'flowConfig.json' | ||
FLOWS_TO_REMOVE = [ | ||
"afl_CogVideoX-Fun-i2v-es", | ||
"afl_CogVideoX-Fun-i2v", | ||
"afl_MimicMotioni2v", | ||
"afl_abase", | ||
"afl_abasei2i", | ||
"afl_abasesd35t3v", | ||
"afl_abasevea", | ||
"afl_abaseveai2i", | ||
"afl_base-fluxd_at2i", | ||
"afl_base-fluxdggufi2i", | ||
"afl_base-fluxdgguft2i", | ||
"afl_base-fluxdi2i", | ||
"afl_base-fluxs_ai2t", | ||
"afl_base-fluxsi2i", | ||
"afl_baseAD", | ||
"afl_baseAdLcm", | ||
"afl_cogvidx_at2v", | ||
"afl_cogvidxi2v", | ||
"afl_cogvidxinteri2v", | ||
"afl_flowup", | ||
"afl_flux_dev", | ||
"afl_flux_dev_lora", | ||
"afl_genfill", | ||
"afl_ipivsMorph", | ||
"afl_mochi2v", | ||
"afl_pulid_flux", | ||
"afl_pulid_flux_GGUF", | ||
"afl_reactor" | ||
"5otvy-cogvideox-orbit-left-lora", | ||
] | ||
|
||
NODE_CLASS_MAPPINGS = {} | ||
NODE_DISPLAY_NAME_MAPPINGS = {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import subprocess | ||
import tempfile | ||
import shutil | ||
from pathlib import Path | ||
from .constants import FLOWS_DOWNLOAD_PATH, FLOWS_PATH, FLOWS_TO_REMOVE, FLOWMSG, logger | ||
|
||
def download_update_flows() -> None: | ||
try: | ||
for flow in FLOWS_TO_REMOVE: | ||
flow_path = FLOWS_PATH / flow | ||
if flow_path.exists() and flow_path.is_dir(): | ||
# logger.info(f"{FLOWMSG}: Removing existing flow directory '{flow}'") | ||
shutil.rmtree(flow_path) | ||
# logger.debug(f"{FLOWMSG}: Successfully removed '{flow}'") | ||
|
||
with tempfile.TemporaryDirectory() as tmpdirname: | ||
temp_repo_path = Path(tmpdirname) / "Flows" | ||
logger.info(f"{FLOWMSG}: Downloading and Upading Flows") | ||
|
||
result = subprocess.run( | ||
['git', 'clone', FLOWS_DOWNLOAD_PATH, str(temp_repo_path)], | ||
capture_output=True, | ||
text=True | ||
) | ||
if result.returncode != 0: | ||
logger.error(f"{FLOWMSG}: Failed to clone flows repository:\n{result.stderr}") | ||
return | ||
else: | ||
# logger.debug(f"{FLOWMSG}: Successfully cloned flows repository") | ||
pass | ||
|
||
if not FLOWS_PATH.exists(): | ||
FLOWS_PATH.mkdir(parents=True) | ||
# logger.debug(f"{FLOWMSG}: Created flows directory at '{FLOWS_PATH}'") | ||
|
||
for item in temp_repo_path.iterdir(): | ||
if item.name in ['.git', '.github']: | ||
# logger.debug(f"{FLOWMSG}: Skipping directory '{item.name}'") | ||
continue | ||
dest_item = FLOWS_PATH / item.name | ||
if item.is_dir(): | ||
if dest_item.exists(): | ||
# logger.info(f"{FLOWMSG}: Updating existing directory '{item.name}'") | ||
_copy_directory(item, dest_item) | ||
else: | ||
shutil.copytree(item, dest_item) | ||
# logger.info(f"{FLOWMSG}: Copied new directory '{item.name}'") | ||
else: | ||
shutil.copy2(item, dest_item) | ||
# logger.info(f"{FLOWMSG}: Copied file '{item.name}'") | ||
|
||
logger.info(f"{FLOWMSG}: Flows have been updated successfully.") | ||
except Exception as e: | ||
logger.error(f"{FLOWMSG}: An error occurred while downloading or updating flows: {e}") | ||
|
||
def _copy_directory(src: Path, dest: Path) -> None: | ||
for item in src.iterdir(): | ||
if item.name in ['.git', '.github']: | ||
continue | ||
dest_item = dest / item.name | ||
if item.is_dir(): | ||
if not dest_item.exists(): | ||
dest_item.mkdir() | ||
_copy_directory(item, dest_item) | ||
else: | ||
shutil.copy2(item, dest_item) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import json | ||
from pathlib import Path | ||
from aiohttp import web | ||
from typing import Dict, Any | ||
from .constants import ( | ||
FLOWS_PATH, CORE_PATH, LINKER_PATH, FLOW_PATH, APP_CONFIGS, FLOWMSG,FLOWS_CONFIG_FILE, logger | ||
) | ||
from .route_manager import RouteManager | ||
from .api_handlers import ( | ||
list_themes_handler, get_theme_css_handler, flow_version_handler, | ||
apps_handler, extension_node_map_handler, | ||
install_package_handler, update_package_handler, uninstall_package_handler, | ||
installed_custom_nodes_handler, preview_flow_handler, | ||
reset_preview_handler, create_flow_handler, update_flow_handler, delete_flow_handler | ||
) | ||
|
||
class FlowManager: | ||
@staticmethod | ||
def setup_app_routes(app: web.Application) -> None: | ||
try: | ||
FlowManager._setup_flows_routes(app) | ||
|
||
FlowManager._setup_core_routes(app) | ||
|
||
FlowManager._setup_api_routes(app) | ||
|
||
FlowManager._setup_additional_routes(app) | ||
|
||
except Exception as e: | ||
logger.error(f"{FLOWMSG}: Failed to set up routes: {e}") | ||
|
||
@staticmethod | ||
def _setup_flows_routes(app: web.Application) -> None: | ||
for flow_dir in filter(lambda d: d.is_dir(), FLOWS_PATH.iterdir()): | ||
conf_file = flow_dir / FLOWS_CONFIG_FILE | ||
if not conf_file.is_file(): | ||
# logger.warning(f"{FLOWMSG}: Config file not found in {flow_dir}") | ||
continue | ||
|
||
conf = FlowManager._load_config(conf_file) | ||
flow_url = conf.get('url') | ||
if not flow_url: | ||
logger.warning(f"{FLOWMSG}: Missing 'url' in config for {flow_dir}") | ||
continue | ||
|
||
app.add_routes(RouteManager.create_routes(f"flow/{flow_url}", flow_dir)) | ||
APP_CONFIGS.append(conf) | ||
|
||
@staticmethod | ||
def _setup_core_routes(app: web.Application) -> None: | ||
if CORE_PATH.is_dir(): | ||
app.router.add_get('/core/css/themes/list', list_themes_handler) | ||
app.router.add_get('/core/css/themes/{filename}', get_theme_css_handler) | ||
app.router.add_static('/core/', path=CORE_PATH, name='core') | ||
|
||
@staticmethod | ||
def _setup_api_routes(app: web.Application) -> None: | ||
api_routes = [ | ||
(f'/flow/api/apps', 'GET', apps_handler), | ||
(f'/flow/api/extension-node-map', 'GET', extension_node_map_handler), | ||
(f'/flow/api/install-package', 'POST', install_package_handler), | ||
(f'/flow/api/update-package', 'POST', update_package_handler), | ||
(f'/flow/api/uninstall-package', 'POST', uninstall_package_handler), | ||
(f'/flow/api/flow-version', 'GET', flow_version_handler), | ||
(f'/flow/api/installed-custom-nodes', 'GET', installed_custom_nodes_handler), | ||
(f'/flow/api/preview-flow', 'POST', preview_flow_handler), | ||
(f'/flow/api/reset-preview', 'POST', reset_preview_handler), | ||
(f'/flow/api/create-flow', 'POST', create_flow_handler), | ||
(f'/flow/api/update-flow', 'POST', update_flow_handler), | ||
(f'/flow/api/delete-flow', 'DELETE', delete_flow_handler), | ||
] | ||
|
||
for path, method, handler in api_routes: | ||
if method == 'GET': | ||
app.router.add_get(path, handler) | ||
elif method == 'POST': | ||
app.router.add_post(path, handler) | ||
elif method == 'DELETE': | ||
app.router.add_delete(path, handler) | ||
|
||
@staticmethod | ||
def _setup_additional_routes(app: web.Application) -> None: | ||
if LINKER_PATH.is_dir(): | ||
app.add_routes(RouteManager.create_routes('flow/linker', LINKER_PATH)) | ||
if FLOW_PATH.is_dir(): | ||
app.add_routes(RouteManager.create_routes('flow', FLOW_PATH)) | ||
|
||
@staticmethod | ||
def _load_config(conf_file: Path) -> Dict[str, Any]: | ||
try: | ||
with conf_file.open('r') as f: | ||
return json.load(f) | ||
except json.JSONDecodeError as e: | ||
logger.error(f"{FLOWMSG}: Invalid JSON in {conf_file}: {e}") | ||
return {} | ||
except Exception as e: | ||
logger.error(f"{FLOWMSG}: Error loading config from {conf_file}: {e}") | ||
return {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
class Flow: | ||
def __init__(self): | ||
pass | ||
|
||
@classmethod | ||
def INPUT_TYPES(s): | ||
return { | ||
"required": { | ||
}, | ||
} | ||
|
||
RETURN_TYPES = ("Flow",) | ||
FUNCTION = "flow" | ||
CATEGORY = '🅓 diSty/Flow' | ||
def flow(self): | ||
return "Flow" | ||
|
||
NODE_CLASS_MAPPINGS = { | ||
"Flow": Flow | ||
} | ||
|
||
NODE_DISPLAY_NAME_MAPPINGS = { | ||
"Flow": "Flow" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# flow/route_manager.py | ||
|
||
from aiohttp import web | ||
from pathlib import Path | ||
|
||
class RouteManager: | ||
|
||
@staticmethod | ||
def create_routes(base_path: str, app_dir: Path) -> web.RouteTableDef: | ||
routes = web.RouteTableDef() | ||
index_html = app_dir / 'index.html' | ||
|
||
@routes.get(f"/{base_path}") | ||
async def serve_html(request: web.Request) -> web.FileResponse: | ||
return web.FileResponse(index_html) | ||
|
||
for static_dir in ['css', 'js', 'media']: | ||
static_path = app_dir / static_dir | ||
if static_path.is_dir(): | ||
routes.static(f"/{static_dir}/", path=static_path) | ||
|
||
routes.static(f"/{base_path}/", path=app_dir, show_index=False) | ||
return routes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from aiohttp import web | ||
import server | ||
from .flow_manager import FlowManager | ||
from .downloader import download_update_flows | ||
from .constants import FLOWMSG, logger | ||
|
||
def setup_server() -> None: | ||
try: | ||
server_instance = server.PromptServer.instance | ||
except Exception as e: | ||
logger.error(f"{FLOWMSG}: Failed to get server instance: {e}") | ||
return | ||
|
||
download_update_flows() | ||
|
||
try: | ||
FlowManager.setup_app_routes(server_instance.app) | ||
except Exception as e: | ||
logger.error(f"{FLOWMSG}: Failed to set up app routes: {e}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.