diff --git a/app/boxes.py b/app/boxes.py index 6a941d6..6c76956 100644 --- a/app/boxes.py +++ b/app/boxes.py @@ -438,6 +438,9 @@ async def _send_create( elif visibility == ap.VisibilityEnum.UNLISTED: to = [f"{BASE_URL}/followers"] cc = [ap.AS_PUBLIC] + elif visibility == ap.VisibilityEnum.FOLLOWERS_ONLY: + to = [f"{BASE_URL}/followers"] + cc = [] else: raise ValueError(f"Unsupport visibility {visibility}") diff --git a/app/hysql.hy b/app/hysql.hy index e618faa..5d11d9a 100644 --- a/app/hysql.hy +++ b/app/hysql.hy @@ -2,6 +2,7 @@ (import app [models]) (import app.database [async_session]) (import sqlalchemy [select]) +(import app.activitypub [VisibilityEnum]) (import pprint [pprint]) @@ -10,3 +11,12 @@ (.all (await (.scalars db (.where (select models.InboxObject) (= models.InboxObject.ap_type ap_type)))))) + + +(defn/a get_index_status + [db] + (.all (await + (.scalars db + (.where (select models.OutboxObject) + (.in_ models.OutboxObject.visibility [VisibilityEnum.PUBLIC VisibilityEnum.UNLISTED]) + (.is_ models.OutboxObject.is_deleted False)))))) diff --git a/app/main.py b/app/main.py index cfa477f..b9acd2b 100644 --- a/app/main.py +++ b/app/main.py @@ -30,6 +30,7 @@ from app.boxes import save_incoming from app.activitypub import VisibilityEnum from app.boxes import _send_create from app.orgpython import to_html +from app.hysql import get_index_status def _check_0rtt_early_data(request: Request) -> None: @@ -81,16 +82,7 @@ async def index( if is_ap_requested(request): return ActivityPubResponse(ME) - statues = ( - await db_session.scalars( - select(models.OutboxObject) - .where( - models.OutboxObject.ap_type == "Note", - models.OutboxObject.is_deleted.is_(False), - ) - .order_by(models.OutboxObject.created_at.desc()) - ) - ).all() + statues = await get_index_status(db_session) return templates.TemplateResponse( request, diff --git a/tests/test_main.py b/tests/test_main.py index 0db7cfa..f530cc5 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 import pytest +import httpx +import respx from fastapi.testclient import TestClient from sqlalchemy.orm import Session from app import activitypub as ap from app.config import AP_CONTENT_TYPE +from tests.utils import build_remote_actor _ACCEPTED_AP_HEADERS = [ @@ -26,3 +29,33 @@ def test_index__ap(db: Session, client: TestClient, accept: str): assert response.status_code == 200 assert response.headers["content-type"] == AP_CONTENT_TYPE assert response.json() == ap.ME + + + +@pytest.mark.asyncio +async def test_follow_only_status( + 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)) + + + response = client.post( + "/outbox", + headers={"Authorization": "Basic test-token"}, + content='{"visibility": "followers-only","content": "note content"}' + ) + + assert response.status_code == 200 + # And the Note was not show in the index + + indext_content = client.get("/").text + assert "note content" not in indext_content