aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlevlam <levlam@telegram.org>2026-03-13 19:48:58 +0300
committerlevlam <levlam@telegram.org>2026-03-13 19:48:58 +0300
commit9738ba6e10d6a141283ab8df90bfdb867a366aff (patch)
treef8b0dcbcdec1372a9a1823cc45cdcce86859523b
parent758423ab22faf282e643aef01d891a674f2e6019 (diff)
Add td_api::internalLinkTypeRequestManagedBot.
-rw-r--r--td/generate/scheme/td_api.tl12
-rw-r--r--td/telegram/LinkManager.cpp49
-rw-r--r--td/telegram/LinkManager.h1
-rw-r--r--test/link.cpp19
4 files changed, 79 insertions, 2 deletions
diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl
index 43ea15fa7..fa95ce319 100644
--- a/td/generate/scheme/td_api.tl
+++ b/td/generate/scheme/td_api.tl
@@ -3395,8 +3395,8 @@ keyboardButtonTypeRequestChat id:int32 chat_is_channel:Bool restrict_chat_is_for
//@description A button that requests creation of a managed bot by the current user; available only in private chats. Use the method createManagedBot to complete the request
//@id Unique button identifier
-//@suggested_name Suggested name for the bot; empty if not specified
-//@suggested_username Suggested username for the bot; empty if not specified
+//@suggested_name Suggested name for the bot; may be empty if not specified
+//@suggested_username Suggested username for the bot; may be empty if not specified
keyboardButtonTypeRequestManagedBot id:int32 suggested_name:string suggested_username:string = KeyboardButtonType;
//@description A button that opens a Web App by calling getWebAppUrl @url An HTTP URL to pass to getWebAppUrl
@@ -8849,6 +8849,14 @@ internalLinkTypePublicChat chat_username:string draft_text:string open_profile:B
//-"This code can be used to allow someone to log in to your Telegram account. To confirm Telegram login, please go to Settings > Devices > Scan QR and scan the code" needs to be shown
internalLinkTypeQrCodeAuthentication = InternalLinkType;
+//@description The link is a link for creation of a managed bot. Call searchPublicChat with the given manager bot username.
+//-If the chat is found and it is a bot, then show bot creation confirmation dialog with the given suggested_bot_username and suggested_bot_name.
+//-If user agrees, call createBot with via_link == true to create the bot
+//@manager_bot_username Username of the bot which will manage the new bot
+//@suggested_bot_username Suggested username for the bot
+//@suggested_bot_name Suggested name for the bot; may be empty if not specified
+internalLinkTypeRequestManagedBot manager_bot_username:string suggested_bot_username:string suggested_bot_name:string = InternalLinkType;
+
//@description The link forces restore of App Store purchases when opened. For official iOS application only
internalLinkTypeRestorePurchases = InternalLinkType;
diff --git a/td/telegram/LinkManager.cpp b/td/telegram/LinkManager.cpp
index c19bfe58b..217518008 100644
--- a/td/telegram/LinkManager.cpp
+++ b/td/telegram/LinkManager.cpp
@@ -1111,6 +1111,24 @@ class LinkManager::InternalLinkQrCodeAuthentication final : public InternalLink
}
};
+class LinkManager::InternalLinkRequestManagedBot final : public InternalLink {
+ string manager_bot_username_;
+ string bot_username_;
+ string bot_name_;
+
+ td_api::object_ptr<td_api::InternalLinkType> get_internal_link_type_object() const final {
+ return td_api::make_object<td_api::internalLinkTypeRequestManagedBot>(manager_bot_username_, bot_username_,
+ bot_name_);
+ }
+
+ public:
+ InternalLinkRequestManagedBot(string &&manager_bot_username, string &&bot_username, string &&bot_name)
+ : manager_bot_username_(std::move(manager_bot_username))
+ , bot_username_(std::move(bot_username))
+ , bot_name_(std::move(bot_name)) {
+ }
+};
+
class LinkManager::InternalLinkRestorePurchases final : public InternalLink {
td_api::object_ptr<td_api::InternalLinkType> get_internal_link_type_object() const final {
return td_api::make_object<td_api::internalLinkTypeRestorePurchases>();
@@ -2505,6 +2523,14 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice que
// stargift_auction?slug=<slug>
return td::make_unique<InternalLinkGiftAuction>(slug);
}
+ } else if (path.size() == 1 && path[0] == "newbot") {
+ // newbot?manager=<manager_bot_username>&username=<new_bot_username>&name=<new_bot_name>
+ auto manager_bot_username = get_arg("manager");
+ auto new_bot_username = get_arg("username");
+ if (is_valid_username(manager_bot_username) && is_valid_username(new_bot_username)) {
+ return td::make_unique<InternalLinkRequestManagedBot>(std::move(manager_bot_username),
+ std::move(new_bot_username), get_arg("name"));
+ }
}
if (!path.empty() && !path[0].empty()) {
return td::make_unique<InternalLinkUnknownDeepLink>(PSTRING() << "tg://" << query);
@@ -2714,6 +2740,9 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_t_me_link_query(Slice q
return td::make_unique<InternalLinkInstantView>(
PSTRING() << get_t_me_url() << "iv" << copy_arg("url") << copy_arg("rhash"), get_arg("url"));
}
+ } else if (path.size() >= 3u && path[0] == "newbot" && is_valid_username(path[1]) && is_valid_username(path[2])) {
+ // /newbot/<manager_bot_username>/<new_bot_username>?name=<new_bot_name>
+ return td::make_unique<InternalLinkRequestManagedBot>(string(path[1]), string(path[2]), get_arg("name"));
} else if (is_valid_username(path[0]) && path[0] != "i") {
if (path.size() >= 2 && to_integer<int64>(path[1]) > 0) {
// /<username>/12345?single&thread=<thread_id>&comment=<message_id>&t=<media_timestamp>
@@ -3535,6 +3564,26 @@ Result<string> LinkManager::get_internal_link_impl(const td_api::InternalLinkTyp
}
case td_api::internalLinkTypeQrCodeAuthentication::ID:
return Status::Error("The link must never be generated client-side");
+ case td_api::internalLinkTypeRequestManagedBot::ID: {
+ auto link = static_cast<const td_api::internalLinkTypeRequestManagedBot *>(type_ptr);
+ if (!is_valid_username(link->manager_bot_username_)) {
+ return Status::Error(400, "Invalid manager bot username specified");
+ }
+ if (!is_valid_username(link->suggested_bot_username_)) {
+ return Status::Error(400, "Invalid suggested bot username specified");
+ }
+ if (!check_utf8(link->suggested_bot_name_)) {
+ return Status::Error(400, "Suggested bot name must be encoded in UTF-8");
+ }
+ if (is_internal) {
+ return PSTRING() << "tg://newbot?manager=" << link->manager_bot_username_
+ << "&username=" << link->suggested_bot_username_
+ << "&name=" << url_encode(link->suggested_bot_name_);
+ } else {
+ return PSTRING() << get_t_me_url() << "newbot/" << link->manager_bot_username_ << '/'
+ << link->suggested_bot_username_ << "?name=" << url_encode(link->suggested_bot_name_);
+ }
+ }
case td_api::internalLinkTypeRestorePurchases::ID:
if (!is_internal) {
return Status::Error("HTTP link is unavailable for the link type");
diff --git a/td/telegram/LinkManager.h b/td/telegram/LinkManager.h
index 284660c4b..b80aa5e95 100644
--- a/td/telegram/LinkManager.h
+++ b/td/telegram/LinkManager.h
@@ -180,6 +180,7 @@ class LinkManager final : public Actor {
class InternalLinkProxy;
class InternalLinkPublicDialog;
class InternalLinkQrCodeAuthentication;
+ class InternalLinkRequestManagedBot;
class InternalLinkRestorePurchases;
class InternalLinkSavedMessages;
class InternalLinkSearch;
diff --git a/test/link.cpp b/test/link.cpp
index 2dad978db..3f618400e 100644
--- a/test/link.cpp
+++ b/test/link.cpp
@@ -468,6 +468,12 @@ static auto qr_code_authentication() {
return td::td_api::make_object<td::td_api::internalLinkTypeQrCodeAuthentication>();
}
+static auto request_managed_bot(const td::string &manager_bot_username, const td::string &suggested_bot_username,
+ const td::string &suggested_bot_name) {
+ return td::td_api::make_object<td::td_api::internalLinkTypeRequestManagedBot>(
+ manager_bot_username, suggested_bot_username, suggested_bot_name);
+}
+
static auto restore_purchases() {
return td::td_api::make_object<td::td_api::internalLinkTypeRestorePurchases>();
}
@@ -1819,6 +1825,19 @@ TEST(Link, parse_internal_link_part4) {
parse_internal_link("tg:premium_multigift?ref=abcde%ff", unknown_deep_link("tg://premium_multigift?ref=abcde%ff"));
parse_internal_link("tg://premium_multigift?ref=", premium_gift_purchase(""));
+ parse_internal_link("t.me/newbot/0manager/tesager?name=", public_chat("newbot"));
+ parse_internal_link("t.me/newbot/manager/0testbot?name=", public_chat("newbot"));
+ parse_internal_link("t.me/newbot/manager/testbot?name=", request_managed_bot("manager", "testbot", ""));
+ parse_internal_link("t.me/newbot/manager/testbot?name=asd", request_managed_bot("manager", "testbot", "asd"));
+
+ parse_internal_link("tg:newbot?manager=managerot&username=testbot&name=asd",
+ request_managed_bot("managerot", "testbot", "asd"));
+ parse_internal_link("tg:newbot?manager=managerot&username=testbot", request_managed_bot("managerot", "testbot", ""));
+ parse_internal_link("tg:newbot?manager=0manager&username=testbot",
+ unknown_deep_link("tg://newbot?manager=0manager&username=testbot"));
+ parse_internal_link("tg:newbot?manager=managerot&username=0testbot",
+ unknown_deep_link("tg://newbot?manager=managerot&username=0testbot"));
+
parse_internal_link("tg://settings", settings());
parse_internal_link("tg://setting", unknown_deep_link("tg://setting"));
parse_internal_link("tg://settings?asdsa?D?SADasD?asD", settings());