Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
f73adb408a
@ -143,8 +143,7 @@ void set_menu_button(Td *td, UserId user_id, td_api::object_ptr<td_api::botMenuB
|
||||
}
|
||||
auto r_url = LinkManager::check_link(menu_button->url_, true, !G()->is_test_dc());
|
||||
if (r_url.is_error()) {
|
||||
return promise.set_error(Status::Error(400, PSLICE() << "Menu button web app URL '" << menu_button->url_
|
||||
<< "' is invalid: " << r_url.error().message()));
|
||||
return promise.set_error(Status::Error(400, PSLICE() << "Menu button Web App " << r_url.error().message()));
|
||||
}
|
||||
input_bot_menu_button = telegram_api::make_object<telegram_api::botMenuButton>(menu_button->text_, r_url.ok());
|
||||
}
|
||||
|
@ -15808,6 +15808,10 @@ void ContactsManager::on_update_dialog_administrators(DialogId dialog_id, vector
|
||||
void ContactsManager::reload_dialog_administrators(DialogId dialog_id,
|
||||
const vector<DialogAdministrator> &dialog_administrators,
|
||||
Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise) {
|
||||
auto dialog_type = dialog_id.get_type();
|
||||
if (dialog_type == DialogType::Chat && !get_chat_permissions(dialog_id.get_chat_id()).is_member()) {
|
||||
return promise.set_value(td_api::object_ptr<td_api::chatAdministrators>());
|
||||
}
|
||||
auto query_promise = PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this), dialog_id, promise = std::move(promise)](Result<Unit> &&result) mutable {
|
||||
if (promise) {
|
||||
@ -15818,7 +15822,7 @@ void ContactsManager::reload_dialog_administrators(DialogId dialog_id,
|
||||
}
|
||||
}
|
||||
});
|
||||
switch (dialog_id.get_type()) {
|
||||
switch (dialog_type) {
|
||||
case DialogType::Chat:
|
||||
load_chat_full(dialog_id.get_chat_id(), false, std::move(query_promise), "reload_dialog_administrators");
|
||||
break;
|
||||
|
@ -4675,14 +4675,15 @@ bool GroupCallManager::set_group_call_participant_count(GroupCall *group_call, i
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Set " << group_call->group_call_id << " participant count to " << count << " from " << source;
|
||||
auto input_group_call_id = get_input_group_call_id(group_call->group_call_id).ok();
|
||||
if (count < 0) {
|
||||
LOG(ERROR) << "Participant count became negative in " << group_call->group_call_id << " in "
|
||||
<< group_call->dialog_id << " from " << source;
|
||||
count = 0;
|
||||
reload_group_call(input_group_call_id, Auto());
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
auto input_group_call_id = get_input_group_call_id(group_call->group_call_id).ok();
|
||||
if (need_group_call_participants(input_group_call_id, group_call)) {
|
||||
auto known_participant_count =
|
||||
static_cast<int32>(add_group_call_participants(input_group_call_id)->participants.size());
|
||||
@ -4738,6 +4739,8 @@ bool GroupCallManager::set_group_call_unmuted_video_count(GroupCall *group_call,
|
||||
LOG(ERROR) << "Video participant count became negative in " << group_call->group_call_id << " in "
|
||||
<< group_call->dialog_id << " from " << source;
|
||||
count = 0;
|
||||
auto input_group_call_id = get_input_group_call_id(group_call->group_call_id).ok();
|
||||
reload_group_call(input_group_call_id, Auto());
|
||||
}
|
||||
|
||||
if (group_call->unmuted_video_count == count) {
|
||||
|
@ -708,7 +708,28 @@ static bool tolower_begins_with(Slice str, Slice prefix) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Result<string> LinkManager::check_link(Slice link, bool http_only, bool https_only) {
|
||||
Result<string> LinkManager::check_link(CSlice link, bool http_only, bool https_only) {
|
||||
auto result = check_link_impl(link, http_only, https_only);
|
||||
if (result.is_ok()) {
|
||||
return std::move(result);
|
||||
}
|
||||
auto error = result.move_as_error();
|
||||
if (check_utf8(link)) {
|
||||
return Status::Error(400, PSLICE() << "URL '" << link << "' is invalid: " << error.message());
|
||||
} else {
|
||||
return Status::Error(400, PSLICE() << "URL is invalid: " << error.message());
|
||||
}
|
||||
}
|
||||
|
||||
string LinkManager::get_checked_link(Slice link, bool http_only, bool https_only) {
|
||||
auto result = check_link_impl(link, http_only, https_only);
|
||||
if (result.is_ok()) {
|
||||
return result.move_as_ok();
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
Result<string> LinkManager::check_link_impl(Slice link, bool http_only, bool https_only) {
|
||||
bool is_tg = false;
|
||||
bool is_ton = false;
|
||||
if (tolower_begins_with(link, "tg:")) {
|
||||
|
@ -47,7 +47,10 @@ class LinkManager final : public Actor {
|
||||
};
|
||||
|
||||
// checks whether the link is a valid tg, ton or HTTP(S) URL and returns it in a canonical form
|
||||
static Result<string> check_link(Slice link, bool http_only = false, bool https_only = false);
|
||||
static Result<string> check_link(CSlice link, bool http_only = false, bool https_only = false);
|
||||
|
||||
// same as check_link, but returns an empty string instead of an error
|
||||
static string get_checked_link(Slice link, bool http_only = false, bool https_only = false);
|
||||
|
||||
// checks whether the link is a supported tg or t.me link and parses it
|
||||
static unique_ptr<InternalLink> parse_internal_link(Slice link);
|
||||
@ -128,6 +131,8 @@ class LinkManager final : public Actor {
|
||||
|
||||
static unique_ptr<InternalLink> get_internal_link_message_draft(Slice url, Slice text);
|
||||
|
||||
static Result<string> check_link_impl(Slice link, bool http_only, bool https_only);
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
|
||||
|
@ -1723,7 +1723,7 @@ static Result<InputMessageContent> create_input_message_content(
|
||||
td->animations_manager_->create_animation(
|
||||
file_id, string(), thumbnail, AnimationSize(), has_stickers, std::move(sticker_file_ids),
|
||||
std::move(file_name), std::move(mime_type), input_animation->duration_,
|
||||
get_dimensions(input_animation->width_, input_animation->height_, "inputMessageAnimation"), false);
|
||||
get_dimensions(input_animation->width_, input_animation->height_, nullptr), false);
|
||||
|
||||
content = make_unique<MessageAnimation>(file_id, std::move(caption));
|
||||
break;
|
||||
@ -1792,7 +1792,7 @@ static Result<InputMessageContent> create_input_message_content(
|
||||
|
||||
PhotoSize s;
|
||||
s.type = type;
|
||||
s.dimensions = get_dimensions(input_photo->width_, input_photo->height_, "inputMessagePhoto");
|
||||
s.dimensions = get_dimensions(input_photo->width_, input_photo->height_, nullptr);
|
||||
s.size = static_cast<int32>(file_view.size());
|
||||
s.file_id = file_id;
|
||||
|
||||
@ -1815,10 +1815,9 @@ static Result<InputMessageContent> create_input_message_content(
|
||||
|
||||
emoji = std::move(input_sticker->emoji_);
|
||||
|
||||
td->stickers_manager_->create_sticker(
|
||||
file_id, string(), thumbnail,
|
||||
get_dimensions(input_sticker->width_, input_sticker->height_, "inputMessageSticker"), nullptr,
|
||||
StickerFormat::Unknown, nullptr);
|
||||
td->stickers_manager_->create_sticker(file_id, string(), thumbnail,
|
||||
get_dimensions(input_sticker->width_, input_sticker->height_, nullptr),
|
||||
nullptr, StickerFormat::Unknown, nullptr);
|
||||
|
||||
content = make_unique<MessageSticker>(file_id);
|
||||
break;
|
||||
@ -1829,11 +1828,10 @@ static Result<InputMessageContent> create_input_message_content(
|
||||
ttl = input_video->ttl_;
|
||||
|
||||
bool has_stickers = !sticker_file_ids.empty();
|
||||
td->videos_manager_->create_video(file_id, string(), thumbnail, AnimationSize(), has_stickers,
|
||||
std::move(sticker_file_ids), std::move(file_name), std::move(mime_type),
|
||||
input_video->duration_,
|
||||
get_dimensions(input_video->width_, input_video->height_, "inputMessageVideo"),
|
||||
input_video->supports_streaming_, false);
|
||||
td->videos_manager_->create_video(
|
||||
file_id, string(), thumbnail, AnimationSize(), has_stickers, std::move(sticker_file_ids),
|
||||
std::move(file_name), std::move(mime_type), input_video->duration_,
|
||||
get_dimensions(input_video->width_, input_video->height_, nullptr), input_video->supports_streaming_, false);
|
||||
|
||||
content = make_unique<MessageVideo>(file_id, std::move(caption));
|
||||
break;
|
||||
@ -1847,7 +1845,7 @@ static Result<InputMessageContent> create_input_message_content(
|
||||
}
|
||||
|
||||
td->video_notes_manager_->create_video_note(file_id, string(), thumbnail, input_video_note->duration_,
|
||||
get_dimensions(length, length, "inputMessageVideoNote"), false);
|
||||
get_dimensions(length, length, nullptr), false);
|
||||
|
||||
content = make_unique<MessageVideoNote>(file_id, false);
|
||||
break;
|
||||
@ -2083,7 +2081,7 @@ Result<InputMessageContent> get_input_message_content(
|
||||
LOG(WARNING) << "Ignore thumbnail file: " << r_thumbnail_file_id.error().message();
|
||||
} else {
|
||||
thumbnail.type = 't';
|
||||
thumbnail.dimensions = get_dimensions(input_thumbnail->width_, input_thumbnail->height_, "inputThumbnail");
|
||||
thumbnail.dimensions = get_dimensions(input_thumbnail->width_, input_thumbnail->height_, nullptr);
|
||||
thumbnail.file_id = r_thumbnail_file_id.ok();
|
||||
CHECK(thumbnail.file_id.is_valid());
|
||||
|
||||
@ -4334,8 +4332,8 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
|
||||
}
|
||||
case telegram_api::messageMediaPoll::ID: {
|
||||
auto media_poll = move_tl_object_as<telegram_api::messageMediaPoll>(media);
|
||||
auto poll_id =
|
||||
td->poll_manager_->on_get_poll(PollId(), std::move(media_poll->poll_), std::move(media_poll->results_));
|
||||
auto poll_id = td->poll_manager_->on_get_poll(PollId(), std::move(media_poll->poll_),
|
||||
std::move(media_poll->results_), "messageMediaPoll");
|
||||
if (!poll_id.is_valid()) {
|
||||
break;
|
||||
}
|
||||
|
@ -1876,9 +1876,9 @@ Result<vector<MessageEntity>> parse_markdown(string &text) {
|
||||
if (user_id.is_valid()) {
|
||||
entities.emplace_back(entity_offset, entity_length, user_id);
|
||||
} else {
|
||||
auto r_url = LinkManager::check_link(url);
|
||||
if (r_url.is_ok()) {
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, r_url.move_as_ok());
|
||||
url = LinkManager::get_checked_link(url);
|
||||
if (!url.empty()) {
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, std::move(url));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2092,11 +2092,11 @@ static Result<vector<MessageEntity>> do_parse_markdown_v2(CSlice text, string &r
|
||||
}
|
||||
user_id = LinkManager::get_link_user_id(url);
|
||||
if (!user_id.is_valid()) {
|
||||
auto r_url = LinkManager::check_link(url);
|
||||
if (r_url.is_error()) {
|
||||
url = LinkManager::get_checked_link(url);
|
||||
if (url.empty()) {
|
||||
skip_entity = true;
|
||||
} else {
|
||||
argument = r_url.move_as_ok();
|
||||
argument = std::move(url);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2169,7 +2169,7 @@ static vector<Slice> find_text_url_entities_v3(Slice text) {
|
||||
|
||||
if (url_end < size) {
|
||||
Slice url = text.substr(url_begin + 1, url_end - url_begin - 1);
|
||||
if (LinkManager::check_link(url).is_ok()) {
|
||||
if (!LinkManager::get_checked_link(url).empty()) {
|
||||
result.push_back(text.substr(text_begin, text_end - text_begin + 1));
|
||||
result.push_back(text.substr(url_begin, url_end - url_begin + 1));
|
||||
}
|
||||
@ -2241,7 +2241,7 @@ static FormattedText parse_text_url_entities_v3(Slice text, const vector<Message
|
||||
Slice url = parsed_part_text.substr(url_begin_pos + 1, url_end_pos - url_begin_pos - 1);
|
||||
auto url_utf16_length = text_length(url);
|
||||
result.entities.emplace_back(MessageEntity::Type::TextUrl, result_text_utf16_length, text_url_utf16_length,
|
||||
LinkManager::check_link(url).move_as_ok());
|
||||
LinkManager::get_checked_link(url));
|
||||
result.text.append(text_url.begin(), text_url.size());
|
||||
result_text_utf16_length += text_url_utf16_length;
|
||||
|
||||
@ -3075,9 +3075,9 @@ static Result<vector<MessageEntity>> do_parse_html(CSlice text, string &result)
|
||||
if (user_id.is_valid()) {
|
||||
entities.emplace_back(entity_offset, entity_length, user_id);
|
||||
} else {
|
||||
auto r_url = LinkManager::check_link(url);
|
||||
if (r_url.is_ok()) {
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, r_url.move_as_ok());
|
||||
url = LinkManager::get_checked_link(url);
|
||||
if (!url.empty()) {
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity_offset, entity_length, std::move(url));
|
||||
}
|
||||
}
|
||||
} else if (tag_name == "pre") {
|
||||
@ -3284,7 +3284,7 @@ Result<vector<MessageEntity>> get_message_entities(const ContactsManager *contac
|
||||
}
|
||||
auto r_url = LinkManager::check_link(entity->url_);
|
||||
if (r_url.is_error()) {
|
||||
return Status::Error(400, PSTRING() << "Wrong URL entity specified: " << r_url.error().message());
|
||||
return Status::Error(400, PSTRING() << "Entity " << r_url.error().message());
|
||||
}
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, offset, length, r_url.move_as_ok());
|
||||
break;
|
||||
@ -3418,8 +3418,7 @@ vector<MessageEntity> get_message_entities(const ContactsManager *contacts_manag
|
||||
auto entity = static_cast<const telegram_api::messageEntityTextUrl *>(server_entity.get());
|
||||
auto r_url = LinkManager::check_link(entity->url_);
|
||||
if (r_url.is_error()) {
|
||||
LOG(ERROR) << "Wrong URL entity: \"" << entity->url_ << "\": " << r_url.error().message() << " from "
|
||||
<< source;
|
||||
LOG(ERROR) << "Entity " << r_url.error().message() << " from " << source;
|
||||
continue;
|
||||
}
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok());
|
||||
@ -3540,7 +3539,7 @@ vector<MessageEntity> get_message_entities(vector<tl_object_ptr<secret_api::Mess
|
||||
}
|
||||
auto r_url = LinkManager::check_link(entity->url_);
|
||||
if (r_url.is_error()) {
|
||||
LOG(WARNING) << "Wrong URL entity: \"" << entity->url_ << "\": " << r_url.error().message();
|
||||
LOG(WARNING) << "Entity " << r_url.error().message();
|
||||
continue;
|
||||
}
|
||||
entities.emplace_back(MessageEntity::Type::TextUrl, entity->offset_, entity->length_, r_url.move_as_ok());
|
||||
|
@ -871,6 +871,9 @@ class SearchPublicDialogsQuery final : public Td::ResultHandler {
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (!G()->is_expected_error(status)) {
|
||||
if (status.message() == "QUERY_TOO_SHORT") {
|
||||
return td_->messages_manager_->on_get_public_dialogs_search_result(query_, {}, {});
|
||||
}
|
||||
LOG(ERROR) << "Receive error for SearchPublicDialogsQuery: " << status;
|
||||
}
|
||||
td_->messages_manager_->on_failed_public_dialogs_search(query_, std::move(status));
|
||||
@ -9683,7 +9686,7 @@ void MessagesManager::on_get_history(DialogId dialog_id, MessageId from_message_
|
||||
// new server messages were added to the dialog since the request was sent, but weren't received
|
||||
// they should have been received, so we must repeat the request to get them
|
||||
if (from_the_end) {
|
||||
get_history_from_the_end_impl(d, false, false, std::move(promise));
|
||||
get_history_from_the_end_impl(d, false, false, std::move(promise), "on_get_history");
|
||||
} else {
|
||||
get_history_impl(d, from_message_id, offset, limit, false, false, std::move(promise));
|
||||
}
|
||||
@ -9786,14 +9789,15 @@ void MessagesManager::on_get_history(DialogId dialog_id, MessageId from_message_
|
||||
}
|
||||
|
||||
for (auto &message : messages) {
|
||||
if (!have_next && from_the_end && get_message_id(message, false) < d->last_message_id) {
|
||||
auto expected_message_id = get_message_id(message, false);
|
||||
if (!have_next && from_the_end && expected_message_id < d->last_message_id) {
|
||||
// last message in the dialog should be attached to the next message if there is some
|
||||
have_next = true;
|
||||
}
|
||||
|
||||
auto message_dialog_id = get_message_dialog_id(message);
|
||||
if (message_dialog_id != dialog_id) {
|
||||
LOG(ERROR) << "Receive " << get_message_id(message, false) << " in wrong " << message_dialog_id << " instead of "
|
||||
LOG(ERROR) << "Receive " << expected_message_id << " in wrong " << message_dialog_id << " instead of "
|
||||
<< dialog_id << ": " << oneline(to_string(message));
|
||||
continue;
|
||||
}
|
||||
@ -9802,6 +9806,7 @@ void MessagesManager::on_get_history(DialogId dialog_id, MessageId from_message_
|
||||
on_get_message(std::move(message), false, is_channel_message, false, false, have_next, "get history");
|
||||
auto message_id = full_message_id.get_message_id();
|
||||
if (message_id.is_valid()) {
|
||||
CHECK(message_id == expected_message_id);
|
||||
if (!last_added_message_id.is_valid()) {
|
||||
last_added_message_id = message_id;
|
||||
}
|
||||
@ -12666,7 +12671,7 @@ void MessagesManager::set_dialog_max_unavailable_message_id(DialogId dialog_id,
|
||||
}
|
||||
|
||||
if (max_unavailable_message_id.is_valid() && max_unavailable_message_id.is_yet_unsent()) {
|
||||
LOG(ERROR) << "Tried to update " << dialog_id << " last read outbox message with " << max_unavailable_message_id
|
||||
LOG(ERROR) << "Tried to update " << dialog_id << " max unavailable message with " << max_unavailable_message_id
|
||||
<< " from " << source;
|
||||
return;
|
||||
}
|
||||
@ -17373,7 +17378,9 @@ void MessagesManager::synchronize_dialog_filters() {
|
||||
vector<DialogId> MessagesManager::search_public_dialogs(const string &query, Promise<Unit> &&promise) {
|
||||
LOG(INFO) << "Search public chats with query = \"" << query << '"';
|
||||
|
||||
if (utf8_length(query) < MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN) {
|
||||
auto query_length = utf8_length(query);
|
||||
if (query_length < MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN ||
|
||||
(query_length == MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN && query[0] == '@')) {
|
||||
string username = clean_username(query);
|
||||
if (username[0] == '@') {
|
||||
username = username.substr(1);
|
||||
@ -23631,7 +23638,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
// new messages where added to the database since the request was sent
|
||||
// they should have been received from the database, so we must repeat the request to get them
|
||||
if (from_the_end) {
|
||||
get_history_from_the_end_impl(d, true, only_local, std::move(promise));
|
||||
get_history_from_the_end_impl(d, true, only_local, std::move(promise), "on_get_history_from_database 20");
|
||||
} else {
|
||||
get_history_impl(d, from_message_id, offset, limit, true, only_local, std::move(promise));
|
||||
}
|
||||
@ -23660,7 +23667,8 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
auto debug_first_database_message_id = d->first_database_message_id;
|
||||
auto debug_last_message_id = d->last_message_id;
|
||||
auto debug_last_new_message_id = d->last_new_message_id;
|
||||
auto last_received_message_id = MessageId::max();
|
||||
auto first_received_message_id = MessageId::max();
|
||||
MessageId last_received_message_id;
|
||||
size_t pos = 0;
|
||||
for (auto &message_slice : messages) {
|
||||
if (!d->first_database_message_id.is_valid() && !d->have_full_history) {
|
||||
@ -23675,13 +23683,16 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (message->message_id >= last_received_message_id) {
|
||||
LOG(ERROR) << "Receive " << message->message_id << " after " << last_received_message_id
|
||||
if (message->message_id >= first_received_message_id) {
|
||||
LOG(ERROR) << "Receive " << message->message_id << " after " << first_received_message_id
|
||||
<< " from database in the history of " << dialog_id << " from " << from_message_id << " with offset "
|
||||
<< offset << ", limit " << limit << ", from_the_end = " << from_the_end;
|
||||
break;
|
||||
}
|
||||
first_received_message_id = message->message_id;
|
||||
if (!last_received_message_id.is_valid()) {
|
||||
last_received_message_id = message->message_id;
|
||||
}
|
||||
|
||||
if (message->message_id < d->first_database_message_id) {
|
||||
if (d->have_full_history) {
|
||||
@ -23718,10 +23729,11 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
}
|
||||
if (next_message != nullptr && !next_message->have_previous) {
|
||||
LOG_CHECK(m->message_id < next_message->message_id)
|
||||
<< m->message_id << ' ' << next_message->message_id << ' ' << last_received_message_id << ' ' << dialog_id
|
||||
<< ' ' << from_message_id << ' ' << offset << ' ' << limit << ' ' << from_the_end << ' ' << only_local
|
||||
<< ' ' << messages.size() << ' ' << debug_first_database_message_id << ' ' << last_added_message_id << ' '
|
||||
<< added_new_message << ' ' << pos << ' ' << m << ' ' << next_message << ' ' << old_message << ' '
|
||||
<< m->message_id << ' ' << next_message->message_id << ' ' << first_received_message_id << ' '
|
||||
<< last_received_message_id << ' ' << dialog_id << ' ' << from_message_id << ' ' << offset << ' ' << limit
|
||||
<< ' ' << from_the_end << ' ' << only_local << ' ' << messages.size() << ' '
|
||||
<< debug_first_database_message_id << ' ' << last_added_message_id << ' ' << added_new_message << ' ' << pos
|
||||
<< ' ' << m << ' ' << next_message << ' ' << old_message << ' '
|
||||
<< to_string(get_message_object(dialog_id, m, "on_get_history_from_database"))
|
||||
<< to_string(get_message_object(dialog_id, next_message, "on_get_history_from_database"));
|
||||
LOG(INFO) << "Fix have_previous for " << next_message->message_id;
|
||||
@ -23744,35 +23756,39 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
|
||||
if (from_the_end && !last_added_message_id.is_valid() && d->first_database_message_id.is_valid() &&
|
||||
!d->have_full_history) {
|
||||
if (last_received_message_id <= d->first_database_message_id) {
|
||||
if (first_received_message_id <= d->first_database_message_id) {
|
||||
// database definitely has no messages from first_database_message_id to last_database_message_id; drop them
|
||||
set_dialog_first_database_message_id(d, MessageId(), "on_get_history_from_database 8");
|
||||
set_dialog_last_database_message_id(d, MessageId(), "on_get_history_from_database 9");
|
||||
} else {
|
||||
CHECK(last_received_message_id.is_valid());
|
||||
CHECK(first_received_message_id.is_valid());
|
||||
// if a message was received, but wasn't added, then it is likely to be already deleted
|
||||
// if it is less than d->last_database_message_id, then we can adjust d->last_database_message_id and
|
||||
// try again database search without chance to loop
|
||||
if (last_received_message_id < d->last_database_message_id) {
|
||||
set_dialog_last_database_message_id(d, last_received_message_id, "on_get_history_from_database 12");
|
||||
if (first_received_message_id < d->last_database_message_id) {
|
||||
set_dialog_last_database_message_id(d, first_received_message_id, "on_get_history_from_database 12");
|
||||
|
||||
get_history_from_the_end_impl(d, true, only_local, std::move(promise));
|
||||
get_history_from_the_end_impl(d, true, only_local, std::move(promise), "on_get_history_from_database 21");
|
||||
return;
|
||||
}
|
||||
|
||||
if (limit > 1) {
|
||||
// we expected to have messages [first_database_message_id, last_database_message_id] in the database, but
|
||||
// received no messages or newer messages [last_received_message_id, ...], none of which can be added
|
||||
// received messages [first_received_message_id, last_received_message_id], none of which can be added
|
||||
// first_database_message_id and last_database_message_id are very wrong, so it is better to drop them,
|
||||
// pretending that the database has no usable messages
|
||||
if (last_received_message_id == MessageId::max()) {
|
||||
if (first_received_message_id == MessageId::max()) {
|
||||
CHECK(last_received_message_id == MessageId());
|
||||
LOG(ERROR) << "Receive no usable messages in " << dialog_id
|
||||
<< " from database from the end, but expected messages from " << d->last_database_message_id
|
||||
<< " up to " << d->first_database_message_id;
|
||||
<< " from database from the end, but expected messages from " << d->first_database_message_id
|
||||
<< " up to " << d->last_database_message_id
|
||||
<< ". Have old last_database_message_id = " << old_last_database_message_id << " and "
|
||||
<< messages.size() << " received messages";
|
||||
} else {
|
||||
LOG(ERROR) << "Receive " << messages.size() << " unusable messages up to " << last_received_message_id
|
||||
<< " in " << dialog_id << " from database from the end, but expected messages from "
|
||||
<< d->last_database_message_id << " up to " << d->first_database_message_id;
|
||||
LOG(ERROR) << "Receive " << messages.size() << " unusable messages [" << first_received_message_id << " ... "
|
||||
<< last_received_message_id << "] in " << dialog_id
|
||||
<< " from database from the end, but expected messages from " << d->first_database_message_id
|
||||
<< " up to " << d->last_database_message_id;
|
||||
}
|
||||
set_dialog_first_database_message_id(d, MessageId(), "on_get_history_from_database 13");
|
||||
set_dialog_last_database_message_id(d, MessageId(), "on_get_history_from_database 14");
|
||||
@ -23821,7 +23837,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
}
|
||||
}
|
||||
if (first_added_message_id.is_valid() && first_added_message_id != d->first_database_message_id &&
|
||||
last_received_message_id < d->first_database_message_id && d->last_new_message_id.is_valid() &&
|
||||
first_received_message_id < d->first_database_message_id && d->last_new_message_id.is_valid() &&
|
||||
!d->have_full_history) {
|
||||
CHECK(first_added_message_id > d->first_database_message_id);
|
||||
set_dialog_first_database_message_id(d, first_added_message_id, "on_get_history_from_database 10");
|
||||
@ -23839,11 +23855,12 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
|
||||
|
||||
void MessagesManager::get_history_from_the_end(DialogId dialog_id, bool from_database, bool only_local,
|
||||
Promise<Unit> &&promise) {
|
||||
get_history_from_the_end_impl(get_dialog(dialog_id), from_database, only_local, std::move(promise));
|
||||
get_history_from_the_end_impl(get_dialog(dialog_id), from_database, only_local, std::move(promise),
|
||||
"get_history_from_the_end");
|
||||
}
|
||||
|
||||
void MessagesManager::get_history_from_the_end_impl(const Dialog *d, bool from_database, bool only_local,
|
||||
Promise<Unit> &&promise) {
|
||||
Promise<Unit> &&promise, const char *source) {
|
||||
CHECK(d != nullptr);
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
@ -23861,7 +23878,7 @@ void MessagesManager::get_history_from_the_end_impl(const Dialog *d, bool from_d
|
||||
// repair last database message ID
|
||||
limit = 10;
|
||||
}
|
||||
LOG(INFO) << "Get history from the end of " << dialog_id << " from database";
|
||||
LOG(INFO) << "Get history from the end of " << dialog_id << " from database from " << source;
|
||||
MessagesDbMessagesQuery db_query;
|
||||
db_query.dialog_id = dialog_id;
|
||||
db_query.from_message_id = MessageId::max();
|
||||
@ -23885,7 +23902,7 @@ void MessagesManager::get_history_from_the_end_impl(const Dialog *d, bool from_d
|
||||
limit = 10;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Get history from the end of " << dialog_id << " from server";
|
||||
LOG(INFO) << "Get history from the end of " << dialog_id << " from server from " << source;
|
||||
td_->create_handler<GetHistoryQuery>(std::move(promise))
|
||||
->send_get_from_the_end(dialog_id, d->last_new_message_id, limit);
|
||||
}
|
||||
@ -23962,7 +23979,7 @@ void MessagesManager::load_messages_impl(const Dialog *d, MessageId from_message
|
||||
bool from_database = (left_tries > 2 || only_local) && G()->parameters().use_message_db;
|
||||
|
||||
if (from_message_id == MessageId()) {
|
||||
get_history_from_the_end_impl(d, from_database, only_local, std::move(promise));
|
||||
get_history_from_the_end_impl(d, from_database, only_local, std::move(promise), "load_messages_impl");
|
||||
return;
|
||||
}
|
||||
if ((!d->first_database_message_id.is_valid() || from_message_id <= d->first_database_message_id) &&
|
||||
@ -32906,7 +32923,7 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
|
||||
return;
|
||||
}
|
||||
CHECK(m->message_id.is_yet_unsent());
|
||||
if (m->forward_info != nullptr || m->had_forward_info || m->message_id.is_scheduled() ||
|
||||
if (m->forward_info != nullptr || m->had_forward_info || m->is_copy || m->message_id.is_scheduled() ||
|
||||
m->sender_dialog_id.is_valid()) {
|
||||
return;
|
||||
}
|
||||
@ -36380,7 +36397,8 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
|
||||
d->last_new_message_id = MessageId();
|
||||
}
|
||||
if (last_message_id.is_valid()) {
|
||||
if ((last_message_id.is_server() || dialog_type == DialogType::SecretChat) && !d->last_new_message_id.is_valid()) {
|
||||
if ((last_message_id.is_server() || dialog_type == DialogType::SecretChat) && !last_message_id.is_yet_unsent() &&
|
||||
!d->last_new_message_id.is_valid()) {
|
||||
LOG(ERROR) << "Bugfixing wrong last_new_message_id to " << last_message_id << " in " << dialog_id;
|
||||
// must be called before set_dialog_first_database_message_id and set_dialog_last_database_message_id
|
||||
set_dialog_last_new_message_id(d, last_message_id, "fix_new_dialog 1");
|
||||
@ -36418,19 +36436,24 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
|
||||
}
|
||||
};
|
||||
|
||||
auto last_message_date = last_database_message->date;
|
||||
if (dependent_dialog_count == 0) {
|
||||
add_dialog_last_database_message(d, std::move(last_database_message));
|
||||
if (!add_dialog_last_database_message(d, std::move(last_database_message))) {
|
||||
// failed to add last message; keep the current position and get history from the database
|
||||
d->pending_last_message_date = last_message_date;
|
||||
d->pending_last_message_id = last_message_id;
|
||||
}
|
||||
} else {
|
||||
// can't add message immediately, because need to notify first about adding of dependent dialogs
|
||||
d->pending_last_message_date = last_database_message->date;
|
||||
d->pending_last_message_id = last_database_message->message_id;
|
||||
d->pending_last_message_date = last_message_date;
|
||||
d->pending_last_message_id = last_message_id;
|
||||
pending_add_dialog_last_database_message_[dialog_id] = {dependent_dialog_count, std::move(last_database_message)};
|
||||
}
|
||||
} else if (last_database_message_id.is_valid()) {
|
||||
auto date = DialogDate(order, dialog_id).get_date();
|
||||
if (date < MIN_PINNED_DIALOG_DATE) {
|
||||
d->pending_last_message_date = date;
|
||||
d->pending_last_message_id = last_database_message_id;
|
||||
d->pending_last_message_id = last_message_id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -36558,7 +36581,7 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
|
||||
if (need_get_history && !td_->auth_manager_->is_bot() && dialog_id != being_added_dialog_id_ &&
|
||||
dialog_id != being_added_by_new_message_dialog_id_ && have_input_peer(dialog_id, AccessRights::Read) &&
|
||||
(d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) {
|
||||
get_history_from_the_end_impl(d, true, false, Auto());
|
||||
get_history_from_the_end_impl(d, true, false, Auto(), "fix_new_dialog");
|
||||
}
|
||||
if (d->need_repair_server_unread_count && need_unread_counter(d->order)) {
|
||||
CHECK(dialog_type != DialogType::SecretChat);
|
||||
@ -36569,7 +36592,7 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
|
||||
}
|
||||
}
|
||||
|
||||
void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message) {
|
||||
bool MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message) {
|
||||
CHECK(d != nullptr);
|
||||
CHECK(last_database_message != nullptr);
|
||||
CHECK(last_database_message->left == nullptr);
|
||||
@ -36608,13 +36631,14 @@ void MessagesManager::add_dialog_last_database_message(Dialog *d, unique_ptr<Mes
|
||||
if (!td_->auth_manager_->is_bot() && dialog_id != being_added_dialog_id_ &&
|
||||
dialog_id != being_added_by_new_message_dialog_id_ && have_input_peer(dialog_id, AccessRights::Read) &&
|
||||
(d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) {
|
||||
get_history_from_the_end_impl(d, true, false, Auto());
|
||||
get_history_from_the_end_impl(d, true, false, Auto(), "add_dialog_last_database_message 5");
|
||||
}
|
||||
}
|
||||
|
||||
if (need_update_dialog_pos) {
|
||||
update_dialog_pos(d, "add_dialog_last_database_message 5");
|
||||
update_dialog_pos(d, "add_dialog_last_database_message 6");
|
||||
}
|
||||
return m != nullptr;
|
||||
}
|
||||
|
||||
void MessagesManager::update_dialogs_hints(const Dialog *d) {
|
||||
@ -38192,10 +38216,13 @@ void MessagesManager::on_get_channel_difference(
|
||||
}
|
||||
|
||||
// bots can receive channelDifferenceEmpty with pts bigger than known pts
|
||||
LOG_IF(ERROR, request_pts != difference->pts_ && !td_->auth_manager_->is_bot())
|
||||
<< "Receive channelDifferenceEmpty as result of getChannelDifference with pts = " << request_pts
|
||||
<< " and limit = " << request_limit << " in " << dialog_id << ", but pts has changed from " << request_pts
|
||||
<< " to " << difference->pts_;
|
||||
// also, this can happen for deleted channels
|
||||
if (request_pts != difference->pts_ && !td_->auth_manager_->is_bot() &&
|
||||
have_input_peer(dialog_id, AccessRights::Read)) {
|
||||
LOG(ERROR) << "Receive channelDifferenceEmpty as result of getChannelDifference with pts = " << request_pts
|
||||
<< " and limit = " << request_limit << " in " << dialog_id << ", but pts has changed to "
|
||||
<< difference->pts_;
|
||||
}
|
||||
set_channel_pts(d, difference->pts_, "channel difference empty");
|
||||
break;
|
||||
}
|
||||
@ -38429,7 +38456,7 @@ void MessagesManager::after_get_channel_difference(DialogId dialog_id, bool succ
|
||||
|
||||
if (d != nullptr && !td_->auth_manager_->is_bot() && have_access && !d->last_message_id.is_valid() && !d->is_empty &&
|
||||
(d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) {
|
||||
get_history_from_the_end_impl(d, true, false, Auto());
|
||||
get_history_from_the_end_impl(d, true, false, Auto(), "after_get_channel_difference");
|
||||
}
|
||||
}
|
||||
|
||||
@ -39501,7 +39528,7 @@ void MessagesManager::suffix_load_loop(Dialog *d) {
|
||||
get_history_impl(d, from_message_id, -1, 100, true, true, std::move(promise));
|
||||
} else {
|
||||
CHECK(from_message_id == MessageId());
|
||||
get_history_from_the_end_impl(d, true, true, std::move(promise));
|
||||
get_history_from_the_end_impl(d, true, true, std::move(promise), "suffix_load_loop");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2235,7 +2235,8 @@ class MessagesManager final : public Actor {
|
||||
|
||||
void get_history_from_the_end(DialogId dialog_id, bool from_database, bool only_local, Promise<Unit> &&promise);
|
||||
|
||||
void get_history_from_the_end_impl(const Dialog *d, bool from_database, bool only_local, Promise<Unit> &&promise);
|
||||
void get_history_from_the_end_impl(const Dialog *d, bool from_database, bool only_local, Promise<Unit> &&promise,
|
||||
const char *source);
|
||||
|
||||
void get_history(DialogId dialog_id, MessageId from_message_id, int32 offset, int32 limit, bool from_database,
|
||||
bool only_local, Promise<Unit> &&promise);
|
||||
@ -2694,7 +2695,7 @@ class MessagesManager final : public Actor {
|
||||
DialogId default_join_group_call_as_dialog_id, DialogId default_send_message_as_dialog_id,
|
||||
bool need_drop_default_send_message_as_dialog_id, bool is_loaded_from_database);
|
||||
|
||||
void add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message);
|
||||
bool add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message);
|
||||
|
||||
void fix_dialog_action_bar(const Dialog *d, DialogActionBar *action_bar);
|
||||
|
||||
|
@ -3205,7 +3205,7 @@ Status NotificationManager::process_push_notification_payload(string payload, bo
|
||||
return Status::Error("Receive wrong chat type");
|
||||
}
|
||||
|
||||
if (begins_with(loc_key, "CHAT_MESSAGE") || loc_key == "CHAT_ALBUM") {
|
||||
if (begins_with(loc_key, "CHAT_MESSAGE") || begins_with(loc_key, "CHAT_REACT") || loc_key == "CHAT_ALBUM") {
|
||||
loc_key = loc_key.substr(5);
|
||||
}
|
||||
if (loc_args.empty()) {
|
||||
@ -3236,6 +3236,11 @@ Status NotificationManager::process_push_notification_payload(string payload, bo
|
||||
return Status::Error(406, "Phone call notification is not supported");
|
||||
}
|
||||
|
||||
if (begins_with(loc_key, "REACT_")) {
|
||||
// TODO REACT_* notifications
|
||||
return Status::Error(406, "Reaction notifications are unsupported");
|
||||
}
|
||||
|
||||
loc_key = convert_loc_key(loc_key);
|
||||
if (loc_key.empty()) {
|
||||
return Status::Error("Push type is unknown");
|
||||
|
@ -1458,22 +1458,6 @@ void NotificationSettingsManager::get_notify_settings_exceptions(NotificationSet
|
||||
td_->create_handler<GetNotifySettingsExceptionsQuery>(std::move(promise))->send(scope, filter_scope, compare_sound);
|
||||
}
|
||||
|
||||
void NotificationSettingsManager::after_get_difference() {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!users_notification_settings_.is_synchronized) {
|
||||
send_get_scope_notification_settings_query(NotificationSettingsScope::Private, Promise<>());
|
||||
}
|
||||
if (!chats_notification_settings_.is_synchronized) {
|
||||
send_get_scope_notification_settings_query(NotificationSettingsScope::Group, Promise<>());
|
||||
}
|
||||
if (!channels_notification_settings_.is_synchronized) {
|
||||
send_get_scope_notification_settings_query(NotificationSettingsScope::Channel, Promise<>());
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationSettingsManager::on_binlog_events(vector<BinlogEvent> &&events) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
|
@ -95,8 +95,6 @@ class NotificationSettingsManager final : public Actor {
|
||||
|
||||
void init();
|
||||
|
||||
void after_get_difference();
|
||||
|
||||
void on_binlog_events(vector<BinlogEvent> &&events);
|
||||
|
||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||
|
@ -734,8 +734,7 @@ Result<InputInvoice> process_input_message_invoice(
|
||||
|
||||
PhotoSize s;
|
||||
s.type = 'n';
|
||||
s.dimensions =
|
||||
get_dimensions(input_invoice->photo_width_, input_invoice->photo_height_, "process_input_message_invoice");
|
||||
s.dimensions = get_dimensions(input_invoice->photo_width_, input_invoice->photo_height_, nullptr);
|
||||
s.size = input_invoice->photo_size_; // TODO use invoice_file_id size
|
||||
s.file_id = invoice_file_id;
|
||||
|
||||
|
@ -270,7 +270,7 @@ Photo get_encrypted_file_photo(FileManager *file_manager, unique_ptr<EncryptedFi
|
||||
|
||||
PhotoSize s;
|
||||
s.type = 'i';
|
||||
s.dimensions = get_dimensions(photo->w_, photo->h_, "get_encrypted_file_photo");
|
||||
s.dimensions = get_dimensions(photo->w_, photo->h_, nullptr);
|
||||
s.size = photo->size_;
|
||||
s.file_id = file_id;
|
||||
res.photos.push_back(s);
|
||||
|
@ -25,7 +25,9 @@ namespace td {
|
||||
|
||||
static uint16 get_dimension(int32 size, const char *source) {
|
||||
if (size < 0 || size > 65535) {
|
||||
if (source != nullptr) {
|
||||
LOG(ERROR) << "Wrong image dimension = " << size << " from " << source;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return narrow_cast<uint16>(size);
|
||||
@ -179,7 +181,7 @@ PhotoSize get_secret_thumbnail_photo_size(FileManager *file_manager, BufferSlice
|
||||
}
|
||||
PhotoSize res;
|
||||
res.type = 't';
|
||||
res.dimensions = get_dimensions(width, height, "get_secret_thumbnail_photo_size");
|
||||
res.dimensions = get_dimensions(width, height, nullptr);
|
||||
res.size = narrow_cast<int32>(bytes.size());
|
||||
|
||||
// generate some random remote location to save
|
||||
|
@ -1292,6 +1292,9 @@ void PollManager::on_unload_poll_timeout(PollId poll_id) {
|
||||
if (!can_unload_poll(poll_id)) {
|
||||
return;
|
||||
}
|
||||
if (!have_poll(poll_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Unload " << poll_id;
|
||||
|
||||
@ -1303,6 +1306,7 @@ void PollManager::on_unload_poll_timeout(PollId poll_id) {
|
||||
|
||||
poll_voters_.erase(poll_id);
|
||||
loaded_from_database_polls_.erase(poll_id);
|
||||
unload_poll_timeout_.cancel_timeout(poll_id.get());
|
||||
}
|
||||
|
||||
void PollManager::on_get_poll_results(PollId poll_id, uint64 generation,
|
||||
@ -1422,38 +1426,41 @@ vector<PollManager::PollOption> PollManager::get_poll_options(
|
||||
}
|
||||
|
||||
PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll> &&poll_server,
|
||||
tl_object_ptr<telegram_api::pollResults> &&poll_results) {
|
||||
tl_object_ptr<telegram_api::pollResults> &&poll_results, const char *source) {
|
||||
bool is_bot = td_->auth_manager_->is_bot();
|
||||
bool need_update_poll = poll_id.is_valid() && is_bot;
|
||||
if (!poll_id.is_valid() && poll_server != nullptr) {
|
||||
poll_id = PollId(poll_server->id_);
|
||||
}
|
||||
if (!poll_id.is_valid() || is_local_poll_id(poll_id)) {
|
||||
LOG(ERROR) << "Receive " << poll_id << " from server: " << oneline(to_string(poll_server)) << " "
|
||||
LOG(ERROR) << "Receive " << poll_id << " from " << source << ": " << oneline(to_string(poll_server)) << " "
|
||||
<< oneline(to_string(poll_results));
|
||||
return PollId();
|
||||
}
|
||||
if (poll_server != nullptr && poll_server->id_ != poll_id.get()) {
|
||||
LOG(ERROR) << "Receive poll " << poll_server->id_ << " instead of " << poll_id;
|
||||
LOG(ERROR) << "Receive poll " << poll_server->id_ << " instead of " << poll_id << " from " << source;
|
||||
return PollId();
|
||||
}
|
||||
constexpr size_t MAX_POLL_OPTIONS = 10; // server-side limit
|
||||
if (poll_server != nullptr &&
|
||||
(poll_server->answers_.size() <= 1 || poll_server->answers_.size() > 10 * MAX_POLL_OPTIONS)) {
|
||||
LOG(ERROR) << "Receive " << poll_id << " with wrong number of answers: " << to_string(poll_server);
|
||||
LOG(ERROR) << "Receive " << poll_id << " from " << source
|
||||
<< " with wrong number of answers: " << to_string(poll_server);
|
||||
return PollId();
|
||||
}
|
||||
if (poll_server != nullptr) {
|
||||
FlatHashSet<Slice, SliceHash> option_data;
|
||||
for (auto &answer : poll_server->answers_) {
|
||||
if (answer->option_.empty()) {
|
||||
LOG(ERROR) << "Receive " << poll_id << " with an empty option data: " << to_string(poll_server);
|
||||
LOG(ERROR) << "Receive " << poll_id << " from " << source
|
||||
<< " with an empty option data: " << to_string(poll_server);
|
||||
return PollId();
|
||||
}
|
||||
option_data.insert(answer->option_.as_slice());
|
||||
}
|
||||
if (option_data.size() != poll_server->answers_.size()) {
|
||||
LOG(ERROR) << "Receive " << poll_id << " with duplicate options: " << to_string(poll_server);
|
||||
LOG(ERROR) << "Receive " << poll_id << " from " << source
|
||||
<< " with duplicate options: " << to_string(poll_server);
|
||||
return PollId();
|
||||
}
|
||||
}
|
||||
@ -1571,7 +1578,7 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
bool allow_multiple_answers = (poll_server->flags_ & telegram_api::poll::MULTIPLE_CHOICE_MASK) != 0;
|
||||
bool is_quiz = (poll_server->flags_ & telegram_api::poll::QUIZ_MASK) != 0;
|
||||
if (is_quiz && allow_multiple_answers) {
|
||||
LOG(ERROR) << "Receive quiz " << poll_id << " allowing multiple answers";
|
||||
LOG(ERROR) << "Receive quiz " << poll_id << " from " << source << " allowing multiple answers";
|
||||
allow_multiple_answers = false;
|
||||
}
|
||||
if (allow_multiple_answers != poll->allow_multiple_answers) {
|
||||
@ -1590,7 +1597,7 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
if (has_total_voters && poll_results->total_voters_ != poll->total_voter_count) {
|
||||
poll->total_voter_count = poll_results->total_voters_;
|
||||
if (poll->total_voter_count < 0) {
|
||||
LOG(ERROR) << "Receive " << poll->total_voter_count << " voters in " << poll_id;
|
||||
LOG(ERROR) << "Receive " << poll->total_voter_count << " voters in " << poll_id << " from " << source;
|
||||
poll->total_voter_count = 0;
|
||||
}
|
||||
is_changed = true;
|
||||
@ -1614,7 +1621,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
bool is_correct = poll_result->correct_;
|
||||
if (is_correct) {
|
||||
if (correct_option_id != -1) {
|
||||
LOG(ERROR) << "Receive more than 1 correct answers " << correct_option_id << " and " << option_index;
|
||||
LOG(ERROR) << "Receive more than 1 correct answers " << correct_option_id << " and " << option_index
|
||||
<< " in " << poll_id << " from " << source;
|
||||
}
|
||||
correct_option_id = static_cast<int32>(option_index);
|
||||
}
|
||||
@ -1623,21 +1631,23 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
}
|
||||
|
||||
if (poll_result->voters_ < 0) {
|
||||
LOG(ERROR) << "Receive " << poll_result->voters_ << " voters for an option in " << poll_id;
|
||||
LOG(ERROR) << "Receive " << poll_result->voters_ << " voters for an option in " << poll_id << " from "
|
||||
<< source;
|
||||
poll_result->voters_ = 0;
|
||||
}
|
||||
if (option.is_chosen && poll_result->voters_ == 0) {
|
||||
LOG(ERROR) << "Receive 0 voters for the chosen option in " << poll_id;
|
||||
LOG(ERROR) << "Receive 0 voters for the chosen option in " << poll_id << " from " << source;
|
||||
poll_result->voters_ = 1;
|
||||
}
|
||||
if (poll_result->voters_ > poll->total_voter_count) {
|
||||
LOG(ERROR) << "Have only " << poll->total_voter_count << " poll voters, but there are " << poll_result->voters_
|
||||
<< " voters for an option in " << poll_id;
|
||||
<< " voters for an option in " << poll_id << " from " << source;
|
||||
poll->total_voter_count = poll_result->voters_;
|
||||
}
|
||||
auto max_voter_count = std::numeric_limits<int32>::max() / narrow_cast<int32>(poll->options.size()) - 2;
|
||||
if (poll_result->voters_ > max_voter_count) {
|
||||
LOG(ERROR) << "Have too many " << poll_result->voters_ << " poll voters for an option in " << poll_id;
|
||||
LOG(ERROR) << "Have too many " << poll_result->voters_ << " poll voters for an option in " << poll_id
|
||||
<< " from " << source;
|
||||
poll_result->voters_ = max_voter_count;
|
||||
}
|
||||
if (poll_result->voters_ != option.voter_count) {
|
||||
@ -1654,13 +1664,13 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
}
|
||||
if (poll->total_voter_count > max_total_voter_count && max_total_voter_count != 0) {
|
||||
LOG(ERROR) << "Have only " << max_total_voter_count << " total poll voters, but there are "
|
||||
<< poll->total_voter_count << " voters in " << poll_id;
|
||||
<< poll->total_voter_count << " voters in " << poll_id << " from " << source;
|
||||
poll->total_voter_count = max_total_voter_count;
|
||||
}
|
||||
}
|
||||
|
||||
auto entities =
|
||||
get_message_entities(td_->contacts_manager_.get(), std::move(poll_results->solution_entities_), "on_get_poll");
|
||||
get_message_entities(td_->contacts_manager_.get(), std::move(poll_results->solution_entities_), source);
|
||||
auto status = fix_formatted_text(poll_results->solution_, entities, true, true, true, true, false);
|
||||
if (status.is_error()) {
|
||||
if (!clean_input_string(poll_results->solution_)) {
|
||||
@ -1674,7 +1684,7 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
if (poll->correct_option_id != correct_option_id) {
|
||||
if (correct_option_id == -1 && poll->correct_option_id != -1) {
|
||||
LOG(ERROR) << "Can't change correct option of " << poll_id << " from " << poll->correct_option_id << " to "
|
||||
<< correct_option_id;
|
||||
<< correct_option_id << " from " << source;
|
||||
} else {
|
||||
poll->correct_option_id = correct_option_id;
|
||||
is_changed = true;
|
||||
@ -1682,7 +1692,7 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
}
|
||||
if (poll->explanation != explanation && (!is_min || poll_server_is_closed)) {
|
||||
if (explanation.text.empty() && !poll->explanation.text.empty()) {
|
||||
LOG(ERROR) << "Can't change known " << poll_id << " explanation to empty";
|
||||
LOG(ERROR) << "Can't change known " << poll_id << " explanation to empty from " << source ;
|
||||
} else {
|
||||
poll->explanation = std::move(explanation);
|
||||
is_changed = true;
|
||||
@ -1690,10 +1700,10 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
}
|
||||
} else {
|
||||
if (correct_option_id != -1) {
|
||||
LOG(ERROR) << "Receive correct option " << correct_option_id << " in non-quiz " << poll_id;
|
||||
LOG(ERROR) << "Receive correct option " << correct_option_id << " in non-quiz " << poll_id << " from " << source;
|
||||
}
|
||||
if (!explanation.text.empty()) {
|
||||
LOG(ERROR) << "Receive explanation " << explanation << " in non-quiz " << poll_id;
|
||||
LOG(ERROR) << "Receive explanation " << explanation << " in non-quiz " << poll_id << " from " << source;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1704,12 +1714,13 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
|
||||
if (user_id.is_valid()) {
|
||||
recent_voter_user_ids.push_back(user_id);
|
||||
} else {
|
||||
LOG(ERROR) << "Receive " << user_id << " as recent voter in " << poll_id;
|
||||
LOG(ERROR) << "Receive " << user_id << " as recent voter in " << poll_id << " from " << source;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (poll->is_anonymous && !recent_voter_user_ids.empty()) {
|
||||
LOG(ERROR) << "Receive anonymous " << poll_id << " with recent voters " << recent_voter_user_ids;
|
||||
LOG(ERROR) << "Receive anonymous " << poll_id << " with recent voters " << recent_voter_user_ids << " from "
|
||||
<< source;
|
||||
recent_voter_user_ids.clear();
|
||||
}
|
||||
if (recent_voter_user_ids != poll->recent_voter_user_ids) {
|
||||
|
@ -79,7 +79,7 @@ class PollManager final : public Actor {
|
||||
tl_object_ptr<telegram_api::InputMedia> get_input_media(PollId poll_id) const;
|
||||
|
||||
PollId on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll> &&poll_server,
|
||||
tl_object_ptr<telegram_api::pollResults> &&poll_results);
|
||||
tl_object_ptr<telegram_api::pollResults> &&poll_results, const char *source);
|
||||
|
||||
void on_get_poll_vote(PollId poll_id, UserId user_id, vector<BufferSlice> &&options);
|
||||
|
||||
|
@ -442,18 +442,17 @@ static Result<KeyboardButton> get_keyboard_button(tl_object_ptr<td_api::keyboard
|
||||
}
|
||||
case td_api::keyboardButtonTypeWebApp::ID: {
|
||||
if (!request_buttons_allowed) {
|
||||
return Status::Error(400, "Web app can be used in private chats only");
|
||||
return Status::Error(400, "Web App buttons can be used in private chats only");
|
||||
}
|
||||
|
||||
auto button_type = move_tl_object_as<td_api::keyboardButtonTypeWebApp>(button->type_);
|
||||
auto user_id = LinkManager::get_link_user_id(button_type->url_);
|
||||
if (user_id.is_valid()) {
|
||||
return Status::Error(400, "Link to a user can't be used in web app URL buttons");
|
||||
return Status::Error(400, "Link to a user can't be used in Web App URL buttons");
|
||||
}
|
||||
auto r_url = LinkManager::check_link(button_type->url_, true, !G()->is_test_dc());
|
||||
if (r_url.is_error()) {
|
||||
return Status::Error(400, PSLICE() << "Inline keyboard button web app URL '" << button_type->url_
|
||||
<< "' is invalid: " << r_url.error().message());
|
||||
return Status::Error(400, PSLICE() << "Keyboard button Web App " << r_url.error().message());
|
||||
}
|
||||
current_button.type = KeyboardButton::Type::WebView;
|
||||
current_button.url = std::move(button_type->url_);
|
||||
@ -491,8 +490,7 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
|
||||
}
|
||||
auto r_url = LinkManager::check_link(button_type->url_);
|
||||
if (r_url.is_error()) {
|
||||
return Status::Error(400, PSLICE() << "Inline keyboard button URL '" << button_type->url_
|
||||
<< "' is invalid: " << r_url.error().message());
|
||||
return Status::Error(400, PSLICE() << "Inline keyboard button " << r_url.error().message());
|
||||
}
|
||||
current_button.type = InlineKeyboardButton::Type::Url;
|
||||
current_button.data = r_url.move_as_ok();
|
||||
@ -541,8 +539,7 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
|
||||
}
|
||||
auto r_url = LinkManager::check_link(button_type->url_, true);
|
||||
if (r_url.is_error()) {
|
||||
return Status::Error(400, PSLICE() << "Inline keyboard button login URL '" << button_type->url_
|
||||
<< "' is invalid: " << r_url.error().message());
|
||||
return Status::Error(400, PSLICE() << "Inline keyboard button login " << r_url.error().message());
|
||||
}
|
||||
current_button.type = InlineKeyboardButton::Type::UrlAuth;
|
||||
current_button.data = r_url.move_as_ok();
|
||||
@ -573,17 +570,16 @@ static Result<InlineKeyboardButton> get_inline_keyboard_button(tl_object_ptr<td_
|
||||
auto button_type = move_tl_object_as<td_api::inlineKeyboardButtonTypeWebApp>(button->type_);
|
||||
auto user_id = LinkManager::get_link_user_id(button_type->url_);
|
||||
if (user_id.is_valid()) {
|
||||
return Status::Error(400, "Link to a user can't be used in web app URL buttons");
|
||||
return Status::Error(400, "Link to a user can't be used in Web App URL buttons");
|
||||
}
|
||||
auto r_url = LinkManager::check_link(button_type->url_, true, !G()->is_test_dc());
|
||||
if (r_url.is_error()) {
|
||||
return Status::Error(400, PSLICE() << "Inline keyboard button web app URL '" << button_type->url_
|
||||
<< "' is invalid: " << r_url.error().message());
|
||||
return Status::Error(400, PSLICE() << "Inline keyboard button Web App " << r_url.error().message());
|
||||
}
|
||||
current_button.type = InlineKeyboardButton::Type::WebView;
|
||||
current_button.data = r_url.move_as_ok();
|
||||
if (!clean_input_string(current_button.data)) {
|
||||
return Status::Error(400, "Inline keyboard button web app URL must be encoded in UTF-8");
|
||||
return Status::Error(400, "Inline keyboard button Web App URL must be encoded in UTF-8");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -950,6 +950,9 @@ Status SecretChatActor::do_inbound_message_decrypted_unchecked(unique_ptr<log_ev
|
||||
return status;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Receive message encrypted with MTProto " << mtproto_version << ": "
|
||||
<< to_string(message->decrypted_message_layer);
|
||||
|
||||
if (message->decrypted_message_layer->message_->get_id() == secret_api::decryptedMessageService8::ID) {
|
||||
auto old = move_tl_object_as<secret_api::decryptedMessageService8>(message->decrypted_message_layer->message_);
|
||||
message->decrypted_message_layer->message_ =
|
||||
@ -985,9 +988,6 @@ Status SecretChatActor::do_inbound_message_decrypted_unchecked(unique_ptr<log_ev
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Receive message encrypted with MTProto " << mtproto_version << ": "
|
||||
<< to_string(message->decrypted_message_layer);
|
||||
|
||||
if (status.is_error()) {
|
||||
CHECK(status.code() == 2); // gap found
|
||||
do_inbound_message_decrypted_pending(std::move(message));
|
||||
|
@ -713,7 +713,7 @@ static Result<int32> to_int32(Slice str) {
|
||||
int32 integer_value = 0;
|
||||
for (auto c : str) {
|
||||
if (!is_digit(c)) {
|
||||
return Status::Error(PSLICE() << "Can't parse \"" << str << "\" as number");
|
||||
return Status::Error(400, PSLICE() << "Can't parse \"" << utf8_encode(str.str()) << "\" as number");
|
||||
}
|
||||
integer_value = integer_value * 10 + c - '0';
|
||||
}
|
||||
@ -725,12 +725,12 @@ static Result<td_api::object_ptr<td_api::date>> get_date_object(Slice date) {
|
||||
return nullptr;
|
||||
}
|
||||
if (date.size() > 10u || date.size() < 8u) {
|
||||
return Status::Error(400, PSLICE() << "Date \"" << date << "\" has wrong length");
|
||||
return Status::Error(400, PSLICE() << "Date \"" << utf8_encode(date.str()) << "\" has wrong length");
|
||||
}
|
||||
auto parts = full_split(date, '.');
|
||||
if (parts.size() != 3 || parts[0].size() > 2 || parts[1].size() > 2 || parts[2].size() != 4 || parts[0].empty() ||
|
||||
parts[1].empty()) {
|
||||
return Status::Error(400, PSLICE() << "Date \"" << date << "\" has wrong parts");
|
||||
return Status::Error(400, PSLICE() << "Date \"" << utf8_encode(date.str()) << "\" has wrong parts");
|
||||
}
|
||||
TRY_RESULT(day, to_int32(parts[0]));
|
||||
TRY_RESULT(month, to_int32(parts[1]));
|
||||
@ -1196,7 +1196,7 @@ Result<SecureValueWithCredentials> decrypt_secure_value(FileManager *file_manage
|
||||
res_credentials.hash = encrypted_secure_value.hash;
|
||||
switch (encrypted_secure_value.type) {
|
||||
case SecureValueType::None:
|
||||
return Status::Error("Receive invalid Telegram Passport element");
|
||||
return Status::Error(400, "Receive invalid Telegram Passport element");
|
||||
case SecureValueType::EmailAddress:
|
||||
case SecureValueType::PhoneNumber:
|
||||
res.data = encrypted_secure_value.data.data;
|
||||
|
@ -5647,8 +5647,7 @@ Result<std::tuple<FileId, bool, bool, StickerFormat>> StickersManager::prepare_i
|
||||
|
||||
if (format == StickerFormat::Tgs) {
|
||||
int32 width = for_thumbnail ? 100 : 512;
|
||||
create_sticker(file_id, string(), PhotoSize(), get_dimensions(width, width, "prepare_input_file"), nullptr, format,
|
||||
nullptr);
|
||||
create_sticker(file_id, string(), PhotoSize(), get_dimensions(width, width, nullptr), nullptr, format, nullptr);
|
||||
} else if (format == StickerFormat::Webm) {
|
||||
td_->documents_manager_->create_document(file_id, string(), PhotoSize(), "sticker.webm", "video/webm", false);
|
||||
} else {
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "td/telegram/net/DcOptions.h"
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/NotificationSettings.h"
|
||||
#include "td/telegram/NotificationSettingsManager.h"
|
||||
#include "td/telegram/Payments.h"
|
||||
#include "td/telegram/PollId.h"
|
||||
@ -1601,7 +1602,6 @@ void UpdatesManager::after_get_difference() {
|
||||
td_->download_manager_->after_get_difference();
|
||||
td_->inline_queries_manager_->after_get_difference();
|
||||
td_->messages_manager_->after_get_difference();
|
||||
td_->notification_settings_manager_->after_get_difference();
|
||||
send_closure_later(td_->notification_manager_actor_, &NotificationManager::after_get_difference);
|
||||
send_closure(G()->state_manager(), &StateManager::on_synchronized, true);
|
||||
get_difference_start_time_ = 0.0;
|
||||
@ -1648,6 +1648,12 @@ void UpdatesManager::try_reload_data() {
|
||||
td_->contacts_manager_->reload_created_public_dialogs(PublicDialogType::HasUsername, Auto());
|
||||
td_->contacts_manager_->reload_created_public_dialogs(PublicDialogType::IsLocationBased, Auto());
|
||||
td_->notification_settings_manager_->reload_saved_ringtones(Auto());
|
||||
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Private,
|
||||
Auto());
|
||||
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Group,
|
||||
Auto());
|
||||
td_->notification_settings_manager_->send_get_scope_notification_settings_query(NotificationSettingsScope::Channel,
|
||||
Auto());
|
||||
td_->stickers_manager_->reload_reactions();
|
||||
td_->stickers_manager_->get_installed_sticker_sets(false, Auto());
|
||||
td_->stickers_manager_->get_installed_sticker_sets(true, Auto());
|
||||
@ -1773,6 +1779,7 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
|
||||
|
||||
size_t ordinary_new_message_count = 0;
|
||||
size_t scheduled_new_message_count = 0;
|
||||
size_t update_message_id_count = 0;
|
||||
for (auto &update : updates) {
|
||||
if (update != nullptr) {
|
||||
auto constructor_id = update->get_id();
|
||||
@ -1781,11 +1788,13 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
|
||||
ordinary_new_message_count++;
|
||||
} else if (constructor_id == telegram_api::updateNewScheduledMessage::ID) {
|
||||
scheduled_new_message_count++;
|
||||
} else if (constructor_id == telegram_api::updateMessageID::ID) {
|
||||
update_message_id_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ordinary_new_message_count != 0 && scheduled_new_message_count != 0) {
|
||||
if (update_message_id_count != 0 && ordinary_new_message_count != 0 && scheduled_new_message_count != 0) {
|
||||
LOG(ERROR) << "Receive mixed message types in updates:";
|
||||
for (auto &update : updates) {
|
||||
LOG(ERROR) << "Update: " << oneline(to_string(update));
|
||||
@ -3341,7 +3350,8 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGeoLiveViewed>
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateMessagePoll> update, Promise<Unit> &&promise) {
|
||||
td_->poll_manager_->on_get_poll(PollId(update->poll_id_), std::move(update->poll_), std::move(update->results_));
|
||||
td_->poll_manager_->on_get_poll(PollId(update->poll_id_), std::move(update->poll_), std::move(update->results_),
|
||||
"updateMessagePoll");
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,8 @@ class FileData {
|
||||
};
|
||||
|
||||
inline StringBuilder &operator<<(StringBuilder &sb, const FileData &file_data) {
|
||||
sb << "[" << tag("remote_name", file_data.remote_name_) << " " << file_data.owner_dialog_id_ << " "
|
||||
<< tag("size", file_data.size_) << tag("expected_size", file_data.expected_size_) << " "
|
||||
<< file_data.encryption_key_;
|
||||
sb << "[" << tag("remote_name", file_data.remote_name_) << " " << tag("size", file_data.size_)
|
||||
<< tag("expected_size", file_data.expected_size_) << " " << file_data.encryption_key_;
|
||||
if (!file_data.url_.empty()) {
|
||||
sb << tag("url", file_data.url_);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "td/utils/Time.h"
|
||||
#include "td/utils/tl_helpers.h"
|
||||
#include "td/utils/tl_parsers.h"
|
||||
#include "td/utils/utf8.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@ -990,27 +991,29 @@ Status FileManager::check_local_location(FullLocalFileLocation &location, int64
|
||||
} else if (!are_modification_times_equal(location.mtime_nsec_, stat.mtime_nsec_)) {
|
||||
VLOG(file_loader) << "File \"" << location.path_ << "\" was modified: old mtime = " << location.mtime_nsec_
|
||||
<< ", new mtime = " << stat.mtime_nsec_;
|
||||
return Status::Error(400, PSLICE() << "File \"" << location.path_ << "\" was modified");
|
||||
return Status::Error(400, PSLICE() << "File \"" << utf8_encode(location.path_) << "\" was modified");
|
||||
}
|
||||
if (skip_file_size_checks) {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
auto get_file_size_error = [&](Slice reason) {
|
||||
return Status::Error(400, PSLICE() << "File \"" << utf8_encode(location.path_) << "\" of size " << size
|
||||
<< " bytes is too big" << reason);
|
||||
};
|
||||
if ((location.file_type_ == FileType::Thumbnail || location.file_type_ == FileType::EncryptedThumbnail) &&
|
||||
size > MAX_THUMBNAIL_SIZE && !begins_with(PathView(location.path_).file_name(), "map")) {
|
||||
return Status::Error(400, PSLICE() << "File \"" << location.path_ << "\" is too big for a thumbnail "
|
||||
<< tag("size", format::as_size(size)));
|
||||
return get_file_size_error(" for a thumbnail");
|
||||
}
|
||||
if (size > MAX_FILE_SIZE) {
|
||||
return Status::Error(400, PSLICE() << "File \"" << location.path_ << "\" of size " << size << " bytes is too big");
|
||||
return get_file_size_error("");
|
||||
}
|
||||
if (location.file_type_ == FileType::Photo && size > MAX_PHOTO_SIZE) {
|
||||
return Status::Error(
|
||||
400, PSLICE() << "File \"" << location.path_ << "\" of size " << size << " bytes is too big for a photo");
|
||||
return get_file_size_error(" for a photo");
|
||||
}
|
||||
if (location.file_type_ == FileType::VideoNote &&
|
||||
size > G()->shared_config().get_option_integer("video_note_size_max", DEFAULT_VIDEO_NOTE_SIZE_MAX)) {
|
||||
return Status::Error(
|
||||
400, PSLICE() << "File \"" << location.path_ << "\" of size " << size << " bytes is too big for a video note");
|
||||
return get_file_size_error(" for a video note");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ TDJSON_EXPORT const char *td_execute(const char *request);
|
||||
* \param verbosity_level Log verbosity level with which the message was added (-1 - 1024).
|
||||
* If 0, then TDLib will crash as soon as the callback returns.
|
||||
* None of the TDLib methods can be called from the callback.
|
||||
* \param message Null-terminated string with the logged message.
|
||||
* \param message Null-terminated string with the logged message. The string isn't guaranteed to be encoded in UTF-8.
|
||||
*/
|
||||
typedef void (*td_log_message_callback_ptr)(int verbosity_level, const char *message);
|
||||
|
||||
|
@ -1113,7 +1113,10 @@ Status create_openssl_error(int code, Slice message) {
|
||||
|
||||
void clear_openssl_errors(Slice source) {
|
||||
if (ERR_peek_error() != 0) {
|
||||
LOG(ERROR) << source << ": " << create_openssl_error(0, "Unprocessed OPENSSL_ERROR");
|
||||
auto error = create_openssl_error(0, "Unprocessed OPENSSL_ERROR");
|
||||
if (!ends_with(error.message(), ":def_load:system lib}]")) {
|
||||
LOG(ERROR) << source << ": " << error;
|
||||
}
|
||||
}
|
||||
#if TD_PORT_WINDOWS
|
||||
WSASetLastError(0);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "td/utils/utf8.h"
|
||||
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/unicode.h"
|
||||
|
||||
namespace td {
|
||||
@ -121,4 +123,11 @@ string utf8_to_lower(Slice str) {
|
||||
return result;
|
||||
}
|
||||
|
||||
string utf8_encode(CSlice data) {
|
||||
if (check_utf8(data)) {
|
||||
return data.str();
|
||||
}
|
||||
return PSTRING() << "url_decode(" << url_encode(data) << ')';
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -118,4 +118,7 @@ T utf8_utf16_substr(T str, size_t offset, size_t length) {
|
||||
/// Returns UTF-8 string converted to lower case.
|
||||
string utf8_to_lower(Slice str);
|
||||
|
||||
/// Returns valid UTF-8 representation of the string.
|
||||
string utf8_encode(CSlice data);
|
||||
|
||||
} // namespace td
|
||||
|
Loading…
Reference in New Issue
Block a user