startchat: don't allow spamming get contact list request

This commit is contained in:
Tulir Asokan
2025-12-12 14:30:06 +02:00
parent ef65f9f1ea
commit ae05331420
2 changed files with 28 additions and 16 deletions
+2
View File
@@ -102,6 +102,8 @@ type TelegramClient struct {
cachedContacts *tg.ContactsContacts
cachedContactsHash int64
contactsLock sync.Mutex
lastContactReq time.Time
takeoutLock sync.Mutex
takeoutAccepted *exsync.Event
+26 -16
View File
@@ -23,6 +23,7 @@ import (
"regexp"
"strconv"
"strings"
"time"
"github.com/rs/zerolog"
"go.mau.fi/util/ptr"
@@ -200,25 +201,34 @@ func (t *TelegramClient) SearchUsers(ctx context.Context, query string) (resp []
}
func (t *TelegramClient) GetContactList(ctx context.Context) (resp []*bridgev2.ResolveIdentifierResponse, err error) {
contacts, err := APICallWithOnlyUserUpdates(ctx, t, func() (*tg.ContactsContacts, error) {
c, err := t.client.API().ContactsGetContacts(ctx, t.cachedContactsHash)
t.contactsLock.Lock()
defer t.contactsLock.Unlock()
var contacts *tg.ContactsContacts
if time.Since(t.lastContactReq) > 10*time.Minute {
contacts, err = APICallWithOnlyUserUpdates(ctx, t, func() (*tg.ContactsContacts, error) {
c, err := t.client.API().ContactsGetContacts(ctx, t.cachedContactsHash)
if err != nil {
return nil, err
}
switch typedResp := c.(type) {
case *tg.ContactsContacts:
t.cachedContacts = typedResp
var h hasher.Hasher
for _, contact := range t.cachedContacts.Contacts {
h.Update(uint32(contact.UserID))
}
t.cachedContactsHash = h.Sum()
case *tg.ContactsContactsNotModified:
// No changes
default:
return nil, fmt.Errorf("unexpected contacts type: %T", c)
}
return t.cachedContacts, nil
})
if err != nil {
return nil, err
}
if c.TypeID() == tg.ContactsContactsTypeID {
t.cachedContacts = c.(*tg.ContactsContacts)
var h hasher.Hasher
for _, contact := range t.cachedContacts.Contacts {
h.Update(uint32(contact.UserID))
}
t.cachedContactsHash = h.Sum()
} else if c.TypeID() != tg.ContactsContactsNotModifiedTypeID {
return nil, fmt.Errorf("unexpected contacts type: %T", c)
}
return t.cachedContacts, nil
})
if err != nil {
return nil, err
t.lastContactReq = time.Now()
}
users := map[int64]tg.UserClass{}
for _, user := range contacts.GetUsers() {