2020-06-19 01:00:24 +00:00
|
|
|
package segments
|
|
|
|
|
|
|
|
import (
|
2020-12-20 05:44:26 +00:00
|
|
|
"github.com/diamondburned/arikawa/v2/discord"
|
|
|
|
"github.com/diamondburned/arikawa/v2/state/store"
|
2020-10-05 03:45:34 +00:00
|
|
|
"github.com/diamondburned/cchat-discord/internal/segments/embed"
|
|
|
|
"github.com/diamondburned/cchat-discord/internal/segments/renderer"
|
2020-06-19 01:00:24 +00:00
|
|
|
"github.com/diamondburned/cchat/text"
|
2020-12-20 05:44:26 +00:00
|
|
|
"github.com/diamondburned/ningen/v2/md"
|
2020-11-06 06:14:52 +00:00
|
|
|
|
|
|
|
_ "github.com/diamondburned/cchat-discord/internal/segments/blockquote"
|
|
|
|
_ "github.com/diamondburned/cchat-discord/internal/segments/codeblock"
|
|
|
|
_ "github.com/diamondburned/cchat-discord/internal/segments/colored"
|
|
|
|
_ "github.com/diamondburned/cchat-discord/internal/segments/emoji"
|
|
|
|
_ "github.com/diamondburned/cchat-discord/internal/segments/inline"
|
|
|
|
_ "github.com/diamondburned/cchat-discord/internal/segments/link"
|
|
|
|
_ "github.com/diamondburned/cchat-discord/internal/segments/mention"
|
2020-06-19 01:00:24 +00:00
|
|
|
)
|
|
|
|
|
2020-12-20 05:44:26 +00:00
|
|
|
func ParseMessage(m *discord.Message, s store.Cabinet) text.Rich {
|
2020-12-31 02:58:36 +00:00
|
|
|
var rich text.Rich
|
|
|
|
ParseMessageRich(&rich, m, s)
|
|
|
|
return rich
|
|
|
|
}
|
|
|
|
|
|
|
|
func ParseMessageRich(rich *text.Rich, m *discord.Message, s store.Cabinet) {
|
2021-01-07 01:07:29 +00:00
|
|
|
content := []byte(m.Content)
|
2020-07-06 00:18:40 +00:00
|
|
|
|
2021-01-06 02:40:01 +00:00
|
|
|
r := renderer.New(content)
|
2020-12-31 02:58:36 +00:00
|
|
|
r.Buffer.Grow(len(rich.Content))
|
|
|
|
r.Buffer.WriteString(rich.Content)
|
|
|
|
|
2020-07-08 08:35:30 +00:00
|
|
|
// Register the needed states for some renderers.
|
|
|
|
r.WithState(m, s)
|
2021-01-07 01:07:29 +00:00
|
|
|
|
2020-07-08 08:35:30 +00:00
|
|
|
// Render the main message body.
|
2021-01-07 01:07:29 +00:00
|
|
|
if len(content) > 0 {
|
|
|
|
node := md.ParseWithMessage(content, s, m, true)
|
|
|
|
r.Walk(node)
|
|
|
|
}
|
|
|
|
|
2020-07-08 08:35:30 +00:00
|
|
|
// Render the extra bits.
|
2020-10-05 03:45:34 +00:00
|
|
|
embed.RenderAttachments(r, m.Attachments)
|
|
|
|
embed.RenderEmbeds(r, m.Embeds, m, s)
|
2020-07-06 00:18:40 +00:00
|
|
|
|
2020-12-31 02:58:36 +00:00
|
|
|
rich.Content = r.String()
|
|
|
|
rich.Segments = append(rich.Segments, r.Segments...)
|
2020-06-19 01:00:24 +00:00
|
|
|
}
|
|
|
|
|
2021-01-06 02:40:01 +00:00
|
|
|
func ParseWithMessage(b []byte, m *discord.Message, s store.Cabinet) text.Rich {
|
|
|
|
var rich text.Rich
|
|
|
|
ParseWithMessageRich(&rich, b, m, s)
|
|
|
|
return rich
|
|
|
|
}
|
|
|
|
|
|
|
|
func ParseWithMessageRich(rich *text.Rich, b []byte, m *discord.Message, s store.Cabinet) {
|
|
|
|
if len(b) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
node := md.ParseWithMessage(b, s, m, true)
|
|
|
|
|
|
|
|
r := renderer.New(b)
|
|
|
|
r.Buffer.Grow(len(rich.Content))
|
|
|
|
r.Buffer.WriteString(rich.Content)
|
|
|
|
|
|
|
|
r.WithState(m, s)
|
|
|
|
r.Walk(node)
|
|
|
|
|
|
|
|
rich.Content = r.String()
|
|
|
|
rich.Segments = append(rich.Segments, r.Segments...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ellipsize caps the length of the rendered text segment to be not longer than
|
|
|
|
// the given length. The ellipsize will be appended if it is.
|
|
|
|
func Ellipsize(rich text.Rich, maxLen int) text.Rich {
|
2021-01-07 01:07:29 +00:00
|
|
|
ellipsize := maxLen < len(rich.Content)
|
|
|
|
if !ellipsize {
|
|
|
|
maxLen = len(rich.Content)
|
|
|
|
}
|
2021-01-06 02:40:01 +00:00
|
|
|
|
2021-01-07 01:07:29 +00:00
|
|
|
substr := Substring(rich, 0, maxLen)
|
|
|
|
if ellipsize {
|
|
|
|
substr.Content += "…"
|
2021-01-06 02:40:01 +00:00
|
|
|
}
|
|
|
|
|
2021-01-07 01:07:29 +00:00
|
|
|
return substr
|
2021-01-06 02:40:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Substring slices the given rich text.
|
|
|
|
func Substring(rich text.Rich, start, end int) text.Rich {
|
|
|
|
substring := text.Rich{
|
|
|
|
Content: rich.Content[start:end],
|
|
|
|
Segments: make([]text.Segment, 0, len(rich.Segments)),
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, seg := range rich.Segments {
|
|
|
|
i, j := seg.Bounds()
|
|
|
|
|
|
|
|
// Bound-check: check if the starting point is within the range.
|
|
|
|
if start <= i && i <= end {
|
|
|
|
// If the current segment is cleanly within the bound, then we can
|
|
|
|
// directly insert it.
|
|
|
|
if j <= end {
|
|
|
|
substring.Segments = append(substring.Segments, seg)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
substring.Segments = append(substring.Segments, trimmedSegment{
|
|
|
|
Segment: seg,
|
|
|
|
start: i, // preserve the segment's starting point
|
|
|
|
end: end,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return substring
|
|
|
|
}
|
|
|
|
|
|
|
|
type trimmedSegment struct {
|
|
|
|
text.Segment
|
|
|
|
start, end int
|
2020-07-08 08:35:30 +00:00
|
|
|
}
|
2020-12-31 02:58:36 +00:00
|
|
|
|
2021-01-06 02:40:01 +00:00
|
|
|
func (seg trimmedSegment) Bounds() (int, int) {
|
|
|
|
return seg.start, seg.end
|
2020-12-31 02:58:36 +00:00
|
|
|
}
|