send_as_peers.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "main/session/send_as_peers.h"
  8. #include "data/data_user.h"
  9. #include "data/data_channel.h"
  10. #include "data/data_session.h"
  11. #include "data/data_changes.h"
  12. #include "main/main_session.h"
  13. #include "apiwrap.h"
  14. namespace Main {
  15. namespace {
  16. constexpr auto kRequestEach = 30 * crl::time(1000);
  17. } // namespace
  18. SendAsPeers::SendAsPeers(not_null<Session*> session)
  19. : _session(session)
  20. , _onlyMe({ { .peer = session->user(), .premiumRequired = false } })
  21. , _onlyMePaid({ session->user() }) {
  22. _session->changes().peerUpdates(
  23. Data::PeerUpdate::Flag::Rights
  24. ) | rpl::map([=](const Data::PeerUpdate &update) {
  25. const auto peer = update.peer;
  26. const auto channel = peer->asChannel();
  27. const auto bits = 0
  28. | (peer->amAnonymous() ? (1 << 0) : 0)
  29. | ((channel && channel->isPublic()) ? (1 << 1) : 0)
  30. | ((channel && channel->addsSignature()) ? (1 << 2) : 0)
  31. | ((channel && channel->signatureProfiles()) ? (1 << 3) : 0);
  32. return std::tuple(peer, bits);
  33. }) | rpl::distinct_until_changed(
  34. ) | rpl::filter([=](not_null<PeerData*> peer, int) {
  35. return _lists.contains(peer) || _lastRequestTime.contains(peer);
  36. }) | rpl::start_with_next([=](not_null<PeerData*> peer, int) {
  37. refresh(peer, true);
  38. }, _lifetime);
  39. }
  40. bool SendAsPeers::shouldChoose(not_null<PeerData*> peer) {
  41. refresh(peer);
  42. const auto channel = peer->asBroadcast();
  43. return Data::CanSendAnything(peer, false)
  44. && (list(peer).size() > 1)
  45. && (!channel
  46. || channel->addsSignature()
  47. || channel->signatureProfiles());
  48. }
  49. void SendAsPeers::refresh(not_null<PeerData*> peer, bool force) {
  50. if (!peer->isChannel()) {
  51. return;
  52. }
  53. const auto now = crl::now();
  54. const auto i = _lastRequestTime.find(peer);
  55. const auto when = (i == end(_lastRequestTime)) ? -1 : i->second;
  56. if (!force && (when >= 0 && now < when + kRequestEach)) {
  57. return;
  58. }
  59. _lastRequestTime[peer] = now;
  60. request(peer);
  61. request(peer, true);
  62. }
  63. const std::vector<SendAsPeer> &SendAsPeers::list(
  64. not_null<PeerData*> peer) const {
  65. const auto i = _lists.find(peer);
  66. return (i != end(_lists)) ? i->second : _onlyMe;
  67. }
  68. const std::vector<not_null<PeerData*>> &SendAsPeers::paidReactionList(
  69. not_null<PeerData*> peer) const {
  70. const auto i = _paidReactionLists.find(peer);
  71. return (i != end(_paidReactionLists)) ? i->second : _onlyMePaid;
  72. }
  73. rpl::producer<not_null<PeerData*>> SendAsPeers::updated() const {
  74. return _updates.events();
  75. }
  76. void SendAsPeers::saveChosen(
  77. not_null<PeerData*> peer,
  78. not_null<PeerData*> chosen) {
  79. peer->session().api().request(MTPmessages_SaveDefaultSendAs(
  80. peer->input,
  81. chosen->input
  82. )).send();
  83. setChosen(peer, chosen->id);
  84. }
  85. void SendAsPeers::setChosen(not_null<PeerData*> peer, PeerId chosenId) {
  86. if (chosen(peer) == chosenId) {
  87. return;
  88. }
  89. const auto fallback = peer->amAnonymous()
  90. ? peer
  91. : peer->session().user();
  92. if (fallback->id == chosenId) {
  93. _chosen.remove(peer);
  94. } else {
  95. _chosen[peer] = chosenId;
  96. }
  97. _updates.fire_copy(peer);
  98. }
  99. PeerId SendAsPeers::chosen(not_null<PeerData*> peer) const {
  100. const auto i = _chosen.find(peer);
  101. return (i != end(_chosen)) ? i->second : PeerId();
  102. }
  103. not_null<PeerData*> SendAsPeers::resolveChosen(
  104. not_null<PeerData*> peer) const {
  105. return ResolveChosen(peer, list(peer), chosen(peer));
  106. }
  107. not_null<PeerData*> SendAsPeers::ResolveChosen(
  108. not_null<PeerData*> peer,
  109. const std::vector<SendAsPeer> &list,
  110. PeerId chosen) {
  111. const auto fallback = peer->amAnonymous()
  112. ? peer
  113. : peer->session().user();
  114. if (!chosen) {
  115. chosen = fallback->id;
  116. }
  117. const auto i = ranges::find(list, chosen, [](const SendAsPeer &as) {
  118. return as.peer->id;
  119. });
  120. return (i != end(list))
  121. ? i->peer
  122. : !list.empty()
  123. ? list.front().peer
  124. : fallback;
  125. }
  126. void SendAsPeers::request(not_null<PeerData*> peer, bool forPaidReactions) {
  127. using Flag = MTPchannels_GetSendAs::Flag;
  128. peer->session().api().request(MTPchannels_GetSendAs(
  129. MTP_flags(forPaidReactions ? Flag::f_for_paid_reactions : Flag()),
  130. peer->input
  131. )).done([=](const MTPchannels_SendAsPeers &result) {
  132. auto parsed = std::vector<SendAsPeer>();
  133. auto &owner = peer->owner();
  134. result.match([&](const MTPDchannels_sendAsPeers &data) {
  135. owner.processUsers(data.vusers());
  136. owner.processChats(data.vchats());
  137. const auto &list = data.vpeers().v;
  138. parsed.reserve(list.size());
  139. for (const auto &as : list) {
  140. const auto &data = as.data();
  141. const auto peerId = peerFromMTP(data.vpeer());
  142. if (const auto peer = owner.peerLoaded(peerId)) {
  143. parsed.push_back({
  144. .peer = peer,
  145. .premiumRequired = data.is_premium_required(),
  146. });
  147. }
  148. }
  149. });
  150. if (forPaidReactions) {
  151. auto peers = parsed | ranges::views::transform(
  152. &SendAsPeer::peer
  153. ) | ranges::to_vector;
  154. if (!peers.empty()) {
  155. _paidReactionLists[peer] = std::move(peers);
  156. } else {
  157. _paidReactionLists.remove(peer);
  158. }
  159. } else {
  160. if (parsed.size() > 1) {
  161. auto &now = _lists[peer];
  162. if (now != parsed) {
  163. now = std::move(parsed);
  164. _updates.fire_copy(peer);
  165. }
  166. } else if (const auto i = _lists.find(peer); i != end(_lists)) {
  167. _lists.erase(i);
  168. _updates.fire_copy(peer);
  169. }
  170. }
  171. }).send();
  172. }
  173. } // namespace Main