reply.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package gomatrix
  2. import (
  3. "fmt"
  4. "regexp"
  5. "strings"
  6. "golang.org/x/net/html"
  7. )
  8. var HTMLReplyFallbackRegex = regexp.MustCompile(`^<mx-reply>[\s\S]+?</mx-reply>`)
  9. func TrimReplyFallbackHTML(html string) string {
  10. return HTMLReplyFallbackRegex.ReplaceAllString(html, "")
  11. }
  12. func TrimReplyFallbackText(text string) string {
  13. if !strings.HasPrefix(text, "> ") || !strings.Contains(text, "\n") {
  14. return text
  15. }
  16. lines := strings.Split(text, "\n")
  17. for len(lines) > 0 && strings.HasPrefix(lines[0], "> ") {
  18. lines = lines[1:]
  19. }
  20. return strings.TrimSpace(strings.Join(lines, "\n"))
  21. }
  22. func (content *Content) RemoveReplyFallback() {
  23. if len(content.GetReplyTo()) > 0 {
  24. if content.Format == FormatHTML {
  25. content.FormattedBody = TrimReplyFallbackHTML(content.FormattedBody)
  26. }
  27. content.Body = TrimReplyFallbackText(content.Body)
  28. }
  29. }
  30. func (content *Content) GetReplyTo() string {
  31. if content.RelatesTo != nil {
  32. return content.RelatesTo.InReplyTo.EventID
  33. }
  34. return ""
  35. }
  36. const ReplyFormat = `<mx-reply><blockquote>
  37. <a href="https://matrix.to/#/%s/%s">In reply to</a>
  38. <a href="https://matrix.to/#/%s">%s</a>
  39. %s
  40. </blockquote></mx-reply>
  41. `
  42. func (evt *Event) GenerateReplyFallbackHTML() string {
  43. body := evt.Content.FormattedBody
  44. if len(body) == 0 {
  45. body = html.EscapeString(evt.Content.Body)
  46. }
  47. senderDisplayName := evt.Sender
  48. return fmt.Sprintf(ReplyFormat, evt.RoomID, evt.ID, evt.Sender, senderDisplayName, body)
  49. }
  50. func (evt *Event) GenerateReplyFallbackText() string {
  51. body := evt.Content.Body
  52. lines := strings.Split(strings.TrimSpace(body), "\n")
  53. firstLine, lines := lines[0], lines[1:]
  54. senderDisplayName := evt.Sender
  55. var fallbackText strings.Builder
  56. fmt.Fprintf(&fallbackText, "> <%s> %s", senderDisplayName, firstLine)
  57. for _, line := range lines {
  58. fmt.Fprintf(&fallbackText, "\n> %s", line)
  59. }
  60. fallbackText.WriteString("\n\n")
  61. return fallbackText.String()
  62. }
  63. func (content *Content) SetReply(inReplyTo *Event) {
  64. if content.RelatesTo == nil {
  65. content.RelatesTo = &RelatesTo{}
  66. }
  67. content.RelatesTo.InReplyTo = InReplyTo{
  68. EventID: inReplyTo.ID,
  69. RoomID: inReplyTo.RoomID,
  70. }
  71. if content.MsgType == MsgText || content.MsgType == MsgNotice {
  72. if len(content.FormattedBody) == 0 || content.Format != FormatHTML {
  73. content.FormattedBody = html.EscapeString(content.Body)
  74. content.Format = FormatHTML
  75. }
  76. content.FormattedBody = inReplyTo.GenerateReplyFallbackHTML() + content.FormattedBody
  77. content.Body = inReplyTo.GenerateReplyFallbackText() + content.Body
  78. }
  79. }