[feat] process inbox request

This commit is contained in:
SouthFox 2023-07-28 01:20:56 +08:00
parent 4497fb646f
commit 03af5cedb7
2 changed files with 139 additions and 0 deletions

2
app.py
View file

@ -5,6 +5,7 @@ import sys
from flask import Flask, Response, request, Request, abort, jsonify from flask import Flask, Response, request, Request, abort, jsonify
from loguru import logger from loguru import logger
from demo.boxes import process_inbox
from demo.utils.checker import inbox_prechecker from demo.utils.checker import inbox_prechecker
from demo.activitypub import ME from demo.activitypub import ME
@ -43,6 +44,7 @@ def inbox():
"""Process inbox request""" """Process inbox request"""
is_verify = inbox_prechecker(request) is_verify = inbox_prechecker(request)
if is_verify: if is_verify:
process_inbox(request.json)
return "STUB", 202 return "STUB", 202
abort(401) abort(401)

137
demo/boxes.py Normal file
View 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