diff --git a/packages/backend/src/server/api/mastodon/endpoints/account.ts b/packages/backend/src/server/api/mastodon/endpoints/account.ts index d5dff331a..3d6e1a981 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/account.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/account.ts @@ -110,7 +110,7 @@ export function apiAccountMastodon(router: Router): void { const cache = UserHelpers.getFreshAccountCache(); const query = await UserHelpers.getUserCached(userId, cache); const args = normalizeUrlQuery(convertPaginationArgsIds(argsToBools(limitToInt(ctx.query)))); - const tl = await UserHelpers.getUserStatuses(query, user, args.max_id, args.since_id, args.min_id, args.limit, args.only_media, args.exclude_replies, args.exclude_reblogs, args.pinned, args.tagged) + const tl = await UserHelpers.getUserStatuses(query, user, args.max_id, args.since_id, args.min_id, args.limit, args['only_media'], args['exclude_replies'], args['exclude_reblogs'], args.pinned, args.tagged) .then(n => NoteConverter.encodeMany(n, user, cache)); ctx.body = tl.map(s => convertStatus(s)); diff --git a/packages/backend/src/server/api/mastodon/helpers/user.ts b/packages/backend/src/server/api/mastodon/helpers/user.ts index bc09d97fa..7634cc2cb 100644 --- a/packages/backend/src/server/api/mastodon/helpers/user.ts +++ b/packages/backend/src/server/api/mastodon/helpers/user.ts @@ -32,7 +32,7 @@ import { publishUserEvent } from "@/services/stream.js"; import { UserConverter } from "@/server/api/mastodon/converters/user.js"; import acceptFollowRequest from "@/services/following/requests/accept.js"; import { rejectFollowRequest } from "@/services/following/reject.js"; -import { IsNull } from "typeorm"; +import { Brackets, IsNull } from "typeorm"; import { VisibilityConverter } from "@/server/api/mastodon/converters/visibility.js"; import { UserProfile } from "@/models/entities/user-profile.js"; @@ -300,15 +300,28 @@ export class UserHelpers { ) .andWhere("note.userId = :userId", { userId: user.id }); - if (excludeReblogs) query.andWhere("(note.renoteId IS NOT NULL) OR (note.text IS NOT NULL)"); + if (excludeReblogs) { + query.andWhere( + new Brackets(qb => { + qb.where('note.renoteId IS NULL') + .orWhere('note.text IS NOT NULL'); + })); + } - query - .leftJoinAndSelect("note.renote", "renote"); + if (excludeReplies) { + query.leftJoin("note", "thread", "note.threadId = thread.id") + .andWhere( + new Brackets(qb => { + qb.where("note.replyId IS NULL") + .orWhere(new Brackets(qb => { + qb.where('note.mentions = :mentions', {mentions: []}) + .andWhere('thread.userId = :userId', {userId: user.id}) + })); + })); + } + + query.leftJoinAndSelect("note.renote", "renote"); - //this doesn't exclude replies to your own reply to someone else's post - //this also breaks when checking your own profile - //FIXME write new the replies query generator specific to the mastodon client api - generateRepliesQuery(query, !excludeReplies, localUser); generateVisibilityQuery(query, localUser); if (localUser) { generateMutedUserQuery(query, localUser, user); @@ -318,6 +331,7 @@ export class UserHelpers { if (onlyMedia) query.andWhere("note.fileIds != '{}'"); query.andWhere("note.visibility != 'hidden'"); + query.andWhere("note.visibility != 'specified'"); return PaginationHelpers.execQuery(query, limit, minId !== undefined); }