| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /*
- 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 "api/api_blocked_peers.h"
- #include "apiwrap.h"
- #include "base/unixtime.h"
- #include "data/data_changes.h"
- #include "data/data_peer.h"
- #include "data/data_peer_id.h"
- #include "data/data_session.h"
- #include "main/main_session.h"
- namespace Api {
- namespace {
- constexpr auto kBlockedFirstSlice = 16;
- constexpr auto kBlockedPerPage = 40;
- BlockedPeers::Slice TLToSlice(
- const MTPcontacts_Blocked &blocked,
- Data::Session &owner) {
- const auto create = [&](int count, const QVector<MTPPeerBlocked> &list) {
- auto slice = BlockedPeers::Slice();
- slice.total = std::max(count, int(list.size()));
- slice.list.reserve(list.size());
- for (const auto &contact : list) {
- contact.match([&](const MTPDpeerBlocked &data) {
- slice.list.push_back({
- .id = peerFromMTP(data.vpeer_id()),
- .date = data.vdate().v,
- });
- });
- }
- return slice;
- };
- return blocked.match([&](const MTPDcontacts_blockedSlice &data) {
- owner.processUsers(data.vusers());
- owner.processChats(data.vchats());
- return create(data.vcount().v, data.vblocked().v);
- }, [&](const MTPDcontacts_blocked &data) {
- owner.processUsers(data.vusers());
- owner.processChats(data.vchats());
- return create(0, data.vblocked().v);
- });
- }
- } // namespace
- BlockedPeers::BlockedPeers(not_null<ApiWrap*> api)
- : _session(&api->session())
- , _api(&api->instance()) {
- }
- bool BlockedPeers::Slice::Item::operator==(const Item &other) const {
- return (id == other.id) && (date == other.date);
- }
- bool BlockedPeers::Slice::Item::operator!=(const Item &other) const {
- return !(*this == other);
- }
- bool BlockedPeers::Slice::operator==(const BlockedPeers::Slice &other) const {
- return (total == other.total) && (list == other.list);
- }
- bool BlockedPeers::Slice::operator!=(const BlockedPeers::Slice &other) const {
- return !(*this == other);
- }
- void BlockedPeers::block(not_null<PeerData*> peer) {
- if (peer->isBlocked()) {
- _session->changes().peerUpdated(
- peer,
- Data::PeerUpdate::Flag::IsBlocked);
- return;
- } else if (blockAlreadySent(peer, true)) {
- return;
- }
- const auto requestId = _api.request(MTPcontacts_Block(
- MTP_flags(0),
- peer->input
- )).done([=] {
- const auto data = _blockRequests.take(peer);
- peer->setIsBlocked(true);
- if (_slice) {
- _slice->list.insert(
- _slice->list.begin(),
- { peer->id, base::unixtime::now() });
- ++_slice->total;
- _changes.fire_copy(*_slice);
- }
- if (data) {
- for (const auto &callback : data->callbacks) {
- callback(false);
- }
- }
- }).fail([=] {
- if (const auto data = _blockRequests.take(peer)) {
- for (const auto &callback : data->callbacks) {
- callback(false);
- }
- }
- }).send();
- _blockRequests.emplace(peer, Request{
- .requestId = requestId,
- .blocking = true,
- });
- }
- void BlockedPeers::unblock(
- not_null<PeerData*> peer,
- Fn<void(bool success)> done,
- bool force) {
- if (!force && !peer->isBlocked()) {
- _session->changes().peerUpdated(
- peer,
- Data::PeerUpdate::Flag::IsBlocked);
- return;
- } else if (blockAlreadySent(peer, false, done)) {
- return;
- }
- const auto requestId = _api.request(MTPcontacts_Unblock(
- MTP_flags(0),
- peer->input
- )).done([=] {
- const auto data = _blockRequests.take(peer);
- peer->setIsBlocked(false);
- if (_slice) {
- auto &list = _slice->list;
- for (auto i = list.begin(); i != list.end(); ++i) {
- if (i->id == peer->id) {
- list.erase(i);
- break;
- }
- }
- if (_slice->total > list.size()) {
- --_slice->total;
- }
- _changes.fire_copy(*_slice);
- }
- if (data) {
- for (const auto &callback : data->callbacks) {
- callback(true);
- }
- }
- }).fail([=] {
- if (const auto data = _blockRequests.take(peer)) {
- for (const auto &callback : data->callbacks) {
- callback(false);
- }
- }
- }).send();
- const auto i = _blockRequests.emplace(peer, Request{
- .requestId = requestId,
- .blocking = false,
- }).first;
- if (done) {
- i->second.callbacks.push_back(std::move(done));
- }
- }
- bool BlockedPeers::blockAlreadySent(
- not_null<PeerData*> peer,
- bool blocking,
- Fn<void(bool success)> done) {
- const auto i = _blockRequests.find(peer);
- if (i == end(_blockRequests)) {
- return false;
- } else if (i->second.blocking == blocking) {
- if (done) {
- i->second.callbacks.push_back(std::move(done));
- }
- return true;
- }
- const auto callbacks = base::take(i->second.callbacks);
- _blockRequests.erase(i);
- for (const auto &callback : callbacks) {
- callback(false);
- }
- return false;
- }
- void BlockedPeers::reload() {
- if (_requestId) {
- return;
- }
- request(0, [=](Slice &&slice) {
- if (!_slice || *_slice != slice) {
- _slice = slice;
- _changes.fire(std::move(slice));
- }
- });
- }
- auto BlockedPeers::slice() -> rpl::producer<BlockedPeers::Slice> {
- if (!_slice) {
- reload();
- }
- return _slice
- ? _changes.events_starting_with_copy(*_slice)
- : (_changes.events() | rpl::type_erased());
- }
- void BlockedPeers::request(int offset, Fn<void(BlockedPeers::Slice)> done) {
- if (_requestId) {
- return;
- }
- _requestId = _api.request(MTPcontacts_GetBlocked(
- MTP_flags(0),
- MTP_int(offset),
- MTP_int(offset ? kBlockedPerPage : kBlockedFirstSlice)
- )).done([=](const MTPcontacts_Blocked &result) {
- _requestId = 0;
- done(TLToSlice(result, _session->data()));
- }).fail([=] {
- _requestId = 0;
- }).send();
- }
- } // namespace Api
|