diff --git a/packages/pl-api/lib/client.ts b/packages/pl-api/lib/client.ts index 5fa25d3bf..8039639c4 100644 --- a/packages/pl-api/lib/client.ts +++ b/packages/pl-api/lib/client.ts @@ -2649,6 +2649,44 @@ class PlApiClient { return response.json as {}; }, + /** + * Accept multiple notification requests + * Accepts multiple notification requests, which merges the filtered notifications from those users back into the main notifications and accepts any future notification from them. + * @see {@link https://docs.joinmastodon.org/methods/notifications/#accept-multiple-requests} + * Requires features{@link Features['notificationsRequestsAcceptMultiple']}. + */ + acceptMultipleNotificationRequests: async (notificationRequestIds: Array) => { + const response = await this.request('/api/v1/notifications/requests/accept', { method: 'POST', body: { id: notificationRequestIds } }); + + return response.json as {}; + }, + + /** + * Dismiss multiple notification requests + * Dismiss multiple notification requests, which hides them and prevent them from contributing to the pending notification requests count. + * @see {@link https://docs.joinmastodon.org/methods/notifications/#dismiss-multiple-requests} + * Requires features{@link Features['notificationsRequestsAcceptMultiple']}. + */ + dismissMultipleNotificationRequests: async (notificationRequestIds: Array) => { + const response = await this.request('/api/v1/notifications/requests/dismiss', { method: 'POST', body: { id: notificationRequestIds } }); + + return response.json as {}; + }, + + /** + * Check if accepted notification requests have been merged + * Check whether accepted notification requests have been merged. Accepting notification requests schedules a background job to merge the filtered notifications back into the normal notification list. When that process has finished, the client should refresh the notifications list at its earliest convenience. This is communicated by the `notifications_merged` streaming event but can also be polled using this endpoint. + * @see {@link https://docs.joinmastodon.org/methods/notifications/#requests-merged} + * Requires features{@link Features['notificationsRequestsAcceptMultiple']}. + */ + checkNotificationRequestsMerged: async () => { + const response = await this.request('/api/v1/notifications/requests/merged'); + + return v.parse(v.object({ + merged: v.boolean(), + }), response.json); + }, + /** * An endpoint to delete multiple statuses by IDs. * @@ -2663,6 +2701,8 @@ class PlApiClient { return response.json as {}; }, + + }; public readonly pushNotifications = { diff --git a/packages/pl-api/lib/entities/application.ts b/packages/pl-api/lib/entities/application.ts index 046cce016..333c9ccd5 100644 --- a/packages/pl-api/lib/entities/application.ts +++ b/packages/pl-api/lib/entities/application.ts @@ -1,21 +1,29 @@ import * as v from 'valibot'; +import { filteredArray } from './utils'; + /** * @category Schemas * @see {@link https://docs.joinmastodon.org/entities/Application/} */ -const applicationSchema = v.object({ +const applicationSchema = v.pipe(v.any(), v.transform((application) => ({ + redirect_uris: [application.redirect_uri], + ...application, +})), v.object({ name: v.fallback(v.string(), ''), website: v.fallback(v.optional(v.string()), undefined), client_id: v.fallback(v.optional(v.string()), undefined), client_secret: v.fallback(v.optional(v.string()), undefined), - redirect_uri: v.fallback(v.optional(v.string()), undefined), + client_secret_expires_at: v.fallback(v.optional(v.string()), undefined), + redirect_uris: filteredArray(v.string()), id: v.fallback(v.optional(v.string()), undefined), + /** @deprecated */ + redirect_uri: v.fallback(v.optional(v.string()), undefined), /** @deprecated */ vapid_key: v.fallback(v.optional(v.string()), undefined), -}); +})); type Application = v.InferOutput; diff --git a/packages/pl-api/lib/entities/preview-card-author.ts b/packages/pl-api/lib/entities/preview-card-author.ts new file mode 100644 index 000000000..000ce3783 --- /dev/null +++ b/packages/pl-api/lib/entities/preview-card-author.ts @@ -0,0 +1,17 @@ +import * as v from 'valibot'; + +import { accountSchema } from './account'; + +/** + * @category Schemas + * @see {@link https://docs.joinmastodon.org/entities/PreviewCardAuthor/} + */ +const previewCardAuthorSchema = v.object({ + name: v.string(), + url: v.pipe(v.string(), v.url()), + account: v.fallback(v.nullable(accountSchema), null), +}); + +type PreviewCardAuthor = v.InferOutput; + +export { previewCardAuthorSchema, type PreviewCardAuthor }; diff --git a/packages/pl-api/lib/entities/preview-card.ts b/packages/pl-api/lib/entities/preview-card.ts index 2a875d39e..aeab1c07b 100644 --- a/packages/pl-api/lib/entities/preview-card.ts +++ b/packages/pl-api/lib/entities/preview-card.ts @@ -1,12 +1,18 @@ import * as v from 'valibot'; +import { previewCardAuthorSchema } from './preview-card-author'; +import { filteredArray } from './utils'; + /** * @category Schemas * @see {@link https://docs.joinmastodon.org/entities/PreviewCard/} */ const previewCardSchema = v.object({ + /** @deprecated */ author_name: v.fallback(v.string(), ''), + /** @deprecated */ author_url: v.fallback(v.pipe(v.string(), v.url()), ''), + authors: filteredArray(previewCardAuthorSchema), blurhash: v.fallback(v.nullable(v.string()), null), description: v.fallback(v.string(), ''), embed_url: v.fallback(v.pipe(v.string(), v.url()), ''), diff --git a/packages/pl-api/lib/entities/streaming-event.ts b/packages/pl-api/lib/entities/streaming-event.ts index ab4c34024..8126c03cf 100644 --- a/packages/pl-api/lib/entities/streaming-event.ts +++ b/packages/pl-api/lib/entities/streaming-event.ts @@ -99,6 +99,11 @@ const markerStreamingEventSchema = v.object({ payload: v.pipe(v.any(), v.transform((payload: any) => JSON.parse(payload)), markersSchema), }); +const notificationsMergedEventSchema = v.object({ + ...baseStreamingEventSchema.entries, + event: v.literal('notifications_merged'), +}); + /** * @category Schemas * @see {@link https://docs.joinmastodon.org/methods/streaming/#events} @@ -121,6 +126,7 @@ const streamingEventSchema: v.BaseSchema; export { diff --git a/packages/pl-api/lib/features.ts b/packages/pl-api/lib/features.ts index 22ebf0e68..4998ff5bd 100644 --- a/packages/pl-api/lib/features.ts +++ b/packages/pl-api/lib/features.ts @@ -896,6 +896,12 @@ const getFeatures = (instance: Instance) => { */ notificationsPolicy: instance.api_versions.mastodon >= 1, + /** + * @see POST /api/v1/notifications/requests/accept + * @see POST /api/v1/notifications/requests/dismiss + */ + notificationsRequestsAcceptMultiple: instance.api_versions.mastodon >= 1, + pleromaAdminAccounts: v.software === PLEROMA, /** diff --git a/packages/pl-api/lib/params/accounts.ts b/packages/pl-api/lib/params/accounts.ts index 391febf0d..c3c58c216 100644 --- a/packages/pl-api/lib/params/accounts.ts +++ b/packages/pl-api/lib/params/accounts.ts @@ -37,7 +37,7 @@ interface FollowAccountParams { notify?: boolean; /** * Array of String (ISO 639-1 language two-letter code). Filter received statuses for these languages. If not provided, you will receive this account’s posts in all languages. - * Requires `features.followAccountLanguages`. + * Requires features{@link Features['followAccountLanguages']}. */ languages?: string[]; } diff --git a/packages/pl-api/lib/params/common.ts b/packages/pl-api/lib/params/common.ts index ed239f0cb..ab62db18f 100644 --- a/packages/pl-api/lib/params/common.ts +++ b/packages/pl-api/lib/params/common.ts @@ -13,7 +13,7 @@ interface WithMutedParam { /** * Boolean. Also show statuses from muted users. Default to false. * - * Requires `features.timelinesWithMuted`. + * Requires features{@link Features['timelinesWithMuted']}. */ with_muted?: boolean; } @@ -35,7 +35,7 @@ interface OnlyEventsParam { /** * Boolean. Filter out statuses without events. * - * Requires `features.events`. + * Requires features{@link Features['events']}. */ only_events?: boolean; } @@ -44,7 +44,7 @@ interface LanguageParam { /** * Fetch a translation in given language * - * Requires `features.fetchStatusesWithTranslation`. + * Requires features{@link Features['fetchStatusesWithTranslation']}. */ language?: string; } diff --git a/packages/pl-api/lib/params/my-account.ts b/packages/pl-api/lib/params/my-account.ts index d8edde5c4..039132e9c 100644 --- a/packages/pl-api/lib/params/my-account.ts +++ b/packages/pl-api/lib/params/my-account.ts @@ -6,7 +6,7 @@ import type { PaginationParams } from './common'; interface GetBookmarksParams extends PaginationParams { /** * Bookmark folder ID - * Requires `features.bookmarkFolders`. + * Requires features{@link Features['bookmarkFolders']}. */ folder_id?: string; } diff --git a/packages/pl-api/lib/params/notifications.ts b/packages/pl-api/lib/params/notifications.ts index 90125ebbc..b970d2ccb 100644 --- a/packages/pl-api/lib/params/notifications.ts +++ b/packages/pl-api/lib/params/notifications.ts @@ -10,9 +10,14 @@ interface GetNotificationParams extends PaginationParams { exclude_types?: string[]; /** Return only notifications received from the specified account. */ account_id?: string; + /** + * Whether to include notifications filtered by the user’s NotificationPolicy. Defaults to false. + * Requires features.{@link Features['notificationsPolicy']}. + */ + include_filtered?: boolean; /** * will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`). - * Requires `features.notificationsExcludeVisibilities`. + * Requires features{@link Features['notificationsExcludeVisibilities']}. */ exclude_visibilities?: string[]; } diff --git a/packages/pl-api/lib/params/settings.ts b/packages/pl-api/lib/params/settings.ts index 8b0f5432e..01e3f2a53 100644 --- a/packages/pl-api/lib/params/settings.ts +++ b/packages/pl-api/lib/params/settings.ts @@ -106,17 +106,18 @@ interface UpdateCredentialsParams { /** * Description of avatar image, for alt-text. - * Requires `features.accountAvatarDescription`. + * + * Requires features{@link Features['accountAvatarDescription']}. */ avatar_description?: boolean; /** * Description of header image, for alt-text. - * Requires `features.accountAvatarDescription`. + * Requires features{@link Features['accountAvatarDescription']}. */ header_description?: boolean; /** * Enable RSS feed for this account's Public posts at `/[username]/feed.rss` - * Requires `features.accountEnableRss`. + * Requires features{@link Features['accountEnableRss']}. */ enable_rss?: boolean; } diff --git a/packages/pl-api/lib/params/statuses.ts b/packages/pl-api/lib/params/statuses.ts index e83d71ed5..5e5bdb03f 100644 --- a/packages/pl-api/lib/params/statuses.ts +++ b/packages/pl-api/lib/params/statuses.ts @@ -46,8 +46,8 @@ interface CreateStatusOptionalParams { spoiler_text?: string; /** * String. Sets the visibility of the posted status to `public`, `unlisted`, `private`, `direct`. - * `local` — requires `features.createStatusLocalScope`. - * `list:LIST_ID` — requires `features.createStatusListScope`. + * `local` — Requires features{@link Features['createStatusLocalScope']}. + * `list:LIST_ID` — Requires features{@link Features['createStatusListScope']}. */ visibility?: string; /** String. ISO 639 language code for this status. */ @@ -57,7 +57,7 @@ interface CreateStatusOptionalParams { /** * boolean, if set to true the post won't be actually posted, but the status entity would still be rendered back. This could be useful for previewing rich text/custom emoji, for example. - * Requires `features.createStatusPreview`. + * Requires features{@link Features['createStatusPreview']}. */ preview?: boolean; /** @@ -66,22 +66,22 @@ interface CreateStatusOptionalParams { content_type?: string; /** * A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for post visibility are not affected by this and will still apply. - * Requires `features.createStatusExplicitAddressing`. + * Requires features{@link Features['createStatusExplicitAddressing']}. */ to?: string[]; /** * The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour. - * Requires `features.createStatusExpiration`. + * Requires features{@link Features['createStatusExpiration']}. */ expires_in?: number; /** * Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`. - * Requires `features.createStatusReplyToConversation`. + * Requires features{@link Features['createStatusReplyToConversation']}. */ in_reply_to_conversation_id?: string; /** * ID of the status being quoted, if any. - * Requires `features.quotePosts`. + * Requires features{@link Features['quotePosts']}. */ quote_id?: string; @@ -108,7 +108,7 @@ type CreateStatusParams = (CreateStatusWithContent | CreateStatusWithMedia) & Cr * @category Request params */ interface LanguageParam { - /** Attach translated version of a post. Requires `features.autoTranslate`. */ + /** Attach translated version of a post. Requires features{@link Features['autoTranslate']}. */ language?: string; } diff --git a/packages/pl-api/lib/params/timelines.ts b/packages/pl-api/lib/params/timelines.ts index ba295ec1b..34e880ca6 100644 --- a/packages/pl-api/lib/params/timelines.ts +++ b/packages/pl-api/lib/params/timelines.ts @@ -11,7 +11,7 @@ interface PublicTimelineParams extends PaginationParams, WithMutedParam, OnlyEve /** * Boolean. Show only statuses from the given domain. * - * Requires `features.instanceTimeline`. + * Requires features{@link Features['instanceTimeline']}. */ instance?: string; } @@ -53,7 +53,7 @@ type ListTimelineParams = PaginationParams & WithMutedParam & OnlyEventsParam & interface GetConversationsParams extends PaginationParams, LanguageParam { /** * Only return conversations with the given recipients (a list of user ids). - * Requires `features.conversationsByRecipients`. + * Requires features{@link Features['conversationsByRecipients']}. * */ recipients?: string[]; }