From afed1e13adf88343cba448ae19f71a2410561d1b Mon Sep 17 00:00:00 2001 From: diamondburned Date: Thu, 13 Aug 2020 16:54:33 -0700 Subject: [PATCH] Separated read-only channels --- category.go | 7 +++- channel.go | 89 +++++++++++-------------------------------- channel_completion.go | 6 +-- channel_memberlist.go | 1 + channel_send.go | 76 ++++++++++++++++++++++++++++++++++++ guild.go | 6 ++- 6 files changed, 114 insertions(+), 71 deletions(-) create mode 100644 channel_memberlist.go create mode 100644 channel_send.go diff --git a/category.go b/category.go index 3615b66..febb56f 100644 --- a/category.go +++ b/category.go @@ -59,7 +59,12 @@ func (c *Category) Servers(container cchat.ServersContainer) error { var chv = make([]cchat.Server, len(chs)) for i := range chs { - chv[i] = NewChannel(c.session, chs[i]) + c, err := NewChannel(c.session, chs[i]) + if err != nil { + return errors.Wrapf(err, "Failed to make channel %s: %v", chs[i].Name, err) + } + + chv[i] = c } container.SetServers(chv) diff --git a/channel.go b/channel.go index 646259b..6b1ce8f 100644 --- a/channel.go +++ b/channel.go @@ -5,7 +5,6 @@ import ( "sort" "time" - "github.com/diamondburned/arikawa/api" "github.com/diamondburned/arikawa/discord" "github.com/diamondburned/arikawa/gateway" "github.com/diamondburned/cchat" @@ -67,19 +66,31 @@ type Channel struct { } var ( - _ cchat.Server = (*Channel)(nil) - _ cchat.ServerMessage = (*Channel)(nil) - _ cchat.ServerMessageSender = (*Channel)(nil) - _ cchat.ServerMessageAttachmentSender = (*Channel)(nil) - _ cchat.ServerMessageSendCompleter = (*Channel)(nil) - _ cchat.ServerNickname = (*Channel)(nil) - _ cchat.ServerMessageEditor = (*Channel)(nil) - _ cchat.ServerMessageActioner = (*Channel)(nil) - _ cchat.ServerMessageTypingIndicator = (*Channel)(nil) - _ cchat.ServerMessageUnreadIndicator = (*Channel)(nil) + _ cchat.Server = (*Channel)(nil) + _ cchat.ServerMessage = (*Channel)(nil) + _ cchat.ServerNickname = (*Channel)(nil) + _ cchat.ServerMessageEditor = (*Channel)(nil) + _ cchat.ServerMessageActioner = (*Channel)(nil) + _ cchat.ServerMessageTypingIndicator = (*Channel)(nil) + _ cchat.ServerMessageUnreadIndicator = (*Channel)(nil) ) -func NewChannel(s *Session, ch discord.Channel) *Channel { +func NewChannel(s *Session, ch discord.Channel) (cchat.Server, error) { + p, err := s.Permissions(ch.ID, s.userID) + if err != nil { + return nil, errors.Wrap(err, "Failed to get permission") + } + + var channel = NewROChannel(s, ch) + if p.Has(discord.PermissionSendMessages) { + return NewSendableChannel(channel), nil + } + return channel, nil +} + +// NewROChannel creates a new read-only channel. This function is mainly used +// internally. +func NewROChannel(s *Session, ch discord.Channel) *Channel { return &Channel{ id: ch.ID, guildID: ch.GuildID, @@ -276,37 +287,6 @@ func (ch *Channel) JoinServer(ctx context.Context, ct cchat.MessagesContainer) ( return joinCancels(addcancel()), nil } -func (ch *Channel) SendMessage(msg cchat.SendableMessage) error { - var send = api.SendMessageData{Content: msg.Content()} - if noncer, ok := msg.(cchat.MessageNonce); ok { - send.Nonce = noncer.Nonce() - } - if attcher, ok := msg.(cchat.SendableMessageAttachments); ok { - send.Files = addAttachments(attcher.Attachments()) - } - - _, err := ch.session.SendMessageComplex(ch.id, send) - return err -} - -func (ch *Channel) SendAttachments(atts []cchat.MessageAttachment) error { - _, err := ch.session.SendMessageComplex(ch.id, api.SendMessageData{ - Files: addAttachments(atts), - }) - return err -} - -func addAttachments(atts []cchat.MessageAttachment) []api.SendMessageFile { - var files = make([]api.SendMessageFile, len(atts)) - for i, a := range atts { - files[i] = api.SendMessageFile{ - Name: a.Name, - Reader: a, - } - } - return files -} - // MessageEditable returns true if the given message ID belongs to the current // user. func (ch *Channel) MessageEditable(id string) bool { @@ -434,29 +414,6 @@ func (ch *Channel) canManageMessages(userID discord.Snowflake) bool { return p.Has(discord.PermissionManageMessages) } -// CompleteMessage implements message input completion capability for Discord. -// This method supports user mentions, channel mentions and emojis. -// -// For the individual implementations, refer to channel_completion.go. -func (ch *Channel) CompleteMessage(words []string, i int) (entries []cchat.CompletionEntry) { - var word = words[i] - // Word should have at least a character for the char check. - if len(word) < 1 { - return - } - - switch word[0] { - case '@': - return ch.completeMentions(word[1:]) - case '#': - return ch.completeChannels(word[1:]) - case ':': - return ch.completeEmojis(word[1:]) - } - - return -} - func (ch *Channel) Typing() error { return ch.session.Typing(ch.id) } diff --git a/channel_completion.go b/channel_completion.go index a4e96cd..e70d714 100644 --- a/channel_completion.go +++ b/channel_completion.go @@ -32,7 +32,7 @@ func completionUserEntry(s *Session, u discord.User, g *discord.Guild) cchat.Com } } -func (ch *Channel) completeMentions(word string) (entries []cchat.CompletionEntry) { +func (ch *SendableChannel) completeMentions(word string) (entries []cchat.CompletionEntry) { // If there is no input, then we should grab the latest messages. if word == "" { msgs, _ := ch.messages() @@ -120,7 +120,7 @@ func (ch *Channel) completeMentions(word string) (entries []cchat.CompletionEntr return } -func (ch *Channel) completeChannels(word string) (entries []cchat.CompletionEntry) { +func (ch *SendableChannel) completeChannels(word string) (entries []cchat.CompletionEntry) { // Ignore if empty word. if word == "" { return @@ -164,7 +164,7 @@ func (ch *Channel) completeChannels(word string) (entries []cchat.CompletionEntr return } -func (ch *Channel) completeEmojis(word string) (entries []cchat.CompletionEntry) { +func (ch *SendableChannel) completeEmojis(word string) (entries []cchat.CompletionEntry) { // Ignore if empty word. if word == "" { return diff --git a/channel_memberlist.go b/channel_memberlist.go new file mode 100644 index 0000000..d9f7d22 --- /dev/null +++ b/channel_memberlist.go @@ -0,0 +1 @@ +package discord diff --git a/channel_send.go b/channel_send.go new file mode 100644 index 0000000..03f8202 --- /dev/null +++ b/channel_send.go @@ -0,0 +1,76 @@ +package discord + +import ( + "github.com/diamondburned/arikawa/api" + "github.com/diamondburned/cchat" +) + +type SendableChannel struct { + Channel +} + +// NewSendableChannel creates a sendable channel. This function is mainly used +// internally +func NewSendableChannel(ch *Channel) *SendableChannel { + return &SendableChannel{*ch} +} + +var ( + _ cchat.ServerMessageSender = (*SendableChannel)(nil) + _ cchat.ServerMessageSendCompleter = (*SendableChannel)(nil) + _ cchat.ServerMessageAttachmentSender = (*SendableChannel)(nil) +) + +func (ch *SendableChannel) SendMessage(msg cchat.SendableMessage) error { + var send = api.SendMessageData{Content: msg.Content()} + if noncer, ok := msg.(cchat.MessageNonce); ok { + send.Nonce = noncer.Nonce() + } + if attcher, ok := msg.(cchat.SendableMessageAttachments); ok { + send.Files = addAttachments(attcher.Attachments()) + } + + _, err := ch.session.SendMessageComplex(ch.id, send) + return err +} + +func (ch *SendableChannel) SendAttachments(atts []cchat.MessageAttachment) error { + _, err := ch.session.SendMessageComplex(ch.id, api.SendMessageData{ + Files: addAttachments(atts), + }) + return err +} + +func addAttachments(atts []cchat.MessageAttachment) []api.SendMessageFile { + var files = make([]api.SendMessageFile, len(atts)) + for i, a := range atts { + files[i] = api.SendMessageFile{ + Name: a.Name, + Reader: a, + } + } + return files +} + +// CompleteMessage implements message input completion capability for Discord. +// This method supports user mentions, channel mentions and emojis. +// +// For the individual implementations, refer to channel_completion.go. +func (ch *SendableChannel) CompleteMessage(words []string, i int) (entries []cchat.CompletionEntry) { + var word = words[i] + // Word should have at least a character for the char check. + if len(word) < 1 { + return + } + + switch word[0] { + case '@': + return ch.completeMentions(word[1:]) + case '#': + return ch.completeChannels(word[1:]) + case ':': + return ch.completeEmojis(word[1:]) + } + + return +} diff --git a/guild.go b/guild.go index 802c6f7..0da76a5 100644 --- a/guild.go +++ b/guild.go @@ -175,7 +175,11 @@ func (g *Guild) Servers(container cchat.ServersContainer) error { case discord.GuildCategory: chs = append(chs, NewCategory(g.session, ch)) case discord.GuildText: - chs = append(chs, NewChannel(g.session, ch)) + c, err := NewChannel(g.session, ch) + if err != nil { + return errors.Wrapf(err, "Failed to make channel %q: %v", ch.Name, err) + } + chs = append(chs, c) } }