[feat] process inbox request
This commit is contained in:
parent
4497fb646f
commit
03af5cedb7
2 changed files with 139 additions and 0 deletions
2
app.py
2
app.py
|
@ -5,6 +5,7 @@ import sys
|
|||
from flask import Flask, Response, request, Request, abort, jsonify
|
||||
|
||||
from loguru import logger
|
||||
from demo.boxes import process_inbox
|
||||
|
||||
from demo.utils.checker import inbox_prechecker
|
||||
from demo.activitypub import ME
|
||||
|
@ -43,6 +44,7 @@ def inbox():
|
|||
"""Process inbox request"""
|
||||
is_verify = inbox_prechecker(request)
|
||||
if is_verify:
|
||||
process_inbox(request.json)
|
||||
return "STUB", 202
|
||||
abort(401)
|
||||
|
||||
|
|
137
demo/boxes.py
Normal file
137
demo/boxes.py
Normal file
|
@ -0,0 +1,137 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Inbox or Outbox."""
|
||||
from datetime import datetime as dtime
|
||||
from datetime import timezone
|
||||
|
||||
from loguru import logger
|
||||
from demo.config import BASE_URL, ID
|
||||
from demo.actor import fetch_actor
|
||||
from demo import activitypub as ap
|
||||
|
||||
import json
|
||||
import uuid
|
||||
import os
|
||||
|
||||
|
||||
def process_inbox(
|
||||
payload
|
||||
) -> None:
|
||||
if "@context" not in payload:
|
||||
logger.warning(f"invalid object: {payload}")
|
||||
return None
|
||||
|
||||
if "Follow" == payload["type"]:
|
||||
ap_actor = fetch_actor(payload["actor"])
|
||||
_send_accept(payload, ap_actor["inbox"])
|
||||
_save_ap_object(payload, "inbox")
|
||||
_save_ap_object(ap_actor, "actor")
|
||||
if "STUB" == payload["type"]:
|
||||
send_note("STUB")
|
||||
|
||||
|
||||
def _save_ap_object(
|
||||
ap_object: dict,
|
||||
path: str,
|
||||
):
|
||||
file_name = hash(ap_object["id"])
|
||||
with open(f"data/{path}/{file_name}.json", 'w') as f:
|
||||
json.dump(ap_object, f)
|
||||
|
||||
|
||||
def _send_accept(
|
||||
ap_object,
|
||||
inbox_url: str,
|
||||
) -> None :
|
||||
try:
|
||||
payload = {
|
||||
"@context": ap.AS_CTX,
|
||||
"id": f"{BASE_URL}/" + str(uuid.uuid4()),
|
||||
"type": "Accept",
|
||||
"actor": ap.ME["id"],
|
||||
"object": ap_object["id"],
|
||||
}
|
||||
_save_ap_object(payload, "outbox")
|
||||
|
||||
ap.post(inbox_url, payload)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
|
||||
def send_note(
|
||||
content: str,
|
||||
):
|
||||
"""Send Note!"""
|
||||
published = dtime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")
|
||||
|
||||
to = []
|
||||
cc = []
|
||||
|
||||
to = [ap.AS_PUBLIC]
|
||||
cc = [f"{BASE_URL}/followers"]
|
||||
object_id = f"{BASE_URL}/" + str(uuid.uuid4())
|
||||
|
||||
ap_object = {
|
||||
"@context": ap.AS_EXTENDED_CTX,
|
||||
"type": "Note",
|
||||
"id": object_id,
|
||||
"attributedTo": ID,
|
||||
"content": content,
|
||||
"to": to,
|
||||
"cc": cc,
|
||||
"published": published,
|
||||
"url": object_id,
|
||||
"tag": [],
|
||||
"summary": None,
|
||||
"inReplyTo": None,
|
||||
"sensitive": False,
|
||||
"attachment": [],
|
||||
}
|
||||
|
||||
recipients = _compute_recipients()
|
||||
ap_object = _wrap_ap_object(ap_object)
|
||||
|
||||
|
||||
for inbox_url in recipients:
|
||||
ap.post(
|
||||
inbox_url,
|
||||
ap_object,
|
||||
)
|
||||
|
||||
|
||||
def _compute_recipients() -> set[str]:
|
||||
recipients = set()
|
||||
filelist = []
|
||||
path = os.getcwd()
|
||||
for root, _, files in os.walk(path + '/data/actor'):
|
||||
for name in files :
|
||||
filelist.append(os.path.join(root, name))
|
||||
|
||||
for filename in filelist:
|
||||
if filename.endswith('.json'):
|
||||
with open(filename, 'r') as f:
|
||||
ap_actor = json.load(f)
|
||||
inbox_url = ap_actor.get("endpoints", {}).get("sharedInbox") \
|
||||
or ap_actor.get("inbox")
|
||||
recipients.add(inbox_url)
|
||||
|
||||
return recipients
|
||||
|
||||
|
||||
def _wrap_ap_object(ap_object: dict) -> dict:
|
||||
if ap_object["type"] in ["Note"]:
|
||||
|
||||
if "@context" in ap_object:
|
||||
del ap_object["@context"]
|
||||
|
||||
return {
|
||||
"@context": ap.AS_EXTENDED_CTX,
|
||||
"actor": ID,
|
||||
"to": ap_object.get("to", []),
|
||||
"cc": ap_object.get("cc", []),
|
||||
"id": ap_object["id"] + "/activity",
|
||||
"object": ap_object,
|
||||
"published": ap_object["published"],
|
||||
"type": "Create",
|
||||
}
|
||||
|
||||
return ap_object
|
Loading…
Reference in a new issue