Skip to content

Refactor GUI to modern HTML/CSS and improve Docker setup#2456

Open
CesarPetrescu wants to merge 3 commits intoelebumm:masterfrom
CesarPetrescu:claude/integrate-qwen3-tts-MzKX2
Open

Refactor GUI to modern HTML/CSS and improve Docker setup#2456
CesarPetrescu wants to merge 3 commits intoelebumm:masterfrom
CesarPetrescu:claude/integrate-qwen3-tts-MzKX2

Conversation

@CesarPetrescu
Copy link

Description

This PR modernizes the GUI infrastructure and improves the Docker containerization of the Reddit Video Maker Bot. The changes include:

GUI Refactoring

  • Converted Jinja2 templates to standalone HTML: Replaced the Flask template inheritance system with self-contained HTML files that use modern vanilla JavaScript for dynamic content loading

  • Redesigned backgrounds.html: Completely restructured the backgrounds management page with:

    • Modern card-based layout with sidebar navigation
    • Separate sections for video and audio backgrounds
    • Direct file upload functionality with progress tracking
    • Improved UX with empty states and file size display
    • RESTful API integration instead of form submissions
  • Added new dashboard.html: New landing page featuring:

    • Quick action buttons for video generation
    • Current configuration summary
    • Real-time progress tracking
    • Recent videos display
    • WebSocket integration for live updates
  • Added new progress.html: Dedicated progress tracking page with:

    • Real-time job status monitoring
    • Step-by-step progress visualization
    • Job history tracking
    • Connection status indicator
    • Preview section for generated content

Docker Improvements

  • Enhanced Dockerfile with:
    • Proper environment variables (PYTHONDONTWRITEBYTECODE, PYTHONUNBUFFERED, REDDIT_BOT_GUI)
    • Comprehensive system dependencies for Playwright/Chromium support
    • Optimized layer caching (requirements.txt copied before application code)
    • Playwright browser installation and dependencies
    • spaCy language model pre-download
    • Pre-created necessary directories for assets and results
    • Port exposure (5000) for web GUI
    • Custom entrypoint script support
    • Reduced image size with --no-install-recommends and cleanup of apt cache

Technical Improvements

  • Replaced jQuery-based form validation with modern vanilla JavaScript
  • Implemented RESTful API endpoints for background management
  • Added WebSocket support for real-time progress updates
  • Improved error handling and user feedback with notifications
  • Better separation of concerns with dedicated CSS and JavaScript files

Dependencies

  • Playwright (for browser automation)
  • spaCy (for NLP tasks)
  • Flask-SocketIO (for real-time updates)
  • Modern browser with ES6+ support

Testing Notes

  • Test the backgrounds upload functionality with various video/audio formats
  • Verify Docker build completes successfully and all dependencies are installed
  • Test real-time progress updates via WebSocket connection
  • Verify the GUI is accessible at http://localhost:5000

https://claude.ai/code/session_01HLLH3WjpmRzvaoY6eYSFAD

Major changes:
- Add Qwen3 TTS provider with authentication support
- Remove local pyttsx3 TTS (replaced with cloud TTS)
- Add real-time progress GUI with WebSocket updates
- Comprehensive Docker setup with docker-compose
- Updated README with new documentation

New features:
- Qwen TTS: Supports multiple speakers and languages
- Progress GUI: Live step-by-step tracking at http://localhost:5000
- Docker: Full containerization with environment variables
- Config: Example config file for easy setup

Files added:
- TTS/qwen_tts.py - Qwen3 TTS provider
- progress_gui.py - Flask/SocketIO progress server
- utils/progress.py - Progress tracking module
- GUI/progress.html - Progress dashboard template
- GUI/static/css/progress.css - Progress GUI styles
- GUI/static/js/progress.js - WebSocket client
- docker-compose.yml - Docker orchestration
- docker-entrypoint.sh - Container startup script
- config.example.toml - Example configuration

https://claude.ai/code/session_01HLLH3WjpmRzvaoY6eYSFAD
Major changes:
- Remove PRAW dependency and Reddit API credentials
- Add no-OAuth Reddit scraper using public .json endpoints
- No Reddit API keys required - simpler setup!

