From ab758cc2336e88d9cd967238310b433e75d500dc Mon Sep 17 00:00:00 2001
From: Vyr Cossont
Date: Fri, 31 Jan 2025 02:40:39 -0800
Subject: [PATCH] [feature] Add system message wrappers for pending replies and
placeholder attachments (#3713)
Fixes #3712
---
internal/typeutils/internaltofrontend_test.go | 4 +-
internal/typeutils/util.go | 38 +++++++++++++++----
2 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/internal/typeutils/internaltofrontend_test.go b/internal/typeutils/internaltofrontend_test.go
index df6edd553..27b6df139 100644
--- a/internal/typeutils/internaltofrontend_test.go
+++ b/internal/typeutils/internaltofrontend_test.go
@@ -1278,7 +1278,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontendUnknownAttachments
"muted": false,
"bookmarked": false,
"pinned": false,
- "content": "\u003cp\u003ehi \u003cspan class=\"h-card\"\u003e\u003ca href=\"http://localhost:8080/@admin\" class=\"u-url mention\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e@\u003cspan\u003eadmin\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e here's some media for ya\u003c/p\u003e\u003chr\u003e\u003cp\u003e\u003ci lang=\"en\"\u003eℹ️ Note from localhost:8080: 2 attachments in this status were not downloaded. Treat the following external links with care:\u003c/i\u003e\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003ca href=\"http://example.org/fileserver/01HE7Y659ZWZ02JM4AWYJZ176Q/attachment/original/01HE7ZGJYTSYMXF927GF9353KR.svg\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e01HE7ZGJYTSYMXF927GF9353KR.svg\u003c/a\u003e [SVG line art of a sloth, public domain]\u003c/li\u003e\u003cli\u003e\u003ca href=\"http://example.org/fileserver/01HE7Y659ZWZ02JM4AWYJZ176Q/attachment/original/01HE892Y8ZS68TQCNPX7J888P3.mp3\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e01HE892Y8ZS68TQCNPX7J888P3.mp3\u003c/a\u003e [Jolly salsa song, public domain.]\u003c/li\u003e\u003c/ul\u003e",
+ "content": "\u003cp\u003ehi \u003cspan class=\"h-card\"\u003e\u003ca href=\"http://localhost:8080/@admin\" class=\"u-url mention\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e@\u003cspan\u003eadmin\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e here's some media for ya\u003c/p\u003e\u003cdiv class=\"gts-system-message gts-placeholder-attachments\"\u003e\u003chr\u003e\u003cp\u003e\u003ci lang=\"en\"\u003eℹ️ Note from localhost:8080: 2 attachments in this status were not downloaded. Treat the following external links with care:\u003c/i\u003e\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003ca href=\"http://example.org/fileserver/01HE7Y659ZWZ02JM4AWYJZ176Q/attachment/original/01HE7ZGJYTSYMXF927GF9353KR.svg\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e01HE7ZGJYTSYMXF927GF9353KR.svg\u003c/a\u003e [SVG line art of a sloth, public domain]\u003c/li\u003e\u003cli\u003e\u003ca href=\"http://example.org/fileserver/01HE7Y659ZWZ02JM4AWYJZ176Q/attachment/original/01HE892Y8ZS68TQCNPX7J888P3.mp3\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e01HE892Y8ZS68TQCNPX7J888P3.mp3\u003c/a\u003e [Jolly salsa song, public domain.]\u003c/li\u003e\u003c/ul\u003e\u003c/div\u003e",
"reblog": null,
"account": {
"id": "01FHMQX3GAABWSM0S2VZEC2SWC",
@@ -1828,7 +1828,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToAPIStatusPendingApproval()
"muted": false,
"bookmarked": false,
"pinned": false,
- "content": "Hi @1happyturtle, can I reply?
ℹ️ Note from localhost:8080: This reply is pending your approval. You can quickly accept it by liking, boosting or replying to it. You can also accept or reject it at the following link: http://localhost:8080/settings/user/interaction_requests/01J5QVXCCEATJYSXM9H6MZT4JR.
",
+ "content": "Hi @1happyturtle, can I reply?
",
"reblog": null,
"application": {
"name": "superseriousbusiness",
diff --git a/internal/typeutils/util.go b/internal/typeutils/util.go
index 1747dbdcd..b4f2e41aa 100644
--- a/internal/typeutils/util.go
+++ b/internal/typeutils/util.go
@@ -128,12 +128,14 @@ func misskeyReportInlineURLs(content string) []*url.URL {
//
// Example:
//
-//
-// ℹ️ Note from your.instance.com: 2 attachment(s) in this status were not downloaded. Treat the following external link(s) with care:
-//
+//
+//
+//
ℹ️ Note from your.instance.com: 2 attachment(s) in this status were not downloaded. Treat the following external link(s) with care:
+//
+//
func placeholderAttachments(arr []*apimodel.Attachment) (string, []*apimodel.Attachment) {
// Extract non-locally stored attachments into a
@@ -187,7 +189,7 @@ func placeholderAttachments(arr []*apimodel.Attachment) (string, []*apimodel.Att
}
note.WriteString(``)
- return text.SanitizeToHTML(note.String()), arr
+ return systemMessage("gts-placeholder-attachments", note.String()), arr
}
func (c *Converter) pendingReplyNote(
@@ -228,7 +230,27 @@ func (c *Converter) pendingReplyNote(
note.WriteString(`.`)
note.WriteString(`
`)
- return text.SanitizeToHTML(note.String()), nil
+ return systemMessage("gts-pending-reply", note.String()), nil
+}
+
+// systemMessage wraps a note with a div with semantic classes that aren't allowed through the sanitizer,
+// but may be emitted to the client as an addition to the status's actual content.
+// Clients may want to display these specially or suppress them in favor of their own UI.
+//
+// messageClass must be valid inside an HTML attribute and should be one or more classes starting with `gts-`.
+func systemMessage(
+ messageClass string,
+ unsanitizedNoteHTML string,
+) string {
+ var wrappedNote strings.Builder
+
+ wrappedNote.WriteString(``)
+ wrappedNote.WriteString(text.SanitizeToHTML(unsanitizedNoteHTML))
+ wrappedNote.WriteString(`
`)
+
+ return wrappedNote.String()
}
// ContentToContentLanguage tries to