Sharkey/packages/backend/src/core/entities/MetaEntityService.ts

177 lines
5.9 KiB
TypeScript
Raw Normal View History

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Brackets } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common';
import JSON5 from 'json5';
import type { Packed } from '@/misc/json-schema.js';
import type { MiMeta } from '@/models/Meta.js';
import type { AdsRepository } from '@/models/_.js';
import { MetaService } from '@/core/MetaService.js';
import { bindThis } from '@/decorators.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { InstanceActorService } from '@/core/InstanceActorService.js';
import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js';
import { DEFAULT_POLICIES } from '@/core/RoleService.js';
@Injectable()
export class MetaEntityService {
constructor(
@Inject(DI.config)
private config: Config,
@Inject(DI.adsRepository)
private adsRepository: AdsRepository,
private userEntityService: UserEntityService,
private metaService: MetaService,
private instanceActorService: InstanceActorService,
) { }
@bindThis
public async pack(meta?: MiMeta): Promise<Packed<'MetaLite'>> {
let instance = meta;
if (!instance) {
instance = await this.metaService.fetch();
}
const ads = await this.adsRepository.createQueryBuilder('ads')
.where('ads.expiresAt > :now', { now: new Date() })
.andWhere('ads.startsAt <= :now', { now: new Date() })
.andWhere(new Brackets(qb => {
// 曜日のビットフラグを確認する
qb.where('ads.dayOfWeek & :dayOfWeek > 0', { dayOfWeek: 1 << new Date().getDay() })
.orWhere('ads.dayOfWeek = 0');
}))
.getMany();
// クライアントの手間を減らすためあらかじめJSONに変換しておく
let defaultLightTheme = null;
let defaultDarkTheme = null;
if (instance.defaultLightTheme) {
try {
defaultLightTheme = JSON.stringify(JSON5.parse(instance.defaultLightTheme));
} catch (e) {
}
}
if (instance.defaultDarkTheme) {
try {
defaultDarkTheme = JSON.stringify(JSON5.parse(instance.defaultDarkTheme));
} catch (e) {
}
}
const packed: Packed<'MetaLite'> = {
maintainerName: instance.maintainerName,
maintainerEmail: instance.maintainerEmail,
version: this.config.version,
providesTarball: this.config.publishTarballInsteadOfProvideRepositoryUrl,
name: instance.name,
shortName: instance.shortName,
uri: this.config.url,
description: instance.description,
langs: instance.langs,
tosUrl: instance.termsOfServiceUrl,
repositoryUrl: instance.repositoryUrl,
feedbackUrl: instance.feedbackUrl,
impressumUrl: instance.impressumUrl,
2024-02-23 13:42:52 +01:00
donationUrl: instance.donationUrl,
privacyPolicyUrl: instance.privacyPolicyUrl,
inquiryUrl: instance.inquiryUrl,
disableRegistration: instance.disableRegistration,
emailRequiredForSignup: instance.emailRequiredForSignup,
2024-02-23 13:42:52 +01:00
approvalRequiredForSignup: instance.approvalRequiredForSignup,
enableHcaptcha: instance.enableHcaptcha,
hcaptchaSiteKey: instance.hcaptchaSiteKey,
enableMcaptcha: instance.enableMcaptcha,
mcaptchaSiteKey: instance.mcaptchaSitekey,
mcaptchaInstanceUrl: instance.mcaptchaInstanceUrl,
enableRecaptcha: instance.enableRecaptcha,
2024-02-23 13:42:52 +01:00
enableAchievements: instance.enableAchievements,
recaptchaSiteKey: instance.recaptchaSiteKey,
enableTurnstile: instance.enableTurnstile,
turnstileSiteKey: instance.turnstileSiteKey,
swPublickey: instance.swPublicKey,
themeColor: instance.themeColor,
mascotImageUrl: instance.mascotImageUrl ?? '/assets/ai.png',
bannerUrl: instance.bannerUrl,
infoImageUrl: instance.infoImageUrl,
serverErrorImageUrl: instance.serverErrorImageUrl,
notFoundImageUrl: instance.notFoundImageUrl,
iconUrl: instance.iconUrl,
2024-09-22 18:27:41 +02:00
sidebarLogoUrl: instance.sidebarLogoUrl,
backgroundImageUrl: instance.backgroundImageUrl,
logoImageUrl: instance.logoImageUrl,
2024-02-23 13:42:52 +01:00
maxNoteTextLength: this.config.maxNoteLength,
defaultLightTheme,
defaultDarkTheme,
2024-02-23 13:42:52 +01:00
defaultLike: instance.defaultLike,
ads: ads.map(ad => ({
id: ad.id,
url: ad.url,
place: ad.place,
ratio: ad.ratio,
imageUrl: ad.imageUrl,
dayOfWeek: ad.dayOfWeek,
})),
trustedLinkUrlPatterns: instance.trustedLinkUrlPatterns,
notesPerOneAd: instance.notesPerOneAd,
enableEmail: instance.enableEmail,
enableServiceWorker: instance.enableServiceWorker,
2024-02-23 13:42:52 +01:00
translatorAvailable: instance.deeplAuthKey != null || instance.deeplFreeMode && instance.deeplFreeInstance != null,
serverRules: instance.serverRules,
policies: { ...DEFAULT_POLICIES, ...instance.policies },
mediaProxy: this.config.mediaProxy,
enableUrlPreview: instance.urlPreviewEnabled,
noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local',
};
return packed;
}
@bindThis
public async packDetailed(meta?: MiMeta): Promise<Packed<'MetaDetailed'>> {
let instance = meta;
if (!instance) {
instance = await this.metaService.fetch();
}
const packed = await this.pack(instance);
const proxyAccount = instance.proxyAccountId ? await this.userEntityService.pack(instance.proxyAccountId).catch(() => null) : null;
const packDetailed: Packed<'MetaDetailed'> = {
...packed,
cacheRemoteFiles: instance.cacheRemoteFiles,
cacheRemoteSensitiveFiles: instance.cacheRemoteSensitiveFiles,
requireSetup: !await this.instanceActorService.realLocalUsersPresent(),
proxyAccountName: proxyAccount ? proxyAccount.username : null,
features: {
localTimeline: instance.policies.ltlAvailable,
globalTimeline: instance.policies.gtlAvailable,
registration: !instance.disableRegistration,
emailRequiredForSignup: instance.emailRequiredForSignup,
hcaptcha: instance.enableHcaptcha,
recaptcha: instance.enableRecaptcha,
turnstile: instance.enableTurnstile,
objectStorage: instance.useObjectStorage,
serviceWorker: instance.enableServiceWorker,
miauth: true,
},
};
return packDetailed;
}
}