mirror of
https://github.com/tdlight-team/tdlight-telegram-bot-api.git
synced 2024-11-27 06:26:50 +01:00
parent
14bf658b86
commit
100a7cc846
76
README.md
76
README.md
@ -15,6 +15,7 @@ Please note that only TDLight-specific issues are suitable for this repository.
|
|||||||
- [TDLight features](#tdlight-features)
|
- [TDLight features](#tdlight-features)
|
||||||
- [Added features](#added-features)
|
- [Added features](#added-features)
|
||||||
- [Modified features](#modified-features)
|
- [Modified features](#modified-features)
|
||||||
|
- [User Mode](#user-mode)
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Dependencies](#dependencies)
|
- [Dependencies](#dependencies)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
@ -126,6 +127,81 @@ In addition, the member list now shows the full bot list (previously only the bo
|
|||||||
|
|
||||||
The bot will now receive Updates for all received media, even if a destruction timer is set.
|
The bot will now receive Updates for all received media, even if a destruction timer is set.
|
||||||
|
|
||||||
|
<a name="user-mode"></a>
|
||||||
|
### User Mode
|
||||||
|
|
||||||
|
You can allow user accounts to access the bot api with the command-line option `--allow-users` or set the env variable
|
||||||
|
`TELEGRAM_ALLOW_USERS` to `1` when using docker. User Mode is disabled by default, so only bots can access the api.
|
||||||
|
|
||||||
|
You can now log into the bot api with user accounts to create userbots running on your account.
|
||||||
|
|
||||||
|
Note: Never send your 2fa password over a plain http connection. Make sure https is enabled or use this api locally.
|
||||||
|
|
||||||
|
#### User Authorization Process
|
||||||
|
1. Send a request to `{api_url}/userlogin`
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- `phone_number`: `string`. The phone number of your Telegram Account.
|
||||||
|
|
||||||
|
Returns your `user_token` as `string`. You can use this just like a normal bot token on the `/user` endpoint
|
||||||
|
|
||||||
|
2. Send the received code to `{api_url}/user{user_token}/authcode`
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- `code`: `int`. The code send to you by Telegram In-App or by SMS
|
||||||
|
|
||||||
|
Will send `{"ok": true, "result": true}` on success.
|
||||||
|
|
||||||
|
3. Optional: Send your 2fa password to `{api_url}/user{user_token}/2fapassword`
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- `password`: `string`. Password for 2fa authentication
|
||||||
|
|
||||||
|
Will send `{"ok": true, "result": true}` on success.
|
||||||
|
|
||||||
|
4. Optional: Register the user by calling `{api_url}/user{user_token}/registerUser`.
|
||||||
|
|
||||||
|
User registration is disabled by default. You can enable it with the `--allow-users-registration` command line
|
||||||
|
option or the env variable `TELEGRAM_ALLOW_USERS_REGISTRATION` set to `1` when using docker.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- `first_name`: `string`. First name for the new account.
|
||||||
|
- `last_name`: `string`, optional. Last name for the new account.
|
||||||
|
|
||||||
|
Will send `{"ok": true, "result": true}` on success.
|
||||||
|
|
||||||
|
You are now logged in and can use all methods like in the bot api, just replace the
|
||||||
|
`/bot{bot_token}/` in your urls with `/user{token}/`.
|
||||||
|
|
||||||
|
You only need to authenticate once, the account will stay logged in. You can use the `logOut` method to log out
|
||||||
|
or simply close the session in your account settings.
|
||||||
|
|
||||||
|
Some methods are (obviously) not available as a user. This includes:
|
||||||
|
- `answerCallbackQuery`
|
||||||
|
- `setMyCommands`
|
||||||
|
- `editMessageReplyMarkup`
|
||||||
|
- `uploadStickerFile`
|
||||||
|
- `createNewStickerSet`
|
||||||
|
- `addStickerToSet`
|
||||||
|
- `setStickerPositionInSet`
|
||||||
|
- `deleteStickerFromSet`
|
||||||
|
- `setStickerSetThumb`
|
||||||
|
- `sendInvoice`
|
||||||
|
- `answerShippingQuery`
|
||||||
|
- `answerPreCheckoutQuery`
|
||||||
|
- `setPassportDataErrors`
|
||||||
|
- `sendGame`
|
||||||
|
- `setGameScore`
|
||||||
|
- `getGameHighscores`
|
||||||
|
|
||||||
|
It is also not possible to attach a `reply_markup` to any message.
|
||||||
|
|
||||||
|
Your api wrapper may behave different in
|
||||||
|
some cases, for examples command message-entities are not created in chats that don't contain any
|
||||||
|
bots, so your Command Handler may not detect it.
|
||||||
|
|
||||||
|
It is possible to have multiple user-tokens to multiple client instances on the same bot api server.
|
||||||
|
|
||||||
<a name="installation"></a>
|
<a name="installation"></a>
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@ -40,6 +40,12 @@ fi
|
|||||||
if [ -n "$TELEGRAM_NO_FILE_LIMIT" ]; then
|
if [ -n "$TELEGRAM_NO_FILE_LIMIT" ]; then
|
||||||
CUSTOM_ARGS="${CUSTOM_ARGS} --no-file-limit"
|
CUSTOM_ARGS="${CUSTOM_ARGS} --no-file-limit"
|
||||||
fi
|
fi
|
||||||
|
if [ -n "$TELEGRAM_ALLOW_USERS" ]; then
|
||||||
|
CUSTOM_ARGS="${CUSTOM_ARGS} --allow-users"
|
||||||
|
fi
|
||||||
|
if [ -n "$TELEGRAM_ALLOW_USERS_REGISTRATION" ]; then
|
||||||
|
CUSTOM_ARGS="${CUSTOM_ARGS} --allow-users-registration"
|
||||||
|
fi
|
||||||
if [ -n "$TELEGRAM_INSECURE" ]; then
|
if [ -n "$TELEGRAM_INSECURE" ]; then
|
||||||
CUSTOM_ARGS="${CUSTOM_ARGS} --insecure"
|
CUSTOM_ARGS="${CUSTOM_ARGS} --insecure"
|
||||||
fi
|
fi
|
||||||
|
2
td
2
td
@ -1 +1 @@
|
|||||||
Subproject commit b47fab11cd7dddbb2829ef1830007632332b717b
|
Subproject commit 2b92c16998d39e7bfee580defcb0109151e4fb81
|
@ -34,6 +34,21 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#define CHECK_IS_BOT() \
|
||||||
|
if (is_user_) { \
|
||||||
|
return Status::Error(BOT_ONLY_ERROR_CODE, BOT_ONLY_ERROR_DESCRIPTION); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_IS_USER() \
|
||||||
|
if (!is_user_) { \
|
||||||
|
return Status::Error(USER_ONLY_ERROR_CODE, USER_ONLY_ERROR_DESCRIPTION); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_USER_REPLY_MARKUP() \
|
||||||
|
if (reply_markup != nullptr && is_user_) { \
|
||||||
|
return Status::Error(BOT_ONLY_ERROR_CODE, BOT_ONLY_ERROR_DESCRIPTION); \
|
||||||
|
}
|
||||||
|
|
||||||
namespace telegram_bot_api {
|
namespace telegram_bot_api {
|
||||||
|
|
||||||
using td::Jsonable;
|
using td::Jsonable;
|
||||||
@ -124,6 +139,9 @@ void Client::fail_query_with_error(PromisedQueryPtr query, int32 error_code, Sli
|
|||||||
case 403:
|
case 403:
|
||||||
prefix = Slice("Forbidden");
|
prefix = Slice("Forbidden");
|
||||||
break;
|
break;
|
||||||
|
case 405:
|
||||||
|
prefix = Slice("Method Not Allowed");
|
||||||
|
break;
|
||||||
case 500:
|
case 500:
|
||||||
prefix = Slice("Internal Server Error");
|
prefix = Slice("Internal Server Error");
|
||||||
break;
|
break;
|
||||||
@ -156,11 +174,31 @@ void Client::fail_query_with_error(PromisedQueryPtr &&query, object_ptr<td_api::
|
|||||||
fail_query_with_error(std::move(query), error->code_, error->message_, default_message);
|
fail_query_with_error(std::move(query), error->code_, error->message_, default_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::Client(td::ActorShared<> parent, const td::string &bot_token, bool is_test_dc, int64 tqueue_id,
|
Client::Client(td::ActorShared<> parent, const td::string &bot_token, bool is_user, bool is_test_dc, int64 tqueue_id,
|
||||||
std::shared_ptr<const ClientParameters> parameters, td::ActorId<BotStatActor> stat_actor)
|
std::shared_ptr<const ClientParameters> parameters, td::ActorId<BotStatActor> stat_actor)
|
||||||
: parent_(std::move(parent))
|
: parent_(std::move(parent))
|
||||||
, bot_token_(bot_token)
|
, bot_token_(bot_token)
|
||||||
, bot_token_id_("<unknown>")
|
, bot_token_id_("<unknown>")
|
||||||
|
, is_user_(is_user)
|
||||||
|
, is_test_dc_(is_test_dc)
|
||||||
|
, tqueue_id_(tqueue_id)
|
||||||
|
, parameters_(std::move(parameters))
|
||||||
|
, stat_actor_(std::move(stat_actor)) {
|
||||||
|
messages_lru_root_.lru_next = &messages_lru_root_;
|
||||||
|
messages_lru_root_.lru_prev = &messages_lru_root_;
|
||||||
|
|
||||||
|
static auto is_inited = init_methods();
|
||||||
|
CHECK(is_inited);
|
||||||
|
}
|
||||||
|
|
||||||
|
Client::Client(td::ActorShared<> parent, const td::string &bot_token, const td::string &phone_number, bool is_user,
|
||||||
|
bool is_test_dc, int64 tqueue_id, std::shared_ptr<const ClientParameters> parameters,
|
||||||
|
td::ActorId<BotStatActor> stat_actor)
|
||||||
|
: parent_(std::move(parent))
|
||||||
|
, bot_token_(bot_token)
|
||||||
|
, bot_token_id_("<unknown>")
|
||||||
|
, phone_number_(phone_number)
|
||||||
|
, is_user_(is_user)
|
||||||
, is_test_dc_(is_test_dc)
|
, is_test_dc_(is_test_dc)
|
||||||
, tqueue_id_(tqueue_id)
|
, tqueue_id_(tqueue_id)
|
||||||
, parameters_(std::move(parameters))
|
, parameters_(std::move(parameters))
|
||||||
@ -2295,7 +2333,10 @@ class Client::TdOnAuthorizationCallback : public TdQueryCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_result(object_ptr<td_api::Object> result) override {
|
void on_result(object_ptr<td_api::Object> result) override {
|
||||||
bool was_ready = client_->authorization_state_->get_id() != td_api::authorizationStateWaitPhoneNumber::ID;
|
bool was_ready = client_->authorization_state_->get_id() != td_api::authorizationStateWaitPhoneNumber::ID &&
|
||||||
|
client_->authorization_state_->get_id() != td_api::authorizationStateWaitCode::ID &&
|
||||||
|
client_->authorization_state_->get_id() != td_api::authorizationStateWaitPassword::ID &&
|
||||||
|
client_->authorization_state_->get_id() != td_api::authorizationStateWaitRegistration::ID;
|
||||||
if (result->get_id() == td_api::error::ID) {
|
if (result->get_id() == td_api::error::ID) {
|
||||||
auto error = move_object_as<td_api::error>(result);
|
auto error = move_object_as<td_api::error>(result);
|
||||||
if (error->code_ == 429 || error->code_ >= 500 || (error->code_ != 401 && was_ready)) {
|
if (error->code_ == 429 || error->code_ >= 500 || (error->code_ != 401 && was_ready)) {
|
||||||
@ -2314,6 +2355,38 @@ class Client::TdOnAuthorizationCallback : public TdQueryCallback {
|
|||||||
Client *client_;
|
Client *client_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Client::TdOnAuthorizationQueryCallback : public TdQueryCallback {
|
||||||
|
public:
|
||||||
|
TdOnAuthorizationQueryCallback(Client *client, PromisedQueryPtr query) :
|
||||||
|
client_(client), query_(std::move(query)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(object_ptr<td_api::Object> result) override {
|
||||||
|
bool was_ready = client_->authorization_state_->get_id() != td_api::authorizationStateWaitPhoneNumber::ID &&
|
||||||
|
client_->authorization_state_->get_id() != td_api::authorizationStateWaitCode::ID &&
|
||||||
|
client_->authorization_state_->get_id() != td_api::authorizationStateWaitPassword::ID &&
|
||||||
|
client_->authorization_state_->get_id() != td_api::authorizationStateWaitRegistration::ID;
|
||||||
|
if (result->get_id() == td_api::error::ID) {
|
||||||
|
auto error = move_object_as<td_api::error>(result);
|
||||||
|
if (error->code_ == 429 || error->code_ >= 500 || (error->code_ != 401 && was_ready)) {
|
||||||
|
// try again
|
||||||
|
return client_->on_update_authorization_state();
|
||||||
|
}
|
||||||
|
fail_query(401, "Unauthorized: Log in failed, logging out due to " + td::oneline(to_string(error)),
|
||||||
|
std::move(query_));
|
||||||
|
LOG(WARNING) << "Logging out due to " << td::oneline(to_string(error));
|
||||||
|
client_->log_out();
|
||||||
|
} else {
|
||||||
|
answer_query(td::JsonTrue(), std::move(query_));
|
||||||
|
client_->on_update_authorization_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Client *client_;
|
||||||
|
PromisedQueryPtr query_;
|
||||||
|
};
|
||||||
|
|
||||||
class Client::TdOnInitCallback : public TdQueryCallback {
|
class Client::TdOnInitCallback : public TdQueryCallback {
|
||||||
public:
|
public:
|
||||||
explicit TdOnInitCallback(Client *client) : client_(client) {
|
explicit TdOnInitCallback(Client *client) : client_(client) {
|
||||||
@ -3237,7 +3310,7 @@ class Client::TdOnSendCustomRequestCallback : public TdQueryCallback {
|
|||||||
|
|
||||||
class Client::TdOnPingCallback : public TdQueryCallback {
|
class Client::TdOnPingCallback : public TdQueryCallback {
|
||||||
public:
|
public:
|
||||||
TdOnPingCallback(PromisedQueryPtr query)
|
explicit TdOnPingCallback(PromisedQueryPtr query)
|
||||||
: query_(std::move(query)) {
|
: query_(std::move(query)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3245,7 +3318,7 @@ class Client::TdOnPingCallback : public TdQueryCallback {
|
|||||||
if (result->get_id() == td_api::error::ID) {
|
if (result->get_id() == td_api::error::ID) {
|
||||||
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result), "Server not available");
|
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result), "Server not available");
|
||||||
}
|
}
|
||||||
CHECK(result->get_id() == 959899022); // id for return type `seconds`
|
CHECK(result->get_id() == td_api::seconds::ID);
|
||||||
|
|
||||||
auto seconds_ = move_object_as<td_api::seconds>(result);
|
auto seconds_ = move_object_as<td_api::seconds>(result);
|
||||||
answer_query(td::VirtuallyJsonableString(std::to_string(seconds_->seconds_)), std::move(query_));
|
answer_query(td::VirtuallyJsonableString(std::to_string(seconds_->seconds_)), std::move(query_));
|
||||||
@ -3386,7 +3459,7 @@ void Client::raw_event(const td::Event::Raw &event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::loop() {
|
void Client::loop() {
|
||||||
if (logging_out_ || closing_ || was_authorized_) {
|
if (logging_out_ || closing_ || was_authorized_ || waiting_for_auth_input_) {
|
||||||
while (!cmd_queue_.empty()) {
|
while (!cmd_queue_.empty()) {
|
||||||
auto query = std::move(cmd_queue_.front());
|
auto query = std::move(cmd_queue_.front());
|
||||||
cmd_queue_.pop();
|
cmd_queue_.pop();
|
||||||
@ -3947,9 +4020,20 @@ void Client::on_update_authorization_state() {
|
|||||||
case td_api::authorizationStateWaitEncryptionKey::ID:
|
case td_api::authorizationStateWaitEncryptionKey::ID:
|
||||||
return send_request(make_object<td_api::checkDatabaseEncryptionKey>(), std::make_unique<TdOnInitCallback>(this));
|
return send_request(make_object<td_api::checkDatabaseEncryptionKey>(), std::make_unique<TdOnInitCallback>(this));
|
||||||
case td_api::authorizationStateWaitPhoneNumber::ID:
|
case td_api::authorizationStateWaitPhoneNumber::ID:
|
||||||
|
if (is_user_) {
|
||||||
|
return send_request(make_object<td_api::setAuthenticationPhoneNumber>(phone_number_, nullptr),
|
||||||
|
std::make_unique<TdOnAuthorizationCallback>(this));
|
||||||
|
} else {
|
||||||
return send_request(make_object<td_api::checkAuthenticationBotToken>(bot_token_),
|
return send_request(make_object<td_api::checkAuthenticationBotToken>(bot_token_),
|
||||||
std::make_unique<TdOnAuthorizationCallback>(this));
|
std::make_unique<TdOnAuthorizationCallback>(this));
|
||||||
|
}
|
||||||
|
case td_api::authorizationStateWaitCode::ID:
|
||||||
|
case td_api::authorizationStateWaitPassword::ID:
|
||||||
|
case td_api::authorizationStateWaitRegistration::ID:
|
||||||
|
waiting_for_auth_input_ = true;
|
||||||
|
return loop();
|
||||||
case td_api::authorizationStateReady::ID: {
|
case td_api::authorizationStateReady::ID: {
|
||||||
|
waiting_for_auth_input_ = false;
|
||||||
auto user_info = get_user_info(my_id_);
|
auto user_info = get_user_info(my_id_);
|
||||||
if (my_id_ <= 0 || user_info == nullptr) {
|
if (my_id_ <= 0 || user_info == nullptr) {
|
||||||
return send_request(make_object<td_api::getMe>(), std::make_unique<TdOnAuthorizationCallback>(this));
|
return send_request(make_object<td_api::getMe>(), std::make_unique<TdOnAuthorizationCallback>(this));
|
||||||
@ -3970,12 +4054,14 @@ void Client::on_update_authorization_state() {
|
|||||||
return loop();
|
return loop();
|
||||||
}
|
}
|
||||||
case td_api::authorizationStateLoggingOut::ID:
|
case td_api::authorizationStateLoggingOut::ID:
|
||||||
|
waiting_for_auth_input_ = false;
|
||||||
if (!logging_out_) {
|
if (!logging_out_) {
|
||||||
LOG(WARNING) << "Logging out";
|
LOG(WARNING) << "Logging out";
|
||||||
logging_out_ = true;
|
logging_out_ = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case td_api::authorizationStateClosing::ID:
|
case td_api::authorizationStateClosing::ID:
|
||||||
|
waiting_for_auth_input_ = false;
|
||||||
if (!closing_) {
|
if (!closing_) {
|
||||||
LOG(WARNING) << "Closing";
|
LOG(WARNING) << "Closing";
|
||||||
closing_ = true;
|
closing_ = true;
|
||||||
@ -4334,6 +4420,7 @@ void Client::on_closed() {
|
|||||||
|
|
||||||
if (logging_out_) {
|
if (logging_out_) {
|
||||||
parameters_->shared_data_->webhook_db_->erase(bot_token_with_dc_);
|
parameters_->shared_data_->webhook_db_->erase(bot_token_with_dc_);
|
||||||
|
parameters_->shared_data_->user_db_->erase(bot_token_with_dc_);
|
||||||
|
|
||||||
class RmWorker : public td::Actor {
|
class RmWorker : public td::Actor {
|
||||||
public:
|
public:
|
||||||
@ -6029,6 +6116,17 @@ void Client::on_cmd(PromisedQueryPtr query) {
|
|||||||
return do_send_request(make_object<td_api::logOut>(), std::make_unique<TdOnOkQueryCallback>(std::move(query)));
|
return do_send_request(make_object<td_api::logOut>(), std::make_unique<TdOnOkQueryCallback>(std::move(query)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (waiting_for_auth_input_) {
|
||||||
|
if (query->method() == "authcode") {
|
||||||
|
return process_authcode_query(query);
|
||||||
|
} else if (query->method() == "2fapassword") {
|
||||||
|
return process_2fapassword_query(query);
|
||||||
|
} else if (query->method() == "registeruser" && parameters_->allow_users_registration_) {
|
||||||
|
return process_register_user_query(query);
|
||||||
|
} else {
|
||||||
|
return fail_query(404, "Not Found: method not found", std::move(query));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (logging_out_) {
|
if (logging_out_) {
|
||||||
return fail_query(LOGGING_OUT_ERROR_CODE, LOGGING_OUT_ERROR_DESCRIPTION, std::move(query));
|
return fail_query(LOGGING_OUT_ERROR_CODE, LOGGING_OUT_ERROR_DESCRIPTION, std::move(query));
|
||||||
@ -6063,6 +6161,7 @@ td::Status Client::process_get_my_commands_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_set_my_commands_query(PromisedQueryPtr &query) {
|
td::Status Client::process_set_my_commands_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(bot_commands, get_bot_commands(query.get()));
|
TRY_RESULT(bot_commands, get_bot_commands(query.get()));
|
||||||
send_request(make_object<td_api::setCommands>(std::move(bot_commands)),
|
send_request(make_object<td_api::setCommands>(std::move(bot_commands)),
|
||||||
std::make_unique<TdOnOkQueryCallback>(std::move(query)));
|
std::make_unique<TdOnOkQueryCallback>(std::move(query)));
|
||||||
@ -6208,12 +6307,14 @@ td::Status Client::process_send_voice_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_send_game_query(PromisedQueryPtr &query) {
|
td::Status Client::process_send_game_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(game_short_name, get_required_string_arg(query.get(), "game_short_name"));
|
TRY_RESULT(game_short_name, get_required_string_arg(query.get(), "game_short_name"));
|
||||||
do_send_message(make_object<td_api::inputMessageGame>(my_id_, game_short_name.str()), std::move(query));
|
do_send_message(make_object<td_api::inputMessageGame>(my_id_, game_short_name.str()), std::move(query));
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_send_invoice_query(PromisedQueryPtr &query) {
|
td::Status Client::process_send_invoice_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(title, get_required_string_arg(query.get(), "title"));
|
TRY_RESULT(title, get_required_string_arg(query.get(), "title"));
|
||||||
TRY_RESULT(description, get_required_string_arg(query.get(), "description"));
|
TRY_RESULT(description, get_required_string_arg(query.get(), "description"));
|
||||||
TRY_RESULT(payload, get_required_string_arg(query.get(), "payload"));
|
TRY_RESULT(payload, get_required_string_arg(query.get(), "payload"));
|
||||||
@ -6351,6 +6452,7 @@ td::Status Client::process_stop_poll_query(PromisedQueryPtr &query) {
|
|||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
||||||
|
CHECK_USER_REPLY_MARKUP();
|
||||||
|
|
||||||
resolve_reply_markup_bot_usernames(
|
resolve_reply_markup_bot_usernames(
|
||||||
std::move(reply_markup), std::move(query),
|
std::move(reply_markup), std::move(query),
|
||||||
@ -6446,6 +6548,7 @@ td::Status Client::process_edit_message_text_query(PromisedQueryPtr &query) {
|
|||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
||||||
|
CHECK_USER_REPLY_MARKUP();
|
||||||
|
|
||||||
if (chat_id.empty() && message_id == 0) {
|
if (chat_id.empty() && message_id == 0) {
|
||||||
TRY_RESULT(inline_message_id, get_inline_message_id(query.get()));
|
TRY_RESULT(inline_message_id, get_inline_message_id(query.get()));
|
||||||
@ -6485,6 +6588,7 @@ td::Status Client::process_edit_message_live_location_query(PromisedQueryPtr &qu
|
|||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
||||||
|
CHECK_USER_REPLY_MARKUP();
|
||||||
|
|
||||||
if (chat_id.empty() && message_id == 0) {
|
if (chat_id.empty() && message_id == 0) {
|
||||||
TRY_RESULT(inline_message_id, get_inline_message_id(query.get()));
|
TRY_RESULT(inline_message_id, get_inline_message_id(query.get()));
|
||||||
@ -6520,6 +6624,7 @@ td::Status Client::process_edit_message_media_query(PromisedQueryPtr &query) {
|
|||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
||||||
|
CHECK_USER_REPLY_MARKUP();
|
||||||
TRY_RESULT(input_media, get_input_media(query.get(), "media", false));
|
TRY_RESULT(input_media, get_input_media(query.get(), "media", false));
|
||||||
|
|
||||||
if (chat_id.empty() && message_id == 0) {
|
if (chat_id.empty() && message_id == 0) {
|
||||||
@ -6554,6 +6659,7 @@ td::Status Client::process_edit_message_caption_query(PromisedQueryPtr &query) {
|
|||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
||||||
|
CHECK_USER_REPLY_MARKUP();
|
||||||
TRY_RESULT(caption, get_caption(query.get()));
|
TRY_RESULT(caption, get_caption(query.get()));
|
||||||
|
|
||||||
if (chat_id.empty() && message_id == 0) {
|
if (chat_id.empty() && message_id == 0) {
|
||||||
@ -6584,9 +6690,11 @@ td::Status Client::process_edit_message_caption_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_edit_message_reply_markup_query(PromisedQueryPtr &query) {
|
td::Status Client::process_edit_message_reply_markup_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
TRY_RESULT(reply_markup, get_reply_markup(query.get()));
|
||||||
|
CHECK_USER_REPLY_MARKUP();
|
||||||
|
|
||||||
if (chat_id.empty() && message_id == 0) {
|
if (chat_id.empty() && message_id == 0) {
|
||||||
TRY_RESULT(inline_message_id, get_inline_message_id(query.get()));
|
TRY_RESULT(inline_message_id, get_inline_message_id(query.get()));
|
||||||
@ -6636,6 +6744,7 @@ td::Status Client::process_delete_message_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_set_game_score_query(PromisedQueryPtr &query) {
|
td::Status Client::process_set_game_score_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||||
@ -6673,6 +6782,7 @@ td::Status Client::process_set_game_score_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_get_game_high_scores_query(PromisedQueryPtr &query) {
|
td::Status Client::process_get_game_high_scores_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto chat_id = query->arg("chat_id");
|
auto chat_id = query->arg("chat_id");
|
||||||
auto message_id = get_message_id(query.get());
|
auto message_id = get_message_id(query.get());
|
||||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||||
@ -6698,6 +6808,7 @@ td::Status Client::process_get_game_high_scores_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_answer_inline_query_query(PromisedQueryPtr &query) {
|
td::Status Client::process_answer_inline_query_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto inline_query_id = td::to_integer<int64>(query->arg("inline_query_id"));
|
auto inline_query_id = td::to_integer<int64>(query->arg("inline_query_id"));
|
||||||
auto is_personal = to_bool(query->arg("is_personal"));
|
auto is_personal = to_bool(query->arg("is_personal"));
|
||||||
int32 cache_time = get_integer_arg(query.get(), "cache_time", 300, 0, 24 * 60 * 60);
|
int32 cache_time = get_integer_arg(query.get(), "cache_time", 300, 0, 24 * 60 * 60);
|
||||||
@ -6721,6 +6832,7 @@ td::Status Client::process_answer_inline_query_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_answer_callback_query_query(PromisedQueryPtr &query) {
|
td::Status Client::process_answer_callback_query_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto callback_query_id = td::to_integer<int64>(query->arg("callback_query_id"));
|
auto callback_query_id = td::to_integer<int64>(query->arg("callback_query_id"));
|
||||||
td::string text = query->arg("text").str();
|
td::string text = query->arg("text").str();
|
||||||
bool show_alert = to_bool(query->arg("show_alert"));
|
bool show_alert = to_bool(query->arg("show_alert"));
|
||||||
@ -6733,6 +6845,7 @@ td::Status Client::process_answer_callback_query_query(PromisedQueryPtr &query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_answer_shipping_query_query(PromisedQueryPtr &query) {
|
td::Status Client::process_answer_shipping_query_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto shipping_query_id = td::to_integer<int64>(query->arg("shipping_query_id"));
|
auto shipping_query_id = td::to_integer<int64>(query->arg("shipping_query_id"));
|
||||||
auto ok = to_bool(query->arg("ok"));
|
auto ok = to_bool(query->arg("ok"));
|
||||||
td::vector<object_ptr<td_api::shippingOption>> shipping_options;
|
td::vector<object_ptr<td_api::shippingOption>> shipping_options;
|
||||||
@ -6749,6 +6862,7 @@ td::Status Client::process_answer_shipping_query_query(PromisedQueryPtr &query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_answer_pre_checkout_query_query(PromisedQueryPtr &query) {
|
td::Status Client::process_answer_pre_checkout_query_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto pre_checkout_query_id = td::to_integer<int64>(query->arg("pre_checkout_query_id"));
|
auto pre_checkout_query_id = td::to_integer<int64>(query->arg("pre_checkout_query_id"));
|
||||||
auto ok = to_bool(query->arg("ok"));
|
auto ok = to_bool(query->arg("ok"));
|
||||||
td::MutableSlice error_message;
|
td::MutableSlice error_message;
|
||||||
@ -7226,6 +7340,7 @@ td::Status Client::process_get_sticker_set_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_upload_sticker_file_query(PromisedQueryPtr &query) {
|
td::Status Client::process_upload_sticker_file_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||||
auto png_sticker = get_input_file(query.get(), "png_sticker");
|
auto png_sticker = get_input_file(query.get(), "png_sticker");
|
||||||
|
|
||||||
@ -7238,6 +7353,7 @@ td::Status Client::process_upload_sticker_file_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query) {
|
td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||||
auto name = query->arg("name");
|
auto name = query->arg("name");
|
||||||
auto title = query->arg("title");
|
auto title = query->arg("title");
|
||||||
@ -7254,6 +7370,7 @@ td::Status Client::process_create_new_sticker_set_query(PromisedQueryPtr &query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_add_sticker_to_set_query(PromisedQueryPtr &query) {
|
td::Status Client::process_add_sticker_to_set_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||||
auto name = query->arg("name");
|
auto name = query->arg("name");
|
||||||
TRY_RESULT(stickers, get_input_stickers(query.get()));
|
TRY_RESULT(stickers, get_input_stickers(query.get()));
|
||||||
@ -7268,6 +7385,7 @@ td::Status Client::process_add_sticker_to_set_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_set_sticker_set_thumb_query(PromisedQueryPtr &query) {
|
td::Status Client::process_set_sticker_set_thumb_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||||
auto name = query->arg("name");
|
auto name = query->arg("name");
|
||||||
auto thumbnail = get_input_file(query.get(), "thumb");
|
auto thumbnail = get_input_file(query.get(), "thumb");
|
||||||
@ -7280,6 +7398,7 @@ td::Status Client::process_set_sticker_set_thumb_query(PromisedQueryPtr &query)
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_set_sticker_position_in_set_query(PromisedQueryPtr &query) {
|
td::Status Client::process_set_sticker_position_in_set_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto file_id = trim(query->arg("sticker"));
|
auto file_id = trim(query->arg("sticker"));
|
||||||
if (file_id.empty()) {
|
if (file_id.empty()) {
|
||||||
return Status::Error(400, "Sticker is not specified");
|
return Status::Error(400, "Sticker is not specified");
|
||||||
@ -7293,6 +7412,7 @@ td::Status Client::process_set_sticker_position_in_set_query(PromisedQueryPtr &q
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_delete_sticker_from_set_query(PromisedQueryPtr &query) {
|
td::Status Client::process_delete_sticker_from_set_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
auto file_id = trim(query->arg("sticker"));
|
auto file_id = trim(query->arg("sticker"));
|
||||||
if (file_id.empty()) {
|
if (file_id.empty()) {
|
||||||
return Status::Error(400, "Sticker is not specified");
|
return Status::Error(400, "Sticker is not specified");
|
||||||
@ -7304,6 +7424,7 @@ td::Status Client::process_delete_sticker_from_set_query(PromisedQueryPtr &query
|
|||||||
}
|
}
|
||||||
|
|
||||||
td::Status Client::process_set_passport_data_errors_query(PromisedQueryPtr &query) {
|
td::Status Client::process_set_passport_data_errors_query(PromisedQueryPtr &query) {
|
||||||
|
CHECK_IS_BOT();
|
||||||
TRY_RESULT(user_id, get_user_id(query.get()));
|
TRY_RESULT(user_id, get_user_id(query.get()));
|
||||||
TRY_RESULT(passport_element_errors, get_passport_element_errors(query.get()));
|
TRY_RESULT(passport_element_errors, get_passport_element_errors(query.get()));
|
||||||
|
|
||||||
@ -7557,6 +7678,45 @@ td::Status Client::process_ping_query(PromisedQueryPtr &query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//end custom methods impl
|
//end custom methods impl
|
||||||
|
//start costom auth methods impl
|
||||||
|
|
||||||
|
void Client::process_authcode_query(PromisedQueryPtr &query) {
|
||||||
|
auto code = query->arg("code");
|
||||||
|
if (code.empty()) {
|
||||||
|
return fail_query(400, "Bad Request: code not found", std::move(query));
|
||||||
|
}
|
||||||
|
if (authorization_state_->get_id() != td_api::authorizationStateWaitCode::ID) {
|
||||||
|
return fail_query(400, "Bad Request: currently not waiting for a code", std::move(query));
|
||||||
|
}
|
||||||
|
send_request(make_object<td_api::checkAuthenticationCode>(code.str()),
|
||||||
|
std::make_unique<TdOnAuthorizationQueryCallback>(this, std::move(query)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::process_2fapassword_query(PromisedQueryPtr &query) {
|
||||||
|
auto password = query->arg("password");
|
||||||
|
if (password.empty()) {
|
||||||
|
return fail_query(400, "Bad Request: password not found", std::move(query));
|
||||||
|
}
|
||||||
|
if (authorization_state_->get_id() != td_api::authorizationStateWaitPassword::ID) {
|
||||||
|
return fail_query(400, "Bad Request: currently not waiting for a password", std::move(query));
|
||||||
|
}
|
||||||
|
send_request(make_object<td_api::checkAuthenticationPassword>(password.str()),
|
||||||
|
std::make_unique<TdOnAuthorizationQueryCallback>(this, std::move(query)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::process_register_user_query(PromisedQueryPtr &query) {
|
||||||
|
auto first_name = query->arg("first_name");
|
||||||
|
if (first_name.empty()) {
|
||||||
|
return fail_query(400, "Bad Request: first_name not found", std::move(query));
|
||||||
|
}
|
||||||
|
auto last_name = query->arg("last_name");
|
||||||
|
if (authorization_state_->get_id() != td_api::authorizationStateWaitRegistration::ID) {
|
||||||
|
return fail_query(400, "Bad Request: currently not waiting for registration", std::move(query));
|
||||||
|
}
|
||||||
|
send_request(make_object<td_api::registerUser>(first_name.str(), last_name.str()),
|
||||||
|
std::make_unique<TdOnAuthorizationQueryCallback>(this, std::move(query)));
|
||||||
|
}
|
||||||
|
//end custom auth methods impl
|
||||||
|
|
||||||
void Client::do_get_file(object_ptr<td_api::file> file, PromisedQueryPtr query) {
|
void Client::do_get_file(object_ptr<td_api::file> file, PromisedQueryPtr query) {
|
||||||
if ((!parameters_->local_mode_ || !parameters_->no_file_limit_) &&
|
if ((!parameters_->local_mode_ || !parameters_->no_file_limit_) &&
|
||||||
@ -7776,6 +7936,9 @@ void Client::do_send_message(object_ptr<td_api::InputMessageContent> input_messa
|
|||||||
return fail_query_with_error(std::move(query), 400, r_reply_markup.error().message());
|
return fail_query_with_error(std::move(query), 400, r_reply_markup.error().message());
|
||||||
}
|
}
|
||||||
auto reply_markup = r_reply_markup.move_as_ok();
|
auto reply_markup = r_reply_markup.move_as_ok();
|
||||||
|
if (reply_markup != nullptr && is_user_) {
|
||||||
|
return fail_query_with_error(std::move(query), 405, "Method Not Allowed: reply markup not available as user.");
|
||||||
|
}
|
||||||
|
|
||||||
resolve_reply_markup_bot_usernames(
|
resolve_reply_markup_bot_usernames(
|
||||||
std::move(reply_markup), std::move(query),
|
std::move(reply_markup), std::move(query),
|
||||||
@ -9335,6 +9498,12 @@ constexpr Client::Slice Client::LOGGING_OUT_ERROR_DESCRIPTION;
|
|||||||
constexpr int Client::CLOSING_ERROR_CODE;
|
constexpr int Client::CLOSING_ERROR_CODE;
|
||||||
constexpr Client::Slice Client::CLOSING_ERROR_DESCRIPTION;
|
constexpr Client::Slice Client::CLOSING_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
constexpr int Client::BOT_ONLY_ERROR_CODE;
|
||||||
|
constexpr Client::Slice Client::BOT_ONLY_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
|
constexpr int Client::USER_ONLY_ERROR_CODE;
|
||||||
|
constexpr Client::Slice Client::USER_ONLY_ERROR_DESCRIPTION;
|
||||||
|
|
||||||
std::unordered_map<td::string, td::Status (Client::*)(PromisedQueryPtr &query)> Client::methods_;
|
std::unordered_map<td::string, td::Status (Client::*)(PromisedQueryPtr &query)> Client::methods_;
|
||||||
|
|
||||||
} // namespace telegram_bot_api
|
} // namespace telegram_bot_api
|
||||||
|
@ -38,9 +38,13 @@ namespace td_api = td::td_api;
|
|||||||
|
|
||||||
class Client : public WebhookActor::Callback {
|
class Client : public WebhookActor::Callback {
|
||||||
public:
|
public:
|
||||||
Client(td::ActorShared<> parent, const td::string &bot_token, bool is_test_dc, td::int64 tqueue_id,
|
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);
|
std::shared_ptr<const ClientParameters> parameters, td::ActorId<BotStatActor> stat_actor);
|
||||||
|
|
||||||
|
Client(td::ActorShared<> parent, const td::string &bot_token, const td::string &phone_number, bool is_user,
|
||||||
|
bool is_test_dc, td::int64 tqueue_id, std::shared_ptr<const ClientParameters> parameters,
|
||||||
|
td::ActorId<BotStatActor> stat_actor);
|
||||||
|
|
||||||
void send(PromisedQueryPtr query) override;
|
void send(PromisedQueryPtr query) override;
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
@ -82,6 +86,12 @@ class Client : public WebhookActor::Callback {
|
|||||||
static constexpr int CLOSING_ERROR_CODE = 500;
|
static constexpr int CLOSING_ERROR_CODE = 500;
|
||||||
static constexpr Slice CLOSING_ERROR_DESCRIPTION = "Internal Server Error: restart";
|
static constexpr Slice CLOSING_ERROR_DESCRIPTION = "Internal Server Error: restart";
|
||||||
|
|
||||||
|
static constexpr int BOT_ONLY_ERROR_CODE = 405;
|
||||||
|
static constexpr Slice BOT_ONLY_ERROR_DESCRIPTION = "Method Not Allowed: You can only use this method as a bot";
|
||||||
|
|
||||||
|
static constexpr int USER_ONLY_ERROR_CODE = 405;
|
||||||
|
static constexpr Slice USER_ONLY_ERROR_DESCRIPTION = "Method Not Allowed: You can only use this method as a user";
|
||||||
|
|
||||||
class JsonFile;
|
class JsonFile;
|
||||||
class JsonDatedFile;
|
class JsonDatedFile;
|
||||||
class JsonDatedFiles;
|
class JsonDatedFiles;
|
||||||
@ -149,6 +159,7 @@ class Client : public WebhookActor::Callback {
|
|||||||
|
|
||||||
class TdOnOkCallback;
|
class TdOnOkCallback;
|
||||||
class TdOnAuthorizationCallback;
|
class TdOnAuthorizationCallback;
|
||||||
|
class TdOnAuthorizationQueryCallback;
|
||||||
class TdOnInitCallback;
|
class TdOnInitCallback;
|
||||||
class TdOnGetUserProfilePhotosCallback;
|
class TdOnGetUserProfilePhotosCallback;
|
||||||
class TdOnSendMessageCallback;
|
class TdOnSendMessageCallback;
|
||||||
@ -498,6 +509,11 @@ class Client : public WebhookActor::Callback {
|
|||||||
Status process_toggle_group_invites_query(PromisedQueryPtr &query);
|
Status process_toggle_group_invites_query(PromisedQueryPtr &query);
|
||||||
Status process_ping_query(PromisedQueryPtr &query);
|
Status process_ping_query(PromisedQueryPtr &query);
|
||||||
|
|
||||||
|
//custom auth methods
|
||||||
|
void process_authcode_query(PromisedQueryPtr &query);
|
||||||
|
void process_2fapassword_query(PromisedQueryPtr &query);
|
||||||
|
void process_register_user_query(PromisedQueryPtr &query);
|
||||||
|
|
||||||
|
|
||||||
void webhook_verified(td::string cached_ip_address) override;
|
void webhook_verified(td::string cached_ip_address) override;
|
||||||
void webhook_success() override;
|
void webhook_success() override;
|
||||||
@ -823,11 +839,14 @@ class Client : public WebhookActor::Callback {
|
|||||||
bool logging_out_ = false;
|
bool logging_out_ = false;
|
||||||
bool need_close_ = false;
|
bool need_close_ = false;
|
||||||
bool clear_tqueue_ = false;
|
bool clear_tqueue_ = false;
|
||||||
|
bool waiting_for_auth_input_ = false;
|
||||||
|
|
||||||
td::ActorShared<> parent_;
|
td::ActorShared<> parent_;
|
||||||
td::string bot_token_;
|
td::string bot_token_;
|
||||||
td::string bot_token_with_dc_;
|
td::string bot_token_with_dc_;
|
||||||
td::string bot_token_id_;
|
td::string bot_token_id_;
|
||||||
|
td::string phone_number_;
|
||||||
|
bool is_user_;
|
||||||
bool is_test_dc_;
|
bool is_test_dc_;
|
||||||
int64 tqueue_id_;
|
int64 tqueue_id_;
|
||||||
double start_time_ = 0;
|
double start_time_ = 0;
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include "td/utils/StackAllocator.h"
|
#include "td/utils/StackAllocator.h"
|
||||||
#include "td/utils/StringBuilder.h"
|
#include "td/utils/StringBuilder.h"
|
||||||
#include "td/utils/Time.h"
|
#include "td/utils/Time.h"
|
||||||
|
#include "td/utils/Random.h"
|
||||||
|
#include "td/utils/base64.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
@ -62,7 +64,9 @@ void ClientManager::send(PromisedQueryPtr query) {
|
|||||||
// automatically send 429
|
// automatically send 429
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!parameters_->allow_users_ && query->is_user()) {
|
||||||
|
return fail_query(405, "Method Not Allowed: Users are not allowed to use the api", std::move(query));
|
||||||
|
}
|
||||||
td::string token = query->token().str();
|
td::string token = query->token().str();
|
||||||
if (token[0] == '0' || token.size() > 80u || token.find('/') != td::string::npos ||
|
if (token[0] == '0' || token.size() > 80u || token.find('/') != td::string::npos ||
|
||||||
token.find(':') == td::string::npos) {
|
token.find(':') == td::string::npos) {
|
||||||
@ -77,9 +81,83 @@ void ClientManager::send(PromisedQueryPtr query) {
|
|||||||
token += "/test";
|
token += "/test";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto bot_token_with_dc = PSTRING() << query->token() << (query->is_test_dc() ? ":T" : "");
|
||||||
|
if (parameters_->shared_data_->user_db_->isset(bot_token_with_dc) != query->is_user()) {
|
||||||
|
return fail_query(400, "Bad Request: Please use the correct api endpoint for bots or users", std::move(query));
|
||||||
|
}
|
||||||
|
|
||||||
auto id_it = token_to_id_.find(token);
|
auto id_it = token_to_id_.find(token);
|
||||||
if (id_it == token_to_id_.end()) {
|
if (id_it == token_to_id_.end()) {
|
||||||
std::string ip_address;
|
if (!check_flood_limits(query)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto id = clients_.create(ClientInfo{BotStatActor(stat_.actor_id(&stat_)), token, td::ActorOwn<Client>()});
|
||||||
|
auto *client_info = clients_.get(id);
|
||||||
|
auto stat_actor = client_info->stat_.actor_id(&client_info->stat_);
|
||||||
|
auto client_id = td::create_actor<Client>(
|
||||||
|
PSLICE() << "Client/" << token, actor_shared(this, id), query->token().str(), query->is_user(),
|
||||||
|
query->is_test_dc(), get_tqueue_id(r_user_id.ok(), query->is_test_dc()), parameters_, std::move(stat_actor));
|
||||||
|
|
||||||
|
auto method = query->method();
|
||||||
|
if (method != "deletewebhook" && method != "setwebhook") {
|
||||||
|
auto webhook_info = parameters_->shared_data_->webhook_db_->get(bot_token_with_dc);
|
||||||
|
if (!webhook_info.empty()) {
|
||||||
|
send_closure(client_id, &Client::send,
|
||||||
|
get_webhook_restore_query(bot_token_with_dc, query->is_user(), webhook_info, parameters_->shared_data_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clients_.get(id)->client_ = std::move(client_id);
|
||||||
|
std::tie(id_it, std::ignore) = token_to_id_.emplace(token, id);
|
||||||
|
}
|
||||||
|
auto *client_info = clients_.get(id_it->second);
|
||||||
|
|
||||||
|
if (!query->is_internal()) {
|
||||||
|
query->set_stat_actor(client_info->stat_.actor_id(&client_info->stat_));
|
||||||
|
}
|
||||||
|
send_closure(client_info->client_, &Client::send, std::move(query)); // will send 429 if the client is already closed
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClientManager::user_login(PromisedQueryPtr query) {
|
||||||
|
if (!check_flood_limits(query, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!parameters_->allow_users_) {
|
||||||
|
return fail_query(405, "Method Not Allowed: Users are not allowed to use the api", std::move(query));
|
||||||
|
}
|
||||||
|
td::MutableSlice r_phone_number = query->arg("phone_number");
|
||||||
|
if (r_phone_number.size() < 5 || r_phone_number.size() > 15) {
|
||||||
|
return fail_query(401, "Unauthorized: invalid phone number specified", std::move(query));
|
||||||
|
}
|
||||||
|
td::int64 phone_number = 0;
|
||||||
|
for (char const &c: r_phone_number) {
|
||||||
|
if (isdigit(c)) {
|
||||||
|
phone_number = phone_number * 10 + (c - 48);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
td::UInt256 token_data;
|
||||||
|
td::Random::secure_bytes(token_data.raw, sizeof(token_data));
|
||||||
|
td::string user_token = td::to_string(phone_number) + ":" + td::base64url_encode(token_data.as_slice());
|
||||||
|
auto user_token_with_dc = PSTRING() << user_token << (query->is_test_dc() ? ":T" : "");
|
||||||
|
|
||||||
|
long token_hash = std::hash<td::string>{}(user_token);
|
||||||
|
|
||||||
|
auto id = clients_.create(ClientInfo{BotStatActor(stat_.actor_id(&stat_)), user_token, td::ActorOwn<Client>()});
|
||||||
|
auto *client_info = clients_.get(id);
|
||||||
|
auto stat_actor = client_info->stat_.actor_id(&client_info->stat_);
|
||||||
|
auto client_id = td::create_actor<Client>(
|
||||||
|
PSLICE() << "Client/" << user_token, actor_shared(this, id), user_token, td::to_string(phone_number),
|
||||||
|
true, query->is_test_dc(), get_tqueue_id(token_hash, query->is_test_dc()), parameters_, std::move(stat_actor));
|
||||||
|
|
||||||
|
clients_.get(id)->client_ = std::move(client_id);
|
||||||
|
auto id_it = token_to_id_.end();
|
||||||
|
std::tie(id_it, std::ignore) = token_to_id_.emplace(user_token, id);
|
||||||
|
parameters_->shared_data_->user_db_->set(user_token_with_dc, "1");
|
||||||
|
answer_query(td::VirtuallyJsonableString(user_token), std::move(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientManager::check_flood_limits(PromisedQueryPtr &query, bool is_user_login) {
|
||||||
|
td::string ip_address;
|
||||||
if (query->peer_address().is_valid() && !query->peer_address().is_reserved()) { // external connection
|
if (query->peer_address().is_valid() && !query->peer_address().is_reserved()) { // external connection
|
||||||
ip_address = query->peer_address().get_ip_str().str();
|
ip_address = query->peer_address().get_ip_str().str();
|
||||||
} else {
|
} else {
|
||||||
@ -94,50 +172,33 @@ void ClientManager::send(PromisedQueryPtr query) {
|
|||||||
ip_address = tmp.get_ip_str().str();
|
ip_address = tmp.get_ip_str().str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG(DEBUG) << "Receive incoming query for new bot " << token << " from " << query->peer_address();
|
LOG(DEBUG) << "Receive incoming query for new bot " << query->token() << " from " << query->peer_address();
|
||||||
if (!ip_address.empty()) {
|
if (!ip_address.empty()) {
|
||||||
LOG(DEBUG) << "Check Client creation flood control for IP address " << ip_address;
|
LOG(DEBUG) << "Check Client creation flood control for IP address " << ip_address;
|
||||||
|
if (is_user_login) {
|
||||||
|
ip_address += "/user";
|
||||||
|
}
|
||||||
auto res = flood_controls_.emplace(std::move(ip_address), td::FloodControlFast());
|
auto res = flood_controls_.emplace(std::move(ip_address), td::FloodControlFast());
|
||||||
auto &flood_control = res.first->second;
|
auto &flood_control = res.first->second;
|
||||||
if (res.second) {
|
if (res.second) {
|
||||||
|
if (is_user_login) {
|
||||||
|
flood_control.add_limit(60, 5); // 5 in a minute
|
||||||
|
flood_control.add_limit(60 * 60, 15); // 15 in an hour
|
||||||
|
} else {
|
||||||
flood_control.add_limit(60, 20); // 20 in a minute
|
flood_control.add_limit(60, 20); // 20 in a minute
|
||||||
flood_control.add_limit(60 * 60, 600); // 600 in an hour
|
flood_control.add_limit(60 * 60, 600); // 600 in an hour
|
||||||
}
|
}
|
||||||
td::uint32 now = static_cast<td::uint32>(td::Time::now());
|
}
|
||||||
|
auto now = static_cast<td::uint32>(td::Time::now());
|
||||||
td::uint32 wakeup_at = flood_control.get_wakeup_at();
|
td::uint32 wakeup_at = flood_control.get_wakeup_at();
|
||||||
if (wakeup_at > now) {
|
if (wakeup_at > now) {
|
||||||
LOG(INFO) << "Failed to create Client from IP address " << ip_address;
|
LOG(INFO) << "Failed to create Client from IP address " << ip_address;
|
||||||
return query->set_retry_after_error(static_cast<int>(wakeup_at - now) + 1);
|
query->set_retry_after_error(static_cast<int>(wakeup_at - now) + 1);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
flood_control.add_event(static_cast<td::int32>(now));
|
flood_control.add_event(static_cast<td::int32>(now));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
auto id = clients_.create(ClientInfo{BotStatActor(stat_.actor_id(&stat_)), token, td::ActorOwn<Client>()});
|
|
||||||
auto *client_info = clients_.get(id);
|
|
||||||
auto stat_actor = client_info->stat_.actor_id(&client_info->stat_);
|
|
||||||
auto client_id = td::create_actor<Client>(
|
|
||||||
PSLICE() << "Client/" << token, actor_shared(this, id), query->token().str(), query->is_test_dc(),
|
|
||||||
get_tqueue_id(r_user_id.ok(), query->is_test_dc()), parameters_, std::move(stat_actor));
|
|
||||||
|
|
||||||
auto method = query->method();
|
|
||||||
if (method != "deletewebhook" && method != "setwebhook") {
|
|
||||||
auto bot_token_with_dc = PSTRING() << query->token() << (query->is_test_dc() ? ":T" : "");
|
|
||||||
auto webhook_info = parameters_->shared_data_->webhook_db_->get(bot_token_with_dc);
|
|
||||||
if (!webhook_info.empty()) {
|
|
||||||
send_closure(client_id, &Client::send,
|
|
||||||
get_webhook_restore_query(bot_token_with_dc, webhook_info, parameters_->shared_data_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clients_.get(id)->client_ = std::move(client_id);
|
|
||||||
std::tie(id_it, std::ignore) = token_to_id_.emplace(token, id);
|
|
||||||
}
|
|
||||||
auto *client_info = clients_.get(id_it->second);
|
|
||||||
|
|
||||||
if (!query->is_internal()) {
|
|
||||||
query->set_stat_actor(client_info->stat_.actor_id(&client_info->stat_));
|
|
||||||
}
|
|
||||||
send_closure(client_info->client_, &Client::send, std::move(query)); // will send 429 if the client is already closed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::get_stats(td::PromiseActor<td::BufferSlice> promise,
|
void ClientManager::get_stats(td::PromiseActor<td::BufferSlice> promise,
|
||||||
@ -297,13 +358,19 @@ void ClientManager::start_up() {
|
|||||||
parameters_->shared_data_->tqueue_ = std::move(tqueue);
|
parameters_->shared_data_->tqueue_ = std::move(tqueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// init webhook_db
|
// init webhook_db and user_db
|
||||||
auto concurrent_webhook_db = td::make_unique<td::BinlogKeyValue<td::ConcurrentBinlog>>();
|
auto concurrent_webhook_db = td::make_unique<td::BinlogKeyValue<td::ConcurrentBinlog>>();
|
||||||
auto status = concurrent_webhook_db->init("webhooks_db.binlog", td::DbKey::empty(), scheduler_id);
|
auto status = concurrent_webhook_db->init("webhooks_db.binlog", td::DbKey::empty(), scheduler_id);
|
||||||
LOG_IF(FATAL, status.is_error()) << "Can't open webhooks_db.binlog " << status.error();
|
LOG_IF(FATAL, status.is_error()) << "Can't open webhooks_db.binlog " << status.error();
|
||||||
parameters_->shared_data_->webhook_db_ = std::move(concurrent_webhook_db);
|
parameters_->shared_data_->webhook_db_ = std::move(concurrent_webhook_db);
|
||||||
|
|
||||||
|
auto concurrent_user_db = td::make_unique<td::BinlogKeyValue<td::ConcurrentBinlog>>();
|
||||||
|
status = concurrent_user_db->init("user_db.binlog", td::DbKey::empty(), scheduler_id);
|
||||||
|
LOG_IF(FATAL, status.is_error()) << "Can't open user_db.binlog " << status.error();
|
||||||
|
parameters_->shared_data_->user_db_ = std::move(concurrent_user_db);
|
||||||
|
|
||||||
auto &webhook_db = *parameters_->shared_data_->webhook_db_;
|
auto &webhook_db = *parameters_->shared_data_->webhook_db_;
|
||||||
|
auto &user_db = *parameters_->shared_data_->user_db_;
|
||||||
for (auto key_value : webhook_db.get_all()) {
|
for (auto key_value : webhook_db.get_all()) {
|
||||||
if (!token_range_(td::to_integer<td::uint64>(key_value.first))) {
|
if (!token_range_(td::to_integer<td::uint64>(key_value.first))) {
|
||||||
LOG(WARNING) << "DROP WEBHOOK: " << key_value.first << " ---> " << key_value.second;
|
LOG(WARNING) << "DROP WEBHOOK: " << key_value.first << " ---> " << key_value.second;
|
||||||
@ -311,12 +378,13 @@ void ClientManager::start_up() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto query = get_webhook_restore_query(key_value.first, key_value.second, parameters_->shared_data_);
|
auto query = get_webhook_restore_query(key_value.first, user_db.isset(key_value.first), key_value.second, parameters_->shared_data_);
|
||||||
send_closure_later(actor_id(this), &ClientManager::send, std::move(query));
|
send_closure_later(actor_id(this), &ClientManager::send, std::move(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PromisedQueryPtr ClientManager::get_webhook_restore_query(td::Slice token, td::Slice webhook_info,
|
PromisedQueryPtr ClientManager::get_webhook_restore_query(td::Slice token, bool is_user, td::Slice webhook_info,
|
||||||
std::shared_ptr<SharedData> shared_data) {
|
std::shared_ptr<SharedData> shared_data) {
|
||||||
// create Query with empty promise
|
// create Query with empty promise
|
||||||
td::vector<td::BufferSlice> containers;
|
td::vector<td::BufferSlice> containers;
|
||||||
@ -364,7 +432,7 @@ PromisedQueryPtr ClientManager::get_webhook_restore_query(td::Slice token, td::S
|
|||||||
args.emplace_back(add_string("url"), add_string(parser.read_all()));
|
args.emplace_back(add_string("url"), add_string(parser.read_all()));
|
||||||
|
|
||||||
const auto method = add_string("setwebhook");
|
const auto method = add_string("setwebhook");
|
||||||
auto query = std::make_unique<Query>(std::move(containers), token, is_test_dc, method, std::move(args),
|
auto query = std::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<std::pair<td::MutableSlice, td::MutableSlice>>(),
|
||||||
td::vector<td::HttpFile>(), std::move(shared_data), td::IPAddress());
|
td::vector<td::HttpFile>(), std::move(shared_data), td::IPAddress());
|
||||||
query->set_internal(true);
|
query->set_internal(true);
|
||||||
@ -392,6 +460,7 @@ void ClientManager::close_db() {
|
|||||||
|
|
||||||
parameters_->shared_data_->tqueue_->close(mpromise.get_promise());
|
parameters_->shared_data_->tqueue_->close(mpromise.get_promise());
|
||||||
parameters_->shared_data_->webhook_db_->close(mpromise.get_promise());
|
parameters_->shared_data_->webhook_db_->close(mpromise.get_promise());
|
||||||
|
parameters_->shared_data_->user_db_->close(mpromise.get_promise());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::finish_close() {
|
void ClientManager::finish_close() {
|
||||||
|
@ -42,6 +42,9 @@ class ClientManager final : public td::Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void send(PromisedQueryPtr query);
|
void send(PromisedQueryPtr query);
|
||||||
|
void user_login(PromisedQueryPtr query);
|
||||||
|
|
||||||
|
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);
|
void get_stats(td::PromiseActor<td::BufferSlice> promise, td::vector<std::pair<td::string, td::string>> args);
|
||||||
|
|
||||||
@ -68,7 +71,7 @@ class ClientManager final : public td::Actor {
|
|||||||
|
|
||||||
static td::int64 get_tqueue_id(td::int64 user_id, bool is_test_dc);
|
static td::int64 get_tqueue_id(td::int64 user_id, bool is_test_dc);
|
||||||
|
|
||||||
static PromisedQueryPtr get_webhook_restore_query(td::Slice token, td::Slice webhook_info,
|
static PromisedQueryPtr get_webhook_restore_query(td::Slice token, bool is_user, td::Slice webhook_info,
|
||||||
std::shared_ptr<SharedData> shared_data);
|
std::shared_ptr<SharedData> shared_data);
|
||||||
|
|
||||||
void start_up() override;
|
void start_up() override;
|
||||||
|
@ -34,6 +34,7 @@ struct SharedData {
|
|||||||
// not thread-safe
|
// not thread-safe
|
||||||
td::ListNode query_list_;
|
td::ListNode query_list_;
|
||||||
td::unique_ptr<td::KeyValueSyncInterface> webhook_db_;
|
td::unique_ptr<td::KeyValueSyncInterface> webhook_db_;
|
||||||
|
td::unique_ptr<td::KeyValueSyncInterface> user_db_;
|
||||||
td::unique_ptr<td::TQueue> tqueue_;
|
td::unique_ptr<td::TQueue> tqueue_;
|
||||||
|
|
||||||
double unix_time_difference_{-1e100};
|
double unix_time_difference_{-1e100};
|
||||||
@ -58,6 +59,8 @@ struct ClientParameters {
|
|||||||
bool allow_http_ = false;
|
bool allow_http_ = false;
|
||||||
bool use_relative_path_ = false;
|
bool use_relative_path_ = false;
|
||||||
bool no_file_limit_ = true;
|
bool no_file_limit_ = true;
|
||||||
|
bool allow_users_ = false;
|
||||||
|
bool allow_users_registration_ = false;
|
||||||
|
|
||||||
td::int32 api_id_ = 0;
|
td::int32 api_id_ = 0;
|
||||||
td::string api_hash_;
|
td::string api_hash_;
|
||||||
|
@ -28,12 +28,24 @@ void HttpConnection::handle(td::unique_ptr<td::HttpQuery> http_query,
|
|||||||
return send_http_error(404, "Not Found: absolute URI is specified in the Request-Line");
|
return send_http_error(404, "Not Found: absolute URI is specified in the Request-Line");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!url_path_parser.try_skip("/bot")) {
|
bool is_login = false;
|
||||||
|
bool is_user = false;
|
||||||
|
if (url_path_parser.try_skip("/bot")) {
|
||||||
|
} else if (url_path_parser.try_skip("/userlogin")) {
|
||||||
|
is_user = true;
|
||||||
|
is_login = true;
|
||||||
|
} else if (url_path_parser.try_skip("/user")) {
|
||||||
|
is_user = true;
|
||||||
|
} else {
|
||||||
return send_http_error(404, "Not Found");
|
return send_http_error(404, "Not Found");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto token = url_path_parser.read_till('/');
|
td::MutableSlice token;
|
||||||
bool is_test_dc = false;
|
bool is_test_dc = false;
|
||||||
|
td::MutableSlice method;
|
||||||
|
if (!is_login) {
|
||||||
|
token = url_path_parser.read_till('/');
|
||||||
|
is_test_dc = false;
|
||||||
if (url_path_parser.try_skip("/test")) {
|
if (url_path_parser.try_skip("/test")) {
|
||||||
is_test_dc = true;
|
is_test_dc = true;
|
||||||
}
|
}
|
||||||
@ -42,8 +54,11 @@ void HttpConnection::handle(td::unique_ptr<td::HttpQuery> http_query,
|
|||||||
return send_http_error(404, "Not Found");
|
return send_http_error(404, "Not Found");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto method = url_path_parser.data();
|
method = url_path_parser.data();
|
||||||
auto query = std::make_unique<Query>(std::move(http_query->container_), token, is_test_dc, method,
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto query = std::make_unique<Query>(std::move(http_query->container_), token, is_user, is_test_dc, method,
|
||||||
std::move(http_query->args_), std::move(http_query->headers_),
|
std::move(http_query->args_), std::move(http_query->headers_),
|
||||||
std::move(http_query->files_), shared_data_, http_query->peer_address_);
|
std::move(http_query->files_), shared_data_, http_query->peer_address_);
|
||||||
|
|
||||||
@ -52,7 +67,11 @@ void HttpConnection::handle(td::unique_ptr<td::HttpQuery> http_query,
|
|||||||
td::init_promise_future(&promise, &future);
|
td::init_promise_future(&promise, &future);
|
||||||
future.set_event(td::EventCreator::yield(actor_id()));
|
future.set_event(td::EventCreator::yield(actor_id()));
|
||||||
auto promised_query = PromisedQueryPtr(query.release(), PromiseDeleter(std::move(promise)));
|
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));
|
send_closure(client_manager_, &ClientManager::send, std::move(promised_query));
|
||||||
|
}
|
||||||
result_ = std::move(future);
|
result_ = std::move(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ namespace telegram_bot_api {
|
|||||||
|
|
||||||
std::unordered_map<td::string, std::unique_ptr<td::VirtuallyJsonable>> empty_parameters;
|
std::unordered_map<td::string, std::unique_ptr<td::VirtuallyJsonable>> empty_parameters;
|
||||||
|
|
||||||
Query::Query(td::vector<td::BufferSlice> &&container, td::Slice token, bool is_test_dc, td::MutableSlice method,
|
Query::Query(td::vector<td::BufferSlice> &&container, td::Slice token, bool is_user, bool is_test_dc, td::MutableSlice method,
|
||||||
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&args,
|
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&args,
|
||||||
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&headers, td::vector<td::HttpFile> &&files,
|
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&headers, td::vector<td::HttpFile> &&files,
|
||||||
std::shared_ptr<SharedData> shared_data, const td::IPAddress &peer_address)
|
std::shared_ptr<SharedData> shared_data, const td::IPAddress &peer_address)
|
||||||
@ -31,6 +31,7 @@ Query::Query(td::vector<td::BufferSlice> &&container, td::Slice token, bool is_t
|
|||||||
, peer_address_(peer_address)
|
, peer_address_(peer_address)
|
||||||
, container_(std::move(container))
|
, container_(std::move(container))
|
||||||
, token_(token)
|
, token_(token)
|
||||||
|
, is_user_(is_user)
|
||||||
, is_test_dc_(is_test_dc)
|
, is_test_dc_(is_test_dc)
|
||||||
, method_(method)
|
, method_(method)
|
||||||
, args_(std::move(args))
|
, args_(std::move(args))
|
||||||
|
@ -37,6 +37,9 @@ class Query : public td::ListNode {
|
|||||||
td::Slice token() const {
|
td::Slice token() const {
|
||||||
return token_;
|
return token_;
|
||||||
}
|
}
|
||||||
|
bool is_user() const {
|
||||||
|
return is_user_;
|
||||||
|
}
|
||||||
bool is_test_dc() const {
|
bool is_test_dc() const {
|
||||||
return is_test_dc_;
|
return is_test_dc_;
|
||||||
}
|
}
|
||||||
@ -122,7 +125,7 @@ class Query : public td::ListNode {
|
|||||||
is_internal_ = is_internal;
|
is_internal_ = is_internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
Query(td::vector<td::BufferSlice> &&container, td::Slice token, bool is_test_dc, td::MutableSlice method,
|
Query(td::vector<td::BufferSlice> &&container, td::Slice token, bool is_user, bool is_test_dc, td::MutableSlice method,
|
||||||
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&args,
|
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&args,
|
||||||
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&headers, td::vector<td::HttpFile> &&files,
|
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> &&headers, td::vector<td::HttpFile> &&files,
|
||||||
std::shared_ptr<SharedData> shared_data, const td::IPAddress &peer_address);
|
std::shared_ptr<SharedData> shared_data, const td::IPAddress &peer_address);
|
||||||
@ -155,6 +158,7 @@ class Query : public td::ListNode {
|
|||||||
// request
|
// request
|
||||||
td::vector<td::BufferSlice> container_;
|
td::vector<td::BufferSlice> container_;
|
||||||
td::Slice token_;
|
td::Slice token_;
|
||||||
|
bool is_user_;
|
||||||
bool is_test_dc_;
|
bool is_test_dc_;
|
||||||
td::MutableSlice method_;
|
td::MutableSlice method_;
|
||||||
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> args_;
|
td::vector<std::pair<td::MutableSlice, td::MutableSlice>> args_;
|
||||||
|
@ -586,7 +586,7 @@ void WebhookActor::handle(td::unique_ptr<td::HttpQuery> response) {
|
|||||||
method != "logout" && !td::begins_with(method, "get")) {
|
method != "logout" && !td::begins_with(method, "get")) {
|
||||||
VLOG(webhook) << "Receive request " << method << " in response to webhook";
|
VLOG(webhook) << "Receive request " << method << " in response to webhook";
|
||||||
auto query =
|
auto query =
|
||||||
std::make_unique<Query>(std::move(response->container_), td::MutableSlice(), false, td::MutableSlice(),
|
std::make_unique<Query>(std::move(response->container_), td::MutableSlice(), false, false, td::MutableSlice(),
|
||||||
std::move(response->args_), std::move(response->headers_),
|
std::move(response->args_), std::move(response->headers_),
|
||||||
std::move(response->files_), parameters_->shared_data_, response->peer_address_);
|
std::move(response->files_), parameters_->shared_data_, response->peer_address_);
|
||||||
auto promised_query =
|
auto promised_query =
|
||||||
|
@ -176,6 +176,9 @@ int main(int argc, char *argv[]) {
|
|||||||
[&] { parameters->no_file_limit_ = true; });
|
[&] { parameters->no_file_limit_ = true; });
|
||||||
options.add_option('\0', "insecure", "allow the Bot API to send request via insecure HTTP", [&] { parameters->allow_http_ = true; });
|
options.add_option('\0', "insecure", "allow the Bot API to send request via insecure HTTP", [&] { parameters->allow_http_ = true; });
|
||||||
options.add_option('\0', "relative", "use relative file path in local mode", [&] { parameters->use_relative_path_ = true; });
|
options.add_option('\0', "relative", "use relative file path in local mode", [&] { parameters->use_relative_path_ = true; });
|
||||||
|
options.add_option('\0', "allow-users", "allow user accounts to use the API", [&] { parameters->allow_users_ = true; });
|
||||||
|
options.add_option('\0', "allow-users-registration", "allow user accounts to be registered on the API",
|
||||||
|
[&] { parameters->allow_users_registration_ = true; });
|
||||||
|
|
||||||
options.add_checked_option(
|
options.add_checked_option(
|
||||||
'\0', "api-id",
|
'\0', "api-id",
|
||||||
|
Loading…
Reference in New Issue
Block a user