Start of maemo.org service: http://hermes.garage.maemo.org/mo-list.csv will be regula...
[hermes] / package / src / org / maemo / hermes / engine / maemoorg / service.py
1 import urllib
2 import csv
3 import org.maemo.hermes.engine.service
4 from org.maemo.hermes.engine.friend import Friend
5
6 class Service(org.maemo.hermes.engine.service.Service):
7     """maemo.org backend for Hermes.
8        
9        Copyright (c) Andrew Flegg <andrew@bleb.org> 2010.
10        Released under the Artistic Licence."""
11        
12     #_account_url = "http://hermes.garage.maemo.org/mo-list.csv"
13     _account_url = "file:///home/andrew/src/scratchbox/hermes/www/mo-list.csv"
14        
15     # -----------------------------------------------------------------------
16     def __init__(self):
17         """Initialise the maemo.org service."""
18         
19         org.maemo.hermes.engine.service.Service.__init__(self, "maemo.org")
20
21         self._api_email = api_email
22         self._api_key = api_key
23          
24         self._address_to_contact = {}
25         self._hash_to_address = {}
26         self._hash_has_gravatar = {}
27         
28         self._friends_by_contact = {}
29         self._contacts_by_friend = {}
30     
31     
32     # -----------------------------------------------------------------------
33     def pre_process_contact(self, contact):
34         """Extracts addresses from the contact."""
35         
36         for address in contact.get_emails():
37             self._address_to_contact[address] = contact
38     
39     
40     # -----------------------------------------------------------------------
41     def process_friends(self):
42         self._lookup_addresses()
43
44     
45     # -----------------------------------------------------------------------
46     def process_contact(self, contact):
47         """On first call (with a contact missing a photo), go get data from 
48            Gravatar's servers."""
49         
50         if not self._has_photo(contact):
51             for address in contact.get_emails():
52                 hash = self._get_hash_for_address(address)
53                 if (self._hash_has_gravatar.has_key(hash) and self._hash_has_gravatar[hash]):
54                     friend = Friend(contact.get_name())
55                     friend.set_photo_url(self._get_url_for_email_hash(hash))
56                     self._register_match(contact, friend)
57                     return friend
58         
59         return None
60
61
62     # -----------------------------------------------------------------------
63     def get_unmatched_friends(self):
64         """Will always return empty list - Gravatar only reacts on e-mail 
65            addresses from existing contacts."""
66
67         return []
68     
69
70     # -----------------------------------------------------------------------
71     def _get_friends(self):
72         return self._contacts_by_friend.keys()
73
74
75     # -----------------------------------------------------------------------    
76     def _get_contacts_with_match(self):
77         """Returns a dict with Contact objects as keys and Friend objects as 
78            values"""
79         
80         return self._friends_by_contact
81
82
83     # -----------------------------------------------------------------------
84     def _register_match(self, contact, friend):
85         friend.set_contact(contact)
86         self._friends_by_contact[contact] = friend
87         self._contacts_by_friend[friend] = contact
88         
89     # -----------------------------------------------------------------------
90     # FIXME
91     def _has_photo(self, contact):
92         return False
93     
94         
95     # -----------------------------------------------------------------------
96     def _lookup_addresses(self):
97         """Constructs hashes for address_to_contact, makes call to the Gravatar.com service and updates
98         self._hash_has_gravatar"""
99         
100         addresses = self._address_to_contact.keys()
101         if len(addresses) == 0:
102             self._set_hash_information({})
103         else:
104             args = { "apikey" : self._api_key}
105             hashes = self._construct_hashes(addresses)
106             args["hashes"] = list(hashes)
107             url = self._api_url
108             self._set_hash_information(self._get_hash_info_from_server(args, url))
109             
110
111     # -----------------------------------------------------------------------
112     def _get_hash_info_from_server(self, args, url):
113         """Makes the actual XML-RPC call - override this for testing"""
114         
115         service = xmlrpclib.ServerProxy(url)
116         return service.grav.exists(args)
117
118
119     # -----------------------------------------------------------------------
120     def _set_hash_information(self, hash_info):
121         self._hash_has_gravatar = hash_info
122         
123
124     # -----------------------------------------------------------------------
125     def _get_url_for_email_hash(self, hash, default="404", size="128"):
126         """Assembles the URL to a gravatar, based on a hash of an e-mail address"""
127     
128         return self._image_url_base + urllib.urlencode({'gravatar_id':hash, 'd':default, 'size':size})
129     
130     
131     # -----------------------------------------------------------------------
132     def _construct_hashes(self, addresses):
133         """Creates hashes for all addresses specified, returning a set of hashes"""
134     
135         result = set()
136         for address in addresses:
137             hash = self._get_hash_for_address(address)
138             self._hash_to_address[hash] = address
139             result.add(hash)
140     
141         return result
142
143     # -----------------------------------------------------------------------
144     def _get_hash_for_address(self, address):
145         return hashlib.md5(address.lower()).hexdigest()