| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #!/usr/bin/python3
- # coding=utf-8
- # Doc
- # Script to extract Contacts from Sailfish Contact SQLite DB located at
- #
- #
- # Links
- # FileFormatdescription: https://docs.fileformat.com/email/vcf/#vcf-30-example
- # Pytho vobject: http://eventable.github.io/vobject/
- # Version
- version=0.2
- # ChangeLog
- # 2021-08-03 - 0.1 - multiple E-Mails with different types are working correctly
- # 2021-08-09 - 0.2 - Phonenumbers with parameters, Addresses with parameters, E-Mail-Addresses with marameters
- import sqlite3
- import vobject
- import uuid
- import argparse
- def DEBUG(debug,msg):
- if debug is not None:
- print("..DEBUG: " + msg)
- parser = argparse.ArgumentParser(description='Restore SailfishOS 3 Contacts', epilog='This script was written to restore SailfishOS 3 contacts as VCF files. To see additional information, visit: https://wiki.siningsoft.de/doku.php?id=sailfishos:projects:sailfish_contacts_rescue' )
- parser.add_argument('--db','-d', required=True, help="Sqlite3 Database file usually /home/{nemo,defaultuser)/.local/share/system/Contacts/qtcontacts-sqlite/contacts.db")
- parser.add_argument('--output','-o',required=True, help="Output directory for vcf files")
- parser.add_argument('--debug',action="store_true",help="debugging output to identify problems")
- parser.add_argument('--version', action='version', version='%(prog)s ' + str(version))
- args = parser.parse_args()
- SQLconn = sqlite3.connect(args.db)
- try:
- SQLContCur = SQLconn.cursor()
- for row in SQLContCur.execute('SELECT * FROM Contacts'):
-
- # contactID abfragen
- contactID=row[0]
-
- # wir erstellen das Objekt
- vcf = vobject.vCard()
-
- vcf.add('uid').value = str(uuid.uuid4())
- #vcf.add('uid').value = "Testdaten"
- vcf.add('n').value = vobject.vcard.Name( family=row[6], given=row[4] )
- vcf.add('fn').value =row[1]
-
- DEBUG(args.debug,"Contact " + row[1])
-
- # abfrage der Adressdaten
- SQLADRCur = SQLconn.cursor()
- for ADRrow in SQLADRCur.execute('SELECT * FROM Addresses JOIN Details on Details.detailId = Addresses.detailId where Addresses.contactId = ' + str(contactID)):
-
- if ADRrow[2] is not None:
- ADRstr=str(ADRrow[2])
- else:
- ADRstr=""
- if ADRrow[5] is not None:
- ADRcit=str(ADRrow[5])
- else:
- ADRcit=""
-
- if ADRrow[4] is not None:
- ADRreg=str(ADRrow[4])
- else:
- ADRreg=""
- if ADRrow[6] is not None:
- ADRcod=str(ADRrow[6])
- else:
- ADRcod=""
- if ADRrow[7] is not None:
- ADRcou=str(ADRrow[7])
- else:
- ADRcou=""
- DEBUG(args.debug,"Addressdata: street=" + ADRstr + " city=" + ADRcit + " region=" + ADRreg + " code=" + ADRcod + " country=" + ADRcou)
- adr = vcf.add('ADR').value = vobject.vcard.Address(street=ADRstr, city=ADRcit, region=ADRreg, code=ADRcod,country=ADRcou)
-
- ## Abfragen Organisation
- SQLORGCur = SQLconn.cursor()
- for ORGrow in SQLORGCur.execute('SELECT * from Organizations where contactId = ' + str(contactID)):
- org = vcf.add('ORG').value = [str(ORGrow[2]), str(ORGrow[6])]
-
- if ORGrow[4] is not None:
- title = vcf.add('TITLE').value = str(ORGrow[4])
-
- if ORGrow[3] is not None:
- role = vcf.add('ROLE').value = str(ORGrow[3])
-
- # Also parameters are possible. Could be read out
- # | columnID | column |
- # ----------------------------
- # | 0 | detailId |
- # | 1 | contactId |
- # | 2 | name |
- # | 3 | role |
- # | 4 | title |
- # | 5 | location |
- # | 6 | department |
- # | 7 | logoUrl |
- # | 8 | assistantName |
-
- ## Abfragen E-Mail-Adressen
- SQLEmailCur = SQLconn.cursor()
- for Emailrow in SQLEmailCur.execute('SELECT * from EmailAddresses JOIN Details on Details.detailId= EmailAddresses.detailId where EmailAddresses.contactId = ' + str(contactID)):
-
- # debug ausgabe
- DEBUG(args.debug,str(Emailrow[2]) + " at " + str(Emailrow[9]))
-
- email = vcf.add('email')
- email.value = str(Emailrow[2])
-
- # nur den Typ einpflegen, wenn das hier nicht none ist
- if Emailrow[9] != None:
- email.type_param = str(Emailrow[9])
- SQLPhoneCur = SQLconn.cursor()
-
- ## Abfragen Telefonnummer, Fax, SMS - Nummern kommen aus der gleichen Tabelle
- for Phonerow in SQLPhoneCur.execute('SELECT * from PhoneNumbers JOIN Details on Details.detailId = PhoneNumbers.detailId where PhoneNumbers.contactId = ' + str(contactID)):
-
- # wir müssen die SubTypen unterscheiden
- #Null voice
- #1 cell
- #2 fax
- #3 pager
- #6 video
- #10 Assistent
-
-
- # debug ausgabe
- DEBUG(args.debug,str(Phonerow[2]) + " at " + str(Phonerow[10]) + " subtype=" + str(Phonerow[3]))
-
- # None is a normal phone Number
- if Phonerow[3] == "1":
- phcat='cell'
- elif Phonerow[3] == "2":
- phcat='fax'
- elif Phonerow[3] == "3":
- phcat='pager'
- elif Phonerow[3] == "6":
- phcat='video'
- elif Phonerow[3] == "10":
- phcat='assistent'
- elif Phonerow[3] is None:
- phcat='voice'
-
- DEBUG(args.debug,phcat)
- phone = vcf.add(phcat).value = str(Phonerow[2])
-
- # nur den Typ einpflegen, wenn das hier nicht none ist
- if Phonerow[10] != None:
- try:
- phone.type_param = str(Phonerow[10])
- except AttributeError:
- continue
- # Ausgabe
- print(vcf.serialize())
- # hier brauchen wir einige eception handles -> wie bekommen wir die einzelnen exceptions heruas ?
- #except:
- #print("Error in executing SQL")
-
-
- except AttributeError:
- print("Datatype mismatch")
- raise
- # das generöse Except am Ende
- except:
- print("unhandled error")
- raise
|