refactor (backend-rs): rewrite Mastodon ID conversion

Co-authored-by: sup39 <dev@sup39.dev>
This commit is contained in:
naskya 2024-04-12 19:05:14 +09:00
parent 35ca75bfe5
commit 603ec70b97
No known key found for this signature in database
GPG Key ID: 712D413B3A9FED5C
14 changed files with 111 additions and 201 deletions

View File

@ -132,6 +132,8 @@ export function isSelfHost(host?: string | undefined | null): boolean
export function isSameOrigin(uri: string): boolean export function isSameOrigin(uri: string): boolean
export function extractHost(uri: string): string export function extractHost(uri: string): string
export function toPuny(host: string): string export function toPuny(host: string): string
export function toMastodonId(firefishId: string): string | null
export function fromMastodonId(mastodonId: string): string | null
export function nyaify(text: string, lang?: string | undefined | null): string export function nyaify(text: string, lang?: string | undefined | null): string
export interface AbuseUserReport { export interface AbuseUserReport {
id: string id: string
@ -996,8 +998,3 @@ export function getTimestamp(id: string): number
*/ */
export function genId(date?: Date | undefined | null): string export function genId(date?: Date | undefined | null): string
export function secureRndstr(length?: number | undefined | null): string export function secureRndstr(length?: number | undefined | null): string
export const enum IdConvertType {
MastodonId = 0,
FirefishId = 1
}
export function convertId(inId: string, idConvertType: IdConvertType): string

View File

@ -310,7 +310,7 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`) throw new Error(`Failed to load native binding`)
} }
const { readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, nyaify, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr, IdConvertType, convertId } = nativeBinding const { readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, toMastodonId, fromMastodonId, nyaify, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding
module.exports.readServerConfig = readServerConfig module.exports.readServerConfig = readServerConfig
module.exports.stringToAcct = stringToAcct module.exports.stringToAcct = stringToAcct
@ -321,6 +321,8 @@ module.exports.isSelfHost = isSelfHost
module.exports.isSameOrigin = isSameOrigin module.exports.isSameOrigin = isSameOrigin
module.exports.extractHost = extractHost module.exports.extractHost = extractHost
module.exports.toPuny = toPuny module.exports.toPuny = toPuny
module.exports.toMastodonId = toMastodonId
module.exports.fromMastodonId = fromMastodonId
module.exports.nyaify = nyaify module.exports.nyaify = nyaify
module.exports.AntennaSrcEnum = AntennaSrcEnum module.exports.AntennaSrcEnum = AntennaSrcEnum
module.exports.MutedNoteReasonEnum = MutedNoteReasonEnum module.exports.MutedNoteReasonEnum = MutedNoteReasonEnum
@ -336,5 +338,3 @@ module.exports.initIdGenerator = initIdGenerator
module.exports.getTimestamp = getTimestamp module.exports.getTimestamp = getTimestamp
module.exports.genId = genId module.exports.genId = genId
module.exports.secureRndstr = secureRndstr module.exports.secureRndstr = secureRndstr
module.exports.IdConvertType = IdConvertType
module.exports.convertId = convertId

View File

@ -5,6 +5,3 @@ pub mod database;
pub mod misc; pub mod misc;
pub mod model; pub mod model;
pub mod util; pub mod util;
#[cfg(feature = "napi")]
pub mod mastodon_api;

View File

@ -1,70 +0,0 @@
use napi::{Error, Status};
use napi_derive::napi;
static CHAR_COLLECTION: &str = "0123456789abcdefghijklmnopqrstuvwxyz";
// -- NAPI exports --
#[napi]
pub enum IdConvertType {
MastodonId,
FirefishId,
}
#[napi]
pub fn convert_id(in_id: String, id_convert_type: IdConvertType) -> napi::Result<String> {
use IdConvertType::*;
match id_convert_type {
MastodonId => {
let mut out: i128 = 0;
for (i, c) in in_id.to_lowercase().chars().rev().enumerate() {
out += num_from_char(c)? as i128 * 36_i128.pow(i as u32);
}
Ok(out.to_string())
}
FirefishId => {
let mut input: i128 = match in_id.parse() {
Ok(s) => s,
Err(_) => {
return Err(Error::new(
Status::InvalidArg,
"Unable to parse ID as MastodonId",
))
}
};
let mut out = String::new();
while input != 0 {
out.insert(0, char_from_num((input % 36) as u8)?);
input /= 36;
}
Ok(out)
}
}
}
// -- end --
#[inline(always)]
fn num_from_char(character: char) -> napi::Result<u8> {
for (i, c) in CHAR_COLLECTION.chars().enumerate() {
if c == character {
return Ok(i as u8);
}
}
Err(Error::new(
Status::InvalidArg,
"Invalid character in parsed base36 id",
))
}
#[inline(always)]
fn char_from_num(number: u8) -> napi::Result<char> {
CHAR_COLLECTION
.chars()
.nth(number as usize)
.ok_or(Error::from_status(Status::Unknown))
}

View File

@ -0,0 +1,35 @@
#[crate::export]
pub fn to_mastodon_id(firefish_id: &str) -> Option<String> {
let decoded: [u8; 16] = basen::BASE36.decode_var_len(&firefish_id.to_ascii_lowercase())?;
Some(basen::BASE10.encode_var_len(&decoded))
}
#[crate::export]
pub fn from_mastodon_id(mastodon_id: &str) -> Option<String> {
let decoded: [u8; 16] = basen::BASE10.decode_var_len(mastodon_id)?;
Some(basen::BASE36.encode_var_len(&decoded))
}
#[cfg(test)]
mod unit_test {
use super::{from_mastodon_id, to_mastodon_id};
use pretty_assertions::assert_eq;
#[test]
fn to_mastodon_id_test() {
assert_eq!(
to_mastodon_id("9pdqi3rjl4lxirq3").unwrap(),
"2145531976185871567229403"
);
assert_eq!(to_mastodon_id("9pdqi3r*irq3"), None);
}
#[test]
fn from_mastodon_id_test() {
assert_eq!(
from_mastodon_id("2145531976185871567229403").unwrap(),
"9pdqi3rjl4lxirq3"
);
assert_eq!(from_mastodon_id("9pdqi3rjl4lxirq3"), None);
}
}

View File

@ -1,4 +1,5 @@
pub mod acct; pub mod acct;
pub mod check_word_mute; pub mod check_word_mute;
pub mod convert_host; pub mod convert_host;
pub mod mastodon_id;
pub mod nyaify; pub mod nyaify;

View File

@ -23,13 +23,8 @@ import verifyEmail from "./private/verify-email.js";
import { koaBody } from "koa-body"; import { koaBody } from "koa-body";
import { convertAttachment } from "./mastodon/converters.js"; import { convertAttachment } from "./mastodon/converters.js";
import { apiLogger } from "./logger.js"; import { apiLogger } from "./logger.js";
import { convertId, IdConvertType as IdType } from "backend-rs";
import { inspect } from "node:util"; import { inspect } from "node:util";
// re-export native rust id conversion (function and enum)
export { IdType, convertId };
// Init app // Init app
const app = new Koa(); const app = new Koa();

View File

@ -13,7 +13,7 @@ import {
convertAnnouncement, convertAnnouncement,
convertFilter, convertFilter,
} from "./converters.js"; } from "./converters.js";
import { convertId, IdType } from "@/server/api/index.js"; import { fromMastodonId } from "backend-rs";
import { Users } from "@/models/index.js"; import { Users } from "@/models/index.js";
import { IsNull } from "typeorm"; import { IsNull } from "typeorm";
import { apiLogger } from "../logger.js"; import { apiLogger } from "../logger.js";
@ -105,7 +105,7 @@ export function apiMastodonCompatible(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.dismissInstanceAnnouncement( const data = await client.dismissInstanceAnnouncement(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = data.data; ctx.body = data.data;
} catch (e: any) { } catch (e: any) {

View File

@ -1,10 +1,10 @@
import { Entity } from "megalodon"; import { Entity } from "megalodon";
import { convertId, IdType } from "@/server/api/index.js"; import { toMastodonId } from "backend-rs";
function simpleConvert(data: any) { function simpleConvert(data: any) {
// copy the object to bypass weird pass by reference bugs // copy the object to bypass weird pass by reference bugs
const result = Object.assign({}, data); const result = Object.assign({}, data);
result.id = convertId(data.id, IdType.MastodonId); result.id = toMastodonId(data.id);
return result; return result;
} }
@ -29,7 +29,7 @@ export function convertFeaturedTag(tag: Entity.FeaturedTag) {
export function convertNotification(notification: Entity.Notification) { export function convertNotification(notification: Entity.Notification) {
notification.account = convertAccount(notification.account); notification.account = convertAccount(notification.account);
notification.id = convertId(notification.id, IdType.MastodonId); notification.id = toMastodonId(notification.id);
if (notification.status) if (notification.status)
notification.status = convertStatus(notification.status); notification.status = convertStatus(notification.status);
if (notification.reaction) if (notification.reaction)
@ -52,20 +52,17 @@ export function convertRelationship(relationship: Entity.Relationship) {
export function convertStatus(status: Entity.Status) { export function convertStatus(status: Entity.Status) {
status.account = convertAccount(status.account); status.account = convertAccount(status.account);
status.id = convertId(status.id, IdType.MastodonId); status.id = toMastodonId(status.id);
if (status.in_reply_to_account_id) if (status.in_reply_to_account_id)
status.in_reply_to_account_id = convertId( status.in_reply_to_account_id = toMastodonId(status.in_reply_to_account_id);
status.in_reply_to_account_id,
IdType.MastodonId,
);
if (status.in_reply_to_id) if (status.in_reply_to_id)
status.in_reply_to_id = convertId(status.in_reply_to_id, IdType.MastodonId); status.in_reply_to_id = toMastodonId(status.in_reply_to_id);
status.media_attachments = status.media_attachments.map((attachment) => status.media_attachments = status.media_attachments.map((attachment) =>
convertAttachment(attachment), convertAttachment(attachment),
); );
status.mentions = status.mentions.map((mention) => ({ status.mentions = status.mentions.map((mention) => ({
...mention, ...mention,
id: convertId(mention.id, IdType.MastodonId), id: toMastodonId(mention.id),
})); }));
if (status.poll) status.poll = convertPoll(status.poll); if (status.poll) status.poll = convertPoll(status.poll);
if (status.reblog) status.reblog = convertStatus(status.reblog); if (status.reblog) status.reblog = convertStatus(status.reblog);
@ -76,7 +73,7 @@ export function convertStatus(status: Entity.Status) {
} }
export function convertConversation(conversation: Entity.Conversation) { export function convertConversation(conversation: Entity.Conversation) {
conversation.id = convertId(conversation.id, IdType.MastodonId); conversation.id = toMastodonId(conversation.id);
conversation.accounts = conversation.accounts.map(convertAccount); conversation.accounts = conversation.accounts.map(convertAccount);
if (conversation.last_status) { if (conversation.last_status) {
conversation.last_status = convertStatus(conversation.last_status); conversation.last_status = convertStatus(conversation.last_status);

View File

@ -1,7 +1,7 @@
import Router from "@koa/router"; import Router from "@koa/router";
import { getClient } from "../ApiMastodonCompatibleService.js"; import { getClient } from "../ApiMastodonCompatibleService.js";
import { argsToBools, convertTimelinesArgsId, limitToInt } from "./timeline.js"; import { argsToBools, convertTimelinesArgsId, limitToInt } from "./timeline.js";
import { convertId, IdType } from "@/server/api/index.js"; import { fromMastodonId, toMastodonId } from "backend-rs";
import { import {
convertAccount, convertAccount,
convertFeaturedTag, convertFeaturedTag,
@ -37,7 +37,7 @@ export function apiAccountMastodon(router: Router): void {
try { try {
const data = await client.verifyAccountCredentials(); const data = await client.verifyAccountCredentials();
let acct = data.data; let acct = data.data;
acct.id = convertId(acct.id, IdType.MastodonId); acct.id = toMastodonId(acct.id);
acct.display_name = acct.display_name || acct.username; acct.display_name = acct.display_name || acct.username;
acct.url = `${BASE_URL}/@${acct.url}`; acct.url = `${BASE_URL}/@${acct.url}`;
acct.note = acct.note || ""; acct.note = acct.note || "";
@ -110,7 +110,7 @@ export function apiAccountMastodon(router: Router): void {
let reqIds = []; let reqIds = [];
for (let i = 0; i < ids.length; i++) { for (let i = 0; i < ids.length; i++) {
reqIds.push(convertId(ids[i], IdType.FirefishId)); reqIds.push(fromMastodonId(ids[i]));
} }
const data = await client.getRelationships(reqIds); const data = await client.getRelationships(reqIds);
@ -130,7 +130,7 @@ export function apiAccountMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const calcId = convertId(ctx.params.id, IdType.FirefishId); const calcId = fromMastodonId(ctx.params.id);
const data = await client.getAccount(calcId); const data = await client.getAccount(calcId);
ctx.body = convertAccount(data.data); ctx.body = convertAccount(data.data);
} catch (e: any) { } catch (e: any) {
@ -147,7 +147,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getAccountStatuses( const data = await client.getAccountStatuses(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
convertTimelinesArgsId(argsToBools(limitToInt(ctx.query as any))), convertTimelinesArgsId(argsToBools(limitToInt(ctx.query as any))),
); );
ctx.body = data.data.map((status) => convertStatus(status)); ctx.body = data.data.map((status) => convertStatus(status));
@ -166,7 +166,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getAccountFeaturedTags( const data = await client.getAccountFeaturedTags(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = data.data.map((tag) => convertFeaturedTag(tag)); ctx.body = data.data.map((tag) => convertFeaturedTag(tag));
} catch (e: any) { } catch (e: any) {
@ -184,7 +184,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getAccountFollowers( const data = await client.getAccountFollowers(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
convertTimelinesArgsId(limitToInt(ctx.query as any)), convertTimelinesArgsId(limitToInt(ctx.query as any)),
); );
ctx.body = data.data.map((account) => convertAccount(account)); ctx.body = data.data.map((account) => convertAccount(account));
@ -203,7 +203,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getAccountFollowing( const data = await client.getAccountFollowing(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
convertTimelinesArgsId(limitToInt(ctx.query as any)), convertTimelinesArgsId(limitToInt(ctx.query as any)),
); );
ctx.body = data.data.map((account) => convertAccount(account)); ctx.body = data.data.map((account) => convertAccount(account));
@ -222,7 +222,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getAccountLists( const data = await client.getAccountLists(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = data.data.map((list) => convertList(list)); ctx.body = data.data.map((list) => convertList(list));
} catch (e: any) { } catch (e: any) {
@ -239,9 +239,7 @@ export function apiAccountMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.followAccount( const data = await client.followAccount(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
let acct = convertRelationship(data.data); let acct = convertRelationship(data.data);
acct.following = true; acct.following = true;
ctx.body = acct; ctx.body = acct;
@ -260,7 +258,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.unfollowAccount( const data = await client.unfollowAccount(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
let acct = convertRelationship(data.data); let acct = convertRelationship(data.data);
acct.following = false; acct.following = false;
@ -279,9 +277,7 @@ export function apiAccountMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.blockAccount( const data = await client.blockAccount(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertRelationship(data.data); ctx.body = convertRelationship(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -297,9 +293,7 @@ export function apiAccountMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.unblockAccount( const data = await client.unblockAccount(toMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.MastodonId),
);
ctx.body = convertRelationship(data.data); ctx.body = convertRelationship(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -316,7 +310,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.muteAccount( const data = await client.muteAccount(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
(ctx.request as any).body as any, (ctx.request as any).body as any,
); );
ctx.body = convertRelationship(data.data); ctx.body = convertRelationship(data.data);
@ -334,9 +328,7 @@ export function apiAccountMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.unmuteAccount( const data = await client.unmuteAccount(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertRelationship(data.data); ctx.body = convertRelationship(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -454,7 +446,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.acceptFollowRequest( const data = await client.acceptFollowRequest(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = convertRelationship(data.data); ctx.body = convertRelationship(data.data);
} catch (e: any) { } catch (e: any) {
@ -472,7 +464,7 @@ export function apiAccountMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.rejectFollowRequest( const data = await client.rejectFollowRequest(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = convertRelationship(data.data); ctx.body = convertRelationship(data.data);
} catch (e: any) { } catch (e: any) {

View File

@ -27,9 +27,7 @@ export function apiFilterMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
const body: any = ctx.request.body; const body: any = ctx.request.body;
try { try {
const data = await client.getFilter( const data = await client.getFilter(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertFilter(data.data); ctx.body = convertFilter(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -60,7 +58,7 @@ export function apiFilterMastodon(router: Router): void {
const body: any = ctx.request.body; const body: any = ctx.request.body;
try { try {
const data = await client.updateFilter( const data = await client.updateFilter(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
body.phrase, body.phrase,
body.context, body.context,
); );
@ -78,9 +76,7 @@ export function apiFilterMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
const body: any = ctx.request.body; const body: any = ctx.request.body;
try { try {
const data = await client.deleteFilter( const data = await client.deleteFilter(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = data.data; ctx.body = data.data;
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));

View File

@ -1,5 +1,5 @@
import Router from "@koa/router"; import Router from "@koa/router";
import { convertId, IdType } from "@/server/api/index.js"; import { fromMastodonId } from "backend-rs";
import { getClient } from "../ApiMastodonCompatibleService.js"; import { getClient } from "../ApiMastodonCompatibleService.js";
import { convertTimelinesArgsId } from "./timeline.js"; import { convertTimelinesArgsId } from "./timeline.js";
import { convertNotification } from "../converters.js"; import { convertNotification } from "../converters.js";
@ -46,7 +46,7 @@ export function apiNotificationsMastodon(router: Router): void {
const body: any = ctx.request.body; const body: any = ctx.request.body;
try { try {
const dataRaw = await client.getNotification( const dataRaw = await client.getNotification(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
const data = convertNotification(dataRaw.data); const data = convertNotification(dataRaw.data);
ctx.body = data; ctx.body = data;
@ -86,7 +86,7 @@ export function apiNotificationsMastodon(router: Router): void {
const body: any = ctx.request.body; const body: any = ctx.request.body;
try { try {
const data = await client.dismissNotification( const data = await client.dismissNotification(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = data.data; ctx.body = data.data;
} catch (e: any) { } catch (e: any) {

View File

@ -4,7 +4,7 @@ import { emojiRegexAtStartToEnd } from "@/misc/emoji-regex.js";
import querystring from "node:querystring"; import querystring from "node:querystring";
import qs from "qs"; import qs from "qs";
import { convertTimelinesArgsId, limitToInt } from "./timeline.js"; import { convertTimelinesArgsId, limitToInt } from "./timeline.js";
import { convertId, IdType } from "@/server/api/index.js"; import { fromMastodonId } from "backend-rs";
import { import {
convertAccount, convertAccount,
convertAttachment, convertAttachment,
@ -28,9 +28,8 @@ export function apiStatusMastodon(router: Router): void {
try { try {
let body: any = ctx.request.body; let body: any = ctx.request.body;
if (body.in_reply_to_id) if (body.in_reply_to_id)
body.in_reply_to_id = convertId(body.in_reply_to_id, IdType.FirefishId); body.in_reply_to_id = fromMastodonId(body.in_reply_to_id);
if (body.quote_id) if (body.quote_id) body.quote_id = fromMastodonId(body.quote_id);
body.quote_id = convertId(body.quote_id, IdType.FirefishId);
if ( if (
(!body.poll && body["poll[options][]"]) || (!body.poll && body["poll[options][]"]) ||
(!body.media_ids && body["media_ids[]"]) (!body.media_ids && body["media_ids[]"])
@ -65,7 +64,7 @@ export function apiStatusMastodon(router: Router): void {
if (body.media_ids && !body.media_ids.length) body.media_ids = undefined; if (body.media_ids && !body.media_ids.length) body.media_ids = undefined;
if (body.media_ids) { if (body.media_ids) {
body.media_ids = (body.media_ids as string[]).map((p) => body.media_ids = (body.media_ids as string[]).map((p) =>
convertId(p, IdType.FirefishId), fromMastodonId(p),
); );
} }
const { sensitive } = body; const { sensitive } = body;
@ -103,9 +102,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getStatus( const data = await client.getStatus(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -118,9 +115,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.deleteStatus( const data = await client.deleteStatus(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = data.data; ctx.body = data.data;
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -141,7 +136,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const id = convertId(ctx.params.id, IdType.FirefishId); const id = fromMastodonId(ctx.params.id);
const data = await client.getStatusContext( const data = await client.getStatusContext(
id, id,
convertTimelinesArgsId(limitToInt(ctx.query as any)), convertTimelinesArgsId(limitToInt(ctx.query as any)),
@ -169,7 +164,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getStatusHistory( const data = await client.getStatusHistory(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = data.data.map((account) => convertAccount(account)); ctx.body = data.data.map((account) => convertAccount(account));
} catch (e: any) { } catch (e: any) {
@ -187,7 +182,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getStatusRebloggedBy( const data = await client.getStatusRebloggedBy(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = data.data.map((account) => convertAccount(account)); ctx.body = data.data.map((account) => convertAccount(account));
} catch (e: any) { } catch (e: any) {
@ -205,7 +200,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getStatusFavouritedBy( const data = await client.getStatusFavouritedBy(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = data.data.map((account) => convertAccount(account)); ctx.body = data.data.map((account) => convertAccount(account));
} catch (e: any) { } catch (e: any) {
@ -225,7 +220,7 @@ export function apiStatusMastodon(router: Router): void {
const react = meta.defaultReaction; const react = meta.defaultReaction;
try { try {
const a = (await client.createEmojiReaction( const a = (await client.createEmojiReaction(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
react, react,
)) as any; )) as any;
//const data = await client.favouriteStatus(ctx.params.id) as any; //const data = await client.favouriteStatus(ctx.params.id) as any;
@ -247,7 +242,7 @@ export function apiStatusMastodon(router: Router): void {
const react = meta.defaultReaction; const react = meta.defaultReaction;
try { try {
const data = await client.deleteEmojiReaction( const data = await client.deleteEmojiReaction(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
react, react,
); );
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
@ -266,9 +261,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.reblogStatus( const data = await client.reblogStatus(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -285,9 +278,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.unreblogStatus( const data = await client.unreblogStatus(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -304,9 +295,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.bookmarkStatus( const data = await client.bookmarkStatus(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -324,7 +313,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.unbookmarkStatus( const data = await client.unbookmarkStatus(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
); );
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
@ -342,9 +331,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.pinStatus( const data = await client.pinStatus(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -361,9 +348,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.unpinStatus( const data = await client.unpinStatus(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -381,7 +366,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.reactStatus( const data = await client.reactStatus(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
ctx.params.name, ctx.params.name,
); );
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
@ -401,7 +386,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.unreactStatus( const data = await client.unreactStatus(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
ctx.params.name, ctx.params.name,
); );
ctx.body = convertStatus(data.data); ctx.body = convertStatus(data.data);
@ -418,9 +403,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getMedia( const data = await client.getMedia(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertAttachment(data.data); ctx.body = convertAttachment(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -434,7 +417,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.updateMedia( const data = await client.updateMedia(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
ctx.request.body as any, ctx.request.body as any,
); );
ctx.body = convertAttachment(data.data); ctx.body = convertAttachment(data.data);
@ -449,9 +432,7 @@ export function apiStatusMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getPoll( const data = await client.getPoll(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertPoll(data.data); ctx.body = convertPoll(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -467,7 +448,7 @@ export function apiStatusMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.votePoll( const data = await client.votePoll(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
(ctx.request.body as any).choices, (ctx.request.body as any).choices,
); );
ctx.body = convertPoll(data.data); ctx.body = convertPoll(data.data);

View File

@ -7,7 +7,7 @@ import {
convertList, convertList,
convertStatus, convertStatus,
} from "../converters.js"; } from "../converters.js";
import { convertId, IdType } from "@/server/api/index.js"; import { fromMastodonId } from "backend-rs";
import { apiLogger } from "@/server/api/logger.js"; import { apiLogger } from "@/server/api/logger.js";
import { inspect } from "node:util"; import { inspect } from "node:util";
@ -47,12 +47,9 @@ export function argsToBools(q: ParsedUrlQuery) {
} }
export function convertTimelinesArgsId(q: ParsedUrlQuery) { export function convertTimelinesArgsId(q: ParsedUrlQuery) {
if (typeof q.min_id === "string") if (typeof q.min_id === "string") q.min_id = fromMastodonId(q.min_id);
q.min_id = convertId(q.min_id, IdType.FirefishId); if (typeof q.max_id === "string") q.max_id = fromMastodonId(q.max_id);
if (typeof q.max_id === "string") if (typeof q.since_id === "string") q.since_id = fromMastodonId(q.since_id);
q.max_id = convertId(q.max_id, IdType.FirefishId);
if (typeof q.since_id === "string")
q.since_id = convertId(q.since_id, IdType.FirefishId);
return q; return q;
} }
@ -120,7 +117,7 @@ export function apiTimelineMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getListTimeline( const data = await client.getListTimeline(
convertId(ctx.params.listId, IdType.FirefishId), fromMastodonId(ctx.params.listId),
convertTimelinesArgsId(limitToInt(ctx.query)), convertTimelinesArgsId(limitToInt(ctx.query)),
); );
ctx.body = data.data.map((status) => convertStatus(status)); ctx.body = data.data.map((status) => convertStatus(status));
@ -168,9 +165,7 @@ export function apiTimelineMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getList( const data = await client.getList(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = convertList(data.data); ctx.body = convertList(data.data);
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -200,7 +195,7 @@ export function apiTimelineMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.updateList( const data = await client.updateList(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
(ctx.request.body as any).title, (ctx.request.body as any).title,
); );
ctx.body = convertList(data.data); ctx.body = convertList(data.data);
@ -218,9 +213,7 @@ export function apiTimelineMastodon(router: Router): void {
const accessTokens = ctx.headers.authorization; const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.deleteList( const data = await client.deleteList(fromMastodonId(ctx.params.id));
convertId(ctx.params.id, IdType.FirefishId),
);
ctx.body = data.data; ctx.body = data.data;
} catch (e: any) { } catch (e: any) {
apiLogger.error(inspect(e)); apiLogger.error(inspect(e));
@ -237,7 +230,7 @@ export function apiTimelineMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.getAccountsInList( const data = await client.getAccountsInList(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
convertTimelinesArgsId(ctx.query as any), convertTimelinesArgsId(ctx.query as any),
); );
ctx.body = data.data.map((account) => convertAccount(account)); ctx.body = data.data.map((account) => convertAccount(account));
@ -256,10 +249,8 @@ export function apiTimelineMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.addAccountsToList( const data = await client.addAccountsToList(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
(ctx.query.account_ids as string[]).map((id) => (ctx.query.account_ids as string[]).map((id) => fromMastodonId(id)),
convertId(id, IdType.FirefishId),
),
); );
ctx.body = data.data; ctx.body = data.data;
} catch (e: any) { } catch (e: any) {
@ -277,10 +268,8 @@ export function apiTimelineMastodon(router: Router): void {
const client = getClient(BASE_URL, accessTokens); const client = getClient(BASE_URL, accessTokens);
try { try {
const data = await client.deleteAccountsFromList( const data = await client.deleteAccountsFromList(
convertId(ctx.params.id, IdType.FirefishId), fromMastodonId(ctx.params.id),
(ctx.query.account_ids as string[]).map((id) => (ctx.query.account_ids as string[]).map((id) => fromMastodonId(id)),
convertId(id, IdType.FirefishId),
),
); );
ctx.body = data.data; ctx.body = data.data;
} catch (e: any) { } catch (e: any) {