[mastodon-client] GET /v1/instance

This commit is contained in:
Laura Hausmann 2023-10-04 23:40:16 +02:00
parent c90161189f
commit 2a64fe4ebf
No known key found for this signature in database
GPG Key ID: D044E84C5BE01605
3 changed files with 88 additions and 91 deletions

View File

@ -1,70 +0,0 @@
import { Entity } from "megalodon";
import config from "@/config/index.js";
import { fetchMeta } from "@/misc/fetch-meta.js";
import { Notes, Users } from "@/models/index.js";
import { IsNull } from "typeorm";
import { FILE_TYPE_BROWSERSAFE, MAX_NOTE_TEXT_LENGTH } from "@/const.js";
// TODO: add iceshrimp features
export async function getInstance(
response: Entity.Instance,
contact: Entity.Account,
) {
const [meta, totalUsers, totalStatuses] = await Promise.all([
fetchMeta(true),
Users.count({where: {host: IsNull()}}),
Notes.count({where: {userHost: IsNull()}}),
]);
return {
uri: response.uri,
title: response.title || "Iceshrimp",
short_description:
response.description?.substring(0, 50) || "See real server website",
description:
response.description ||
"This is a vanilla Iceshrimp Instance. It doesn't seem to have a description.",
email: response.email || "",
version: `4.1.0 (compatible; Iceshrimp ${config.version})`,
urls: response.urls,
stats: {
user_count: await totalUsers,
status_count: await totalStatuses,
domain_count: response.stats.domain_count,
},
thumbnail: response.thumbnail || "/static-assets/transparent.png",
languages: meta.langs,
registrations: !meta.disableRegistration || response.registrations,
approval_required: !response.registrations,
invites_enabled: response.registrations,
configuration: {
accounts: {
max_featured_tags: 20,
},
statuses: {
max_characters: MAX_NOTE_TEXT_LENGTH,
max_media_attachments: 16,
characters_reserved_per_url: response.uri.length,
},
media_attachments: {
supported_mime_types: FILE_TYPE_BROWSERSAFE,
image_size_limit: 10485760,
image_matrix_limit: 16777216,
video_size_limit: 41943040,
video_frame_rate_limit: 60,
video_matrix_limit: 2304000,
},
polls: {
max_options: 10,
max_characters_per_option: 50,
min_expiration: 50,
max_expiration: 2629746,
},
reactions: {
max_reactions: 1,
},
},
contact_account: contact,
rules: [],
};
}

View File

@ -5,6 +5,7 @@ import { convertAccount, convertAnnouncement, convertFilter } from "@/server/api
import { Users } from "@/models/index.js"; import { Users } from "@/models/index.js";
import { getInstance } from "@/server/api/mastodon/endpoints/meta.js"; import { getInstance } from "@/server/api/mastodon/endpoints/meta.js";
import { IsNull } from "typeorm"; import { IsNull } from "typeorm";
import { MiscHelpers } from "@/server/api/mastodon/helpers/misc.js";
export function setupEndpointsMisc(router: Router): void { export function setupEndpointsMisc(router: Router): void {
router.get("/v1/custom_emojis", async (ctx) => { router.get("/v1/custom_emojis", async (ctx) => {
@ -22,30 +23,12 @@ export function setupEndpointsMisc(router: Router): void {
}); });
router.get("/v1/instance", async (ctx) => { router.get("/v1/instance", async (ctx) => {
const BASE_URL = `${ctx.request.protocol}://${ctx.request.hostname}`;
const accessTokens = ctx.request.headers.authorization;
const client = getClient(BASE_URL, accessTokens); // we are using this here, because in private mode some info isnt
// displayed without being logged in
try { try {
const data = await client.getInstance(); ctx.body = await MiscHelpers.getInstance();
const admin = await Users.findOne({
where: {
host: IsNull(),
isAdmin: true,
isDeleted: false,
isSuspended: false,
},
order: {id: "ASC"},
});
const contact =
admin == null
? null
: convertAccount((await client.getAccount(admin.id)).data);
ctx.body = await getInstance(data.data, contact);
} catch (e: any) { } catch (e: any) {
console.error(e); console.error(e);
ctx.status = 401; ctx.status = 500;
ctx.body = e.response.data; ctx.body = { error: e.message };
} }
}); });

View File

@ -0,0 +1,84 @@
import config from "@/config/index.js";
import { FILE_TYPE_BROWSERSAFE, MAX_NOTE_TEXT_LENGTH } from "@/const.js";
import { fetchMeta } from "@/misc/fetch-meta.js";
import { Instances, Notes, Users } from "@/models/index.js";
import { IsNull } from "typeorm";
import { awaitAll } from "@/prelude/await-all.js";
import { UserConverter } from "@/server/api/mastodon/converters/user.js";
import { convertAccount } from "@/server/api/mastodon/converters.js";
export class MiscHelpers {
public static async getInstance(): Promise<MastodonEntity.Instance> {
const userCount = Users.count({where: {host: IsNull()}});
const noteCount = Notes.count({where: {userHost: IsNull()}});
const instanceCount = Instances.count({ cache: 3600000 });
const contact = await Users.findOne({
where: {
host: IsNull(),
isAdmin: true,
isDeleted: false,
isSuspended: false,
},
order: {id: "ASC"},
})
.then(p => p ? UserConverter.encode(p) : null)
.then(p => p ? convertAccount(p) : null);
const meta = await fetchMeta(true);
const res = {
uri: config.domain,
title: meta.name || "Iceshrimp",
short_description:
meta.description?.substring(0, 50) || "This is an Iceshrimp instance. It doesn't seem to have a description.",
description:
meta.description ||
"This is an Iceshrimp instance. It doesn't seem to have a description.",
email: meta.maintainerEmail || "",
version: `4.1.0 (compatible; Iceshrimp ${config.version})`,
urls: {
streaming_api: `${config.url.replace(/^http(?=s?:\/\/)/, "ws")}/streaming`,
},
stats: awaitAll({
user_count: userCount,
status_count: noteCount,
domain_count: instanceCount,
}),
thumbnail: meta.bannerUrl || "/static-assets/transparent.png",
languages: meta.langs,
registrations: !meta.disableRegistration,
approval_required: meta.disableRegistration,
invites_enabled: meta.disableRegistration,
configuration: {
accounts: {
max_featured_tags: 20,
},
statuses: {
max_characters: MAX_NOTE_TEXT_LENGTH,
max_media_attachments: 16,
characters_reserved_per_url: 23,
},
media_attachments: {
supported_mime_types: FILE_TYPE_BROWSERSAFE,
image_size_limit: 10485760,
image_matrix_limit: 16777216,
video_size_limit: 41943040,
video_frame_limit: 60,
video_matrix_limit: 2304000,
},
polls: {
max_options: 10,
max_characters_per_option: 50,
min_expiration: 50,
max_expiration: 2629746,
},
reactions: {
max_reactions: 1,
},
},
contact_account: contact,
rules: [],
};
return awaitAll(res);
}
}