# HG changeset patch # User souliane # Date 1403014902 -7200 # Node ID 0bbbef1d53a8b96f7dcff031e5b4506441041f5b # Parent 437eefa53a0139dfda19cf1ac0e01b514af4a96a server side (blog): use user's avatar a the blog's favicon + small refactorization diff -r 437eefa53a01 -r 0bbbef1d53a8 src/browser/libervia_main.py --- a/src/browser/libervia_main.py Sun Jun 15 18:16:24 2014 +0200 +++ b/src/browser/libervia_main.py Tue Jun 17 16:21:42 2014 +0200 @@ -807,8 +807,7 @@ def _entityDataUpdatedCb(self, entity_jid_s, key, value): if key == "avatar": - avatar = '/avatars/%s' % value - + avatar = '/' + C.AVATARS_DIR + value self.avatars_cache[entity_jid_s] = avatar self.contact_panel.updateAvatar(entity_jid_s, avatar) diff -r 437eefa53a01 -r 0bbbef1d53a8 src/browser/sat_browser/constants.py --- a/src/browser/sat_browser/constants.py Sun Jun 15 18:16:24 2014 +0200 +++ b/src/browser/sat_browser/constants.py Tue Jun 17 16:21:42 2014 +0200 @@ -32,6 +32,5 @@ # - list them as a couple (category, name) CACHED_PARAMS = [(C.COMPOSITION_KEY, C.ENABLE_UNIBOX_PARAM)] - # Empty and default avatars + # Empty avatar EMPTY_AVATAR = "/media/misc/empty_avatar" - DEFAULT_AVATAR = "/media/misc/default_avatar.png" diff -r 437eefa53a01 -r 0bbbef1d53a8 src/common/constants.py --- a/src/common/constants.py Sun Jun 15 18:16:24 2014 +0200 +++ b/src/common/constants.py Tue Jun 17 16:21:42 2014 +0200 @@ -45,3 +45,9 @@ UPLOAD_OK = 'UPLOAD OK' UPLOAD_KO = 'UPLOAD KO' UNKNOWN_ERROR = 'UNMANAGED FAULT STRING (%s)' + + # PATHS + AVATARS_DIR = "avatars/" + + # Default avatar + DEFAULT_AVATAR = "/media/misc/default_avatar.png" diff -r 437eefa53a01 -r 0bbbef1d53a8 src/server/blog.py --- a/src/server/blog.py Sun Jun 15 18:16:24 2014 +0200 +++ b/src/server/blog.py Tue Jun 17 16:21:42 2014 +0200 @@ -19,6 +19,8 @@ from sat.core.i18n import _ from sat_frontends.tools.strings import addURLToText +from sat.core.log import getLogger +log = getLogger(__name__) from twisted.internet import defer from twisted.web import server @@ -27,6 +29,7 @@ from datetime import datetime import uuid import re +import os from libervia.server.html_tools import sanitizeHtml from libervia.server.constants import Const as C @@ -50,6 +53,62 @@ def __init__(self, host): self.host = host Resource.__init__(self) + self.host.bridge.register('entityDataUpdated', self.entityDataUpdatedCb) + self.host.bridge.register('actionResult', self.actionResultCb) # FIXME: actionResult is to be removed + self.waiting_deferreds = {} + + def entityDataUpdatedCb(self, entity_jid_s, key, value, dummy): + """Retrieve the avatar we've been waiting for and fires the callback + for self.getAvatar to return. + + @param entity_jid_s (str): JID of the contact + @param key (str): entity data key + @param value (str): entity data value + @param dummy (str): that would be C.SERVICE_PROFILE + """ + if key != 'avatar': + return + try: + avatar = (C.AVATARS_DIR + value) + self.waiting_deferreds[entity_jid_s][1].callback(avatar) + del self.waiting_deferreds[entity_jid_s] + except KeyError: + log.error(_("Avatar retrieved but key not found in the waiting list for entity %s" % entity_jid_s)) + + def actionResultCb(self, answer_type, action_id, data, dummy): + """Fires the callback for self.getAvatar to return + + @param answer_type (str): 'SUPPRESS' or another value that we would ignore + @param action_id (str): the request ID + @param data (dict): ignored + @param dummy (str): that would be C.SERVICE_PROFILE + """ + # FIXME: actionResult is to be removed. For now we use it to get notified + # when the requested vCard hasn't been found. Replace with the new system. + if answer_type != 'SUPPRESS': + return + try: + entity_jid_s = [key for (key, value) in self.waiting_deferreds.items() if value[0] == action_id][0] + except IndexError: + log.error(_("Key not found in the waiting list for request ID %s" % action_id)) + return + self.waiting_deferreds[entity_jid_s][1].callback(C.DEFAULT_AVATAR) + del self.waiting_deferreds[entity_jid_s] + + def getAvatar(self, profile): + """Get the avatar of the given profile + + @param profile (str): + @return: deferred avatar path, relative to the server's root + """ + jid_s = profile + '@' + self.host.bridge.getNewAccountDomain() + data = self.host.bridge.getEntityData(jid_s, ['avatar'], C.SERVICE_PROFILE) + if 'avatar' in data: + return defer.succeed(C.AVATARS_DIR + data['avatar']) + # FIXME: request_id is no more need when actionResult is removed + request_id = self.host.bridge.getCard(jid_s, C.SERVICE_PROFILE) + self.waiting_deferreds[jid_s] = (request_id, defer.Deferred()) + return self.waiting_deferreds[jid_s][1] def render_GET(self, request): if not request.postpath: @@ -100,43 +159,44 @@ @param profile """ d_list = [] - style = {} + options = {} def getCallback(param_name): d = defer.Deferred() - d.addCallback(lambda value: style.update({param_name: value})) + d.addCallback(lambda value: options.update({param_name: value})) d_list.append(d) return d.callback eb = lambda failure: self.render_error_blog(failure, request, profile) + self.getAvatar(profile).addCallbacks(getCallback('avatar'), eb) for param_name in (C.STATIC_BLOG_PARAM_TITLE, C.STATIC_BLOG_PARAM_BANNER, C.STATIC_BLOG_PARAM_KEYWORDS, C.STATIC_BLOG_PARAM_DESCRIPTION): self.host.bridge.asyncGetParamA(param_name, C.STATIC_BLOG_KEY, 'value', C.SERVER_SECURITY_LIMIT, profile, callback=getCallback(param_name), errback=eb) - cb = lambda dummy: self.__render_html_blog(mblog_data, style, request, profile) + cb = lambda dummy: self.__render_html_blog(mblog_data, options, request, profile) defer.DeferredList(d_list).addCallback(cb) - def __render_html_blog(self, mblog_data, style, request, profile): + def __render_html_blog(self, mblog_data, options, request, profile): """Actually render the static blog. If mblog_data is a list of dict, we are missing the comments items so we just display the main items. If mblog_data is a list of couple, each couple is associating a main item data with the list of its comments, so we render all. @param mblog_data: list of microblog data or list of couple (microblog data, list of microblog data) - @param style: dict defining the blog's rendering parameters + @param options: dict defining the blog's parameters @param request: the HTTP request @profile """ - if not isinstance(style, dict): - style = {} + if not isinstance(options, dict): + options = {} user = sanitizeHtml(profile).encode('utf-8') root_url = '../' * len(request.postpath) base_url = root_url + 'blog/' + user - def getFromData(key): - return sanitizeHtml(style[key]).encode('utf-8') if key in style else '' + def getOption(key): + return sanitizeHtml(options[key]).encode('utf-8') if key in options else '' - def getImageFromData(key, alt): + def getImageOption(key, alt): """regexp from http://answers.oreilly.com/topic/280-how-to-validate-urls-with-regular-expressions/""" - url = style[key].encode('utf-8') if key in style else '' + url = options[key].encode('utf-8') if key in options else '' regexp = r"^(https?|ftp)://[a-z0-9-]+(\.[a-z0-9-]+)+(/[\w-]+)*/[\w-]+\.(gif|png|jpg)$" return "%(alt)s" % {'alt': alt, 'url': url} if re.match(regexp, url) else alt @@ -148,7 +208,7 @@ - + %(title)s @@ -156,10 +216,11 @@ """ % {'base': base_url, 'root': root_url, 'user': user, - 'keywords': getFromData(C.STATIC_BLOG_PARAM_KEYWORDS), - 'description': getFromData(C.STATIC_BLOG_PARAM_DESCRIPTION), - 'title': getFromData(C.STATIC_BLOG_PARAM_TITLE) or "%s's microblog" % user, - 'banner_elt': getImageFromData(C.STATIC_BLOG_PARAM_BANNER, user)}) + 'keywords': getOption(C.STATIC_BLOG_PARAM_KEYWORDS), + 'description': getOption(C.STATIC_BLOG_PARAM_DESCRIPTION), + 'title': getOption(C.STATIC_BLOG_PARAM_TITLE) or "%s's microblog" % user, + 'favicon': os.path.normpath(root_url + getOption('avatar')), + 'banner_elt': getImageOption(C.STATIC_BLOG_PARAM_BANNER, getOption(C.STATIC_BLOG_PARAM_TITLE) or user)}) mblog_data = [(entry if isinstance(entry, tuple) else (entry, [])) for entry in mblog_data] mblog_data = sorted(mblog_data, key=lambda entry: (-float(entry[0].get('published', 0)))) for entry in mblog_data: diff -r 437eefa53a01 -r 0bbbef1d53a8 src/server/constants.py --- a/src/server/constants.py Sun Jun 15 18:16:24 2014 +0200 +++ b/src/server/constants.py Tue Jun 17 16:21:42 2014 +0200 @@ -30,7 +30,6 @@ HTML_DIR = "html/" SERVER_CSS_DIR = "server_css/" MEDIA_DIR = "media/" - AVATARS_DIR = "avatars/" CARDS_DIR = "games/cards/tarot" ERRNUM_BRIDGE_ERRBACK = 0 # FIXME