comparison src/server/blog.py @ 727:3bd097380da7

server side (blog): fixes displaying the avatar
author souliane <souliane@mailoo.org>
date Mon, 05 Oct 2015 09:15:47 +0200
parents e949b7c7ed9c
children 9d35d75566fb
comparison
equal deleted inserted replaced
726:e949b7c7ed9c 727:3bd097380da7
72 72
73 def __init__(self, host): 73 def __init__(self, host):
74 self.host = host 74 self.host = host
75 Resource.__init__(self) 75 Resource.__init__(self)
76 TemplateProcessor.__init__(self, host) 76 TemplateProcessor.__init__(self, host)
77 self.host.bridge.register('entityDataUpdated', self.entityDataUpdatedCb) 77 self.host.bridge.register('entityDataUpdated', self.entityDataUpdatedHandler)
78 self.host.bridge.register('actionResult', self.actionResultCb) # FIXME: actionResult is to be removed
79 self.avatars_cache = {} 78 self.avatars_cache = {}
80 self.waiting_deferreds = {} 79 self.waiting_deferreds = {}
81 80
82 def entityDataUpdatedCb(self, entity_jid_s, key, value, dummy): 81 def entityDataUpdatedHandler(self, entity_s, key, value, dummy):
83 """Retrieve the avatar we've been waiting for and fires the callback 82 """Retrieve the avatar we've been waiting for and fires the callback.
84 for self.getAvatar to return. 83
85 84 @param entity_s (str): JID of the contact
86 @param entity_jid_s (str): JID of the contact
87 @param key (str): entity data key 85 @param key (str): entity data key
88 @param value (str): entity data value 86 @param value (str): entity data value
89 @param dummy (str): that would be C.SERVICE_PROFILE 87 @param dummy (str): that would be C.SERVICE_PROFILE
90 """ 88 """
91 if key != 'avatar': 89 if key != "avatar":
92 return 90 return
93 entity_jid_s = entity_jid_s.lower() 91 log.debug(_(u"Received a new avatar for entity %s") % entity_s)
94 log.debug(_(u"Received a new avatar for entity %s") % entity_jid_s) 92
95 avatar = C.AVATARS_DIR + value 93 url = os.path.join(C.AVATARS_DIR, value)
96 self.avatars_cache[entity_jid_s] = avatar 94 self.avatars_cache[entity_s] = url
95 self.waiting_deferreds[entity_s].callback(url)
96 del self.waiting_deferreds[entity_s]
97
98 def getAvatarURL(self, pub_jid):
99 """Return avatar of a jid if in cache, else ask for it.
100
101 @param pub_jid (JID): publisher JID
102 @return: deferred avatar URL (unicode)
103 """
104 bare_jid_s = pub_jid.userhost()
97 try: 105 try:
98 self.waiting_deferreds[entity_jid_s][1].callback(avatar) 106 url = self.avatars_cache[bare_jid_s]
99 del self.waiting_deferreds[entity_jid_s]
100 except KeyError: 107 except KeyError:
101 pass 108 self.avatars_cache[bare_jid_s] = '' # avoid to request the vcard several times
102 109 self.host.bridge.getCard(bare_jid_s, C.SERVICE_PROFILE)
103 def actionResultCb(self, answer_type, action_id, data, dummy): 110 d = defer.Deferred()
104 """Fires the callback for self.getAvatar to return 111 self.waiting_deferreds[bare_jid_s] = d
105 112 return d
106 @param answer_type (str): 'SUPPRESS' or another value that we would ignore 113 return defer.succeed(url if url else C.DEFAULT_AVATAR_URL)
107 @param action_id (str): the request ID
108 @param data (dict): ignored
109 @param dummy (str): that would be C.SERVICE_PROFILE
110 """
111 # FIXME: actionResult is to be removed. For now we use it to get notified
112 # when the requested vCard hasn't been found. Replace with the new system.
113 if answer_type != 'SUPPRESS':
114 return
115 try:
116 entity_jid_s = [key for (key, value) in self.waiting_deferreds.items() if value[0] == action_id][0]
117 except IndexError: # impossible to guess the entity
118 return
119 log.debug(_(u"Using default avatar for entity %s") % entity_jid_s)
120 self.avatars_cache[entity_jid_s] = C.DEFAULT_AVATAR_URL
121 self.waiting_deferreds[entity_jid_s][1].callback(C.DEFAULT_AVATAR_URL)
122 del self.waiting_deferreds[entity_jid_s]
123
124 def getAvatar(self, profile):
125 """Get the avatar of the given profile
126
127 @param profile(unicode): %(doc_profile)s
128 @return: deferred avatar path, relative to the server's root
129 """
130 jid_s = (profile + '@' + self.host.bridge.getNewAccountDomain()).lower()
131 if jid_s in self.avatars_cache:
132 return defer.succeed(self.avatars_cache[jid_s])
133 # FIXME: request_id is no more needed when actionResult is removed
134 request_id = self.host.bridge.getCard(jid_s, C.SERVICE_PROFILE)
135 self.waiting_deferreds[jid_s] = (request_id, defer.Deferred())
136 return self.waiting_deferreds[jid_s][1]
137 114
138 def render_GET(self, request): 115 def render_GET(self, request):
139 if not request.postpath: 116 if not request.postpath:
140 return self.useTemplate(request, "static_blog_error", {'message': "You must indicate a nickname"}) 117 return self.useTemplate(request, "static_blog_error", {'message': "You must indicate a nickname"})
141 118
163 140
164 if request.atom: 141 if request.atom:
165 self.host.bridge.mbGetAtom(pub_jid.userhost(), NS_MICROBLOG, max_items, item_ids, 142 self.host.bridge.mbGetAtom(pub_jid.userhost(), NS_MICROBLOG, max_items, item_ids,
166 request.extra_dict, C.SERVICE_PROFILE, 143 request.extra_dict, C.SERVICE_PROFILE,
167 lambda feed: self.render_atom_feed(feed, request), 144 lambda feed: self.render_atom_feed(feed, request),
168 lambda failure: self.render_error_blog(failure, request, profile)) 145 lambda failure: self.render_error_blog(failure, request, pub_jid))
169 elif request.item_id: 146 elif request.item_id:
170 self.getItemById(pub_jid, request.item_id, request.extra_dict, 147 self.getItemById(pub_jid, request.item_id, request.extra_dict,
171 request.extra_comments_dict, request, profile) 148 request.extra_comments_dict, request, profile)
172 else: 149 else:
173 self.getItems(pub_jid, max_items, request.extra_dict, 150 self.getItems(pub_jid, max_items, request.extra_dict,
255 metadata['rsm_first'] = metadata['rsm_last'] = item["id"] 232 metadata['rsm_first'] = metadata['rsm_last'] = item["id"]
256 233
257 def gotComments(comments): 234 def gotComments(comments):
258 # build the items as self.getItems would do it (and as self.render_html_blog expects them to be) 235 # build the items as self.getItems would do it (and as self.render_html_blog expects them to be)
259 comments = [(item['comments_service'], item['comments_node'], "", comments[0], comments[1])] 236 comments = [(item['comments_service'], item['comments_node'], "", comments[0], comments[1])]
260 self.render_html_blog([(item, comments)], metadata, request, profile) 237 self.render_html_blog([(item, comments)], metadata, request, pub_jid, profile)
261 238
262 # get the comments 239 # get the comments
263 max_comments = int(extra_comments_dict['rsm_max']) 240 max_comments = int(extra_comments_dict['rsm_max'])
264 self.host.bridge.mbGet(item['comments_service'], item['comments_node'], max_comments, [], 241 self.host.bridge.mbGet(item['comments_service'], item['comments_node'], max_comments, [],
265 extra_comments_dict, C.SERVICE_PROFILE, callback=gotComments) 242 extra_comments_dict, C.SERVICE_PROFILE, callback=gotComments)
286 def getResultCb(data, rt_session): 263 def getResultCb(data, rt_session):
287 remaining, results = data 264 remaining, results = data
288 for result in results: 265 for result in results:
289 service, node, failure, items, metadata = result 266 service, node, failure, items, metadata = result
290 if not failure: 267 if not failure:
291 self.render_html_blog(items, metadata, request, profile) 268 self.render_html_blog(items, metadata, request, pub_jid, profile)
292 269
293 if remaining: 270 if remaining:
294 self._getResults(rt_session) 271 self._getResults(rt_session)
295 272
296 def getResult(rt_session): 273 def getResult(rt_session):
297 self.host.bridge.mbGetFromManyWithCommentsRTResult(rt_session, C.SERVICE_PROFILE, 274 self.host.bridge.mbGetFromManyWithCommentsRTResult(rt_session, C.SERVICE_PROFILE,
298 callback=lambda data: getResultCb(data, rt_session), 275 callback=lambda data: getResultCb(data, rt_session),
299 errback=lambda failure: self.render_error_blog(failure, request, profile)) 276 errback=lambda failure: self.render_error_blog(failure, request, pub_jid))
300 277
301 max_comments = int(extra_comments_dict['rsm_max']) 278 max_comments = int(extra_comments_dict['rsm_max'])
302 self.host.bridge.mbGetFromManyWithComments(C.JID, [pub_jid.userhost()], max_items, 279 self.host.bridge.mbGetFromManyWithComments(C.JID, [pub_jid.userhost()], max_items,
303 max_comments, extra_dict, extra_comments_dict, 280 max_comments, extra_dict, extra_comments_dict,
304 C.SERVICE_PROFILE, callback=getResult) 281 C.SERVICE_PROFILE, callback=getResult)
305 282
306 def render_html_blog(self, items, metadata, request, profile): 283 def render_html_blog(self, items, metadata, request, pub_jid, profile):
307 """Retrieve the user parameters before actually rendering the static blog 284 """Retrieve the user parameters before actually rendering the static blog
308 285
309 @param items(list[tuple(dict, list)]): same as in self.__render_html_blog 286 @param items(list[tuple(dict, list)]): same as in self.__render_html_blog
310 @param metadata(dict): original node metadata 287 @param metadata(dict): original node metadata
311 @param request: HTTP request 288 @param request: HTTP request
312 @param profile 289 @param pub_jid (JID): publisher JID
290 @param profile (unicode): %(doc_profile)s
313 """ 291 """
314 d_list = [] 292 d_list = []
315 options = {} 293 options = {}
316 294
317 def getCallback(param_name): 295 def getCallback(param_name):
318 d = defer.Deferred() 296 d = defer.Deferred()
319 d.addCallback(lambda value: options.update({param_name: value})) 297 d.addCallback(lambda value: options.update({param_name: value}))
320 d_list.append(d) 298 d_list.append(d)
321 return d.callback 299 return d.callback
322 300
323 eb = lambda failure: self.render_error_blog(failure, request, profile) 301 eb = lambda failure: self.render_error_blog(failure, request, pub_jid)
324 302
325 self.getAvatar(profile).addCallbacks(getCallback('avatar'), eb) 303 self.getAvatarURL(pub_jid).addCallbacks(getCallback('avatar'), eb)
326 for param_name in (C.STATIC_BLOG_PARAM_TITLE, C.STATIC_BLOG_PARAM_BANNER, C.STATIC_BLOG_PARAM_KEYWORDS, C.STATIC_BLOG_PARAM_DESCRIPTION): 304 for param_name in (C.STATIC_BLOG_PARAM_TITLE, C.STATIC_BLOG_PARAM_BANNER, C.STATIC_BLOG_PARAM_KEYWORDS, C.STATIC_BLOG_PARAM_DESCRIPTION):
327 self.host.bridge.asyncGetParamA(param_name, C.STATIC_BLOG_KEY, 'value', C.SERVER_SECURITY_LIMIT, profile, callback=getCallback(param_name), errback=eb) 305 self.host.bridge.asyncGetParamA(param_name, C.STATIC_BLOG_KEY, 'value', C.SERVER_SECURITY_LIMIT, profile, callback=getCallback(param_name), errback=eb)
328 306
329 cb = lambda dummy: self.__render_html_blog(items, metadata, options, request, profile) 307 cb = lambda dummy: self.__render_html_blog(items, metadata, options, request, pub_jid)
330 defer.DeferredList(d_list).addCallback(cb) 308 defer.DeferredList(d_list).addCallback(cb)
331 309
332 def __render_html_blog(self, items, metadata, options, request, profile): 310 def __render_html_blog(self, items, metadata, options, request, pub_jid):
333 """Actually render the static blog. 311 """Actually render the static blog.
334 312
335 If mblog_data is a list of dict, we are missing the comments items so we just 313 If mblog_data is a list of dict, we are missing the comments items so we just
336 display the main items. If mblog_data is a list of couple, each couple is 314 display the main items. If mblog_data is a list of couple, each couple is
337 associating a main item data with the list of its comments, so we render all. 315 associating a main item data with the list of its comments, so we render all.
345 - comments(list[dict]): list of microblog data 323 - comments(list[dict]): list of microblog data
346 - comments_metadata(dict): metadata of the comment node 324 - comments_metadata(dict): metadata of the comment node
347 @param metadata(dict): original node metadata 325 @param metadata(dict): original node metadata
348 @param options: dict defining the blog's parameters 326 @param options: dict defining the blog's parameters
349 @param request: the HTTP request 327 @param request: the HTTP request
350 @param profile 328 @param pub_jid (JID): publisher JID
351 """ 329 """
352 if not isinstance(options, dict): 330 if not isinstance(options, dict):
353 options = {} 331 options = {}
354 user = sanitizeHtml(profile) 332 user = sanitizeHtml(pub_jid.user)
355 root_url = '../' * len(request.postpath) 333 root_url = '../' * len(request.postpath)
356 base_url = root_url + 'blog/' + user 334 base_url = root_url + 'blog/' + user
357 335
358 def getOption(key): 336 def getOption(key):
359 return sanitizeHtml(options[key]) if key in options else '' 337 return sanitizeHtml(options[key]) if key in options else ''
398 376
399 def render_atom_feed(self, feed, request): 377 def render_atom_feed(self, feed, request):
400 request.write(feed.encode('utf-8')) 378 request.write(feed.encode('utf-8'))
401 request.finish() 379 request.finish()
402 380
403 def render_error_blog(self, error, request, profile): 381 def render_error_blog(self, error, request, pub_jid):
404 request.write(self.useTemplate(request, "static_blog_error", {'message': "Can't access requested data"})) 382 request.write(self.useTemplate(request, "static_blog_error", {'message': "Can't access requested data"}))
405 request.finish() 383 request.finish()
406 384
407 385
408 class NavigationLinks(object): 386 class NavigationLinks(object):