Merge branch 'jaywink/set-activitypub-profile-icon' into 'master'

Set profile icon properly for ActivityPub profiles

See merge request jaywink/federation!147
merge-requests/149/head
Jason Robinson 2019-06-29 21:24:59 +00:00
commit 14116923be
4 zmienionych plików z 52 dodań i 4 usunięć

Wyświetl plik

@ -2,11 +2,14 @@ import logging
import uuid import uuid
from typing import Dict from typing import Dict
import attr
from federation.entities.activitypub.constants import ( from federation.entities.activitypub.constants import (
CONTEXTS_DEFAULT, CONTEXT_MANUALLY_APPROVES_FOLLOWERS, CONTEXT_SENSITIVE, CONTEXT_HASHTAG, CONTEXTS_DEFAULT, CONTEXT_MANUALLY_APPROVES_FOLLOWERS, CONTEXT_SENSITIVE, CONTEXT_HASHTAG,
CONTEXT_LD_SIGNATURES) CONTEXT_LD_SIGNATURES)
from federation.entities.activitypub.enums import ActorType, ObjectType, ActivityType from federation.entities.activitypub.enums import ActorType, ObjectType, ActivityType
from federation.entities.activitypub.mixins import ActivitypubObjectMixin, ActivitypubActorMixin from federation.entities.activitypub.mixins import ActivitypubObjectMixin, ActivitypubActorMixin
from federation.entities.activitypub.objects import ImageObject
from federation.entities.base import Profile, Post, Follow, Accept from federation.entities.base import Profile, Post, Follow, Accept
from federation.outbound import handle_send from federation.outbound import handle_send
from federation.types import UserType from federation.types import UserType
@ -168,5 +171,8 @@ class ActivitypubProfile(ActivitypubActorMixin, Profile):
if self.raw_content: if self.raw_content:
as2['summary'] = self.raw_content as2['summary'] = self.raw_content
if self.image_urls.get('large'): if self.image_urls.get('large'):
as2['icon'] = self.image_urls.get('large') try:
as2['icon'] = attr.asdict(ImageObject(url=self.image_urls.get('large')))
except Exception as ex:
logger.warning("ActivitypubProfile.to_as2 - failed to set profile icon: %s", ex)
return as2 return as2

Wyświetl plik

@ -0,0 +1,25 @@
import attr
from federation.utils.network import fetch_content_type
@attr.s
class ImageObject:
"""
An Image object for AS2 serialization.
"""
_allowed_types = (
"image/jpeg",
"image/png",
"image/gif",
)
url: str = attr.ib()
type: str = attr.ib(default="Image")
mediaType: str = attr.ib()
@mediaType.default
def cache_media_type(self):
content_type = fetch_content_type(self.url)
if content_type in self._allowed_types:
return content_type
return ""

Wyświetl plik

@ -79,7 +79,8 @@ class TestEntitiesConvertToAS2:
'published': '2019-04-27T00:00:00', 'published': '2019-04-27T00:00:00',
} }
def test_profile_to_as2(self, activitypubprofile): @patch("federation.entities.activitypub.objects.fetch_content_type", return_value="image/jpeg")
def test_profile_to_as2(self, mock_fetch, activitypubprofile):
result = activitypubprofile.to_as2() result = activitypubprofile.to_as2()
assert result == { assert result == {
"@context": CONTEXTS_DEFAULT + [ "@context": CONTEXTS_DEFAULT + [
@ -104,7 +105,11 @@ class TestEntitiesConvertToAS2:
"type": "Person", "type": "Person",
"url": "https://example.com/bob-bobertson", "url": "https://example.com/bob-bobertson",
"summary": "foobar", "summary": "foobar",
"icon": "urllarge", "icon": {
"type": "Image",
"url": "urllarge",
"mediaType": "image/jpeg",
}
} }

Wyświetl plik

@ -3,7 +3,7 @@ import datetime
import logging import logging
import re import re
import socket import socket
from typing import Tuple from typing import Optional, Tuple
import requests import requests
from ipdata import ipdata from ipdata import ipdata
@ -18,6 +18,18 @@ logger = logging.getLogger("federation")
USER_AGENT = "python/federation/%s" % __version__ USER_AGENT = "python/federation/%s" % __version__
def fetch_content_type(url: str) -> Optional[str]:
"""
Fetch the HEAD of the remote url to determine the content type.
"""
try:
response = requests.head(url, headers={'user-agent': USER_AGENT}, timeout=10)
except RequestException as ex:
logger.warning("fetch_content_type - %s when fetching url %s", ex, url)
else:
return response.headers.get('Content-Type')
def fetch_country_by_ip(ip): def fetch_country_by_ip(ip):
""" """
Fetches country code by IP Fetches country code by IP