Add API support to manage Telegram proxies.

This adds new endpoints: getProxies, addProxy, deleteProxy, enableProxy
and disableProxy.
The yaml doc file has been updated to hopefully correct information.
This commit is contained in:
David Guillen Fandos 2021-07-04 21:22:23 +02:00
parent 1c8ab81135
commit de37889af1
3 changed files with 518 additions and 0 deletions

View File

@ -2080,6 +2080,322 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/getProxies:
post:
tags:
- added
description: |-
Returns all configured proxies. Requires no parameters.
responses:
'200':
description: ''
content:
application/json:
schema:
type: object
properties:
ok:
default: true
type: boolean
result:
type: array
items:
$ref: '#/components/schemas/Proxy'
required:
- ok
- result
default:
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/addProxy:
post:
tags:
- added
description: |-
Adds a proxy.
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
server:
description: Server hostname or IP address to reach the proxy server.
type: string
port:
description: TCP port where the server is listening for incomming connections.
type: integer
type:
description: Type of proxy to be added. Must be either `mtproto` or `socks5`. MTProto proxies must provide a `secret` and Socks5 proxies can a `username` and `password`.
type: string
username:
description: Username used to authenticate against a Socks5 proxy.
type: string
password:
description: Password used to authenticate against a Socks5 proxy.
type: string
secret:
description: Secret used to authenticate against an MTProto proxy.
type: string
required:
- server
- port
- type
multipart/form-data:
schema:
type: object
properties:
server:
description: Server hostname or IP address to reach the proxy server.
type: string
port:
description: TCP port where the server is listening for incomming connections.
type: integer
type:
description: Type of proxy to be added. Must be either `mtproto` or `socks5`. MTProto proxies must provide a `secret` and Socks5 proxies can a `username` and `password`.
type: string
username:
description: Username used to authenticate against a Socks5 proxy.
type: string
password:
description: Password used to authenticate against a Socks5 proxy.
type: string
secret:
description: Secret used to authenticate against an MTProto proxy.
type: string
required:
- server
- port
- type
application/json:
schema:
type: object
properties:
server:
description: Server hostname or IP address to reach the proxy server.
type: string
port:
description: TCP port where the server is listening for incomming connections.
type: integer
type:
description: Type of proxy to be added. Must be either `mtproto` or `socks5`. MTProto proxies must provide a `secret` and Socks5 proxies can a `username` and `password`.
type: string
username:
description: Username used to authenticate against a Socks5 proxy.
type: string
password:
description: Password used to authenticate against a Socks5 proxy.
type: string
secret:
description: Secret used to authenticate against an MTProto proxy.
type: string
required:
- server
- port
- type
required: true
responses:
'200':
description: ''
content:
application/json:
schema:
type: object
properties:
ok:
default: true
type: boolean
result:
$ref: '#/components/schemas/Proxy'
required:
- ok
- result
default:
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/deleteProxy:
post:
tags:
- added
description: |-
Deletes a proxy.
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
multipart/form-data:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
application/json:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
required: true
responses:
'200':
description: ''
content:
application/json:
schema:
type: object
properties:
ok:
default: true
type: boolean
result:
default: true
type: boolean
required:
- ok
- result
default:
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/enableProxy:
post:
tags:
- added
description: |-
Enables the specified proxy. Takes immediate effect.
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
multipart/form-data:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
application/json:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
required: true
responses:
'200':
description: ''
content:
application/json:
schema:
type: object
properties:
ok:
default: true
type: boolean
result:
default: true
type: boolean
required:
- ok
- result
default:
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/disableProxy:
post:
tags:
- added
description: |-
Disables the specified proxy. Takes immediate effect.
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
multipart/form-data:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
application/json:
schema:
type: object
properties:
proxy_id:
description: The id that uniquely identifies that proxy server.
type: integer
required:
- proxy_id
required: true
responses:
'200':
description: ''
content:
application/json:
schema:
type: object
properties:
ok:
default: true
type: boolean
result:
default: true
type: boolean
required:
- ok
- result
default:
description: ''
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/getUpdates:
post:
@ -12102,6 +12418,44 @@ components:
type: string
required:
- text
Proxy:
description: Contains a proxy definition.
type: object
properties:
id:
description: 'Unique ID of the proxy'
type: integer
last_used_date:
description: 'Unix timestamp indicating when the proxy was used for the last time.'
type: integer
is_enabled:
description: 'Whether the bot is being used at the moment.'
type: boolean
server:
description: 'Hostname or IP of the proxy server.'
type: string
port:
description: 'TCP port where the proxy server listens.'
type: integer
type:
description: 'Type of proxy server, either socks5 or mtproto.'
type: string
username:
description: 'Username to authenticate to the proxy server.'
type: string
password:
description: 'Password to authenticate to the proxy server.'
type: string
secret:
description: 'Secret to authenticate to the proxy server.'
type: string
required:
- id
- last_used_date
- is_enabled
- server
- port
- type
externalDocs:
description: The Bot API is an HTTP-based interface created for developers keen on building bots for Telegram.
url: 'https://core.telegram.org/bots/api'

