[mastodon-client] Refactor converters

This commit is contained in:
Laura Hausmann 2023-09-15 12:14:36 +02:00
parent d258789c34
commit 2fe58b0017
No known key found for this signature in database
GPG Key ID: D044E84C5BE01605
6 changed files with 64 additions and 59 deletions

View File

@ -1,17 +1,19 @@
import { User } from "@/models/entities/user.js"; import { User } from "@/models/entities/user.js";
import config from "@/config/index.js"; import config from "@/config/index.js";
export function convertMention(u: User): MastodonEntity.Mention { export class MentionConverter {
let acct = u.username; public static encode(u: User): MastodonEntity.Mention {
let acctUrl = `https://${u.host || config.host}/@${u.username}`; let acct = u.username;
if (u.host) { let acctUrl = `https://${u.host || config.host}/@${u.username}`;
acct = `${u.username}@${u.host}`; if (u.host) {
acctUrl = `https://${u.host}/@${u.username}`; acct = `${u.username}@${u.host}`;
} acctUrl = `https://${u.host}/@${u.username}`;
return { }
id: u.id, return {
username: u.username, id: u.id,
acct: acct, username: u.username,
url: u.uri ?? acctUrl, acct: acct,
}; url: u.uri ?? acctUrl,
};
}
} }

View File

