# HG changeset patch # User Goffi # Date 1618590780 -7200 # Node ID 6132d363f0e9b3607ce928a7ae5eb757be76f0b2 # Parent 85b8a899f407e96ade5818342475b5fe36ce2dd3 plugin XEP-0277: user friendly ID: when publishing a blog post without `id` specified, instead of using uuid, a user friendly ID based on title or content is used. This allow to have better URLs in web frontend. There is a (very low) risk of name collision if several articles with the same title or content are published on the same pubsub node, user friendly ID can be deactivated by using `user_friendly_id=False` in blog data to avoid that. diff -r 85b8a899f407 -r 6132d363f0e9 sat/plugins/plugin_xep_0277.py --- a/sat/plugins/plugin_xep_0277.py Fri Apr 16 18:32:44 2021 +0200 +++ b/sat/plugins/plugin_xep_0277.py Fri Apr 16 18:33:00 2021 +0200 @@ -16,14 +16,16 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -import shortuuid import time import dateutil import calendar import urllib.parse +from secrets import token_urlsafe from typing import Optional from functools import partial +import shortuuid + from twisted.words.protocols.jabber import jid, error from twisted.words.protocols.jabber.xmlstream import XMPPHandler from twisted.words.xish import domish @@ -45,6 +47,7 @@ from sat.tools import utils from sat.tools.common import data_format from sat.tools.common import uri as xmpp_uri +from sat.tools.common import regex log = getLogger(__name__) @@ -807,6 +810,11 @@ data = data_format.deserialise(data) return self.send(client, data, service, node) + def friendlyId(self, data): + """Generate a user friendly id from title or content""" + id_base = regex.urlFriendlyText(data.get('title') or data.get('content', '')) + return f"{id_base}-{token_urlsafe(3)}" + @defer.inlineCallbacks def send(self, client, data, service=None, node=NS_MICROBLOG): """Send XEP-0277's microblog data @@ -823,7 +831,12 @@ if node is None: node = NS_MICROBLOG - item_id = data.get("id") or str(shortuuid.uuid()) + item_id = data.get("id") + if item_id is None: + if data.get("user_friendly_id", True): + item_id = self.friendlyId(data) + else: + item_id = str(shortuuid.uuid()) try: yield self._manageComments(client, data, service, node, item_id, access=None)