mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 05:07:10 +02:00
Edit paid messages exceptions.
This commit is contained in:
parent
1684465e04
commit
c6fd8bcb99
11 changed files with 184 additions and 48 deletions
|
@ -210,6 +210,7 @@ MTPInputPrivacyKey KeyToTL(UserPrivacy::Key key) {
|
|||
case Key::About: return MTP_inputPrivacyKeyAbout();
|
||||
case Key::Birthday: return MTP_inputPrivacyKeyBirthday();
|
||||
case Key::GiftsAutoSave: return MTP_inputPrivacyKeyStarGiftsAutoSave();
|
||||
case Key::NoPaidMessages: return MTP_inputPrivacyKeyNoPaidMessages();
|
||||
}
|
||||
Unexpected("Key in Api::UserPrivacy::KetToTL.");
|
||||
}
|
||||
|
@ -241,6 +242,8 @@ std::optional<UserPrivacy::Key> TLToKey(mtpTypeId type) {
|
|||
case mtpc_inputPrivacyKeyBirthday: return Key::Birthday;
|
||||
case mtpc_privacyKeyStarGiftsAutoSave:
|
||||
case mtpc_inputPrivacyKeyStarGiftsAutoSave: return Key::GiftsAutoSave;
|
||||
case mtpc_privacyKeyNoPaidMessages:
|
||||
case mtpc_inputPrivacyKeyNoPaidMessages: return Key::NoPaidMessages;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
About,
|
||||
Birthday,
|
||||
GiftsAutoSave,
|
||||
NoPaidMessages,
|
||||
};
|
||||
enum class Option {
|
||||
Everyone,
|
||||
|
|
|
@ -523,6 +523,7 @@ void ApiWrap::sendMessageFail(
|
|||
uint64 randomId,
|
||||
FullMsgId itemId) {
|
||||
const auto show = ShowForPeer(peer);
|
||||
const auto paidStarsPrefix = u"ALLOW_PAYMENT_REQUIRED_"_q;
|
||||
if (show && error == u"PEER_FLOOD"_q) {
|
||||
show->showBox(
|
||||
Ui::MakeInformBox(
|
||||
|
@ -577,11 +578,19 @@ void ApiWrap::sendMessageFail(
|
|||
if (show) {
|
||||
show->showToast(tr::lng_error_schedule_limit(tr::now));
|
||||
}
|
||||
} else if (error.startsWith(u"ALLOW_PAYMENT_REQUIRED_"_q)) {
|
||||
} else if (error.startsWith(paidStarsPrefix)) {
|
||||
if (show) {
|
||||
show->showToast(
|
||||
u"Payment requirements changed. Please, try again."_q);
|
||||
}
|
||||
if (const auto stars = error.mid(paidStarsPrefix.size()).toInt()) {
|
||||
if (const auto user = peer->asUser()) {
|
||||
user->setStarsPerMessage(stars);
|
||||
} else if (const auto channel = peer->asChannel()) {
|
||||
channel->setStarsPerMessage(stars);
|
||||
}
|
||||
}
|
||||
peer->updateFull();
|
||||
}
|
||||
if (const auto item = _session->data().message(itemId)) {
|
||||
Assert(randomId != 0);
|
||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "settings/settings_privacy_controllers.h"
|
||||
#include "settings/settings_privacy_security.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
@ -561,6 +562,39 @@ auto PrivacyExceptionsBoxController::createRow(not_null<History*> history)
|
|||
return result;
|
||||
}
|
||||
|
||||
void EditNoPaidMessagesExceptions(
|
||||
not_null<Window::SessionController*> window,
|
||||
const Api::UserPrivacy::Rule &value) {
|
||||
auto controller = std::make_unique<PrivacyExceptionsBoxController>(
|
||||
&window->session(),
|
||||
tr::lng_messages_privacy_remove_fee(),
|
||||
value.always,
|
||||
std::optional<SpecialRowType>());
|
||||
auto initBox = [=, controller = controller.get()](
|
||||
not_null<PeerListBox*> box) {
|
||||
box->addButton(tr::lng_settings_save(), [=] {
|
||||
auto copy = value;
|
||||
auto &setTo = copy.always;
|
||||
setTo.peers = box->collectSelectedRows();
|
||||
setTo.premiums = false;
|
||||
setTo.miniapps = false;
|
||||
auto &removeFrom = copy.never;
|
||||
for (const auto peer : setTo.peers) {
|
||||
removeFrom.peers.erase(
|
||||
ranges::remove(removeFrom.peers, peer),
|
||||
end(removeFrom.peers));
|
||||
}
|
||||
window->session().api().userPrivacy().save(
|
||||
Api::UserPrivacy::Key::NoPaidMessages,
|
||||
copy);
|
||||
box->closeBox();
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||
};
|
||||
window->show(
|
||||
Box<PeerListBox>(std::move(controller), std::move(initBox)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool EditPrivacyController::hasOption(Option option) const {
|
||||
|
@ -923,11 +957,12 @@ void EditMessagesPrivacyBox(
|
|||
constexpr auto kOptionPremium = 1;
|
||||
constexpr auto kOptionCharge = 2;
|
||||
|
||||
const auto session = &controller->session();
|
||||
const auto allowed = [=] {
|
||||
return controller->session().premium()
|
||||
|| controller->session().appConfig().newRequirePremiumFree();
|
||||
return session->premium()
|
||||
|| session->appConfig().newRequirePremiumFree();
|
||||
};
|
||||
const auto privacy = &controller->session().api().globalPrivacy();
|
||||
const auto privacy = &session->api().globalPrivacy();
|
||||
const auto inner = box->verticalLayout();
|
||||
inner->add(object_ptr<Ui::PlainShadow>(box));
|
||||
|
||||
|
@ -995,18 +1030,45 @@ void EditMessagesPrivacyBox(
|
|||
|
||||
state->stars = SetupChargeSlider(
|
||||
chargeInner,
|
||||
controller->session().user(),
|
||||
session->user(),
|
||||
savedValue);
|
||||
|
||||
Ui::AddSkip(chargeInner);
|
||||
Ui::AddSubsectionTitle(
|
||||
chargeInner,
|
||||
tr::lng_messages_privacy_exceptions());
|
||||
|
||||
const auto key = Api::UserPrivacy::Key::NoPaidMessages;
|
||||
session->api().userPrivacy().reload(key);
|
||||
auto label = session->api().userPrivacy().value(
|
||||
key
|
||||
) | rpl::map([=](const Api::UserPrivacy::Rule &value) {
|
||||
using namespace Settings;
|
||||
const auto always = ExceptionUsersCount(value.always.peers);
|
||||
return always
|
||||
? tr::lng_edit_privacy_exceptions_count(
|
||||
tr::now,
|
||||
lt_count,
|
||||
always)
|
||||
: QString();
|
||||
});
|
||||
|
||||
const auto exceptions = Settings::AddButtonWithLabel(
|
||||
chargeInner,
|
||||
tr::lng_messages_privacy_remove_fee(),
|
||||
rpl::single(u""_q),
|
||||
std::move(label),
|
||||
st::settingsButtonNoIcon);
|
||||
|
||||
const auto shower = exceptions->lifetime().make_state<rpl::lifetime>();
|
||||
exceptions->setClickedCallback([=] {
|
||||
*shower = session->api().userPrivacy().value(
|
||||
key
|
||||
) | rpl::take(
|
||||
1
|
||||
) | rpl::start_with_next([=](const Api::UserPrivacy::Rule &value) {
|
||||
EditNoPaidMessagesExceptions(controller, value);
|
||||
});
|
||||
});
|
||||
Ui::AddSkip(chargeInner);
|
||||
Ui::AddDividerText(chargeInner, tr::lng_messages_privacy_remove_about());
|
||||
|
||||
|
|
|
@ -869,15 +869,11 @@ int ChannelData::starsPerMessage() const {
|
|||
}
|
||||
|
||||
void ChannelData::setStarsPerMessage(int stars) {
|
||||
if (!mgInfo || starsPerMessage() == stars) {
|
||||
return;
|
||||
}
|
||||
const auto removed = mgInfo->_starsPerMessage && !stars;
|
||||
mgInfo->_starsPerMessage = stars;
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
if (removed) {
|
||||
session().local().clearPeerTrusted(id);
|
||||
if (mgInfo && starsPerMessage() != stars) {
|
||||
mgInfo->_starsPerMessage = stars;
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
}
|
||||
checkTrustedPayForMessage();
|
||||
}
|
||||
|
||||
int ChannelData::peerGiftsCount() const {
|
||||
|
|
|
@ -50,6 +50,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/history_view_element.h"
|
||||
#include "history/history_item.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "storage/storage_facade.h"
|
||||
#include "storage/storage_shared_media.h"
|
||||
|
||||
|
@ -341,6 +342,17 @@ void PeerData::invalidateEmptyUserpic() {
|
|||
_userpicEmpty = nullptr;
|
||||
}
|
||||
|
||||
void PeerData::checkTrustedPayForMessage() {
|
||||
if (!_checkedTrustedPayForMessage
|
||||
&& !starsPerMessage()
|
||||
&& session().local().peerTrustedPayForMessageRead()) {
|
||||
_checkedTrustedPayForMessage = 1;
|
||||
if (session().local().hasPeerTrustedPayForMessageEntry(id)) {
|
||||
session().local().clearPeerTrustedPayForMessage(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ClickHandlerPtr PeerData::createOpenLink() {
|
||||
return std::make_shared<PeerClickHandler>(this);
|
||||
}
|
||||
|
|
|
@ -504,6 +504,7 @@ protected:
|
|||
void updateUserpic(PhotoId photoId, MTP::DcId dcId, bool hasVideo);
|
||||
void clearUserpic();
|
||||
void invalidateEmptyUserpic();
|
||||
void checkTrustedPayForMessage();
|
||||
|
||||
private:
|
||||
void fillNames();
|
||||
|
@ -538,9 +539,10 @@ private:
|
|||
crl::time _lastFullUpdate = 0;
|
||||
|
||||
QString _name;
|
||||
uint32 _nameVersion : 30 = 1;
|
||||
uint32 _nameVersion : 29 = 1;
|
||||
uint32 _sensitiveContent : 1 = 0;
|
||||
uint32 _wallPaperOverriden : 1 = 0;
|
||||
uint32 _checkedTrustedPayForMessage : 1 = 0;
|
||||
|
||||
TimeId _ttlPeriod = 0;
|
||||
|
||||
|
|
|
@ -543,13 +543,10 @@ int UserData::starsPerMessage() const {
|
|||
|
||||
void UserData::setStarsPerMessage(int stars) {
|
||||
if (_starsPerMessage != stars) {
|
||||
const auto removed = _starsPerMessage && !stars;
|
||||
_starsPerMessage = stars;
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
if (removed) {
|
||||
session().local().clearPeerTrusted(id);
|
||||
}
|
||||
}
|
||||
checkTrustedPayForMessage();
|
||||
}
|
||||
|
||||
bool UserData::canAddContact() const {
|
||||
|
|
|
@ -284,7 +284,7 @@ void ShowSendPaidConfirm(
|
|||
const auto singlePeer = (peers.size() > 1)
|
||||
? (PeerData*)nullptr
|
||||
: peers.front().get();
|
||||
const auto recipientId = singlePeer ? singlePeer->id : PeerId();
|
||||
const auto singlePeerId = singlePeer ? singlePeer->id : PeerId();
|
||||
const auto check = [=] {
|
||||
const auto required = details.stars;
|
||||
if (!required) {
|
||||
|
@ -299,7 +299,7 @@ void ShowSendPaidConfirm(
|
|||
Settings::MaybeRequestBalanceIncrease(
|
||||
show,
|
||||
required,
|
||||
Settings::SmallBalanceForMessage{ .recipientId = recipientId },
|
||||
Settings::SmallBalanceForMessage{ .recipientId = singlePeerId },
|
||||
done);
|
||||
};
|
||||
auto usersOnly = true;
|
||||
|
@ -309,9 +309,15 @@ void ShowSendPaidConfirm(
|
|||
break;
|
||||
}
|
||||
}
|
||||
const auto singlePeerStars = singlePeer
|
||||
? singlePeer->starsPerMessageChecked()
|
||||
: 0;
|
||||
if (singlePeer) {
|
||||
const auto session = &singlePeer->session();
|
||||
if (session->local().isPeerTrustedPayForMessage(recipientId)) {
|
||||
const auto trusted = session->local().isPeerTrustedPayForMessage(
|
||||
singlePeerId,
|
||||
singlePeerStars);
|
||||
if (trusted) {
|
||||
check();
|
||||
return;
|
||||
}
|
||||
|
@ -323,7 +329,9 @@ void ShowSendPaidConfirm(
|
|||
const auto proceed = [=](Fn<void()> close) {
|
||||
if (singlePeer && (*trust)->checked()) {
|
||||
const auto session = &singlePeer->session();
|
||||
session->local().markPeerTrustedPayForMessage(recipientId);
|
||||
session->local().markPeerTrustedPayForMessage(
|
||||
singlePeerId,
|
||||
singlePeerStars);
|
||||
}
|
||||
check();
|
||||
close();
|
||||
|
|
|
@ -3148,7 +3148,7 @@ void Account::readSelf(
|
|||
}
|
||||
|
||||
void Account::writeTrustedPeers() {
|
||||
if (_trustedPeers.empty()) {
|
||||
if (_trustedPeers.empty() && _trustedPayPerMessage.empty()) {
|
||||
if (_trustedPeersKey) {
|
||||
ClearKey(_trustedPeersKey, _basePath);
|
||||
_trustedPeersKey = 0;
|
||||
|
@ -3160,7 +3160,10 @@ void Account::writeTrustedPeers() {
|
|||
_trustedPeersKey = GenerateKey(_basePath);
|
||||
writeMapQueued();
|
||||
}
|
||||
quint32 size = sizeof(qint32) + _trustedPeers.size() * sizeof(quint64);
|
||||
quint32 size = sizeof(qint32)
|
||||
+ _trustedPeers.size() * sizeof(quint64)
|
||||
+ sizeof(qint32)
|
||||
+ _trustedPayPerMessage.size() * (sizeof(quint64) + sizeof(qint32));
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << qint32(_trustedPeers.size());
|
||||
for (const auto &[peerId, mask] : _trustedPeers) {
|
||||
|
@ -3170,6 +3173,10 @@ void Account::writeTrustedPeers() {
|
|||
value |= (quint64(mask) << 56);
|
||||
data.stream << value;
|
||||
}
|
||||
data.stream << qint32(_trustedPayPerMessage.size());
|
||||
for (const auto &[peerId, stars] : _trustedPayPerMessage) {
|
||||
data.stream << SerializePeerId(peerId) << qint32(stars);
|
||||
}
|
||||
|
||||
FileWriteDescriptor file(_trustedPeersKey, _basePath);
|
||||
file.writeEncrypted(data, _localKey);
|
||||
|
@ -3192,9 +3199,9 @@ void Account::readTrustedPeers() {
|
|||
return;
|
||||
}
|
||||
|
||||
qint32 size = 0;
|
||||
trusted.stream >> size;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
qint32 trustedCount = 0;
|
||||
trusted.stream >> trustedCount;
|
||||
for (int i = 0; i < trustedCount; ++i) {
|
||||
auto value = quint64();
|
||||
trusted.stream >> value;
|
||||
const auto mask = base::flags<PeerTrustFlag>::from_raw(
|
||||
|
@ -3203,6 +3210,28 @@ void Account::readTrustedPeers() {
|
|||
const auto peerId = DeserializePeerId(peerIdSerialized);
|
||||
_trustedPeers.emplace(peerId, mask);
|
||||
}
|
||||
if (trusted.stream.atEnd()) {
|
||||
return;
|
||||
}
|
||||
qint32 payPerMessageCount = 0;
|
||||
trusted.stream >> payPerMessageCount;
|
||||
const auto owner = _owner->sessionExists()
|
||||
? &_owner->session().data()
|
||||
: nullptr;
|
||||
for (int i = 0; i < payPerMessageCount; ++i) {
|
||||
auto value = quint64();
|
||||
auto stars = qint32();
|
||||
trusted.stream >> value >> stars;
|
||||
const auto peerId = DeserializePeerId(value);
|
||||
const auto peer = owner ? owner->peerLoaded(peerId) : nullptr;
|
||||
const auto now = peer ? peer->starsPerMessage() : stars;
|
||||
if (now > 0 && now <= stars) {
|
||||
_trustedPayPerMessage.emplace(peerId, stars);
|
||||
}
|
||||
}
|
||||
if (_trustedPayPerMessage.size() != payPerMessageCount) {
|
||||
writeTrustedPeers();
|
||||
}
|
||||
}
|
||||
|
||||
void Account::markPeerTrustedOpenGame(PeerId peerId) {
|
||||
|
@ -3269,32 +3298,45 @@ bool Account::isPeerTrustedOpenWebView(PeerId peerId) {
|
|||
&& ((i->second & PeerTrustFlag::OpenWebView) != 0);
|
||||
}
|
||||
|
||||
void Account::markPeerTrustedPayForMessage(PeerId peerId) {
|
||||
if (isPeerTrustedPayForMessage(peerId)) {
|
||||
void Account::markPeerTrustedPayForMessage(
|
||||
PeerId peerId,
|
||||
int starsPerMessage) {
|
||||
if (isPeerTrustedPayForMessage(peerId, starsPerMessage)) {
|
||||
return;
|
||||
}
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
if (i == end(_trustedPeers)) {
|
||||
_trustedPeers.emplace(
|
||||
peerId,
|
||||
PeerTrustFlag::NoOpenGame | PeerTrustFlag::PayForMessage);
|
||||
const auto i = _trustedPayPerMessage.find(peerId);
|
||||
if (i == end(_trustedPayPerMessage)) {
|
||||
_trustedPayPerMessage.emplace(peerId, starsPerMessage);
|
||||
} else {
|
||||
i->second |= PeerTrustFlag::PayForMessage;
|
||||
i->second = starsPerMessage;
|
||||
}
|
||||
writeTrustedPeers();
|
||||
}
|
||||
|
||||
bool Account::isPeerTrustedPayForMessage(PeerId peerId) {
|
||||
bool Account::isPeerTrustedPayForMessage(
|
||||
PeerId peerId,
|
||||
int starsPerMessage) {
|
||||
if (starsPerMessage <= 0) {
|
||||
return true;
|
||||
}
|
||||
readTrustedPeers();
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
return (i != end(_trustedPeers))
|
||||
&& ((i->second & PeerTrustFlag::PayForMessage) != 0);
|
||||
const auto i = _trustedPayPerMessage.find(peerId);
|
||||
return (i != end(_trustedPayPerMessage))
|
||||
&& (i->second >= starsPerMessage);
|
||||
}
|
||||
|
||||
void Account::clearPeerTrusted(PeerId peerId) {
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
if (i != end(_trustedPeers)) {
|
||||
_trustedPeers.erase(i);
|
||||
bool Account::peerTrustedPayForMessageRead() const {
|
||||
return _trustedPeersRead;
|
||||
}
|
||||
|
||||
bool Account::hasPeerTrustedPayForMessageEntry(PeerId peerId) const {
|
||||
return _trustedPayPerMessage.contains(peerId);
|
||||
}
|
||||
|
||||
void Account::clearPeerTrustedPayForMessage(PeerId peerId) {
|
||||
const auto i = _trustedPayPerMessage.find(peerId);
|
||||
if (i != end(_trustedPayPerMessage)) {
|
||||
_trustedPayPerMessage.erase(i);
|
||||
writeTrustedPeers();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,9 +173,13 @@ public:
|
|||
[[nodiscard]] bool isPeerTrustedPayment(PeerId peerId);
|
||||
void markPeerTrustedOpenWebView(PeerId peerId);
|
||||
[[nodiscard]] bool isPeerTrustedOpenWebView(PeerId peerId);
|
||||
void markPeerTrustedPayForMessage(PeerId peerId);
|
||||
[[nodiscard]] bool isPeerTrustedPayForMessage(PeerId peerId);
|
||||
void clearPeerTrusted(PeerId peerId);
|
||||
void markPeerTrustedPayForMessage(PeerId peerId, int starsPerMessage);
|
||||
[[nodiscard]] bool isPeerTrustedPayForMessage(
|
||||
PeerId peerId,
|
||||
int starsPerMessage);
|
||||
[[nodiscard]] bool peerTrustedPayForMessageRead() const;
|
||||
[[nodiscard]] bool hasPeerTrustedPayForMessageEntry(PeerId peerId) const;
|
||||
void clearPeerTrustedPayForMessage(PeerId peerId);
|
||||
|
||||
void enforceModernStorageIdBots();
|
||||
[[nodiscard]] Webview::StorageId resolveStorageIdBots();
|
||||
|
@ -210,7 +214,6 @@ private:
|
|||
NoOpenGame = (1 << 0),
|
||||
Payment = (1 << 1),
|
||||
OpenWebView = (1 << 2),
|
||||
PayForMessage = (1 << 3),
|
||||
};
|
||||
friend inline constexpr bool is_flag_type(PeerTrustFlag) { return true; };
|
||||
|
||||
|
@ -329,6 +332,7 @@ private:
|
|||
qint32 _cacheBigFileTotalTimeLimit = 0;
|
||||
|
||||
base::flat_map<PeerId, base::flags<PeerTrustFlag>> _trustedPeers;
|
||||
base::flat_map<PeerId, int> _trustedPayPerMessage;
|
||||
bool _trustedPeersRead = false;
|
||||
bool _readingUserSettings = false;
|
||||
bool _recentHashtagsAndBotsWereRead = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue