File size: 3,415 Bytes
75c718c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import asyncio
import asyncpg
import csv
import argparse
import os
import re
from dotenv import load_dotenv

load_dotenv()

DATABASE_URL = os.getenv("DATABASE_URL")

def normalize_phone(phone: str) -> str:
    """Normalize phone number to E.164 format for matching."""
    phone = str(phone).strip()
    if not phone:
        return ""
    phone = re.sub(r'[\s\-\(\)]', '', phone)
    if phone.startswith('+'): return phone
    if phone.startswith('91') and len(phone) == 12: return f'+{phone}'
    if len(phone) == 10 and phone[0] in '6789': return f'+91{phone}'
    return f'+{phone}' if not phone.startswith('+') else phone

async def import_contacts(csv_file: str, tenant_id: str):
    if not DATABASE_URL:
        print("ERROR: DATABASE_URL not set in .env")
        return

    print(f"Connecting to database to import contacts for tenant {tenant_id}...")
    conn = await asyncpg.connect(DATABASE_URL)
    
    success_count = 0
    fail_count = 0

    try:
        with open(csv_file, mode='r', encoding='utf-8-sig') as f:
            reader = csv.DictReader(f)
            
            # Expected columns: Name, Phone, Notes (optional)
            for row in reader:
                raw_phone = row.get("Phone", "").strip()
                name = row.get("Name", "").strip()
                notes = row.get("Notes", "").strip()
                
                if not raw_phone or not name:
                    print(f"Skipping invalid row: {row}")
                    fail_count += 1
                    continue
                
                phone = normalize_phone(raw_phone)
                
                try:
                    # Upsert contact
                    # We set call_count = 0 so that they are still considered "first time callers" 
                    # from the system's perspective of having an actual conversation, 
                    # but we WILL know their name and greet them warmly because of the data presence!
                    await conn.execute(
                        """
                        INSERT INTO caller_profiles (tenant_id, phone_number, name, notes, call_count)
                        VALUES ($1, $2, $3, $4, 0)
                        ON CONFLICT (tenant_id, phone_number) 
                        DO UPDATE SET name = EXCLUDED.name, notes = EXCLUDED.notes
                        """,
                        tenant_id, phone, name, notes if notes else None
                    )
                    success_count += 1
                except Exception as e:
                    print(f"Failed to insert {name} ({phone}): {e}")
                    fail_count += 1

        print(f"\n✅ Import complete! Successfully added/updated {success_count} contacts.")
        if fail_count > 0:
            print(f"❌ Failed to import {fail_count} contacts.")
            
    except FileNotFoundError:
        print(f"ERROR: File '{csv_file}' not found.")
    except Exception as e:
        print(f"ERROR: {e}")
    finally:
        await conn.close()

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Import existing client contacts into Maya's memory.")
    parser.add_argument("csv_file", help="Path to the CSV file (must have 'Name' and 'Phone' columns)")
    parser.add_argument("--tenant", required=True, help="Tenant UUID")
    
    args = parser.parse_args()
    asyncio.run(import_contacts(args.csv_file, args.tenant))