diff --git a/locales/index.d.ts b/locales/index.d.ts index 39f0b80fdf..5ee0d2f0e1 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -8105,6 +8105,14 @@ export interface Locale extends ILocale { * 文字の上にルビを表示します。 */ "rubyDescription": string; + /** + * ボーダー + */ + "border": string; + /** + * 内容を枠線で囲みます。 + */ + "borderDescription": string; }; "_instanceTicker": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 9a25d81d0f..1ad1dd9c48 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2062,7 +2062,7 @@ _mfm: inlineCode: "コード(インライン)" inlineCodeDescription: "プログラムなどのコードをインラインでシンタックスハイライトします。" blockCode: "コード(ブロック)" - blockCodeDescription: "複数行のプログラムなどのコードをブロックでシンタックスハイライトします。" + blockCodeDescription: "複数行のプログラムなどのコードをブロックでシンタックスハイライトします。いくつかの言語を指定するとその言語に合わせたシンタックスハイライトになります。" inlineMath: "数式(インライン)" inlineMathDescription: "数式(KaTeX)をインラインで表示します。" blockMath: "数式(ブロック)" @@ -2119,6 +2119,8 @@ _mfm: plainDescription: "内側の構文を全て無効にします。" ruby: "ルビ" rubyDescription: "文字の上にルビを表示します。" + border: "border" + borderDescription: "内容を枠線で囲むことができます。" _instanceTicker: none: "表示しない" diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts index f3cda78038..71fa742686 100644 --- a/packages/backend/src/core/activitypub/models/ApPersonService.ts +++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts @@ -39,6 +39,8 @@ import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.j import type { AccountMoveService } from '@/core/AccountMoveService.js'; import { checkHttps } from '@/misc/check-https.js'; import { AvatarDecorationService } from '@/core/AvatarDecorationService.js'; +import { HttpRequestService } from '@/core/HttpRequestService.js'; +import { isNotNull } from '@/misc/is-not-null.js'; import { getApId, getApType, getOneApHrefNullable, isActor, isCollection, isCollectionOrOrderedCollection, isPropertyValue } from '../type.js'; import { extractApHashtags } from './tag.js'; import type { OnModuleInit } from '@nestjs/common'; @@ -103,6 +105,7 @@ export class ApPersonService implements OnModuleInit { private followingsRepository: FollowingsRepository, private avatarDecorationService: AvatarDecorationService, + private httpRequestService: HttpRequestService, ) { } @@ -371,6 +374,34 @@ export class ApPersonService implements OnModuleInit { }); //#endregion + let isReactionPublic = false; + let followingVisibility: 'private' | 'followers' | 'public' | undefined = typeof person.following === 'string' ? 'private' : 'public'; + let followersVisibility: 'private' | 'followers' | 'public' | undefined = typeof person.followers === 'string' ? 'private' : 'public'; + const instance = await this.instancesRepository.findOneBy({ host: host }); + + if (instance?.softwareName === 'misskey' || instance?.softwareName === 'cherrypick') { + const userHostUrl = `https://${host}`; + const showUserApiUrl = `${userHostUrl}/api/users/show`; + const res = await this.httpRequestService.send(showUserApiUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ 'username': person.preferredUsername }), + }); + + const userData: any = await res.json(); + if (userData.publicReactions === undefined ) { + isReactionPublic = userData.publicReactions; + } + + if (userData._ffVisibility === undefined) { + followingVisibility = userData._ffVisibility; + followersVisibility = userData._ffVisibility; + } else { + followingVisibility = userData.followingVisibility; + followersVisibility = userData.followersVisibility; + } + } + try { // Start transaction await this.db.transaction(async transactionalEntityManager => { @@ -439,6 +470,9 @@ export class ApPersonService implements OnModuleInit { birthday: bday?.[0] ?? null, location: person['vcard:Address'] ?? null, userHost: host, + followersVisibility: followersVisibility, + followingVisibility: followingVisibility, + publicReactions: isReactionPublic, })); if (person.publicKey) { @@ -549,10 +583,37 @@ export class ApPersonService implements OnModuleInit { const url = getOneApHrefNullable(person.url); + const host = this.punyHost(uri); + if (url && !checkHttps(url)) { throw new Error('unexpected schema of person url: ' + url); } + let isReactionPublic = false; + let followingVisibility: 'private' | 'followers' | 'public' | undefined = typeof person.following === 'string' ? 'private' : 'public'; + let followersVisibility: 'private' | 'followers' | 'public' | undefined = typeof person.followers === 'string' ? 'private' : 'public'; + const instance = await this.instancesRepository.findOneBy({ host: host }); + + if (instance?.softwareName === 'misskey' || instance?.softwareName === 'cherrypick') { + const userHostUrl = `https://${host}`; + const showUserApiUrl = `${userHostUrl}/api/users/show`; + const res = await this.httpRequestService.send(showUserApiUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ 'username': person.preferredUsername }), + }); + const userData: any = await res.json(); + + if (userData.publicReactions === undefined ) { + isReactionPublic = userData.publicReactions; + } + + if (userData._ffVisibility === undefined) { + followingVisibility = userData._ffVisibility; + followersVisibility = userData._ffVisibility; + } + } + let followersCount: number | undefined; if (typeof person.followers === 'string') { @@ -686,6 +747,9 @@ export class ApPersonService implements OnModuleInit { description: _description, birthday: bday?.[0] ?? null, location: person['vcard:Address'] ?? null, + followersVisibility: followersVisibility, + followingVisibility: followingVisibility, + publicReactions: isReactionPublic, }); this.globalEventService.publishInternalEvent('remoteUserUpdated', { id: exist.id }); diff --git a/packages/frontend/src/pages/mfm-cheat-sheet.vue b/packages/frontend/src/pages/mfm-cheat-sheet.vue index a93d2019d7..37bb0a6a4b 100644 --- a/packages/frontend/src/pages/mfm-cheat-sheet.vue +++ b/packages/frontend/src/pages/mfm-cheat-sheet.vue @@ -380,6 +380,16 @@ SPDX-License-Identifier: AGPL-3.0-only +
{{ i18n.ts._mfm.borderDescription }}
+