Add Eclipse project settings and make indent-level consistent
[hermes] / package / src / contacts.py
index 0b7a1e9..9fa159f 100644 (file)
@@ -3,45 +3,144 @@ import os.path
 import urllib
 import Image
 import ImageOps
+import StringIO
+import datetime
+import re
+from pygobject import *
+from ctypes import *
 
-class ContactStore:
-  """Provide an API for changing contact data. Abstracts limitations
-     in the evolution-python bindings.
-
-     Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
-     Released under the Artistic Licence."""
-
+# Constants from http://library.gnome.org/devel/libebook/stable/EContact.html#EContactField
+ebook = CDLL('libebook-1.2.so.5')
+E_CONTACT_HOMEPAGE_URL = 42
+E_CONTACT_PHOTO = 94
+E_CONTACT_BIRTHDAY_DATE = 107
 
-  # -----------------------------------------------------------------------
-  def __init__(self, book):
-    """Create a new contact store for modifying contacts in the given
-       EBook."""
 
-    self.temp_file = os.tmpnam()
-    self.book = book
-
-  # -----------------------------------------------------------------------
-  def close(self):
-    """Close the store and tidy-up any resources."""
-
-    if (os.path.isfile(self.temp_file)):
-      os.unlink(self.temp_file)
+class ContactStore:
+    """Provide an API for changing contact data. Abstracts limitations
+       in the evolution-python bindings.
 
+       Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
+       Released under the Artistic Licence."""
 
-  # -----------------------------------------------------------------------
-  def set_photo(self, contact, url):
-    """Set the given contact's photo to the picture found at the URL. If the
-       photo is wider than it is tall, it will be cropped with a bias towards
-       the top of the photo."""
 
-    urllib.urlretrieve(url, self.temp_file)
-    im = Image.open(self.temp_file)
-    (w, h) = im.size
-    if (h > w):
-      print "Shrinking photo for %s as it's %d x %d" % (contact.get_name(), w, h)
-      im = ImageOps.fit(im, (w, w), Image.NEAREST, 0, (0, 0.1))
-      im.save(self.temp_file, "JPEG")
+    # -----------------------------------------------------------------------
+    def __init__(self, book):
+        """Create a new contact store for modifying contacts in the given
+           EBook."""
+        
+        self.book = book
+    
+    
+    # -----------------------------------------------------------------------
+    def close(self):
+        """Close the store and tidy-up any resources."""
+        
+        pass
+    
+    
+    # -----------------------------------------------------------------------
+    def set_photo(self, contact, url):
+        """Set the given contact's photo to the picture found at the URL. If the
+           photo is wider than it is tall, it will be cropped with a bias towards
+           the top of the photo."""
+        
+        f = urllib.urlopen(url)
+        data = ''
+        while True:
+            read_data = f.read()
+            data += read_data
+            if not read_data:
+                break
+        
+        im = Image.open(StringIO.StringIO(data))
+        (w, h) = im.size
+        if (h > w):
+            print "Shrinking photo for %s as it's %d x %d" % (contact.get_name(), w, h)
+            im = ImageOps.fit(im, (w, w), Image.NEAREST, 0, (0, 0.1))
+          
+        print "Updating photo for %s" % (contact.get_name())
+        f = StringIO.StringIO()
+        im.save(f, "JPEG")
+        image_data = f.getvalue()
+        photo = EContactPhoto()
+        photo.type = 0
+        photo.data = EContactPhoto_data()
+        photo.data.inlined = EContactPhoto_inlined()
+        photo.data.inlined.mime_type = cast(create_string_buffer("image/jpeg"), c_char_p)
+        photo.data.inlined.length = len(image_data)
+        photo.data.inlined.data = cast(create_string_buffer(image_data), c_void_p)
+        ebook.e_contact_set(hash(contact), E_CONTACT_PHOTO, addressof(photo))
+        return True
       
-    print "Updating photo for %s" % (contact.get_name())
-    os.spawnl(os.P_WAIT, '/opt/hermes/bin/contact-update', 'contact-update', contact.get_name(), '--photo', 'image/jpeg', self.temp_file)
+      
+    # -----------------------------------------------------------------------
+    def set_birthday(self, contact, day, month, year = 0):
+        if year == 0:
+            year = datetime.date.today().year
+          
+        birthday = EContactDate()
+        birthday.year = year
+        birthday.month = month
+        birthday.day = day
+        print "Setting birthday for [%s] to %d-%d-%d" % (contact.get_name(), year, month, day)
+        ebook.e_contact_set(hash(contact), E_CONTACT_BIRTHDAY_DATE, addressof(birthday))
+        return True
+      
+      
+    # -----------------------------------------------------------------------
+    def get_urls(self, contact):
+        """Return a list of URLs which are associated with this contact."""
+        
+        urls = []
+        ai = GList.new(ebook.e_contact_get_attributes(hash(contact), E_CONTACT_HOMEPAGE_URL))
+        while ai.has_next():
+            attr = ai.next(as_a = EVCardAttribute)
+            if not attr:
+                raise Exception("Unexpected null attribute for [" + contact.get_name() + "] with URLs " + urls)
+            urls.append(string_at(attr.value().next()))
+          
+        return urls
+    
+      
+    # -----------------------------------------------------------------------
+    def add_url(self, contact, str, unique = ''):
+        """Add a new URL to the set of URLs for the given contact."""
+        
+        urls = re.findall('(?:(?:ftp|https?):\/\/|\\bwww\.|\\bftp\.)[,\w\.\-\/@:%?&=%+#~_$\*]+[\w=\/&=+#]', str, re.I | re.S)
+        updated = False
+        for url in urls:
+            updated = self._add_url(contact, url, unique or re.sub('(?:.*://)?(\w+(?:[\w\.])*).*', '\\1', url)) or updated
+        
+        return updated
+    
+    
+    # -----------------------------------------------------------------------
+    def _add_url(self, contact, url, unique):
+        """Do the work of adding a unique URL to a contact."""
+        
+        url_attr = None
+        ai = GList.new(ebook.e_contact_get_attributes(hash(contact), E_CONTACT_HOMEPAGE_URL))
+        while ai.has_next():
+            attr = ai.next(as_a = EVCardAttribute)
+            existing = string_at(attr.value().next())
+            #print "Existing URL [%s] when adding [%s] to [%s] with constraint [%s]" % (existing, url, contact.get_name(), unique)
+            if existing == unique or existing == url:
+                return False
+            elif existing.find(unique) > -1:
+                url_attr = attr
+          
+        if not url_attr:
+            ai.add()
+            url_attr = EVCardAttribute()
+            url_attr.group = ''
+            url_attr.name = 'URL'
+        
+        val = GList()
+        print "Setting URL for [%s] to [%s]" % (contact.get_name(), url)
+        val.set(create_string_buffer(url))
+        ai.set(addressof(url_attr))
+        url_attr.values = cast(addressof(val), POINTER(GList))
+        ebook.e_contact_set_attributes(hash(contact), E_CONTACT_HOMEPAGE_URL, addressof(ai))
+        return True
+