Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2021-11-29 14:05:43 +01:00
commit b8d144cfd2
17 changed files with 623 additions and 387 deletions

View File

@ -305,6 +305,7 @@ set(TDLIB_SOURCE
td/telegram/DeviceTokenManager.cpp
td/telegram/DhCache.cpp
td/telegram/DialogAction.cpp
td/telegram/DialogActionBar.cpp
td/telegram/DialogAdministrator.cpp
td/telegram/DialogDb.cpp
td/telegram/DialogEventLog.cpp
@ -490,6 +491,7 @@ set(TDLIB_SOURCE
td/telegram/DhCache.h
td/telegram/DhConfig.h
td/telegram/DialogAction.h
td/telegram/DialogActionBar.h
td/telegram/DialogAdministrator.h
td/telegram/DialogDate.h
td/telegram/DialogDb.h

View File

@ -50,17 +50,20 @@ AuthKeyHandshake::AuthKeyHandshake(int32 dc_id, int32 expires_in)
: mode_(expires_in == 0 ? Mode::Main : Mode::Temp)
, dc_id_(dc_id)
, expires_in_(expires_in)
, timeout_at_(Time::now() + 1e9) {
, start_time_(Time::now())
, timeout_in_(1e9) {
}
void AuthKeyHandshake::set_timeout_in(double timeout_in) {
timeout_at_ = Time::now() + timeout_in;
start_time_ = Time::now();
timeout_in_ = timeout_in;
}
void AuthKeyHandshake::clear() {
last_query_ = BufferSlice();
state_ = Start;
timeout_at_ = Time::now() + 1e9;
start_time_ = Time::now();
timeout_in_ = 1e9;
}
bool AuthKeyHandshake::is_ready_for_finish() const {
@ -81,6 +84,10 @@ string AuthKeyHandshake::store_object(const mtproto_api::Object &object) {
}
Status AuthKeyHandshake::on_res_pq(Slice message, Callback *connection, PublicRsaKeyInterface *public_rsa_key) {
if (Time::now() >= start_time_ + timeout_in_ * 0.6) {
return Status::Error("Handshake ResPQ timeout expired");
}
TRY_RESULT(res_pq, fetch_result<mtproto_api::req_pq_multi>(message, false));
if (res_pq->nonce_ != nonce_) {
return Status::Error("Nonce mismatch");
@ -155,6 +162,10 @@ Status AuthKeyHandshake::on_res_pq(Slice message, Callback *connection, PublicRs
}
Status AuthKeyHandshake::on_server_dh_params(Slice message, Callback *connection, DhCallback *dh_callback) {
if (Time::now() >= start_time_ + timeout_in_ * 0.8) {
return Status::Error("Handshake DH params timeout expired");
}
TRY_RESULT(dh_params, fetch_result<mtproto_api::req_DH_params>(message, false));
// server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params;
@ -318,10 +329,6 @@ Status AuthKeyHandshake::on_start(Callback *connection) {
Status AuthKeyHandshake::on_message(Slice message, Callback *connection, AuthKeyHandshakeContext *context) {
Status status = [&] {
if (Time::now() >= timeout_at_) {
return Status::Error("Handshake timeout expired");
}
switch (state_) {
case ResPQ:
return on_res_pq(message, connection, context->get_public_rsa_key_interface());

View File

@ -82,7 +82,8 @@ class AuthKeyHandshake {
int32 expires_in_ = 0;
double expires_at_ = 0;
double timeout_at_ = 0;
double start_time_ = 0;
double timeout_in_ = 0;
AuthKey auth_key_;
double server_time_diff_ = 0;

View File

@ -1600,6 +1600,7 @@ class GetChatInviteImportersQuery final : public Td::ResultHandler {
class GetChatJoinRequestsQuery final : public Td::ResultHandler {
Promise<td_api::object_ptr<td_api::chatJoinRequests>> promise_;
DialogId dialog_id_;
bool is_full_list_ = false;
public:
explicit GetChatJoinRequestsQuery(Promise<td_api::object_ptr<td_api::chatJoinRequests>> &&promise)
@ -1609,6 +1610,8 @@ class GetChatJoinRequestsQuery final : public Td::ResultHandler {
void send(DialogId dialog_id, const string &invite_link, const string &query, int32 offset_date,
UserId offset_user_id, int32 limit) {
dialog_id_ = dialog_id;
is_full_list_ = invite_link.empty() && query.empty() && offset_date == 0 && !offset_user_id.is_valid() && limit >= 3;
auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
if (input_peer == nullptr) {
return on_error(Status::Error(400, "Can't access the chat"));
@ -1663,8 +1666,10 @@ class GetChatJoinRequestsQuery final : public Td::ResultHandler {
join_requests.push_back(td_api::make_object<td_api::chatJoinRequest>(
td_->contacts_manager_->get_user_id_object(user_id, "chatJoinRequest"), request->date_, request->about_));
}
td_->messages_manager_->on_update_dialog_pending_join_requests(dialog_id_, total_count,
std::move(recent_requesters));
if (is_full_list_) {
td_->messages_manager_->on_update_dialog_pending_join_requests(dialog_id_, total_count,
std::move(recent_requesters));
}
promise_.set_value(td_api::make_object<td_api::chatJoinRequests>(total_count, std::move(join_requests)));
}
@ -7595,17 +7600,8 @@ void ContactsManager::remove_dialog_suggested_action(SuggestedAction action) {
}
}
void ContactsManager::dismiss_suggested_action(SuggestedAction action, Promise<Unit> &&promise) {
if (action.is_empty()) {
return promise.set_error(Status::Error(400, "Action must be non-empty"));
}
void ContactsManager::dismiss_dialog_suggested_action(SuggestedAction action, Promise<Unit> &&promise) {
auto dialog_id = action.dialog_id_;
if (dialog_id == DialogId()) {
send_closure_later(G()->config_manager(), &ConfigManager::dismiss_suggested_action, std::move(action),
std::move(promise));
return;
}
if (!td_->messages_manager_->have_dialog(dialog_id)) {
return promise.set_error(Status::Error(400, "Chat not found"));
}
@ -9547,6 +9543,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
CHECK(u != nullptr);
if (u->is_name_changed || u->is_username_changed || u->is_is_contact_changed) {
update_contacts_hints(u, user_id, from_database);
u->is_username_changed = false;
}
if (u->is_is_contact_changed) {
td_->messages_manager_->on_dialog_user_is_contact_updated(DialogId(user_id), u->is_contact);
@ -9557,6 +9554,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
update_user_full(user_full, user_id, "update_user");
}
}
u->is_is_contact_changed = false;
}
if (u->is_is_deleted_changed) {
td_->messages_manager_->on_dialog_user_is_deleted_updated(DialogId(user_id), u->is_deleted);
@ -9566,6 +9564,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
drop_user_full(user_id);
}
}
u->is_is_deleted_changed = false;
}
if (u->is_name_changed) {
auto messages_manager = td_->messages_manager_.get();
@ -9573,6 +9572,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) {
messages_manager->on_dialog_title_updated(DialogId(secret_chat_id));
});
u->is_name_changed = false;
}
if (u->is_photo_changed) {
auto messages_manager = td_->messages_manager_.get();
@ -9580,6 +9580,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) {
messages_manager->on_dialog_photo_updated(DialogId(secret_chat_id));
});
u->is_photo_changed = false;
}
if (u->is_status_changed && user_id != get_my_id()) {
auto left_time = get_user_was_online(u, user_id) - G()->server_time_cached();
@ -9592,9 +9593,6 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
user_online_timeout_.cancel_timeout(user_id.get());
}
}
if (u->is_default_permissions_changed) {
td_->messages_manager_->on_dialog_permissions_updated(DialogId(user_id));
}
if (!td_->auth_manager_->is_bot()) {
if (u->restriction_reasons.empty()) {
restricted_user_ids_.erase(user_id);
@ -9603,13 +9601,6 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
}
}
u->is_name_changed = false;
u->is_username_changed = false;
u->is_photo_changed = false;
u->is_is_contact_changed = false;
u->is_is_deleted_changed = false;
u->is_default_permissions_changed = false;
if (u->is_deleted) {
td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>());
}

View File

@ -420,7 +420,7 @@ class ContactsManager final : public Actor {
vector<DialogId> get_inactive_channels(Promise<Unit> &&promise);
void dismiss_suggested_action(SuggestedAction action, Promise<Unit> &&promise);
void dismiss_dialog_suggested_action(SuggestedAction action, Promise<Unit> &&promise);
bool is_user_contact(UserId user_id, bool is_mutual = false) const;
@ -642,7 +642,6 @@ class ContactsManager final : public Actor {
bool is_photo_changed = true;
bool is_is_contact_changed = true;
bool is_is_deleted_changed = true;
bool is_default_permissions_changed = true;
bool is_changed = true; // have new changes that need to be sent to the client and database
bool need_save_to_database = true; // have new changes that need only to be saved to the database
bool is_status_changed = true;

View File

@ -0,0 +1,249 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/DialogActionBar.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Td.h"
namespace td {
unique_ptr<DialogActionBar> DialogActionBar::create(bool can_report_spam, bool can_add_contact, bool can_block_user,
bool can_share_phone_number, bool can_report_location,
bool can_unarchive, int32 distance, bool can_invite_members) {
if (!can_report_spam && !can_add_contact && !can_block_user && !can_share_phone_number && !can_report_location &&
!can_invite_members) {
return nullptr;
}
auto action_bar = make_unique<DialogActionBar>();
action_bar->can_report_spam_ = can_report_spam;
action_bar->can_add_contact_ = can_add_contact;
action_bar->can_block_user_ = can_block_user;
action_bar->can_share_phone_number_ = can_share_phone_number;
action_bar->can_report_location_ = can_report_location;
action_bar->can_unarchive_ = can_unarchive;
action_bar->distance_ = distance >= 0 ? distance : -1;
action_bar->can_invite_members_ = can_invite_members;
return action_bar;
}
bool DialogActionBar::is_empty() const {
return !can_report_spam_ && !can_add_contact_ && !can_block_user_ && !can_share_phone_number_ &&
!can_report_location_ && !can_invite_members_;
}
void DialogActionBar::fix(Td *td, DialogId dialog_id, bool is_dialog_blocked, FolderId folder_id) {
auto dialog_type = dialog_id.get_type();
if (distance_ >= 0 && dialog_type != DialogType::User) {
LOG(ERROR) << "Receive distance_ " << distance_ << " to " << dialog_id;
distance_ = -1;
}
if (can_report_location_) {
if (dialog_type != DialogType::Channel) {
LOG(ERROR) << "Receive can_report_location_ in " << dialog_id;
can_report_location_ = false;
} else if (can_report_spam_ || can_add_contact_ || can_block_user_ || can_share_phone_number_ || can_unarchive_ ||
can_invite_members_) {
LOG(ERROR) << "Receive action bar " << can_report_spam_ << "/" << can_add_contact_ << "/" << can_block_user_
<< "/" << can_share_phone_number_ << "/" << can_report_location_ << "/" << can_unarchive_ << "/"
<< can_invite_members_;
can_report_spam_ = false;
can_add_contact_ = false;
can_block_user_ = false;
can_share_phone_number_ = false;
can_unarchive_ = false;
can_invite_members_ = false;
CHECK(distance_ == -1);
}
}
if (can_invite_members_) {
if (dialog_type != DialogType::Chat &&
(dialog_type != DialogType::Channel || td->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) ==
ContactsManager::ChannelType::Broadcast)) {
LOG(ERROR) << "Receive can_invite_members_ in " << dialog_id;
can_invite_members_ = false;
} else if (can_report_spam_ || can_add_contact_ || can_block_user_ || can_share_phone_number_ || can_unarchive_) {
LOG(ERROR) << "Receive action bar " << can_report_spam_ << "/" << can_add_contact_ << "/" << can_block_user_
<< "/" << can_share_phone_number_ << "/" << can_unarchive_ << "/" << can_invite_members_;
can_report_spam_ = false;
can_add_contact_ = false;
can_block_user_ = false;
can_share_phone_number_ = false;
can_unarchive_ = false;
CHECK(distance_ == -1);
}
}
if (dialog_type == DialogType::User) {
auto user_id = dialog_id.get_user_id();
bool is_me = user_id == td->contacts_manager_->get_my_id();
bool is_deleted = td->contacts_manager_->is_user_deleted(user_id);
bool is_contact = td->contacts_manager_->is_user_contact(user_id);
if (is_me || is_dialog_blocked) {
can_report_spam_ = false;
can_unarchive_ = false;
}
if (is_me || is_dialog_blocked || is_deleted) {
can_share_phone_number_ = false;
}
if (is_me || is_dialog_blocked || is_deleted || is_contact) {
can_block_user_ = false;
can_add_contact_ = false;
}
}
if (folder_id != FolderId::archive()) {
can_unarchive_ = false;
}
if (can_share_phone_number_) {
CHECK(!can_report_location_);
CHECK(!can_invite_members_);
if (dialog_type != DialogType::User) {
LOG(ERROR) << "Receive can_share_phone_number_ in " << dialog_id;
can_share_phone_number_ = false;
} else if (can_report_spam_ || can_add_contact_ || can_block_user_ || can_unarchive_ || distance_ >= 0) {
LOG(ERROR) << "Receive action bar " << can_report_spam_ << "/" << can_add_contact_ << "/" << can_block_user_
<< "/" << can_share_phone_number_ << "/" << can_unarchive_ << "/" << distance_;
can_report_spam_ = false;
can_add_contact_ = false;
can_block_user_ = false;
can_unarchive_ = false;
}
}
if (can_block_user_) {
CHECK(!can_report_location_);
CHECK(!can_invite_members_);
CHECK(!can_share_phone_number_);
if (dialog_type != DialogType::User) {
LOG(ERROR) << "Receive can_block_user_ in " << dialog_id;
can_block_user_ = false;
} else if (!can_report_spam_ || !can_add_contact_) {
LOG(ERROR) << "Receive action bar " << can_report_spam_ << "/" << can_add_contact_ << "/" << can_block_user_;
can_report_spam_ = true;
can_add_contact_ = true;
}
}
if (can_add_contact_) {
CHECK(!can_report_location_);
CHECK(!can_invite_members_);
CHECK(!can_share_phone_number_);
if (dialog_type != DialogType::User) {
LOG(ERROR) << "Receive can_add_contact_ in " << dialog_id;
can_add_contact_ = false;
} else if (can_report_spam_ != can_block_user_) {
LOG(ERROR) << "Receive action bar " << can_report_spam_ << "/" << can_add_contact_ << "/" << can_block_user_;
can_report_spam_ = false;
can_block_user_ = false;
can_unarchive_ = false;
}
}
if (!can_block_user_) {
distance_ = -1;
}
if (!can_report_spam_) {
can_unarchive_ = false;
}
}
td_api::object_ptr<td_api::ChatActionBar> DialogActionBar::get_chat_action_bar_object(DialogType dialog_type,
bool hide_unarchive) const {
if (can_report_location_) {
CHECK(dialog_type == DialogType::Channel);
CHECK(!can_share_phone_number_ && !can_block_user_ && !can_add_contact_ && !can_report_spam_ &&
!can_invite_members_);
return td_api::make_object<td_api::chatActionBarReportUnrelatedLocation>();
}
if (can_invite_members_) {
CHECK(!can_share_phone_number_ && !can_block_user_ && !can_add_contact_ && !can_report_spam_);
return td_api::make_object<td_api::chatActionBarInviteMembers>();
}
if (can_share_phone_number_) {
CHECK(dialog_type == DialogType::User);
CHECK(!can_block_user_ && !can_add_contact_ && !can_report_spam_);
return td_api::make_object<td_api::chatActionBarSharePhoneNumber>();
}
if (hide_unarchive) {
if (can_add_contact_) {
return td_api::make_object<td_api::chatActionBarAddContact>();
} else {
return nullptr;
}
}
if (can_block_user_) {
CHECK(dialog_type == DialogType::User);
CHECK(can_report_spam_ && can_add_contact_);
return td_api::make_object<td_api::chatActionBarReportAddBlock>(can_unarchive_, distance_);
}
if (can_add_contact_) {
CHECK(dialog_type == DialogType::User);
CHECK(!can_report_spam_);
return td_api::make_object<td_api::chatActionBarAddContact>();
}
if (can_report_spam_) {
return td_api::make_object<td_api::chatActionBarReportSpam>(can_unarchive_);
}
return nullptr;
}
bool DialogActionBar::on_dialog_unarchived() {
if (!can_unarchive_) {
return false;
}
can_unarchive_ = false;
can_report_spam_ = false;
can_block_user_ = false;
// keep can_add_contact_
return true;
}
bool DialogActionBar::on_user_contact_added() {
if (!can_block_user_ && !can_add_contact_) {
return false;
}
can_block_user_ = false;
can_add_contact_ = false;
// keep can_unarchive_
distance_ = -1;
return true;
}
bool DialogActionBar::on_user_deleted() {
if (!can_share_phone_number_ && !can_block_user_ && !can_add_contact_ && distance_ < 0) {
return false;
}
can_share_phone_number_ = false;
can_block_user_ = false;
can_add_contact_ = false;
distance_ = -1;
return true;
}
bool DialogActionBar::on_outgoing_message() {
if (distance_ < 0) {
return false;
}
distance_ = -1;
return true;
}
bool operator==(const unique_ptr<DialogActionBar> &lhs, const unique_ptr<DialogActionBar> &rhs) {
if (lhs == nullptr) {
return rhs == nullptr;
}
if (rhs == nullptr) {
return false;
}
return lhs->can_report_spam_ == rhs->can_report_spam_ && lhs->can_add_contact_ == rhs->can_add_contact_ &&
lhs->can_block_user_ == rhs->can_block_user_ && lhs->can_share_phone_number_ == rhs->can_share_phone_number_ &&
lhs->can_report_location_ == rhs->can_report_location_ && lhs->can_unarchive_ == rhs->can_unarchive_ &&
lhs->distance_ == rhs->distance_ && lhs->can_invite_members_ == rhs->can_invite_members_;
}
} // namespace td

View File

@ -0,0 +1,100 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/FolderId.h"
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/tl_helpers.h"
namespace td {
class Td;
class DialogActionBar {
int32 distance_ = -1; // distance to the peer
bool can_report_spam_ = false;
bool can_add_contact_ = false;
bool can_block_user_ = false;
bool can_share_phone_number_ = false;
bool can_report_location_ = false;
bool can_unarchive_ = false;
bool can_invite_members_ = false;
friend bool operator==(const unique_ptr<DialogActionBar> &lhs, const unique_ptr<DialogActionBar> &rhs);
public:
static unique_ptr<DialogActionBar> create(bool can_report_spam, bool can_add_contact, bool can_block_user,
bool can_share_phone_number, bool can_report_location, bool can_unarchive,
int32 distance, bool can_invite_members);
bool is_empty() const;
bool can_report_spam() const {
return can_report_spam_;
}
bool can_unarchive() const {
return can_unarchive_;
}
td_api::object_ptr<td_api::ChatActionBar> get_chat_action_bar_object(DialogType dialog_type,
bool hide_unarchive) const;
void fix(Td *td, DialogId dialog_id, bool is_dialog_blocked, FolderId folder_id);
bool on_dialog_unarchived();
bool on_user_contact_added();
bool on_user_deleted();
bool on_outgoing_message();
template <class StorerT>
void store(StorerT &storer) const {
bool has_distance = distance_ >= 0;
BEGIN_STORE_FLAGS();
STORE_FLAG(can_report_spam_);
STORE_FLAG(can_add_contact_);
STORE_FLAG(can_block_user_);
STORE_FLAG(can_share_phone_number_);
STORE_FLAG(can_report_location_);
STORE_FLAG(can_unarchive_);
STORE_FLAG(can_invite_members_);
STORE_FLAG(has_distance);
END_STORE_FLAGS();
if (has_distance) {
td::store(distance_, storer);
}
}
template <class ParserT>
void parse(ParserT &parser) {
bool has_distance;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(can_report_spam_);
PARSE_FLAG(can_add_contact_);
PARSE_FLAG(can_block_user_);
PARSE_FLAG(can_share_phone_number_);
PARSE_FLAG(can_report_location_);
PARSE_FLAG(can_unarchive_);
PARSE_FLAG(can_invite_members_);
PARSE_FLAG(has_distance);
END_PARSE_FLAGS();
if (has_distance) {
td::parse(distance_, parser);
}
}
};
bool operator==(const unique_ptr<DialogActionBar> &lhs, const unique_ptr<DialogActionBar> &rhs);
} // namespace td

View File

@ -35,6 +35,8 @@
#include "td/utils/StringBuilder.h"
#include "td/utils/Time.h"
#include <tuple>
namespace td {
static bool is_valid_start_parameter(Slice start_parameter) {
@ -1233,6 +1235,48 @@ string LinkManager::get_dialog_invite_link_hash(Slice invite_link) {
return get_url_query_hash(link_info.is_tg_, url_query);
}
UserId LinkManager::get_link_user_id(Slice url) {
string lower_cased_url = to_lower(url);
url = lower_cased_url;
Slice link_scheme("tg:");
if (!begins_with(url, link_scheme)) {
return UserId();
}
url.remove_prefix(link_scheme.size());
if (begins_with(url, "//")) {
url.remove_prefix(2);
}
Slice host("user");
if (!begins_with(url, host)) {
return UserId();
}
url.remove_prefix(host.size());
if (begins_with(url, "/")) {
url.remove_prefix(1);
}
if (!begins_with(url, "?")) {
return UserId();
}
url.remove_prefix(1);
url.truncate(url.find('#'));
for (auto parameter : full_split(url, '&')) {
Slice key;
Slice value;
std::tie(key, value) = split(parameter, '=');
if (key == Slice("id")) {
auto r_user_id = to_integer_safe<int64>(value);
if (r_user_id.is_error()) {
return UserId();
}
return UserId(r_user_id.ok());
}
}
return UserId();
}
Result<MessageLinkInfo> LinkManager::get_message_link_info(Slice url) {
if (url.empty()) {
return Status::Error("URL must be non-empty");

View File

@ -9,6 +9,7 @@
#include "td/telegram/FullMessageId.h"
#include "td/telegram/MessageLinkInfo.h"
#include "td/telegram/td_api.h"
#include "td/telegram/UserId.h"
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
@ -69,6 +70,8 @@ class LinkManager final : public Actor {
static string get_dialog_invite_link_hash(Slice invite_link);
static UserId get_link_user_id(Slice url);
static Result<MessageLinkInfo> get_message_link_info(Slice url);
private:

View File

@ -1773,48 +1773,6 @@ string get_first_url(Slice text, const vector<MessageEntity> &entities) {
return string();
}
static UserId get_link_user_id(Slice url) {
string lower_cased_url = to_lower(url);
url = lower_cased_url;
Slice link_scheme("tg:");
if (!begins_with(url, link_scheme)) {
return UserId();
}
url.remove_prefix(link_scheme.size());
if (begins_with(url, "//")) {
url.remove_prefix(2);
}
Slice host("user");
if (!begins_with(url, host)) {
return UserId();
}
url.remove_prefix(host.size());
if (begins_with(url, "/")) {
url.remove_prefix(1);
}
if (!begins_with(url, "?")) {
return UserId();
}
url.remove_prefix(1);
url.truncate(url.find('#'));
for (auto parameter : full_split(url, '&')) {
Slice key;
Slice value;
std::tie(key, value) = split(parameter, '=');
if (key == Slice("id")) {
auto r_user_id = to_integer_safe<int64>(value);
if (r_user_id.is_error()) {
return UserId();
}
return UserId(r_user_id.ok());
}
}
return UserId();
}
Result<vector<MessageEntity>> parse_markdown(string &text) {
string result;
vector<MessageEntity> entities;
@ -1900,7 +1858,7 @@ Result<vector<MessageEntity>> parse_markdown(string &text) {
url.push_back(text[i++]);
}
}
auto user_id = get_link_user_id(url);
auto user_id = LinkManager::get_link_user_id(url);
if (user_id.is_valid()) {
entities.emplace_back(entity_offset, entity_length, user_id);
} else {
@ -2106,7 +2064,7 @@ static Result<vector<MessageEntity>> do_parse_markdown_v2(CSlice text, string &r
return Status::Error(400, PSLICE() << "Can't find end of a URL at byte offset " << url_begin_pos);
}
}
user_id = get_link_user_id(url);
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()) {
@ -3056,7 +3014,7 @@ static Result<vector<MessageEntity>> do_parse_html(CSlice text, string &result)
if (url.empty()) {
url = result.substr(nested_entities.back().entity_begin_pos);
}
auto user_id = get_link_user_id(url);
auto user_id = LinkManager::get_link_user_id(url);
if (user_id.is_valid()) {
entities.emplace_back(entity_offset, entity_length, user_id);
} else {

View File

@ -11,6 +11,7 @@
#include "td/telegram/ConfigShared.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Dependencies.h"
#include "td/telegram/DialogActionBar.h"
#include "td/telegram/DialogDb.h"
#include "td/telegram/DialogFilter.h"
#include "td/telegram/DialogFilter.hpp"
@ -5170,7 +5171,6 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
max_notification_message_id.is_valid() && max_notification_message_id > last_new_message_id;
bool has_folder_id = folder_id != FolderId();
bool has_pending_read_channel_inbox = pending_read_channel_inbox_pts != 0;
bool has_distance = distance >= 0;
bool has_last_yet_unsent_message = last_message_id.is_valid() && last_message_id.is_yet_unsent();
bool has_active_group_call_id = active_group_call_id.is_valid();
bool has_message_ttl_setting = !message_ttl_setting.is_empty();
@ -5179,13 +5179,14 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
bool has_theme_name = !theme_name.empty();
bool has_flags3 = true;
bool has_pending_join_requests = pending_join_request_count != 0;
bool has_action_bar = action_bar != nullptr;
BEGIN_STORE_FLAGS();
STORE_FLAG(has_draft_message);
STORE_FLAG(has_last_database_message);
STORE_FLAG(know_can_report_spam);
STORE_FLAG(can_report_spam);
STORE_FLAG(false); // legacy_know_can_report_spam
STORE_FLAG(false); // action_bar->can_report_spam
STORE_FLAG(has_first_database_message_id);
STORE_FLAG(false);
STORE_FLAG(false); // legacy_is_pinned
STORE_FLAG(has_first_database_message_id_by_index);
STORE_FLAG(has_message_count_by_index);
STORE_FLAG(has_client_data);
@ -5221,23 +5222,23 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
STORE_FLAG(is_folder_id_inited);
STORE_FLAG(has_pending_read_channel_inbox);
STORE_FLAG(know_action_bar);
STORE_FLAG(can_add_contact);
STORE_FLAG(can_block_user);
STORE_FLAG(can_share_phone_number);
STORE_FLAG(can_report_location);
STORE_FLAG(false); // action_bar->can_add_contact
STORE_FLAG(false); // action_bar->can_block_user
STORE_FLAG(false); // action_bar->can_share_phone_number
STORE_FLAG(false); // action_bar->can_report_location
STORE_FLAG(has_scheduled_server_messages);
STORE_FLAG(has_scheduled_database_messages);
STORE_FLAG(need_repair_channel_server_unread_count);
STORE_FLAG(can_unarchive);
STORE_FLAG(has_distance);
STORE_FLAG(hide_distance);
STORE_FLAG(false); // action_bar->can_unarchive
STORE_FLAG(false); // action_bar_has_distance
STORE_FLAG(has_outgoing_messages);
STORE_FLAG(has_last_yet_unsent_message);
STORE_FLAG(is_blocked);
STORE_FLAG(is_is_blocked_inited);
STORE_FLAG(has_active_group_call);
STORE_FLAG(is_group_call_empty);
STORE_FLAG(has_active_group_call_id);
STORE_FLAG(can_invite_members);
STORE_FLAG(false); // action_bar->can_invite_members
STORE_FLAG(has_message_ttl_setting);
STORE_FLAG(is_message_ttl_setting_inited);
STORE_FLAG(has_default_join_group_call_as_dialog_id);
@ -5251,6 +5252,8 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
if (has_flags3) {
BEGIN_STORE_FLAGS();
STORE_FLAG(has_pending_join_requests);
STORE_FLAG(need_repair_action_bar);
STORE_FLAG(has_action_bar);
END_STORE_FLAGS();
}
@ -5332,9 +5335,6 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
store(pending_read_channel_inbox_max_message_id, storer);
store(pending_read_channel_inbox_server_unread_count, storer);
}
if (has_distance) {
store(distance, storer);
}
if (has_active_group_call_id) {
store(active_group_call_id, storer);
}
@ -5351,6 +5351,9 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
store(pending_join_request_count, storer);
store(pending_join_request_user_ids, storer);
}
if (has_action_bar) {
store(action_bar, storer);
}
}
// do not forget to resolve dialog dependencies including dependencies of last_message
@ -5359,6 +5362,7 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
using td::parse;
bool has_draft_message;
bool has_last_database_message;
bool legacy_know_can_report_spam;
bool has_first_database_message_id;
bool legacy_is_pinned;
bool has_first_database_message_id_by_index;
@ -5379,18 +5383,26 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
bool has_max_notification_message_id = false;
bool has_folder_id = false;
bool has_pending_read_channel_inbox = false;
bool has_distance = false;
bool has_active_group_call_id = false;
bool has_message_ttl_setting = false;
bool has_default_join_group_call_as_dialog_id = false;
bool has_theme_name = false;
bool has_flags3 = false;
bool has_pending_join_requests = false;
bool action_bar_can_report_spam = false;
bool action_bar_can_add_contact = false;
bool action_bar_can_block_user = false;
bool action_bar_can_share_phone_number = false;
bool action_bar_can_report_location = false;
bool action_bar_can_unarchive = false;
bool action_bar_has_distance = false;
bool action_bar_can_invite_members = false;
bool has_action_bar = false;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_draft_message);
PARSE_FLAG(has_last_database_message);
PARSE_FLAG(know_can_report_spam);
PARSE_FLAG(can_report_spam);
PARSE_FLAG(legacy_know_can_report_spam);
PARSE_FLAG(action_bar_can_report_spam);
PARSE_FLAG(has_first_database_message_id);
PARSE_FLAG(legacy_is_pinned);
PARSE_FLAG(has_first_database_message_id_by_index);
@ -5428,23 +5440,23 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
PARSE_FLAG(is_folder_id_inited);
PARSE_FLAG(has_pending_read_channel_inbox);
PARSE_FLAG(know_action_bar);
PARSE_FLAG(can_add_contact);
PARSE_FLAG(can_block_user);
PARSE_FLAG(can_share_phone_number);
PARSE_FLAG(can_report_location);
PARSE_FLAG(action_bar_can_add_contact);
PARSE_FLAG(action_bar_can_block_user);
PARSE_FLAG(action_bar_can_share_phone_number);
PARSE_FLAG(action_bar_can_report_location);
PARSE_FLAG(has_scheduled_server_messages);
PARSE_FLAG(has_scheduled_database_messages);
PARSE_FLAG(need_repair_channel_server_unread_count);
PARSE_FLAG(can_unarchive);
PARSE_FLAG(has_distance);
PARSE_FLAG(hide_distance);
PARSE_FLAG(action_bar_can_unarchive);
PARSE_FLAG(action_bar_has_distance);
PARSE_FLAG(has_outgoing_messages);
PARSE_FLAG(had_last_yet_unsent_message);
PARSE_FLAG(is_blocked);
PARSE_FLAG(is_is_blocked_inited);
PARSE_FLAG(has_active_group_call);
PARSE_FLAG(is_group_call_empty);
PARSE_FLAG(has_active_group_call_id);
PARSE_FLAG(can_invite_members);
PARSE_FLAG(action_bar_can_invite_members);
PARSE_FLAG(has_message_ttl_setting);
PARSE_FLAG(is_message_ttl_setting_inited);
PARSE_FLAG(has_default_join_group_call_as_dialog_id);
@ -5456,22 +5468,15 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
END_PARSE_FLAGS();
} else {
is_folder_id_inited = false;
know_action_bar = false;
can_add_contact = false;
can_block_user = false;
can_share_phone_number = false;
can_report_location = false;
has_scheduled_server_messages = false;
has_scheduled_database_messages = false;
need_repair_channel_server_unread_count = false;
can_unarchive = false;
hide_distance = false;
has_outgoing_messages = false;
had_last_yet_unsent_message = false;
is_blocked = false;
is_is_blocked_inited = false;
has_active_group_call = false;
is_group_call_empty = false;
can_invite_members = false;
is_message_ttl_setting_inited = false;
has_bots = false;
is_has_bots_inited = false;
@ -5480,7 +5485,11 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
if (has_flags3) {
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_pending_join_requests);
PARSE_FLAG(need_repair_action_bar);
PARSE_FLAG(has_action_bar);
END_PARSE_FLAGS();
} else {
need_repair_action_bar = false;
}
parse(last_new_message_id, parser);
@ -5594,8 +5603,9 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
parse(pending_read_channel_inbox_max_message_id, parser);
parse(pending_read_channel_inbox_server_unread_count, parser);
}
if (has_distance) {
parse(distance, parser);
int32 action_bar_distance = -1;
if (action_bar_has_distance) {
parse(action_bar_distance, parser);
}
if (has_active_group_call_id) {
parse(active_group_call_id, parser);
@ -5613,6 +5623,17 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
parse(pending_join_request_count, parser);
parse(pending_join_request_user_ids, parser);
}
if (has_action_bar) {
parse(action_bar, parser);
}
(void)legacy_know_can_report_spam;
if (know_action_bar && !has_action_bar) {
action_bar = DialogActionBar::create(
action_bar_can_report_spam, action_bar_can_add_contact, action_bar_can_block_user,
action_bar_can_share_phone_number, action_bar_can_report_location, action_bar_can_unarchive,
has_outgoing_messages ? -1 : action_bar_distance, action_bar_can_invite_members);
}
}
template <class StorerT>
@ -7972,11 +7993,21 @@ bool MessagesManager::update_dialog_silent_send_message(Dialog *d, bool silent_s
return true;
}
void MessagesManager::reget_dialog_action_bar(DialogId dialog_id, const char *source) {
void MessagesManager::reget_dialog_action_bar(DialogId dialog_id, const char *source, bool is_repair) {
if (G()->close_flag() || !dialog_id.is_valid() || td_->auth_manager_->is_bot()) {
return;
}
Dialog *d = get_dialog_force(dialog_id, source);
if (d == nullptr) {
return;
}
if (is_repair && !d->need_repair_action_bar) {
d->need_repair_action_bar = true;
on_dialog_updated(dialog_id, source);
}
LOG(INFO) << "Reget action bar in " << dialog_id << " from " << source;
switch (dialog_id.get_type()) {
case DialogType::User:
@ -7999,12 +8030,12 @@ void MessagesManager::reget_dialog_action_bar(DialogId dialog_id, const char *so
void MessagesManager::repair_dialog_action_bar(Dialog *d, const char *source) {
CHECK(d != nullptr);
auto dialog_id = d->dialog_id;
d->know_action_bar = false;
d->need_repair_action_bar = true;
if (have_input_peer(dialog_id, AccessRights::Read)) {
create_actor<SleepActor>(
"RepairChatActionBarActor", 1.0,
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, source](Result<Unit> result) {
send_closure(actor_id, &MessagesManager::reget_dialog_action_bar, dialog_id, source);
send_closure(actor_id, &MessagesManager::reget_dialog_action_bar, dialog_id, source, true);
}))
.release();
}
@ -8022,22 +8053,18 @@ void MessagesManager::hide_dialog_action_bar(DialogId dialog_id) {
void MessagesManager::hide_dialog_action_bar(Dialog *d) {
CHECK(d->dialog_id.get_type() != DialogType::SecretChat);
if (!d->know_can_report_spam) {
if (!d->know_action_bar) {
return;
}
if (!d->can_report_spam && !d->can_add_contact && !d->can_block_user && !d->can_share_phone_number &&
!d->can_report_location && !d->can_unarchive && d->distance < 0 && !d->can_invite_members) {
if (d->need_repair_action_bar) {
d->need_repair_action_bar = false;
on_dialog_updated(d->dialog_id, "hide_dialog_action_bar");
}
if (d->action_bar == nullptr) {
return;
}
d->can_report_spam = false;
d->can_add_contact = false;
d->can_block_user = false;
d->can_share_phone_number = false;
d->can_report_location = false;
d->can_unarchive = false;
d->distance = -1;
d->can_invite_members = false;
d->action_bar = nullptr;
send_update_chat_action_bar(d);
}
@ -8062,16 +8089,19 @@ void MessagesManager::remove_dialog_action_bar(DialogId dialog_id, Promise<Unit>
}
}
if (!d->know_can_report_spam) {
if (!d->know_action_bar) {
return promise.set_error(Status::Error(400, "Can't update chat action bar"));
}
if (!d->can_report_spam && !d->can_add_contact && !d->can_block_user && !d->can_share_phone_number &&
!d->can_report_location && !d->can_unarchive && d->distance < 0 && !d->can_invite_members) {
if (d->need_repair_action_bar) {
d->need_repair_action_bar = false;
on_dialog_updated(dialog_id, "remove_dialog_action_bar");
}
if (d->action_bar == nullptr) {
return promise.set_value(Unit());
}
hide_dialog_action_bar(d);
d->action_bar = nullptr;
send_update_chat_action_bar(d);
toggle_dialog_report_spam_state_on_server(dialog_id, false, 0, std::move(promise));
}
@ -8196,7 +8226,7 @@ void MessagesManager::report_dialog(DialogId dialog_id, const vector<MessageId>
Dialog *user_d = d;
bool is_dialog_spam_report = false;
bool can_report_spam = d->can_report_spam;
bool can_report_spam = false;
if (reason.is_spam() && message_ids.empty()) {
// report from action bar
if (dialog_id.get_type() == DialogType::SecretChat) {
@ -8205,12 +8235,9 @@ void MessagesManager::report_dialog(DialogId dialog_id, const vector<MessageId>
if (user_d == nullptr) {
return promise.set_error(Status::Error(400, "Chat with the user not found"));
}
is_dialog_spam_report = user_d->know_can_report_spam;
can_report_spam = user_d->can_report_spam;
} else {
is_dialog_spam_report = d->know_can_report_spam;
}
is_dialog_spam_report = user_d->know_action_bar;
can_report_spam = user_d->action_bar != nullptr && user_d->action_bar->can_report_spam();
}
if (is_dialog_spam_report && can_report_spam) {
@ -8275,6 +8302,10 @@ void MessagesManager::on_get_peer_settings(DialogId dialog_id,
tl_object_ptr<telegram_api::peerSettings> &&peer_settings,
bool ignore_privacy_exception) {
CHECK(peer_settings != nullptr);
if (td_->auth_manager_->is_bot()) {
return;
}
if (dialog_id.get_type() == DialogType::User && !ignore_privacy_exception) {
td_->contacts_manager_->on_update_user_need_phone_number_privacy_exception(dialog_id.get_user_id(),
peer_settings->need_contacts_exception_);
@ -8285,160 +8316,41 @@ void MessagesManager::on_get_peer_settings(DialogId dialog_id,
return;
}
auto can_report_spam = peer_settings->report_spam_;
auto can_add_contact = peer_settings->add_contact_;
auto can_block_user = peer_settings->block_contact_;
auto can_share_phone_number = peer_settings->share_contact_;
auto can_report_location = peer_settings->report_geo_;
auto can_unarchive = peer_settings->autoarchived_;
auto distance =
(peer_settings->flags_ & telegram_api::peerSettings::GEO_DISTANCE_MASK) != 0 ? peer_settings->geo_distance_ : -1;
auto can_invite_members = peer_settings->invite_members_;
if (d->can_report_spam == can_report_spam && d->can_add_contact == can_add_contact &&
d->can_block_user == can_block_user && d->can_share_phone_number == can_share_phone_number &&
d->can_report_location == can_report_location && d->can_unarchive == can_unarchive && d->distance == distance &&
d->can_invite_members == can_invite_members) {
if (!d->know_action_bar || !d->know_can_report_spam) {
d->know_can_report_spam = true;
if (distance < -1 || d->has_outgoing_messages) {
distance = -1;
}
auto action_bar =
DialogActionBar::create(peer_settings->report_spam_, peer_settings->add_contact_, peer_settings->block_contact_,
peer_settings->share_contact_, peer_settings->report_geo_, peer_settings->autoarchived_,
distance, peer_settings->invite_members_);
fix_dialog_action_bar(d, action_bar.get());
if (d->action_bar == action_bar) {
if (!d->know_action_bar || d->need_repair_action_bar) {
d->know_action_bar = true;
d->need_repair_action_bar = false;
on_dialog_updated(d->dialog_id, "on_get_peer_settings");
}
return;
}
d->know_can_report_spam = true;
d->know_action_bar = true;
d->can_report_spam = can_report_spam;
d->can_add_contact = can_add_contact;
d->can_block_user = can_block_user;
d->can_share_phone_number = can_share_phone_number;
d->can_report_location = can_report_location;
d->can_unarchive = can_unarchive;
d->distance = distance < 0 ? -1 : distance;
d->can_invite_members = can_invite_members;
fix_dialog_action_bar(d);
d->need_repair_action_bar = false;
d->action_bar = std::move(action_bar);
send_update_chat_action_bar(d);
}
void MessagesManager::fix_dialog_action_bar(Dialog *d) {
CHECK(d != nullptr);
if (!d->know_action_bar) {
void MessagesManager::fix_dialog_action_bar(const Dialog *d, DialogActionBar *action_bar) {
if (action_bar == nullptr) {
return;
}
auto dialog_type = d->dialog_id.get_type();
if (d->distance >= 0 && dialog_type != DialogType::User) {
LOG(ERROR) << "Receive distance " << d->distance << " to " << d->dialog_id;
d->distance = -1;
}
if (d->can_report_location) {
if (dialog_type != DialogType::Channel) {
LOG(ERROR) << "Receive can_report_location in " << d->dialog_id;
d->can_report_location = false;
} else if (d->can_report_spam || d->can_add_contact || d->can_block_user || d->can_share_phone_number ||
d->can_unarchive || d->can_invite_members) {
LOG(ERROR) << "Receive action bar " << d->can_report_spam << "/" << d->can_add_contact << "/" << d->can_block_user
<< "/" << d->can_share_phone_number << "/" << d->can_report_location << "/" << d->can_unarchive << "/"
<< d->can_invite_members;
d->can_report_spam = false;
d->can_add_contact = false;
d->can_block_user = false;
d->can_share_phone_number = false;
d->can_unarchive = false;
d->can_invite_members = false;
CHECK(d->distance == -1);
}
}
if (d->can_invite_members) {
if (dialog_type != DialogType::Chat && (dialog_type != DialogType::Channel || is_broadcast_channel(d->dialog_id))) {
LOG(ERROR) << "Receive can_invite_members in " << d->dialog_id;
d->can_invite_members = false;
} else if (d->can_report_spam || d->can_add_contact || d->can_block_user || d->can_share_phone_number ||
d->can_unarchive) {
LOG(ERROR) << "Receive action bar " << d->can_report_spam << "/" << d->can_add_contact << "/" << d->can_block_user
<< "/" << d->can_share_phone_number << "/" << d->can_unarchive << "/" << d->can_invite_members;
d->can_report_spam = false;
d->can_add_contact = false;
d->can_block_user = false;
d->can_share_phone_number = false;
d->can_unarchive = false;
CHECK(d->distance == -1);
}
}
if (dialog_type == DialogType::User) {
auto user_id = d->dialog_id.get_user_id();
bool is_me = user_id == td_->contacts_manager_->get_my_id();
bool is_blocked = d->is_blocked;
bool is_deleted = td_->contacts_manager_->is_user_deleted(user_id);
bool is_contact = td_->contacts_manager_->is_user_contact(user_id);
if (is_me || is_blocked) {
d->can_report_spam = false;
d->can_unarchive = false;
}
if (is_me || is_blocked || is_deleted) {
d->can_share_phone_number = false;
}
if (is_me || is_blocked || is_deleted || is_contact) {
d->can_block_user = false;
d->can_add_contact = false;
}
}
if (d->folder_id != FolderId::archive()) {
d->can_unarchive = false;
}
if (d->can_share_phone_number) {
CHECK(!d->can_report_location);
CHECK(!d->can_invite_members);
if (dialog_type != DialogType::User) {
LOG(ERROR) << "Receive can_share_phone_number in " << d->dialog_id;
d->can_share_phone_number = false;
} else if (d->can_report_spam || d->can_add_contact || d->can_block_user || d->can_unarchive || d->distance >= 0) {
LOG(ERROR) << "Receive action bar " << d->can_report_spam << "/" << d->can_add_contact << "/" << d->can_block_user
<< "/" << d->can_share_phone_number << "/" << d->can_unarchive << "/" << d->distance;
d->can_report_spam = false;
d->can_add_contact = false;
d->can_block_user = false;
d->can_unarchive = false;
}
}
if (d->can_block_user) {
CHECK(!d->can_report_location);
CHECK(!d->can_invite_members);
CHECK(!d->can_share_phone_number);
if (dialog_type != DialogType::User) {
LOG(ERROR) << "Receive can_block_user in " << d->dialog_id;
d->can_block_user = false;
} else if (!d->can_report_spam || !d->can_add_contact) {
LOG(ERROR) << "Receive action bar " << d->can_report_spam << "/" << d->can_add_contact << "/"
<< d->can_block_user;
d->can_report_spam = true;
d->can_add_contact = true;
}
}
if (d->can_add_contact) {
CHECK(!d->can_report_location);
CHECK(!d->can_invite_members);
CHECK(!d->can_share_phone_number);
if (dialog_type != DialogType::User) {
LOG(ERROR) << "Receive can_add_contact in " << d->dialog_id;
d->can_add_contact = false;
} else if (d->can_report_spam != d->can_block_user) {
LOG(ERROR) << "Receive action bar " << d->can_report_spam << "/" << d->can_add_contact << "/"
<< d->can_block_user;
d->can_report_spam = false;
d->can_block_user = false;
d->can_unarchive = false;
}
}
if (!d->can_block_user) {
d->distance = -1;
}
if (!d->can_report_spam) {
d->can_unarchive = false;
}
CHECK(d != nullptr);
action_bar->fix(td_, d->dialog_id, d->is_blocked, d->folder_id);
}
Result<string> MessagesManager::get_login_button_url(FullMessageId full_message_id, int64 button_id) {
@ -20030,7 +19942,7 @@ void MessagesManager::open_dialog(Dialog *d) {
break;
case DialogType::Chat:
td_->contacts_manager_->repair_chat_participants(dialog_id.get_chat_id());
reget_dialog_action_bar(dialog_id, "open_dialog");
reget_dialog_action_bar(dialog_id, "open_dialog", false);
break;
case DialogType::Channel:
if (!is_broadcast_channel(dialog_id)) {
@ -20042,7 +19954,7 @@ void MessagesManager::open_dialog(Dialog *d) {
}
}
get_channel_difference(dialog_id, d->pts, true, "open_dialog");
reget_dialog_action_bar(dialog_id, "open_dialog");
reget_dialog_action_bar(dialog_id, "open_dialog", false);
break;
case DialogType::SecretChat: {
// to repair dialog action bar
@ -20181,65 +20093,25 @@ td_api::object_ptr<td_api::ChatType> MessagesManager::get_chat_type_object(Dialo
}
}
td_api::object_ptr<td_api::ChatActionBar> MessagesManager::get_chat_action_bar_object(const Dialog *d,
bool hide_unarchive) const {
td_api::object_ptr<td_api::ChatActionBar> MessagesManager::get_chat_action_bar_object(const Dialog *d) const {
CHECK(d != nullptr);
if (d->dialog_id.get_type() == DialogType::SecretChat) {
auto dialog_type = d->dialog_id.get_type();
if (dialog_type == DialogType::SecretChat) {
auto user_id = td_->contacts_manager_->get_secret_chat_user_id(d->dialog_id.get_secret_chat_id());
if (!user_id.is_valid()) {
return nullptr;
}
const Dialog *user_d = get_dialog(DialogId(user_id));
if (user_d == nullptr) {
if (user_d == nullptr || user_d->action_bar == nullptr) {
return nullptr;
}
return get_chat_action_bar_object(user_d, d->folder_id != FolderId::archive());
return user_d->action_bar->get_chat_action_bar_object(DialogType::User, d->folder_id != FolderId::archive());
}
if (!d->know_action_bar) {
if (d->know_can_report_spam && d->dialog_id.get_type() != DialogType::SecretChat && d->can_report_spam) {
return td_api::make_object<td_api::chatActionBarReportSpam>(false);
}
if (d->action_bar == nullptr) {
return nullptr;
}
if (d->can_report_location) {
CHECK(d->dialog_id.get_type() == DialogType::Channel);
CHECK(!d->can_share_phone_number && !d->can_block_user && !d->can_add_contact && !d->can_report_spam &&
!d->can_invite_members);
return td_api::make_object<td_api::chatActionBarReportUnrelatedLocation>();
}
if (d->can_invite_members) {
CHECK(!d->can_share_phone_number && !d->can_block_user && !d->can_add_contact && !d->can_report_spam);
return td_api::make_object<td_api::chatActionBarInviteMembers>();
}
if (d->can_share_phone_number) {
CHECK(d->dialog_id.get_type() == DialogType::User);
CHECK(!d->can_block_user && !d->can_add_contact && !d->can_report_spam);
return td_api::make_object<td_api::chatActionBarSharePhoneNumber>();
}
if (hide_unarchive) {
if (d->can_add_contact) {
return td_api::make_object<td_api::chatActionBarAddContact>();
} else {
return nullptr;
}
}
if (d->can_block_user) {
CHECK(d->dialog_id.get_type() == DialogType::User);
CHECK(d->can_report_spam && d->can_add_contact);
auto distance = d->hide_distance ? -1 : d->distance;
return td_api::make_object<td_api::chatActionBarReportAddBlock>(d->can_unarchive, distance);
}
if (d->can_add_contact) {
CHECK(d->dialog_id.get_type() == DialogType::User);
CHECK(!d->can_report_spam);
return td_api::make_object<td_api::chatActionBarAddContact>();
}
if (d->can_report_spam) {
return td_api::make_object<td_api::chatActionBarReportSpam>(d->can_unarchive);
}
return nullptr;
return d->action_bar->get_chat_action_bar_object(dialog_type, false);
}
string MessagesManager::get_dialog_theme_name(const Dialog *d) const {
@ -29279,10 +29151,13 @@ void MessagesManager::send_update_secret_chats_with_user_action_bar(const Dialog
});
}
void MessagesManager::send_update_chat_action_bar(const Dialog *d) {
void MessagesManager::send_update_chat_action_bar(Dialog *d) {
if (td_->auth_manager_->is_bot()) {
return;
}
if (d->action_bar != nullptr && d->action_bar->is_empty()) {
d->action_bar = nullptr;
}
CHECK(d != nullptr);
LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_action_bar";
@ -30255,14 +30130,8 @@ void MessagesManager::set_dialog_is_blocked(Dialog *d, bool is_blocked) {
if (d->know_action_bar) {
if (is_blocked) {
if (d->can_report_spam || d->can_share_phone_number || d->can_block_user || d->can_add_contact ||
d->can_unarchive || d->distance >= 0) {
d->can_report_spam = false;
d->can_share_phone_number = false;
d->can_block_user = false;
d->can_add_contact = false;
d->can_unarchive = false;
d->distance = -1;
if (d->action_bar != nullptr) {
d->action_bar = nullptr;
send_update_chat_action_bar(d);
}
} else {
@ -30605,17 +30474,13 @@ void MessagesManager::do_set_dialog_folder_id(Dialog *d, FolderId folder_id) {
auto user_id = td_->contacts_manager_->get_secret_chat_user_id(d->dialog_id.get_secret_chat_id());
if (d->is_update_new_chat_sent && user_id.is_valid()) {
const Dialog *user_d = get_dialog(DialogId(user_id));
if (user_d != nullptr && user_d->can_unarchive && user_d->know_action_bar) {
if (user_d != nullptr && user_d->action_bar != nullptr && user_d->action_bar->can_unarchive()) {
send_closure(
G()->td(), &Td::send_update,
td_api::make_object<td_api::updateChatActionBar>(d->dialog_id.get(), get_chat_action_bar_object(d)));
}
}
} else if (d->can_unarchive && folder_id != FolderId::archive()) {
d->can_unarchive = false;
d->can_report_spam = false;
d->can_block_user = false;
// keep d->can_add_contact
} else if (folder_id != FolderId::archive() && d->action_bar != nullptr && d->action_bar->on_dialog_unarchived()) {
send_update_chat_action_bar(d);
}
@ -30890,11 +30755,7 @@ void MessagesManager::on_dialog_user_is_contact_updated(DialogId dialog_id, bool
if (d != nullptr && d->is_update_new_chat_sent) {
if (d->know_action_bar) {
if (is_contact) {
if (d->can_block_user || d->can_add_contact) {
d->can_block_user = false;
d->can_add_contact = false;
// keep d->can_unarchive
d->distance = -1;
if (d->action_bar != nullptr && d->action_bar->on_user_contact_added()) {
send_update_chat_action_bar(d);
}
} else {
@ -30922,11 +30783,7 @@ void MessagesManager::on_dialog_user_is_deleted_updated(DialogId dialog_id, bool
if (d != nullptr && d->is_update_new_chat_sent) {
if (d->know_action_bar) {
if (is_deleted) {
if (d->can_share_phone_number || d->can_block_user || d->can_add_contact || d->distance >= 0) {
d->can_share_phone_number = false;
d->can_block_user = false;
d->can_add_contact = false;
d->distance = -1;
if (d->action_bar != nullptr && d->action_bar->on_user_deleted()) {
send_update_chat_action_bar(d);
}
} else {
@ -33119,7 +32976,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
update_used_hashtags(dialog_id, m);
update_top_dialogs(dialog_id, m);
cancel_user_dialog_action(dialog_id, m);
try_hide_distance(dialog_id, m);
update_has_outgoing_messages(dialog_id, m);
if (!td_->auth_manager_->is_bot() && d->messages == nullptr && !m->is_outgoing && dialog_id != get_my_dialog_id()) {
switch (dialog_type) {
@ -33333,7 +33190,7 @@ MessagesManager::Message *MessagesManager::add_scheduled_message_to_dialog(Dialo
if (from_update) {
update_sent_message_contents(dialog_id, m);
update_used_hashtags(dialog_id, m);
try_hide_distance(dialog_id, m);
update_has_outgoing_messages(dialog_id, m);
}
if (m->message_id.is_scheduled_server()) {
@ -34558,7 +34415,7 @@ MessagesManager::Dialog *MessagesManager::add_new_dialog(unique_ptr<Dialog> &&d,
Dialog *dialog = dialog_it->second.get();
fix_dialog_action_bar(dialog);
fix_dialog_action_bar(dialog, dialog->action_bar.get());
send_update_new_chat(dialog);
@ -34621,10 +34478,11 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_datab
// asynchronously get dialog message TTL setting from the server
get_dialog_info_full(dialog_id, Auto(), "fix_new_dialog init message_ttl_setting");
}
if (!d->know_action_bar && !td_->auth_manager_->is_bot() && dialog_type != DialogType::SecretChat &&
dialog_id != get_my_dialog_id() && have_input_peer(dialog_id, AccessRights::Read)) {
if ((!d->know_action_bar || d->need_repair_action_bar) && !td_->auth_manager_->is_bot() &&
dialog_type != DialogType::SecretChat && dialog_id != get_my_dialog_id() &&
have_input_peer(dialog_id, AccessRights::Read)) {
// asynchronously get action bar from the server
reget_dialog_action_bar(dialog_id, "fix_new_dialog");
reget_dialog_action_bar(dialog_id, "fix_new_dialog", false);
}
if (d->has_active_group_call && !d->active_group_call_id.is_valid() && !td_->auth_manager_->is_bot()) {
repair_dialog_active_group_call_id(dialog_id);
@ -36942,7 +36800,7 @@ void MessagesManager::update_forward_count(DialogId dialog_id, MessageId message
}
}
void MessagesManager::try_hide_distance(DialogId dialog_id, const Message *m) {
void MessagesManager::update_has_outgoing_messages(DialogId dialog_id, const Message *m) {
CHECK(m != nullptr);
if (td_->auth_manager_->is_bot() || (!m->is_outgoing && dialog_id != get_my_dialog_id())) {
return;
@ -36959,21 +36817,21 @@ void MessagesManager::try_hide_distance(DialogId dialog_id, const Message *m) {
case DialogType::SecretChat: {
auto user_id = td_->contacts_manager_->get_secret_chat_user_id(dialog_id.get_secret_chat_id());
if (user_id.is_valid()) {
d = get_dialog_force(DialogId(user_id), "try_hide_distance");
d = get_dialog_force(DialogId(user_id), "update_has_outgoing_messages");
}
break;
}
default:
UNREACHABLE();
}
if (d == nullptr || d->hide_distance) {
if (d == nullptr || d->has_outgoing_messages) {
return;
}
d->hide_distance = true;
on_dialog_updated(dialog_id, "try_hide_distance");
d->has_outgoing_messages = true;
on_dialog_updated(dialog_id, "update_has_outgoing_messages");
if (d->distance != -1) {
if (d->action_bar != nullptr && d->action_bar->on_outgoing_message()) {
send_update_chat_action_bar(d);
}
}

View File

@ -86,6 +86,7 @@ namespace td {
struct BinlogEvent;
struct Dependencies;
class DialogActionBar;
class DialogFilter;
class DraftMessage;
struct InputMessageContent;
@ -806,7 +807,7 @@ class MessagesManager final : public Actor {
void remove_dialog_action_bar(DialogId dialog_id, Promise<Unit> &&promise);
void reget_dialog_action_bar(DialogId dialog_id, const char *source);
void reget_dialog_action_bar(DialogId dialog_id, const char *source, bool is_repair = true);
void report_dialog(DialogId dialog_id, const vector<MessageId> &message_ids, ReportReason &&reason,
Promise<Unit> &&promise);
@ -1183,6 +1184,7 @@ class MessagesManager final : public Actor {
DialogNotificationSettings notification_settings;
MessageTtlSetting message_ttl_setting;
unique_ptr<DraftMessage> draft_message;
unique_ptr<DialogActionBar> action_bar;
LogEventIdWithGeneration save_draft_message_log_event_id;
LogEventIdWithGeneration save_notification_settings_log_event_id;
std::unordered_map<int64, LogEventIdWithGeneration> read_history_log_event_ids;
@ -1203,8 +1205,6 @@ class MessagesManager final : public Actor {
MessageId
max_unavailable_message_id; // maximum unavailable message identifier for dialogs with cleared/unavailable history
int32 distance = -1; // distance to the peer
int32 last_clear_history_date = 0;
MessageId last_clear_history_message_id;
int64 order = DEFAULT_ORDER;
@ -1232,16 +1232,9 @@ class MessagesManager final : public Actor {
bool is_last_message_deleted_locally = false;
bool know_can_report_spam = false;
bool can_report_spam = false;
bool need_repair_action_bar = false;
bool know_action_bar = false;
bool can_add_contact = false;
bool can_block_user = false;
bool can_share_phone_number = false;
bool can_report_location = false;
bool can_unarchive = false;
bool hide_distance = false;
bool can_invite_members = false;
bool has_outgoing_messages = false;
bool is_opened = false;
bool was_opened = false;
@ -2363,7 +2356,7 @@ class MessagesManager final : public Actor {
void send_update_secret_chats_with_user_action_bar(const Dialog *d) const;
void send_update_chat_action_bar(const Dialog *d);
void send_update_chat_action_bar(Dialog *d);
void send_update_secret_chats_with_user_theme(const Dialog *d) const;
@ -2559,12 +2552,11 @@ class MessagesManager final : public Actor {
void add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message);
void fix_dialog_action_bar(Dialog *d);
void fix_dialog_action_bar(const Dialog *d, DialogActionBar *action_bar);
td_api::object_ptr<td_api::ChatType> get_chat_type_object(DialogId dialog_id) const;
td_api::object_ptr<td_api::ChatActionBar> get_chat_action_bar_object(const Dialog *d,
bool hide_unarchive = false) const;
td_api::object_ptr<td_api::ChatActionBar> get_chat_action_bar_object(const Dialog *d) const;
string get_dialog_theme_name(const Dialog *d) const;
@ -3062,7 +3054,7 @@ class MessagesManager final : public Actor {
void update_forward_count(DialogId dialog_id, MessageId message_id, int32 update_date);
void try_hide_distance(DialogId dialog_id, const Message *m);
void update_has_outgoing_messages(DialogId dialog_id, const Message *m);
string get_message_search_text(const Message *m) const;

View File

@ -168,13 +168,14 @@ td_api::object_ptr<td_api::sponsoredMessage> SponsoredMessageManager::get_sponso
link = td_api::make_object<td_api::internalLinkTypeBotStart>(bot_username, sponsored_message.start_param);
break;
}
case DialogType::Channel: {
auto channel_id = sponsored_message.sponsor_dialog_id.get_channel_id();
auto t_me = G()->shared_config().get_option_string("t_me_url", "https://t.me/");
link = td_api::make_object<td_api::internalLinkTypeMessage>(
PSTRING() << t_me << "/c" << channel_id.get() << '/' << sponsored_message.server_message_id.get());
case DialogType::Channel:
if (sponsored_message.server_message_id.is_valid()) {
auto channel_id = sponsored_message.sponsor_dialog_id.get_channel_id();
auto t_me = G()->shared_config().get_option_string("t_me_url", "https://t.me/");
link = td_api::make_object<td_api::internalLinkTypeMessage>(
PSTRING() << t_me << "c/" << channel_id.get() << '/' << sponsored_message.server_message_id.get());
}
break;
}
default:
break;
}

View File

@ -7,6 +7,8 @@
#include "td/telegram/SuggestedAction.h"
#include "td/telegram/ChannelId.h"
#include "td/telegram/ConfigManager.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/Td.h"
@ -151,4 +153,23 @@ void remove_suggested_action(vector<SuggestedAction> &suggested_actions, Suggest
}
}
void dismiss_suggested_action(SuggestedAction action, Promise<Unit> &&promise) {
switch (action.type_) {
case SuggestedAction::Type::Empty:
return promise.set_error(Status::Error(400, "Action must be non-empty"));
case SuggestedAction::Type::EnableArchiveAndMuteNewChats:
case SuggestedAction::Type::CheckPassword:
case SuggestedAction::Type::CheckPhoneNumber:
case SuggestedAction::Type::SeeTicksHint:
return send_closure_later(G()->config_manager(), &ConfigManager::dismiss_suggested_action, std::move(action),
std::move(promise));
case SuggestedAction::Type::ConvertToGigagroup:
return send_closure_later(G()->contacts_manager(), &ContactsManager::dismiss_dialog_suggested_action,
std::move(action), std::move(promise));
default:
UNREACHABLE();
return;
}
}
} // namespace td

View File

@ -9,6 +9,8 @@
#include "td/telegram/DialogId.h"
#include "td/telegram/td_api.h"
#include "td/actor/PromiseFuture.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
@ -70,4 +72,6 @@ void update_suggested_actions(vector<SuggestedAction> &suggested_actions,
void remove_suggested_action(vector<SuggestedAction> &suggested_actions, SuggestedAction suggested_action);
void dismiss_suggested_action(SuggestedAction action, Promise<Unit> &&promise);
} // namespace td

View File

@ -7718,7 +7718,7 @@ void Td::on_request(uint64 id, td_api::stopPoll &request) {
void Td::on_request(uint64 id, const td_api::hideSuggestedAction &request) {
CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE();
contacts_manager_->dismiss_suggested_action(SuggestedAction(request.action_), std::move(promise));
dismiss_suggested_action(SuggestedAction(request.action_), std::move(promise));
}
void Td::on_request(uint64 id, const td_api::getLoginUrlInfo &request) {

View File

@ -441,6 +441,9 @@ class CliClient final : public Actor {
if (str == "me") {
return my_id_;
}
if (str == ".") {
return opened_chat_id_;
}
if (str[0] == '@') {
str.remove_prefix(1);
}
@ -2596,7 +2599,9 @@ class CliClient final : public Actor {
} else if (op == "gdialog" || op == "gd") {
send_request(td_api::make_object<td_api::getChat>(as_chat_id(args)));
} else if (op == "open") {
send_request(td_api::make_object<td_api::openChat>(as_chat_id(args)));
auto chat_id = as_chat_id(args);
opened_chat_id_ = chat_id;
send_request(td_api::make_object<td_api::openChat>(chat_id));
} else if (op == "close") {
send_request(td_api::make_object<td_api::closeChat>(as_chat_id(args)));
} else if (op == "gm") {
@ -4554,6 +4559,7 @@ class CliClient final : public Actor {
int64 my_id_ = 0;
string schedule_date_;
string message_thread_id_;
int64 opened_chat_id_ = 0;
ConcurrentScheduler *scheduler_{nullptr};