Actually upload file in sendCallLog.

This commit is contained in:
levlam 2022-04-22 18:17:36 +03:00
parent af97e963a9
commit 0511b962b9
3 changed files with 134 additions and 6 deletions

View File

@ -5424,7 +5424,7 @@ sendCallRating call_id:int32 rating:int32 comment:string problems:vector<CallPro
//@description Sends debug information for a call to Telegram servers @call_id Call identifier @debug_information Debug information in application-specific format
sendCallDebugInformation call_id:int32 debug_information:string = Ok;
//@description Sends log file for a call to Telegram servers @call_id Call identifier @log_file Call log file
//@description Sends log file for a call to Telegram servers @call_id Call identifier @log_file Call log file. Only inputFileLocal and inputFileGenerated are supported
sendCallLog call_id:int32 log_file:InputFile = Ok;

View File

@ -10,6 +10,7 @@
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DhCache.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/NetQueryCreator.h"
@ -327,12 +328,12 @@ void CallActor::send_call_debug_information(string data, Promise<Unit> promise)
auto query = G()->net_query_creator().create(tl_query);
send_with_promise(std::move(query),
PromiseCreator::lambda([actor_id = actor_id(this)](Result<NetQueryPtr> r_net_query) {
send_closure(actor_id, &CallActor::on_set_debug_query_result, std::move(r_net_query));
send_closure(actor_id, &CallActor::on_save_debug_query_result, std::move(r_net_query));
}));
loop();
}
void CallActor::on_set_debug_query_result(Result<NetQueryPtr> r_net_query) {
void CallActor::on_save_debug_query_result(Result<NetQueryPtr> r_net_query) {
auto res = fetch_result<telegram_api::phone_saveCallDebug>(std::move(r_net_query));
if (res.is_error()) {
return on_error(res.move_as_error());
@ -352,8 +353,123 @@ void CallActor::send_call_log(td_api::object_ptr<td_api::InputFile> log_file, Pr
if (!call_state_.need_log) {
return promise.set_error(Status::Error(400, "Unexpected sendCallLog"));
}
TRY_STATUS_PROMISE(promise, G()->close_status());
promise.set_error(Status::Error(500, "Unsupported"));
auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get();
auto r_file_id = file_manager->get_input_file_id(FileType::CallLog, log_file, DialogId(), false, false);
if (r_file_id.is_error()) {
return promise.set_error(Status::Error(400, r_file_id.error().message()));
}
auto file_id = r_file_id.move_as_ok();
FileView file_view = file_manager->get_file_view(file_id);
if (file_view.is_encrypted()) {
return promise.set_error(Status::Error(400, "Can't use encrypted file"));
}
if (!file_view.has_local_location() && !file_view.has_generate_location()) {
return promise.set_error(Status::Error(400, "Need local or generate location to upload call log"));
}
upload_log_file(file_id, std::move(promise));
}
void CallActor::upload_log_file(FileId file_id, Promise<Unit> &&promise) {
auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get();
auto upload_file_id = file_manager->dup_file_id(file_id);
LOG(INFO) << "Ask to upload call log file " << upload_file_id;
class UploadLogFileCallback final : public FileManager::UploadCallback {
ActorId<CallActor> actor_id_;
FileId file_id_;
Promise<Unit> promise_;
public:
UploadLogFileCallback(ActorId<CallActor> actor_id, FileId file_id, Promise<Unit> &&promise)
: actor_id_(actor_id), file_id_(file_id), promise_(std::move(promise)) {
}
void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
CHECK(file_id == file_id_);
send_closure_later(actor_id_, &CallActor::on_upload_log_file, file_id, std::move(promise_),
std::move(input_file));
}
void on_upload_encrypted_ok(FileId file_id, tl_object_ptr<telegram_api::InputEncryptedFile> input_file) final {
UNREACHABLE();
}
void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) final {
UNREACHABLE();
}
void on_upload_error(FileId file_id, Status error) final {
CHECK(file_id == file_id_);
send_closure_later(actor_id_, &CallActor::on_upload_log_file_error, file_id, std::move(promise_),
std::move(error));
}
};
file_manager->upload(upload_file_id,
std::make_shared<UploadLogFileCallback>(actor_id(this), upload_file_id, std::move(promise)), 1,
0);
}
void CallActor::on_upload_log_file(FileId file_id, Promise<Unit> &&promise,
tl_object_ptr<telegram_api::InputFile> input_file) {
LOG(INFO) << "Log file " << file_id << " has been uploaded";
TRY_STATUS_PROMISE(promise, G()->close_status());
do_upload_log_file(file_id, std::move(input_file), std::move(promise));
}
void CallActor::on_upload_log_file_error(FileId file_id, Promise<Unit> &&promise, Status status) {
LOG(WARNING) << "Log file " << file_id << " has upload error " << status;
CHECK(status.is_error());
TRY_STATUS_PROMISE(promise, G()->close_status());
promise.set_error(Status::Error(status.code() > 0 ? status.code() : 500,
status.message())); // TODO CHECK that status has always a code
}
void CallActor::do_upload_log_file(FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file,
Promise<Unit> &&promise) {
if (input_file == nullptr) {
return promise.set_error(Status::Error(500, "Failed to reupload call log"));
}
auto tl_query = telegram_api::phone_saveCallLog(get_input_phone_call("do_upload_log_file"), std::move(input_file));
send_with_promise(G()->net_query_creator().create(tl_query),
PromiseCreator::lambda([actor_id = actor_id(this), file_id,
promise = std::move(promise)](Result<NetQueryPtr> r_net_query) mutable {
send_closure(actor_id, &CallActor::on_save_log_query_result, file_id, std::move(promise),
std::move(r_net_query));
}));
loop();
}
void CallActor::on_save_log_query_result(FileId file_id, Promise<Unit> promise, Result<NetQueryPtr> r_net_query) {
TRY_STATUS_PROMISE(promise, G()->close_status());
auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get();
file_manager->delete_partial_remote_location(file_id);
file_manager->cancel_upload(file_id);
auto res = fetch_result<telegram_api::phone_saveCallLog>(std::move(r_net_query));
if (res.is_error()) {
auto error = res.move_as_error();
if (begins_with(error.message(), "FILE_PART_") && ends_with(error.message(), "_MISSING")) {
// TODO on_upload_log_file_part_missing(file_id, to_integer<int32>(error.message().substr(10)));
// return;
}
return promise.set_error(std::move(error));
}
if (call_state_.need_log) {
call_state_.need_log = false;
call_state_need_flush_ = true;
}
loop();
promise.set_value(Unit());
}
// Requests
@ -830,7 +946,7 @@ void CallActor::loop() {
break;
case State::Discarded: {
if (call_state_.type == CallState::Type::Discarded &&
(call_state_.need_rating || call_state_.need_debug_information)) {
(call_state_.need_rating || call_state_.need_debug_information || call_state_.need_log)) {
break;
}
LOG(INFO) << "Close " << local_call_id_;

View File

@ -9,6 +9,7 @@
#include "td/telegram/CallDiscardReason.h"
#include "td/telegram/CallId.h"
#include "td/telegram/DhConfig.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
@ -184,7 +185,18 @@ class CallActor final : public NetQueryCallback {
void on_call_discarded(CallDiscardReason reason, bool need_rating, bool need_debug, bool is_video);
void on_set_rating_query_result(Result<NetQueryPtr> r_net_query);
void on_set_debug_query_result(Result<NetQueryPtr> r_net_query);
void on_save_debug_query_result(Result<NetQueryPtr> r_net_query);
void upload_log_file(FileId file_id, Promise<Unit> &&promise);
void on_upload_log_file(FileId file_id, Promise<Unit> &&promise, tl_object_ptr<telegram_api::InputFile> input_file);
void on_upload_log_file_error(FileId file_id, Promise<Unit> &&promise, Status status);
void do_upload_log_file(FileId file_id, tl_object_ptr<telegram_api::InputFile> &&input_file, Promise<Unit> &&promise);
void on_save_log_query_result(FileId file_id, Promise<Unit> promise, Result<NetQueryPtr> r_net_query);
void on_get_call_config_result(Result<NetQueryPtr> r_net_query);