Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2022-06-01 23:25:22 +02:00
commit f73adb408a
28 changed files with 247 additions and 169 deletions

View File

@ -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());
}

View File

@ -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;

View File

@ -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) {

View File

@ -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:")) {

View File

@ -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_;

View File

@ -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;
}

View File

@ -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());

View File

@ -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;
}
last_received_message_id = message->message_id;
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");
}
}

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -25,7 +25,9 @@ namespace td {
static uint16 get_dimension(int32 size, const char *source) {
if (size < 0 || size > 65535) {
LOG(ERROR) << "Wrong image dimension = " << size << " from " << source;
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

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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));

View File

@ -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;

View File

@ -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 {

View File

@ -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());
}

View File

@ -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_);
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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