Files
WhatsApp-Chat-Exporter/Whatsapp_Chat_Exporter/contacts_names_from_vcards.py
2024-07-13 12:12:32 +08:00

80 lines
2.8 KiB
Python

import itertools
from typing import List, TypedDict
import vobject
class ContactsNamesFromVCards:
def __init__(self) -> None:
self.l = []
def should_enrich_from_vcards(self):
return len(self.l) > 0
def load_vcf_file(self, vcfFilePath: str, default_country_calling_code: str):
self.l = readVCardsFile(vcfFilePath, default_country_calling_code)
def enrich_names_from_vCards(self, chats):
for counter, (number, name) in enumerate(self.l):
# short number must be a bad contact, lets skip it
if len(number) <= 5:
continue
for counter, chat in enumerate(filter_dict_by_prefix(chats, number).values()):
if not hasattr(chat, 'name') or (hasattr(chat, 'name') and chat.name is None):
setattr(chat, 'name', name)
def readVCardsFile(vcfFilePath, default_country_calling_code: str):
contacts = []
with open(vcfFilePath, mode="r") as f:
reader = vobject.readComponents(f)
for row in reader:
if not hasattr(row, 'fn'):
continue
if not hasattr(row, 'tel'):
continue
contact: ExportedGoogleContactVCARDRawNumbers = {
"full_name": row.fn.value,
"numbers": list(map(lambda tel:tel.value, row.tel_list)),
}
contacts.append(contact)
step2 = createNumberToNameDicts(contacts, default_country_calling_code)
return step2
def filter_dict_by_prefix(d, prefix: str):
return {k: v for k, v in d.items() if k.startswith(prefix)}
def createNumberToNameDicts(inContacts, default_country_calling_code: str):
outContacts = list(itertools.chain.from_iterable(
[[normalize_number(num, default_country_calling_code), f"{contact['full_name']} ({i+1})" if len(contact['numbers']) > 1 else contact['full_name']]
for i, num in enumerate(contact['numbers'])]
for contact in inContacts
))
return outContacts
class ExportedGoogleContactVCARDRawNumbers(TypedDict):
full_name: str
numbers: List[str]
def normalize_number(number: str, default_country_calling_code: str):
afterSomeCleaning = number.replace('(', '').replace(')', '').replace(' ', '').replace('-', '')
# A number that starts with a + or 00 means it already have country_calling_code
if afterSomeCleaning.startswith('+'):
afterSomeCleaning = afterSomeCleaning.replace('+', '')
elif afterSomeCleaning.startswith('00'):
afterSomeCleaning = afterSomeCleaning[2:]
else:
# Remove leading zero
if afterSomeCleaning.startswith('0'):
afterSomeCleaning = afterSomeCleaning[1:]
afterSomeCleaning = default_country_calling_code + afterSomeCleaning
return afterSomeCleaning