Add getMessagePublicForwards method.

GitOrigin-RevId: a0b16c241bcf3276c245423f7fff3f41751883b6
This commit is contained in:
levlam 2020-08-21 14:47:43 +03:00
parent 605e0844fb
commit f9c0ddae06
7 changed files with 266 additions and 25 deletions

View File

@ -3590,12 +3590,13 @@ searchChatMessages chat_id:int53 query:string sender_user_id:int32 from_message_
//@offset_date The date of the message starting from which the results should be fetched. Use 0 or any date in the future to get results from the last message //@offset_date The date of the message starting from which the results should be fetched. Use 0 or any date in the future to get results from the last message
//@offset_chat_id The chat identifier of the last found message, or 0 for the first request //@offset_chat_id The chat identifier of the last found message, or 0 for the first request
//@offset_message_id The message identifier of the last found message, or 0 for the first request //@offset_message_id The message identifier of the last found message, or 0 for the first request
//@limit The maximum number of messages to be returned, up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached //@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id:int53 offset_message_id:int53 limit:int32 = Messages; searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id:int53 offset_message_id:int53 limit:int32 = Messages;
//@description Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance the number of returned messages is chosen by the library //@description Searches for messages in secret chats. Returns the results in reverse chronological order. For optimal performance the number of returned messages is chosen by the library
//@chat_id Identifier of the chat in which to search. Specify 0 to search in all secret chats @query Query to search for. If empty, searchChatMessages should be used instead //@chat_id Identifier of the chat in which to search. Specify 0 to search in all secret chats
//@offset Offset of the first entry to return; use empty string to get results from the last message //@query Query to search for. If empty, searchChatMessages should be used instead
//@offset Offset of the first entry to return as received from the previous request; use empty string to get first chunk of results
//@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached //@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
//@filter A filter for the content of messages in the search results //@filter A filter for the content of messages in the search results
searchSecretMessages chat_id:int53 query:string offset:string limit:int32 filter:SearchMessagesFilter = FoundMessages; searchSecretMessages chat_id:int53 query:string offset:string limit:int32 filter:SearchMessagesFilter = FoundMessages;
@ -3620,6 +3621,13 @@ getChatMessageCount chat_id:int53 filter:SearchMessagesFilter return_local:Bool
//@description Returns all scheduled messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id) @chat_id Chat identifier //@description Returns all scheduled messages in a chat. The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id) @chat_id Chat identifier
getChatScheduledMessages chat_id:int53 = Messages; getChatScheduledMessages chat_id:int53 = Messages;
//@description Returns forwarded copies of a channel message to another public channels. For optimal performance the number of returned messages is chosen by the library
//@chat_id Chat identifier of the message
//@message_id Message identifier
//@offset Offset of the first entry to return as received from the previous request; use empty string to get first chunk of results
//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. Fewer messages may be returned than specified by the limit, even if the end of the list has not been reached
getMessagePublicForwards chat_id:int53 message_id:int53 offset:string limit:int32 = FoundMessages;
//@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 //@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
removeNotification notification_group_id:int32 notification_id:int32 = Ok; removeNotification notification_group_id:int32 notification_id:int32 = Ok;

Binary file not shown.

View File

