Sharkey/packages/backend/src/server/api/mastodon/endpoints/instance.ts
2025-03-27 19:51:42 -04:00

104 lines
3.4 KiB
TypeScript

/*
* SPDX-FileCopyrightText: marie and other Sharkey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { IsNull } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
import { FILE_TYPE_BROWSERSAFE } from '@/const.js';
import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js';
import type { MiMeta, UsersRepository } from '@/models/_.js';
import { MastoConverters } from '@/server/api/mastodon/converters.js';
import { MastodonClientService } from '@/server/api/mastodon/MastodonClientService.js';
import { RoleService } from '@/core/RoleService.js';
import type { FastifyInstance } from 'fastify';
import type { MastodonEntity } from 'megalodon';
@Injectable()
export class ApiInstanceMastodon {
constructor(
@Inject(DI.meta)
private readonly meta: MiMeta,
@Inject(DI.usersRepository)
private readonly usersRepository: UsersRepository,
@Inject(DI.config)
private readonly config: Config,
private readonly mastoConverters: MastoConverters,
private readonly clientService: MastodonClientService,
private readonly roleService: RoleService,
) {}
public register(fastify: FastifyInstance): void {
fastify.get('/v1/instance', async (_request, reply) => {
const { client, me } = await this.clientService.getAuthClient(_request);
const data = await client.getInstance();
const instance = data.data;
const admin = await this.usersRepository.findOne({
where: {
host: IsNull(),
isRoot: true,
isDeleted: false,
isSuspended: false,
},
order: { id: 'ASC' },
});
const contact = admin == null ? null : await this.mastoConverters.convertAccount((await client.getAccount(admin.id)).data);
const roles = await this.roleService.getUserPolicies(me?.id ?? null);
const response: MastodonEntity.Instance = {
uri: this.config.url,
title: this.meta.name || 'Sharkey',
description: this.meta.description || 'This is a vanilla Sharkey Instance. It doesn\'t seem to have a description.',
email: instance.email || '',
version: `3.0.0 (compatible; Sharkey ${this.config.version})`,
urls: instance.urls,
stats: {
user_count: instance.stats.user_count,
status_count: instance.stats.status_count,
domain_count: instance.stats.domain_count,
},
thumbnail: this.meta.backgroundImageUrl || '/static-assets/transparent.png',
languages: this.meta.langs,
registrations: !this.meta.disableRegistration || instance.registrations,
approval_required: this.meta.approvalRequiredForSignup,
invites_enabled: instance.registrations,
configuration: {
accounts: {
max_featured_tags: 20,
max_pinned_statuses: roles.pinLimit,
},
statuses: {
max_characters: this.config.maxNoteLength,
max_media_attachments: 16,
characters_reserved_per_url: instance.uri.length,
},
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: 150,
min_expiration: 50,
max_expiration: 2629746,
},
reactions: {
max_reactions: 1,
},
},
contact_account: contact,
rules: instance.rules ?? [],
};
reply.send(response);
});
}
}