JayBene1 commited on
Commit
9c1601a
Β·
verified Β·
1 Parent(s): fffbdce

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +331 -0
app.py ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import json
4
+ from typing import List, Dict, Any
5
+ import pandas as pd
6
+
7
+ # Hardcoded API endpoint
8
+ API_ENDPOINT = "https://huggingface.co/spaces/JayBene1/testapicontacts"
9
+
10
+ # Professional color scheme inspired by corporate/real estate companies
11
+ theme = gr.themes.Soft(
12
+ primary_hue="blue",
13
+ secondary_hue="slate",
14
+ neutral_hue="slate",
15
+ text_size="md",
16
+ spacing_size="md",
17
+ radius_size="md"
18
+ ).set(
19
+ body_background_fill="#f8fafc",
20
+ body_background_fill_dark="#1e293b",
21
+ block_background_fill="#ffffff",
22
+ block_background_fill_dark="#334155",
23
+ block_border_color="#e2e8f0",
24
+ block_border_color_dark="#475569",
25
+ input_background_fill="#ffffff",
26
+ input_background_fill_dark="#334155",
27
+ input_border_color="#cbd5e1",
28
+ input_border_color_dark="#64748b",
29
+ button_primary_background_fill="#1e40af",
30
+ button_primary_background_fill_hover="#1d4ed8",
31
+ button_primary_text_color="#ffffff",
32
+ button_secondary_background_fill="#f1f5f9",
33
+ button_secondary_background_fill_hover="#e2e8f0",
34
+ button_secondary_text_color="#334155"
35
+ )
36
+
37
+ def search_contacts(url: str) -> tuple[str, str]:
38
+ """
39
+ Search for contacts associated with a given URL using the Hugging Face API.
40
+
41
+ Args:
42
+ url: The website URL to search for contacts
43
+
44
+ Returns:
45
+ Tuple of (formatted_results, raw_json)
46
+ """
47
+
48
+ if not url.strip():
49
+ return "❌ Please enter a website URL", ""
50
+
51
+ # Clean and validate URL
52
+ url = url.strip()
53
+ if not url.startswith(('http://', 'https://')):
54
+ url = 'https://' + url
55
+
56
+ try:
57
+ # Prepare the API request
58
+ headers = {
59
+ 'Content-Type': 'application/json'
60
+ }
61
+
62
+ payload = {
63
+ "inputs": url,
64
+ "parameters": {
65
+ "task": "contact_search",
66
+ "url": url
67
+ }
68
+ }
69
+
70
+ # Make the API request to the hardcoded endpoint
71
+ response = requests.post(
72
+ API_ENDPOINT,
73
+ headers=headers,
74
+ json=payload,
75
+ timeout=30
76
+ )
77
+
78
+ if response.status_code == 200:
79
+ try:
80
+ result = response.json()
81
+
82
+ # Format the results for display
83
+ formatted_output = format_contact_results(result, url)
84
+ raw_json = json.dumps(result, indent=2)
85
+
86
+ return formatted_output, raw_json
87
+
88
+ except json.JSONDecodeError:
89
+ return f"❌ Error: Invalid JSON response from API", response.text
90
+
91
+ else:
92
+ return f"❌ API Error ({response.status_code}): {response.text}", ""
93
+
94
+ except requests.exceptions.Timeout:
95
+ return "❌ Request timeout. Please try again.", ""
96
+ except requests.exceptions.ConnectionError:
97
+ return "❌ Connection error. Please check your API endpoint.", ""
98
+ except Exception as e:
99
+ return f"❌ Error: {str(e)}", ""
100
+
101
+ def format_contact_results(results: Dict[Any, Any], url: str) -> str:
102
+ """
103
+ Format the API results into a readable format.
104
+
105
+ Args:
106
+ results: The JSON response from the API
107
+ url: The searched URL
108
+
109
+ Returns:
110
+ Formatted string with contact information
111
+ """
112
+
113
+ output = f"# πŸ” Contact Search Results for: {url}\n\n"
114
+
115
+ # Handle different possible result structures
116
+ if isinstance(results, dict):
117
+ if 'contacts' in results:
118
+ contacts = results['contacts']
119
+ elif 'results' in results:
120
+ contacts = results['results']
121
+ elif 'data' in results:
122
+ contacts = results['data']
123
+ else:
124
+ contacts = results
125
+
126
+ if isinstance(contacts, list) and len(contacts) > 0:
127
+ output += f"**Found {len(contacts)} contact(s):**\n\n"
128
+
129
+ for i, contact in enumerate(contacts, 1):
130
+ output += f"## πŸ‘€ Contact {i}\n"
131
+
132
+ # Handle different contact field names
133
+ name = contact.get('name') or contact.get('full_name') or contact.get('contact_name') or "N/A"
134
+ email = contact.get('email') or contact.get('email_address') or "N/A"
135
+ title = contact.get('title') or contact.get('job_title') or contact.get('position') or "N/A"
136
+ company = contact.get('company') or contact.get('organization') or "N/A"
137
+ phone = contact.get('phone') or contact.get('phone_number') or "N/A"
138
+ linkedin = contact.get('linkedin') or contact.get('linkedin_url') or "N/A"
139
+
140
+ output += f"- **Name:** {name}\n"
141
+ output += f"- **Email:** {email}\n"
142
+ output += f"- **Title:** {title}\n"
143
+ output += f"- **Company:** {company}\n"
144
+ output += f"- **Phone:** {phone}\n"
145
+ output += f"- **LinkedIn:** {linkedin}\n\n"
146
+
147
+ # Add any additional fields
148
+ additional_fields = {k: v for k, v in contact.items()
149
+ if k not in ['name', 'full_name', 'contact_name', 'email', 'email_address',
150
+ 'title', 'job_title', 'position', 'company', 'organization',
151
+ 'phone', 'phone_number', 'linkedin', 'linkedin_url']}
152
+
153
+ if additional_fields:
154
+ output += "**Additional Information:**\n"
155
+ for key, value in additional_fields.items():
156
+ output += f"- **{key.replace('_', ' ').title()}:** {value}\n"
157
+ output += "\n"
158
+
159
+ output += "---\n\n"
160
+
161
+ else:
162
+ output += "❌ No contacts found for this URL.\n\n"
163
+
164
+ elif isinstance(results, list):
165
+ if len(results) > 0:
166
+ output += f"**Found {len(results)} contact(s):**\n\n"
167
+ for i, contact in enumerate(results, 1):
168
+ output += f"## πŸ‘€ Contact {i}\n"
169
+ output += f"{contact}\n\n"
170
+ else:
171
+ output += "❌ No contacts found for this URL.\n\n"
172
+ else:
173
+ output += f"**Result:** {results}\n\n"
174
+
175
+ output += f"*Search completed at: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}*"
176
+
177
+ return output
178
+
179
+ def create_sample_data():
180
+ """Create sample data for demonstration"""
181
+ return '''# πŸ” Contact Search Results for: example.com
182
+
183
+ **Found 2 contact(s):**
184
+
185
+ ## πŸ‘€ Contact 1
186
+ - **Name:** John Smith
187
+ - **Email:** john.smith@example.com
188
+ - **Title:** CEO
189
+ - **Company:** Example Corp
190
+ - **Phone:** (555) 123-4567
191
+ - **LinkedIn:** linkedin.com/in/johnsmith
192
+
193
+ ---
194
+
195
+ ## πŸ‘€ Contact 2
196
+ - **Name:** Jane Doe
197
+ - **Email:** jane.doe@example.com
198
+ - **Title:** VP of Sales
199
+ - **Company:** Example Corp
200
+ - **Phone:** (555) 123-4568
201
+ - **LinkedIn:** linkedin.com/in/janedoe
202
+
203
+ ---
204
+
205
+ *Search completed at: 2025-01-15 10:30:00*'''
206
+
207
+ # Create the Gradio interface
208
+ with gr.Blocks(theme=theme, title="Contact Search - Kwekel Companies", css="""
209
+ .gradio-container {
210
+ max-width: 1200px !important;
211
+ margin: 0 auto !important;
212
+ }
213
+ .header {
214
+ background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%);
215
+ color: white;
216
+ padding: 2rem;
217
+ border-radius: 0.5rem;
218
+ margin-bottom: 2rem;
219
+ text-align: center;
220
+ }
221
+ .header h1 {
222
+ margin: 0;
223
+ font-size: 2.5rem;
224
+ font-weight: 700;
225
+ margin-bottom: 0.5rem;
226
+ }
227
+ .header p {
228
+ margin: 0;
229
+ font-size: 1.2rem;
230
+ opacity: 0.9;
231
+ }
232
+ .info-box {
233
+ background: #f0f9ff;
234
+ border: 1px solid #0ea5e9;
235
+ border-radius: 0.5rem;
236
+ padding: 1rem;
237
+ margin: 1rem 0;
238
+ }
239
+ .footer {
240
+ text-align: center;
241
+ margin-top: 2rem;
242
+ padding-top: 2rem;
243
+ border-top: 1px solid #e2e8f0;
244
+ color: #64748b;
245
+ }
246
+ """) as demo:
247
+
248
+ # Header
249
+ gr.HTML("""
250
+ <div class="header">
251
+ <h1>πŸ” Contact Search Tool</h1>
252
+ <p>Professional contact discovery powered by AI</p>
253
+ </div>
254
+ """)
255
+
256
+ # Info box
257
+ gr.HTML(f"""
258
+ <div class="info-box">
259
+ <h3>πŸ“‹ Instructions:</h3>
260
+ <ol>
261
+ <li>Enter the website URL you want to search for contacts</li>
262
+ <li>Click "Search Contacts" to get results</li>
263
+ <li>View formatted results and raw JSON response</li>
264
+ </ol>
265
+ <p><strong>API Endpoint:</strong> {API_ENDPOINT}</p>
266
+ </div>
267
+ """)
268
+
269
+ with gr.Row():
270
+ with gr.Column(scale=2):
271
+ url_input = gr.Textbox(
272
+ label="🌐 Website URL",
273
+ placeholder="example.com or https://example.com",
274
+ info="Enter the website URL to search for contacts",
275
+ lines=1
276
+ )
277
+
278
+ with gr.Row():
279
+ search_btn = gr.Button("πŸ” Search Contacts", variant="primary", scale=2)
280
+ demo_btn = gr.Button("πŸ“‹ Show Demo", variant="secondary", scale=1)
281
+ clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", scale=1)
282
+
283
+ with gr.Row():
284
+ with gr.Column(scale=1):
285
+ results_output = gr.Markdown(
286
+ label="πŸ“Š Contact Results",
287
+ value="Enter a URL and click 'Search Contacts' to see results here.",
288
+ height=400
289
+ )
290
+
291
+ with gr.Column(scale=1):
292
+ json_output = gr.Code(
293
+ label="πŸ“ Raw JSON Response",
294
+ language="json",
295
+ value="",
296
+ height=400
297
+ )
298
+
299
+ # Event handlers
300
+ search_btn.click(
301
+ fn=search_contacts,
302
+ inputs=[url_input],
303
+ outputs=[results_output, json_output]
304
+ )
305
+
306
+ demo_btn.click(
307
+ fn=lambda: (create_sample_data(), '{"contacts": [{"name": "John Smith", "email": "john.smith@example.com", "title": "CEO"}]}'),
308
+ outputs=[results_output, json_output]
309
+ )
310
+
311
+ clear_btn.click(
312
+ fn=lambda: ("", ""),
313
+ outputs=[url_input, results_output]
314
+ )
315
+
316
+ # Footer
317
+ gr.HTML("""
318
+ <div class="footer">
319
+ <p>Β© 2025 Contact Search Tool - Professional contact discovery solution</p>
320
+ </div>
321
+ """)
322
+
323
+ # Launch the app
324
+ if __name__ == "__main__":
325
+ demo.launch(
326
+ share=True,
327
+ server_name="0.0.0.0",
328
+ server_port=7860,
329
+ show_error=True,
330
+ debug=True
331
+ )