22import logging
33import os
44import sys
5+ import uuid
56
67from cryptography .hazmat .primitives import serialization as crypto_serialization
7- from cryptography .hazmat .primitives .asymmetric import rsa
8+ from cryptography .hazmat .primitives .asymmetric import ed25519 , rsa
89from fastapi import Request , Response
910from fastapi .responses import JSONResponse
1011
11- from apkit .client import WebfingerLink , WebfingerResource , WebfingerResult
12- from apkit .client .asyncio .client import ActivityPubClient
12+ from apkit .client import (
13+ ActivityPubClient ,
14+ WebfingerLink ,
15+ WebfingerResource ,
16+ WebfingerResult ,
17+ )
1318from apkit .models import (
1419 Actor as APKitActor ,
1520)
8388actor = Person (
8489 id = f"https://{ HOST } /users/{ USER_ID } " ,
8590 name = "apkit Demo" ,
86- preferredUsername = "demo" ,
91+ preferred_username = "demo" ,
8792 summary = "This is a demo actor powered by apkit!" ,
8893 inbox = f"https://{ HOST } /users/{ USER_ID } /inbox" ,
8994 outbox = f"https://{ HOST } /users/{ USER_ID } /outbox" ,
90- publicKey = CryptographicKey (
95+ public_key = CryptographicKey (
9196 id = f"https://{ HOST } /users/{ USER_ID } #main-key" ,
9297 owner = f"https://{ HOST } /users/{ USER_ID } " ,
93- publicKeyPem = public_key_pem ,
98+ public_key_pem = public_key_pem ,
9499 ),
95100)
96101
102+
97103# --- Server Initialization ---
98104app = ActivityPubServer ()
99105
100106
101107# --- Key Retrieval Function ---
102108# This function provides the private key for signing outgoing activities.
103109def get_keys_for_actor (identifier : str ) -> list [ActorKey ]:
104- if identifier == USER_ID :
105- return [ActorKey (key_id = actor .publicKey .id , private_key = private_key )]
110+ if not actor .public_key :
111+ raise ValueError ("PublicKey not found." )
112+ if not isinstance (private_key , rsa .RSAPrivateKey ) and not isinstance (
113+ private_key , ed25519 .Ed25519PrivateKey
114+ ):
115+ raise ValueError ("Invalid Key" )
116+ if identifier == USER_ID and actor .public_key .id :
117+ return [ActorKey (key_id = actor .public_key .id , private_key = private_key )]
106118 return []
107119
108120
@@ -177,7 +189,7 @@ async def outbox(ctx: Context):
177189
178190 if not ctx .request .query_params .get ("page" ):
179191 outbox = OrderedCollection ()
180- outbox .totalItems = 0 # No letter in the mail today.
192+ outbox .total_items = 0 # No letter in the mail today.
181193 outbox .id = f"https://{ HOST } /users/{ identifier } /outbox"
182194 outbox .first = f"{ outbox .id } ?page=true"
183195 outbox .last = f"{ outbox .id } ?min_id=0&page=true"
@@ -202,15 +214,15 @@ async def on_follow_activity(ctx: Context) -> Response:
202214 elif isinstance (activity .actor , APKitActor ):
203215 follower_actor = activity .actor
204216
205- if not follower_actor :
217+ if not follower_actor or not isinstance ( follower_actor , APKitActor ) :
206218 return JSONResponse (
207219 {"error" : "Could not resolve follower actor" }, status_code = 400
208220 )
209221
210222 logger .info (f"🫂 { follower_actor .name } follows me." )
211223
212224 # Automatically accept the follow request
213- id_ = "https://{HOST}/activity/{uuid.uuid4()}"
225+ id_ = f "https://{ HOST } /activity/{ uuid .uuid4 ()} "
214226 accept_activity = activity .accept (id_ , actor )
215227
216228 # Send the signed Accept activity back to the follower's inbox
0 commit comments