Mercurial > libervia-web
view src/pages/common/blog/page_meta.py @ 1039:6bc7768faa5d
pages (common/blog): don't fail if author is missing
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 24 Jan 2018 09:58:00 +0100 |
parents | 6b906b1f419a |
children | 90b11cd6f28f |
line wrap: on
line source
#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- from libervia.server.constants import Const as C from twisted.words.protocols.jabber import jid from twisted.internet import defer from sat.tools.common import data_objects from libervia.server import session_iface from sat.core.i18n import _ from sat.core.log import getLogger from sat.tools.common.template import safe from server import utils import re import cgi log = getLogger('pages/common/blog') """generic blog (with service/node provided)""" name = u'blog' template = u"blog/articles.html" uri_handlers = {(u'pubsub', u'microblog'): 'microblog_uri'} RE_TEXT_URL = re.compile(ur'[^a-zA-Zéèêôà,_]+') TEXT_MAX_LEN = 60 def microblog_uri(self, uri_data): args = [uri_data[u'path'], uri_data[u'node']] if u'item' in uri_data: args.extend([u'id', uri_data[u'item']]) return self.getURL(*args) def parse_url(self, request): """URL is /[service]/[node]/[filter_keyword]/[item]|[other] if [node] is '@', default namespace is used if a value is unset, default one will be used keyword can be one of: id: next value is a item id tag: next value is a blog tag """ data = self.getRData(request) try: service = self.nextPath(request) except IndexError: data['service'] = u'' else: try: data[u"service"] = jid.JID(service) except Exception: log.warning(_(u"bad service entered: {}").format(service)) self.pageError(request, C.HTTP_BAD_REQUEST) try: data['node'] = self.nextPath(request) except IndexError: data['node'] = u'' else: if data['node'] == u'@': data['node'] = u'' try: filter_kw = data['filter_keyword'] = self.nextPath(request) except IndexError: pass else: if filter_kw == u'id': try: data[u'item'] = self.nextPath(request) except IndexError: self.pageError(request, C.HTTP_BAD_REQUEST) # we get one more argument in case text has been added to have a nice URL try: self.nextPath(request) except IndexError: pass elif filter_kw == u'tag': try: data[u'tag'] = self.nextPath(request) except IndexError: self.pageError(request, C.HTTP_BAD_REQUEST) else: # invalid filter keyword log.warning(_(u"invalid filter keyword: {filter_kw}").format(filter_kw=filter_kw)) self.pageError(request, C.HTTP_BAD_REQUEST) @defer.inlineCallbacks def appendComments(self, blog_items, identities, profile): for blog_item in blog_items: if identities is not None: author = blog_item.author_jid if not author: log.warning(_(u"no author found for item {item_id}").format(item_id=blog_item.id)) else: if author not in identities: identities[author] = yield self.host.bridgeCall(u'identityGet', author, profile) for comment_data in blog_item.comments: service = comment_data[u'service'] node = comment_data[u'node'] try: comments_data = yield self.host.bridge.mbGet( service, node, C.NO_LIMIT, [], {}, profile) except Exception as e: log.warning(_(u"Can't get comments at {node} (service: {service}): {msg}").format( service=service, node=node, msg=e)) continue comments = data_objects.BlogItems(comments_data) blog_item.appendCommentsItems(comments) yield appendComments(self, comments, identities, profile) @defer.inlineCallbacks def getBlogData(self, request, service, node, item_id, extra, profile): try: if item_id: items_id = [item_id] else: items_id = [] blog_data = yield self.host.bridge.mbGet( service.userhost(), node, C.NO_LIMIT, items_id, extra, profile) except Exception as e: # FIXME: need a better way to test errors in bridge errback if u"forbidden" in unicode(e): self.pageError(request, 401) else: raise e items = data_objects.BlogItems(blog_data) defer.returnValue((blog_data, items)) @defer.inlineCallbacks def prepare_render(self, request): data = self.getRData(request) # if the comments are not explicitly hidden, we show them service, node, item_id, show_comments = data.get(u'service', u''), data.get(u'node', u''), data.get(u'item'), data.get(u'show_comments', True) profile = self.getProfile(request) if profile is None: profile = C.SERVICE_PROFILE params = self.getAllPostedData(request, multiple=False) if item_id: extra = {} else: extra = {u'rsm_max': u'10'} if u'after' in params: extra[u'rsm_after'] = params[u'after'] elif u'before' in params: extra[u'rsm_before'] = params[u'before'] tag = data.get('tag') if tag: extra[u'mam_filter_{}'.format(C.MAM_FILTER_CATEGORY)] = tag blog_data, items = yield getBlogData(self, request, service, node, item_id, extra, profile) template_data = request.template_data target_profile = template_data.get(u'target_profile') if items: if not item_id: last_id = items[-1].id template_data['older_url'] = self.getParamURL(request, after=last_id) if u'before' in params or u'after' in params: first_id = items[0].id template_data['newer_url'] = self.getParamURL(request, before=first_id) else: if item_id: # if item id has been specified in URL and it's not found, # we must return an error self.pageError(request, C.HTTP_NOT_FOUND) # no items, we have requested items before last post, or blog is empty extra = {u'rsm_max': u'10'} blog_data, items = yield getBlogData(self, request, service, node, None, extra, profile) if items: last_id = items[-1].id template_data['older_url'] = self.getParamURL(request, after=last_id) identities = template_data[u'identities'] = self.host.getSessionData(request, session_iface.ISATSession).identities if show_comments: yield appendComments(self, items, identities, profile) # if we know the profile, we use it instead of service + blog (nicer url) if target_profile is None: blog_base_url = self.getPageByName(u'blog_view').getURL(service.full(), node or u'@') else: blog_base_url = self.getURLByNames([(u'user', [target_profile]), (u'user_blog', [])]) # we also set the background image if specified by user bg_img = yield self.host.bridgeCall(u'asyncGetParamA', u'Background', u'Blog page', u'value', -1, template_data[u'target_profile']) if bg_img: template_data['dynamic_style'] = safe(u""" :root { --bg-img: url("%s"); } """ % cgi.escape(bg_img, True)) template_data[u'items'] = data[u'items'] = items if request.args.get('reverse') == ['1']: template_data[u'items'].items.reverse() template_data[u'items_http_uri'] = items_http_uri = {} template_data[u'tags_http_uri'] = tags_http_uri = {} for item in items: # we add text from title or body at the end of URL # to make it more readable text = item.title or item.content text = RE_TEXT_URL.sub(u'-', text).lower().strip(u'-') while len(text) > TEXT_MAX_LEN: if u'-' in text: text = text.rsplit(u'-', 1)[0] else: text = text[:TEXT_MAX_LEN] # now we can compute item URL blog_url = u'/'.join([blog_base_url, u'id', utils.quote(item.id), text]) items_http_uri[item.id] = self.host.getExtBaseURL(request, blog_url) for tag in item.tags: if tag not in tags_http_uri: tag_url = u'/'.join([blog_base_url, u'tag', utils.quote(tag)]) tags_http_uri[tag] = self.host.getExtBaseURL(request, tag_url) template_data[u'allow_commenting'] = data.get(u'allow_commenting', False) @defer.inlineCallbacks def on_data_post(self, request): profile = self.getProfile(request) if profile is None: self.pageError(request, C.HTTP_UNAUTHORIZED) type_ = self.getPostedData(request, u'type') if type_ == u'comment': service, node, body = self.getPostedData(request, (u'service', u'node', u'body')) if not body: self.pageError(request, C.HTTP_BAD_REQUEST) comment_data = {u"content": body} try: yield self.host.bridge.mbSend(service, node, comment_data, profile) except Exception as e: if u"forbidden" in unicode(e): self.pageError(request, 401) else: raise e else: log.warning(_(u"Unhandled data type: {}").format(type_))