[feat] return real actor activitypub+json
This commit is contained in:
parent
54db6c3065
commit
a8aa5105ab
5 changed files with 73 additions and 17 deletions
14
app.py
14
app.py
|
@ -1,11 +1,14 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Creatr App"""
|
"""Creatr App"""
|
||||||
from flask import Flask, Response, request, Request, abort, jsonify
|
from flask import Flask, Response, request, Request, abort, jsonify
|
||||||
|
|
||||||
from demo.utils.checker import inbox_prechecker
|
from demo.utils.checker import inbox_prechecker
|
||||||
|
from demo.activitypub import ME
|
||||||
from demo import config
|
from demo import config
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__,
|
||||||
|
static_folder="demo/static",)
|
||||||
|
|
||||||
def is_ap_requested(ap_request: Request) -> bool:
|
def is_ap_requested(ap_request: Request) -> bool:
|
||||||
"""Check request accept headers."""
|
"""Check request accept headers."""
|
||||||
|
@ -100,3 +103,12 @@ def wellknown_webfinger() -> Response:
|
||||||
resp.headers["Content-Type"] = "application/jrd+json; charset=utf-8"
|
resp.headers["Content-Type"] = "application/jrd+json; charset=utf-8"
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
@app.route(f"/meow/{config.USERNAME}")
|
||||||
|
def locate_user() -> Response:
|
||||||
|
"""Return user ActivityPub response."""
|
||||||
|
resp = jsonify(ME)
|
||||||
|
resp.headers["Content-Type"] = "application/activity+json"
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
|
@ -2,6 +2,61 @@
|
||||||
"""ActivityPub settings, fetch & post"""
|
"""ActivityPub settings, fetch & post"""
|
||||||
import httpx
|
import httpx
|
||||||
from demo import config
|
from demo import config
|
||||||
|
from demo.utils.key import get_pubkey_as_pem
|
||||||
|
|
||||||
|
|
||||||
|
AS_CTX = "https://www.w3.org/ns/activitystreams"
|
||||||
|
AS_PUBLIC = "https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
|
||||||
|
AS_EXTENDED_CTX = [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
# AS ext
|
||||||
|
"Hashtag": "as:Hashtag",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||||
|
"alsoKnownAs": {"@id": "as:alsoKnownAs", "@type": "@id"},
|
||||||
|
"movedTo": {"@id": "as:movedTo", "@type": "@id"},
|
||||||
|
# toot
|
||||||
|
"toot": "http://joinmastodon.org/ns#",
|
||||||
|
"featured": {"@id": "toot:featured", "@type": "@id"},
|
||||||
|
"Emoji": "toot:Emoji",
|
||||||
|
"blurhash": "toot:blurhash",
|
||||||
|
"votersCount": "toot:votersCount",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
ME = {
|
||||||
|
"@context": AS_EXTENDED_CTX,
|
||||||
|
"type": "Person",
|
||||||
|
"id": config.ID,
|
||||||
|
"following": config.BASE_URL + "/following",
|
||||||
|
"followers": config.BASE_URL + "/followers",
|
||||||
|
"featured": config.BASE_URL + "/featured",
|
||||||
|
"inbox": config.BASE_URL + "/inbox",
|
||||||
|
"outbox": config.BASE_URL + "/outbox",
|
||||||
|
"preferredUsername": config.USERNAME,
|
||||||
|
"name": config.NICKNAME,
|
||||||
|
"summary": config.ACTOR_SUMMARY,
|
||||||
|
"endpoints": {
|
||||||
|
"sharedInbox": config.BASE_URL + "/inbox",
|
||||||
|
},
|
||||||
|
"url": config.ID + "/", # the path is important for Mastodon compat
|
||||||
|
"manuallyApprovesFollowers": False,
|
||||||
|
"attachment": [],
|
||||||
|
"icon": {
|
||||||
|
"mediaType": "image/png",
|
||||||
|
"type": "Image",
|
||||||
|
"url": config.AVATAR_URL,
|
||||||
|
},
|
||||||
|
"publicKey": {
|
||||||
|
"id": f"{config.ID}#main-key",
|
||||||
|
"owner": config.ID,
|
||||||
|
"publicKeyPem": get_pubkey_as_pem(config.KEY_PATH),
|
||||||
|
},
|
||||||
|
"tag": [] # TODO tag support
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def fetch(
|
def fetch(
|
||||||
|
|
|
@ -7,8 +7,11 @@ KEY_PATH = _ROOT_DIR / "data" / "key.pem"
|
||||||
USER_AGENT = "COSCUP-demo"
|
USER_AGENT = "COSCUP-demo"
|
||||||
AP_CONTENT_TYPE = "application/activity+json"
|
AP_CONTENT_TYPE = "application/activity+json"
|
||||||
|
|
||||||
|
ACTOR_SUMMARY = "I'm banana"
|
||||||
USERNAME = "foo"
|
USERNAME = "foo"
|
||||||
DOMAIN = "localhost"
|
NICKNAME = "foo"
|
||||||
SCHEME = "http"
|
SCHEME = "http"
|
||||||
|
DOMAIN = "localhost"
|
||||||
|
BASE_URL = f"{SCHEME}://{DOMAIN}"
|
||||||
ID = f"{SCHEME}://{DOMAIN}/user/{USERNAME}"
|
ID = f"{SCHEME}://{DOMAIN}/user/{USERNAME}"
|
||||||
BASE_URL = f"{SCHEME}://{DOMAIN}/"
|
AVATAR_URL = f"{BASE_URL}/static/avatar.png"
|
||||||
|
|
BIN
demo/static/avatar.png
Normal file
BIN
demo/static/avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
|
@ -1,8 +1,5 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""process Key."""
|
"""process Key."""
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
from demo.config import KEY_PATH
|
from demo.config import KEY_PATH
|
||||||
|
@ -12,14 +9,3 @@ def get_pubkey_as_pem(key_path: Path) -> str:
|
||||||
"""Exporting public key from private key file."""
|
"""Exporting public key from private key file."""
|
||||||
text = key_path.read_text()
|
text = key_path.read_text()
|
||||||
return RSA.import_key(text).public_key().export_key("PEM").decode("utf-8")
|
return RSA.import_key(text).public_key().export_key("PEM").decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def gen_key():
|
|
||||||
"""Generate key."""
|
|
||||||
if KEY_PATH.exists():
|
|
||||||
print("is existing!")
|
|
||||||
sys.exit(2)
|
|
||||||
else:
|
|
||||||
k = RSA.generate(2048)
|
|
||||||
privkey_pem = k.exportKey("PEM").decode("utf-8")
|
|
||||||
KEY_PATH.write_text(privkey_pem)
|
|
||||||
|
|
Loading…
Reference in a new issue