Files
ncd-fe/packages/pl-api/lib/client/accounts.ts
nicole mikołajczyk d5d453e645 pl-api: allow importing parts of the client
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2026-02-23 10:39:26 +01:00

454 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as v from 'valibot';
import {
accountSchema,
antennaSchema,
circleSchema,
familiarFollowersSchema,
featuredTagSchema,
listSchema,
relationshipSchema,
reportSchema,
scrobbleSchema,
statusSchema,
} from '../entities';
import { filteredArray } from '../entities/utils';
import { ICESHRIMP_NET, PIXELFED, PLEROMA } from '../features';
import { type RequestMeta } from '../request';
import type { PlApiBaseClient } from '../client-base';
import type {
CreateScrobbleParams,
FollowAccountParams,
GetAccountEndorsementsParams,
GetAccountFavouritesParams,
GetAccountFollowersParams,
GetAccountFollowingParams,
GetAccountParams,
GetAccountStatusesParams,
GetAccountSubscribersParams,
GetRelationshipsParams,
GetScrobblesParams,
ReportAccountParams,
SearchAccountParams,
} from '../params/accounts';
type EmptyObject = Record<string, never>;
const accounts = (client: PlApiBaseClient) => ({
/**
* Get account
* View information about a profile.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#get}
*/
getAccount: async (accountId: string, params?: GetAccountParams) => {
const response = await client.request(`/api/v1/accounts/${accountId}`, { params });
return v.parse(accountSchema, response.json);
},
/**
* Get multiple accounts
* View information about multiple profiles.
*
* Requires features{@link Features.getAccounts}.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#index}
*/
getAccounts: async (accountId: string[]) => {
const response = await client.request('/api/v1/accounts', { params: { id: accountId } });
return v.parse(filteredArray(accountSchema), response.json);
},
/**
* Get accounts statuses
* Statuses posted to the given account.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#statuses}
*/
getAccountStatuses: (accountId: string, params?: GetAccountStatusesParams) =>
client.paginatedGet(`/api/v1/accounts/${accountId}/statuses`, { params }, statusSchema),
/**
* Get accounts followers
* Accounts which follow the given account, if network is not hidden by the account owner.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#followers}
*/
getAccountFollowers: (accountId: string, params?: GetAccountFollowersParams) =>
client.paginatedGet(`/api/v1/accounts/${accountId}/followers`, { params }, accountSchema),
/**
* Get accounts following
* Accounts which the given account is following, if network is not hidden by the account owner.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#following}
*/
getAccountFollowing: (accountId: string, params?: GetAccountFollowingParams) =>
client.paginatedGet(`/api/v1/accounts/${accountId}/following`, { params }, accountSchema),
/**
* Subscriptions to the given user.
*
* Requires features{@link Features.subscriptions}.
*/
getAccountSubscribers: (accountId: string, params?: GetAccountSubscribersParams) =>
client.paginatedGet(`/api/v1/accounts/${accountId}/subscribers`, { params }, accountSchema),
/**
* Get accounts featured tags
* Tags featured by this account.
*
* Requires features{@link Features.featuredTags}.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#featured_tags}
*/
getAccountFeaturedTags: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/featured_tags`);
return v.parse(filteredArray(featuredTagSchema), response.json);
},
/**
* Get lists containing this account
* User lists that you have added this account to.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#lists}
*/
getAccountLists: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/lists`);
return v.parse(filteredArray(listSchema), response.json);
},
/**
* Get antennas containing this account
* User antennas that you have added this account to.
* Requires features{@link Features.antennas}.
*/
getAccountAntennas: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/antennas`);
return v.parse(filteredArray(antennaSchema), response.json);
},
/**
* Get antennas excluding this account
* Requires features{@link Features.antennas}.
*/
getAccountExcludeAntennas: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/exclude_antennas`);
return v.parse(filteredArray(circleSchema), response.json);
},
/**
* Get circles including this account
* User circles that you have added this account to.
* Requires features{@link Features.circles}.
*/
getAccountCircles: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/circles`);
return v.parse(filteredArray(antennaSchema), response.json);
},
/**
* Follow account
* Follow the given account. Can also be used to update whether to show reblogs or enable notifications.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#follow}
*/
followAccount: async (accountId: string, params?: FollowAccountParams) => {
const response = await client.request(`/api/v1/accounts/${accountId}/follow`, {
method: 'POST',
body: params,
});
return v.parse(relationshipSchema, response.json);
},
/**
* Unfollow account
* Unfollow the given account.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#unfollow}
*/
unfollowAccount: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/unfollow`, {
method: 'POST',
});
return v.parse(relationshipSchema, response.json);
},
/**
* Remove account from followers
* Remove the given account from your followers.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#remove_from_followers}
*/
removeAccountFromFollowers: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/remove_from_followers`, {
method: 'POST',
});
return v.parse(relationshipSchema, response.json);
},
/**
* Feature account on your profile
* Add the given account to the users featured profiles.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#pin}
*/
pinAccount: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/pin`, { method: 'POST' });
return v.parse(relationshipSchema, response.json);
},
/**
* Unfeature account from profile
* Remove the given account from the users featured profiles.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#unpin}
*/
unpinAccount: async (accountId: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/unpin`, {
method: 'POST',
});
return v.parse(relationshipSchema, response.json);
},
/**
* Set private note on profile
* Sets a private note on a user.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#note}
*/
updateAccountNote: async (accountId: string, comment: string) => {
const response = await client.request(`/api/v1/accounts/${accountId}/note`, {
method: 'POST',
body: { comment },
});
return v.parse(relationshipSchema, response.json);
},
/**
* Check relationships to other accounts
* Find out whether a given account is followed, blocked, muted, etc.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#relationships}
*/
getRelationships: async (accountIds: string[], params?: GetRelationshipsParams) => {
const response = await client.request('/api/v1/accounts/relationships', {
params: { ...params, id: accountIds },
});
return v.parse(filteredArray(relationshipSchema), response.json);
},
/**
* Find familiar followers
* Obtain a list of all accounts that follow a given account, filtered for accounts you follow.
*
* Requires features{@link Features.familiarFollowers}.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#familiar_followers}
*/
getFamiliarFollowers: async (accountIds: string[]) => {
let response: any;
if (client.features.version.software === PIXELFED) {
const settledResponse = await Promise.allSettled(
accountIds.map(async (accountId) => {
const accounts = (await client.request(`/api/v1.1/accounts/mutuals/${accountId}`)).json;
return {
id: accountId,
accounts,
};
}),
);
response = settledResponse.map((result, index) =>
result.status === 'fulfilled'
? result.value
: {
id: accountIds[index],
accounts: [],
},
);
} else {
response = (
await client.request('/api/v1/accounts/familiar_followers', { params: { id: accountIds } })
).json;
}
return v.parse(filteredArray(familiarFollowersSchema), response);
},
/**
* Search for matching accounts
* Search for matching accounts by username or display name.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#search}
*/
searchAccounts: async (q: string, params?: SearchAccountParams, meta?: RequestMeta) => {
const response = await client.request('/api/v1/accounts/search', {
...meta,
params: { ...params, q },
});
return v.parse(filteredArray(accountSchema), response.json);
},
/**
* Lookup account ID from Webfinger address
* Quickly lookup a username to see if it is available, skipping WebFinger resolution.
* Requires features{@link Features.accountLookup}.
* @see {@link https://docs.joinmastodon.org/methods/accounts/#lookup}
*/
lookupAccount: async (acct: string, meta?: RequestMeta) => {
const response = await client.request('/api/v1/accounts/lookup', { ...meta, params: { acct } });
return v.parse(accountSchema, response.json);
},
/**
* File a report
* @see {@link https://docs.joinmastodon.org/methods/reports/#post}
*/
reportAccount: async (accountId: string, params: ReportAccountParams) => {
const response = await client.request('/api/v1/reports', {
method: 'POST',
body: { ...params, account_id: accountId },
});
return v.parse(reportSchema, response.json);
},
/**
* Endorsements
* Returns endorsed accounts
*
* Requires features{@link Features.accountEndorsements}.
* @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#apiv1pleromaaccountsidendorsements}
* @see {@link https://docs.joinmastodon.org/methods/accounts/endorsements}
*/
getAccountEndorsements: (accountId: string, params?: GetAccountEndorsementsParams) =>
client.paginatedGet(
`/api/v1/${[PLEROMA].includes(client.features.version.software as string) ? 'pleroma/' : ''}accounts/${accountId}/endorsements`,
{ params },
accountSchema,
),
/**
* Birthday reminders
* Birthday reminders about users you follow.
*
* Requires features{@link Features.birthdays}.
*/
getBirthdays: async (day: number, month: number) => {
const response = await client.request('/api/v1/pleroma/birthdays', { params: { day, month } });
return v.parse(filteredArray(accountSchema), response.json);
},
/**
* Returns favorites timeline of any user
*
* Requires features{@link Features.publicFavourites}.
* @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#apiv1pleromaaccountsidfavourites}
*/
getAccountFavourites: (accountId: string, params?: GetAccountFavouritesParams) =>
client.paginatedGet(
`/api/v1/pleroma/accounts/${accountId}/favourites`,
{ params },
statusSchema,
),
/**
* Interact with profile or status from remote account
*
* Requires features{@link Features.remoteInteractions}.
* @param ap_id - Profile or status ActivityPub ID
* @param profile - Remote profile webfinger
* @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#apiv1pleromaremote_interaction}
*/
remoteInteraction: async (ap_id: string, profile: string) => {
const response = await client.request('/api/v1/pleroma/remote_interaction', {
method: 'POST',
body: { ap_id, profile },
});
if (response.json?.error) throw response.json.error;
return v.parse(
v.object({
url: v.string(),
}),
response.json,
);
},
/**
* Bite the given user.
*
* Requires features{@link Features.bites}.
* @see {@link https://github.com/purifetchi/Toki/blob/master/Toki/Controllers/MastodonApi/Bite/BiteController.cs}
*/
biteAccount: async (accountId: string) => {
let response;
switch (client.features.version.software) {
case ICESHRIMP_NET:
response = await client.request<EmptyObject>('/api/v1/bite', {
method: 'POST',
body: accountId,
});
break;
default:
response = await client.request<EmptyObject>('/api/v1/bite', {
method: 'POST',
params: { id: accountId },
});
break;
}
return response.json;
},
/**
* Requests a list of current and recent Listen activities for an account
*
* Requires features{@link Features.scrobbles}
* @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#get-apiv1pleromaaccountsidscrobbles}
*/
getScrobbles: (accountId: string, params?: GetScrobblesParams) =>
client.paginatedGet(
`/api/v1/pleroma/accounts/${accountId}/scrobbles`,
{ params },
scrobbleSchema,
),
/**
* Creates a new Listen activity for an account
*
* Requires features{@link Features.scrobbles}
* @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#post-apiv1pleromascrobble}
*/
createScrobble: async (params: CreateScrobbleParams) => {
if (params.external_link) (params as any).externalLink = params.external_link;
const response = await client.request('/api/v1/pleroma/scrobble', { body: params });
return v.parse(scrobbleSchema, response.json);
},
/**
* Load latest activities from outbox
*
* Requires features{@link Features.loadActivities}
*/
loadActivities: async (accountId: string) => {
const response = await client.request<EmptyObject>(
`/api/v1/accounts/${accountId}/load_activities`,
{ method: 'POST' },
);
return response.json;
},
});
export { accounts };