From 1fd9720dacd29acfb3902ae48a9e85509dd564ab Mon Sep 17 00:00:00 2001 From: ajaysi Date: Sun, 22 Mar 2026 12:47:00 +0530 Subject: [PATCH] Cleanup: Add migration scripts to gitignore and remove from tracking - Add debug_usage.py, fix_database.py, migrate_usage_summaries.py, simple_migrate.py, validate_implementation.py to .gitignore - Add CAMERA_SELFIE_IMPLEMENTATION.md to .gitignore - Remove these files from git tracking (keep locally) --- .gitignore | 10 ++ CAMERA_SELFIE_IMPLEMENTATION.md | 137 -------------------------- debug_usage.py | 64 ------------ fix_database.py | 74 -------------- migrate_usage_summaries.py | 131 ------------------------- simple_migrate.py | 50 ---------- validate_implementation.py | 166 -------------------------------- 7 files changed, 10 insertions(+), 622 deletions(-) delete mode 100644 CAMERA_SELFIE_IMPLEMENTATION.md delete mode 100644 debug_usage.py delete mode 100644 fix_database.py delete mode 100644 migrate_usage_summaries.py delete mode 100644 simple_migrate.py delete mode 100644 validate_implementation.py diff --git a/.gitignore b/.gitignore index 6c4b7bcf..6ea2d5a7 100644 --- a/.gitignore +++ b/.gitignore @@ -261,3 +261,13 @@ docs/__pycache__/ backend/.onboarding_progress*.json backend/researchtools_text/projects/Draft__AI_advanc_c2f90698.json backend/researchtools_text/projects/Draft__AI_adv_388d4491.json + +# Migration and debug scripts +debug_usage.py +fix_database.py +migrate_usage_summaries.py +simple_migrate.py +validate_implementation.py + +# Camera selfie implementation (not needed) +CAMERA_SELFIE_IMPLEMENTATION.md diff --git a/CAMERA_SELFIE_IMPLEMENTATION.md b/CAMERA_SELFIE_IMPLEMENTATION.md deleted file mode 100644 index db0006e5..00000000 --- a/CAMERA_SELFIE_IMPLEMENTATION.md +++ /dev/null @@ -1,137 +0,0 @@ -# Camera Selfie Feature - Implementation Complete - -## โœ… **Feature Successfully Implemented** - -The camera selfie feature has been successfully added to the Podcast Maker's avatar upload section. - -## ๐Ÿš€ **What Was Built** - -### 1. **CameraSelfie Component** (`CameraSelfie.tsx`) -- **Full camera functionality** using MediaDevices API -- **Live video preview** with mirror effect for natural selfie experience -- **Camera controls**: Capture, flip camera, close -- **Face positioning guide** overlay for better framing -- **Comprehensive error handling** for permissions and device limitations -- **Mobile support** with front/back camera switching -- **Responsive design** for desktop and mobile - -### 2. **AvatarSelector Integration** -- **New "Take Selfie" tab** added before "Upload Your Photo" -- **Seamless integration** with existing avatar flow -- **Consistent UI/UX** matching current design patterns -- **Updated help text** to include camera option - -### 3. **CreateModal Integration** -- **Camera state management** with React hooks -- **Image processing**: DataURL โ†’ File conversion -- **Upload integration**: Reuses existing upload logic -- **Error handling** for camera capture failures - -## ๐ŸŽฏ **Key Features** - -### **Camera Experience** -- **One-click camera access** from avatar selector -- **Live preview** with natural mirror effect -- **Face guide overlay** to help users position themselves -- **Camera flip** for mobile devices (front/back) -- **Instant capture** with visual feedback - -### **Technical Features** -- **MediaDevices API** for camera access -- **Canvas-based image capture** with proper formatting -- **File conversion** to maintain compatibility with existing upload flow -- **Permission handling** with user-friendly error messages -- **Resource cleanup** to prevent camera leaks - -### **User Experience** -- **Intuitive tab placement** before file upload -- **Clear visual indicators** and instructions -- **Graceful fallback** to file upload if camera unavailable -- **Consistent styling** with existing UI components - -## ๐Ÿ“ฑ **Browser Compatibility** - -### **Supported** -- โœ… Modern browsers with MediaDevices API support -- โœ… Chrome 60+, Firefox 55+, Safari 11+, Edge 79+ -- โœ… Mobile browsers with camera access - -### **Fallback Handling** -- โŒ Camera not available โ†’ Shows message with file upload suggestion -- โŒ Permission denied โ†’ Clear instructions to enable camera -- โŒ Camera in use โ†’ User-friendly error message - -## ๐Ÿ”ง **How It Works** - -### **User Flow** -1. User clicks "Take Selfie" tab in avatar selector -2. Camera dialog opens with live preview -3. User positions face using guide overlay -4. User clicks capture button (or uses controls) -5. Image is processed and uploaded automatically -6. User can use "Make Presentable" feature like uploaded photos - -### **Technical Flow** -1. `setCameraSelfieOpen(true)` opens camera dialog -2. `CameraSelfie` component requests camera access -3. Live video stream displayed with mirror effect -4. User captures photo โ†’ canvas conversion -5. DataURL passed to `handleCameraSelfie` -6. DataURL โ†’ File conversion and upload -7. Integration with existing avatar preview system - -## ๐ŸŽจ **UI Components** - -### **Camera Dialog** -- **Modal dialog** with full-screen camera view -- **Control overlay** at bottom with capture, flip, close buttons -- **Face guide** overlay in center -- **Loading states** and error messages - -### **Tab Integration** -- **New tab** with camera icon -- **Consistent styling** with existing tabs -- **Hover effects** and visual feedback -- **Help text** updates - -## ๐Ÿ” **Files Modified/Created** - -### **New Files** -- `frontend/src/components/PodcastMaker/CameraSelfie.tsx` - Full camera component - -### **Modified Files** -- `frontend/src/components/PodcastMaker/CreateStep/AvatarSelector.tsx` - Added camera tab and integration -- `frontend/src/components/PodcastMaker/CreateModal.tsx` - Added camera state and handlers - -## ๐Ÿงช **Testing Instructions** - -### **Manual Testing** -1. Start frontend development server -2. Navigate to Podcast Maker -3. Click "Create New Podcast" -4. Select "Take Selfie" tab in avatar section -5. Grant camera permissions when prompted -6. Test camera preview and capture functionality -7. Verify "Make Presentable" works with captured photo -8. Test error scenarios (deny permission, no camera) - -### **Test Scenarios** -- โœ… Camera permission granted -- โœ… Camera permission denied -- โœ… No camera available -- โœ… Camera already in use -- โœ… Mobile camera switching -- โœ… Image capture and upload -- โœ… Integration with "Make Presentable" -- โœ… Avatar removal and re-capture - -## ๐ŸŽ‰ **Ready for Production** - -The camera selfie feature is now fully implemented and ready for user testing. It provides a modern, intuitive way for users to capture their podcast presenter photos directly from their device camera, with full integration into the existing avatar upload and enhancement workflow. - -**Key Benefits:** -- ๐Ÿ“ธ **Faster than file upload** - No need to find and select photos -- ๐ŸŽฏ **Better framing** - Face guide helps users position themselves correctly -- ๐Ÿ“ฑ **Mobile optimized** - Native camera experience on phones -- ๐Ÿ”„ **Seamless integration** - Works with existing "Make Presentable" feature -- ๐Ÿ›ก๏ธ **Robust error handling** - Graceful fallbacks and clear instructions diff --git a/debug_usage.py b/debug_usage.py deleted file mode 100644 index 71a514ac..00000000 --- a/debug_usage.py +++ /dev/null @@ -1,64 +0,0 @@ - -import sys -import os -from sqlalchemy import create_engine, text -from sqlalchemy.orm import sessionmaker - -# Add backend to path -sys.path.append(os.path.join(os.getcwd(), 'backend')) - -from services.database import Base -from models.subscription_models import APIUsageLog, UserSubscription -from services.subscription import UsageTrackingService, PricingService - -# Setup DB connection -# dynamic path resolution as per codebase -DB_PATH = os.path.join(os.getcwd(), 'backend', 'data', 'alwrity.db') -# Note: The codebase might use user-specific DBs now. -# Let's check how get_db works or if we need to look at a specific user db. -# user_memories says: Database path updated to `workspace/workspace_{user_id}/db/alwrity.db` to support user isolation. - -USER_ID = "user_33Gz1FPI86VDXhRY8QN4ragRFGN" -WORKSPACE_DB_PATH = os.path.join(os.getcwd(), 'workspace', f'workspace_{USER_ID}', 'db', 'alwrity.db') - -print(f"Checking specific user DB at: {WORKSPACE_DB_PATH}") - -if os.path.exists(WORKSPACE_DB_PATH): - db_url = f"sqlite:///{WORKSPACE_DB_PATH}" -else: - print(f"User DB not found at {WORKSPACE_DB_PATH}, falling back to main DB for check (legacy/shared mode)") - db_url = f"sqlite:///backend/data/alwrity.db" - -engine = create_engine(db_url) -SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) -db = SessionLocal() - -try: - print(f"\n--- Checking Usage for User: {USER_ID} ---") - - # Check API Usage Logs - logs_count = db.query(APIUsageLog).filter(APIUsageLog.user_id == USER_ID).count() - print(f"Total API Usage Logs: {logs_count}") - - if logs_count > 0: - last_log = db.query(APIUsageLog).filter(APIUsageLog.user_id == USER_ID).order_by(APIUsageLog.created_at.desc()).first() - print(f"Last Activity: {last_log.created_at} - {last_log.endpoint} ({last_log.provider})") - - # Check Subscription - sub = db.query(UserSubscription).filter(UserSubscription.user_id == USER_ID).first() - if sub: - print(f"Subscription: {sub.plan_type} (Status: {sub.status})") - else: - print("No subscription record found.") - - # Run Service Logic - print("\n--- Running UsageTrackingService.get_user_usage_stats ---") - usage_service = UsageTrackingService(db) - stats = usage_service.get_user_usage_stats(USER_ID) - print("Stats returned:") - print(stats) - -except Exception as e: - print(f"Error: {e}") -finally: - db.close() diff --git a/fix_database.py b/fix_database.py deleted file mode 100644 index fec59cb8..00000000 --- a/fix_database.py +++ /dev/null @@ -1,74 +0,0 @@ -""" -Quick fix for missing wavespeed columns in usage_summaries table -Run this script to fix the database schema issue -""" - -import sqlite3 -import os - -def fix_database(): - # Find database file - db_path = None - for path in ["backend/database.db", "database.db"]: - if os.path.exists(path): - db_path = path - break - - if not db_path: - print("โŒ Database not found!") - print("Please make sure you're running this from the project root directory") - return - - print(f"๐Ÿ“ Using database: {db_path}") - - try: - conn = sqlite3.connect(db_path) - cursor = conn.cursor() - - # Check if table exists - cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='usage_summaries'") - if not cursor.fetchone(): - print("โŒ Table 'usage_summaries' not found!") - return - - # Get current columns - cursor.execute("PRAGMA table_info(usage_summaries)") - columns = [row[1] for row in cursor.fetchall()] - - # Columns that need to be added - missing_columns = [] - required_columns = [ - 'wavespeed_calls', 'tavily_calls', 'serper_calls', 'metaphor_calls', - 'firecrawl_calls', 'stability_calls', 'exa_calls', 'video_calls', - 'image_edit_calls', 'audio_calls', 'wavespeed_tokens', 'wavespeed_cost', - 'tavily_cost', 'serper_cost', 'metaphor_cost', 'firecrawl_cost', - 'stability_cost', 'exa_cost', 'video_cost', 'image_edit_cost', 'audio_cost' - ] - - for col in required_columns: - if col not in columns: - missing_columns.append(col) - - if missing_columns: - print(f"โž• Adding {len(missing_columns)} missing columns...") - for col in missing_columns: - if col.endswith('_calls') or col.endswith('_tokens'): - cursor.execute(f"ALTER TABLE usage_summaries ADD COLUMN {col} INTEGER DEFAULT 0") - else: # cost columns - cursor.execute(f"ALTER TABLE usage_summaries ADD COLUMN {col} FLOAT DEFAULT 0.0") - print(f" โœ… Added {col}") - - conn.commit() - print("๐ŸŽ‰ Database schema updated successfully!") - else: - print("โœ… All columns already exist!") - - conn.close() - - except Exception as e: - print(f"โŒ Error: {e}") - -if __name__ == "__main__": - print("๐Ÿ”ง Fixing database schema for usage_summaries...") - fix_database() - print("โœ… Done!") diff --git a/migrate_usage_summaries.py b/migrate_usage_summaries.py deleted file mode 100644 index 4b468b81..00000000 --- a/migrate_usage_summaries.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python3 -""" -Migration script to add missing wavespeed columns to usage_summaries table -""" - -import sqlite3 -import sys -import os -from pathlib import Path - -def get_db_path(): - """Find the database file""" - # Look for common database locations - possible_paths = [ - "backend/database.db", - "backend/data/database.db", - "database.db", - "data/database.db" - ] - - for path in possible_paths: - if os.path.exists(path): - return path - - # If not found, check if there's a .db file in backend directory - backend_dir = Path("backend") - if backend_dir.exists(): - for db_file in backend_dir.glob("*.db"): - return str(db_file) - - return None - -def migrate_usage_summaries(): - """Add missing wavespeed columns to usage_summaries table""" - - db_path = get_db_path() - if not db_path: - print("โŒ Database file not found!") - print("Looked in:") - for path in ["backend/database.db", "backend/data/database.db", "database.db", "data/database.db"]: - print(f" - {path}") - return False - - print(f"๐Ÿ“ Using database: {db_path}") - - try: - conn = sqlite3.connect(db_path) - cursor = conn.cursor() - - # Check if table exists - cursor.execute(""" - SELECT name FROM sqlite_master - WHERE type='table' AND name='usage_summaries' - """) - - if not cursor.fetchone(): - print("โŒ Table 'usage_summaries' does not exist!") - return False - - # Get current columns - cursor.execute("PRAGMA table_info(usage_summaries)") - columns = [row[1] for row in cursor.fetchall()] - print(f"๐Ÿ“‹ Current columns: {columns}") - - # Columns to add - columns_to_add = [ - ("wavespeed_calls", "INTEGER DEFAULT 0"), - ("tavily_calls", "INTEGER DEFAULT 0"), - ("serper_calls", "INTEGER DEFAULT 0"), - ("metaphor_calls", "INTEGER DEFAULT 0"), - ("firecrawl_calls", "INTEGER DEFAULT 0"), - ("stability_calls", "INTEGER DEFAULT 0"), - ("exa_calls", "INTEGER DEFAULT 0"), - ("video_calls", "INTEGER DEFAULT 0"), - ("image_edit_calls", "INTEGER DEFAULT 0"), - ("audio_calls", "INTEGER DEFAULT 0"), - ("wavespeed_tokens", "INTEGER DEFAULT 0"), - ("wavespeed_cost", "FLOAT DEFAULT 0.0"), - ("tavily_cost", "FLOAT DEFAULT 0.0"), - ("serper_cost", "FLOAT DEFAULT 0.0"), - ("metaphor_cost", "FLOAT DEFAULT 0.0"), - ("firecrawl_cost", "FLOAT DEFAULT 0.0"), - ("stability_cost", "FLOAT DEFAULT 0.0"), - ("exa_cost", "FLOAT DEFAULT 0.0"), - ("video_cost", "FLOAT DEFAULT 0.0"), - ("image_edit_cost", "FLOAT DEFAULT 0.0"), - ("audio_cost", "FLOAT DEFAULT 0.0") - ] - - # Add missing columns - added_columns = [] - for column_name, column_def in columns_to_add: - if column_name not in columns: - print(f"โž• Adding column: {column_name}") - cursor.execute(f"ALTER TABLE usage_summaries ADD COLUMN {column_name} {column_def}") - added_columns.append(column_name) - else: - print(f"โœ… Column already exists: {column_name}") - - if added_columns: - conn.commit() - print(f"๐ŸŽ‰ Successfully added {len(added_columns)} columns:") - for col in added_columns: - print(f" - {col}") - else: - print("โœ… All columns already exist!") - - # Verify the changes - cursor.execute("PRAGMA table_info(usage_summaries)") - new_columns = [row[1] for row in cursor.fetchall()] - print(f"๐Ÿ“‹ Updated columns: {new_columns}") - - conn.close() - return True - - except sqlite3.Error as e: - print(f"โŒ Database error: {e}") - return False - except Exception as e: - print(f"โŒ Unexpected error: {e}") - return False - -if __name__ == "__main__": - print("๐Ÿš€ Starting usage_summaries migration...") - - if migrate_usage_summaries(): - print("โœ… Migration completed successfully!") - sys.exit(0) - else: - print("โŒ Migration failed!") - sys.exit(1) diff --git a/simple_migrate.py b/simple_migrate.py deleted file mode 100644 index 13ca6d38..00000000 --- a/simple_migrate.py +++ /dev/null @@ -1,50 +0,0 @@ -import sqlite3 -import os - -# Find database -db_paths = ["backend/database.db", "backend/data/database.db", "database.db", "data/database.db"] -db_path = None - -for path in db_paths: - if os.path.exists(path): - db_path = path - break - -if not db_path: - print("Database not found!") - exit(1) - -print(f"Using database: {db_path}") - -try: - conn = sqlite3.connect(db_path) - cursor = conn.cursor() - - # Check table - cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='usage_summaries'") - if not cursor.fetchone(): - print("Table usage_summaries not found!") - exit(1) - - # Get columns - cursor.execute("PRAGMA table_info(usage_summaries)") - columns = [row[1] for row in cursor.fetchall()] - print(f"Columns: {columns}") - - # Check for wavespeed_calls - if "wavespeed_calls" in columns: - print("โœ… wavespeed_calls column exists") - else: - print("โŒ wavespeed_calls column missing") - - # Add the column - print("Adding wavespeed_calls column...") - cursor.execute("ALTER TABLE usage_summaries ADD COLUMN wavespeed_calls INTEGER DEFAULT 0") - conn.commit() - print("โœ… wavespeed_calls column added") - - conn.close() - print("Migration completed!") - -except Exception as e: - print(f"Error: {e}") diff --git a/validate_implementation.py b/validate_implementation.py deleted file mode 100644 index 55c3a2c1..00000000 --- a/validate_implementation.py +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env python3 -""" -Validation script for the enhanced topic feature implementation. -Checks that all files and components are properly implemented. -""" - -import os -import sys -import json - -def check_file_exists(filepath, description): - """Check if a file exists.""" - if os.path.exists(filepath): - print(f"โœ… {description}: {filepath}") - return True - else: - print(f"โŒ {description}: {filepath} (NOT FOUND)") - return False - -def check_file_content(filepath, search_strings, description): - """Check if file contains required content.""" - if not os.path.exists(filepath): - print(f"โŒ {description}: File not found") - return False - - try: - with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - - missing = [] - for search in search_strings: - if search not in content: - missing.append(search) - - if missing: - print(f"โŒ {description}: Missing content: {missing}") - return False - else: - print(f"โœ… {description}: All required content found") - return True - except Exception as e: - print(f"โŒ {description}: Error reading file: {e}") - return False - -def main(): - """Validate the complete implementation.""" - print("๐Ÿ” Validating Enhanced Topic Feature Implementation") - print("=" * 60) - - backend_root = "c:\\Users\\diksha rawat\\Desktop\\ALwrity_github\\windsurf\\ALwrity\\backend" - frontend_root = "c:\\Users\\diksha rawat\\Desktop\\ALwrity_github\\windsurf\\ALwrity\\frontend\\src\\components\\PodcastMaker" - - checks_passed = 0 - total_checks = 0 - - # Backend Checks - print("\n๐Ÿ“‹ BACKEND VALIDATION") - print("-" * 30) - - # Check models.py - total_checks += 1 - if check_file_content( - f"{backend_root}\\api\\podcast\\models.py", - ["enhanced_ideas: List[str]", "rationales: List[str]"], - "Backend Response Model" - ): - checks_passed += 1 - - # Check analysis.py handler - total_checks += 1 - if check_file_content( - f"{backend_root}\\api\\podcast\\handlers\\analysis.py", - ["Professional & Expert-led angle", "Storytelling & Human interest angle", "Trendy & Contemporary angle"], - "Backend Enhancement Prompt" - ): - checks_passed += 1 - - # Check response handling - total_checks += 1 - if check_file_content( - f"{backend_root}\\api\\podcast\\handlers\\analysis.py", - ["enhanced_ideas[:3]", "rationales[:3]"], - "Backend Response Handling" - ): - checks_passed += 1 - - # Frontend Checks - print("\n๐Ÿ“‹ FRONTEND VALIDATION") - print("-" * 30) - - # Check modal component - total_checks += 1 - if check_file_exists( - f"{frontend_root}\\EnhancedTopicChoicesModal.tsx", - "Enhanced Topic Choices Modal Component" - ): - checks_passed += 1 - - # Check modal content - total_checks += 1 - if check_file_content( - f"{frontend_root}\\EnhancedTopicChoicesModal.tsx", - ["CHOICE_LABELS", "handleChoiceEdit", "handleSelectChoice"], - "Modal Component Logic" - ): - checks_passed += 1 - - # Check CreateModal state - total_checks += 1 - if check_file_content( - f"{frontend_root}\\CreateModal.tsx", - ["enhancedChoices", "enhancedRationales", "choicesModalOpen", "editedChoices"], - "CreateModal State Management" - ): - checks_passed += 1 - - # Check CreateModal handlers - total_checks += 1 - if check_file_content( - f"{frontend_root}\\CreateModal.tsx", - ["handleChoiceSelection", "result.enhanced_ideas", "setChoicesModalOpen(true)"], - "CreateModal Event Handlers" - ): - checks_passed += 1 - - # Check API service update - total_checks += 1 - if check_file_content( - f"{frontend_root}\\..\\..\\services\\podcastApi.ts", - ["enhanced_ideas: string[]", "rationales: string[]"], - "Frontend API Service Update" - ): - checks_passed += 1 - - # Check modal import and usage - total_checks += 1 - if check_file_content( - f"{frontend_root}\\CreateModal.tsx", - ["import { EnhancedTopicChoicesModal }", "