summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2023-02-13 20:53:50 +0300
committerGeorge Hazan <ghazan@miranda.im>2023-02-13 20:53:50 +0300
commit9c5bcfa55b13b5df3703d4ba8ab9d70527a2587a (patch)
tree9ec5cded86fe3fdef47bba9537a3373c78a30661
parent1856842de4420fe77901759000a7295ae45fb94a (diff)
fixes #3329 (Telegram: implement search and add contacts)
-rw-r--r--protocols/Telegram/src/proto.cpp84
-rw-r--r--protocols/Telegram/src/proto.h43
-rw-r--r--protocols/Telegram/src/server.cpp69
-rw-r--r--protocols/Telegram/src/stdafx.h1
-rw-r--r--protocols/Telegram/src/utils.cpp78
-rw-r--r--protocols/Telegram/src/utils.h3
6 files changed, 223 insertions, 55 deletions
diff --git a/protocols/Telegram/src/proto.cpp b/protocols/Telegram/src/proto.cpp
index 3ac7dcb924..c823679106 100644
--- a/protocols/Telegram/src/proto.cpp
+++ b/protocols/Telegram/src/proto.cpp
@@ -16,6 +16,10 @@ static int CompareRequests(const TG_REQUEST_BASE *p1, const TG_REQUEST_BASE *p2)
return (p1->requestId < p2->requestId) ? -1 : 1;
}
+static int CompareChats(const TG_USER *p1, const TG_USER *p2)
+{ return CompareId(p1->chatId, p2->chatId);
+}
+
static int CompareUsers(const TG_USER *p1, const TG_USER *p2)
{ return CompareId(p1->id, p2->id);
}
@@ -32,7 +36,8 @@ CTelegramProto::CTelegramProto(const char* protoName, const wchar_t* userName) :
PROTO<CTelegramProto>(protoName, userName),
m_impl(*this),
m_arFiles(1),
- m_arUsers(10, CompareUsers),
+ m_arChats(100, CompareChats),
+ m_arUsers(100, CompareUsers),
m_arRequests(10, CompareRequests),
m_arBasicGroups(10, CompareBasicGroups),
m_arSuperGroups(10, CompareSuperGroups),
@@ -60,8 +65,6 @@ CTelegramProto::CTelegramProto(const char* protoName, const wchar_t* userName) :
CreateDirectoryTreeW(GetAvatarPath());
// default contacts group
- if (m_wszDefaultGroup == NULL)
- m_wszDefaultGroup = mir_wstrdup(L"WhatsApp");
m_iBaseGroup = Clist_GroupCreate(0, m_wszDefaultGroup);
// create standard network connection
@@ -99,8 +102,11 @@ void CTelegramProto::OnContactDeleted(MCONTACT hContact)
void CTelegramProto::OnModulesLoaded()
{
CMStringA szId(getMStringA(DBKEY_ID));
- if (!szId.IsEmpty())
- m_arUsers.insert(new TG_USER(_atoi64(szId.c_str()), 0));
+ if (!szId.IsEmpty()) {
+ auto *pUser = new TG_USER(_atoi64(szId.c_str()), 0);
+ m_arUsers.insert(pUser);
+ m_arChats.insert(pUser);
+ }
for (auto &cc : AccContacts()) {
ptrA szPath(getStringA(cc, "AvatarPath"));
@@ -115,6 +121,8 @@ void CTelegramProto::OnModulesLoaded()
auto *pUser = new TG_USER(_atoi64(szId.c_str()), cc, isGroupChat);
pUser->szAvatarHash = getMStringA(cc, DBKEY_AVATAR_HASH);
m_arUsers.insert(pUser);
+ if (!isGroupChat)
+ m_arChats.insert(pUser);
}
}
@@ -164,11 +172,32 @@ void CTelegramProto::OnMarkRead(MCONTACT hContact, MEVENT hDbEvent)
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MCONTACT CTelegramProto::AddToList(int flags, PROTOSEARCHRESULT *psr)
+{
+ if (psr->cbSize != sizeof(PROTOSEARCHRESULT) && psr->id.w == nullptr)
+ return 0;
+
+ auto id = _wtoi64(psr->id.w);
+ if (auto *pUser = FindUser(id))
+ if (pUser->hContact != INVALID_CONTACT_ID)
+ return pUser->hContact;
+
+ auto *pUser = AddUser(id, false);
+ if (flags & PALF_TEMPORARY)
+ Contact::RemoveFromList(pUser->hContact);
+
+ auto cc = TD::make_object<TD::contact>(); cc->user_id_ = id;
+ SendQuery(new TD::addContact(std::move(cc), false));
+ return pUser->hContact;
+}
+
INT_PTR CTelegramProto::GetCaps(int type, MCONTACT)
{
switch (type) {
case PFLAGNUM_1:
- return PF1_IM | PF1_FILE | PF1_CHAT | PF1_EXTSEARCH | PF1_ADDSEARCHRES | PF1_MODEMSGRECV | PF1_SERVERCLIST;
+ return PF1_IM | PF1_FILE | PF1_CHAT | PF1_SEARCHBYNAME | PF1_ADDSEARCHRES | PF1_MODEMSGRECV | PF1_SERVERCLIST;
case PFLAGNUM_2:
return PF2_ONLINE | PF2_SHORTAWAY | PF2_LONGAWAY;
case PFLAGNUM_4:
@@ -176,12 +205,53 @@ INT_PTR CTelegramProto::GetCaps(int type, MCONTACT)
case PFLAGNUM_5:
return PF2_SHORTAWAY | PF2_LONGAWAY;
case PFLAG_UNIQUEIDTEXT:
- return (INT_PTR)L"Phone";
+ return (INT_PTR)L"ID";
default:
return 0;
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CTelegramProto::OnSearchResults(td::ClientManager::Response &response)
+{
+ m_searchIds.clear();
+
+ if (!response.object)
+ return;
+
+ if (response.object->get_id() != TD::chats::ID) {
+ debugLogA("Gotten class ID %d instead of %d, exiting", response.object->get_id(), TD::chats::ID);
+ return;
+ }
+
+ auto *pChats = ((TD::chats*)response.object.get());
+ if (pChats->total_count_) {
+ for (auto &it : pChats->chat_ids_) {
+ if (auto *pUser = FindChat(it))
+ ReportSearchUser(pUser);
+ else
+ m_searchIds.push_back(it);
+ }
+ }
+
+ if (m_searchIds.empty())
+ ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, this);
+}
+
+HANDLE CTelegramProto::SearchByName(const wchar_t *nick, const wchar_t *firstName, const wchar_t *lastName)
+{
+ CMStringA szQuery(FORMAT, "%s %s %s", T2Utf(nick).get(), T2Utf(firstName).get(), T2Utf(lastName).get());
+ if (szQuery.GetLength() == 2)
+ return nullptr;
+
+ szQuery.Trim();
+ SendQuery(new TD::searchPublicChats(szQuery.c_str()), &CTelegramProto::OnSearchResults);
+ return this;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
int CTelegramProto::SendMsg(MCONTACT hContact, int, const char *pszMessage)
{
ptrA szId(getStringA(hContact, DBKEY_ID));
diff --git a/protocols/Telegram/src/proto.h b/protocols/Telegram/src/proto.h
index 2c0fe18116..b0dc9645a0 100644
--- a/protocols/Telegram/src/proto.h
+++ b/protocols/Telegram/src/proto.h
@@ -80,13 +80,15 @@ struct TG_USER
id(_1),
hContact(_2),
isGroupChat(_3)
- {}
+ {
+ chatId = (isGroupChat) ? -1 :id;
+ }
- int64_t id;
+ int64_t id, chatId;
MCONTACT hContact;
bool isGroupChat;
CMStringA szAvatarHash;
- CMStringW wszNick;
+ CMStringW wszNick, wszFirstName, wszLastName;
time_t m_timer1 = 0, m_timer2 = 0;
SESSION_INFO *m_si = nullptr;
};
@@ -168,6 +170,7 @@ class CTelegramProto : public PROTO<CTelegramProto>
}
void OnEndSession(td::ClientManager::Response &response);
+ void OnSearchResults(td::ClientManager::Response &response);
void OnSendMessage(td::ClientManager::Response &response, void *pUserInfo);
void OnUpdateAuth(td::ClientManager::Response &response);
@@ -212,13 +215,22 @@ class CTelegramProto : public PROTO<CTelegramProto>
void InitGroupChat(TG_USER *pUser, const TD::chat *pChat, bool bUpdateMembers);
void StartGroupChat(td::ClientManager::Response &response, void *pUserData);
+ // Search
+ TD::array<TD::int53> m_searchIds;
+
+ bool CheckSearchUser(TG_USER *pUser);
+ void ReportSearchUser(TG_USER *pUser);
+
// Users
int64_t m_iOwnId;
MGROUP m_iBaseGroup;
+ LIST<TG_USER> m_arChats;
OBJLIST<TG_USER> m_arUsers;
+ TG_USER* FindChat(int64_t id);
TG_USER* FindUser(int64_t id);
TG_USER* AddUser(int64_t id, bool bIsChat);
+ TG_USER* AddFakeUser(int64_t id, bool bIsChat);
// Popups
HANDLE m_hPopupClass;
@@ -236,17 +248,20 @@ public:
//////////////////////////////////////////////////////////////////////////////////////
// Virtual functions
- INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override;
-
- int SendMsg(MCONTACT hContact, int flags, const char *pszMessage) override;
- int SetStatus(int iNewStatus) override;
-
- void OnContactDeleted(MCONTACT hContact) override;
- MWindow OnCreateAccMgrUI(MWindow) override;
- void OnMarkRead(MCONTACT, MEVENT) override;
- void OnModulesLoaded() override;
- void OnShutdown() override;
- void OnErase() override;
+ MCONTACT AddToList(int flags, PROTOSEARCHRESULT *psr);
+
+ INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override;
+
+ HANDLE SearchByName(const wchar_t *nick, const wchar_t *firstName, const wchar_t *lastName) override;
+ int SendMsg(MCONTACT hContact, int flags, const char *pszMessage) override;
+ int SetStatus(int iNewStatus) override;
+
+ void OnContactDeleted(MCONTACT hContact) override;
+ MWindow OnCreateAccMgrUI(MWindow hwndParent) override;
+ void OnMarkRead(MCONTACT, MEVENT) override;
+ void OnModulesLoaded() override;
+ void OnShutdown() override;
+ void OnErase() override;
// Events ////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/Telegram/src/server.cpp b/protocols/Telegram/src/server.cpp
index 34c8ff5936..291cf9e056 100644
--- a/protocols/Telegram/src/server.cpp
+++ b/protocols/Telegram/src/server.cpp
@@ -183,7 +183,7 @@ void CTelegramProto::OnSendMessage(td::ClientManager::Response &response, void *
}
auto *pMessage = ((TD::message *)response.object.get());
- auto *pUser = FindUser(pMessage->chat_id_);
+ auto *pUser = FindChat(pMessage->chat_id_);
if (pUser) {
char szMsgId[100];
_i64toa(pMessage->id_, szMsgId, 10);
@@ -256,9 +256,11 @@ void CTelegramProto::ProcessBasicGroup(TD::updateBasicGroup *pObj)
else
pGroup->group = std::move(pObj->basic_group_);
- auto *pUser = AddUser(tmp.id, true);
- if (iStatusId == TD::chatMemberStatusLeft::ID)
- Contact::Hide(pUser->hContact);
+ if (iStatusId == TD::chatMemberStatusLeft::ID) {
+ auto *pUser = AddFakeUser(tmp.id, true);
+ pUser->wszFirstName.Format(TranslateT("%d member(s)"), pGroup->group->member_count_);
+ }
+ else AddUser(tmp.id, true);
}
void CTelegramProto::ProcessChat(TD::updateNewChat *pObj)
@@ -288,10 +290,22 @@ void CTelegramProto::ProcessChat(TD::updateNewChat *pObj)
}
if (auto *pUser = FindUser(chatId)) {
- if (!pChat->title_.empty() && pUser->hContact != INVALID_CONTACT_ID)
- setUString(pUser->hContact, "Nick", pChat->title_.c_str());
+ pUser->chatId = pChat->id_;
+
+ if (!m_arChats.find(pUser))
+ m_arChats.insert(pUser);
+
+ if (!pChat->title_.empty()) {
+ if (pUser->hContact != INVALID_CONTACT_ID)
+ setUString(pUser->hContact, "Nick", pChat->title_.c_str());
+ else
+ pUser->wszNick = Utf2T(pChat->title_.c_str());
+ }
- if (pUser->isGroupChat)
+ if (CheckSearchUser(pUser))
+ return;
+
+ if (pUser->isGroupChat && pUser->hContact != INVALID_CONTACT_ID)
InitGroupChat(pUser, pChat, bIsBasicGroup);
}
else debugLogA("Unknown chat id %lld, ignoring", chatId);
@@ -304,7 +318,7 @@ void CTelegramProto::ProcessChatPosition(TD::updateChatPosition *pObj)
return;
}
- auto *pUser = FindUser(pObj->chat_id_);
+ auto *pUser = FindChat(pObj->chat_id_);
if (pUser == nullptr) {
debugLogA("Unknown chat, skipping");
return;
@@ -359,7 +373,7 @@ void CTelegramProto::ProcessGroups(TD::updateChatFilters *pObj)
void CTelegramProto::ProcessMarkRead(TD::updateChatReadInbox *pObj)
{
- auto *pUser = FindUser(pObj->chat_id_);
+ auto *pUser = FindChat(pObj->chat_id_);
if (pUser == nullptr) {
debugLogA("message from unknown chat/user, ignored");
return;
@@ -393,7 +407,7 @@ void CTelegramProto::ProcessMessage(TD::updateNewMessage *pObj)
{
auto &pMessage = pObj->message_;
- auto *pUser = FindUser(pMessage->chat_id_);
+ auto *pUser = FindChat(pMessage->chat_id_);
if (pUser == nullptr) {
debugLogA("message from unknown chat/user, ignored");
return;
@@ -446,14 +460,18 @@ void CTelegramProto::ProcessSuperGroup(TD::updateSupergroup *pObj)
TG_SUPER_GROUP tmp(pObj->supergroup_->id_, 0);
auto *pGroup = m_arSuperGroups.find(&tmp);
- if (pGroup == nullptr)
- m_arSuperGroups.insert(new TG_SUPER_GROUP(tmp.id, std::move(pObj->supergroup_)));
- else
- pGroup->group = std::move(pObj->supergroup_);
+ if (pGroup == nullptr) {
+ pGroup = new TG_SUPER_GROUP(tmp.id, std::move(pObj->supergroup_));
+ m_arSuperGroups.insert(pGroup);
+ }
+ else pGroup->group = std::move(pObj->supergroup_);
- auto *pUser = AddUser(tmp.id, true);
- if (iStatusId == TD::chatMemberStatusLeft::ID)
- Contact::Hide(pUser->hContact);
+ if (iStatusId == TD::chatMemberStatusLeft::ID) {
+ auto *pUser = AddFakeUser(tmp.id, true);
+ pUser->wszNick = getName(pGroup->group->usernames_.get());
+ pUser->wszFirstName.Format(TranslateT("%d member(s)"), pGroup->group->member_count_);
+ }
+ else AddUser(tmp.id, true);
}
void CTelegramProto::ProcessUser(TD::updateUser *pObj)
@@ -468,15 +486,18 @@ void CTelegramProto::ProcessUser(TD::updateUser *pObj)
}
if (!pUser->is_contact_) {
- auto *pu = FindUser(pUser->id_);
- if (pu == nullptr) {
- pu = new TG_USER(pUser->id_, INVALID_CONTACT_ID, false);
- m_arUsers.insert(pu);
+ auto *pu = AddFakeUser(pUser->id_, false);
+ pu->wszFirstName = Utf2T(pUser->first_name_.c_str());
+ pu->wszLastName = Utf2T(pUser->last_name_.c_str());
+ if (pUser->usernames_)
+ pu->wszNick = Utf2T(pUser->usernames_->editable_username_.c_str());
+ else {
+ pu->wszNick = Utf2T(pUser->first_name_.c_str());
+ if (!pUser->last_name_.empty())
+ pu->wszNick.AppendFormat(L" %s", Utf2T(pUser->last_name_.c_str()).get());
}
- pu->wszNick = Utf2T(pUser->first_name_.c_str());
- if (!pUser->last_name_.empty())
- pu->wszNick.AppendFormat(L" %s", Utf2T(pUser->last_name_.c_str()).get());
+ CheckSearchUser(pu);
debugLogA("User doesn't belong to your contacts, skipping");
return;
diff --git a/protocols/Telegram/src/stdafx.h b/protocols/Telegram/src/stdafx.h
index bce763709d..b16b91840c 100644
--- a/protocols/Telegram/src/stdafx.h
+++ b/protocols/Telegram/src/stdafx.h
@@ -1,6 +1,7 @@
#ifndef _COMMON_H_
#define _COMMON_H_
+#include <malloc.h>
#include <time.h>
#include <windows.h>
diff --git a/protocols/Telegram/src/utils.cpp b/protocols/Telegram/src/utils.cpp
index b725ba5f90..7dfe0c3096 100644
--- a/protocols/Telegram/src/utils.cpp
+++ b/protocols/Telegram/src/utils.cpp
@@ -17,7 +17,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
-char* getSender(const TD::MessageSender *pSender, char *pDest, size_t cbSize)
+const char *getName(const TD::usernames *pName)
+{
+ return (pName == nullptr) ? TranslateU("none") : pName->editable_username_.c_str();
+}
+
+const char* getSender(const TD::MessageSender *pSender, char *pDest, size_t cbSize)
{
switch (pSender->get_id()) {
case TD::messageSenderChat::ID:
@@ -34,6 +39,49 @@ char* getSender(const TD::MessageSender *pSender, char *pDest, size_t cbSize)
/////////////////////////////////////////////////////////////////////////////////////////
+bool CTelegramProto::CheckSearchUser(TG_USER *pUser)
+{
+ auto pSearchId = std::find(m_searchIds.begin(), m_searchIds.end(), pUser->chatId);
+ if (pSearchId == m_searchIds.end())
+ return false;
+
+ ReportSearchUser(pUser);
+
+ m_searchIds.erase(pSearchId);
+ if (m_searchIds.empty())
+ ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, this);
+ return true;
+}
+
+void CTelegramProto::ReportSearchUser(TG_USER *pUser)
+{
+ CMStringW wszId(FORMAT, L"%lld", pUser->id);
+
+ PROTOSEARCHRESULT psr = {};
+ psr.cbSize = sizeof(psr);
+ psr.flags = PSR_UNICODE;
+ psr.id.w = wszId.GetBuffer();
+
+ if (pUser->hContact != INVALID_CONTACT_ID) {
+ CMStringW wszNick = getMStringW(pUser->hContact, "Nick");
+ CMStringW wszLastName = getMStringW(pUser->hContact, "LastName");
+ CMStringW wszFirstName = getMStringW(pUser->hContact, "FirstName");
+
+ psr.nick.w = wszNick.GetBuffer();
+ psr.lastName.w = wszLastName.GetBuffer();
+ psr.firstName.w = wszFirstName.GetBuffer();
+ }
+ else {
+ psr.firstName.w = pUser->wszFirstName.GetBuffer();
+ psr.lastName.w = pUser->wszLastName.GetBuffer();
+ psr.nick.w = pUser->wszNick.GetBuffer();
+ }
+
+ ProtoBroadcastAck(0, ACKTYPE_SEARCH, ACKRESULT_DATA, this, (LPARAM)&psr);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
void CTelegramProto::UpdateString(MCONTACT hContact, const char *pszSetting, const std::string &str)
{
if (str.empty())
@@ -45,18 +93,28 @@ void CTelegramProto::UpdateString(MCONTACT hContact, const char *pszSetting, con
/////////////////////////////////////////////////////////////////////////////////////////
// Users
+TG_USER* CTelegramProto::FindChat(int64_t id)
+{
+ auto *tmp = (TG_USER *)_alloca(sizeof(TG_USER));
+ tmp->chatId = id;
+ return m_arChats.find(tmp);
+}
+
TG_USER* CTelegramProto::FindUser(int64_t id)
{
- if (auto *pCache = m_arUsers.find((TG_USER *)&id))
- return pCache;
+ return m_arUsers.find((TG_USER *)&id);
+}
- if (id < 0) {
- id = -id;
- if (auto *pCache = m_arUsers.find((TG_USER *)&id))
- return pCache;
+TG_USER* CTelegramProto::AddFakeUser(int64_t id, bool bIsChat)
+{
+ auto *pu = FindUser(id);
+ if (pu == nullptr) {
+ pu = new TG_USER(id, INVALID_CONTACT_ID, bIsChat);
+ m_arUsers.insert(pu);
+ if (!bIsChat)
+ m_arChats.insert(pu);
}
-
- return nullptr;
+ return pu;
}
TG_USER* CTelegramProto::AddUser(int64_t id, bool bIsChat)
@@ -81,6 +139,8 @@ TG_USER* CTelegramProto::AddUser(int64_t id, bool bIsChat)
pUser = new TG_USER(id, hContact, bIsChat);
m_arUsers.insert(pUser);
+ if (!bIsChat)
+ m_arChats.insert(pUser);
return pUser;
}
diff --git a/protocols/Telegram/src/utils.h b/protocols/Telegram/src/utils.h
index 846428a086..d563350585 100644
--- a/protocols/Telegram/src/utils.h
+++ b/protocols/Telegram/src/utils.h
@@ -1,3 +1,4 @@
#pragma once
-char *getSender(const TD::MessageSender *pSender, char *pDest, size_t cbSize);
+const char *getName(const TD::usernames *pName);
+const char *getSender(const TD::MessageSender *pSender, char *pDest, size_t cbSize);