Add pl-api to workspace
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
7
packages/pl-api/.eslintignore
Normal file
7
packages/pl-api/.eslintignore
Normal file
@ -0,0 +1,7 @@
|
||||
/node_modules/**
|
||||
/dist/**
|
||||
/static/**
|
||||
/public/**
|
||||
/tmp/**
|
||||
/coverage/**
|
||||
/custom/**
|
||||
214
packages/pl-api/.eslintrc.json
Normal file
214
packages/pl-api/.eslintrc.json
Normal file
@ -0,0 +1,214 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:compat/recommended"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest": true
|
||||
},
|
||||
"globals": {
|
||||
"ATTACHMENT_HOST": false
|
||||
},
|
||||
"plugins": [
|
||||
"import",
|
||||
"promise",
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true
|
||||
},
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"settings": {
|
||||
"import/extensions": [
|
||||
".js",
|
||||
".cjs",
|
||||
".mjs",
|
||||
".ts"
|
||||
],
|
||||
"import/ignore": [
|
||||
"node_modules",
|
||||
"\\.(css|scss|json)$"
|
||||
],
|
||||
"import/resolver": {
|
||||
"typescript": true,
|
||||
"node": true
|
||||
},
|
||||
"polyfills": [
|
||||
"es:all",
|
||||
"fetch",
|
||||
"IntersectionObserver",
|
||||
"Promise",
|
||||
"ResizeObserver",
|
||||
"URL",
|
||||
"URLSearchParams"
|
||||
],
|
||||
"tailwindcss": {
|
||||
"config": "tailwind.config.ts"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"brace-style": "error",
|
||||
"comma-dangle": [
|
||||
"error",
|
||||
"always-multiline"
|
||||
],
|
||||
"comma-spacing": [
|
||||
"warn",
|
||||
{
|
||||
"before": false,
|
||||
"after": true
|
||||
}
|
||||
],
|
||||
"comma-style": [
|
||||
"warn",
|
||||
"last"
|
||||
],
|
||||
"import/no-duplicates": "error",
|
||||
"space-before-function-paren": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"space-infix-ops": "error",
|
||||
"space-in-parens": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"keyword-spacing": "error",
|
||||
"dot-notation": "error",
|
||||
"eqeqeq": "error",
|
||||
"indent": [
|
||||
"error",
|
||||
2,
|
||||
{
|
||||
"SwitchCase": 1,
|
||||
"ignoredNodes": [
|
||||
"TemplateLiteral"
|
||||
]
|
||||
}
|
||||
],
|
||||
"key-spacing": [
|
||||
"error",
|
||||
{
|
||||
"mode": "minimum"
|
||||
}
|
||||
],
|
||||
"no-catch-shadow": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-console": [
|
||||
"warn",
|
||||
{
|
||||
"allow": [
|
||||
"error",
|
||||
"warn"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-extra-semi": "error",
|
||||
"no-const-assign": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-mixed-spaces-and-tabs": "error",
|
||||
"no-nested-ternary": "warn",
|
||||
"no-trailing-spaces": "warn",
|
||||
"no-undef": "error",
|
||||
"no-unreachable": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"vars": "all",
|
||||
"args": "none",
|
||||
"ignoreRestSiblings": true
|
||||
}
|
||||
],
|
||||
"no-useless-escape": "warn",
|
||||
"no-var": "error",
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"padded-blocks": [
|
||||
"error",
|
||||
{
|
||||
"classes": "always"
|
||||
}
|
||||
],
|
||||
"prefer-const": "error",
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"semi": "error",
|
||||
"space-unary-ops": [
|
||||
"error",
|
||||
{
|
||||
"words": true,
|
||||
"nonwords": false
|
||||
}
|
||||
],
|
||||
"strict": "off",
|
||||
"valid-typeof": "error",
|
||||
"import/extensions": [
|
||||
"error",
|
||||
"always",
|
||||
{
|
||||
"js": "never",
|
||||
"mjs": "ignorePackages",
|
||||
"ts": "never"
|
||||
}
|
||||
],
|
||||
"import/newline-after-import": "error",
|
||||
"import/no-extraneous-dependencies": "error",
|
||||
"import/no-unresolved": "error",
|
||||
"import/no-webpack-loader-syntax": "error",
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"groups": [
|
||||
"builtin",
|
||||
"external",
|
||||
"internal",
|
||||
"parent",
|
||||
"sibling",
|
||||
"index",
|
||||
"object",
|
||||
"type"
|
||||
],
|
||||
"newlines-between": "always",
|
||||
"alphabetize": {
|
||||
"order": "asc"
|
||||
}
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/member-delimiter-style": "error",
|
||||
"promise/catch-or-return": "error",
|
||||
"sort-imports": [
|
||||
"error",
|
||||
{
|
||||
"ignoreCase": true,
|
||||
"ignoreDeclarationSort": true
|
||||
}
|
||||
],
|
||||
"eol-last": "error"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/*.ts"],
|
||||
"rules": {
|
||||
"no-undef": "off",
|
||||
"space-before-function-paren": "off"
|
||||
},
|
||||
"parser": "@typescript-eslint/parser"
|
||||
}
|
||||
]
|
||||
}
|
||||
24
packages/pl-api/.gitignore
vendored
Normal file
24
packages/pl-api/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
24
packages/pl-api/README.md
Normal file
24
packages/pl-api/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# `pl-api`
|
||||
|
||||
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.
|
||||
|
||||
## 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.
|
||||
|
||||
## License
|
||||
|
||||
`pl-api` utilizes 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
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
16
packages/pl-api/index.html
Normal file
16
packages/pl-api/index.html
Normal file
@ -0,0 +1,16 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>pl-api</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module" src="/lib/main.ts"></script>
|
||||
<script type="module">
|
||||
import PlApiClient from './lib/client.ts';
|
||||
|
||||
window.client = PlApiClient;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
3990
packages/pl-api/lib/client.ts
Normal file
3990
packages/pl-api/lib/client.ts
Normal file
File diff suppressed because it is too large
Load Diff
27
packages/pl-api/lib/entities/account-warning.ts
Normal file
27
packages/pl-api/lib/entities/account-warning.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { dateSchema } from './utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Appeal/} */
|
||||
const appealSchema = z.object({
|
||||
text: z.string(),
|
||||
state: z.enum(['approved', 'rejected', 'pending']),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/AccountWarning/} */
|
||||
const accountWarningSchema = z.object({
|
||||
id: z.string(),
|
||||
action: z.enum(['none', 'disable', 'mark_statuses_as_sensitive', 'delete_statuses', 'sensitive', 'silence', 'suspend']),
|
||||
text: z.string().catch(''),
|
||||
status_ids: z.array(z.string()).catch([]),
|
||||
target_account: accountSchema,
|
||||
appeal: appealSchema.nullable().catch(null),
|
||||
created_at: dateSchema,
|
||||
});
|
||||
|
||||
type AccountWarning = Resolve<z.infer<typeof accountWarningSchema>>;
|
||||
|
||||
export { accountWarningSchema, type AccountWarning };
|
||||
177
packages/pl-api/lib/entities/account.ts
Normal file
177
packages/pl-api/lib/entities/account.ts
Normal file
@ -0,0 +1,177 @@
|
||||
import pick from 'lodash.pick';
|
||||
import z from 'zod';
|
||||
|
||||
import { customEmojiSchema } from './custom-emoji';
|
||||
import { relationshipSchema } from './relationship';
|
||||
import { roleSchema } from './role';
|
||||
import { coerceObject, dateSchema, filteredArray } from './utils';
|
||||
|
||||
const filterBadges = (tags?: string[]) =>
|
||||
tags?.filter(tag => tag.startsWith('badge:')).map(tag => roleSchema.parse({ id: tag, name: tag.replace(/^badge:/, '') }));
|
||||
|
||||
const preprocessAccount = (account: any) => {
|
||||
if (!account?.acct) return null;
|
||||
|
||||
return {
|
||||
username: account.username || account.acct.split('@')[0],
|
||||
display_name: account.display_name.trim() || account.username,
|
||||
roles: account.roles?.length ? account.roles : filterBadges(account.pleroma?.tags),
|
||||
avatar_static: account.avatar_static || account.avatar,
|
||||
header_static: account.header_static || account.header,
|
||||
source: account.source
|
||||
? { ...(pick(account.pleroma?.source || {}, [
|
||||
'show_role', 'no_rich_text', 'discoverable', 'actor_type', 'show_birthday',
|
||||
])), ...account.source }
|
||||
: undefined,
|
||||
local: typeof account.pleroma?.is_local === 'boolean' ? account.pleroma.is_local : account.acct.split('@')[1] === undefined,
|
||||
discoverable: account.discoverable || account.pleroma?.source?.discoverable,
|
||||
verified: account.verified || account.pleroma?.tags?.includes('verified'),
|
||||
...(pick(account.pleroma || {}, [
|
||||
'ap_id',
|
||||
'background_image',
|
||||
'relationship',
|
||||
'is_moderator',
|
||||
'is_admin',
|
||||
'hide_favorites',
|
||||
'hide_followers',
|
||||
'hide_follows',
|
||||
'hide_followers_count',
|
||||
'hide_follows_count',
|
||||
'accepts_chat_messages',
|
||||
'favicon',
|
||||
'birthday',
|
||||
'deactivated',
|
||||
|
||||
'settings_store',
|
||||
'chat_token',
|
||||
'allow_following_move',
|
||||
'unread_conversation_count',
|
||||
'unread_notifications_count',
|
||||
'notification_settings',
|
||||
|
||||
'location',
|
||||
])),
|
||||
...(pick(account.other_settings || {}), ['birthday', 'location']),
|
||||
__meta: pick(account, ['pleroma', 'source']),
|
||||
...account,
|
||||
};
|
||||
};
|
||||
|
||||
const fieldSchema = z.object({
|
||||
name: z.string(),
|
||||
value: z.string(),
|
||||
verified_at: z.string().datetime({ offset: true }).nullable().catch(null),
|
||||
});
|
||||
|
||||
const baseAccountSchema = z.object({
|
||||
id: z.string(),
|
||||
username: z.string().catch(''),
|
||||
acct: z.string().catch(''),
|
||||
url: z.string().url(),
|
||||
display_name: z.string().catch(''),
|
||||
note: z.string().catch(''),
|
||||
avatar: z.string().catch(''),
|
||||
avatar_static: z.string().url().catch(''),
|
||||
header: z.string().url().catch(''),
|
||||
header_static: z.string().url().catch(''),
|
||||
locked: z.boolean().catch(false),
|
||||
fields: filteredArray(fieldSchema),
|
||||
emojis: filteredArray(customEmojiSchema),
|
||||
bot: z.boolean().catch(false),
|
||||
group: z.boolean().catch(false),
|
||||
discoverable: z.boolean().catch(false),
|
||||
noindex: z.boolean().nullable().catch(null),
|
||||
suspended: z.boolean().optional().catch(undefined),
|
||||
limited: z.boolean().optional().catch(undefined),
|
||||
created_at: z.string().datetime().catch(new Date().toUTCString()),
|
||||
last_status_at: z.string().date().nullable().catch(null),
|
||||
statuses_count: z.number().catch(0),
|
||||
followers_count: z.number().catch(0),
|
||||
following_count: z.number().catch(0),
|
||||
roles: filteredArray(roleSchema),
|
||||
|
||||
fqn: z.string().nullable().catch(null),
|
||||
ap_id: z.string().nullable().catch(null),
|
||||
background_image: z.string().nullable().catch(null),
|
||||
relationship: relationshipSchema.optional().catch(undefined),
|
||||
is_moderator: z.boolean().optional().catch(undefined),
|
||||
is_admin: z.boolean().optional().catch(undefined),
|
||||
is_suggested: z.boolean().optional().catch(undefined),
|
||||
hide_favorites: z.boolean().catch(true),
|
||||
hide_followers: z.boolean().optional().catch(undefined),
|
||||
hide_follows: z.boolean().optional().catch(undefined),
|
||||
hide_followers_count: z.boolean().optional().catch(undefined),
|
||||
hide_follows_count: z.boolean().optional().catch(undefined),
|
||||
accepts_chat_messages: z.boolean().nullable().catch(null),
|
||||
favicon: z.string().optional().catch(undefined),
|
||||
birthday: z.string().date().optional().catch(undefined),
|
||||
deactivated: z.boolean().optional().catch(undefined),
|
||||
|
||||
location: z.string().optional().catch(undefined),
|
||||
local: z.boolean().optional().catch(false),
|
||||
|
||||
avatar_description: z.string().catch(''),
|
||||
enable_rss: z.boolean().catch(false),
|
||||
header_description: z.string().catch(''),
|
||||
|
||||
verified: z.boolean().optional().catch(undefined),
|
||||
|
||||
__meta: coerceObject({
|
||||
pleroma: z.any().optional().catch(undefined),
|
||||
source: z.any().optional().catch(undefined),
|
||||
}),
|
||||
});
|
||||
|
||||
const accountWithMovedAccountSchema = baseAccountSchema.extend({
|
||||
moved: baseAccountSchema.optional().catch(undefined),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Account/} */
|
||||
const accountSchema = z.preprocess(preprocessAccount, accountWithMovedAccountSchema);
|
||||
|
||||
type Account = z.infer<typeof accountSchema>;
|
||||
|
||||
const credentialAccountSchema = z.preprocess(preprocessAccount, accountWithMovedAccountSchema.extend({
|
||||
source: z.object({
|
||||
note: z.string().catch(''),
|
||||
fields: filteredArray(fieldSchema),
|
||||
privacy: z.enum(['public', 'unlisted', 'private', 'direct']),
|
||||
sensitive: z.boolean().catch(false),
|
||||
language: z.string().nullable().catch(null),
|
||||
follow_requests_count: z.number().int().nonnegative().catch(0),
|
||||
|
||||
show_role: z.boolean().optional().nullable().catch(undefined),
|
||||
no_rich_text: z.boolean().optional().nullable().catch(undefined),
|
||||
discoverable: z.boolean().optional().catch(undefined),
|
||||
actor_type: z.string().optional().catch(undefined),
|
||||
show_birthday: z.boolean().optional().catch(undefined),
|
||||
}).nullable().catch(null),
|
||||
role: roleSchema.nullable().catch(null),
|
||||
|
||||
settings_store: z.record(z.any()).optional().catch(undefined),
|
||||
chat_token: z.string().optional().catch(undefined),
|
||||
allow_following_move: z.boolean().optional().catch(undefined),
|
||||
unread_conversation_count: z.number().optional().catch(undefined),
|
||||
unread_notifications_count: z.number().optional().catch(undefined),
|
||||
notification_settings: z.object({
|
||||
block_from_strangers: z.boolean().catch(false),
|
||||
hide_notification_contents: z.boolean().catch(false),
|
||||
}).optional().catch(undefined),
|
||||
}));
|
||||
|
||||
type CredentialAccount = z.infer<typeof credentialAccountSchema>;
|
||||
|
||||
const mutedAccountSchema = z.preprocess(preprocessAccount, accountWithMovedAccountSchema.extend({
|
||||
mute_expires_at: dateSchema.nullable().catch(null),
|
||||
}));
|
||||
|
||||
type MutedAccount = z.infer<typeof mutedAccountSchema>;
|
||||
|
||||
export {
|
||||
accountSchema,
|
||||
credentialAccountSchema,
|
||||
mutedAccountSchema,
|
||||
type Account,
|
||||
type CredentialAccount,
|
||||
type MutedAccount,
|
||||
};
|
||||
69
packages/pl-api/lib/entities/admin/account.ts
Normal file
69
packages/pl-api/lib/entities/admin/account.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { accountSchema } from '../account';
|
||||
import { roleSchema } from '../role';
|
||||
import { dateSchema, filteredArray } from '../utils';
|
||||
|
||||
import { adminIpSchema } from './ip';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Account/} */
|
||||
const adminAccountSchema = z.preprocess((account: any) => {
|
||||
if (!account.account) {
|
||||
/**
|
||||
* Convert Pleroma account schema
|
||||
* @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminusers}
|
||||
*/
|
||||
return {
|
||||
id: account.id,
|
||||
account: null,
|
||||
username: account.nickname,
|
||||
domain: account.nickname.split('@')[1] || null,
|
||||
created_at: account.created_at,
|
||||
email: account.email,
|
||||
invite_request: account.registration_reason,
|
||||
role: account.roles?.is_admin
|
||||
? roleSchema.parse({ name: 'Admin' })
|
||||
: account.roles?.moderator
|
||||
? roleSchema.parse({ name: 'Moderator ' }) :
|
||||
null,
|
||||
confirmed: account.is_confirmed,
|
||||
approved: account.is_approved,
|
||||
disabled: !account.is_active,
|
||||
|
||||
actor_type: account.actor_type,
|
||||
display_name: account.display_name,
|
||||
suggested: account.is_suggested,
|
||||
};
|
||||
}
|
||||
return account;
|
||||
}, z.object({
|
||||
id: z.string(),
|
||||
username: z.string(),
|
||||
domain: z.string().nullable().catch(null),
|
||||
created_at: dateSchema,
|
||||
email: z.string().nullable().catch(null),
|
||||
ip: z.string().ip().nullable().catch(null),
|
||||
ips: filteredArray(adminIpSchema),
|
||||
locale: z.string().nullable().catch(null),
|
||||
invite_request: z.string().nullable().catch(null),
|
||||
role: roleSchema.nullable().catch(null),
|
||||
confirmed: z.boolean().catch(false),
|
||||
approved: z.boolean().catch(false),
|
||||
disabled: z.boolean().catch(false),
|
||||
silenced: z.boolean().catch(false),
|
||||
suspended: z.boolean().catch(false),
|
||||
account: accountSchema.nullable().catch(null),
|
||||
created_by_application_id: z.string().optional().catch(undefined),
|
||||
invited_by_account_id: z.string().optional().catch(undefined),
|
||||
|
||||
actor_type: z.string().nullable().catch(null),
|
||||
display_name: z.string().nullable().catch(null),
|
||||
suggested: z.boolean().nullable().catch(null),
|
||||
}));
|
||||
|
||||
type AdminAccount = z.infer<typeof adminAccountSchema>;
|
||||
|
||||
export {
|
||||
adminAccountSchema,
|
||||
type AdminAccount,
|
||||
};
|
||||
17
packages/pl-api/lib/entities/admin/announcement.ts
Normal file
17
packages/pl-api/lib/entities/admin/announcement.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import pick from 'lodash.pick';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../../utils/types';
|
||||
import { announcementSchema } from '../announcement';
|
||||
|
||||
/** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminannouncements} */
|
||||
const adminAnnouncementSchema = z.preprocess((announcement: any) => ({
|
||||
...announcement,
|
||||
...pick(announcement.pleroma, 'raw_content'),
|
||||
}), announcementSchema.extend({
|
||||
raw_content: z.string().catch(''),
|
||||
}));
|
||||
|
||||
type AdminAnnouncement = Resolve<z.infer<typeof adminAnnouncementSchema>>;
|
||||
|
||||
export { adminAnnouncementSchema, type AdminAnnouncement };
|
||||
14
packages/pl-api/lib/entities/admin/canonical-email-block.ts
Normal file
14
packages/pl-api/lib/entities/admin/canonical-email-block.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_CanonicalEmailBlock/} */
|
||||
const adminCanonicalEmailBlockSchema = z.object({
|
||||
id: z.string(),
|
||||
canonical_email_hash: z.string(),
|
||||
});
|
||||
|
||||
type AdminCanonicalEmailBlock = z.infer<typeof adminCanonicalEmailBlockSchema>;
|
||||
|
||||
export {
|
||||
adminCanonicalEmailBlockSchema,
|
||||
type AdminCanonicalEmailBlock,
|
||||
};
|
||||
19
packages/pl-api/lib/entities/admin/cohort.ts
Normal file
19
packages/pl-api/lib/entities/admin/cohort.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Cohort/} */
|
||||
const adminCohortSchema = z.object({
|
||||
period: z.string().datetime({ offset: true }),
|
||||
frequency: z.enum(['day', 'month']),
|
||||
data: z.array(z.object({
|
||||
date: z.string().datetime({ offset: true }),
|
||||
rate: z.number(),
|
||||
value: z.number().int(),
|
||||
})),
|
||||
});
|
||||
|
||||
type AdminCohort = z.infer<typeof adminCohortSchema>;
|
||||
|
||||
export {
|
||||
adminCohortSchema,
|
||||
type AdminCohort,
|
||||
};
|
||||
20
packages/pl-api/lib/entities/admin/dimension.ts
Normal file
20
packages/pl-api/lib/entities/admin/dimension.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Dimension/} */
|
||||
const adminDimensionSchema = z.object({
|
||||
key: z.string(),
|
||||
data: z.object({
|
||||
key: z.string(),
|
||||
human_key: z.string(),
|
||||
value: z.string(),
|
||||
unit: z.string().optional().catch(undefined),
|
||||
human_value: z.string().optional().catch(undefined),
|
||||
}),
|
||||
});
|
||||
|
||||
type AdminDimension = z.infer<typeof adminDimensionSchema>;
|
||||
|
||||
export {
|
||||
adminDimensionSchema,
|
||||
type AdminDimension,
|
||||
};
|
||||
17
packages/pl-api/lib/entities/admin/domain-allow.ts
Normal file
17
packages/pl-api/lib/entities/admin/domain-allow.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from '../utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_DomainAllow/} */
|
||||
const adminDomainAllowSchema = z.object({
|
||||
id: z.string(),
|
||||
domain: z.string(),
|
||||
created_at: dateSchema,
|
||||
});
|
||||
|
||||
type AdminDomainAllow = z.infer<typeof adminDomainAllowSchema>;
|
||||
|
||||
export {
|
||||
adminDomainAllowSchema,
|
||||
type AdminDomainAllow,
|
||||
};
|
||||
24
packages/pl-api/lib/entities/admin/domain-block.ts
Normal file
24
packages/pl-api/lib/entities/admin/domain-block.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from '../utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_DomainBlock/} */
|
||||
const adminDomainBlockSchema = z.object({
|
||||
id: z.string(),
|
||||
domain: z.string(),
|
||||
digest: z.string(),
|
||||
created_at: dateSchema,
|
||||
severity: z.enum(['silence', 'suspend', 'noop']),
|
||||
reject_media: z.boolean(),
|
||||
reject_reports: z.boolean(),
|
||||
private_comment: z.string().nullable().catch(null),
|
||||
public_comment: z.string().nullable().catch(null),
|
||||
obfuscate: z.boolean(),
|
||||
});
|
||||
|
||||
type AdminDomainBlock = z.infer<typeof adminDomainBlockSchema>;
|
||||
|
||||
export {
|
||||
adminDomainBlockSchema,
|
||||
type AdminDomainBlock,
|
||||
};
|
||||
13
packages/pl-api/lib/entities/admin/domain.ts
Normal file
13
packages/pl-api/lib/entities/admin/domain.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import z from 'zod';
|
||||
|
||||
const adminDomainSchema = z.object({
|
||||
domain: z.string().catch(''),
|
||||
id: z.coerce.string(),
|
||||
public: z.boolean().catch(false),
|
||||
resolves: z.boolean().catch(false),
|
||||
last_checked_at: z.string().datetime().catch(''),
|
||||
});
|
||||
|
||||
type AdminDomain = z.infer<typeof adminDomainSchema>
|
||||
|
||||
export { adminDomainSchema, type AdminDomain };
|
||||
22
packages/pl-api/lib/entities/admin/email-domain-block.ts
Normal file
22
packages/pl-api/lib/entities/admin/email-domain-block.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from '../utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_EmailDomainBlock/} */
|
||||
const adminEmailDomainBlockSchema = z.object({
|
||||
id: z.string(),
|
||||
domain: z.string(),
|
||||
created_at: dateSchema,
|
||||
history: z.array(z.object({
|
||||
day: z.coerce.string(),
|
||||
accounts: z.coerce.string(),
|
||||
uses: z.coerce.string(),
|
||||
})),
|
||||
});
|
||||
|
||||
type AdminEmailDomainBlock = z.infer<typeof adminEmailDomainBlockSchema>;
|
||||
|
||||
export {
|
||||
adminEmailDomainBlockSchema,
|
||||
type AdminEmailDomainBlock,
|
||||
};
|
||||
20
packages/pl-api/lib/entities/admin/ip-block.ts
Normal file
20
packages/pl-api/lib/entities/admin/ip-block.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from '../utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_IpBlock/} */
|
||||
const adminIpBlockSchema = z.object({
|
||||
id: z.string(),
|
||||
ip: z.string().ip(),
|
||||
severity: z.enum(['sign_up_requires_approval', 'sign_up_block', 'no_access']),
|
||||
comment: z.string().catch(''),
|
||||
created_at: dateSchema,
|
||||
expires_at: z.string().datetime({ offset: true }),
|
||||
});
|
||||
|
||||
type AdminIpBlock = z.infer<typeof adminIpBlockSchema>;
|
||||
|
||||
export {
|
||||
adminIpBlockSchema,
|
||||
type AdminIpBlock,
|
||||
};
|
||||
16
packages/pl-api/lib/entities/admin/ip.ts
Normal file
16
packages/pl-api/lib/entities/admin/ip.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from '../utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Ip/} */
|
||||
const adminIpSchema = z.object({
|
||||
ip: z.string().ip(),
|
||||
used_at: dateSchema,
|
||||
});
|
||||
|
||||
type AdminIp = z.infer<typeof adminIpSchema>;
|
||||
|
||||
export {
|
||||
adminIpSchema,
|
||||
type AdminIp,
|
||||
};
|
||||
21
packages/pl-api/lib/entities/admin/measure.ts
Normal file
21
packages/pl-api/lib/entities/admin/measure.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Measure/} */
|
||||
const adminMeasureSchema = z.object({
|
||||
key: z.string(),
|
||||
unit: z.string().nullable().catch(null),
|
||||
total: z.coerce.number(),
|
||||
human_value: z.string().optional().catch(undefined),
|
||||
previous_total: z.coerce.string().optional().catch(undefined),
|
||||
data: z.array(z.object({
|
||||
date: z.string().datetime({ offset: true }),
|
||||
value: z.coerce.string(),
|
||||
})),
|
||||
});
|
||||
|
||||
type AdminMeasure = z.infer<typeof adminMeasureSchema>;
|
||||
|
||||
export {
|
||||
adminMeasureSchema,
|
||||
type AdminMeasure,
|
||||
};
|
||||
13
packages/pl-api/lib/entities/admin/moderation-log-entry.ts
Normal file
13
packages/pl-api/lib/entities/admin/moderation-log-entry.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import z from 'zod';
|
||||
|
||||
/** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminmoderation_log} */
|
||||
const adminModerationLogEntrySchema = z.object({
|
||||
id: z.coerce.string(),
|
||||
data: z.record(z.string(), z.any()).catch({}),
|
||||
time: z.number().catch(0),
|
||||
message: z.string().catch(''),
|
||||
});
|
||||
|
||||
type AdminModerationLogEntry = z.infer<typeof adminModerationLogEntrySchema>
|
||||
|
||||
export { adminModerationLogEntrySchema, type AdminModerationLogEntry };
|
||||
11
packages/pl-api/lib/entities/admin/relay.ts
Normal file
11
packages/pl-api/lib/entities/admin/relay.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import z from 'zod';
|
||||
|
||||
const adminRelaySchema = z.preprocess((data: any) => ({ id: data.actor, ...data }), z.object({
|
||||
actor: z.string().catch(''),
|
||||
id: z.string(),
|
||||
followed_back: z.boolean().catch(false),
|
||||
}));
|
||||
|
||||
type AdminRelay = z.infer<typeof adminRelaySchema>
|
||||
|
||||
export { adminRelaySchema, type AdminRelay };
|
||||
46
packages/pl-api/lib/entities/admin/report.ts
Normal file
46
packages/pl-api/lib/entities/admin/report.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import pick from 'lodash.pick';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ruleSchema } from '../rule';
|
||||
import { statusWithoutAccountSchema } from '../status';
|
||||
import { dateSchema, filteredArray } from '../utils';
|
||||
|
||||
import { adminAccountSchema } from './account';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Admin_Report/} */
|
||||
const adminReportSchema = z.preprocess((report: any) => {
|
||||
if (report.actor) {
|
||||
/**
|
||||
* Convert Pleroma report schema
|
||||
* @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminreports}
|
||||
*/
|
||||
return {
|
||||
action_taken: report.state !== 'open',
|
||||
comment: report.content,
|
||||
updated_at: report.created_at,
|
||||
account: report.actor,
|
||||
target_account: report.account,
|
||||
...(pick(report, ['id', 'assigned_account', 'created_at', 'rules', 'statuses'])),
|
||||
};
|
||||
}
|
||||
return report;
|
||||
}, z.object({
|
||||
id: z.string(),
|
||||
action_taken: z.boolean().optional().catch(undefined),
|
||||
action_taken_at: dateSchema.nullable().catch(null),
|
||||
category: z.string().optional().catch(undefined),
|
||||
comment: z.string().optional().catch(undefined),
|
||||
forwarded: z.boolean().optional().catch(undefined),
|
||||
created_at: dateSchema.optional().catch(undefined),
|
||||
updated_at: dateSchema.optional().catch(undefined),
|
||||
account: adminAccountSchema,
|
||||
target_account: adminAccountSchema,
|
||||
assigned_account: adminAccountSchema.nullable().catch(null),
|
||||
action_taken_by_account: adminAccountSchema.nullable().catch(null),
|
||||
statuses: filteredArray(statusWithoutAccountSchema),
|
||||
rules: filteredArray(ruleSchema),
|
||||
}));
|
||||
|
||||
type AdminReport = z.infer<typeof adminReportSchema>;
|
||||
|
||||
export { adminReportSchema, type AdminReport };
|
||||
13
packages/pl-api/lib/entities/admin/rule.ts
Normal file
13
packages/pl-api/lib/entities/admin/rule.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.pleroma.social/backend/development/API/admin_api/#get-apiv1pleromaadminrules} */
|
||||
const adminRuleSchema = z.object({
|
||||
id: z.string(),
|
||||
text: z.string().catch(''),
|
||||
hint: z.string().catch(''),
|
||||
priority: z.number().nullable().catch(null),
|
||||
});
|
||||
|
||||
type AdminRule = z.infer<typeof adminRuleSchema>;
|
||||
|
||||
export { adminRuleSchema, type AdminRule };
|
||||
18
packages/pl-api/lib/entities/admin/tag.ts
Normal file
18
packages/pl-api/lib/entities/admin/tag.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { tagSchema } from '../tag';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Tag/#admin} */
|
||||
const adminTagSchema = tagSchema.extend({
|
||||
id: z.string(),
|
||||
trendable: z.boolean(),
|
||||
usable: z.boolean(),
|
||||
requires_review: z.boolean(),
|
||||
});
|
||||
|
||||
type AdminTag = z.infer<typeof adminTagSchema>;
|
||||
|
||||
export {
|
||||
adminTagSchema,
|
||||
type AdminTag,
|
||||
};
|
||||
17
packages/pl-api/lib/entities/announcement-reaction.ts
Normal file
17
packages/pl-api/lib/entities/announcement-reaction.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { Resolve } from '../utils/types';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/announcement/} */
|
||||
const announcementReactionSchema = z.object({
|
||||
name: z.string().catch(''),
|
||||
count: z.number().int().nonnegative().catch(0),
|
||||
me: z.boolean().catch(false),
|
||||
url: z.string().nullable().catch(null),
|
||||
static_url: z.string().nullable().catch(null),
|
||||
announcement_id: z.string().catch(''),
|
||||
});
|
||||
|
||||
type AnnouncementReaction = Resolve<z.infer<typeof announcementReactionSchema>>;
|
||||
|
||||
export { announcementReactionSchema, type AnnouncementReaction };
|
||||
35
packages/pl-api/lib/entities/announcement.ts
Normal file
35
packages/pl-api/lib/entities/announcement.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { announcementReactionSchema } from './announcement-reaction';
|
||||
import { customEmojiSchema } from './custom-emoji';
|
||||
import { mentionSchema } from './mention';
|
||||
import { tagSchema } from './tag';
|
||||
import { dateSchema, filteredArray } from './utils';
|
||||
|
||||
import type { Resolve } from '../utils/types';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/announcement/} */
|
||||
const announcementSchema = z.object({
|
||||
id: z.string(),
|
||||
content: z.string().catch(''),
|
||||
starts_at: z.string().datetime().nullable().catch(null),
|
||||
ends_at: z.string().datetime().nullable().catch(null),
|
||||
all_day: z.boolean().catch(false),
|
||||
read: z.boolean().catch(false),
|
||||
published_at: dateSchema,
|
||||
reactions: filteredArray(announcementReactionSchema),
|
||||
statuses: z.preprocess(
|
||||
(statuses: any) => Array.isArray(statuses)
|
||||
? Object.fromEntries(statuses.map((status: any) => [status.url, status.account?.acct]) || [])
|
||||
: statuses,
|
||||
z.record(z.string(), z.string()),
|
||||
),
|
||||
mentions: filteredArray(mentionSchema),
|
||||
tags: filteredArray(tagSchema),
|
||||
emojis: filteredArray(customEmojiSchema),
|
||||
updated_at: dateSchema,
|
||||
});
|
||||
|
||||
type Announcement = Resolve<z.infer<typeof announcementSchema>>;
|
||||
|
||||
export { announcementSchema, type Announcement };
|
||||
21
packages/pl-api/lib/entities/application.ts
Normal file
21
packages/pl-api/lib/entities/application.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { Resolve } from '../utils/types';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Application/} */
|
||||
const applicationSchema = z.object({
|
||||
name: z.string().catch(''),
|
||||
website: z.string().optional().catch(undefined),
|
||||
client_id: z.string().optional().catch(undefined),
|
||||
client_secret: z.string().optional().catch(undefined),
|
||||
redirect_uri: z.string().optional().catch(undefined),
|
||||
|
||||
id: z.string().optional().catch(undefined),
|
||||
|
||||
/** @deprecated */
|
||||
vapid_key: z.string().optional().catch(undefined),
|
||||
});
|
||||
|
||||
type Application = Resolve<z.infer<typeof applicationSchema>>;
|
||||
|
||||
export { applicationSchema, type Application };
|
||||
19
packages/pl-api/lib/entities/backup.ts
Normal file
19
packages/pl-api/lib/entities/backup.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema, mimeSchema } from './utils';
|
||||
|
||||
import type { Resolve } from '../utils/types';
|
||||
|
||||
/** @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#post-apiv1pleromabackups} */
|
||||
const backupSchema = z.object({
|
||||
id: z.coerce.string(),
|
||||
contentType: mimeSchema,
|
||||
file_size: z.number().catch(0),
|
||||
inserted_at: dateSchema,
|
||||
processed: z.boolean().catch(false),
|
||||
url: z.string().catch(''),
|
||||
});
|
||||
|
||||
type Backup = Resolve<z.infer<typeof backupSchema>>;
|
||||
|
||||
export { backupSchema, type Backup };
|
||||
14
packages/pl-api/lib/entities/bookmark-folder.ts
Normal file
14
packages/pl-api/lib/entities/bookmark-folder.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { Resolve } from '../utils/types';
|
||||
|
||||
const bookmarkFolderSchema = z.object({
|
||||
id: z.coerce.string(),
|
||||
name: z.string().catch(''),
|
||||
emoji: z.string().nullable().catch(null),
|
||||
emoji_url: z.string().nullable().catch(null),
|
||||
});
|
||||
|
||||
type BookmarkFolder = Resolve<z.infer<typeof bookmarkFolderSchema>>;
|
||||
|
||||
export { bookmarkFolderSchema, type BookmarkFolder };
|
||||
23
packages/pl-api/lib/entities/chat-message.ts
Normal file
23
packages/pl-api/lib/entities/chat-message.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { customEmojiSchema } from './custom-emoji';
|
||||
import { mediaAttachmentSchema } from './media-attachment';
|
||||
import { previewCardSchema } from './preview-card';
|
||||
import { dateSchema, filteredArray } from './utils';
|
||||
|
||||
/** @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-the-messages-for-a-chat} */
|
||||
const chatMessageSchema = z.object({
|
||||
id: z.string(),
|
||||
content: z.string().catch(''),
|
||||
chat_id: z.string(),
|
||||
account_id: z.string(),
|
||||
created_at: dateSchema,
|
||||
emojis: filteredArray(customEmojiSchema),
|
||||
attachment: mediaAttachmentSchema.nullable().catch(null),
|
||||
unread: z.boolean(),
|
||||
card: previewCardSchema.nullable().catch(null),
|
||||
});
|
||||
|
||||
type ChatMessage = z.infer<typeof chatMessageSchema>;
|
||||
|
||||
export { chatMessageSchema, type ChatMessage };
|
||||
18
packages/pl-api/lib/entities/chat.ts
Normal file
18
packages/pl-api/lib/entities/chat.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { chatMessageSchema } from './chat-message';
|
||||
import { dateSchema } from './utils';
|
||||
|
||||
/** @see {@link https://docs.pleroma.social/backend/development/API/chats/#getting-a-list-of-chats} */
|
||||
const chatSchema = z.object({
|
||||
id: z.string(),
|
||||
account: accountSchema,
|
||||
unread: z.number().int(),
|
||||
last_message: chatMessageSchema.nullable().catch(null),
|
||||
created_at: dateSchema,
|
||||
});
|
||||
|
||||
type Chat = z.infer<typeof chatSchema>;
|
||||
|
||||
export { chatSchema, type Chat };
|
||||
15
packages/pl-api/lib/entities/context.ts
Normal file
15
packages/pl-api/lib/entities/context.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { statusSchema } from './status';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Context/} */
|
||||
const contextSchema = z.object({
|
||||
ancestors: z.array(statusSchema),
|
||||
descendants: z.array(statusSchema),
|
||||
});
|
||||
|
||||
type Context = Resolve<z.infer<typeof contextSchema>>;
|
||||
|
||||
export { contextSchema, type Context };
|
||||
17
packages/pl-api/lib/entities/conversation.ts
Normal file
17
packages/pl-api/lib/entities/conversation.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
import { accountSchema, statusSchema } from '.';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Conversation} */
|
||||
const conversationSchema = z.object({
|
||||
id: z.string(),
|
||||
unread: z.boolean().catch(false),
|
||||
accounts: filteredArray(accountSchema),
|
||||
last_status: statusSchema.nullable().catch(null),
|
||||
});
|
||||
|
||||
type Conversation = z.infer<typeof conversationSchema>;
|
||||
|
||||
export { conversationSchema, type Conversation };
|
||||
17
packages/pl-api/lib/entities/custom-emoji.ts
Normal file
17
packages/pl-api/lib/entities/custom-emoji.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import z from 'zod';
|
||||
|
||||
/**
|
||||
* Represents a custom emoji.
|
||||
* @see {@link https://docs.joinmastodon.org/entities/CustomEmoji/}
|
||||
*/
|
||||
const customEmojiSchema = z.object({
|
||||
shortcode: z.string(),
|
||||
url: z.string(),
|
||||
static_url: z.string().catch(''),
|
||||
visible_in_picker: z.boolean().catch(true),
|
||||
category: z.string().nullable().catch(null),
|
||||
});
|
||||
|
||||
type CustomEmoji = z.infer<typeof customEmojiSchema>;
|
||||
|
||||
export { customEmojiSchema, type CustomEmoji };
|
||||
13
packages/pl-api/lib/entities/domain-block.ts
Normal file
13
packages/pl-api/lib/entities/domain-block.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/DomainBlock} */
|
||||
const domainBlockSchema = z.object({
|
||||
domain: z.string(),
|
||||
digest: z.string(),
|
||||
severity: z.enum(['silence', 'suspend']),
|
||||
comment: z.string().optional().catch(undefined),
|
||||
});
|
||||
|
||||
type DomainBlock = z.infer<typeof domainBlockSchema>;
|
||||
|
||||
export { domainBlockSchema, type DomainBlock };
|
||||
27
packages/pl-api/lib/entities/emoji-reaction.ts
Normal file
27
packages/pl-api/lib/entities/emoji-reaction.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { emojiSchema, filteredArray } from './utils';
|
||||
|
||||
const baseEmojiReactionSchema = z.object({
|
||||
count: z.number().nullable().catch(null),
|
||||
me: z.boolean().catch(false),
|
||||
name: emojiSchema,
|
||||
url: z.literal(undefined).catch(undefined),
|
||||
accounts: filteredArray(accountSchema),
|
||||
});
|
||||
|
||||
const customEmojiReactionSchema = baseEmojiReactionSchema.extend({
|
||||
name: z.string(),
|
||||
url: z.string().url(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Pleroma emoji reaction.
|
||||
* @see {@link https://docs.pleroma.social/backend/development/API/differences_in_mastoapi_responses/#statuses}
|
||||
*/
|
||||
const emojiReactionSchema = baseEmojiReactionSchema.or(customEmojiReactionSchema);
|
||||
|
||||
type EmojiReaction = z.infer<typeof emojiReactionSchema>;
|
||||
|
||||
export { emojiReactionSchema, type EmojiReaction };
|
||||
13
packages/pl-api/lib/entities/extended-description.ts
Normal file
13
packages/pl-api/lib/entities/extended-description.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from './utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/ExtendedDescription} */
|
||||
const extendedDescriptionSchema = z.object({
|
||||
updated_at: dateSchema,
|
||||
content: z.string(),
|
||||
});
|
||||
|
||||
type ExtendedDescription = z.infer<typeof extendedDescriptionSchema>;
|
||||
|
||||
export { extendedDescriptionSchema, type ExtendedDescription };
|
||||
14
packages/pl-api/lib/entities/familiar-followers.ts
Normal file
14
packages/pl-api/lib/entities/familiar-followers.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import z from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/FamiliarFollowers/} */
|
||||
const familiarFollowersSchema = z.object({
|
||||
id: z.string(),
|
||||
accounts: filteredArray(accountSchema),
|
||||
});
|
||||
|
||||
type FamiliarFollowers = z.infer<typeof familiarFollowersSchema>
|
||||
|
||||
export { familiarFollowersSchema, type FamiliarFollowers };
|
||||
14
packages/pl-api/lib/entities/featured-tag.ts
Normal file
14
packages/pl-api/lib/entities/featured-tag.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/FeaturedTag/} */
|
||||
const featuredTagSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
url: z.string().optional().catch(undefined),
|
||||
statuses_count: z.number(),
|
||||
last_status_at: z.number(),
|
||||
});
|
||||
|
||||
type FeaturedTag = z.infer<typeof featuredTagSchema>;
|
||||
|
||||
export { featuredTagSchema, type FeaturedTag };
|
||||
16
packages/pl-api/lib/entities/filter-result.ts
Normal file
16
packages/pl-api/lib/entities/filter-result.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { filterSchema } from './filter';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/FilterResult/} */
|
||||
const filterResultSchema = z.object({
|
||||
filter: filterSchema,
|
||||
keyword_matches: z.array(z.string()).nullable().catch(null),
|
||||
status_matches: z.array(z.string()).nullable().catch(null),
|
||||
});
|
||||
|
||||
type FilterResult = Resolve<z.infer<typeof filterResultSchema>>;
|
||||
|
||||
export { filterResultSchema, type FilterResult };
|
||||
47
packages/pl-api/lib/entities/filter.ts
Normal file
47
packages/pl-api/lib/entities/filter.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/FilterKeyword/} */
|
||||
const filterKeywordSchema = z.object({
|
||||
id: z.string(),
|
||||
keyword: z.string(),
|
||||
whole_word: z.boolean(),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/FilterStatus/} */
|
||||
const filterStatusSchema = z.object({
|
||||
id: z.string(),
|
||||
status_id: z.string(),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Filter/} */
|
||||
const filterSchema = z.preprocess((filter: any) => {
|
||||
if (filter.phrase) {
|
||||
return {
|
||||
...filter,
|
||||
title: filter.phrase,
|
||||
keywords: [{
|
||||
id: '1',
|
||||
keyword: filter.phrase,
|
||||
whole_word: filter.whole_word,
|
||||
}],
|
||||
filter_action: filter.irreversible ? 'hide' : 'warn',
|
||||
};
|
||||
}
|
||||
return filter;
|
||||
}, z.object({
|
||||
id: z.string(),
|
||||
title: z.string(),
|
||||
context: z.array(z.enum(['home', 'notifications', 'public', 'thread', 'account'])),
|
||||
expires_at: z.string().datetime({ offset: true }).nullable().catch(null),
|
||||
filter_action: z.enum(['warn', 'hide']).catch('warn'),
|
||||
keywords: filteredArray(filterKeywordSchema),
|
||||
statuses: filteredArray(filterStatusSchema),
|
||||
}));
|
||||
|
||||
type Filter = Resolve<z.infer<typeof filterSchema>>;
|
||||
|
||||
export { filterKeywordSchema, filterStatusSchema, filterSchema, type Filter };
|
||||
21
packages/pl-api/lib/entities/group-member.ts
Normal file
21
packages/pl-api/lib/entities/group-member.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import z from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
|
||||
enum GroupRoles {
|
||||
OWNER = 'owner',
|
||||
ADMIN = 'admin',
|
||||
USER = 'user'
|
||||
}
|
||||
|
||||
type GroupRole =`${GroupRoles}`;
|
||||
|
||||
const groupMemberSchema = z.object({
|
||||
id: z.string(),
|
||||
account: accountSchema,
|
||||
role: z.nativeEnum(GroupRoles),
|
||||
});
|
||||
|
||||
type GroupMember = z.infer<typeof groupMemberSchema>;
|
||||
|
||||
export { groupMemberSchema, type GroupMember, GroupRoles, type GroupRole };
|
||||
14
packages/pl-api/lib/entities/group-relationship.ts
Normal file
14
packages/pl-api/lib/entities/group-relationship.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import z from 'zod';
|
||||
|
||||
import { GroupRoles } from './group-member';
|
||||
|
||||
const groupRelationshipSchema = z.object({
|
||||
id: z.string(),
|
||||
member: z.boolean().catch(false),
|
||||
role: z.nativeEnum(GroupRoles).catch(GroupRoles.USER),
|
||||
requested: z.boolean().catch(false),
|
||||
});
|
||||
|
||||
type GroupRelationship = z.infer<typeof groupRelationshipSchema>;
|
||||
|
||||
export { groupRelationshipSchema, type GroupRelationship };
|
||||
33
packages/pl-api/lib/entities/group.ts
Normal file
33
packages/pl-api/lib/entities/group.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import z from 'zod';
|
||||
|
||||
import { customEmojiSchema } from './custom-emoji';
|
||||
import { groupRelationshipSchema } from './group-relationship';
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
const groupSchema = z.object({
|
||||
avatar: z.string().catch(''),
|
||||
avatar_static: z.string().catch(''),
|
||||
created_at: z.string().datetime().catch(new Date().toUTCString()),
|
||||
display_name: z.string().catch(''),
|
||||
domain: z.string().catch(''),
|
||||
emojis: filteredArray(customEmojiSchema),
|
||||
header: z.string().catch(''),
|
||||
header_static: z.string().catch(''),
|
||||
id: z.coerce.string(),
|
||||
locked: z.boolean().catch(false),
|
||||
membership_required: z.boolean().catch(false),
|
||||
members_count: z.number().catch(0),
|
||||
owner: z.object({ id: z.string() }).nullable().catch(null),
|
||||
note: z.string().transform(note => note === '<p></p>' ? '' : note).catch(''),
|
||||
relationship: groupRelationshipSchema.nullable().catch(null), // Dummy field to be overwritten later
|
||||
statuses_visibility: z.string().catch('public'),
|
||||
uri: z.string().catch(''),
|
||||
url: z.string().catch(''),
|
||||
|
||||
avatar_description: z.string().catch(''),
|
||||
header_description: z.string().catch(''),
|
||||
});
|
||||
|
||||
type Group = z.infer<typeof groupSchema>;
|
||||
|
||||
export { groupSchema, type Group };
|
||||
69
packages/pl-api/lib/entities/index.ts
Normal file
69
packages/pl-api/lib/entities/index.ts
Normal file
@ -0,0 +1,69 @@
|
||||
export * from './account';
|
||||
export * from './account-warning';
|
||||
export * from './admin/account';
|
||||
export * from './admin/announcement';
|
||||
export * from './admin/canonical-email-block';
|
||||
export * from './admin/cohort';
|
||||
export * from './admin/dimension';
|
||||
export * from './admin/domain';
|
||||
export * from './admin/domain-allow';
|
||||
export * from './admin/domain-block';
|
||||
export * from './admin/email-domain-block';
|
||||
export * from './admin/ip';
|
||||
export * from './admin/ip-block';
|
||||
export * from './admin/measure';
|
||||
export * from './admin/moderation-log-entry';
|
||||
export * from './admin/relay';
|
||||
export * from './admin/report';
|
||||
export * from './admin/rule';
|
||||
export * from './admin/tag';
|
||||
export * from './announcement';
|
||||
export * from './announcement-reaction';
|
||||
export * from './application';
|
||||
export * from './backup';
|
||||
export * from './bookmark-folder';
|
||||
export * from './chat';
|
||||
export * from './chat-message';
|
||||
export * from './context';
|
||||
export * from './conversation';
|
||||
export * from './custom-emoji';
|
||||
export * from './domain-block';
|
||||
export * from './emoji-reaction';
|
||||
export * from './extended-description';
|
||||
export * from './familiar-followers';
|
||||
export * from './featured-tag';
|
||||
export * from './filter';
|
||||
export * from './group';
|
||||
export * from './group-member';
|
||||
export * from './group-relationship';
|
||||
export * from './instance';
|
||||
export * from './interaction-policy';
|
||||
export * from './interaction-request';
|
||||
export * from './list';
|
||||
export * from './location';
|
||||
export * from './marker';
|
||||
export * from './media-attachment';
|
||||
export * from './mention';
|
||||
export * from './notification';
|
||||
export * from './notification-policy';
|
||||
export * from './notification-request';
|
||||
export * from './oauth-token';
|
||||
export * from './poll';
|
||||
export * from './preview-card';
|
||||
export * from './relationship';
|
||||
export * from './relationship-severance-event';
|
||||
export * from './report';
|
||||
export * from './role';
|
||||
export * from './rule';
|
||||
export * from './scheduled-status';
|
||||
export * from './search';
|
||||
export * from './status';
|
||||
export * from './status-edit';
|
||||
export * from './status-source';
|
||||
export * from './streaming-event';
|
||||
export * from './suggestion';
|
||||
export * from './tag';
|
||||
export * from './token';
|
||||
export * from './translation';
|
||||
export * from './trends-link';
|
||||
export * from './web-push-subscription';
|
||||
325
packages/pl-api/lib/entities/instance.ts
Normal file
325
packages/pl-api/lib/entities/instance.ts
Normal file
@ -0,0 +1,325 @@
|
||||
/* eslint sort-keys: "error" */
|
||||
import z from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { ruleSchema } from './rule';
|
||||
import { coerceObject, filteredArray, mimeSchema } from './utils';
|
||||
|
||||
const fixVersion = (version: string) => {
|
||||
// Handle Mastodon release candidates
|
||||
if (new RegExp(/[0-9.]+rc[0-9]+/g).test(version)) {
|
||||
version = version.split('rc').join('-rc');
|
||||
}
|
||||
|
||||
// Rename Akkoma to Pleroma+akkoma
|
||||
if (version.includes('Akkoma')) {
|
||||
version = '2.7.2 (compatible; Pleroma 2.4.50+akkoma)';
|
||||
}
|
||||
|
||||
// Set Takahē version to a Pleroma-like string
|
||||
if (version.startsWith('takahe/')) {
|
||||
version = `0.0.0 (compatible; Takahe ${version.slice(7)})`;
|
||||
}
|
||||
|
||||
return version;
|
||||
};
|
||||
|
||||
const configurationSchema = coerceObject({
|
||||
accounts: z.object({
|
||||
allow_custom_css: z.boolean(),
|
||||
max_featured_tags: z.number().int(),
|
||||
max_profile_fields: z.number().int(),
|
||||
}).nullable().catch(null),
|
||||
chats: coerceObject({
|
||||
max_characters: z.number().catch(5000),
|
||||
}),
|
||||
groups: coerceObject({
|
||||
max_characters_description: z.number().catch(160),
|
||||
max_characters_name: z.number().catch(50),
|
||||
}),
|
||||
media_attachments: coerceObject({
|
||||
image_matrix_limit: z.number().optional().catch(undefined),
|
||||
image_size_limit: z.number().optional().catch(undefined),
|
||||
supported_mime_types: mimeSchema.array().optional().catch(undefined),
|
||||
video_duration_limit: z.number().optional().catch(undefined),
|
||||
video_frame_rate_limit: z.number().optional().catch(undefined),
|
||||
video_matrix_limit: z.number().optional().catch(undefined),
|
||||
video_size_limit: z.number().optional().catch(undefined),
|
||||
}),
|
||||
polls: coerceObject({
|
||||
max_characters_per_option: z.number().optional().catch(undefined),
|
||||
max_expiration: z.number().optional().catch(undefined),
|
||||
max_options: z.number().optional().catch(undefined),
|
||||
min_expiration: z.number().optional().catch(undefined),
|
||||
}),
|
||||
reactions: coerceObject({
|
||||
max_reactions: z.number().catch(0),
|
||||
}),
|
||||
statuses: coerceObject({
|
||||
characters_reserved_per_url: z.number().optional().catch(undefined),
|
||||
max_characters: z.number().optional().catch(undefined),
|
||||
max_media_attachments: z.number().optional().catch(undefined),
|
||||
|
||||
}),
|
||||
translation: coerceObject({
|
||||
enabled: z.boolean().catch(false),
|
||||
}),
|
||||
urls: coerceObject({
|
||||
streaming: z.string().url().optional().catch(undefined),
|
||||
}),
|
||||
});
|
||||
|
||||
const contactSchema = coerceObject({
|
||||
contact_account: accountSchema.optional().catch(undefined),
|
||||
email: z.string().email().catch(''),
|
||||
});
|
||||
|
||||
const pleromaSchema = coerceObject({
|
||||
metadata: coerceObject({
|
||||
account_activation_required: z.boolean().catch(false),
|
||||
birthday_min_age: z.number().catch(0),
|
||||
birthday_required: z.boolean().catch(false),
|
||||
description_limit: z.number().catch(1500),
|
||||
features: z.string().array().catch([]),
|
||||
federation: coerceObject({
|
||||
enabled: z.boolean().catch(true), // Assume true unless explicitly false
|
||||
mrf_policies: z.string().array().optional().catch(undefined),
|
||||
mrf_simple: coerceObject({
|
||||
accept: z.string().array().catch([]),
|
||||
avatar_removal: z.string().array().catch([]),
|
||||
banner_removal: z.string().array().catch([]),
|
||||
federated_timeline_removal: z.string().array().catch([]),
|
||||
followers_only: z.string().array().catch([]),
|
||||
media_nsfw: z.string().array().catch([]),
|
||||
media_removal: z.string().array().catch([]),
|
||||
reject: z.string().array().catch([]),
|
||||
reject_deletes: z.string().array().catch([]),
|
||||
report_removal: z.string().array().catch([]),
|
||||
}),
|
||||
}),
|
||||
fields_limits: coerceObject({
|
||||
max_fields: z.number().nonnegative().catch(4),
|
||||
name_length: z.number().nonnegative().catch(255),
|
||||
value_length: z.number().nonnegative().catch(2047),
|
||||
}),
|
||||
markup: coerceObject({
|
||||
allow_headings: z.boolean().catch(false),
|
||||
allow_inline_images: z.boolean().catch(false),
|
||||
}),
|
||||
migration_cooldown_period: z.number().optional().catch(undefined),
|
||||
multitenancy: coerceObject({
|
||||
domains: z
|
||||
.array(
|
||||
z.object({
|
||||
domain: z.coerce.string(),
|
||||
id: z.string(),
|
||||
public: z.boolean().catch(false),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
enabled: z.boolean().catch(false),
|
||||
}),
|
||||
post_formats: z.string().array().optional().catch(undefined),
|
||||
restrict_unauthenticated: coerceObject({
|
||||
activities: coerceObject({
|
||||
local: z.boolean().catch(false),
|
||||
remote: z.boolean().catch(false),
|
||||
}),
|
||||
profiles: coerceObject({
|
||||
local: z.boolean().catch(false),
|
||||
remote: z.boolean().catch(false),
|
||||
}),
|
||||
timelines: coerceObject({
|
||||
bubble: z.boolean().catch(false),
|
||||
federated: z.boolean().catch(false),
|
||||
local: z.boolean().catch(false),
|
||||
}),
|
||||
}),
|
||||
translation: coerceObject({
|
||||
allow_remote: z.boolean().catch(true),
|
||||
allow_unauthenticated: z.boolean().catch(false),
|
||||
source_languages: z.string().array().optional().catch(undefined),
|
||||
target_languages: z.string().array().optional().catch(undefined),
|
||||
}),
|
||||
}),
|
||||
oauth_consumer_strategies: z.string().array().catch([]),
|
||||
stats: coerceObject({
|
||||
mau: z.number().optional().catch(undefined),
|
||||
}),
|
||||
vapid_public_key: z.string().catch(''),
|
||||
});
|
||||
|
||||
const pleromaPollLimitsSchema = coerceObject({
|
||||
max_expiration: z.number().optional().catch(undefined),
|
||||
max_option_chars: z.number().optional().catch(undefined),
|
||||
max_options: z.number().optional().catch(undefined),
|
||||
min_expiration: z.number().optional().catch(undefined),
|
||||
});
|
||||
|
||||
const registrations = coerceObject({
|
||||
approval_required: z.boolean().catch(false),
|
||||
enabled: z.boolean().catch(false),
|
||||
message: z.string().optional().catch(undefined),
|
||||
});
|
||||
|
||||
const statsSchema = coerceObject({
|
||||
domain_count: z.number().optional().catch(undefined),
|
||||
status_count: z.number().optional().catch(undefined),
|
||||
user_count: z.number().optional().catch(undefined),
|
||||
});
|
||||
|
||||
const thumbnailSchema = coerceObject({
|
||||
url: z.string().catch(''),
|
||||
});
|
||||
|
||||
const usageSchema = coerceObject({
|
||||
users: coerceObject({
|
||||
active_month: z.number().catch(0),
|
||||
}),
|
||||
});
|
||||
|
||||
const instanceV1Schema = coerceObject({
|
||||
account_domain: z.string().catch(''),
|
||||
approval_required: z.boolean().catch(false),
|
||||
configuration: configurationSchema,
|
||||
contact_account: accountSchema.optional().catch(undefined),
|
||||
description: z.string().catch(''),
|
||||
description_limit: z.number().catch(1500),
|
||||
email: z.string().email().catch(''),
|
||||
feature_quote: z.boolean().catch(false),
|
||||
fedibird_capabilities: z.array(z.string()).catch([]),
|
||||
languages: z.string().array().catch([]),
|
||||
max_media_attachments: z.number().optional().catch(undefined),
|
||||
max_toot_chars: z.number().optional().catch(undefined),
|
||||
pleroma: pleromaSchema,
|
||||
poll_limits: pleromaPollLimitsSchema,
|
||||
registrations: z.boolean().catch(false),
|
||||
rules: filteredArray(ruleSchema),
|
||||
short_description: z.string().catch(''),
|
||||
stats: statsSchema,
|
||||
thumbnail: z.string().catch(''),
|
||||
title: z.string().catch(''),
|
||||
uri: z.string().catch(''),
|
||||
urls: coerceObject({
|
||||
streaming_api: z.string().url().optional().catch(undefined),
|
||||
}),
|
||||
usage: usageSchema,
|
||||
version: z.string().catch('0.0.0'),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Instance/} */
|
||||
const instanceSchema = z.preprocess((data: any) => {
|
||||
// Detect GoToSocial
|
||||
if (typeof data.configuration?.accounts?.allow_custom_css === 'boolean') {
|
||||
data.version = `0.0.0 (compatible; GoToSocial ${data.version})`;
|
||||
}
|
||||
|
||||
if (data.domain) return { account_domain: data.domain, ...data };
|
||||
|
||||
const {
|
||||
approval_required,
|
||||
configuration,
|
||||
contact_account,
|
||||
description,
|
||||
description_limit,
|
||||
email,
|
||||
max_media_attachments,
|
||||
max_toot_chars,
|
||||
poll_limits,
|
||||
pleroma,
|
||||
registrations,
|
||||
short_description,
|
||||
thumbnail,
|
||||
uri,
|
||||
urls,
|
||||
...instance
|
||||
} = instanceV1Schema.parse(data);
|
||||
|
||||
return {
|
||||
...instance,
|
||||
account_domain: instance.account_domain || uri,
|
||||
configuration: {
|
||||
...configuration,
|
||||
polls: {
|
||||
...configuration.polls,
|
||||
max_characters_per_option: configuration.polls.max_characters_per_option ?? poll_limits.max_option_chars ?? 25,
|
||||
max_expiration: configuration.polls.max_expiration ?? poll_limits.max_expiration ?? 2629746,
|
||||
max_options: configuration.polls.max_options ?? poll_limits.max_options ?? 4,
|
||||
min_expiration: configuration.polls.min_expiration ?? poll_limits.min_expiration ?? 300,
|
||||
},
|
||||
statuses: {
|
||||
...configuration.statuses,
|
||||
max_characters: configuration.statuses.max_characters ?? max_toot_chars ?? 500,
|
||||
max_media_attachments: configuration.statuses.max_media_attachments ?? max_media_attachments,
|
||||
},
|
||||
urls: {
|
||||
streaming: urls.streaming_api,
|
||||
},
|
||||
},
|
||||
contact: {
|
||||
account: contact_account,
|
||||
email: email,
|
||||
},
|
||||
description: short_description || description,
|
||||
domain: uri,
|
||||
pleroma: {
|
||||
...pleroma,
|
||||
metadata: {
|
||||
...pleroma.metadata,
|
||||
description_limit,
|
||||
},
|
||||
},
|
||||
registrations: {
|
||||
approval_required: approval_required,
|
||||
enabled: registrations,
|
||||
},
|
||||
thumbnail: { url: thumbnail },
|
||||
};
|
||||
}, coerceObject({
|
||||
account_domain: z.string().catch(''),
|
||||
configuration: configurationSchema,
|
||||
contact: contactSchema,
|
||||
description: z.string().catch(''),
|
||||
domain: z.string().catch(''),
|
||||
feature_quote: z.boolean().catch(false),
|
||||
fedibird_capabilities: z.array(z.string()).catch([]),
|
||||
languages: z.string().array().catch([]),
|
||||
pleroma: pleromaSchema,
|
||||
registrations: registrations,
|
||||
rules: filteredArray(ruleSchema),
|
||||
stats: statsSchema,
|
||||
thumbnail: thumbnailSchema,
|
||||
title: z.string().catch(''),
|
||||
usage: usageSchema,
|
||||
version: z.string().catch('0.0.0'),
|
||||
}).transform(({ configuration, ...instance }) => {
|
||||
const version = fixVersion(instance.version);
|
||||
|
||||
const polls = {
|
||||
...configuration.polls,
|
||||
max_characters_per_option: configuration.polls.max_characters_per_option ?? 25,
|
||||
max_expiration: configuration.polls.max_expiration ?? 2629746,
|
||||
max_options: configuration.polls.max_options ?? 4,
|
||||
min_expiration: configuration.polls.min_expiration ?? 300,
|
||||
};
|
||||
|
||||
const statuses = {
|
||||
...configuration.statuses,
|
||||
max_characters: configuration.statuses.max_characters ?? 500,
|
||||
max_media_attachments: configuration.statuses.max_media_attachments ?? 4,
|
||||
};
|
||||
|
||||
return {
|
||||
...instance,
|
||||
configuration: {
|
||||
...configuration,
|
||||
polls,
|
||||
statuses,
|
||||
},
|
||||
version,
|
||||
};
|
||||
}));
|
||||
|
||||
type Instance = z.infer<typeof instanceSchema>;
|
||||
|
||||
export { instanceSchema, type Instance };
|
||||
33
packages/pl-api/lib/entities/interaction-policy.ts
Normal file
33
packages/pl-api/lib/entities/interaction-policy.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { coerceObject } from './utils';
|
||||
|
||||
const interactionPolicyEntrySchema = z.enum(['public', 'followers', 'following', 'mutuals', 'mentioned', 'author', 'me']);
|
||||
|
||||
const interactionPolicyRuleSchema = coerceObject({
|
||||
always: z.array(interactionPolicyEntrySchema).default(['public']),
|
||||
with_approval: z.array(interactionPolicyEntrySchema).default([]),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.gotosocial.org/en/latest/api/swagger/} */
|
||||
const interactionPolicySchema = coerceObject({
|
||||
can_favourite: interactionPolicyRuleSchema,
|
||||
can_reblog: interactionPolicyRuleSchema,
|
||||
can_reply: interactionPolicyRuleSchema,
|
||||
});
|
||||
|
||||
type InteractionPolicy = Resolve<z.infer<typeof interactionPolicySchema>>;
|
||||
|
||||
const interactionPoliciesSchema = coerceObject({
|
||||
public: interactionPolicySchema,
|
||||
unlisted: interactionPolicySchema,
|
||||
private: interactionPolicySchema,
|
||||
direct: interactionPolicySchema,
|
||||
});
|
||||
|
||||
type InteractionPolicies = Resolve<z.infer<typeof interactionPoliciesSchema>>;
|
||||
|
||||
export { interactionPolicySchema, interactionPoliciesSchema, type InteractionPolicy, type InteractionPolicies };
|
||||
|
||||
23
packages/pl-api/lib/entities/interaction-request.ts
Normal file
23
packages/pl-api/lib/entities/interaction-request.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { statusSchema } from './status';
|
||||
|
||||
/** @see {@link https://docs.gotosocial.org/en/latest/api/swagger.yaml#/definitions/interactionRequest} */
|
||||
const interactionRequestSchema = z.object({
|
||||
accepted_at: z.string().datetime().nullable().catch(null),
|
||||
account: accountSchema,
|
||||
created_at: z.string().datetime(),
|
||||
id: z.string(),
|
||||
rejected_at: z.string().datetime().nullable().catch(null),
|
||||
reply: statusSchema.nullable().catch(null),
|
||||
status: statusSchema.nullable().catch(null),
|
||||
type: z.enum(['favourite', 'reply', 'reblog']),
|
||||
uri: z.string().nullable().catch(null),
|
||||
});
|
||||
|
||||
type InteractionRequest = Resolve<z.infer<typeof interactionRequestSchema>>;
|
||||
|
||||
export { interactionRequestSchema, type InteractionRequest };
|
||||
13
packages/pl-api/lib/entities/list.ts
Normal file
13
packages/pl-api/lib/entities/list.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/List/} */
|
||||
const listSchema = z.object({
|
||||
id: z.coerce.string(),
|
||||
title: z.string(),
|
||||
replies_policy: z.string().optional().catch(undefined),
|
||||
exclusive: z.boolean().optional().catch(undefined),
|
||||
});
|
||||
|
||||
type List = z.infer<typeof listSchema>;
|
||||
|
||||
export { listSchema, type List };
|
||||
23
packages/pl-api/lib/entities/location.ts
Normal file
23
packages/pl-api/lib/entities/location.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const locationSchema = z.object({
|
||||
url: z.string().url().catch(''),
|
||||
description: z.string().catch(''),
|
||||
country: z.string().catch(''),
|
||||
locality: z.string().catch(''),
|
||||
region: z.string().catch(''),
|
||||
postal_code: z.string().catch(''),
|
||||
street: z.string().catch(''),
|
||||
origin_id: z.string().catch(''),
|
||||
origin_provider: z.string().catch(''),
|
||||
type: z.string().catch(''),
|
||||
timezone: z.string().catch(''),
|
||||
geom: z.object({
|
||||
coordinates: z.tuple([z.number(), z.number()]).nullable().catch(null),
|
||||
srid: z.string().catch(''),
|
||||
}).nullable().catch(null),
|
||||
});
|
||||
|
||||
type Location = z.infer<typeof locationSchema>;
|
||||
|
||||
export { locationSchema, type Location };
|
||||
27
packages/pl-api/lib/entities/marker.ts
Normal file
27
packages/pl-api/lib/entities/marker.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from './utils';
|
||||
|
||||
const markerSchema = z.preprocess((marker: any) => ({
|
||||
unread_count: marker.pleroma?.unread_count,
|
||||
...marker,
|
||||
}), z.object({
|
||||
last_read_id: z.string(),
|
||||
version: z.number().int(),
|
||||
updated_at: dateSchema,
|
||||
unread_count: z.number().int().optional().catch(undefined),
|
||||
}));
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Marker/} */
|
||||
type Marker = z.infer<typeof markerSchema>;
|
||||
|
||||
const markersSchema = z.record(markerSchema);
|
||||
|
||||
type Markers = z.infer<typeof markersSchema>;
|
||||
|
||||
export {
|
||||
markerSchema,
|
||||
markersSchema,
|
||||
type Marker,
|
||||
type Markers,
|
||||
};
|
||||
105
packages/pl-api/lib/entities/media-attachment.ts
Normal file
105
packages/pl-api/lib/entities/media-attachment.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import { isBlurhashValid } from 'blurhash';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { mimeSchema } from './utils';
|
||||
|
||||
const blurhashSchema = z.string().superRefine((value, ctx) => {
|
||||
const r = isBlurhashValid(value);
|
||||
|
||||
if (!r.result) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: r.errorReason,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const baseAttachmentSchema = z.object({
|
||||
id: z.string(),
|
||||
type: z.string(),
|
||||
url: z.string().url().catch(''),
|
||||
preview_url: z.string().url().catch(''),
|
||||
remote_url: z.string().url().nullable().catch(null),
|
||||
description: z.string().catch(''),
|
||||
blurhash: blurhashSchema.nullable().catch(null),
|
||||
|
||||
mime_type: mimeSchema.nullable().catch(null),
|
||||
});
|
||||
|
||||
const imageMetaSchema = z.object({
|
||||
width: z.number(),
|
||||
height: z.number(),
|
||||
size: z.string().regex(/\d+x\d+$/).nullable().catch(null),
|
||||
aspect: z.number().nullable().catch(null),
|
||||
});
|
||||
|
||||
const imageAttachmentSchema = baseAttachmentSchema.extend({
|
||||
type: z.literal('image'),
|
||||
meta: z.object({
|
||||
original: imageMetaSchema.optional().catch(undefined),
|
||||
small: imageMetaSchema.optional().catch(undefined),
|
||||
focus: z.object({
|
||||
x: z.number().min(-1).max(1),
|
||||
y: z.number().min(-1).max(1),
|
||||
}).optional().catch(undefined),
|
||||
}).catch({}),
|
||||
});
|
||||
|
||||
const videoAttachmentSchema = baseAttachmentSchema.extend({
|
||||
type: z.literal('video'),
|
||||
meta: z.object({
|
||||
duration: z.number().optional().catch(undefined),
|
||||
original: imageMetaSchema.extend({
|
||||
frame_rate: z.string().regex(/\d+\/\d+$/).nullable().catch(null),
|
||||
duration: z.number().nonnegative().nullable().catch(null),
|
||||
}).optional().catch(undefined),
|
||||
small: imageMetaSchema.optional().catch(undefined),
|
||||
// WIP: add rest
|
||||
}).catch({}),
|
||||
});
|
||||
|
||||
const gifvAttachmentSchema = baseAttachmentSchema.extend({
|
||||
type: z.literal('gifv'),
|
||||
meta: z.object({
|
||||
duration: z.number().optional().catch(undefined),
|
||||
original: imageMetaSchema.optional().catch(undefined),
|
||||
}).catch({}),
|
||||
});
|
||||
|
||||
const audioAttachmentSchema = baseAttachmentSchema.extend({
|
||||
type: z.literal('audio'),
|
||||
meta: z.object({
|
||||
duration: z.number().optional().catch(undefined),
|
||||
colors: z.object({
|
||||
background: z.string().optional().catch(undefined),
|
||||
foreground: z.string().optional().catch(undefined),
|
||||
accent: z.string().optional().catch(undefined),
|
||||
duration: z.number().optional().catch(undefined),
|
||||
}).optional().catch(undefined),
|
||||
original: z.object({
|
||||
duration: z.number().optional().catch(undefined),
|
||||
bitrate: z.number().nonnegative().optional().catch(undefined),
|
||||
}).optional().catch(undefined),
|
||||
}).catch({}),
|
||||
});
|
||||
|
||||
const unknownAttachmentSchema = baseAttachmentSchema.extend({
|
||||
type: z.literal('unknown'),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/MediaAttachment} */
|
||||
const mediaAttachmentSchema = z.preprocess((data: any) => ({
|
||||
mime_type: data.pleroma?.mime_type,
|
||||
preview_url: data.url,
|
||||
...data,
|
||||
}), z.discriminatedUnion('type', [
|
||||
imageAttachmentSchema,
|
||||
videoAttachmentSchema,
|
||||
gifvAttachmentSchema,
|
||||
audioAttachmentSchema,
|
||||
unknownAttachmentSchema,
|
||||
]));
|
||||
|
||||
type MediaAttachment = z.infer<typeof mediaAttachmentSchema>;
|
||||
|
||||
export { blurhashSchema, mediaAttachmentSchema, type MediaAttachment };
|
||||
19
packages/pl-api/lib/entities/mention.ts
Normal file
19
packages/pl-api/lib/entities/mention.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Status/#Mention} */
|
||||
const mentionSchema = z.object({
|
||||
id: z.string(),
|
||||
username: z.string().catch(''),
|
||||
url: z.string().url().catch(''),
|
||||
acct: z.string(),
|
||||
}).transform((mention) => {
|
||||
if (!mention.username) {
|
||||
mention.username = mention.acct.split('@')[0];
|
||||
}
|
||||
|
||||
return mention;
|
||||
});
|
||||
|
||||
type Mention = z.infer<typeof mentionSchema>;
|
||||
|
||||
export { mentionSchema, type Mention };
|
||||
17
packages/pl-api/lib/entities/notification-policy.ts
Normal file
17
packages/pl-api/lib/entities/notification-policy.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/NotificationPolicy} */
|
||||
const notificationPolicySchema = z.object({
|
||||
filter_not_following: z.boolean(),
|
||||
filter_not_followers: z.boolean(),
|
||||
filter_new_accounts: z.boolean(),
|
||||
filter_private_mentions: z.boolean(),
|
||||
summary: z.object({
|
||||
pending_requests_count: z.number().int(),
|
||||
pending_notifications_count: z.number().int(),
|
||||
}),
|
||||
});
|
||||
|
||||
type NotificationPolicy = z.infer<typeof notificationPolicySchema>;
|
||||
|
||||
export { notificationPolicySchema, type NotificationPolicy };
|
||||
19
packages/pl-api/lib/entities/notification-request.ts
Normal file
19
packages/pl-api/lib/entities/notification-request.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { dateSchema } from './utils';
|
||||
|
||||
import { accountSchema, statusSchema } from '.';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/NotificationRequest} */
|
||||
const notificationRequestSchema = z.object({
|
||||
id: z.string(),
|
||||
created_at: dateSchema,
|
||||
updated_at: dateSchema,
|
||||
account: accountSchema,
|
||||
notifications_count: z.coerce.string(),
|
||||
last_status: statusSchema.optional().catch(undefined),
|
||||
});
|
||||
|
||||
type NotificationRequest = z.infer<typeof notificationRequestSchema>;
|
||||
|
||||
export { notificationRequestSchema, type NotificationRequest };
|
||||
100
packages/pl-api/lib/entities/notification.ts
Normal file
100
packages/pl-api/lib/entities/notification.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import pick from 'lodash.pick';
|
||||
import { z } from 'zod';
|
||||
|
||||
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 { dateSchema } from './utils';
|
||||
|
||||
const baseNotificationSchema = z.object({
|
||||
account: accountSchema,
|
||||
created_at: dateSchema,
|
||||
id: z.string(),
|
||||
type: z.string(),
|
||||
|
||||
is_muted: z.boolean().optional().catch(undefined),
|
||||
is_seen: z.boolean().optional().catch(undefined),
|
||||
});
|
||||
|
||||
const accountNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.enum(['follow', 'follow_request', 'admin.sign_up', 'bite']),
|
||||
});
|
||||
|
||||
const statusNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.enum(['mention', 'status', 'reblog', 'favourite', 'poll', 'update', 'event_reminder']),
|
||||
status: statusSchema,
|
||||
});
|
||||
|
||||
const reportNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.literal('admin.report'),
|
||||
report: reportSchema,
|
||||
});
|
||||
|
||||
const severedRelationshipNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.literal('severed_relationships'),
|
||||
relationship_severance_event: relationshipSeveranceEventSchema,
|
||||
});
|
||||
|
||||
const moderationWarningNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.literal('moderation_warning'),
|
||||
moderation_warning: accountWarningSchema,
|
||||
});
|
||||
|
||||
const moveNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.literal('move'),
|
||||
target: accountSchema,
|
||||
});
|
||||
|
||||
const emojiReactionNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.literal('emoji_reaction'),
|
||||
emoji: z.string(),
|
||||
emoji_url: z.string().nullable().catch(null),
|
||||
status: statusSchema,
|
||||
});
|
||||
|
||||
const chatMentionNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.literal('chat_mention'),
|
||||
chat_message: chatMessageSchema,
|
||||
});
|
||||
|
||||
const eventParticipationRequestNotificationSchema = baseNotificationSchema.extend({
|
||||
type: z.enum(['participation_accepted', 'participation_request']),
|
||||
status: statusSchema,
|
||||
participation_message: z.string().nullable().catch(null),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Notification/} */
|
||||
const notificationSchema: z.ZodType<Notification> = z.preprocess((notification: any) => ({
|
||||
...pick(notification.pleroma || {}, ['is_muted', 'is_seen']),
|
||||
...notification,
|
||||
type: notification.type === 'pleroma:report'
|
||||
? 'admin.report'
|
||||
: notification.type?.replace(/^pleroma:/, ''),
|
||||
}), z.discriminatedUnion('type', [
|
||||
accountNotificationSchema,
|
||||
statusNotificationSchema,
|
||||
reportNotificationSchema,
|
||||
severedRelationshipNotificationSchema,
|
||||
moderationWarningNotificationSchema,
|
||||
moveNotificationSchema,
|
||||
emojiReactionNotificationSchema,
|
||||
chatMentionNotificationSchema,
|
||||
eventParticipationRequestNotificationSchema,
|
||||
])) as any;
|
||||
|
||||
type Notification = z.infer<
|
||||
| typeof accountNotificationSchema
|
||||
| typeof statusNotificationSchema
|
||||
| typeof reportNotificationSchema
|
||||
| typeof severedRelationshipNotificationSchema
|
||||
| typeof moderationWarningNotificationSchema
|
||||
| typeof moveNotificationSchema
|
||||
| typeof emojiReactionNotificationSchema
|
||||
| typeof chatMentionNotificationSchema
|
||||
| typeof eventParticipationRequestNotificationSchema
|
||||
>;
|
||||
|
||||
export { notificationSchema, type Notification };
|
||||
15
packages/pl-api/lib/entities/oauth-token.ts
Normal file
15
packages/pl-api/lib/entities/oauth-token.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.pleroma.social/backend/development/API/pleroma_api/#get-apioauth_tokens} */
|
||||
const oauthTokenSchema = z.preprocess((token: any) => ({
|
||||
...token,
|
||||
valid_until: token?.valid_until?.padEnd(27, 'Z'),
|
||||
}), z.object({
|
||||
app_name: z.string(),
|
||||
id: z.number(),
|
||||
valid_until: z.string().datetime({ offset: true }),
|
||||
}));
|
||||
|
||||
type OauthToken = z.infer<typeof oauthTokenSchema>;
|
||||
|
||||
export { oauthTokenSchema, type OauthToken };
|
||||
32
packages/pl-api/lib/entities/poll.ts
Normal file
32
packages/pl-api/lib/entities/poll.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { customEmojiSchema } from './custom-emoji';
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
const pollOptionSchema = z.object({
|
||||
title: z.string().catch(''),
|
||||
votes_count: z.number().catch(0),
|
||||
|
||||
title_map: z.record(z.string()).nullable().catch(null),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Poll/} */
|
||||
const pollSchema = z.object({
|
||||
emojis: filteredArray(customEmojiSchema),
|
||||
expired: z.boolean().catch(false),
|
||||
expires_at: z.string().datetime().nullable().catch(null),
|
||||
id: z.string(),
|
||||
multiple: z.boolean().catch(false),
|
||||
options: z.array(pollOptionSchema).min(2),
|
||||
voters_count: z.number().catch(0),
|
||||
votes_count: z.number().catch(0),
|
||||
own_votes: z.array(z.number()).nonempty().nullable().catch(null),
|
||||
voted: z.boolean().catch(false),
|
||||
|
||||
non_anonymous: z.boolean().catch(false),
|
||||
});
|
||||
|
||||
type Poll = z.infer<typeof pollSchema>;
|
||||
type PollOption = Poll['options'][number];
|
||||
|
||||
export { pollSchema, type Poll, type PollOption };
|
||||
24
packages/pl-api/lib/entities/preview-card.ts
Normal file
24
packages/pl-api/lib/entities/preview-card.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/PreviewCard/} */
|
||||
const previewCardSchema = z.object({
|
||||
author_name: z.string().catch(''),
|
||||
author_url: z.string().url().catch(''),
|
||||
blurhash: z.string().nullable().catch(null),
|
||||
description: z.string().catch(''),
|
||||
embed_url: z.string().url().catch(''),
|
||||
height: z.number().catch(0),
|
||||
html: z.string().catch(''),
|
||||
image: z.string().nullable().catch(null),
|
||||
image_description: z.string().catch(''),
|
||||
provider_name: z.string().catch(''),
|
||||
provider_url: z.string().url().catch(''),
|
||||
title: z.string().catch(''),
|
||||
type: z.enum(['link', 'photo', 'video', 'rich']).catch('link'),
|
||||
url: z.string().url(),
|
||||
width: z.number().catch(0),
|
||||
});
|
||||
|
||||
type PreviewCard = z.infer<typeof previewCardSchema>;
|
||||
|
||||
export { previewCardSchema, type PreviewCard };
|
||||
18
packages/pl-api/lib/entities/relationship-severance-event.ts
Normal file
18
packages/pl-api/lib/entities/relationship-severance-event.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { dateSchema } from './utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/RelationshipSeveranceEvent/} */
|
||||
const relationshipSeveranceEventSchema = z.object({
|
||||
id: z.string(),
|
||||
type: z.enum(['domain_block', 'user_domain_block', 'account_suspension']),
|
||||
purged: z.string(),
|
||||
relationships_count: z.number().optional().catch(undefined),
|
||||
created_at: dateSchema,
|
||||
});
|
||||
|
||||
type RelationshipSeveranceEvent = Resolve<z.infer<typeof relationshipSeveranceEventSchema>>;
|
||||
|
||||
export { relationshipSeveranceEventSchema, type RelationshipSeveranceEvent };
|
||||
22
packages/pl-api/lib/entities/relationship.ts
Normal file
22
packages/pl-api/lib/entities/relationship.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import z from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Relationship/} */
|
||||
const relationshipSchema = z.object({
|
||||
blocked_by: z.boolean().catch(false),
|
||||
blocking: z.boolean().catch(false),
|
||||
domain_blocking: z.boolean().catch(false),
|
||||
endorsed: z.boolean().catch(false),
|
||||
followed_by: z.boolean().catch(false),
|
||||
following: z.boolean().catch(false),
|
||||
id: z.string(),
|
||||
muting: z.boolean().catch(false),
|
||||
muting_notifications: z.boolean().catch(false),
|
||||
note: z.string().catch(''),
|
||||
notifying: z.boolean().catch(false),
|
||||
requested: z.boolean().catch(false),
|
||||
showing_reblogs: z.boolean().catch(false),
|
||||
});
|
||||
|
||||
type Relationship = z.infer<typeof relationshipSchema>;
|
||||
|
||||
export { relationshipSchema, type Relationship };
|
||||
22
packages/pl-api/lib/entities/report.ts
Normal file
22
packages/pl-api/lib/entities/report.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { dateSchema } from './utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Report/} */
|
||||
const reportSchema = z.object({
|
||||
id: z.string(),
|
||||
action_taken: z.boolean().optional().catch(undefined),
|
||||
action_taken_at: dateSchema.nullable().catch(null),
|
||||
category: z.string().optional().catch(undefined),
|
||||
comment: z.string().optional().catch(undefined),
|
||||
forwarded: z.boolean().optional().catch(undefined),
|
||||
created_at: dateSchema.optional().catch(undefined),
|
||||
status_ids: z.array(z.string()).nullable().catch(null),
|
||||
rule_ids: z.array(z.string()).nullable().catch(null),
|
||||
target_account: accountSchema,
|
||||
});
|
||||
|
||||
type Report = z.infer<typeof reportSchema>;
|
||||
|
||||
export { reportSchema, type Report };
|
||||
18
packages/pl-api/lib/entities/role.ts
Normal file
18
packages/pl-api/lib/entities/role.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const hexSchema = z.string().regex(/^#[a-f0-9]{6}$/i);
|
||||
|
||||
const roleSchema = z.object({
|
||||
id: z.string().catch(''),
|
||||
name: z.string().catch(''),
|
||||
color: hexSchema.catch(''),
|
||||
permissions: z.string().catch(''),
|
||||
highlighted: z.boolean().catch(true),
|
||||
});
|
||||
|
||||
type Role = z.infer<typeof roleSchema>;
|
||||
|
||||
export {
|
||||
roleSchema,
|
||||
type Role,
|
||||
};
|
||||
17
packages/pl-api/lib/entities/rule.ts
Normal file
17
packages/pl-api/lib/entities/rule.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const baseRuleSchema = z.object({
|
||||
id: z.string(),
|
||||
text: z.string().catch(''),
|
||||
hint: z.string().catch(''),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Rule/} */
|
||||
const ruleSchema = z.preprocess((data: any) => ({
|
||||
...data,
|
||||
hint: data.hint || data.subtext,
|
||||
}), baseRuleSchema);
|
||||
|
||||
type Rule = z.infer<typeof ruleSchema>;
|
||||
|
||||
export { ruleSchema, type Rule };
|
||||
38
packages/pl-api/lib/entities/scheduled-status.ts
Normal file
38
packages/pl-api/lib/entities/scheduled-status.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { mediaAttachmentSchema } from './media-attachment';
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
import type { Resolve } from '../utils/types';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/ScheduledStatus/} */
|
||||
const scheduledStatusSchema = z.object({
|
||||
id: z.string(),
|
||||
scheduled_at: z.string().datetime({ offset: true }),
|
||||
params: z.object({
|
||||
text: z.string().nullable().catch(null),
|
||||
poll: z.object({
|
||||
options: z.array(z.string()),
|
||||
expires_in: z.coerce.string(),
|
||||
multiple: z.boolean().optional().catch(undefined),
|
||||
hide_totals: z.boolean().optional().catch(undefined),
|
||||
}).nullable().catch(null),
|
||||
media_ids: z.array(z.string()).nullable().catch(null),
|
||||
sensitive: z.coerce.boolean().nullable().catch(null),
|
||||
spoiler_text: z.string().nullable().catch(null),
|
||||
visibility: z.string().catch('public'),
|
||||
in_reply_to_id: z.string().nullable().catch(null),
|
||||
language: z.string().nullable().catch(null),
|
||||
application_id: z.number().int().nullable().catch(null),
|
||||
scheduled_at: z.string().datetime({ offset: true }).nullable().catch(null),
|
||||
idempotency: z.string().nullable().catch(null),
|
||||
with_rate_limit: z.boolean().catch(false),
|
||||
|
||||
expires_in: z.number().nullable().catch(null),
|
||||
}),
|
||||
media_attachments: filteredArray(mediaAttachmentSchema),
|
||||
});
|
||||
|
||||
type ScheduledStatus = Resolve<z.infer<typeof scheduledStatusSchema>>;
|
||||
|
||||
export { scheduledStatusSchema, type ScheduledStatus };
|
||||
17
packages/pl-api/lib/entities/search.ts
Normal file
17
packages/pl-api/lib/entities/search.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
import { accountSchema, groupSchema, statusSchema, tagSchema } from '.';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Search} */
|
||||
const searchSchema = z.object({
|
||||
accounts: filteredArray(accountSchema),
|
||||
statuses: filteredArray(statusSchema),
|
||||
hashtags: filteredArray(tagSchema),
|
||||
groups: filteredArray(groupSchema),
|
||||
});
|
||||
|
||||
type Search = z.infer<typeof searchSchema>;
|
||||
|
||||
export { searchSchema, type Search };
|
||||
28
packages/pl-api/lib/entities/status-edit.ts
Normal file
28
packages/pl-api/lib/entities/status-edit.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { customEmojiSchema } from './custom-emoji';
|
||||
import { mediaAttachmentSchema } from './media-attachment';
|
||||
import { dateSchema, filteredArray } from './utils';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/StatusEdit/} */
|
||||
const statusEditSchema = z.object({
|
||||
content: z.string().catch(''),
|
||||
spoiler_text: z.string().catch(''),
|
||||
sensitive: z.coerce.boolean(),
|
||||
created_at: dateSchema,
|
||||
account: accountSchema,
|
||||
poll: z.object({
|
||||
options: z.array(z.object({
|
||||
title: z.string(),
|
||||
})),
|
||||
}).nullable().catch(null),
|
||||
media_attachments: filteredArray(mediaAttachmentSchema),
|
||||
emojis: filteredArray(customEmojiSchema),
|
||||
});
|
||||
|
||||
type StatusEdit = Resolve<z.infer<typeof statusEditSchema>>;
|
||||
|
||||
export { statusEditSchema, type StatusEdit };
|
||||
22
packages/pl-api/lib/entities/status-source.ts
Normal file
22
packages/pl-api/lib/entities/status-source.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { locationSchema } from './location';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/StatusSource/} */
|
||||
const statusSourceSchema = z.object({
|
||||
id: z.string(),
|
||||
text: z.string().catch(''),
|
||||
spoiler_text: z.string().catch(''),
|
||||
|
||||
content_type: z.string().catch('text/plain'),
|
||||
location: locationSchema.nullable().catch(null),
|
||||
|
||||
text_map: z.record(z.string()).nullable().catch(null),
|
||||
spoiler_text_map: z.record(z.string()).nullable().catch(null),
|
||||
});
|
||||
|
||||
type StatusSource = Resolve<z.infer<typeof statusSourceSchema>>;
|
||||
|
||||
export { statusSourceSchema, type StatusSource };
|
||||
151
packages/pl-api/lib/entities/status.ts
Normal file
151
packages/pl-api/lib/entities/status.ts
Normal file
@ -0,0 +1,151 @@
|
||||
import pick from 'lodash.pick';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
import { customEmojiSchema } from './custom-emoji';
|
||||
import { emojiReactionSchema } from './emoji-reaction';
|
||||
import { filterResultSchema } from './filter-result';
|
||||
import { groupSchema } from './group';
|
||||
import { interactionPolicySchema } from './interaction-policy';
|
||||
import { mediaAttachmentSchema } from './media-attachment';
|
||||
import { mentionSchema } from './mention';
|
||||
import { pollSchema } from './poll';
|
||||
import { previewCardSchema } from './preview-card';
|
||||
import { tagSchema } from './tag';
|
||||
import { translationSchema } from './translation';
|
||||
import { dateSchema, filteredArray } from './utils';
|
||||
|
||||
import type { Resolve } from '../utils/types';
|
||||
|
||||
const statusEventSchema = z.object({
|
||||
name: z.string().catch(''),
|
||||
start_time: z.string().datetime().nullable().catch(null),
|
||||
end_time: z.string().datetime().nullable().catch(null),
|
||||
join_mode: z.enum(['free', 'restricted', 'invite']).nullable().catch(null),
|
||||
participants_count: z.number().catch(0),
|
||||
location: z.object({
|
||||
name: z.string().catch(''),
|
||||
url: z.string().url().catch(''),
|
||||
latitude: z.number().catch(0),
|
||||
longitude: z.number().catch(0),
|
||||
street: z.string().catch(''),
|
||||
postal_code: z.string().catch(''),
|
||||
locality: z.string().catch(''),
|
||||
region: z.string().catch(''),
|
||||
country: z.string().catch(''),
|
||||
}).nullable().catch(null),
|
||||
join_state: z.enum(['pending', 'reject', 'accept']).nullable().catch(null),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Status/} */
|
||||
const baseStatusSchema = z.object({
|
||||
id: z.string(),
|
||||
uri: z.string().url().catch(''),
|
||||
created_at: dateSchema,
|
||||
account: accountSchema,
|
||||
content: z.string().catch(''),
|
||||
visibility: z.string().catch('public'),
|
||||
sensitive: z.coerce.boolean(),
|
||||
spoiler_text: z.string().catch(''),
|
||||
media_attachments: filteredArray(mediaAttachmentSchema),
|
||||
application: z.object({
|
||||
name: z.string(),
|
||||
website: z.string().url().nullable().catch(null),
|
||||
}).nullable().catch(null),
|
||||
mentions: filteredArray(mentionSchema),
|
||||
tags: filteredArray(tagSchema),
|
||||
emojis: filteredArray(customEmojiSchema),
|
||||
reblogs_count: z.number().catch(0),
|
||||
favourites_count: z.number().catch(0),
|
||||
replies_count: z.number().catch(0),
|
||||
url: z.string().url().catch(''),
|
||||
in_reply_to_id: z.string().nullable().catch(null),
|
||||
in_reply_to_account_id: z.string().nullable().catch(null),
|
||||
poll: pollSchema.nullable().catch(null),
|
||||
card: previewCardSchema.nullable().catch(null),
|
||||
language: z.string().nullable().catch(null),
|
||||
text: z.string().nullable().catch(null),
|
||||
edited_at: z.string().datetime().nullable().catch(null),
|
||||
favourited: z.coerce.boolean(),
|
||||
reblogged: z.coerce.boolean(),
|
||||
muted: z.coerce.boolean(),
|
||||
bookmarked: z.coerce.boolean(),
|
||||
pinned: z.coerce.boolean(),
|
||||
filtered: filteredArray(filterResultSchema),
|
||||
approval_status: z.enum(['pending', 'approval', 'rejected']).nullable().catch(null),
|
||||
group: groupSchema.nullable().catch(null),
|
||||
scheduled_at: z.null().catch(null),
|
||||
|
||||
local: z.boolean().optional().catch(undefined),
|
||||
conversation_id: z.string().optional().catch(undefined),
|
||||
direct_conversation_id: z.string().optional().catch(undefined),
|
||||
in_reply_to_account_acct: z.string().optional().catch(undefined),
|
||||
expires_at: z.string().datetime({ offset: true }).optional().catch(undefined),
|
||||
thread_muted: z.boolean().optional().catch(undefined),
|
||||
emoji_reactions: filteredArray(emojiReactionSchema),
|
||||
parent_visible: z.boolean().optional().catch(undefined),
|
||||
pinned_at: z.string().datetime({ offset: true }).nullable().catch(null),
|
||||
quote_visible: z.boolean().optional().catch(undefined),
|
||||
quote_url: z.string().optional().catch(undefined),
|
||||
quotes_count: z.number().catch(0),
|
||||
bookmark_folder: z.string().nullable().catch(null),
|
||||
|
||||
event: statusEventSchema.nullable().catch(null),
|
||||
translation: translationSchema.nullable().or(z.literal(false)).catch(null),
|
||||
|
||||
content_map: z.record(z.string()).nullable().catch(null),
|
||||
text_map: z.record(z.string()).nullable().catch(null),
|
||||
spoiler_text_map: z.record(z.string()).nullable().catch(null),
|
||||
|
||||
dislikes_count: z.number().catch(0),
|
||||
disliked: z.coerce.boolean().catch(false),
|
||||
|
||||
interaction_policy: interactionPolicySchema,
|
||||
});
|
||||
|
||||
const preprocess = (status: any) => {
|
||||
if (!status) return null;
|
||||
status = {
|
||||
...(pick(status.pleroma || {}, [
|
||||
'quote',
|
||||
'local',
|
||||
'conversation_id',
|
||||
'direct_conversation_id',
|
||||
'in_reply_to_account_acct',
|
||||
'expires_at',
|
||||
'thread_muted',
|
||||
'emoji_reactions',
|
||||
'parent_visible',
|
||||
'pinned_at',
|
||||
'quotes_count',
|
||||
'bookmark_folder',
|
||||
|
||||
'event',
|
||||
'translation',
|
||||
])),
|
||||
...(pick(status.friendica || {}, [
|
||||
'dislikes_count',
|
||||
'disliked',
|
||||
])),
|
||||
...status,
|
||||
};
|
||||
|
||||
return status;
|
||||
};
|
||||
|
||||
const statusSchema = z.preprocess(preprocess, baseStatusSchema.extend({
|
||||
reblog: z.lazy(() => baseStatusSchema).nullable().catch(null),
|
||||
|
||||
quote: z.lazy(() => baseStatusSchema).nullable().catch(null),
|
||||
}));
|
||||
|
||||
const statusWithoutAccountSchema = z.preprocess(preprocess, baseStatusSchema.omit({ account: true }).extend({
|
||||
account: accountSchema.nullable().catch(null),
|
||||
reblog: z.lazy(() => baseStatusSchema).nullable().catch(null),
|
||||
|
||||
quote: z.lazy(() => baseStatusSchema).nullable().catch(null),
|
||||
}));
|
||||
|
||||
type Status = Resolve<z.infer<typeof statusSchema>>;
|
||||
|
||||
export { statusSchema, statusWithoutAccountSchema, type Status };
|
||||
117
packages/pl-api/lib/entities/streaming-event.ts
Normal file
117
packages/pl-api/lib/entities/streaming-event.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { announcementSchema } from './announcement';
|
||||
import { announcementReactionSchema } from './announcement-reaction';
|
||||
import { chatSchema } from './chat';
|
||||
import { conversationSchema } from './conversation';
|
||||
import { notificationSchema } from './notification';
|
||||
import { statusSchema } from './status';
|
||||
|
||||
const followRelationshipUpdateSchema = z.object({
|
||||
state: z.enum(['follow_pending', 'follow_accept', 'follow_reject']),
|
||||
follower: z.object({
|
||||
id: z.string(),
|
||||
follower_count: z.number().nullable().catch(null),
|
||||
following_count: z.number().nullable().catch(null),
|
||||
}),
|
||||
following: z.object({
|
||||
id: z.string(),
|
||||
follower_count: z.number().nullable().catch(null),
|
||||
following_count: z.number().nullable().catch(null),
|
||||
}),
|
||||
});
|
||||
|
||||
type FollowRelationshipUpdate = z.infer<typeof followRelationshipUpdateSchema>;
|
||||
|
||||
const baseStreamingEventSchema = z.object({
|
||||
stream: z.array(z.string()).catch([]),
|
||||
});
|
||||
|
||||
const statusStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.enum(['update', 'status.update']),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), statusSchema),
|
||||
});
|
||||
|
||||
const stringStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.enum(['delete', 'announcement.delete']),
|
||||
payload: z.string(),
|
||||
});
|
||||
|
||||
const notificationStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('notification'),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), notificationSchema),
|
||||
});
|
||||
|
||||
const emptyStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('filters_changed'),
|
||||
});
|
||||
|
||||
const conversationStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('conversation'),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), conversationSchema),
|
||||
});
|
||||
|
||||
const announcementStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('announcement'),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), announcementSchema),
|
||||
});
|
||||
|
||||
const announcementReactionStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('announcement.reaction'),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), announcementReactionSchema),
|
||||
});
|
||||
|
||||
const chatUpdateStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('chat_update'),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), chatSchema),
|
||||
});
|
||||
|
||||
const followRelationshipsUpdateStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('follow_relationships_update'),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), followRelationshipUpdateSchema),
|
||||
});
|
||||
|
||||
const respondStreamingEventSchema = baseStreamingEventSchema.extend({
|
||||
event: z.literal('respond'),
|
||||
payload: z.preprocess((payload: any) => JSON.parse(payload), z.object({
|
||||
type: z.string(),
|
||||
result: z.enum(['success', 'ignored', 'error']),
|
||||
})),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/methods/streaming/#events} */
|
||||
const streamingEventSchema: z.ZodType<StreamingEvent> = z.preprocess((event: any) => ({
|
||||
...event,
|
||||
event: event.event?.replace(/^pleroma:/, ''),
|
||||
}), z.discriminatedUnion('event', [
|
||||
statusStreamingEventSchema,
|
||||
stringStreamingEventSchema,
|
||||
notificationStreamingEventSchema,
|
||||
emptyStreamingEventSchema,
|
||||
conversationStreamingEventSchema,
|
||||
announcementStreamingEventSchema,
|
||||
announcementReactionStreamingEventSchema,
|
||||
chatUpdateStreamingEventSchema,
|
||||
followRelationshipsUpdateStreamingEventSchema,
|
||||
respondStreamingEventSchema,
|
||||
])) as any;
|
||||
|
||||
type StreamingEvent = z.infer<
|
||||
| typeof statusStreamingEventSchema
|
||||
| typeof stringStreamingEventSchema
|
||||
| typeof notificationStreamingEventSchema
|
||||
| typeof emptyStreamingEventSchema
|
||||
| typeof conversationStreamingEventSchema
|
||||
| typeof announcementStreamingEventSchema
|
||||
| typeof announcementReactionStreamingEventSchema
|
||||
| typeof chatUpdateStreamingEventSchema
|
||||
| typeof followRelationshipsUpdateStreamingEventSchema
|
||||
| typeof respondStreamingEventSchema
|
||||
>;
|
||||
|
||||
export {
|
||||
followRelationshipUpdateSchema,
|
||||
streamingEventSchema,
|
||||
type FollowRelationshipUpdate,
|
||||
type StreamingEvent,
|
||||
};
|
||||
25
packages/pl-api/lib/entities/suggestion.ts
Normal file
25
packages/pl-api/lib/entities/suggestion.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { accountSchema } from './account';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Suggestion} */
|
||||
const suggestionSchema = z.preprocess((suggestion: any) => {
|
||||
/**
|
||||
* Support `/api/v1/suggestions`
|
||||
* @see {@link https://docs.joinmastodon.org/methods/suggestions/#v1}
|
||||
*/
|
||||
if (suggestion?.acct) return {
|
||||
source: 'staff',
|
||||
sources: 'featured',
|
||||
account: suggestion,
|
||||
};
|
||||
return suggestion;
|
||||
}, z.object({
|
||||
source: z.string(),
|
||||
sources: z.array(z.string()),
|
||||
account: accountSchema,
|
||||
}));
|
||||
|
||||
type Suggestion = z.infer<typeof suggestionSchema>;
|
||||
|
||||
export { suggestionSchema, type Suggestion };
|
||||
19
packages/pl-api/lib/entities/tag.ts
Normal file
19
packages/pl-api/lib/entities/tag.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const historySchema = z.object({
|
||||
day: z.coerce.number(),
|
||||
accounts: z.coerce.number(),
|
||||
uses: z.coerce.number(),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/tag} */
|
||||
const tagSchema = z.object({
|
||||
name: z.string().min(1),
|
||||
url: z.string().url().catch(''),
|
||||
history: z.array(historySchema).nullable().catch(null),
|
||||
following: z.boolean().optional().catch(undefined),
|
||||
});
|
||||
|
||||
type Tag = z.infer<typeof tagSchema>;
|
||||
|
||||
export { historySchema, tagSchema, type Tag };
|
||||
18
packages/pl-api/lib/entities/token.ts
Normal file
18
packages/pl-api/lib/entities/token.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Token/} */
|
||||
const tokenSchema = z.object({
|
||||
access_token: z.string(),
|
||||
token_type: z.string(),
|
||||
scope: z.string(),
|
||||
created_at: z.number().optional().catch(undefined),
|
||||
|
||||
id: z.number().optional().catch(undefined),
|
||||
refresh_token: z.string().optional().catch(undefined),
|
||||
expires_in: z.number().optional().catch(undefined),
|
||||
me: z.string().optional().catch(undefined),
|
||||
});
|
||||
|
||||
type Token = z.infer<typeof tokenSchema>;
|
||||
|
||||
export { tokenSchema, type Token };
|
||||
43
packages/pl-api/lib/entities/translation.ts
Normal file
43
packages/pl-api/lib/entities/translation.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Resolve } from '../utils/types';
|
||||
|
||||
import { filteredArray } from './utils';
|
||||
|
||||
const translationPollSchema = z.object({
|
||||
id: z.string(),
|
||||
options: z.array(z.object({
|
||||
title: z.string(),
|
||||
})),
|
||||
});
|
||||
|
||||
const translationMediaAttachment = z.object({
|
||||
id: z.string(),
|
||||
description: z.string().catch(''),
|
||||
});
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/Translation/} */
|
||||
const translationSchema = z.preprocess((translation: any) => {
|
||||
/**
|
||||
* handle Akkoma
|
||||
* @see {@link https://akkoma.dev/AkkomaGang/akkoma/src/branch/develop/lib/pleroma/web/mastodon_api/controllers/status_controller.ex#L504}
|
||||
*/
|
||||
if (translation?.text) return {
|
||||
content: translation.text,
|
||||
detected_source_language: translation.detected_language,
|
||||
provider: '',
|
||||
};
|
||||
|
||||
return translation;
|
||||
}, z.object({
|
||||
content: z.string().catch(''),
|
||||
spoiler_text: z.string().catch(''),
|
||||
poll: translationPollSchema.optional().catch(undefined),
|
||||
media_attachments: filteredArray(translationMediaAttachment),
|
||||
detected_source_language: z.string(),
|
||||
provider: z.string(),
|
||||
}));
|
||||
|
||||
type Translation = Resolve<z.infer<typeof translationSchema>>;
|
||||
|
||||
export { translationSchema, type Translation };
|
||||
29
packages/pl-api/lib/entities/trends-link.ts
Normal file
29
packages/pl-api/lib/entities/trends-link.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { blurhashSchema } from './media-attachment';
|
||||
import { historySchema } from './tag';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/PreviewCard/#trends-link} */
|
||||
const trendsLinkSchema = z.preprocess((link: any) => ({ ...link, id: link.url }), z.object({
|
||||
id: z.string().catch(''),
|
||||
url: z.string().url().catch(''),
|
||||
title: z.string().catch(''),
|
||||
description: z.string().catch(''),
|
||||
type: z.enum(['link', 'photo', 'video', 'rich']).catch('link'),
|
||||
author_name: z.string().catch(''),
|
||||
author_url: z.string().catch(''),
|
||||
provider_name: z.string().catch(''),
|
||||
provider_url: z.string().catch(''),
|
||||
html: z.string().catch(''),
|
||||
width: z.number().nullable().catch(null),
|
||||
height: z.number().nullable().catch(null),
|
||||
image: z.string().nullable().catch(null),
|
||||
image_description: z.string().nullable().catch(null),
|
||||
embed_url: z.string().catch(''),
|
||||
blurhash: blurhashSchema.nullable().catch(null),
|
||||
history: z.array(historySchema).nullable().catch(null),
|
||||
}));
|
||||
|
||||
type TrendsLink = z.infer<typeof trendsLinkSchema>;
|
||||
|
||||
export { trendsLinkSchema, type TrendsLink };
|
||||
26
packages/pl-api/lib/entities/utils.ts
Normal file
26
packages/pl-api/lib/entities/utils.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import z from 'zod';
|
||||
|
||||
/** Validate to Mastodon's date format, or use the current date. */
|
||||
const dateSchema = z.string().datetime({ offset: true }).catch(new Date().toUTCString());
|
||||
|
||||
/** Validates individual items in an array, dropping any that aren't valid. */
|
||||
const filteredArray = <T extends z.ZodTypeAny>(schema: T) =>
|
||||
z.any().array().catch([])
|
||||
.transform((arr) => (
|
||||
arr.map((item) => {
|
||||
const parsed = schema.safeParse(item);
|
||||
return parsed.success ? parsed.data : undefined;
|
||||
}).filter((item): item is z.infer<T> => Boolean(item))
|
||||
));
|
||||
|
||||
/** Validates the string as an emoji. */
|
||||
const emojiSchema = z.string().refine((v) => /\p{Extended_Pictographic}|[\u{1F1E6}-\u{1F1FF}]{2}/u.test(v));
|
||||
|
||||
/** MIME schema, eg `image/png`. */
|
||||
const mimeSchema = z.string().regex(/^\w+\/[-+.\w]+$/);
|
||||
|
||||
/** zod schema to force the value into an object, if it isn't already. */
|
||||
const coerceObject = <T extends z.ZodRawShape>(shape: T) =>
|
||||
z.object({}).passthrough().catch({}).pipe(z.object(shape));
|
||||
|
||||
export { filteredArray, emojiSchema, dateSchema, mimeSchema, coerceObject };
|
||||
13
packages/pl-api/lib/entities/web-push-subscription.ts
Normal file
13
packages/pl-api/lib/entities/web-push-subscription.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/** @see {@link https://docs.joinmastodon.org/entities/WebPushSubscription/} */
|
||||
const webPushSubscriptionSchema = z.object({
|
||||
id: z.coerce.string(),
|
||||
endpoint: z.string(),
|
||||
alerts: z.record(z.boolean()),
|
||||
server_key: z.string(),
|
||||
});
|
||||
|
||||
type WebPushSubscription = z.infer<typeof webPushSubscriptionSchema>;
|
||||
|
||||
export { webPushSubscriptionSchema, type WebPushSubscription };
|
||||
1188
packages/pl-api/lib/features.ts
Normal file
1188
packages/pl-api/lib/features.ts
Normal file
File diff suppressed because it is too large
Load Diff
6
packages/pl-api/lib/main.ts
Normal file
6
packages/pl-api/lib/main.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export { PlApiClient } from './client';
|
||||
export { type Response as PlApiResponse } from './request';
|
||||
export * from './entities';
|
||||
export * from './features';
|
||||
export * from './params';
|
||||
export * from './responses';
|
||||
67
packages/pl-api/lib/params/accounts.ts
Normal file
67
packages/pl-api/lib/params/accounts.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import type { LanguageParam, OnlyEventsParam, OnlyMediaParam, PaginationParams, WithMutedParam, WithRelationshipsParam } from './common';
|
||||
|
||||
type GetAccountParams = WithMutedParam;
|
||||
|
||||
interface GetAccountStatusesParams extends PaginationParams, WithMutedParam, OnlyEventsParam, OnlyMediaParam, LanguageParam {
|
||||
/** Boolean. Filter out statuses in reply to a different account. */
|
||||
exclude_replies?: boolean;
|
||||
/** Boolean. Filter for pinned statuses only. Defaults to false, which includes all statuses. Pinned statuses do not receive special priority in the order of the returned results. */
|
||||
pinned?: boolean;
|
||||
/** String. Filter for statuses using a specific hashtag. */
|
||||
tagged?: string;
|
||||
}
|
||||
|
||||
type GetAccountFollowersParams = PaginationParams & WithRelationshipsParam;
|
||||
type GetAccountFollowingParams = PaginationParams & WithRelationshipsParam;
|
||||
|
||||
interface FollowAccountParams {
|
||||
/** Boolean. Receive this account’s reblogs in home timeline? Defaults to true. */
|
||||
reblogs?: boolean;
|
||||
/** Boolean. Receive notifications when this account posts a status? Defaults to false. */
|
||||
notify?: boolean;
|
||||
/**
|
||||
* Array of String (ISO 639-1 language two-letter code). Filter received statuses for these languages. If not provided, you will receive this account’s posts in all languages.
|
||||
* Requires `features.followAccountLangugaes`.
|
||||
*/
|
||||
languages?: string[];
|
||||
}
|
||||
|
||||
interface GetRelationshipsParams {
|
||||
/** Boolean. Whether relationships should be returned for suspended users, defaults to false. */
|
||||
with_suspended?: boolean;
|
||||
}
|
||||
|
||||
interface SearchAccountParams {
|
||||
/** Integer. Maximum number of results. Defaults to 40 accounts. Max 80 accounts. */
|
||||
limit?: number;
|
||||
/** Integer. Skip the first n results. */
|
||||
offset?: number;
|
||||
/** Boolean. Attempt WebFinger lookup. Defaults to false. Use this when `q` is an exact address. */
|
||||
resolve?: boolean;
|
||||
/** Boolean. Limit the search to users you are following. Defaults to false. */
|
||||
following?: boolean;
|
||||
}
|
||||
|
||||
interface ReportAccountParams {
|
||||
status_ids?: string[];
|
||||
comment?: string;
|
||||
forward?: boolean;
|
||||
category?: 'spam' | 'legal' | 'violation' | 'other';
|
||||
rule_ids?: string[];
|
||||
}
|
||||
|
||||
type GetAccountEndorsementsParams = WithRelationshipsParam;
|
||||
type GetAccountFavouritesParams = PaginationParams;
|
||||
|
||||
export type {
|
||||
GetAccountParams,
|
||||
GetAccountStatusesParams,
|
||||
GetAccountFollowersParams,
|
||||
GetAccountFollowingParams,
|
||||
FollowAccountParams,
|
||||
GetRelationshipsParams,
|
||||
SearchAccountParams,
|
||||
ReportAccountParams,
|
||||
GetAccountEndorsementsParams,
|
||||
GetAccountFavouritesParams,
|
||||
};
|
||||
200
packages/pl-api/lib/params/admin.ts
Normal file
200
packages/pl-api/lib/params/admin.ts
Normal file
@ -0,0 +1,200 @@
|
||||
import type { PaginationParams } from './common';
|
||||
|
||||
interface AdminGetAccountsParams extends PaginationParams {
|
||||
/** String. Filter for `local` or `remote` accounts. */
|
||||
origin?: 'local' | 'remote';
|
||||
/** String. Filter for `active`, `pending`, `disabled`, `silenced`, or suspended accounts. */
|
||||
status?: 'active' | 'pending' | 'disabled' | 'silenced' | 'suspended';
|
||||
/** String. Filter for accounts with `staff` permissions (users that can manage reports). */
|
||||
permissions?: 'staff';
|
||||
/** Array of String. Filter for users with these roles. */
|
||||
role_ids?: string[];
|
||||
/** String. Lookup users invited by the account with this ID. */
|
||||
invited_by?: string;
|
||||
/** String. Search for the given username. */
|
||||
username?: string;
|
||||
/** String. Search for the given display name */
|
||||
display_name?: string;
|
||||
/** String. Filter by the given domain */
|
||||
by_domain?: string;
|
||||
/** String. Lookup a user with this email */
|
||||
email?: string;
|
||||
/** String. Lookup users with this IP address */
|
||||
ip?: string;
|
||||
}
|
||||
|
||||
type AdminAccountAction = 'none' | 'sensitive' | 'disable' | 'silence' | 'suspend';
|
||||
|
||||
interface AdminPerformAccountActionParams {
|
||||
/** String. The ID of an associated report that caused this action to be taken. */
|
||||
report_id?: string;
|
||||
/** String. The ID of a preset warning. */
|
||||
warning_preset_id?: string;
|
||||
/** String. Additional clarification for why this action was taken. */
|
||||
text?: string;
|
||||
/** Boolean. Should an email be sent to the user with the above information? */
|
||||
send_email_notification?: boolean;
|
||||
}
|
||||
|
||||
type AdminGetDomainBlocksParams = PaginationParams;
|
||||
|
||||
interface AdminCreateDomainBlockParams {
|
||||
/** String. Whether to apply a `silence`, `suspend`, or `noop` to the domain. Defaults to `silence` */
|
||||
severity?: 'silence' | 'suspend' | 'noop';
|
||||
/** Boolean. Whether media attachments should be rejected. Defaults to false */
|
||||
reject_media?: boolean;
|
||||
/** Boolean. Whether reports from this domain should be rejected. Defaults to false */
|
||||
reject_reports?: boolean;
|
||||
/** String. A private note about this domain block, visible only to admins. */
|
||||
private_comment?: string;
|
||||
/** String. A public note about this domain block, optionally shown on the about page. */
|
||||
public_comment?: string;
|
||||
/** Boolean. Whether to partially censor the domain when shown in public. Defaults to false */
|
||||
obfuscate?: boolean;
|
||||
}
|
||||
|
||||
type AdminUpdateDomainBlockParams = AdminCreateDomainBlockParams;
|
||||
|
||||
interface AdminGetReportsParams extends PaginationParams {
|
||||
/** Boolean. Filter for resolved reports? */
|
||||
resolved?: boolean;
|
||||
/** String. Filter for reports filed by this account. */
|
||||
account_id?: string;
|
||||
/** String. Filter for reports targeting this account. */
|
||||
target_account_id?: string;
|
||||
}
|
||||
|
||||
interface AdminUpdateReportParams {
|
||||
/** String. Change the classification of the report to `spam`, `violation`, or `other`. */
|
||||
category?: 'spam' | 'violation' | 'other';
|
||||
/** Array of Integer. For `violation` category reports, specify the ID of the exact rules broken. Rules and their IDs are available via [GET /api/v1/instance/rules](https://docs.joinmastodon.org/methods/instance/#rules) and [GET /api/v1/instance](https://docs.joinmastodon.org/methods/instance/#get). */
|
||||
rule_ids?: string[];
|
||||
}
|
||||
|
||||
interface AdminGetStatusesParams {
|
||||
limit?: number;
|
||||
local_only?: boolean;
|
||||
with_reblogs?: boolean;
|
||||
with_private?: boolean;
|
||||
}
|
||||
|
||||
interface AdminUpdateStatusParams {
|
||||
sensitive?: boolean;
|
||||
visibility?: 'public' | 'private' | 'unlisted';
|
||||
}
|
||||
|
||||
type AdminGetCanonicalEmailBlocks = PaginationParams;
|
||||
|
||||
type AdminDimensionKey = 'languages' | 'sources' | 'servers' | 'space_usage' | 'software_versions' | 'tag_servers' | 'tag_languages' | 'instance_accounts' | 'instance_languages';
|
||||
|
||||
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;
|
||||
/** String (ISO 8601 Datetime). The end date for the time period. If a time is provided, it will be ignored. */
|
||||
end_at?: string;
|
||||
/** Integer. The maximum number of results to return for sources, servers, languages, tag or instance dimensions. */
|
||||
limit?: number;
|
||||
tag_servers?: {
|
||||
/** String. When tag_servers is one of the requested keys, you must provide a trending tag ID to obtain information about which servers are posting the tag. */
|
||||
id?: string;
|
||||
};
|
||||
tag_languages?: {
|
||||
/** String. When tag_languages is one of the requested keys, you must provide a trending tag ID to obtain information about which languages are posting the tag. */
|
||||
id?: string;
|
||||
};
|
||||
instance_accounts?: {
|
||||
/** String. When instance_accounts is one of the requested keys, you must provide a domain to obtain information about popular accounts from that server. */
|
||||
domain?: string;
|
||||
};
|
||||
instance_languages?: {
|
||||
/** String. When instance_accounts is one of the requested keys, you must provide a domain to obtain information about popular languages from that server. */
|
||||
domain?: string;
|
||||
};
|
||||
}
|
||||
|
||||
type AdminGetDomainAllowsParams = PaginationParams;
|
||||
|
||||
type AdminGetEmailDomainBlocksParams = PaginationParams;
|
||||
|
||||
type AdminGetIpBlocksParams = PaginationParams;
|
||||
|
||||
interface AdminCreateIpBlockParams {
|
||||
/** String. The IP address and prefix to block. Defaults to 0.0.0.0/32 */
|
||||
ip?: string;
|
||||
/** String. The policy to apply to this IP range: sign_up_requires_approval, sign_up_block, or no_access */
|
||||
severity: string;
|
||||
/** String. The reason for this IP block. */
|
||||
comment?: string;
|
||||
/** Integer. The number of seconds in which this IP block will expire. */
|
||||
expires_in?: number;
|
||||
}
|
||||
|
||||
type AdminUpdateIpBlockParams = Partial<AdminCreateIpBlockParams>;
|
||||
|
||||
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';
|
||||
|
||||
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. */
|
||||
id?: string;
|
||||
};
|
||||
tag_uses?: {
|
||||
/** String. When `tag_uses` is one of the requested keys, you must provide a tag ID to obtain the measure of how many statuses used that hashtag within the given time period. */
|
||||
id?: string;
|
||||
};
|
||||
tag_servers?: {
|
||||
/** String. When `tag_servers` is one of the requested keys, you must provide a tag ID to obtain the measure of how many servers used that hashtag in at least one status within the given time period. */
|
||||
id?: string;
|
||||
};
|
||||
instance_accounts?: {
|
||||
/** String. When `instance_accounts` is one of the requested keys, you must provide a remote domain to obtain the measure of how many accounts have been discovered from that server within the given time period. */
|
||||
domain?: string;
|
||||
};
|
||||
instance_media_attachments?: {
|
||||
/** String. When `instance_media_attachments` is one of the requested keys, you must provide a remote domain to obtain the measure of how much space is used by media attachments from that server within the given time period. */
|
||||
domain?: string;
|
||||
};
|
||||
instance_reports?: {
|
||||
/** String. When `instance_reports` is one of the requested keys, you must provide a remote domain to obtain the measure of how many reports have been filed against accounts from that server within the given time period. */
|
||||
domain?: string;
|
||||
};
|
||||
instance_statuses?: {
|
||||
/** String. When `instance_statuses` is one of the requested keys, you must provide a remote domain to obtain the measure of how many statuses originate from that server within the given time period. */
|
||||
domain?: string;
|
||||
};
|
||||
instance_follows?: {
|
||||
/** String. When `instance_follows` is one of the requested keys, you must provide a remote domain to obtain the measure of how many follows were performed on accounts from that server by local accounts within the given time period. */
|
||||
domain?: string;
|
||||
};
|
||||
instance_followers?: {
|
||||
/** String. When `instance_followers` is one of the requested keys, you must provide a remote domain to obtain the measure of how many follows were performed by accounts from that server on local accounts within the given time period. */
|
||||
domain?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface AdminGetGroupsParams {
|
||||
}
|
||||
|
||||
export type {
|
||||
AdminGetAccountsParams,
|
||||
AdminAccountAction,
|
||||
AdminPerformAccountActionParams,
|
||||
AdminGetDomainBlocksParams,
|
||||
AdminCreateDomainBlockParams,
|
||||
AdminUpdateDomainBlockParams,
|
||||
AdminGetReportsParams,
|
||||
AdminUpdateReportParams,
|
||||
AdminGetStatusesParams,
|
||||
AdminUpdateStatusParams,
|
||||
AdminGetCanonicalEmailBlocks,
|
||||
AdminDimensionKey,
|
||||
AdminGetDimensionsParams,
|
||||
AdminGetDomainAllowsParams,
|
||||
AdminGetEmailDomainBlocksParams,
|
||||
AdminGetIpBlocksParams,
|
||||
AdminCreateIpBlockParams,
|
||||
AdminUpdateIpBlockParams,
|
||||
AdminMeasureKey,
|
||||
AdminGetMeasuresParams,
|
||||
AdminGetGroupsParams,
|
||||
};
|
||||
14
packages/pl-api/lib/params/apps.ts
Normal file
14
packages/pl-api/lib/params/apps.ts
Normal file
@ -0,0 +1,14 @@
|
||||
interface CreateApplicationParams {
|
||||
/** String. A name for your application */
|
||||
client_name: string;
|
||||
/** String. Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter. */
|
||||
redirect_uris: string;
|
||||
/** String. Space separated list of scopes. If none is provided, defaults to `read`. See [OAuth Scopes](https://docs.joinmastodon.org/api/oauth-scopes/) for a list of possible scopes. */
|
||||
scopes?: string;
|
||||
/** String. A URL to the homepage of your app */
|
||||
website?: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
CreateApplicationParams,
|
||||
};
|
||||
18
packages/pl-api/lib/params/chats.ts
Normal file
18
packages/pl-api/lib/params/chats.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { PaginationParams, WithMutedParam } from './common';
|
||||
|
||||
type GetChatsParams = PaginationParams & WithMutedParam;
|
||||
type GetChatMessagesParams = PaginationParams;
|
||||
|
||||
type CreateChatMessageParams = {
|
||||
content?: string;
|
||||
media_id: string;
|
||||
} | {
|
||||
content: string;
|
||||
media_id?: string;
|
||||
};
|
||||
|
||||
export type {
|
||||
GetChatsParams,
|
||||
GetChatMessagesParams,
|
||||
CreateChatMessageParams,
|
||||
};
|
||||
59
packages/pl-api/lib/params/common.ts
Normal file
59
packages/pl-api/lib/params/common.ts
Normal file
@ -0,0 +1,59 @@
|
||||
interface PaginationParams {
|
||||
/** String. All results returned will be lesser than this ID. In effect, sets an upper bound on results. */
|
||||
max_id?: string;
|
||||
/** String. All results returned will be greater than this ID. In effect, sets a lower bound on results. */
|
||||
since_id?: string;
|
||||
/** Integer. Maximum number of results to return. */
|
||||
limit?: number;
|
||||
/** String. Returns results immediately newer than this ID. In effect, sets a cursor at this ID and paginates forward. */
|
||||
min_id?: string;
|
||||
}
|
||||
|
||||
interface WithMutedParam {
|
||||
/**
|
||||
* Boolean. Also show statuses from muted users. Default to false.
|
||||
*
|
||||
* Requires `features.timelinesWithMuted`.
|
||||
*/
|
||||
with_muted?: boolean;
|
||||
}
|
||||
|
||||
interface WithRelationshipsParam {
|
||||
/**
|
||||
* Embed relationships into accounts.
|
||||
* Supported by Pleroma.
|
||||
*/
|
||||
with_relationships?: boolean;
|
||||
}
|
||||
|
||||
interface OnlyMediaParam {
|
||||
/** Boolean. Show only statuses with media attached? Defaults to false. */
|
||||
only_media?: boolean;
|
||||
}
|
||||
|
||||
interface OnlyEventsParam {
|
||||
/**
|
||||
* Boolean. Filter out statuses without events.
|
||||
*
|
||||
* Requires `features.events`.
|
||||
*/
|
||||
only_events?: boolean;
|
||||
}
|
||||
|
||||
interface LanguageParam {
|
||||
/**
|
||||
* Fetch a translation in given language
|
||||
*
|
||||
* Requires `features.fetchStatusesWithTranslation`.
|
||||
*/
|
||||
language?: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
PaginationParams,
|
||||
WithMutedParam,
|
||||
WithRelationshipsParam,
|
||||
OnlyMediaParam,
|
||||
OnlyEventsParam,
|
||||
LanguageParam,
|
||||
};
|
||||
33
packages/pl-api/lib/params/events.ts
Normal file
33
packages/pl-api/lib/params/events.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { PaginationParams } from './common';
|
||||
|
||||
interface CreateEventParams {
|
||||
/** name of the event */
|
||||
name: string;
|
||||
/** optional, description of the event */
|
||||
status?: string;
|
||||
/** optional, event banner attachment ID */
|
||||
banner_id?: string;
|
||||
/** start time of the event */
|
||||
start_time?: string;
|
||||
/** optional, end time of the event */
|
||||
end_time?: string;
|
||||
/** optional, event join mode, either free or restricted, defaults to free */
|
||||
join_mode?: 'free' | 'restricted';
|
||||
/** optional, location ID from the location provider used by server */
|
||||
location_id?: string;
|
||||
/** string, contain the MIME type of the status. */
|
||||
content_type?: string;
|
||||
}
|
||||
|
||||
type EditEventParams = Partial<Omit<CreateEventParams, 'join_mode'>>;
|
||||
type GetJoinedEventsParams = PaginationParams;
|
||||
type GetEventParticipationsParams = PaginationParams;
|
||||
type GetEventParticipationRequestsParams = PaginationParams;
|
||||
|
||||
export type {
|
||||
CreateEventParams,
|
||||
EditEventParams,
|
||||
GetJoinedEventsParams,
|
||||
GetEventParticipationsParams,
|
||||
GetEventParticipationRequestsParams,
|
||||
};
|
||||
48
packages/pl-api/lib/params/filtering.ts
Normal file
48
packages/pl-api/lib/params/filtering.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import type { PaginationParams, WithRelationshipsParam } from './common';
|
||||
|
||||
interface MuteAccountParams {
|
||||
/** Boolean. Mute notifications in addition to statuses? Defaults to true. */
|
||||
notifications?: boolean;
|
||||
/** Number. How long the mute should last, in seconds. Defaults to 0 (indefinite). */
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
type GetMutesParams = Omit<PaginationParams, 'min_id'> & WithRelationshipsParam;
|
||||
type GetBlocksParams = PaginationParams & WithRelationshipsParam;
|
||||
type GetDomainBlocksParams = PaginationParams;
|
||||
|
||||
type FilterContext = 'home' | 'notifications' | 'public' | 'thread' | 'account';
|
||||
|
||||
interface CreateFilterParams {
|
||||
title: string;
|
||||
context: Array<FilterContext>;
|
||||
filter_action?: 'warn' | 'hide';
|
||||
expires_in?: number;
|
||||
keywords_attributes: Array<{
|
||||
keyword: string;
|
||||
whole_word?: boolean;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface UpdateFilterParams {
|
||||
title?: string;
|
||||
context?: Array<FilterContext>;
|
||||
filter_action?: 'warn' | 'hide';
|
||||
expires_in?: number;
|
||||
keywords_attributes?: Array<{
|
||||
keyword: string;
|
||||
whole_word?: boolean;
|
||||
id?: string;
|
||||
_destroy?: boolean;
|
||||
}>;
|
||||
}
|
||||
|
||||
export type {
|
||||
MuteAccountParams,
|
||||
GetMutesParams,
|
||||
GetBlocksParams,
|
||||
GetDomainBlocksParams,
|
||||
FilterContext,
|
||||
CreateFilterParams,
|
||||
UpdateFilterParams,
|
||||
};
|
||||
27
packages/pl-api/lib/params/groups.ts
Normal file
27
packages/pl-api/lib/params/groups.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import type { PaginationParams } from './common';
|
||||
|
||||
interface CreateGroupParams {
|
||||
display_name: string;
|
||||
note?: string;
|
||||
avatar?: File;
|
||||
header?: File;
|
||||
}
|
||||
|
||||
interface UpdateGroupParams {
|
||||
display_name?: string;
|
||||
note?: string;
|
||||
avatar?: File | '';
|
||||
header?: File | '';
|
||||
}
|
||||
|
||||
type GetGroupMembershipsParams = Omit<PaginationParams, 'min_id'>;
|
||||
type GetGroupMembershipRequestsParams = Omit<PaginationParams, 'min_id'>;
|
||||
type GetGroupBlocksParams = Omit<PaginationParams, 'min_id'>;
|
||||
|
||||
export type {
|
||||
CreateGroupParams,
|
||||
UpdateGroupParams,
|
||||
GetGroupMembershipsParams,
|
||||
GetGroupMembershipRequestsParams,
|
||||
GetGroupBlocksParams,
|
||||
};
|
||||
21
packages/pl-api/lib/params/index.ts
Normal file
21
packages/pl-api/lib/params/index.ts
Normal file
@ -0,0 +1,21 @@
|
||||
export * from './accounts';
|
||||
export * from './admin';
|
||||
export * from './apps';
|
||||
export * from './chats';
|
||||
export * from './events';
|
||||
export * from './filtering';
|
||||
export * from './groups';
|
||||
export * from './instance';
|
||||
export * from './interaction-requests';
|
||||
export * from './lists';
|
||||
export * from './media';
|
||||
export * from './my-account';
|
||||
export * from './notifications';
|
||||
export * from './oauth';
|
||||
export * from './push-notifications';
|
||||
export * from './scheduled-statuses';
|
||||
export * from './search';
|
||||
export * from './settings';
|
||||
export * from './statuses';
|
||||
export * from './timelines';
|
||||
export * from './trends';
|
||||
14
packages/pl-api/lib/params/instance.ts
Normal file
14
packages/pl-api/lib/params/instance.ts
Normal file
@ -0,0 +1,14 @@
|
||||
interface ProfileDirectoryParams {
|
||||
/** Number. Skip the first n results. */
|
||||
offset?: number;
|
||||
/** Number. How many accounts to load. Defaults to 40 accounts. Max 80 accounts. */
|
||||
limit?: number;
|
||||
/** String. Use active to sort by most recently posted statuses (default) or new to sort by most recently created profiles. */
|
||||
order?: string;
|
||||
/** Boolean. If true, returns only local accounts. */
|
||||
local?: boolean;
|
||||
}
|
||||
|
||||
export type {
|
||||
ProfileDirectoryParams,
|
||||
};
|
||||
16
packages/pl-api/lib/params/interaction-requests.ts
Normal file
16
packages/pl-api/lib/params/interaction-requests.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { PaginationParams } from './common';
|
||||
|
||||
interface GetInteractionRequestsParams extends PaginationParams {
|
||||
/** If set, then only interactions targeting the given status_id will be included in the results. */
|
||||
status_id?: string;
|
||||
/** If true or not set, pending favourites will be included in the results. At least one of favourites, replies, and reblogs must be true. */
|
||||
favourites?: boolean;
|
||||
/** If true or not set, pending replies will be included in the results. At least one of favourites, replies, and reblogs must be true. */
|
||||
replies?: boolean;
|
||||
/** If true or not set, pending reblogs will be included in the results. At least one of favourites, replies, and reblogs must be true. */
|
||||
reblogs?: boolean;
|
||||
}
|
||||
|
||||
export type {
|
||||
GetInteractionRequestsParams,
|
||||
};
|
||||
19
packages/pl-api/lib/params/lists.ts
Normal file
19
packages/pl-api/lib/params/lists.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import type { PaginationParams } from './common';
|
||||
|
||||
interface CreateListParams {
|
||||
/** String. The title of the list to be created. */
|
||||
title: string;
|
||||
/** String. One of followed, list, or none. Defaults to list. */
|
||||
replies_policy?: 'followed' | 'list' | 'none';
|
||||
/** Boolean. Whether members of this list need to get removed from the “Home” feed */
|
||||
exclusive?: boolean;
|
||||
}
|
||||
|
||||
type UpdateListParams = CreateListParams;
|
||||
type GetListAccountsParams = PaginationParams;
|
||||
|
||||
export type {
|
||||
CreateListParams,
|
||||
UpdateListParams,
|
||||
GetListAccountsParams,
|
||||
};
|
||||
30
packages/pl-api/lib/params/media.ts
Normal file
30
packages/pl-api/lib/params/media.ts
Normal file
@ -0,0 +1,30 @@
|
||||
interface UploadMediaParams {
|
||||
/** Object. The file to be attached, encoded using multipart form data. The file must have a MIME type. */
|
||||
file: File;
|
||||
/** Object. The custom thumbnail of the media to be attached, encoded using multipart form data. */
|
||||
thumbnail?: File;
|
||||
/** String. A plain-text description of the media, for accessibility purposes. */
|
||||
description?: string;
|
||||
/**
|
||||
* String. Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0. See Focal points for cropping media thumbnails for more information.
|
||||
* @see {@link https://docs.joinmastodon.org/api/guidelines/#focal-points}
|
||||
*/
|
||||
focus?: string;
|
||||
}
|
||||
|
||||
interface UpdateMediaParams {
|
||||
/** Object. The custom thumbnail of the media to be attached, encoded using multipart form data. */
|
||||
thumbnail?: File;
|
||||
/** String. A plain-text description of the media, for accessibility purposes. */
|
||||
description?: string;
|
||||
/**
|
||||
* String. Two floating points (x,y), comma-delimited, ranging from -1.0 to 1.0. See Focal points for cropping media thumbnails for more information.
|
||||
* @see {@link https://docs.joinmastodon.org/api/guidelines/#focal-points}
|
||||
*/
|
||||
focus?: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
UploadMediaParams,
|
||||
UpdateMediaParams,
|
||||
};
|
||||
31
packages/pl-api/lib/params/my-account.ts
Normal file
31
packages/pl-api/lib/params/my-account.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import type { PaginationParams } from './common';
|
||||
|
||||
interface GetBookmarksParams extends PaginationParams {
|
||||
/**
|
||||
* Bookmark folder ID
|
||||
* Requires `features.bookmarkFolders`.
|
||||
*/
|
||||
folder_id?: string;
|
||||
}
|
||||
|
||||
type GetFavouritesParams = PaginationParams;
|
||||
type GetFollowRequestsParams = Omit<PaginationParams, 'min_id'>;
|
||||
type GetEndorsementsParams = Omit<PaginationParams, 'min_id'>;
|
||||
type GetFollowedTagsParams = PaginationParams;
|
||||
|
||||
interface CreateBookmarkFolderParams {
|
||||
name: string;
|
||||
emoji?: string;
|
||||
}
|
||||
|
||||
type UpdateBookmarkFolderParams = Partial<CreateBookmarkFolderParams>;
|
||||
|
||||
export type {
|
||||
GetBookmarksParams,
|
||||
GetFavouritesParams,
|
||||
GetFollowRequestsParams,
|
||||
GetEndorsementsParams,
|
||||
GetFollowedTagsParams,
|
||||
CreateBookmarkFolderParams,
|
||||
UpdateBookmarkFolderParams,
|
||||
};
|
||||
34
packages/pl-api/lib/params/notifications.ts
Normal file
34
packages/pl-api/lib/params/notifications.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import type { PaginationParams } from './common';
|
||||
|
||||
interface GetNotificationParams extends PaginationParams {
|
||||
/** Array of String. Types to include in the result. */
|
||||
types?: string[];
|
||||
/** Array of String. Types to exclude from the results. */
|
||||
exclude_types?: string[];
|
||||
/** String. Return only notifications received from the specified account. */
|
||||
account_id?: string;
|
||||
/**
|
||||
* will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`).
|
||||
* Requires `features.notificationsExcludeVisibilities`.
|
||||
*/
|
||||
exclude_visibilities?: string[];
|
||||
}
|
||||
|
||||
interface UpdateNotificationPolicyRequest {
|
||||
/** Boolean. Whether to filter notifications from accounts the user is not following. */
|
||||
filter_not_following?: boolean;
|
||||
/** Boolean. Whether to filter notifications from accounts that are not following the user. */
|
||||
filter_not_followers?: boolean;
|
||||
/** Boolean. Whether to filter notifications from accounts created in the past 30 days. */
|
||||
filter_new_accounts?: boolean;
|
||||
/** Boolean. Whether to filter notifications from private mentions. Replies to private mentions initiated by the user, as well as accounts the user follows, are never filtered. */
|
||||
filter_private_mentions?: boolean;
|
||||
}
|
||||
|
||||
type GetNotificationRequestsParams = PaginationParams;
|
||||
|
||||
export type {
|
||||
GetNotificationParams,
|
||||
UpdateNotificationPolicyRequest,
|
||||
GetNotificationRequestsParams,
|
||||
};
|
||||
54
packages/pl-api/lib/params/oauth.ts
Normal file
54
packages/pl-api/lib/params/oauth.ts
Normal file
@ -0,0 +1,54 @@
|
||||
interface OauthAuthorizeParams {
|
||||
/** String. Should be set equal to `code`. */
|
||||
response_type: string;
|
||||
/** String. The client ID, obtained during app registration. */
|
||||
client_id: string;
|
||||
/** String. Set a URI to redirect the user to. If this parameter is set to `urn:ietf:wg:oauth:2.0:oob` then the authorization code will be shown instead. Must match one of the `redirect_uris` declared during app registration. */
|
||||
redirect_uri: string;
|
||||
/** String. List of requested OAuth scopes, separated by spaces (or by pluses, if using query parameters). Must be a subset of `scopes` declared during app registration. If not provided, defaults to `read`. */
|
||||
scope?: string;
|
||||
/** Boolean. Forces the user to re-login, which is necessary for authorizing with multiple accounts from the same instance. */
|
||||
force_login?: boolean;
|
||||
/** String. The ISO 639-1 two-letter language code to use while rendering the authorization form. */
|
||||
lang?: string;
|
||||
}
|
||||
|
||||
interface GetTokenParams {
|
||||
/** String. Set equal to `authorization_code` if `code` is provided in order to gain user-level access. Otherwise, set equal to `client_credentials` to obtain app-level access only. */
|
||||
grant_type: string;
|
||||
/** String. A user authorization code, obtained via [GET /oauth/authorize](https://docs.joinmastodon.org/methods/oauth/#authorize). */
|
||||
code?: string;
|
||||
/** String. The client ID, obtained during app registration. */
|
||||
client_id: string;
|
||||
/** String. The client secret, obtained during app registration. */
|
||||
client_secret: string;
|
||||
/** String. Set a URI to redirect the user to. If this parameter is set to urn:ietf:wg:oauth:2.0:oob then the token will be shown instead. Must match one of the `redirect_uris` declared during app registration. */
|
||||
redirect_uri: string;
|
||||
/** String. List of requested OAuth scopes, separated by spaces (or by pluses, if using query parameters). If `code` was provided, then this must be equal to the `scope` requested from the user. Otherwise, it must be a subset of `scopes` declared during app registration. If not provided, defaults to `read`. */
|
||||
scope?: string;
|
||||
}
|
||||
|
||||
interface RevokeTokenParams {
|
||||
/** String. The client ID, obtained during app registration. */
|
||||
client_id: string;
|
||||
/** String. The client secret, obtained during app registration. */
|
||||
client_secret: string;
|
||||
/** String. The previously obtained token, to be invalidated. */
|
||||
token: string;
|
||||
}
|
||||
|
||||
interface MfaChallengeParams {
|
||||
client_id: string;
|
||||
client_secret: string;
|
||||
/** access token to check second step of mfa */
|
||||
mfa_token: string;
|
||||
challenge_type: 'totp' | 'recovery';
|
||||
code: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
OauthAuthorizeParams,
|
||||
GetTokenParams,
|
||||
RevokeTokenParams,
|
||||
MfaChallengeParams,
|
||||
};
|
||||
30
packages/pl-api/lib/params/push-notifications.ts
Normal file
30
packages/pl-api/lib/params/push-notifications.ts
Normal file
@ -0,0 +1,30 @@
|
||||
interface CreatePushNotificationsSubscriptionParams {
|
||||
subscription: {
|
||||
/** String. The endpoint URL that is called when a notification event occurs. */
|
||||
endpoint: string;
|
||||
keys?: {
|
||||
/** String. User agent public key. Base64 encoded string of a public key from a ECDH keypair using the prime256v1 curve. */
|
||||
p256dh: string;
|
||||
/** String. Auth secret. Base64 encoded string of 16 bytes of random data. */
|
||||
auth: string;
|
||||
};
|
||||
};
|
||||
data?: {
|
||||
alerts?: Record<string, boolean>;
|
||||
/** String. Specify whether to receive push notifications from `all`, `followed`, `follower`, or `none` users. */
|
||||
policy?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdatePushNotificationsSubscriptionParams {
|
||||
data?: {
|
||||
alerts?: Record<string, boolean>;
|
||||
};
|
||||
/** String. Specify whether to receive push notifications from `all`, `followed`, `follower`, or `none` users. */
|
||||
policy?: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
CreatePushNotificationsSubscriptionParams,
|
||||
UpdatePushNotificationsSubscriptionParams,
|
||||
};
|
||||
7
packages/pl-api/lib/params/scheduled-statuses.ts
Normal file
7
packages/pl-api/lib/params/scheduled-statuses.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import type { PaginationParams } from './common';
|
||||
|
||||
type GetScheduledStatusesParams = PaginationParams;
|
||||
|
||||
export type {
|
||||
GetScheduledStatusesParams,
|
||||
};
|
||||
20
packages/pl-api/lib/params/search.ts
Normal file
20
packages/pl-api/lib/params/search.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import type { PaginationParams, WithRelationshipsParam } from './common';
|
||||
|
||||
interface SearchParams extends Exclude<PaginationParams, 'since_id'>, WithRelationshipsParam {
|
||||
/** String. Specify whether to search for only `accounts`, `hashtags`, `statuses` */
|
||||
type?: 'accounts' | 'hashtags' | 'statuses' | 'groups';
|
||||
/** Boolean. Only relevant if `type` includes `accounts`. If `true` and (a) the search query is for a remote account (e.g., `someaccount@someother.server`) and (b) the local server does not know about the account, WebFinger is used to try and resolve the account at `someother.server`. This provides the best recall at higher latency. If `false` only accounts the server knows about are returned. */
|
||||
resolve?: boolean;
|
||||
/** Boolean. Only include accounts that the user is following? Defaults to false. */
|
||||
following?: boolean;
|
||||
/** String. If provided, will only return statuses authored by this account. */
|
||||
account_id?: string;
|
||||
/** Boolean. Filter out unreviewed tags? Defaults to false. Use true when trying to find trending tags. */
|
||||
exclude_unreviewed?: boolean;
|
||||
/** Integer. Skip the first n results. */
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export type {
|
||||
SearchParams,
|
||||
};
|
||||
146
packages/pl-api/lib/params/settings.ts
Normal file
146
packages/pl-api/lib/params/settings.ts
Normal file
@ -0,0 +1,146 @@
|
||||
interface CreateAccountParams {
|
||||
/** String. The desired username for the account */
|
||||
username: string;
|
||||
/** String. The email address to be used for login */
|
||||
email: string;
|
||||
/** String. The password to be used for login */
|
||||
password: string;
|
||||
/** Whether the user agrees to the local rules, terms, and policies. These should be presented to the user in order to allow them to consent before setting this parameter to TRUE. */
|
||||
agreement: boolean;
|
||||
/** String. The language of the confirmation email that will be sent. */
|
||||
locale: string;
|
||||
/** String. If registrations require manual approval, this text will be reviewed by moderators. */
|
||||
reason?: string;
|
||||
|
||||
fullname?: string;
|
||||
bio?: string;
|
||||
/** optional, contains provider-specific captcha solution */
|
||||
captcha_solution?: string;
|
||||
/** optional, contains provider-specific captcha token */
|
||||
captcha_token?: string;
|
||||
/** optional, contains provider-specific captcha data */
|
||||
captcha_answer_data?: string;
|
||||
/** invite token required when the registrations aren't public. */
|
||||
token?: string;
|
||||
birthday?: string;
|
||||
|
||||
/** optional, domain id, if multitenancy is enabled. */
|
||||
domain?: string;
|
||||
|
||||
accepts_email_list?: boolean;
|
||||
}
|
||||
|
||||
interface UpdateCredentialsParams {
|
||||
/** String. The display name to use for the profile. */
|
||||
display_name?: string;
|
||||
/** String. The account bio. */
|
||||
note?: string;
|
||||
/** Avatar image encoded using `multipart/form-data` */
|
||||
avatar?: File | '';
|
||||
/** Header image encoded using `multipart/form-data` */
|
||||
header?: File | '';
|
||||
/** Boolean. Whether manual approval of follow requests is required. */
|
||||
locked?: boolean;
|
||||
/** Boolean. Whether the account has a bot flag. */
|
||||
bot?: boolean;
|
||||
/** Boolean. Whether the account should be shown in the profile directory. */
|
||||
discoverable?: boolean;
|
||||
/** Boolean. Whether to hide followers and followed accounts. */
|
||||
hide_collections?: boolean;
|
||||
/** Boolean. Whether public posts should be searchable to anyone. */
|
||||
indexable?: boolean;
|
||||
/** Hash. The profile fields to be set. Inside this hash, the key is an integer cast to a string (although the exact integer does not matter), and the value is another hash including name and value. By default, max 4 fields. */
|
||||
fields_attributes?: Array<{
|
||||
/** String. The name of the profile field. By default, max 255 characters. */
|
||||
name: string;
|
||||
/** String. The value of the profile field. By default, max 255 characters. */
|
||||
value: string;
|
||||
}>;
|
||||
source?: {
|
||||
/** String. Default post privacy for authored statuses. Can be public, unlisted, or private. */
|
||||
privacy?: string;
|
||||
/** Boolean. Whether to mark authored statuses as sensitive by default. */
|
||||
sensitive?: string;
|
||||
/** String. Default language to use for authored statuses (ISO 6391) */
|
||||
language?: string;
|
||||
};
|
||||
|
||||
/** if true, html tags are stripped from all statuses requested from the API */
|
||||
no_rich_text?: boolean;
|
||||
/** if true, user's followers will be hidden*/
|
||||
hide_followers?: boolean;
|
||||
/** if true, user's follows will be hidden */
|
||||
hide_follows?: boolean;
|
||||
/** if true, user's follower count will be hidden */
|
||||
hide_followers_count?: boolean;
|
||||
/** if true, user's follow count will be hidden */
|
||||
hide_follows_count?: boolean;
|
||||
/** if true, user's favorites timeline will be hidden */
|
||||
hide_favorites?: boolean;
|
||||
/** if true, user's role (e.g admin, moderator) will be exposed to anyone in the API */
|
||||
show_role?: boolean;
|
||||
/** the scope returned under privacy key in Source subentity */
|
||||
default_scope?: string;
|
||||
/** Opaque user settings to be saved on the backend. */
|
||||
settings_store?: Record<string, any>;
|
||||
/** if true, skip filtering out broken threads */
|
||||
skip_thread_containment?: boolean;
|
||||
/** if true, allows automatically follow moved following accounts */
|
||||
allow_following_move?: boolean;
|
||||
/** array of ActivityPub IDs, needed for following move */
|
||||
also_known_as?: string[];
|
||||
/** sets the background image of the user. Can be set to "" (an empty string) to reset. */
|
||||
background_image?: string;
|
||||
/** the type of this account. */
|
||||
actor_type?: string;
|
||||
/** if false, this account will reject all chat messages. */
|
||||
accepts_chat_messages?: boolean;
|
||||
/** user's preferred language for receiving emails (digest, confirmation, etc.) */
|
||||
language?: string;
|
||||
|
||||
/**
|
||||
* Description of avatar image, for alt-text.
|
||||
* Requires `features.accountAvatarDescription`.
|
||||
*/
|
||||
avatar_description?: boolean;
|
||||
/**
|
||||
* Description of header image, for alt-text.
|
||||
* Requires `features.accountAvatarDescription`.
|
||||
*/
|
||||
header_description?: boolean;
|
||||
/**
|
||||
* Enable RSS feed for this account's Public posts at `/[username]/feed.rss`
|
||||
* Requires `features.accountEnableRss`.
|
||||
*/
|
||||
enable_rss?: boolean;
|
||||
}
|
||||
|
||||
interface UpdateNotificationSettingsParams {
|
||||
/**
|
||||
* blocks notifications from accounts you do not follow
|
||||
*/
|
||||
block_from_strangers?: boolean;
|
||||
|
||||
/**
|
||||
* When set to true, it removes the contents of a message from the push notification.
|
||||
*/
|
||||
hide_notification_contents?: boolean;
|
||||
}
|
||||
|
||||
type UpdateInteractionPoliciesParams = Record<
|
||||
'public' | 'unlisted' | 'private' | 'direct',
|
||||
Record<
|
||||
'can_favourite' | 'can_reblog' | 'can_reply',
|
||||
Record<
|
||||
'always' | 'with_approval',
|
||||
Array<'public' | 'followers' | 'following' | 'mutuals' | 'mentioned' | 'author' | 'me' | string>
|
||||
>
|
||||
>
|
||||
>;
|
||||
|
||||
export type {
|
||||
CreateAccountParams,
|
||||
UpdateCredentialsParams,
|
||||
UpdateNotificationSettingsParams,
|
||||
UpdateInteractionPoliciesParams,
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user