2018-06-13 18:08:12 +00:00
|
|
|
import abc
|
2018-06-16 19:57:07 +00:00
|
|
|
import binascii
|
2018-06-16 19:58:48 +00:00
|
|
|
import os
|
|
|
|
import typing
|
2018-06-16 12:19:47 +00:00
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
from .__version__ import __version__
|
2018-06-16 20:16:33 +00:00
|
|
|
from .errors import ActivityNotFoundError
|
2018-06-22 21:38:25 +00:00
|
|
|
from .errors import RemoteActivityGoneError
|
2018-06-17 18:26:53 +00:00
|
|
|
from .urlutils import check_url
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
if typing.TYPE_CHECKING:
|
2018-06-13 18:09:58 +00:00
|
|
|
from little_boxes import activitypub as ap # noqa: type checking
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Backend(abc.ABC):
|
2018-06-16 12:19:47 +00:00
|
|
|
def user_agent(self) -> str:
|
2018-06-22 20:57:38 +00:00
|
|
|
return (
|
|
|
|
f"{requests.utils.default_user_agent()} (Little Boxes/{__version__};"
|
|
|
|
" +http://github.com/tsileo/little-boxes)"
|
|
|
|
)
|
2018-06-16 12:19:47 +00:00
|
|
|
|
2018-06-16 19:57:07 +00:00
|
|
|
def random_object_id(self) -> str:
|
|
|
|
"""Generates a random object ID."""
|
|
|
|
return binascii.hexlify(os.urandom(8)).decode("utf-8")
|
|
|
|
|
2018-06-16 16:54:17 +00:00
|
|
|
def fetch_json(self, url: str, **kwargs):
|
2018-06-17 18:26:53 +00:00
|
|
|
check_url(url)
|
2018-06-16 12:19:47 +00:00
|
|
|
resp = requests.get(
|
2018-06-16 16:54:17 +00:00
|
|
|
url,
|
|
|
|
headers={"User-Agent": self.user_agent(), "Accept": "application/json"},
|
|
|
|
**kwargs,
|
2018-06-16 12:19:47 +00:00
|
|
|
)
|
2018-06-22 21:38:25 +00:00
|
|
|
|
|
|
|
resp.raise_for_status()
|
|
|
|
|
2018-06-16 16:54:17 +00:00
|
|
|
return resp
|
2018-06-16 12:19:47 +00:00
|
|
|
|
2018-06-16 19:58:48 +00:00
|
|
|
def is_from_outbox(
|
|
|
|
self, as_actor: "ap.Person", activity: "ap.BaseActivity"
|
|
|
|
) -> bool:
|
2018-06-16 19:57:07 +00:00
|
|
|
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
|
|
|
|
|
2018-06-16 09:17:15 +00:00
|
|
|
@abc.abstractmethod
|
|
|
|
def base_url(self) -> str:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-16 09:17:15 +00:00
|
|
|
|
2018-06-16 20:16:33 +00:00
|
|
|
def fetch_iri(self, iri: str, **kwargs) -> "ap.ObjectType": # pragma: no cover
|
2018-06-17 18:26:53 +00:00
|
|
|
check_url(iri)
|
2018-06-16 20:16:33 +00:00
|
|
|
resp = requests.get(
|
|
|
|
iri,
|
|
|
|
headers={
|
|
|
|
"User-Agent": self.user_agent(),
|
|
|
|
"Accept": "application/activity+json",
|
|
|
|
},
|
|
|
|
**kwargs,
|
|
|
|
)
|
|
|
|
if resp.status_code == 404:
|
|
|
|
raise ActivityNotFoundError(f"{iri} is not found")
|
2018-06-22 21:38:25 +00:00
|
|
|
elif resp.status_code == 410:
|
|
|
|
raise RemoteActivityGoneError(f"{iri} is gone")
|
2018-06-16 20:16:33 +00:00
|
|
|
|
|
|
|
resp.raise_for_status()
|
|
|
|
|
|
|
|
return resp.json()
|
2018-06-13 18:08:12 +00:00
|
|
|
|
2018-06-16 19:57:07 +00:00
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_check_duplicate(self, as_actor: "ap.Person", iri: str) -> bool:
|
|
|
|
pass # pragma: no cover
|
|
|
|
|
2018-06-13 18:08:12 +00:00
|
|
|
@abc.abstractmethod
|
|
|
|
def activity_url(self, obj_id: str) -> str:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_create(self, as_actor: "ap.Person", activity: "ap.Create") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
2018-06-13 21:15:09 +00:00
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_delete(self, as_actor: "ap.Person", activity: "ap.Delete") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 21:15:09 +00:00
|
|
|
|
2018-06-13 18:08:12 +00:00
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_create(self, as_actor: "ap.Person", activity: "ap.Create") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
2018-06-13 21:15:09 +00:00
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_delete(self, as_actor: "ap.Person", activity: "ap.Delete") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 21:15:09 +00:00
|
|
|
|
2018-06-13 18:08:12 +00:00
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_is_blocked(self, as_actor: "ap.Person", actor_id: str) -> bool:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_new(self, as_actor: "ap.Person", activity: "ap.BaseActivity") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_new(self, as_actor: "ap.Person", activity: "ap.BaseActivity") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def new_follower(self, as_actor: "ap.Person", follow: "ap.Follow") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def new_following(self, as_actor: "ap.Person", follow: "ap.Follow") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def undo_new_follower(self, as_actor: "ap.Person", follow: "ap.Follow") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def undo_new_following(self, as_actor: "ap.Person", follow: "ap.Follow") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-13 18:08:12 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_update(self, as_actor: "ap.Person", activity: "ap.Update") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-15 21:53:25 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_update(self, as_actor: "ap.Person", activity: "ap.Update") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 06:10:45 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_like(self, as_actor: "ap.Person", activity: "ap.Like") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 06:10:45 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_undo_like(self, as_actor: "ap.Person", activity: "ap.Like") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 06:10:45 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_like(self, as_actor: "ap.Person", activity: "ap.Like") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 06:10:45 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_undo_like(self, as_actor: "ap.Person", activity: "ap.Like") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 21:39:05 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def inbox_announce(self, as_actor: "ap.Person", activity: "ap.Announce") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 21:39:05 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
2018-06-14 22:00:54 +00:00
|
|
|
def inbox_undo_announce(
|
|
|
|
self, as_actor: "ap.Person", activity: "ap.Announce"
|
|
|
|
) -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 21:39:05 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_announce(self, as_actor: "ap.Person", activity: "ap.Announce") -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|
2018-06-14 21:39:05 +00:00
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def outbox_undo_announce(
|
|
|
|
self, as_actor: "ap.Person", activity: "ap.Announce"
|
|
|
|
) -> None:
|
2018-06-16 16:54:17 +00:00
|
|
|
pass # pragma: no cover
|