Commit Graph
147 Commits
Author SHA1 Message Date
AEmotionStudioandClaude Opus 4.5 618b9ae4bb docs(prd): update PRD to reflect phases 1-4 completion
- Mark phases 1-4 as complete with commit references
- Add phase 4.1 for PR review bug fixes (5 issues)
- Update success metrics with actual line counts:
  - Image node: 986 → 836 (-15%)
  - Video node: 1562 → 1092 (-30%)
  - Total: 2548 → 1928 (-24%)
  - Utility modules: 6 → 17
- Update change log with all phase completions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 03:22:18 -08:00
AEmotionStudioandClaude Opus 4.5 0d6ed9d9c5 fix(message_builder): add trailing newline to metadata section
The build_metadata_section function used "\n".join(metadata_lines)
which lacks a trailing newline. When dimensions were appended later,
they concatenated directly without proper spacing, producing malformed
output like "**Format:** PNG**Original Dimensions:** 1024x1024".

Added trailing newline so subsequent content appears on a new line.

Fixes issue identified in PR #35 review.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 03:07:13 -08:00
AEmotionStudioandClaude Opus 4.5 cc07d20f86 fix(image_node): prevent redundant CDN URL sends on 204 responses
The refactored code checked only `if save_cdn_urls:` instead of the
original `if save_cdn_urls and response.status_code == 200:`. While
extract_cdn_urls_from_response correctly returns empty for 204 responses,
accumulated URLs from prior iterations could still trigger the
`if batch_cdn_urls:` condition, causing duplicate sends.

Fixed in both individual image send and batch send sections.

Fixes issue identified in PR #35 review.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 02:54:58 -08:00
AEmotionStudioandClaude Opus 4.5 36c5d06cf8 fix(prompt_extractor): restore SDXL workflow prompt extraction support
The refactored prompt extractor only detected CLIPTextEncode nodes,
losing support for SDXL-specific nodes that was present in the original
code. This caused SDXL workflows using SDXLPromptEncoder or SDXLTextEncode
nodes to not have their prompts included in Discord messages.

Changes:
- Add PROMPT_NODE_TYPES list with CLIPTextEncode, SDXLPromptEncoder,
  and SDXLTextEncode
- Rename functions from clip-specific to generic prompt node naming
- Add fallback detection for custom text/encode/prompt nodes
- Update docstrings to reflect broader node type support

Fixes regression identified in PR #35 review.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 02:42:25 -08:00
AEmotionStudioandClaude Opus 4.5 b8aadd7faa fix(image_node): add section header when only dimensions are displayed
When add_dimensions or resize_to_power_of_2 was enabled but add_date,
add_time, and include_format_in_message were all disabled, dimensions
would be appended to the Discord message without the "Image Information:"
section header.

Now checks if dimensions will be added but no other metadata exists,
and adds the section header in that case.

Fixes issue identified in PR #35 review.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 02:27:42 -08:00
AEmotionStudioandClaude Opus 4.5 1e94a69e5f fix(image_node): correct else block indentation in batch Discord send
The else block for error handling was incorrectly associated with the
`if save_cdn_urls:` condition instead of the `if response.status_code
in [200, 204]:` check. This caused discord_send_success to always be
set to False after a successful batch send, regardless of the actual
outcome.

Fixes control flow bug identified in PR #35 review.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 02:13:16 -08:00
AEmotionStudioandClaude Opus 4.5 87c97e04a3 refactor(phase4): create BaseDiscordNode with shared utilities
- Create nodes/base_node.py with BaseDiscordNode class
- Provide common INPUT_TYPES generators (discord, cdn, filename)
- Extract shared methods:
  - sanitize_workflow_data()
  - build_filename_prefix()
  - get_dest_folder()
  - extract_workflow_from_metadata()
  - build_prompt_message()
  - send_discord_files()
  - send_cdn_urls_to_discord()
  - update_github_cdn()

