From c97581278dd98d61eb6609dd6a3cc53f89962f29 Mon Sep 17 00:00:00 2001 From: SouthFox Date: Mon, 4 Mar 2024 20:57:57 +0800 Subject: [PATCH] [feat] support unlisted visibility note --- app/boxes.py | 3 +++ app/main.py | 11 +++++------ data/tests.toml | 2 ++ tests/test_outbox.py | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/app/boxes.py b/app/boxes.py index efa2e5b..f40eb65 100644 --- a/app/boxes.py +++ b/app/boxes.py @@ -435,6 +435,9 @@ async def _send_create( if visibility == ap.VisibilityEnum.PUBLIC: to = [ap.AS_PUBLIC] cc = [f"{BASE_URL}/followers"] + elif visibility == ap.VisibilityEnum.UNLISTED: + to = [f"{BASE_URL}/followers"] + cc = [ap.AS_PUBLIC] else: raise ValueError(f"Unsupport visibility {visibility}") diff --git a/app/main.py b/app/main.py index 3c75f57..cfa477f 100644 --- a/app/main.py +++ b/app/main.py @@ -126,9 +126,8 @@ async def outbox( db_session: AsyncSession = Depends(get_db_session), ) -> Response: """ActivityPub outbox endpoint, now only process client post request.""" - payload = await request.body() - content = payload.decode("utf-8") - logger.info(content) + payload = await request.json() + logger.info(payload) post_token = request.headers.get("Authorization") def _check_post_token() -> bool: @@ -144,13 +143,13 @@ async def outbox( return Response(status_code=406) logger.info("True token") - content = to_html(content).replace("\n", "") + note_content = to_html(payload["content"]).replace("\n", "") await _send_create( db_session, "Note", - content, - VisibilityEnum.PUBLIC + note_content, + payload["visibility"] ) return Response(status_code=200) diff --git a/data/tests.toml b/data/tests.toml index aed5e8e..abeb19b 100644 --- a/data/tests.toml +++ b/data/tests.toml @@ -10,3 +10,5 @@ debug = true # In-mem DB sqlalchemy_database = "file:pytest?mode=memory&cache=shared&uri=true" + +post_token = "test-token" diff --git a/tests/test_outbox.py b/tests/test_outbox.py index c72a153..06dedda 100644 --- a/tests/test_outbox.py +++ b/tests/test_outbox.py @@ -155,3 +155,36 @@ async def test_outbox_send_create_activity( outbox_object = db.execute(select(models.OutboxObject)).scalar_one() assert outbox_object.ap_type == "Note" assert outbox_object.ap_object["content"] == content + + +@pytest.mark.asyncio +async def test_outbox_send_unlisted_note( + db: Session, + async_db_session, + client: TestClient, + respx_mock: respx.MockRouter, +) -> None: + # build test actor + ra = build_remote_actor() + remote_ap_id = ra.ap_id # type: ignore + + # mock request + respx_mock.get(remote_ap_id).mock( + return_value=httpx.Response(200,json=ra.ap_actor)) + respx_mock.post(remote_ap_id + "/inbox").mock( + return_value=httpx.Response(202)) + + from app.activitypub import VisibilityEnum + + + response = client.post( + "/outbox", + headers={"Authorization": "Basic test-token"}, + content='{"visibility": "unlisted","content": "note content"}' + ) + + assert response.status_code == 200 + # And the Follow activity was created in the outbox + outbox_object = db.execute(select(models.OutboxObject)).scalar_one() + assert outbox_object.ap_type == "Note" + assert outbox_object.visibility == VisibilityEnum.UNLISTED