GeopJr / Tuba

Browse the Fediverse
https://tuba.geopjr.dev/
GNU General Public License v3.0
503 stars 55 forks source link

feat(Notifications): requests #968

Closed GeopJr closed 1 month ago

GeopJr commented 1 month ago

Mastodon 4.3 introduced notification requests / junk. Users set a policy for rejecting notifications, like if the actor is a new account or doesn't follow you etc. and when they send you a notification, it ends up in a dedicated space where you can see them, dismiss them or accept them.

This PR adds the whole feature: Dedicated space for them, approving/declining and policy settings


This is undocumented so far, but I did write the spec to keep track of it myself, in case any other fellow fedidevs need it:

Policy Entity

Attributes:

Whether you are filtering people you don't follow

Whether you are filtering people that do not follow you

Whether you are filtering accounts created the past 30 days

Whether you are filtering private mentions unless the author is replying to you or you follow them

Stats of the filter inbox

Summary Entity

One account can send you multiple filtered notifications, so they don't always match.

Attributes

Amount of filter accounts

Amount of filtered notifications

Request Entity

Attributes:

Request ID

DateTime of the request creation

DateTime of the request update (this is not null if the request hasn't been updated, but it will match created_at)

The amount of notifications the request includes (remember, 1 request = 1 user but >= 1 notifications). This is a string cast from an int, e.g. "2"

The account that made the request

I assume this is option but haven't done a thorough test. The last status attached to the request.

GET /api/v1/notifications/policy

Call this when you need to check if there's any filtered notifications or get the active policies.

Returns: PolicyEntity

Example:

{
  "filter_not_following": true,
  "filter_not_followers": true,
  "filter_new_accounts": true,
  "filter_private_mentions": true,
  "summary": {
    "pending_requests_count": 1,
    "pending_notifications_count": 2
  }
}

PUT /api/v1/notifications/policy

Update policies.

Returns: PolicyEntity

Params:

Example:

{
  "filter_not_following": false
}

GET /api/v1/notifications/requests

Get the 'filtered notifications' inbox aka requests. This is a timeline, so the usual query params are available.

Returns: RequestEntity[]

Example:

[
  {
    "id": "112537648409652955",
    "created_at": "2024-05-31T20:43:58.699Z",
    "updated_at": "2024-05-31T20:43:58.699Z",
    "notifications_count": "2",
    "account": {
      "id": "112537647853644195",
      "username": "agent1y278390812",
      "acct": "agent1y278390812@mastodon.online",
      "display_name": "agent12973y29138",
      "locked": false,
      "bot": false,
      "discoverable": false,
      "indexable": false,
      "group": false,
      "created_at": "2023-02-17T00:00:00.000Z",
      "note": "",
      "url": "https://mastodon.online/@agent1y278390812",
      "uri": "https://mastodon.online/users/agent1y278390812",
      "avatar": "https://mastodon.social/avatars/original/missing.png",
      "avatar_static": "https://mastodon.social/avatars/original/missing.png",
      "header": "https://mastodon.social/headers/original/missing.png",
      "header_static": "https://mastodon.social/headers/original/missing.png",
      "followers_count": 1,
      "following_count": 2,
      "statuses_count": 10,
      "last_status_at": null,
      "hide_collections": false,
      "emojis": [],
      "fields": []
    },
    "last_status": {
      "id": "112537648329693223",
      "created_at": "2024-05-31T20:43:56.000Z",
      "in_reply_to_id": null,
      "in_reply_to_account_id": null,
      "sensitive": false,
      "spoiler_text": "",
      "visibility": "direct",
      "language": "en",
      "uri": "https://mastodon.online/users/agent1y278390812/statuses/112537648261061944",
      "url": "https://mastodon.online/@agent1y278390812/112537648261061944",
      "replies_count": 0,
      "reblogs_count": 0,
      "favourites_count": 0,
      "edited_at": null,
      "favourited": false,
      "reblogged": false,
      "muted": false,
      "bookmarked": false,
      "content": "<p>hi <span class=\"h-card\" translate=\"no\"><a href=\"https://mastodon.social/@agenthsudabbuwiadn\" class=\"u-url mention\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">@<span>agenthsudabbuwiadn</span></a></span></p>",
      "filtered": [],
      "reblog": null,
      "account": {
        "id": "112537647853644195",
        "username": "agent1y278390812",
        "acct": "agent1y278390812@mastodon.online",
        "display_name": "agent12973y29138",
        "locked": false,
        "bot": false,
        "discoverable": false,
        "indexable": false,
        "group": false,
        "created_at": "2023-02-17T00:00:00.000Z",
        "note": "",
        "url": "https://mastodon.online/@agent1y278390812",
        "uri": "https://mastodon.online/users/agent1y278390812",
        "avatar": "https://mastodon.social/avatars/original/missing.png",
        "avatar_static": "https://mastodon.social/avatars/original/missing.png",
        "header": "https://mastodon.social/headers/original/missing.png",
        "header_static": "https://mastodon.social/headers/original/missing.png",
        "followers_count": 1,
        "following_count": 2,
        "statuses_count": 10,
        "last_status_at": null,
        "hide_collections": false,
        "emojis": [],
        "fields": []
      },
      "media_attachments": [],
      "mentions": [
        {
          "id": "110371061354627964",
          "username": "agenthsudabbuwiadn",
          "url": "https://mastodon.social/@agenthsudabbuwiadn",
          "acct": "agenthsudabbuwiadn"
        }
      ],
      "tags": [],
      "emojis": [],
      "card": null,
      "poll": null
    }
  }
]

POST /api/v1/notifications/requests/<id>/accept

Accept a request. There's no error if the request has already been accepted.

Returns: {}

Query Params:

The request ID you are accepting.

POST /api/v1/notifications/requests/<id>/dismiss

Dismiss a request. There's no error if the request has already been dismissed.

Returns: {}

Query Params:

The request ID you are dismissing.