Last active
April 12, 2017 01:21
-
-
Save amalex5/a22ed2acdf983ff2d7bbecd49a9999b0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
this is a set of scripts that have evolved over the years to make life easier with my fliphone | |
my LG VX8150 lets you download all of your contacts to your computer as vCard (.vcf) files | |
and these scripts can parse them and save them into a variety of convenient formats | |
""" | |
def loadContactsFromPhone(): | |
""" | |
no, just kidding. there doesn't seem to be an easy way to automate the phone-> computer contacts transfer | |
here are my manual steps | |
1) on the phone: contacts menu -> options -> "2. Manage Contacts" -> "4. Send" -> "4. Via Bluetooth" | |
2) which gets you to "Send Name Card" pane and a list of all your contacts | |
3) options -> "2. Mark All" | |
4) and then "Done" | |
5) and then select device | |
the contacts arrive each as a seperte .vcf (vCard) file | |
""" | |
def loadContactsFromVCards(directory): | |
""" | |
the LG VX8150 lets you download all your contacts as vCard (.vcf) files | |
this function opens all the .vcf files in the given directory and pulls out the name and phone number | |
(in principle it might be nicer to use a vCard library | |
in practice, they all seemed shitty, and it works fine to pull these two fields out with regexes | |
a parser would be nicer, too. | |
this function returns a python list of contacts in the form, [{'displayName': 'Alistair Russell', 'number': 6073421613}] | |
""" | |
import re,os | |
namePattern = re.compile("(?<=FN\;CHARSET\=utf\-8:)(.*)") | |
phonePattern = re.compile("(?<=TEL;(?:CELL|HOME):)(.*)") | |
contacts = [] | |
files = filter(lambda x: x[0] != '#' and x[-4:] == '.vcf' , os.listdir(directory)) | |
for file in files: | |
contents = open(directory+file,"r").read() | |
contact = {} | |
if namePattern.findall(contents) and phonePattern.findall(contents): | |
phname = namePattern.findall(contents)[0][:-1] | |
phone = phonePattern.findall(contents)[0] | |
if phone[0] == "1": phone = phone[1:] | |
contact['number'] = int(phone) | |
contact['displayName'] = phname | |
#print contact | |
splits = phname.split(' ') | |
if len(splits) >= 2: | |
testFirstName = splits[0] | |
testLastName = splits[1] | |
contact['firstName'] = testFirstName | |
contact['lastName'] = testLastName | |
contacts.append(contact) | |
print str(len(contacts)) + " contacts processed!" | |
return contacts | |
def prettyPrintContacts(contacts): | |
pp = '' | |
for i in range(len(contacts)): | |
thisContact = contacts[i] | |
pp += thisContact['displayName'] + ' ' + printPhone(str(thisContact['number'])) + '\n' | |
if i != (len(contacts) -1): | |
nextContact = contacts[i+1] | |
if nextContact['displayName'][0] != thisContact['displayName'][0]: | |
pp += '\n' | |
return pp | |
def loadContactsFromJson(sourcePath): | |
import json | |
myJsonFile = open(sourcePath,'rb').read() | |
decoded = json.loads(myJsonFile) | |
decoded.sort(key=lambda item: item['displayName'].lower() ) #have to convert it to lowercase or it sorts by case | |
return decoded | |
def loadContactsFromCSV(sourcePath): | |
# load contacts from a comma-delimeted CSV file | |
# no fancy parsing or anything, so breaks easily | |
contacts = [] | |
with open(sourcePath,'r+') as f: | |
lines = f.readlines() | |
for line in lines: | |
contact = {} | |
splat = line.split(",") | |
contact['displayName'] = splat[0] | |
contact['number'] = int(splat[1]) | |
contacts.append(contact) | |
return contacts | |
def diffContacts(contacts1,contacts2): | |
""" | |
i got a new phone, and it turned out verizon had auto-saved all my contacts | |
but from like 2014 | |
so i wrote this to figure out which new contacts I needed to re-enter by hand | |
holy shit, list comprehensions make this so easy! | |
""" | |
additions = [x for x in contacts2 if not contactPresentByNumber(x['number'],contacts1)] | |
deletions = [x for x in contacts1 if not contactPresentByNumber(x['number'],contacts2)] | |
print "deletions:\n----------" | |
for contact in deletions: print prettyPrintContact(contact) | |
print "" | |
print "additions:\n----------" | |
for contact in additions: print prettyPrintContact(contact) | |
return {'additions':additions, 'deletions':deletions} | |
def contactPresentByNumber(number,contacts): | |
if len(filter(lambda z: z['number'] == number,contacts)) > 0 : return True | |
else: return False | |
def updateMergeContacts(contacts1,contacts2): | |
diff = diffContacts(contacts1,contacts2) | |
return contacts1 + diff['additions'] #screw deletions! | |
def printPhone(number): | |
""" | |
pretty-prints phone numbers into the form "(607) 257-2653" | |
accepts as input unformatted phone numbers ("6072572653") either as string or int | |
(aaagh weak typing!) | |
""" | |
# coerce if int | |
if type(number) == int: number = str(number) | |
#strip leading 1 | |
if number[0] == "1": number = number[1:] | |
#deal with weird short text numbers | |
if len(number) < 10: return number | |
return "(" + number[0:3] + ") " + number[3:6] + "-" + number[6:] | |
def today(): | |
""" | |
returns today's date in the format "19861204" | |
used for prepending to files | |
""" | |
import datetime | |
return datetime.date.today().strftime("%Y%m%d") | |
def todayPretty(): | |
""" | |
returns today's date in the format "4 December 1986" | |
used for pretty-printing | |
""" | |
import datetime | |
day = str(int(datetime.date.today().strftime("%d"))) # yipes. doing this to strip the potential leading zero | |
return day + ' ' + datetime.date.today().strftime("%B %Y") | |
def prettyPrintContact(contact): | |
""" | |
doesn't actually print; just formats for other uses | |
returns something like "Andrew Alexander: (607) 592-4759" | |
""" | |
return contact['displayName'] + ': ' + printPhone(str(contact['number'])) | |
def saveJson(contacts,destinationPath): | |
""" | |
save contacts as a JSON file | |
(with pretty-printed JSON) | |
""" | |
import json | |
destinationFile = destinationPath + today() + 'allContacts.json' | |
with open(destinationFile, 'w') as f: | |
json.dump(contacts, f, sort_keys=True, | |
indent=4, separators=(',', ': ')) | |
def saveCSV(contacts,destinationPath): | |
""" | |
save contacts as a minimal csv, comma-delimeted | |
with names as in the cell phone | |
and numbers unformatted | |
note that it doesn't escape commas :( | |
""" | |
destinationFile = destinationPath + today() + 'allContacts.csv' | |
delimiter = ',' | |
with open(destinationFile,'w') as f: | |
f.seek(0) | |
f.truncate() #clear anything existing in the file | |
for contact in contacts: | |
outputLine = contact['displayName'] + delimiter + str(contact['number']) + '\n' | |
f.write(outputLine) | |
def savePretty(contacts,destinationPath): | |
""" | |
save contacts as an easily-human-readable text file | |
with names as in the cell phone, numbers nicely formatted, and line breaks at every new starting letter | |
""" | |
destinationFile = destinationPath + today() + 'allContacts.txt' | |
with open(destinationFile,'w') as f: | |
f.seek(0) | |
f.truncate() #clear anything existing in the file | |
outputLines = "Andrew's phone book\n" | |
outputLines += "as rendered " + todayPretty() + "\n" | |
outputLines += "=============\n\n" | |
for i in range(len(contacts)): | |
print contacts[i] | |
#outputLines += contacts[i]['displayName'] + ': ' + printPhone(str(contacts[i]['number'])) | |
outputLines += prettyPrintContact(contacts[i]) | |
if i+1 != len(contacts): #this is a stupid way to do it but it complains otherwise | |
# double newline if there's a letter change; single newline outherwise | |
# (no trailing newline) | |
if contacts[i+1]['displayName'][0].lower() != contacts[i]['displayName'][0].lower(): outputLines += '\n\n' | |
else: outputLines += '\n' | |
print outputLines | |
f.write(outputLines) | |
def main(): | |
source = '/Users/amha/Documents/allContacts20160601.json' | |
destination = '/Users/amha/Documents/' | |
contacts = loadContactsFromJson(source) | |
savePretty(contacts,destination) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment