Take all history attributes into account conscientiously

This commit is contained in:
Bohdan Horbeshko 2025-05-18 04:27:25 -04:00
parent 538b9bca8b
commit f1b5774490
3 changed files with 111 additions and 12 deletions

View file

@ -1118,7 +1118,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
}
}
messages, err := c.getNLastMessages(chatID, limit)
messages, err := c.getNLastMessages(chatID, NewMessageLimitMessages(limit))
if err != nil {
return err.Error(), true, false
}

View file

@ -93,6 +93,44 @@ const (
MembersListBannedAndAdministrators
)
const (
MessageLimitMessages = iota
MessageLimitChars
MessageLimitSince
)
// MessageLimitType is an enum of MUC history limit types
type MessageLimitType int
// MessageLimit stores a MUC history limit
type MessageLimit struct {
Type MessageLimitType
Messages int32
Chars int
Since int64
}
func NewMessageLimitMessages(stanzas int32) *MessageLimit {
var limit MessageLimit
limit.Type = MessageLimitMessages
limit.Messages = stanzas
return &limit
}
func NewMessageLimitChars(chars int) *MessageLimit {
var limit MessageLimit
limit.Type = MessageLimitChars
limit.Chars = chars
return &limit
}
func NewMessageLimitSince(since int64) *MessageLimit {
var limit MessageLimit
limit.Type = MessageLimitSince
limit.Since = since
return &limit
}
// GetContactByUsername resolves username to user id retrieves user and chat information
func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) {
if !c.Online() {
@ -485,7 +523,7 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
}
// JoinMUC saves MUC join fact and sends initialization data
func (c *Client) JoinMUC(chatId int64, resource string, limit int32) {
func (c *Client) JoinMUC(chatId int64, resource string, limit *MessageLimit) {
// save the nickname in this MUC, also as a marker of join
c.locks.mucCacheLock.Lock()
mucState, ok := c.mucCache[chatId]
@ -1915,13 +1953,31 @@ func (c *Client) getLastMessages(id int64, query string, from int64, count int32
})
}
func (c *Client) getNLastMessages(chatID int64, limit int32) ([]*client.Message, error) {
func (c *Client) getNLastMessages(chatID int64, limit *MessageLimit) ([]*client.Message, error) {
var newMessages *client.Messages
var messages []*client.Message
var err error
var fromId int64
var safetyLimit int32
var charsCount int
for _ = range make([]struct{}, limit) { // safety limit
if limit == nil {
return nil, nil
}
switch limit.Type {
case MessageLimitMessages:
safetyLimit = limit.Messages
case MessageLimitChars:
safetyLimit = int32(limit.Chars)
if safetyLimit > 1000 {
safetyLimit = 1000
}
case MessageLimitSince:
safetyLimit = 1000
}
safetyLoop:
for _ = range make([]struct{}, safetyLimit) {
if len(messages) > 0 {
fromId = messages[len(messages)-1].Id
}
@ -1929,17 +1985,46 @@ func (c *Client) getNLastMessages(chatID int64, limit int32) ([]*client.Message,
newMessages, err = c.client.GetChatHistory(&client.GetChatHistoryRequest{
ChatId: chatID,
FromMessageId: fromId,
Limit: limit,
Limit: safetyLimit,
})
if err != nil {
return nil, err
}
messages = append(messages, newMessages.Messages...)
if len(newMessages.Messages) == 0 || len(messages) >= int(limit) {
if len(newMessages.Messages) == 0 {
break
}
for _, message := range newMessages.Messages {
if limit.Type == MessageLimitSince && limit.Since > int64(message.Date) { // durov…
break safetyLoop
}
messages = append(messages, message)
switch limit.Type {
case MessageLimitMessages:
if len(messages) >= int(limit.Messages) {
break safetyLoop
}
case MessageLimitChars:
// rough but why care
if message.Content != nil && message.Content.MessageContentType() == client.TypeMessageText {
textContent, ok := message.Content.(*client.MessageText)
if !ok {
uhOh()
}
if textContent.Text != nil {
charsCount += len(textContent.Text.Text)
if charsCount >= limit.Chars {
break safetyLoop
}
}
}
}
}
}
return messages, nil

View file

@ -7,6 +7,7 @@ import (
"sort"
"strconv"
"strings"
"time"
"dev.narayana.im/narayana/telegabber/persistence"
"dev.narayana.im/narayana/telegabber/telegram"
@ -544,11 +545,24 @@ func handleMUCPresence(s xmpp.Sender, p stanza.Presence, mucExt stanza.MucPresen
return
}
limit, ok := mucExt.History.MaxStanzas.Get()
if !ok {
limit = 20
log.Debugf("%#v", mucExt)
maxStanzas, maxStanzasOk := mucExt.History.MaxStanzas.Get()
maxChars, maxCharsOk := mucExt.History.MaxChars.Get()
seconds, secondsOk := mucExt.History.Seconds.Get()
var limit *telegram.MessageLimit
if maxStanzasOk {
limit = telegram.NewMessageLimitMessages(int32(maxStanzas))
} else if maxCharsOk {
limit = telegram.NewMessageLimitChars(maxChars)
} else if secondsOk {
limit = telegram.NewMessageLimitSince(time.Now().Add(time.Duration(seconds) * -time.Second).Unix())
} else if !mucExt.History.Since.IsZero() {
limit = telegram.NewMessageLimitSince(mucExt.History.Since.Unix())
} else {
limit = telegram.NewMessageLimitMessages(20)
}
session.JoinMUC(chatId, fromResource, int32(limit))
session.JoinMUC(chatId, fromResource, limit)
}
}
}