diff --git a/packages/backend/src/server/api/mastodon/endpoints/meta.ts b/packages/backend/src/server/api/mastodon/endpoints/meta.ts deleted file mode 100644 index 6115fef47..000000000 --- a/packages/backend/src/server/api/mastodon/endpoints/meta.ts +++ /dev/null @@ -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: [], - }; -} diff --git a/packages/backend/src/server/api/mastodon/endpoints/misc.ts b/packages/backend/src/server/api/mastodon/endpoints/misc.ts index 93583bc56..f0011eaaa 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/misc.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/misc.ts @@ -5,6 +5,7 @@ import { convertAccount, convertAnnouncement, convertFilter } from "@/server/api import { Users } from "@/models/index.js"; import { getInstance } from "@/server/api/mastodon/endpoints/meta.js"; import { IsNull } from "typeorm"; +import { MiscHelpers } from "@/server/api/mastodon/helpers/misc.js"; export function setupEndpointsMisc(router: Router): void { router.get("/v1/custom_emojis", async (ctx) => { @@ -22,30 +23,12 @@ export function setupEndpointsMisc(router: Router): void { }); 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 { - const data = await client.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); + ctx.body = await MiscHelpers.getInstance(); } catch (e: any) { console.error(e); - ctx.status = 401; - ctx.body = e.response.data; + ctx.status = 500; + ctx.body = { error: e.message }; } }); diff --git a/packages/backend/src/server/api/mastodon/helpers/misc.ts b/packages/backend/src/server/api/mastodon/helpers/misc.ts new file mode 100644 index 000000000..eec930e3e --- /dev/null +++ b/packages/backend/src/server/api/mastodon/helpers/misc.ts @@ -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 { + 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); + } +} \ No newline at end of file