mirror of
https://github.com/tdlight-team/tdlight-telegram-bot-api.git
synced 2024-09-01 12:05:41 +02:00
Merge version 6.2
This commit is contained in:
commit
bcc8c6e60e
@ -6,7 +6,7 @@ if (POLICY CMP0065)
|
||||
cmake_policy(SET CMP0065 NEW)
|
||||
endif()
|
||||
|
||||
project(TelegramBotApi VERSION 6.1 LANGUAGES CXX)
|
||||
project(TelegramBotApi VERSION 6.2 LANGUAGES CXX)
|
||||
|
||||
if (POLICY CMP0069)
|
||||
option(TELEGRAM_BOT_API_ENABLE_LTO "Use \"ON\" to enable Link Time Optimization.")
|
||||
|
10
build.html
10
build.html
@ -181,7 +181,7 @@
|
||||
|
||||
<div class="main">
|
||||
<div id="osSelectDiv" class="large">
|
||||
<p>Choose an operating system, on which you want to use the Telegram Bot API server:</p>
|
||||
<p>Choose an operating system on which you want to use the Telegram Bot API server:</p>
|
||||
<select id="osSelect" onchange="onOsChanged(false)" autofocus class="large">
|
||||
<option>Choose an operating system:</option>
|
||||
<option>Windows</option>
|
||||
@ -195,7 +195,7 @@
|
||||
</div>
|
||||
|
||||
<div id="linuxSelectDiv" class="hide">
|
||||
<p>Choose a Linux distro, on which you want to use the Telegram Bot API server:</p>
|
||||
<p>Choose a Linux distro on which you want to use the Telegram Bot API server:</p>
|
||||
<select id="linuxSelect" onchange="onOsChanged(false)" class="large">
|
||||
<option>Choose a Linux distro:</option>
|
||||
<option>Alpine</option>
|
||||
@ -207,6 +207,7 @@
|
||||
<option>Ubuntu 16</option>
|
||||
<option>Ubuntu 18</option>
|
||||
<option>Ubuntu 20</option>
|
||||
<option>Ubuntu 22</option>
|
||||
<option>Other</option>
|
||||
</select>
|
||||
<p></p>
|
||||
@ -493,6 +494,8 @@ function onOptionsChanged() {
|
||||
return '-6.0';
|
||||
case 'Ubuntu 20':
|
||||
return '-10';
|
||||
case 'Ubuntu 22':
|
||||
return '-14';
|
||||
default:
|
||||
return ''; // use default version
|
||||
}
|
||||
@ -534,6 +537,7 @@ function onOptionsChanged() {
|
||||
case 'Ubuntu 16':
|
||||
case 'Ubuntu 18':
|
||||
case 'Ubuntu 20':
|
||||
case 'Ubuntu 22':
|
||||
if (linux_distro.includes('Debian') && !use_root) {
|
||||
commands.push('su -');
|
||||
}
|
||||
@ -550,7 +554,7 @@ function onOptionsChanged() {
|
||||
}
|
||||
if (use_clang) {
|
||||
packages += ' clang' + getClangVersionSuffix() + ' libc++-dev';
|
||||
if (linux_distro === 'Debian 10+' || linux_distro === 'Ubuntu 18' || linux_distro === 'Ubuntu 20') {
|
||||
if (linux_distro === 'Debian 10+' || linux_distro === 'Ubuntu 18' || linux_distro === 'Ubuntu 20' || linux_distro === 'Ubuntu 22') {
|
||||
packages += ' libc++abi-dev';
|
||||
}
|
||||
} else {
|
||||
|
2
td
2
td
@ -1 +1 @@
|
||||
Subproject commit b393215d6671863b6baf2a589d343cff9474f6ba
|
||||
Subproject commit d9cfcf88fe4ad06dae1716ce8f66bbeb7f9491d9
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "td/db/TQueue.h"
|
||||
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
#include "td/actor/MultiPromise.h"
|
||||
#include "td/actor/SleepActor.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
@ -22,7 +22,6 @@
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/PathView.h"
|
||||
#include "td/utils/port/path.h"
|
||||
#include "td/utils/port/Stat.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/Span.h"
|
||||
@ -207,6 +206,12 @@ Client::Client(td::ActorShared<> parent, const td::string &bot_token, bool is_us
|
||||
CHECK(is_inited);
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
td::Scheduler::instance()->destroy_on_scheduler(get_file_gc_scheduler_id(), messages_, users_, groups_, supergroups_,
|
||||
chats_, reply_message_ids_, yet_unsent_reply_message_ids_,
|
||||
sticker_set_names_);
|
||||
}
|
||||
|
||||
bool Client::init_methods() {
|
||||
methods_.emplace("getme", &Client::process_get_me_query);
|
||||
methods_.emplace("getmycommands", &Client::process_get_my_commands_query);
|
||||
@ -285,6 +290,7 @@ bool Client::init_methods() {
|
||||
methods_.emplace("approvechatjoinrequest", &Client::process_approve_chat_join_request_query);
|
||||
methods_.emplace("declinechatjoinrequest", &Client::process_decline_chat_join_request_query);
|
||||
methods_.emplace("getstickerset", &Client::process_get_sticker_set_query);
|
||||
methods_.emplace("getcustomemojistickers", &Client::process_get_custom_emoji_stickers_query);
|
||||
methods_.emplace("uploadstickerfile", &Client::process_upload_sticker_file_query);
|
||||
methods_.emplace("createnewstickerset", &Client::process_create_new_sticker_set_query);
|
||||
methods_.emplace("addstickertoset", &Client::process_add_sticker_to_set_query);
|
||||
@ -526,6 +532,12 @@ class Client::JsonEntity final : public Jsonable {
|
||||
object("user", JsonUser(entity->user_id_, client_));
|
||||
break;
|
||||
}
|
||||
case td_api::textEntityTypeCustomEmoji::ID: {
|
||||
auto entity = static_cast<const td_api::textEntityTypeCustomEmoji *>(entity_->type_.get());
|
||||
object("type", "custom_emoji");
|
||||
object("custom_emoji_id", td::to_string(entity->custom_emoji_id_));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -738,6 +750,9 @@ class Client::JsonChat final : public Jsonable {
|
||||
if (user_info->has_private_forwards) {
|
||||
object("has_private_forwards", td::JsonTrue());
|
||||
}
|
||||
if (user_info->has_restricted_voice_and_video_messages) {
|
||||
object("has_restricted_voice_and_video_messages", td::JsonTrue());
|
||||
}
|
||||
}
|
||||
photo = user_info->photo.get();
|
||||
break;
|
||||
@ -1117,14 +1132,20 @@ class Client::JsonSticker final : public Jsonable {
|
||||
if (!set_name.empty()) {
|
||||
object("set_name", set_name);
|
||||
}
|
||||
auto type = sticker_->type_->get_id();
|
||||
object("is_animated", td::JsonBool(type == td_api::stickerTypeAnimated::ID));
|
||||
object("is_video", td::JsonBool(type == td_api::stickerTypeVideo::ID));
|
||||
if (type == td_api::stickerTypeMask::ID) {
|
||||
const auto &mask_position = static_cast<const td_api::stickerTypeMask *>(sticker_->type_.get())->mask_position_;
|
||||
if (mask_position != nullptr) {
|
||||
object("mask_position", JsonMaskPosition(mask_position.get()));
|
||||
}
|
||||
|
||||
auto format = sticker_->format_->get_id();
|
||||
object("is_animated", td::JsonBool(format == td_api::stickerFormatTgs::ID));
|
||||
object("is_video", td::JsonBool(format == td_api::stickerFormatWebm::ID));
|
||||
|
||||
object("type", Client::get_sticker_type(sticker_->type_));
|
||||
|
||||
if (sticker_->custom_emoji_id_ != 0) {
|
||||
object("custom_emoji_id", td::to_string(sticker_->custom_emoji_id_));
|
||||
}
|
||||
|
||||
const auto &mask_position = sticker_->mask_position_;
|
||||
if (mask_position != nullptr) {
|
||||
object("mask_position", JsonMaskPosition(mask_position.get()));
|
||||
}
|
||||
if (sticker_->premium_animation_ != nullptr) {
|
||||
object("premium_animation", JsonFile(sticker_->premium_animation_.get(), client_, false));
|
||||
@ -2136,6 +2157,8 @@ void Client::JsonMessage::store(JsonValueScope *scope) const {
|
||||
object("web_app_data", JsonWebAppData(content));
|
||||
break;
|
||||
}
|
||||
case td_api::messageGiftedPremium::ID:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -2751,10 +2774,15 @@ class Client::JsonStickerSet final : public Jsonable {
|
||||
if (sticker_set_->thumbnail_ != nullptr) {
|
||||
client_->json_store_thumbnail(object, sticker_set_->thumbnail_.get());
|
||||
}
|
||||
auto type = sticker_set_->sticker_type_->get_id();
|
||||
object("is_animated", td::JsonBool(type == td_api::stickerTypeAnimated::ID));
|
||||
object("is_video", td::JsonBool(type == td_api::stickerTypeVideo::ID));
|
||||
object("contains_masks", td::JsonBool(type == td_api::stickerTypeMask::ID));
|
||||
|
||||
auto format = sticker_set_->sticker_format_->get_id();
|
||||
object("is_animated", td::JsonBool(format == td_api::stickerFormatTgs::ID));
|
||||
object("is_video", td::JsonBool(format == td_api::stickerFormatWebm::ID));
|
||||
|
||||
auto type = Client::get_sticker_type(sticker_set_->sticker_type_);
|
||||
object("sticker_type", type);
|
||||
object("contains_masks", td::JsonBool(type == "mask"));
|
||||
|
||||
object("stickers", JsonStickers(sticker_set_->stickers_, client_));
|
||||
}
|
||||
|
||||
@ -4075,6 +4103,68 @@ class Client::TdOnReturnStickerSetCallback final : public TdQueryCallback {
|
||||
PromisedQueryPtr query_;
|
||||
};
|
||||
|
||||
class Client::TdOnGetStickerSetPromiseCallback final : public TdQueryCallback {
|
||||
public:
|
||||
TdOnGetStickerSetPromiseCallback(Client *client, td::Promise<td::Unit> &&promise)
|
||||
: client_(client), promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void on_result(object_ptr<td_api::Object> result) final {
|
||||
if (result->get_id() == td_api::error::ID) {
|
||||
auto error = move_object_as<td_api::error>(result);
|
||||
return promise_.set_error(Status::Error(error->code_, error->message_));
|
||||
}
|
||||
|
||||
CHECK(result->get_id() == td_api::stickerSet::ID);
|
||||
auto sticker_set = move_object_as<td_api::stickerSet>(result);
|
||||
client_->on_get_sticker_set_name(sticker_set->id_, sticker_set->name_);
|
||||
promise_.set_value(td::Unit());
|
||||
}
|
||||
|
||||
private:
|
||||
Client *client_;
|
||||
td::Promise<td::Unit> promise_;
|
||||
};
|
||||
|
||||
class Client::TdOnGetStickersCallback final : public TdQueryCallback {
|
||||
public:
|
||||
TdOnGetStickersCallback(Client *client, PromisedQueryPtr query) : client_(client), query_(std::move(query)) {
|
||||
}
|
||||
|
||||
void on_result(object_ptr<td_api::Object> result) final {
|
||||
if (result->get_id() == td_api::error::ID) {
|
||||
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result));
|
||||
}
|
||||
|
||||
CHECK(result->get_id() == td_api::stickers::ID);
|
||||
auto stickers = move_object_as<td_api::stickers>(result);
|
||||
td::FlatHashSet<int64> sticker_set_ids;
|
||||
for (const auto &sticker : stickers->stickers_) {
|
||||
if (sticker->set_id_ != 0 && client_->get_sticker_set_name(sticker->set_id_).empty()) {
|
||||
sticker_set_ids.insert(sticker->set_id_);
|
||||
}
|
||||
}
|
||||
|
||||
td::MultiPromiseActorSafe mpas("GetStickerSetsMultiPromiseActor");
|
||||
mpas.add_promise(td::PromiseCreator::lambda([actor_id = client_->actor_id(client_), stickers = std::move(stickers),
|
||||
query = std::move(query_)](td::Unit) mutable {
|
||||
send_closure(actor_id, &Client::return_stickers, std::move(stickers), std::move(query));
|
||||
}));
|
||||
mpas.set_ignore_errors(true);
|
||||
|
||||
auto lock = mpas.get_promise();
|
||||
for (auto sticker_set_id : sticker_set_ids) {
|
||||
client_->send_request(make_object<td_api::getStickerSet>(sticker_set_id),
|
||||
td::make_unique<TdOnGetStickerSetPromiseCallback>(client_, mpas.get_promise()));
|
||||
}
|
||||
lock.set_value(td::Unit());
|
||||
}
|
||||
|
||||
private:
|
||||
Client *client_;
|
||||
PromisedQueryPtr query_;
|
||||
};
|
||||
|
||||
class Client::TdOnSendCustomRequestCallback final : public TdQueryCallback {
|
||||
public:
|
||||
explicit TdOnSendCustomRequestCallback(PromisedQueryPtr query) : query_(std::move(query)) {
|
||||
@ -5308,6 +5398,8 @@ void Client::on_update(object_ptr<td_api::Object> result) {
|
||||
set_user_bio(user_id, std::move(full_info->bio_->text_));
|
||||
}
|
||||
set_user_has_private_forwards(user_id, full_info->has_private_forwards_);
|
||||
set_user_has_restricted_voice_and_video_messages(user_id,
|
||||
full_info->has_restricted_voice_and_video_note_messages_);
|
||||
break;
|
||||
}
|
||||
case td_api::updateUserStatus::ID: {
|
||||
@ -5532,30 +5624,13 @@ void Client::on_closed() {
|
||||
parameters_->shared_data_->webhook_db_->erase(bot_token_with_dc_);
|
||||
parameters_->shared_data_->user_db_->erase(bot_token_with_dc_);
|
||||
|
||||
class RmWorker final : public td::Actor {
|
||||
public:
|
||||
RmWorker(td::string dir, td::ActorId<Client> parent) : dir_(std::move(dir)), parent_(std::move(parent)) {
|
||||
}
|
||||
|
||||
private:
|
||||
td::string dir_;
|
||||
td::ActorId<Client> parent_;
|
||||
|
||||
void start_up() final {
|
||||
CHECK(dir_.size() >= 24);
|
||||
CHECK(dir_.back() == TD_DIR_SLASH);
|
||||
td::rmrf(dir_).ignore();
|
||||
stop();
|
||||
}
|
||||
void tear_down() final {
|
||||
send_closure(parent_, &Client::finish_closing);
|
||||
}
|
||||
};
|
||||
// NB: the same scheduler as for database in Td
|
||||
auto current_scheduler_id = td::Scheduler::instance()->sched_id();
|
||||
auto scheduler_count = td::Scheduler::instance()->sched_count();
|
||||
auto scheduler_id = td::min(current_scheduler_id + 1, scheduler_count - 1);
|
||||
td::create_actor_on_scheduler<RmWorker>("RmWorker", scheduler_id, dir_, actor_id(this)).release();
|
||||
td::Scheduler::instance()->run_on_scheduler(get_file_gc_scheduler_id(),
|
||||
[actor_id = actor_id(this), dir = dir_](td::Unit) {
|
||||
CHECK(dir.size() >= 24);
|
||||
CHECK(dir.back() == TD_DIR_SLASH);
|
||||
td::rmrf(dir).ignore();
|
||||
send_closure(actor_id, &Client::finish_closing);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5575,6 +5650,20 @@ void Client::timeout_expired() {
|
||||
stop();
|
||||
}
|
||||
|
||||
td::int32 Client::get_database_scheduler_id() {
|
||||
// the same scheduler as for database in Td
|
||||
auto current_scheduler_id = td::Scheduler::instance()->sched_id();
|
||||
auto scheduler_count = td::Scheduler::instance()->sched_count();
|
||||
return td::min(current_scheduler_id + 1, scheduler_count - 1);
|
||||
}
|
||||
|
||||
td::int32 Client::get_file_gc_scheduler_id() {
|
||||
// the same scheduler as for file GC in Td
|
||||
auto current_scheduler_id = td::Scheduler::instance()->sched_id();
|
||||
auto scheduler_count = td::Scheduler::instance()->sched_count();
|
||||
return td::min(current_scheduler_id + 2, scheduler_count - 1);
|
||||
}
|
||||
|
||||
void Client::clear_tqueue() {
|
||||
CHECK(webhook_id_.empty());
|
||||
auto &tqueue = parameters_->shared_data_->tqueue_;
|
||||
@ -6818,27 +6907,23 @@ td::Result<td_api::object_ptr<td_api::maskPosition>> Client::get_mask_position(c
|
||||
return r_mask_position.move_as_ok();
|
||||
}
|
||||
|
||||
td::Result<td::vector<td_api::object_ptr<td_api::inputSticker>>> Client::get_input_stickers(const Query *query,
|
||||
bool is_masks) const {
|
||||
td::Result<td::vector<td_api::object_ptr<td_api::inputSticker>>> Client::get_input_stickers(const Query *query) const {
|
||||
auto emojis = query->arg("emojis");
|
||||
|
||||
auto sticker = get_input_file(query, "png_sticker");
|
||||
object_ptr<td_api::StickerType> sticker_type;
|
||||
object_ptr<td_api::StickerFormat> sticker_format;
|
||||
object_ptr<td_api::maskPosition> mask_position;
|
||||
if (sticker != nullptr) {
|
||||
if (is_masks) {
|
||||
TRY_RESULT(mask_position, get_mask_position(query, "mask_position"));
|
||||
sticker_type = make_object<td_api::stickerTypeMask>(std::move(mask_position));
|
||||
} else {
|
||||
sticker_type = make_object<td_api::stickerTypeStatic>();
|
||||
}
|
||||
sticker_format = make_object<td_api::stickerFormatWebp>();
|
||||
TRY_RESULT_ASSIGN(mask_position, get_mask_position(query, "mask_position"));
|
||||
} else {
|
||||
sticker = get_input_file(query, "tgs_sticker", true);
|
||||
if (sticker != nullptr) {
|
||||
sticker_type = make_object<td_api::stickerTypeAnimated>();
|
||||
sticker_format = make_object<td_api::stickerFormatTgs>();
|
||||
} else {
|
||||
sticker = get_input_file(query, "webm_sticker", true);
|
||||
if (sticker != nullptr) {
|
||||
sticker_type = make_object<td_api::stickerTypeVideo>();
|
||||
sticker_format = make_object<td_api::stickerFormatWebm>();
|
||||
} else {
|
||||
if (!query->arg("tgs_sticker").empty()) {
|
||||
return Status::Error(400, "Bad Request: animated sticker must be uploaded as an InputFile");
|
||||
@ -6852,7 +6937,8 @@ td::Result<td::vector<td_api::object_ptr<td_api::inputSticker>>> Client::get_inp
|
||||
}
|
||||
|
||||
td::vector<object_ptr<td_api::inputSticker>> stickers;
|
||||
stickers.push_back(make_object<td_api::inputSticker>(std::move(sticker), emojis.str(), std::move(sticker_type)));
|
||||
stickers.push_back(make_object<td_api::inputSticker>(std::move(sticker), emojis.str(), std::move(sticker_format),
|
||||
std::move(mask_position)));
|
||||
return std::move(stickers);
|
||||
}
|
||||
|
||||
@ -7028,6 +7114,10 @@ td::Result<td_api::object_ptr<td_api::TextEntityType>> Client::get_text_entity_t
|
||||
TRY_RESULT(user_id, get_json_object_long_field(user.get_object(), "id", false));
|
||||
return make_object<td_api::textEntityTypeMentionName>(user_id);
|
||||
}
|
||||
if (type == "custom_emoji") {
|
||||
TRY_RESULT(custom_emoji_id, get_json_object_long_field(object, "custom_emoji_id", false));
|
||||
return make_object<td_api::textEntityTypeCustomEmoji>(custom_emoji_id);
|
||||
}
|
||||
if (type == "mention" || type == "hashtag" || type == "cashtag" || type == "bot_command" || type == "url" ||
|
||||
type == "email" || type == "phone_number" || type == "bank_card_number") {
|
||||
return nullptr;
|
||||
@ -9111,18 +9201,48 @@ td::Status Client::process_get_sticker_set_query(PromisedQueryPtr &query) {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
td::Status Client::process_get_custom_emoji_stickers_query(PromisedQueryPtr &query) {
|
||||
TRY_RESULT(custom_emoji_ids_json, get_required_string_arg(query.get(), "custom_emoji_ids"));
|
||||
|
||||
LOG(INFO) << "Parsing JSON object: " << custom_emoji_ids_json;
|
||||
auto r_value = json_decode(custom_emoji_ids_json);
|
||||
if (r_value.is_error()) {
|
||||
return Status::Error(400, "Can't parse custom emoji identifiers JSON object");
|
||||
}
|
||||
auto value = r_value.move_as_ok();
|
||||
if (value.type() != JsonValue::Type::Array) {
|
||||
return Status::Error(400, "Expected an Array of custom emoji identifiers");
|
||||
}
|
||||
|
||||
td::vector<int64> custom_emoji_ids;
|
||||
for (auto &custom_emoji_id : value.get_array()) {
|
||||
if (custom_emoji_id.type() != JsonValue::Type::String) {
|
||||
return Status::Error(400, "Custom emoji identifier must be of type String");
|
||||
}
|
||||
auto parsed_id = td::to_integer_safe<int64>(custom_emoji_id.get_string());
|
||||
if (parsed_id.is_error()) {
|
||||
return Status::Error(400, "Invalid custom emoji identifier specified");
|
||||
}
|
||||
custom_emoji_ids.push_back(parsed_id.ok());
|
||||
}
|
||||
|
||||
send_request(make_object<td_api::getCustomEmojiStickers>(std::move(custom_emoji_ids)),
|
||||
td::make_unique<TdOnGetStickersCallback>(this, std::move(query)));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
td::Status Client::process_upload_sticker_file_query(PromisedQueryPtr &query) {
|
||||
CHECK_IS_BOT();
|
||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||
auto png_sticker = get_input_file(query.get(), "png_sticker");
|
||||
|
||||
check_user(user_id, std::move(query),
|
||||
[this, user_id, png_sticker = std::move(png_sticker)](PromisedQueryPtr query) mutable {
|
||||
send_request(make_object<td_api::uploadStickerFile>(
|
||||
user_id, make_object<td_api::inputSticker>(std::move(png_sticker), "",
|
||||
make_object<td_api::stickerTypeStatic>())),
|
||||
td::make_unique<TdOnReturnFileCallback>(this, std::move(query)));
|
||||
});
|
||||
check_user(
|
||||
user_id, std::move(query), [this, user_id, png_sticker = std::move(png_sticker)](PromisedQueryPtr query) mutable {
|
||||
send_request(make_object<td_api::uploadStickerFile>(
|
||||
user_id, make_object<td_api::inputSticker>(std::move(png_sticker), "",
|
||||
make_object<td_api::stickerFormatWebp>(), nullptr)),
|
||||
td::make_unique<TdOnReturnFileCallback>(this, std::move(query)));
|
||||
});
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
@ -9131,14 +9251,20 @@ td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query)
|
||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||
auto name = query->arg("name");
|
||||
auto title = query->arg("title");
|
||||
auto is_masks = to_bool(query->arg("contains_masks"));
|
||||
TRY_RESULT(stickers, get_input_stickers(query.get(), is_masks));
|
||||
TRY_RESULT(stickers, get_input_stickers(query.get()));
|
||||
|
||||
TRY_RESULT(sticker_type, get_sticker_type(query->arg("sticker_type")));
|
||||
if (to_bool(query->arg("contains_masks"))) {
|
||||
sticker_type = make_object<td_api::stickerTypeMask>();
|
||||
}
|
||||
|
||||
check_user(user_id, std::move(query),
|
||||
[this, user_id, title, name, stickers = std::move(stickers)](PromisedQueryPtr query) mutable {
|
||||
send_request(make_object<td_api::createNewStickerSet>(user_id, title.str(), name.str(),
|
||||
std::move(stickers), PSTRING() << "bot" << my_id_),
|
||||
td::make_unique<TdOnReturnStickerSetCallback>(this, false, std::move(query)));
|
||||
[this, user_id, title, name, sticker_type = std::move(sticker_type),
|
||||
stickers = std::move(stickers)](PromisedQueryPtr query) mutable {
|
||||
send_request(
|
||||
make_object<td_api::createNewStickerSet>(user_id, title.str(), name.str(), std::move(sticker_type),
|
||||
std::move(stickers), PSTRING() << "bot" << my_id_),
|
||||
td::make_unique<TdOnReturnStickerSetCallback>(this, false, std::move(query)));
|
||||
});
|
||||
return Status::OK();
|
||||
}
|
||||
@ -9147,7 +9273,7 @@ td::Status Client::process_add_sticker_to_set_query(PromisedQueryPtr &query) {
|
||||
CHECK_IS_BOT();
|
||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||
auto name = query->arg("name");
|
||||
TRY_RESULT(stickers, get_input_stickers(query.get(), true));
|
||||
TRY_RESULT(stickers, get_input_stickers(query.get()));
|
||||
CHECK(!stickers.empty());
|
||||
|
||||
check_user(user_id, std::move(query),
|
||||
@ -9818,16 +9944,6 @@ void Client::do_get_file(object_ptr<td_api::file> file, PromisedQueryPtr query)
|
||||
|
||||
auto file_id = file->id_;
|
||||
file_download_listeners_[file_id].push_back(std::move(query));
|
||||
if (file->local_->is_downloading_completed_) {
|
||||
Slice relative_path = td::PathView::relative(file->local_->path_, dir_, true);
|
||||
if (!relative_path.empty()) {
|
||||
auto r_stat = td::stat(file->local_->path_);
|
||||
if (r_stat.is_ok() && r_stat.ok().is_reg_ && r_stat.ok().size_ == file->size_) {
|
||||
return on_file_download(file_id, std::move(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
send_request(make_object<td_api::downloadFile>(file_id, 1, 0, 0, false),
|
||||
td::make_unique<TdOnDownloadFileCallback>(this, file_id));
|
||||
}
|
||||
@ -9854,6 +9970,10 @@ void Client::on_file_download(int32 file_id, td::Result<object_ptr<td_api::file>
|
||||
}
|
||||
}
|
||||
|
||||
void Client::return_stickers(object_ptr<td_api::stickers> stickers, PromisedQueryPtr query) {
|
||||
answer_query(JsonStickers(stickers->stickers_, this), std::move(query));
|
||||
}
|
||||
|
||||
void Client::webhook_verified(td::string cached_ip_address) {
|
||||
if (get_link_token() != webhook_generation_) {
|
||||
return;
|
||||
@ -9916,14 +10036,25 @@ void Client::webhook_error(Status status) {
|
||||
}
|
||||
|
||||
void Client::webhook_closed(Status status) {
|
||||
if (has_webhook_certificate_) {
|
||||
td::Scheduler::instance()->run_on_scheduler(get_database_scheduler_id(),
|
||||
[actor_id = actor_id(this), path = get_webhook_certificate_path(),
|
||||
status = std::move(status)](td::Unit) mutable {
|
||||
LOG(INFO) << "Unlink certificate " << path;
|
||||
td::unlink(path).ignore();
|
||||
send_closure(actor_id, &Client::on_webhook_closed, std::move(status));
|
||||
});
|
||||
return;
|
||||
}
|
||||
on_webhook_closed(std::move(status));
|
||||
}
|
||||
|
||||
void Client::on_webhook_closed(Status status) {
|
||||
LOG(WARNING) << "Webhook closed: " << status
|
||||
<< ", webhook_query_type = " << (webhook_query_type_ == WebhookQueryType::Verify ? "verify" : "change");
|
||||
webhook_id_.release();
|
||||
webhook_url_ = td::string();
|
||||
if (has_webhook_certificate_) {
|
||||
td::unlink(get_webhook_certificate_path()).ignore();
|
||||
has_webhook_certificate_ = false;
|
||||
}
|
||||
has_webhook_certificate_ = false;
|
||||
webhook_max_connections_ = 0;
|
||||
webhook_ip_address_ = td::string();
|
||||
webhook_fix_ip_address_ = false;
|
||||
@ -10216,7 +10347,7 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu
|
||||
CHECK(total_size >= updates.size());
|
||||
total_size -= updates.size();
|
||||
|
||||
bool need_warning = false;
|
||||
bool need_warning = total_size > 0 && (query->start_timestamp() - previous_get_updates_finish_time_ > 10.0);
|
||||
if (total_size <= MIN_PENDING_UPDATES_WARNING / 2) {
|
||||
if (last_pending_update_count_ > MIN_PENDING_UPDATES_WARNING) {
|
||||
need_warning = true;
|
||||
@ -10228,7 +10359,7 @@ void Client::do_get_updates(int32 offset, int32 limit, int32 timeout, PromisedQu
|
||||
last_pending_update_count_ *= 2;
|
||||
}
|
||||
}
|
||||
if (need_warning) {
|
||||
if (need_warning && previous_get_updates_finish_time_ > 0) {
|
||||
LOG(WARNING) << "Found " << updates.size() << " updates out of " << (total_size + updates.size())
|
||||
<< " after last getUpdates call " << (query->start_timestamp() - previous_get_updates_finish_time_)
|
||||
<< " seconds ago in " << (td::Time::now() - query->start_timestamp()) << " seconds";
|
||||
@ -10351,6 +10482,11 @@ void Client::set_user_has_private_forwards(int64 user_id, bool has_private_forwa
|
||||
add_user_info(user_id)->has_private_forwards = has_private_forwards;
|
||||
}
|
||||
|
||||
void Client::set_user_has_restricted_voice_and_video_messages(int64 user_id,
|
||||
bool has_restricted_voice_and_video_messages) {
|
||||
add_user_info(user_id)->has_restricted_voice_and_video_messages = has_restricted_voice_and_video_messages;
|
||||
}
|
||||
|
||||
void Client::set_user_status(int64 user_id, object_ptr<td_api::UserStatus> &&status) {
|
||||
add_user_info(user_id)->status = std::move(status);
|
||||
}
|
||||
@ -11113,6 +11249,8 @@ bool Client::need_skip_update_message(int64 chat_id, const object_ptr<td_api::me
|
||||
return true;
|
||||
case td_api::messageWebAppDataSent::ID:
|
||||
return true;
|
||||
case td_api::messageGiftedPremium::ID:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -11165,6 +11303,34 @@ void Client::set_message_reply_to_message_id(MessageInfo *message_info, int64 re
|
||||
message_info->reply_to_message_id = reply_to_message_id;
|
||||
}
|
||||
|
||||
td::Slice Client::get_sticker_type(const object_ptr<td_api::StickerType> &type) {
|
||||
CHECK(type != nullptr);
|
||||
switch (type->get_id()) {
|
||||
case td_api::stickerTypeRegular::ID:
|
||||
return Slice("regular");
|
||||
case td_api::stickerTypeMask::ID:
|
||||
return Slice("mask");
|
||||
case td_api::stickerTypeCustomEmoji::ID:
|
||||
return Slice("custom_emoji");
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Slice();
|
||||
}
|
||||
}
|
||||
|
||||
td::Result<td_api::object_ptr<td_api::StickerType>> Client::get_sticker_type(Slice type) {
|
||||
if (type.empty() || type == "regular") {
|
||||
return make_object<td_api::stickerTypeRegular>();
|
||||
}
|
||||
if (type == "mask") {
|
||||
return make_object<td_api::stickerTypeMask>();
|
||||
}
|
||||
if (type == "custom_emoji") {
|
||||
return make_object<td_api::stickerTypeCustomEmoji>();
|
||||
}
|
||||
return Status::Error(400, "Unsupported sticker type specified");
|
||||
}
|
||||
|
||||
td::CSlice Client::get_callback_data(const object_ptr<td_api::InlineKeyboardButtonType> &type) {
|
||||
CHECK(type != nullptr);
|
||||
switch (type->get_id()) {
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "td/net/HttpFile.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
#include "td/actor/SignalSlot.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
@ -24,6 +23,7 @@
|
||||
#include "td/utils/FlatHashMap.h"
|
||||
#include "td/utils/FlatHashSet.h"
|
||||
#include "td/utils/JsonBuilder.h"
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
@ -42,6 +42,11 @@ class Client final : public WebhookActor::Callback {
|
||||
public:
|
||||
Client(td::ActorShared<> parent, const td::string &bot_token, bool is_user, bool is_test_dc, td::int64 tqueue_id,
|
||||
std::shared_ptr<const ClientParameters> parameters, td::ActorId<BotStatActor> stat_actor);
|
||||
Client(const Client &) = delete;
|
||||
Client &operator=(const Client &) = delete;
|
||||
Client(Client &&) = delete;
|
||||
Client &operator=(Client &&) = delete;
|
||||
~Client();
|
||||
|
||||
void send(PromisedQueryPtr query) final;
|
||||
|
||||
@ -212,6 +217,8 @@ class Client final : public WebhookActor::Callback {
|
||||
class TdOnAnswerWebAppQueryCallback;
|
||||
class TdOnReturnFileCallback;
|
||||
class TdOnReturnStickerSetCallback;
|
||||
class TdOnGetStickerSetPromiseCallback;
|
||||
class TdOnGetStickersCallback;
|
||||
class TdOnDownloadFileCallback;
|
||||
class TdOnCancelDownloadFileCallback;
|
||||
class TdOnSendCustomRequestCallback;
|
||||
@ -346,6 +353,10 @@ class Client final : public WebhookActor::Callback {
|
||||
void on_closed();
|
||||
void finish_closing();
|
||||
|
||||
static int32 get_database_scheduler_id();
|
||||
|
||||
static int32 get_file_gc_scheduler_id();
|
||||
|
||||
void clear_tqueue();
|
||||
|
||||
bool allow_update_before_authorization(const td_api::Object *update) const;
|
||||
@ -432,7 +443,7 @@ class Client final : public WebhookActor::Callback {
|
||||
|
||||
static object_ptr<td_api::MaskPoint> mask_index_to_point(int32 index);
|
||||
|
||||
td::Result<td::vector<object_ptr<td_api::inputSticker>>> get_input_stickers(const Query *query, bool is_masks) const;
|
||||
td::Result<td::vector<object_ptr<td_api::inputSticker>>> get_input_stickers(const Query *query) const;
|
||||
|
||||
static td::Result<td::string> get_passport_element_hash(Slice encoded_hash);
|
||||
|
||||
@ -599,6 +610,7 @@ class Client final : public WebhookActor::Callback {
|
||||
Status process_approve_chat_join_request_query(PromisedQueryPtr &query);
|
||||
Status process_decline_chat_join_request_query(PromisedQueryPtr &query);
|
||||
Status process_get_sticker_set_query(PromisedQueryPtr &query);
|
||||
Status process_get_custom_emoji_stickers_query(PromisedQueryPtr &query);
|
||||
Status process_upload_sticker_file_query(PromisedQueryPtr &query);
|
||||
Status process_create_new_sticker_set_query(PromisedQueryPtr &query);
|
||||
Status process_add_sticker_to_set_query(PromisedQueryPtr &query);
|
||||
@ -663,6 +675,8 @@ class Client final : public WebhookActor::Callback {
|
||||
void save_webhook() const;
|
||||
td::string get_webhook_certificate_path() const;
|
||||
|
||||
void on_webhook_closed(Status status);
|
||||
|
||||
void do_send_message(object_ptr<td_api::InputMessageContent> input_message_content, PromisedQueryPtr query);
|
||||
|
||||
int64 get_send_message_query_id(PromisedQueryPtr query, bool is_multisend);
|
||||
@ -674,6 +688,8 @@ class Client final : public WebhookActor::Callback {
|
||||
bool is_file_being_downloaded(int32 file_id) const;
|
||||
void on_file_download(int32 file_id, td::Result<object_ptr<td_api::file>> r_file);
|
||||
|
||||
void return_stickers(object_ptr<td_api::stickers> stickers, PromisedQueryPtr query);
|
||||
|
||||
void fix_reply_markup_bot_user_ids(object_ptr<td_api::ReplyMarkup> &reply_markup) const;
|
||||
void fix_inline_query_results_bot_user_ids(td::vector<object_ptr<td_api::InputInlineQueryResult>> &results) const;
|
||||
|
||||
@ -726,6 +742,7 @@ class Client final : public WebhookActor::Callback {
|
||||
bool can_read_all_group_messages = false;
|
||||
bool is_inline_bot = false;
|
||||
bool has_private_forwards = false;
|
||||
bool has_restricted_voice_and_video_messages = false;
|
||||
bool is_premium = false;
|
||||
bool added_to_attachment_menu = false;
|
||||
};
|
||||
@ -733,7 +750,10 @@ class Client final : public WebhookActor::Callback {
|
||||
void set_user_photo(int64 user_id, object_ptr<td_api::chatPhoto> &&photo);
|
||||
void set_user_bio(int64 user_id, td::string &&bio);
|
||||
void set_user_has_private_forwards(int64 user_id, bool has_private_forwards);
|
||||
void set_user_has_restricted_voice_and_video_messages(int64 user_id, bool has_restricted_voice_and_video_messages);
|
||||
|
||||
void set_user_status(int64 user_id, object_ptr<td_api::UserStatus> &&status);
|
||||
|
||||
UserInfo *add_user_info(int64 user_id);
|
||||
const UserInfo *get_user_info(int64 user_id) const;
|
||||
|
||||
@ -851,6 +871,10 @@ class Client final : public WebhookActor::Callback {
|
||||
|
||||
void set_message_reply_to_message_id(MessageInfo *message_info, int64 reply_to_message_id);
|
||||
|
||||
static Slice get_sticker_type(const object_ptr<td_api::StickerType> &type);
|
||||
|
||||
static td::Result<object_ptr<td_api::StickerType>> get_sticker_type(Slice type);
|
||||
|
||||
static td::CSlice get_callback_data(const object_ptr<td_api::InlineKeyboardButtonType> &type);
|
||||
|
||||
static bool are_equal_inline_keyboard_buttons(const td_api::inlineKeyboardButton *lhs,
|
||||
|
@ -99,8 +99,8 @@ void ClientManager::send(PromisedQueryPtr query) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto tqueue_id = get_tqueue_id(r_user_id.ok(), query->is_test_dc());
|
||||
if (active_client_count_.find(tqueue_id) != active_client_count_.end()) {
|
||||
auto tqueue_id = get_tqueue_id(user_id, query->is_test_dc());
|
||||
if (active_client_count_.count(tqueue_id) != 0) {
|
||||
// return query->set_retry_after_error(1);
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ void ClientManager::user_login(PromisedQueryPtr query) {
|
||||
parameters_, std::move(stat_actor));
|
||||
|
||||
clients_.get(id)->client_ = std::move(client_id);
|
||||
auto id_it = token_to_id_.end();
|
||||
auto id_it = token_to_id_.find(user_token);
|
||||
std::tie(id_it, std::ignore) = token_to_id_.emplace(user_token, id);
|
||||
send_closure(client_info->client_, &Client::send, std::move(query)); // will send 429 if the client is already closed
|
||||
|
||||
@ -216,7 +216,7 @@ bool ClientManager::check_flood_limits(PromisedQueryPtr &query, bool is_user_log
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClientManager::get_stats(td::PromiseActor<td::BufferSlice> promise,
|
||||
void ClientManager::get_stats(td::Promise<td::BufferSlice> promise,
|
||||
td::vector<std::pair<td::string, td::string>> args,
|
||||
bool as_json) {
|
||||
if (close_flag_) {
|
||||
@ -544,7 +544,7 @@ PromisedQueryPtr ClientManager::get_webhook_restore_query(td::Slice token, bool
|
||||
auto query = td::make_unique<Query>(std::move(containers), token, is_user, is_test_dc, method, std::move(args),
|
||||
td::vector<std::pair<td::MutableSlice, td::MutableSlice>>(),
|
||||
td::vector<td::HttpFile>(), std::move(shared_data), td::IPAddress(), true);
|
||||
return PromisedQueryPtr(query.release(), PromiseDeleter(td::PromiseActor<td::unique_ptr<Query>>()));
|
||||
return PromisedQueryPtr(query.release(), PromiseDeleter(td::Promise<td::unique_ptr<Query>>()));
|
||||
}
|
||||
|
||||
void ClientManager::raw_event(const td::Event::Raw &event) {
|
||||
|
@ -11,13 +11,13 @@
|
||||
#include "telegram-bot-api/Stats.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Container.h"
|
||||
#include "td/utils/FlatHashMap.h"
|
||||
#include "td/utils/FloodControlFast.h"
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/Slice.h"
|
||||
|
||||
#include <memory>
|
||||
@ -46,7 +46,7 @@ class ClientManager final : public td::Actor {
|
||||
|
||||
bool check_flood_limits(PromisedQueryPtr &query, bool is_user_login=false);
|
||||
|
||||
void get_stats(td::PromiseActor<td::BufferSlice> promise, td::vector<std::pair<td::string, td::string>> args, bool as_json);
|
||||
void get_stats(td::Promise<td::BufferSlice> promise, td::vector<std::pair<td::string, td::string>> args, bool as_json);
|
||||
|
||||
void close(td::Promise<td::Unit> &&promise);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "td/utils/JsonBuilder.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Parser.h"
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
|
||||
namespace telegram_bot_api {
|
||||
@ -63,26 +64,21 @@ void HttpConnection::handle(td::unique_ptr<td::HttpQuery> http_query,
|
||||
std::move(http_query->args_), std::move(http_query->headers_),
|
||||
std::move(http_query->files_), shared_data_, http_query->peer_address_, false);
|
||||
|
||||
td::PromiseActor<td::unique_ptr<Query>> promise;
|
||||
td::FutureActor<td::unique_ptr<Query>> future;
|
||||
td::init_promise_future(&promise, &future);
|
||||
future.set_event(td::EventCreator::yield(actor_id()));
|
||||
auto promise = td::PromiseCreator::lambda([actor_id = actor_id(this)](td::Result<td::unique_ptr<Query>> r_query) {
|
||||
send_closure(actor_id, &HttpConnection::on_query_finished, std::move(r_query));
|
||||
});
|
||||
auto promised_query = PromisedQueryPtr(query.release(), PromiseDeleter(std::move(promise)));
|
||||
if (is_login) {
|
||||
send_closure(client_manager_, &ClientManager::user_login, std::move(promised_query));
|
||||
} else {
|
||||
send_closure(client_manager_, &ClientManager::send, std::move(promised_query));
|
||||
}
|
||||
result_ = std::move(future);
|
||||
}
|
||||
|
||||
void HttpConnection::wakeup() {
|
||||
if (result_.empty()) {
|
||||
return;
|
||||
}
|
||||
LOG_CHECK(result_.is_ok()) << result_.move_as_error();
|
||||
void HttpConnection::on_query_finished(td::Result<td::unique_ptr<Query>> r_query) {
|
||||
LOG_CHECK(r_query.is_ok()) << r_query.error();
|
||||
|
||||
auto query = result_.move_as_ok();
|
||||
auto query = r_query.move_as_ok();
|
||||
send_response(query->http_status_code(), std::move(query->answer()), query->retry_after());
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,10 @@
|
||||
#include "td/net/HttpQuery.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -32,10 +32,7 @@ class HttpConnection final : public td::HttpInboundConnection::Callback {
|
||||
|
||||
void handle(td::unique_ptr<td::HttpQuery> http_query, td::ActorOwn<td::HttpInboundConnection> connection) final;
|
||||
|
||||
void wakeup() final;
|
||||
|
||||
private:
|
||||
td::FutureActor<td::unique_ptr<Query>> result_;
|
||||
td::ActorId<ClientManager> client_manager_;
|
||||
td::ActorOwn<td::HttpInboundConnection> connection_;
|
||||
std::shared_ptr<SharedData> shared_data_;
|
||||
@ -45,6 +42,8 @@ class HttpConnection final : public td::HttpInboundConnection::Callback {
|
||||
stop();
|
||||
}
|
||||
|
||||
void on_query_finished(td::Result<td::unique_ptr<Query>> r_query);
|
||||
|
||||
void send_response(int http_status_code, td::BufferSlice &&content, int retry_after);
|
||||
|
||||
void send_http_error(int http_status_code, td::Slice description);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "td/net/HttpHeaderCreator.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Promise.h"
|
||||
|
||||
namespace telegram_bot_api {
|
||||
|
||||
@ -17,25 +17,23 @@ void HttpStatConnection::handle(td::unique_ptr<td::HttpQuery> http_query,
|
||||
td::ActorOwn<td::HttpInboundConnection> connection) {
|
||||
CHECK(connection_->empty());
|
||||
connection_ = std::move(connection);
|
||||
|
||||
td::PromiseActor<td::BufferSlice> promise;
|
||||
td::FutureActor<td::BufferSlice> future;
|
||||
init_promise_future(&promise, &future);
|
||||
future.set_event(td::EventCreator::yield(actor_id()));
|
||||
LOG(DEBUG) << "SEND";
|
||||
td::Parser url_path_parser(http_query->url_path_);
|
||||
as_json_ = url_path_parser.try_skip("/json");
|
||||
|
||||
auto promise = td::PromiseCreator::lambda([actor_id = actor_id(this)](td::Result<td::BufferSlice> result) {
|
||||
send_closure(actor_id, &HttpStatConnection::on_result, std::move(result));
|
||||
});
|
||||
send_closure(client_manager_, &ClientManager::get_stats, std::move(promise), http_query->get_args(), as_json_);
|
||||
result_ = std::move(future);
|
||||
}
|
||||
|
||||
void HttpStatConnection::wakeup() {
|
||||
if (result_.empty()) {
|
||||
void HttpStatConnection::on_result(td::Result<td::BufferSlice> result) {
|
||||
if (result.is_error()) {
|
||||
send_closure(connection_.release(), &td::HttpInboundConnection::write_error,
|
||||
td::Status::Error(500, "Internal Server Error: closing"));
|
||||
return;
|
||||
}
|
||||
LOG_CHECK(result_.is_ok()) << result_.move_as_error();
|
||||
|
||||
auto content = result_.move_as_ok();
|
||||
auto content = result.move_as_ok();
|
||||
td::HttpHeaderCreator hc;
|
||||
hc.init_status_line(200);
|
||||
hc.set_keep_alive();
|
||||
|
@ -12,9 +12,9 @@
|
||||
#include "td/net/HttpQuery.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace telegram_bot_api {
|
||||
|
||||
@ -22,16 +22,16 @@ class HttpStatConnection final : public td::HttpInboundConnection::Callback {
|
||||
public:
|
||||
explicit HttpStatConnection(td::ActorId<ClientManager> client_manager) : client_manager_(client_manager) {
|
||||
}
|
||||
void handle(td::unique_ptr<td::HttpQuery> http_query, td::ActorOwn<td::HttpInboundConnection> connection) final;
|
||||
|
||||
void wakeup() final;
|
||||
void handle(td::unique_ptr<td::HttpQuery> http_query, td::ActorOwn<td::HttpInboundConnection> connection) final;
|
||||
|
||||
private:
|
||||
bool as_json_;
|
||||
td::FutureActor<td::BufferSlice> result_;
|
||||
td::ActorId<ClientManager> client_manager_;
|
||||
td::ActorOwn<td::HttpInboundConnection> connection_;
|
||||
|
||||
void on_result(td::Result<td::BufferSlice> result);
|
||||
|
||||
void hangup() final {
|
||||
connection_.release();
|
||||
stop();
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "td/net/HttpFile.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/common.h"
|
||||
@ -19,6 +18,7 @@
|
||||
#include "td/utils/JsonBuilder.h"
|
||||
#include "td/utils/List.h"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
@ -231,7 +231,7 @@ class JsonQueryError final : public td::Jsonable {
|
||||
|
||||
class PromiseDeleter {
|
||||
public:
|
||||
explicit PromiseDeleter(td::PromiseActor<td::unique_ptr<Query>> &&promise) : promise_(std::move(promise)) {
|
||||
explicit PromiseDeleter(td::Promise<td::unique_ptr<Query>> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
PromiseDeleter() = default;
|
||||
PromiseDeleter(const PromiseDeleter &) = delete;
|
||||
@ -240,7 +240,7 @@ class PromiseDeleter {
|
||||
PromiseDeleter &operator=(PromiseDeleter &&) = default;
|
||||
void operator()(Query *raw_ptr) {
|
||||
td::unique_ptr<Query> query(raw_ptr); // now I cannot forget to delete this pointer
|
||||
if (!promise_.empty_promise()) {
|
||||
if (promise_) {
|
||||
if (!query->is_ready()) {
|
||||
query->set_retry_after_error(5);
|
||||
}
|
||||
@ -249,11 +249,11 @@ class PromiseDeleter {
|
||||
}
|
||||
}
|
||||
~PromiseDeleter() {
|
||||
CHECK(promise_.empty());
|
||||
CHECK(!promise_);
|
||||
}
|
||||
|
||||
private:
|
||||
td::PromiseActor<td::unique_ptr<Query>> promise_;
|
||||
td::Promise<td::unique_ptr<Query>> promise_;
|
||||
};
|
||||
using PromisedQueryPtr = std::unique_ptr<Query, PromiseDeleter>;
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "td/net/TransparentProxy.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/base64.h"
|
||||
#include "td/utils/buffer.h"
|
||||
@ -26,6 +25,7 @@
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/port/IPAddress.h"
|
||||
#include "td/utils/port/SocketFd.h"
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
@ -82,7 +82,7 @@ void WebhookActor::relax_wakeup_at(double wakeup_at, const char *source) {
|
||||
}
|
||||
|
||||
void WebhookActor::resolve_ip_address() {
|
||||
if (fix_ip_address_) {
|
||||
if (fix_ip_address_ || is_ip_address_being_resolved_) {
|
||||
return;
|
||||
}
|
||||
if (td::Time::now() < next_ip_address_resolve_time_) {
|
||||
@ -90,43 +90,42 @@ void WebhookActor::resolve_ip_address() {
|
||||
return;
|
||||
}
|
||||
|
||||
bool future_created = false;
|
||||
if (future_ip_address_.empty()) {
|
||||
td::PromiseActor<td::IPAddress> promise;
|
||||
init_promise_future(&promise, &future_ip_address_);
|
||||
future_created = true;
|
||||
send_closure(parameters_->get_host_by_name_actor_id_, &td::GetHostByNameActor::run, url_.host_, url_.port_, false,
|
||||
td::PromiseCreator::from_promise_actor(std::move(promise)));
|
||||
is_ip_address_being_resolved_ = true;
|
||||
auto promise = td::PromiseCreator::lambda([actor_id = actor_id(this)](td::Result<td::IPAddress> r_ip_address) {
|
||||
send_closure(actor_id, &WebhookActor::on_resolved_ip_address, std::move(r_ip_address));
|
||||
});
|
||||
send_closure(parameters_->get_host_by_name_actor_id_, &td::GetHostByNameActor::run, url_.host_, url_.port_, false,
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void WebhookActor::on_resolved_ip_address(td::Result<td::IPAddress> r_ip_address) {
|
||||
CHECK(is_ip_address_being_resolved_);
|
||||
is_ip_address_being_resolved_ = false;
|
||||
|
||||
next_ip_address_resolve_time_ =
|
||||
td::Time::now() + IP_ADDRESS_CACHE_TIME + td::Random::fast(0, IP_ADDRESS_CACHE_TIME / 10);
|
||||
relax_wakeup_at(next_ip_address_resolve_time_, "on_resolved_ip_address");
|
||||
|
||||
SCOPE_EXIT {
|
||||
loop();
|
||||
};
|
||||
|
||||
if (r_ip_address.is_error()) {
|
||||
return on_error(r_ip_address.move_as_error());
|
||||
}
|
||||
|
||||
if (future_ip_address_.is_ready()) {
|
||||
next_ip_address_resolve_time_ =
|
||||
td::Time::now() + IP_ADDRESS_CACHE_TIME + td::Random::fast(0, IP_ADDRESS_CACHE_TIME / 10);
|
||||
relax_wakeup_at(next_ip_address_resolve_time_, "resolve_ip_address");
|
||||
|
||||
auto r_ip_address = future_ip_address_.move_as_result();
|
||||
if (r_ip_address.is_error()) {
|
||||
CHECK(!(r_ip_address.error() == td::Status::Error<td::FutureActor<td::IPAddress>::HANGUP_ERROR_CODE>()));
|
||||
return on_error(r_ip_address.move_as_error());
|
||||
}
|
||||
auto new_ip_address = r_ip_address.move_as_ok();
|
||||
if (!check_ip_address(new_ip_address)) {
|
||||
return on_error(td::Status::Error(PSLICE() << "IP address " << new_ip_address.get_ip_str() << " is reserved"));
|
||||
}
|
||||
if (!(ip_address_ == new_ip_address)) {
|
||||
VLOG(webhook) << "IP address has changed: " << ip_address_ << " --> " << new_ip_address;
|
||||
ip_address_ = new_ip_address;
|
||||
ip_generation_++;
|
||||
if (was_checked_) {
|
||||
on_webhook_verified();
|
||||
}
|
||||
}
|
||||
VLOG(webhook) << "IP address was verified";
|
||||
} else {
|
||||
if (future_created) {
|
||||
future_ip_address_.set_event(td::EventCreator::yield(actor_id()));
|
||||
auto new_ip_address = r_ip_address.move_as_ok();
|
||||
if (!check_ip_address(new_ip_address)) {
|
||||
return on_error(td::Status::Error(PSLICE() << "IP address " << new_ip_address.get_ip_str() << " is reserved"));
|
||||
}
|
||||
if (!(ip_address_ == new_ip_address)) {
|
||||
VLOG(webhook) << "IP address has changed: " << ip_address_ << " --> " << new_ip_address;
|
||||
ip_address_ = new_ip_address;
|
||||
ip_generation_++;
|
||||
if (was_checked_) {
|
||||
on_webhook_verified();
|
||||
}
|
||||
}
|
||||
VLOG(webhook) << "IP address was verified";
|
||||
}
|
||||
|
||||
td::Status WebhookActor::create_connection() {
|
||||
@ -602,11 +601,10 @@ void WebhookActor::handle(td::unique_ptr<td::HttpQuery> response) {
|
||||
method != "logout" && !td::begins_with(method, "get")) {
|
||||
VLOG(webhook) << "Receive request " << method << " in response to webhook";
|
||||
auto query = td::make_unique<Query>(std::move(response->container_), td::MutableSlice(), false, false,
|
||||
td::MutableSlice(), std::move(response->args_),
|
||||
std::move(response->headers_), std::move(response->files_),
|
||||
parameters_->shared_data_, response->peer_address_, false);
|
||||
auto promised_query =
|
||||
PromisedQueryPtr(query.release(), PromiseDeleter(td::PromiseActor<td::unique_ptr<Query>>()));
|
||||
td::MutableSlice(), std::move(response->args_),
|
||||
std::move(response->headers_), std::move(response->files_),
|
||||
parameters_->shared_data_, response->peer_address_, false);
|
||||
auto promised_query = PromisedQueryPtr(query.release(), PromiseDeleter(td::Promise<td::unique_ptr<Query>>()));
|
||||
send_closure(callback_, &Callback::send, std::move(promised_query));
|
||||
}
|
||||
first_error_410_time_ = 0;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "td/net/SslStream.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/BufferedFd.h"
|
||||
#include "td/utils/common.h"
|
||||
@ -137,7 +136,7 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback {
|
||||
td::IPAddress ip_address_;
|
||||
td::int32 ip_generation_ = 0;
|
||||
double next_ip_address_resolve_time_ = 0;
|
||||
td::FutureActor<td::IPAddress> future_ip_address_;
|
||||
bool is_ip_address_being_resolved_ = false;
|
||||
|
||||
class Connection final : public td::ListNode {
|
||||
public:
|
||||
@ -175,6 +174,7 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback {
|
||||
void relax_wakeup_at(double wakeup_at, const char *source);
|
||||
|
||||
void resolve_ip_address();
|
||||
void on_resolved_ip_address(td::Result<td::IPAddress> r_ip_address);
|
||||
|
||||
td::Result<td::SslStream> create_ssl_stream();
|
||||
td::Status create_connection() TD_WARN_UNUSED_RESULT;
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/ConcurrentScheduler.h"
|
||||
#include "td/actor/PromiseFuture.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/CombinedLog.h"
|
||||
@ -45,6 +44,7 @@
|
||||
#include "td/utils/port/stacktrace.h"
|
||||
#include "td/utils/port/Stat.h"
|
||||
#include "td/utils/port/user.h"
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/Status.h"
|
||||
@ -200,7 +200,7 @@ int main(int argc, char *argv[]) {
|
||||
auto start_time = td::Time::now();
|
||||
auto shared_data = std::make_shared<SharedData>();
|
||||
auto parameters = std::make_unique<ClientParameters>();
|
||||
parameters->version_ = "6.1";
|
||||
parameters->version_ = "6.2";
|
||||
parameters->shared_data_ = shared_data;
|
||||
parameters->start_time_ = start_time;
|
||||
auto net_query_stats = td::create_net_query_stats();
|
||||
|
Loading…
Reference in New Issue
Block a user