mirror of
https://github.com/diamondburned/cchat-discord.git
synced 2025-01-08 20:16:45 +00:00
Added message reference read support
This commit is contained in:
parent
6beff52250
commit
96e97aa117
|
@ -56,13 +56,6 @@ func richMember(
|
|||
|
||||
start, end = segutil.Write(rich, displayName)
|
||||
|
||||
// Update the color.
|
||||
if c := discord.MemberColor(g, m); c > 0 {
|
||||
rich.Segments = append(rich.Segments,
|
||||
colored.NewSegment(start, end, c.Uint32()),
|
||||
)
|
||||
}
|
||||
|
||||
// Append the bot prefix if the user is a bot.
|
||||
if m.User.Bot {
|
||||
rich.Content += " "
|
||||
|
@ -157,6 +150,7 @@ func (a *Author) AddMessageReference(msgref discord.Message, s *state.Instance)
|
|||
m, err := s.Cabinet.Member(g.ID, msgref.Author.ID)
|
||||
if err != nil {
|
||||
a.addAuthorReference(msgref, s)
|
||||
s.MemberState.RequestMember(msgref.GuildID, msgref.Author.ID)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/diamondburned/cchat-discord/internal/discord/state"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/mention"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/reference"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
)
|
||||
|
||||
|
@ -101,6 +102,11 @@ func NewMessageUpdateContent(msg discord.Message, s *state.Instance) Message {
|
|||
func NewMessageUpdateAuthor(
|
||||
msg discord.Message, member discord.Member, g discord.Guild, s *state.Instance) Message {
|
||||
|
||||
author := NewGuildMember(member, g, s)
|
||||
if ref := ReferencedMessage(msg, s, true); ref != nil {
|
||||
author.AddMessageReference(*ref, s)
|
||||
}
|
||||
|
||||
return Message{
|
||||
messageHeader: newHeader(msg),
|
||||
author: NewGuildMember(member, g, s),
|
||||
|
@ -156,8 +162,25 @@ func NewDirectMessage(m discord.Message, s *state.Instance) Message {
|
|||
}
|
||||
|
||||
func NewMessage(m discord.Message, s *state.Instance, author Author) Message {
|
||||
var content text.Rich
|
||||
|
||||
if ref := ReferencedMessage(m, s, true); ref != nil {
|
||||
// TODO: markup support
|
||||
var refmsg = "> " + ref.Content
|
||||
if len(refmsg) > 120 {
|
||||
refmsg = refmsg[:120] + "..."
|
||||
}
|
||||
|
||||
content.Content = refmsg + "\n"
|
||||
content.Segments = []text.Segment{
|
||||
reference.NewMessageSegment(0, len(refmsg), ref.ID),
|
||||
}
|
||||
|
||||
author.AddMessageReference(*ref, s)
|
||||
}
|
||||
|
||||
// Render the message content.
|
||||
var content = segments.ParseMessage(&m, s.Cabinet)
|
||||
segments.ParseMessageRich(&content, &m, s.Cabinet)
|
||||
|
||||
// Request members in mentions if we're in a guild.
|
||||
if m.GuildID.IsValid() {
|
||||
|
@ -206,3 +229,23 @@ func (m Message) Nonce() string {
|
|||
func (m Message) Mentioned() bool {
|
||||
return m.mentioned
|
||||
}
|
||||
|
||||
// ReferencedMessage searches for the referenced message if needed.
|
||||
func ReferencedMessage(m discord.Message, s *state.Instance, wait bool) (reply *discord.Message) {
|
||||
if m.ReferencedMessage != nil {
|
||||
return m.ReferencedMessage
|
||||
}
|
||||
|
||||
// Deleted or does not exist.
|
||||
if m.Reference == nil || !m.Reference.MessageID.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !wait {
|
||||
reply, _ = s.Cabinet.Message(m.Reference.ChannelID, m.Reference.MessageID)
|
||||
} else {
|
||||
reply, _ = s.Message(m.Reference.ChannelID, m.Reference.MessageID)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,10 +18,19 @@ import (
|
|||
)
|
||||
|
||||
func ParseMessage(m *discord.Message, s store.Cabinet) text.Rich {
|
||||
var rich text.Rich
|
||||
ParseMessageRich(&rich, m, s)
|
||||
return rich
|
||||
}
|
||||
|
||||
func ParseMessageRich(rich *text.Rich, m *discord.Message, s store.Cabinet) {
|
||||
var content = []byte(m.Content)
|
||||
var node = md.ParseWithMessage(content, s, m, true)
|
||||
|
||||
r := renderer.New(content, node)
|
||||
r.Buffer.Grow(len(rich.Content))
|
||||
r.Buffer.WriteString(rich.Content)
|
||||
|
||||
// Register the needed states for some renderers.
|
||||
r.WithState(m, s)
|
||||
// Render the main message body.
|
||||
|
@ -30,13 +39,16 @@ func ParseMessage(m *discord.Message, s store.Cabinet) text.Rich {
|
|||
embed.RenderAttachments(r, m.Attachments)
|
||||
embed.RenderEmbeds(r, m.Embeds, m, s)
|
||||
|
||||
return text.Rich{
|
||||
Content: r.String(),
|
||||
Segments: r.Segments,
|
||||
}
|
||||
rich.Content = r.String()
|
||||
rich.Segments = append(rich.Segments, r.Segments...)
|
||||
}
|
||||
|
||||
func ParseWithMessage(b []byte, m *discord.Message, s store.Cabinet, msg bool) text.Rich {
|
||||
node := md.ParseWithMessage(b, s, m, msg)
|
||||
return renderer.RenderNode(b, node)
|
||||
}
|
||||
|
||||
func ParseWithMessageRich(b []byte, m *discord.Message, s store.Cabinet, msg bool) text.Rich {
|
||||
node := md.ParseWithMessage(b, s, m, msg)
|
||||
return renderer.RenderNode(b, node)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mention
|
||||
|
||||
import (
|
||||
"github.com/diamondburned/arikawa/v2/discord"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/renderer"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
"github.com/diamondburned/cchat/utils/empty"
|
||||
|
@ -55,7 +56,7 @@ func (s Segment) Bounds() (start, end int) {
|
|||
|
||||
func (s Segment) AsColorer() text.Colorer {
|
||||
switch {
|
||||
case s.User != nil:
|
||||
case s.User != nil && s.User.HasColor():
|
||||
return s.User
|
||||
case s.Role != nil:
|
||||
return s.Role
|
||||
|
@ -81,3 +82,23 @@ func (s Segment) AsMentioner() text.Mentioner {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MemberColor(guild discord.Guild, member discord.Member) (c uint32, ok bool) {
|
||||
var pos int
|
||||
|
||||
for _, r := range guild.Roles {
|
||||
for _, mr := range member.RoleIDs {
|
||||
if mr != r.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
if r.Color > 0 && r.Position > pos {
|
||||
c = r.Color.Uint32()
|
||||
ok = true
|
||||
pos = r.Position
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/diamondburned/cchat-discord/internal/segments/colored"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/inline"
|
||||
"github.com/diamondburned/cchat-discord/internal/segments/segutil"
|
||||
"github.com/diamondburned/cchat-discord/internal/urlutils"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
"github.com/diamondburned/cchat/utils/empty"
|
||||
"github.com/diamondburned/ningen/v2"
|
||||
|
@ -63,7 +64,7 @@ func (m NameSegment) AsAvatarer() text.Avatarer { return &m.um }
|
|||
// AsColorer only returns User if the user actually has a colored role.
|
||||
func (m NameSegment) AsColorer() text.Colorer {
|
||||
if m.um.HasColor() {
|
||||
return &m.um
|
||||
return m.um
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -82,8 +83,7 @@ var (
|
|||
_ text.Mentioner = (*User)(nil)
|
||||
)
|
||||
|
||||
// NewUser creates a new user mention. If state is of type *ningen.State, then
|
||||
// it'll fetch additional information asynchronously.
|
||||
// NewUser creates a new user mention.
|
||||
func NewUser(store store.Cabinet, guild discord.GuildID, guser discord.GuildUser) *User {
|
||||
if guser.Member == nil {
|
||||
m, err := store.Member(guild, guser.ID)
|
||||
|
@ -111,6 +111,7 @@ func NewUser(store store.Cabinet, guild discord.GuildID, guser discord.GuildUser
|
|||
|
||||
func (um *User) WithState(state *ningen.State) {
|
||||
um.ningen = state
|
||||
um.store = state.Cabinet
|
||||
}
|
||||
|
||||
// HasColor returns true if the current user has a color.
|
||||
|
@ -125,7 +126,8 @@ func (um User) HasColor() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
return discord.MemberColor(*g, um.Member) > 0
|
||||
_, ok := MemberColor(*g, um.Member)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (um User) Color() uint32 {
|
||||
|
@ -134,12 +136,12 @@ func (um User) Color() uint32 {
|
|||
return colored.Blurple
|
||||
}
|
||||
|
||||
var color = discord.MemberColor(*g, um.Member)
|
||||
if color == 0 {
|
||||
color, ok := MemberColor(*g, um.Member)
|
||||
if !ok {
|
||||
return colored.Blurple
|
||||
}
|
||||
|
||||
return text.SolidColor(color.Uint32())
|
||||
return text.SolidColor(color)
|
||||
}
|
||||
|
||||
func (um User) AvatarSize() int {
|
||||
|
@ -154,7 +156,7 @@ func (um User) AvatarText() string {
|
|||
}
|
||||
|
||||
func (um User) Avatar() (url string) {
|
||||
return um.Member.User.AvatarURL()
|
||||
return urlutils.AvatarURL(um.Member.User.AvatarURL())
|
||||
}
|
||||
|
||||
func (um User) MentionInfo() text.Rich {
|
||||
|
|
|
@ -21,6 +21,8 @@ func Register(kind ast.NodeKind, r Renderer) {
|
|||
renderers[kind] = r
|
||||
}
|
||||
|
||||
var smallRenderers = map[ast.NodeKind]Renderer{}
|
||||
|
||||
// Parse parses the raw Markdown bytes into a rich text.
|
||||
func Parse(b []byte) text.Rich {
|
||||
node := md.Parse(b)
|
||||
|
@ -188,10 +190,10 @@ func (r *Text) RenderNode(n ast.Node, enter bool) (ast.WalkStatus, error) {
|
|||
switch n := n.(type) {
|
||||
case *ast.Document:
|
||||
case *ast.Paragraph:
|
||||
if !enter {
|
||||
// TODO: investigate
|
||||
// r.Buffer.WriteByte('\n')
|
||||
}
|
||||
// if !enter {
|
||||
// TODO: investigate
|
||||
// r.Buffer.WriteByte('\n')
|
||||
// }
|
||||
case *ast.String:
|
||||
if enter {
|
||||
r.Buffer.Write(n.Value)
|
||||
|
|
Loading…
Reference in a new issue