The base class is ready for nodes to inherit from, enabling
gradual adoption of shared functionality without disrupting
existing node implementations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 23:41:05 -08:00
AEmotionStudioandClaude Opus 4.5 76da850b3d refactor(phase3): extract video encoding utilities to shared modules
- Create shared/media/format_utils.py with format detection and validation
- Create shared/media/video_encoder.py with FFmpegEncoder and PILEncoder classes
- Extract validate_video_for_discord to shared utility
- Extract ffmpeg detection to shared detect_ffmpeg() function
- Extract Discord video optimization to shared optimize_video_for_discord()
- Remove duplicate code from video_node.py (-109 lines)

Phase 3 summary:
- video_node.py: 1201 -> 1092 lines (9% reduction this phase)
- Total reduction from original: 1562 -> 1092 lines (30% reduction)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 23:38:58 -08:00
AEmotionStudioandClaude Opus 4.5 a208cd482b refactor(phase2): extract shared utilities and reduce node duplication
- Create shared/filename_utils.py for date/time/dimension filename building
- Create shared/path_utils.py for output directory handling
- Create shared/discord/message_builder.py for Discord message construction
- Create shared/discord/cdn_extractor.py for CDN URL extraction
- Refactor image_node.py to use shared utilities (-161 lines, 16.3%)
- Refactor video_node.py to use shared utilities (-361 lines, 23.1%)
- Fix setup_logging missing from logging_config.py
- Fix test imports to use new module paths (nodes.* instead of discord_*_node)
- Total reduction: 522 lines (20.5%), exceeding PRD target of ~200 lines

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 23:33:10 -08:00
AEmotionStudio 852840dcae refactor(core): restructure project into shared/ and nodes/ modules 2026-01-19 22:02:47 -08:00
AEmotionStudio 06d7b955f5 Merge branch 'main' of https://github.com/AEmotionStudio/ComfyUI-DiscordSend into refactor/separation-of-concerns 2026-01-19 21:26:44 -08:00
Æmotion Studio 64179a3170 Merge pull request #32 from AEmotionStudio/bolt-remove-redundant-sanitization-5640104545261640127
⚡ Bolt: Remove redundant sanitization in save_images
2026-01-19 19:57:10 -08:00
google-labs-jules[bot] 1a84f62ec1 ⚡ Bolt: Fix test input to include github_token
- Updated `tests/test_image_node_sanitization.py` to include `github_token` in test inputs.
- Verified test now correctly covers github token sanitization.
2026-01-20 03:05:28 +00:00
google-labs-jules[bot] d7b20fc717 ⚡ Bolt: Fix test to not swallow assertions
- Updated `tests/test_image_node_sanitization.py` to avoid bare `try...except` that swallowed `AssertionError`.
- Verified the test fails correctly when sanitization is broken.
2026-01-20 02:34:53 +00:00
Æmotion Studio 95e00c65bf Merge pull request #33 from AEmotionStudio/fix-discord-video-node-imports-11402248337429151758
Fix incorrect imports and dead code in discord_video_node.py
2026-01-19 18:33:32 -08:00
google-labs-jules[bot] 4d34e27463 I have fixed incorrect imports in discord_video_node.py.
I removed a try-except block that attempted to import non-existent variables (`ffmpeg_path`, `get_audio`, etc.) from `discordsend_utils`. These variables were not used in the codebase and were causing import errors or false positives in static analysis.

- Replaced the failing import block with explicit definitions for `ffmpeg_path`, `ENCODE_ARGS`, and `has_vhs_formats`.
- Imported `ProgressBar` from `comfy.utils` with a fallback for standalone usage.
- Removed unused variables `floatOrInt`, `imageOrLatent`, and `BIGMAX`.
- Verified that the removed variables and functions are dead code.
2026-01-20 02:00:56 +00:00
google-labs-jules[bot] 5c6f15469d ⚡ Bolt: Remove redundant metadata sanitization in save_images
- Removed redundant calls to `sanitize_json_for_export` in `discord_image_node.py` loop.
- Verified ~33ms performance gain per batch via benchmark.
- Added regression test `tests/test_image_node_sanitization.py`.
2026-01-20 01:45:03 +00:00
Æmotion Studio 9acae29f27 Merge pull request #30 from AEmotionStudio/fix/temp-file-leak-video-node-7583297146289477645
🛡️ Sentinel: [MEDIUM] Fix Resource Exhaustion via Unbounded Temporary Files
2026-01-19 17:33:53 -08:00
google-labs-jules[bot] 83f0059720 Fix temporary file leak in discord_video_node.py 2026-01-20 01:23:20 +00:00
Æmotion Studio 81010bbb4e Merge pull request #29 from AEmotionStudio/palette-tooltip-improvements-547592080699549748
🎨 Palette: Enhance configuration tooltips for better UX
2026-01-19 17:22:13 -08:00
google-labs-jules[bot] c4dcfd586d Improve tooltips for GitHub and Discord settings
- Update `filename_prefix` tooltip to clarify `%batch_num%` usage.
- Update `github_repo` tooltip with an example format.
- Update `github_token` tooltip with navigation instructions to find the token.
- Standardize `webhook_url` tooltip across image and video nodes.
- Add `.jules/palette.md` for UX learnings.
2026-01-20 01:14:51 +00:00
AEmotionStudioandClaude Opus 4.5 e3e95ab197 fix(bot): resolve 4 critical bugs preventing bot startup
Phase 0 of separation-of-concerns refactor:

