diff --git a/packages/backend/src/server/api/mastodon/endpoints/list.ts b/packages/backend/src/server/api/mastodon/endpoints/list.ts index 9455cea7b..1f90f6e42 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/list.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/list.ts @@ -1,5 +1,4 @@ import Router from "@koa/router"; -import { getClient } from "../index.js"; import { convertAccount, convertList, } from "../converters.js"; import { convertId, IdType } from "../../index.js"; import authenticate from "@/server/api/authenticate.js"; @@ -206,22 +205,37 @@ export function setupEndpointsList(router: Router): void { router.delete<{ Params: { id: string } }>( "/v1/lists/:id/accounts", async (ctx, reply) => { - const BASE_URL = `${ctx.protocol}://${ctx.hostname}`; - const accessTokens = ctx.headers.authorization; - const client = getClient(BASE_URL, accessTokens); try { - const data = await client.deleteAccountsFromList( - convertId(ctx.params.id, IdType.IceshrimpId), - (ctx.query.account_ids as string[]).map((id) => - convertId(id, IdType.IceshrimpId), - ), - ); - ctx.body = data.data; + const auth = await authenticate(ctx.headers.authorization, null); + const user = auth[0] ?? undefined; + + if (!user) { + ctx.status = 401; + return; + } + + const id = convertId(ctx.params.id, IdType.IceshrimpId); + const list = await UserLists.findOneBy({userId: user.id, id: id}); + + if (!list) { + ctx.status = 404; + return; + } + + const body = ctx.request.body as any; + if (!body['account_ids']) { + ctx.status = 400; + ctx.body = { error: "Missing account_ids[] field" }; + return; + } + + const ids = NoteHelpers.normalizeToArray(body['account_ids']).map(p => convertId(p, IdType.IceshrimpId)); + const targets = await Promise.all(ids.map(p => getUser(p))); + await ListHelpers.removeFromList(user, list, targets); + ctx.body = {} } catch (e: any) { - console.error(e); - console.error(e.response.data); - ctx.status = 401; - ctx.body = e.response.data; + ctx.status = 400; + ctx.body = { error: e.message }; } }, ); diff --git a/packages/backend/src/server/api/mastodon/helpers/list.ts b/packages/backend/src/server/api/mastodon/helpers/list.ts index 3cf34bb7c..c1bc8119a 100644 --- a/packages/backend/src/server/api/mastodon/helpers/list.ts +++ b/packages/backend/src/server/api/mastodon/helpers/list.ts @@ -1,10 +1,11 @@ import { ILocalUser, User } from "@/models/entities/user.js"; -import { Blockings, UserListJoinings, UserLists } from "@/models/index.js"; +import { Blockings, UserListJoinings, UserLists, Users } from "@/models/index.js"; import { LinkPaginationObject } from "@/server/api/mastodon/helpers/user.js"; import { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js"; import { UserList } from "@/models/entities/user-list.js"; import { pushUserToUserList } from "@/services/user-list/push.js"; import { genId } from "@/misc/gen-id.js"; +import { publishUserListStream } from "@/services/stream.js"; export class ListHelpers { public static async getLists(user: ILocalUser): Promise { @@ -81,6 +82,22 @@ export class ListHelpers { } } + public static async removeFromList(localUser: ILocalUser, list: UserList, usersToRemove: User[]) { + if (localUser.id != list.userId) throw new Error("List is not owned by user"); + for (const user of usersToRemove) { + const exist = await UserListJoinings.exist({ + where: { + userListId: list.id, + userId: user.id, + }, + }); + + if (!exist) continue; + await UserListJoinings.delete({ userListId: list.id, userId: user.id }); + publishUserListStream(list.id, "userRemoved", await Users.pack(user)); + } + } + public static async createList(user: ILocalUser, title: string): Promise { const list = await UserLists.insert({ id: genId(), diff --git a/packages/backend/src/server/api/mastodon/index.ts b/packages/backend/src/server/api/mastodon/index.ts index c172b83eb..d9911d24a 100644 --- a/packages/backend/src/server/api/mastodon/index.ts +++ b/packages/backend/src/server/api/mastodon/index.ts @@ -9,7 +9,7 @@ import { setupEndpointsNotifications } from "./endpoints/notifications.js"; import { setupEndpointsSearch } from "./endpoints/search.js"; import { setupEndpointsMedia } from "@/server/api/mastodon/endpoints/media.js"; import { setupEndpointsMisc } from "@/server/api/mastodon/endpoints/misc.js"; -import { koaBody } from "koa-body"; +import { HttpMethodEnum, koaBody } from "koa-body"; import multer from "@koa/multer"; import { setupEndpointsList } from "@/server/api/mastodon/endpoints/list.js"; @@ -29,6 +29,7 @@ export function setupMastodonApi(router: Router, fileRouter: Router, upload: mul koaBody({ multipart: true, urlencoded: true, + parsedMethods: [HttpMethodEnum.POST, HttpMethodEnum.PUT, HttpMethodEnum.PATCH, HttpMethodEnum.DELETE] // dear god mastodon why }), );