diff --git a/federation/entities/mixins.py b/federation/entities/mixins.py index 8bc7cf5..036b6b7 100644 --- a/federation/entities/mixins.py +++ b/federation/entities/mixins.py @@ -1,6 +1,7 @@ import datetime import importlib import warnings +from typing import Optional from federation.entities.activitypub.enums import ActivityType @@ -115,6 +116,14 @@ class BaseEntity: """Implement in subclasses if needed.""" pass + @property + def username(self) -> Optional[str]: + if self.handle: + username_part = self.handle.rsplit('@', 1) + if username_part: + # Strip any remaining '@' if this is a Mastodon style handle + return username_part[0].strip('@') + class PublicMixin(BaseEntity): public = False diff --git a/federation/tests/entities/test_base.py b/federation/tests/entities/test_base.py index df40652..ff28c0c 100644 --- a/federation/tests/entities/test_base.py +++ b/federation/tests/entities/test_base.py @@ -18,6 +18,16 @@ class TestPostEntityTags: assert post.tags == set() +class TestBaseEntity: + def test_username(self): + entity = Profile(handle='foobar@localhost.local') + assert entity.username == 'foobar' + entity = Profile(handle='@foobar@localhost.local') + assert entity.username == 'foobar' + entity = Profile() + assert entity.username is None + + class TestBaseEntityCallsValidateMethods: def test_entity_calls_attribute_validate_method(self): post = PostFactory()