- Fix BotConfig class name mismatch in bot/__main__.py
  (was importing 'Config' but class is 'BotConfig')
- Add missing 'import json' to bot/services/delivery.py
  (json.loads was called without import)
- Remove unused PermissionLevel import from bot/cogs/admin.py
- Fix config attribute path: config.comfyui.url (was config.comfyui_url)

Also adds REFACTOR_PRD.md to .gitignore for project planning docs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 17:07:29 -08:00
Æmotion Studio 7cc72606a5 Merge pull request #28 from AEmotionStudio/bolt-video-memory-optimization-3922534104789050158
⚡ Bolt: Zero-copy video frame writing
2026-01-18 19:16:33 -08:00
google-labs-jules[bot] 8be6270aef fix(video): ensure contiguous arrays for both audio and video paths
- Fix potential BufferError in video frame writing path by enforcing C-contiguity with np.ascontiguousarray
- Add regression tests for non-contiguous array writing to Popen.stdin
- Rename variables for clarity (images_bytes -> image_chunks)
- Ensure cross-platform compatibility in tests
2026-01-19 03:06:07 +00:00
google-labs-jules[bot] b944db244e fix(video): ensure contiguous array for audio subprocess and rename var
- Fix BufferError when passing non-contiguous transposed audio array to memoryview/subprocess by using np.ascontiguousarray
- Rename 'images_bytes' to 'image_chunks' to better reflect that it contains numpy arrays, not bytes objects
- Improve test portability by using sys.executable instead of 'cat'
2026-01-19 02:39:37 +00:00
google-labs-jules[bot] d99aa60623 ⚡ Optimize video frame writing to ffmpeg
Avoids unnecessary memory copying by passing numpy arrays/memoryviews directly to subprocess stdin instead of creating intermediate bytes objects. This reduces memory pressure and allocation overhead when processing high-resolution video frames.
2026-01-19 02:15:43 +00:00
Æmotion Studio 214ecf35eb Merge pull request #26 from AEmotionStudio/sentinel-github-validation-17856768252331476057
🛡️ Sentinel: [HIGH] Fix GitHub repo traversal vulnerability
2026-01-18 17:48:47 -08:00
Æmotion Studio 711aeed35d Merge pull request #27 from AEmotionStudio/palette/tooltip-improvements-8687887650900939019
🎨 Palette: Improve Tooltips for Critical Options
2026-01-18 17:44:36 -08:00
google-labs-jules[bot] a9ff597d5c 🎨 Palette: Improve Tooltips for Critical Options
💡 What: Updated tooltips for `add_time` (video/image) and `filename_prefix` (image).
🎯 Why:
- Video `add_time`: Warns users that disabling this causes the "single frame" bug on Discord, guiding them to `include_video_info` instead.
- Image `add_time`: Clarifies caching behavior.
- Image `filename_prefix`: Documents `%batch_num%` support.
♿ Accessibility: Provides critical context directly in the UI, reducing reliance on external documentation (README).
2026-01-19 01:33:23 +00:00
google-labs-jules[bot] e1f9b50c3d Sentinel: Fix GitHub repo traversal vulnerability
Prevent arbitrary file write and repo traversal by strictly validating
`github_repo` and `file_path` inputs in `update_github_cdn_urls`.

