Add endpoint to get notification by id (#594)
This commit is contained in:
parent
82a9c18205
commit
542e3836af
|
@ -76,6 +76,7 @@ urlpatterns = [
|
||||||
path("v1/statuses/<id>/source", statuses.status_source),
|
path("v1/statuses/<id>/source", statuses.status_source),
|
||||||
# Notifications
|
# Notifications
|
||||||
path("v1/notifications", notifications.notifications),
|
path("v1/notifications", notifications.notifications),
|
||||||
|
path("v1/notifications/<id>", notifications.get_notification),
|
||||||
# Polls
|
# Polls
|
||||||
path("v1/polls/<id>", polls.get_poll),
|
path("v1/polls/<id>", polls.get_poll),
|
||||||
path("v1/polls/<id>/votes", polls.vote_poll),
|
path("v1/polls/<id>/votes", polls.vote_poll),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from hatchway import ApiResponse, api_view
|
from hatchway import ApiResponse, api_view
|
||||||
|
|
||||||
from activities.models import TimelineEvent
|
from activities.models import TimelineEvent
|
||||||
|
@ -7,6 +8,15 @@ from api import schemas
|
||||||
from api.decorators import scope_required
|
from api.decorators import scope_required
|
||||||
from api.pagination import MastodonPaginator, PaginatingApiResponse, PaginationResult
|
from api.pagination import MastodonPaginator, PaginatingApiResponse, PaginationResult
|
||||||
|
|
||||||
|
# Types/exclude_types use weird syntax so we have to handle them manually
|
||||||
|
NOTIFICATION_TYPES = {
|
||||||
|
"favourite": TimelineEvent.Types.liked,
|
||||||
|
"reblog": TimelineEvent.Types.boosted,
|
||||||
|
"mention": TimelineEvent.Types.mentioned,
|
||||||
|
"follow": TimelineEvent.Types.followed,
|
||||||
|
"admin.sign_up": TimelineEvent.Types.identity_created,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@scope_required("read:notifications")
|
@scope_required("read:notifications")
|
||||||
@api_view.get
|
@api_view.get
|
||||||
|
@ -18,22 +28,14 @@ def notifications(
|
||||||
limit: int = 20,
|
limit: int = 20,
|
||||||
account_id: str | None = None,
|
account_id: str | None = None,
|
||||||
) -> ApiResponse[list[schemas.Notification]]:
|
) -> ApiResponse[list[schemas.Notification]]:
|
||||||
# Types/exclude_types use weird syntax so we have to handle them manually
|
|
||||||
base_types = {
|
|
||||||
"favourite": TimelineEvent.Types.liked,
|
|
||||||
"reblog": TimelineEvent.Types.boosted,
|
|
||||||
"mention": TimelineEvent.Types.mentioned,
|
|
||||||
"follow": TimelineEvent.Types.followed,
|
|
||||||
"admin.sign_up": TimelineEvent.Types.identity_created,
|
|
||||||
}
|
|
||||||
requested_types = set(request.GET.getlist("types[]"))
|
requested_types = set(request.GET.getlist("types[]"))
|
||||||
excluded_types = set(request.GET.getlist("exclude_types[]"))
|
excluded_types = set(request.GET.getlist("exclude_types[]"))
|
||||||
if not requested_types:
|
if not requested_types:
|
||||||
requested_types = set(base_types.keys())
|
requested_types = set(NOTIFICATION_TYPES.keys())
|
||||||
requested_types.difference_update(excluded_types)
|
requested_types.difference_update(excluded_types)
|
||||||
# Use that to pull relevant events
|
# Use that to pull relevant events
|
||||||
queryset = TimelineService(request.identity).notifications(
|
queryset = TimelineService(request.identity).notifications(
|
||||||
[base_types[r] for r in requested_types if r in base_types]
|
[NOTIFICATION_TYPES[r] for r in requested_types if r in NOTIFICATION_TYPES]
|
||||||
)
|
)
|
||||||
paginator = MastodonPaginator()
|
paginator = MastodonPaginator()
|
||||||
pager: PaginationResult[TimelineEvent] = paginator.paginate(
|
pager: PaginationResult[TimelineEvent] = paginator.paginate(
|
||||||
|
@ -48,3 +50,18 @@ def notifications(
|
||||||
request=request,
|
request=request,
|
||||||
include_params=["limit", "account_id"],
|
include_params=["limit", "account_id"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@scope_required("read:notifications")
|
||||||
|
@api_view.get
|
||||||
|
def get_notification(
|
||||||
|
request: HttpRequest,
|
||||||
|
id: str,
|
||||||
|
) -> schemas.Notification:
|
||||||
|
notification = get_object_or_404(
|
||||||
|
TimelineService(request.identity).notifications(
|
||||||
|
list(NOTIFICATION_TYPES.values())
|
||||||
|
),
|
||||||
|
id=id,
|
||||||
|
)
|
||||||
|
return schemas.Notification.from_timeline_event(notification)
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from activities.models import TimelineEvent
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_notifications(api_client, identity, remote_identity):
|
||||||
|
event = TimelineEvent.objects.create(
|
||||||
|
identity=identity,
|
||||||
|
type=TimelineEvent.Types.followed,
|
||||||
|
subject_identity=remote_identity,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = api_client.get("/api/v1/notifications").json()
|
||||||
|
|
||||||
|
assert len(response) == 1
|
||||||
|
assert response[0]["type"] == "follow"
|
||||||
|
assert response[0]["account"]["id"] == str(remote_identity.id)
|
||||||
|
|
||||||
|
event.delete()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_get_notification(api_client, identity, remote_identity):
|
||||||
|
event = TimelineEvent.objects.create(
|
||||||
|
identity=identity,
|
||||||
|
type=TimelineEvent.Types.followed,
|
||||||
|
subject_identity=remote_identity,
|
||||||
|
)
|
||||||
|
|
||||||
|
response = api_client.get(f"/api/v1/notifications/{event.id}").json()
|
||||||
|
assert response["type"] == "follow"
|
||||||
|
assert response["account"]["id"] == str(remote_identity.id)
|
||||||
|
|
||||||
|
event.delete()
|
Loading…
Reference in New Issue