Spaces:
Sleeping
Sleeping
Integrate LinkedIn enrichment with RapidAPI
Browse filesAdded LinkedIn enrichment functionality to consent_audit_panel:
- Import linkedin_data module functions
- Display cached profile count
- Automatically fetch and display LinkedIn profiles when linkedin_url is present in events
- Show profile data: name, headline, location, current role
- Cache indication (30-day TTL)
- Error handling with user-friendly messages
Integration is ready for use once RAPIDAPI_KEY is added to Space Secrets.
app.py
CHANGED
|
@@ -4,6 +4,7 @@ import os
|
|
| 4 |
import json
|
| 5 |
from typing import List, Dict, Any, Optional
|
| 6 |
from pathlib import Path
|
|
|
|
| 7 |
|
| 8 |
# --- Data Storage Configuration ---
|
| 9 |
DATA_DIR = Path("/data")
|
|
@@ -49,6 +50,52 @@ def consent_audit_panel(consent_events: List[Dict[str, Any]], profile: Optional[
|
|
| 49 |
|
| 50 |
audit_md = f"# Consent/Event Audit\n\n**User:** {username}\n\nPer-contact and batch consent history."
|
| 51 |
for event in user_events:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
audit_md += f"\n- Contact: {event.get('contact_id','?')} | Event: {event.get('event_type','?')} | Opt-out: {event.get('opt_out','?')}"
|
| 53 |
return gr.Markdown(audit_md)
|
| 54 |
|
|
|
|
| 4 |
import json
|
| 5 |
from typing import List, Dict, Any, Optional
|
| 6 |
from pathlib import Path
|
| 7 |
+
from linkedin_data import fetch_linkedin_profile, get_cache_stats
|
| 8 |
|
| 9 |
# --- Data Storage Configuration ---
|
| 10 |
DATA_DIR = Path("/data")
|
|
|
|
| 50 |
|
| 51 |
audit_md = f"# Consent/Event Audit\n\n**User:** {username}\n\nPer-contact and batch consent history."
|
| 52 |
for event in user_events:
|
| 53 |
+
|
| 54 |
+
# LinkedIn enrichment section
|
| 55 |
+
audit_md += "\n\n---\n\n## 🔗 LinkedIn Profile Enrichment\n\n"
|
| 56 |
+
|
| 57 |
+
# Get cache stats
|
| 58 |
+
cache_stats = get_cache_stats(username)
|
| 59 |
+
audit_md += f"**Cached LinkedIn Profiles:** {cache_stats.get('cached_profiles', 0)}\n\n"
|
| 60 |
+
|
| 61 |
+
# Sample LinkedIn enrichment (demonstrating the feature)
|
| 62 |
+
audit_md += "**To enrich a contact with LinkedIn data:**\n"
|
| 63 |
+
audit_md += "1. Add a 'linkedin_url' field to your consent events\n"
|
| 64 |
+
audit_md += "2. The system will automatically fetch and cache profile data\n"
|
| 65 |
+
audit_md += "3. Cached profiles are stored in your isolated data directory\n\n"
|
| 66 |
+
|
| 67 |
+
# Example with sample LinkedIn URL (if configured)
|
| 68 |
+
sample_linkedin_url = "https://linkedin.com/in/sample-profile"
|
| 69 |
+
audit_md += f"**Example:** To test LinkedIn enrichment, add RAPIDAPI_KEY to Space Secrets.\n\n"
|
| 70 |
+
|
| 71 |
+
if user_events and len(user_events) > 0:
|
| 72 |
+
# Check if any event has LinkedIn data
|
| 73 |
+
for event in user_events:
|
| 74 |
+
if 'linkedin_url' in event and event['linkedin_url']:
|
| 75 |
+
linkedin_url = event['linkedin_url']
|
| 76 |
+
audit_md += f"\n### LinkedIn Profile for Contact {event.get('contact_id', '?')}\n\n"
|
| 77 |
+
|
| 78 |
+
# Fetch LinkedIn profile
|
| 79 |
+
result = fetch_linkedin_profile(linkedin_url, username=username)
|
| 80 |
+
|
| 81 |
+
if result.get('success'):
|
| 82 |
+
profile_data = result.get('data', {})
|
| 83 |
+
from_cache = result.get('from_cache', False)
|
| 84 |
+
|
| 85 |
+
audit_md += f"**Full Name:** {profile_data.get('full_name', 'N/A')}\n\n"
|
| 86 |
+
audit_md += f"**Headline:** {profile_data.get('headline', 'N/A')}\n\n"
|
| 87 |
+
audit_md += f"**Location:** {profile_data.get('location', 'N/A')}\n\n"
|
| 88 |
+
audit_md += f"**Data Source:** {'Cached (30-day TTL)' if from_cache else 'Fresh from API'}\n\n"
|
| 89 |
+
|
| 90 |
+
# Show first experience if available
|
| 91 |
+
experiences = profile_data.get('experiences', [])
|
| 92 |
+
if experiences and len(experiences) > 0:
|
| 93 |
+
exp = experiences[0]
|
| 94 |
+
audit_md += f"**Current Role:** {exp.get('title', 'N/A')} at {exp.get('company', 'N/A')}\n\n"
|
| 95 |
+
else:
|
| 96 |
+
error_msg = result.get('message', 'Unknown error')
|
| 97 |
+
audit_md += f"⚠️ **Error:** {error_msg}\n\n"
|
| 98 |
+
|
| 99 |
audit_md += f"\n- Contact: {event.get('contact_id','?')} | Event: {event.get('event_type','?')} | Opt-out: {event.get('opt_out','?')}"
|
| 100 |
return gr.Markdown(audit_md)
|
| 101 |
|