Merge pull request 'frontend-rw' (#1) from frontend-rw into develop
Some checks are pending
pl-api CI / Test for a successful build (push) Waiting to run
pl-fe CI / Test and upload artifacts (push) Waiting to run
pl-fe CI / deploy (push) Blocked by required conditions
pl-hooks CI / Test for a successful build (push) Waiting to run

Reviewed-on: #1
This commit is contained in:
marcin mikołajczak 2024-12-05 15:32:17 -08:00
commit cf4b6cbda2
608 changed files with 10722 additions and 12025 deletions

View file

@ -34,7 +34,7 @@ jobs:
working-directory: ./packages/pl-api
run: yarn lint
- name: build
- name: Build
env:
NODE_ENV: production
working-directory: ./packages/pl-api

View file

@ -12,7 +12,7 @@ jobs:
name: Test and upload artifacts
strategy:
matrix:
node-version: [21.x]
node-version: [22.x]
steps:
- name: Install system dependencies
@ -59,6 +59,18 @@ jobs:
working-directory: ./packages/pl-fe/dist
run: zip -r pl-fe.zip .
- name: Install pl-api deps
working-directory: ./packages/pl-api
run: yarn install --ignore-scripts
- name: Build pl-api documentation
working-directory: ./packages/pl-api
run: npx typedoc
- name: Copy pl-api documentation
working-directory: ./packages/pl-api
run: cp docs ../pl-fe/dist/pl-api-docs -r
- name: Upload Github Pages artifact
uses: actions/upload-pages-artifact@v3
with:

View file

@ -4,6 +4,6 @@
"bradlc.vscode-tailwindcss",
"stylelint.vscode-stylelint",
"wix.vscode-import-cost",
"redhat.vscode-yaml"
"bradlc.vscode-tailwindcss"
]
}

View file

