diff options
author | George Hazan <ghazan@miranda.im> | 2023-02-13 20:53:50 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2023-02-13 20:53:50 +0300 |
commit | 9c5bcfa55b13b5df3703d4ba8ab9d70527a2587a (patch) | |
tree | 9ec5cded86fe3fdef47bba9537a3373c78a30661 | |
parent | 1856842de4420fe77901759000a7295ae45fb94a (diff) |
fixes #3329 (Telegram: implement search and add contacts)
-rw-r--r-- | protocols/Telegram/src/proto.cpp | 84 | ||||
-rw-r--r-- | protocols/Telegram/src/proto.h | 43 | ||||
-rw-r--r-- | protocols/Telegram/src/server.cpp | 69 | ||||
-rw-r--r-- | protocols/Telegram/src/stdafx.h | 1 | ||||
-rw-r--r-- | protocols/Telegram/src/utils.cpp | 78 | ||||
-rw-r--r-- | protocols/Telegram/src/utils.h | 3 |
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);
|