diff --git a/packages/backend/src/server/api/mastodon/converters/note.ts b/packages/backend/src/server/api/mastodon/converters/note.ts index ef8af2dbc..9b0ad43c6 100644 --- a/packages/backend/src/server/api/mastodon/converters/note.ts +++ b/packages/backend/src/server/api/mastodon/converters/note.ts @@ -38,7 +38,7 @@ export class NoteConverter { host, )); - const reactionCount = NoteReactions.countBy({noteId: note.id}); + const reactionCount = NoteReactions.countBy({ noteId: note.id }); const reaction = user ? NoteReactions.findOneBy({ userId: user.id, @@ -87,7 +87,7 @@ export class NoteConverter { }); const isPinned = user && note.userId === user.id - ? UserNotePinings.exist({where: {userId: user.id, noteId: note.id}}) + ? UserNotePinings.exist({ where: { userId: user.id, noteId: note.id } }) : undefined; const tags = note.tags.map(tag => { diff --git a/packages/backend/src/server/api/mastodon/converters/user.ts b/packages/backend/src/server/api/mastodon/converters/user.ts index b4f0372d9..4e951f6cd 100644 --- a/packages/backend/src/server/api/mastodon/converters/user.ts +++ b/packages/backend/src/server/api/mastodon/converters/user.ts @@ -27,14 +27,14 @@ export class UserConverter { acct = `${u.username}@${u.host}`; acctUrl = `https://${u.host}/@${u.username}`; } - const profile = UserProfiles.findOneBy({userId: u.id}); + const profile = UserProfiles.findOneBy({ userId: u.id }); const bio = profile.then(profile => MfmHelpers.toHtml(mfm.parse(profile?.description ?? "")) ?? escapeMFM(profile?.description ?? "")); const avatar = u.avatarId - ? (DriveFiles.findOneBy({id: u.avatarId})) + ? (DriveFiles.findOneBy({ id: u.avatarId })) .then(p => p?.url ?? Users.getIdenticonUrl(u.id)) : Users.getIdenticonUrl(u.id); const banner = u.bannerId - ? (DriveFiles.findOneBy({id: u.bannerId})) + ? (DriveFiles.findOneBy({ id: u.bannerId })) .then(p => p?.url ?? `${config.url}/static-assets/transparent.png`) : `${config.url}/static-assets/transparent.png`; const followersCount = profile.then(profile => { diff --git a/packages/backend/src/server/api/mastodon/endpoints/filter.ts b/packages/backend/src/server/api/mastodon/endpoints/filter.ts index a2bc5401f..069d0044e 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/filter.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/filter.ts @@ -11,7 +11,7 @@ export function setupEndpointsFilter(router: Router): void { router.post(["/v1/filters", "/v2/filters"], auth(true, ['write:filters']), async (ctx) => { - ctx.status = 400; + ctx.status = 400; ctx.body = { error: "Please change word mute settings in the web frontend settings." }; } ); diff --git a/packages/backend/src/server/api/mastodon/endpoints/list.ts b/packages/backend/src/server/api/mastodon/endpoints/list.ts index fa1e05dea..b08ce9ade 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/list.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/list.ts @@ -44,7 +44,7 @@ export function setupEndpointsList(router: Router): void { 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: id }); if (!list) throw new MastoApiError(404); const body = ctx.request.body as any; @@ -58,7 +58,7 @@ export function setupEndpointsList(router: Router): void { 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: id }); if (!list) throw new MastoApiError(404); await ListHelpers.deleteList(ctx.user, list); @@ -83,7 +83,7 @@ export function setupEndpointsList(router: Router): void { 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: id }); if (!list) throw new MastoApiError(404); const body = ctx.request.body as any; @@ -100,7 +100,7 @@ export function setupEndpointsList(router: Router): void { 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: id }); if (!list) throw new MastoApiError(404); const body = ctx.request.body as any; diff --git a/packages/backend/src/server/api/mastodon/endpoints/misc.ts b/packages/backend/src/server/api/mastodon/endpoints/misc.ts index 8b205d752..1c59f97a8 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/misc.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/misc.ts @@ -34,7 +34,7 @@ export function setupEndpointsMisc(router: Router): void { 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: id }); if (!announcement) throw new MastoApiError(404); await MiscHelpers.dismissAnnouncement(announcement, ctx.user); diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index b0ab32886..18a93bf05 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -1,6 +1,12 @@ import Router from "@koa/router"; import { convertId, IdType } from "../../index.js"; -import { convertAccountId, convertPollId, convertStatusIds, convertStatusEditIds, convertStatusSourceId, } from "../converters.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"; @@ -29,7 +35,7 @@ export function setupEndpointsStatus(router: Router): void { .then(p => NoteConverter.encode(p, ctx.user)) .then(p => convertStatusIds(p)); - if (key !== null) NoteHelpers.postIdempotencyCache.set(key, {status: ctx.body}); + if (key !== null) NoteHelpers.postIdempotencyCache.set(key, { status: ctx.body }); } ); router.put("/v1/statuses/:id", @@ -264,7 +270,7 @@ export function setupEndpointsStatus(router: Router): void { const note = await NoteHelpers.getNoteOr404(id, ctx.user); const data = await PollHelpers.getPoll(note, ctx.user); ctx.body = convertPollId(data); - }); + }); router.post<{ Params: { id: string } }>( "/v1/polls/:id/votes", auth(true, ["write:statuses"]), @@ -276,7 +282,7 @@ export function setupEndpointsStatus(router: Router): void { const choices = toArray(body.choices ?? []).map(p => parseInt(p)); if (choices.length < 1) { ctx.status = 400; - ctx.body = {error: 'Must vote for at least one option'}; + ctx.body = { error: 'Must vote for at least one option' }; return; } diff --git a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts index 35e934cb6..e7fe23597 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts @@ -74,7 +74,7 @@ export function setupEndpointsTimeline(router: Router): void { .then(n => NoteConverter.encodeMany(n, ctx.user, cache)); ctx.body = tl.map(s => convertStatusIds(s)); - }); + }); router.get<{ Params: { hashtag: string } }>( "/v1/timelines/tag/:hashtag", auth(false, ['read:statuses']), @@ -97,13 +97,13 @@ export function setupEndpointsTimeline(router: Router): void { .then(n => NoteConverter.encodeMany(n, ctx.user, cache)); ctx.body = tl.map(s => convertStatusIds(s)); - }); + }); 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: listId }); if (!list) throw new MastoApiError(404); const args = normalizeUrlQuery(convertPaginationArgsIds(limitToInt(ctx.query))); diff --git a/packages/backend/src/server/api/mastodon/helpers/list.ts b/packages/backend/src/server/api/mastodon/helpers/list.ts index 4949c3f7c..191e25244 100644 --- a/packages/backend/src/server/api/mastodon/helpers/list.ts +++ b/packages/backend/src/server/api/mastodon/helpers/list.ts @@ -10,7 +10,7 @@ import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js" export class ListHelpers { public static async getLists(user: ILocalUser): Promise { - return UserLists.findBy({userId: user.id}).then(p => p.map(list => { + return UserLists.findBy({ userId: user.id }).then(p => p.map(list => { return { id: list.id, title: list.name @@ -19,7 +19,7 @@ export class ListHelpers { } public static async getList(user: ILocalUser, id: string): Promise { - return UserLists.findOneByOrFail({userId: user.id, id: id}).then(list => { + return UserLists.findOneByOrFail({ userId: user.id, id: id }).then(list => { return { id: list.id, title: list.name @@ -32,9 +32,10 @@ export class ListHelpers { throw new MastoApiError(404); }) } + public static async getListUsers(user: ILocalUser, id: string, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 40): Promise> { if (limit > 80) limit = 80; - const list = await UserLists.findOneBy({userId: user.id, id: id}); + const list = await UserLists.findOneBy({ userId: user.id, id: id }); if (!list) throw new MastoApiError(404); const query = PaginationHelpers.makePaginationQuery( UserListJoinings.createQueryBuilder('member'), @@ -42,7 +43,7 @@ export class ListHelpers { maxId, minId ) - .andWhere("member.userListId = :listId", {listId: list.id}) + .andWhere("member.userListId = :listId", { listId: list.id }) .innerJoinAndSelect("member.user", "user"); return query.take(limit).getMany().then(async p => { @@ -125,9 +126,9 @@ export class ListHelpers { if (title.length < 1) throw new MastoApiError(400, "Title must not be empty"); if (user.id != list.userId) throw new Error("List is not owned by user"); - const partial = {name: title}; + const partial = { name: title }; const result = await UserLists.update(list.id, partial) - .then(async _ => await UserLists.findOneByOrFail({id: list.id})); + .then(async _ => await UserLists.findOneByOrFail({ id: list.id })); return { id: result.id, @@ -140,9 +141,9 @@ export class ListHelpers { .select("member.userListId") .where("member.userId = :memberId"); const query = UserLists.createQueryBuilder('list') - .where("list.userId = :userId", {userId: user.id}) + .where("list.userId = :userId", { userId: user.id }) .andWhere(`list.id IN (${joinQuery.getQuery()})`) - .setParameters({memberId: member.id}); + .setParameters({ memberId: member.id }); return query.getMany() .then(results => results.map(result => { diff --git a/packages/backend/src/server/api/mastodon/helpers/media.ts b/packages/backend/src/server/api/mastodon/helpers/media.ts index 345447ca7..b20b4ee38 100644 --- a/packages/backend/src/server/api/mastodon/helpers/media.ts +++ b/packages/backend/src/server/api/mastodon/helpers/media.ts @@ -34,7 +34,7 @@ export class MediaHelpers { comment: body?.description ?? undefined }); - return DriveFiles.findOneByOrFail({id: file.id, userId: user.id}) + return DriveFiles.findOneByOrFail({ id: file.id, userId: user.id }) .then(p => DriveFiles.pack(p)); } @@ -51,13 +51,13 @@ export class MediaHelpers { } public static async getMedia(user: ILocalUser, id: string): Promise { - return DriveFiles.findOneBy({id: id, userId: user.id}); + return DriveFiles.findOneBy({ id: id, userId: user.id }); } public static async getMediaOr404(user: ILocalUser, id: string): Promise { return this.getMedia(user, id).then(p => { - if (p) return p; - throw new MastoApiError(404); + if (p) return p; + throw new MastoApiError(404); }); } } diff --git a/packages/backend/src/server/api/mastodon/helpers/mfm.ts b/packages/backend/src/server/api/mastodon/helpers/mfm.ts index c18a7f1ae..298762534 100644 --- a/packages/backend/src/server/api/mastodon/helpers/mfm.ts +++ b/packages/backend/src/server/api/mastodon/helpers/mfm.ts @@ -13,7 +13,7 @@ export class MfmHelpers { return null; } - const {window} = new JSDOM(""); + const { window } = new JSDOM(""); const doc = window.document; @@ -122,7 +122,7 @@ export class MfmHelpers { mention(node) { const a = doc.createElement("a"); - const {username, host, acct} = node.props; + const { username, host, acct } = node.props; const remoteUserInfo = mentionedRemoteUsers.find( (remoteUser) => remoteUser.username === username && remoteUser.host === host, diff --git a/packages/backend/src/server/api/mastodon/helpers/misc.ts b/packages/backend/src/server/api/mastodon/helpers/misc.ts index 8ddf11b1f..ca5910c35 100644 --- a/packages/backend/src/server/api/mastodon/helpers/misc.ts +++ b/packages/backend/src/server/api/mastodon/helpers/misc.ts @@ -7,11 +7,10 @@ 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 } from "@/models/entities/user.js"; +import { ILocalUser, User } from "@/models/entities/user.js"; import { AnnouncementConverter } from "@/server/api/mastodon/converters/announcement.js"; import { genId } from "@/misc/gen-id.js"; import * as Acct from "@/misc/acct.js"; -import { User } from "@/models/entities/user.js"; import { UserHelpers } from "@/server/api/mastodon/helpers/user.js"; import { generateMutedUserQueryForUsers } from "@/server/api/common/generate-muted-user-query.js"; import { generateBlockQueryForUsers } from "@/server/api/common/generate-block-query.js"; @@ -23,8 +22,8 @@ import { VisibilityConverter } from "@/server/api/mastodon/converters/visibility export class MiscHelpers { public static async getInstance(): Promise { - const userCount = Users.count({where: {host: IsNull()}}); - const noteCount = Notes.count({where: {userHost: IsNull()}}); + const userCount = Users.count({ where: { host: IsNull() } }); + const noteCount = Notes.count({ where: { userHost: IsNull() } }); const instanceCount = Instances.count({ cache: 3600000 }); const contact = await Users.findOne({ where: { @@ -33,7 +32,7 @@ export class MiscHelpers { isDeleted: false, isSuspended: false, }, - order: {id: "ASC"}, + order: { id: "ASC" }, }) .then(p => p ? UserConverter.encode(p) : null) .then(p => p ? convertAccountId(p) : null); @@ -100,9 +99,9 @@ export class MiscHelpers { if (includeRead) { const [announcements, reads] = await Promise.all([ Announcements.createQueryBuilder("announcement") - .orderBy({"announcement.id": "DESC"}) + .orderBy({ "announcement.id": "DESC" }) .getMany(), - AnnouncementReads.findBy({userId: user.id}) + AnnouncementReads.findBy({ userId: user.id }) .then(p => p.map(x => x.announcementId)) ]); @@ -115,7 +114,7 @@ export class MiscHelpers { const query = Announcements.createQueryBuilder("announcement") .where(`announcement.id NOT IN (${sq.getQuery()})`) - .orderBy({"announcement.id": "DESC"}) + .orderBy({ "announcement.id": "DESC" }) .setParameter("userId", user.id); return query.getMany() @@ -123,7 +122,7 @@ export class MiscHelpers { } public static async dismissAnnouncement(announcement: Announcement, user: ILocalUser): Promise { - const exists = await AnnouncementReads.exist({where: {userId: user.id, announcementId: announcement.id}}); + const exists = await AnnouncementReads.exist({ where: { userId: user.id, announcementId: announcement.id } }); if (!exists) { await AnnouncementReads.insert({ id: genId(), @@ -139,19 +138,19 @@ export class MiscHelpers { const results: Promise[] = []; const pinned = fetchMeta().then(meta => Promise.all( - meta.pinnedUsers - .map((acct) => Acct.parse(acct)) - .map((acct) => - Users.findOneBy({ - usernameLower: acct.username.toLowerCase(), - host: acct.host ?? IsNull(), - })) + meta.pinnedUsers + .map((acct) => Acct.parse(acct)) + .map((acct) => + Users.findOneBy({ + usernameLower: acct.username.toLowerCase(), + host: acct.host ?? IsNull(), + })) ) - .then(p => p.filter(x => !!x) as User[]) - .then(p => UserConverter.encodeMany(p, cache)) - .then(p => p.map(x => { - return {source: "staff", account: x} as MastodonEntity.SuggestedAccount - })) + .then(p => p.filter(x => !!x) as User[]) + .then(p => UserConverter.encodeMany(p, cache)) + .then(p => p.map(x => { + return { source: "staff", account: x } as MastodonEntity.SuggestedAccount + })) ); const query = Users.createQueryBuilder("user") @@ -170,7 +169,7 @@ export class MiscHelpers { .getMany() .then(p => UserConverter.encodeMany(p, cache)) .then(p => p.map(x => { - return {source: "global", account: x} as MastodonEntity.SuggestedAccount + return { source: "global", account: x } as MastodonEntity.SuggestedAccount })); results.push(pinned); @@ -182,17 +181,18 @@ export class MiscHelpers { public static async getCustomEmoji() { return Emojis.find({ - where: { - host: IsNull(), - }, - order: { - category: "ASC", - name: "ASC", - }, - cache: { - id: "meta_emojis", - milliseconds: 3600000, // 1 hour - }} + where: { + host: IsNull(), + }, + order: { + category: "ASC", + name: "ASC", + }, + cache: { + id: "meta_emojis", + milliseconds: 3600000, // 1 hour + } + } ) .then(dbRes => populateEmojis(dbRes.map(p => p.name), null) .then(p => p.map(x => EmojiConverter.encode(x)) @@ -230,7 +230,7 @@ export class MiscHelpers { } public static getPreferences(user: ILocalUser): Promise { - const profile = UserProfiles.findOneByOrFail({userId: user.id}); + const profile = UserProfiles.findOneByOrFail({ userId: user.id }); const sensitive = profile.then(p => p.alwaysMarkNsfw); const language = profile.then(p => p.lang); const privacy = UserHelpers.getDefaultNoteVisibility(user) diff --git a/packages/backend/src/server/api/mastodon/helpers/note.ts b/packages/backend/src/server/api/mastodon/helpers/note.ts index a48aae59a..f2dee4992 100644 --- a/packages/backend/src/server/api/mastodon/helpers/note.ts +++ b/packages/backend/src/server/api/mastodon/helpers/note.ts @@ -147,7 +147,7 @@ export class NoteHelpers { maxId, minId ) - .andWhere("reaction.noteId = :noteId", {noteId: note.id}) + .andWhere("reaction.noteId = :noteId", { noteId: note.id }) .innerJoinAndSelect("reaction.user", "user"); return query.take(limit).getMany().then(async p => { @@ -168,7 +168,7 @@ export class NoteHelpers { const cache = UserHelpers.getFreshAccountCache(); const account = Promise.resolve(note.user ?? await UserHelpers.getUserCached(note.userId, cache)) .then(p => UserConverter.encode(p, cache)); - const edits = await NoteEdits.find({where: {noteId: note.id}, order: {id: "ASC"}}); + const edits = await NoteEdits.find({ where: { noteId: note.id }, order: { id: "ASC" } }); const history: Promise[] = []; const curr = { @@ -219,7 +219,7 @@ export class NoteHelpers { maxId, minId ) - .andWhere("note.renoteId = :noteId", {noteId: note.id}) + .andWhere("note.renoteId = :noteId", { noteId: note.id }) .andWhere("note.text IS NULL") // We don't want to count quotes as renotes .innerJoinAndSelect("note.user", "user"); @@ -244,7 +244,7 @@ export class NoteHelpers { const query = makePaginationQuery(Notes.createQueryBuilder("note")) .andWhere( "note.id IN (SELECT id FROM note_replies(:noteId, :depth, :limit))", - {noteId, depth, limit}, + { noteId, depth, limit }, ); generateVisibilityQuery(query, user); diff --git a/packages/backend/src/server/api/mastodon/helpers/notification.ts b/packages/backend/src/server/api/mastodon/helpers/notification.ts index 1ed6c5920..532693a0e 100644 --- a/packages/backend/src/server/api/mastodon/helpers/notification.ts +++ b/packages/backend/src/server/api/mastodon/helpers/notification.ts @@ -2,7 +2,7 @@ import { ILocalUser } from "@/models/entities/user.js"; import { Notes, Notifications } from "@/models/index.js"; import { PaginationHelpers } from "@/server/api/mastodon/helpers/pagination.js"; import { Notification } from "@/models/entities/notification.js"; -import {MastoApiError} from "@/server/api/mastodon/middleware/catch-errors.js"; +import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js"; export class NotificationHelpers { public static async getNotifications(user: ILocalUser, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 40, types: string[] | undefined, excludeTypes: string[] | undefined, accountId: string | undefined): Promise { @@ -24,11 +24,11 @@ export class NotificationHelpers { maxId, minId ) - .andWhere("notification.notifieeId = :userId", {userId: user.id}) - .andWhere("notification.type IN (:...types)", {types: requestedTypes}); + .andWhere("notification.notifieeId = :userId", { userId: user.id }) + .andWhere("notification.type IN (:...types)", { types: requestedTypes }); if (accountId !== undefined) - query.andWhere("notification.notifierId = :notifierId", {notifierId: accountId}); + query.andWhere("notification.notifierId = :notifierId", { notifierId: accountId }); query.leftJoinAndSelect("notification.note", "note"); @@ -36,22 +36,22 @@ export class NotificationHelpers { } public static async getNotification(id: string, user: ILocalUser): Promise { - return Notifications.findOneBy({id: id, notifieeId: user.id}); + return Notifications.findOneBy({ id: id, notifieeId: user.id }); } public static async getNotificationOr404(id: string, user: ILocalUser): Promise { return this.getNotification(id, user).then(p => { - if (p) return p; - throw new MastoApiError(404); + if (p) return p; + throw new MastoApiError(404); }); } public static async dismissNotification(id: string, user: ILocalUser): Promise { - const result = await Notifications.update({id: id, notifieeId: user.id}, {isRead: true}); + const result = await Notifications.update({ id: id, notifieeId: user.id }, { isRead: true }); } public static async clearAllNotifications(user: ILocalUser): Promise { - await Notifications.update({notifieeId: user.id}, {isRead: true}); + await Notifications.update({ notifieeId: user.id }, { isRead: true }); } public static async markConversationAsRead(id: string, user: ILocalUser): Promise { @@ -68,7 +68,7 @@ export class NotificationHelpers { .setParameter("conversationId", id) .setParameter("types", ['reply', 'mention']) .update() - .set({isRead: true}) + .set({ isRead: true }) .execute(); } diff --git a/packages/backend/src/server/api/mastodon/helpers/pagination.ts b/packages/backend/src/server/api/mastodon/helpers/pagination.ts index d24d01255..ee97fb96f 100644 --- a/packages/backend/src/server/api/mastodon/helpers/pagination.ts +++ b/packages/backend/src/server/api/mastodon/helpers/pagination.ts @@ -13,22 +13,22 @@ export class PaginationHelpers { if (sinceId && minId) throw new Error("Can't user both sinceId and minId params"); if (sinceId && maxId) { - q.andWhere(`${idField} > :sinceId`, {sinceId: sinceId}); - q.andWhere(`${idField} < :maxId`, {maxId: maxId}); + q.andWhere(`${idField} > :sinceId`, { sinceId: sinceId }); + q.andWhere(`${idField} < :maxId`, { maxId: maxId }); q.orderBy(`${idField}`, "DESC"); } if (minId && maxId) { - q.andWhere(`${idField} > :minId`, {minId: minId}); - q.andWhere(`${idField} < :maxId`, {maxId: maxId}); + q.andWhere(`${idField} > :minId`, { minId: minId }); + q.andWhere(`${idField} < :maxId`, { maxId: maxId }); q.orderBy(`${idField}`, "ASC"); } else if (sinceId) { - q.andWhere(`${idField} > :sinceId`, {sinceId: sinceId}); + q.andWhere(`${idField} > :sinceId`, { sinceId: sinceId }); q.orderBy(`${idField}`, "DESC"); } else if (minId) { - q.andWhere(`${idField} > :minId`, {minId: minId}); + q.andWhere(`${idField} > :minId`, { minId: minId }); q.orderBy(`${idField}`, "ASC"); } else if (maxId) { - q.andWhere(`${idField} < :maxId`, {maxId: maxId}); + q.andWhere(`${idField} < :maxId`, { maxId: maxId }); q.orderBy(`${idField}`, "DESC"); } else { q.orderBy(`${idField}`, "DESC"); diff --git a/packages/backend/src/server/api/mastodon/helpers/poll.ts b/packages/backend/src/server/api/mastodon/helpers/poll.ts index 6f93588d2..2280e082f 100644 --- a/packages/backend/src/server/api/mastodon/helpers/poll.ts +++ b/packages/backend/src/server/api/mastodon/helpers/poll.ts @@ -10,7 +10,7 @@ import { deliver } from "@/queue/index.js"; import { renderActivity } from "@/remote/activitypub/renderer/index.js"; import renderVote from "@/remote/activitypub/renderer/vote.js"; import { Not } from "typeorm"; -import {MastoApiError} from "@/server/api/mastodon/middleware/catch-errors.js"; +import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js"; export class PollHelpers { public static async getPoll(note: Note, user: ILocalUser | null): Promise { @@ -34,7 +34,7 @@ export class PollHelpers { if (block) throw new Error('You are blocked by the poll author'); } - const poll = await Polls.findOneByOrFail({noteId: note.id}); + const poll = await Polls.findOneByOrFail({ noteId: note.id }); if (poll.expiresAt && poll.expiresAt < createdAt) throw new Error('Poll is expired'); diff --git a/packages/backend/src/server/api/mastodon/helpers/search.ts b/packages/backend/src/server/api/mastodon/helpers/search.ts index d2ba06681..f8136fb35 100644 --- a/packages/backend/src/server/api/mastodon/helpers/search.ts +++ b/packages/backend/src/server/api/mastodon/helpers/search.ts @@ -63,7 +63,10 @@ export class SearchHelpers { if (!match) match = q.match(/^@(?[a-zA-Z0-9_]+)$/) if (match) { // check if user is already in database - const dbResult = await Users.findOneBy({usernameLower: match.groups!.user.toLowerCase(), host: match.groups?.host ?? IsNull()}); + const dbResult = await Users.findOneBy({ + usernameLower: match.groups!.user.toLowerCase(), + host: match.groups?.host ?? IsNull() + }); if (dbResult) return [dbResult]; const result = await resolveUser(match.groups!.user.toLowerCase(), match.groups?.host ?? null); @@ -89,23 +92,23 @@ export class SearchHelpers { if (following) { const followingQuery = Followings.createQueryBuilder("following") .select("following.followeeId") - .where("following.followerId = :followerId", {followerId: user.id}); + .where("following.followerId = :followerId", { followerId: user.id }); query.andWhere( new Brackets((qb) => { - qb.where(`user.id IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, {meId: user.id}); + qb.where(`user.id IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, { meId: user.id }); }), ); } query.andWhere( new Brackets((qb) => { - qb.where("user.name ILIKE :q", {q: `%${sqlLikeEscape(q)}%`}); - qb.orWhere("user.usernameLower ILIKE :q", {q: `%${sqlLikeEscape(q)}%`}); + qb.where("user.name ILIKE :q", { q: `%${sqlLikeEscape(q)}%` }); + qb.orWhere("user.usernameLower ILIKE :q", { q: `%${sqlLikeEscape(q)}%` }); }) ); - query.orderBy({'user.notesCount': 'DESC'}); + query.orderBy({ 'user.notesCount': 'DESC' }); return query.skip(offset ?? 0).take(limit).getMany().then(p => minId ? p.reverse() : p); } @@ -184,8 +187,8 @@ export class SearchHelpers { const chunk = ids.slice(start, start + chunkSize); const query = Notes.createQueryBuilder("note") - .where({id: In(chunk)}) - .orderBy({id: "DESC"}) + .where({ id: In(chunk) }) + .orderBy({ id: "DESC" }) generateVisibilityQuery(query, user); @@ -197,11 +200,11 @@ export class SearchHelpers { if (following) { const followingQuery = Followings.createQueryBuilder("following") .select("following.followeeId") - .where("following.followerId = :followerId", {followerId: user.id}); + .where("following.followerId = :followerId", { followerId: user.id }); query.andWhere( new Brackets((qb) => { - qb.where(`note.userId IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, {meId: user.id}); + qb.where(`note.userId IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, { meId: user.id }); }), ) } @@ -267,8 +270,8 @@ export class SearchHelpers { const chunk = ids.slice(start, start + chunkSize); const query = Notes.createQueryBuilder("note") - .where({id: In(chunk)}) - .orderBy({id: "DESC"}) + .where({ id: In(chunk) }) + .orderBy({ id: "DESC" }) generateVisibilityQuery(query, user); @@ -356,23 +359,23 @@ export class SearchHelpers { ); if (accountId) { - query.andWhere("note.userId = :userId", {userId: accountId}); + query.andWhere("note.userId = :userId", { userId: accountId }); } if (following) { const followingQuery = Followings.createQueryBuilder("following") .select("following.followeeId") - .where("following.followerId = :followerId", {followerId: user.id}); + .where("following.followerId = :followerId", { followerId: user.id }); query.andWhere( new Brackets((qb) => { - qb.where(`note.userId IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, {meId: user.id}); + qb.where(`note.userId IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, { meId: user.id }); }), ) } query - .andWhere("note.text ILIKE :q", {q: `%${sqlLikeEscape(q)}%`}) + .andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(q)}%` }) .leftJoinAndSelect("note.renote", "renote"); @@ -390,8 +393,8 @@ export class SearchHelpers { const tags = Hashtags.createQueryBuilder('tag') .select('tag.name') .distinctOn(['tag.name']) - .where("tag.name ILIKE :q", {q: `%${sqlLikeEscape(q)}%`}) - .orderBy({'tag.name': 'ASC'}) + .where("tag.name ILIKE :q", { q: `%${sqlLikeEscape(q)}%` }) + .orderBy({ 'tag.name': 'ASC' }) .skip(offset ?? 0).take(limit).getMany(); return tags.then(p => p.map(tag => { diff --git a/packages/backend/src/server/api/mastodon/helpers/timeline.ts b/packages/backend/src/server/api/mastodon/helpers/timeline.ts index b2c227e01..4be265fda 100644 --- a/packages/backend/src/server/api/mastodon/helpers/timeline.ts +++ b/packages/backend/src/server/api/mastodon/helpers/timeline.ts @@ -17,7 +17,7 @@ import { UserConverter } from "@/server/api/mastodon/converters/user.js"; import { NoteConverter } from "@/server/api/mastodon/converters/note.js"; import { awaitAll } from "@/prelude/await-all.js"; import { unique } from "@/prelude/array.js"; -import {MastoApiError} from "@/server/api/mastodon/middleware/catch-errors.js"; +import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js"; export class TimelineHelpers { public static async getHomeTimeline(user: ILocalUser, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 20): Promise { @@ -25,7 +25,7 @@ export class TimelineHelpers { const followingQuery = Followings.createQueryBuilder("following") .select("following.followeeId") - .where("following.followerId = :followerId", {followerId: user.id}); + .where("following.followerId = :followerId", { followerId: user.id }); const query = PaginationHelpers.makePaginationQuery( Notes.createQueryBuilder("note"), @@ -35,7 +35,7 @@ export class TimelineHelpers { ) .andWhere( new Brackets((qb) => { - qb.where(`note.userId IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, {meId: user.id}); + qb.where(`note.userId IN (${followingQuery.getQuery()} UNION ALL VALUES (:meId))`, { meId: user.id }); }), ) .leftJoinAndSelect("note.renote", "renote"); @@ -114,7 +114,7 @@ export class TimelineHelpers { .andWhere(`note.userId IN (${listQuery.getQuery()})`) .andWhere("note.visibility != 'specified'") .leftJoinAndSelect("note.renote", "renote") - .setParameters({listId: list.id}); + .setParameters({ listId: list.id }); generateVisibilityQuery(query, user); @@ -137,11 +137,11 @@ export class TimelineHelpers { minId ) .andWhere("note.visibility = 'public'") - .andWhere("note.tags @> array[:tag]::varchar[]", {tag: tag}); + .andWhere("note.tags @> array[:tag]::varchar[]", { tag: tag }); - if (any.length > 0) query.andWhere("note.tags && array[:...any]::varchar[]", {any: any}); - if (all.length > 0) query.andWhere("note.tags @> array[:...all]::varchar[]", {all: all}); - if (none.length > 0) query.andWhere("NOT(note.tags @> array[:...none]::varchar[])", {none: none}); + if (any.length > 0) query.andWhere("note.tags && array[:...any]::varchar[]", { any: any }); + if (all.length > 0) query.andWhere("note.tags @> array[:...all]::varchar[]", { all: all }); + if (none.length > 0) query.andWhere("NOT(note.tags @> array[:...none]::varchar[])", { none: none }); if (remote) query.andWhere("note.userHost IS NOT NULL"); if (local) query.andWhere("note.userHost IS NULL"); @@ -168,7 +168,7 @@ export class TimelineHelpers { .select("COALESCE(note.threadId, note.id)", "conversationId") .addSelect("note.id", "latest") .distinctOn(["COALESCE(note.threadId, note.id)"]) - .orderBy({"COALESCE(note.threadId, note.id)": minId ? "ASC" : "DESC", "note.id": "DESC"}) + .orderBy({ "COALESCE(note.threadId, note.id)": minId ? "ASC" : "DESC", "note.id": "DESC" }) .andWhere("note.visibility = 'specified'") .andWhere( new Brackets(qb => { @@ -183,7 +183,7 @@ export class TimelineHelpers { minId ) .innerJoin(`(${sq.getQuery()})`, "sq", "note.id = sq.latest") - .setParameters({userId: user.id}) + .setParameters({ userId: user.id }) return query.take(limit).getMany().then(p => { if (minId !== undefined) p = p.reverse(); diff --git a/packages/backend/src/server/api/mastodon/helpers/user.ts b/packages/backend/src/server/api/mastodon/helpers/user.ts index 6e5590f1e..4bc851e9b 100644 --- a/packages/backend/src/server/api/mastodon/helpers/user.ts +++ b/packages/backend/src/server/api/mastodon/helpers/user.ts @@ -67,8 +67,8 @@ type RelationshipType = 'followers' | 'following'; export class UserHelpers { public static async followUser(target: User, localUser: ILocalUser, reblogs: boolean, notify: boolean): Promise { //FIXME: implement reblogs & notify params - const following = await Followings.exist({where: {followerId: localUser.id, followeeId: target.id}}); - const requested = await FollowRequests.exist({where: {followerId: localUser.id, followeeId: target.id}}); + const following = await Followings.exist({ where: { followerId: localUser.id, followeeId: target.id } }); + const requested = await FollowRequests.exist({ where: { followerId: localUser.id, followeeId: target.id } }); if (!following && !requested) await createFollowing(localUser, target); @@ -76,8 +76,8 @@ export class UserHelpers { } public static async unfollowUser(target: User, localUser: ILocalUser): Promise { - const following = await Followings.exist({where: {followerId: localUser.id, followeeId: target.id}}); - const requested = await FollowRequests.exist({where: {followerId: localUser.id, followeeId: target.id}}); + const following = await Followings.exist({ where: { followerId: localUser.id, followeeId: target.id } }); + const requested = await FollowRequests.exist({ where: { followerId: localUser.id, followeeId: target.id } }); if (following) await deleteFollowing(localUser, target); if (requested) @@ -87,7 +87,7 @@ export class UserHelpers { } public static async blockUser(target: User, localUser: ILocalUser): Promise { - const blocked = await Blockings.exist({where: {blockerId: localUser.id, blockeeId: target.id}}); + const blocked = await Blockings.exist({ where: { blockerId: localUser.id, blockeeId: target.id } }); if (!blocked) await createBlocking(localUser, target); @@ -95,7 +95,7 @@ export class UserHelpers { } public static async unblockUser(target: User, localUser: ILocalUser): Promise { - const blocked = await Blockings.exist({where: {blockerId: localUser.id, blockeeId: target.id}}); + const blocked = await Blockings.exist({ where: { blockerId: localUser.id, blockeeId: target.id } }); if (blocked) await deleteBlocking(localUser, target); @@ -104,7 +104,7 @@ export class UserHelpers { public static async muteUser(target: User, localUser: ILocalUser, notifications: boolean = true, duration: number = 0): Promise { //FIXME: respect notifications parameter - const muted = await Mutings.exist({where: {muterId: localUser.id, muteeId: target.id}}); + const muted = await Mutings.exist({ where: { muterId: localUser.id, muteeId: target.id } }); if (!muted) { await Mutings.insert({ id: genId(), @@ -126,7 +126,7 @@ export class UserHelpers { } public static async unmuteUser(target: User, localUser: ILocalUser): Promise { - const muting = await Mutings.findOneBy({muterId: localUser.id, muteeId: target.id}); + const muting = await Mutings.findOneBy({ muterId: localUser.id, muteeId: target.id }); if (muting) { await Mutings.delete({ id: muting.id, @@ -139,14 +139,14 @@ export class UserHelpers { } public static async acceptFollowRequest(target: User, localUser: ILocalUser): Promise { - const pending = await FollowRequests.exist({where: {followerId: target.id, followeeId: localUser.id}}); + const pending = await FollowRequests.exist({ where: { followerId: target.id, followeeId: localUser.id } }); if (pending) await acceptFollowRequest(localUser, target); return this.getUserRelationshipTo(target.id, localUser.id); } public static async rejectFollowRequest(target: User, localUser: ILocalUser): Promise { - const pending = await FollowRequests.exist({where: {followerId: target.id, followeeId: localUser.id}}); + const pending = await FollowRequests.exist({ where: { followerId: target.id, followeeId: localUser.id } }); if (pending) await rejectFollowRequest(localUser, target); return this.getUserRelationshipTo(target.id, localUser.id); @@ -193,7 +193,7 @@ export class UserHelpers { public static async verifyCredentials(user: ILocalUser): Promise { const acct = UserConverter.encode(user); - const profile = UserProfiles.findOneByOrFail({userId: user.id}); + const profile = UserProfiles.findOneByOrFail({ userId: user.id }); const privacy = this.getDefaultNoteVisibility(user); const fields = profile.then(profile => profile.fields.map(field => { return { @@ -222,7 +222,7 @@ export class UserHelpers { public static async getUserFromAcct(acct: string): Promise { const split = acct.toLowerCase().split('@'); if (split.length > 2) throw new Error('Invalid acct'); - return Users.findOneBy({usernameLower: split[0], host: split[1] ?? IsNull()}) + return Users.findOneBy({ usernameLower: split[0], host: split[1] ?? IsNull() }) .then(p => { if (p) return p; throw new MastoApiError(404); @@ -239,7 +239,7 @@ export class UserHelpers { minId ); - query.andWhere("muting.muterId = :userId", {userId: user.id}) + query.andWhere("muting.muterId = :userId", { userId: user.id }) .innerJoinAndSelect("muting.mutee", "mutee"); return query.take(limit).getMany().then(async p => { @@ -275,7 +275,7 @@ export class UserHelpers { minId ); - query.andWhere("blocking.blockerId = :userId", {userId: user.id}) + query.andWhere("blocking.blockerId = :userId", { userId: user.id }) .innerJoinAndSelect("blocking.blockee", "blockee"); return query.take(limit).getMany().then(p => { @@ -302,7 +302,7 @@ export class UserHelpers { minId ); - query.andWhere("request.followeeId = :userId", {userId: user.id}) + query.andWhere("request.followeeId = :userId", { userId: user.id }) .innerJoinAndSelect("request.follower", "follower"); return query.take(limit).getMany().then(p => { @@ -356,7 +356,7 @@ export class UserHelpers { new Brackets(qb => { qb.where("note.replyId IS NULL") .orWhere(new Brackets(qb => { - qb.where('note.mentions = :mentions', {mentions: []}) + qb.where('note.mentions = :mentions', { mentions: [] }) .andWhere('thread.userId = :userId') })); })); @@ -375,7 +375,7 @@ export class UserHelpers { query.andWhere("note.visibility != 'hidden'"); query.andWhere("note.visibility != 'specified'"); - query.setParameters({userId: user.id}); + query.setParameters({ userId: user.id }); return PaginationHelpers.execQuery(query, limit, minId !== undefined); } @@ -389,7 +389,7 @@ export class UserHelpers { maxId, minId ) - .andWhere("favorite.userId = :meId", {meId: localUser.id}) + .andWhere("favorite.userId = :meId", { meId: localUser.id }) .leftJoinAndSelect("favorite.note", "note"); generateVisibilityQuery(query, localUser); @@ -413,7 +413,7 @@ export class UserHelpers { maxId, minId ) - .andWhere("reaction.userId = :meId", {meId: localUser.id}) + .andWhere("reaction.userId = :meId", { meId: localUser.id }) .leftJoinAndSelect("reaction.note", "note"); generateVisibilityQuery(query, localUser); @@ -431,11 +431,11 @@ export class UserHelpers { private static async getUserRelationships(type: RelationshipType, user: User, localUser: ILocalUser | null, maxId: string | undefined, sinceId: string | undefined, minId: string | undefined, limit: number = 40): Promise> { if (limit > 80) limit = 80; - const profile = await UserProfiles.findOneByOrFail({userId: user.id}); + const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); if (profile.ffVisibility === "private") { - if (!localUser || user.id !== localUser.id) return {data: []}; + if (!localUser || user.id !== localUser.id) return { data: [] }; } else if (profile.ffVisibility === "followers") { - if (!localUser) return {data: []}; + if (!localUser) return { data: [] }; if (user.id !== localUser.id) { const isFollowed = await Followings.exist({ where: { @@ -443,7 +443,7 @@ export class UserHelpers { followerId: localUser.id, }, }); - if (!isFollowed) return {data: []}; + if (!isFollowed) return { data: [] }; } } @@ -455,10 +455,10 @@ export class UserHelpers { ); if (type === "followers") { - query.andWhere("following.followeeId = :userId", {userId: user.id}) + query.andWhere("following.followeeId = :userId", { userId: user.id }) .innerJoinAndSelect("following.follower", "follower"); } else { - query.andWhere("following.followerId = :userId", {userId: user.id}) + query.andWhere("following.followerId = :userId", { userId: user.id }) .innerJoinAndSelect("following.followee", "followee"); } @@ -538,6 +538,11 @@ export class UserHelpers { } public static async getDefaultNoteVisibility(user: ILocalUser): Promise { - return RegistryItems.findOneBy({domain: IsNull(), userId: user.id, key: 'defaultNoteVisibility', scope: '{client,base}'}).then(p => p?.value ?? 'public') + return RegistryItems.findOneBy({ + domain: IsNull(), + userId: user.id, + key: 'defaultNoteVisibility', + scope: '{client,base}' + }).then(p => p?.value ?? 'public') } } diff --git a/packages/backend/src/server/api/mastodon/middleware/auth.ts b/packages/backend/src/server/api/mastodon/middleware/auth.ts index df5044199..152dfb73a 100644 --- a/packages/backend/src/server/api/mastodon/middleware/auth.ts +++ b/packages/backend/src/server/api/mastodon/middleware/auth.ts @@ -19,12 +19,11 @@ export function auth(required: boolean, scopes: string[] = []) { return; } - if (!AuthConverter.decode(scopes).every(p => ctx.scopes.includes(p))) { + if (!AuthConverter.decode(scopes).every(p => ctx.scopes.includes(p))) { if (required) { ctx.status = 403; - ctx.body = {error: "This action is outside the authorized scopes"}; - } - else { + ctx.body = { error: "This action is outside the authorized scopes" }; + } else { ctx.user = null; ctx.scopes = []; } diff --git a/packages/backend/src/server/api/mastodon/middleware/catch-errors.ts b/packages/backend/src/server/api/mastodon/middleware/catch-errors.ts index 918ce1ce6..cea536a3f 100644 --- a/packages/backend/src/server/api/mastodon/middleware/catch-errors.ts +++ b/packages/backend/src/server/api/mastodon/middleware/catch-errors.ts @@ -1,9 +1,10 @@ -import { MastoContext, logger } from "@/server/api/mastodon/index.js"; +import { logger, MastoContext } from "@/server/api/mastodon/index.js"; import { IdentifiableError } from "@/misc/identifiable-error.js"; import { ApiError } from "@/server/api/error.js"; export class MastoApiError extends Error { statusCode: number; + constructor(statusCode: number, message?: string) { if (message == null) { switch (statusCode) { @@ -26,20 +27,16 @@ export async function CatchErrorsMiddleware(ctx: MastoContext, next: () => Promi } catch (e: any) { if (e instanceof MastoApiError) { ctx.status = e.statusCode; - } - else if (e instanceof IdentifiableError) { + } else if (e instanceof IdentifiableError) { ctx.status = 400; - } - else if (e instanceof ApiError) { + } else if (e instanceof ApiError) { ctx.status = e.httpStatusCode ?? 500; - } - else { + } else { logger.error(`Error occured in ${ctx.method} ${ctx.path}:`); if (e instanceof Error) { if (e.stack) logger.error(e.stack); else logger.error(`${e.name}: ${e.message}`); - } - else { + } else { logger.error(e); } ctx.status = 500; diff --git a/packages/backend/src/server/api/mastodon/middleware/normalize-query.ts b/packages/backend/src/server/api/mastodon/middleware/normalize-query.ts index 85ca1a594..9c073c6a3 100644 --- a/packages/backend/src/server/api/mastodon/middleware/normalize-query.ts +++ b/packages/backend/src/server/api/mastodon/middleware/normalize-query.ts @@ -5,7 +5,7 @@ export async function NormalizeQueryMiddleware(ctx: MastoContext, next: () => Pr if (!ctx.request.body || Object.keys(ctx.request.body).length === 0) { ctx.request.body = ctx.request.query; } else { - ctx.request.body = {...ctx.request.body, ...ctx.request.query}; + ctx.request.body = { ...ctx.request.body, ...ctx.request.query }; } } await next();