Spaces:
Sleeping
Sleeping
| from datetime import datetime, timezone | |
| from urllib.parse import urlparse | |
| def normalize_url(url: str | None) -> str | None: | |
| """Normalize user-provided URL to include scheme and validate basic structure.""" | |
| if not url: | |
| return None | |
| url = url.strip() | |
| if not url: | |
| return None | |
| if not url.startswith(("http://", "https://")): | |
| url = "https://" + url # add https if missing | |
| # quick parse check | |
| parsed = urlparse(url) | |
| if not parsed.netloc: | |
| return None # invalid URL | |
| return url | |
| def extract_tally_payload(payload: dict): | |
| """ | |
| Extracts key chatbot information from a Tally webhook payload. | |
| Handles optional/missing multi-select and dropdown values. | |
| """ | |
| fields = payload.get("data", {}).get("fields", []) | |
| # Map key -> field | |
| key_map = {f["key"]: f for f in fields} | |
| # Submission ID | |
| submission_id = payload.get("data", {}).get("submissionId") | |
| pricing_plan = key_map.get("question_K6rZP8_15f06788-71a0-4a4a-903e-68944b6cb967", {}).get("value") or None | |
| # Company info | |
| company_name = key_map.get("question_kyp5Dd", {}).get("value") | |
| chatbot_name = key_map.get("question_vAp47X", {}).get("value") or f"{company_name} Assistant" | |
| raw_url = key_map.get("question_K6gL7z", {}).get("value") | |
| website_url = normalize_url(raw_url) | |
| # Multi-select chatbot purpose | |
| purpose_field = key_map.get("question_1lxMZ4", {}) | |
| option_map = {opt["id"]: opt["text"] for opt in purpose_field.get("options", [])} | |
| value_ids = purpose_field.get("value") or [] | |
| chatbot_purpose = [option_map.get(v, v) for v in value_ids] | |
| # Multi-select additional content | |
| content_field = key_map.get("question_MbgLkE", {}) | |
| content_option_map = {opt["id"]: opt["text"] for opt in content_field.get("options", [])} | |
| value_ids = content_field.get("value") or [] | |
| additional_content = [content_option_map.get(v, v) for v in value_ids] | |
| # Sensitive topics | |
| sensitive_topics = key_map.get("question_J6gLaz", {}).get("value") or None | |
| # Tone/style dropdown | |
| tone_field = key_map.get("question_N694OQ", {}) | |
| tone_option_map = {opt["id"]: opt["text"] for opt in tone_field.get("options", [])} | |
| value_ids = tone_field.get("value") or [] | |
| tone_style = [tone_option_map.get(v, v) for v in value_ids] if value_ids else None | |
| # Contact | |
| contact_email = key_map.get("question_qd7YN7", {}).get("value") | |
| contact_phone = key_map.get("question_QDaxEp", {}).get("value") | |
| # Timestamps | |
| submitted_at_str = payload.get("data", {}).get("createdAt") | |
| submitted_at = datetime.fromisoformat(submitted_at_str.replace("Z", "+00:00")) | |
| return { | |
| "submission_id": submission_id, | |
| "company_name": company_name, | |
| "chatbot_name": chatbot_name, | |
| "pricing_plan": pricing_plan, | |
| "website_url": website_url, | |
| "chatbot_purpose": chatbot_purpose, | |
| "additional_content": additional_content, | |
| "sensitive_topics": sensitive_topics, | |
| "tone_style": tone_style, | |
| "contact_email": contact_email, | |
| "contact_phone": contact_phone, | |
| "submitted_at": submitted_at, | |
| } | |