Move check_dialog_username to DialogManager.
This commit is contained in:
parent
466c841b4e
commit
9a90089879
@ -863,31 +863,6 @@ class UpdateProfileQuery final : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
class CheckUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<bool> promise_;
|
||||
|
||||
public:
|
||||
explicit CheckUsernameQuery(Promise<bool> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(const string &username) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::account_checkUsername(username), {{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_checkUsername>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
promise_.set_value(result_ptr.move_as_ok());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
|
||||
@ -1116,45 +1091,6 @@ class UpdateEmojiStatusQuery final : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
class CheckChannelUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<bool> promise_;
|
||||
ChannelId channel_id_;
|
||||
string username_;
|
||||
|
||||
public:
|
||||
explicit CheckChannelUsernameQuery(Promise<bool> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(ChannelId channel_id, const string &username) {
|
||||
channel_id_ = channel_id;
|
||||
tl_object_ptr<telegram_api::InputChannel> input_channel;
|
||||
if (channel_id.is_valid()) {
|
||||
input_channel = td_->contacts_manager_->get_input_channel(channel_id);
|
||||
} else {
|
||||
input_channel = make_tl_object<telegram_api::inputChannelEmpty>();
|
||||
}
|
||||
CHECK(input_channel != nullptr);
|
||||
send_query(
|
||||
G()->net_query_creator().create(telegram_api::channels_checkUsername(std::move(input_channel), username)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::channels_checkUsername>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
promise_.set_value(result_ptr.move_as_ok());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (channel_id_.is_valid()) {
|
||||
td_->contacts_manager_->on_get_channel_error(channel_id_, status, "CheckChannelUsernameQuery");
|
||||
}
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UpdateChannelUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
ChannelId channel_id_;
|
||||
@ -5269,6 +5205,14 @@ string ContactsManager::get_channel_first_username(ChannelId channel_id) const {
|
||||
return c->usernames.get_first_username();
|
||||
}
|
||||
|
||||
string ContactsManager::get_channel_editable_username(ChannelId channel_id) const {
|
||||
auto c = get_channel(channel_id);
|
||||
if (c == nullptr) {
|
||||
return string();
|
||||
}
|
||||
return c->usernames.get_editable_username();
|
||||
}
|
||||
|
||||
UserId ContactsManager::get_secret_chat_user_id(SecretChatId secret_chat_id) const {
|
||||
auto c = get_secret_chat(secret_chat_id);
|
||||
if (c == nullptr) {
|
||||
@ -5450,131 +5394,6 @@ ChatId ContactsManager::get_unsupported_chat_id() {
|
||||
return ChatId(static_cast<int64>(G()->is_test_dc() ? 10304875 : 1535424647));
|
||||
}
|
||||
|
||||
void ContactsManager::check_dialog_username(DialogId dialog_id, const string &username,
|
||||
Promise<CheckDialogUsernameResult> &&promise) {
|
||||
if (dialog_id != DialogId() && !dialog_id.is_valid()) {
|
||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||
}
|
||||
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User: {
|
||||
if (dialog_id.get_user_id() != get_my_id()) {
|
||||
return promise.set_error(Status::Error(400, "Can't check username for private chat with other user"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogType::Channel: {
|
||||
auto c = get_channel(dialog_id.get_channel_id());
|
||||
if (c == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||
}
|
||||
if (!get_channel_status(c).is_creator()) {
|
||||
return promise.set_error(Status::Error(400, "Not enough rights to change username"));
|
||||
}
|
||||
|
||||
if (username == c->usernames.get_editable_username()) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Ok);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogType::None:
|
||||
break;
|
||||
case DialogType::Chat:
|
||||
case DialogType::SecretChat:
|
||||
if (username.empty()) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Ok);
|
||||
}
|
||||
return promise.set_error(Status::Error(400, "Chat can't have username"));
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
if (username.empty()) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Ok);
|
||||
}
|
||||
|
||||
if (!is_allowed_username(username) && username.size() != 4) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Invalid);
|
||||
}
|
||||
|
||||
auto request_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<bool> result) mutable {
|
||||
if (result.is_error()) {
|
||||
auto error = result.move_as_error();
|
||||
if (error.message() == "CHANNEL_PUBLIC_GROUP_NA") {
|
||||
return promise.set_value(CheckDialogUsernameResult::PublicGroupsUnavailable);
|
||||
}
|
||||
if (error.message() == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||
return promise.set_value(CheckDialogUsernameResult::PublicDialogsTooMany);
|
||||
}
|
||||
if (error.message() == "USERNAME_INVALID") {
|
||||
return promise.set_value(CheckDialogUsernameResult::Invalid);
|
||||
}
|
||||
if (error.message() == "USERNAME_PURCHASE_AVAILABLE") {
|
||||
if (begins_with(G()->get_option_string("my_phone_number"), "1")) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Invalid);
|
||||
}
|
||||
return promise.set_value(CheckDialogUsernameResult::Purchasable);
|
||||
}
|
||||
return promise.set_error(std::move(error));
|
||||
}
|
||||
|
||||
promise.set_value(result.ok() ? CheckDialogUsernameResult::Ok : CheckDialogUsernameResult::Occupied);
|
||||
});
|
||||
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
return td_->create_handler<CheckUsernameQuery>(std::move(request_promise))->send(username);
|
||||
case DialogType::Channel:
|
||||
return td_->create_handler<CheckChannelUsernameQuery>(std::move(request_promise))
|
||||
->send(dialog_id.get_channel_id(), username);
|
||||
case DialogType::None:
|
||||
return td_->create_handler<CheckChannelUsernameQuery>(std::move(request_promise))->send(ChannelId(), username);
|
||||
case DialogType::Chat:
|
||||
case DialogType::SecretChat:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::CheckChatUsernameResult> ContactsManager::get_check_chat_username_result_object(
|
||||
CheckDialogUsernameResult result) {
|
||||
switch (result) {
|
||||
case CheckDialogUsernameResult::Ok:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultOk>();
|
||||
case CheckDialogUsernameResult::Invalid:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultUsernameInvalid>();
|
||||
case CheckDialogUsernameResult::Occupied:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultUsernameOccupied>();
|
||||
case CheckDialogUsernameResult::Purchasable:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultUsernamePurchasable>();
|
||||
case CheckDialogUsernameResult::PublicDialogsTooMany:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultPublicChatsTooMany>();
|
||||
case CheckDialogUsernameResult::PublicGroupsUnavailable:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultPublicGroupsUnavailable>();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool ContactsManager::is_allowed_username(const string &username) {
|
||||
if (!is_valid_username(username)) {
|
||||
return false;
|
||||
}
|
||||
if (username.size() < 5) {
|
||||
return false;
|
||||
}
|
||||
auto username_lowered = to_lower(username);
|
||||
if (username_lowered.find("admin") == 0 || username_lowered.find("telegram") == 0 ||
|
||||
username_lowered.find("support") == 0 || username_lowered.find("security") == 0 ||
|
||||
username_lowered.find("settings") == 0 || username_lowered.find("contacts") == 0 ||
|
||||
username_lowered.find("service") == 0 || username_lowered.find("telegraph") == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 ContactsManager::get_user_was_online(const User *u, UserId user_id, int32 unix_time) const {
|
||||
if (u == nullptr || u->is_deleted) {
|
||||
return 0;
|
||||
|
@ -171,6 +171,7 @@ class ContactsManager final : public Actor {
|
||||
|
||||
string get_user_first_username(UserId user_id) const;
|
||||
string get_channel_first_username(ChannelId channel_id) const;
|
||||
string get_channel_editable_username(ChannelId channel_id) const;
|
||||
|
||||
int32 get_secret_chat_date(SecretChatId secret_chat_id) const;
|
||||
int32 get_secret_chat_ttl(SecretChatId secret_chat_id) const;
|
||||
@ -353,20 +354,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void invalidate_user_full(UserId user_id);
|
||||
|
||||
enum class CheckDialogUsernameResult : uint8 {
|
||||
Ok,
|
||||
Invalid,
|
||||
Occupied,
|
||||
Purchasable,
|
||||
PublicDialogsTooMany,
|
||||
PublicGroupsUnavailable
|
||||
};
|
||||
|
||||
void check_dialog_username(DialogId dialog_id, const string &username, Promise<CheckDialogUsernameResult> &&promise);
|
||||
|
||||
static td_api::object_ptr<td_api::CheckChatUsernameResult> get_check_chat_username_result_object(
|
||||
CheckDialogUsernameResult result);
|
||||
|
||||
void add_contact(Contact contact, bool share_phone_number, Promise<Unit> &&promise);
|
||||
|
||||
std::pair<vector<UserId>, vector<int32>> import_contacts(const vector<Contact> &contacts, int64 &random_id,
|
||||
@ -1387,8 +1374,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void set_my_id(UserId my_id);
|
||||
|
||||
static bool is_allowed_username(const string &username);
|
||||
|
||||
void on_set_emoji_status(EmojiStatus emoji_status, Promise<Unit> &&promise);
|
||||
|
||||
void on_update_user_name(User *u, UserId user_id, string &&first_name, string &&last_name);
|
||||
|
@ -37,6 +37,70 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
class CheckUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<bool> promise_;
|
||||
|
||||
public:
|
||||
explicit CheckUsernameQuery(Promise<bool> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(const string &username) {
|
||||
send_query(G()->net_query_creator().create(telegram_api::account_checkUsername(username), {{"me"}}));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::account_checkUsername>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
promise_.set_value(result_ptr.move_as_ok());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class CheckChannelUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<bool> promise_;
|
||||
ChannelId channel_id_;
|
||||
string username_;
|
||||
|
||||
public:
|
||||
explicit CheckChannelUsernameQuery(Promise<bool> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(ChannelId channel_id, const string &username) {
|
||||
channel_id_ = channel_id;
|
||||
telegram_api::object_ptr<telegram_api::InputChannel> input_channel;
|
||||
if (channel_id.is_valid()) {
|
||||
input_channel = td_->contacts_manager_->get_input_channel(channel_id);
|
||||
} else {
|
||||
input_channel = telegram_api::make_object<telegram_api::inputChannelEmpty>();
|
||||
}
|
||||
CHECK(input_channel != nullptr);
|
||||
send_query(
|
||||
G()->net_query_creator().create(telegram_api::channels_checkUsername(std::move(input_channel), username)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::channels_checkUsername>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
promise_.set_value(result_ptr.move_as_ok());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (channel_id_.is_valid()) {
|
||||
td_->contacts_manager_->on_get_channel_error(channel_id_, status, "CheckChannelUsernameQuery");
|
||||
}
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class ResolveUsernameQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
string username_;
|
||||
@ -1675,6 +1739,110 @@ void DialogManager::on_dialog_usernames_received(DialogId dialog_id, const Usern
|
||||
}
|
||||
}
|
||||
|
||||
void DialogManager::check_dialog_username(DialogId dialog_id, const string &username,
|
||||
Promise<CheckDialogUsernameResult> &&promise) {
|
||||
if (dialog_id != DialogId() && !have_dialog_force(dialog_id, "check_dialog_username")) {
|
||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||
}
|
||||
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User: {
|
||||
if (dialog_id != get_my_dialog_id()) {
|
||||
return promise.set_error(Status::Error(400, "Can't check username for private chat with other user"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogType::Channel: {
|
||||
auto channel_id = dialog_id.get_channel_id();
|
||||
if (!td_->contacts_manager_->get_channel_status(channel_id).is_creator()) {
|
||||
return promise.set_error(Status::Error(400, "Not enough rights to change username"));
|
||||
}
|
||||
if (username == td_->contacts_manager_->get_channel_editable_username(channel_id)) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Ok);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DialogType::None:
|
||||
break;
|
||||
case DialogType::Chat:
|
||||
case DialogType::SecretChat:
|
||||
if (!username.empty()) {
|
||||
return promise.set_error(Status::Error(400, "The chat can't have a username"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
if (username.empty()) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Ok);
|
||||
}
|
||||
|
||||
if (!is_allowed_username(username) && username.size() != 4) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Invalid);
|
||||
}
|
||||
|
||||
auto request_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<bool> result) mutable {
|
||||
if (result.is_error()) {
|
||||
auto error = result.move_as_error();
|
||||
if (error.message() == "CHANNEL_PUBLIC_GROUP_NA") {
|
||||
return promise.set_value(CheckDialogUsernameResult::PublicGroupsUnavailable);
|
||||
}
|
||||
if (error.message() == "CHANNELS_ADMIN_PUBLIC_TOO_MUCH") {
|
||||
return promise.set_value(CheckDialogUsernameResult::PublicDialogsTooMany);
|
||||
}
|
||||
if (error.message() == "USERNAME_INVALID") {
|
||||
return promise.set_value(CheckDialogUsernameResult::Invalid);
|
||||
}
|
||||
if (error.message() == "USERNAME_PURCHASE_AVAILABLE") {
|
||||
if (begins_with(G()->get_option_string("my_phone_number"), "1")) {
|
||||
return promise.set_value(CheckDialogUsernameResult::Invalid);
|
||||
}
|
||||
return promise.set_value(CheckDialogUsernameResult::Purchasable);
|
||||
}
|
||||
return promise.set_error(std::move(error));
|
||||
}
|
||||
|
||||
promise.set_value(result.ok() ? CheckDialogUsernameResult::Ok : CheckDialogUsernameResult::Occupied);
|
||||
});
|
||||
|
||||
switch (dialog_id.get_type()) {
|
||||
case DialogType::User:
|
||||
return td_->create_handler<CheckUsernameQuery>(std::move(request_promise))->send(username);
|
||||
case DialogType::Channel:
|
||||
return td_->create_handler<CheckChannelUsernameQuery>(std::move(request_promise))
|
||||
->send(dialog_id.get_channel_id(), username);
|
||||
case DialogType::None:
|
||||
return td_->create_handler<CheckChannelUsernameQuery>(std::move(request_promise))->send(ChannelId(), username);
|
||||
case DialogType::Chat:
|
||||
case DialogType::SecretChat:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::CheckChatUsernameResult> DialogManager::get_check_chat_username_result_object(
|
||||
CheckDialogUsernameResult result) {
|
||||
switch (result) {
|
||||
case CheckDialogUsernameResult::Ok:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultOk>();
|
||||
case CheckDialogUsernameResult::Invalid:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultUsernameInvalid>();
|
||||
case CheckDialogUsernameResult::Occupied:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultUsernameOccupied>();
|
||||
case CheckDialogUsernameResult::Purchasable:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultUsernamePurchasable>();
|
||||
case CheckDialogUsernameResult::PublicDialogsTooMany:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultPublicChatsTooMany>();
|
||||
case CheckDialogUsernameResult::PublicGroupsUnavailable:
|
||||
return td_api::make_object<td_api::checkChatUsernameResultPublicGroupsUnavailable>();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DialogManager::send_resolve_dialog_username_query(const string &username, Promise<Unit> &&promise) {
|
||||
td_->create_handler<ResolveUsernameQuery>(std::move(promise))->send(username);
|
||||
}
|
||||
|
@ -172,6 +172,19 @@ class DialogManager final : public Actor {
|
||||
|
||||
void on_dialog_usernames_received(DialogId dialog_id, const Usernames &usernames, bool from_database);
|
||||
|
||||
enum class CheckDialogUsernameResult : uint8 {
|
||||
Ok,
|
||||
Invalid,
|
||||
Occupied,
|
||||
Purchasable,
|
||||
PublicDialogsTooMany,
|
||||
PublicGroupsUnavailable
|
||||
};
|
||||
void check_dialog_username(DialogId dialog_id, const string &username, Promise<CheckDialogUsernameResult> &&promise);
|
||||
|
||||
static td_api::object_ptr<td_api::CheckChatUsernameResult> get_check_chat_username_result_object(
|
||||
CheckDialogUsernameResult result);
|
||||
|
||||
void resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> promise);
|
||||
|
||||
DialogId get_resolved_dialog_by_username(const string &username) const;
|
||||
|
@ -5240,14 +5240,14 @@ void Td::on_request(uint64 id, td_api::checkChatUsername &request) {
|
||||
CLEAN_INPUT_STRING(request.username_);
|
||||
CREATE_REQUEST_PROMISE();
|
||||
auto query_promise = PromiseCreator::lambda(
|
||||
[promise = std::move(promise)](Result<ContactsManager::CheckDialogUsernameResult> result) mutable {
|
||||
[promise = std::move(promise)](Result<DialogManager::CheckDialogUsernameResult> result) mutable {
|
||||
if (result.is_error()) {
|
||||
promise.set_error(result.move_as_error());
|
||||
} else {
|
||||
promise.set_value(ContactsManager::get_check_chat_username_result_object(result.ok()));
|
||||
promise.set_value(DialogManager::get_check_chat_username_result_object(result.ok()));
|
||||
}
|
||||
});
|
||||
contacts_manager_->check_dialog_username(DialogId(request.chat_id_), request.username_, std::move(query_promise));
|
||||
dialog_manager_->check_dialog_username(DialogId(request.chat_id_), request.username_, std::move(query_promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getCreatedPublicChats &request) {
|
||||
|
@ -268,6 +268,23 @@ bool is_valid_username(Slice username) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_allowed_username(Slice username) {
|
||||
if (!is_valid_username(username)) {
|
||||
return false;
|
||||
}
|
||||
if (username.size() < 5) {
|
||||
return false;
|
||||
}
|
||||
auto username_lowered = to_lower(username);
|
||||
if (username_lowered.find("admin") == 0 || username_lowered.find("telegram") == 0 ||
|
||||
username_lowered.find("support") == 0 || username_lowered.find("security") == 0 ||
|
||||
username_lowered.find("settings") == 0 || username_lowered.find("contacts") == 0 ||
|
||||
username_lowered.find("service") == 0 || username_lowered.find("telegraph") == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int64 get_vector_hash(const vector<uint64> &numbers) {
|
||||
uint64 acc = 0;
|
||||
for (auto number : numbers) {
|
||||
|
@ -36,6 +36,9 @@ bool is_empty_string(const string &str) TD_WARN_UNUSED_RESULT;
|
||||
// checks whether a string could be a valid username
|
||||
bool is_valid_username(Slice username);
|
||||
|
||||
// checks whether a string can be set as a username
|
||||
bool is_allowed_username(Slice username);
|
||||
|
||||
// calculates hash of list of uint64
|
||||
int64 get_vector_hash(const vector<uint64> &numbers) TD_WARN_UNUSED_RESULT;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user