Add Eclipse project settings and make indent-level consistent
[hermes] / package / src / contacts.py
1 import os
2 import os.path
3 import urllib
4 import Image
5 import ImageOps
6 import StringIO
7 import datetime
8 import re
9 from pygobject import *
10 from ctypes import *
11
12 # Constants from http://library.gnome.org/devel/libebook/stable/EContact.html#EContactField
13 ebook = CDLL('libebook-1.2.so.5')
14 E_CONTACT_HOMEPAGE_URL = 42
15 E_CONTACT_PHOTO = 94
16 E_CONTACT_BIRTHDAY_DATE = 107
17
18
19 class ContactStore:
20     """Provide an API for changing contact data. Abstracts limitations
21        in the evolution-python bindings.
22
23        Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
24        Released under the Artistic Licence."""
25
26
27     # -----------------------------------------------------------------------
28     def __init__(self, book):
29         """Create a new contact store for modifying contacts in the given
30            EBook."""
31         
32         self.book = book
33     
34     
35     # -----------------------------------------------------------------------
36     def close(self):
37         """Close the store and tidy-up any resources."""
38         
39         pass
40     
41     
42     # -----------------------------------------------------------------------
43     def set_photo(self, contact, url):
44         """Set the given contact's photo to the picture found at the URL. If the
45            photo is wider than it is tall, it will be cropped with a bias towards
46            the top of the photo."""
47         
48         f = urllib.urlopen(url)
49         data = ''
50         while True:
51             read_data = f.read()
52             data += read_data
53             if not read_data:
54                 break
55         
56         im = Image.open(StringIO.StringIO(data))
57         (w, h) = im.size
58         if (h > w):
59             print "Shrinking photo for %s as it's %d x %d" % (contact.get_name(), w, h)
60             im = ImageOps.fit(im, (w, w), Image.NEAREST, 0, (0, 0.1))
61           
62         print "Updating photo for %s" % (contact.get_name())
63         f = StringIO.StringIO()
64         im.save(f, "JPEG")
65         image_data = f.getvalue()
66         photo = EContactPhoto()
67         photo.type = 0
68         photo.data = EContactPhoto_data()
69         photo.data.inlined = EContactPhoto_inlined()
70         photo.data.inlined.mime_type = cast(create_string_buffer("image/jpeg"), c_char_p)
71         photo.data.inlined.length = len(image_data)
72         photo.data.inlined.data = cast(create_string_buffer(image_data), c_void_p)
73         ebook.e_contact_set(hash(contact), E_CONTACT_PHOTO, addressof(photo))
74         return True
75       
76       
77     # -----------------------------------------------------------------------
78     def set_birthday(self, contact, day, month, year = 0):
79         if year == 0:
80             year = datetime.date.today().year
81           
82         birthday = EContactDate()
83         birthday.year = year
84         birthday.month = month
85         birthday.day = day
86         print "Setting birthday for [%s] to %d-%d-%d" % (contact.get_name(), year, month, day)
87         ebook.e_contact_set(hash(contact), E_CONTACT_BIRTHDAY_DATE, addressof(birthday))
88         return True
89       
90       
91     # -----------------------------------------------------------------------
92     def get_urls(self, contact):
93         """Return a list of URLs which are associated with this contact."""
94         
95         urls = []
96         ai = GList.new(ebook.e_contact_get_attributes(hash(contact), E_CONTACT_HOMEPAGE_URL))
97         while ai.has_next():
98             attr = ai.next(as_a = EVCardAttribute)
99             if not attr:
100                 raise Exception("Unexpected null attribute for [" + contact.get_name() + "] with URLs " + urls)
101             urls.append(string_at(attr.value().next()))
102           
103         return urls
104     
105       
106     # -----------------------------------------------------------------------
107     def add_url(self, contact, str, unique = ''):
108         """Add a new URL to the set of URLs for the given contact."""
109         
110         urls = re.findall('(?:(?:ftp|https?):\/\/|\\bwww\.|\\bftp\.)[,\w\.\-\/@:%?&=%+#~_$\*]+[\w=\/&=+#]', str, re.I | re.S)
111         updated = False
112         for url in urls:
113             updated = self._add_url(contact, url, unique or re.sub('(?:.*://)?(\w+(?:[\w\.])*).*', '\\1', url)) or updated
114         
115         return updated
116     
117     
118     # -----------------------------------------------------------------------
119     def _add_url(self, contact, url, unique):
120         """Do the work of adding a unique URL to a contact."""
121         
122         url_attr = None
123         ai = GList.new(ebook.e_contact_get_attributes(hash(contact), E_CONTACT_HOMEPAGE_URL))
124         while ai.has_next():
125             attr = ai.next(as_a = EVCardAttribute)
126             existing = string_at(attr.value().next())
127             #print "Existing URL [%s] when adding [%s] to [%s] with constraint [%s]" % (existing, url, contact.get_name(), unique)
128             if existing == unique or existing == url:
129                 return False
130             elif existing.find(unique) > -1:
131                 url_attr = attr
132           
133         if not url_attr:
134             ai.add()
135             url_attr = EVCardAttribute()
136             url_attr.group = ''
137             url_attr.name = 'URL'
138         
139         val = GList()
140         print "Setting URL for [%s] to [%s]" % (contact.get_name(), url)
141         val.set(create_string_buffer(url))
142         ai.set(addressof(url_attr))
143         url_attr.values = cast(addressof(val), POINTER(GList))
144         ebook.e_contact_set_attributes(hash(contact), E_CONTACT_HOMEPAGE_URL, addressof(ai))
145         return True
146