mirror of
https://github.com/diamondburned/cchat-discord.git
synced 2024-12-23 12:56:42 +00:00
105 lines
2.6 KiB
Go
105 lines
2.6 KiB
Go
package hub
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/diamondburned/arikawa/v2/discord"
|
|
"github.com/diamondburned/cchat"
|
|
"github.com/diamondburned/cchat-discord/internal/discord/channel/message/send"
|
|
"github.com/diamondburned/cchat-discord/internal/discord/channel/message/send/complete"
|
|
"github.com/diamondburned/cchat-discord/internal/discord/state"
|
|
"github.com/diamondburned/cchat-discord/internal/discord/state/nonce"
|
|
"github.com/diamondburned/cchat/utils/empty"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// ChannelAdder is used to add a new direct message channel into a container.
|
|
type ChannelAdder interface {
|
|
AddChannel(state *state.Instance, ch *discord.Channel)
|
|
}
|
|
|
|
// TODO: unexport Sender
|
|
|
|
type Sender struct {
|
|
empty.Sender
|
|
adder ChannelAdder
|
|
acList *activeList
|
|
sentMsgs *nonce.Set
|
|
state *state.Instance
|
|
|
|
completers complete.Completer
|
|
}
|
|
|
|
// mentionRegex matche the following:
|
|
//
|
|
// <#123123>
|
|
// <#!12312> // This is OK because we're not sending it.
|
|
// <@123123>
|
|
// <@!12312>
|
|
//
|
|
var mentionRegex = regexp.MustCompile(`(?m)^<(@|#)!?(\d+)> ?`)
|
|
|
|
// wrappedMessage wraps around a SendableMessage to override its content.
|
|
type wrappedMessage struct {
|
|
cchat.SendableMessage
|
|
content string
|
|
}
|
|
|
|
func (wrMsg wrappedMessage) Content() string {
|
|
return wrMsg.content
|
|
}
|
|
|
|
func (s *Sender) CanAttach() bool { return true }
|
|
|
|
func (s *Sender) Send(sendable cchat.SendableMessage) error {
|
|
content := sendable.Content()
|
|
|
|
// Validate message.
|
|
matches := mentionRegex.FindStringSubmatch(content)
|
|
if matches == nil {
|
|
return errors.New("message must start with a user or channel mention")
|
|
}
|
|
|
|
targetID, err := discord.ParseSnowflake(matches[2])
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to parse recipient ID")
|
|
}
|
|
|
|
var channel *discord.Channel
|
|
switch matches[1] {
|
|
case "@":
|
|
channel, _ = s.state.CreatePrivateChannel(discord.UserID(targetID))
|
|
case "#":
|
|
channel, _ = s.state.Channel(discord.ChannelID(targetID))
|
|
}
|
|
if channel == nil {
|
|
return errors.New("unknown channel")
|
|
}
|
|
|
|
switch channel.Type {
|
|
case discord.DirectMessage, discord.GroupDM:
|
|
// valid
|
|
default:
|
|
return errors.New("not a [group] direct message channel")
|
|
}
|
|
|
|
// We should only add the channel if it's not already in the active list.
|
|
if s.acList.add(channel.ID) {
|
|
s.adder.AddChannel(s.state, channel)
|
|
}
|
|
|
|
sendData := send.WrapMessage(s.state, sendable)
|
|
sendData.Content = strings.TrimPrefix(content, matches[0])
|
|
|
|
// Store the nonce.
|
|
s.sentMsgs.Store(sendData.Nonce)
|
|
|
|
_, err = s.state.SendMessageComplex(channel.ID, sendData)
|
|
return errors.Wrap(err, "failed to send message")
|
|
}
|
|
|
|
func (s *Sender) AsCompleter() cchat.Completer {
|
|
return s.completers
|
|
}
|