@ -4,14 +4,14 @@ import { Note } from "@/models/entities/note.js";
import config from "@/config/index.js"; import config from "@/config/index.js";
import mfm from "mfm-js"; import mfm from "mfm-js";
import { toHtml } from "@/mfm/to-html.js"; import { toHtml } from "@/mfm/to-html.js";
import { convertUser } from "@/server/api/mastodon/converters/user.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js";
import { Visibility } from "@/server/api/mastodon/converters/visibility.js"; import { VisibilityConverter } from "@/server/api/mastodon/converters/visibility.js";
import { escapeMFM } from "@/server/api/mastodon/converters/mfm.js"; import { escapeMFM } from "@/server/api/mastodon/converters/mfm.js";
import { populateEmojis } from "@/misc/populate-emojis.js"; import { populateEmojis } from "@/misc/populate-emojis.js";
import { EmojiConverter } from "@/server/api/mastodon/converters/emoji.js"; import { EmojiConverter } from "@/server/api/mastodon/converters/emoji.js";
import { DriveFiles, NoteFavorites, NoteReactions, Notes, NoteThreadMutings } from "@/models/index.js"; import { DriveFiles, NoteFavorites, NoteReactions, Notes, NoteThreadMutings } from "@/models/index.js";
import { decodeReaction } from "@/misc/reaction-lib.js"; import { decodeReaction } from "@/misc/reaction-lib.js";
import { convertMention } from "@/server/api/mastodon/converters/mention.js"; import { MentionConverter } from "@/server/api/mastodon/converters/mention.js";
import { PollConverter } from "@/server/api/mastodon/converters/poll.js"; import { PollConverter } from "@/server/api/mastodon/converters/poll.js";
import { populatePoll } from "@/models/repositories/note.js"; import { populatePoll } from "@/models/repositories/note.js";
import { FileConverter } from "@/server/api/mastodon/converters/file.js"; import { FileConverter } from "@/server/api/mastodon/converters/file.js";
@ -74,7 +74,7 @@ export class NoteConverter {
id: note.id, id: note.id,
uri: note.uri ? note.uri : `https://${config.host}/notes/${note.id}`, uri: note.uri ? note.uri : `https://${config.host}/notes/${note.id}`,
url: note.uri ? note.uri : `https://${config.host}/notes/${note.id}`, url: note.uri ? note.uri : `https://${config.host}/notes/${note.id}`,
account: await convertUser(noteUser), account: await UserConverter.encode(noteUser),
in_reply_to_id: note.replyId, in_reply_to_id: note.replyId,
in_reply_to_account_id: reply?.userId ?? null, in_reply_to_account_id: reply?.userId ?? null,
reblog: note.renote ? await this.encode(note.renote, user) : null, reblog: note.renote ? await this.encode(note.renote, user) : null,
@ -93,9 +93,9 @@ export class NoteConverter {
muted: isMuted, muted: isMuted,
sensitive: files.length > 0 ? files.some((f) => f.isSensitive) : false, sensitive: files.length > 0 ? files.some((f) => f.isSensitive) : false,
spoiler_text: note.cw ? note.cw : "", spoiler_text: note.cw ? note.cw : "",
visibility: Visibility.encode(note.visibility), visibility: VisibilityConverter.encode(note.visibility),
media_attachments: files.length > 0 ? files.map((f) => FileConverter.encode(f)) : [], media_attachments: files.length > 0 ? files.map((f) => FileConverter.encode(f)) : [],
mentions: await Promise.all(note.mentions.map(async p => convertMention(await getUser(p)))), mentions: await Promise.all(note.mentions.map(async p => MentionConverter.encode(await getUser(p)))),
tags: [], //FIXME tags: [], //FIXME
card: null, //FIXME card: null, //FIXME
poll: note.hasPoll ? PollConverter.encode(await populatePoll(note, user.id), note.id) : null, poll: note.hasPoll ? PollConverter.encode(await populatePoll(note, user.id), note.id) : null,

View File

@ -13,43 +13,46 @@ type Field = {
verified?: boolean; verified?: boolean;
}; };
export async function convertUser(u: User): Promise<MastodonEntity.Account> { export class UserConverter {
let acct = u.username; public static async encode(u: User): Promise<MastodonEntity.Account> {
let acctUrl = `https://${u.host || config.host}/@${u.username}`; let acct = u.username;
if (u.host) { let acctUrl = `https://${u.host || config.host}/@${u.username}`;
acct = `${u.username}@${u.host}`; if (u.host) {
acctUrl = `https://${u.host}/@${u.username}`; acct = `${u.username}@${u.host}`;
} acctUrl = `https://${u.host}/@${u.username}`;
}
const profile = await UserProfiles.findOneBy({userId: u.id}); const profile = await UserProfiles.findOneBy({userId: u.id});
const bio = toHtml(mfm.parse(profile?.description ?? "")) ?? escapeMFM(profile?.description ?? ""); const bio = toHtml(mfm.parse(profile?.description ?? "")) ?? escapeMFM(profile?.description ?? "");
return { return {
id: u.id, id: u.id,
username: u.username, username: u.username,
acct: acct, acct: acct,
display_name: u.name || u.username, display_name: u.name || u.username,
locked: u.isLocked, locked: u.isLocked,
created_at: new Date().toISOString(), created_at: new Date().toISOString(),
followers_count: u.followersCount, followers_count: u.followersCount,
following_count: u.followingCount, following_count: u.followingCount,
statuses_count: u.notesCount, statuses_count: u.notesCount,
note: bio, note: bio,
url: u.uri ?? acctUrl, url: u.uri ?? acctUrl,
avatar: u.avatar?.url ?? Users.getIdenticonUrl(u.id), avatar: u.avatar?.url ?? Users.getIdenticonUrl(u.id),
avatar_static: u.avatar?.url ?? Users.getIdenticonUrl(u.id), avatar_static: u.avatar?.url ?? Users.getIdenticonUrl(u.id),
header: u.banner?.url ?? `${config.url}/static-assets/transparent.png`, header: u.banner?.url ?? `${config.url}/static-assets/transparent.png`,
header_static: u.banner?.url ?? `${config.url}/static-assets/transparent.png`, header_static: u.banner?.url ?? `${config.url}/static-assets/transparent.png`,
emojis: (await populateEmojis(u.emojis, u.host)).map((e) => EmojiConverter.encode(e)), emojis: (await populateEmojis(u.emojis, u.host)).map((e) => EmojiConverter.encode(e)),
moved: null, //FIXME moved: null, //FIXME
fields: profile?.fields.map(p => convertField(p)) ?? [], fields: profile?.fields.map(p => this.encodeField(p)) ?? [],
bot: u.isBot bot: u.isBot
}; };
}
function convertField(f: Field): MastodonEntity.Field {
return {
name: f.name,
value: toHtml(mfm.parse(f.value)) ?? escapeMFM(f.value),
verified_at: f.verified ? (new Date()).toISOString() : null,
} }
private static encodeField(f: Field): MastodonEntity.Field {
return {
name: f.name,
value: toHtml(mfm.parse(f.value)) ?? escapeMFM(f.value),
verified_at: f.verified ? (new Date()).toISOString() : null,
}
}
} }

View File

@ -1,7 +1,7 @@
type IceshrimpVisibility = "public" | "home" | "followers" | "specified" | "hidden"; type IceshrimpVisibility = "public" | "home" | "followers" | "specified" | "hidden";
type MastodonVisibility = "public" | "unlisted" | "private" | "direct"; type MastodonVisibility = "public" | "unlisted" | "private" | "direct";
export class Visibility { export class VisibilityConverter {
public static encode (v: IceshrimpVisibility): MastodonVisibility { public static encode (v: IceshrimpVisibility): MastodonVisibility {
switch (v) { switch (v) {
case "public": case "public":

View File

@ -13,7 +13,7 @@ import {
convertStatus, convertStatus,
} from "../converters.js"; } from "../converters.js";
import { getNote, getUser } from "@/server/api/common/getters.js"; import { getNote, getUser } from "@/server/api/common/getters.js";
import { convertUser } from "@/server/api/mastodon/converters/user.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js";
const relationshipModel = { const relationshipModel = {
id: "", id: "",
@ -135,7 +135,7 @@ export function apiAccountMastodon(router: Router): void {
router.get<{ Params: { id: string } }>("/v1/accounts/:id", async (ctx) => { router.get<{ Params: { id: string } }>("/v1/accounts/:id", async (ctx) => {
try { try {
const userId = convertId(ctx.params.id, IdType.IceshrimpId); const userId = convertId(ctx.params.id, IdType.IceshrimpId);
const account = await convertUser(await getUser(userId)); const account = await UserConverter.encode(await getUser(userId));
ctx.body = convertAccount(account); ctx.body = convertAccount(account);
} catch (e: any) { } catch (e: any) {
console.error(e); console.error(e);

View File

@ -12,8 +12,8 @@ import {
convertPoll, convertPoll,
convertStatus, convertStatus,
} from "../converters.js"; } from "../converters.js";
import {NoteConverter} from "@/server/api/mastodon/converters/note.js"; import { NoteConverter } from "@/server/api/mastodon/converters/note.js";
import {getNote} from "@/server/api/common/getters.js"; import { getNote } from "@/server/api/common/getters.js";
import authenticate from "@/server/api/authenticate.js"; import authenticate from "@/server/api/authenticate.js";
import {Notes} from "@/models"; import {Notes} from "@/models";