Csv To Vcf -

def __init__(self): self.version = "3.0" self.encoding_detected = False def detect_encoding(self, file_path: str) -> str: """Detect file encoding automatically""" with open(file_path, 'rb') as f: raw_data = f.read() result = chardet.detect(raw_data) return result['encoding'] or 'utf-8'

def escape_vcf_text(self, text: str) -> str: """Escape special characters for VCF format""" if not text: return "" # VCF escaping rules text = text.replace('\\', '\\\\') text = text.replace(';', '\\;') text = text.replace(',', '\\,') text = text.replace('\n', '\\n') text = text.replace('\r', '') return text

class CSVToVCFConverter: """Convert CSV contacts to VCF vCard format""" csv to vcf

with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f: f.write(csv_content) f.flush() result = self.converter.convert_to_string(f.name) self.assertIn("FN:John Doe", result) self.assertIn("TEL;TYPE=CELL:+1234567890", result) os.unlink(f.name)

def read_csv(self, file_path: str, encoding: Optional[str] = None) -> List[Dict]: """Read CSV file and return list of dictionaries""" if not encoding: encoding = self.detect_encoding(file_path) print(f"Detected encoding: encoding") contacts = [] try: with open(file_path, 'r', encoding=encoding) as f: # Detect delimiter sample = f.read(1024) f.seek(0) delimiter = self.detect_delimiter(sample) print(f"Detected delimiter: delimiter") reader = csv.DictReader(f, delimiter=delimiter) # Normalize column names reader.fieldnames = [self.normalize_column_name(col) for col in reader.fieldnames] for row_num, row in enumerate(reader, start=2): contact = self.normalize_contact(row) if contact.get('name') or contact.get('phone'): contacts.append(contact) else: print(f"Warning: Row row_num skipped - missing name or phone") except Exception as e: raise Exception(f"Error reading CSV file: str(e)") return contacts def __init__(self): self

args = parser.parse_args()

def add_photo(self, contact: Dict, photo_path: str) -> str: """Add photo to vCard (base64 encoded)""" import base64 with open(photo_path, 'rb') as f: photo_data = base64.b64encode(f.read()).decode('utf-8') return f"PHOTO;ENCODING=b;TYPE=JPEG:photo_data" file_path: str) -&gt

def format_phone(self, phone: str) -> str: """Format phone number for VCF""" if not phone: return "" # Remove spaces and common separators phone = re.sub(r'[\(\)\s\-\.]', '', phone) # Add international prefix if missing if phone.startswith('0') and not phone.startswith('+'): phone = '+1' + phone[1:] # Default to US/Canada, customize as needed return self.escape_vcf_text(phone)