From ae053314204ef057502cd3cec8fd76cfe5629627 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 12 Dec 2025 14:30:06 +0200 Subject: [PATCH] startchat: don't allow spamming get contact list request --- pkg/connector/client.go | 2 ++ pkg/connector/startchat.go | 42 +++++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/pkg/connector/client.go b/pkg/connector/client.go index 824e8e7e..c489e33d 100644 --- a/pkg/connector/client.go +++ b/pkg/connector/client.go @@ -102,6 +102,8 @@ type TelegramClient struct { cachedContacts *tg.ContactsContacts cachedContactsHash int64 + contactsLock sync.Mutex + lastContactReq time.Time takeoutLock sync.Mutex takeoutAccepted *exsync.Event diff --git a/pkg/connector/startchat.go b/pkg/connector/startchat.go index ae7ab4b1..6126eb1c 100644 --- a/pkg/connector/startchat.go +++ b/pkg/connector/startchat.go @@ -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() {