Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2021-09-14 23:58:34 +02:00
commit 71c2330749
25 changed files with 181 additions and 164 deletions

View File

@ -138,7 +138,7 @@ TDLib can be used from the Swift programming language through the [JSON](https:/
See [example/ios](https://github.com/tdlib/td/tree/master/example/ios) for an example of building TDLib for iOS, watchOS, tvOS, and macOS.
See [TDLib-iOS](https://github.com/leoMehlig/TDLib-iOS) or [tdlib-swift](https://github.com/modestman/tdlib-swift), which provide convenient TDLib clients with automatically generated and fully-documented classes for all TDLib API methods and objects.
See [TDLibKit](https://github.com/Swiftgram/TDLibKit), [tdlib-swift](https://github.com/modestman/tdlib-swift), or [TDLib-iOS](https://github.com/leoMehlig/TDLib-iOS), which provide convenient TDLib clients with automatically generated and fully-documented classes for all TDLib API methods and objects.
See [example/swift](https://github.com/tdlib/td/tree/master/example/swift) for an example of a macOS Swift application.

View File

@ -803,7 +803,7 @@ foundMessages total_count:int32 messages:vector<message> next_offset:string = Fo
//@description Describes a sponsored message @id Unique sponsored message identifier @sponsor_chat_id Chat identifier
//@start_parameter Parameter for the bot start message if the sponsored chat is a chat with a bot @content Content of the message
sponsoredMessage id:bytes sponsor_chat_id:int53 start_parameter:string content:MessageContent = SponsoredMessage;
sponsoredMessage id:int32 sponsor_chat_id:int53 start_parameter:string content:MessageContent = SponsoredMessage;
//@description Contains a list of sponsored messages @messages List of sponsored messages
sponsoredMessages messages:vector<sponsoredMessage> = SponsoredMessages;
@ -4267,8 +4267,8 @@ getMessagePublicForwards chat_id:int53 message_id:int53 offset:string limit:int3
//@description Returns sponsored messages to be shown in a chat; for channel chats only @chat_id Identifier of the chat
getChatSponsoredMessages chat_id:int53 = SponsoredMessages;
//@description Informs TDLib that a sponsored message was viewed by the user @chat_id Chat identifier @message_id The identifier of the sponsored message being viewed
viewSponsoredMessage chat_id:int53 message_id:bytes = Ok;
//@description Informs TDLib that a sponsored message was viewed by the user @chat_id Identifier of the chat with the sponsored message @sponsored_message_id The identifier of the sponsored message being viewed
viewSponsoredMessage chat_id:int53 sponsored_message_id:int32 = Ok;
//@description Removes an active notification from notification list. Needs to be called only if the notification is removed by the current user @notification_group_id Identifier of notification group to which the notification belongs @notification_id Identifier of removed notification
@ -4368,7 +4368,8 @@ editMessageText chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_me
//@proximity_alert_radius The new maximum distance for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled
editMessageLiveLocation chat_id:int53 message_id:int53 reply_markup:ReplyMarkup location:location heading:int32 proximity_alert_radius:int32 = Message;
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video. The media in the message can't be replaced if the message was set to self-destruct. Media can't be replaced by self-destructing media. Media in an album can be edited only to contain a photo or a video. Returns the edited message after the edit is completed on the server side
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video, including message caption. If only the caption needs to be edited, use editMessageCaption instead.
//-The media can't be edited if the message was set to self-destruct or to a self-destructing media. The type of message content in an album can't be changed with exception of replacing a photo with a video or vice versa. Returns the edited message after the edit is completed on the server side
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: inputMessageAnimation, inputMessageAudio, inputMessageDocument, inputMessagePhoto or inputMessageVideo
editMessageMedia chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
@ -4623,7 +4624,7 @@ setChatMessageTtlSetting chat_id:int53 ttl:int32 = Ok;
//@chat_id Chat identifier @permissions New non-administrator members permissions in the chat
setChatPermissions chat_id:int53 permissions:chatPermissions = Ok;
//@description Changes the chat theme. Requires can_change_info administrator right in groups, supergroups and channels @chat_id Chat identifier
//@description Changes the chat theme. Supported only in private and secret chats @chat_id Chat identifier
//@theme_name Name of the new chat theme; may be empty to return the default theme
setChatTheme chat_id:int53 theme_name:string = Ok;

View File

@ -140,6 +140,9 @@ class PingConnectionPingPong final
return Status::OK();
}
Status on_update(BufferSlice packet) final {
return Status::OK();
}
void on_message_ack(uint64 id) final {
}
Status on_message_result_ok(uint64 id, BufferSlice packet, size_t original_size) final {

View File

@ -253,26 +253,31 @@ Status SessionConnection::on_packet_rpc_result(const MsgInfo &info, Slice packet
return Status::Error("Receive an update in rpc_result");
}
auto object_begin_pos = packet.size() - parser.get_left_len();
int32 id = parser.fetch_int();
if (id == mtproto_api::rpc_error::ID) {
mtproto_api::rpc_error rpc_error(parser);
if (parser.get_error()) {
return Status::Error(PSLICE() << "Failed to parse mtproto_api::rpc_error: " << parser.get_error());
switch (parser.fetch_int()) {
case mtproto_api::rpc_error::ID: {
mtproto_api::rpc_error rpc_error(parser);
if (parser.get_error()) {
return Status::Error(PSLICE() << "Failed to parse mtproto_api::rpc_error: " << parser.get_error());
}
VLOG(mtproto) << "ERROR " << tag("code", rpc_error.error_code_) << tag("message", rpc_error.error_message_)
<< tag("req_msg_id", req_msg_id);
callback_->on_message_result_error(req_msg_id, rpc_error.error_code_, rpc_error.error_message_.str());
return Status::OK();
}
return on_packet(info, req_msg_id, rpc_error);
} else if (id == mtproto_api::gzip_packed::ID) {
mtproto_api::gzip_packed gzip(parser);
if (parser.get_error()) {
return Status::Error(PSLICE() << "Failed to parse mtproto_api::gzip_packed: " << parser.get_error());
case mtproto_api::gzip_packed::ID: {
mtproto_api::gzip_packed gzip(parser);
if (parser.get_error()) {
return Status::Error(PSLICE() << "Failed to parse mtproto_api::gzip_packed: " << parser.get_error());
}
// yep, gzip in rpc_result
BufferSlice object = gzdecode(gzip.packed_data_);
// send header no more optimization
return callback_->on_message_result_ok(req_msg_id, std::move(object), info.size);
}
// yep, gzip in rpc_result
BufferSlice object = gzdecode(gzip.packed_data_);
// send header no more optimization
return callback_->on_message_result_ok(req_msg_id, std::move(object), info.size);
default:
packet.remove_prefix(4 + sizeof(req_msg_id));
return callback_->on_message_result_ok(req_msg_id, as_buffer_slice(packet), info.size);
}
return callback_->on_message_result_ok(req_msg_id, as_buffer_slice(packet.substr(object_begin_pos)), info.size);
}
template <class T>
@ -297,17 +302,7 @@ Status SessionConnection::on_destroy_auth_key(const mtproto_api::DestroyAuthKeyR
}
Status SessionConnection::on_packet(const MsgInfo &info, const mtproto_api::rpc_error &rpc_error) {
return on_packet(info, 0, rpc_error);
}
Status SessionConnection::on_packet(const MsgInfo &info, uint64 req_msg_id, const mtproto_api::rpc_error &rpc_error) {
VLOG(mtproto) << "ERROR " << tag("code", rpc_error.error_code_) << tag("message", rpc_error.error_message_)
<< tag("req_msg_id", req_msg_id);
if (req_msg_id != 0) {
callback_->on_message_result_error(req_msg_id, rpc_error.error_code_, rpc_error.error_message_.str());
} else {
LOG(ERROR) << "Receive rpc_error as update: [" << rpc_error.error_code_ << "][" << rpc_error.error_message_ << "]";
}
LOG(ERROR) << "Receive rpc_error as update: [" << rpc_error.error_code_ << "][" << rpc_error.error_message_ << "]";
return Status::OK();
}
@ -523,7 +518,7 @@ Status SessionConnection::on_slice_packet(const MsgInfo &info, Slice packet) {
<< " in container " << container_id_ << " from session " << auth_data_->get_session_id()
<< " with message_id " << info.message_id << ", main_message_id = " << main_message_id_
<< ", seq_no = " << info.seq_no << " and original size " << info.size;
return callback_->on_message_result_ok(0, as_buffer_slice(packet), info.size);
return callback_->on_update(as_buffer_slice(packet));
}
}

View File

@ -109,6 +109,8 @@ class SessionConnection final
virtual void on_container_sent(uint64 container_id, vector<uint64> msgs_id) = 0;
virtual Status on_pong() = 0;
virtual Status on_update(BufferSlice packet) = 0;
virtual void on_message_ack(uint64 id) = 0;
virtual Status on_message_result_ok(uint64 id, BufferSlice packet, size_t original_size) = 0;
virtual void on_message_result_error(uint64 id, int code, string message) = 0;
@ -216,8 +218,6 @@ class SessionConnection final
Status parse_packet(TlParser &parser) TD_WARN_UNUSED_RESULT;
Status on_packet_container(const MsgInfo &info, Slice packet) TD_WARN_UNUSED_RESULT;
Status on_packet_rpc_result(const MsgInfo &info, Slice packet) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, uint64 req_msg_id,
const mtproto_api::rpc_error &rpc_error) TD_WARN_UNUSED_RESULT;
template <class T>
Status on_packet(const MsgInfo &info, const T &packet) TD_WARN_UNUSED_RESULT;

View File

@ -406,6 +406,12 @@ ActorOwn<> get_full_config(DcOption option, Promise<FullConfig> promise, ActorSh
void on_tmp_auth_key_updated(mtproto::AuthKey auth_key) final {
// nop
}
void on_server_salt_updated(std::vector<mtproto::ServerSalt> server_salts) final {
// nop
}
void on_update(BufferSlice &&update) final {
// nop
}
void on_result(NetQueryPtr net_query) final {
G()->net_query_dispatcher().dispatch(std::move(net_query));
}

View File

@ -11583,7 +11583,9 @@ void ContactsManager::on_get_chat_participants(tl_object_ptr<telegram_api::ChatP
on_update_chat_full_participants(chat_full, chat_id, std::move(new_participants), participants->version_,
from_update);
update_chat_full(chat_full, chat_id, "on_get_chat_participants");
if (from_update) {
update_chat_full(chat_full, chat_id, "on_get_chat_participants");
}
break;
}
default:

View File

@ -60,9 +60,6 @@ class ThemeManager;
class TopDialogManager;
class UpdatesManager;
class WebPagesManager;
} // namespace td
namespace td {
class Global final : public ActorContext {
public:

View File

@ -668,6 +668,7 @@ static vector<Slice> match_urls(Slice str) {
case '<':
case '>':
case '"':
case '@':
case 0xab: // «
case 0xbb: // »
return false;
@ -697,20 +698,34 @@ static vector<Slice> match_urls(Slice str) {
continue;
}
const unsigned char *last_at_ptr = nullptr;
const unsigned char *domain_end_ptr = begin + dot_pos;
while (domain_end_ptr != end) {
const unsigned char *domain_begin_ptr = begin + dot_pos;
while (domain_begin_ptr != begin) {
domain_begin_ptr = prev_utf8_unsafe(domain_begin_ptr);
uint32 code = 0;
auto next_ptr = next_utf8_unsafe(domain_end_ptr, &code, "match_urls");
if (code == '@') {
last_at_ptr = domain_end_ptr;
}
if (!is_user_data_symbol(code)) {
auto next_ptr = next_utf8_unsafe(domain_begin_ptr, &code, "match_urls 0");
if (!is_domain_symbol(code)) {
domain_begin_ptr = next_ptr;
break;
}
domain_end_ptr = next_ptr;
}
domain_end_ptr = last_at_ptr == nullptr ? begin + dot_pos : last_at_ptr + 1;
const unsigned char *last_at_ptr = nullptr;
const unsigned char *domain_end_ptr = begin + dot_pos;
if (domain_begin_ptr == begin || domain_begin_ptr[-1] != '@') {
// try to find '@' to the right if there is no '@' to the left
while (domain_end_ptr != end) {
uint32 code = 0;
auto next_ptr = next_utf8_unsafe(domain_end_ptr, &code, "match_urls");
if (code == '@') {
last_at_ptr = domain_end_ptr;
}
if (!is_user_data_symbol(code)) {
break;
}
domain_end_ptr = next_ptr;
}
domain_end_ptr = last_at_ptr == nullptr ? begin + dot_pos : last_at_ptr + 1;
}
while (domain_end_ptr != end) {
uint32 code = 0;
auto next_ptr = next_utf8_unsafe(domain_end_ptr, &code, "match_urls 2");
@ -720,14 +735,15 @@ static vector<Slice> match_urls(Slice str) {
domain_end_ptr = next_ptr;
}
const unsigned char *domain_begin_ptr = begin + dot_pos;
while (domain_begin_ptr != begin) {
domain_begin_ptr = prev_utf8_unsafe(domain_begin_ptr);
uint32 code = 0;
auto next_ptr = next_utf8_unsafe(domain_begin_ptr, &code, "match_urls 3");
if (last_at_ptr == nullptr ? !is_domain_symbol(code) : !is_user_data_symbol(code)) {
domain_begin_ptr = next_ptr;
break;
if (last_at_ptr != nullptr) {
while (domain_begin_ptr != begin) {
domain_begin_ptr = prev_utf8_unsafe(domain_begin_ptr);
uint32 code = 0;
auto next_ptr = next_utf8_unsafe(domain_begin_ptr, &code, "match_urls 3");
if (!is_user_data_symbol(code)) {
domain_begin_ptr = next_ptr;
break;
}
}
}
// LOG(ERROR) << "Domain: " << Slice(domain_begin_ptr, domain_end_ptr);
@ -776,6 +792,9 @@ static vector<Slice> match_urls(Slice str) {
bool is_bad = false;
const unsigned char *url_begin_ptr = domain_begin_ptr;
if (url_begin_ptr != begin && url_begin_ptr[-1] == '@') {
if (last_at_ptr != nullptr) {
is_bad = true;
}
auto user_data_begin_ptr = url_begin_ptr - 1;
while (user_data_begin_ptr != begin) {
user_data_begin_ptr = prev_utf8_unsafe(user_data_begin_ptr);

View File

@ -31586,33 +31586,18 @@ void MessagesManager::set_dialog_theme(DialogId dialog_id, const string &theme_n
auto d = get_dialog_force(dialog_id, "set_dialog_theme");
if (d == nullptr) {
return promise.set_error(Status::Error(3, "Chat not found"));
return promise.set_error(Status::Error(400, "Chat not found"));
}
if (!have_input_peer(dialog_id, AccessRights::Write)) {
return promise.set_error(Status::Error(3, "Can't access the chat"));
return promise.set_error(Status::Error(400, "Can't access the chat"));
}
switch (dialog_id.get_type()) {
case DialogType::User:
break;
case DialogType::Chat: {
auto chat_id = dialog_id.get_chat_id();
auto status = td_->contacts_manager_->get_chat_permissions(chat_id);
if (!status.can_change_info_and_settings()) {
return promise.set_error(Status::Error(3, "Not enough rights to change chat theme"));
}
break;
}
case DialogType::Channel: {
if (is_broadcast_channel(dialog_id)) {
return promise.set_error(Status::Error(3, "Can't change channel chat permissions"));
}
auto status = td_->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id());
if (!status.can_change_info_and_settings()) {
return promise.set_error(Status::Error(3, "Not enough rights to change chat theme"));
}
break;
}
case DialogType::Chat:
case DialogType::Channel:
return promise.set_error(Status::Error(400, "Can't change theme in the chat"));
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()) {

View File

@ -21,6 +21,8 @@
#include "td/utils/logging.h"
#include "td/utils/Status.h"
#include <limits>
namespace td {
class GetSponsoredMessagesQuery final : public Td::ResultHandler {
@ -91,14 +93,14 @@ class ViewSponsoredMessageQuery final : public Td::ResultHandler {
};
struct SponsoredMessageManager::SponsoredMessage {
string random_id;
int32 local_id = 0;
DialogId sponsor_dialog_id;
string start_param;
unique_ptr<MessageContent> content;
SponsoredMessage() = default;
SponsoredMessage(string random_id, DialogId sponsor_dialog_id, string start_param, unique_ptr<MessageContent> content)
: random_id(std::move(random_id))
SponsoredMessage(int32 local_id, DialogId sponsor_dialog_id, string start_param, unique_ptr<MessageContent> content)
: local_id(local_id)
, sponsor_dialog_id(sponsor_dialog_id)
, start_param(std::move(start_param))
, content(std::move(content)) {
@ -108,6 +110,7 @@ struct SponsoredMessageManager::SponsoredMessage {
struct SponsoredMessageManager::DialogSponsoredMessages {
vector<Promise<td_api::object_ptr<td_api::sponsoredMessages>>> promises;
vector<SponsoredMessage> messages;
std::unordered_map<int32, string> message_random_ids;
};
SponsoredMessageManager::SponsoredMessageManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
@ -146,7 +149,7 @@ void SponsoredMessageManager::delete_cached_sponsored_messages(DialogId dialog_i
td_api::object_ptr<td_api::sponsoredMessage> SponsoredMessageManager::get_sponsored_message_object(
DialogId dialog_id, const SponsoredMessage &sponsored_message) const {
return td_api::make_object<td_api::sponsoredMessage>(
sponsored_message.random_id, sponsored_message.sponsor_dialog_id.get(), sponsored_message.start_param,
sponsored_message.local_id, sponsored_message.sponsor_dialog_id.get(), sponsored_message.start_param,
get_message_content_object(sponsored_message.content.get(), td_, dialog_id, 0, false, true, -1));
}
@ -194,6 +197,8 @@ void SponsoredMessageManager::on_get_dialog_sponsored_messages(
CHECK(messages != nullptr);
auto promises = std::move(messages->promises);
reset_to_empty(messages->promises);
CHECK(messages->messages.empty());
CHECK(messages->message_random_ids.empty());
if (result.is_ok() && G()->close_flag()) {
result = Status::Error(500, "Request aborted");
@ -211,7 +216,6 @@ void SponsoredMessageManager::on_get_dialog_sponsored_messages(
td_->contacts_manager_->on_get_users(std::move(sponsored_messages->users_), "on_get_dialog_sponsored_messages");
td_->contacts_manager_->on_get_chats(std::move(sponsored_messages->chats_), "on_get_dialog_sponsored_messages");
reset_to_empty(messages->messages);
for (auto &sponsored_message : sponsored_messages->messages_) {
DialogId sponsor_dialog_id(sponsored_message->from_id_);
if (!sponsor_dialog_id.is_valid() || !td_->messages_manager_->have_dialog_info_force(sponsor_dialog_id)) {
@ -229,8 +233,11 @@ void SponsoredMessageManager::on_get_dialog_sponsored_messages(
continue;
}
messages->messages.emplace_back(sponsored_message->random_id_.as_slice().str(), sponsor_dialog_id,
std::move(sponsored_message->start_param_), std::move(content));
CHECK(current_sponsored_message_id_ < std::numeric_limits<int32>::max());
auto local_id = ++current_sponsored_message_id_;
messages->message_random_ids[local_id] = sponsored_message->random_id_.as_slice().str();
messages->messages.emplace_back(local_id, sponsor_dialog_id, std::move(sponsored_message->start_param_),
std::move(content));
}
for (auto &promise : promises) {
@ -239,18 +246,24 @@ void SponsoredMessageManager::on_get_dialog_sponsored_messages(
delete_cached_sponsored_messages_timeout_.set_timeout_in(dialog_id.get(), 300.0);
}
void SponsoredMessageManager::view_sponsored_message(DialogId dialog_id, const string &message_id,
void SponsoredMessageManager::view_sponsored_message(DialogId dialog_id, int32 sponsored_message_id,
Promise<Unit> &&promise) {
if (!td_->messages_manager_->have_dialog_force(dialog_id, "view_sponsored_message")) {
return promise.set_error(Status::Error(400, "Chat not found"));
}
if (dialog_id.get_type() != DialogType::Channel ||
td_->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) != ContactsManager::ChannelType::Broadcast ||
message_id.empty()) {
return promise.set_error(Status::Error(400, "Message not found"));
auto it = dialog_sponsored_messages_.find(dialog_id);
if (it == dialog_sponsored_messages_.end()) {
return promise.set_value(Unit());
}
auto random_id_it = it->second->message_random_ids.find(sponsored_message_id);
if (random_id_it == it->second->message_random_ids.end()) {
return promise.set_value(Unit());
}
td_->create_handler<ViewSponsoredMessageQuery>(std::move(promise))->send(dialog_id.get_channel_id(), message_id);
auto random_id = std::move(random_id_it->second);
it->second->message_random_ids.erase(random_id_it);
td_->create_handler<ViewSponsoredMessageQuery>(std::move(promise))->send(dialog_id.get_channel_id(), random_id);
}
} // namespace td

View File

@ -35,7 +35,7 @@ class SponsoredMessageManager final : public Actor {
void get_dialog_sponsored_messages(DialogId dialog_id,
Promise<td_api::object_ptr<td_api::sponsoredMessages>> &&promise);
void view_sponsored_message(DialogId dialog_id, const string &message_id, Promise<Unit> &&promise);
void view_sponsored_message(DialogId dialog_id, int32 sponsored_message_id, Promise<Unit> &&promise);
private:
struct SponsoredMessage;
@ -59,6 +59,8 @@ class SponsoredMessageManager final : public Actor {
std::unordered_map<DialogId, unique_ptr<DialogSponsoredMessages>, DialogIdHash> dialog_sponsored_messages_;
int32 current_sponsored_message_id_ = 0;
MultiTimeout delete_cached_sponsored_messages_timeout_{"DeleteCachedSponsoredMessagesTimeout"};
Td *td_;

View File

@ -3343,10 +3343,30 @@ void Td::invalidate_handler(ResultHandler *handler) {
void Td::send(NetQueryPtr &&query) {
VLOG(net_query) << "Send " << query << " to dispatcher";
query->debug("Td: send to NetQueryDispatcher");
query->set_callback(actor_shared(this, 1));
G()->net_query_dispatcher().dispatch(std::move(query));
}
void Td::on_update(BufferSlice &&update) {
if (close_flag_ > 1) {
return;
}
TlBufferParser parser(&update);
auto ptr = telegram_api::Updates::fetch(parser);
parser.fetch_end();
if (parser.get_error()) {
LOG(ERROR) << "Failed to fetch update: " << parser.get_error() << format::as_hex_dump<4>(update.as_slice());
updates_manager_->schedule_get_difference("failed to fetch update");
} else {
updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
if (auth_manager_->is_bot() && auth_manager_->is_authorized()) {
alarm_timeout_.set_timeout_in(PING_SERVER_ALARM_ID,
PING_SERVER_TIMEOUT + Random::fast(0, PING_SERVER_TIMEOUT / 5));
set_is_bot_online(true);
}
}
}
void Td::on_result(NetQueryPtr query) {
query->debug("Td: received from DcManager");
VLOG(net_query) << "Receive result of " << query;
@ -3354,30 +3374,6 @@ void Td::on_result(NetQueryPtr query) {
return;
}
if (query->id() == 0) {
if (query->is_error()) {
query->clear();
updates_manager_->schedule_get_difference("error in update");
LOG(ERROR) << "Error in update";
return;
}
auto ok = query->move_as_ok();
TlBufferParser parser(&ok);
auto ptr = telegram_api::Updates::fetch(parser);
parser.fetch_end();
if (parser.get_error()) {
LOG(ERROR) << "Failed to fetch update: " << parser.get_error() << format::as_hex_dump<4>(ok.as_slice());
updates_manager_->schedule_get_difference("failed to fetch update");
} else {
updates_manager_->on_get_updates(std::move(ptr), Promise<Unit>());
if (auth_manager_->is_bot() && auth_manager_->is_authorized()) {
alarm_timeout_.set_timeout_in(PING_SERVER_ALARM_ID,
PING_SERVER_TIMEOUT + Random::fast(0, PING_SERVER_TIMEOUT / 5));
set_is_bot_online(true);
}
}
return;
}
auto handler = extract_handler(query->id());
if (handler == nullptr) {
query->clear();
@ -3575,7 +3571,7 @@ void Td::hangup_shared() {
auto type = Container<int>::type_from_id(token);
if (type == RequestActorIdType) {
request_actors_.erase(get_link_token());
request_actors_.erase(token);
dec_request_actor_refcnt();
} else if (type == ActorIdType) {
dec_actor_refcnt();
@ -5042,7 +5038,7 @@ void Td::on_request(uint64 id, const td_api::getChatSponsoredMessages &request)
void Td::on_request(uint64 id, const td_api::viewSponsoredMessage &request) {
CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE();
sponsored_message_manager_->view_sponsored_message(DialogId(request.chat_id_), request.message_id_,
sponsored_message_manager_->view_sponsored_message(DialogId(request.chat_id_), request.sponsored_message_id_,
std::move(promise));
}

View File

@ -84,10 +84,6 @@ class VideosManager;
class VoiceNotesManager;
class WebPagesManager;
} // namespace td
namespace td {
extern int VERBOSITY_NAME(td_init);
extern int VERBOSITY_NAME(td_requests);
extern int VERBOSITY_NAME(messages);
@ -103,7 +99,7 @@ extern int VERBOSITY_NAME(add_pending_update);
//
// Parent needs a way to know that it will receive no more updates.
// It happens after destruction of callback or after on_closed.
class Td final : public NetQueryCallback {
class Td final : public Actor {
public:
Td(const Td &) = delete;
Td(Td &&) = delete;
@ -125,7 +121,9 @@ class Td final : public NetQueryCallback {
void schedule_get_promo_data(int32 expires_in);
void on_result(NetQueryPtr query) final;
void on_update(BufferSlice &&update);
void on_result(NetQueryPtr query);
void on_update_server_time_difference();

View File

@ -2603,9 +2603,10 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::getChatSponsoredMessages>(as_chat_id(args)));
} else if (op == "vsm") {
string chat_id;
string message_id;
get_args(args, chat_id, message_id);
send_request(td_api::make_object<td_api::viewSponsoredMessage>(as_chat_id(chat_id), message_id));
string sponsored_message_id;
get_args(args, chat_id, sponsored_message_id);
send_request(td_api::make_object<td_api::viewSponsoredMessage>(as_chat_id(chat_id),
to_integer<int32>(sponsored_message_id)));
} else if (op == "gmlink") {
string chat_id;
string message_id;

View File

@ -17,13 +17,11 @@
#include <unordered_map>
namespace td {
namespace td_api {
class storageStatistics;
class storageStatisticsFast;
} // namespace td_api
} // namespace td
namespace td {
struct FileTypeStat {
int64 size{0};

View File

@ -48,10 +48,6 @@ class StatsCallback;
class GetHostByNameActor;
} // namespace td
namespace td {
extern int VERBOSITY_NAME(connections);
class ConnectionCreator final : public NetQueryCallback {

View File

@ -354,6 +354,7 @@ class NetQuery final : public TsListNode<NetQueryDebug> {
, answer_(std::move(answer))
, tl_constructor_(tl_constructor)
, total_timeout_limit_(total_timeout_limit) {
CHECK(id_ != 0);
auto &data = get_data_unsafe();
data.my_id_ = get_my_id();
data.start_timestamp_ = data.state_timestamp_ = Time::now();

View File

@ -11,6 +11,7 @@
#include "td/telegram/Td.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/buffer.h"
#include "td/utils/format.h"
#include "td/utils/Gzip.h"
#include "td/utils/logging.h"

View File

@ -11,7 +11,6 @@
#include "td/telegram/net/NetQueryStats.h"
#include "td/telegram/UniqueId.h"
#include "td/utils/buffer.h"
#include "td/utils/ObjectPool.h"
#include <memory>
@ -33,12 +32,6 @@ class NetQueryCreator {
object_pool_.set_check_empty(false);
}
NetQueryPtr create_update(BufferSlice &&buffer) {
return object_pool_.create(NetQuery::State::OK, 0, BufferSlice(), std::move(buffer), DcId::main(),
NetQuery::Type::Common, NetQuery::AuthFlag::On, NetQuery::GzipFlag::Off, 0, 0,
net_query_stats_.get());
}
NetQueryPtr create(const telegram_api::Function &function, DcId dc_id = DcId::main(),
NetQuery::Type type = NetQuery::Type::Common);

View File

@ -34,22 +34,20 @@ void NetQueryDispatcher::complete_net_query(NetQueryPtr net_query) {
auto callback = net_query->move_callback();
if (callback.empty()) {
net_query->debug("sent to td (no callback)");
send_closure(G()->td(), &NetQueryCallback::on_result, std::move(net_query));
send_closure_later(G()->td(), &Td::on_result, std::move(net_query));
} else {
net_query->debug("sent to callback", true);
send_closure(std::move(callback), &NetQueryCallback::on_result, std::move(net_query));
send_closure_later(std::move(callback), &NetQueryCallback::on_result, std::move(net_query));
}
}
void NetQueryDispatcher::dispatch(NetQueryPtr net_query) {
// net_query->debug("dispatch");
if (stop_flag_.load(std::memory_order_relaxed)) {
if (net_query->id() != 0) {
net_query->set_error(Status::Error(500, "Request aborted"));
}
net_query->set_error(Status::Error(500, "Request aborted"));
return complete_net_query(std::move(net_query));
}
if (net_query->id() != 0 && G()->shared_config().get_option_boolean("test_flood_wait")) {
if (G()->shared_config().get_option_boolean("test_flood_wait")) {
net_query->set_error(Status::Error(429, "Too Many Requests: retry after 10"));
return complete_net_query(std::move(net_query));
}

View File

@ -569,7 +569,8 @@ void Session::on_session_created(uint64 unique_id, uint64 first_id) {
LOG(DEBUG) << "Sending updatesTooLong to force getDifference";
BufferSlice packet(4);
as<int32>(packet.as_slice().begin()) = telegram_api::updatesTooLong::ID;
return_query(G()->net_query_creator().create_update(std::move(packet)));
last_activity_timestamp_ = Time::now();
callback_->on_update(std::move(packet));
}
for (auto it = sent_queries_.begin(); it != sent_queries_.end();) {
@ -710,15 +711,18 @@ void Session::mark_as_unknown(uint64 id, Query *query) {
unknown_queries_.insert(id);
}
Status Session::on_message_result_ok(uint64 id, BufferSlice packet, size_t original_size) {
if (id == 0) {
if (is_cdn_) {
return Status::Error("Got update from CDN connection");
}
last_success_timestamp_ = Time::now();
return_query(G()->net_query_creator().create_update(std::move(packet)));
return Status::OK();
Status Session::on_update(BufferSlice packet) {
if (is_cdn_) {
return Status::Error("Receive at update from CDN connection");
}
last_success_timestamp_ = Time::now();
last_activity_timestamp_ = Time::now();
callback_->on_update(std::move(packet));
return Status::OK();
}
Status Session::on_message_result_ok(uint64 id, BufferSlice packet, size_t original_size) {
last_success_timestamp_ = Time::now();
TlParser parser(packet.as_slice());

View File

@ -61,9 +61,8 @@ class Session final
virtual void request_raw_connection(unique_ptr<mtproto::AuthData> auth_data,
Promise<unique_ptr<mtproto::RawConnection>>) = 0;
virtual void on_tmp_auth_key_updated(mtproto::AuthKey auth_key) = 0;
virtual void on_server_salt_updated(std::vector<mtproto::ServerSalt> server_salts) {
}
// one still have to call close after on_closed
virtual void on_server_salt_updated(std::vector<mtproto::ServerSalt> server_salts) = 0;
virtual void on_update(BufferSlice &&update) = 0;
virtual void on_result(NetQueryPtr net_query) = 0;
};
@ -206,6 +205,8 @@ class Session final
void on_container_sent(uint64 container_id, vector<uint64> msg_ids) final;
Status on_update(BufferSlice packet) final;
void on_message_ack(uint64 id) final;
Status on_message_result_ok(uint64 id, BufferSlice packet, size_t original_size) final;
void on_message_result_error(uint64 id, int error_code, string message) final;

View File

@ -11,6 +11,7 @@
#include "td/telegram/net/DcId.h"
#include "td/telegram/net/NetQueryDispatcher.h"
#include "td/telegram/net/Session.h"
#include "td/telegram/Td.h"
#include "td/telegram/UniqueId.h"
#include "td/actor/PromiseFuture.h"
@ -58,9 +59,12 @@ class SessionCallback final : public Session::Callback {
send_closure(parent_, &SessionProxy::on_server_salt_updated, std::move(server_salts));
}
void on_update(BufferSlice &&update) final {
send_closure_later(G()->td(), &Td::on_update, std::move(update));
}
void on_result(NetQueryPtr query) final {
if (UniqueId::extract_type(query->id()) != UniqueId::BindKey &&
query->id() != 0) { // not bind key query and not an update
if (UniqueId::extract_type(query->id()) != UniqueId::BindKey) {
send_closure(parent_, &SessionProxy::on_query_finished);
}
G()->net_query_dispatcher().dispatch(std::move(query));
@ -240,6 +244,7 @@ void SessionProxy::on_tmp_auth_key_updated(mtproto::AuthKey auth_key) {
LOG(WARNING) << "Have tmp_auth_key " << auth_key.id() << ": " << state;
tmp_auth_key_ = std::move(auth_key);
}
void SessionProxy::on_server_salt_updated(std::vector<mtproto::ServerSalt> server_salts) {
server_salts_ = std::move(server_salts);
}

View File

@ -480,7 +480,7 @@ TEST(MessageEntities, url) {
check_url(".", {});
check_url("http://@google.com", {});
check_url("http://@goog.com", {}); // TODO: server fix
check_url("http://@@google.com", {"http://@@google.com"});
check_url("http://@@google.com", {});
check_url("http://a@google.com", {"http://a@google.com"});
check_url("http://test@google.com", {"http://test@google.com"});
check_url("google.com:᪉᪉᪉᪉᪉", {"google.com"});
@ -692,6 +692,8 @@ TEST(MessageEntities, url) {
check_url(".?", {});
check_url("http://test―@―google―.―com―/―–―‐―/―/―/―?―‑―#―――", {"http://test―@―google―.―com―/―–―‐―/―/―/―?―‑―#―――"});
check_url("http://google.com/‖", {"http://google.com/"});
check_url("a@b@c.com", {}, {});
check_url("a@b.com:c@1", {}, {"a@b.com"});
}
static void check_fix_formatted_text(td::string str, td::vector<td::MessageEntity> entities,