diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index fd694f1e4..9c2e9c01d 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -158,7 +158,9 @@ inputFileRemote id:string = InputFile; //@description A file defined by a local path @path Local path to the file inputFileLocal path:string = InputFile; -//@description A file generated by the client @original_path Local path to a file from which the file is generated; may be empty if there is no such file @conversion String specifying the conversion applied to the original file; should be persistent across application restarts @expected_size Expected size of the generated file; 0 if unknown +//@description A file generated by the client @original_path Local path to a file from which the file is generated; may be empty if there is no such file +//@conversion String specifying the conversion applied to the original file; should be persistent across application restarts. Conversions beginning with '#' are reserved for internal TDLib usage +//@expected_size Expected size of the generated file; 0 if unknown inputFileGenerated original_path:string conversion:string expected_size:int32 = InputFile; diff --git a/td/telegram/SecureValue.cpp b/td/telegram/SecureValue.cpp index 177052273..c1c0f2c57 100644 --- a/td/telegram/SecureValue.cpp +++ b/td/telegram/SecureValue.cpp @@ -670,13 +670,6 @@ td_api::object_ptr get_encrypted_credentials_objec credentials.encrypted_secret); } -static string lpad0(string str, size_t size) { - if (str.size() >= size) { - return str; - } - return string(size - str.size(), '0') + str; -} - // TODO tests static Status check_date(int32 day, int32 month, int32 year) { if (day < 1 || day > 31) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index e56b819af..e3a30cbd6 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -361,7 +361,7 @@ class CliClient final : public Actor { FileGeneration file_generation; file_generation.id = update.generation_id_; file_generation.destination = update.destination_path_; - if (update.conversion_ == "#url#") { + if (update.conversion_ == "#url#" || update.conversion_ == "url") { // TODO: actually download file_generation.source = "test.jpg"; file_generation.part_size = 1000000; diff --git a/td/telegram/files/FileGenerateManager.cpp b/td/telegram/files/FileGenerateManager.cpp index ade86e8a4..476e523a5 100644 --- a/td/telegram/files/FileGenerateManager.cpp +++ b/td/telegram/files/FileGenerateManager.cpp @@ -343,34 +343,39 @@ FileGenerateManager::Query::~Query() = default; FileGenerateManager::Query::Query(Query &&other) = default; FileGenerateManager::Query &FileGenerateManager::Query::operator=(Query &&other) = default; -Status check_mtime(std::string &conversion, CSlice original_path) { +static Status check_mtime(std::string &conversion, CSlice original_path) { if (original_path.empty()) { return Status::OK(); } Parser parser(conversion); if (!parser.skip_start_with("#mtime#")) { - return td::Status::OK(); + return Status::OK(); } auto mtime_str = parser.read_till('#'); parser.skip('#'); + while (mtime_str.size() >= 2 && mtime_str[0] == '0') { + mtime_str.remove_prefix(1); + } auto r_mtime = to_integer_safe(mtime_str); if (parser.status().is_error() || r_mtime.is_error()) { - return td::Status::OK(); + return Status::OK(); } auto expected_mtime = r_mtime.move_as_ok(); conversion = parser.read_all().str(); auto r_stat = stat(original_path); uint64 actual_mtime = r_stat.is_ok() ? r_stat.ok().mtime_nsec_ : 0; if (expected_mtime == actual_mtime) { - return td::Status::OK(); + return Status::OK(); } - return td::Status::Error(PSLICE() << "mtime changed " << tag("file", original_path) - << tag("expected mtime", expected_mtime) << tag("actual mtime", actual_mtime)); + return Status::Error(PSLICE() << "File \"" << original_path + << "\" was modified: " << tag("expected modification time", expected_mtime) + << tag("actual modification time", actual_mtime)); } void FileGenerateManager::generate_file(uint64 query_id, FullGenerateFileLocation generate_location, const LocalFileLocation &local_location, string name, unique_ptr callback) { + LOG(INFO) << "Begin to generate file with " << generate_location; auto mtime_status = check_mtime(generate_location.conversion_, generate_location.original_path_); if (mtime_status.is_error()) { return callback->on_error(std::move(mtime_status)); diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index fd69e6693..e36fe9915 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -698,11 +698,10 @@ Result FileManager::register_generate(FileType file_type, FileLocationSo string original_path, string conversion, DialogId owner_dialog_id, int64 expected_size) { // add #mtime# into conversion - if (!original_path.empty() && !begins_with(conversion, "#mtime#") && !begins_with(conversion, "#file_id#") && - !begins_with(conversion, "#map#")) { + if (!original_path.empty() && conversion[0] != '#') { auto r_stat = stat(original_path); uint64 mtime = r_stat.is_ok() ? r_stat.ok().mtime_nsec_ : 0; - auto new_conversion = PSTRING() << "#mtime#" << mtime << "#" << conversion; + auto new_conversion = PSTRING() << "#mtime#" << lpad0(to_string(mtime), 20) << '#' << conversion; conversion = std::move(new_conversion); } @@ -849,12 +848,23 @@ static int merge_choose_remote_location(const RemoteFileLocation &x, int8 x_sour } return 2; } + static int merge_choose_generate_location(const unique_ptr &x, const unique_ptr &y) { - int x_type = static_cast(x != nullptr); - int y_type = static_cast(y != nullptr); - if (x_type != y_type) { - return x_type < y_type; + int x_empty = (x == nullptr); + int y_empty = (y == nullptr); + if (x_empty != y_empty) { + return x_empty ? 1 : 0; + } + if (!x_empty) { + bool x_has_mtime = begins_with(x->conversion_, "#mtime#"); + bool y_has_mtime = begins_with(y->conversion_, "#mtime#"); + if (x_has_mtime != y_has_mtime) { + return x_has_mtime ? 0 : 1; + } + return x->conversion_ >= y->conversion_ + ? 0 + : 1; // the bigger conversion, the bigger mtime or at least more stable choise } return 2; } diff --git a/tdutils/td/utils/misc.cpp b/tdutils/td/utils/misc.cpp index b935b137e..a6816f79c 100644 --- a/tdutils/td/utils/misc.cpp +++ b/tdutils/td/utils/misc.cpp @@ -36,6 +36,13 @@ string implode(vector v, char delimiter) { return result; } +string lpad0(string str, size_t size) { + if (str.size() >= size) { + return str; + } + return string(size - str.size(), '0') + str; +} + string oneline(Slice str) { string result; result.reserve(str.size()); diff --git a/tdutils/td/utils/misc.h b/tdutils/td/utils/misc.h index ee6f8ea84..7998bfc0c 100644 --- a/tdutils/td/utils/misc.h +++ b/tdutils/td/utils/misc.h @@ -194,6 +194,8 @@ T trim(T str) { return T(begin, end); } +string lpad0(string str, size_t size); + string oneline(Slice str); template