diff --git a/account-data.h b/account-data.h index 7ef8612..35c0cc8 100644 --- a/account-data.h +++ b/account-data.h @@ -34,11 +34,6 @@ public: : PendingRequest(requestId), groupId(groupId) {} }; -enum class FileFallback: uint8_t { - None, - ReplaceTgs, -}; - // Matching completed downloads to chats they belong to class DownloadRequest: public PendingRequest { public: @@ -46,15 +41,13 @@ public: std::string sender; int32_t timestamp; bool outgoing; - std::string label; - FileFallback fallbackType; - td::td_api::object_ptr fallback; + td::td_api::object_ptr thumbnail; + // Could not pass object_ptr through variadic funciton :( DownloadRequest(uint64_t requestId, int64_t chatId, const std::string &sender, int32_t timestamp, - bool outgoing, const std::string &label, FileFallback fallbackType, - td::td_api::file *fallback) + bool outgoing, td::td_api::file *thumbnail) : PendingRequest(requestId), chatId(chatId), sender(sender), timestamp(timestamp), - outgoing(outgoing), label(label), fallbackType(fallbackType), fallback(fallback) {} + outgoing(outgoing), thumbnail(thumbnail) {} }; class TdAccountData { diff --git a/td-client.cpp b/td-client.cpp index ad35eb4..8e43f90 100644 --- a/td-client.cpp +++ b/td-client.cpp @@ -559,6 +559,23 @@ void PurpleTdClient::showPhotoMessage(const td::td_api::chat &chat, const td::td showImage(chat, message, *file); } +void PurpleTdClient::requestDownload(int32_t fileId, int64_t chatId, const std::string &sender, + int32_t timestamp, bool outgoing, + td::td_api::object_ptr thumbnail, + TdTransceiver::ResponseCb responseCb) +{ + td::td_api::object_ptr downloadReq = + td::td_api::make_object(); + downloadReq->file_id_ = fileId; + downloadReq->priority_ = FILE_DOWNLOAD_PRIORITY; + downloadReq->offset_ = 0; + downloadReq->limit_ = 0; + downloadReq->synchronous_ = true; + + uint64_t requestId = m_transceiver.sendQuery(std::move(downloadReq), responseCb); + m_data.addPendingRequest(requestId, chatId, sender, timestamp, outgoing, thumbnail.release()); +} + void PurpleTdClient::showImage(const td::td_api::chat &chat, const td::td_api::message &message, const td::td_api::file &file) { @@ -568,41 +585,36 @@ void PurpleTdClient::showImage(const td::td_api::chat &chat, const td::td_api::m showDownloadedImage(chat.id_, sender, message.date_, message.is_outgoing_, file.local_->path_); else { purple_debug_misc(config::pluginId, "Downloading image (file id %d)\n", (int)file.id_); - td::td_api::object_ptr downloadReq = - td::td_api::make_object(); - downloadReq->file_id_ = file.id_; - downloadReq->priority_ = FILE_DOWNLOAD_PRIORITY; - downloadReq->offset_ = 0; - downloadReq->limit_ = 0; - downloadReq->synchronous_ = true; - - uint64_t requestId = m_transceiver.sendQuery(std::move(downloadReq), - &PurpleTdClient::imageDownloadResponse); - m_data.addPendingRequest(requestId, message.chat_id_, sender, message.date_, - message.is_outgoing_, "", FileFallback::None, nullptr); + requestDownload(file.id_, chat.id_, sender, message.date_, message.is_outgoing_, + nullptr, &PurpleTdClient::imageDownloadResponse); } } +static std::string getDownloadPath(const td::td_api::Object *object) +{ + if (!object) + purple_debug_misc(config::pluginId, "No response after downloading file\n"); + else if (object->get_id() == td::td_api::file::ID) { + const td::td_api::file &file = static_cast(*object); + if (!file.local_) + purple_debug_misc(config::pluginId, "No local file info after downloading\n"); + else if (!file.local_->is_downloading_completed_) + purple_debug_misc(config::pluginId, "File not completely downloaded\n"); + else + return file.local_->path_; + } else + purple_debug_misc(config::pluginId, "Unexpected response to downloading file: id %d\n", + (int)object->get_id()); + + return ""; +} + void PurpleTdClient::imageDownloadResponse(uint64_t requestId, td::td_api::object_ptr object) { - std::string path; + std::string path = getDownloadPath(object.get()); std::unique_ptr request = m_data.getPendingRequest(requestId); - if (!request) - return; - if (object->get_id() == td::td_api::file::ID) { - const td::td_api::file &file = static_cast(*object); - if (!file.local_) - purple_debug_misc(config::pluginId, "No local file info after downloading photo\n"); - else if (!file.local_->is_downloading_completed_) - purple_debug_misc(config::pluginId, "Image not completely downloaded\n"); - else - path = file.local_->path_; - } else - purple_debug_misc(config::pluginId, "Unexpected response to downloading image: id %d\n", - (int)object->get_id()); - - if (!path.empty()) { + if (request && !path.empty()) { purple_debug_misc(config::pluginId, "Image downloaded, path: %s\n", path.c_str()); showDownloadedImage(request->chatId, request->sender, request->timestamp, request->outgoing, path); } @@ -656,63 +668,19 @@ void PurpleTdClient::showSticker(const td::td_api::chat &chat, const td::td_api: if (!stickerContent.sticker_) return; td::td_api::sticker &sticker = *stickerContent.sticker_; - if (sticker.sticker_) - showInlineFile(chat, getSenderPurpleName(chat, message, m_data), message.date_, - message.is_outgoing_, *sticker.sticker_, "Sticker", FileFallback::ReplaceTgs, - sticker.thumbnail_ ? std::move(sticker.thumbnail_->photo_) : nullptr); -} + if (sticker.sticker_) { + std::string sender = getSenderPurpleName(chat, message, m_data); + auto thumbnail = sticker.thumbnail_ ? std::move(sticker.thumbnail_->photo_) : nullptr; -void PurpleTdClient::showInlineFile(const td::td_api::chat &chat, const std::string &sender, - int32_t timestamp, bool outgoing, - const td::td_api::file &file, const char *label, - FileFallback fallbackType, - td::td_api::object_ptr fallback) -{ - if (file.local_ && file.local_->is_downloading_completed_) - showDownloadedInlineFile(chat.id_, sender, timestamp, outgoing, - file.local_->path_, label, fallbackType, std::move(fallback)); - else { - purple_debug_misc(config::pluginId, "Downloading file (id %d)\n", (int)file.id_); - td::td_api::object_ptr downloadReq = - td::td_api::make_object(); - downloadReq->file_id_ = file.id_; - downloadReq->priority_ = FILE_DOWNLOAD_PRIORITY; - downloadReq->offset_ = 0; - downloadReq->limit_ = 0; - downloadReq->synchronous_ = true; - - uint64_t requestId = m_transceiver.sendQuery(std::move(downloadReq), - &PurpleTdClient::fileDownloadResponse); - m_data.addPendingRequest(requestId, chat.id_, sender, timestamp, - outgoing, label, fallbackType, - fallback.release()); - } -} - -void PurpleTdClient::fileDownloadResponse(uint64_t requestId, td::td_api::object_ptr object) -{ - std::string path; - std::unique_ptr request = m_data.getPendingRequest(requestId); - if (!request) - return; - - if (object->get_id() == td::td_api::file::ID) { - const td::td_api::file &file = static_cast(*object); - if (!file.local_) - purple_debug_misc(config::pluginId, "No local file info after downloading\n"); - else if (!file.local_->is_downloading_completed_) - purple_debug_misc(config::pluginId, "File not completely downloaded\n"); - else - path = file.local_->path_; - } else - purple_debug_misc(config::pluginId, "Unexpected response to downloading file: id %d\n", - (int)object->get_id()); - - if (!path.empty()) { - purple_debug_misc(config::pluginId, "File downloaded, path: %s\n", path.c_str()); - showDownloadedInlineFile(request->chatId, request->sender, request->timestamp, - request->outgoing, path, request->label.c_str(), - request->fallbackType, std::move(request->fallback)); + if (sticker.sticker_->local_ && sticker.sticker_->local_->is_downloading_completed_) + showDownloadedSticker(chat.id_, sender, message.date_, message.is_outgoing_, + sticker.sticker_->local_->path_, std::move(thumbnail)); + else { + purple_debug_misc(config::pluginId, "Downloading sticker (file id %d)\n", (int)sticker.sticker_->id_); + requestDownload(sticker.sticker_->id_, chat.id_, getSenderPurpleName(chat, message, m_data), + message.date_, message.is_outgoing_, std::move(thumbnail), + &PurpleTdClient::stickerDownloadResponse); + } } } @@ -725,19 +693,66 @@ static bool isTgs(const std::string &path) return false; } + +void PurpleTdClient::stickerDownloadResponse(uint64_t requestId, td::td_api::object_ptr object) +{ + std::string path = getDownloadPath(object.get()); + std::unique_ptr request = m_data.getPendingRequest(requestId); + + if (request && !path.empty()) + showDownloadedSticker(request->chatId, request->sender, request->timestamp, request->outgoing, + path, std::move(request->thumbnail)); +} + +void PurpleTdClient::showDownloadedSticker(int64_t chatId, const std::string &sender, int32_t timestamp, + bool outgoing, const std::string &filePath, + td::td_api::object_ptr thumbnail) +{ + if (isTgs(filePath) && thumbnail) { + if (thumbnail->local_ && thumbnail->local_->is_downloading_completed_) + showDownloadedInlineFile(chatId, sender, timestamp, outgoing, + thumbnail->local_->path_, "Sticker"); + else + requestDownload(thumbnail->id_, chatId, sender, + timestamp, outgoing, nullptr, + &PurpleTdClient::stickerDownloadResponse); + } else + showDownloadedInlineFile(chatId, sender, timestamp, outgoing, filePath, "Sticker"); +} + + +void PurpleTdClient::showInlineFile(const td::td_api::chat &chat, const td::td_api::message &message, + const td::td_api::file &file) +{ + std::string sender = getSenderPurpleName(chat, message, m_data); + + if (file.local_ && file.local_->is_downloading_completed_) + showDownloadedInlineFile(chat.id_, sender, message.date_, message.is_outgoing_, + file.local_->path_, "Sent file"); + else { + purple_debug_misc(config::pluginId, "Downloading file (id %d)\n", (int)file.id_); + requestDownload(file.id_, chat.id_, sender, message.date_, message.is_outgoing_, nullptr, + &PurpleTdClient::fileDownloadResponse); + } +} + +void PurpleTdClient::fileDownloadResponse(uint64_t requestId, td::td_api::object_ptr object) +{ + std::string path = getDownloadPath(object.get()); + std::unique_ptr request = m_data.getPendingRequest(requestId); + + if (request && !path.empty()) { + purple_debug_misc(config::pluginId, "File downloaded, path: %s\n", path.c_str()); + showDownloadedInlineFile(request->chatId, request->sender, request->timestamp, + request->outgoing, path, "Sent file"); + } +} + void PurpleTdClient::showDownloadedInlineFile(int64_t chatId, const std::string &sender, int32_t timestamp, - bool outgoing, const std::string &filePath, const char *label, - FileFallback fallbackType, - td::td_api::object_ptr fallback) + bool outgoing, const std::string &filePath, const char *label) { const td::td_api::chat *chat = m_data.getChat(chatId); if (chat) { - if ((fallbackType == FileFallback::ReplaceTgs && isTgs(filePath)) && fallback) { - showInlineFile(*chat, sender, timestamp, outgoing, *fallback, label, - FileFallback::None, nullptr); - return; - } - if (filePath.find('"') != std::string::npos) showMessageText(m_account, *chat, sender, NULL, "Cannot show file: path contains quotes", timestamp, outgoing, m_data); diff --git a/td-client.h b/td-client.h index 9512d8d..7fa5bc3 100644 --- a/td-client.h +++ b/td-client.h @@ -69,18 +69,23 @@ private: void addContactCreatePrivateChatResponse(uint64_t requestId, td::td_api::object_ptr object); void notifyFailedContact(const std::string &phoneNumber, const std::string &errorMessage); + void requestDownload(int32_t fileId, int64_t chatId, const std::string &sender, + int32_t timestamp, bool outgoing, + td::td_api::object_ptr thumbnail, + TdTransceiver::ResponseCb responseCb); void showImage(const td::td_api::chat &chat, const td::td_api::message &message, const td::td_api::file &file); void imageDownloadResponse(uint64_t requestId, td::td_api::object_ptr object); void showDownloadedImage(int64_t chatId, const std::string &sender, int32_t timestamp, bool outgoing, const std::string &filePath); - void showInlineFile(const td::td_api::chat &chat, const std::string &sender, int32_t timestamp, bool outgoing, - const td::td_api::file &file, const char *label, FileFallback fallbackType, - td::td_api::object_ptr fallback); + void showInlineFile(const td::td_api::chat &chat, const td::td_api::message &message, + const td::td_api::file &file); void fileDownloadResponse(uint64_t requestId, td::td_api::object_ptr object); void showDownloadedInlineFile(int64_t chatId, const std::string &sender, int32_t timestamp, - bool outgoing, const std::string &filePath, const char *label, - FileFallback fallbackType, - td::td_api::object_ptr fallback); + bool outgoing, const std::string &filePath, const char *label); + void stickerDownloadResponse(uint64_t requestId, td::td_api::object_ptr object); + void showDownloadedSticker(int64_t chatId, const std::string &sender, int32_t timestamp, + bool outgoing, const std::string &filePath, + td::td_api::object_ptr thumbnail); PurpleAccount *m_account; TdTransceiver m_transceiver;