From 9d24f8aea5cb1825ac3e64cb1593b01d02e5b18c Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Sat, 7 Oct 2023 22:16:17 +0200 Subject: [PATCH] [mastodon-client] Remove ID conversion BREAKING: Please log out and log back in of any clients in use, as their cache is now invalid --- packages/backend/src/misc/convert-id.ts | 27 ---- packages/backend/src/server/api/index.ts | 4 - .../src/server/api/mastodon/converters.ts | 117 --------------- .../server/api/mastodon/endpoints/account.ts | 120 ++++++--------- .../src/server/api/mastodon/endpoints/auth.ts | 3 +- .../src/server/api/mastodon/endpoints/list.ts | 44 ++---- .../server/api/mastodon/endpoints/media.ts | 17 +-- .../src/server/api/mastodon/endpoints/misc.ts | 14 +- .../api/mastodon/endpoints/notifications.ts | 19 +-- .../server/api/mastodon/endpoints/search.ts | 11 +- .../server/api/mastodon/endpoints/status.ts | 140 ++++++------------ .../server/api/mastodon/endpoints/timeline.ts | 45 ++---- .../src/server/api/mastodon/helpers/misc.ts | 4 +- .../src/server/api/mastodon/helpers/note.ts | 5 +- .../api/mastodon/middleware/pagination.ts | 5 +- 15 files changed, 139 insertions(+), 436 deletions(-) delete mode 100644 packages/backend/src/misc/convert-id.ts delete mode 100644 packages/backend/src/server/api/mastodon/converters.ts diff --git a/packages/backend/src/misc/convert-id.ts b/packages/backend/src/misc/convert-id.ts deleted file mode 100644 index c82a9b86a..000000000 --- a/packages/backend/src/misc/convert-id.ts +++ /dev/null @@ -1,27 +0,0 @@ -export enum IdType { - IceshrimpId, - MastodonId -} - -const chars = '0123456789abcdefghijklmnopqrstuvwxyz'; - -//FIXME: This implementation breaks for IceshrimpIDs with leading zeroes -//FIXME: Make this idempotent -export function convertId(id: string, target: IdType): string { - if (target == IdType.IceshrimpId) { - return BigInt(id).toString(36); - } - else if (target == IdType.MastodonId) { - let result = 0n; - const iter = id.toLowerCase(); - - for (let i = 0; i < iter.length; i++){ - const char = iter[i]; - if (!chars.includes(char)) throw new Error('Invalid ID'); - result = result * 36n + BigInt(chars.indexOf(char)); - } - - return result.toString(); - } - throw new Error('Unknown ID type'); -} diff --git a/packages/backend/src/server/api/index.ts b/packages/backend/src/server/api/index.ts index 976191599..e3535ae39 100644 --- a/packages/backend/src/server/api/index.ts +++ b/packages/backend/src/server/api/index.ts @@ -20,10 +20,6 @@ import verifyEmail from "./private/verify-email.js"; import discord from "./service/discord.js"; import github from "./service/github.js"; import twitter from "./service/twitter.js"; -import { convertId, IdType } from "@/misc/convert-id.js"; - -// re-export native rust id conversion (function and enum) -export { IdType, convertId }; // Init app const app = new Koa(); diff --git a/packages/backend/src/server/api/mastodon/converters.ts b/packages/backend/src/server/api/mastodon/converters.ts deleted file mode 100644 index 0f4e7fab1..000000000 --- a/packages/backend/src/server/api/mastodon/converters.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { convertId, IdType } from "../index.js"; - -// It's *very* important to put `param = structuredClone(param)` at the top of each function that doesn't simply call simpleConvertId on the param object directly. - -function simpleConvertId(data: any) { - // copy the object to bypass weird pass by reference bugs - data = structuredClone(data); - data.id = convertId(data.id, IdType.MastodonId); - return data; -} - -export function convertAccountId(account: MastodonEntity.Account | MastodonEntity.MutedAccount) { - return simpleConvertId(account); -} - -export function convertAnnouncementId(announcement: MastodonEntity.Announcement) { - return simpleConvertId(announcement); -} - -export function convertAttachmentId(attachment: MastodonEntity.Attachment) { - return simpleConvertId(attachment); -} - -export function convertListId(list: MastodonEntity.List) { - return simpleConvertId(list); -} - -export function convertPollId(poll: MastodonEntity.Poll) { - return simpleConvertId(poll); -} - -export function convertRelationshipId(relationship: MastodonEntity.Relationship) { - return simpleConvertId(relationship); -} - -export function convertStatusSourceId(statusSource: MastodonEntity.StatusSource) { - return simpleConvertId(statusSource); -} - -export function convertSuggestionIds(suggestion: MastodonEntity.SuggestedAccount) { - suggestion = structuredClone(suggestion); - suggestion.account = convertAccountId(suggestion.account) - return suggestion -} - -export function convertNotificationIds(notification: MastodonEntity.Notification) { - notification = structuredClone(notification); - notification.account = convertAccountId(notification.account); - notification.id = convertId(notification.id, IdType.MastodonId); - if (notification.status) - notification.status = convertStatusIds(notification.status); - if (notification.reaction) - notification.reaction = convertReactionIds(notification.reaction); - return notification; -} - -export function convertReactionIds(reaction: MastodonEntity.Reaction) { - reaction = structuredClone(reaction); - if (reaction.accounts) { - reaction.accounts = reaction.accounts.map(convertAccountId); - } - return reaction; -} - -export function convertSearchIds(search: MastodonEntity.Search) { - search = structuredClone(search); - search.accounts = search.accounts.map(p => convertAccountId(p)); - search.statuses = search.statuses.map(p => convertStatusIds(p)); - return search; -} - -export function convertStatusIds(status: MastodonEntity.Status) { - status = structuredClone(status); - status.account = convertAccountId(status.account); - status.id = convertId(status.id, IdType.MastodonId); - if (status.in_reply_to_account_id) - status.in_reply_to_account_id = convertId( - status.in_reply_to_account_id, - IdType.MastodonId, - ); - if (status.in_reply_to_id) - status.in_reply_to_id = convertId(status.in_reply_to_id, IdType.MastodonId); - status.media_attachments = status.media_attachments.map((attachment) => - convertAttachmentId(attachment), - ); - status.mentions = status.mentions.map((mention) => ({ - ...mention, - id: convertId(mention.id, IdType.MastodonId), - })); - if (status.poll) status.poll = convertPollId(status.poll); - if (status.reblog) status.reblog = convertStatusIds(status.reblog); - if (status.quote) status.quote = convertStatusIds(status.quote); - status.reactions = status.reactions.map(convertReactionIds); - - return status; -} - -export function convertStatusEditIds(edit: MastodonEntity.StatusEdit) { - edit = structuredClone(edit); - edit.account = convertAccountId(edit.account); - edit.media_attachments = edit.media_attachments.map((attachment) => - convertAttachmentId(attachment), - ); - if (edit.poll) edit.poll = convertPollId(edit.poll); - return edit; -} - -export function convertConversationIds(conversation: MastodonEntity.Conversation) { - conversation = structuredClone(conversation); - conversation.id = convertId(conversation.id, IdType.MastodonId); - conversation.accounts = conversation.accounts.map(convertAccountId); - if (conversation.last_status) { - conversation.last_status = convertStatusIds(conversation.last_status); - } - - return conversation; -} diff --git a/packages/backend/src/server/api/mastodon/endpoints/account.ts b/packages/backend/src/server/api/mastodon/endpoints/account.ts index afb54e710..dc111bfc6 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/account.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/account.ts @@ -1,7 +1,5 @@ import Router from "@koa/router"; -import { argsToBools, convertPaginationArgsIds, limitToInt, normalizeUrlQuery } from "./timeline.js"; -import { convertId, IdType } from "../../index.js"; -import { convertAccountId, convertListId, convertRelationshipId, convertStatusIds, } from "../converters.js"; +import { argsToBools, limitToInt, normalizeUrlQuery } from "./timeline.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js"; import { NoteConverter } from "@/server/api/mastodon/converters/note.js"; import { UserHelpers } from "@/server/api/mastodon/helpers/user.js"; @@ -12,53 +10,43 @@ export function setupEndpointsAccount(router: Router): void { router.get("/v1/accounts/verify_credentials", auth(true, ['read:accounts']), async (ctx) => { - const acct = await UserHelpers.verifyCredentials(ctx); - ctx.body = convertAccountId(acct); + ctx.body = await UserHelpers.verifyCredentials(ctx); } ); router.patch("/v1/accounts/update_credentials", auth(true, ['write:accounts']), async (ctx) => { - const acct = await UserHelpers.updateCredentials(ctx); - ctx.body = convertAccountId(acct) + ctx.body = await UserHelpers.updateCredentials(ctx) } ); router.get("/v1/accounts/lookup", async (ctx) => { const args = normalizeUrlQuery(ctx.query); const user = await UserHelpers.getUserFromAcct(args.acct); - const account = await UserConverter.encode(user, ctx); - ctx.body = convertAccountId(account); + ctx.body = await UserConverter.encode(user, ctx); } ); router.get("/v1/accounts/relationships", auth(true, ['read:follows']), async (ctx) => { - const ids = (normalizeUrlQuery(ctx.query, ['id[]'])['id[]'] ?? []) - .map((id: string) => convertId(id, IdType.IceshrimpId)); - const result = await UserHelpers.getUserRelationhipToMany(ids, ctx.user.id); - ctx.body = result.map(rel => convertRelationshipId(rel)); + const ids = (normalizeUrlQuery(ctx.query, ['id[]'])['id[]'] ?? []); + ctx.body = await UserHelpers.getUserRelationhipToMany(ids, ctx.user.id); } ); router.get<{ Params: { id: string } }>("/v1/accounts/:id", auth(false), async (ctx) => { - const userId = convertId(ctx.params.id, IdType.IceshrimpId); - const account = await UserConverter.encode(await UserHelpers.getUserOr404(userId), ctx); - ctx.body = convertAccountId(account); + ctx.body = await UserConverter.encode(await UserHelpers.getUserOr404(ctx.params.id), ctx); } ); router.get<{ Params: { id: string } }>( "/v1/accounts/:id/statuses", auth(false, ["read:statuses"]), async (ctx) => { - const userId = convertId(ctx.params.id, IdType.IceshrimpId); - const query = await UserHelpers.getUserCachedOr404(userId, ctx); - const args = normalizeUrlQuery(convertPaginationArgsIds(argsToBools(limitToInt(ctx.query)))); + const query = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + const args = normalizeUrlQuery(argsToBools(limitToInt(ctx.query))); const res = await UserHelpers.getUserStatuses(query, args.max_id, args.since_id, args.min_id, args.limit, args['only_media'], args['exclude_replies'], args['exclude_reblogs'], args.pinned, args.tagged, ctx); - const tl = await NoteConverter.encodeMany(res, ctx); - - ctx.body = tl.map(s => convertStatusIds(s)); + ctx.body = await NoteConverter.encodeMany(res, ctx); }, ); router.get<{ Params: { id: string } }>( @@ -71,72 +59,61 @@ export function setupEndpointsAccount(router: Router): void { "/v1/accounts/:id/followers", auth(false), async (ctx) => { - const userId = convertId(ctx.params.id, IdType.IceshrimpId); - const query = await UserHelpers.getUserCachedOr404(userId, ctx); - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const query = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await UserHelpers.getUserFollowers(query, args.max_id, args.since_id, args.min_id, args.limit, ctx); - const followers = await UserConverter.encodeMany(res, ctx); - - ctx.body = followers.map((account) => convertAccountId(account)); + ctx.body = await UserConverter.encodeMany(res, ctx); }, ); router.get<{ Params: { id: string } }>( "/v1/accounts/:id/following", auth(false), async (ctx) => { - const userId = convertId(ctx.params.id, IdType.IceshrimpId); - const query = await UserHelpers.getUserCachedOr404(userId, ctx); - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const query = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await UserHelpers.getUserFollowing(query, args.max_id, args.since_id, args.min_id, args.limit, ctx); - const following = await UserConverter.encodeMany(res, ctx); - - ctx.body = following.map((account) => convertAccountId(account)); + ctx.body = await UserConverter.encodeMany(res, ctx); }, ); router.get<{ Params: { id: string } }>( "/v1/accounts/:id/lists", auth(true, ["read:lists"]), async (ctx) => { - const member = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const results = await ListHelpers.getListsByMember(member, ctx); - ctx.body = results.map(p => convertListId(p)); + const member = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await ListHelpers.getListsByMember(member, ctx); }, ); router.post<{ Params: { id: string } }>( "/v1/accounts/:id/follow", auth(true, ["write:follows"]), async (ctx) => { - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); //FIXME: Parse form data - const result = await UserHelpers.followUser(target, true, false, ctx); - ctx.body = convertRelationshipId(result); + ctx.body = await UserHelpers.followUser(target, true, false, ctx); }, ); router.post<{ Params: { id: string } }>( "/v1/accounts/:id/unfollow", auth(true, ["write:follows"]), async (ctx) => { - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const result = await UserHelpers.unfollowUser(target, ctx); - ctx.body = convertRelationshipId(result); + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await UserHelpers.unfollowUser(target, ctx); }, ); router.post<{ Params: { id: string } }>( "/v1/accounts/:id/block", auth(true, ["write:blocks"]), async (ctx) => { - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const result = await UserHelpers.blockUser(target, ctx); - ctx.body = convertRelationshipId(result); + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await UserHelpers.blockUser(target, ctx); }, ); router.post<{ Params: { id: string } }>( "/v1/accounts/:id/unblock", auth(true, ["write:blocks"]), async (ctx) => { - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const result = await UserHelpers.unblockUser(target, ctx); - ctx.body = convertRelationshipId(result) + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await UserHelpers.unblockUser(target, ctx); }, ); router.post<{ Params: { id: string } }>( @@ -145,18 +122,16 @@ export function setupEndpointsAccount(router: Router): void { async (ctx) => { //FIXME: parse form data const args = normalizeUrlQuery(argsToBools(limitToInt(ctx.query, ['duration']), ['notifications'])); - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const result = await UserHelpers.muteUser(target, args.notifications, args.duration, ctx); - ctx.body = convertRelationshipId(result) + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await UserHelpers.muteUser(target, args.notifications, args.duration, ctx); }, ); router.post<{ Params: { id: string } }>( "/v1/accounts/:id/unmute", auth(true, ["write:mutes"]), async (ctx) => { - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const result = await UserHelpers.unmuteUser(target, ctx); - ctx.body = convertRelationshipId(result) + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await UserHelpers.unmuteUser(target, ctx); }, ); router.get("/v1/featured_tags", @@ -172,63 +147,56 @@ export function setupEndpointsAccount(router: Router): void { router.get("/v1/bookmarks", auth(true, ["read:bookmarks"]), async (ctx) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await UserHelpers.getUserBookmarks(args.max_id, args.since_id, args.min_id, args.limit, ctx); - const bookmarks = await NoteConverter.encodeMany(res, ctx); - ctx.body = bookmarks.map(s => convertStatusIds(s)); + ctx.body = await NoteConverter.encodeMany(res, ctx); } ); router.get("/v1/favourites", auth(true, ["read:favourites"]), async (ctx) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await UserHelpers.getUserFavorites(args.max_id, args.since_id, args.min_id, args.limit, ctx); - const favorites = await NoteConverter.encodeMany(res, ctx); - ctx.body = favorites.map(s => convertStatusIds(s)); + ctx.body = await NoteConverter.encodeMany(res, ctx); } ); router.get("/v1/mutes", auth(true, ["read:mutes"]), async (ctx) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); - const res = await UserHelpers.getUserMutes(args.max_id, args.since_id, args.min_id, args.limit, ctx); - ctx.body = res.map(m => convertAccountId(m)); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); + ctx.body = await UserHelpers.getUserMutes(args.max_id, args.since_id, args.min_id, args.limit, ctx); } ); router.get("/v1/blocks", auth(true, ["read:blocks"]), async (ctx) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await UserHelpers.getUserBlocks(args.max_id, args.since_id, args.min_id, args.limit, ctx); - const blocks = await UserConverter.encodeMany(res, ctx); - ctx.body = blocks.map(b => convertAccountId(b)); + ctx.body = await UserConverter.encodeMany(res, ctx); } ); router.get("/v1/follow_requests", auth(true, ["read:follows"]), async (ctx) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await UserHelpers.getUserFollowRequests(args.max_id, args.since_id, args.min_id, args.limit, ctx); - const requests = await UserConverter.encodeMany(res, ctx); - ctx.body = requests.map(b => convertAccountId(b)); + ctx.body = await UserConverter.encodeMany(res, ctx); } ); router.post<{ Params: { id: string } }>( "/v1/follow_requests/:id/authorize", auth(true, ["write:follows"]), async (ctx) => { - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const result = await UserHelpers.acceptFollowRequest(target, ctx); - ctx.body = convertRelationshipId(result); + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await UserHelpers.acceptFollowRequest(target, ctx); }, ); router.post<{ Params: { id: string } }>( "/v1/follow_requests/:id/reject", auth(true, ["write:follows"]), async (ctx) => { - const target = await UserHelpers.getUserCachedOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - const result = await UserHelpers.rejectFollowRequest(target, ctx); - ctx.body = convertRelationshipId(result); + const target = await UserHelpers.getUserCachedOr404(ctx.params.id, ctx); + ctx.body = await UserHelpers.rejectFollowRequest(target, ctx); }, ); } diff --git a/packages/backend/src/server/api/mastodon/endpoints/auth.ts b/packages/backend/src/server/api/mastodon/endpoints/auth.ts index 98e2ad9e8..c0ab5dab5 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/auth.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/auth.ts @@ -1,6 +1,5 @@ import Router from "@koa/router"; import { AuthHelpers } from "@/server/api/mastodon/helpers/auth.js"; -import { convertId, IdType } from "@/misc/convert-id.js"; import { AuthConverter } from "@/server/api/mastodon/converters/auth.js"; import { v4 as uuid } from "uuid"; import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js"; @@ -15,7 +14,7 @@ export function setupEndpointsAuth(router: Router): void { const red = body.redirect_uris; const appData = await AuthHelpers.registerApp(body['client_name'], scopeArr, red, body['website']); ctx.body = { - id: convertId(appData.id, IdType.MastodonId), + id: appData.id, name: appData.name, website: body.website, redirect_uri: red, diff --git a/packages/backend/src/server/api/mastodon/endpoints/list.ts b/packages/backend/src/server/api/mastodon/endpoints/list.ts index 516aa822e..1d7fb15d1 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/list.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/list.ts @@ -1,7 +1,5 @@ import Router from "@koa/router"; -import { convertAccountId, convertListId, } from "../converters.js"; -import { convertId, IdType } from "../../index.js"; -import { convertPaginationArgsIds, limitToInt, normalizeUrlQuery } from "@/server/api/mastodon/endpoints/timeline.js"; +import { limitToInt, normalizeUrlQuery } from "@/server/api/mastodon/endpoints/timeline.js"; import { ListHelpers } from "@/server/api/mastodon/helpers/list.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js"; import { UserLists } from "@/models/index.js"; @@ -14,18 +12,14 @@ export function setupEndpointsList(router: Router): void { router.get("/v1/lists", auth(true, ['read:lists']), async (ctx, reply) => { - ctx.body = await ListHelpers.getLists(ctx) - .then(p => p.map(list => convertListId(list))); + ctx.body = await ListHelpers.getLists(ctx); } ); router.get<{ Params: { id: string } }>( "/v1/lists/:id", auth(true, ['read:lists']), async (ctx, reply) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - - ctx.body = await ListHelpers.getListOr404(id, ctx) - .then(p => convertListId(p)); + ctx.body = await ListHelpers.getListOr404(ctx.params.id, ctx); }, ); router.post("/v1/lists", @@ -33,31 +27,26 @@ export function setupEndpointsList(router: Router): void { async (ctx, reply) => { const body = ctx.request.body as any; const title = (body.title ?? '').trim(); - - ctx.body = await ListHelpers.createList(title, ctx) - .then(p => convertListId(p)); + ctx.body = await ListHelpers.createList(title, ctx); } ); router.put<{ Params: { id: string } }>( "/v1/lists/:id", auth(true, ['write:lists']), async (ctx, reply) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const list = await UserLists.findOneBy({ userId: ctx.user.id, id: id }); + const list = await UserLists.findOneBy({ userId: ctx.user.id, id: ctx.params.id }); if (!list) throw new MastoApiError(404); const body = ctx.request.body as any; const title = (body.title ?? '').trim(); - ctx.body = await ListHelpers.updateList(list, title, ctx) - .then(p => convertListId(p)); + ctx.body = await ListHelpers.updateList(list, title, ctx); }, ); router.delete<{ Params: { id: string } }>( "/v1/lists/:id", auth(true, ['write:lists']), async (ctx, reply) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const list = await UserLists.findOneBy({ userId: ctx.user.id, id: id }); + const list = await UserLists.findOneBy({ userId: ctx.user.id, id: ctx.params.id }); if (!list) throw new MastoApiError(404); await ListHelpers.deleteList(list, ctx); @@ -68,26 +57,22 @@ export function setupEndpointsList(router: Router): void { "/v1/lists/:id/accounts", auth(true, ['read:lists']), async (ctx, reply) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query))); - const res = await ListHelpers.getListUsers(id, args.max_id, args.since_id, args.min_id, args.limit, ctx); - const accounts = await UserConverter.encodeMany(res, ctx); - - ctx.body = accounts.map(account => convertAccountId(account)); + const args = normalizeUrlQuery(limitToInt(ctx.query)); + const res = await ListHelpers.getListUsers(ctx.params.id, args.max_id, args.since_id, args.min_id, args.limit, ctx); + ctx.body = await UserConverter.encodeMany(res, ctx); }, ); router.post<{ Params: { id: string } }>( "/v1/lists/:id/accounts", auth(true, ['write:lists']), async (ctx, reply) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const list = await UserLists.findOneBy({ userId: ctx.user.id, id: id }); + const list = await UserLists.findOneBy({ userId: ctx.user.id, id: ctx.params.id }); if (!list) throw new MastoApiError(404); const body = ctx.request.body as any; if (!body['account_ids']) throw new MastoApiError(400, "Missing account_ids[] field"); - const ids = toArray(body['account_ids']).map(p => convertId(p, IdType.IceshrimpId)); + const ids = toArray(body['account_ids']); const targets = await Promise.all(ids.map(p => getUser(p))); await ListHelpers.addToList(list, targets, ctx); ctx.body = {} @@ -97,14 +82,13 @@ export function setupEndpointsList(router: Router): void { "/v1/lists/:id/accounts", auth(true, ['write:lists']), async (ctx, reply) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const list = await UserLists.findOneBy({ userId: ctx.user.id, id: id }); + const list = await UserLists.findOneBy({ userId: ctx.user.id, id: ctx.params.id }); if (!list) throw new MastoApiError(404); const body = ctx.request.body as any; if (!body['account_ids']) throw new MastoApiError(400, "Missing account_ids[] field"); - const ids = toArray(body['account_ids']).map(p => convertId(p, IdType.IceshrimpId)); + const ids = toArray(body['account_ids']); const targets = await Promise.all(ids.map(p => getUser(p))); await ListHelpers.removeFromList(list, targets, ctx); ctx.body = {} diff --git a/packages/backend/src/server/api/mastodon/endpoints/media.ts b/packages/backend/src/server/api/mastodon/endpoints/media.ts index a37869788..b47da0bfb 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/media.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/media.ts @@ -1,6 +1,4 @@ import Router from "@koa/router"; -import { convertId, IdType } from "@/misc/convert-id.js"; -import { convertAttachmentId } from "@/server/api/mastodon/converters.js"; import { MediaHelpers } from "@/server/api/mastodon/helpers/media.js"; import { FileConverter } from "@/server/api/mastodon/converters/file.js"; import { auth } from "@/server/api/mastodon/middleware/auth.js"; @@ -9,28 +7,23 @@ export function setupEndpointsMedia(router: Router): void { router.get<{ Params: { id: string } }>("/v1/media/:id", auth(true, ['write:media']), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const file = await MediaHelpers.getMediaPackedOr404(id, ctx); - const attachment = FileConverter.encode(file); - ctx.body = convertAttachmentId(attachment); + const file = await MediaHelpers.getMediaPackedOr404(ctx.params.id, ctx); + ctx.body = FileConverter.encode(file); } ); router.put<{ Params: { id: string } }>("/v1/media/:id", auth(true, ['write:media']), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const file = await MediaHelpers.getMediaOr404(id, ctx); - const result = await MediaHelpers.updateMedia(file, ctx) + const file = await MediaHelpers.getMediaOr404(ctx.params.id, ctx); + ctx.body = await MediaHelpers.updateMedia(file, ctx) .then(p => FileConverter.encode(p)); - ctx.body = convertAttachmentId(result); } ); router.post(["/v2/media", "/v1/media"], auth(true, ['write:media']), async (ctx) => { - const result = await MediaHelpers.uploadMedia(ctx) + ctx.body = await MediaHelpers.uploadMedia(ctx) .then(p => FileConverter.encode(p)); - ctx.body = convertAttachmentId(result); } ); } diff --git a/packages/backend/src/server/api/mastodon/endpoints/misc.ts b/packages/backend/src/server/api/mastodon/endpoints/misc.ts index 0077ab2fa..d141b8f65 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/misc.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/misc.ts @@ -2,8 +2,6 @@ import Router from "@koa/router"; import { MiscHelpers } from "@/server/api/mastodon/helpers/misc.js"; import { argsToBools, limitToInt } from "@/server/api/mastodon/endpoints/timeline.js"; import { Announcements } from "@/models/index.js"; -import { convertAnnouncementId, convertStatusIds, convertSuggestionIds } from "@/server/api/mastodon/converters.js"; -import { convertId, IdType } from "@/misc/convert-id.js"; import { auth } from "@/server/api/mastodon/middleware/auth.js"; import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js"; @@ -24,8 +22,7 @@ export function setupEndpointsMisc(router: Router): void { auth(true), async (ctx) => { const args = argsToBools(ctx.query, ['with_dismissed']); - ctx.body = await MiscHelpers.getAnnouncements(args['with_dismissed'], ctx) - .then(p => p.map(x => convertAnnouncementId(x))); + ctx.body = await MiscHelpers.getAnnouncements(args['with_dismissed'], ctx); } ); @@ -33,8 +30,7 @@ export function setupEndpointsMisc(router: Router): void { "/v1/announcements/:id/dismiss", auth(true, ['write:accounts']), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const announcement = await Announcements.findOneBy({ id: id }); + const announcement = await Announcements.findOneBy({ id: ctx.params.id }); if (!announcement) throw new MastoApiError(404); await MiscHelpers.dismissAnnouncement(announcement, ctx); @@ -54,8 +50,7 @@ export function setupEndpointsMisc(router: Router): void { router.get("/v1/trends/statuses", async (ctx) => { const args = limitToInt(ctx.query); - ctx.body = await MiscHelpers.getTrendingStatuses(args.limit, args.offset, ctx) - .then(p => p.map(x => convertStatusIds(x))); + ctx.body = await MiscHelpers.getTrendingStatuses(args.limit, args.offset, ctx); } ); @@ -76,8 +71,7 @@ export function setupEndpointsMisc(router: Router): void { auth(true, ['read']), async (ctx) => { const args = limitToInt(ctx.query); - ctx.body = await MiscHelpers.getFollowSuggestions(args.limit, ctx) - .then(p => p.map(x => convertSuggestionIds(x))); + ctx.body = await MiscHelpers.getFollowSuggestions(args.limit, ctx); } ); } diff --git a/packages/backend/src/server/api/mastodon/endpoints/notifications.ts b/packages/backend/src/server/api/mastodon/endpoints/notifications.ts index 78959236e..21aa3b95f 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/notifications.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/notifications.ts @@ -1,7 +1,5 @@ import Router from "@koa/router"; -import { convertId, IdType } from "../../index.js"; -import { convertPaginationArgsIds, limitToInt, normalizeUrlQuery } from "./timeline.js"; -import { convertNotificationIds } from "../converters.js"; +import { limitToInt, normalizeUrlQuery } from "./timeline.js"; import { NotificationHelpers } from "@/server/api/mastodon/helpers/notification.js"; import { NotificationConverter } from "@/server/api/mastodon/converters/notification.js"; import { auth } from "@/server/api/mastodon/middleware/auth.js"; @@ -10,19 +8,17 @@ export function setupEndpointsNotifications(router: Router): void { router.get("/v1/notifications", auth(true, ['read:notifications']), async (ctx) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query)), ['types[]', 'exclude_types[]']); + const args = normalizeUrlQuery(limitToInt(ctx.query), ['types[]', 'exclude_types[]']); const res = await NotificationHelpers.getNotifications(args.max_id, args.since_id, args.min_id, args.limit, args['types[]'], args['exclude_types[]'], args.account_id, ctx); - const data = await NotificationConverter.encodeMany(res, ctx); - - ctx.body = data.map(n => convertNotificationIds(n)); + ctx.body = await NotificationConverter.encodeMany(res, ctx); } ); router.get("/v1/notifications/:id", auth(true, ['read:notifications']), async (ctx) => { - const notification = await NotificationHelpers.getNotificationOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); - ctx.body = convertNotificationIds(await NotificationConverter.encode(notification, ctx)); + const notification = await NotificationHelpers.getNotificationOr404(ctx.params.id, ctx); + ctx.body = await NotificationConverter.encode(notification, ctx); } ); @@ -37,7 +33,7 @@ export function setupEndpointsNotifications(router: Router): void { router.post("/v1/notifications/:id/dismiss", auth(true, ['write:notifications']), async (ctx) => { - const notification = await NotificationHelpers.getNotificationOr404(convertId(ctx.params.id, IdType.IceshrimpId), ctx); + const notification = await NotificationHelpers.getNotificationOr404(ctx.params.id, ctx); await NotificationHelpers.dismissNotification(notification.id, ctx); ctx.body = {}; } @@ -46,8 +42,7 @@ export function setupEndpointsNotifications(router: Router): void { router.post("/v1/conversations/:id/read", auth(true, ['write:conversations']), async (ctx, reply) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - await NotificationHelpers.markConversationAsRead(id, ctx); + await NotificationHelpers.markConversationAsRead(ctx.params.id, ctx); ctx.body = {}; } ); diff --git a/packages/backend/src/server/api/mastodon/endpoints/search.ts b/packages/backend/src/server/api/mastodon/endpoints/search.ts index c5f3f5905..6dc080334 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/search.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/search.ts @@ -1,6 +1,5 @@ import Router from "@koa/router"; -import { argsToBools, convertPaginationArgsIds, limitToInt, normalizeUrlQuery } from "./timeline.js"; -import { convertSearchIds } from "../converters.js"; +import { argsToBools, limitToInt, normalizeUrlQuery } from "./timeline.js"; import { SearchHelpers } from "@/server/api/mastodon/helpers/search.js"; import { auth } from "@/server/api/mastodon/middleware/auth.js"; @@ -8,15 +7,13 @@ export function setupEndpointsSearch(router: Router): void { router.get(["/v1/search", "/v2/search"], auth(true, ['read:search']), async (ctx) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(argsToBools(limitToInt(ctx.query), ['resolve', 'following', 'exclude_unreviewed']))); - const result = await SearchHelpers.search(args.q, args.type, args.resolve, args.following, args.account_id, args['exclude_unreviewed'], args.max_id, args.min_id, args.limit, args.offset, ctx); - - ctx.body = convertSearchIds(result); + const args = normalizeUrlQuery(argsToBools(limitToInt(ctx.query), ['resolve', 'following', 'exclude_unreviewed'])); + ctx.body = await SearchHelpers.search(args.q, args.type, args.resolve, args.following, args.account_id, args['exclude_unreviewed'], args.max_id, args.min_id, args.limit, args.offset, ctx); if (ctx.path === "/v1/search") { ctx.body = { ...ctx.body, - hashtags: result.hashtags.map(p => p.name), + hashtags: ctx.body.hashtags.map((p: MastodonEntity.Tag) => p.name), }; } } diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index 0acc46e15..b0adf55b6 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -1,15 +1,7 @@ import Router from "@koa/router"; -import { convertId, IdType } from "../../index.js"; -import { - convertAccountId, - convertPollId, - convertStatusEditIds, - convertStatusIds, - convertStatusSourceId, -} from "../converters.js"; import { NoteConverter } from "@/server/api/mastodon/converters/note.js"; import { NoteHelpers } from "@/server/api/mastodon/helpers/note.js"; -import { convertPaginationArgsIds, limitToInt, normalizeUrlQuery } from "@/server/api/mastodon/endpoints/timeline.js"; +import { limitToInt, normalizeUrlQuery } from "@/server/api/mastodon/endpoints/timeline.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js"; import { PollHelpers } from "@/server/api/mastodon/helpers/poll.js"; import { toArray } from "@/prelude/array.js"; @@ -32,8 +24,7 @@ export function setupEndpointsStatus(router: Router): void { let request = NoteHelpers.normalizeComposeOptions(ctx.request.body); ctx.body = await NoteHelpers.createNote(request, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); if (key !== null) NoteHelpers.postIdempotencyCache.set(key, { status: ctx.body }); } @@ -41,31 +32,25 @@ export function setupEndpointsStatus(router: Router): void { router.put("/v1/statuses/:id", auth(true, ['write:statuses']), async (ctx) => { - const noteId = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(noteId, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); let request = NoteHelpers.normalizeEditOptions(ctx.request.body); ctx.body = await NoteHelpers.editNote(request, note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); } ); router.get<{ Params: { id: string } }>("/v1/statuses/:id", auth(false, ["read:statuses"]), async (ctx) => { - const noteId = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(noteId, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); - const status = await NoteConverter.encode(note, ctx); - ctx.body = convertStatusIds(status); + ctx.body = await NoteConverter.encode(note, ctx); } ); router.delete<{ Params: { id: string } }>("/v1/statuses/:id", auth(true, ['write:statuses']), async (ctx) => { - const noteId = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(noteId, ctx); - ctx.body = await NoteHelpers.deleteNote(note, ctx) - .then(p => convertStatusIds(p)); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); + ctx.body = await NoteHelpers.deleteNote(note, ctx); } ); @@ -74,14 +59,11 @@ export function setupEndpointsStatus(router: Router): void { auth(false, ["read:statuses"]), async (ctx) => { //FIXME: determine final limits within helper functions instead of here - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); const ancestors = await NoteHelpers.getNoteAncestors(note, ctx.user ? 4096 : 60, ctx) - .then(n => NoteConverter.encodeMany(n, ctx)) - .then(n => n.map(s => convertStatusIds(s))); + .then(n => NoteConverter.encodeMany(n, ctx)); const descendants = await NoteHelpers.getNoteDescendants(note, ctx.user ? 4096 : 40, ctx.user ? 4096 : 20, ctx) - .then(n => NoteConverter.encodeMany(n, ctx)) - .then(n => n.map(s => convertStatusIds(s))); + .then(n => NoteConverter.encodeMany(n, ctx)); ctx.body = { ancestors, @@ -93,69 +75,57 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/history", auth(false, ["read:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); - const res = await NoteHelpers.getNoteEditHistory(note, ctx); - ctx.body = res.map(p => convertStatusEditIds(p)); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); + ctx.body = await NoteHelpers.getNoteEditHistory(note, ctx); } ); router.get<{ Params: { id: string } }>( "/v1/statuses/:id/source", auth(true, ["read:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); - const src = NoteHelpers.getNoteSource(note); - ctx.body = convertStatusSourceId(src); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); + ctx.body = NoteHelpers.getNoteSource(note); } ); router.get<{ Params: { id: string } }>( "/v1/statuses/:id/reblogged_by", auth(false, ["read:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await NoteHelpers.getNoteRebloggedBy(note, args.max_id, args.since_id, args.min_id, args.limit, ctx); - const users = await UserConverter.encodeMany(res, ctx); - ctx.body = users.map(m => convertAccountId(m)); + ctx.body = await UserConverter.encodeMany(res, ctx); } ); router.get<{ Params: { id: string } }>( "/v1/statuses/:id/favourited_by", auth(false, ["read:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query as any))); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); + const args = normalizeUrlQuery(limitToInt(ctx.query as any)); const res = await NoteHelpers.getNoteFavoritedBy(note, args.max_id, args.since_id, args.min_id, args.limit, ctx); - const users = await UserConverter.encodeMany(res, ctx); - ctx.body = users.map(m => convertAccountId(m)); + ctx.body = await UserConverter.encodeMany(res, ctx); } ); router.post<{ Params: { id: string } }>( "/v1/statuses/:id/favourite", auth(true, ["write:favourites"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); const reaction = await NoteHelpers.getDefaultReaction(); ctx.body = await NoteHelpers.reactToNote(note, reaction, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); } ); router.post<{ Params: { id: string } }>( "/v1/statuses/:id/unfavourite", auth(true, ["write:favourites"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.removeReactFromNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -163,12 +133,10 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/reblog", auth(true, ["write:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.reblogNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -176,12 +144,10 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/unreblog", auth(true, ["write:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.unreblogNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -189,12 +155,10 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/bookmark", auth(true, ["write:bookmarks"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.bookmarkNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -202,12 +166,10 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/unbookmark", auth(true, ["write:bookmarks"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.unbookmarkNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -215,12 +177,10 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/pin", auth(true, ["write:accounts"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.pinNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -228,12 +188,10 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/unpin", auth(true, ["write:accounts"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.unpinNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -241,12 +199,10 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/react/:name", auth(true, ["write:favourites"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.id, ctx); ctx.body = await NoteHelpers.reactToNote(note, ctx.params.name, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); @@ -254,35 +210,29 @@ export function setupEndpointsStatus(router: Router): void { "/v1/statuses/:id/unreact/:name", auth(true, ["write:favourites"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.name, ctx); ctx.body = await NoteHelpers.removeReactFromNote(note, ctx) - .then(p => NoteConverter.encode(p, ctx)) - .then(p => convertStatusIds(p)); + .then(p => NoteConverter.encode(p, ctx)); }, ); router.get<{ Params: { id: string } }>("/v1/polls/:id", auth(false, ["read:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); - const data = await PollHelpers.getPoll(note, ctx); - ctx.body = convertPollId(data); + const note = await NoteHelpers.getNoteOr404(ctx.params.name, ctx); + ctx.body = await PollHelpers.getPoll(note, ctx); }); router.post<{ Params: { id: string } }>( "/v1/polls/:id/votes", auth(true, ["write:statuses"]), async (ctx) => { - const id = convertId(ctx.params.id, IdType.IceshrimpId); - const note = await NoteHelpers.getNoteOr404(id, ctx); + const note = await NoteHelpers.getNoteOr404(ctx.params.name, ctx); const body: any = ctx.request.body; const choices = toArray(body.choices ?? []).map(p => parseInt(p)); if (choices.length < 1) throw new MastoApiError(400, "Must vote for at least one option"); - const data = await PollHelpers.voteInPoll(choices, note, ctx); - ctx.body = convertPollId(data); + ctx.body = await PollHelpers.voteInPoll(choices, note, ctx); }, ); } diff --git a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts index 3395bcf5a..dc93c8b58 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts @@ -1,7 +1,5 @@ import Router from "@koa/router"; import { ParsedUrlQuery } from "querystring"; -import { convertConversationIds, convertStatusIds, } from "../converters.js"; -import { convertId, IdType } from "../../index.js"; import { TimelineHelpers } from "@/server/api/mastodon/helpers/timeline.js"; import { NoteConverter } from "@/server/api/mastodon/converters/note.js"; import { UserLists } from "@/models/index.js"; @@ -39,16 +37,6 @@ export function argsToBools(q: ParsedUrlQuery, additional: string[] = []) { return object; } -export function convertPaginationArgsIds(q: ParsedUrlQuery) { - if (typeof q.min_id === "string") - q.min_id = convertId(q.min_id, IdType.IceshrimpId); - if (typeof q.max_id === "string") - q.max_id = convertId(q.max_id, IdType.IceshrimpId); - if (typeof q.since_id === "string") - q.since_id = convertId(q.since_id, IdType.IceshrimpId); - return q; -} - export function normalizeUrlQuery(q: ParsedUrlQuery, arrayKeys: string[] = []): any { const dict: any = {}; @@ -66,55 +54,44 @@ export function setupEndpointsTimeline(router: Router): void { router.get("/v1/timelines/public", auth(true, ['read:statuses']), async (ctx, reply) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(argsToBools(limitToInt(ctx.query)))); + const args = normalizeUrlQuery(argsToBools(limitToInt(ctx.query))); const res = await TimelineHelpers.getPublicTimeline(args.max_id, args.since_id, args.min_id, args.limit, args.only_media, args.local, args.remote, ctx); - const tl = await NoteConverter.encodeMany(res, ctx); - - ctx.body = tl.map(s => convertStatusIds(s)); + ctx.body = await NoteConverter.encodeMany(res, ctx); }); router.get<{ Params: { hashtag: string } }>( "/v1/timelines/tag/:hashtag", auth(false, ['read:statuses']), async (ctx, reply) => { const tag = (ctx.params.hashtag ?? '').trim(); - const args = normalizeUrlQuery(convertPaginationArgsIds(argsToBools(limitToInt(ctx.query))), ['any[]', 'all[]', 'none[]']); + const args = normalizeUrlQuery(argsToBools(limitToInt(ctx.query)), ['any[]', 'all[]', 'none[]']); const res = await TimelineHelpers.getTagTimeline(tag, args.max_id, args.since_id, args.min_id, args.limit, args['any[]'] ?? [], args['all[]'] ?? [], args['none[]'] ?? [], args.only_media, args.local, args.remote, ctx); - const tl = await NoteConverter.encodeMany(res, ctx); - - ctx.body = tl.map(s => convertStatusIds(s)); + ctx.body = await NoteConverter.encodeMany(res, ctx); }, ); router.get("/v1/timelines/home", auth(true, ['read:statuses']), async (ctx, reply) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query))); + const args = normalizeUrlQuery(limitToInt(ctx.query)); const res = await TimelineHelpers.getHomeTimeline(args.max_id, args.since_id, args.min_id, args.limit, ctx); - const tl = await NoteConverter.encodeMany(res, ctx); - - ctx.body = tl.map(s => convertStatusIds(s)); + ctx.body = await NoteConverter.encodeMany(res, ctx); }); router.get<{ Params: { listId: string } }>( "/v1/timelines/list/:listId", auth(true, ['read:lists']), async (ctx, reply) => { - const listId = convertId(ctx.params.listId, IdType.IceshrimpId); - const list = await UserLists.findOneBy({ userId: ctx.user.id, id: listId }); + const list = await UserLists.findOneBy({ userId: ctx.user.id, id: ctx.params.listId }); if (!list) throw new MastoApiError(404); - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query))); + const args = normalizeUrlQuery(limitToInt(ctx.query)); const res = await TimelineHelpers.getListTimeline(list, args.max_id, args.since_id, args.min_id, args.limit, ctx); - const tl = await NoteConverter.encodeMany(res, ctx); - - ctx.body = tl.map(s => convertStatusIds(s)); + ctx.body = await NoteConverter.encodeMany(res, ctx); }, ); router.get("/v1/conversations", auth(true, ['read:statuses']), async (ctx, reply) => { - const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query))); - const res = await TimelineHelpers.getConversations(args.max_id, args.since_id, args.min_id, args.limit, ctx); - - ctx.body = res.map(c => convertConversationIds(c)); + const args = normalizeUrlQuery(limitToInt(ctx.query)); + ctx.body = await TimelineHelpers.getConversations(args.max_id, args.since_id, args.min_id, args.limit, ctx); } ); } diff --git a/packages/backend/src/server/api/mastodon/helpers/misc.ts b/packages/backend/src/server/api/mastodon/helpers/misc.ts index 39a620ce8..5ff385c8f 100644 --- a/packages/backend/src/server/api/mastodon/helpers/misc.ts +++ b/packages/backend/src/server/api/mastodon/helpers/misc.ts @@ -5,7 +5,6 @@ import { AnnouncementReads, Announcements, Emojis, Instances, Notes, UserProfile import { IsNull } from "typeorm"; import { awaitAll } from "@/prelude/await-all.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js"; -import { convertAccountId } from "@/server/api/mastodon/converters.js"; import { Announcement } from "@/models/entities/announcement.js"; import { ILocalUser, User } from "@/models/entities/user.js"; import { AnnouncementConverter } from "@/server/api/mastodon/converters/announcement.js"; @@ -35,8 +34,7 @@ export class MiscHelpers { }, order: { id: "ASC" }, }) - .then(p => p ? UserConverter.encode(p, ctx) : null) - .then(p => p ? convertAccountId(p) : null); + .then(p => p ? UserConverter.encode(p, ctx) : null); const meta = await fetchMeta(true); const res = { diff --git a/packages/backend/src/server/api/mastodon/helpers/note.ts b/packages/backend/src/server/api/mastodon/helpers/note.ts index a035bda35..cf33c866f 100644 --- a/packages/backend/src/server/api/mastodon/helpers/note.ts +++ b/packages/backend/src/server/api/mastodon/helpers/note.ts @@ -18,7 +18,6 @@ import { UserHelpers } from "@/server/api/mastodon/helpers/user.js"; import { generatePaginationData } from "@/server/api/mastodon/middleware/pagination.js" import { addPinned, removePinned } from "@/services/i/pin.js"; import { NoteConverter } from "@/server/api/mastodon/converters/note.js"; -import { convertId, IdType } from "@/misc/convert-id.js"; import { awaitAll } from "@/prelude/await-all.js"; import { VisibilityConverter } from "@/server/api/mastodon/converters/visibility.js"; import mfm from "mfm-js"; @@ -360,11 +359,10 @@ export class NoteHelpers { if (body.scheduled_at != null) result.scheduled_at = new Date(Date.parse(body.scheduled_at)); if (body.in_reply_to_id) - result.in_reply_to_id = convertId(body.in_reply_to_id, IdType.IceshrimpId); + result.in_reply_to_id = body.in_reply_to_id; if (body.media_ids) result.media_ids = body.media_ids && body.media_ids.length > 0 ? toArray(body.media_ids) - .map(p => convertId(p, IdType.IceshrimpId)) : undefined; if (body.poll) { @@ -392,7 +390,6 @@ export class NoteHelpers { if (body.media_ids) result.media_ids = body.media_ids && body.media_ids.length > 0 ? toArray(body.media_ids) - .map(p => convertId(p, IdType.IceshrimpId)) : undefined; if (body.poll) { diff --git a/packages/backend/src/server/api/mastodon/middleware/pagination.ts b/packages/backend/src/server/api/mastodon/middleware/pagination.ts index 988b71015..25c44476b 100644 --- a/packages/backend/src/server/api/mastodon/middleware/pagination.ts +++ b/packages/backend/src/server/api/mastodon/middleware/pagination.ts @@ -1,6 +1,5 @@ import { MastoContext } from "@/server/api/mastodon/index.js"; import config from "@/config/index.js"; -import { convertId, IdType } from "@/misc/convert-id.js"; type PaginationData = { limit: number; @@ -15,11 +14,11 @@ export async function PaginationMiddleware(ctx: MastoContext, next: () => Promis const link: string[] = []; const limit = ctx.pagination.limit; if (ctx.pagination.maxId) { - const l = `<${config.url}/api${ctx.path}?limit=${limit}&max_id=${convertId(ctx.pagination.maxId, IdType.MastodonId)}>; rel="next"`; + const l = `<${config.url}/api${ctx.path}?limit=${limit}&max_id=${ctx.pagination.maxId}>; rel="next"`; link.push(l); } if (ctx.pagination.minId) { - const l = `<${config.url}/api${ctx.path}?limit=${limit}&min_id=${convertId(ctx.pagination.maxId, IdType.MastodonId)}>; rel="prev"`; + const l = `<${config.url}/api${ctx.path}?limit=${limit}&min_id=${ctx.pagination.maxId}>; rel="prev"`; link.push(l); } if (link.length > 0) {