Add td_api::transferChatOwnership.

GitOrigin-RevId: ce897af94815412b2e8ff09c727e04b284726b41
This commit is contained in:
levlam 2019-10-17 17:05:01 +03:00
parent 47625f39f0
commit 8206c05952
9 changed files with 169 additions and 23 deletions

View File

@ -288,7 +288,7 @@ botCommand command:string description:string = BotCommand;
botInfo description:string commands:vector<botCommand> = BotInfo;
//@description Represents a location of a chat @location The location @address Location address; 1-64 characters, as defined by the chat creator
//@description Represents a location of a chat @location The location @address Location address; 1-64 characters, as defined by the chat owner
chatLocation location:location address:string = ChatLocation;
@ -333,7 +333,7 @@ chatPermissions can_send_messages:Bool can_send_media_messages:Bool can_send_pol
//@class ChatMemberStatus @description Provides information about the status of a member in a chat
//@description The user is the creator of a chat and has all the administrator privileges @is_member True, if the user is a member of the chat
//@description The user is the owner of a chat and has all the administrator privileges @is_member True, if the user is a member of the chat
chatMemberStatusCreator is_member:Bool = ChatMemberStatus;
//@description The user is a member of a chat and has some additional privileges. In basic groups, administrators can edit and delete messages sent by others, add new members, and ban unprivileged members. In supergroups and channels, there are more detailed options for administrator privileges
@ -378,7 +378,7 @@ chatMembers total_count:int32 members:vector<chatMember> = ChatMembers;
//@description Returns contacts of the user
chatMembersFilterContacts = ChatMembersFilter;
//@description Returns the creator and administrators
//@description Returns the owner and administrators
chatMembersFilterAdministrators = ChatMembersFilter;
//@description Returns all chat members, including restricted chat members
@ -402,7 +402,7 @@ supergroupMembersFilterRecent = SupergroupMembersFilter;
//@description Returns contacts of the user, which are members of the supergroup or channel @query Query to search for
supergroupMembersFilterContacts query:string = SupergroupMembersFilter;
//@description Returns the creator and administrators
//@description Returns the owner and administrators
supergroupMembersFilterAdministrators = SupergroupMembersFilter;
//@description Used to search for supergroup or channel members via a (string) query @query Query to search for
@ -426,7 +426,7 @@ supergroupMembersFilterBots = SupergroupMembersFilter;
//@upgraded_to_supergroup_id Identifier of the supergroup to which this group was upgraded; 0 if none
basicGroup id:int32 member_count:int32 status:ChatMemberStatus is_active:Bool upgraded_to_supergroup_id:int32 = BasicGroup;
//@description Contains full information about a basic group @param_description Group description @creator_user_id User identifier of the creator of the group; 0 if unknown @members Group members @invite_link Invite link for this group; available only for the group creator and only after it has been generated at least once
//@description Contains full information about a basic group @param_description Group description @creator_user_id User identifier of the creator of the group; 0 if unknown @members Group members @invite_link Invite link for this group; available only after it has been generated at least once and only for the group creator
basicGroupFullInfo description:string creator_user_id:int32 members:vector<chatMember> invite_link:string = BasicGroupFullInfo;
@ -663,7 +663,7 @@ chatInviteLink invite_link:string = ChatInviteLink;
//@photo Chat photo; may be null
//@member_count Number of members
//@member_user_ids User identifiers of some chat members that may be known to the current user
//@is_public True, if the chat is a public supergroup or a channel, i.e. it has a username or it is a location-based supergroup
//@is_public True, if the chat is a public supergroup or channel, i.e. it has a username or it is a location-based supergroup
chatInviteLinkInfo chat_id:int53 type:ChatType title:string photo:chatPhoto member_count:int32 member_user_ids:vector<int32> is_public:Bool = ChatInviteLinkInfo;
@ -675,13 +675,13 @@ chatActionBarReportSpam = ChatActionBar;
//@description The chat is a location-based supergroup, which can be reported as having unrelated location using the method reportChat with the reason chatReportReasonUnrelatedLocation
chatActionBarReportUnrelatedLocation = ChatActionBar;
//@description The chat is a private or a secret chat, which can be reported using the method reportChat, or the other user can be added to the contact list using the method addContact, or the other user can be blocked using the method blockUser
//@description The chat is a private or secret chat, which can be reported using the method reportChat, or the other user can be added to the contact list using the method addContact, or the other user can be blocked using the method blockUser
chatActionBarReportAddBlock = ChatActionBar;
//@description The chat is a private or a secret chat and the other user can be added to the contact list using the method addContact
//@description The chat is a private or secret chat and the other user can be added to the contact list using the method addContact
chatActionBarAddContact = ChatActionBar;
//@description The chat is a private or a secret chat with a mutual contact and the user's phone number can be shared with the other user using the method sharePhoneNumber
//@description The chat is a private or secret chat with a mutual contact and the user's phone number can be shared with the other user using the method sharePhoneNumber
chatActionBarSharePhoneNumber = ChatActionBar;
@ -1791,8 +1791,8 @@ inputInlineQueryResultLocation id:string location:location live_period:int32 tit
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessagePhoto, InputMessageLocation, InputMessageVenue or InputMessageContact
inputInlineQueryResultPhoto id:string title:string description:string thumbnail_url:string photo_url:string photo_width:int32 photo_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
//@description Represents a link to a WEBP or a TGS sticker @id Unique identifier of the query result @thumbnail_url URL of the sticker thumbnail, if it exists
//@sticker_url The URL of the WEBP or a TGS sticker (sticker file size must not exceed 5MB) @sticker_width Width of the sticker @sticker_height Height of the sticker
//@description Represents a link to a WEBP or TGS sticker @id Unique identifier of the query result @thumbnail_url URL of the sticker thumbnail, if it exists
//@sticker_url The URL of the WEBP or TGS sticker (sticker file size must not exceed 5MB) @sticker_width Width of the sticker @sticker_height Height of the sticker
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, inputMessageSticker, InputMessageLocation, InputMessageVenue or InputMessageContact
inputInlineQueryResultSticker id:string thumbnail_url:string sticker_url:string sticker_width:int32 sticker_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
@ -2390,7 +2390,7 @@ chatReportReasonUnrelatedLocation = ChatReportReason;
chatReportReasonCustom text:string = ChatReportReason;
//@description Contains a public HTTPS link to a message in a supergroup or a channel with a username @link Message link @html HTML-code for embedding the message
//@description Contains a public HTTPS link to a message in a supergroup or channel with a username @link Message link @html HTML-code for embedding the message
publicMessageLink link:string html:string = PublicMessageLink;
//@description Contains information about a link to a message in a chat
@ -2570,7 +2570,7 @@ topChatCategoryForwardChats = TopChatCategory;
//@description A URL linking to a user @user_id Identifier of the user
tMeUrlTypeUser user_id:int32 = TMeUrlType;
//@description A URL linking to a public supergroup or a channel @supergroup_id Identifier of the supergroup or channel
//@description A URL linking to a public supergroup or channel @supergroup_id Identifier of the supergroup or channel
tMeUrlTypeSupergroup supergroup_id:int53 = TMeUrlType;
//@description A chat invite link @info Chat invite link info
@ -3025,10 +3025,10 @@ getBasicGroup basic_group_id:int32 = BasicGroup;
//@description Returns full information about a basic group by its identifier @basic_group_id Basic group identifier
getBasicGroupFullInfo basic_group_id:int32 = BasicGroupFullInfo;
//@description Returns information about a supergroup or channel by its identifier. This is an offline request if the current user is not a bot @supergroup_id Supergroup or channel identifier
//@description Returns information about a supergroup or a channel by its identifier. This is an offline request if the current user is not a bot @supergroup_id Supergroup or channel identifier
getSupergroup supergroup_id:int32 = Supergroup;
//@description Returns full information about a supergroup or channel by its identifier, cached for up to 1 minute @supergroup_id Supergroup or channel identifier
//@description Returns full information about a supergroup or a channel by its identifier, cached for up to 1 minute @supergroup_id Supergroup or channel identifier
getSupergroupFullInfo supergroup_id:int32 = SupergroupFullInfo;
//@description Returns information about a secret chat by its identifier. This is an offline request @secret_chat_id Secret chat identifier
@ -3237,7 +3237,7 @@ addLocalMessage chat_id:int53 sender_user_id:int32 reply_to_message_id:int53 dis
//@description Deletes messages @chat_id Chat identifier @message_ids Identifiers of the messages to be deleted @revoke Pass true to try to delete messages for all chat members. Always true for supergroups, channels and secret chats
deleteMessages chat_id:int53 message_ids:vector<int53> revoke:Bool = Ok;
//@description Deletes all messages sent by the specified user to a chat. Supported only in supergroups; requires can_delete_messages administrator privileges @chat_id Chat identifier @user_id User identifier
//@description Deletes all messages sent by the specified user to a chat. Supported only for supergroups; requires can_delete_messages administrator privileges @chat_id Chat identifier @user_id User identifier
deleteChatMessagesFromUser chat_id:int53 user_id:int32 = Ok;
@ -3479,10 +3479,14 @@ addChatMember chat_id:int53 user_id:int32 forward_limit:int32 = Ok;
//@chat_id Chat identifier @user_ids Identifiers of the users to be added to the chat
addChatMembers chat_id:int53 user_ids:vector<int32> = Ok;
//@description Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for adding new members to the chat; instead, use addChatMember. The chat member status will not be changed until it has been synchronized with the server
//@description Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for adding new members to the chat and transferring chat ownership; instead, use addChatMember or transferChatOwnership. The chat member status will not be changed until it has been synchronized with the server
//@chat_id Chat identifier @user_id User identifier @status The new status of the member in the chat
setChatMemberStatus chat_id:int53 user_id:int32 status:ChatMemberStatus = Ok;
//@description Changes owner of a chat. The current user must be a current owner of the chat. Use the method canTransferOwnership to check whether the ownership can be transferred from the current session. Available only for supergroups and channel chats
//@chat_id Chat identifier @user_id Identifier of the user to which transfer the ownership. The ownership can't be transferred to a bot or to a deleted user @password The password of the current user
transferChatOwnership chat_id:int53 user_id:int32 password:string = Ok;
//@description Returns information about a single member of a chat @chat_id Chat identifier @user_id User identifier
getChatMember chat_id:int53 user_id:int32 = ChatMember;
@ -3781,7 +3785,7 @@ disconnectWebsite website_id:int64 = Ok;
disconnectAllWebsites = Ok;
//@description Changes the username of a supergroup or channel, requires creator privileges in the supergroup or channel @supergroup_id Identifier of the supergroup or channel @username New value of the username. Use an empty string to remove the username
//@description Changes the username of a supergroup or channel, requires owner privileges in the supergroup or channel @supergroup_id Identifier of the supergroup or channel @username New value of the username. Use an empty string to remove the username
setSupergroupUsername supergroup_id:int32 username:string = Ok;
//@description Changes the sticker set of a supergroup; requires can_change_info rights @supergroup_id Identifier of the supergroup @sticker_set_id New value of the supergroup sticker set identifier. Use 0 to remove the supergroup sticker set
@ -3800,7 +3804,7 @@ reportSupergroupSpam supergroup_id:int32 user_id:int32 message_ids:vector<int53>
//@filter The type of users to return. By default, supergroupMembersRecent @offset Number of users to skip @limit The maximum number of users be returned; up to 200
getSupergroupMembers supergroup_id:int32 filter:SupergroupMembersFilter offset:int32 limit:int32 = ChatMembers;
//@description Deletes a supergroup or channel along with all messages in the corresponding chat. This will release the supergroup or channel username and remove all members; requires creator privileges in the supergroup or channel. Chats with more than 1000 members can't be deleted using this method @supergroup_id Identifier of the supergroup or channel
//@description Deletes a supergroup or channel along with all messages in the corresponding chat. This will release the supergroup or channel username and remove all members; requires owner privileges in the supergroup or channel. Chats with more than 1000 members can't be deleted using this method @supergroup_id Identifier of the supergroup or channel
deleteSupergroup supergroup_id:int32 = Ok;
@ -3808,7 +3812,7 @@ deleteSupergroup supergroup_id:int32 = Ok;
closeSecretChat secret_chat_id:int32 = Ok;
//@description Returns a list of service actions taken by chat members and administrators in the last 48 hours. Available only in supergroups and channels. Requires administrator rights. Returns results in reverse chronological order (i. e., in order of decreasing event_id)
//@description Returns a list of service actions taken by chat members and administrators in the last 48 hours. Available only for supergroups and channels. Requires administrator rights. Returns results in reverse chronological order (i. e., in order of decreasing event_id)
//@chat_id Chat identifier @query Search query by which to filter events @from_event_id Identifier of an event from which to return results. Use 0 to get results from the latest events @limit Maximum number of events to return; up to 100
//@filters The types of events to return. By default, all types will be returned @user_ids User identifiers by which to filter events. By default, events relating to all users will be returned
getChatEventLog chat_id:int53 query:string from_event_id:int64 limit:int32 filters:chatEventLogFilters user_ids:vector<int32> = ChatEvents;

