Download app.py from JayBene1/apptest3: direct link, hf CLI and curl.
- Browser
- Download file 10.6 kB
-
https://huggingface.co/spaces/JayBene1/apptest3/resolve/main/app.py
- Command line
-
hf download hf://spaces/JayBene1/apptest3/app.py
-
curl -L -o app.py https://huggingface.co/spaces/JayBene1/apptest3/resolve/main/app.py
10.6 kB
| import gradio as gr | |
| import requests | |
| import json | |
| from typing import List, Dict, Any | |
| import pandas as pd | |
| # Hardcoded API endpoint | |
| API_ENDPOINT = "https://huggingface.co/spaces/JayBene1/testapicontacts" | |
| # Professional color scheme inspired by corporate/real estate companies | |
| theme = gr.themes.Soft( | |
| primary_hue="blue", | |
| secondary_hue="slate", | |
| neutral_hue="slate", | |
| text_size="md", | |
| spacing_size="md", | |
| radius_size="md" | |
| ).set( | |
| body_background_fill="#f8fafc", | |
| body_background_fill_dark="#1e293b", | |
| block_background_fill="#ffffff", | |
| block_background_fill_dark="#334155", | |
| block_border_color="#e2e8f0", | |
| block_border_color_dark="#475569", | |
| input_background_fill="#ffffff", | |
| input_background_fill_dark="#334155", | |
| input_border_color="#cbd5e1", | |
| input_border_color_dark="#64748b", | |
| button_primary_background_fill="#1e40af", | |
| button_primary_background_fill_hover="#1d4ed8", | |
| button_primary_text_color="#ffffff", | |
| button_secondary_background_fill="#f1f5f9", | |
| button_secondary_background_fill_hover="#e2e8f0", | |
| button_secondary_text_color="#334155" | |
| ) | |
| def search_contacts(url: str) -> tuple[str, str]: | |
| """ | |
| Search for contacts associated with a given URL using the Hugging Face API. | |
| Args: | |
| url: The website URL to search for contacts | |
| Returns: | |
| Tuple of (formatted_results, raw_json) | |
| """ | |
| if not url.strip(): | |
| return "β Please enter a website URL", "" | |
| # Clean and validate URL | |
| url = url.strip() | |
| if not url.startswith(('http://', 'https://')): | |
| url = 'https://' + url | |
| try: | |
| # Prepare the API request | |
| headers = { | |
| 'Content-Type': 'application/json' | |
| } | |
| payload = { | |
| "inputs": url, | |
| "parameters": { | |
| "task": "contact_search", | |
| "url": url | |
| } | |
| } | |
| # Make the API request to the hardcoded endpoint | |
| response = requests.post( | |
| API_ENDPOINT, | |
| headers=headers, | |
| json=payload, | |
| timeout=30 | |
| ) | |
| if response.status_code == 200: | |
| try: | |
| result = response.json() | |
| # Format the results for display | |
| formatted_output = format_contact_results(result, url) | |
| raw_json = json.dumps(result, indent=2) | |
| return formatted_output, raw_json | |
| except json.JSONDecodeError: | |
| return f"β Error: Invalid JSON response from API", response.text | |
| else: | |
| return f"β API Error ({response.status_code}): {response.text}", "" | |
| except requests.exceptions.Timeout: | |
| return "β Request timeout. Please try again.", "" | |
| except requests.exceptions.ConnectionError: | |
| return "β Connection error. Please check your API endpoint.", "" | |
| except Exception as e: | |
| return f"β Error: {str(e)}", "" | |
| def format_contact_results(results: Dict[Any, Any], url: str) -> str: | |
| """ | |
| Format the API results into a readable format. | |
| Args: | |
| results: The JSON response from the API | |
| url: The searched URL | |
| Returns: | |
| Formatted string with contact information | |
| """ | |
| output = f"# π Contact Search Results for: {url}\n\n" | |
| # Handle different possible result structures | |
| if isinstance(results, dict): | |
| if 'contacts' in results: | |
| contacts = results['contacts'] | |
| elif 'results' in results: | |
| contacts = results['results'] | |
| elif 'data' in results: | |
| contacts = results['data'] | |
| else: | |
| contacts = results | |
| if isinstance(contacts, list) and len(contacts) > 0: | |
| output += f"**Found {len(contacts)} contact(s):**\n\n" | |
| for i, contact in enumerate(contacts, 1): | |
| output += f"## π€ Contact {i}\n" | |
| # Handle different contact field names | |
| name = contact.get('name') or contact.get('full_name') or contact.get('contact_name') or "N/A" | |
| email = contact.get('email') or contact.get('email_address') or "N/A" | |
| title = contact.get('title') or contact.get('job_title') or contact.get('position') or "N/A" | |
| company = contact.get('company') or contact.get('organization') or "N/A" | |
| phone = contact.get('phone') or contact.get('phone_number') or "N/A" | |
| linkedin = contact.get('linkedin') or contact.get('linkedin_url') or "N/A" | |
| output += f"- **Name:** {name}\n" | |
| output += f"- **Email:** {email}\n" | |
| output += f"- **Title:** {title}\n" | |
| output += f"- **Company:** {company}\n" | |
| output += f"- **Phone:** {phone}\n" | |
| output += f"- **LinkedIn:** {linkedin}\n\n" | |
| # Add any additional fields | |
| additional_fields = {k: v for k, v in contact.items() | |
| if k not in ['name', 'full_name', 'contact_name', 'email', 'email_address', | |
| 'title', 'job_title', 'position', 'company', 'organization', | |
| 'phone', 'phone_number', 'linkedin', 'linkedin_url']} | |
| if additional_fields: | |
| output += "**Additional Information:**\n" | |
| for key, value in additional_fields.items(): | |
| output += f"- **{key.replace('_', ' ').title()}:** {value}\n" | |
| output += "\n" | |
| output += "---\n\n" | |
| else: | |
| output += "β No contacts found for this URL.\n\n" | |
| elif isinstance(results, list): | |
| if len(results) > 0: | |
| output += f"**Found {len(results)} contact(s):**\n\n" | |
| for i, contact in enumerate(results, 1): | |
| output += f"## π€ Contact {i}\n" | |
| output += f"{contact}\n\n" | |
| else: | |
| output += "β No contacts found for this URL.\n\n" | |
| else: | |
| output += f"**Result:** {results}\n\n" | |
| output += f"*Search completed at: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}*" | |
| return output | |
| def create_sample_data(): | |
| """Create sample data for demonstration""" | |
| return '''# π Contact Search Results for: example.com | |
| **Found 2 contact(s):** | |
| ## π€ Contact 1 | |
| - **Name:** John Smith | |
| - **Email:** john.smith@example.com | |
| - **Title:** CEO | |
| - **Company:** Example Corp | |
| - **Phone:** (555) 123-4567 | |
| - **LinkedIn:** linkedin.com/in/johnsmith | |
| --- | |
| ## π€ Contact 2 | |
| - **Name:** Jane Doe | |
| - **Email:** jane.doe@example.com | |
| - **Title:** VP of Sales | |
| - **Company:** Example Corp | |
| - **Phone:** (555) 123-4568 | |
| - **LinkedIn:** linkedin.com/in/janedoe | |
| --- | |
| *Search completed at: 2025-01-15 10:30:00*''' | |
| # Create the Gradio interface | |
| with gr.Blocks(theme=theme, title="Contact Search - Kwekel Companies", css=""" | |
| .gradio-container { | |
| max-width: 1200px !important; | |
| margin: 0 auto !important; | |
| } | |
| .header { | |
| background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%); | |
| color: white; | |
| padding: 2rem; | |
| border-radius: 0.5rem; | |
| margin-bottom: 2rem; | |
| text-align: center; | |
| } | |
| .header h1 { | |
| margin: 0; | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| margin-bottom: 0.5rem; | |
| } | |
| .header p { | |
| margin: 0; | |
| font-size: 1.2rem; | |
| opacity: 0.9; | |
| } | |
| .info-box { | |
| background: #f0f9ff; | |
| border: 1px solid #0ea5e9; | |
| border-radius: 0.5rem; | |
| padding: 1rem; | |
| margin: 1rem 0; | |
| } | |
| .footer { | |
| text-align: center; | |
| margin-top: 2rem; | |
| padding-top: 2rem; | |
| border-top: 1px solid #e2e8f0; | |
| color: #64748b; | |
| } | |
| """) as demo: | |
| # Header | |
| gr.HTML(""" | |
| <div class="header"> | |
| <h1>π Contact Search Tool</h1> | |
| <p>Professional contact discovery powered by AI</p> | |
| </div> | |
| """) | |
| # Info box | |
| gr.HTML(f""" | |
| <div class="info-box"> | |
| <h3>π Instructions:</h3> | |
| <ol> | |
| <li>Enter the website URL you want to search for contacts</li> | |
| <li>Click "Search Contacts" to get results</li> | |
| <li>View formatted results and raw JSON response</li> | |
| </ol> | |
| <p><strong>API Endpoint:</strong> {API_ENDPOINT}</p> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| url_input = gr.Textbox( | |
| label="π Website URL", | |
| placeholder="example.com or https://example.com", | |
| info="Enter the website URL to search for contacts", | |
| lines=1 | |
| ) | |
| with gr.Row(): | |
| search_btn = gr.Button("π Search Contacts", variant="primary", scale=2) | |
| demo_btn = gr.Button("π Show Demo", variant="secondary", scale=1) | |
| clear_btn = gr.Button("ποΈ Clear", variant="secondary", scale=1) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| results_output = gr.Markdown( | |
| label="π Contact Results", | |
| value="Enter a URL and click 'Search Contacts' to see results here.", | |
| height=400 | |
| ) | |
| with gr.Column(scale=1): | |
| json_output = gr.Code( | |
| label="π Raw JSON Response", | |
| language="json", | |
| value="", | |
| height=400 | |
| ) | |
| # Event handlers | |
| search_btn.click( | |
| fn=search_contacts, | |
| inputs=[url_input], | |
| outputs=[results_output, json_output] | |
| ) | |
| demo_btn.click( | |
| fn=lambda: (create_sample_data(), '{"contacts": [{"name": "John Smith", "email": "john.smith@example.com", "title": "CEO"}]}'), | |
| outputs=[results_output, json_output] | |
| ) | |
| clear_btn.click( | |
| fn=lambda: ("", ""), | |
| outputs=[url_input, results_output] | |
| ) | |
| # Footer | |
| gr.HTML(""" | |
| <div class="footer"> | |
| <p>Β© 2025 Contact Search Tool - Professional contact discovery solution</p> | |
| </div> | |
| """) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.launch( | |
| share=True, | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| show_error=True, | |
| debug=True | |
| ) |