[mastodon-client] GET /mutes

This commit is contained in:
Laura Hausmann 2023-09-28 22:01:01 +02:00
parent f667f2f985
commit 82c96392c2
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
4 changed files with 61 additions and 12 deletions

View file

@ -8,7 +8,7 @@ function simpleConvert(data: any) {
return result;
}
export function convertAccount(account: Entity.Account) {
export function convertAccount(account: Entity.Account | MastodonEntity.MutedAccount) {
return simpleConvert(account);
}
export function convertAnnouncement(announcement: Entity.Announcement) {

View file

@ -344,6 +344,7 @@ export function apiAccountMastodon(router: Router): void {
return;
}
//FIXME: parse form data
const args = normalizeUrlQuery(argsToBools(limitToInt(ctx.query, ['duration']), ['notifications']));
const target = await UserHelpers.getUserCached(convertId(ctx.params.id, IdType.IceshrimpId));
const result = await UserHelpers.muteUser(target, user, args.notifications, args.duration);
@ -456,14 +457,20 @@ export function apiAccountMastodon(router: Router): void {
}
});
router.get("/v1/mutes", async (ctx) => {
const BASE_URL = `${ctx.protocol}://${ctx.hostname}`;
const accessTokens = ctx.headers.authorization;
const client = getClient(BASE_URL, accessTokens);
try {
const data = await client.getMutes(
convertTimelinesArgsId(limitToInt(ctx.query as any)),
);
ctx.body = data.data.map((account) => convertAccount(account));
const auth = await authenticate(ctx.headers.authorization, null);
const user = auth[0] ?? null;
if (!user) {
ctx.status = 401;
return;
}
const cache = UserHelpers.getFreshAccountCache();
const args = normalizeUrlQuery(convertTimelinesArgsId(limitToInt(ctx.query as any)));
const res = await UserHelpers.getUserMutes(user, args.max_id, args.since_id, args.min_id, args.limit, cache);
ctx.body = res.data.map(m => convertAccount(m));
PaginationHelpers.appendLinkPaginationHeader(args, ctx, res);
} catch (e: any) {
console.error(e);
console.error(e.response.data);

View file

@ -24,4 +24,8 @@ namespace MastodonEntity {
bot: boolean | null;
source?: Source;
};
export type MutedAccount = Account | {
mute_expires_at: string | null;
}
}

View file

@ -3,19 +3,19 @@ import { ILocalUser, User } from "@/models/entities/user.js";
import {
Blockings,
Followings,
FollowRequests, Mutings,
FollowRequests,
Mutings,
NoteFavorites,
NoteReactions,
Notes, NoteWatchings,
Notes,
NoteWatchings,
UserProfiles,
Users
} from "@/models/index.js";
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
import { generateRepliesQuery } from "@/server/api/common/generate-replies-query.js";
import { generateVisibilityQuery } from "@/server/api/common/generate-visibility-query.js";
import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-query.js";
import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js";
import { NoteHelpers } from "@/server/api/mastodon/helpers/note.js";
import Entity from "megalodon/src/entity.js";
import AsyncLock from "async-lock";
import { getUser } from "@/server/api/common/getters.js";
@ -29,6 +29,8 @@ import deleteBlocking from "@/services/blocking/delete.js";
import { genId } from "@/misc/gen-id.js";
import { Muting } from "@/models/entities/muting.js";
import { publishUserEvent } from "@/services/stream.js";
import { UserConverter } from "@/server/api/mastodon/converters/user.js";
import { convertId, IdType } from "@/misc/convert-id.js";
export type AccountCache = {
locks: AsyncLock;
@ -118,6 +120,42 @@ export class UserHelpers {
return this.getUserRelationshipTo(target.id, localUser.id);
}
public static async getUserMutes(user: ILocalUser, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 40, cache: AccountCache = UserHelpers.getFreshAccountCache()): Promise<LinkPaginationObject<MastodonEntity.MutedAccount[]>> {
if (limit > 80) limit = 80;
const query = PaginationHelpers.makePaginationQuery(
Mutings.createQueryBuilder("muting"),
sinceId,
maxId,
minId
);
query.andWhere("muting.muterId = :userId", {userId: user.id})
.innerJoinAndSelect("muting.mutee", "mutee");
return query.take(limit).getMany().then(async p => {
if (minId !== undefined) p = p.reverse();
const users = p
.map(p => p.mutee)
.filter(p => p) as User[];
const result = await UserConverter.encodeMany(users, cache)
.then(res => res.map(m => {
const muting = p.find(acc => acc.muteeId === m.id);
return {
...m,
mute_expires_at: muting?.expiresAt?.toISOString() ?? null
} as MastodonEntity.MutedAccount
}));
return {
data: result,
maxId: p.map(p => p.id).at(-1),
minId: p.map(p => p.id)[0],
};
});
}
public static async getUserStatuses(user: User, localUser: ILocalUser | null, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 20, onlyMedia: boolean = false, excludeReplies: boolean = false, excludeReblogs: boolean = false, pinned: boolean = false, tagged: string | undefined): Promise<Note[]> {
if (limit > 40) limit = 40;