mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-26 19:14:02 +02:00
408 lines
11 KiB
C++
408 lines
11 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
*/
|
|
#include "boxes/peers/add_bot_to_chat_box.h"
|
|
|
|
#include "lang/lang_keys.h"
|
|
#include "data/data_user.h"
|
|
#include "data/data_chat.h"
|
|
#include "data/data_channel.h"
|
|
#include "data/data_session.h"
|
|
#include "data/data_histories.h"
|
|
#include "history/history.h"
|
|
#include "main/main_session.h"
|
|
#include "boxes/peers/edit_participant_box.h"
|
|
#include "boxes/peers/edit_participants_box.h"
|
|
#include "boxes/filters/edit_filter_chats_list.h"
|
|
#include "ui/boxes/confirm_box.h"
|
|
#include "ui/wrap/vertical_layout.h"
|
|
#include "ui/wrap/slide_wrap.h"
|
|
#include "base/random.h"
|
|
#include "base/weak_ptr.h"
|
|
#include "api/api_chat_participants.h"
|
|
#include "window/window_session_controller.h"
|
|
#include "apiwrap.h"
|
|
#include "styles/style_boxes.h"
|
|
|
|
namespace {
|
|
|
|
class Controller final
|
|
: public PeerListController
|
|
, public base::has_weak_ptr {
|
|
public:
|
|
Controller(
|
|
not_null<Main::Session*> session,
|
|
rpl::producer<not_null<PeerData*>> add,
|
|
Fn<void(not_null<PeerData*> chat)> callback);
|
|
|
|
Main::Session &session() const override;
|
|
void prepare() override;
|
|
void rowClicked(not_null<PeerListRow*> row) override;
|
|
|
|
private:
|
|
void addRow(not_null<PeerData*> peer);
|
|
|
|
const not_null<Main::Session*> _session;
|
|
Fn<void(not_null<PeerData*> chat)> _callback;
|
|
std::vector<not_null<PeerData*>> _list;
|
|
bool _prepared = false;
|
|
bool _refreshing = false;
|
|
|
|
rpl::lifetime _lifetime;
|
|
|
|
};
|
|
|
|
Controller::Controller(
|
|
not_null<Main::Session*> session,
|
|
rpl::producer<not_null<PeerData*>> add,
|
|
Fn<void(not_null<PeerData*> chat)> callback)
|
|
: _session(session)
|
|
, _callback(std::move(callback)) {
|
|
std::move(
|
|
add
|
|
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
|
if (_prepared) {
|
|
addRow(peer);
|
|
} else {
|
|
_list.push_back(peer);
|
|
}
|
|
}, _lifetime);
|
|
}
|
|
|
|
Main::Session &Controller::session() const {
|
|
return *_session;
|
|
}
|
|
|
|
void Controller::prepare() {
|
|
_prepared = true;
|
|
for (const auto &peer : _list) {
|
|
addRow(peer);
|
|
}
|
|
}
|
|
|
|
void Controller::rowClicked(not_null<PeerListRow*> row) {
|
|
_callback(row->peer());
|
|
}
|
|
|
|
void Controller::addRow(not_null<PeerData*> peer) {
|
|
if (delegate()->peerListFindRow(peer->id.value)) {
|
|
return;
|
|
}
|
|
delegate()->peerListAppendRow(std::make_unique<PeerListRow>(peer));
|
|
if (!_refreshing) {
|
|
_refreshing = true;
|
|
Ui::PostponeCall(this, [=] {
|
|
_refreshing = false;
|
|
delegate()->peerListRefreshRows();
|
|
});
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void AddBotToGroupBoxController::Start(
|
|
not_null<Window::SessionController*> controller,
|
|
not_null<UserData*> bot,
|
|
Scope scope,
|
|
const QString &token,
|
|
ChatAdminRights requestedRights) {
|
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
|
box->addButton(tr::lng_cancel(), [box] { box->closeBox(); });
|
|
};
|
|
controller->show(Box<PeerListBox>(
|
|
std::make_unique<AddBotToGroupBoxController>(
|
|
controller,
|
|
bot,
|
|
scope,
|
|
token,
|
|
requestedRights),
|
|
std::move(initBox)));
|
|
}
|
|
|
|
AddBotToGroupBoxController::AddBotToGroupBoxController(
|
|
not_null<Window::SessionController*> controller,
|
|
not_null<UserData*> bot,
|
|
Scope scope,
|
|
const QString &token,
|
|
ChatAdminRights requestedRights)
|
|
: ChatsListBoxController(std::unique_ptr<PeerListSearchController>())
|
|
, _controller(controller)
|
|
, _bot(bot)
|
|
, _scope(scope)
|
|
, _token(token)
|
|
, _requestedRights(requestedRights)
|
|
, _adminToGroup((scope == Scope::GroupAdmin)
|
|
|| (scope == Scope::All && _bot->botInfo->groupAdminRights != 0))
|
|
, _adminToChannel((scope == Scope::ChannelAdmin)
|
|
|| (scope == Scope::All && _bot->botInfo->channelAdminRights != 0))
|
|
, _memberToGroup(scope == Scope::All) {
|
|
}
|
|
|
|
Main::Session &AddBotToGroupBoxController::session() const {
|
|
return _bot->session();
|
|
}
|
|
|
|
void AddBotToGroupBoxController::rowClicked(not_null<PeerListRow*> row) {
|
|
addBotToGroup(row->peer());
|
|
}
|
|
|
|
void AddBotToGroupBoxController::requestExistingRights(
|
|
not_null<ChannelData*> channel) {
|
|
if (_existingRightsChannel == channel) {
|
|
return;
|
|
}
|
|
_existingRightsChannel = channel;
|
|
_bot->session().api().request(_existingRightsRequestId).cancel();
|
|
_existingRightsRequestId = _bot->session().api().request(
|
|
MTPchannels_GetParticipant(
|
|
_existingRightsChannel->inputChannel,
|
|
_bot->input)
|
|
).done([=](const MTPchannels_ChannelParticipant &result) {
|
|
result.match([&](const MTPDchannels_channelParticipant &data) {
|
|
channel->owner().processUsers(data.vusers());
|
|
const auto participant = Api::ChatParticipant(
|
|
data.vparticipant(),
|
|
channel);
|
|
_existingRights = participant.rights().flags;
|
|
_existingRank = participant.rank();
|
|
addBotToGroup(_existingRightsChannel);
|
|
});
|
|
}).fail([=] {
|
|
_existingRights = ChatAdminRights();
|
|
_existingRank = QString();
|
|
addBotToGroup(_existingRightsChannel);
|
|
}).send();
|
|
}
|
|
|
|
void AddBotToGroupBoxController::addBotToGroup(not_null<PeerData*> chat) {
|
|
if (const auto megagroup = chat->asMegagroup()) {
|
|
if (!megagroup->canAddMembers()) {
|
|
_controller->show(
|
|
Ui::MakeInformBox(tr::lng_error_cant_add_member()));
|
|
return;
|
|
}
|
|
}
|
|
if (_existingRightsChannel != chat) {
|
|
_existingRights = {};
|
|
_existingRank = QString();
|
|
_existingRightsChannel = nullptr;
|
|
_bot->session().api().request(_existingRightsRequestId).cancel();
|
|
}
|
|
const auto requestedAddAdmin = (_scope == Scope::GroupAdmin)
|
|
|| (_scope == Scope::ChannelAdmin);
|
|
if (chat->isChannel()
|
|
&& requestedAddAdmin
|
|
&& !_existingRights.has_value()) {
|
|
requestExistingRights(chat->asChannel());
|
|
return;
|
|
}
|
|
const auto bot = _bot;
|
|
const auto controller = _controller;
|
|
const auto close = [=](auto&&...) {
|
|
using Way = Window::SectionShow::Way;
|
|
controller->hideLayer();
|
|
controller->showPeerHistory(chat, Way::ClearStack, ShowAtUnreadMsgId);
|
|
};
|
|
const auto rights = requestedAddAdmin
|
|
? _requestedRights
|
|
: (chat->isBroadcast()
|
|
&& chat->asBroadcast()->canAddAdmins())
|
|
? bot->botInfo->channelAdminRights
|
|
: ((chat->isMegagroup() && chat->asMegagroup()->canAddAdmins())
|
|
|| (chat->isChat() && chat->asChat()->canAddAdmins()))
|
|
? bot->botInfo->groupAdminRights
|
|
: ChatAdminRights();
|
|
const auto addingAdmin = requestedAddAdmin || (rights != 0);
|
|
if (addingAdmin) {
|
|
const auto scope = _scope;
|
|
const auto token = _token;
|
|
const auto done = [=](
|
|
ChatAdminRightsInfo newRights,
|
|
const QString &rank) {
|
|
if (scope == Scope::GroupAdmin) {
|
|
chat->session().api().sendBotStart(bot, chat, token);
|
|
}
|
|
close();
|
|
};
|
|
const auto saveCallback = SaveAdminCallback(
|
|
chat,
|
|
bot,
|
|
done,
|
|
close);
|
|
auto box = Box<EditAdminBox>(
|
|
chat,
|
|
bot,
|
|
ChatAdminRightsInfo(rights),
|
|
_existingRank,
|
|
EditAdminBotFields{
|
|
_token,
|
|
_existingRights.value_or(ChatAdminRights()) });
|
|
box->setSaveCallback(saveCallback);
|
|
controller->show(std::move(box));
|
|
} else {
|
|
auto callback = crl::guard(this, [=] {
|
|
AddBotToGroup(bot, chat, _token);
|
|
controller->hideLayer();
|
|
});
|
|
controller->show(Ui::MakeConfirmBox({
|
|
tr::lng_bot_sure_invite(tr::now, lt_group, chat->name()),
|
|
std::move(callback),
|
|
}));
|
|
}
|
|
}
|
|
|
|
auto AddBotToGroupBoxController::createRow(not_null<History*> history)
|
|
-> std::unique_ptr<ChatsListBoxController::Row> {
|
|
if (!needToCreateRow(history->peer)) {
|
|
return nullptr;
|
|
}
|
|
return std::make_unique<Row>(history);
|
|
}
|
|
|
|
bool AddBotToGroupBoxController::needToCreateRow(
|
|
not_null<PeerData*> peer) const {
|
|
if (const auto chat = peer->asChat()) {
|
|
if (onlyAdminToGroup()) {
|
|
return chat->canAddAdmins();
|
|
} else if (_adminToGroup && chat->canAddAdmins()) {
|
|
_groups.fire_copy(peer);
|
|
} else if (!onlyAdminToChannel()) {
|
|
return chat->canAddMembers();
|
|
}
|
|
} else if (const auto group = peer->asMegagroup()) {
|
|
if (onlyAdminToGroup()) {
|
|
return group->canAddAdmins();
|
|
} else if (_adminToGroup && group->canAddAdmins()) {
|
|
_groups.fire_copy(peer);
|
|
} else if (!onlyAdminToChannel()) {
|
|
return group->canAddMembers();
|
|
}
|
|
} else if (const auto channel = peer->asBroadcast()) {
|
|
if (onlyAdminToChannel()) {
|
|
return channel->canAddAdmins();
|
|
} else if (_adminToChannel && channel->canAddAdmins()) {
|
|
_channels.fire_copy(peer);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
QString AddBotToGroupBoxController::emptyBoxText() const {
|
|
return !session().data().chatsListLoaded()
|
|
? tr::lng_contacts_loading(tr::now)
|
|
: _adminToChannel
|
|
? tr::lng_bot_no_chats(tr::now)
|
|
: tr::lng_bot_no_groups(tr::now);
|
|
}
|
|
|
|
QString AddBotToGroupBoxController::noResultsText() const {
|
|
return !session().data().chatsListLoaded()
|
|
? tr::lng_contacts_loading(tr::now)
|
|
: _adminToChannel
|
|
? tr::lng_bot_chats_not_found(tr::now)
|
|
: tr::lng_bot_groups_not_found(tr::now);
|
|
}
|
|
|
|
void AddBotToGroupBoxController::updateLabels() {
|
|
setSearchNoResultsText(noResultsText());
|
|
}
|
|
|
|
object_ptr<Ui::RpWidget> AddBotToGroupBoxController::prepareAdminnedChats() {
|
|
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
|
|
const auto container = result.data();
|
|
|
|
const auto callback = [=](not_null<PeerData*> chat) {
|
|
addBotToGroup(chat);
|
|
};
|
|
|
|
const auto addList = [&](
|
|
tr::phrase<> subtitle,
|
|
rpl::event_stream<not_null<PeerData*>> &items) {
|
|
const auto wrap = container->add(
|
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
|
container,
|
|
object_ptr<Ui::VerticalLayout>(container)));
|
|
wrap->hide(anim::type::instant);
|
|
|
|
const auto inner = wrap->entity();
|
|
inner->add(CreatePeerListSectionSubtitle(inner, subtitle()));
|
|
|
|
const auto delegate = inner->lifetime().make_state<
|
|
PeerListContentDelegateSimple
|
|
>();
|
|
const auto controller = inner->lifetime().make_state<Controller>(
|
|
&session(),
|
|
items.events(),
|
|
callback);
|
|
const auto content = inner->add(object_ptr<PeerListContent>(
|
|
container,
|
|
controller));
|
|
delegate->setContent(content);
|
|
controller->setDelegate(delegate);
|
|
|
|
items.events() | rpl::take(1) | rpl::start_with_next([=] {
|
|
wrap->show(anim::type::instant);
|
|
}, inner->lifetime());
|
|
};
|
|
if (_adminToChannel) {
|
|
addList(tr::lng_bot_channels_manage, _channels);
|
|
}
|
|
if (_adminToGroup) {
|
|
addList(tr::lng_bot_groups_manage, _groups);
|
|
}
|
|
|
|
rpl::merge(
|
|
_groups.events(),
|
|
_channels.events()
|
|
) | rpl::take(1) | rpl::start_with_next([=] {
|
|
container->add(CreatePeerListSectionSubtitle(
|
|
container,
|
|
tr::lng_bot_groups()));
|
|
}, container->lifetime());
|
|
|
|
return result;
|
|
}
|
|
|
|
bool AddBotToGroupBoxController::onlyAdminToGroup() const {
|
|
return _adminToGroup && !_memberToGroup && !_adminToChannel;
|
|
}
|
|
|
|
bool AddBotToGroupBoxController::onlyAdminToChannel() const {
|
|
return _adminToChannel && !_memberToGroup && !_adminToGroup;
|
|
}
|
|
|
|
void AddBotToGroupBoxController::prepareViewHook() {
|
|
delegate()->peerListSetTitle(_adminToChannel
|
|
? tr::lng_bot_choose_chat()
|
|
: tr::lng_bot_choose_group());
|
|
if ((_adminToGroup && !onlyAdminToGroup())
|
|
|| (_adminToChannel && !onlyAdminToChannel())) {
|
|
delegate()->peerListSetAboveWidget(prepareAdminnedChats());
|
|
}
|
|
|
|
updateLabels();
|
|
session().data().chatsListLoadedEvents(
|
|
) | rpl::filter([=](Data::Folder *folder) {
|
|
return !folder;
|
|
}) | rpl::start_with_next([=] {
|
|
updateLabels();
|
|
}, lifetime());
|
|
}
|
|
|
|
void AddBotToGroup(
|
|
not_null<UserData*> bot,
|
|
not_null<PeerData*> chat,
|
|
const QString &startToken) {
|
|
if (!startToken.isEmpty()) {
|
|
chat->session().api().sendBotStart(bot, chat, startToken);
|
|
} else {
|
|
chat->session().api().chatParticipants().add(chat, { 1, bot });
|
|
}
|
|
if (const auto window = chat->session().tryResolveWindow()) {
|
|
window->showPeerHistory(chat);
|
|
}
|
|
}
|