# Path: federation/entities/activitypub/constants.py
# NAMESPACE_PUBLIC = "https://www.w3.org/ns/activitystreams#Public"
# 
# Path: federation/protocols/activitypub/signing.py
# def get_http_authentication(private_key: RsaKey, private_key_id: str) -> HTTPSignatureHeaderAuth:
#     """
#     Get HTTP signature authentication for a request.
#     """
#     key = private_key.exportKey()
#     return HTTPSignatureHeaderAuth(
#         headers=["(request-target)", "user-agent", "host", "date"],
#         algorithm="rsa-sha256",
#         key=key,
#         key_id=private_key_id,
#     )
# 
# Path: federation/types.py
# class UserType:
#     id: str = attr.ib()
#     private_key: Optional[Union[RsaKey, str]] = attr.ib(default=None)
#     receiver_variant: Optional[ReceiverVariant] = attr.ib(default=None)
# 
#     # Required only if sending to Diaspora protocol platforms
#     handle: Optional[str] = attr.ib(default=None)
#     guid: Optional[str] = attr.ib(default=None)
# 
#     # Required only if sending to Matrix protocol
#     mxid: Optional[str] = attr.ib(default=None)
#     # TODO needed?
#     variant: Optional[UserVariant] = attr.ib(default=None)
# 
#     @property
#     def rsa_private_key(self) -> RsaKey:
#         if isinstance(self.private_key, str):
#             return RSA.importKey(self.private_key)
#         return self.private_key
# 
# Path: federation/utils/network.py
# def send_document(url, data, timeout=10, method="post", *args, **kwargs):
#     """Helper method to send a document via POST.
# 
#     Additional ``*args`` and ``**kwargs`` will be passed on to ``requests.post``.
# 
#     :arg url: Full url to send to, including protocol
#     :arg data: Dictionary (will be form-encoded), bytes, or file-like object to send in the body
#     :arg timeout: Seconds to wait for response (defaults to 10)
#     :arg method: Method to use, defaults to post
#     :returns: Tuple of status code (int or None) and error (exception class instance or None)
#     """
#     logger.debug("send_document: url=%s, data=%s, timeout=%s, method=%s", url, data, timeout, method)
#     if not method:
#         method = "post"
#     headers = CaseInsensitiveDict({
#         'User-Agent': USER_AGENT,
#     })
#     if "headers" in kwargs:
#         # Update from kwargs
#         headers.update(kwargs.get("headers"))
#     kwargs.update({
#         "data": data, "timeout": timeout, "headers": headers
#     })
#     request_func = getattr(requests, method)
#     try:
#         response = request_func(url, *args, **kwargs)
#         logger.debug("send_document: response status code %s", response.status_code)
#         return response.status_code, None
#     # TODO support rate limit 429 code
#     except RequestException as ex:
#         logger.debug("send_document: exception %s", ex)
#         return None, ex


import copy
import importlib
import json
import logging
import traceback
from typing import List, Dict, Union
from Crypto.PublicKey import RSA
from Crypto.PublicKey.RSA import RsaKey
from iteration_utilities import unique_everseen
from federation.entities.activitypub.constants import NAMESPACE_PUBLIC
from federation.entities.mixins import BaseEntity
from federation.protocols.activitypub.signing import get_http_authentication
from federation.types import UserType
from federation.utils.matrix import get_matrix_configuration
from federation.utils.network import send_document

# noinspection PyPackageRequirements
# noinspection PyPackageRequirements


logger = logging.getLogger("federation")


def handle_create_payload(
        entity: BaseEntity,
        author_user: UserType,
        protocol_name: str,
        to_user_key: RsaKey = None,

# Path: federation/entities/activitypub/constants.py
# NAMESPACE_PUBLIC = "https://www.w3.org/ns/activitystreams#Public"
# 
# Path: federation/protocols/activitypub/signing.py
# def get_http_authentication(private_key: RsaKey, private_key_id: str) -> HTTPSignatureHeaderAuth:
#     """
#     Get HTTP signature authentication for a request.
#     """
#     key = private_key.exportKey()
#     return HTTPSignatureHeaderAuth(
#         headers=["(request-target)", "user-agent", "host", "date"],
#         algorithm="rsa-sha256",
#         key=key,
#         key_id=private_key_id,
#     )
# 
# Path: federation/types.py
# class UserType:
#     id: str = attr.ib()
#     private_key: Optional[Union[RsaKey, str]] = attr.ib(default=None)
#     receiver_variant: Optional[ReceiverVariant] = attr.ib(default=None)
# 
#     # Required only if sending to Diaspora protocol platforms
#     handle: Optional[str] = attr.ib(default=None)
#     guid: Optional[str] = attr.ib(default=None)
# 
#     # Required only if sending to Matrix protocol
#     mxid: Optional[str] = attr.ib(default=None)
#     # TODO needed?
#     variant: Optional[UserVariant] = attr.ib(default=None)
# 
#     @property
#     def rsa_private_key(self) -> RsaKey:
#         if isinstance(self.private_key, str):
#             return RSA.importKey(self.private_key)
#         return self.private_key
# 
# Path: federation/utils/network.py
# def send_document(url, data, timeout=10, method="post", *args, **kwargs):
#     """Helper method to send a document via POST.
# 
#     Additional ``*args`` and ``**kwargs`` will be passed on to ``requests.post``.
# 
#     :arg url: Full url to send to, including protocol
#     :arg data: Dictionary (will be form-encoded), bytes, or file-like object to send in the body
#     :arg timeout: Seconds to wait for response (defaults to 10)
#     :arg method: Method to use, defaults to post
#     :returns: Tuple of status code (int or None) and error (exception class instance or None)
#     """
#     logger.debug("send_document: url=%s, data=%s, timeout=%s, method=%s", url, data, timeout, method)
#     if not method:
#         method = "post"
#     headers = CaseInsensitiveDict({
#         'User-Agent': USER_AGENT,
#     })
#     if "headers" in kwargs:
#         # Update from kwargs
#         headers.update(kwargs.get("headers"))
#     kwargs.update({
#         "data": data, "timeout": timeout, "headers": headers
#     })
#     request_func = getattr(requests, method)
#     try:
#         response = request_func(url, *args, **kwargs)
#         logger.debug("send_document: response status code %s", response.status_code)
#         return response.status_code, None
#     # TODO support rate limit 429 code
#     except RequestException as ex:
#         logger.debug("send_document: exception %s", ex)
#         return None, ex


# Path: federation/outbound.py
import copy
import importlib
import json
import logging
import traceback
from typing import List, Dict, Union
from Crypto.PublicKey import RSA
from Crypto.PublicKey.RSA import RsaKey
from iteration_utilities import unique_everseen
from federation.entities.activitypub.constants import NAMESPACE_PUBLIC
from federation.entities.mixins import BaseEntity
from federation.protocols.activitypub.signing import get_http_authentication
from federation.types import UserType
from federation.utils.matrix import get_matrix_configuration
from federation.utils.network import send_document


# noinspection PyPackageRequirements
# noinspection PyPackageRequirements


logger = logging.getLogger("federation")


def handle_create_payload(
        entity: BaseEntity,
        author_user: UserType,
        protocol_name: str,
        to_user_key: RsaKey = None,

        parent_user: UserType = None,