""" Gradio web interface for the Logo Downloader """ import os import gradio as gr import logging from pathlib import Path from typing import Optional from services.logo_downloader import LogoDownloader from services.appconfig import GEMINI_API_KEY, DEFAULT_LOGOS_PER_ENTITY, MAX_LOGOS_PER_ENTITY # Setup logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def process_text_request(text: str, api_key: Optional[str], num_logos: int = DEFAULT_LOGOS_PER_ENTITY): """ Process text and download logos through Gradio interface Args: text (str): Input text api_key (str): Optional Gemini API key num_logos (int): Number of logos per entity Returns: Tuple: (status_message, zip_file_path or None, detailed_results) """ try: # Validate inputs if not text or not text.strip(): return "❌ Please provide some text to analyze.", None, "No text provided." if num_logos < 1 or num_logos > MAX_LOGOS_PER_ENTITY: return f"❌ Number of logos must be between 1 and {MAX_LOGOS_PER_ENTITY}.", None, f"Invalid number: {num_logos}" # Use provided API key or environment variable final_api_key = api_key.strip() if api_key and api_key.strip() else GEMINI_API_KEY # Initialize downloader downloader = LogoDownloader(gemini_api_key=final_api_key) # Process the text results = downloader.process_text(text, num_logos) # Format response based on results if results['status'] == 'success' and results['stats']['total_downloads'] > 0: status_msg = f"✅ {downloader.get_stats_summary()}" zip_path = results.get('zip_path') # Create detailed results detailed_results = _format_detailed_results(results) return status_msg, zip_path, detailed_results elif results['status'] == 'warning': return f"⚠️ {results['message']}", None, results.get('message', 'No details available') else: return f"❌ Processing failed: {results['message']}", None, results.get('message', 'Unknown error') except Exception as e: logger.error(f"Error in process_text_request: {e}") return f"❌ An error occurred: {str(e)}", None, f"Error details: {str(e)}" def _format_detailed_results(results): """Format detailed results for display""" if not results.get('results'): return "No detailed results available." details = [] details.append(f"📊 **Processing Summary:**") details.append(f"- Total entities found: {results['stats']['total_entities']}") details.append(f"- Total logos downloaded: {results['stats']['total_downloads']}") details.append(f"- Successful entities: {results['stats']['successful_entities']}") details.append(f"- Failed entities: {results['stats']['failed_entities']}") details.append("") details.append("📋 **Entity Details:**") for result in results['results']: entity = result['entity'] count = result['downloaded_count'] if count > 0: details.append(f"✅ **{entity}**: {count} logos downloaded") else: error_msg = result.get('error', 'No logos found') details.append(f"❌ **{entity}**: Failed ({error_msg})") return "\n".join(details) def create_interface(): """Create and configure Gradio interface""" # Custom CSS for better styling css = """ .gradio-container { max-width: 1200px !important; margin: auto !important; } .main-header { text-align: center; margin-bottom: 2rem; } .status-success { color: #10b981 !important; } .status-error { color: #ef4444 !important; } .status-warning { color: #f59e0b !important; } """ with gr.Blocks(css=css, title="Logo Downloader", theme=gr.themes.Soft()) as interface: # Header gr.HTML("""

🎨 Logo Downloader

Extract entities from text and download their logos automatically

""") with gr.Row(): with gr.Column(scale=2): # Input section gr.Markdown("## 📝 Input") text_input = gr.Textbox( label="Text to analyze", placeholder="Enter text containing company names, products, or brands (e.g., 'We use AWS, Docker, React, and Adobe Photoshop for our projects')", lines=5, max_lines=10 ) with gr.Row(): api_key_input = gr.Textbox( label="Gemini API Key (optional)", placeholder="Enter your Gemini API key for better entity extraction", type="password", value="" ) num_logos_input = gr.Slider( label="Logos per entity", minimum=1, maximum=MAX_LOGOS_PER_ENTITY, value=DEFAULT_LOGOS_PER_ENTITY, step=1 ) process_btn = gr.Button("🚀 Download Logos", variant="primary", size="lg") # API key help gr.Markdown(""" 💡 **Tip:** Get a free Gemini API key at [Google AI Studio](https://makersuite.google.com/app/apikey) for better entity extraction. Without an API key, the tool will use basic pattern matching. """) with gr.Column(scale=1): # Output section gr.Markdown("## 📊 Results") status_output = gr.Textbox( label="Status", interactive=False, lines=2 ) download_output = gr.File( label="Download ZIP", interactive=False ) detailed_output = gr.Textbox( label="Detailed Results", interactive=False, lines=10, max_lines=15 ) # Examples section gr.Markdown("## 💡 Examples") examples = [ [ "Our tech stack includes React, Node.js, MongoDB, Docker, AWS, and we use Figma for design, along with GitHub for version control.", "", 8 ], [ "The team uses Microsoft Office, Adobe Creative Suite, Slack for communication, Zoom for meetings, and Salesforce for CRM.", "", 6 ], [ "Popular social media platforms like Instagram, TikTok, Twitter, LinkedIn, and YouTube are essential for digital marketing.", "", 5 ] ] gr.Examples( examples=examples, inputs=[text_input, api_key_input, num_logos_input], outputs=[status_output, download_output, detailed_output], fn=process_text_request, cache_examples=False ) # Process button click event process_btn.click( fn=process_text_request, inputs=[text_input, api_key_input, num_logos_input], outputs=[status_output, download_output, detailed_output], show_progress='minimal' ) # Footer gr.HTML("""

🔧 Built with Gradio | 🤖 Powered by Gemini AI

This tool respects rate limits and downloads publicly available logos.

""") return interface def main(): """Main function to launch the application""" logger.info("Starting Logo Downloader application...") # Check for API key if not GEMINI_API_KEY: logger.warning("No Gemini API key found in environment variables") logger.info("The application will work with fallback entity extraction") else: logger.info("Gemini API key found") # Create and launch interface interface = create_interface() # Launch configuration launch_kwargs = { "server_name": "0.0.0.0", "server_port": int(os.environ.get("PORT", 7860)), "share": False, "show_error": True, "max_threads": 4 } # Launch the interface interface.launch(**launch_kwargs) if __name__ == "__main__": main()