Files
ncd-fe/packages/pl-api/lib/client/experimental.ts
nicole mikołajczyk a4dd5e0358 pl-api: reimport TypeObject, need to eep
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2026-02-27 02:32:38 +01:00

297 lines
11 KiB
TypeScript

import * as v from 'valibot';
import {
accountSchema,
groupMemberSchema,
groupRelationshipSchema,
groupSchema,
statusSchema,
} from '@/entities';
import { filteredArray } from '@/entities/utils';
import { PIXELFED } from '../features';
import type { PlApiBaseClient } from '@/client-base';
import type { GroupRole } from '@/entities';
import type { AdminGetGroupsParams } from '@/params/admin';
import type {
CreateGroupParams,
GetGroupBlocksParams,
GetGroupMembershipRequestsParams,
GetGroupMembershipsParams,
UpdateGroupParams,
} from '@/params/groups';
import type { EmptyObject } from '@/utils/types';
/** Routes that are not part of any stable release */
const experimental = (client: PlApiBaseClient) => {
const category = {
admin: {
/** @see {@link https://github.com/mastodon/mastodon/pull/19059} */
groups: {
/** list groups known to the instance. Mimics the interface of `/api/v1/admin/accounts` */
getGroups: async (params?: AdminGetGroupsParams) => {
const response = await client.request('/api/v1/admin/groups', { params });
return v.parse(filteredArray(groupSchema), response.json);
},
/** return basic group information */
getGroup: async (groupId: string) => {
const response = await client.request(`/api/v1/admin/groups/${groupId}`);
return v.parse(groupSchema, response.json);
},
/** suspends a group */
suspendGroup: async (groupId: string) => {
const response = await client.request(`/api/v1/admin/groups/${groupId}/suspend`, {
method: 'POST',
});
return v.parse(groupSchema, response.json);
},
/** lift a suspension */
unsuspendGroup: async (groupId: string) => {
const response = await client.request(`/api/v1/admin/groups/${groupId}/unsuspend`, {
method: 'POST',
});
return v.parse(groupSchema, response.json);
},
/** deletes an already-suspended group */
deleteGroup: async (groupId: string) => {
const response = await client.request(`/api/v1/admin/groups/${groupId}`, {
method: 'DELETE',
});
return v.parse(groupSchema, response.json);
},
},
},
/** @see {@link https://github.com/mastodon/mastodon/pull/19059} */
groups: {
/** returns an array of `Group` entities the current user is a member of */
getGroups: async () => {
let response;
if (client.features.version.software === PIXELFED) {
response = await client.request('/api/v0/groups/self/list');
} else {
response = await client.request('/api/v1/groups');
}
return v.parse(filteredArray(groupSchema), response.json);
},
/** create a group with the given attributes (`display_name`, `note`, `avatar` and `header`). Sets the user who made the request as group administrator */
createGroup: async (params: CreateGroupParams) => {
let response;
if (client.features.version.software === PIXELFED) {
response = await client.request('/api/v0/groups/create', {
method: 'POST',
body: {
...params,
name: params.display_name,
description: params.note,
membership: 'public',
},
contentType: params.avatar || params.header ? '' : undefined,
});
if (response.json?.id) {
return category.groups.getGroup(response.json.id);
}
} else {
response = await client.request('/api/v1/groups', {
method: 'POST',
body: params,
contentType: params.avatar || params.header ? '' : undefined,
});
}
return v.parse(groupSchema, response.json);
},
/** returns the `Group` entity describing a given group */
getGroup: async (groupId: string) => {
let response;
if (client.features.version.software === PIXELFED) {
response = await client.request(`/api/v0/groups/${groupId}`);
} else {
response = await client.request(`/api/v1/groups/${groupId}`);
}
return v.parse(groupSchema, response.json);
},
/** update group attributes (`display_name`, `note`, `avatar` and `header`) */
updateGroup: async (groupId: string, params: UpdateGroupParams) => {
const response = await client.request(`/api/v1/groups/${groupId}`, {
method: 'PUT',
body: params,
contentType: params.avatar || params.header ? '' : undefined,
});
return v.parse(groupSchema, response.json);
},
/** irreversibly deletes the group */
deleteGroup: async (groupId: string) => {
let response;
if (client.features.version.software === PIXELFED) {
response = await client.request<EmptyObject>('/api/v0/groups/delete', {
method: 'POST',
params: { gid: groupId },
});
} else {
response = await client.request<EmptyObject>(`/api/v1/groups/${groupId}`, {
method: 'DELETE',
});
}
return response.json;
},
/** Has an optional role attribute that can be used to filter by role (valid roles are `"admin"`, `"moderator"`, `"user"`). */
getGroupMemberships: (
groupId: string,
role?: GroupRole,
params?: GetGroupMembershipsParams,
) =>
client.paginatedGet(
client.features.version.software === PIXELFED
? `/api/v0/groups/members/list?gid=${groupId}`
: `/api/v1/groups/${groupId}/memberships`,
{ params: { ...params, role } },
groupMemberSchema,
),
/** returns an array of `Account` entities representing pending requests to join a group */
getGroupMembershipRequests: (groupId: string, params?: GetGroupMembershipRequestsParams) =>
client.paginatedGet(
client.features.version.software === PIXELFED
? `/api/v0/groups/members/requests?gid=${groupId}`
: `/api/v1/groups/${groupId}/membership_requests`,
{ params },
accountSchema,
),
/** accept a pending request to become a group member */
acceptGroupMembershipRequest: async (groupId: string, accountId: string) => {
const response = await client.request<EmptyObject>(
`/api/v1/groups/${groupId}/membership_requests/${accountId}/authorize`,
{ method: 'POST' },
);
return response.json;
},
/** reject a pending request to become a group member */
rejectGroupMembershipRequest: async (groupId: string, accountId: string) => {
const response = await client.request<EmptyObject>(
`/api/v1/groups/${groupId}/membership_requests/${accountId}/reject`,
{ method: 'POST' },
);
return response.json;
},
/** delete a group post (actually marks it as `revoked` if it is a local post) */
deleteGroupStatus: async (groupId: string, statusId: string) => {
const response = await client.request(`/api/v1/groups/${groupId}/statuses/${statusId}`, {
method: 'DELETE',
});
return v.parse(statusSchema, response.json);
},
/** list accounts blocked from interacting with the group */
getGroupBlocks: (groupId: string, params?: GetGroupBlocksParams) =>
client.paginatedGet(`/api/v1/groups/${groupId}/blocks`, { params }, accountSchema),
/** block one or more users. If they were in the group, they are also kicked of it */
blockGroupUsers: async (groupId: string, accountIds: string[]) => {
const response = await client.request<EmptyObject>(`/api/v1/groups/${groupId}/blocks`, {
method: 'POST',
params: { account_ids: accountIds },
});
return response.json;
},
/** block one or more users. If they were in the group, they are also kicked of it */
unblockGroupUsers: async (groupId: string, accountIds: string[]) => {
const response = await client.request<EmptyObject>(`/api/v1/groups/${groupId}/blocks`, {
method: 'DELETE',
params: { account_ids: accountIds },
});
return response.json;
},
/** joins (or request to join) a given group */
joinGroup: async (groupId: string) => {
const response = await client.request(`/api/v1/groups/${groupId}/join`, { method: 'POST' });
return v.parse(groupRelationshipSchema, response.json);
},
/** leaves a given group */
leaveGroup: async (groupId: string) => {
const response = await client.request(`/api/v1/groups/${groupId}/leave`, {
method: 'POST',
});
return v.parse(groupRelationshipSchema, response.json);
},
/** kick one or more group members */
kickGroupUsers: async (groupId: string, accountIds: string[]) => {
const response = await client.request<EmptyObject>(`/api/v1/groups/${groupId}/kick`, {
method: 'POST',
params: { account_ids: accountIds },
});
return response.json;
},
/** promote one or more accounts to role `new_role`. An error is returned if any of those accounts has a higher role than `new_role` already, or if the role is higher than the issuing user's. Valid roles are `admin`, and `moderator` and `user`. */
promoteGroupUsers: async (groupId: string, accountIds: string[], role: GroupRole) => {
const response = await client.request(`/api/v1/groups/${groupId}/promote`, {
method: 'POST',
params: { account_ids: accountIds, role },
});
return v.parse(filteredArray(groupMemberSchema), response.json);
},
/** demote one or more accounts to role `new_role`. Returns an error unless every of the target account has a strictly lower role than the user (you cannot demote someone with the same role as you), or if any target account already has a role lower than `new_role`. Valid roles are `admin`, `moderator` and `user`. */
demoteGroupUsers: async (groupId: string, accountIds: string[], role: GroupRole) => {
const response = await client.request(`/api/v1/groups/${groupId}/demote`, {
method: 'POST',
params: { account_ids: accountIds, role },
});
return v.parse(filteredArray(groupMemberSchema), response.json);
},
getGroupRelationships: async (groupIds: string[]) => {
const response = await client.request('/api/v1/groups/relationships', {
params: { id: groupIds },
});
return v.parse(filteredArray(groupRelationshipSchema), response.json);
},
},
};
return category;
};
export { experimental };