diff --git a/telegram-bot-api/Client.cpp b/telegram-bot-api/Client.cpp index ea8e2f1..44cc67c 100644 --- a/telegram-bot-api/Client.cpp +++ b/telegram-bot-api/Client.cpp @@ -8382,13 +8382,14 @@ td::Status Client::process_set_webhook_query(PromisedQueryPtr &query) { int32 new_max_connections = new_url.empty() ? 0 : get_webhook_max_connections(query.get()); Slice new_ip_address = new_url.empty() ? Slice() : query->arg("ip_address"); bool new_fix_ip_address = new_url.empty() ? false : get_webhook_fix_ip_address(query.get()); + Slice new_secret_token = new_url.empty() ? Slice() : query->arg("secret_token"); bool drop_pending_updates = to_bool(query->arg("drop_pending_updates")); if (webhook_set_query_) { // already updating webhook. Cancel previous request fail_query_conflict("Conflict: terminated by other setWebhook", std::move(webhook_set_query_)); } else if (webhook_url_ == new_url && !has_webhook_certificate_ && query->file("certificate") == nullptr && query->arg("certificate").empty() && new_max_connections == webhook_max_connections_ && - new_fix_ip_address == webhook_fix_ip_address_ && + new_fix_ip_address == webhook_fix_ip_address_ && new_secret_token == webhook_secret_token_ && (!new_fix_ip_address || new_ip_address == webhook_ip_address_) && !drop_pending_updates) { if (update_allowed_update_types(query.get())) { save_webhook(); @@ -8512,6 +8513,9 @@ void Client::save_webhook() const { if (webhook_fix_ip_address_) { value += "#fix_ip/"; } + if (!webhook_secret_token_.empty()) { + value += PSTRING() << "#secret" << webhook_secret_token_ << '/'; + } if (allowed_update_types_ != DEFAULT_ALLOWED_UPDATE_TYPES) { value += PSTRING() << "#allow" << allowed_update_types_ << '/'; } @@ -8555,6 +8559,7 @@ void Client::webhook_closed(Status status) { webhook_max_connections_ = 0; webhook_ip_address_ = td::string(); webhook_fix_ip_address_ = false; + webhook_secret_token_ = td::string(); webhook_set_time_ = td::Time::now(); last_webhook_error_date_ = 0; last_webhook_error_ = Status::OK(); @@ -8604,6 +8609,13 @@ void Client::do_set_webhook(PromisedQueryPtr query, bool was_deleted) { if (url.is_error()) { return fail_query(400, "Bad Request: invalid webhook URL specified", std::move(query)); } + auto secret_token = query->arg("secret_token"); + if (secret_token.size() > 256) { + return fail_query(400, "Bad Request: secret token is too long", std::move(query)); + } + if (!td::is_base64url_characters(secret_token)) { + return fail_query(400, "Bad Request: secret token contains unallowed characters", std::move(query)); + } auto *cert_file_ptr = query->file("certificate"); has_webhook_certificate_ = false; if (cert_file_ptr != nullptr) { @@ -8627,6 +8639,7 @@ void Client::do_set_webhook(PromisedQueryPtr query, bool was_deleted) { webhook_url_ = new_url.str(); webhook_set_time_ = td::Time::now(); webhook_max_connections_ = get_webhook_max_connections(query.get()); + webhook_secret_token_ = secret_token.str(); webhook_ip_address_ = query->arg("ip_address").str(); webhook_fix_ip_address_ = get_webhook_fix_ip_address(query.get()); last_webhook_error_date_ = 0; @@ -8639,7 +8652,7 @@ void Client::do_set_webhook(PromisedQueryPtr query, bool was_deleted) { webhook_id_ = td::create_actor( webhook_actor_name, actor_shared(this, webhook_generation_), tqueue_id_, url.move_as_ok(), has_webhook_certificate_ ? get_webhook_certificate_path() : "", webhook_max_connections_, query->is_internal(), - webhook_ip_address_, webhook_fix_ip_address_, parameters_); + webhook_ip_address_, webhook_fix_ip_address_, webhook_secret_token_, parameters_); // wait for webhook verified or webhook callback webhook_query_type_ = WebhookQueryType::Verify; webhook_set_query_ = std::move(query); diff --git a/telegram-bot-api/Client.h b/telegram-bot-api/Client.h index 1168835..ac46db3 100644 --- a/telegram-bot-api/Client.h +++ b/telegram-bot-api/Client.h @@ -1007,6 +1007,7 @@ class Client final : public WebhookActor::Callback { int32 webhook_max_connections_ = 0; td::string webhook_ip_address_; bool webhook_fix_ip_address_ = false; + td::string webhook_secret_token_; int32 last_webhook_error_date_ = 0; Status last_webhook_error_; double next_allowed_set_webhook_time_ = 0; diff --git a/telegram-bot-api/ClientManager.cpp b/telegram-bot-api/ClientManager.cpp index 740f92d..13bf98a 100644 --- a/telegram-bot-api/ClientManager.cpp +++ b/telegram-bot-api/ClientManager.cpp @@ -378,6 +378,11 @@ PromisedQueryPtr ClientManager::get_webhook_restore_query(td::Slice token, td::S parser.skip('/'); } + if (parser.try_skip("#secret")) { + args.emplace_back(add_string("secret_token"), add_string(parser.read_till('/'))); + parser.skip('/'); + } + if (parser.try_skip("#allow")) { args.emplace_back(add_string("allowed_updates"), add_string(parser.read_till('/'))); parser.skip('/'); diff --git a/telegram-bot-api/WebhookActor.cpp b/telegram-bot-api/WebhookActor.cpp index 1a42b81..68b9ac9 100644 --- a/telegram-bot-api/WebhookActor.cpp +++ b/telegram-bot-api/WebhookActor.cpp @@ -42,7 +42,7 @@ std::atomic WebhookActor::total_connections_count_{0}; WebhookActor::WebhookActor(td::ActorShared callback, td::int64 tqueue_id, td::HttpUrl url, td::string cert_path, td::int32 max_connections, bool from_db_flag, - td::string cached_ip_address, bool fix_ip_address, + td::string cached_ip_address, bool fix_ip_address, td::string secret_token, std::shared_ptr parameters) : callback_(std::move(callback)) , tqueue_id_(tqueue_id) @@ -51,7 +51,8 @@ WebhookActor::WebhookActor(td::ActorShared callback, td::int64 tqueue_ , parameters_(std::move(parameters)) , fix_ip_address_(fix_ip_address) , from_db_flag_(from_db_flag) - , max_connections_(max_connections) { + , max_connections_(max_connections) + , secret_token_(std::move(secret_token)) { CHECK(max_connections_ > 0); if (!cached_ip_address.empty()) { @@ -539,6 +540,9 @@ td::Status WebhookActor::send_update() { if (!url_.userinfo_.empty()) { hc.add_header("Authorization", PSLICE() << "Basic " << td::base64_encode(url_.userinfo_)); } + if (!secret_token_.empty()) { + hc.add_header("X-Telegram-Bot-Api-Secret-Token", secret_token_); + } hc.set_content_type("application/json"); hc.set_content_size(body.size()); hc.set_keep_alive(); diff --git a/telegram-bot-api/WebhookActor.h b/telegram-bot-api/WebhookActor.h index 71d702e..d5e2499 100644 --- a/telegram-bot-api/WebhookActor.h +++ b/telegram-bot-api/WebhookActor.h @@ -54,7 +54,7 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback { WebhookActor(td::ActorShared callback, td::int64 tqueue_id, td::HttpUrl url, td::string cert_path, td::int32 max_connections, bool from_db_flag, td::string cached_ip_address, bool fix_ip_address, - std::shared_ptr parameters); + td::string secret_token, std::shared_ptr parameters); void update(); @@ -163,6 +163,7 @@ class WebhookActor final : public td::HttpOutboundConnection::Callback { td::vector> ready_sockets_; td::int32 max_connections_ = 0; + td::string secret_token_; td::Container connections_; td::ListNode ready_connections_; td::FloodControlFast active_new_connection_flood_;