@ -1782,6 +1782,52 @@ class GetRecentLocationsQuery : public Td::ResultHandler {
} }
}; };
class GetMessagePublicForwardsQuery : public Td::ResultHandler {
Promise<Unit> promise_;
DialogId dialog_id_;
int32 limit_;
int64 random_id_;
public:
explicit GetMessagePublicForwardsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(FullMessageId full_message_id, int32 offset_date, DialogId offset_dialog_id,
ServerMessageId offset_message_id, int32 limit, int64 random_id) {
dialog_id_ = full_message_id.get_dialog_id();
limit_ = limit;
random_id_ = random_id;
auto input_peer = MessagesManager::get_input_peer_force(offset_dialog_id);
CHECK(input_peer != nullptr);
send_query(G()->net_query_creator().create(telegram_api::stats_getMessagePublicForwards(
td->contacts_manager_->get_input_channel(dialog_id_.get_channel_id()),
full_message_id.get_message_id().get_server_message_id().get(), offset_date, std::move(input_peer),
offset_message_id.get(), limit)));
}
void on_result(uint64 id, BufferSlice packet) override {
auto result_ptr = fetch_result<telegram_api::stats_getMessagePublicForwards>(packet);
if (result_ptr.is_error()) {
return on_error(id, result_ptr.move_as_error());
}
auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetMessagePublicForwardsQuery");
LOG_IF(ERROR, !info.is_channel_messages) << "Receive ordinary messages in GetMessagePublicForwardsQuery";
td->messages_manager_->on_get_message_public_forwards_result(random_id_, info.total_count,
std::move(info.messages));
promise_.set_value(Unit());
}
void on_error(uint64 id, Status status) override {
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetMessagePublicForwardsQuery");
td->messages_manager_->on_failed_get_message_public_forwards(random_id_);
promise_.set_error(std::move(status));
}
};
class HidePromoDataQuery : public Td::ResultHandler { class HidePromoDataQuery : public Td::ResultHandler {
DialogId dialog_id_; DialogId dialog_id_;
@ -8838,6 +8884,48 @@ void MessagesManager::on_get_recent_locations_failed(int64 random_id) {
found_dialog_recent_location_messages_.erase(it); found_dialog_recent_location_messages_.erase(it);
} }
void MessagesManager::on_get_message_public_forwards_result(int64 random_id, int32 total_count,
vector<tl_object_ptr<telegram_api::Message>> &&messages) {
LOG(INFO) << "Receive " << messages.size() << " forwarded messages";
auto it = found_message_public_forwards_.find(random_id);
CHECK(it != found_message_public_forwards_.end());
auto &result = it->second.full_message_ids;
CHECK(result.empty());
FullMessageId last_full_message_id;
for (auto &message : messages) {
auto dialog_id = get_message_dialog_id(message);
auto new_full_message_id = on_get_message(std::move(message), false, dialog_id.get_type() == DialogType::Channel,
false, false, false, "get message public forwards");
if (new_full_message_id != FullMessageId()) {
CHECK(dialog_id == new_full_message_id.get_dialog_id());
result.push_back(new_full_message_id);
last_full_message_id = new_full_message_id;
} else {
total_count--;
}
}
if (total_count < static_cast<int32>(result.size())) {
LOG(ERROR) << "Receive " << result.size() << " valid messages out of " << total_count << " in " << messages.size()
<< " messages";
total_count = static_cast<int32>(result.size());
}
if (!result.empty()) {
auto m = get_message(last_full_message_id);
CHECK(m != nullptr);
it->second.next_offset = PSTRING() << m->date << "," << last_full_message_id.get_dialog_id().get() << ","
<< m->message_id.get_server_message_id().get();
}
// it->second.total_count = total_count;
}
void MessagesManager::on_failed_get_message_public_forwards(int64 random_id) {
auto it = found_message_public_forwards_.find(random_id);
CHECK(it != found_message_public_forwards_.end());
found_message_public_forwards_.erase(it);
}
void MessagesManager::delete_messages_from_updates(const vector<MessageId> &message_ids) { void MessagesManager::delete_messages_from_updates(const vector<MessageId> &message_ids) {
std::unordered_map<DialogId, vector<int64>, DialogIdHash> deleted_message_ids; std::unordered_map<DialogId, vector<int64>, DialogIdHash> deleted_message_ids;
std::unordered_map<DialogId, bool, DialogIdHash> need_update_dialog_pos; std::unordered_map<DialogId, bool, DialogIdHash> need_update_dialog_pos;
@ -18994,7 +19082,21 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo
promise.set_value(Unit()); promise.set_value(Unit());
} }
std::pair<string, vector<FullMessageId>> MessagesManager::offline_search_messages( td_api::object_ptr<td_api::foundMessages> MessagesManager::get_found_messages_object(
const FoundMessages &found_messages) {
vector<tl_object_ptr<td_api::message>> result;
result.reserve(found_messages.full_message_ids.size());
for (auto full_message_id : found_messages.full_message_ids) {
auto message = get_message_object(full_message_id);
if (message != nullptr) {
result.push_back(std::move(message));
}
}
return td_api::make_object<td_api::foundMessages>(std::move(result), found_messages.next_offset);
}
MessagesManager::FoundMessages MessagesManager::offline_search_messages(
DialogId dialog_id, const string &query, const string &offset, int32 limit, DialogId dialog_id, const string &query, const string &offset, int32 limit,
const tl_object_ptr<td_api::SearchMessagesFilter> &filter, int64 &random_id, Promise<> &&promise) { const tl_object_ptr<td_api::SearchMessagesFilter> &filter, int64 &random_id, Promise<> &&promise) {
if (!G()->parameters().use_message_db) { if (!G()->parameters().use_message_db) {
@ -19070,7 +19172,7 @@ void MessagesManager::on_messages_db_fts_result(Result<MessagesDbFtsResult> resu
auto it = found_fts_messages_.find(random_id); auto it = found_fts_messages_.find(random_id);
CHECK(it != found_fts_messages_.end()); CHECK(it != found_fts_messages_.end());
auto &res = it->second.second; auto &res = it->second.full_message_ids;
res.reserve(fts_result.messages.size()); res.reserve(fts_result.messages.size());
for (auto &message : fts_result.messages) { for (auto &message : fts_result.messages) {
@ -19081,7 +19183,7 @@ void MessagesManager::on_messages_db_fts_result(Result<MessagesDbFtsResult> resu
} }
} }
it->second.first = fts_result.next_search_id <= 1 ? string() : to_string(fts_result.next_search_id); it->second.next_offset = fts_result.next_search_id <= 1 ? string() : to_string(fts_result.next_search_id);
promise.set_value(Unit()); promise.set_value(Unit());
} }
@ -19930,6 +20032,83 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id
} }
} }
MessagesManager::FoundMessages MessagesManager::get_message_public_forwards(FullMessageId full_message_id,
const string &offset, int32 limit,
int64 &random_id, Promise<Unit> &&promise) {
if (random_id != 0) {
// request has already been sent before
auto it = found_message_public_forwards_.find(random_id);
CHECK(it != found_message_public_forwards_.end());
auto result = std::move(it->second);
found_message_public_forwards_.erase(it);
promise.set_value(Unit());
return result;
}
auto dialog_id = full_message_id.get_dialog_id();
Dialog *d = get_dialog_force(dialog_id);
if (d == nullptr) {
promise.set_error(Status::Error(5, "Chat not found"));
return {};
}
const Message *m = get_message_force(d, full_message_id.get_message_id(), "get_message_public_forwards");
if (m == nullptr) {
promise.set_error(Status::Error(5, "Message not found"));
return {};
}
if (m->view_count == 0 || m->forward_info != nullptr || m->had_forward_info || m->message_id.is_scheduled() ||
!m->message_id.is_server()) {
promise.set_error(Status::Error(5, "Message forwards are inaccessible"));
return {};
}
FoundMessages result;
if (limit <= 0) {
promise.set_error(Status::Error(3, "Parameter limit must be positive"));
return {};
}
if (limit > MAX_SEARCH_MESSAGES) {
limit = MAX_SEARCH_MESSAGES;
}
int32 offset_date = std::numeric_limits<int32>::max();
DialogId offset_dialog_id;
ServerMessageId offset_message_id;
if (!offset.empty()) {
auto parts = full_split(offset, ',');
if (parts.size() != 3) {
promise.set_error(Status::Error(3, "Wrong offset specified"));
return {};
}
auto r_offset_date = to_integer_safe<int32>(parts[0]);
auto r_offset_dialog_id = to_integer_safe<int64>(parts[1]);
auto r_offset_message_id = to_integer_safe<int32>(parts[2]);
if (r_offset_date.is_error() || r_offset_dialog_id.is_error() || r_offset_message_id.is_error()) {
promise.set_error(Status::Error(3, "Wrong offset specified"));
return {};
}
offset_date = r_offset_date.ok();
offset_dialog_id = DialogId(r_offset_dialog_id.ok());
offset_message_id = ServerMessageId(r_offset_message_id.ok());
}
do {
random_id = Random::secure_int64();
} while (random_id == 0 || found_message_public_forwards_.find(random_id) != found_message_public_forwards_.end());
found_message_public_forwards_[random_id]; // reserve place for result
LOG(DEBUG) << "Get public message forwards from date " << offset_date << ", " << offset_dialog_id
<< ", server message " << offset_message_id.get() << " and with limit " << limit;
td_->create_handler<GetMessagePublicForwardsQuery>(std::move(promise))
->send(full_message_id, offset_date, offset_dialog_id, offset_message_id, limit, random_id);
return {};
}
Result<int32> MessagesManager::get_message_schedule_date( Result<int32> MessagesManager::get_message_schedule_date(
td_api::object_ptr<td_api::MessageSchedulingState> &&scheduling_state) { td_api::object_ptr<td_api::MessageSchedulingState> &&scheduling_state) {
if (scheduling_state == nullptr) { if (scheduling_state == nullptr) {

View File

@ -246,6 +246,10 @@ class MessagesManager : public Actor {
vector<tl_object_ptr<telegram_api::Message>> &&messages); vector<tl_object_ptr<telegram_api::Message>> &&messages);
void on_get_recent_locations_failed(int64 random_id); void on_get_recent_locations_failed(int64 random_id);
void on_get_message_public_forwards_result(int64 random_id, int32 total_count,
vector<tl_object_ptr<telegram_api::Message>> &&messages);
void on_failed_get_message_public_forwards(int64 random_id);
// if message is from_update, flags have_previous and have_next are ignored and should be both true // if message is from_update, flags have_previous and have_next are ignored and should be both true
FullMessageId on_get_message(tl_object_ptr<telegram_api::Message> message_ptr, bool from_update, FullMessageId on_get_message(tl_object_ptr<telegram_api::Message> message_ptr, bool from_update,
bool is_channel_message, bool is_scheduled, bool have_previous, bool have_next, bool is_channel_message, bool is_scheduled, bool have_previous, bool have_next,
@ -653,9 +657,16 @@ class MessagesManager : public Actor {
const tl_object_ptr<td_api::SearchMessagesFilter> &filter, const tl_object_ptr<td_api::SearchMessagesFilter> &filter,
int64 &random_id, bool use_db, Promise<Unit> &&promise); int64 &random_id, bool use_db, Promise<Unit> &&promise);
std::pair<string, vector<FullMessageId>> offline_search_messages( struct FoundMessages {
DialogId dialog_id, const string &query, const string &offset, int32 limit, vector<FullMessageId> full_message_ids;
const tl_object_ptr<td_api::SearchMessagesFilter> &filter, int64 &random_id, Promise<> &&promise); string next_offset;
};
td_api::object_ptr<td_api::foundMessages> get_found_messages_object(const FoundMessages &found_messages);
FoundMessages offline_search_messages(DialogId dialog_id, const string &query, const string &offset, int32 limit,
const tl_object_ptr<td_api::SearchMessagesFilter> &filter, int64 &random_id,
Promise<> &&promise);
std::pair<int32, vector<FullMessageId>> search_messages(FolderId folder_id, bool ignore_folder_id, std::pair<int32, vector<FullMessageId>> search_messages(FolderId folder_id, bool ignore_folder_id,
const string &query, int32 offset_date, const string &query, int32 offset_date,
@ -683,6 +694,9 @@ class MessagesManager : public Actor {
vector<MessageId> get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result, vector<MessageId> get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result,
Promise<Unit> &&promise); Promise<Unit> &&promise);
FoundMessages get_message_public_forwards(FullMessageId full_message_id, const string &offset, int32 limit,
int64 &random_id, Promise<Unit> &&promise);
tl_object_ptr<td_api::message> get_dialog_message_by_date_object(int64 random_id); tl_object_ptr<td_api::message> get_dialog_message_by_date_object(int64 random_id);
tl_object_ptr<td_api::message> get_message_object(FullMessageId full_message_id); tl_object_ptr<td_api::message> get_message_object(FullMessageId full_message_id);
@ -2931,8 +2945,8 @@ class MessagesManager : public Actor {
std::unordered_map<int64, std::pair<int32, vector<MessageId>>> std::unordered_map<int64, std::pair<int32, vector<MessageId>>>
found_dialog_recent_location_messages_; // random_id -> [total_count, [message_id]...] found_dialog_recent_location_messages_; // random_id -> [total_count, [message_id]...]
std::unordered_map<int64, std::pair<string, vector<FullMessageId>>> std::unordered_map<int64, FoundMessages> found_fts_messages_; // random_id -> FoundMessages
found_fts_messages_; // random_id -> [next_offset, [full_message_id]...] std::unordered_map<int64, FoundMessages> found_message_public_forwards_; // random_id -> FoundMessages
std::unordered_map<FullMessageId, std::pair<string, string>, FullMessageIdHash> public_message_links_[2]; std::unordered_map<FullMessageId, std::pair<string, string>, FullMessageIdHash> public_message_links_[2];

View File

@ -1473,21 +1473,15 @@ class SearchSecretMessagesRequest : public RequestActor<> {
tl_object_ptr<td_api::SearchMessagesFilter> filter_; tl_object_ptr<td_api::SearchMessagesFilter> filter_;
int64 random_id_; int64 random_id_;
std::pair<string, vector<FullMessageId>> messages_; MessagesManager::FoundMessages found_messages_;
void do_run(Promise<Unit> &&promise) override { void do_run(Promise<Unit> &&promise) override {
messages_ = td->messages_manager_->offline_search_messages(dialog_id_, query_, offset_, limit_, filter_, random_id_, found_messages_ = td->messages_manager_->offline_search_messages(dialog_id_, query_, offset_, limit_, filter_,
std::move(promise)); random_id_, std::move(promise));
} }
void do_send_result() override { void do_send_result() override {
vector<tl_object_ptr<td_api::message>> result; send_result(td->messages_manager_->get_found_messages_object(found_messages_));
result.reserve(messages_.second.size());
for (auto full_message_id : messages_.second) {
result.push_back(td->messages_manager_->get_message_object(full_message_id));
}
send_result(make_tl_object<td_api::foundMessages>(std::move(result), std::move(messages_.first)));
} }
public: public:
@ -1685,6 +1679,34 @@ class GetChatScheduledMessagesRequest : public RequestActor<> {
} }
}; };
class GetMessagePublicForwardsRequest : public RequestActor<> {
FullMessageId full_message_id_;
string offset_;
int32 limit_;
int64 random_id_;
MessagesManager::FoundMessages messages_;
void do_run(Promise<Unit> &&promise) override {
messages_ = td->messages_manager_->get_message_public_forwards(full_message_id_, offset_, limit_, random_id_,
std::move(promise));
}
void do_send_result() override {
send_result(td->messages_manager_->get_found_messages_object(messages_));
}
public:
GetMessagePublicForwardsRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id,
string offset, int32 limit)
: RequestActor(std::move(td), request_id)
, full_message_id_(DialogId(dialog_id), MessageId(message_id))
, offset_(std::move(offset))
, limit_(limit)
, random_id_(0) {
}
};
class GetWebPagePreviewRequest : public RequestOnceActor { class GetWebPagePreviewRequest : public RequestOnceActor {
td_api::object_ptr<td_api::formattedText> text_; td_api::object_ptr<td_api::formattedText> text_;
@ -1875,10 +1897,6 @@ class GetChatMemberRequest : public RequestActor<> {
send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_)); send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_));
} }
void do_send_error(Status &&status) override {
send_error(std::move(status));
}
public: public:
GetChatMemberRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int32 user_id) GetChatMemberRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int32 user_id)
: RequestActor(std::move(td), request_id), dialog_id_(dialog_id), user_id_(user_id), random_id_(0) { : RequestActor(std::move(td), request_id), dialog_id_(dialog_id), user_id_(user_id), random_id_(0) {
@ -5463,6 +5481,7 @@ void Td::on_request(uint64 id, td_api::searchChatMessages &request) {
void Td::on_request(uint64 id, td_api::searchSecretMessages &request) { void Td::on_request(uint64 id, td_api::searchSecretMessages &request) {
CHECK_IS_USER(); CHECK_IS_USER();
CLEAN_INPUT_STRING(request.query_); CLEAN_INPUT_STRING(request.query_);
CLEAN_INPUT_STRING(request.offset_);
CREATE_REQUEST(SearchSecretMessagesRequest, request.chat_id_, std::move(request.query_), std::move(request.offset_), CREATE_REQUEST(SearchSecretMessagesRequest, request.chat_id_, std::move(request.query_), std::move(request.offset_),
request.limit_, std::move(request.filter_)); request.limit_, std::move(request.filter_));
} }
@ -5508,6 +5527,13 @@ void Td::on_request(uint64 id, const td_api::getChatScheduledMessages &request)
CREATE_REQUEST(GetChatScheduledMessagesRequest, request.chat_id_); CREATE_REQUEST(GetChatScheduledMessagesRequest, request.chat_id_);
} }
void Td::on_request(uint64 id, td_api::getMessagePublicForwards &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.offset_);
CREATE_REQUEST(GetMessagePublicForwardsRequest, request.chat_id_, request.message_id_, request.offset_,
request.limit_);
}
void Td::on_request(uint64 id, const td_api::removeNotification &request) { void Td::on_request(uint64 id, const td_api::removeNotification &request) {
CHECK_IS_USER(); CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();

View File

@ -585,6 +585,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::getChatScheduledMessages &request); void on_request(uint64 id, const td_api::getChatScheduledMessages &request);
void on_request(uint64 id, td_api::getMessagePublicForwards &request);
void on_request(uint64 id, const td_api::removeNotification &request); void on_request(uint64 id, const td_api::removeNotification &request);
void on_request(uint64 id, const td_api::removeNotificationGroup &request); void on_request(uint64 id, const td_api::removeNotificationGroup &request);

View File

@ -1843,6 +1843,18 @@ class CliClient final : public Actor {
} else if (op == "gcsm") { } else if (op == "gcsm") {
string chat_id = args; string chat_id = args;
send_request(td_api::make_object<td_api::getChatScheduledMessages>(as_chat_id(chat_id))); send_request(td_api::make_object<td_api::getChatScheduledMessages>(as_chat_id(chat_id)));
} else if (op == "gmpf") {
string chat_id;
string message_id;
string offset;
string limit;
std::tie(chat_id, args) = split(args);
std::tie(message_id, args) = split(args);
std::tie(offset, limit) = split(args);
send_request(td_api::make_object<td_api::getMessagePublicForwards>(as_chat_id(chat_id), as_message_id(message_id),
offset, to_integer<int32>(limit)));
} else if (op == "ghf") { } else if (op == "ghf") {
get_history_chat_id_ = as_chat_id(args); get_history_chat_id_ = as_chat_id(args);