Binary file not shown.

View File

@ -24,6 +24,7 @@
#include "td/telegram/misc.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/NotificationManager.h"
#include "td/telegram/PasswordManager.h"
#include "td/telegram/Photo.h"
#include "td/telegram/Photo.hpp"
#include "td/telegram/SecretChatActor.h"
@ -1861,6 +1862,50 @@ class LeaveChannelQuery : public Td::ResultHandler {
}
};
class EditChannelCreatorQuery : public Td::ResultHandler {
Promise<Unit> promise_;
ChannelId channel_id_;
public:
explicit EditChannelCreatorQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
}
void send(ChannelId channel_id, UserId user_id,
tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password) {
channel_id_ = channel_id;
auto input_channel = td->contacts_manager_->get_input_channel(channel_id);
if (input_channel == nullptr) {
return promise_.set_error(Status::Error(400, "Have no access to the chat"));
}
auto input_user = td->contacts_manager_->get_input_user(user_id);
if (input_user == nullptr) {
return promise_.set_error(Status::Error(400, "Have no access to the user"));
}
send_query(G()->net_query_creator().create(create_storer(telegram_api::channels_editCreator(
std::move(input_channel), std::move(input_user), std::move(input_check_password)))));
}
void on_result(uint64 id, BufferSlice packet) override {
auto result_ptr = fetch_result<telegram_api::channels_editCreator>(packet);
if (result_ptr.is_error()) {
return on_error(id, result_ptr.move_as_error());
}
auto ptr = result_ptr.move_as_ok();
LOG(INFO) << "Receive result for editChannelCreator: " << to_string(ptr);
td->updates_manager_->on_get_updates(std::move(ptr));
td->contacts_manager_->invalidate_channel_full(channel_id_, false);
promise_.set_value(Unit());
}
void on_error(uint64 id, Status status) override {
td->contacts_manager_->on_get_channel_error(channel_id_, status, "EditChannelCreatorQuery");
promise_.set_error(std::move(status));
td->updates_manager_->get_difference("EditChannelCreatorQuery");
}
};
class MigrateChatQuery : public Td::ResultHandler {
Promise<Unit> promise_;
@ -5353,6 +5398,59 @@ void ContactsManager::change_chat_participant_status(ChatId chat_id, UserId user
->send(chat_id, std::move(input_user), status.is_administrator());
}
void ContactsManager::transfer_dialog_ownership(DialogId dialog_id, UserId user_id, const string &password,
Promise<Unit> &&promise) {
if (!td_->messages_manager_->have_dialog_force(dialog_id)) {
return promise.set_error(Status::Error(3, "Chat not found"));
}
if (!have_user_force(user_id)) {
return promise.set_error(Status::Error(3, "User not found"));
}
if (is_user_bot(user_id)) {
return promise.set_error(Status::Error(3, "User is a bot"));
}
if (is_user_deleted(user_id)) {
return promise.set_error(Status::Error(3, "User is deleted"));
}
if (password.empty()) {
return promise.set_error(Status::Error(400, "PASSWORD_HASH_INVALID"));
}
switch (dialog_id.get_type()) {
case DialogType::User:
case DialogType::Chat:
case DialogType::SecretChat:
return promise.set_error(Status::Error(3, "Can't transfer chat ownership"));
case DialogType::Channel:
send_closure(
td_->password_manager_, &PasswordManager::get_input_check_password_srp, password,
PromiseCreator::lambda([actor_id = actor_id(this), channel_id = dialog_id.get_channel_id(), user_id,
promise = std::move(promise)](
Result<tl_object_ptr<telegram_api::InputCheckPasswordSRP>> result) mutable {
if (result.is_error()) {
return promise.set_error(result.move_as_error());
}
send_closure(actor_id, &ContactsManager::transfer_channel_ownership, channel_id, user_id,
result.move_as_ok(), std::move(promise));
}));
break;
case DialogType::None:
default:
UNREACHABLE();
}
}
void ContactsManager::transfer_channel_ownership(
ChannelId channel_id, UserId user_id, tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
Promise<Unit> &&promise) {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
td_->create_handler<EditChannelCreatorQuery>(std::move(promise))
->send(channel_id, user_id, std::move(input_check_password));
}
void ContactsManager::export_chat_invite_link(ChatId chat_id, Promise<Unit> &&promise) {
const Chat *c = get_chat(chat_id);
if (c == nullptr) {
@ -9873,12 +9971,19 @@ void ContactsManager::on_update_channel_title(Channel *c, ChannelId channel_id,
void ContactsManager::on_update_channel_status(Channel *c, ChannelId channel_id, DialogParticipantStatus &&status) {
if (c->status != status) {
LOG(INFO) << "Update " << channel_id << " status from " << c->status << " to " << status;
bool reget_channel_full = c->status.is_creator() != status.is_creator();
bool drop_invite_link =
c->status.is_administrator() != status.is_administrator() || c->status.is_member() != status.is_member();
c->status = status;
c->is_status_changed = true;
c->need_send_update = true;
invalidate_channel_full(channel_id, drop_invite_link);
if (reget_channel_full) {
auto input_channel = get_input_channel(channel_id);
if (input_channel != nullptr) {
send_get_channel_full_query(channel_id, std::move(input_channel), Auto(), "update channel creator");
}
}
}
}

View File

@ -336,6 +336,8 @@ class ContactsManager : public Actor {
void change_channel_participant_status(ChannelId channel_id, UserId user_id, DialogParticipantStatus status,
Promise<Unit> &&promise);
void transfer_dialog_ownership(DialogId dialog_id, UserId user_id, const string &password, Promise<Unit> &&promise);
void export_chat_invite_link(ChatId chat_id, Promise<Unit> &&promise);
void export_channel_invite_link(ChannelId channel_id, Promise<Unit> &&promise);
@ -1210,6 +1212,10 @@ class ContactsManager : public Actor {
void restrict_channel_participant(ChannelId channel_id, UserId user_id, DialogParticipantStatus status,
DialogParticipantStatus old_status, Promise<Unit> &&promise);
void transfer_channel_ownership(ChannelId channel_id, UserId user_id,
tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
Promise<Unit> &&promise);
static void on_user_online_timeout_callback(void *contacts_manager_ptr, int64 user_id_long);
static void on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);

View File

@ -144,11 +144,22 @@ tl_object_ptr<telegram_api::InputCheckPasswordSRP> PasswordManager::get_input_ch
}
tl_object_ptr<telegram_api::InputCheckPasswordSRP> PasswordManager::get_input_check_password(
Slice password, const PasswordState &state) const {
Slice password, const PasswordState &state) {
return get_input_check_password(password, state.current_client_salt, state.current_server_salt, state.current_srp_g,
state.current_srp_p, state.current_srp_B, state.current_srp_id);
}
void PasswordManager::get_input_check_password_srp(
string password, Promise<tl_object_ptr<telegram_api::InputCheckPasswordSRP>> &&promise) {
do_get_state(PromiseCreator::lambda(
[promise = std::move(promise), password = std::move(password)](Result<PasswordState> r_state) mutable {
if (r_state.is_error()) {
return promise.set_error(r_state.move_as_error());
}
promise.set_value(PasswordManager::get_input_check_password(password, r_state.move_as_ok()));
}));
}
void PasswordManager::set_password(string current_password, string new_password, string new_hint,
bool set_recovery_email_address, string recovery_email_address,
Promise<State> promise) {

View File

@ -79,6 +79,8 @@ class PasswordManager : public NetQueryCallback {
void recover_password(string code, Promise<State> promise);
void get_secure_secret(string password, Promise<secure_storage::Secret> promise);
void get_input_check_password_srp(string password,
Promise<tl_object_ptr<telegram_api::InputCheckPasswordSRP>> &&promise);
void get_temp_password_state(Promise<TempState> promise) /*const*/;
void create_temp_password(string password, int32 timeout, Promise<TempState> promise);
@ -171,8 +173,8 @@ class PasswordManager : public NetQueryCallback {
static Result<BufferSlice> calc_password_srp_hash(Slice password, Slice client_salt, Slice server_salt, int32 g,
Slice p);
tl_object_ptr<telegram_api::InputCheckPasswordSRP> get_input_check_password(Slice password,
const PasswordState &state) const;
static tl_object_ptr<telegram_api::InputCheckPasswordSRP> get_input_check_password(Slice password,
const PasswordState &state);
void update_password_settings(UpdateSettings update_settings, Promise<State> promise);
void do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state, Promise<bool> promise);

View File

@ -6118,6 +6118,13 @@ void Td::on_request(uint64 id, td_api::setChatMemberStatus &request) {
request.status_, std::move(promise));
}
void Td::on_request(uint64 id, td_api::transferChatOwnership &request) {
CREATE_OK_REQUEST_PROMISE();
CLEAN_INPUT_STRING(request.password_);
contacts_manager_->transfer_dialog_ownership(DialogId(request.chat_id_), UserId(request.user_id_), request.password_,
std::move(promise));
}
void Td::on_request(uint64 id, const td_api::getChatMember &request) {
CREATE_REQUEST(GetChatMemberRequest, request.chat_id_, request.user_id_);
}

View File

@ -688,6 +688,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, td_api::setChatMemberStatus &request);
void on_request(uint64 id, td_api::transferChatOwnership &request);
void on_request(uint64 id, const td_api::getChatMember &request);
void on_request(uint64 id, td_api::searchChatMembers &request);

View File

@ -3420,6 +3420,15 @@ class CliClient final : public Actor {
} else {
LOG(ERROR) << "Unknown status \"" << status_str << "\"";
}
} else if (op == "transferChatOwnership") {
string chat_id;
string user_id;
string password;
std::tie(chat_id, args) = split(args);
std::tie(user_id, password) = split(args);
send_request(
td_api::make_object<td_api::transferChatOwnership>(as_chat_id(chat_id), as_user_id(user_id), password));
} else if (op == "log") {
string chat_id;
string limit;