[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 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
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