component AP: XMPP identity => AP actor data converstion:

XMPP identity data (coming from various XEPs, notably XEP-0292 (vCard4) and XEP-0084 (User
Avatar)) are now used to complete actor data.

Avatar files can now be delivered with the `avatar` type in URL.

rel 368
This commit is contained in:
Goffi 2022-06-29 12:06:21 +02:00
commit 303e25f72e
2 changed files with 37 additions and 3 deletions

View file

@ -87,8 +87,8 @@ PLUGIN_INFO = {
C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT,
C.PI_PROTOCOLS: [],
C.PI_DEPENDENCIES: [
"XEP-0060", "XEP-0106", "XEP-0277", "XEP-0329", "XEP-0424", "XEP-0465",
"PUBSUB_CACHE", "TEXT_SYNTAXES"
"XEP-0060", "XEP-0084", "XEP-0106", "XEP-0277", "XEP-0292", "XEP-0329",
"XEP-0424", "XEP-0465", "PUBSUB_CACHE", "TEXT_SYNTAXES", "IDENTITY", "XEP-0054"
],
C.PI_RECOMMENDATIONS: [],
C.PI_MAIN: "APGateway",

View file

@ -17,14 +17,17 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import time
import html
from typing import Optional, Dict, List, Any
import json
from urllib import parse
from collections import deque
import unicodedata
from pathlib import Path
from pprint import pformat
from twisted.web import http, resource as web_resource, server
from twisted.web import static
from twisted.python import failure
from twisted.internet import reactor, defer
from twisted.words.protocols.jabber import jid, error
@ -300,7 +303,10 @@ class HTTPAPGServer(web_resource.Resource):
# we have to use AP account as preferredUsername because it is used to retrieve
# actor handle (see https://socialhub.activitypub.rocks/t/how-to-retrieve-user-server-tld-handle-from-actors-url/2196)
preferred_username = ap_account.split("@", 1)[0]
return {
identity_data = await self.apg._i.getIdentity(self.apg.client, account_jid)
actor_data = {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
@ -323,6 +329,28 @@ class HTTPAPGServer(web_resource.Resource):
},
}
if identity_data.get("nicknames"):
actor_data["name"] = identity_data["nicknames"][0]
if identity_data.get("description"):
# description is plain text while summary expects HTML
actor_data["summary"] = html.escape(identity_data["description"])
if identity_data.get("avatar"):
avatar_data = identity_data["avatar"]
try:
filename = avatar_data["filename"]
media_type = avatar_data["media_type"]
except KeyError:
log.error(f"incomplete avatar data: {identity_data!r}")
else:
avatar_url = self.apg.buildAPURL("avatar", filename)
actor_data["icon"] = {
"type": "Image",
"url": avatar_url,
"mediaType": media_type
}
return actor_data
def getCanonicalURL(self, request: "HTTPRequest") -> str:
return parse.urljoin(
f"https://{self.apg.public_url}",
@ -618,6 +646,12 @@ class HTTPAPGServer(web_resource.Resource):
ret_data = await self.APInboxRequest(
request, None, None, None, ap_url, signing_actor
)
elif request_type == "avatar":
if len(extra_args) != 1:
raise exceptions.DataError("avatar argument expected in URL")
avatar_filename = extra_args[0]
avatar_path = self.apg.host.common_cache.getPath(avatar_filename)
return static.File(str(avatar_path)).render(request)
else:
if len(extra_args) > 1:
log.warning(f"unexpected extra arguments: {extra_args!r}")