Added `validate_github_repo` and `validate_file_path` functions to
enforce strict whitelisting of characters and reject path traversal sequences.
Added comprehensive unit tests in `tests/test_github_validation.py`.
2026-01-19 01:25:52 +00:00
Æmotion Studio 87a0a5d5fe Merge pull request #25 from AEmotionStudio/sentinel-token-leakage-fix-3044798694332217439
🛡️ Sentinel: Fix token leakage in API error messages
2026-01-17 18:19:03 -08:00
Æmotion Studio 45a1627992 Merge pull request #24 from AEmotionStudio/palette-dynamic-video-tooltip-393470356119147179
🎨 Palette: Dynamic video format tooltip & default based on FFmpeg availability
2026-01-17 17:51:24 -08:00
google-labs-jules[bot] 1c9ab10e16 security: fix token leakage in API error handling
- Sanitize `DiscordWebhookClient` exception messages to redact webhook tokens.
- Sanitize GitHub API response text in error messages to prevent token leakage.
- Update `tests/test_utils.py` with mocks and new security test cases.
- Record security learning in `.jules/sentinel.md`.

This addresses potential credential exposure in logs and error messages.
2026-01-18 01:36:51 +00:00
Æmotion Studio f67a978c5d Merge pull request #23 from AEmotionStudio/bolt-optimize-metadata-creation-6062947008644414884
⚡ Bolt: Optimize metadata sanitization loop
2026-01-17 17:31:05 -08:00
google-labs-jules[bot] 291fa65a7b feat(video-node): Make video format tooltip dynamic based on ffmpeg availability
This change modifies `DiscordSendSaveVideo.INPUT_TYPES` to check for `ffmpeg_path` existence.
- If FFmpeg is missing: The default format is set to "video/gif" (the only available fallback), and the tooltip is updated to explicitly warn the user and explain that FFmpeg installation is required for other formats.
- If FFmpeg is present: The behavior remains unchanged with the full list of formats and detailed tooltip.

This improves UX by preventing confusion when users see MP4 options in the tooltip but can't select them, and provides a clear call to action.
2026-01-18 01:26:25 +00:00
google-labs-jules[bot] c5e79124cc ⚡ Bolt: Optimize metadata sanitization loop
Moved expensive metadata sanitization and JSON serialization outside of the image processing loop in `discord_image_node.py`.

💡 What:
- Hoisted `sanitize_json_for_export` calls for `prompt` and `extra_pnginfo` out of the batch loop.
- Removed redundant triple-sanitization check inside the PNG saving block.
- Created `metadata` object once per batch instead of N times.

🎯 Why:
- Sanitizing complex workflow JSON (recursive + regex) for every image in a batch is O(N * M) work.
- Previous implementation re-sanitized already clean data multiple times per image.

📊 Impact:
- Benchmark shows massive reduction in processing time for batches with large metadata.
- Processing 50 images with complex workflow metadata:
  - Before: ~8.9s
  - After: ~0.34s
  - Speedup: ~25x faster for this specific operation.

🔬 Measurement:
- Verified with `tests/benchmark_metadata.py` (simulating 500-node workflow).
- Verified existing tests pass with `python -m unittest discover tests`.
2026-01-18 01:17:00 +00:00
Æmotion Studio 5610f51a71 Merge pull request #22 from AEmotionStudio/palette-ux-improvements-17493252807334638890
🎨 Palette: Enhance UX with better defaults and clearer tooltips
2026-01-16 17:48:19 -08:00
google-labs-jules[bot] 3fd583c483 Enhance UX for Discord nodes with better tooltips and defaults
- Default `add_time` to True in `discord_image_node.py` to prevent Discord caching issues.
- Clarify `lossless` tooltip to explain PNG vs WebP behavior.
- Add security warnings to `webhook_url` and `github_token` tooltips.
- Add markdown examples to `discord_message` tooltip.
- Ensure consistency between image and video node tooltips.
2026-01-17 01:39:56 +00:00
Æmotion Studio 8888c2cb0b Merge pull request #20 from AEmotionStudio/palette-ux-tooltips-833601383731603595
🎨 Palette: Improve node tooltips for clarity
2026-01-16 17:26:18 -08:00
Æmotion Studio 35178b92c8 Merge pull request #18 from AEmotionStudio/bolt-optimize-png-encoding-13594472244144470660
⚡ Bolt: Optimize Discord PNG encoding
2026-01-16 17:25:38 -08:00
Æmotion Studio d35caae023 Merge pull request #19 from AEmotionStudio/sentinel-enforce-https-webhooks-16770274636701043555
🛡️ Sentinel: Enforce HTTPS for Discord Webhooks
2026-01-16 17:23:13 -08:00
google-labs-jules[bot] 3f553e600a feat(ui): improve node input tooltips for clarity and usability
- Update `resize_method` tooltip in `discord_image_node.py` to explain when to use each algorithm (e.g., Lanczos for photos, Nearest for pixel art).
- Update `webhook_url` tooltip to clearly label it as sensitive data.