View File

@ -289,6 +289,11 @@ bool Client::init_methods() {
methods_.emplace("togglegroupinvites", &Client::process_toggle_group_invites_query);
methods_.emplace("ping", &Client::process_ping_query);
methods_.emplace("getmemorystats", &Client::process_get_memory_stats_query);
methods_.emplace("getproxies", &Client::process_get_proxies_query);
methods_.emplace("addproxy", &Client::process_add_proxy_query);
methods_.emplace("deleteproxy", &Client::process_delete_proxy_query);
methods_.emplace("enableproxy", &Client::process_enable_proxy_query);
methods_.emplace("disableproxy", &Client::process_disable_proxy_query);
//custom user methods
methods_.emplace("getchats", &Client::process_get_chats_query);
@ -2686,6 +2691,56 @@ class Client::JsonMessagesArray : public Jsonable {
Client *client_;
};
class Client::JsonProxy : public Jsonable {
public:
explicit JsonProxy(object_ptr<td_api::proxy> &proxy) : proxy_(proxy) {
}
void store(JsonValueScope *scope) const {
auto object = scope->enter_object();
object("id", proxy_->id_);
object("last_used_date", proxy_->last_used_date_);
object("is_enabled", td::JsonBool(proxy_->is_enabled_));
object("server", proxy_->server_);
object("port", proxy_->port_);
switch (proxy_->type_->get_id()) {
case td_api::proxyTypeSocks5::ID:
{
auto ptype = static_cast<td_api::proxyTypeSocks5 *>(proxy_->type_.get());
object("type", "socks5");
object("username", ptype->username_);
object("password", ptype->password_);
}
break;
case td_api::proxyTypeMtproto::ID:
{
auto ptype = static_cast<td_api::proxyTypeMtproto *>(proxy_->type_.get());
object("type", "mtproto");
object("secret", ptype->secret_);
}
break;
};
}
private:
object_ptr<td_api::proxy> &proxy_;
};
class Client::JsonProxiesArray : public Jsonable {
public:
explicit JsonProxiesArray(object_ptr<td_api::proxies> &proxies) : proxies_(proxies) {
}
void store(JsonValueScope *scope) const {
auto array = scope->enter_array();
for (auto &proxy : proxies_->proxies_) {
array << JsonProxy(proxy);
}
}
private:
object_ptr<td_api::proxies> &proxies_;
};
//end custom Json objects impl
class Client::TdOnOkCallback : public TdQueryCallback {
@ -3879,6 +3934,46 @@ class Client::TdOnGetCallbackQueryAnswerCallback : public TdQueryCallback {
PromisedQueryPtr query_;
};
class Client::TdOnGetProxiesQueryCallback : public TdQueryCallback {
public:
explicit TdOnGetProxiesQueryCallback(PromisedQueryPtr query) : query_(std::move(query)) {
CHECK(query_ != nullptr);
}
void on_result(object_ptr<td_api::Object> result) override {
if (result->get_id() == td_api::error::ID) {
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result));
}
CHECK(result->get_id() == td_api::proxies::ID);
auto proxies = move_object_as<td_api::proxies>(result);
answer_query(JsonProxiesArray(proxies), std::move(query_));
}
private:
PromisedQueryPtr query_;
};
class Client::TdOnAddProxyQueryCallback : public TdQueryCallback {
public:
explicit TdOnAddProxyQueryCallback(PromisedQueryPtr query) : query_(std::move(query)) {
CHECK(query_ != nullptr);
}
void on_result(object_ptr<td_api::Object> result) override {
if (result->get_id() == td_api::error::ID) {
return fail_query_with_error(std::move(query_), move_object_as<td_api::error>(result));
}
CHECK(result->get_id() == td_api::proxy::ID);
auto proxy = move_object_as<td_api::proxy>(result);
answer_query(JsonProxy(proxy), std::move(query_));
}
private:
PromisedQueryPtr query_;
};
//end custom callbacks impl
void Client::close() {
@ -8638,6 +8733,66 @@ td::Status Client::process_get_memory_stats_query(PromisedQueryPtr &query) {
*/
return Status::OK();
}
td::Status Client::process_get_proxies_query(PromisedQueryPtr &query) {
send_request(make_object<td_api::getProxies>(),
std::make_unique<TdOnGetProxiesQueryCallback>(std::move(query)));
return Status::OK();
}
td::Status Client::process_add_proxy_query(PromisedQueryPtr &query) {
TRY_RESULT(server, get_required_string_arg(query.get(), "server"));
TRY_RESULT(proxy_type, get_required_string_arg(query.get(), "type"));
td::int32 port = get_integer_arg(query.get(), "port", 0, 0, 65535);
if (!port) {
return Status::Error(400, PSLICE() << "Parameter port with a value between 1-65535 is required");
}
td_api::object_ptr<td_api::ProxyType> type;
td::to_lower_inplace(proxy_type);
if (proxy_type == "mtproto") {
TRY_RESULT(proxy_secret, get_required_string_arg(query.get(), "secret"));
type = td_api::make_object<td_api::proxyTypeMtproto>(proxy_secret.str());
} else if (proxy_type == "socks5") {
auto proxy_user = query->arg("username");
auto proxy_pass = query->arg("password");
type = td_api::make_object<td_api::proxyTypeSocks5>(proxy_user.str(), proxy_pass.str());
} else {
return Status::Error(400, "Unsupported proxy type");
}
send_request(make_object<td_api::addProxy>(server.str(), port, false, std::move(type)),
std::make_unique<TdOnAddProxyQueryCallback>(std::move(query)));
return Status::OK();
}
td::Status Client::process_delete_proxy_query(PromisedQueryPtr &query) {
int32 pid = get_integer_arg(query.get(), "proxy_id", 0, 0);
if (pid == 0) {
return Status::Error(400, PSLICE() << "Invalid proxy_id specified");
}
send_request(make_object<td_api::removeProxy>(pid),
std::make_unique<TdOnOkQueryCallback>(std::move(query)));
return Status::OK();
}
td::Status Client::process_enable_proxy_query(PromisedQueryPtr &query) {
int32 pid = get_integer_arg(query.get(), "proxy_id", 0, 0);
if (pid == 0) {
return Status::Error(400, PSLICE() << "Invalid proxy_id specified");
}
send_request(make_object<td_api::enableProxy>(pid),
std::make_unique<TdOnOkQueryCallback>(std::move(query)));
return Status::OK();
}
td::Status Client::process_disable_proxy_query(PromisedQueryPtr &query) {
send_request(make_object<td_api::disableProxy>(),
std::make_unique<TdOnOkQueryCallback>(std::move(query)));
return Status::OK();
}
//end custom methods impl
//start custom user methods impl

View File

@ -167,6 +167,8 @@ class Client : public WebhookActor::Callback {
class JsonChats;
class JsonChatsNearby;
class JsonMessagesArray;
class JsonProxy;
class JsonProxiesArray;
//stop custom Json objects
class TdOnOkCallback;
@ -211,6 +213,8 @@ class Client : public WebhookActor::Callback {
class TdOnReturnChatCallback;
class TdOnReturnMessagesCallback;
class TdOnGetCallbackQueryAnswerCallback;
class TdOnGetProxiesQueryCallback;
class TdOnAddProxyQueryCallback;
//end custom callbacks
void on_get_reply_message(int64 chat_id, object_ptr<td_api::message> reply_to_message);
@ -575,6 +579,11 @@ class Client : public WebhookActor::Callback {
Status process_toggle_group_invites_query(PromisedQueryPtr &query);
Status process_ping_query(PromisedQueryPtr &query);
Status process_get_memory_stats_query(PromisedQueryPtr &query);
Status process_get_proxies_query(PromisedQueryPtr &query);
Status process_add_proxy_query(PromisedQueryPtr &query);
Status process_delete_proxy_query(PromisedQueryPtr &query);
Status process_enable_proxy_query(PromisedQueryPtr &query);
Status process_disable_proxy_query(PromisedQueryPtr &query);
//custom user methods
Status process_get_chats_query(PromisedQueryPtr &query);