diff options
author | George Hazan <ghazan@miranda.im> | 2023-01-10 20:14:41 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2023-01-10 20:14:41 +0300 |
commit | 605743d6e763b3aa2868133f50f99f15293a9a29 (patch) | |
tree | 415b27490160a9dd0ec3f5f4a085bf07ec5c5f34 | |
parent | 83278f1c0a1b12b349617b7ebc5583be17e69daa (diff) |
Telegram: support for avatars
-rw-r--r-- | protocols/Telegram/Telegram.vcxproj | 1 | ||||
-rw-r--r-- | protocols/Telegram/Telegram.vcxproj.filters | 3 | ||||
-rw-r--r-- | protocols/Telegram/src/avatars.cpp | 95 | ||||
-rw-r--r-- | protocols/Telegram/src/mt_proto.cpp | 11 | ||||
-rw-r--r-- | protocols/Telegram/src/mt_proto.h | 26 | ||||
-rw-r--r-- | protocols/Telegram/src/server.cpp | 19 | ||||
-rw-r--r-- | protocols/Telegram/src/stdafx.h | 1 |
7 files changed, 146 insertions, 10 deletions
diff --git a/protocols/Telegram/Telegram.vcxproj b/protocols/Telegram/Telegram.vcxproj index eed1b057f3..9c1812a737 100644 --- a/protocols/Telegram/Telegram.vcxproj +++ b/protocols/Telegram/Telegram.vcxproj @@ -27,6 +27,7 @@ </ImportGroup> <ItemGroup> <ClCompile Include="src\auth.cpp" /> + <ClCompile Include="src\avatars.cpp" /> <ClCompile Include="src\main.cpp" /> <ClCompile Include="src\mt_proto.cpp" /> <ClCompile Include="src\options.cpp" /> diff --git a/protocols/Telegram/Telegram.vcxproj.filters b/protocols/Telegram/Telegram.vcxproj.filters index ffd20c351c..e6d8a2433a 100644 --- a/protocols/Telegram/Telegram.vcxproj.filters +++ b/protocols/Telegram/Telegram.vcxproj.filters @@ -20,6 +20,9 @@ <ClCompile Include="src\auth.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="src\avatars.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClCompile Include="src\stdafx.cxx"> diff --git a/protocols/Telegram/src/avatars.cpp b/protocols/Telegram/src/avatars.cpp new file mode 100644 index 0000000000..b21ddf81d0 --- /dev/null +++ b/protocols/Telegram/src/avatars.cpp @@ -0,0 +1,95 @@ +/* +Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdafx.h" + +INT_PTR CMTProto::SvcGetAvatarCaps(WPARAM wParam, LPARAM lParam) +{ + switch (wParam) { + case AF_MAXSIZE: + ((POINT *)lParam)->x = 160; + ((POINT *)lParam)->y = 160; + break; + + case AF_MAXFILESIZE: + return 32000; + + case AF_PROPORTION: + return PIP_SQUARE; + + case AF_FORMATSUPPORTED: + case AF_ENABLED: + case AF_DONTNEEDDELAYS: + case AF_FETCHIFPROTONOTVISIBLE: + case AF_FETCHIFCONTACTOFFLINE: + return 1; + } + return 0; +} + +INT_PTR CMTProto::SvcGetAvatarInfo(WPARAM, LPARAM lParam) +{ + auto *pai = (PROTO_AVATAR_INFORMATION *)lParam; + + ptrW wszPath(getWStringA(pai->hContact, DBKEY_AVATAR_PATH)); + if (wszPath == nullptr) + return GAIR_NOAVATAR; + + pai->format = getByte(pai->hContact, DBKEY_AVATAR_TYPE, PA_FORMAT_JPEG); + wcsncpy_s(pai->filename, wszPath, _TRUNCATE); + + if (::_waccess(pai->filename, 0) == 0) + return GAIR_SUCCESS; + + debugLogA("No avatar"); + return GAIR_NOAVATAR; +} + +INT_PTR CMTProto::SvcGetMyAvatar(WPARAM, LPARAM) +{ + return 1; +} + +INT_PTR CMTProto::SvcSetMyAvatar(WPARAM, LPARAM) +{ + return 1; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMTProto::ProcessFile(TD::updateFile *pObj) +{ + if (auto *pFile = pObj->file_.get()) { + if (!pFile->local_->is_downloading_completed_) + return; + + for (auto &it : m_arUsers) { + if (it->szAvatarHash == pFile->remote_->unique_id_.c_str()) { + PROTO_AVATAR_INFORMATION pai; + wcsncpy_s(pai.filename, Utf2T(pFile->local_->path_.c_str()), _TRUNCATE); + pai.hContact = it->hContact; + pai.format = ProtoGetAvatarFileFormat(pai.filename); + + setByte(pai.hContact, DBKEY_AVATAR_TYPE, pai.format); + setWString(pai.hContact, DBKEY_AVATAR_PATH, pai.filename); + + ProtoBroadcastAck(it->hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &pai); + break; + } + } + } +} diff --git a/protocols/Telegram/src/mt_proto.cpp b/protocols/Telegram/src/mt_proto.cpp index d00f84c434..87e7f5c7d7 100644 --- a/protocols/Telegram/src/mt_proto.cpp +++ b/protocols/Telegram/src/mt_proto.cpp @@ -30,6 +30,10 @@ CMTProto::CMTProto(const char* protoName, const wchar_t* userName) : m_iOwnId = _atoi64(getMStringA(DBKEY_ID)); CreateProtoService(PS_CREATEACCMGRUI, &CMTProto::SvcCreateAccMgrUI); + CreateProtoService(PS_GETAVATARCAPS, &CMTProto::SvcGetAvatarCaps); + CreateProtoService(PS_GETAVATARINFO, &CMTProto::SvcGetAvatarInfo); + CreateProtoService(PS_GETMYAVATAR, &CMTProto::SvcGetMyAvatar); + CreateProtoService(PS_SETMYAVATAR, &CMTProto::SvcSetMyAvatar); HookProtoEvent(ME_OPT_INITIALISE, &CMTProto::OnOptionsInit); HookProtoEvent(ME_DB_EVENT_MARKED_READ, &CMTProto::OnDbMarkedRead); @@ -70,8 +74,11 @@ void CMTProto::OnModulesLoaded() for (auto &cc : AccContacts()) { bool isGroupChat = isChatRoom(cc); szId = getMStringA(cc, isGroupChat ? "ChatRoomID" : DBKEY_ID); - if (!szId.IsEmpty()) - m_arUsers.insert(new TG_USER(_atoi64(szId.c_str()), cc, isGroupChat)); + if (!szId.IsEmpty()) { + auto *pUser = new TG_USER(_atoi64(szId.c_str()), cc, isGroupChat); + pUser->szAvatarHash = getMStringA(cc, DBKEY_AVATAR_HASH); + m_arUsers.insert(pUser); + } } } diff --git a/protocols/Telegram/src/mt_proto.h b/protocols/Telegram/src/mt_proto.h index 46439aee5f..99a1160b97 100644 --- a/protocols/Telegram/src/mt_proto.h +++ b/protocols/Telegram/src/mt_proto.h @@ -2,6 +2,10 @@ #define DBKEY_ID "id" +#define DBKEY_AVATAR_HASH "AvatarHash" +#define DBKEY_AVATAR_PATH "AvatarPath" +#define DBKEY_AVATAR_TYPE "AvatarType" + class CMTProto; typedef void (CMTProto:: *TG_QUERY_HANDLER)(td::ClientManager::Response &response); typedef void (CMTProto:: *TG_QUERY_HANDLER_FULL)(td::ClientManager::Response &response, void *pUserInfo); @@ -62,10 +66,11 @@ struct TG_USER isGroupChat(_3) {} - uint64_t id; - MCONTACT hContact; - bool isGroupChat; - time_t m_timer1 = 0, m_timer2 = 0; + uint64_t id; + MCONTACT hContact; + bool isGroupChat; + CMStringA szAvatarHash; + time_t m_timer1 = 0, m_timer2 = 0; }; class CMTProto : public PROTO<CMTProto> @@ -109,28 +114,29 @@ class CMTProto : public PROTO<CMTProto> { return CMStringW(VARSW(L"%miranda_userdata%")) + L"\\" + _A2T(m_szModuleName); } + void OnEndSession(td::ClientManager::Response &response); + void OnSendMessage(td::ClientManager::Response &response, void *pUserInfo); void OnUpdateAuth(td::ClientManager::Response &response); void LogOut(void); - void OnEndSession(td::ClientManager::Response &response); void OnLoggedIn(void); void ProcessResponse(td::ClientManager::Response); + void SendKeepAlive(void); void SendQuery(TD::Function *pFunc, TG_QUERY_HANDLER pHandler = nullptr); void SendQuery(TD::Function *pFunc, TG_QUERY_HANDLER_FULL pHandler, void *pUserInfo); + int SendTextMessage(uint64_t chatId, const char *pszMessage); void ProcessAuth(TD::updateAuthorizationState *pObj); void ProcessChat(TD::updateNewChat *pObj); void ProcessChatPosition(TD::updateChatPosition *pObj); + void ProcessFile(TD::updateFile *pObj); void ProcessGroups(TD::updateChatFilters *pObj); void ProcessMarkRead(TD::updateChatReadInbox *pObj); void ProcessMessage(TD::updateNewMessage *pObj); void ProcessStatus(TD::updateUserStatus *pObj); void ProcessUser(TD::updateUser *pObj); - void OnSendMessage(td::ClientManager::Response &response, void *pUserInfo); - int SendTextMessage(uint64_t chatId, const char *pszMessage); - void UpdateString(MCONTACT hContact, const char *pszSetting, const std::string &str); // Users @@ -169,6 +175,10 @@ public: // Services ////////////////////////////////////////////////////////////////////////// INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM, LPARAM); + INT_PTR __cdecl SvcGetAvatarCaps(WPARAM, LPARAM); + INT_PTR __cdecl SvcGetAvatarInfo(WPARAM, LPARAM); + INT_PTR __cdecl SvcGetMyAvatar(WPARAM, LPARAM); + INT_PTR __cdecl SvcSetMyAvatar(WPARAM, LPARAM); // Events //////////////////////////////////////////////////////////////////////////// diff --git a/protocols/Telegram/src/server.cpp b/protocols/Telegram/src/server.cpp index c3c54b3065..fbb6c53f3d 100644 --- a/protocols/Telegram/src/server.cpp +++ b/protocols/Telegram/src/server.cpp @@ -124,6 +124,10 @@ void CMTProto::ProcessResponse(td::ClientManager::Response response) ProcessMarkRead((TD::updateChatReadInbox *)response.object.get()); break; + case TD::updateFile::ID: + ProcessFile((TD::updateFile*)response.object.get()); + break; + case TD::updateNewChat::ID: ProcessChat((TD::updateNewChat *)response.object.get()); break; @@ -379,6 +383,21 @@ void CMTProto::ProcessUser(TD::updateUser *pObj) else ExtraIcon_SetIconByName(g_plugin.m_hIcon, pu->hContact, nullptr); + if (auto *pPhoto = pUser->profile_photo_.get()) { + if (auto *pSmall = pPhoto->small_.get()) { + auto remoteId = pSmall->remote_->unique_id_; + auto storedId = getMStringA(pu->hContact, DBKEY_AVATAR_HASH); + if (remoteId != storedId.c_str()) { + if (!remoteId.empty()) { + pu->szAvatarHash = remoteId.c_str(); + setString(pu->hContact, DBKEY_AVATAR_HASH, remoteId.c_str()); + SendQuery(new TD::downloadFile(pSmall->id_, 5, 0, 0, false)); + } + else delSetting(pu->hContact, DBKEY_AVATAR_HASH); + } + } + } + if (pUser->status_) { if (pUser->status_->get_id() == TD::userStatusOffline::ID) { auto *pOffline = (TD::userStatusOffline *)pUser->status_.get(); diff --git a/protocols/Telegram/src/stdafx.h b/protocols/Telegram/src/stdafx.h index ff63a27ac9..cae3629bf9 100644 --- a/protocols/Telegram/src/stdafx.h +++ b/protocols/Telegram/src/stdafx.h @@ -12,6 +12,7 @@ #include <m_protoint.h> #include <m_protosvc.h> +#include <m_avatars.h> #include <m_clist.h> #include <m_chat.h> #include <m_contacts.h> |