New scraper features:
- Uses Reddit's public .json endpoints (www.reddit.com/r/subreddit.json)
- Configurable rate limiting via request_delay setting
- Automatic retry with exponential backoff
- Fetches posts and comments without authentication

Files changed:
- reddit/scraper.py (new) - No-OAuth Reddit scraper
- reddit/subreddit.py - Updated to use scraper instead of PRAW
- requirements.txt - Removed praw dependency
- utils/.config.template.toml - Removed Reddit credentials
- config.example.toml - Updated with scraper settings
- docker-entrypoint.sh - Updated for no-auth setup
- docker-compose.yml - Removed Reddit credential env vars
- main.py - Updated exception handling

Limitations:
- Subject to Reddit's rate limiting (configurable delay)
- ~1000 post cap per subreddit listing
- Some comments may be missing in large threads

https://claude.ai/code/session_01HLLH3WjpmRzvaoY6eYSFAD
- Add dashboard page with quick actions and progress overview
- Add settings page for Qwen TTS, Reddit scraper, and video configuration
- Add backgrounds page for uploading custom video/audio backgrounds
- Add videos page for viewing and downloading generated content
- Add TTS connection test endpoint
- Update docker-compose for standalone operation
- Create unified CSS and JavaScript for consistent UI experience

https://claude.ai/code/session_01HLLH3WjpmRzvaoY6eYSFAD
Copilot AI review requested due to automatic review settings February 4, 2026 03:14
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes the Reddit Video Maker Bot by replacing OAuth-based Reddit API access with a public JSON endpoint scraper, implementing a new web-based progress tracking GUI with WebSocket support, switching from pyttsx to Qwen TTS, and improving Docker containerization. While the goals are ambitious and the new features are valuable, the implementation has several critical security vulnerabilities and breaking changes that must be addressed before merging.

Changes:

  • Replaced PRAW OAuth authentication with a no-auth Reddit JSON scraper to eliminate API key requirements
  • Added comprehensive web GUI with real-time progress tracking via WebSocket, background management, and video generation controls
  • Switched default TTS engine from pyttsx to Qwen TTS with support for multiple languages and voices
  • Enhanced Dockerfile with proper dependency management, Playwright browser installation, and optimized layer caching

Reviewed changes

Copilot reviewed 24 out of 25 changed files in this pull request and generated 34 comments.

