diff --git a/api_tests/package.json b/api_tests/package.json index d3f72ab9e..27210e47f 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -28,7 +28,7 @@ "eslint": "^9.16.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.5.0", - "lemmy-js-client": "0.20.0-modlog-combined.1", + "lemmy-js-client": "0.20.0-inbox-combined.0", "prettier": "^3.4.2", "ts-jest": "^29.1.0", "typescript": "^5.7.2", diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 79ba15359..2a44eb96f 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -30,8 +30,8 @@ importers: specifier: ^29.5.0 version: 29.7.0(@types/node@22.10.1) lemmy-js-client: - specifier: 0.20.0-modlog-combined.1 - version: 0.20.0-modlog-combined.1 + specifier: 0.20.0-inbox-combined.0 + version: 0.20.0-inbox-combined.0 prettier: specifier: ^3.4.2 version: 3.4.2 @@ -1166,8 +1166,8 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - lemmy-js-client@0.20.0-modlog-combined.1: - resolution: {integrity: sha512-TL7Vk/G25xALDNDdc5UGgxPNUw2EML33Rh5+1F/0u126RC+l4uoLZvFAczSgu0Na3qDedjMPFnDpvsA60OrlTw==} + lemmy-js-client@0.20.0-inbox-combined.0: + resolution: {integrity: sha512-JHUwr5UabGf12EETBtYf149Ye0r2nQBdKSpR7FnEuyc7dcAV1gAmYooVurgDcagqf6Xim0UwUTPDyvTaLGeJnQ==} leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} @@ -3078,7 +3078,7 @@ snapshots: kleur@3.0.3: {} - lemmy-js-client@0.20.0-modlog-combined.1: {} + lemmy-js-client@0.20.0-inbox-combined.0: {} leven@3.1.0: {} diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 0a937847e..c60d4fda2 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -16,7 +16,6 @@ import { editComment, deleteComment, removeComment, - getMentions, resolvePost, unfollowRemotes, createCommunity, @@ -27,7 +26,6 @@ import { getComments, getCommentParentId, resolveCommunity, - getReplies, getUnreadCount, waitUntil, waitForPost, @@ -38,11 +36,14 @@ import { saveUserSettings, listReports, listPersonContent, + listInbox, } from "./shared"; import { + CommentReplyView, CommentReportView, CommentView, CommunityView, + PersonCommentMentionView, ReportCombinedView, SaveUserSettings, } from "lemmy-js-client"; @@ -356,7 +357,7 @@ test("Federated comment like", async () => { }); test("Reply to a comment from another instance, get notification", async () => { - await alpha.markAllAsRead(); + await alpha.markAllNotificationsAsRead(); let betaCommunity = ( await waitUntil( @@ -423,18 +424,18 @@ test("Reply to a comment from another instance, get notification", async () => { // Did alpha get notified of the reply from beta? let alphaUnreadCountRes = await waitUntil( () => getUnreadCount(alpha), - e => e.replies >= 1, + e => e.count >= 1, ); - expect(alphaUnreadCountRes.replies).toBeGreaterThanOrEqual(1); + expect(alphaUnreadCountRes.count).toBeGreaterThanOrEqual(1); // check inbox of replies on alpha, fetching read/unread both let alphaRepliesRes = await waitUntil( - () => getReplies(alpha), - r => r.replies.length > 0, - ); - const alphaReply = alphaRepliesRes.replies.find( - r => r.comment.id === alphaComment.comment.id, + () => listInbox(alpha, "CommentReply"), + r => r.inbox.length > 0, ); + const alphaReply = alphaRepliesRes.inbox.find( + r => r.type_ == "CommentReply" && r.comment.id === alphaComment.comment.id, + ) as CommentReplyView | undefined; expect(alphaReply).toBeDefined(); if (!alphaReply) throw Error(); expect(alphaReply.comment.content).toBeDefined(); @@ -463,7 +464,7 @@ test("Bot reply notifications are filtered when bots are hidden", async () => { throw "Missing alpha community"; } - await alpha.markAllAsRead(); + await alpha.markAllNotificationsAsRead(); form = { show_bot_accounts: false, }; @@ -478,10 +479,7 @@ test("Bot reply notifications are filtered when bots are hidden", async () => { expect(commentRes).toBeDefined(); let alphaUnreadCountRes = await getUnreadCount(alpha); - expect(alphaUnreadCountRes.replies).toBe(0); - - let alphaUnreadRepliesRes = await getReplies(alpha, true); - expect(alphaUnreadRepliesRes.replies.length).toBe(0); + expect(alphaUnreadCountRes.count).toBe(0); // This both restores the original state that may be expected by other tests // implicitly and is used by the next steps to ensure replies are still @@ -492,16 +490,16 @@ test("Bot reply notifications are filtered when bots are hidden", async () => { await saveUserSettings(alpha, form); alphaUnreadCountRes = await getUnreadCount(alpha); - expect(alphaUnreadCountRes.replies).toBe(1); + expect(alphaUnreadCountRes.count).toBe(1); - alphaUnreadRepliesRes = await getReplies(alpha, true); - expect(alphaUnreadRepliesRes.replies.length).toBe(1); - expect(alphaUnreadRepliesRes.replies[0].comment.id).toBe( + let alphaUnreadRepliesRes = await listInbox(alpha, "CommentReply", true); + expect(alphaUnreadRepliesRes.inbox.length).toBe(1); + expect((alphaUnreadRepliesRes.inbox[0] as CommentReplyView).comment.id).toBe( commentRes.comment_view.comment.id, ); }); -test("Mention beta from alpha", async () => { +test("Mention beta from alpha comment", async () => { if (!betaCommunity) throw Error("no community"); const postOnAlphaRes = await createPost(alpha, betaCommunity.community.id); // Create a new branch, trunk-level comment branch, from alpha instance @@ -548,15 +546,17 @@ test("Mention beta from alpha", async () => { assertCommentFederation(betaRootComment, commentRes.comment_view); let mentionsRes = await waitUntil( - () => getMentions(beta), - m => !!m.mentions[0], + () => listInbox(beta, "CommentMention"), + m => !!m.inbox[0], ); - expect(mentionsRes.mentions[0].comment.content).toBeDefined(); - expect(mentionsRes.mentions[0].community.local).toBe(true); - expect(mentionsRes.mentions[0].creator.local).toBe(false); - expect(mentionsRes.mentions[0].counts.score).toBe(1); + + const firstMention = mentionsRes.inbox[0] as PersonCommentMentionView; + expect(firstMention.comment.content).toBeDefined(); + expect(firstMention.community.local).toBe(true); + expect(firstMention.creator.local).toBe(false); + expect(firstMention.counts.score).toBe(1); // the reply comment with mention should be the most fresh, newest, index 0 - expect(mentionsRes.mentions[0].person_mention.comment_id).toBe( + expect(firstMention.person_comment_mention.comment_id).toBe( betaPostComments.comments[0].comment.id, ); }); @@ -623,15 +623,17 @@ test("A and G subscribe to B (center) A posts, G mentions B, it gets announced t ); // Make sure beta has mentions - let relevantMention = await waitUntil( + let relevantMention = (await waitUntil( () => - getMentions(beta).then(m => - m.mentions.find( - m => m.comment.ap_id === commentRes.comment_view.comment.ap_id, + listInbox(beta, "CommentMention").then(m => + m.inbox.find( + m => + m.type_ == "CommentMention" && + m.comment.ap_id === commentRes.comment_view.comment.ap_id, ), ), e => !!e, - ); + )) as PersonCommentMentionView | undefined; if (!relevantMention) throw Error("could not find mention"); expect(relevantMention.comment.content).toBe(commentContent); expect(relevantMention.community.local).toBe(false); @@ -837,7 +839,7 @@ test("Dont send a comment reply to a blocked community", async () => { // Check beta's inbox count let unreadCount = await getUnreadCount(beta); - expect(unreadCount.replies).toBe(1); + expect(unreadCount.count).toBe(1); // Beta blocks the new beta community let blockRes = await blockCommunity(beta, newCommunityId, true); @@ -857,10 +859,10 @@ test("Dont send a comment reply to a blocked community", async () => { // Check beta's inbox count, make sure it stays the same unreadCount = await getUnreadCount(beta); - expect(unreadCount.replies).toBe(1); + expect(unreadCount.count).toBe(1); - let replies = await getReplies(beta); - expect(replies.replies.length).toBe(1); + let replies = await listInbox(beta, "CommentReply"); + expect(replies.inbox.length).toBe(1); // Unblock the community blockRes = await blockCommunity(beta, newCommunityId, false); diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 52f86e8ef..8ac46de22 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -38,11 +38,13 @@ import { createCommunity, listReports, getMyUser, + listInbox, } from "./shared"; import { PostView } from "lemmy-js-client/dist/types/PostView"; import { AdminBlockInstanceParams } from "lemmy-js-client/dist/types/AdminBlockInstanceParams"; import { EditSite, + PersonPostMentionView, PostReport, PostReportView, ReportCombinedView, @@ -799,6 +801,44 @@ test("Fetch post with redirect", async () => { expect(gammaPost2.post).toBeDefined(); }); +test("Mention beta from alpha post body", async () => { + if (!betaCommunity) throw Error("no community"); + let mentionContent = "A test mention of @lemmy_beta@lemmy-beta:8551"; + + const postOnAlphaRes = await createPost( + alpha, + betaCommunity.community.id, + undefined, + mentionContent, + ); + + expect(postOnAlphaRes.post_view.post.body).toBeDefined(); + expect(postOnAlphaRes.post_view.community.local).toBe(false); + expect(postOnAlphaRes.post_view.creator.local).toBe(true); + expect(postOnAlphaRes.post_view.counts.score).toBe(1); + + // get beta's localized copy of the alpha post + let betaPost = await waitForPost(beta, postOnAlphaRes.post_view.post); + if (!betaPost) { + throw "unable to locate post on beta"; + } + expect(betaPost.post.ap_id).toBe(postOnAlphaRes.post_view.post.ap_id); + expect(betaPost.post.name).toBe(postOnAlphaRes.post_view.post.name); + await assertPostFederation(betaPost, postOnAlphaRes.post_view); + + let mentionsRes = await waitUntil( + () => listInbox(beta, "PostMention"), + m => !!m.inbox[0], + ); + + const firstMention = mentionsRes.inbox[0] as PersonPostMentionView; + expect(firstMention.post.body).toBeDefined(); + expect(firstMention.community.local).toBe(true); + expect(firstMention.creator.local).toBe(false); + expect(firstMention.counts.score).toBe(1); + expect(firstMention.person_post_mention.post_id).toBe(betaPost.post.id); +}); + test("Rewrite markdown links", async () => { const community = (await resolveBetaCommunity(beta)).community!; diff --git a/api_tests/src/private_message.spec.ts b/api_tests/src/private_message.spec.ts index 8fd683ff0..8f3b0a36e 100644 --- a/api_tests/src/private_message.spec.ts +++ b/api_tests/src/private_message.spec.ts @@ -1,4 +1,5 @@ jest.setTimeout(120000); +import { PrivateMessageView } from "lemmy-js-client"; import { alpha, beta, @@ -6,11 +7,11 @@ import { followBeta, createPrivateMessage, editPrivateMessage, - listPrivateMessages, deletePrivateMessage, waitUntil, reportPrivateMessage, unfollows, + listInbox, } from "./shared"; let recipient_id: number; @@ -31,13 +32,14 @@ test("Create a private message", async () => { expect(pmRes.private_message_view.recipient.local).toBe(false); let betaPms = await waitUntil( - () => listPrivateMessages(beta), - e => !!e.private_messages[0], + () => listInbox(beta, "PrivateMessage"), + e => !!e.inbox[0], ); - expect(betaPms.private_messages[0].private_message.content).toBeDefined(); - expect(betaPms.private_messages[0].private_message.local).toBe(false); - expect(betaPms.private_messages[0].creator.local).toBe(false); - expect(betaPms.private_messages[0].recipient.local).toBe(true); + const firstPm = betaPms.inbox[0] as PrivateMessageView; + expect(firstPm.private_message.content).toBeDefined(); + expect(firstPm.private_message.local).toBe(false); + expect(firstPm.creator.local).toBe(false); + expect(firstPm.recipient.local).toBe(true); }); test("Update a private message", async () => { @@ -53,10 +55,12 @@ test("Update a private message", async () => { ); let betaPms = await waitUntil( - () => listPrivateMessages(beta), - p => p.private_messages[0].private_message.content === updatedContent, + () => listInbox(beta, "PrivateMessage"), + p => + p.inbox[0].type_ == "PrivateMessage" && + p.inbox[0].private_message.content === updatedContent, ); - expect(betaPms.private_messages[0].private_message.content).toBe( + expect((betaPms.inbox[0] as PrivateMessageView).private_message.content).toBe( updatedContent, ); }); @@ -64,12 +68,13 @@ test("Update a private message", async () => { test("Delete a private message", async () => { let pmRes = await createPrivateMessage(alpha, recipient_id); let betaPms1 = await waitUntil( - () => listPrivateMessages(beta), + () => listInbox(beta, "PrivateMessage"), m => - !!m.private_messages.find( + !!m.inbox.find( e => + e.type_ == "PrivateMessage" && e.private_message.ap_id === - pmRes.private_message_view.private_message.ap_id, + pmRes.private_message_view.private_message.ap_id, ), ); let deletedPmRes = await deletePrivateMessage( @@ -83,12 +88,10 @@ test("Delete a private message", async () => { // even though they are in the actual database. // no reason to show them let betaPms2 = await waitUntil( - () => listPrivateMessages(beta), - p => p.private_messages.length === betaPms1.private_messages.length - 1, - ); - expect(betaPms2.private_messages.length).toBe( - betaPms1.private_messages.length - 1, + () => listInbox(beta, "PrivateMessage"), + p => p.inbox.length === betaPms1.inbox.length - 1, ); + expect(betaPms2.inbox.length).toBe(betaPms1.inbox.length - 1); // Undelete let undeletedPmRes = await deletePrivateMessage( @@ -101,26 +104,25 @@ test("Delete a private message", async () => { ); let betaPms3 = await waitUntil( - () => listPrivateMessages(beta), - p => p.private_messages.length === betaPms1.private_messages.length, - ); - expect(betaPms3.private_messages.length).toBe( - betaPms1.private_messages.length, + () => listInbox(beta, "PrivateMessage"), + p => p.inbox.length === betaPms1.inbox.length, ); + expect(betaPms3.inbox.length).toBe(betaPms1.inbox.length); }); test("Create a private message report", async () => { let pmRes = await createPrivateMessage(alpha, recipient_id); let betaPms1 = await waitUntil( - () => listPrivateMessages(beta), + () => listInbox(beta, "PrivateMessage"), m => - !!m.private_messages.find( + !!m.inbox.find( e => + e.type_ == "PrivateMessage" && e.private_message.ap_id === - pmRes.private_message_view.private_message.ap_id, + pmRes.private_message_view.private_message.ap_id, ), ); - let betaPm = betaPms1.private_messages[0]; + let betaPm = betaPms1.inbox[0] as PrivateMessageView; expect(betaPm).toBeDefined(); // Make sure that only the recipient can report it, so this should fail diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 771b1dc57..1bb1e7d0e 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -7,8 +7,6 @@ import { CreatePrivateMessageReport, EditCommunity, GetCommunityPendingFollowsCountResponse, - GetReplies, - GetRepliesResponse, GetUnreadCountResponse, InstanceId, LemmyHttp, @@ -26,6 +24,9 @@ import { ListPersonContentResponse, ListPersonContent, PersonContentType, + ListInboxResponse, + ListInbox, + InboxDataType, } from "lemmy-js-client"; import { CreatePost } from "lemmy-js-client/dist/types/CreatePost"; import { DeletePost } from "lemmy-js-client/dist/types/DeletePost"; @@ -59,8 +60,6 @@ import { CreateComment } from "lemmy-js-client/dist/types/CreateComment"; import { EditComment } from "lemmy-js-client/dist/types/EditComment"; import { DeleteComment } from "lemmy-js-client/dist/types/DeleteComment"; import { RemoveComment } from "lemmy-js-client/dist/types/RemoveComment"; -import { GetPersonMentionsResponse } from "lemmy-js-client/dist/types/GetPersonMentionsResponse"; -import { GetPersonMentions } from "lemmy-js-client/dist/types/GetPersonMentions"; import { CreateCommentLike } from "lemmy-js-client/dist/types/CreateCommentLike"; import { CreateCommunity } from "lemmy-js-client/dist/types/CreateCommunity"; import { GetCommunity } from "lemmy-js-client/dist/types/GetCommunity"; @@ -75,8 +74,6 @@ import { Register } from "lemmy-js-client/dist/types/Register"; import { SaveUserSettings } from "lemmy-js-client/dist/types/SaveUserSettings"; import { DeleteAccount } from "lemmy-js-client/dist/types/DeleteAccount"; import { GetSiteResponse } from "lemmy-js-client/dist/types/GetSiteResponse"; -import { PrivateMessagesResponse } from "lemmy-js-client/dist/types/PrivateMessagesResponse"; -import { GetPrivateMessages } from "lemmy-js-client/dist/types/GetPrivateMessages"; import { PostReportResponse } from "lemmy-js-client/dist/types/PostReportResponse"; import { CreatePostReport } from "lemmy-js-client/dist/types/CreatePostReport"; import { CommentReportResponse } from "lemmy-js-client/dist/types/CommentReportResponse"; @@ -377,15 +374,16 @@ export async function getUnreadCount( return api.getUnreadCount(); } -export async function getReplies( +export async function listInbox( api: LemmyHttp, + type_?: InboxDataType, unread_only: boolean = false, -): Promise { - let form: GetReplies = { - sort: "New", +): Promise { + let form: ListInbox = { unread_only, + type_, }; - return api.getReplies(form); + return api.listInbox(form); } export async function resolveComment( @@ -542,16 +540,6 @@ export async function removeComment( return api.removeComment(form); } -export async function getMentions( - api: LemmyHttp, -): Promise { - let form: GetPersonMentions = { - sort: "New", - unread_only: false, - }; - return api.getPersonMentions(form); -} - export async function likeComment( api: LemmyHttp, score: number, @@ -777,15 +765,6 @@ export async function getMyUser(api: LemmyHttp): Promise { return api.getMyUser(); } -export async function listPrivateMessages( - api: LemmyHttp, -): Promise { - let form: GetPrivateMessages = { - unread_only: false, - }; - return api.getPrivateMessages(form); -} - export async function unfollowRemotes(api: LemmyHttp): Promise { // Unfollow all remote communities let my_user = await getMyUser(api); diff --git a/src/api_routes_v4.rs b/src/api_routes_v4.rs index 396320608..af289710e 100644 --- a/src/api_routes_v4.rs +++ b/src/api_routes_v4.rs @@ -333,10 +333,7 @@ pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) { "/mention/post/mark_as_read", post().to(mark_post_mention_as_read), ) - .route( - "/mark_as_read/all", - post().to(mark_all_notifications_read), - ) + .route("/mark_as_read/all", post().to(mark_all_notifications_read)) .route("/report_count", get().to(report_count)) .route("/unread_count", get().to(unread_count)) .route("/list_logins", get().to(list_logins))