@ -1,8 +1,12 @@
[![GitHub Repo stars](https://img.shields.io/github/stars/mkljczk/pl-fe)](https://github.com/mkljczk/pl-fe)
[![GitHub License](https://img.shields.io/github/license/mkljczk/pl-fe)](https://github.com/mkljczk/pl-fe?tab=AGPL-3.0-1-ov-file#readme)
[![Discord](https://img.shields.io/discord/1279834339470872598)](https://discord.gg/NCZZsqqgUH)
This repo hosts a few of my projects related to the Fediverse client `pl-fe`. This includes:
- [pl-fe](./packages/pl-fe/) — a social networking client app forked from Soapbox
- [pl-api](./packages/pl-api) — a library for interacting with Mastodon API-compatible servers, focused on support for projects extending the official Mastodon API. It is used by `pl-fe`.
- [pl-hooks](./packages/pl-hooks) — a library including hooks for integrating with Mastodon API, based on `pl-api` and TanStack. It is intended to be used within `pl-fe`. Work in progress.
- [pl-hooks](./packages/pl-hooks) — a library including hooks for integrating with Mastodon API, based on `pl-api` and TanStack Query. It is intended to be used within `pl-fe`. Work in progress.
More projects to be announced.

View file

@ -12,6 +12,7 @@ lerna-debug.log*
node_modules
dist
dist-ssr
docs
*.local
.idea

View file

@ -1,16 +1,48 @@
# `pl-api`
A library for interacting with Mastodon API-compatible servers, focused on support for projects extending the official Mastodon API.
[![GitHub License](https://img.shields.io/github/license/mkljczk/pl-fe)](https://github.com/mkljczk/pl-fe?tab=AGPL-3.0-1-ov-file#readme)
[![NPM Version](https://img.shields.io/npm/v/pl-api)
![NPM Downloads](https://img.shields.io/npm/dw/pl-api)](https://www.npmjs.com/package/pl-api)
A JavaScript library for interacting with Mastodon API-compatible servers, focused on support for projects extending the official Mastodon API.
`pl-api` attempts to abstract out the implementation details when supporting different backends, implementing the same features in different ways. It uses [Valibot](https://valibot.dev/) to ensure type safety and normalize API responses.
Example:
```ts
import { PlApiClient, type CreateApplicationParams } from 'pl-api';
const { ACCESS_TOKEN } = process.env;
const client = new PlApiClient('https://mastodon.example/', ACCESS_TOKEN, {
fetchInstance: true,
onInstanceFetchSuccess: () => console.log('Instance fetched'),
});
await client.statuses.createStatus({
status: 'Hello, world!',
language: 'en',
});
```
Some sort of documentation is available on https://pl.mkljczk.pl/pl-api-docs
> This project should be considered unstable before the 1.0.0 release. I will not provide any changelog or information on breaking changes until then.
## Supported projects
Currently, `pl-api` includes compatibility definitions for 12 independent Mastodon API implementations and 5 variants of them (like, forks). As the combination of software name and version is not the only way `pl-api` infers feature availability, some feature definitions will also work on other software.
For unsupported projects, it falls back to a basic feature set, though every method of PlApiClient may be used anyway.
## Projects using `pl-api`
[`pl-fe`](https://github.com/mkljczk/pl-fe) is a web client for Mastodon-compatible servers forked from Soapbox. It uses `pl-api` for API interactions.
* [`pl-fe`](https://github.com/mkljczk/pl-fe/tree/develop/packages/pl-fe) is a web client for Mastodon-compatible servers forked from Soapbox. It uses `pl-api` for API interactions.
* [`pl-hooks`](https://github.com/mkljczk/pl-fe/tree/develop/packages/pl-hooks) is a work-in-progress library utilizing `pl-api`.
## License
`pl-api` utilizes code from [Soapbox](https://gitlab.com/soapbox-pub/soapbox) and bases off official [Mastodon documentation](https://docs.joinmastodon.org).
`pl-api` utilizes parts of code from [Soapbox](https://gitlab.com/soapbox-pub/soapbox) and bases off official [Mastodon documentation](https://docs.joinmastodon.org).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View file

@ -1,3 +1,6 @@
import { WebSocket } from 'isows';
import omit from 'lodash.omit';
import pick from 'lodash.pick';
import * as v from 'valibot';
import {
@ -27,6 +30,7 @@ import {
contextSchema,
conversationSchema,
credentialAccountSchema,
credentialApplicationSchema,
customEmojiSchema,
domainBlockSchema,
emojiReactionSchema,
@ -70,22 +74,140 @@ import {
trendsLinkSchema,
webPushSubscriptionSchema,
} from './entities';
import { GroupedNotificationsResults, groupedNotificationsResultsSchema, NotificationGroup } from './entities/grouped-notifications-results';
import { filteredArray } from './entities/utils';
import { AKKOMA, type Features, getFeatures, GOTOSOCIAL, MITRA } from './features';
import {
CreateScrobbleParams,
FollowAccountParams,
GetAccountEndorsementsParams,
GetAccountFavouritesParams,
GetAccountFollowersParams,
GetAccountFollowingParams,
GetAccountParams,
GetAccountStatusesParams,
GetRelationshipsParams,
GetScrobblesParams,
ReportAccountParams,
SearchAccountParams,
} from './params/accounts';
import { CreateApplicationParams } from './params/apps';
import {
CreateChatMessageParams,
GetChatMessagesParams,
GetChatsParams,
} from './params/chats';
import {
CreateEventParams,
EditEventParams,
GetEventParticipationRequestsParams,
GetEventParticipationsParams,
GetJoinedEventsParams,
} from './params/events';
import {
CreateFilterParams,
GetBlocksParams,
GetDomainBlocksParams,
GetMutesParams,
MuteAccountParams,
UpdateFilterParams,
} from './params/filtering';
import { GetGroupedNotificationsParams, GetUnreadNotificationGroupCountParams } from './params/grouped-notifications';
import {
CreateGroupParams,
GetGroupBlocksParams,
GetGroupMembershipRequestsParams,
GetGroupMembershipsParams,
UpdateGroupParams,
} from './params/groups';
import { ProfileDirectoryParams } from './params/instance';
import {
GetInteractionRequestsParams,
} from './params/interaction-requests';
import {
CreateListParams,
GetListAccountsParams,
UpdateListParams,
} from './params/lists';
import {
UpdateMediaParams,
UploadMediaParams,
} from './params/media';
import {
CreateBookmarkFolderParams,
GetBookmarksParams,
GetEndorsementsParams,
GetFavouritesParams,
GetFollowedTagsParams,
GetFollowRequestsParams,
UpdateBookmarkFolderParams,
} from './params/my-account';
import {
GetNotificationParams,
GetNotificationRequestsParams,
GetUnreadNotificationCountParams,
UpdateNotificationPolicyRequest,
} from './params/notifications';
import {
GetTokenParams,
MfaChallengeParams,
OauthAuthorizeParams,
RevokeTokenParams,
} from './params/oauth';
import {
CreatePushNotificationsSubscriptionParams,
UpdatePushNotificationsSubscriptionParams,
} from './params/push-notifications';
import { GetScheduledStatusesParams } from './params/scheduled-statuses';
import { SearchParams } from './params/search';
import {
CreateAccountParams,
UpdateCredentialsParams,
UpdateInteractionPoliciesParams,
UpdateNotificationSettingsParams,
} from './params/settings';
import {
CreateStatusParams,
EditStatusParams,
GetFavouritedByParams,
GetRebloggedByParams,
GetStatusContextParams,
GetStatusesParams,
GetStatusParams,
GetStatusQuotesParams,
} from './params/statuses';
import {
BubbleTimelineParams,
GetConversationsParams,
GroupTimelineParams,
HashtagTimelineParams,
HomeTimelineParams,
ListTimelineParams,
PublicTimelineParams,
SaveMarkersParams,
} from './params/timelines';
import {
GetTrendingLinks,
GetTrendingStatuses,
GetTrendingTags,
} from './params/trends';
import request, { getNextLink, getPrevLink, type RequestBody, RequestMeta } from './request';
import { buildFullPath } from './utils/url';
import type {
Account,
AdminAccount,
AdminAnnouncement,
AdminModerationLogEntry,
AdminReport,
GroupRole,
Instance,
Notification,
PleromaConfig,
Status,
StreamingEvent,
} from './entities';
import type { PlApiResponse } from './main';
import type {
AdminAccountAction,
AdminCreateAnnouncementParams,
@ -114,89 +236,29 @@ import type {
AdminUpdateReportParams,
AdminUpdateRuleParams,
AdminUpdateStatusParams,
BubbleTimelineParams,
CreateAccountParams,
CreateApplicationParams,
CreateBookmarkFolderParams,
CreateChatMessageParams,
CreateEventParams,
CreateFilterParams,
CreateGroupParams,
CreateListParams,
CreatePushNotificationsSubscriptionParams,
CreateScrobbleParams,
CreateStatusParams,
EditEventParams,
EditStatusParams,
FollowAccountParams,
GetAccountEndorsementsParams,
GetAccountFavouritesParams,
GetAccountFollowersParams,
GetAccountFollowingParams,
GetAccountParams,
GetAccountStatusesParams,
GetBlocksParams,
GetBookmarksParams,
GetChatMessagesParams,
GetChatsParams,
GetConversationsParams,
GetDomainBlocksParams,
GetEndorsementsParams,
GetEventParticipationRequestsParams,
GetEventParticipationsParams,
GetFavouritedByParams,
GetFavouritesParams,
GetFollowedTagsParams,
GetFollowRequestsParams,
GetGroupBlocksParams,
GetGroupMembershipRequestsParams,
GetGroupMembershipsParams,
GetInteractionRequestsParams,
GetJoinedEventsParams,
GetListAccountsParams,
GetMutesParams,
GetNotificationParams,
GetNotificationRequestsParams,
GetRebloggedByParams,
GetRelationshipsParams,
GetScheduledStatusesParams,
GetScrobblesParams,
GetStatusContextParams,
GetStatusesParams,
GetStatusParams,
GetStatusQuotesParams,
GetTokenParams,
GetTrendingLinks,
GetTrendingStatuses,
GetTrendingTags,
GroupTimelineParams,
HashtagTimelineParams,
HomeTimelineParams,
ListTimelineParams,
MfaChallengeParams,
MuteAccountParams,
OauthAuthorizeParams,
ProfileDirectoryParams,
PublicTimelineParams,
ReportAccountParams,
RevokeTokenParams,
SaveMarkersParams,
SearchAccountParams,
SearchParams,
UpdateBookmarkFolderParams,
UpdateCredentialsParams,
UpdateFilterParams,
UpdateGroupParams,
UpdateInteractionPoliciesParams,
UpdateListParams,
UpdateMediaParams,
UpdateNotificationPolicyRequest,
UpdateNotificationSettingsParams,
UpdatePushNotificationsSubscriptionParams,
UploadMediaParams,
} from './params';
} from './params/admin';
import type { PaginatedResponse } from './responses';
const GROUPED_TYPES = ['favourite', 'reblog', 'emoji_reaction', 'event_reminder', 'participation_accepted', 'participation_request'];
interface PlApiClientConstructorOpts {
/** Instance object to use by default, to be populated eg. from cache */
instance?: Instance;
/** Fetch instance after constructing */
fetchInstance?: boolean;
/** Abort signal which can be used to cancel the callbacks */
fetchInstanceSignal?: AbortSignal;
/** Executed after the initial instance fetch */
onInstanceFetchSuccess?: (instance: Instance) => void;
/** Executed when the initial instance fetch failed */
onInstanceFetchError?: (error?: any) => void;
}
/**
* @category Clients
*
* Mastodon API client.
*/
class PlApiClient {
baseURL: string;
@ -209,13 +271,21 @@ class PlApiClient {
unlisten: (listener: any) => void;
subscribe: (stream: string, params?: { list?: string; tag?: string }) => void;
unsubscribe: (stream: string, params?: { list?: string; tag?: string }) => void;
close: () => void;
close: () => void;
};
constructor(baseURL: string, accessToken?: string, { instance, fetchInstance }: {
instance?: Instance;
fetchInstance?: boolean;
} = {}) {
/**
*
* @param baseURL Mastodon API-compatible server URL
* @param accessToken OAuth token for an authorized user
*/
constructor(baseURL: string, accessToken?: string, {
instance,
fetchInstance,
fetchInstanceSignal,
onInstanceFetchSuccess,
onInstanceFetchError,
}: PlApiClientConstructorOpts = {}) {
this.baseURL = baseURL;
this.#accessToken = accessToken;
@ -223,30 +293,31 @@ class PlApiClient {
this.#setInstance(instance);
}
if (fetchInstance) {
this.instance.getInstance();
this.instance.getInstance().then((instance) => {
if (fetchInstanceSignal?.aborted) return;
onInstanceFetchSuccess?.(instance);
}).catch((error) => {
if (fetchInstanceSignal?.aborted) return;
onInstanceFetchError?.(error);
});
}
}
#paginatedGet = async <T>(input: URL | RequestInfo, body: RequestBody, schema: v.BaseSchema<any, T, v.BaseIssue<unknown>>): Promise<PaginatedResponse<T>> => {
const getMore = (input: string | null) => input ? async () => {
const response = await this.request(input);
#paginatedGet = async <T, IsArray extends true | false = true>(input: URL | RequestInfo, body: RequestBody, schema: v.BaseSchema<any, T, v.BaseIssue<unknown>>, isArray = true as IsArray): Promise<PaginatedResponse<T, typeof isArray>> => {
const targetSchema = isArray ? filteredArray(schema) : schema;
return {
previous: getMore(getPrevLink(response)),
next: getMore(getNextLink(response)),
items: v.parse(filteredArray(schema), response.json),
partial: response.status === 206,
};
} : null;
const processResponse = (response: PlApiResponse<any>) => ({
previous: getMore(getPrevLink(response)),
next: getMore(getNextLink(response)),
items: v.parse(targetSchema, response.json),
partial: response.status === 206,
} as PaginatedResponse<T, IsArray>);
const getMore = (input: string | null) => input ? () => this.request(input).then(processResponse) : null;
const response = await this.request(input, body);
return {
previous: getMore(getPrevLink(response)),
next: getMore(getNextLink(response)),
items: v.parse(filteredArray(schema), response.json),
partial: response.status === 206,
};
return processResponse(response);
};
#paginatedPleromaAccounts = async (params: {
@ -310,6 +381,65 @@ class PlApiClient {
};
};
#groupNotifications = ({ previous, next, items, ...response }: PaginatedResponse<Notification>, params?: GetGroupedNotificationsParams): PaginatedResponse<GroupedNotificationsResults, false> => {
const notificationGroups: Array<NotificationGroup> = [];
for (const notification of items) {
let existingGroup: NotificationGroup | undefined;
if ((params?.grouped_types || GROUPED_TYPES).includes(notification.type)) {
existingGroup = notificationGroups
.find(notificationGroup =>
notificationGroup.type === notification.type
&& ((notification.type === 'emoji_reaction' && notificationGroup.type === 'emoji_reaction') ? notification.emoji === notificationGroup.emoji : true)
// @ts-ignore
&& notificationGroup.status_id === notification.status?.id,
);
}
if (existingGroup) {
existingGroup.notifications_count += 1;
existingGroup.page_min_id = notification.id;
existingGroup.sample_account_ids.push(notification.account.id);
} else {
notificationGroups.push({
...(omit(notification, ['account', 'status', 'target'])),
group_key: notification.id,
notifications_count: 1,
most_recent_notification_id: notification.id,
page_min_id: notification.id,
page_max_id: notification.id,
latest_page_notification_at: notification.created_at,
sample_account_ids: [notification.account.id],
// @ts-ignore
status_id: notification.status?.id,
// @ts-ignore
target_id: notification.target?.id,
});
}
}
const groupedNotificationsResults: GroupedNotificationsResults = {
accounts: Object.values(items.reduce<Record<string, Account>>((accounts, notification) => {
accounts[notification.account.id] = notification.account;
if ('target' in notification) accounts[notification.target.id] = notification.target;
return accounts;
}, {})),
statuses: Object.values(items.reduce<Record<string, Status>>((statuses, notification) => {
if ('status' in notification) statuses[notification.status.id] = notification.status;
return statuses;
}, {})),
notification_groups: notificationGroups,
};
return {
...response,
previous: previous ? async () => this.#groupNotifications(await previous(), params) : null,
next: next ? async () => this.#groupNotifications(await next(), params) : null,
items: groupedNotificationsResults,
};
};
/** Register client applications that can be used to obtain OAuth tokens. */
public readonly apps = {
/**
@ -320,7 +450,7 @@ class PlApiClient {
createApplication: async (params: CreateApplicationParams) => {
const response = await this.request('/api/v1/apps', { method: 'POST', body: params });
return v.parse(applicationSchema, response.json);
return v.parse(credentialApplicationSchema, response.json);
},
/**
@ -910,7 +1040,7 @@ class PlApiClient {
* Register an account
* Creates a user and account records. Returns an account access token for the app that initiated the request. The app should save this token for later, and should wait for the user to confirm their account by clicking a link in their email inbox.
*
* Requires features{@link Features['accountCreation`
* Requires features{@link Features['accountCreation']}
* @see {@link https://docs.joinmastodon.org/methods/accounts/#create}
*/
createAccount: async (params: CreateAccountParams) => {
@ -1216,7 +1346,7 @@ class PlApiClient {
mfa: {
/**
* Requires features{@link Features['manageMfa`.
* Requires features{@link Features['manageMfa']}.
*/
getMfaSettings: async () => {
const response = await this.request('/api/pleroma/accounts/mfa');
@ -1230,7 +1360,7 @@ class PlApiClient {
},
/**
* Requires features{@link Features['manageMfa`.
* Requires features{@link Features['manageMfa']}.
*/
getMfaBackupCodes: async () => {
const response = await this.request('/api/pleroma/accounts/mfa/backup_codes');
@ -1241,7 +1371,7 @@ class PlApiClient {
},
/**
* Requires features{@link Features['manageMfa`.
* Requires features{@link Features['manageMfa']}.
*/
getMfaSetup: async (method: 'totp') => {
const response = await this.request(`/api/pleroma/accounts/mfa/setup/${method}`);
@ -1253,7 +1383,7 @@ class PlApiClient {
},
/**
* Requires features{@link Features['manageMfa`.
* Requires features{@link Features['manageMfa']}.
*/
confirmMfaSetup: async (method: 'totp', code: string, password: string) => {
const response = await this.request(`/api/pleroma/accounts/mfa/confirm/${method}`, {
@ -1267,7 +1397,7 @@ class PlApiClient {
},
/**
* Requires features{@link Features['manageMfa`.
* Requires features{@link Features['manageMfa']}.
*/
disableMfa: async (method: 'totp', password: string) => {
const response = await this.request(`/api/pleroma/accounts/mfa/${method}`, {
@ -2084,11 +2214,8 @@ class PlApiClient {
* Requires features{@link Features['statusDislikes']}.
* @see {@link https://github.com/friendica/friendica/blob/2024.06-rc/doc/API-Friendica.md#get-apifriendicastatusesiddisliked_by}
*/
getDislikedBy: async (statusId: string) => {
const response = await this.request(`/api/friendica/statuses/${statusId}/disliked_by`);
return v.parse(filteredArray(accountSchema), response.json);
},
getDislikedBy: async (statusId: string) =>
this.#paginatedGet(`/api/v1/statuses/${statusId}/disliked_by`, {}, accountSchema),
/**
* Marks the given status as disliked by this user
@ -2524,13 +2651,30 @@ class PlApiClient {
return response.json as {};
},
/**
* Get the number of unread notification
* Get the (capped) number of unread notifications for the current user.
*
* Requires features{@link Features['notificationsGetUnreadCount']}.
* @see {@link https://docs.joinmastodon.org/methods/notifications/#unread-count}
*/
getUnreadNotificationCount: async (params?: GetUnreadNotificationCountParams) => {
const response = await this.request('/api/v1/notifications/unread_count', { params });
return v.parse(v.object({
count: v.number(),
}), response.json);
},
/**
* Get the filtering policy for notifications
* Notifications filtering policy for the user.
*
* Requires features{@link Features['notificationsPolicy']}.
* @see {@link https://docs.joinmastodon.org/methods/notifications/#get-policy}
*/
getNotificationPolicy: async () => {
const response = await this.request('/api/v1/notifications/policy');
const response = await this.request('/api/v2/notifications/policy');
return v.parse(notificationPolicySchema, response.json);
},
@ -2538,10 +2682,12 @@ class PlApiClient {
/**
* Update the filtering policy for notifications
* Update the users notifications filtering policy.
*
* Requires features{@link Features['notificationsPolicy']}.
* @see {@link https://docs.joinmastodon.org/methods/notifications/#update-the-filtering-policy-for-notifications}
*/
updateNotificationPolicy: async (params: UpdateNotificationPolicyRequest) => {
const response = await this.request('/api/v1/notifications/policy', { method: 'POST', body: params });
const response = await this.request('/api/v2/notifications/policy', { method: 'PATCH', body: params });
return v.parse(notificationPolicySchema, response.json);
},
@ -2587,6 +2733,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<string>) => {
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<string>) => {
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.
*
@ -2603,6 +2787,108 @@ class PlApiClient {
},
};
/**
* It is recommended to only use this with features{@link Features['groupedNotifications']} available. However, there is a fallback that groups the notifications client-side.
*/
public readonly groupedNotifications = {
/**
* Get all grouped notifications
* Return grouped notifications concerning the user. This API returns Link headers containing links to the next/previous page. However, the links can also be constructed dynamically using query params and `id` values.
*
* Requires features{@link Features['groupedNotifications']}.
* @see {@link https://docs.joinmastodon.org/methods/grouped_notifications/#get-grouped}
*/
getGroupedNotifications: async (params: GetGroupedNotificationsParams, meta?: RequestMeta) => {
if (this.features.groupedNotifications) {
return this.#paginatedGet('/api/v2/notifications', { ...meta, params }, groupedNotificationsResultsSchema, false);
} else {
const response = await this.notifications.getNotifications(
pick(params, ['max_id', 'since_id', 'limit', 'min_id', 'types', 'exclude_types', 'account_id', 'include_filtered']),
);
return this.#groupNotifications(response, params);
}
},
/**
* Get a single notification group
* View information about a specific notification group with a given group key.
*
* Requires features{@link Features['groupedNotifications']}.
* @see {@link https://docs.joinmastodon.org/methods/grouped_notifications/#get-notification-group}
*/
getNotificationGroup: async (groupKey: string) => {
if (this.features.groupedNotifications) {
const response = await this.request(`/api/v2/notifications/${groupKey}`);
return v.parse(groupedNotificationsResultsSchema, response.json);
} else {
const response = await this.request(`/api/v1/notifications/${groupKey}`);
return this.#groupNotifications({
previous: null,
next: null,
items: [response.json],
partial: false,
}).items;
}
},
/**
* Dismiss a single notification group
* Dismiss a single notification group from the server.
*
* Requires features{@link Features['groupedNotifications']}.
* @see {@link https://docs.joinmastodon.org/methods/grouped_notifications/#dismiss-group}
*/
dismissNotificationGroup: async (groupKey: string) => {
if (this.features.groupedNotifications) {
const response = await this.request(`/api/v2/notifications/${groupKey}/dismiss`, { method: 'POST' });
return response.json as {};
} else {
return this.notifications.dismissNotification(groupKey);
}
},
/**
* Get accounts of all notifications in a notification group
*
* Requires features{@link Features['groupedNotifications']}.
* @see {@link https://docs.joinmastodon.org/methods/grouped_notifications/#get-group-accounts}
*/
getNotificationGroupAccounts: async (groupKey: string) => {
if (this.features.groupedNotifications) {
const response = await this.request(`/api/v2/notifications/${groupKey}/accounts`);
return v.parse(filteredArray(accountSchema), response.json);
} else {
return (await (this.groupedNotifications.getNotificationGroup(groupKey))).accounts;
}
},
/**
* Get the number of unread notifications
* Get the (capped) number of unread notification groups for the current user. A notification is considered unread if it is more recent than the notifications read marker. Because the count is dependant on the parameters, it is computed every time and is thus a relatively slow operation (although faster than getting the full corresponding notifications), therefore the number of returned notifications is capped.
*
* Requires features{@link Features['groupedNotifications']}.
* @see {@link https://docs.joinmastodon.org/methods/grouped_notifications/#unread-group-count}
*/
getUnreadNotificationGroupCount: async (params: GetUnreadNotificationGroupCountParams) => {
if (this.features.groupedNotifications) {
const response = await this.request('/api/v2/notifications/unread_count', { params });
return v.parse(v.object({
count: v.number(),
}), response.json);
} else {
return this.notifications.getUnreadNotificationCount(
pick(params || {}, ['max_id', 'since_id', 'limit', 'min_id', 'types', 'exclude_types', 'account_id']),
);
}
},
};
public readonly pushNotifications = {
/**
* Subscribe to push notifications
@ -4051,7 +4337,7 @@ class PlApiClient {
public readonly events = {
/**
* Creates an event
* @see {@link }
* @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaevents}
*/
createEvent: async (params: CreateEventParams) => {
const response = await this.request('/api/v1/pleroma/events', { method: 'POST', body: params });
@ -4061,7 +4347,7 @@ class PlApiClient {
/**
* Edits an event
* @see {@link }
* @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsid}
*/
editEvent: async (statusId: string, params: EditEventParams) => {
const response = await this.request(`/api/v1/pleroma/events/${statusId}`, { method: 'PUT', body: params });
@ -4071,7 +4357,7 @@ class PlApiClient {
/**
* Gets user's joined events
* @see {@link }
* @see {@link https://github.com/mkljczk/pl/blob/fork/docs/development/API/pleroma_api.md#apiv1pleromaeventsjoined_events}
*/
getJoinedEvents: async (state?: 'pending' | 'reject' | 'accept', params?: GetJoinedEventsParams) =>
this.#paginatedGet('/api/v1/pleroma/events/joined_events', { params: { ...params, state } }, statusSchema),

View file

@ -8,19 +8,36 @@ import { filteredArray } from './entities/utils';
import request from './request';
interface Params {
/** ISO 639 language code for servers. */
language?: string;
/** Server topic. */
category?: string;
/** Region where teh server is legally based. */
region?: 'europe' | 'north_america' | 'south_america' | 'africa' | 'asia' | 'oceania';
/** Whether the server is governed by a public organization or a private individual. */
ownership?: 'juridicial' | 'natural';
/** Whether the registrations are currently open. */
registrations?: 'instant' | 'manual';
}
/**
* @category Clients
*
* joinmastodon.org-compatible server directory client.
*/
class PlApiDirectoryClient {
accessToken = undefined;
/** Unused. */
accessToken: string | undefined = undefined;
/**
* Server directory URL.
*/
baseURL: string;
public request = request.bind(this) as typeof request;
/**
* @param baseURL Server directory URL. e.g. `https://joinmastodon.org`
*/
constructor(baseURL: string) {
this.baseURL = baseURL;
}

View file

@ -9,7 +9,10 @@ const appealSchema = v.object({
state: v.picklist(['approved', 'rejected', 'pending']),
});
/** @see {@link https://docs.joinmastodon.org/entities/AccountWarning/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/AccountWarning/}
*/
const accountWarningSchema = v.object({
id: v.string(),
action: v.picklist(['none', 'disable', 'mark_statuses_as_sensitive', 'delete_statuses', 'sensitive', 'silence', 'suspend']),
@ -20,6 +23,9 @@ const accountWarningSchema = v.object({
created_at: v.fallback(datetimeSchema, new Date().toISOString()),
});
/**
* @category Entity types
*/
type AccountWarning = v.InferOutput<typeof accountWarningSchema>;
export { accountWarningSchema, type AccountWarning };

View file

@ -119,7 +119,7 @@ const baseAccountSchema = v.object({
following_count: v.fallback(v.number(), 0),
roles: filteredArray(roleSchema),
fqn: v.fallback(v.nullable(v.string()), null),
fqn: v.string(),
ap_id: v.fallback(v.nullable(v.string()), null),
background_image: v.fallback(v.nullable(v.string()), null),
relationship: v.fallback(v.optional(relationshipSchema), undefined),
@ -164,8 +164,14 @@ type WithMoved = {
moved: Account | null;
};
/**
* @category Entity types
*/
type Account = v.InferOutput<typeof accountWithMovedAccountSchema> & WithMoved;
/**
* @category Schemas
*/
const accountSchema: v.BaseSchema<any, Account, v.BaseIssue<unknown>> = untypedAccountSchema as any;
const untypedCredentialAccountSchema = v.pipe(v.any(), preprocessAccount, v.object({
@ -197,8 +203,14 @@ const untypedCredentialAccountSchema = v.pipe(v.any(), preprocessAccount, v.obje
})), undefined),
}));
/**
* @category Entity types
*/
type CredentialAccount = v.InferOutput<typeof untypedCredentialAccountSchema> & WithMoved;
/**
* @category Schemas
*/
const credentialAccountSchema: v.BaseSchema<any, CredentialAccount, v.BaseIssue<unknown>> = untypedCredentialAccountSchema as any;
const untypedMutedAccountSchema = v.pipe(v.any(), preprocessAccount, v.object({
@ -206,8 +218,14 @@ const untypedMutedAccountSchema = v.pipe(v.any(), preprocessAccount, v.object({
mute_expires_at: v.fallback(v.nullable(datetimeSchema), null),
}));
/**
* @category Entity types
*/
type MutedAccount = v.InferOutput<typeof untypedMutedAccountSchema> & WithMoved;
/**
* @category Schemas
*/
const mutedAccountSchema: v.BaseSchema<any, MutedAccount, v.BaseIssue<unknown>> = untypedMutedAccountSchema as any;
export {

View file

@ -6,7 +6,10 @@ import { datetimeSchema, filteredArray } from '../utils';
import { adminIpSchema } from './ip';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Account/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_Account/}
*/
const adminAccountSchema = v.pipe(
v.any(),
v.transform((account: any) => {
@ -65,6 +68,9 @@ const adminAccountSchema = v.pipe(
}),
);
/**
* @category Admin entity types
*/
type AdminAccount = v.InferOutput<typeof adminAccountSchema>;
export {

View file

@ -3,7 +3,10 @@ import * as v from 'valibot';
import { announcementSchema } from '../announcement';
/** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminannouncements} */
/**
* @category Admin schemas
* @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminannouncements}
*/
const adminAnnouncementSchema = v.pipe(
v.any(),
v.transform((announcement: any) => ({
@ -16,6 +19,9 @@ const adminAnnouncementSchema = v.pipe(
}),
);
/**
* @category Admin entity types
*/
type AdminAnnouncement = v.InferOutput<typeof adminAnnouncementSchema>;
export { adminAnnouncementSchema, type AdminAnnouncement };

View file

@ -1,11 +1,17 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_CanonicalEmailBlock/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_CanonicalEmailBlock/}
*/
const adminCanonicalEmailBlockSchema = v.object({
id: v.string(),
canonical_email_hash: v.string(),
});
/**
* @category Admin entity types
*/
type AdminCanonicalEmailBlock = v.InferOutput<typeof adminCanonicalEmailBlockSchema>;
export {

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Cohort/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_Cohort/}
*/
const adminCohortSchema = v.object({
period: datetimeSchema,
frequency: v.picklist(['day', 'month']),
@ -13,6 +16,9 @@ const adminCohortSchema = v.object({
})),
});
/**
* @category Admin entity types
*/
type AdminCohort = v.InferOutput<typeof adminCohortSchema>;
export {

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Dimension/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_Dimension/}
*/
const adminDimensionSchema = v.object({
key: v.string(),
data: v.object({
@ -12,6 +15,9 @@ const adminDimensionSchema = v.object({
}),
});
/**
* @category Admin entity types
*/
type AdminDimension = v.InferOutput<typeof adminDimensionSchema>;
export {

View file

@ -2,13 +2,19 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_DomainAllow/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_DomainAllow/}
*/
const adminDomainAllowSchema = v.object({
id: v.string(),
domain: v.string(),
created_at: datetimeSchema,
});
/**
* @category Admin entity types
*/
type AdminDomainAllow = v.InferOutput<typeof adminDomainAllowSchema>;
export {

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_DomainBlock/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_DomainBlock/}
*/
const adminDomainBlockSchema = v.object({
id: v.string(),
domain: v.string(),
@ -16,6 +19,9 @@ const adminDomainBlockSchema = v.object({
obfuscate: v.boolean(),
});
/**
* @category Admin entity types
*/
type AdminDomainBlock = v.InferOutput<typeof adminDomainBlockSchema>;
export {

View file

@ -2,6 +2,9 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/**
* @category Admin schemas
*/
const adminDomainSchema = v.object({
domain: v.fallback(v.string(), ''),
id: v.pipe(v.unknown(), v.transform(String)),
@ -10,6 +13,9 @@ const adminDomainSchema = v.object({
last_checked_at: v.fallback(v.nullable(datetimeSchema), null),
});
/**
* @category Admin entity types
*/
type AdminDomain = v.InferOutput<typeof adminDomainSchema>
export { adminDomainSchema, type AdminDomain };

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_EmailDomainBlock/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_EmailDomainBlock/}
*/
const adminEmailDomainBlockSchema = v.object({
id: v.string(),
domain: v.string(),
@ -14,6 +17,9 @@ const adminEmailDomainBlockSchema = v.object({
})),
});
/**
* @category Admin entity types
*/
type AdminEmailDomainBlock = v.InferOutput<typeof adminEmailDomainBlockSchema>;
export {

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_IpBlock/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_IpBlock/}
*/
const adminIpBlockSchema = v.object({
id: v.string(),
ip: v.pipe(v.string(), v.ip()),
@ -12,6 +15,9 @@ const adminIpBlockSchema = v.object({
expires_at: v.fallback(v.nullable(datetimeSchema), null),
});
/**
* @category Admin entity types
*/
type AdminIpBlock = v.InferOutput<typeof adminIpBlockSchema>;
export {

View file

@ -2,12 +2,18 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Ip/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_Ip/}
*/
const adminIpSchema = v.object({
ip: v.pipe(v.string(), v.ip()),
used_at: datetimeSchema,
});
/**
* @category Admin entity types
*/
type AdminIp = v.InferOutput<typeof adminIpSchema>;
export {

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from '../utils';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Measure/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_Measure/}
*/
const adminMeasureSchema = v.object({
key: v.string(),
unit: v.fallback(v.nullable(v.string()), null),
@ -15,6 +18,9 @@ const adminMeasureSchema = v.object({
})),
});
/**
* @category Admin entity types
*/
type AdminMeasure = v.InferOutput<typeof adminMeasureSchema>;
export {

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminmoderation_log} */
/**
* @category Admin schemas
* @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminmoderation_log}
*/
const adminModerationLogEntrySchema = v.object({
id: v.pipe(v.unknown(), v.transform(String)),
data: v.fallback(v.record(v.string(), v.any()), {}),
@ -8,6 +11,9 @@ const adminModerationLogEntrySchema = v.object({
message: v.fallback(v.string(), ''),
});
/**
* @category Admin entity types
*/
type AdminModerationLogEntry = v.InferOutput<typeof adminModerationLogEntrySchema>
export { adminModerationLogEntrySchema, type AdminModerationLogEntry };

View file

@ -1,5 +1,8 @@
import * as v from 'valibot';
/**
* @category Admin schemas
*/
const pleromaConfigSchema = v.object({
configs: v.array(v.object({
value: v.any(),
@ -9,6 +12,9 @@ const pleromaConfigSchema = v.object({
need_reboot: v.boolean(),
});
/**
* @category Admin entity types
*/
type PleromaConfig = v.InferOutput<typeof pleromaConfigSchema>
export { pleromaConfigSchema, type PleromaConfig };

View file

@ -1,5 +1,8 @@
import * as v from 'valibot';
/**
* @category Admin schemas
*/
const adminRelaySchema = v.pipe(
v.any(),
v.transform((data: any) => ({ id: data.actor, ...data })),
@ -10,6 +13,9 @@ const adminRelaySchema = v.pipe(
}),
);
/**
* @category Admin entity types
*/
type AdminRelay = v.InferOutput<typeof adminRelaySchema>
export { adminRelaySchema, type AdminRelay };

View file

@ -7,7 +7,10 @@ import { datetimeSchema, filteredArray } from '../utils';
import { adminAccountSchema } from './account';
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Report/} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Admin_Report/}
*/
const adminReportSchema = v.pipe(
v.any(),
v.transform((report: any) => {
@ -45,6 +48,9 @@ const adminReportSchema = v.pipe(
}),
);
/**
* @category Admin entity types
*/
type AdminReport = v.InferOutput<typeof adminReportSchema>;
export { adminReportSchema, type AdminReport };

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminrules} */
/**
* @category Admin schemas
* @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminrules}
*/
const adminRuleSchema = v.object({
id: v.string(),
text: v.fallback(v.string(), ''),
@ -8,6 +11,9 @@ const adminRuleSchema = v.object({
priority: v.fallback(v.nullable(v.number()), null),
});
/**
* @category Admin entity types
*/
type AdminRule = v.InferOutput<typeof adminRuleSchema>;
export { adminRuleSchema, type AdminRule };

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { tagSchema } from '../tag';
/** @see {@link https://docs.joinmastodon.org/entities/Tag/#admin} */
/**
* @category Admin schemas
* @see {@link https://docs.joinmastodon.org/entities/Tag/#admin}
*/
const adminTagSchema = v.object({
...tagSchema.entries,
id: v.string(),
@ -11,6 +14,9 @@ const adminTagSchema = v.object({
requires_review: v.boolean(),
});
/**
* @category Admin entity types
*/
type AdminTag = v.InferOutput<typeof adminTagSchema>;
export {

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/announcement/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/announcement/}
*/
const announcementReactionSchema = v.object({
name: v.fallback(v.string(), ''),
count: v.fallback(v.pipe(v.number(), v.integer(), v.minValue(0)), 0),
@ -10,6 +13,9 @@ const announcementReactionSchema = v.object({
announcement_id: v.fallback(v.string(), ''),
});
/**
* @category Entity types
*/
type AnnouncementReaction = v.InferOutput<typeof announcementReactionSchema>;
export { announcementReactionSchema, type AnnouncementReaction };

View file

@ -6,7 +6,10 @@ import { mentionSchema } from './mention';
import { tagSchema } from './tag';
import { datetimeSchema, filteredArray } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/announcement/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/announcement/}
*/
const announcementSchema = v.object({
id: v.string(),
content: v.fallback(v.string(), ''),
@ -29,6 +32,9 @@ const announcementSchema = v.object({
updated_at: v.fallback(datetimeSchema, new Date().toISOString()),
});
/**
* @category Entity types
*/
type Announcement = v.InferOutput<typeof announcementSchema>;
export { announcementSchema, type Announcement };

View file

@ -1,19 +1,47 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/Application/} */
const applicationSchema = v.object({
import { filteredArray } from './utils';
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Application/}
*/
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),
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<typeof applicationSchema>;
export { applicationSchema, type Application };
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Application/#CredentialApplication}
*/
const credentialApplicationSchema = v.pipe(
applicationSchema.pipe[0],
applicationSchema.pipe[1],
v.object({
...applicationSchema.pipe[2].entries,
client_id: v.string(),
client_secret: v.string(),
client_secret_expires_at: v.fallback(v.optional(v.string()), undefined),
}),
);
/**
* @category Entity types
*/
type CredentialApplication = v.InferOutput<typeof credentialApplicationSchema>;
export { applicationSchema, credentialApplicationSchema, type Application, type CredentialApplication };

View file

@ -2,16 +2,22 @@ import * as v from 'valibot';
import { datetimeSchema, mimeSchema } from './utils';
/** @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#post-apiv1pleromabackups} */
/**
* @category Schemas
* @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#post-apiv1pleromabackups}
*/
const backupSchema = v.object({
id: v.pipe(v.unknown(), v.transform(String)),
contentType: mimeSchema,
content_type: mimeSchema,
file_size: v.fallback(v.number(), 0),
inserted_at: datetimeSchema,
processed: v.fallback(v.boolean(), false),
url: v.fallback(v.string(), ''),
});
/**
* @category Entity types
*/
type Backup = v.InferOutput<typeof backupSchema>;
export { backupSchema, type Backup };

View file

@ -1,5 +1,8 @@
import * as v from 'valibot';
/**
* @category Schemas
*/
const bookmarkFolderSchema = v.object({
id: v.pipe(v.unknown(), v.transform(String)),
name: v.fallback(v.string(), ''),
@ -7,6 +10,9 @@ const bookmarkFolderSchema = v.object({
emoji_url: v.fallback(v.nullable(v.string()), null),
});
/**
* @category Entity types
*/
type BookmarkFolder = v.InferOutput<typeof bookmarkFolderSchema>;
export { bookmarkFolderSchema, type BookmarkFolder };

View file

@ -5,7 +5,10 @@ import { mediaAttachmentSchema } from './media-attachment';
import { previewCardSchema } from './preview-card';
import { datetimeSchema, filteredArray } from './utils';
/** @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-the-messages-for-a-chat} */
/**
* @category Schemas
* @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-the-messages-for-a-chat}
*/
const chatMessageSchema = v.object({
id: v.string(),
content: v.fallback(v.string(), ''),
@ -18,6 +21,9 @@ const chatMessageSchema = v.object({
card: v.fallback(v.nullable(previewCardSchema), null),
});
/**
* @category Entity types
*/
type ChatMessage = v.InferOutput<typeof chatMessageSchema>;
export { chatMessageSchema, type ChatMessage };

View file

@ -4,7 +4,10 @@ import { accountSchema } from './account';
import { chatMessageSchema } from './chat-message';
import { datetimeSchema } from './utils';
/** @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-a-list-of-chats} */
/**
* @category Schemas
* @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-a-list-of-chats}
*/
const chatSchema = v.object({
id: v.string(),
account: accountSchema,
@ -13,6 +16,9 @@ const chatSchema = v.object({
updated_at: datetimeSchema,
});
/**
* @category Entity types
*/
type Chat = v.InferOutput<typeof chatSchema>;
export { chatSchema, type Chat };

View file

@ -2,12 +2,18 @@ import * as v from 'valibot';
import { statusSchema } from './status';
/** @see {@link https://docs.joinmastodon.org/entities/Context/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Context/}
*/
const contextSchema = v.object({
ancestors: v.array(statusSchema),
descendants: v.array(statusSchema),
});
/**
* @category Entity types
*/
type Context = v.InferOutput<typeof contextSchema>;
export { contextSchema, type Context };

View file

@ -4,7 +4,10 @@ import { accountSchema } from './account';
import { statusSchema } from './status';
import { filteredArray } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/Conversation} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Conversation}
*/
const conversationSchema = v.object({
id: v.string(),
unread: v.fallback(v.boolean(), false),
@ -12,6 +15,9 @@ const conversationSchema = v.object({
last_status: v.fallback(v.nullable(statusSchema), null),
});
/**
* @category Entity types
*/
type Conversation = v.InferOutput<typeof conversationSchema>;
export { conversationSchema, type Conversation };

View file

@ -2,6 +2,8 @@ import * as v from 'valibot';
/**
* Represents a custom emoji.
*
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/CustomEmoji/}
*/
const customEmojiSchema = v.object({
@ -12,6 +14,9 @@ const customEmojiSchema = v.object({
category: v.fallback(v.nullable(v.string()), null),
});
/**
* @category Entity types
*/
type CustomEmoji = v.InferOutput<typeof customEmojiSchema>;
export { customEmojiSchema, type CustomEmoji };

View file

@ -1,10 +1,16 @@
import * as v from 'valibot';
/**
* @category Directory schemas
*/
const directoryCategorySchema = v.object({
category: v.string(),
servers_count: v.fallback(v.nullable(v.pipe(v.unknown(), v.transform(Number))), null),
});
/**
* @category Directory entity types
*/
type DirectoryCategory = v.InferOutput<typeof directoryCategorySchema>;
export { directoryCategorySchema, type DirectoryCategory };

View file

@ -1,11 +1,17 @@
import * as v from 'valibot';
/**
* @category Directory schemas
*/
const directoryLanguageSchema = v.object({
locale: v.string(),
language: v.string(),
servers_count: v.fallback(v.nullable(v.pipe(v.unknown(), v.transform(Number))), null),
});
/**
* @category Directory entity types
*/
type DirectoryLanguage = v.InferOutput<typeof directoryLanguageSchema>;
export { directoryLanguageSchema, type DirectoryLanguage };

View file

@ -1,5 +1,8 @@
import * as v from 'valibot';
/**
* @category Directory schemas
*/
const directoryServerSchema = v.object({
domain: v.string(),
version: v.string(),
@ -16,6 +19,9 @@ const directoryServerSchema = v.object({
category: v.string(),
});
/**
* @category Directory entity types
*/
type DirectoryServer = v.InferOutput<typeof directoryServerSchema>;
export { directoryServerSchema, type DirectoryServer };

View file

@ -1,5 +1,8 @@
import * as v from 'valibot';
/**
* @category Directory schemas
*/
const directoryStatisticsPeriodSchema = v.object({
period: v.pipe(v.string(), v.isoDate()),
server_count: v.fallback(v.nullable(v.pipe(v.unknown(), v.transform(Number))), null),
@ -7,6 +10,9 @@ const directoryStatisticsPeriodSchema = v.object({
active_user_count: v.fallback(v.nullable(v.pipe(v.unknown(), v.transform(Number))), null),
});
/**
* @category Directory entity types
*/
type DirectoryStatisticsPeriod = v.InferOutput<typeof directoryStatisticsPeriodSchema>;
export { directoryStatisticsPeriodSchema, type DirectoryStatisticsPeriod };

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/DomainBlock} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/DomainBlock}
*/
const domainBlockSchema = v.object({
domain: v.string(),
digest: v.string(),
@ -8,6 +11,9 @@ const domainBlockSchema = v.object({
comment: v.fallback(v.optional(v.string()), undefined),
});
/**
* @category Entity types
*/
type DomainBlock = v.InferOutput<typeof domainBlockSchema>;
export { domainBlockSchema, type DomainBlock };

View file

@ -22,6 +22,8 @@ const customEmojiReactionSchema = v.object({
/**
* Pleroma emoji reaction.
*
* @category Schemas
* @see {@link https://docs.pleroma.social/backend/development/API/differences_in_mastoapi_responses/#statuses}
*/
const emojiReactionSchema = v.pipe(
@ -34,6 +36,9 @@ const emojiReactionSchema = v.pipe(
v.union([baseEmojiReactionSchema, customEmojiReactionSchema]),
);
/**
* @category Entity types
*/
type EmojiReaction = v.InferOutput<typeof emojiReactionSchema>;
export { emojiReactionSchema, type EmojiReaction };

View file

@ -2,12 +2,18 @@ import * as v from 'valibot';
import { datetimeSchema } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/ExtendedDescription} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/ExtendedDescription}
*/
const extendedDescriptionSchema = v.object({
updated_at: datetimeSchema,
content: v.string(),
});
/**
* @category Entity types
*/
type ExtendedDescription = v.InferOutput<typeof extendedDescriptionSchema>;
export { extendedDescriptionSchema, type ExtendedDescription };

View file

@ -3,12 +3,18 @@ import * as v from 'valibot';
import { accountSchema } from './account';
import { filteredArray } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/FamiliarFollowers/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/FamiliarFollowers/}
*/
const familiarFollowersSchema = v.object({
id: v.string(),
accounts: filteredArray(accountSchema),
});
/**
* @category Entity types
*/
type FamiliarFollowers = v.InferOutput<typeof familiarFollowersSchema>
export { familiarFollowersSchema, type FamiliarFollowers };

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/FeaturedTag/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/FeaturedTag/}
*/
const featuredTagSchema = v.object({
id: v.string(),
name: v.string(),
@ -9,6 +12,9 @@ const featuredTagSchema = v.object({
last_status_at: v.number(),
});
/**
* @category Entity types
*/
type FeaturedTag = v.InferOutput<typeof featuredTagSchema>;
export { featuredTagSchema, type FeaturedTag };

View file

@ -2,13 +2,19 @@ import * as v from 'valibot';
import { filterSchema } from './filter';
/** @see {@link https://docs.joinmastodon.org/entities/FilterResult/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/FilterResult/}
*/
const filterResultSchema = v.object({
filter: filterSchema,
keyword_matches: v.fallback(v.nullable(v.string()), null),
status_matches: v.fallback(v.nullable(v.string()), null),
});
/**
* @category Entity types
*/
type FilterResult = v.InferOutput<typeof filterResultSchema>;
export { filterResultSchema, type FilterResult };

View file

@ -2,20 +2,29 @@ import * as v from 'valibot';
import { datetimeSchema, filteredArray } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/FilterKeyword/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/FilterKeyword/}
*/
const filterKeywordSchema = v.object({
id: v.string(),
keyword: v.string(),
whole_word: v.boolean(),
});
/** @see {@link https://docs.joinmastodon.org/entities/FilterStatus/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/FilterStatus/}
*/
const filterStatusSchema = v.object({
id: v.string(),
status_id: v.string(),
});
/** @see {@link https://docs.joinmastodon.org/entities/Filter/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Filter/}
*/
const filterSchema = v.pipe(
v.any(),
v.transform((filter: any) => {
@ -44,6 +53,9 @@ const filterSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type Filter = v.InferOutput<typeof filterSchema>;
export { filterKeywordSchema, filterStatusSchema, filterSchema, type Filter };

View file

@ -8,14 +8,23 @@ enum GroupRoles {
USER = 'user'
}
/**
* @category Entity types
*/
type GroupRole =`${GroupRoles}`;
/**
* @category Schemas
*/
const groupMemberSchema = v.object({
id: v.string(),
account: accountSchema,
role: v.enum(GroupRoles),
});
/**
* @category Entity types
*/
type GroupMember = v.InferOutput<typeof groupMemberSchema>;
export { groupMemberSchema, type GroupMember, GroupRoles, type GroupRole };

View file

@ -2,6 +2,9 @@ import * as v from 'valibot';
import { GroupRoles } from './group-member';
/**
* @category Schemas
*/
const groupRelationshipSchema = v.object({
id: v.string(),
member: v.fallback(v.boolean(), false),
@ -9,6 +12,9 @@ const groupRelationshipSchema = v.object({
requested: v.fallback(v.boolean(), false),
});
/**
* @category Entity types
*/
type GroupRelationship = v.InferOutput<typeof groupRelationshipSchema>;
export { groupRelationshipSchema, type GroupRelationship };

View file

@ -4,6 +4,9 @@ import { customEmojiSchema } from './custom-emoji';
import { groupRelationshipSchema } from './group-relationship';
import { datetimeSchema, filteredArray } from './utils';
/**
* @category Schemas
*/
const groupSchema = v.object({
avatar: v.fallback(v.string(), ''),
avatar_static: v.fallback(v.string(), ''),
@ -28,6 +31,9 @@ const groupSchema = v.object({
header_description: v.fallback(v.string(), ''),
});
/**
* @category Entity types
*/
type Group = v.InferOutput<typeof groupSchema>;
export { groupSchema, type Group };

View file

@ -0,0 +1,157 @@
import pick from 'lodash.pick';
import * as v from 'valibot';
import { accountSchema } from './account';
import { accountWarningSchema } from './account-warning';
import { chatMessageSchema } from './chat-message';
import { relationshipSeveranceEventSchema } from './relationship-severance-event';
import { reportSchema } from './report';
import { statusSchema } from './status';
import { datetimeSchema, filteredArray } from './utils';
const partialAccountWithAvatarSchema = v.object({
id: v.string(),
acct: v.string(),
url: v.pipe(v.string(), v.url()),
avatar: v.pipe(v.string(), v.url()),
avatar_static: v.pipe(v.string(), v.url()),
locked: v.boolean(),
bot: v.boolean(),
});
const baseNotificationGroupSchema = v.object({
group_key: v.string(),
notifications_count: v.pipe(v.number(), v.integer()),
most_recent_notification_id: v.pipe(v.unknown(), v.transform(String), v.string()),
page_min_id: v.fallback(v.optional(v.string()), undefined),
page_max_id: v.fallback(v.optional(v.string()), undefined),
latest_page_notification_at: v.fallback(v.optional(datetimeSchema), undefined),
sample_account_ids: v.array(v.string()),
is_muted: v.fallback(v.optional(v.boolean()), undefined),
is_seen: v.fallback(v.optional(v.boolean()), undefined),
});
const accountNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.picklist(['follow', 'follow_request', 'admin.sign_up', 'bite']),
});
const mentionNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.literal('mention'),
subtype: v.fallback(v.nullable(v.picklist(['reply'])), null),
status_id: v.string(),
});
const statusNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.picklist(['status', 'reblog', 'favourite', 'poll', 'update', 'event_reminder']),
status_id: v.string(),
});
const reportNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.literal('admin.report'),
report: reportSchema,
});
const severedRelationshipNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.literal('severed_relationships'),
relationship_severance_event: relationshipSeveranceEventSchema,
});
const moderationWarningNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.literal('moderation_warning'),
moderation_warning: accountWarningSchema,
});
const moveNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.literal('move'),
target_id: v.string(),
});
const emojiReactionNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.literal('emoji_reaction'),
emoji: v.string(),
emoji_url: v.fallback(v.nullable(v.string()), null),
status_id: v.string(),
});
const chatMentionNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.literal('chat_mention'),
chat_message: chatMessageSchema,
});
const eventParticipationRequestNotificationGroupSchema = v.object({
...baseNotificationGroupSchema.entries,
type: v.picklist(['participation_accepted', 'participation_request']),
status_id: v.string(),
participation_message: v.fallback(v.nullable(v.string()), null),
});
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Notification/}
* */
const notificationGroupSchema: v.BaseSchema<any, NotificationGroup, v.BaseIssue<unknown>> = v.pipe(
v.any(),
v.transform((notification: any) => ({
group_key: `ungrouped-${notification.id}`,
...pick(notification.pleroma || {}, ['is_muted', 'is_seen']),
...notification,
type: notification.type === 'pleroma:report'
? 'admin.report'
: notification.type?.replace(/^pleroma:/, ''),
})),
v.variant('type', [
accountNotificationGroupSchema,
mentionNotificationGroupSchema,
statusNotificationGroupSchema,
reportNotificationGroupSchema,
severedRelationshipNotificationGroupSchema,
moderationWarningNotificationGroupSchema,
moveNotificationGroupSchema,
emojiReactionNotificationGroupSchema,
chatMentionNotificationGroupSchema,
eventParticipationRequestNotificationGroupSchema,
])) as any;
/**
* @category Entity types
*/
type NotificationGroup = v.InferOutput<
| typeof accountNotificationGroupSchema
| typeof mentionNotificationGroupSchema
| typeof statusNotificationGroupSchema
| typeof reportNotificationGroupSchema
| typeof severedRelationshipNotificationGroupSchema
| typeof moderationWarningNotificationGroupSchema
| typeof moveNotificationGroupSchema
| typeof emojiReactionNotificationGroupSchema
| typeof chatMentionNotificationGroupSchema
| typeof eventParticipationRequestNotificationGroupSchema
>;
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/methods/grouped_notifications/#GroupedNotificationsResults}
*/
const groupedNotificationsResultsSchema = v.object({
accounts: filteredArray(accountSchema),
partial_accounts: v.fallback(v.optional(v.array(partialAccountWithAvatarSchema)), undefined),
statuses: filteredArray(statusSchema),
notification_groups: filteredArray(notificationGroupSchema),
});
/**
* @category Entity types
*/
type GroupedNotificationsResults = v.InferOutput<typeof groupedNotificationsResultsSchema>;
export { notificationGroupSchema, groupedNotificationsResultsSchema, type NotificationGroup, type GroupedNotificationsResults };

View file

@ -41,6 +41,7 @@ export * from './filter';
export * from './group';
export * from './group-member';
export * from './group-relationship';
export * from './grouped-notifications-results';
export * from './instance';
export * from './interaction-policy';
export * from './interaction-request';

View file

@ -5,7 +5,7 @@ import { accountSchema } from './account';
import { ruleSchema } from './rule';
import { coerceObject, filteredArray, mimeSchema } from './utils';
const getApiVersions = (instance: any) => ({
const getApiVersions = (instance: any): Record<string, number> => ({
...Object.fromEntries(instance.pleroma?.metadata?.features?.map((feature: string) => {
let string = `${feature}.pleroma.pl-api`;
if (string.startsWith('pleroma:') || string.startsWith('pleroma_')) string = string.slice(8);
@ -166,7 +166,6 @@ const pleromaSchema = coerceObject({
birthday_min_age: v.fallback(v.number(), 0),
birthday_required: v.fallback(v.boolean(), false),
description_limit: v.fallback(v.number(), 1500),
features: v.fallback(v.array(v.string()), []),
federation: coerceObject({
enabled: v.fallback(v.boolean(), true), // Assume true unless explicitly false
mrf_policies: v.fallback(v.optional(v.array(v.string())), undefined),
@ -271,7 +270,6 @@ const instanceV1Schema = coerceObject({
description_limit: v.fallback(v.number(), 1500),
email: v.fallback(v.pipe(v.string(), v.email()), ''),
feature_quote: v.fallback(v.boolean(), false),
fedibird_capabilities: v.fallback(v.array(v.string()), []),
languages: v.fallback(v.array(v.string()), []),
max_media_attachments: v.fallback(v.optional(v.number()), undefined),
max_toot_chars: v.fallback(v.optional(v.number()), undefined),
@ -292,7 +290,10 @@ const instanceV1Schema = coerceObject({
version: v.fallback(v.string(), '0.0.0'),
});
/** @see {@link https://docs.joinmastodon.org/entities/Instance/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Instance/}
*/
const instanceSchema = v.pipe(
v.any(),
v.transform((data: any) => {
@ -305,7 +306,7 @@ const instanceSchema = v.pipe(
if (data.domain) return { account_domain: data.domain, ...data, api_versions: apiVersions };
return instanceV1ToV2({ ...data, api_versions: apiVersions });
return { ...instanceV1ToV2(data), api_versions: apiVersions };
}),
coerceObject({
account_domain: v.fallback(v.string(), ''),
@ -315,7 +316,10 @@ const instanceSchema = v.pipe(
description: v.fallback(v.string(), ''),
domain: v.fallback(v.string(), ''),
feature_quote: v.fallback(v.boolean(), false),
fedibird_capabilities: v.fallback(v.array(v.string()), []),
icons: filteredArray(v.object({
size: v.pipe(v.string(), v.regex(/^[0-9]+x[0-9]+$/)),
src: v.string(),
})),
languages: v.fallback(v.array(v.string()), []),
pleroma: pleromaSchema,
registrations: registrations,
@ -328,6 +332,9 @@ const instanceSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type Instance = v.InferOutput<typeof instanceSchema>;
export { instanceSchema, type Instance };

View file

@ -4,6 +4,9 @@ import { coerceObject } from './utils';
const interactionPolicyEntrySchema = v.picklist(['public', 'followers', 'following', 'mutuals', 'mentioned', 'author', 'me']);
/**
* @category Entity types
*/
type InteractionPolicyEntry = v.InferOutput<typeof interactionPolicyEntrySchema>;
const interactionPolicyRuleSchema = coerceObject({
@ -11,15 +14,24 @@ const interactionPolicyRuleSchema = coerceObject({
with_approval: v.fallback(v.array(interactionPolicyEntrySchema), []),
});
/** @see {@link https://docs.gotosocial.org/en/latest/api/swagger/} */
/**
* @category Schemas
* @see {@link https://docs.gotosocial.org/en/latest/api/swagger/}
*/
const interactionPolicySchema = coerceObject({
can_favourite: interactionPolicyRuleSchema,
can_reblog: interactionPolicyRuleSchema,
can_reply: interactionPolicyRuleSchema,
});
/**
* @category Entity types
*/
type InteractionPolicy = v.InferOutput<typeof interactionPolicySchema>;
/**
* @category Schemas
*/
const interactionPoliciesSchema = coerceObject({
public: interactionPolicySchema,
unlisted: interactionPolicySchema,
@ -27,6 +39,9 @@ const interactionPoliciesSchema = coerceObject({
direct: interactionPolicySchema,
});
/**
* @category Entity types
*/
type InteractionPolicies = v.InferOutput<typeof interactionPoliciesSchema>;
export { interactionPolicySchema, interactionPoliciesSchema, type InteractionPolicyEntry, type InteractionPolicy, type InteractionPolicies };

View file

@ -4,7 +4,10 @@ import { accountSchema } from './account';
import { statusSchema } from './status';
import { datetimeSchema } from './utils';
/** @see {@link https://docs.gotosocial.org/en/latest/api/swagger.yaml#/definitions/interactionRequest} */
/**
* @category Schemas
* @see {@link https://docs.gotosocial.org/en/latest/api/swagger.yaml#/definitions/interactionRequest}
*/
const interactionRequestSchema = v.object({
accepted_at: v.fallback(v.nullable(datetimeSchema), null),
account: accountSchema,
@ -17,6 +20,9 @@ const interactionRequestSchema = v.object({
uri: v.fallback(v.nullable(v.string()), null),
});
/**
* @category Entity types
*/
type InteractionRequest = v.InferOutput<typeof interactionRequestSchema>;
export { interactionRequestSchema, type InteractionRequest };

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/List/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/List/}
*/
const listSchema = v.object({
id: v.pipe(v.unknown(), v.transform(String)),
title: v.string(),
@ -8,6 +11,9 @@ const listSchema = v.object({
exclusive: v.fallback(v.optional(v.boolean()), undefined),
});
/**
* @category Entity types
*/
type List = v.InferOutput<typeof listSchema>;
export { listSchema, type List };

View file

@ -1,5 +1,8 @@
import * as v from 'valibot';
/**
* @category Schemas
*/
const locationSchema = v.object({
url: v.fallback(v.pipe(v.string(), v.url()), ''),
description: v.fallback(v.string(), ''),
@ -18,6 +21,9 @@ const locationSchema = v.object({
})), null),
});
/**
* @category Entity types
*/
type Location = v.InferOutput<typeof locationSchema>;
export { locationSchema, type Location };

View file

@ -2,6 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from './utils';
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Marker/}
*/
const markerSchema = v.pipe(
v.any(),
v.transform((marker: any) => marker ? ({
@ -16,11 +20,19 @@ const markerSchema = v.pipe(
}),
);
/** @see {@link https://docs.joinmastodon.org/entities/Marker/} */
/**
* @category Entity types
*/
type Marker = v.InferOutput<typeof markerSchema>;
/**
* @category Schemas
*/
const markersSchema = v.record(v.string(), markerSchema);
/**
* @category Entity types
*/
type Markers = v.InferOutput<typeof markersSchema>;
export {

View file

@ -3,6 +3,9 @@ import * as v from 'valibot';
import { mimeSchema } from './utils';
/**
* @category Schemas
*/
const blurhashSchema = v.pipe(v.string(), v.check(
(value) => isBlurhashValid(value).result,
'invalid blurhash', // .errorReason
@ -87,7 +90,10 @@ const unknownAttachmentSchema = v.object({
type: v.literal('unknown'),
});
/** @see {@link https://docs.joinmastodon.org/entities/MediaAttachment} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/MediaAttachment}
*/
const mediaAttachmentSchema = v.pipe(
v.any(),
v.transform((data: any) => {
@ -108,6 +114,9 @@ const mediaAttachmentSchema = v.pipe(
]),
);
/**
* @category Entity types
*/
type MediaAttachment = v.InferOutput<typeof mediaAttachmentSchema>;
export { blurhashSchema, mediaAttachmentSchema, type MediaAttachment };

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/Status/#Mention} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Status/#Mention}
*/
const mentionSchema = v.pipe(
v.object({
id: v.string(),
@ -17,6 +20,9 @@ const mentionSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type Mention = v.InferOutput<typeof mentionSchema>;
export { mentionSchema, type Mention };

View file

@ -1,17 +1,26 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/NotificationPolicy} */
const notificationPolicyRuleSchema = v.picklist(['accept', 'filter', 'drop']);
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/NotificationPolicy}
*/
const notificationPolicySchema = v.object({
filter_not_following: v.boolean(),
filter_not_followers: v.boolean(),
filter_new_accounts: v.boolean(),
filter_private_mentions: v.boolean(),
for_not_following: notificationPolicyRuleSchema,
for_not_followers: notificationPolicyRuleSchema,
for_new_accounts: notificationPolicyRuleSchema,
for_private_mentions: notificationPolicyRuleSchema,
for_limited_accounts: notificationPolicyRuleSchema,
summary: v.object({
pending_requests_count: v.pipe(v.number(), v.integer()),
pending_notifications_count: v.pipe(v.number(), v.integer()),
}),
});
/**
* @category Entity types
*/
type NotificationPolicy = v.InferOutput<typeof notificationPolicySchema>;
export { notificationPolicySchema, type NotificationPolicy };

View file

@ -4,7 +4,10 @@ import { accountSchema } from './account';
import { statusSchema } from './status';
import { datetimeSchema } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/NotificationRequest} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/NotificationRequest}
*/
const notificationRequestSchema = v.object({
id: v.string(),
created_at: datetimeSchema,
@ -14,6 +17,9 @@ const notificationRequestSchema = v.object({
last_status: v.fallback(v.optional(statusSchema), undefined),
});
/**
* @category Entity types
*/
type NotificationRequest = v.InferOutput<typeof notificationRequestSchema>;
export { notificationRequestSchema, type NotificationRequest };

View file

@ -83,7 +83,10 @@ const eventParticipationRequestNotificationSchema = v.object({
participation_message: v.fallback(v.nullable(v.string()), null),
});
/** @see {@link https://docs.joinmastodon.org/entities/Notification/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Notification/}
* */
const notificationSchema: v.BaseSchema<any, Notification, v.BaseIssue<unknown>> = v.pipe(
v.any(),
v.transform((notification: any) => ({
@ -107,6 +110,9 @@ const notificationSchema: v.BaseSchema<any, Notification, v.BaseIssue<unknown>>
eventParticipationRequestNotificationSchema,
])) as any;
/**
* @category Entity types
*/
type Notification = v.InferOutput<
| typeof accountNotificationSchema
| typeof mentionNotificationSchema

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from './utils';
/** @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#get-apioauth_tokens} */
/**
* @category Schemas
* @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#get-apioauth_tokens}
*/
const oauthTokenSchema = v.pipe(
v.any(),
v.transform((token: any) => ({
@ -16,6 +19,9 @@ const oauthTokenSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type OauthToken = v.InferOutput<typeof oauthTokenSchema>;
export { oauthTokenSchema, type OauthToken };

View file

@ -10,7 +10,10 @@ const pollOptionSchema = v.object({
title_map: v.fallback(v.nullable(v.record(v.string(), v.string())), null),
});
/** @see {@link https://docs.joinmastodon.org/entities/Poll/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Poll/}
*/
const pollSchema = v.object({
emojis: filteredArray(customEmojiSchema),
expired: v.fallback(v.boolean(), false),
@ -26,7 +29,14 @@ const pollSchema = v.object({
non_anonymous: v.fallback(v.boolean(), false),
});
/**
* @category Entity types
*/
type Poll = v.InferOutput<typeof pollSchema>;
/**
* @category Entity types
*/
type PollOption = Poll['options'][number];
export { pollSchema, type Poll, type PollOption };

View file

@ -0,0 +1,20 @@
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),
});
/**
* @category Entity types
*/
type PreviewCardAuthor = v.InferOutput<typeof previewCardAuthorSchema>;
export { previewCardAuthorSchema, type PreviewCardAuthor };

View file

@ -1,9 +1,18 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/PreviewCard/} */
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()), ''),
@ -19,6 +28,9 @@ const previewCardSchema = v.object({
width: v.fallback(v.number(), 0),
});
/**
* @category Entity types
*/
type PreviewCard = v.InferOutput<typeof previewCardSchema>;
export { previewCardSchema, type PreviewCard };

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { datetimeSchema } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/RelationshipSeveranceEvent/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/RelationshipSeveranceEvent/}
*/
const relationshipSeveranceEventSchema = v.object({
id: v.string(),
type: v.picklist(['domain_block', 'user_domain_block', 'account_suspension']),
@ -11,6 +14,9 @@ const relationshipSeveranceEventSchema = v.object({
created_at: datetimeSchema,
});
/**
* @category Entity types
*/
type RelationshipSeveranceEvent = v.InferOutput<typeof relationshipSeveranceEventSchema>;
export { relationshipSeveranceEventSchema, type RelationshipSeveranceEvent };

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/Relationship/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Relationship/}
*/
const relationshipSchema = v.object({
blocked_by: v.fallback(v.boolean(), false),
blocking: v.fallback(v.boolean(), false),
@ -17,6 +20,9 @@ const relationshipSchema = v.object({
showing_reblogs: v.fallback(v.boolean(), false),
});
/**
* @category Entity types
*/
type Relationship = v.InferOutput<typeof relationshipSchema>;
export { relationshipSchema, type Relationship };

View file

@ -3,7 +3,10 @@ import * as v from 'valibot';
import { accountSchema } from './account';
import { datetimeSchema } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/Report/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Report/}
*/
const reportSchema = v.object({
id: v.string(),
action_taken: v.fallback(v.optional(v.boolean()), undefined),
@ -17,6 +20,9 @@ const reportSchema = v.object({
target_account: v.fallback(v.nullable(accountSchema), null),
});
/**
* @category Entity types
*/
type Report = v.InferOutput<typeof reportSchema>;
export { reportSchema, type Report };

View file

@ -2,6 +2,9 @@ import * as v from 'valibot';
const hexSchema = v.pipe(v.string(), v.regex(/^#[a-f0-9]{6}$/i));
/**
* @category Schemas
*/
const roleSchema = v.object({
id: v.fallback(v.string(), ''),
name: v.fallback(v.string(), ''),
@ -10,6 +13,9 @@ const roleSchema = v.object({
highlighted: v.fallback(v.boolean(), true),
});
/**
* @category Entity types
*/
type Role = v.InferOutput<typeof roleSchema>;
export {

View file

@ -6,7 +6,10 @@ const baseRuleSchema = v.object({
hint: v.fallback(v.string(), ''),
});
/** @see {@link https://docs.joinmastodon.org/entities/Rule/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Rule/}
*/
const ruleSchema = v.pipe(
v.any(),
v.transform((data: any) => ({
@ -16,6 +19,9 @@ const ruleSchema = v.pipe(
baseRuleSchema,
);
/**
* @category Entity types
*/
type Rule = v.InferOutput<typeof ruleSchema>;
export { ruleSchema, type Rule };

View file

@ -3,7 +3,10 @@ import * as v from 'valibot';
import { mediaAttachmentSchema } from './media-attachment';
import { datetimeSchema, filteredArray } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/ScheduledStatus/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/ScheduledStatus/}
*/
const scheduledStatusSchema = v.object({
id: v.string(),
scheduled_at: datetimeSchema,
@ -31,6 +34,9 @@ const scheduledStatusSchema = v.object({
media_attachments: filteredArray(mediaAttachmentSchema),
});
/**
* @category Entity types
*/
type ScheduledStatus = v.InferOutput<typeof scheduledStatusSchema>;
export { scheduledStatusSchema, type ScheduledStatus };

View file

@ -3,6 +3,9 @@ import * as v from 'valibot';
import { accountSchema } from './account';
import { datetimeSchema } from './utils';
/**
* @category Schemas
*/
const scrobbleSchema = v.pipe(
v.any(),
v.transform((scrobble: any) => scrobble ? {
@ -21,6 +24,9 @@ const scrobbleSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type Scrobble = v.InferOutput<typeof scrobbleSchema>;
export { scrobbleSchema, type Scrobble };

View file

@ -6,7 +6,10 @@ import { statusSchema } from './status';
import { tagSchema } from './tag';
import { filteredArray } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/Search} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Search}
*/
const searchSchema = v.object({
accounts: filteredArray(accountSchema),
statuses: filteredArray(statusSchema),
@ -14,6 +17,9 @@ const searchSchema = v.object({
groups: filteredArray(groupSchema),
});
/**
* @category Entity types
*/
type Search = v.InferOutput<typeof searchSchema>;
export { searchSchema, type Search };

View file

@ -5,7 +5,10 @@ import { customEmojiSchema } from './custom-emoji';
import { mediaAttachmentSchema } from './media-attachment';
import { datetimeSchema, filteredArray } from './utils';
/** @see {@link https://docs.joinmastodon.org/entities/StatusEdit/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/StatusEdit/}
*/
const statusEditSchema = v.object({
content: v.fallback(v.string(), ''),
spoiler_text: v.fallback(v.string(), ''),
@ -21,6 +24,9 @@ const statusEditSchema = v.object({
emojis: filteredArray(customEmojiSchema),
});
/**
* @category Entity types
*/
type StatusEdit = v.InferOutput<typeof statusEditSchema>;
export { statusEditSchema, type StatusEdit };

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { locationSchema } from './location';
/** @see {@link https://docs.joinmastodon.org/entities/StatusSource/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/StatusSource/}
*/
const statusSourceSchema = v.object({
id: v.string(),
text: v.fallback(v.string(), ''),
@ -15,6 +18,9 @@ const statusSourceSchema = v.object({
spoiler_text_map: v.fallback(v.nullable(v.record(v.string(), v.string())), null),
});
/**
* @category Entity types
*/
type StatusSource = v.InferOutput<typeof statusSourceSchema>;
export { statusSourceSchema, type StatusSource };

View file

@ -134,6 +134,9 @@ const preprocess = (status: any) => {
return status;
};
/**
* @category Schemas
*/
const statusSchema: v.BaseSchema<any, Status, v.BaseIssue<unknown>> = v.pipe(v.any(), v.transform(preprocess), v.object({
...baseStatusSchema.entries,
reblog: v.fallback(v.nullable(v.lazy(() => statusSchema)), null),
@ -141,6 +144,9 @@ const statusSchema: v.BaseSchema<any, Status, v.BaseIssue<unknown>> = v.pipe(v.a
quote: v.fallback(v.nullable(v.lazy(() => statusSchema)), null),
})) as any;
/**
* @category Schemas
*/
const statusWithoutAccountSchema = v.pipe(v.any(), v.transform(preprocess), v.object({
...(v.omit(baseStatusSchema, ['account']).entries),
account: v.fallback(v.nullable(accountSchema), null),
@ -149,12 +155,18 @@ const statusWithoutAccountSchema = v.pipe(v.any(), v.transform(preprocess), v.ob
quote: v.fallback(v.nullable(v.lazy(() => statusSchema)), null),
}));
/**
* @category Entity types
*/
type StatusWithoutAccount = Omit<v.InferOutput<typeof baseStatusSchema>, 'account'> & {
account: Account | null;
reblog: Status | null;
quote: Status | null;
}
/**
* @category Entity types
*/
type Status = v.InferOutput<typeof baseStatusSchema> & {
reblog: Status | null;
quote: Status | null;

View file

@ -8,6 +8,9 @@ import { markersSchema } from './marker';
import { notificationSchema } from './notification';
import { statusSchema } from './status';
/**
* @category Schemas
*/
const followRelationshipUpdateSchema = v.object({
state: v.picklist(['follow_pending', 'follow_accept', 'follow_reject']),
follower: v.object({
@ -22,6 +25,9 @@ const followRelationshipUpdateSchema = v.object({
}),
});
/**
* @category Entity types
*/
type FollowRelationshipUpdate = v.InferOutput<typeof followRelationshipUpdateSchema>;
const baseStreamingEventSchema = v.object({
@ -96,7 +102,15 @@ const markerStreamingEventSchema = v.object({
payload: v.pipe(v.any(), v.transform((payload: any) => JSON.parse(payload)), markersSchema),
});
/** @see {@link https://docs.joinmastodon.org/methods/streaming/#events} */
const notificationsMergedEventSchema = v.object({
...baseStreamingEventSchema.entries,
event: v.literal('notifications_merged'),
});
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/methods/streaming/#events}
*/
const streamingEventSchema: v.BaseSchema<any, StreamingEvent, v.BaseIssue<unknown>> = v.pipe(
v.any(),
v.transform((event: any) => ({
@ -115,9 +129,13 @@ const streamingEventSchema: v.BaseSchema<any, StreamingEvent, v.BaseIssue<unknow
followRelationshipsUpdateStreamingEventSchema,
respondStreamingEventSchema,
markerStreamingEventSchema,
notificationsMergedEventSchema,
]),
) as any;
/**
* @category Entity types
*/
type StreamingEvent = v.InferOutput<
| typeof statusStreamingEventSchema
| typeof stringStreamingEventSchema
@ -130,6 +148,7 @@ type StreamingEvent = v.InferOutput<
| typeof followRelationshipsUpdateStreamingEventSchema
| typeof respondStreamingEventSchema
| typeof markerStreamingEventSchema
| typeof notificationsMergedEventSchema
>;
export {

View file

@ -2,7 +2,10 @@ import * as v from 'valibot';
import { accountSchema } from './account';
/** @see {@link https://docs.joinmastodon.org/entities/Suggestion} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Suggestion}
*/
const suggestionSchema = v.pipe(
v.any(),
v.transform((suggestion: any) => {
@ -39,6 +42,9 @@ const suggestionSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type Suggestion = v.InferOutput<typeof suggestionSchema>;
export { suggestionSchema, type Suggestion };

View file

@ -1,12 +1,18 @@
import * as v from 'valibot';
/**
* @category Schemas
*/
const historySchema = v.array(v.object({
day: v.pipe(v.unknown(), v.transform(Number)),
accounts: v.pipe(v.unknown(), v.transform(Number)),
uses: v.pipe(v.unknown(), v.transform(Number)),
}));
/** @see {@link https://docs.joinmastodon.org/entities/tag} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/tag}
*/
const tagSchema = v.object({
name: v.pipe(v.string(), v.minLength(1)),
url: v.fallback(v.pipe(v.string(), v.url()), ''),
@ -14,6 +20,9 @@ const tagSchema = v.object({
following: v.fallback(v.optional(v.boolean()), undefined),
});
/**
* @category Entity types
*/
type Tag = v.InferOutput<typeof tagSchema>;
export { historySchema, tagSchema, type Tag };

View file

@ -1,18 +1,24 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/Token/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Token/}
*/
const tokenSchema = v.object({
access_token: v.string(),
token_type: v.string(),
scope: v.string(),
created_at: v.fallback(v.optional(v.number()), undefined),
id: v.fallback(v.optional(v.number()), undefined),
id: v.fallback(v.optional(v.pipe(v.unknown(), v.transform(String))), undefined),
refresh_token: v.fallback(v.optional(v.string()), undefined),
expires_in: v.fallback(v.optional(v.number()), undefined),
me: v.fallback(v.optional(v.string()), undefined),
});
/**
* @category Entity types
*/
type Token = v.InferOutput<typeof tokenSchema>;
export { tokenSchema, type Token };

View file

@ -14,7 +14,10 @@ const translationMediaAttachment = v.object({
description: v.fallback(v.string(), ''),
});
/** @see {@link https://docs.joinmastodon.org/entities/Translation/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/Translation/}
*/
const translationSchema = v.pipe(
v.any(),
v.transform((translation: any) => {
@ -40,6 +43,9 @@ const translationSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type Translation = v.InferOutput<typeof translationSchema>;
export { translationSchema, type Translation };

View file

@ -3,7 +3,10 @@ import * as v from 'valibot';
import { blurhashSchema } from './media-attachment';
import { historySchema } from './tag';
/** @see {@link https://docs.joinmastodon.org/entities/PreviewCard/#trends-link} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/PreviewCard/#trends-link}
*/
const trendsLinkSchema = v.pipe(
v.any(),
v.transform((link: any) => ({ ...link, id: link.url })),
@ -28,6 +31,9 @@ const trendsLinkSchema = v.pipe(
}),
);
/**
* @category Entity types
*/
type TrendsLink = v.InferOutput<typeof trendsLinkSchema>;
export { trendsLinkSchema, type TrendsLink };

View file

@ -1,6 +1,9 @@
import * as v from 'valibot';
/** @see {@link https://docs.joinmastodon.org/entities/WebPushSubscription/} */
/**
* @category Schemas
* @see {@link https://docs.joinmastodon.org/entities/WebPushSubscription/}
*/
const webPushSubscriptionSchema = v.object({
id: v.pipe(v.unknown(), v.transform(String)),
endpoint: v.string(),
@ -8,6 +11,9 @@ const webPushSubscriptionSchema = v.object({
server_key: v.string(),
});
/**
* @category Entity types
*/
type WebPushSubscription = v.InferOutput<typeof webPushSubscriptionSchema>;
export { webPushSubscriptionSchema, type WebPushSubscription };

View file

@ -9,104 +9,151 @@ const any = (arr: Array<any>): boolean => arr.some(Boolean);
/**
* Ditto, a Nostr server with Mastodon API.
*
* @category Software
* @see {@link https://gitlab.com/soapbox-pub/ditto}
*/
const DITTO = 'Ditto';
/**
* Firefish, a fork of Misskey. Formerly known as Calckey.
*
* @category Software
* @see {@link https://joinfirefish.org/}
*/
const FIREFISH = 'Firefish';
/**
* Friendica, decentralized social platform implementing multiple federation protocols.
*
* @category Software
* @see {@link https://friendi.ca/}
*/
const FRIENDICA = 'Friendica';
/**
* GoToSocial, an ActivityPub server written in Golang.
*
* @category Software
* @see {@link https://gotosocial.org/}
*/
const GOTOSOCIAL = 'GoToSocial';
/**
* Iceshrimp, yet another Misskey fork.
*
* @category Software
* @see {@link https://iceshrimp.dev/}
*/
const ICESHRIMP = 'Iceshrimp';
/**
* Iceshrimp.NET, a decentralized and federated social networking service, powered by .NET.
*
* @category Software
* @see {@link https://iceshrimp.dev/}
*/
const ICESHRIMP_NET = 'Iceshrimp.NET';
/**
* Mastodon, the software upon which this is all based.
*
* @category Software
* @see {@link https://joinmastodon.org/}
*/
const MASTODON = 'Mastodon';
/**
* Mitra, a Rust backend with cryptocurrency integrations.
*
* @category Software
* @see {@link https://codeberg.org/silverpill/mitra}
*/
const MITRA = 'Mitra';
/**
* Pixelfed, a federated image sharing platform.
*
* @category Software
* @see {@link https://pixelfed.org/}
*/
const PIXELFED = 'Pixelfed';
/**
* Pleroma, a feature-rich alternative written in Elixir.
*
* @category Software
* @see {@link https://pleroma.social/}
*/
const PLEROMA = 'Pleroma';
/**
* Takahē, backend with support for serving multiple domains.
*
* @category Software
* @see {@link https://jointakahe.org/}
*/
const TAKAHE = 'Takahe';
/**
* Toki, a C# Fediverse server.
*
* @category Software
* @see {@link https://github.com/purifetchi/Toki}
*/
const TOKI = 'Toki';
/**
* Akkoma, a Pleroma fork.
*
* @category Software
* @see {@link https://akkoma.dev/AkkomaGang/akkoma}
*/
const AKKOMA = 'akkoma';
/**
* glitch-soc, fork of Mastodon with a number of experimental features.
*
* @category Software
* @see {@link https://glitch-soc.github.io/docs/}
*/
const GLITCH = 'glitch';
/**
* glitch-soc, fork of Mastodon that provides local posting and a wider range of content types.
*
* @category Software
* @see {@link https://github.com/hometown-fork/hometown}
*/
const HOMETOWN = 'hometown';
/**
* Pl, fork of Pleroma developed by pl-api author.
*
* @category Software
* @see {@link https://github.com/mkljczk/pl}
*/
const PL = 'pl';
/**
* Rebased, fork of Pleroma developed by Soapbox author.
*
* @category Software
* @see {@link https://gitlab.com/soapbox-pub/rebased}
*/
const REBASED = 'soapbox';
/** Backend name reserved only for tests. */
/**
* Backend name reserved only for tests.
*
* @category Software
*/
const UNRELEASED = 'unreleased';
/** Parse features for the given instance */
/**
* Parse features for the given instance
* @category Utils
*/
const getFeatures = (instance: Instance) => {
const v = parseVersion(instance.version || '');
const federation = !!instance.pleroma.metadata.federation.enabled;
@ -210,6 +257,7 @@ const getFeatures = (instance: Instance) => {
announcements: any([
v.software === FIREFISH,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA,
v.software === TAKAHE && gte(v.version, '0.7.0'),
@ -236,6 +284,7 @@ const getFeatures = (instance: Instance) => {
* see POST /api/v1/bite
*/
bites: any([
v.software === ICESHRIMP_NET,
v.software === TOKI,
instance.api_versions['bites.pleroma.pl-api'] >= 1,
]),
@ -262,6 +311,7 @@ const getFeatures = (instance: Instance) => {
v.software === FIREFISH,
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === FRIENDICA,
v.software === MASTODON,
v.software === MITRA && gte(v.version, '3.3.0'),
@ -278,6 +328,7 @@ const getFeatures = (instance: Instance) => {
bots: any([
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA,
]),
@ -312,6 +363,7 @@ const getFeatures = (instance: Instance) => {
v.software === FRIENDICA,
v.software === GOTOSOCIAL && gte(v.version, '0.17.0'),
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PIXELFED,
v.software === PLEROMA,
@ -392,6 +444,7 @@ const getFeatures = (instance: Instance) => {
v.software === FRIENDICA,
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === MITRA,
v.software === PIXELFED,
@ -408,6 +461,7 @@ const getFeatures = (instance: Instance) => {
v.software === FIREFISH,
v.software === FRIENDICA && gte(v.version, '2022.12.0'),
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === MITRA,
v.software === TAKAHE && gte(v.version, '0.8.0'),
@ -480,6 +534,7 @@ const getFeatures = (instance: Instance) => {
v.software === FRIENDICA,
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === TAKAHE && gte(v.version, '0.6.1'),
v.software === TOKI,
@ -516,6 +571,7 @@ const getFeatures = (instance: Instance) => {
*/
filtersV2: any([
v.software === GOTOSOCIAL && gte(v.version, '0.16.0'),
v.software === ICESHRIMP_NET,
v.software === MASTODON,
]),
@ -577,9 +633,19 @@ const getFeatures = (instance: Instance) => {
*/
frontendConfigurations: any([
v.software === DITTO,
v.software === ICESHRIMP_NET,
v.software === PLEROMA,
]),
/**
* @see GET /api/v2/notifications/:group_key
* @see GET /api/v2/notifications/:group_key
* @see POST /api/v2/notifications/:group_key/dismiss
* @see GET /api/v2/notifications/:group_key/accounts
* @see GET /api/v2/notifications/unread_count
*/
groupedNotifications: instance.api_versions.mastodon >= 2,
/**
* Groups.
* @see POST /api/v1/groups
@ -606,7 +672,9 @@ const getFeatures = (instance: Instance) => {
* @see POST /api/v1/admin/groups/:group_id/unsuspend
* @see DELETE /api/v1/admin/groups/:group_id
*/
groups: instance.api_versions['pleroma:groups.pleroma.pl-api'] >= 1,
groups: instance.api_versions['groups.pleroma.pl-api'] >= 1,
groupsSlugs: instance.api_versions['groups.pleroma.pl-api'] >= 1,
/**
* Can hide follows/followers lists and counts.
@ -692,6 +760,7 @@ const getFeatures = (instance: Instance) => {
v.software === FRIENDICA,
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA,
]),
@ -762,6 +831,7 @@ const getFeatures = (instance: Instance) => {
mediaV2: any([
v.software === FIREFISH,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === MITRA,
v.software === PLEROMA,
@ -792,6 +862,7 @@ const getFeatures = (instance: Instance) => {
v.software === FRIENDICA,
v.software === GOTOSOCIAL && gte(v.version, '0.16.0'),
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === MITRA,
v.software === PIXELFED,
@ -807,6 +878,7 @@ const getFeatures = (instance: Instance) => {
v.software === FIREFISH,
v.software === GOTOSOCIAL && gte(v.version, '0.16.0'),
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA,
v.software === TAKAHE,
@ -833,6 +905,11 @@ const getFeatures = (instance: Instance) => {
*/
notificationsExcludeVisibilities: v.software === PLEROMA,
/**
* @see GET /api/v1/notifications/unread_count
*/
notificationsGetUnreadCount: instance.api_versions.mastodon >= 1,
/**
* Allows specifying notification types to include, rather than to exclude.
* @see GET /api/v1/notifications
@ -840,12 +917,25 @@ const getFeatures = (instance: Instance) => {
notificationsIncludeTypes: any([
v.software === FIREFISH,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA && gte(v.version, '2.5.0'),
v.software === TAKAHE && gte(v.version, '0.6.2'),
v.software === GOTOSOCIAL,
]),
/**
* @see GET /api/v2/notifications/policy
* @see PATCH /api/v2/notifications/policy
*/
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,
/**
@ -890,6 +980,7 @@ const getFeatures = (instance: Instance) => {
polls: any([
v.software === FIREFISH,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === TAKAHE && gte(v.version, '0.8.0'),
v.software === GOTOSOCIAL,
@ -936,12 +1027,14 @@ const getFeatures = (instance: Instance) => {
* @see PATCH /api/v1/accounts/update_credentials
*/
profileFields: any([
v.software === DITTO,
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === MITRA,
v.software === PLEROMA,
v.software === TAKAHE && gte(v.version, '0.7.0'),
v.software === MITRA,
v.software === GOTOSOCIAL,
]),
/**
@ -961,6 +1054,7 @@ const getFeatures = (instance: Instance) => {
v.software === FRIENDICA,
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA,
v.software === TAKAHE,
@ -972,6 +1066,7 @@ const getFeatures = (instance: Instance) => {
* @see POST /api/v1/statuses
*/
quotePosts: any([
v.software === ICESHRIMP_NET,
v.software === FRIENDICA && gte(v.version, '2023.3.0'),
v.software === PLEROMA && [REBASED, AKKOMA].includes(v.build!) && gte(v.version, '2.5.0'),
instance.api_versions['quote_posting.pleroma.pl-api'] >= 1,
@ -983,6 +1078,7 @@ const getFeatures = (instance: Instance) => {
* @see POST /api/v1/statuses/:id/reblog
*/
reblogVisibility: any([
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA,
]),
@ -998,6 +1094,7 @@ const getFeatures = (instance: Instance) => {
* @see POST /api/v1/accounts/:id/remove_from_followers
*/
removeFromFollowers: any([
v.software === ICESHRIMP_NET,
v.software === MASTODON,
v.software === PLEROMA && gte(v.version, '2.5.0'),
v.software === PLEROMA && v.build === AKKOMA,
@ -1056,10 +1153,11 @@ const getFeatures = (instance: Instance) => {
* @see POST /api/v2/search
*/
searchFromAccount: any([
v.software === DITTO,
v.software === GOTOSOCIAL,
v.software === ICESHRIMP,
v.software === MASTODON,
v.software === PLEROMA,
v.software === GOTOSOCIAL,
]),
/**
@ -1216,7 +1314,7 @@ interface Backend {
/** Get information about the software from its version string */
const parseVersion = (version: string): Backend => {
const regex = /^([\w+.-]*)(?: \(compatible; ([\w]*) (.*)\))?$/;
const regex = /^([\w+.-]*)(?: \(compatible; ([\w.]*) (.*)\))?$/;
const match = regex.exec(version.replace('/', ' '));
const semverString = match && (match[3] || match[1]);
@ -1249,6 +1347,7 @@ export {
FRIENDICA,
GOTOSOCIAL,
ICESHRIMP,
ICESHRIMP_NET,
MASTODON,
MITRA,
PIXELFED,

View file

@ -1,7 +1,13 @@
import type { LanguageParam, OnlyEventsParam, OnlyMediaParam, PaginationParams, WithMutedParam, WithRelationshipsParam } from './common';
/**
* @category Request params
*/
type GetAccountParams = WithMutedParam;
/**
* @category Request params
*/
interface GetAccountStatusesParams extends PaginationParams, WithMutedParam, OnlyEventsParam, OnlyMediaParam, LanguageParam {
/** Boolean. Filter out statuses in reply to a different account. */
exclude_replies?: boolean;
@ -11,9 +17,19 @@ interface GetAccountStatusesParams extends PaginationParams, WithMutedParam, Onl
tagged?: string;
}
/**
* @category Request params
*/
type GetAccountFollowersParams = PaginationParams & WithRelationshipsParam;
/**
* @category Request params
*/
type GetAccountFollowingParams = PaginationParams & WithRelationshipsParam;
/**
* @category Request params
*/
interface FollowAccountParams {
/** Boolean. Receive this accounts reblogs in home timeline? Defaults to true. */
reblogs?: boolean;
@ -21,16 +37,22 @@ 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 accounts posts in all languages.
* Requires `features.followAccountLanguages`.
* Requires features{@link Features['followAccountLanguages']}.
*/
languages?: string[];
}
/**
* @category Request params
*/
interface GetRelationshipsParams {
/** Boolean. Whether relationships should be returned for suspended users, defaults to false. */
with_suspended?: boolean;
}
/**
* @category Request params
*/
interface SearchAccountParams {
/** Integer. Maximum number of results. Defaults to 40 accounts. Max 80 accounts. */
limit?: number;
@ -42,6 +64,9 @@ interface SearchAccountParams {
following?: boolean;
}
/**
* @category Request params
*/
interface ReportAccountParams {
status_ids?: string[];
comment?: string;
@ -50,11 +75,24 @@ interface ReportAccountParams {
rule_ids?: string[];
}
/**
* @category Request params
*/
type GetAccountEndorsementsParams = WithRelationshipsParam;
/**
* @category Request params
*/
type GetAccountFavouritesParams = PaginationParams;
/**
* @category Request params
*/
type GetScrobblesParams = PaginationParams;
/**
* @category Request params
*/
interface CreateScrobbleParams {
/** the title of the media playing */
title: string;

View file

@ -1,5 +1,8 @@
import type { PaginationParams } from './common';
/**
* @category Request params
*/
interface AdminGetAccountsParams extends PaginationParams {
/** String. Filter for `local` or `remote` accounts. */
origin?: 'local' | 'remote';
@ -23,8 +26,14 @@ interface AdminGetAccountsParams extends PaginationParams {
ip?: string;
}
/**
* @category Request params
*/
type AdminAccountAction = 'none' | 'sensitive' | 'disable' | 'silence' | 'suspend';
/**
* @category Request params
*/
interface AdminPerformAccountActionParams {
/** String. The ID of an associated report that caused this action to be taken. */
report_id?: string;
@ -36,8 +45,14 @@ interface AdminPerformAccountActionParams {
send_email_notification?: boolean;
}
/**
* @category Request params
*/
type AdminGetDomainBlocksParams = PaginationParams;
/**
* @category Request params
*/
interface AdminCreateDomainBlockParams {
/** String. Whether to apply a `silence`, `suspend`, or `noop` to the domain. Defaults to `silence` */
severity?: 'silence' | 'suspend' | 'noop';
@ -53,8 +68,14 @@ interface AdminCreateDomainBlockParams {
obfuscate?: boolean;
}
/**
* @category Request params
*/
type AdminUpdateDomainBlockParams = AdminCreateDomainBlockParams;
/**
* @category Request params
*/
interface AdminGetReportsParams extends PaginationParams {
/** Boolean. Filter for resolved reports? */
resolved?: boolean;
@ -64,6 +85,9 @@ interface AdminGetReportsParams extends PaginationParams {
target_account_id?: string;
}
/**
* @category Request params
*/
interface AdminUpdateReportParams {
/** String. Change the classification of the report to `spam`, `violation`, or `other`. */
category?: 'spam' | 'violation' | 'other';
@ -71,6 +95,9 @@ interface AdminUpdateReportParams {
rule_ids?: string[];
}
/**
* @category Request params
*/
interface AdminGetStatusesParams {
limit?: number;
local_only?: boolean;
@ -78,15 +105,27 @@ interface AdminGetStatusesParams {
with_private?: boolean;
}
/**
* @category Request params
*/
interface AdminUpdateStatusParams {
sensitive?: boolean;
visibility?: 'public' | 'private' | 'unlisted';
}
/**
* @category Request params
*/
type AdminGetCanonicalEmailBlocks = PaginationParams;
/**
* @category Request params
*/
type AdminDimensionKey = 'languages' | 'sources' | 'servers' | 'space_usage' | 'software_versions' | 'tag_servers' | 'tag_languages' | 'instance_accounts' | 'instance_languages';
/**
* @category Request params
*/
interface AdminGetDimensionsParams {
/** String (ISO 8601 Datetime). The start date for the time period. If a time is provided, it will be ignored. */
start_at?: string;
@ -112,12 +151,24 @@ interface AdminGetDimensionsParams {
};
}
/**
* @category Request params
*/
type AdminGetDomainAllowsParams = PaginationParams;
/**
* @category Request params
*/
type AdminGetEmailDomainBlocksParams = PaginationParams;
/**
* @category Request params
*/
type AdminGetIpBlocksParams = PaginationParams;
/**
* @category Request params
*/
interface AdminCreateIpBlockParams {
/** String. The IP address and prefix to block. Defaults to 0.0.0.0/32 */
ip?: string;
@ -129,10 +180,19 @@ interface AdminCreateIpBlockParams {
expires_in?: number;
}
/**
* @category Request params
*/
type AdminUpdateIpBlockParams = Partial<AdminCreateIpBlockParams>;
/**
* @category Request params
*/
type AdminMeasureKey = 'active_users' | 'new_users' | 'interactions' | 'opened_reports' | 'resolved_reports' | 'tag_accounts' | 'tag_uses' | 'tag_servers' | 'instance_accounts' | 'instance_media_attachments' | 'instance_reports' | 'instance_statuses' | 'instance_follows' | 'instance_followers';
/**
* @category Request params
*/
interface AdminGetMeasuresParams {
tag_accounts?: {
/** String. When `tag_accounts` is one of the requested keys, you must provide a tag ID to obtain the measure of how many accounts used that hashtag in at least one status within the given time period. */
@ -172,11 +232,17 @@ interface AdminGetMeasuresParams {
};
}
/**
* @category Request params
*/
interface AdminGetAnnouncementsParams {
offset?: number;
limit?: number;
}
/**
* @category Request params
*/
interface AdminCreateAnnouncementParams {
/** announcement content */
content: string;
@ -188,8 +254,14 @@ interface AdminCreateAnnouncementParams {
all_day?: boolean;
}
/**
* @category Request params
*/
type AdminUpdateAnnouncementParams = Partial<AdminCreateAnnouncementParams>;
/**
* @category Request params
*/
interface AdminCreateDomainParams {
/** domain name */
domain: string;
@ -197,6 +269,9 @@ interface AdminCreateDomainParams {
public?: boolean;
}
/**
* @category Request params
*/
interface AdminGetModerationLogParams extends Pick<PaginationParams, 'limit'> {
/** page number */
page?: number;
@ -210,14 +285,23 @@ interface AdminGetModerationLogParams extends Pick<PaginationParams, 'limit'> {
search?: string;
}
/**
* @category Request params
*/
interface AdminCreateRuleParams {
text: string;
hint?: string;
priority?: number;
}
/**
* @category Request params
*/
type AdminUpdateRuleParams = Partial<AdminCreateRuleParams>;
/**
* @category Request params
*/
interface AdminGetGroupsParams {
}

View file

@ -1,3 +1,6 @@
/**
* @category Request params
*/
interface CreateApplicationParams {
/** String. A name for your application */
client_name: string;

View file

@ -1,8 +1,18 @@
import { PaginationParams, WithMutedParam } from './common';
/**
* @category Request params
*/
type GetChatsParams = PaginationParams & WithMutedParam;
/**
* @category Request params
*/
type GetChatMessagesParams = PaginationParams;
/**
* @category Request params
*/
type CreateChatMessageParams = {
content?: string;
media_id: string;

View file

@ -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;
}

View file

@ -1,5 +1,8 @@
import { PaginationParams } from './common';
/**
* @category Request params
*/
interface CreateEventParams {
/** name of the event */
name: string;
@ -19,9 +22,24 @@ interface CreateEventParams {
content_type?: string;
}
/**
* @category Request params
*/
type EditEventParams = Partial<Omit<CreateEventParams, 'join_mode'>>;
/**
* @category Request params
*/
type GetJoinedEventsParams = PaginationParams;
/**
* @category Request params
*/
type GetEventParticipationsParams = PaginationParams;
/**
* @category Request params
*/
type GetEventParticipationRequestsParams = PaginationParams;
export type {

View file

@ -1,5 +1,8 @@
import type { PaginationParams, WithRelationshipsParam } from './common';
/**
* @category Request params
*/
interface MuteAccountParams {
/** Boolean. Mute notifications in addition to statuses? Defaults to true. */
notifications?: boolean;
@ -7,12 +10,29 @@ interface MuteAccountParams {
duration?: number;
}
/**
* @category Request params
*/
type GetMutesParams = Omit<PaginationParams, 'min_id'> & WithRelationshipsParam;
/**
* @category Request params
*/
type GetBlocksParams = PaginationParams & WithRelationshipsParam;
/**
* @category Request params
*/
type GetDomainBlocksParams = PaginationParams;
/**
* @category Request params
*/
type FilterContext = 'home' | 'notifications' | 'public' | 'thread' | 'account';
/**
* @category Request params
*/
interface CreateFilterParams {
title: string;
context: Array<FilterContext>;
@ -24,6 +44,9 @@ interface CreateFilterParams {
}>;
}
/**
* @category Request params
*/
interface UpdateFilterParams {
title?: string;
context?: Array<FilterContext>;

View file

@ -0,0 +1,37 @@
import type { PaginationParams } from './common';
/**
* @category Request params
*/
interface GetGroupedNotificationsParams extends PaginationParams {
/** Types to include in the result. */
types?: Array<string>;
/** Types to exclude from the results. */
exclude_types?: Array<string>;
/** Return only notifications received from the specified account. */
acccount_id?: string;
/** One of `full` (default) or `partial_avatars`. When set to `partial_avatars`, some accounts will not be rendered in full in the returned `accounts` list but will be instead returned in stripped-down form in the `partial_accounts` list. The most recent account in a notification group is always rendered in full in the `accounts` attribute. */
expand_accounts?: 'full' | 'partial_avatars';
/** Restrict which notification types can be grouped. Use this if there are notification types for which your client does not support grouping. If omitted, the server will group notifications of all types it supports (currently, `favourite`, `follow` and `reblog`). If you do not want any notification grouping, use GET `/api/v1/notifications` instead. Notifications that would be grouped if not for this parameter will instead be returned as individual single-notification groups with a unique `group_key` that can be assumed to be of the form `ungrouped-{notification_id}`. Please note that neither the streaming API nor the individual notification APIs are aware of this parameter and will always include a “proper” `group_key` that can be different from what is returned here, meaning that you may have to ignore `group_key` for such notifications that you do not want grouped and use `ungrouped-{notification_id}` instead for consistency. */
grouped_types?: Array<string>;
/** Whether to include notifications filtered by the users NotificationPolicy. Defaults to false. */
include_filtered?: boolean;
}
/**
* @category Request params
*/
interface GetUnreadNotificationGroupCountParams {
/** Maximum number of results to return. Defaults to 100 notifications. Max 1000 notifications. */
limit?: number;
/** Types of notifications that should count towards unread notifications. */
types?: Array<string>;
/** Types of notifications that should not count towards unread notifications. */
exclude_types?: Array<string>;
/** Only count unread notifications received from the specified account. */
account_id?: string;
/** Restrict which notification types can be grouped. Use this if there are notification types for which your client does not support grouping. If omitted, the server will group notifications of all types it supports (currently, `favourite`, `follow` and `reblog`). If you do not want any notification grouping, use GET /api/v1/notifications/unread_count instead. */
grouped_types?: Array<string>;
}
export type { GetGroupedNotificationsParams, GetUnreadNotificationGroupCountParams };

View file

@ -1,5 +1,8 @@
import type { PaginationParams } from './common';
/**
* @category Request params
*/
interface CreateGroupParams {
display_name: string;
note?: string;
@ -7,6 +10,9 @@ interface CreateGroupParams {
header?: File;
}
/**
* @category Request params
*/
interface UpdateGroupParams {
display_name?: string;
note?: string;
@ -14,8 +20,19 @@ interface UpdateGroupParams {
header?: File | '';
}
/**
* @category Request params
*/
type GetGroupMembershipsParams = Omit<PaginationParams, 'min_id'>;
/**
* @category Request params
*/
type GetGroupMembershipRequestsParams = Omit<PaginationParams, 'min_id'>;
/**
* @category Request params
*/
type GetGroupBlocksParams = Omit<PaginationParams, 'min_id'>;
export type {

View file

@ -4,6 +4,7 @@ export * from './apps';
export * from './chats';
export * from './events';
export * from './filtering';
export * from './grouped-notifications';
export * from './groups';
export * from './instance';
export * from './interaction-requests';

View file

@ -1,3 +1,6 @@
/**
* @category Request params
*/
interface ProfileDirectoryParams {
/** Number. Skip the first n results. */
offset?: number;

View file

@ -1,5 +1,8 @@
import { PaginationParams } from './common';
/**
* @category Request params
*/
interface GetInteractionRequestsParams extends PaginationParams {
/** If set, then only interactions targeting the given status_id will be included in the results. */
status_id?: string;

Some files were not shown because too many files have changed in this diff Show more