Show a summary per file
File Description
reddit/scraper.py New no-auth Reddit scraper using public .json endpoints
reddit/subreddit.py Refactored to use new scraper instead of PRAW
TTS/qwen_tts.py New Qwen TTS engine implementation
TTS/pyttsx.py Removed deprecated pyttsx engine
utils/progress.py New progress tracking system with WebSocket callbacks
progress_gui.py Flask server for web GUI with REST API and SocketIO
main.py Updated with progress tracking integration and Qwen TTS validation
GUI/*.html Modern standalone HTML pages with vanilla JavaScript
GUI/static/js/*.js Client-side progress tracking and API utilities
GUI/static/css/*.css Modern dark theme styling
requirements.txt Updated dependencies (removed praw/pyttsx3, added Flask-SocketIO/gevent)
Dockerfile Enhanced with proper environment variables and system dependencies
docker-compose.yml New compose configuration for containerized deployment
docker-entrypoint.sh Entrypoint script for environment-based configuration
config.example.toml Updated config template with Qwen TTS and scraper settings
README.md Comprehensive rewrite with Docker instructions and new features
utils/.config.template.toml Removed Reddit OAuth fields, added scraper and Qwen TTS config
video_creation/voices.py Updated to import QwenTTS instead of pyttsx

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +110 to +115
submission, similarity_score = _get_undone_post(
sorted_wrappers, subreddit_name, similarity_scores=similarity_scores
)
else:
wrappers = [SubmissionWrapper(post) for post in posts]
submission = _get_undone_post(wrappers, subreddit_name)
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a mismatch between _get_undone_post return type and how it's used. On line 110-112, the function is called and expected to return a tuple (submission, similarity_score), but on line 115 it's called and expects just a submission. However, on line 276, only post is returned when similarity_scores is not None and i < len(similarity_scores), which would cause unpacking errors. The logic should explicitly return a tuple on line 279.

Copilot uses AI. Check for mistakes.
app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024 # 500MB max upload

# Configure SocketIO for real-time updates
socketio = SocketIO(app, cors_allowed_origins="*", async_mode="gevent")
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing CORS configuration: The Flask-SocketIO is configured with cors_allowed_origins="*" which allows connections from any origin. This is a security risk in production environments. Consider restricting CORS to specific trusted origins or making it configurable via environment variables.

Copilot uses AI. Check for mistakes.

[settings.tts]
voice_choice = { optional = false, default = "tiktok", options = ["elevenlabs", "streamlabspolly", "tiktok", "googletranslate", "awspolly", "pyttsx", "OpenAI"], example = "tiktok", explanation = "The voice platform used for TTS generation. " }
voice_choice = { optional = false, default = "qwentts", options = ["elevenlabs", "streamlabspolly", "tiktok", "googletranslate", "awspolly", "qwentts", "OpenAI"], example = "qwentts", explanation = "The voice platform used for TTS generation." }
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conversion of pyttsx to QwenTTS changes the default TTS provider, but there's no migration path mentioned for existing users. The config template still references "pyttsx" in comments and the README should clearly document this breaking change and migration steps for existing installations.

Copilot uses AI. Check for mistakes.
wrappers: List[SubmissionWrapper],
subreddit_name: str,
similarity_scores: Optional[List[float]] = None,
) -> Optional[RedditPost] | Tuple[Optional[RedditPost], float]:
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type annotation uses the deprecated pipe syntax Optional[RedditPost] | Tuple[Optional[RedditPost], float] which mixes Optional and union types incorrectly. This should be Union[Optional[RedditPost], Tuple[Optional[RedditPost], float]] or better yet, Optional[Union[RedditPost, Tuple[RedditPost, float]]] to properly express that the function returns either None, a RedditPost, or a tuple.

Copilot uses AI. Check for mistakes.
Comment on lines +278 to +279
if similarity_scores is not None and i < len(similarity_scores):
return post, similarity_scores[i]
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function _get_undone_post can return different types (RedditPost or tuple) based on whether similarity_scores is provided, but when the wrapper object is used for the check_done call on line 273, it's still a SubmissionWrapper. The return statement on line 281 should return the RedditPost from the wrapper, not None when no undone post is found. Consider returning the tuple consistently when similarity_scores is provided, or refactoring to have clearer return types.

Suggested change
if similarity_scores is not None and i < len(similarity_scores):
return post, similarity_scores[i]
if similarity_scores is not None:
score = similarity_scores[i] if i < len(similarity_scores) else 0.0
return post, score

Copilot uses AI. Check for mistakes.
import os
import json
import time
from dataclasses import dataclass, field, asdict
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'asdict' is not used.

Suggested change
from dataclasses import dataclass, field, asdict
from dataclasses import dataclass, field

Copilot uses AI. Check for mistakes.
Complete web interface for configuration, video generation, and progress tracking.
"""
import os
import json
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'json' is not used.

Suggested change
import json

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +12
import shutil
from pathlib import Path
from datetime import datetime
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'shutil' is not used.

Suggested change
import shutil
from pathlib import Path
from datetime import datetime
from pathlib import Path
from datetime datetime

Copilot uses AI. Check for mistakes.
Note: This approach is subject to rate limiting and may be blocked by Reddit.
For production use, consider using the official Reddit API with OAuth.
"""
import json
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'json' is not used.

Suggested change
import json

Copilot uses AI. Check for mistakes.
from praw.models import MoreComments
from prawcore.exceptions import ResponseException

from reddit.scraper import get_scraper, RedditPost, RedditComment, RedditScraperError
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'RedditComment' is not used.

Suggested change
from reddit.scraper import get_scraper, RedditPost, RedditComment, RedditScraperError
from reddit.scraper import get_scraper, RedditPost, RedditScraperError

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants