fix: true overwrite_last for video node + webhook URL sanitization in JSON
- Implemented true 'overwrite last' for video node: finds most recently modified video file and overwrites it regardless of filename - Fixed missing sanitize_json_for_export import in video_node.py - Added sanitize_json_for_export to image_node.py for all workflow JSON exports - Merged upstream changes: process_batched_images, validate_path_is_safe, format_ext sanitization
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@ current_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
if current_dir not in sys.path:
|
||||
sys.path.insert(0, current_dir)
|
||||
|
||||
# Import nodes from nodes package
|
||||
# Import nodes from nodes package using relative imports
|
||||
from .nodes.image_node import DiscordSendSaveImage
|
||||
from .nodes.video_node import DiscordSendSaveVideo
|
||||
|
||||
|
||||
+7
-2
@@ -17,7 +17,8 @@ from typing import Any, Union, List, Optional
|
||||
from shared import (
|
||||
sanitize_token_from_text,
|
||||
process_batched_images,
|
||||
validate_path_is_safe
|
||||
validate_path_is_safe,
|
||||
sanitize_json_for_export
|
||||
)
|
||||
|
||||
|
||||
@@ -452,6 +453,8 @@ class DiscordSendSaveImage(BaseDiscordNode):
|
||||
if send_workflow_json and (prompt is not None or extra_pnginfo is not None):
|
||||
wflow = self.extract_workflow_from_metadata(original_prompt, original_extra_pnginfo)
|
||||
if wflow:
|
||||
# Sanitize to remove webhook URLs and tokens
|
||||
wflow = sanitize_json_for_export(wflow)
|
||||
json_filename = f"{os.path.splitext(discord_filename)[0]}.json"
|
||||
files["workflow"] = (json_filename, json.dumps(wflow, indent=2).encode('utf-8'))
|
||||
|
||||
@@ -503,8 +506,10 @@ class DiscordSendSaveImage(BaseDiscordNode):
|
||||
files[f"file{i}"] = (filename, file_bytes)
|
||||
|
||||
if send_workflow_json and batch_workflow_json:
|
||||
# Sanitize to remove webhook URLs and tokens
|
||||
sanitized_workflow = sanitize_json_for_export(batch_workflow_json)
|
||||
json_filename = f"workflow-{uuid4()}.json"
|
||||
json_data = json.dumps(batch_workflow_json, indent=2)
|
||||
json_data = json.dumps(sanitized_workflow, indent=2)
|
||||
files["workflow"] = (json_filename, json_data.encode('utf-8'))
|
||||
|
||||
success, response, new_urls = self.send_discord_files(webhook_url, files, batch_discord_data, save_cdn_urls)
|
||||
|
||||
+81
-11
@@ -26,7 +26,8 @@ from shared import (
|
||||
tensor_to_numpy_uint8,
|
||||
process_batched_images,
|
||||
build_metadata_section,
|
||||
validate_path_is_safe
|
||||
validate_path_is_safe,
|
||||
sanitize_json_for_export
|
||||
)
|
||||
# Add BaseDiscordNode import
|
||||
from .base_node import BaseDiscordNode
|
||||
@@ -262,9 +263,28 @@ class DiscordSendSaveVideo(BaseDiscordNode):
|
||||
# 2. Build filename prefix with metadata using base class method
|
||||
height, width = images[0].shape[0], images[0].shape[1]
|
||||
video_info = {}
|
||||
filename_prefix, video_info = self.build_filename_prefix(
|
||||
filename_prefix, add_date, add_time, add_dimensions, width, height
|
||||
)
|
||||
# When overwrite_last is enabled, don't add date/time/dimensions to filename
|
||||
# as these would create unique filenames each run, defeating the overwrite purpose
|
||||
# We still collect video_info for Discord message display
|
||||
if overwrite_last:
|
||||
# Just use the plain prefix for overwriting, but still collect metadata for display
|
||||
filename_prefix, video_info = self.build_filename_prefix(
|
||||
filename_prefix, False, False, False, width, height
|
||||
)
|
||||
# Add the metadata values manually for Discord display if needed
|
||||
if add_date or add_time:
|
||||
import datetime as dt
|
||||
now = dt.datetime.now()
|
||||
if add_date:
|
||||
video_info["date"] = now.strftime("%Y-%m-%d")
|
||||
if add_time:
|
||||
video_info["time"] = now.strftime("%H-%M-%S")
|
||||
if add_dimensions:
|
||||
video_info["dimensions"] = f"{width}x{height}"
|
||||
else:
|
||||
filename_prefix, video_info = self.build_filename_prefix(
|
||||
filename_prefix, add_date, add_time, add_dimensions, width, height
|
||||
)
|
||||
|
||||
# Add prefix append
|
||||
filename_prefix += self.prefix_append
|
||||
@@ -275,11 +295,47 @@ class DiscordSendSaveVideo(BaseDiscordNode):
|
||||
# Setup paths using ComfyUI's path validation
|
||||
full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path(
|
||||
filename_prefix, dest_folder, images[0].shape[1], images[0].shape[0])
|
||||
|
||||
# Process format string (need this early for overwrite detection)
|
||||
format_type, format_ext = format.split("/")
|
||||
|
||||
# Handle special format extensions
|
||||
if format == "video/h264-mp4" or format == "video/h265-mp4":
|
||||
format_ext = "mp4"
|
||||
elif format == "video/vp9-webm":
|
||||
format_ext = "webm"
|
||||
elif format == "video/prores":
|
||||
format_ext = "mov"
|
||||
|
||||
# Video extensions to look for when finding last video
|
||||
video_extensions = {'.mp4', '.webm', '.gif', '.mov', '.webp'}
|
||||
|
||||
# For overwrite functionality
|
||||
# For TRUE overwrite functionality - find the most recently modified video file
|
||||
overwrite_target_path = None
|
||||
if overwrite_last:
|
||||
counter = 1 # Always use the same counter value for overwriting
|
||||
print("Overwrite mode enabled: will overwrite last video with same name")
|
||||
try:
|
||||
# Find all video files in the output folder
|
||||
video_files = []
|
||||
for f in os.listdir(full_output_folder):
|
||||
file_path_check = os.path.join(full_output_folder, f)
|
||||
if os.path.isfile(file_path_check):
|
||||
ext = os.path.splitext(f)[1].lower()
|
||||
if ext in video_extensions:
|
||||
# Get modification time
|
||||
mtime = os.path.getmtime(file_path_check)
|
||||
video_files.append((file_path_check, mtime))
|
||||
|
||||
if video_files:
|
||||
# Sort by modification time (most recent first)
|
||||
video_files.sort(key=lambda x: x[1], reverse=True)
|
||||
overwrite_target_path = video_files[0][0]
|
||||
print(f"Overwrite mode: Found most recent video to overwrite: {overwrite_target_path}")
|
||||
else:
|
||||
print("Overwrite mode: No existing video files found, will create new file")
|
||||
counter = 1 # Fallback to counter 1 for new file
|
||||
except Exception as e:
|
||||
print(f"Overwrite mode: Error finding last video: {e}, will create new file")
|
||||
counter = 1
|
||||
|
||||
# Set metadata
|
||||
metadata = PngInfo()
|
||||
@@ -336,8 +392,16 @@ class DiscordSendSaveVideo(BaseDiscordNode):
|
||||
image_sequence = images
|
||||
|
||||
# Set up file naming and path
|
||||
file = f"{filename}_{counter:05}.{format_ext}"
|
||||
file_path = os.path.join(full_output_folder, file)
|
||||
if overwrite_target_path:
|
||||
# Use the found video file path for overwriting
|
||||
file_path = overwrite_target_path
|
||||
file = os.path.basename(file_path)
|
||||
# Update format_ext to match the target file's extension
|
||||
format_ext = os.path.splitext(file)[1].lstrip('.')
|
||||
print(f"Overwrite mode enabled: will overwrite {file_path}")
|
||||
else:
|
||||
file = f"{filename}_{counter:05}.{format_ext}"
|
||||
file_path = os.path.join(full_output_folder, file)
|
||||
|
||||
# Security: Validate output path to prevent symlink overwrites
|
||||
validate_path_is_safe(file_path)
|
||||
@@ -520,8 +584,11 @@ class DiscordSendSaveVideo(BaseDiscordNode):
|
||||
image_chunks = process_batched_images(image_sequence)
|
||||
|
||||
# Base ffmpeg arguments
|
||||
# Add -y flag if overwrite_last is enabled to force overwrite existing files
|
||||
overwrite_flag = ["-y"] if overwrite_last else []
|
||||
args = [
|
||||
ffmpeg_path, "-v", "error",
|
||||
ffmpeg_path, "-v", "error"
|
||||
] + overwrite_flag + [
|
||||
"-f", "rawvideo",
|
||||
"-pix_fmt", i_pix_fmt,
|
||||
"-s", dimensions,
|
||||
@@ -593,8 +660,11 @@ class DiscordSendSaveVideo(BaseDiscordNode):
|
||||
bitrate_arg = ["-b:v", f"{bitrate}M"]
|
||||
|
||||
# Base ffmpeg arguments
|
||||
# Add -y flag if overwrite_last is enabled to force overwrite existing files
|
||||
overwrite_flag = ["-y"] if overwrite_last else []
|
||||
args = [
|
||||
ffmpeg_path, "-v", "error",
|
||||
ffmpeg_path, "-v", "error"
|
||||
] + overwrite_flag + [
|
||||
"-f", "rawvideo",
|
||||
"-pix_fmt", i_pix_fmt,
|
||||
"-s", dimensions,
|
||||
|
||||
Reference in New Issue
Block a user