From 5e6594d91d3738f3e5da6a60232e34ee13546fb5 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 18:58:24 +0200 Subject: [PATCH 1/9] [mastodon-client] Fail gracefully if user resolve fails --- packages/megalodon/src/misskey.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 5275c70f6..61464522a 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1257,31 +1257,31 @@ export default class Misskey implements MegalodonInterface { } public async getMentions(text: string, cache: AccountCache): Promise { - console.log(`getting mentions for message: '${text}'`); const mentions :Entity.Mention[] = []; if (text == undefined) return mentions; - console.log('text is not undefined, continuing'); - const mentionMatch = text.matchAll(/(?<=^|\s)@(?.*?)(?:@(?.*?)|)(?=\s|$)/g); for (const m of mentionMatch) { - if (m.groups == null) - continue; + try { + if (m.groups == null) + continue; - const account = await this.getAccountByNameCached(m.groups.user, m.groups.host, cache); + const account = await this.getAccountByNameCached(m.groups.user, m.groups.host, cache); - if (account == null) - continue; + if (account == null) + continue; - mentions.push({ - id: account.id, - url: account.url, - username: account.username, - acct: account.acct - }); + mentions.push({ + id: account.id, + url: account.url, + username: account.username, + acct: account.acct + }); + } + catch {} } return mentions; From 7b64cf9688f8f0ac743026c46ad4b9807718a314 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 19:23:47 +0200 Subject: [PATCH 2/9] [mastodon-client] Fix global timeline --- .../src/server/api/mastodon/endpoints/timeline.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts index a155cc93e..efadfe786 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/timeline.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/timeline.ts @@ -45,13 +45,14 @@ export function apiTimelineMastodon(router: Router): void { const client = getClient(BASE_URL, accessTokens); try { const query: any = ctx.query; - const data = query.local - ? await client.getLocalTimeline( - convertTimelinesArgsId(argsToBools(limitToInt(query))), - ) - : await client.getPublicTimeline( - convertTimelinesArgsId(argsToBools(limitToInt(query))), - ); + const data = + query.local === "true" + ? await client.getLocalTimeline( + convertTimelinesArgsId(argsToBools(limitToInt(query))), + ) + : await client.getPublicTimeline( + convertTimelinesArgsId(argsToBools(limitToInt(query))), + ); ctx.body = data.data.map((status) => convertStatus(status)); } catch (e: any) { console.error(e); From d6a4b18744a073cd6628baf45b34da7f2a573cd5 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 19:41:32 +0200 Subject: [PATCH 3/9] [mastodon-client] Don't display unsupported notification types --- packages/megalodon/src/misskey.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 61464522a..42268806f 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -10,6 +10,7 @@ import Entity from './entity' import { MegalodonInterface, WebSocketInterface, NoImplementedError, ArgumentError, UnexpectedError } from './megalodon' import MegalodonEntity from "@/entity"; import fs from "node:fs"; +import MisskeyNotificationType from "./misskey/notification"; type AccountCache = { locks: AsyncLock, @@ -2238,7 +2239,11 @@ export default class Misskey implements MegalodonInterface { } return this.client .post>('/api/i/notifications', params) - .then(res => ({ ...res, data: res.data.map(n => this.converter.notification(n, this.baseUrlToHost(this.baseUrl))) })) + .then(res => ({ + ...res, + data: res.data + .filter(p => p.type != MisskeyNotificationType.FollowRequestAccepted) // these aren't supported on mastodon + .map(n => this.converter.notification(n, this.baseUrlToHost(this.baseUrl))) })) } public async getNotification(_id: string): Promise> { From 72887f54e0deb0824cc37fe8774654b6c84f7e74 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 20:15:24 +0200 Subject: [PATCH 4/9] [mastodon-client] populate user details for all notes --- .../src/server/api/mastodon/converters.ts | 6 +- packages/megalodon/src/misskey.ts | 79 +++++++++++++------ 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/converters.ts b/packages/backend/src/server/api/mastodon/converters.ts index 37c6283a1..cbaf5287f 100644 --- a/packages/backend/src/server/api/mastodon/converters.ts +++ b/packages/backend/src/server/api/mastodon/converters.ts @@ -2,8 +2,10 @@ import { Entity } from "megalodon"; import { convertId, IdType } from "../index.js"; function simpleConvert(data: any) { - data.id = convertId(data.id, IdType.MastodonId); - return data; + // copy the object to bypass weird pass by reference bugs + const result = Object.assign({}, data); + result.id = convertId(data.id, IdType.MastodonId); + return result; } export function convertAccount(account: Entity.Account) { diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 42268806f..4753eb480 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -333,7 +333,7 @@ export default class Misskey implements MegalodonInterface { if (res.data.pinnedNotes) { return { ...res, - data: await Promise.all(res.data.pinnedNotes.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.pinnedNotes.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) } } return {...res, data: []} @@ -385,7 +385,7 @@ export default class Misskey implements MegalodonInterface { }) } return this.client.post>('/api/users/notes', params).then(async res => { - const statuses: Array = await Promise.all(res.data.map(note => this.noteWithMentions(note, this.baseUrlToHost(this.baseUrl), accountCache))) + const statuses: Array = await Promise.all(res.data.map(note => this.noteWithDetails(note, this.baseUrlToHost(this.baseUrl), accountCache))) return Object.assign(res, { data: statuses }) @@ -424,7 +424,7 @@ export default class Misskey implements MegalodonInterface { } return this.client.post>('/api/users/reactions', params).then(async res => { return Object.assign(res, { - data: await Promise.all(res.data.map(fav => this.noteWithMentions(fav.note, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(fav => this.noteWithDetails(fav.note, this.baseUrlToHost(this.baseUrl), accountCache))) }) }) } @@ -764,7 +764,7 @@ export default class Misskey implements MegalodonInterface { } return this.client.post>('/api/i/favorites', params).then(async res => { return Object.assign(res, { - data: await Promise.all(res.data.map(s => this.noteWithMentions(s.note, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(s => this.noteWithDetails(s.note, this.baseUrlToHost(this.baseUrl), accountCache))) }) }) } @@ -1222,7 +1222,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/create', params) .then(async res => ({ ...res, - data: await this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + data: await this.noteWithDetails(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) })) } @@ -1234,7 +1234,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({ ...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})); + .then(async res => ({ ...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})); } private getFreshAccountCache() :AccountCache { @@ -1244,12 +1244,22 @@ export default class Misskey implements MegalodonInterface { } } - public async noteWithMentions(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { - const status = await this.converter.note(n, host); - return status.mentions.length === 0 ? this.addMentionsToStatus(status, cache) : status; + public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { + const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache); + return this.addMentionsToStatus(status, cache); } + public async addUserDetailsToStatus(status: Entity.Status, cache: AccountCache) : Promise { + if (status.account.followers_count === 0 && status.account.followers_count === 0 && status.account.statuses_count === 0) + status.account = await this.getAccountCached(status.account.id, status.account.acct, cache) ?? status.account; + + return status; + } + public async addMentionsToStatus(status: Entity.Status, cache: AccountCache) : Promise { + if (status.mentions.length > 0) + return status; + status.mentions = (await this.getMentions(status.plain_content!, cache)).filter(p => p != null); for (const m of status.mentions.filter((value, index, array) => array.indexOf(value) === index)) { status.content = status.content.replace(`@${m.acct}`, `@${m.acct}`); @@ -1307,6 +1317,23 @@ export default class Misskey implements MegalodonInterface { }) } + public async getAccountCached(id: string, acct: string, cache: AccountCache): Promise { + return await cache.locks.acquire(acct, async () => { + const cacheHit = cache.accounts.find(p => p.id === id); + const account = cacheHit ?? (await this.getAccount(id)).data; + + if (!account) { + return null; + } + + if (cacheHit == null) { + cache.accounts.push(account); + } + + return account; + }) + } + public async editStatus( _id: string, _options: { @@ -1375,11 +1402,11 @@ export default class Misskey implements MegalodonInterface { return this.client.post>('/api/notes/children', params).then(async res => { const accountCache = this.getFreshAccountCache(); const conversation = await this.client.post>('/api/notes/conversation', params); - const parents = await Promise.all(conversation.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))); + const parents = await Promise.all(conversation.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))); const context: Entity.Context = { ancestors: parents.reverse(), - descendants: this.dfs(await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache)))) + descendants: this.dfs(await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache)))) } return { ...res, @@ -1492,7 +1519,7 @@ export default class Misskey implements MegalodonInterface { }) .then(async res => ({ ...res, - data: await this.noteWithMentions(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + data: await this.noteWithDetails(res.data.createdNote, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) })) } @@ -1507,7 +1534,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -1521,7 +1548,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -1535,7 +1562,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } public async muteStatus(_id: string): Promise> { @@ -1563,7 +1590,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -1577,7 +1604,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } // ====================================== @@ -1663,7 +1690,7 @@ export default class Misskey implements MegalodonInterface { noteId: status_id }) .then(async res => { - const note = await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) + const note = await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache()) return {...res, data: note.poll} }) if (!res.data) { @@ -1768,7 +1795,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/global-timeline', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -1826,7 +1853,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/local-timeline', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -1890,7 +1917,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/search-by-tag', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -1945,7 +1972,7 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/timeline', params) .then(async res => ({ ...res, - data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) + data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } @@ -2001,7 +2028,7 @@ export default class Misskey implements MegalodonInterface { } return this.client .post>('/api/notes/user-list-timeline', params) - .then(async res => ({ ...res, data: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) + .then(async res => ({ ...res, data: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))) })) } // ====================================== @@ -2444,7 +2471,7 @@ export default class Misskey implements MegalodonInterface { ...res, data: { accounts: [], - statuses: await Promise.all(res.data.map(n => this.noteWithMentions(n, this.baseUrlToHost(this.baseUrl), accountCache))), + statuses: await Promise.all(res.data.map(n => this.noteWithDetails(n, this.baseUrlToHost(this.baseUrl), accountCache))), hashtags: [] } })) @@ -2582,7 +2609,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } /** @@ -2596,7 +2623,7 @@ export default class Misskey implements MegalodonInterface { .post('/api/notes/show', { noteId: id }) - .then(async res => ({...res, data: await this.noteWithMentions(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) + .then(async res => ({...res, data: await this.noteWithDetails(res.data, this.baseUrlToHost(this.baseUrl), this.getFreshAccountCache())})) } public async getEmojiReactions(id: string): Promise>> { From c3f5836ac1f794580f6f7932ffb001294311665d Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 22:06:26 +0200 Subject: [PATCH 5/9] [mastodon-client] populate note details for notifications --- packages/megalodon/src/misskey.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 4753eb480..85489f8be 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1244,6 +1244,13 @@ export default class Misskey implements MegalodonInterface { } } + public async notificationWithDetails(n: MisskeyAPI.Entity.Notification, host: string, cache: AccountCache): Promise { + const notification = this.converter.notification(n, host); + if (n.note) + notification.status = await this.noteWithDetails(n.note, host, cache); + return notification; + } + public async noteWithDetails(n: MisskeyAPI.Entity.Note, host: string, cache: AccountCache): Promise { const status = await this.addUserDetailsToStatus(this.converter.note(n, host), cache); return this.addMentionsToStatus(status, cache); @@ -2264,13 +2271,15 @@ export default class Misskey implements MegalodonInterface { limit: 20 }) } + const cache = this.getFreshAccountCache(); return this.client .post>('/api/i/notifications', params) - .then(res => ({ + .then(async res => ({ ...res, - data: res.data + data: await Promise.all(res.data .filter(p => p.type != MisskeyNotificationType.FollowRequestAccepted) // these aren't supported on mastodon - .map(n => this.converter.notification(n, this.baseUrlToHost(this.baseUrl))) })) + .map(n => this.notificationWithDetails(n, this.baseUrlToHost(this.baseUrl), cache))) + })) } public async getNotification(_id: string): Promise> { From 2d47cdf53feafac5d4d45abc03ebff0ba8c97699 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 22:40:29 +0200 Subject: [PATCH 6/9] [mastodon-client] implement favorited_by --- .../src/server/api/mastodon/endpoints/status.ts | 14 +++++++++++++- packages/megalodon/src/misskey.ts | 14 +++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/status.ts b/packages/backend/src/server/api/mastodon/endpoints/status.ts index ec978bc84..3c58cf3a4 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/status.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/status.ts @@ -197,7 +197,19 @@ export function apiStatusMastodon(router: Router): void { router.get<{ Params: { id: string } }>( "/v1/statuses/:id/favourited_by", async (ctx) => { - ctx.body = []; + const BASE_URL = `${ctx.protocol}://${ctx.hostname}`; + const accessTokens = ctx.headers.authorization; + const client = getClient(BASE_URL, accessTokens); + try { + const data = await client.getStatusFavouritedBy( + convertId(ctx.params.id, IdType.CalckeyId), + ); + ctx.body = data.data.map((account) => convertAccount(account)); + } catch (e: any) { + console.error(e); + ctx.status = 401; + ctx.body = e.response.data; + } }, ); router.post<{ Params: { id: string } }>( diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index 85489f8be..dda108deb 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1487,11 +1487,15 @@ export default class Misskey implements MegalodonInterface { })) } - public async getStatusFavouritedBy(_id: string): Promise>> { - return new Promise((_, reject) => { - const err = new NoImplementedError('misskey does not support') - reject(err) - }) + public async getStatusFavouritedBy(id: string): Promise>> { + return this.client + .post>('/api/notes/reactions', { + noteId: id + }) + .then(res => ({ + ...res, + data: res.data.map(n => this.converter.user(n.user)) + })) } public async favouriteStatus(id: string): Promise> { From f33ccfc98aba4705f31c973571f141c603a5fa2a Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 22:51:07 +0200 Subject: [PATCH 7/9] [mastodon-client] populate user data for favorited_by and reblogged_by --- packages/megalodon/src/misskey.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index dda108deb..cc589197d 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1481,9 +1481,9 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/renotes', { noteId: id }) - .then(res => ({ + .then(async res => ({ ...res, - data: res.data.map(n => this.converter.user(n.user)) + data: (await Promise.all(res.data.map(n => this.getAccount(n.user.id)))).map(p => p.data) })) } @@ -1492,9 +1492,9 @@ export default class Misskey implements MegalodonInterface { .post>('/api/notes/reactions', { noteId: id }) - .then(res => ({ + .then(async res => ({ ...res, - data: res.data.map(n => this.converter.user(n.user)) + data: (await Promise.all(res.data.map(n => this.getAccount(n.user.id)))).map(p => p.data) })) } From 8323a33f97327c8f8a17df5e89eea17fed56beb2 Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 23:18:43 +0200 Subject: [PATCH 8/9] [mastodon-client] populate details for quote and reblog fields --- packages/megalodon/src/misskey.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/megalodon/src/misskey.ts b/packages/megalodon/src/misskey.ts index cc589197d..48950f943 100644 --- a/packages/megalodon/src/misskey.ts +++ b/packages/megalodon/src/misskey.ts @@ -1260,6 +1260,12 @@ export default class Misskey implements MegalodonInterface { if (status.account.followers_count === 0 && status.account.followers_count === 0 && status.account.statuses_count === 0) status.account = await this.getAccountCached(status.account.id, status.account.acct, cache) ?? status.account; + if (status.reblog != null) + status.reblog = await this.addUserDetailsToStatus(status.reblog, cache); + + if (status.quote != null) + status.quote = await this.addUserDetailsToStatus(status.quote, cache); + return status; } @@ -1267,6 +1273,12 @@ export default class Misskey implements MegalodonInterface { if (status.mentions.length > 0) return status; + if (status.reblog != null) + status.reblog = await this.addMentionsToStatus(status.reblog, cache); + + if (status.quote != null) + status.quote = await this.addMentionsToStatus(status.quote, cache); + status.mentions = (await this.getMentions(status.plain_content!, cache)).filter(p => p != null); for (const m of status.mentions.filter((value, index, array) => array.indexOf(value) === index)) { status.content = status.content.replace(`@${m.acct}`, `@${m.acct}`); From 7ffe30dcdb5b76ba61b7533eccb403cd92dfbf6e Mon Sep 17 00:00:00 2001 From: Laura Hausmann Date: Fri, 7 Jul 2023 23:42:19 +0200 Subject: [PATCH 9/9] [mastodon-client] fix search type param --- .../server/api/mastodon/endpoints/search.ts | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/backend/src/server/api/mastodon/endpoints/search.ts b/packages/backend/src/server/api/mastodon/endpoints/search.ts index df35b9116..c2f828ad7 100644 --- a/packages/backend/src/server/api/mastodon/endpoints/search.ts +++ b/packages/backend/src/server/api/mastodon/endpoints/search.ts @@ -30,21 +30,25 @@ export function apiSearchMastodon(router: Router): void { try { const query: any = convertTimelinesArgsId(limitToInt(ctx.query)); const type = query.type; - if (type) { - const data = await client.search(query.q, type, query); - ctx.body = data.data.accounts.map((account) => convertAccount(account)); - } else { - const acct = await client.search(query.q, "accounts", query); - const stat = await client.search(query.q, "statuses", query); - const tags = await client.search(query.q, "hashtags", query); - ctx.body = { - accounts: acct.data.accounts.map((account) => - convertAccount(account), - ), - statuses: stat.data.statuses.map((status) => convertStatus(status)), - hashtags: tags.data.hashtags, - }; - } + const acct = + !type || type === "accounts" + ? await client.search(query.q, "accounts", query) + : null; + const stat = + !type || type === "statuses" + ? await client.search(query.q, "statuses", query) + : null; + const tags = + !type || type === "hashtags" + ? await client.search(query.q, "hashtags", query) + : null; + ctx.body = { + accounts: + acct?.data?.accounts.map((account) => convertAccount(account)) ?? [], + statuses: + stat?.data?.statuses.map((status) => convertStatus(status)) ?? [], + hashtags: tags?.data?.hashtags ?? [], + }; } catch (e: any) { console.error(e); ctx.status = 401;