mirror of
https://github.com/tdlight-team/tdlight-telegram-bot-api.git
synced 2024-11-27 06:26:50 +01:00
Fix conflict
This commit is contained in:
commit
d6a99d8519
@ -92,7 +92,7 @@ PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false # true
|
||||
SortIncludes: false # disabled, because we need case insensitive sort
|
||||
SortUsingDeclarations: false # true
|
||||
|
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||
|
||||
project(TelegramBotApi VERSION 5.0.1 LANGUAGES CXX)
|
||||
project(TelegramBotApi VERSION 5.1 LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(td EXCLUDE_FROM_ALL)
|
||||
|
||||
|
2
td
2
td
@ -1 +1 @@
|
||||
Subproject commit ec5614fd43c56ba4d6dd7e6a517bc55116ab45cd
|
||||
Subproject commit 1ea79d273976c22655742d4031ebbe62dba6cd7c
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include "td/db/TQueue.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/base64.h"
|
||||
#include "td/utils/filesystem.h"
|
||||
#include "td/utils/HttpUrl.h"
|
||||
@ -20,7 +21,6 @@
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/PathView.h"
|
||||
#include "td/utils/port/Clocks.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/port/Stat.h"
|
||||
#include "td/utils/Random.h"
|
||||
@ -145,6 +145,9 @@ void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, Sli
|
||||
break;
|
||||
case 500:
|
||||
prefix = Slice("Internal Server Error");
|
||||
if (real_error_message != Slice("Request aborted")) {
|
||||
LOG(ERROR) << "Receive Internal Server Error: " << real_error_message;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unsupported error " << real_error_code << ": " << real_error_message;
|
||||
@ -232,6 +235,9 @@ bool Client::init_methods() {
|
||||
methods_.emplace("answershippingquery", &Client::process_answer_shipping_query_query);
|
||||
methods_.emplace("answerprecheckoutquery", &Client::process_answer_pre_checkout_query_query);
|
||||
methods_.emplace("exportchatinvitelink", &Client::process_export_chat_invite_link_query);
|
||||
methods_.emplace("createchatinvitelink", &Client::process_create_chat_invite_link_query);
|
||||
methods_.emplace("editchatinvitelink", &Client::process_edit_chat_invite_link_query);
|
||||
methods_.emplace("revokechatinvitelink", &Client::process_revoke_chat_invite_link_query);
|
||||
methods_.emplace("getchat", &Client::process_get_chat_query);
|
||||
methods_.emplace("setchatphoto", &Client::process_set_chat_photo_query);
|
||||
methods_.emplace("deletechatphoto", &Client::process_delete_chat_photo_query);
|
||||
@ -586,6 +592,30 @@ class Client::JsonChatLocation : public Jsonable {
|
||||
const td_api::chatLocation *chat_location_;
|
||||
};
|
||||
|
||||
class Client::JsonChatInviteLink : public Jsonable {
|
||||
public:
|
||||
JsonChatInviteLink(const td_api::chatInviteLink *chat_invite_link, const Client *client)
|
||||
: chat_invite_link_(chat_invite_link), client_(client) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto object = scope->enter_object();
|
||||
object("invite_link", chat_invite_link_->invite_link_);
|
||||
object("creator", JsonUser(chat_invite_link_->creator_user_id_, client_));
|
||||
if (chat_invite_link_->expire_date_ != 0) {
|
||||
object("expire_date", chat_invite_link_->expire_date_);
|
||||
}
|
||||
if (chat_invite_link_->member_limit_ != 0) {
|
||||
object("member_limit", chat_invite_link_->member_limit_);
|
||||
}
|
||||
object("is_primary", td::JsonBool(chat_invite_link_->is_primary_));
|
||||
object("is_revoked", td::JsonBool(chat_invite_link_->is_revoked_));
|
||||
}
|
||||
|
||||
private:
|
||||
const td_api::chatInviteLink *chat_invite_link_;
|
||||
const Client *client_;
|
||||
};
|
||||
|
||||
class Client::JsonMessage : public Jsonable {
|
||||
public:
|
||||
JsonMessage(const MessageInfo *message, bool need_reply, const td::string &source, const Client *client)
|
||||
@ -752,6 +782,9 @@ class Client::JsonChat : public Jsonable {
|
||||
LOG(ERROR) << "Pinned unknown, inaccessible or deleted message " << pinned_message_id_;
|
||||
}
|
||||
}
|
||||
if (chat_info->message_auto_delete_time != 0) {
|
||||
object("message_auto_delete_time", chat_info->message_auto_delete_time);
|
||||
}
|
||||
}
|
||||
|
||||
// start custom properties impl
|
||||
@ -1462,6 +1495,62 @@ class Client::JsonProximityAlertTriggered : public Jsonable {
|
||||
const Client *client_;
|
||||
};
|
||||
|
||||
class Client::JsonVoiceChatStarted : public Jsonable {
|
||||
public:
|
||||
explicit JsonVoiceChatStarted(const td_api::messageVoiceChatStarted *voice_chat_started)
|
||||
: voice_chat_started_(voice_chat_started) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto object = scope->enter_object();
|
||||
}
|
||||
|
||||
private:
|
||||
const td_api::messageVoiceChatStarted *voice_chat_started_;
|
||||
};
|
||||
|
||||
class Client::JsonVoiceChatEnded : public Jsonable {
|
||||
public:
|
||||
explicit JsonVoiceChatEnded(const td_api::messageVoiceChatEnded *voice_chat_ended)
|
||||
: voice_chat_ended_(voice_chat_ended) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto object = scope->enter_object();
|
||||
object("duration", voice_chat_ended_->duration_);
|
||||
}
|
||||
|
||||
private:
|
||||
const td_api::messageVoiceChatEnded *voice_chat_ended_;
|
||||
};
|
||||
|
||||
class Client::JsonInviteVoiceChatParticipants : public Jsonable {
|
||||
public:
|
||||
JsonInviteVoiceChatParticipants(const td_api::messageInviteVoiceChatParticipants *invite_voice_chat_participants,
|
||||
const Client *client)
|
||||
: invite_voice_chat_participants_(invite_voice_chat_participants), client_(client) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto object = scope->enter_object();
|
||||
object("users", JsonUsers(invite_voice_chat_participants_->user_ids_, client_));
|
||||
}
|
||||
|
||||
private:
|
||||
const td_api::messageInviteVoiceChatParticipants *invite_voice_chat_participants_;
|
||||
const Client *client_;
|
||||
};
|
||||
|
||||
class Client::JsonChatSetTtl : public Jsonable {
|
||||
public:
|
||||
explicit JsonChatSetTtl(const td_api::messageChatSetTtl *chat_set_ttl) : chat_set_ttl_(chat_set_ttl) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto object = scope->enter_object();
|
||||
object("message_auto_delete_time", chat_set_ttl_->ttl_);
|
||||
}
|
||||
|
||||
private:
|
||||
const td_api::messageChatSetTtl *chat_set_ttl_;
|
||||
};
|
||||
|
||||
class Client::JsonCallbackGame : public Jsonable {
|
||||
public:
|
||||
void store(JsonValueScope *scope) const {
|
||||
@ -1821,8 +1910,11 @@ void Client::JsonMessage::store(JsonValueScope *scope) const {
|
||||
break;
|
||||
case td_api::messageScreenshotTaken::ID:
|
||||
break;
|
||||
case td_api::messageChatSetTtl::ID:
|
||||
case td_api::messageChatSetTtl::ID: {
|
||||
auto content = static_cast<const td_api::messageChatSetTtl *>(message_->content.get());
|
||||
object("message_auto_delete_timer_changed", JsonChatSetTtl(content));
|
||||
break;
|
||||
}
|
||||
case td_api::messageUnsupported::ID:
|
||||
break;
|
||||
case td_api::messageContactRegistered::ID:
|
||||
@ -1858,6 +1950,21 @@ void Client::JsonMessage::store(JsonValueScope *scope) const {
|
||||
object("proximity_alert_triggered", JsonProximityAlertTriggered(content, client_));
|
||||
break;
|
||||
}
|
||||
case td_api::messageVoiceChatStarted::ID: {
|
||||
auto content = static_cast<const td_api::messageVoiceChatStarted *>(message_->content.get());
|
||||
object("voice_chat_started", JsonVoiceChatStarted(content));
|
||||
break;
|
||||
}
|
||||
case td_api::messageVoiceChatEnded::ID: {
|
||||
auto content = static_cast<const td_api::messageVoiceChatEnded *>(message_->content.get());
|
||||
object("voice_chat_ended", JsonVoiceChatEnded(content));
|
||||
break;
|
||||
}
|
||||
case td_api::messageInviteVoiceChatParticipants::ID: {
|
||||
auto content = static_cast<const td_api::messageInviteVoiceChatParticipants *>(message_->content.get());
|
||||
object("voice_chat_participants_invited", JsonInviteVoiceChatParticipants(content, client_));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -1903,10 +2010,12 @@ class Client::JsonMessageId : public Jsonable {
|
||||
class Client::JsonInlineQuery : public Jsonable {
|
||||
public:
|
||||
JsonInlineQuery(int64 inline_query_id, int32 sender_user_id, const td_api::location *user_location,
|
||||
const td::string &query, const td::string &offset, const Client *client)
|
||||
const td_api::ChatType *chat_type, const td::string &query, const td::string &offset,
|
||||
const Client *client)
|
||||
: inline_query_id_(inline_query_id)
|
||||
, sender_user_id_(sender_user_id)
|
||||
, user_location_(user_location)
|
||||
, chat_type_(chat_type)
|
||||
, query_(query)
|
||||
, offset_(offset)
|
||||
, client_(client) {
|
||||
@ -1919,6 +2028,35 @@ class Client::JsonInlineQuery : public Jsonable {
|
||||
if (user_location_ != nullptr) {
|
||||
object("location", JsonLocation(user_location_));
|
||||
}
|
||||
if (chat_type_ != nullptr) {
|
||||
auto chat_type = [&] {
|
||||
switch (chat_type_->get_id()) {
|
||||
case td_api::chatTypePrivate::ID: {
|
||||
auto type = static_cast<const td_api::chatTypePrivate *>(chat_type_);
|
||||
if (type->user_id_ == sender_user_id_) {
|
||||
return "sender";
|
||||
}
|
||||
return "private";
|
||||
}
|
||||
case td_api::chatTypeBasicGroup::ID:
|
||||
return "group";
|
||||
case td_api::chatTypeSupergroup::ID: {
|
||||
auto type = static_cast<const td_api::chatTypeSupergroup *>(chat_type_);
|
||||
if (type->is_channel_) {
|
||||
return "channel";
|
||||
} else {
|
||||
return "supergroup";
|
||||
}
|
||||
}
|
||||
case td_api::chatTypeSecret::ID:
|
||||
return "";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return "";
|
||||
}
|
||||
}();
|
||||
object("chat_type", chat_type);
|
||||
}
|
||||
object("query", query_);
|
||||
object("offset", offset_);
|
||||
}
|
||||
@ -1927,6 +2065,7 @@ class Client::JsonInlineQuery : public Jsonable {
|
||||
int64 inline_query_id_;
|
||||
int32 sender_user_id_;
|
||||
const td_api::location *user_location_;
|
||||
const td_api::ChatType *chat_type_;
|
||||
const td::string &query_;
|
||||
const td::string &offset_;
|
||||
const Client *client_;
|
||||
@ -2166,6 +2305,7 @@ class Client::JsonChatMember : public Jsonable {
|
||||
case td_api::chatMemberStatusAdministrator::ID: {
|
||||
auto administrator = static_cast<const td_api::chatMemberStatusAdministrator *>(member_->status_.get());
|
||||
object("can_be_edited", td::JsonBool(administrator->can_be_edited_));
|
||||
object("can_manage_chat", td::JsonBool(administrator->can_manage_chat_));
|
||||
object("can_change_info", td::JsonBool(administrator->can_change_info_));
|
||||
if (chat_type_ == Client::ChatType::Channel) {
|
||||
object("can_post_messages", td::JsonBool(administrator->can_post_messages_));
|
||||
@ -2178,6 +2318,7 @@ class Client::JsonChatMember : public Jsonable {
|
||||
object("can_pin_messages", td::JsonBool(administrator->can_pin_messages_));
|
||||
}
|
||||
object("can_promote_members", td::JsonBool(administrator->can_promote_members_));
|
||||
object("can_manage_voice_chats", td::JsonBool(administrator->can_manage_voice_chats_));
|
||||
if (!administrator->custom_title_.empty()) {
|
||||
object("custom_title", administrator->custom_title_);
|
||||
}
|
||||
@ -2252,6 +2393,29 @@ class Client::JsonChatMembers : public Jsonable {
|
||||
const Client *client_;
|
||||
};
|
||||
|
||||
class Client::JsonChatMemberUpdated : public Jsonable {
|
||||
public:
|
||||
JsonChatMemberUpdated(const td_api::updateChatMember *update, const Client *client)
|
||||
: update_(update), client_(client) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto object = scope->enter_object();
|
||||
object("chat", JsonChat(update_->chat_id_, false, client_));
|
||||
object("from", JsonUser(update_->actor_user_id_, client_));
|
||||
object("date", update_->date_);
|
||||
auto chat_type = client_->get_chat_type(update_->chat_id_);
|
||||
object("old_chat_member", JsonChatMember(update_->old_chat_member_.get(), chat_type, client_));
|
||||
object("new_chat_member", JsonChatMember(update_->new_chat_member_.get(), chat_type, client_));
|
||||
if (update_->invite_link_ != nullptr) {
|
||||
object("invite_link", JsonChatInviteLink(update_->invite_link_.get(), client_));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const td_api::updateChatMember *update_;
|
||||
const Client *client_;
|
||||
};
|
||||
|
||||
class Client::JsonGameHighScore : public Jsonable {
|
||||
public:
|
||||
JsonGameHighScore(const td_api::gameHighScore *score, const Client *client) : score_(score), client_(client) {
|
||||
@ -2507,7 +2671,7 @@ class Client::TdOnAuthorizationCallback : public TdQueryCallback {
|
||||
}
|
||||
|
||||
LOG(WARNING) << "Logging out due to " << td::oneline(to_string(error));
|
||||
client_->log_out();
|
||||
client_->log_out(error->message_ == "API_ID_INVALID");
|
||||
} else if (was_ready) {
|
||||
client_->on_update_authorization_state();
|
||||
}
|
||||
@ -3375,9 +3539,9 @@ class Client::TdOnGetSupergroupMembersCountCallback : public TdQueryCallback {
|
||||
PromisedQueryPtr query_;
|
||||
};
|
||||
|
||||
class Client::TdOnGenerateChatInviteLinkCallback : public TdQueryCallback {
|
||||
class Client::TdOnReplacePrimaryChatInviteLinkCallback : public TdQueryCallback {
|
||||
public:
|
||||
explicit TdOnGenerateChatInviteLinkCallback(PromisedQueryPtr query) : query_(std::move(query)) {
|
||||
explicit TdOnReplacePrimaryChatInviteLinkCallback(PromisedQueryPtr query) : query_(std::move(query)) {
|
||||
}
|
||||
|
||||
void on_result(object_ptr<td_api::Object> result) override {
|
||||
@ -3394,6 +3558,33 @@ class Client::TdOnGenerateChatInviteLinkCallback : public TdQueryCallback {
|
||||
PromisedQueryPtr query_;
|
||||
};
|
||||
|
||||
class Client::TdOnGetChatInviteLinkCallback : public TdQueryCallback {
|
||||
public:
|
||||
TdOnGetChatInviteLinkCallback(const Client *client, PromisedQueryPtr query)
|
||||
: client_(client), query_(std::move(query)) {
|
||||
}
|
||||
|
||||
void on_result(object_ptr<td_api::Object> result) override {
|
||||
if (result->get_id() == td_api::error::ID) {
|
||||
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result));
|
||||
}
|
||||
|
||||
if (result->get_id() == td_api::chatInviteLink::ID) {
|
||||
auto invite_link = move_object_as<td_api::chatInviteLink>(result);
|
||||
return answer_query(JsonChatInviteLink(invite_link.get(), client_), std::move(query_));
|
||||
} else {
|
||||
CHECK(result->get_id() == td_api::chatInviteLinks::ID);
|
||||
auto invite_links = move_object_as<td_api::chatInviteLinks>(result);
|
||||
CHECK(!invite_links->invite_links_.empty());
|
||||
return answer_query(JsonChatInviteLink(invite_links->invite_links_[0].get(), client_), std::move(query_));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Client *client_;
|
||||
PromisedQueryPtr query_;
|
||||
};
|
||||
|
||||
class Client::TdOnGetGameHighScoresCallback : public TdQueryCallback {
|
||||
public:
|
||||
TdOnGetGameHighScoresCallback(const Client *client, PromisedQueryPtr query)
|
||||
@ -3658,7 +3849,8 @@ void Client::close() {
|
||||
}
|
||||
}
|
||||
|
||||
void Client::log_out() {
|
||||
void Client::log_out(bool is_api_id_invalid) {
|
||||
is_api_id_invalid_ |= is_api_id_invalid;
|
||||
if (!td_client_.empty() && !logging_out_ && !closing_) {
|
||||
do_send_request(make_object<td_api::logOut>(), std::make_unique<TdOnOkCallback>());
|
||||
}
|
||||
@ -3704,7 +3896,7 @@ void Client::start_up() {
|
||||
next_set_webhook_logging_time_ = start_time_;
|
||||
next_webhook_is_not_modified_warning_time_ = start_time_;
|
||||
previous_get_updates_start_time_ = start_time_ - 100;
|
||||
previous_get_updates_finish_time_ = start_time_ - 100;
|
||||
next_get_updates_conflict_time_ = start_time_ - 100;
|
||||
|
||||
sticker_set_names_[GREAT_MINDS_SET_ID] = GREAT_MINDS_SET_NAME.str();
|
||||
|
||||
@ -4069,11 +4261,16 @@ void Client::check_message(Slice chat_id_str, int64 message_id, bool allow_empty
|
||||
check_chat(chat_id_str, access_rights, std::move(query),
|
||||
[this, message_id, allow_empty, message_type, on_success = std::move(on_success)](
|
||||
int64 chat_id, PromisedQueryPtr query) mutable {
|
||||
if (!have_message_access(chat_id)) {
|
||||
if ((message_id <= 0 && !allow_empty) || !have_message_access(chat_id)) {
|
||||
return fail_query_with_error(std::move(query), 400, "MESSAGE_NOT_FOUND",
|
||||
PSLICE() << message_type << " not found");
|
||||
}
|
||||
|
||||
if (message_id <= 0) {
|
||||
CHECK(allow_empty);
|
||||
return on_success(chat_id, 0, std::move(query));
|
||||
}
|
||||
|
||||
send_request(make_object<td_api::getMessage>(chat_id, message_id),
|
||||
std::make_unique<TdOnCheckMessageCallback<OnSuccess>>(
|
||||
this, chat_id, allow_empty, message_type, std::move(query), std::move(on_success)));
|
||||
@ -4227,7 +4424,8 @@ void Client::get_chat_member(int64 chat_id, int32 user_id, PromisedQueryPtr quer
|
||||
|
||||
void Client::send_request(object_ptr<td_api::Function> &&f, std::unique_ptr<TdQueryCallback> handler) {
|
||||
if (logging_out_) {
|
||||
return handler->on_result(make_object<td_api::error>(LOGGING_OUT_ERROR_CODE, LOGGING_OUT_ERROR_DESCRIPTION.str()));
|
||||
return handler->on_result(
|
||||
make_object<td_api::error>(LOGGING_OUT_ERROR_CODE, get_logging_out_error_description().str()));
|
||||
}
|
||||
if (closing_) {
|
||||
return handler->on_result(make_object<td_api::error>(CLOSING_ERROR_CODE, CLOSING_ERROR_DESCRIPTION.str()));
|
||||
@ -4265,7 +4463,7 @@ void Client::on_update_file(object_ptr<td_api::file> file) {
|
||||
// also includes all 5xx and 429 errors
|
||||
auto error = Status::Error(400, "Bad Request: wrong file_id or the file is temporarily unavailable");
|
||||
if (logging_out_) {
|
||||
error = Status::Error(LOGGING_OUT_ERROR_CODE, LOGGING_OUT_ERROR_DESCRIPTION);
|
||||
error = Status::Error(LOGGING_OUT_ERROR_CODE, get_logging_out_error_description());
|
||||
}
|
||||
if (closing_) {
|
||||
error = Status::Error(CLOSING_ERROR_CODE, CLOSING_ERROR_DESCRIPTION);
|
||||
@ -4333,7 +4531,7 @@ void Client::on_update_authorization_state() {
|
||||
parameters->api_hash_ = parameters_->api_hash_;
|
||||
parameters->system_language_code_ = "en";
|
||||
parameters->device_model_ = "server";
|
||||
parameters->application_version_ = "5.0.1";
|
||||
parameters->application_version_ = "5.1";
|
||||
parameters->enable_storage_optimizer_ = true;
|
||||
parameters->ignore_file_names_ = true;
|
||||
|
||||
@ -4393,7 +4591,7 @@ void Client::on_update_authorization_state() {
|
||||
case td_api::authorizationStateClosed::ID:
|
||||
return on_closed();
|
||||
default:
|
||||
return log_out(); // just in case
|
||||
return log_out(false); // just in case
|
||||
}
|
||||
}
|
||||
|
||||
@ -4490,33 +4688,32 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
bool need_warning = false;
|
||||
switch (chat->type_->get_id()) {
|
||||
case td_api::chatTypePrivate::ID: {
|
||||
auto info = move_object_as<td_api::chatTypePrivate>(chat->type_);
|
||||
auto type = move_object_as<td_api::chatTypePrivate>(chat->type_);
|
||||
chat_info->type = ChatInfo::Type::Private;
|
||||
auto user_id = info->user_id_;
|
||||
auto user_id = type->user_id_;
|
||||
chat_info->user_id = user_id;
|
||||
need_warning = get_user_info(user_id) == nullptr;
|
||||
break;
|
||||
}
|
||||
case td_api::chatTypeBasicGroup::ID: {
|
||||
auto info = move_object_as<td_api::chatTypeBasicGroup>(chat->type_);
|
||||
auto type = move_object_as<td_api::chatTypeBasicGroup>(chat->type_);
|
||||
chat_info->type = ChatInfo::Type::Group;
|
||||
auto group_id = info->basic_group_id_;
|
||||
auto group_id = type->basic_group_id_;
|
||||
chat_info->group_id = group_id;
|
||||
need_warning = get_group_info(group_id) == nullptr;
|
||||
break;
|
||||
}
|
||||
case td_api::chatTypeSupergroup::ID: {
|
||||
auto info = move_object_as<td_api::chatTypeSupergroup>(chat->type_);
|
||||
auto type = move_object_as<td_api::chatTypeSupergroup>(chat->type_);
|
||||
chat_info->type = ChatInfo::Type::Supergroup;
|
||||
auto supergroup_id = info->supergroup_id_;
|
||||
auto supergroup_id = type->supergroup_id_;
|
||||
chat_info->supergroup_id = supergroup_id;
|
||||
need_warning = get_supergroup_info(supergroup_id) == nullptr;
|
||||
break;
|
||||
}
|
||||
case td_api::chatTypeSecret::ID: {
|
||||
case td_api::chatTypeSecret::ID:
|
||||
// unsupported
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -4527,6 +4724,7 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
chat_info->title = std::move(chat->title_);
|
||||
chat_info->photo = std::move(chat->photo_);
|
||||
chat_info->permissions = std::move(chat->permissions_);
|
||||
chat_info->message_auto_delete_time = chat->message_ttl_setting_;
|
||||
break;
|
||||
}
|
||||
case td_api::updateChatTitle::ID: {
|
||||
@ -4550,6 +4748,13 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
chat_info->permissions = std::move(update->permissions_);
|
||||
break;
|
||||
}
|
||||
case td_api::updateChatMessageTtlSetting::ID: {
|
||||
auto update = move_object_as<td_api::updateChatMessageTtlSetting>(result);
|
||||
auto chat_info = add_chat(update->chat_id_);
|
||||
CHECK(chat_info->type != ChatInfo::Type::Unknown);
|
||||
chat_info->message_auto_delete_time = update->message_ttl_setting_;
|
||||
break;
|
||||
}
|
||||
case td_api::updateUser::ID: {
|
||||
auto update = move_object_as<td_api::updateUser>(result);
|
||||
add_user(users_, std::move(update->user_));
|
||||
@ -4569,8 +4774,11 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
case td_api::updateBasicGroupFullInfo::ID: {
|
||||
auto update = move_object_as<td_api::updateBasicGroupFullInfo>(result);
|
||||
auto group_id = update->basic_group_id_;
|
||||
set_group_description(group_id, std::move(update->basic_group_full_info_->description_));
|
||||
set_group_invite_link(group_id, std::move(update->basic_group_full_info_->invite_link_));
|
||||
auto full_info = std::move(update->basic_group_full_info_);
|
||||
set_group_description(group_id, std::move(full_info->description_));
|
||||
set_group_invite_link(group_id, full_info->invite_link_ != nullptr
|
||||
? std::move(full_info->invite_link_->invite_link_)
|
||||
: td::string());
|
||||
break;
|
||||
}
|
||||
case td_api::updateSupergroup::ID: {
|
||||
@ -4581,18 +4789,21 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
case td_api::updateSupergroupFullInfo::ID: {
|
||||
auto update = move_object_as<td_api::updateSupergroupFullInfo>(result);
|
||||
auto supergroup_id = update->supergroup_id_;
|
||||
set_supergroup_description(supergroup_id, std::move(update->supergroup_full_info_->description_));
|
||||
set_supergroup_invite_link(supergroup_id, std::move(update->supergroup_full_info_->invite_link_));
|
||||
set_supergroup_sticker_set_id(supergroup_id, update->supergroup_full_info_->sticker_set_id_);
|
||||
set_supergroup_can_set_sticker_set(supergroup_id, update->supergroup_full_info_->can_set_sticker_set_);
|
||||
set_supergroup_slow_mode_delay(supergroup_id, update->supergroup_full_info_->slow_mode_delay_);
|
||||
set_supergroup_linked_chat_id(supergroup_id, update->supergroup_full_info_->linked_chat_id_);
|
||||
set_supergroup_location(supergroup_id, std::move(update->supergroup_full_info_->location_));
|
||||
auto full_info = std::move(update->supergroup_full_info_);
|
||||
set_supergroup_description(supergroup_id, std::move(full_info->description_));
|
||||
set_supergroup_invite_link(supergroup_id, full_info->invite_link_ != nullptr
|
||||
? std::move(full_info->invite_link_->invite_link_)
|
||||
: td::string());
|
||||
set_supergroup_sticker_set_id(supergroup_id, full_info->sticker_set_id_);
|
||||
set_supergroup_can_set_sticker_set(supergroup_id, full_info->can_set_sticker_set_);
|
||||
set_supergroup_slow_mode_delay(supergroup_id, full_info->slow_mode_delay_);
|
||||
set_supergroup_linked_chat_id(supergroup_id, full_info->linked_chat_id_);
|
||||
set_supergroup_location(supergroup_id, std::move(full_info->location_));
|
||||
break;
|
||||
}
|
||||
case td_api::updateOption::ID: {
|
||||
auto update = move_object_as<td_api::updateOption>(result);
|
||||
auto name = update->name_;
|
||||
const td::string &name = update->name_;
|
||||
if (name == "my_id") {
|
||||
if (update->value_->get_id() == td_api::optionValueEmpty::ID) {
|
||||
CHECK(logging_out_);
|
||||
@ -4646,8 +4857,8 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
break;
|
||||
case td_api::updateNewInlineQuery::ID: {
|
||||
auto update = move_object_as<td_api::updateNewInlineQuery>(result);
|
||||
add_new_inline_query(update->id_, update->sender_user_id_, std::move(update->user_location_), update->query_,
|
||||
update->offset_);
|
||||
add_new_inline_query(update->id_, update->sender_user_id_, std::move(update->user_location_),
|
||||
std::move(update->chat_type_), update->query_, update->offset_);
|
||||
break;
|
||||
}
|
||||
case td_api::updateNewChosenInlineResult::ID: {
|
||||
@ -4674,6 +4885,9 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
case td_api::updateNewCustomQuery::ID:
|
||||
add_new_custom_query(move_object_as<td_api::updateNewCustomQuery>(result));
|
||||
break;
|
||||
case td_api::updateChatMember::ID:
|
||||
add_update_chat_member(move_object_as<td_api::updateChatMember>(result));
|
||||
break;
|
||||
default:
|
||||
// we are not interested in this updates
|
||||
break;
|
||||
@ -4693,6 +4907,10 @@ void Client::on_result(td::uint64 id, object_ptr<td_api::Object> result) {
|
||||
handlers_.erase(id);
|
||||
}
|
||||
|
||||
td::Slice Client::get_logging_out_error_description() const {
|
||||
return is_api_id_invalid_ ? API_ID_INVALID_ERROR_DESCRIPTION : LOGGING_OUT_ERROR_DESCRIPTION;
|
||||
}
|
||||
|
||||
void Client::on_closed() {
|
||||
LOG(WARNING) << "Closed";
|
||||
CHECK(logging_out_ || closing_);
|
||||
@ -4700,7 +4918,7 @@ void Client::on_closed() {
|
||||
td_client_.reset();
|
||||
|
||||
int http_status_code = logging_out_ ? LOGGING_OUT_ERROR_CODE : CLOSING_ERROR_CODE;
|
||||
Slice description = logging_out_ ? LOGGING_OUT_ERROR_DESCRIPTION : CLOSING_ERROR_DESCRIPTION;
|
||||
Slice description = logging_out_ ? get_logging_out_error_description() : CLOSING_ERROR_DESCRIPTION;
|
||||
if (webhook_set_query_) {
|
||||
fail_query(http_status_code, description, std::move(webhook_set_query_));
|
||||
}
|
||||
@ -5568,7 +5786,7 @@ td::Result<td_api::object_ptr<td_api::InputInlineQueryResult>> Client::get_inlin
|
||||
TRY_RESULT(sticker_file_id, get_json_object_string_field(object, "sticker_file_id", false));
|
||||
|
||||
if (input_message_content == nullptr) {
|
||||
input_message_content = make_object<td_api::inputMessageSticker>(nullptr, nullptr, 0, 0);
|
||||
input_message_content = make_object<td_api::inputMessageSticker>(nullptr, nullptr, 0, 0, td::string());
|
||||
}
|
||||
return make_object<td_api::inputInlineQueryResultSticker>(id, "", sticker_file_id, 0, 0, std::move(reply_markup),
|
||||
std::move(input_message_content));
|
||||
@ -5910,16 +6128,23 @@ td::Result<td::vector<td_api::object_ptr<td_api::inputPassportElementError>>> Cl
|
||||
return std::move(errors);
|
||||
}
|
||||
|
||||
td::Result<td_api::object_ptr<td_api::formattedText>> Client::get_caption(const Query *query) {
|
||||
JsonValue entities;
|
||||
auto r_value = json_decode(query->arg("caption_entities"));
|
||||
if (r_value.is_ok()) {
|
||||
entities = r_value.move_as_ok();
|
||||
} else {
|
||||
LOG(INFO) << "Can't parse JSON object: " << r_value.error();
|
||||
JsonValue Client::get_input_entities(const Query *query, Slice field_name) {
|
||||
auto entities = query->arg(field_name);
|
||||
if (!entities.empty()) {
|
||||
auto r_value = json_decode(entities);
|
||||
if (r_value.is_ok()) {
|
||||
return r_value.move_as_ok();
|
||||
}
|
||||
|
||||
LOG(INFO) << "Can't parse entities JSON object: " << r_value.error();
|
||||
}
|
||||
|
||||
return get_formatted_text(query->arg("caption").str(), query->arg("parse_mode").str(), std::move(entities));
|
||||
return JsonValue();
|
||||
}
|
||||
|
||||
td::Result<td_api::object_ptr<td_api::formattedText>> Client::get_caption(const Query *query) {
|
||||
return get_formatted_text(query->arg("caption").str(), query->arg("parse_mode").str(),
|
||||
get_input_entities(query, "caption_entities"));
|
||||
}
|
||||
|
||||
td::Result<td_api::object_ptr<td_api::TextEntityType>> Client::get_text_entity_type(td::JsonObject &object) {
|
||||
@ -6028,16 +6253,8 @@ td::Result<td_api::object_ptr<td_api::formattedText>> Client::get_formatted_text
|
||||
}
|
||||
|
||||
td::Result<td_api::object_ptr<td_api::inputMessageText>> Client::get_input_message_text(const Query *query) {
|
||||
JsonValue entities;
|
||||
auto r_value = json_decode(query->arg("entities"));
|
||||
if (r_value.is_ok()) {
|
||||
entities = r_value.move_as_ok();
|
||||
} else {
|
||||
LOG(INFO) << "Can't parse JSON object: " << r_value.error();
|
||||
}
|
||||
|
||||
return get_input_message_text(query->arg("text").str(), to_bool(query->arg("disable_web_page_preview")),
|
||||
query->arg("parse_mode").str(), std::move(entities));
|
||||
query->arg("parse_mode").str(), get_input_entities(query, "entities"));
|
||||
}
|
||||
|
||||
td::Result<td_api::object_ptr<td_api::inputMessageText>> Client::get_input_message_text(td::string text,
|
||||
@ -6580,10 +6797,10 @@ void Client::on_cmd(PromisedQueryPtr query) {
|
||||
}
|
||||
|
||||
if (logging_out_) {
|
||||
return fail_query(LOGGING_OUT_ERROR_CODE, LOGGING_OUT_ERROR_DESCRIPTION, std::move(query));
|
||||
return fail_query(LOGGING_OUT_ERROR_CODE, get_logging_out_error_description(), std::move(query));
|
||||
}
|
||||
if (closing_) {
|
||||
return fail_query(CLOSING_ERROR_CODE, LOGGING_OUT_ERROR_DESCRIPTION, std::move(query));
|
||||
return fail_query(CLOSING_ERROR_CODE, CLOSING_ERROR_DESCRIPTION, std::move(query));
|
||||
}
|
||||
CHECK(was_authorized_);
|
||||
|
||||
@ -6708,7 +6925,8 @@ td::Status Client::process_send_sticker_query(PromisedQueryPtr &query) {
|
||||
if (sticker == nullptr) {
|
||||
return Status::Error(400, "There is no sticker in the request");
|
||||
}
|
||||
do_send_message(make_object<td_api::inputMessageSticker>(std::move(sticker), nullptr, 0, 0), std::move(query));
|
||||
do_send_message(make_object<td_api::inputMessageSticker>(std::move(sticker), nullptr, 0, 0, td::string()),
|
||||
std::move(query));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
@ -6873,15 +7091,9 @@ td::Status Client::process_send_poll_query(PromisedQueryPtr &query) {
|
||||
object_ptr<td_api::PollType> poll_type;
|
||||
auto type = query->arg("type");
|
||||
if (type == "quiz") {
|
||||
JsonValue entities;
|
||||
auto r_value = json_decode(query->arg("explanation_entities"));
|
||||
if (r_value.is_ok()) {
|
||||
entities = r_value.move_as_ok();
|
||||
} else {
|
||||
LOG(INFO) << "Can't parse JSON object: " << r_value.error();
|
||||
}
|
||||
TRY_RESULT(explanation, get_formatted_text(query->arg("explanation").str(),
|
||||
query->arg("explanation_parse_mode").str(), std::move(entities)));
|
||||
TRY_RESULT(explanation,
|
||||
get_formatted_text(query->arg("explanation").str(), query->arg("explanation_parse_mode").str(),
|
||||
get_input_entities(query.get(), "explanation_entities")));
|
||||
|
||||
poll_type = make_object<td_api::pollTypeQuiz>(get_integer_arg(query.get(), "correct_option_id", -1),
|
||||
std::move(explanation));
|
||||
@ -6975,7 +7187,7 @@ td::Status Client::process_send_media_group_query(PromisedQueryPtr &query) {
|
||||
std::make_unique<TdOnSendMessageAlbumCallback>(this, std::move(query)));
|
||||
};
|
||||
check_message(chat_id, reply_to_message_id, reply_to_message_id <= 0 || allow_sending_without_reply,
|
||||
AccessRights::Write, "reply message", std::move(query), std::move(on_success));
|
||||
AccessRights::Write, "replied message", std::move(query), std::move(on_success));
|
||||
});
|
||||
return Status::OK();
|
||||
}
|
||||
@ -7331,12 +7543,51 @@ td::Status Client::process_export_chat_invite_link_query(PromisedQueryPtr &query
|
||||
auto chat_id = query->arg("chat_id");
|
||||
|
||||
check_chat(chat_id, AccessRights::Write, std::move(query), [this](int64 chat_id, PromisedQueryPtr query) {
|
||||
send_request(make_object<td_api::generateChatInviteLink>(chat_id),
|
||||
std::make_unique<TdOnGenerateChatInviteLinkCallback>(std::move(query)));
|
||||
send_request(make_object<td_api::replacePrimaryChatInviteLink>(chat_id),
|
||||
std::make_unique<TdOnReplacePrimaryChatInviteLinkCallback>(std::move(query)));
|
||||
});
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
td::Status Client::process_create_chat_invite_link_query(PromisedQueryPtr &query) {
|
||||
auto chat_id = query->arg("chat_id");
|
||||
auto expire_date = get_integer_arg(query.get(), "expire_date", 0, 0);
|
||||
auto member_limit = get_integer_arg(query.get(), "member_limit", 0, 0, 100000);
|
||||
|
||||
check_chat(chat_id, AccessRights::Write, std::move(query),
|
||||
[this, expire_date, member_limit](int64 chat_id, PromisedQueryPtr query) {
|
||||
send_request(make_object<td_api::createChatInviteLink>(chat_id, expire_date, member_limit),
|
||||
std::make_unique<TdOnGetChatInviteLinkCallback>(this, std::move(query)));
|
||||
});
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
td::Status Client::process_edit_chat_invite_link_query(PromisedQueryPtr &query) {
|
||||
auto chat_id = query->arg("chat_id");
|
||||
auto invite_link = query->arg("invite_link");
|
||||
auto expire_date = get_integer_arg(query.get(), "expire_date", 0, 0);
|
||||
auto member_limit = get_integer_arg(query.get(), "member_limit", 0, 0, 100000);
|
||||
|
||||
check_chat(chat_id, AccessRights::Write, std::move(query),
|
||||
[this, invite_link = invite_link.str(), expire_date, member_limit](int64 chat_id, PromisedQueryPtr query) {
|
||||
send_request(make_object<td_api::editChatInviteLink>(chat_id, invite_link, expire_date, member_limit),
|
||||
std::make_unique<TdOnGetChatInviteLinkCallback>(this, std::move(query)));
|
||||
});
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
td::Status Client::process_revoke_chat_invite_link_query(PromisedQueryPtr &query) {
|
||||
auto chat_id = query->arg("chat_id");
|
||||
auto invite_link = query->arg("invite_link");
|
||||
|
||||
check_chat(chat_id, AccessRights::Write, std::move(query),
|
||||
[this, invite_link = invite_link.str()](int64 chat_id, PromisedQueryPtr query) {
|
||||
send_request(make_object<td_api::revokeChatInviteLink>(chat_id, invite_link),
|
||||
std::make_unique<TdOnGetChatInviteLinkCallback>(this, std::move(query)));
|
||||
});
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
td::Status Client::process_get_chat_query(PromisedQueryPtr &query) {
|
||||
auto chat_id = query->arg("chat_id");
|
||||
|
||||
@ -7617,6 +7868,7 @@ td::Status Client::process_leave_chat_query(PromisedQueryPtr &query) {
|
||||
td::Status Client::process_promote_chat_member_query(PromisedQueryPtr &query) {
|
||||
auto chat_id = query->arg("chat_id");
|
||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||
auto can_manage_chat = to_bool(query->arg("can_manage_chat"));
|
||||
auto can_change_info = to_bool(query->arg("can_change_info"));
|
||||
auto can_post_messages = to_bool(query->arg("can_post_messages"));
|
||||
auto can_edit_messages = to_bool(query->arg("can_edit_messages"));
|
||||
@ -7625,10 +7877,12 @@ td::Status Client::process_promote_chat_member_query(PromisedQueryPtr &query) {
|
||||
auto can_restrict_members = to_bool(query->arg("can_restrict_members"));
|
||||
auto can_pin_messages = to_bool(query->arg("can_pin_messages"));
|
||||
auto can_promote_members = to_bool(query->arg("can_promote_members"));
|
||||
auto can_manage_voice_chats = to_bool(query->arg("can_manage_voice_chats"));
|
||||
auto is_anonymous = to_bool(query->arg("is_anonymous"));
|
||||
auto status = make_object<td_api::chatMemberStatusAdministrator>(
|
||||
td::string(), true, can_change_info, can_post_messages, can_edit_messages, can_delete_messages, can_invite_users,
|
||||
can_restrict_members, can_pin_messages, can_promote_members, is_anonymous);
|
||||
td::string(), true, can_manage_chat, can_change_info, can_post_messages, can_edit_messages, can_delete_messages,
|
||||
can_invite_users, can_restrict_members, can_pin_messages, can_promote_members, can_manage_voice_chats,
|
||||
is_anonymous);
|
||||
check_chat(chat_id, AccessRights::Write, std::move(query),
|
||||
[this, user_id, status = std::move(status)](int64 chat_id, PromisedQueryPtr query) mutable {
|
||||
auto chat_info = get_chat(chat_id);
|
||||
@ -7691,13 +7945,14 @@ td::Status Client::process_ban_chat_member_query(PromisedQueryPtr &query) {
|
||||
auto chat_id = query->arg("chat_id");
|
||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||
int32 until_date = get_integer_arg(query.get(), "until_date", 0);
|
||||
auto revoke_messages = to_bool(query->arg("revoke_messages"));
|
||||
|
||||
check_chat(chat_id, AccessRights::Write, std::move(query),
|
||||
[this, user_id, until_date](int64 chat_id, PromisedQueryPtr query) {
|
||||
[this, user_id, until_date, revoke_messages](int64 chat_id, PromisedQueryPtr query) {
|
||||
check_user_no_fail(
|
||||
user_id, std::move(query), [this, chat_id, user_id, until_date](PromisedQueryPtr query) {
|
||||
send_request(make_object<td_api::setChatMemberStatus>(
|
||||
chat_id, user_id, make_object<td_api::chatMemberStatusBanned>(until_date)),
|
||||
user_id, std::move(query),
|
||||
[this, chat_id, user_id, until_date, revoke_messages](PromisedQueryPtr query) {
|
||||
send_request(make_object<td_api::banChatMember>(chat_id, user_id, until_date, revoke_messages),
|
||||
std::make_unique<TdOnOkQueryCallback>(std::move(query)));
|
||||
});
|
||||
});
|
||||
@ -8657,7 +8912,7 @@ void Client::do_send_message(object_ptr<td_api::InputMessageContent> input_messa
|
||||
std::make_unique<TdOnSendMessageCallback>(this, std::move(query)));
|
||||
};
|
||||
check_message(chat_id, reply_to_message_id, reply_to_message_id <= 0 || allow_sending_without_reply,
|
||||
AccessRights::Write, "reply message", std::move(query), std::move(on_success));
|
||||
AccessRights::Write, "replied message", std::move(query), std::move(on_success));
|
||||
});
|
||||
}
|
||||
|
||||
@ -8704,9 +8959,9 @@ void Client::abort_long_poll(bool from_set_webhook) {
|
||||
|
||||
void Client::fail_query_conflict(Slice message, PromisedQueryPtr &&query) {
|
||||
auto now = td::Time::now_cached();
|
||||
if (now >= previous_get_updates_finish_time_) {
|
||||
if (now >= next_get_updates_conflict_time_) {
|
||||
fail_query(409, message, std::move(query));
|
||||
previous_get_updates_finish_time_ = now + 3.0;
|
||||
next_get_updates_conflict_time_ = now + 3.0;
|
||||
} else {
|
||||
td::create_actor<td::SleepActor>(
|
||||
"FailQueryConflictSleepActor", 3.0,
|
||||
@ -8798,7 +9053,8 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu
|
||||
}
|
||||
if (need_warning) {
|
||||
LOG(WARNING) << "Found " << updates.size() << " updates out of " << total_size << " + " << updates.size()
|
||||
<< " after last getUpdates call at " << previous_get_updates_finish_date_;
|
||||
<< " after last getUpdates call " << (td::Time::now() - previous_get_updates_finish_time_)
|
||||
<< " seconds ago";
|
||||
} else {
|
||||
LOG(DEBUG) << "Found " << updates.size() << " updates out of " << total_size << " from " << from;
|
||||
}
|
||||
@ -8814,7 +9070,7 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu
|
||||
long_poll_slot_.set_timeout_at(long_poll_hard_timeout_);
|
||||
return;
|
||||
}
|
||||
previous_get_updates_finish_date_ = td::Clocks::system(); // local time to output it to the log
|
||||
previous_get_updates_finish_time_ = td::Time::now();
|
||||
next_bot_updates_warning_time_ = td::Time::now() + BOT_UPDATES_WARNING_DELAY;
|
||||
if (total_size == updates.size() && was_bot_updates_warning_) {
|
||||
send_request(make_object<td_api::setBotUpdatesStatus>(0, ""), std::make_unique<TdOnOkCallback>());
|
||||
@ -8852,10 +9108,10 @@ void Client::long_poll_wakeup(bool force_flag) {
|
||||
|
||||
void Client::add_user(std::unordered_map<int32, UserInfo> &users, object_ptr<td_api::user> &&user) {
|
||||
auto user_info = &users[user->id_];
|
||||
user_info->first_name = user->first_name_;
|
||||
user_info->last_name = user->last_name_;
|
||||
user_info->username = user->username_;
|
||||
user_info->language_code = user->language_code_;
|
||||
user_info->first_name = std::move(user->first_name_);
|
||||
user_info->last_name = std::move(user->last_name_);
|
||||
user_info->username = std::move(user->username_);
|
||||
user_info->language_code = std::move(user->language_code_);
|
||||
|
||||
// start custom properties
|
||||
user_info->is_verified = user->is_verified_;
|
||||
@ -9156,6 +9412,10 @@ Client::Slice Client::get_update_type_name(UpdateType update_type) {
|
||||
return Slice("poll");
|
||||
case UpdateType::PollAnswer:
|
||||
return Slice("poll_answer");
|
||||
case UpdateType::MyChatMember:
|
||||
return Slice("my_chat_member");
|
||||
case UpdateType::ChatMember:
|
||||
return Slice("chat_member");
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Slice();
|
||||
@ -9302,9 +9562,10 @@ void Client::add_update_poll_answer(object_ptr<td_api::updatePollAnswer> &&updat
|
||||
}
|
||||
|
||||
void Client::add_new_inline_query(int64 inline_query_id, int32 sender_user_id, object_ptr<td_api::location> location,
|
||||
const td::string &query, const td::string &offset) {
|
||||
object_ptr<td_api::ChatType> chat_type, const td::string &query,
|
||||
const td::string &offset) {
|
||||
add_update(UpdateType::InlineQuery,
|
||||
JsonInlineQuery(inline_query_id, sender_user_id, location.get(), query, offset, this), 30,
|
||||
JsonInlineQuery(inline_query_id, sender_user_id, location.get(), chat_type.get(), query, offset, this), 30,
|
||||
sender_user_id + (static_cast<int64>(1) << 33));
|
||||
}
|
||||
|
||||
@ -9426,6 +9687,17 @@ void Client::add_new_custom_query(object_ptr<td_api::updateNewCustomQuery> &&que
|
||||
add_update(UpdateType::CustomQuery, JsonCustomJson(query->data_), timeout, 0);
|
||||
}
|
||||
|
||||
void Client::add_update_chat_member(object_ptr<td_api::updateChatMember> &&update) {
|
||||
CHECK(update != nullptr);
|
||||
auto left_time = update->date_ + 86400 - get_unix_time();
|
||||
if (left_time > 0) {
|
||||
bool is_my = (update->old_chat_member_->user_id_ == my_id_);
|
||||
auto webhook_queue_id = update->chat_id_ + (static_cast<int64>(is_my ? 5 : 6) << 33);
|
||||
auto update_type = is_my ? UpdateType::MyChatMember : UpdateType::ChatMember;
|
||||
add_update(update_type, JsonChatMemberUpdated(update.get(), this), left_time, webhook_queue_id);
|
||||
}
|
||||
}
|
||||
|
||||
td::int32 Client::choose_added_member_id(const td_api::messageChatAddMembers *message_add_members) const {
|
||||
CHECK(message_add_members != nullptr);
|
||||
for (auto &member_user_id : message_add_members->member_user_ids_) {
|
||||
@ -9450,6 +9722,9 @@ bool Client::need_skip_update_message(int64 chat_id, const object_ptr<td_api::me
|
||||
case td_api::messageChatDeleteMember::ID:
|
||||
case td_api::messagePinMessage::ID:
|
||||
case td_api::messageProximityAlertTriggered::ID:
|
||||
case td_api::messageVoiceChatStarted::ID:
|
||||
case td_api::messageVoiceChatEnded::ID:
|
||||
case td_api::messageInviteVoiceChatParticipants::ID:
|
||||
// don't skip
|
||||
break;
|
||||
default:
|
||||
@ -9481,9 +9756,15 @@ bool Client::need_skip_update_message(int64 chat_id, const object_ptr<td_api::me
|
||||
}
|
||||
}
|
||||
|
||||
//if (message->ttl_ > 0) {
|
||||
// return true;
|
||||
//}
|
||||
/*
|
||||
if (message->ttl_ > 0 && message->ttl_expires_in_ == 0) {
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
if (message->forward_info_ != nullptr &&
|
||||
message->forward_info_->origin_->get_id() == td_api::messageForwardOriginMessageImport::ID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (message->content_->get_id()) {
|
||||
case td_api::messagePhoto::ID: {
|
||||
@ -9829,21 +10110,23 @@ void Client::delete_message(int64 chat_id, int64 message_id, bool only_from_cach
|
||||
auto it = messages_.find({chat_id, message_id});
|
||||
if (it == messages_.end()) {
|
||||
if (yet_unsent_messages_.count({chat_id, message_id}) > 0) {
|
||||
// yet unsent message is deleted, possible only if we are trying to write to inaccessible supergroup
|
||||
// yet unsent message is deleted, possible only if we are trying to write to inaccessible supergroup or
|
||||
// sent message was deleted before added to the chat
|
||||
auto chat_info = get_chat(chat_id);
|
||||
CHECK(chat_info != nullptr);
|
||||
|
||||
Status error;
|
||||
if (chat_info->type != ChatInfo::Type::Supergroup) {
|
||||
LOG(ERROR) << "Yet unsent message " << message_id << " is deleted in the chat " << chat_id;
|
||||
error = Status::Error(403, "Forbidden: bot is not a member of the chat");
|
||||
} else {
|
||||
Status error =
|
||||
Status::Error(500, "Internal Server Error: sent message was immediately deleted and can't be returned");
|
||||
if (chat_info->type == ChatInfo::Type::Supergroup) {
|
||||
auto supergroup_info = get_supergroup_info(chat_info->supergroup_id);
|
||||
CHECK(supergroup_info != nullptr);
|
||||
if (supergroup_info->is_supergroup) {
|
||||
error = Status::Error(403, "Forbidden: bot is not a member of the supergroup chat");
|
||||
} else {
|
||||
error = Status::Error(403, "Forbidden: bot is not a member of the channel chat");
|
||||
if (supergroup_info->status->get_id() == td_api::chatMemberStatusBanned::ID ||
|
||||
supergroup_info->status->get_id() == td_api::chatMemberStatusLeft::ID) {
|
||||
if (supergroup_info->is_supergroup) {
|
||||
error = Status::Error(403, "Forbidden: bot is not a member of the supergroup chat");
|
||||
} else {
|
||||
error = Status::Error(403, "Forbidden: bot is not a member of the channel chat");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9977,19 +10260,24 @@ Client::FullMessageId Client::add_message(object_ptr<td_api::message> &&message,
|
||||
case td_api::messageForwardOriginChat::ID: {
|
||||
auto forward_info = move_object_as<td_api::messageForwardOriginChat>(origin);
|
||||
message_info->initial_sender_chat_id = forward_info->sender_chat_id_;
|
||||
message_info->initial_author_signature = forward_info->author_signature_;
|
||||
message_info->initial_author_signature = std::move(forward_info->author_signature_);
|
||||
break;
|
||||
}
|
||||
case td_api::messageForwardOriginHiddenUser::ID: {
|
||||
auto forward_info = move_object_as<td_api::messageForwardOriginHiddenUser>(origin);
|
||||
message_info->initial_sender_name = forward_info->sender_name_;
|
||||
message_info->initial_sender_name = std::move(forward_info->sender_name_);
|
||||
break;
|
||||
}
|
||||
case td_api::messageForwardOriginChannel::ID: {
|
||||
auto forward_info = move_object_as<td_api::messageForwardOriginChannel>(origin);
|
||||
message_info->initial_chat_id = forward_info->chat_id_;
|
||||
message_info->initial_message_id = forward_info->message_id_;
|
||||
message_info->initial_author_signature = forward_info->author_signature_;
|
||||
message_info->initial_author_signature = std::move(forward_info->author_signature_);
|
||||
break;
|
||||
}
|
||||
case td_api::messageForwardOriginMessageImport::ID: {
|
||||
auto forward_info = move_object_as<td_api::messageForwardOriginMessageImport>(origin);
|
||||
message_info->initial_sender_name = std::move(forward_info->sender_name_);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -10220,6 +10508,7 @@ constexpr Client::Slice Client::MASK_POINTS[MASK_POINTS_SIZE];
|
||||
|
||||
constexpr int Client::LOGGING_OUT_ERROR_CODE;
|
||||
constexpr Client::Slice Client::LOGGING_OUT_ERROR_DESCRIPTION;
|
||||
constexpr Client::Slice Client::API_ID_INVALID_ERROR_DESCRIPTION;
|
||||
|
||||
constexpr int Client::CLOSING_ERROR_CODE;
|
||||
constexpr Client::Slice Client::CLOSING_ERROR_DESCRIPTION;
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
@ -78,6 +78,7 @@ class Client : public WebhookActor::Callback {
|
||||
|
||||
static constexpr int LOGGING_OUT_ERROR_CODE = 401;
|
||||
static constexpr Slice LOGGING_OUT_ERROR_DESCRIPTION = "Unauthorized";
|
||||
static constexpr Slice API_ID_INVALID_ERROR_DESCRIPTION = "Unauthorized: invalid api-id/api-hash";
|
||||
|
||||
static constexpr int CLOSING_ERROR_CODE = 500;
|
||||
static constexpr Slice CLOSING_ERROR_DESCRIPTION = "Internal Server Error: restart";
|
||||
@ -96,6 +97,7 @@ class Client : public WebhookActor::Callback {
|
||||
class JsonChatPermissions;
|
||||
class JsonChatPhotoInfo;
|
||||
class JsonChatLocation;
|
||||
class JsonChatInviteLink;
|
||||
class JsonChat;
|
||||
class JsonMessageSender;
|
||||
class JsonAnimation;
|
||||
@ -140,6 +142,7 @@ class Client : public WebhookActor::Callback {
|
||||
class JsonChatPhotos;
|
||||
class JsonChatMember;
|
||||
class JsonChatMembers;
|
||||
class JsonChatMemberUpdated;
|
||||
class JsonGameHighScore;
|
||||
class JsonAddress;
|
||||
class JsonOrderInfo;
|
||||
@ -148,6 +151,10 @@ class Client : public WebhookActor::Callback {
|
||||
class JsonEncryptedCredentials;
|
||||
class JsonPassportData;
|
||||
class JsonProximityAlertTriggered;
|
||||
class JsonVoiceChatStarted;
|
||||
class JsonVoiceChatEnded;
|
||||
class JsonInviteVoiceChatParticipants;
|
||||
class JsonChatSetTtl;
|
||||
class JsonUpdateTypes;
|
||||
class JsonWebhookInfo;
|
||||
class JsonStickerSet;
|
||||
@ -185,7 +192,8 @@ class Client : public WebhookActor::Callback {
|
||||
class TdOnGetGroupMembersCallback;
|
||||
class TdOnGetSupergroupMembersCallback;
|
||||
class TdOnGetSupergroupMembersCountCallback;
|
||||
class TdOnGenerateChatInviteLinkCallback;
|
||||
class TdOnReplacePrimaryChatInviteLinkCallback;
|
||||
class TdOnGetChatInviteLinkCallback;
|
||||
class TdOnGetGameHighScoresCallback;
|
||||
class TdOnReturnFileCallback;
|
||||
class TdOnReturnStickerSetCallback;
|
||||
@ -307,7 +315,8 @@ class Client : public WebhookActor::Callback {
|
||||
void on_result(td::uint64 id, object_ptr<td_api::Object> result);
|
||||
|
||||
void on_update_authorization_state();
|
||||
void log_out();
|
||||
void log_out(bool is_api_id_invalid);
|
||||
Slice get_logging_out_error_description() const;
|
||||
void on_closed();
|
||||
void finish_closing();
|
||||
|
||||
@ -382,6 +391,8 @@ class Client : public WebhookActor::Callback {
|
||||
static td::Result<td::vector<object_ptr<td_api::inputPassportElementError>>> get_passport_element_errors(
|
||||
const Query *query);
|
||||
|
||||
static td::JsonValue get_input_entities(const Query *query, Slice field_name);
|
||||
|
||||
static td::Result<object_ptr<td_api::formattedText>> get_caption(const Query *query);
|
||||
|
||||
static td::Result<object_ptr<td_api::TextEntityType>> get_text_entity_type(td::JsonObject &object);
|
||||
@ -495,6 +506,9 @@ class Client : public WebhookActor::Callback {
|
||||
Status process_answer_shipping_query_query(PromisedQueryPtr &query);
|
||||
Status process_answer_pre_checkout_query_query(PromisedQueryPtr &query);
|
||||
Status process_export_chat_invite_link_query(PromisedQueryPtr &query);
|
||||
Status process_create_chat_invite_link_query(PromisedQueryPtr &query);
|
||||
Status process_edit_chat_invite_link_query(PromisedQueryPtr &query);
|
||||
Status process_revoke_chat_invite_link_query(PromisedQueryPtr &query);
|
||||
Status process_get_chat_query(PromisedQueryPtr &query);
|
||||
Status process_set_chat_photo_query(PromisedQueryPtr &query);
|
||||
Status process_delete_chat_photo_query(PromisedQueryPtr &query);
|
||||
@ -688,6 +702,7 @@ class Client : public WebhookActor::Callback {
|
||||
enum class Type { Private, Group, Supergroup, Unknown };
|
||||
Type type = Type::Unknown;
|
||||
td::string title;
|
||||
int32 message_auto_delete_time = 0;
|
||||
object_ptr<td_api::chatPhotoInfo> photo;
|
||||
object_ptr<td_api::chatPermissions> permissions;
|
||||
union {
|
||||
@ -832,7 +847,7 @@ class Client : public WebhookActor::Callback {
|
||||
void add_update_poll_answer(object_ptr<td_api::updatePollAnswer> &&update);
|
||||
|
||||
void add_new_inline_query(int64 inline_query_id, int32 sender_user_id, object_ptr<td_api::location> location,
|
||||
const td::string &query, const td::string &offset);
|
||||
object_ptr<td_api::ChatType> chat_type, const td::string &query, const td::string &offset);
|
||||
|
||||
void add_new_chosen_inline_result(int32 sender_user_id, object_ptr<td_api::location> location,
|
||||
const td::string &query, const td::string &result_id,
|
||||
@ -851,6 +866,8 @@ class Client : public WebhookActor::Callback {
|
||||
|
||||
void add_new_custom_query(object_ptr<td_api::updateNewCustomQuery> &&query);
|
||||
|
||||
void add_update_chat_member(object_ptr<td_api::updateChatMember> &&update);
|
||||
|
||||
// append only before Size
|
||||
enum class UpdateType : int32 {
|
||||
Message,
|
||||
@ -866,6 +883,8 @@ class Client : public WebhookActor::Callback {
|
||||
PreCheckoutQuery,
|
||||
Poll,
|
||||
PollAnswer,
|
||||
MyChatMember,
|
||||
ChatMember,
|
||||
Size
|
||||
};
|
||||
|
||||
@ -893,13 +912,15 @@ class Client : public WebhookActor::Callback {
|
||||
|
||||
bool have_message_access(int64 chat_id) const;
|
||||
|
||||
// by default all 13 update types up to PollAnswer are allowed
|
||||
static constexpr td::uint32 DEFAULT_ALLOWED_UPDATE_TYPES = ((1 << 13) - 1);
|
||||
// by default ChatMember updates are disabled
|
||||
static constexpr td::uint32 DEFAULT_ALLOWED_UPDATE_TYPES =
|
||||
(1 << static_cast<int32>(UpdateType::Size)) - 1 - (1 << static_cast<int32>(UpdateType::ChatMember));
|
||||
|
||||
object_ptr<td_api::AuthorizationState> authorization_state_;
|
||||
bool was_authorized_ = false;
|
||||
bool closing_ = false;
|
||||
bool logging_out_ = false;
|
||||
bool is_api_id_invalid_ = false;
|
||||
bool need_close_ = false;
|
||||
bool clear_tqueue_ = false;
|
||||
bool waiting_for_auth_input_ = false;
|
||||
@ -1037,8 +1058,8 @@ class Client : public WebhookActor::Callback {
|
||||
|
||||
int32 previous_get_updates_offset_ = -1;
|
||||
double previous_get_updates_start_time_ = 0;
|
||||
double previous_get_updates_finish_date_ = 0;
|
||||
double previous_get_updates_finish_time_ = 0;
|
||||
double next_get_updates_conflict_time_ = 0;
|
||||
|
||||
td::uint64 webhook_generation_ = 1;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020, Luckydonald (tdlight-telegram-bot-api+code@luckydonald.de) 2020
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021, Luckydonald (tdlight-telegram-bot-api+code@luckydonald.de) 2020
|
||||
//
|
||||
// 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)
|
||||
@ -75,7 +75,7 @@ void ClientManager::send(PromisedQueryPtr query) {
|
||||
}
|
||||
auto r_user_id = td::to_integer_safe<td::int64>(query->token().substr(0, token.find(':')));
|
||||
if (r_user_id.is_error() || r_user_id.ok() < 0 || !token_range_(r_user_id.ok())) {
|
||||
return fail_query(401, "Unauthorized: unallowed token specified", std::move(query));
|
||||
return fail_query(421, "Misdirected Request: unallowed token specified", std::move(query));
|
||||
}
|
||||
|
||||
if (query->is_test_dc()) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
@ -8,8 +8,6 @@
|
||||
|
||||
#include "telegram-bot-api/ClientParameters.h"
|
||||
|
||||
#include "td/db/TQueue.h"
|
||||
|
||||
#include "td/net/GetHostByNameActor.h"
|
||||
#include "td/net/HttpHeaderCreator.h"
|
||||
#include "td/net/HttpProxy.h"
|
||||
@ -26,7 +24,6 @@
|
||||
#include "td/utils/JsonBuilder.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/port/Clocks.h"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
#include "td/utils/port/SocketFd.h"
|
||||
#include "td/utils/Random.h"
|
||||
@ -253,7 +250,7 @@ void WebhookActor::on_socket_ready_async(td::Result<td::SocketFd> r_fd, td::int6
|
||||
}
|
||||
|
||||
void WebhookActor::create_new_connections() {
|
||||
size_t need_connections = queues_.size();
|
||||
size_t need_connections = queue_updates_.size();
|
||||
if (need_connections > static_cast<size_t>(max_connections_)) {
|
||||
need_connections = max_connections_;
|
||||
}
|
||||
@ -382,20 +379,18 @@ void WebhookActor::load_updates() {
|
||||
for (auto &update : updates) {
|
||||
VLOG(webhook) << "Load update " << update.id;
|
||||
if (update_map_.find(update.id) != update_map_.end()) {
|
||||
LOG(ERROR) << "Receive duplicated event from tqueue " << update.id;
|
||||
LOG(ERROR) << "Receive duplicated event " << update.id << " from tqueue";
|
||||
continue;
|
||||
}
|
||||
auto &dest = update_map_[update.id];
|
||||
dest.id_ = update.id;
|
||||
dest.json_ = update.data.str();
|
||||
dest.state_ = Update::State::Begin;
|
||||
dest.delay_ = 1;
|
||||
dest.wakeup_at_ = now;
|
||||
CHECK(update.expires_at >= unix_time_now);
|
||||
dest.expires_at_ = update.expires_at;
|
||||
dest.queue_id_ = update.extra;
|
||||
tqueue_offset_ = update.id.next().move_as_ok();
|
||||
begin_updates_n_++;
|
||||
|
||||
if (dest.queue_id_ == 0) {
|
||||
dest.queue_id_ = unique_queue_id_++;
|
||||
@ -421,9 +416,10 @@ void WebhookActor::load_updates() {
|
||||
}
|
||||
}
|
||||
if (need_warning) {
|
||||
LOG(WARNING) << "Loaded " << updates.size() << " updates out of " << total_size << ". Have total of "
|
||||
<< update_map_.size() << " loaded in " << queues_.size() << " queues after last error \""
|
||||
<< last_error_message_ << "\" at " << last_error_date_;
|
||||
LOG(WARNING) << "Loaded " << updates.size() << " updates out of " << total_size << ". Have " << update_map_.size()
|
||||
<< " updates loaded in " << queue_updates_.size() << " queues after last error \""
|
||||
<< last_error_message_ << "\" " << (last_error_time_ == 0 ? -1 : td::Time::now() - last_error_time_)
|
||||
<< " seconds ago";
|
||||
}
|
||||
|
||||
if (updates.size() == total_size && last_update_was_successful_) {
|
||||
@ -439,6 +435,7 @@ void WebhookActor::load_updates() {
|
||||
|
||||
void WebhookActor::drop_event(td::TQueue::EventId event_id) {
|
||||
auto it = update_map_.find(event_id);
|
||||
CHECK(it != update_map_.end());
|
||||
auto queue_id = it->second.queue_id_;
|
||||
update_map_.erase(it);
|
||||
|
||||
@ -460,7 +457,12 @@ void WebhookActor::drop_event(td::TQueue::EventId event_id) {
|
||||
void WebhookActor::on_update_ok(td::TQueue::EventId event_id) {
|
||||
last_update_was_successful_ = true;
|
||||
last_success_time_ = td::Time::now();
|
||||
VLOG(webhook) << "Receive ok for update " << event_id;
|
||||
|
||||
auto it = update_map_.find(event_id);
|
||||
CHECK(it != update_map_.end());
|
||||
|
||||
VLOG(webhook) << "Receive ok for update " << event_id << " in " << (last_success_time_ - it->second.last_send_time_)
|
||||
<< " seconds";
|
||||
|
||||
drop_event(event_id);
|
||||
}
|
||||
@ -470,6 +472,7 @@ void WebhookActor::on_update_error(td::TQueue::EventId event_id, td::Slice error
|
||||
double now = td::Time::now();
|
||||
|
||||
auto it = update_map_.find(event_id);
|
||||
CHECK(it != update_map_.end());
|
||||
|
||||
const int MAX_RETRY_AFTER = 3600;
|
||||
retry_after = td::clamp(retry_after, 0, MAX_RETRY_AFTER);
|
||||
@ -485,14 +488,13 @@ void WebhookActor::on_update_error(td::TQueue::EventId event_id, td::Slice error
|
||||
return;
|
||||
}
|
||||
auto &update = it->second;
|
||||
update.state_ = Update::State::Begin;
|
||||
update.delay_ = next_delay;
|
||||
update.wakeup_at_ = now + next_effective_delay;
|
||||
update.fail_count_++;
|
||||
queues_.emplace(update.wakeup_at_, update.queue_id_);
|
||||
VLOG(webhook) << "Delay update " << event_id << " for " << (update.wakeup_at_ - now) << " seconds because of "
|
||||
<< error << " after " << update.fail_count_ << " fails";
|
||||
begin_updates_n_++;
|
||||
<< error << " after " << update.fail_count_ << " fails received in " << (now - update.last_send_time_)
|
||||
<< " seconds";
|
||||
}
|
||||
|
||||
td::Status WebhookActor::send_update() {
|
||||
@ -501,10 +503,11 @@ td::Status WebhookActor::send_update() {
|
||||
}
|
||||
|
||||
if (queues_.empty()) {
|
||||
return td::Status::Error("No updates");
|
||||
return td::Status::Error("No pending updates");
|
||||
}
|
||||
auto it = queues_.begin();
|
||||
if (it->wakeup_at > td::Time::now()) {
|
||||
auto now = td::Time::now();
|
||||
if (it->wakeup_at > now) {
|
||||
relax_wakeup_at(it->wakeup_at, "send_update");
|
||||
return td::Status::Error("No ready updates");
|
||||
}
|
||||
@ -514,6 +517,7 @@ td::Status WebhookActor::send_update() {
|
||||
auto event_id = queue_updates_[queue_id].event_ids.front();
|
||||
|
||||
auto &update = update_map_[event_id];
|
||||
update.last_send_time_ = now;
|
||||
|
||||
auto body = td::json_encode<td::BufferSlice>(JsonUpdate(update.id_.value(), update.json_));
|
||||
|
||||
@ -533,8 +537,6 @@ td::Status WebhookActor::send_update() {
|
||||
}
|
||||
|
||||
auto &connection = *Connection::from_list_node(ready_connections_.get());
|
||||
begin_updates_n_--;
|
||||
update.state_ = Update::State::Send;
|
||||
connection.event_id_ = update.id_;
|
||||
|
||||
VLOG(webhook) << "Send update " << update.id_ << " from queue " << queue_id << " into connection " << connection.id_
|
||||
@ -548,11 +550,9 @@ td::Status WebhookActor::send_update() {
|
||||
}
|
||||
|
||||
void WebhookActor::send_updates() {
|
||||
VLOG(webhook) << "Have " << begin_updates_n_ << " pending updates to send";
|
||||
while (begin_updates_n_ > 0) {
|
||||
if (send_update().is_error()) {
|
||||
return;
|
||||
}
|
||||
VLOG(webhook) << "Have " << (queues_.size() + update_map_.size() - queue_updates_.size()) << " pending updates in "
|
||||
<< queues_.size() << " queues to send";
|
||||
while (send_update().is_ok()) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -653,7 +653,7 @@ void WebhookActor::handle(td::unique_ptr<td::HttpQuery> response) {
|
||||
void WebhookActor::start_up() {
|
||||
max_loaded_updates_ = max_connections_ * 2;
|
||||
|
||||
next_ip_address_resolve_time_ = last_success_time_ = td::Time::now();
|
||||
next_ip_address_resolve_time_ = last_success_time_ = td::Time::now() - 3600;
|
||||
active_new_connection_flood_.add_limit(1, 10 * max_connections_);
|
||||
active_new_connection_flood_.add_limit(5, 20 * max_connections_);
|
||||
|
||||
@ -749,7 +749,7 @@ void WebhookActor::on_connection_error(td::Status error) {
|
||||
void WebhookActor::on_webhook_error(td::Slice error) {
|
||||
if (was_checked_) {
|
||||
send_closure(callback_, &Callback::webhook_error, td::Status::Error(error));
|
||||
last_error_date_ = td::Clocks::system(); // local time to output it to the log
|
||||
last_error_time_ = td::Time::now();
|
||||
last_error_message_ = error.str();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
@ -79,7 +79,7 @@ class WebhookActor : public td::HttpOutboundConnection::Callback {
|
||||
td::string cert_path_;
|
||||
std::shared_ptr<const ClientParameters> parameters_;
|
||||
|
||||
double last_error_date_ = 0;
|
||||
double last_error_time_ = 0;
|
||||
td::string last_error_message_ = "<none>";
|
||||
|
||||
bool fix_ip_address_ = false;
|
||||
@ -94,11 +94,11 @@ class WebhookActor : public td::HttpOutboundConnection::Callback {
|
||||
td::TQueue::EventId id_;
|
||||
td::string json_;
|
||||
td::int32 expires_at_ = 0;
|
||||
double last_send_time_ = 0;
|
||||
double wakeup_at_ = 0;
|
||||
int delay_ = 0;
|
||||
int fail_count_ = 0;
|
||||
enum State { Begin, Send } state_ = State::Begin;
|
||||
td::int64 queue_id_{0};
|
||||
td::int64 queue_id_ = 0;
|
||||
};
|
||||
|
||||
struct QueueUpdates {
|
||||
@ -119,8 +119,6 @@ class WebhookActor : public td::HttpOutboundConnection::Callback {
|
||||
}
|
||||
};
|
||||
|
||||
td::int32 begin_updates_n_ = 0;
|
||||
|
||||
td::TQueue::EventId tqueue_offset_;
|
||||
std::size_t max_loaded_updates_ = 0;
|
||||
struct EventIdHash {
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
||||
// 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)
|
||||
@ -24,6 +24,7 @@
|
||||
#include "td/actor/ConcurrentScheduler.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/crypto.h"
|
||||
@ -145,7 +146,8 @@ int main(int argc, char *argv[]) {
|
||||
td::string http_ip_address = "0.0.0.0";
|
||||
td::string http_stat_ip_address = "0.0.0.0";
|
||||
td::string log_file_path;
|
||||
int verbosity_level = 0;
|
||||
int default_verbosity_level = 0;
|
||||
int memory_verbosity_level = VERBOSITY_NAME(INFO);
|
||||
td::int64 log_max_file_size = 2000000000;
|
||||
td::string working_directory;
|
||||
td::string temporary_directory;
|
||||
@ -234,7 +236,10 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
options.add_option('l', "log", "path to the file where the log will be written",
|
||||
td::OptionParser::parse_string(log_file_path));
|
||||
options.add_checked_option('v', "verbosity", "log verbosity level", td::OptionParser::parse_integer(verbosity_level));
|
||||
options.add_checked_option('v', "verbosity", "log verbosity level",
|
||||
td::OptionParser::parse_integer(default_verbosity_level));
|
||||
options.add_checked_option('\0', "memory-verbosity", "memory log verbosity level; defaults to 3",
|
||||
td::OptionParser::parse_integer(memory_verbosity_level));
|
||||
options.add_checked_option(
|
||||
'\0', "log-max-file-size",
|
||||
PSLICE() << "maximum size of the log file in bytes before it will be auto-rotated (default is "
|
||||
@ -266,11 +271,17 @@ int main(int argc, char *argv[]) {
|
||||
return td::Status::OK();
|
||||
});
|
||||
options.add_check([&] {
|
||||
if (verbosity_level < 0) {
|
||||
if (default_verbosity_level < 0) {
|
||||
return td::Status::Error("Wrong verbosity level specified");
|
||||
}
|
||||
return td::Status::OK();
|
||||
});
|
||||
options.add_check([&] {
|
||||
if (memory_verbosity_level < 0) {
|
||||
return td::Status::Error("Wrong memory verbosity level specified");
|
||||
}
|
||||
return td::Status::OK();
|
||||
});
|
||||
auto r_non_options = options.run(argc, argv, 0);
|
||||
if (need_print_usage) {
|
||||
LOG(PLAIN) << options;
|
||||
@ -286,6 +297,9 @@ int main(int argc, char *argv[]) {
|
||||
public:
|
||||
void append(td::CSlice slice, int log_level) override {
|
||||
if (first_ && log_level <= first_verbosity_level_) {
|
||||
if (log_level == VERBOSITY_NAME(FATAL) && second_ && VERBOSITY_NAME(FATAL) <= second_verbosity_level_) {
|
||||
second_->append(slice, VERBOSITY_NAME(ERROR));
|
||||
}
|
||||
first_->append(slice, log_level);
|
||||
}
|
||||
if (second_ && log_level <= second_verbosity_level_) {
|
||||
@ -309,6 +323,14 @@ int main(int argc, char *argv[]) {
|
||||
second_verbosity_level_ = verbosity_level;
|
||||
}
|
||||
|
||||
int get_first_verbosity_level() const {
|
||||
return first_verbosity_level_;
|
||||
}
|
||||
|
||||
int get_second_verbosity_level() const {
|
||||
return second_verbosity_level_;
|
||||
}
|
||||
|
||||
void rotate() override {
|
||||
if (first_) {
|
||||
first_->rotate();
|
||||
@ -380,11 +402,14 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
::td::VERBOSITY_NAME(dns_resolver) = VERBOSITY_NAME(WARNING);
|
||||
|
||||
int memory_verbosity_level = td::max(VERBOSITY_NAME(INFO), verbosity_level);
|
||||
SET_VERBOSITY_LEVEL(memory_verbosity_level);
|
||||
log.set_first_verbosity_level(verbosity_level);
|
||||
log.set_second_verbosity_level(memory_verbosity_level);
|
||||
|
||||
auto set_verbosity_level = [&log, memory_verbosity_level](int new_verbosity_level) {
|
||||
SET_VERBOSITY_LEVEL(td::max(memory_verbosity_level, new_verbosity_level));
|
||||
log.set_first_verbosity_level(new_verbosity_level);
|
||||
};
|
||||
set_verbosity_level(default_verbosity_level);
|
||||
|
||||
// LOG(WARNING) << "Bot API server with commit " << td::GitInfo::commit() << ' '
|
||||
// << (td::GitInfo::is_dirty() ? "(dirty)" : "") << " started";
|
||||
LOG(WARNING) << "Bot API server started";
|
||||
@ -455,20 +480,18 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (!need_change_verbosity_level.test_and_set()) {
|
||||
auto current_global_verbosity_level = GET_VERBOSITY_LEVEL();
|
||||
SET_VERBOSITY_LEVEL(256 - current_global_verbosity_level);
|
||||
verbosity_level = 256 - verbosity_level;
|
||||
log.set_first_verbosity_level(verbosity_level);
|
||||
if (log.get_first_verbosity_level() == default_verbosity_level) {
|
||||
// increase default log verbosity level
|
||||
set_verbosity_level(100);
|
||||
} else {
|
||||
// return back verbosity level
|
||||
set_verbosity_level(default_verbosity_level);
|
||||
}
|
||||
}
|
||||
|
||||
auto next_verbosity_level = shared_data->next_verbosity_level_.exchange(-1);
|
||||
if (next_verbosity_level != -1) {
|
||||
verbosity_level = next_verbosity_level;
|
||||
memory_verbosity_level = td::max(VERBOSITY_NAME(INFO), verbosity_level);
|
||||
SET_VERBOSITY_LEVEL(memory_verbosity_level);
|
||||
|
||||
log.set_first_verbosity_level(verbosity_level);
|
||||
log.set_second_verbosity_level(memory_verbosity_level);
|
||||
set_verbosity_level(next_verbosity_level);
|
||||
}
|
||||
|
||||
if (!need_dump_log.test_and_set()) {
|
||||
|
Loading…
Reference in New Issue
Block a user