forked from forks/microblog.pub
Rename the ActivityType enum
This commit is contained in:
parent
12feb38a8f
commit
7a8621e72e
2 changed files with 66 additions and 66 deletions
115
activitypub.py
115
activitypub.py
|
@ -24,12 +24,11 @@ from typing import TypeVar
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
A = TypeVar('A', bound='BaseActivity')
|
||||
ObjectType = Dict[str, Any]
|
||||
ObjectOrIDType = Union[str, ObjectType]
|
||||
|
||||
|
||||
class ActivityTypes(Enum):
|
||||
class ActivityType(Enum):
|
||||
ANNOUNCE = 'Announce'
|
||||
BLOCK = 'Block'
|
||||
LIKE = 'Like'
|
||||
|
@ -84,8 +83,8 @@ def _get_actor_id(actor: ObjectOrIDType) -> str:
|
|||
|
||||
|
||||
class BaseActivity(object):
|
||||
ACTIVITY_TYPE: Optional[ActivityTypes] = None
|
||||
ALLOWED_OBJECT_TYPES: List[ActivityTypes] = []
|
||||
ACTIVITY_TYPE: Optional[ActivityType] = None
|
||||
ALLOWED_OBJECT_TYPES: List[ActivityType] = []
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
if not self.ACTIVITY_TYPE:
|
||||
|
@ -99,7 +98,7 @@ class BaseActivity(object):
|
|||
if 'id' in kwargs:
|
||||
self._data['id'] = kwargs.pop('id')
|
||||
|
||||
if self.ACTIVITY_TYPE != ActivityTypes.PERSON:
|
||||
if self.ACTIVITY_TYPE != ActivityType.PERSON:
|
||||
actor = kwargs.get('actor')
|
||||
if actor:
|
||||
kwargs.pop('actor')
|
||||
|
@ -117,9 +116,9 @@ class BaseActivity(object):
|
|||
else:
|
||||
if not self.ALLOWED_OBJECT_TYPES:
|
||||
raise ValueError('unexpected object')
|
||||
if 'type' not in obj or (self.ACTIVITY_TYPE != ActivityTypes.CREATE and 'id' not in obj):
|
||||
if 'type' not in obj or (self.ACTIVITY_TYPE != ActivityType.CREATE and 'id' not in obj):
|
||||
raise ValueError('invalid object')
|
||||
if ActivityTypes(obj['type']) not in self.ALLOWED_OBJECT_TYPES:
|
||||
if ActivityType(obj['type']) not in self.ALLOWED_OBJECT_TYPES:
|
||||
print(self, kwargs)
|
||||
raise ValueError(f'unexpected object type {obj["type"]} (allowed={self.ALLOWED_OBJECT_TYPES})')
|
||||
self._data['object'] = obj
|
||||
|
@ -185,8 +184,8 @@ class BaseActivity(object):
|
|||
return self._data.get(name)
|
||||
|
||||
@property
|
||||
def type_enum(self) -> ActivityTypes:
|
||||
return ActivityTypes(self.type)
|
||||
def type_enum(self) -> ActivityType:
|
||||
return ActivityType(self.type)
|
||||
|
||||
def _set_id(self, uri: str, obj_id: str) -> None:
|
||||
raise NotImplementedError
|
||||
|
@ -199,7 +198,7 @@ class BaseActivity(object):
|
|||
pass
|
||||
|
||||
def _actor_id(self, obj: ObjectOrIDType) -> str:
|
||||
if isinstance(obj, dict) and obj['type'] == ActivityTypes.PERSON.value:
|
||||
if isinstance(obj, dict) and obj['type'] == ActivityType.PERSON.value:
|
||||
obj_id = obj.get('id')
|
||||
if not obj_id:
|
||||
raise ValueError('missing object id')
|
||||
|
@ -223,11 +222,11 @@ class BaseActivity(object):
|
|||
if isinstance(self._data['object'], dict):
|
||||
p = parse_activity(self._data['object'])
|
||||
else:
|
||||
if self.ACTIVITY_TYPE == ActivityTypes.FOLLOW:
|
||||
if self.ACTIVITY_TYPE == ActivityType.FOLLOW:
|
||||
p = Person(**ACTOR_SERVICE.get(self._data['object']))
|
||||
else:
|
||||
obj = OBJECT_SERVICE.get(self._data['object'])
|
||||
if ActivityTypes(obj.get('type')) not in self.ALLOWED_OBJECT_TYPES:
|
||||
if ActivityType(obj.get('type')) not in self.ALLOWED_OBJECT_TYPES:
|
||||
raise ValueError('invalid object type')
|
||||
|
||||
p = parse_activity(obj)
|
||||
|
@ -249,7 +248,7 @@ class BaseActivity(object):
|
|||
def get_actor(self) -> 'BaseActivity':
|
||||
actor = self._data.get('actor')
|
||||
if not actor:
|
||||
if self.type_enum == ActivityTypes.NOTE:
|
||||
if self.type_enum == ActivityType.NOTE:
|
||||
actor = str(self._data.get('attributedTo'))
|
||||
else:
|
||||
raise ValueError('failed to fetch actor')
|
||||
|
@ -279,7 +278,7 @@ class BaseActivity(object):
|
|||
self.verify()
|
||||
actor = self.get_actor()
|
||||
|
||||
if DB.outbox.find_one({'type': ActivityTypes.BLOCK.value,
|
||||
if DB.outbox.find_one({'type': ActivityType.BLOCK.value,
|
||||
'activity.object': actor.id,
|
||||
'meta.undo': False}):
|
||||
print('actor is blocked, drop activity')
|
||||
|
@ -357,8 +356,8 @@ class BaseActivity(object):
|
|||
actor = Person(**ACTOR_SERVICE.get(recipient))
|
||||
except NotAnActorError as error:
|
||||
# Is the activity a `Collection`/`OrderedCollection`?
|
||||
if error.activity and error.activity['type'] in [ActivityTypes.COLLECTION.value,
|
||||
ActivityTypes.ORDERED_COLLECTION.value]:
|
||||
if error.activity and error.activity['type'] in [ActivityType.COLLECTION.value,
|
||||
ActivityType.ORDERED_COLLECTION.value]:
|
||||
for item in parse_collection(error.activity):
|
||||
if item in [ME, AS_PUBLIC]:
|
||||
continue
|
||||
|
@ -393,7 +392,7 @@ class BaseActivity(object):
|
|||
|
||||
|
||||
class Person(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.PERSON
|
||||
ACTIVITY_TYPE = ActivityType.PERSON
|
||||
|
||||
def _init(self, **kwargs):
|
||||
# if 'icon' in kwargs:
|
||||
|
@ -410,15 +409,15 @@ class Person(BaseActivity):
|
|||
|
||||
|
||||
class Block(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.BLOCK
|
||||
ACTIVITY_TYPE = ActivityType.BLOCK
|
||||
|
||||
|
||||
class Collection(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.COLLECTION
|
||||
ACTIVITY_TYPE = ActivityType.COLLECTION
|
||||
|
||||
|
||||
class Image(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.IMAGE
|
||||
ACTIVITY_TYPE = ActivityType.IMAGE
|
||||
NO_CONTEXT = True
|
||||
|
||||
def _init(self, **kwargs):
|
||||
|
@ -431,11 +430,11 @@ class Image(BaseActivity):
|
|||
|
||||
|
||||
class Follow(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.FOLLOW
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.PERSON]
|
||||
ACTIVITY_TYPE = ActivityType.FOLLOW
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.PERSON]
|
||||
|
||||
def _build_reply(self, reply_type: ActivityTypes) -> BaseActivity:
|
||||
if reply_type == ActivityTypes.ACCEPT:
|
||||
def _build_reply(self, reply_type: ActivityType) -> BaseActivity:
|
||||
if reply_type == ActivityType.ACCEPT:
|
||||
return Accept(
|
||||
object=self.to_dict(embed=True),
|
||||
)
|
||||
|
@ -461,7 +460,7 @@ class Follow(BaseActivity):
|
|||
DB.following.delete_one({'remote_actor': self.get_object().id})
|
||||
|
||||
def build_accept(self) -> BaseActivity:
|
||||
return self._build_reply(ActivityTypes.ACCEPT)
|
||||
return self._build_reply(ActivityType.ACCEPT)
|
||||
|
||||
def build_undo(self) -> BaseActivity:
|
||||
return Undo(object=self.to_dict(embed=True))
|
||||
|
@ -472,8 +471,8 @@ class Follow(BaseActivity):
|
|||
|
||||
|
||||
class Accept(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.ACCEPT
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.FOLLOW]
|
||||
ACTIVITY_TYPE = ActivityType.ACCEPT
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.FOLLOW]
|
||||
|
||||
def _recipients(self) -> List[str]:
|
||||
return [self.get_object().get_actor().id]
|
||||
|
@ -490,12 +489,12 @@ class Accept(BaseActivity):
|
|||
|
||||
|
||||
class Undo(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.UNDO
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.FOLLOW, ActivityTypes.LIKE, ActivityTypes.ANNOUNCE]
|
||||
ACTIVITY_TYPE = ActivityType.UNDO
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.FOLLOW, ActivityType.LIKE, ActivityType.ANNOUNCE]
|
||||
|
||||
def _recipients(self) -> List[str]:
|
||||
obj = self.get_object()
|
||||
if obj.type_enum == ActivityTypes.FOLLOW:
|
||||
if obj.type_enum == ActivityType.FOLLOW:
|
||||
return [obj.get_object().id]
|
||||
else:
|
||||
return [obj.get_object().get_actor().id]
|
||||
|
@ -538,8 +537,8 @@ class Undo(BaseActivity):
|
|||
|
||||
|
||||
class Like(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.LIKE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.NOTE]
|
||||
ACTIVITY_TYPE = ActivityType.LIKE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.NOTE]
|
||||
|
||||
def _recipients(self) -> List[str]:
|
||||
return [self.get_object().get_actor().id]
|
||||
|
@ -577,8 +576,8 @@ class Like(BaseActivity):
|
|||
|
||||
|
||||
class Announce(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.ANNOUNCE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.NOTE]
|
||||
ACTIVITY_TYPE = ActivityType.ANNOUNCE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.NOTE]
|
||||
|
||||
def _recipients(self) -> List[str]:
|
||||
recipients = []
|
||||
|
@ -638,8 +637,8 @@ class Announce(BaseActivity):
|
|||
|
||||
|
||||
class Delete(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.DELETE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.NOTE, ActivityTypes.TOMBSTONE]
|
||||
ACTIVITY_TYPE = ActivityType.DELETE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.NOTE, ActivityType.TOMBSTONE]
|
||||
|
||||
def _recipients(self) -> List[str]:
|
||||
return self.get_object().recipients()
|
||||
|
@ -654,15 +653,15 @@ class Delete(BaseActivity):
|
|||
|
||||
|
||||
class Update(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.UPDATE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.NOTE, ActivityTypes.PERSON]
|
||||
ACTIVITY_TYPE = ActivityType.UPDATE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.NOTE, ActivityType.PERSON]
|
||||
|
||||
# TODO(tsileo): ensure the actor updating is the same as the orinial activity
|
||||
# (ensuring that the Update and its object are of same origin)
|
||||
|
||||
def _process_from_inbox(self):
|
||||
obj = self.get_object()
|
||||
if obj.type_enum == ActivityTypes.NOTE:
|
||||
if obj.type_enum == ActivityType.NOTE:
|
||||
DB.inbox.update_one({'activity.object.id': obj.id}, {'$set': {'activity.object': obj.to_dict()}})
|
||||
return
|
||||
|
||||
|
@ -694,8 +693,8 @@ class Update(BaseActivity):
|
|||
|
||||
|
||||
class Create(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.CREATE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityTypes.NOTE]
|
||||
ACTIVITY_TYPE = ActivityType.CREATE
|
||||
ALLOWED_OBJECT_TYPES = [ActivityType.NOTE]
|
||||
|
||||
def _set_id(self, uri: str, obj_id: str) -> None:
|
||||
self._data['object']['id'] = uri + '/activity'
|
||||
|
@ -768,11 +767,11 @@ class Create(BaseActivity):
|
|||
|
||||
|
||||
class Tombstone(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.TOMBSTONE
|
||||
ACTIVITY_TYPE = ActivityType.TOMBSTONE
|
||||
|
||||
|
||||
class Note(BaseActivity):
|
||||
ACTIVITY_TYPE = ActivityTypes.NOTE
|
||||
ACTIVITY_TYPE = ActivityType.NOTE
|
||||
|
||||
def _init(self, **kwargs):
|
||||
print(self._data)
|
||||
|
@ -831,25 +830,25 @@ class Note(BaseActivity):
|
|||
|
||||
|
||||
_ACTIVITY_TYPE_TO_CLS = {
|
||||
ActivityTypes.IMAGE: Image,
|
||||
ActivityTypes.PERSON: Person,
|
||||
ActivityTypes.FOLLOW: Follow,
|
||||
ActivityTypes.ACCEPT: Accept,
|
||||
ActivityTypes.UNDO: Undo,
|
||||
ActivityTypes.LIKE: Like,
|
||||
ActivityTypes.ANNOUNCE: Announce,
|
||||
ActivityTypes.UPDATE: Update,
|
||||
ActivityTypes.DELETE: Delete,
|
||||
ActivityTypes.CREATE: Create,
|
||||
ActivityTypes.NOTE: Note,
|
||||
ActivityTypes.BLOCK: Block,
|
||||
ActivityTypes.COLLECTION: Collection,
|
||||
ActivityTypes.TOMBSTONE: Tombstone,
|
||||
ActivityType.IMAGE: Image,
|
||||
ActivityType.PERSON: Person,
|
||||
ActivityType.FOLLOW: Follow,
|
||||
ActivityType.ACCEPT: Accept,
|
||||
ActivityType.UNDO: Undo,
|
||||
ActivityType.LIKE: Like,
|
||||
ActivityType.ANNOUNCE: Announce,
|
||||
ActivityType.UPDATE: Update,
|
||||
ActivityType.DELETE: Delete,
|
||||
ActivityType.CREATE: Create,
|
||||
ActivityType.NOTE: Note,
|
||||
ActivityType.BLOCK: Block,
|
||||
ActivityType.COLLECTION: Collection,
|
||||
ActivityType.TOMBSTONE: Tombstone,
|
||||
}
|
||||
|
||||
|
||||
def parse_activity(payload: ObjectType) -> BaseActivity:
|
||||
t = ActivityTypes(payload['type'])
|
||||
t = ActivityType(payload['type'])
|
||||
if t not in _ACTIVITY_TYPE_TO_CLS:
|
||||
raise ValueError('unsupported activity type')
|
||||
|
||||
|
|
17
app.py
17
app.py
|
@ -33,7 +33,7 @@ from werkzeug.utils import secure_filename
|
|||
|
||||
import activitypub
|
||||
import config
|
||||
from activitypub import ActivityTypes
|
||||
from activitypub import ActivityType
|
||||
from activitypub import clean_activity
|
||||
from utils.content_helper import parse_markdown
|
||||
from config import KEY
|
||||
|
@ -444,7 +444,7 @@ def outbox():
|
|||
# FIXME(tsileo): filter deleted, add query support for build_ordered_collection
|
||||
q = {
|
||||
'meta.deleted': False,
|
||||
'type': {'$in': [ActivityTypes.CREATE.value, ActivityTypes.ANNOUNCE.value]},
|
||||
'type': {'$in': [ActivityType.CREATE.value, ActivityType.ANNOUNCE.value]},
|
||||
}
|
||||
return jsonify(**activitypub.build_ordered_collection(
|
||||
DB.outbox,
|
||||
|
@ -463,7 +463,7 @@ def outbox():
|
|||
print(data)
|
||||
activity = activitypub.parse_activity(data)
|
||||
|
||||
if activity.type_enum == ActivityTypes.NOTE:
|
||||
if activity.type_enum == ActivityType.NOTE:
|
||||
activity = activity.build_create()
|
||||
|
||||
activity.post_to_outbox()
|
||||
|
@ -486,7 +486,7 @@ def outbox_activity(item_id):
|
|||
if not data:
|
||||
abort(404)
|
||||
obj = data['activity']
|
||||
if obj['type'] != ActivityTypes.CREATE.value:
|
||||
if obj['type'] != ActivityType.CREATE.value:
|
||||
abort(404)
|
||||
return jsonify(**clean_activity(obj['object']))
|
||||
|
||||
|
@ -496,7 +496,7 @@ def admin():
|
|||
q = {
|
||||
'meta.deleted': False,
|
||||
'meta.undo': False,
|
||||
'type': ActivityTypes.LIKE.value,
|
||||
'type': ActivityType.LIKE.value,
|
||||
}
|
||||
col_liked = DB.outbox.count(q)
|
||||
|
||||
|
@ -801,7 +801,7 @@ def api_new_note():
|
|||
note = activitypub.Note(
|
||||
cc=cc,
|
||||
to=[to if to else config.AS_PUBLIC],
|
||||
content=content, # TODO(tsileo): handle markdown
|
||||
content=content,
|
||||
tag=tags,
|
||||
source={'mediaType': 'text/markdown', 'content': source},
|
||||
)
|
||||
|
@ -810,6 +810,7 @@ def api_new_note():
|
|||
return Response(
|
||||
status=201,
|
||||
response='OK',
|
||||
headers={'Microblogpub-Created-Activity': created.id},
|
||||
)
|
||||
|
||||
@app.route('/api/stream')
|
||||
|
@ -895,7 +896,7 @@ def tags(tag):
|
|||
q = {
|
||||
'meta.deleted': False,
|
||||
'meta.undo': False,
|
||||
'type': ActivityTypes.CREATE.value,
|
||||
'type': ActivityType.CREATE.value,
|
||||
'activity.object.tag.type': 'Hashtag',
|
||||
'activity.object.tag.name': '#'+tag,
|
||||
}
|
||||
|
@ -915,7 +916,7 @@ def liked():
|
|||
q = {
|
||||
'meta.deleted': False,
|
||||
'meta.undo': False,
|
||||
'type': ActivityTypes.LIKE.value,
|
||||
'type': ActivityType.LIKE.value,
|
||||
}
|
||||
return jsonify(**activitypub.build_ordered_collection(
|
||||
DB.outbox,
|
||||
|
|
Loading…
Reference in a new issue