From a1d4ef315aa12a409d55e694384c1c1a3fa4bcc3 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 29 Apr 2023 18:46:37 +0300 Subject: fixes #3330 (support for pictures, videos, voice messages in Telegram) --- protocols/Telegram/src/avatars.cpp | 23 ++++++-- protocols/Telegram/src/proto.cpp | 15 +++++ protocols/Telegram/src/proto.h | 5 +- protocols/Telegram/src/utils.cpp | 112 +++++++++++++++++++++++++++---------- 4 files changed, 122 insertions(+), 33 deletions(-) (limited to 'protocols/Telegram') diff --git a/protocols/Telegram/src/avatars.cpp b/protocols/Telegram/src/avatars.cpp index a588bfa76f..24301cb42c 100644 --- a/protocols/Telegram/src/avatars.cpp +++ b/protocols/Telegram/src/avatars.cpp @@ -105,7 +105,7 @@ void __cdecl CTelegramProto::OfflineFileThread(void *pParam) if (dbei && !strcmp(dbei.szModule, m_szModuleName) && dbei.eventType == EVENTTYPE_FILE) { JSONNode root = JSONNode::parse((const char *)dbei.pBlob); if (root) { - auto *ft = new TG_FILE_REQUEST(TG_FILE_REQUEST::FILE, 0, ""); + auto *ft = new TG_FILE_REQUEST(TG_FILE_REQUEST::Type(root["t"].as_int()), 0, ""); ft->m_fileName = ofd->wszPath; ft->m_bOpen = ofd->bOpen; ft->m_hEvent = ofd->hDbEvent; @@ -182,14 +182,29 @@ void CTelegramProto::ProcessFile(TD::updateFile *pObj) mir_cslock lck(m_csFiles); m_arFiles.remove(F); } - else { // FILE + else { // FILE, PICTURE, VIDEO, VOICE if (pFile->local_->is_downloading_completed_) { - MoveFileW(wszExistingFile, wszFullName); - DBVARIANT dbv = { DBVT_DWORD }; dbv.dVal = pFile->local_->downloaded_size_; db_event_setJson(F->m_hEvent, "ft", &dbv); db_event_setJson(F->m_hEvent, "fs", &dbv); + + if (F->m_type != F->FILE) { + auto *pSlash = strrchr(pFile->local_->path_.c_str(), '\\'); + if (!pSlash) + pSlash = pFile->local_->path_.c_str(); + else + pSlash++; + + dbv.type = DBVT_UTF8; + dbv.pszVal = (char*)pSlash; + db_event_setJson(F->m_hEvent, "f", &dbv); + + wszFullName.Truncate(wszFullName.ReverseFind('\\') + 1); + wszFullName.Append(Utf2T(pSlash)); + } + + MoveFileW(wszExistingFile, wszFullName); NotifyEventHooks(g_plugin.m_hevEventEdited, 0, F->m_hEvent); if (F->m_bOpen) diff --git a/protocols/Telegram/src/proto.cpp b/protocols/Telegram/src/proto.cpp index a8f36fbe2e..a32e1571b3 100644 --- a/protocols/Telegram/src/proto.cpp +++ b/protocols/Telegram/src/proto.cpp @@ -280,6 +280,21 @@ INT_PTR CTelegramProto::GetCaps(int type, MCONTACT) ///////////////////////////////////////////////////////////////////////////////////////// +MEVENT CTelegramProto::RecvFile(MCONTACT hContact, PROTORECVFILE *pre) +{ + MEVENT hEvent = CSuper::RecvFile(hContact, pre); + if (hEvent) + if (auto *ft = (TG_FILE_REQUEST *)pre->lParam) { + DBVARIANT dbv = { DBVT_DWORD }; + dbv.dVal = ft->m_type; + db_event_setJson(hEvent, "t", &dbv); + } + + return hEvent; +} + +///////////////////////////////////////////////////////////////////////////////////////// + void CTelegramProto::OnSearchResults(td::ClientManager::Response &response) { m_searchIds.clear(); diff --git a/protocols/Telegram/src/proto.h b/protocols/Telegram/src/proto.h index 0228ef285a..b7508274e4 100644 --- a/protocols/Telegram/src/proto.h +++ b/protocols/Telegram/src/proto.h @@ -62,7 +62,7 @@ struct TG_REQUEST_FULL : public TG_REQUEST_BASE struct TG_FILE_REQUEST : public MZeroedObject { - enum Type { AVATAR = 1, FILE = 2 }; + enum Type { AVATAR = 1, FILE = 2, PICTURE = 3, VIDEO = 4, VOICE = 5 }; TG_FILE_REQUEST(Type _1, TD::int53 _2, const char *_3) : m_type(_1), @@ -225,6 +225,7 @@ class CTelegramProto : public PROTO void ProcessSuperGroup(TD::updateSupergroup *pObj); void ProcessUser(TD::updateUser *pObj); + bool GetMessageFile(TG_FILE_REQUEST::Type, TG_USER *pUser, const TD::file *pFile, const char *pszFileName, const std::string &caption, const char *szId, const char *szUser); CMStringA GetMessageText(TG_USER *pUser, const TD::message *pMsg); void UpdateString(MCONTACT hContact, const char *pszSetting, const std::string &str); @@ -290,6 +291,8 @@ public: INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override; + MEVENT RecvFile(MCONTACT hContact, PROTORECVFILE *pre) 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; diff --git a/protocols/Telegram/src/utils.cpp b/protocols/Telegram/src/utils.cpp index 5529dd2418..db42a33297 100644 --- a/protocols/Telegram/src/utils.cpp +++ b/protocols/Telegram/src/utils.cpp @@ -239,46 +239,102 @@ bool CTelegramProto::GetGcUserId(TG_USER *pUser, const TD::message *pMsg, char * ///////////////////////////////////////////////////////////////////////////////////////// +bool CTelegramProto::GetMessageFile( + TG_FILE_REQUEST::Type fileType, + TG_USER *pUser, + const TD::file *pFile, + const char *pszFileName, + const std::string &caption, + const char *pszId, + const char *pszUserId) +{ + if (pFile->get_id() != TD::file::ID) { + debugLogA("Document contains unsupported type %d, exiting", pFile->get_id()); + return false; + } + + auto *pRequest = new TG_FILE_REQUEST(fileType, pFile->id_, pFile->remote_->id_.c_str()); + pRequest->m_fileName = Utf2T(pszFileName); + pRequest->m_fileSize = pFile->size_; + { + mir_cslock lck(m_csFiles); + m_arFiles.insert(pRequest); + } + + PROTORECVFILE pre = {}; + pre.dwFlags = PRFF_UTF | PRFF_SILENT; + pre.fileCount = 1; + pre.timestamp = time(0); + pre.files.a = &pszFileName; + pre.lParam = (LPARAM)pRequest; + pre.szId = pszId; + pre.szUserId = pszUserId; + + if (!caption.empty()) + pre.descr.a = caption.c_str(); + ProtoChainRecvFile(pUser->hContact, &pre); + return true; +} + CMStringA CTelegramProto::GetMessageText(TG_USER *pUser, const TD::message *pMsg) { const TD::MessageContent *pBody = pMsg->content_.get(); - char szId[100], szUserId[100]; + char szId[100], szUserId[100], *pszUserId = nullptr; _i64toa(pMsg->id_, szId, 10); + if (GetGcUserId(pUser, pMsg, szUserId)) + pszUserId = szUserId; switch (pBody->get_id()) { - case TD::messageDocument::ID: + case TD::messagePhoto::ID: { - auto *pDoc = ((TD::messageDocument *)pBody); - auto *pFile = pDoc->document_->document_.get(); - - if (pFile->get_id() != TD::file::ID) { - debugLogA("Document contains unsupported type %d, exiting", pDoc->document_->get_id()); + auto *pDoc = (TD::messagePhoto *)pBody; + TD::photoSize *pPhoto = nullptr; + + const char *types[] = { "x", "m", "s" }; + for (auto *pType : types) + for (auto &it: pDoc->photo_->sizes_) + if (it->type_ == pType) { + pPhoto = it.get(); + break; + } + + if (pPhoto == nullptr) { + debugLogA("cannot find photo, exiting"); break; } - - auto *pRequest = new TG_FILE_REQUEST(TG_FILE_REQUEST::FILE, pFile->id_, pFile->remote_->id_.c_str()); - pRequest->m_fileName = Utf2T(pDoc->document_->file_name_.c_str()); - pRequest->m_fileSize = pFile->size_; - { - mir_cslock lck(m_csFiles); - m_arFiles.insert(pRequest); + + CMStringA fileName(FORMAT, "%s (%d x %d)", TranslateU("Picture"), pPhoto->width_, pPhoto->height_); + GetMessageFile(TG_FILE_REQUEST::PICTURE, pUser, pPhoto->photo_.get(), fileName, pDoc->caption_->text_, szId, pszUserId); + } + break; + + case TD::messageVideo::ID: + { + auto *pDoc = (TD::messageVideo *)pBody; + auto *pVideo = pDoc->video_.get(); + CMStringA fileName(FORMAT, "%s (%d x %d, %d %s)", TranslateU("Video"), pVideo->width_, pVideo->height_, pVideo->duration_, TranslateU("seconds")); + std::string caption = fileName.c_str(); + if (!pDoc->caption_->text_.empty()) { + caption += " "; + caption += pDoc->caption_->text_; } + GetMessageFile(TG_FILE_REQUEST::VIDEO, pUser, pVideo->video_.get(), pVideo->file_name_.c_str(), caption, szId, pszUserId); + } + break; - auto *pszFileName = pDoc->document_->file_name_.c_str(); - PROTORECVFILE pre = {}; - pre.dwFlags = PRFF_UTF | PRFF_SILENT; - pre.fileCount = 1; - pre.timestamp = time(0); - pre.files.a = &pszFileName; - pre.lParam = (LPARAM)pRequest; - pre.szId = szId; - if (GetGcUserId(pUser, pMsg, szUserId)) - pre.szUserId = szUserId; - - if (!pDoc->caption_->text_.empty()) - pre.descr.a = pDoc->caption_->text_.c_str(); - ProtoChainRecvFile(pUser->hContact, &pre); + case TD::messageVoiceNote::ID: + { + auto *pDoc = (TD::messageVoiceNote *)pBody; + CMStringA fileName(FORMAT, "%s (%d %s)", TranslateU("Voice note"), pDoc->voice_note_->duration_, TranslateU("seconds")); + GetMessageFile(TG_FILE_REQUEST::VOICE, pUser, pDoc->voice_note_->voice_.get(), fileName, pDoc->caption_->text_, szId, pszUserId); + } + break; + + case TD::messageDocument::ID: + { + auto *pDoc = (TD::messageDocument *)pBody; + GetMessageFile(TG_FILE_REQUEST::FILE, pUser, pDoc->document_->document_.get(), pDoc->document_->file_name_.c_str(), pDoc->caption_->text_, szId, pszUserId); } break; -- cgit v1.2.3