idecnode/pkg/idec/message.go

183 lines
3.8 KiB
Go

package idec
import (
"encoding/base64"
"fmt"
"log"
"strings"
"gitrepo.ru/neonxp/idecnode/pkg/model"
"go.etcd.io/bbolt"
)
func (i *IDEC) GetMessageIDsByEcho(echoID string, offset, limit int) ([]string, int, error) {
messages := make([]string, 0, limit)
count := 0
return messages, count, i.db.View(func(tx *bbolt.Tx) error {
if _, ok := i.config.Echos[echoID]; !ok {
return nil
}
bEcho := tx.Bucket([]byte(echoID))
if bEcho == nil {
return nil
}
count = bEcho.Stats().KeyN
cur := bEcho.Cursor()
cur.First()
if limit == 0 {
limit = count
}
if offset < 0 {
offset = max(0, count+offset-1)
}
for i := 0; i < offset; i++ {
// skip offset entries
cur.Next()
}
for i := 0; i < limit; i++ {
_, v := cur.Next()
if v == nil {
break
}
messages = append(messages, string(v))
}
return nil
})
}
func (i *IDEC) GetMessagesByEcho(echoID string, parent string, offset, limit int) ([]*model.Message, error) {
messages := make([]*model.Message, 0, limit)
return messages, i.db.View(func(tx *bbolt.Tx) error {
if _, ok := i.config.Echos[echoID]; !ok {
return nil
}
bEcho := tx.Bucket([]byte(echoID))
if bEcho == nil {
return nil
}
bMessages := tx.Bucket([]byte(msgBucket))
if bMessages == nil {
return nil
}
count := bEcho.Stats().KeyN
cur := bEcho.Cursor()
cur.First()
if limit == 0 {
limit = count
}
if offset < 0 {
offset = max(0, count+offset-1)
}
for i := 0; i < offset; i++ {
// skip offset entries
cur.Next()
}
for i := 0; len(messages) < limit; i++ {
_, v := cur.Next()
if v == nil {
break
}
msgText := bMessages.Get(v)
msg, err := model.MessageFromBundle(string(v), string(msgText))
if err != nil {
return err
}
if msg.RepTo == parent {
messages = append(messages, msg)
}
}
return nil
})
}
func (i *IDEC) GetMessage(messageID string) (*model.Message, error) {
var msg *model.Message
return msg, i.db.View(func(tx *bbolt.Tx) error {
bucket := tx.Bucket([]byte(msgBucket))
if bucket == nil {
return ErrMessageNotFound
}
b := bucket.Get([]byte(messageID))
var err error
msg, err = model.MessageFromBundle(messageID, string(b))
return err
})
}
func (i *IDEC) GetMessages(messageIDs []string) ([]*model.Message, error) {
msgs := make([]*model.Message, 0, len(messageIDs))
return msgs, i.db.View(func(tx *bbolt.Tx) error {
bucket := tx.Bucket([]byte(msgBucket))
if bucket == nil {
return ErrMessageNotFound
}
for _, messageID := range messageIDs {
b := bucket.Get([]byte(messageID))
msg, err := model.MessageFromBundle(messageID, string(b))
if err != nil {
log.Println(err)
continue
}
msgs = append(msgs, msg)
}
return nil
})
}
func (i *IDEC) SavePointMessage(point string, rawMessage string) error {
rawMessage = strings.NewReplacer("-", "+", "_", "/").Replace(rawMessage)
messageBody, err := base64.StdEncoding.DecodeString(rawMessage)
if err != nil {
return ErrWrongMessageFormat
}
msg, err := model.MessageFromPointMessage(i.config.Node, point, string(messageBody))
if err != nil {
return err
}
return i.SaveMessage(msg)
}
func (i *IDEC) SaveBundleMessage(msgID, text string) error {
msg, err := model.MessageFromBundle(msgID, text)
if err != nil {
return err
}
return i.SaveMessage(msg)
}
func (i *IDEC) SaveMessage(msg *model.Message) error {
return i.db.Update(func(tx *bbolt.Tx) error {
bMessages, err := tx.CreateBucketIfNotExists([]byte(msgBucket))
if err != nil {
return err
}
if err := bMessages.Put([]byte(msg.ID), []byte(msg.Bundle())); err != nil {
return err
}
bEcho, err := tx.CreateBucketIfNotExists([]byte(msg.EchoArea))
if err != nil {
return err
}
bucketKey := fmt.Sprintf("%s.%s", msg.Date.Format("2006.01.02.15.04.05"), msg.ID)
return bEcho.Put([]byte(bucketKey), []byte(msg.ID))
})
}