This improves the user experience by helping users make informed decisions directly within the ComfyUI interface.
2026-01-17 01:22:18 +00:00
google-labs-jules[bot] cd2052757a Enforce HTTPS for Discord webhooks
This change updates the `validate_webhook_url` function to strictly enforce the use of `https://` for Discord webhook URLs. This prevents the accidental transmission of sensitive webhook tokens over unencrypted HTTP connections.

Security Impact:
- Prevents potential Man-in-the-Middle (MitM) attacks from capturing webhook tokens if a user inadvertently copies an `http://` URL (e.g. from a proxy or non-standard source).
- Aligns with Discord's API security best practices.

Changes:
- Updated `WEBHOOK_URL_PATTERNS` regex to require `https`.
- Updated `validate_webhook_url` logic to check for `https://` prefix.
- Added unit test `test_http_url_rejected` to verify the fix.
2026-01-17 01:14:33 +00:00
google-labs-jules[bot] 73cf5fc0dd ⚡ Bolt: Optimize Discord PNG encoding
Avoid unnecessary PIL->Numpy conversion when sending PNGs to Discord, saving ~500ms for 4K images.
This is achieved by tracking if the image was resized and reusing the original numpy array if possible.
2026-01-17 01:11:13 +00:00
Æmotion Studio 2a37c1b410 Merge pull request #15 from AEmotionStudio/sentinel-log-sanitization-282525082312391419
🛡️ Sentinel: [HIGH] Fix webhook token leakage in logs
2026-01-15 22:29:33 -08:00
google-labs-jules[bot] 24d6912396 security: fix case-sensitive sanitization of webhook URLs
- Updated regex to use `re.IGNORECASE` to handle uppercase webhook URLs correctly.
- Prevents token leakage when URLs use non-standard casing.
2026-01-16 06:19:19 +00:00
Æmotion Studio 15883ebb66 Merge pull request #17 from AEmotionStudio/palette-ux-fix-boolean-inputs-17764351605093274064
🎨 Palette: Fix broken boolean inputs in Image Node
2026-01-15 17:38:36 -08:00
google-labs-jules[bot] decd7def28 Fix broken boolean inputs in discord_image_node
The `overwrite_last`, `add_dimensions`, and `resize_to_power_of_2` inputs were checking for string equality `== "enable"`, but the inputs are defined as `BOOLEAN` in `INPUT_TYPES`, which pass Python boolean values (`True`/`False`). This commit fixes the conditional logic to check for truthiness, restoring the functionality of these UI controls.

This is a UX improvement as it fixes broken UI controls.
2026-01-16 01:26:03 +00:00
Æmotion Studio 491e4a2758 Merge pull request #14 from AEmotionStudio/bolt-tensor-optimization-8437656827676600270
⚡ Bolt: Optimize tensor-to-numpy image conversion
2026-01-15 17:25:29 -08:00
google-labs-jules[bot] a81ae85d1e security: redact webhook tokens from exception logs
- Prevents leakage of Discord webhook tokens in application logs when requests fail.
- Sanitizes `requests` exception messages by scrubbing the token part of the URL.
- Preserves exception context (`request`, `response`) when re-raising sanitized exceptions.
2026-01-16 01:17:57 +00:00