diff --git a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts index 13cf45368d..49274f7074 100644 --- a/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts +++ b/packages/backend/src/server/api/mastodon/MastodonApiServerService.ts @@ -305,9 +305,8 @@ export class MastodonApiServerService { try { const sharkId = _request.params.id; const data = await client.getAccount(sharkId); - const profile = await this.userProfilesRepository.findOneBy({ userId: sharkId }); - data.data.fields = profile?.fields.map(f => ({ ...f, verified_at: null })) || []; - reply.send(convertAccount(data.data)); + const account = await this.mastoConverter.convertAccount(data.data); + reply.send(account); } catch (e: any) { /* console.error(e); console.error(e.response.data); */ diff --git a/packages/backend/src/server/api/mastodon/converters.ts b/packages/backend/src/server/api/mastodon/converters.ts index 6019b825e6..55cf60c66a 100644 --- a/packages/backend/src/server/api/mastodon/converters.ts +++ b/packages/backend/src/server/api/mastodon/converters.ts @@ -1,15 +1,16 @@ -import type { Config } from '@/config.js'; -import { MfmService } from '@/core/MfmService.js'; -import { DI } from '@/di-symbols.js'; import { Inject, Injectable } from '@nestjs/common'; import { Entity } from 'megalodon'; import mfm from 'mfm-js'; -import { GetterService } from '../GetterService.js'; +import { DI } from '@/di-symbols.js'; +import { MfmService } from '@/core/MfmService.js'; +import type { Config } from '@/config.js'; import type { IMentionedRemoteUsers } from '@/models/Note.js'; import type { MiUser } from '@/models/User.js'; -import type { NoteEditRepository, NotesRepository, UsersRepository } from '@/models/_.js'; +import type { NoteEditRepository, NotesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { awaitAll } from '@/misc/prelude/await-all.js'; +import { GetterService } from '../GetterService.js'; +import { CustomEmojiService } from '@/core/CustomEmojiService.js'; export enum IdConvertType { MastodonId, @@ -17,13 +18,13 @@ export enum IdConvertType { } export const escapeMFM = (text: string): string => text - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'") - .replace(/`/g, "`") - .replace(/\r?\n/g, "
"); + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/`/g, '`') + .replace(/\r?\n/g, '
'); @Injectable() export class MastoConverters { @@ -31,8 +32,15 @@ export class MastoConverters { @Inject(DI.config) private config: Config, + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + @Inject(DI.userProfilesRepository) + private userProfilesRepository: UserProfilesRepository, + private mfmService: MfmService, private getterService: GetterService, + private customEmojiService: CustomEmojiService, ) { } @@ -60,29 +68,51 @@ export class MastoConverters { }); } + private async encodeField(f: Entity.Field): Promise { + return { + name: f.name, + value: await this.mfmService.toMastoHtml(mfm.parse(f.value), [], true) ?? escapeMFM(f.value), + verified_at: null, + }; + } + public async convertAccount(account: Entity.Account) { + const user = await this.getUser(account.id); + const profile = await this.userProfilesRepository.findOneBy({ userId: user.id }); + const emojis = await this.customEmojiService.populateEmojis(user.emojis, user.host ? user.host : this.config.host); + const emoji: Entity.Emoji[] = []; + Object.entries(emojis).forEach(entry => { + const [key, value] = entry; + emoji.push({ + shortcode: key, + static_url: value, + url: value, + visible_in_picker: true, + category: undefined, + }); + }); return awaitAll({ id: account.id, username: account.username, acct: account.acct, fqn: account.fqn, display_name: account.display_name || account.username, - locked: account.locked, + locked: user.isLocked, created_at: account.created_at, - followers_count: account.followers_count, - following_count: account.following_count, - statuses_count: account.statuses_count, - note: account.note, + followers_count: user.followersCount, + following_count: user.followingCount, + statuses_count: user.notesCount, + note: profile?.description ?? account.note, url: account.url, - avatar: account.avatar, - avatar_static: account.avatar, - header: account.header, - header_static: account.header, - emojis: account.emojis, + avatar: user.avatarUrl ? user.avatarUrl : 'https://dev.joinsharkey.org/static-assets/avatar.png', + avatar_static: user.avatarUrl ? user.avatarUrl : 'https://dev.joinsharkey.org/static-assets/avatar.png', + header: user.bannerUrl ? user.bannerUrl : 'https://dev.joinsharkey.org/static-assets/transparent.png', + header_static: user.bannerUrl ? user.bannerUrl : 'https://dev.joinsharkey.org/static-assets/transparent.png', + emojis: emoji, moved: null, //FIXME - fields: [], - bot: false, - discoverable: true, + fields: Promise.all(profile?.fields.map(async p => this.encodeField(p)) ?? []), + bot: user.isBot, + discoverable: user.isExplorable, }); } diff --git a/packages/megalodon/src/entities/field.ts b/packages/megalodon/src/entities/field.ts index 03e4604b02..71ce3c0cfa 100644 --- a/packages/megalodon/src/entities/field.ts +++ b/packages/megalodon/src/entities/field.ts @@ -2,6 +2,6 @@ namespace Entity { export type Field = { name: string value: string - verified_at: string | null + verified_at?: string | null } } diff --git a/packages/megalodon/src/misskey/entities/field.ts b/packages/megalodon/src/misskey/entities/field.ts index 8bbb2d7c42..1e61178e56 100644 --- a/packages/megalodon/src/misskey/entities/field.ts +++ b/packages/megalodon/src/misskey/entities/field.ts @@ -3,5 +3,6 @@ namespace MisskeyEntity { name: string; value: string; verified?: string; + verified_at?: string; }; }