kopia lustrzana https://github.com/tsileo/little-boxes
Cleanup
rodzic
587e580755
commit
bcf4d14326
|
@ -5,7 +5,7 @@ install:
|
||||||
- pip install -r requirements.txt
|
- pip install -r requirements.txt
|
||||||
- pip install -r dev-requirements.txt
|
- pip install -r dev-requirements.txt
|
||||||
script:
|
script:
|
||||||
# - mypy --ignore-missing-imports little_boxes
|
- mypy --ignore-missing-imports little_boxes
|
||||||
- flake8 little_boxes
|
- flake8 little_boxes
|
||||||
- black --check .
|
- black --check .
|
||||||
- python -m pytest -vv --cov=little_boxes
|
- python -m pytest -vv --cov=little_boxes
|
||||||
|
|
|
@ -3,7 +3,7 @@ import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def strtobool(s: str) -> bool:
|
def strtobool(s: str) -> bool: # pragma: no cover
|
||||||
if s in ["y", "yes", "true", "on", "1"]:
|
if s in ["y", "yes", "true", "on", "1"]:
|
||||||
return True
|
return True
|
||||||
if s in ["n", "no", "false", "off", "0"]:
|
if s in ["n", "no", "false", "off", "0"]:
|
||||||
|
|
|
@ -367,7 +367,7 @@ class BaseActivity(object, metaclass=_ActivityMeta):
|
||||||
actor_id = self._actor_id(actor)
|
actor_id = self._actor_id(actor)
|
||||||
return Person(**BACKEND.fetch_iri(actor_id))
|
return Person(**BACKEND.fetch_iri(actor_id))
|
||||||
|
|
||||||
def _pre_post_to_outbox(self) -> None:
|
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _post_to_outbox(
|
def _post_to_outbox(
|
||||||
|
@ -407,7 +407,7 @@ class BaseActivity(object, metaclass=_ActivityMeta):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
if BACKEND.inbox_get_by_iri(as_actor, self.id):
|
if BACKEND.inbox_check_duplicate(as_actor, self.id):
|
||||||
# The activity is already in the inbox
|
# The activity is already in the inbox
|
||||||
logger.info(f"received duplicate activity {self}, dropping it")
|
logger.info(f"received duplicate activity {self}, dropping it")
|
||||||
return
|
return
|
||||||
|
@ -438,7 +438,7 @@ class BaseActivity(object, metaclass=_ActivityMeta):
|
||||||
self.outbox_set_id(BACKEND.activity_url(obj_id), obj_id)
|
self.outbox_set_id(BACKEND.activity_url(obj_id), obj_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._pre_post_to_outbox()
|
self._pre_post_to_outbox(self.get_actor())
|
||||||
logger.debug(f"called pre post to outbox hook")
|
logger.debug(f"called pre post to outbox hook")
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
logger.debug("pre post to outbox hook not implemented")
|
logger.debug("pre post to outbox hook not implemented")
|
||||||
|
@ -671,12 +671,12 @@ class Undo(BaseActivity):
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _pre_post_to_outbox(self) -> None:
|
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
|
||||||
"""Ensures an Undo activity references an activity owned by the instance."""
|
"""Ensures an Undo activity references an activity owned by the instance."""
|
||||||
if BACKEND is None:
|
if BACKEND is None:
|
||||||
raise UninitializedBackendError
|
raise UninitializedBackendError
|
||||||
|
|
||||||
if not BACKEND.is_from_outbox(self):
|
if not BACKEND.is_from_outbox(as_actor, self):
|
||||||
raise NotFromOutboxError(f"object {self!r} is not owned by this instance")
|
raise NotFromOutboxError(f"object {self!r} is not owned by this instance")
|
||||||
|
|
||||||
def _post_to_outbox(
|
def _post_to_outbox(
|
||||||
|
@ -774,6 +774,9 @@ class Announce(BaseActivity):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if BACKEND is None:
|
||||||
|
raise UninitializedBackendError
|
||||||
|
|
||||||
BACKEND.inbox_announce(as_actor, self)
|
BACKEND.inbox_announce(as_actor, self)
|
||||||
|
|
||||||
def _undo_inbox(self, as_actor: "Person") -> None:
|
def _undo_inbox(self, as_actor: "Person") -> None:
|
||||||
|
@ -789,6 +792,9 @@ class Announce(BaseActivity):
|
||||||
activity: ObjectType,
|
activity: ObjectType,
|
||||||
recipients: List[str],
|
recipients: List[str],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
if BACKEND is None:
|
||||||
|
raise UninitializedBackendError
|
||||||
|
|
||||||
BACKEND.outbox_announce(as_actor, self)
|
BACKEND.outbox_announce(as_actor, self)
|
||||||
|
|
||||||
def _undo_outbox(self, as_actor: "Person") -> None:
|
def _undo_outbox(self, as_actor: "Person") -> None:
|
||||||
|
@ -834,14 +840,14 @@ class Delete(BaseActivity):
|
||||||
BACKEND.inbox_delete(as_actor, self)
|
BACKEND.inbox_delete(as_actor, self)
|
||||||
# FIXME(tsileo): handle the delete_threads here?
|
# FIXME(tsileo): handle the delete_threads here?
|
||||||
|
|
||||||
def _pre_post_to_outbox(self) -> None:
|
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
|
||||||
"""Ensures the Delete activity references a activity from the outbox (i.e. owned by the instance)."""
|
"""Ensures the Delete activity references a activity from the outbox (i.e. owned by the instance)."""
|
||||||
if BACKEND is None:
|
if BACKEND is None:
|
||||||
raise UninitializedBackendError
|
raise UninitializedBackendError
|
||||||
|
|
||||||
obj = self._get_actual_object()
|
obj = self._get_actual_object()
|
||||||
|
|
||||||
if not BACKEND.is_from_outbox(self):
|
if not BACKEND.is_from_outbox(as_actor, self):
|
||||||
raise NotFromOutboxError(
|
raise NotFromOutboxError(
|
||||||
f'object {obj["id"]} is not owned by this instance'
|
f'object {obj["id"]} is not owned by this instance'
|
||||||
)
|
)
|
||||||
|
@ -878,11 +884,11 @@ class Update(BaseActivity):
|
||||||
|
|
||||||
BACKEND.inbox_update(as_actor, self)
|
BACKEND.inbox_update(as_actor, self)
|
||||||
|
|
||||||
def _pre_post_to_outbox(self) -> None:
|
def _pre_post_to_outbox(self, as_actor: "Person") -> None:
|
||||||
if BACKEND is None:
|
if BACKEND is None:
|
||||||
raise UninitializedBackendError
|
raise UninitializedBackendError
|
||||||
|
|
||||||
if not BACKEND.is_from_outbox(self):
|
if not BACKEND.is_from_outbox(as_actor, self):
|
||||||
raise NotFromOutboxError(f"object {self!r} is not owned by this instance")
|
raise NotFromOutboxError(f"object {self!r} is not owned by this instance")
|
||||||
|
|
||||||
def _post_to_outbox(
|
def _post_to_outbox(
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import abc
|
import abc
|
||||||
import typing
|
import typing
|
||||||
|
import os
|
||||||
|
import binascii
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
@ -13,6 +15,10 @@ class Backend(abc.ABC):
|
||||||
def user_agent(self) -> str:
|
def user_agent(self) -> str:
|
||||||
return f"Little Boxes {__version__} (+http://github.com/tsileo/little-boxes)"
|
return f"Little Boxes {__version__} (+http://github.com/tsileo/little-boxes)"
|
||||||
|
|
||||||
|
def random_object_id(self) -> str:
|
||||||
|
"""Generates a random object ID."""
|
||||||
|
return binascii.hexlify(os.urandom(8)).decode("utf-8")
|
||||||
|
|
||||||
def fetch_json(self, url: str, **kwargs):
|
def fetch_json(self, url: str, **kwargs):
|
||||||
resp = requests.get(
|
resp = requests.get(
|
||||||
url,
|
url,
|
||||||
|
@ -21,6 +27,15 @@ class Backend(abc.ABC):
|
||||||
)
|
)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
def is_from_outbox(self, as_actor: "ap.Person", activity: "ap.BaseActivity") -> bool:
|
||||||
|
return activity.get_actor().id == as_actor.id
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def post_to_remote_inbox(
|
||||||
|
self, as_actor: "ap.Person", payload_encoded: str, recp: str
|
||||||
|
) -> None:
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def base_url(self) -> str:
|
def base_url(self) -> str:
|
||||||
pass # pragma: no cover
|
pass # pragma: no cover
|
||||||
|
@ -29,6 +44,10 @@ class Backend(abc.ABC):
|
||||||
def fetch_iri(self, iri: str) -> "ap.ObjectType":
|
def fetch_iri(self, iri: str) -> "ap.ObjectType":
|
||||||
pass # pragma: no cover
|
pass # pragma: no cover
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def inbox_check_duplicate(self, as_actor: "ap.Person", iri: str) -> bool:
|
||||||
|
pass # pragma: no cover
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def activity_url(self, obj_id: str) -> str:
|
def activity_url(self, obj_id: str) -> str:
|
||||||
pass # pragma: no cover
|
pass # pragma: no cover
|
||||||
|
|
|
@ -39,6 +39,9 @@ def mentionify(content: str) -> Tuple[str, List[Dict[str, str]]]:
|
||||||
for mention in re.findall(MENTION_REGEX, content):
|
for mention in re.findall(MENTION_REGEX, content):
|
||||||
_, username, domain = mention.split("@")
|
_, username, domain = mention.split("@")
|
||||||
actor_url = get_actor_url(mention)
|
actor_url = get_actor_url(mention)
|
||||||
|
if not actor_url:
|
||||||
|
# FIXME(tsileo): raise an error?
|
||||||
|
continue
|
||||||
p = get_backend().fetch_iri(actor_url)
|
p = get_backend().fetch_iri(actor_url)
|
||||||
tags.append(dict(type="Mention", href=p["id"], name=mention))
|
tags.append(dict(type="Mention", href=p["id"], name=mention))
|
||||||
link = f'<span class="h-card"><a href="{p["url"]}" class="u-url mention">@<span>{username}</span></a></span>'
|
link = f'<span class="h-card"><a href="{p["url"]}" class="u-url mention">@<span>{username}</span></a></span>'
|
||||||
|
|
|
@ -55,7 +55,7 @@ def _verify_h(signed_string, signature, pubkey):
|
||||||
|
|
||||||
def _body_digest(body: str) -> str:
|
def _body_digest(body: str) -> str:
|
||||||
h = hashlib.new("sha256")
|
h = hashlib.new("sha256")
|
||||||
h.update(body)
|
h.update(body) # type: ignore
|
||||||
return "SHA-256=" + base64.b64encode(h.digest()).decode("utf-8")
|
return "SHA-256=" + base64.b64encode(h.digest()).decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -67,10 +67,6 @@ class InMemBackend(Backend):
|
||||||
|
|
||||||
return calls
|
return calls
|
||||||
|
|
||||||
def random_object_id(self) -> str:
|
|
||||||
"""Generates a random object ID."""
|
|
||||||
return binascii.hexlify(os.urandom(8)).decode("utf-8")
|
|
||||||
|
|
||||||
def setup_actor(self, name, pusername):
|
def setup_actor(self, name, pusername):
|
||||||
"""Create a new actor in this backend."""
|
"""Create a new actor in this backend."""
|
||||||
p = ap.Person(
|
p = ap.Person(
|
||||||
|
@ -126,7 +122,7 @@ class InMemBackend(Backend):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def inbox_get_by_iri(
|
def inbox_check_duplicate(
|
||||||
self, as_actor: ap.Person, iri: str
|
self, as_actor: ap.Person, iri: str
|
||||||
) -> Optional[ap.BaseActivity]:
|
) -> Optional[ap.BaseActivity]:
|
||||||
for activity in self.DB[as_actor.id]["inbox"]:
|
for activity in self.DB[as_actor.id]["inbox"]:
|
||||||
|
@ -194,10 +190,6 @@ class InMemBackend(Backend):
|
||||||
as_actor = ap.parse_activity(self.fetch_iri(recp.replace("/inbox", "")))
|
as_actor = ap.parse_activity(self.fetch_iri(recp.replace("/inbox", "")))
|
||||||
act.process_from_inbox(as_actor)
|
act.process_from_inbox(as_actor)
|
||||||
|
|
||||||
def is_from_outbox(self, activity: ap.BaseActivity) -> bool:
|
|
||||||
# return as_actor.id == activity.get_actor().id
|
|
||||||
return True # FIXME(tsileo): implement this
|
|
||||||
|
|
||||||
@track_call
|
@track_call
|
||||||
def inbox_like(self, as_actor: ap.Person, activity: ap.Like) -> None:
|
def inbox_like(self, as_actor: ap.Person, activity: ap.Like) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
Ładowanie…
Reference in New Issue