mirror of
https://github.com/diamondburned/arikawa.git
synced 2024-10-03 08:08:47 +00:00
diamondburned
c6679dc52c
This commit refactors the Store interface in State into smaller interfaces in package store. These interfaces are combined into one structure called a "Cabinet". The default implementation of those interfaces have been rewritten in package defaultstore, while the old no-op implementation stays with the store package. This commit also omitted several state handlers for user events, as it is unclear what they are actually structured like.
163 lines
3.3 KiB
Go
163 lines
3.3 KiB
Go
package defaultstore
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/diamondburned/arikawa/v2/discord"
|
|
"github.com/diamondburned/arikawa/v2/internal/moreatomic"
|
|
"github.com/diamondburned/arikawa/v2/state/store"
|
|
)
|
|
|
|
type Message struct {
|
|
channels moreatomic.Map
|
|
maxMsgs int
|
|
}
|
|
|
|
var _ store.MessageStore = (*Message)(nil)
|
|
|
|
type messages struct {
|
|
mut sync.Mutex
|
|
messages []discord.Message
|
|
}
|
|
|
|
func NewMessage(maxMsgs int) *Message {
|
|
return &Message{
|
|
channels: *moreatomic.NewMap(func() interface{} {
|
|
return &messages{
|
|
messages: []discord.Message{}, // never use a nil slice
|
|
}
|
|
}),
|
|
}
|
|
}
|
|
|
|
func (s *Message) Reset() error {
|
|
return s.channels.Reset()
|
|
}
|
|
|
|
func (s *Message) Message(chID discord.ChannelID, mID discord.MessageID) (*discord.Message, error) {
|
|
iv, ok := s.channels.Load(chID)
|
|
if !ok {
|
|
return nil, store.ErrNotFound
|
|
}
|
|
|
|
msgs := iv.(*messages)
|
|
|
|
msgs.mut.Lock()
|
|
defer msgs.mut.Unlock()
|
|
|
|
for _, m := range msgs.messages {
|
|
if m.ID == mID {
|
|
return &m, nil
|
|
}
|
|
}
|
|
|
|
return nil, store.ErrNotFound
|
|
}
|
|
|
|
func (s *Message) Messages(channelID discord.ChannelID) ([]discord.Message, error) {
|
|
iv, ok := s.channels.Load(channelID)
|
|
if !ok {
|
|
return nil, store.ErrNotFound
|
|
}
|
|
|
|
msgs := iv.(*messages)
|
|
|
|
msgs.mut.Lock()
|
|
defer msgs.mut.Unlock()
|
|
|
|
return append([]discord.Message(nil), msgs.messages...), nil
|
|
}
|
|
|
|
func (s *Message) MaxMessages() int {
|
|
return s.maxMsgs
|
|
}
|
|
|
|
func (s *Message) MessageSet(message discord.Message) error {
|
|
iv, _ := s.channels.LoadOrStore(message.ChannelID)
|
|
|
|
msgs := iv.(*messages)
|
|
|
|
msgs.mut.Lock()
|
|
defer msgs.mut.Unlock()
|
|
|
|
// Check if we already have the message.
|
|
for i, m := range msgs.messages {
|
|
if m.ID == message.ID {
|
|
DiffMessage(message, &m)
|
|
msgs.messages[i] = m
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Order: latest to earliest, similar to the API.
|
|
|
|
var end = len(msgs.messages)
|
|
if max := s.MaxMessages(); end >= max {
|
|
// If the end (length) is larger than the maximum amount, then cap it.
|
|
end = max
|
|
} else {
|
|
// Else, append an empty message to the end.
|
|
msgs.messages = append(msgs.messages, discord.Message{})
|
|
// Increment to update the length.
|
|
end++
|
|
}
|
|
|
|
// Copy hack to prepend. This copies the 0th-(end-1)th entries to
|
|
// 1st-endth.
|
|
copy(msgs.messages[1:end], msgs.messages[0:end-1])
|
|
// Then, set the 0th entry.
|
|
msgs.messages[0] = message
|
|
|
|
return nil
|
|
}
|
|
|
|
// DiffMessage fills non-empty fields from src to dst.
|
|
func DiffMessage(src discord.Message, dst *discord.Message) {
|
|
// Thanks, Discord.
|
|
if src.Content != "" {
|
|
dst.Content = src.Content
|
|
}
|
|
if src.EditedTimestamp.IsValid() {
|
|
dst.EditedTimestamp = src.EditedTimestamp
|
|
}
|
|
if src.Mentions != nil {
|
|
dst.Mentions = src.Mentions
|
|
}
|
|
if src.Embeds != nil {
|
|
dst.Embeds = src.Embeds
|
|
}
|
|
if src.Attachments != nil {
|
|
dst.Attachments = src.Attachments
|
|
}
|
|
if src.Timestamp.IsValid() {
|
|
dst.Timestamp = src.Timestamp
|
|
}
|
|
if src.Author.ID.IsValid() {
|
|
dst.Author = src.Author
|
|
}
|
|
if src.Reactions != nil {
|
|
dst.Reactions = src.Reactions
|
|
}
|
|
}
|
|
|
|
func (s *Message) MessageRemove(channelID discord.ChannelID, messageID discord.MessageID) error {
|
|
iv, ok := s.channels.Load(channelID)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
msgs := iv.(*messages)
|
|
|
|
msgs.mut.Lock()
|
|
defer msgs.mut.Unlock()
|
|
|
|
for i, m := range msgs.messages {
|
|
if m.ID == messageID {
|
|
msgs.messages = append(msgs.messages[:i], msgs.messages[i+1:]...)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|