Keep separate MTP::Config's for separate accounts.

This commit is contained in:
John Preston 2020-06-17 13:36:25 +04:00
parent 63cdda2df7
commit 357caf8007
142 changed files with 1901 additions and 1263 deletions

View file

@ -755,8 +755,6 @@ PRIVATE
mtproto/connection_tcp.cpp mtproto/connection_tcp.cpp
mtproto/connection_tcp.h mtproto/connection_tcp.h
mtproto/core_types.h mtproto/core_types.h
mtproto/dc_options.cpp
mtproto/dc_options.h
mtproto/dedicated_file_loader.cpp mtproto/dedicated_file_loader.cpp
mtproto/dedicated_file_loader.h mtproto/dedicated_file_loader.h
mtproto/facade.cpp mtproto/facade.cpp
@ -912,6 +910,8 @@ PRIVATE
storage/serialize_common.h storage/serialize_common.h
storage/serialize_document.cpp storage/serialize_document.cpp
storage/serialize_document.h storage/serialize_document.h
storage/serialize_peer.cpp
storage/serialize_peer.h
storage/storage_account.cpp storage/storage_account.cpp
storage/storage_account.h storage/storage_account.h
storage/storage_accounts.cpp storage/storage_accounts.cpp

View file

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Api { namespace Api {
SelfDestruct::SelfDestruct(not_null<ApiWrap*> api) SelfDestruct::SelfDestruct(not_null<ApiWrap*> api)
: _api(api->instance()) { : _api(&api->instance()) {
} }
void SelfDestruct::reload() { void SelfDestruct::reload() {

View file

@ -21,7 +21,7 @@ constexpr auto kRefreshAppConfigTimeout = 3 * crl::time(1000);
SensitiveContent::SensitiveContent(not_null<ApiWrap*> api) SensitiveContent::SensitiveContent(not_null<ApiWrap*> api)
: _session(&api->session()) : _session(&api->session())
, _api(api->instance()) , _api(&api->instance())
, _appConfigReloadTimer([=] { _session->account().appConfig().refresh(); }) { , _appConfigReloadTimer([=] { _session->account().appConfig().refresh(); }) {
} }

View file

@ -11,7 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
@ -39,7 +40,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "app.h" // App::formatPhone #include "app.h" // App::formatPhone
#include "facades.h"
namespace Api { namespace Api {
namespace { namespace {
@ -340,7 +340,9 @@ void Updates::channelDifferenceDone(
channel->ptsSetRequesting(false); channel->ptsSetRequesting(false);
if (!isFinal) { if (!isFinal) {
MTP_LOG(0, ("getChannelDifference { good - after not final channelDifference was received }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getChannelDifference "
"{ good - after not final channelDifference was received }%1"
).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
getChannelDifference(channel); getChannelDifference(channel);
} else if (ranges::contains( } else if (ranges::contains(
_activeChats, _activeChats,
@ -410,7 +412,9 @@ void Updates::differenceDone(const MTPupdates_Difference &result) {
_ptsWaiter.setRequesting(false); _ptsWaiter.setRequesting(false);
MTP_LOG(0, ("getDifference { good - after a slice of difference was received }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getDifference "
"{ good - after a slice of difference was received }%1"
).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
getDifference(); getDifference();
} break; } break;
case mtpc_updates_difference: { case mtpc_updates_difference: {
@ -566,7 +570,9 @@ void Updates::getDifferenceAfterFail() {
wait = _getDifferenceTimeAfterFail - now; wait = _getDifferenceTimeAfterFail - now;
} else { } else {
_ptsWaiter.setRequesting(false); _ptsWaiter.setRequesting(false);
MTP_LOG(0, ("getDifference { force - after get difference failed }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getDifference "
"{ force - after get difference failed }%1"
).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
getDifference(); getDifference();
} }
} }
@ -650,7 +656,7 @@ void Updates::getChannelDifference(
} }
void Updates::sendPing() { void Updates::sendPing() {
_session->mtp()->ping(); _session->mtp().ping();
} }
void Updates::addActiveChat(rpl::producer<PeerData*> chat) { void Updates::addActiveChat(rpl::producer<PeerData*> chat) {
@ -680,9 +686,10 @@ void Updates::requestChannelRangeDifference(not_null<History*> history) {
return; return;
} }
MTP_LOG(0, ("getChannelDifference { good - " MTP_LOG(0, ("getChannelDifference "
"after channelDifferenceTooLong was received, " "{ good - after channelDifferenceTooLong was received, "
"validating history part }%1").arg(cTestMode() ? " TESTMODE" : "")); "validating history part }%1"
).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
channelRangeDifferenceSend(channel, range, channel->pts()); channelRangeDifferenceSend(channel, range, channel->pts());
} }
@ -752,10 +759,10 @@ void Updates::channelRangeDifferenceDone(
} }
if (!isFinal && nextRequestPts) { if (!isFinal && nextRequestPts) {
MTP_LOG(0, ("getChannelDifference { " MTP_LOG(0, ("getChannelDifference "
"good - after not final channelDifference was received, " "{ good - after not final channelDifference was received, "
"validating history part }%1" "validating history part }%1"
).arg(cTestMode() ? " TESTMODE" : "")); ).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
channelRangeDifferenceSend(channel, range, nextRequestPts); channelRangeDifferenceSend(channel, range, nextRequestPts);
} }
} }
@ -764,7 +771,7 @@ void Updates::mtpNewSessionCreated() {
Core::App().checkAutoLock(); Core::App().checkAutoLock();
_updatesSeq = 0; _updatesSeq = 0;
MTP_LOG(0, ("getDifference { after new_session_created }%1" MTP_LOG(0, ("getDifference { after new_session_created }%1"
).arg(cTestMode() ? " TESTMODE" : "")); ).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
getDifference(); getDifference();
} }
@ -789,25 +796,26 @@ bool Updates::isIdle() const {
void Updates::updateOnline(bool gotOtherOffline) { void Updates::updateOnline(bool gotOtherOffline) {
crl::on_main(&session(), [] { Core::App().checkAutoLock(); }); crl::on_main(&session(), [] { Core::App().checkAutoLock(); });
const auto &config = _session->serverConfig();
bool isOnline = Core::App().hasActiveWindow(&session()); bool isOnline = Core::App().hasActiveWindow(&session());
int updateIn = Global::OnlineUpdatePeriod(); int updateIn = config.onlineUpdatePeriod;
Assert(updateIn >= 0); Assert(updateIn >= 0);
if (isOnline) { if (isOnline) {
const auto idle = crl::now() - Core::App().lastNonIdleTime(); const auto idle = crl::now() - Core::App().lastNonIdleTime();
if (idle >= Global::OfflineIdleTimeout()) { if (idle >= config.offlineIdleTimeout) {
isOnline = false; isOnline = false;
if (!_isIdle) { if (!_isIdle) {
_isIdle = true; _isIdle = true;
_idleFinishTimer.callOnce(900); _idleFinishTimer.callOnce(900);
} }
} else { } else {
updateIn = qMin(updateIn, int(Global::OfflineIdleTimeout() - idle)); updateIn = qMin(updateIn, int(config.offlineIdleTimeout - idle));
Assert(updateIn >= 0); Assert(updateIn >= 0);
} }
} }
auto ms = crl::now(); auto ms = crl::now();
if (isOnline != _lastWasOnline if (isOnline != _lastWasOnline
|| (isOnline && _lastSetOnline + Global::OnlineUpdatePeriod() <= ms) || (isOnline && _lastSetOnline + config.onlineUpdatePeriod <= ms)
|| (isOnline && gotOtherOffline)) { || (isOnline && gotOtherOffline)) {
api().request(base::take(_onlineRequest)).cancel(); api().request(base::take(_onlineRequest)).cancel();
@ -828,7 +836,7 @@ void Updates::updateOnline(bool gotOtherOffline) {
} }
const auto self = session().user(); const auto self = session().user();
self->onlineTill = base::unixtime::now() + (isOnline ? (Global::OnlineUpdatePeriod() / 1000) : -1); self->onlineTill = base::unixtime::now() + (isOnline ? (config.onlineUpdatePeriod / 1000) : -1);
session().changes().peerUpdated( session().changes().peerUpdated(
self, self,
Data::PeerUpdate::Flag::OnlineStatus); Data::PeerUpdate::Flag::OnlineStatus);
@ -838,7 +846,7 @@ void Updates::updateOnline(bool gotOtherOffline) {
_lastSetOnline = ms; _lastSetOnline = ms;
} else if (isOnline) { } else if (isOnline) {
updateIn = qMin(updateIn, int(_lastSetOnline + Global::OnlineUpdatePeriod() - ms)); updateIn = qMin(updateIn, int(_lastSetOnline + config.onlineUpdatePeriod - ms));
Assert(updateIn >= 0); Assert(updateIn >= 0);
} }
_onlineTimer.callOnce(updateIn); _onlineTimer.callOnce(updateIn);
@ -846,7 +854,7 @@ void Updates::updateOnline(bool gotOtherOffline) {
void Updates::checkIdleFinish() { void Updates::checkIdleFinish() {
if (crl::now() - Core::App().lastNonIdleTime() if (crl::now() - Core::App().lastNonIdleTime()
< Global::OfflineIdleTimeout()) { < _session->serverConfig().offlineIdleTimeout) {
_idleFinishTimer.cancel(); _idleFinishTimer.cancel();
_isIdle = false; _isIdle = false;
updateOnline(); updateOnline();
@ -1153,7 +1161,9 @@ void Updates::applyUpdates(
|| (viaBotId && !session().data().userLoaded(viaBotId->v)) || (viaBotId && !session().data().userLoaded(viaBotId->v))
|| (entities && !MentionUsersLoaded(&session(), *entities)) || (entities && !MentionUsersLoaded(&session(), *entities))
|| (fwd && !ForwardedInfoDataLoaded(&session(), *fwd))) { || (fwd && !ForwardedInfoDataLoaded(&session(), *fwd))) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getDifference "
"{ good - getting user for updateShortMessage }%1"
).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
return getDifference(); return getDifference();
} }
if (updateAndApply(d.vpts().v, d.vpts_count().v, updates)) { if (updateAndApply(d.vpts().v, d.vpts_count().v, updates)) {
@ -1174,7 +1184,9 @@ void Updates::applyUpdates(
|| (viaBotId && !session().data().userLoaded(viaBotId->v)) || (viaBotId && !session().data().userLoaded(viaBotId->v))
|| (entities && !MentionUsersLoaded(&session(), *entities)) || (entities && !MentionUsersLoaded(&session(), *entities))
|| (fwd && !ForwardedInfoDataLoaded(&session(), *fwd))) { || (fwd && !ForwardedInfoDataLoaded(&session(), *fwd))) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortChatMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getDifference "
"{ good - getting user for updateShortChatMessage }%1"
).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
if (chat && noFrom) { if (chat && noFrom) {
session().api().requestFullPeer(chat); session().api().requestFullPeer(chat);
} }
@ -1232,7 +1244,9 @@ void Updates::applyUpdates(
} break; } break;
case mtpc_updatesTooLong: { case mtpc_updatesTooLong: {
MTP_LOG(0, ("getDifference { good - updatesTooLong received }%1").arg(cTestMode() ? " TESTMODE" : "")); MTP_LOG(0, ("getDifference "
"{ good - updatesTooLong received }%1"
).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
return getDifference(); return getDifference();
} break; } break;
} }
@ -1248,9 +1262,9 @@ void Updates::feedUpdate(const MTPUpdate &update) {
const auto isDataLoaded = AllDataLoadedForMessage(&session(), d.vmessage()); const auto isDataLoaded = AllDataLoadedForMessage(&session(), d.vmessage());
if (!requestingDifference() && isDataLoaded != DataIsLoadedResult::Ok) { if (!requestingDifference() && isDataLoaded != DataIsLoadedResult::Ok) {
MTP_LOG(0, ("getDifference { good - " MTP_LOG(0, ("getDifference "
"after not all data loaded in updateNewMessage }%1" "{ good - after not all data loaded in updateNewMessage }%1"
).arg(cTestMode() ? " TESTMODE" : "")); ).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
// This can be if this update was created by grouping // This can be if this update was created by grouping
// some short message update into an updates vector. // some short message update into an updates vector.
@ -1265,14 +1279,16 @@ void Updates::feedUpdate(const MTPUpdate &update) {
auto channel = session().data().channelLoaded(peerToChannel(PeerFromMessage(d.vmessage()))); auto channel = session().data().channelLoaded(peerToChannel(PeerFromMessage(d.vmessage())));
const auto isDataLoaded = AllDataLoadedForMessage(&session(), d.vmessage()); const auto isDataLoaded = AllDataLoadedForMessage(&session(), d.vmessage());
if (!requestingDifference() && (!channel || isDataLoaded != DataIsLoadedResult::Ok)) { if (!requestingDifference() && (!channel || isDataLoaded != DataIsLoadedResult::Ok)) {
MTP_LOG(0, ("getDifference { good - " MTP_LOG(0, ("getDifference "
"after not all data loaded in updateNewChannelMessage }%1" "{ good - after not all data loaded in updateNewChannelMessage }%1"
).arg(cTestMode() ? " TESTMODE" : "")); ).arg(_session->mtp().isTestMode() ? " TESTMODE" : ""));
// Request last active supergroup participants if the 'from' user was not loaded yet. // Request last active supergroup participants if the 'from' user was not loaded yet.
// This will optimize similar getDifference() calls for almost all next messages. // This will optimize similar getDifference() calls for almost all next messages.
if (isDataLoaded == DataIsLoadedResult::FromNotLoaded && channel && channel->isMegagroup()) { if (isDataLoaded == DataIsLoadedResult::FromNotLoaded && channel && channel->isMegagroup()) {
if (channel->mgInfo->lastParticipants.size() < Global::ChatSizeMax() && (channel->mgInfo->lastParticipants.empty() || channel->mgInfo->lastParticipants.size() < channel->membersCount())) { if (channel->mgInfo->lastParticipants.size() < _session->serverConfig().chatSizeMax
&& (channel->mgInfo->lastParticipants.empty()
|| channel->mgInfo->lastParticipants.size() < channel->membersCount())) {
session().api().requestLastParticipants(channel); session().api().requestLastParticipants(channel);
} }
} }
@ -1657,11 +1673,11 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateDcOptions: { case mtpc_updateDcOptions: {
auto &d = update.c_updateDcOptions(); auto &d = update.c_updateDcOptions();
Core::App().dcOptions()->addFromList(d.vdc_options()); session().mtp().dcOptions().addFromList(d.vdc_options());
} break; } break;
case mtpc_updateConfig: { case mtpc_updateConfig: {
session().mtp()->requestConfig(); session().mtp().requestConfig();
} break; } break;
case mtpc_updateUserPhone: { case mtpc_updateUserPhone: {

View file

@ -43,6 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h" #include "mainwindow.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "boxes/add_contact_box.h" #include "boxes/add_contact_box.h"
#include "mtproto/mtproto_config.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_message.h" #include "history/history_message.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
@ -231,7 +232,7 @@ bool ApiWrap::BlockedUsersSlice::operator!=(const BlockedUsersSlice &other) cons
} }
ApiWrap::ApiWrap(not_null<Main::Session*> session) ApiWrap::ApiWrap(not_null<Main::Session*> session)
: MTP::Sender(session->account().mtp()) : MTP::Sender(&session->account().mtp())
, _session(session) , _session(session)
, _messageDataResolveDelayed([=] { resolveMessageDatas(); }) , _messageDataResolveDelayed([=] { resolveMessageDatas(); })
, _webPagesTimer([=] { resolveWebPages(); }) , _webPagesTimer([=] { resolveWebPages(); })
@ -572,10 +573,10 @@ void ApiWrap::sendMessageFail(
FullMsgId itemId) { FullMsgId itemId) {
if (error.type() == qstr("PEER_FLOOD")) { if (error.type() == qstr("PEER_FLOOD")) {
Ui::show(Box<InformBox>( Ui::show(Box<InformBox>(
PeerFloodErrorText(PeerFloodType::Send))); PeerFloodErrorText(&session(), PeerFloodType::Send)));
} else if (error.type() == qstr("USER_BANNED_IN_CHANNEL")) { } else if (error.type() == qstr("USER_BANNED_IN_CHANNEL")) {
const auto link = textcmdLink( const auto link = textcmdLink(
Core::App().createInternalLinkFull(qsl("spambot")), session().createInternalLinkFull(qsl("spambot")),
tr::lng_cant_more_info(tr::now)); tr::lng_cant_more_info(tr::now));
Ui::show(Box<InformBox>(tr::lng_error_public_groups_denied( Ui::show(Box<InformBox>(tr::lng_error_public_groups_denied(
tr::now, tr::now,
@ -754,7 +755,7 @@ QString ApiWrap::exportDirectMessageLink(not_null<HistoryItem*> item) {
} }
} }
} }
return Core::App().createInternalLinkFull(query); return session().createInternalLinkFull(query);
}; };
const auto i = _unlikelyMessageLinks.find(itemId); const auto i = _unlikelyMessageLinks.find(itemId);
const auto current = (i != end(_unlikelyMessageLinks)) const auto current = (i != end(_unlikelyMessageLinks))
@ -1450,7 +1451,7 @@ void ApiWrap::requestLastParticipants(not_null<ChannelData*> channel) {
channel->inputChannel, channel->inputChannel,
MTP_channelParticipantsRecent(), MTP_channelParticipantsRecent(),
MTP_int(offset), MTP_int(offset),
MTP_int(Global::ChatSizeMax()), MTP_int(_session->serverConfig().chatSizeMax),
MTP_int(participantsHash) MTP_int(participantsHash)
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
_participantsRequests.remove(channel); _participantsRequests.remove(channel);
@ -1480,7 +1481,7 @@ void ApiWrap::requestBots(not_null<ChannelData*> channel) {
channel->inputChannel, channel->inputChannel,
MTP_channelParticipantsBots(), MTP_channelParticipantsBots(),
MTP_int(offset), MTP_int(offset),
MTP_int(Global::ChatSizeMax()), MTP_int(_session->serverConfig().chatSizeMax),
MTP_int(participantsHash) MTP_int(participantsHash)
)).done([this, channel](const MTPchannels_ChannelParticipants &result) { )).done([this, channel](const MTPchannels_ChannelParticipants &result) {
_botsRequests.remove(channel); _botsRequests.remove(channel);
@ -1510,7 +1511,7 @@ void ApiWrap::requestAdmins(not_null<ChannelData*> channel) {
channel->inputChannel, channel->inputChannel,
MTP_channelParticipantsAdmins(), MTP_channelParticipantsAdmins(),
MTP_int(offset), MTP_int(offset),
MTP_int(Global::ChatSizeMax()), MTP_int(_session->serverConfig().chatSizeMax),
MTP_int(participantsHash) MTP_int(participantsHash)
)).done([this, channel](const MTPchannels_ChannelParticipants &result) { )).done([this, channel](const MTPchannels_ChannelParticipants &result) {
_adminsRequests.remove(channel); _adminsRequests.remove(channel);
@ -1820,7 +1821,7 @@ void ApiWrap::requestChannelMembersForAdd(
channel->inputChannel, channel->inputChannel,
MTP_channelParticipantsRecent(), MTP_channelParticipantsRecent(),
MTP_int(offset), MTP_int(offset),
MTP_int(Global::ChatSizeMax()), MTP_int(_session->serverConfig().chatSizeMax),
MTP_int(participantsHash) MTP_int(participantsHash)
)).done([this](const MTPchannels_ChannelParticipants &result) { )).done([this](const MTPchannels_ChannelParticipants &result) {
base::take(_channelMembersForAddRequestId); base::take(_channelMembersForAddRequestId);
@ -5038,7 +5039,10 @@ FileLoadTo ApiWrap::fileLoadTaskOptions(const SendAction &action) const {
void ApiWrap::uploadPeerPhoto(not_null<PeerData*> peer, QImage &&image) { void ApiWrap::uploadPeerPhoto(not_null<PeerData*> peer, QImage &&image) {
peer = peer->migrateToOrMe(); peer = peer->migrateToOrMe();
const auto ready = PreparePeerPhoto(instance()->mainDcId(), peer->id, std::move(image)); const auto ready = PreparePeerPhoto(
instance().mainDcId(),
peer->id,
std::move(image));
const auto fakeId = FullMsgId( const auto fakeId = FullMsgId(
peerToChannel(peer->id), peerToChannel(peer->id),

View file

@ -118,9 +118,11 @@ style::InputField CreateBioFieldStyle() {
return result; return result;
} }
QString PeerFloodErrorText(PeerFloodType type) { QString PeerFloodErrorText(
auto link = textcmdLink( not_null<Main::Session*> session,
Core::App().createInternalLinkFull(qsl("spambot")), PeerFloodType type) {
const auto link = textcmdLink(
session->createInternalLinkFull(qsl("spambot")),
tr::lng_cant_more_info(tr::now)); tr::lng_cant_more_info(tr::now));
if (type == PeerFloodType::InviteGroup) { if (type == PeerFloodType::InviteGroup) {
return tr::lng_cant_invite_not_contact(tr::now, lt_more_info, link); return tr::lng_cant_invite_not_contact(tr::now, lt_more_info, link);
@ -190,10 +192,10 @@ void ShowAddParticipantsError(
} else if (error == qstr("BOT_GROUPS_BLOCKED")) { } else if (error == qstr("BOT_GROUPS_BLOCKED")) {
return tr::lng_error_cant_add_bot(tr::now); return tr::lng_error_cant_add_bot(tr::now);
} else if (error == qstr("PEER_FLOOD")) { } else if (error == qstr("PEER_FLOOD")) {
const auto isGroup = (chat->isChat() || chat->isMegagroup()); const auto type = (chat->isChat() || chat->isMegagroup())
return PeerFloodErrorText(isGroup
? PeerFloodType::InviteGroup ? PeerFloodType::InviteGroup
: PeerFloodType::InviteChannel); : PeerFloodType::InviteChannel;
return PeerFloodErrorText(&chat->session(), type);
} else if (error == qstr("ADMINS_TOO_MUCH")) { } else if (error == qstr("ADMINS_TOO_MUCH")) {
return ((chat->isChat() || chat->isMegagroup()) return ((chat->isChat() || chat->isMegagroup())
? tr::lng_error_admin_limit ? tr::lng_error_admin_limit
@ -453,7 +455,7 @@ GroupInfoBox::GroupInfoBox(
const QString &title, const QString &title,
Fn<void(not_null<ChannelData*>)> channelDone) Fn<void(not_null<ChannelData*>)> channelDone)
: _navigation(navigation) : _navigation(navigation)
, _api(_navigation->session().mtp()) , _api(&_navigation->session().mtp())
, _type(type) , _type(type)
, _initialTitle(title) , _initialTitle(title)
, _channelDone(std::move(channelDone)) { , _channelDone(std::move(channelDone)) {
@ -598,7 +600,9 @@ void GroupInfoBox::createGroup(
} else if (error.type() == qstr("PEER_FLOOD")) { } else if (error.type() == qstr("PEER_FLOOD")) {
Ui::show( Ui::show(
Box<InformBox>( Box<InformBox>(
PeerFloodErrorText(PeerFloodType::InviteGroup)), PeerFloodErrorText(
&_navigation->session(),
PeerFloodType::InviteGroup)),
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
} else if (error.type() == qstr("USER_RESTRICTED")) { } else if (error.type() == qstr("USER_RESTRICTED")) {
Ui::show( Ui::show(
@ -750,7 +754,7 @@ SetupChannelBox::SetupChannelBox(
bool existing) bool existing)
: _navigation(navigation) : _navigation(navigation)
, _channel(channel) , _channel(channel)
, _api(_channel->session().mtp()) , _api(&_channel->session().mtp())
, _existing(existing) , _existing(existing)
, _privacyGroup( , _privacyGroup(
std::make_shared<Ui::RadioenumGroup<Privacy>>(Privacy::Public)) std::make_shared<Ui::RadioenumGroup<Privacy>>(Privacy::Public))
@ -790,7 +794,12 @@ SetupChannelBox::SetupChannelBox(
: tr::lng_create_private_channel_about)(tr::now), : tr::lng_create_private_channel_about)(tr::now),
_defaultOptions, _defaultOptions,
_aboutPublicWidth) _aboutPublicWidth)
, _link(this, st::setupChannelLink, nullptr, channel->username, true) { , _link(
this,
st::setupChannelLink,
nullptr,
channel->username,
channel->session().createInternalLink(QString())) {
} }
void SetupChannelBox::prepare() { void SetupChannelBox::prepare() {
@ -1168,7 +1177,7 @@ void SetupChannelBox::firstCheckFail(const RPCError &error) {
EditNameBox::EditNameBox(QWidget*, not_null<UserData*> user) EditNameBox::EditNameBox(QWidget*, not_null<UserData*> user)
: _user(user) : _user(user)
, _api(_user->session().mtp()) , _api(&_user->session().mtp())
, _first(this, st::defaultInputField, tr::lng_signup_firstname(), _user->firstName) , _first(this, st::defaultInputField, tr::lng_signup_firstname(), _user->firstName)
, _last(this, st::defaultInputField, tr::lng_signup_lastname(), _user->lastName) , _last(this, st::defaultInputField, tr::lng_signup_lastname(), _user->lastName)
, _invertOrder(langFirstNameGoesSecond()) { , _invertOrder(langFirstNameGoesSecond()) {
@ -1292,7 +1301,7 @@ RevokePublicLinkBox::Inner::Inner(
Fn<void()> revokeCallback) Fn<void()> revokeCallback)
: TWidget(parent) : TWidget(parent)
, _session(session) , _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _revokeWidth(st::normalFont->width(tr::lng_channels_too_much_public_revoke(tr::now))) , _revokeWidth(st::normalFont->width(tr::lng_channels_too_much_public_revoke(tr::now)))
, _revokeCallback(std::move(revokeCallback)) { , _revokeCallback(std::move(revokeCallback)) {
@ -1320,7 +1329,7 @@ RevokePublicLinkBox::Inner::Inner(
Ui::NameTextOptions()); Ui::NameTextOptions());
row.status.setText( row.status.setText(
st::defaultTextStyle, st::defaultTextStyle,
Core::App().createInternalLink( _session->createInternalLink(
textcmdLink(1, peer->userName())), textcmdLink(1, peer->userName())),
Ui::DialogTextOptions()); Ui::DialogTextOptions());
_rows.push_back(std::move(row)); _rows.push_back(std::move(row));
@ -1401,7 +1410,7 @@ void RevokePublicLinkBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
auto text = text_method( auto text = text_method(
tr::now, tr::now,
lt_link, lt_link,
Core::App().createInternalLink(pressed->userName()), _session->createInternalLink(pressed->userName()),
lt_group, lt_group,
pressed->name); pressed->name);
auto confirmText = tr::lng_channels_too_much_public_revoke(tr::now); auto confirmText = tr::lng_channels_too_much_public_revoke(tr::now);

View file

@ -46,9 +46,11 @@ enum class PeerFloodType {
InviteChannel, InviteChannel,
}; };
style::InputField CreateBioFieldStyle(); [[nodiscard]] style::InputField CreateBioFieldStyle();
QString PeerFloodErrorText(PeerFloodType type); [[nodiscard]] QString PeerFloodErrorText(
not_null<Main::Session*> session,
PeerFloodType type);
void ShowAddParticipantsError( void ShowAddParticipantsError(
const QString &error, const QString &error,
not_null<PeerData*> chat, not_null<PeerData*> chat,

View file

@ -193,7 +193,7 @@ BackgroundBox::Inner::Inner(
not_null<Main::Session*> session) not_null<Main::Session*> session)
: RpWidget(parent) : RpWidget(parent)
, _session(session) , _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [=] { update(); })) { , _check(std::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [=] { update(); })) {
_check->setChecked(true, anim::type::instant); _check->setChecked(true, anim::type::instant);
if (_session->data().wallpapers().empty()) { if (_session->data().wallpapers().empty()) {

View file

@ -514,7 +514,8 @@ void BackgroundPreviewBox::apply() {
} }
void BackgroundPreviewBox::share() { void BackgroundPreviewBox::share() {
QGuiApplication::clipboard()->setText(_paper.shareUrl()); QGuiApplication::clipboard()->setText(
_paper.shareUrl(&_controller->session()));
Ui::Toast::Show(tr::lng_background_link_copied(tr::now)); Ui::Toast::Show(tr::lng_background_link_copied(tr::now));
} }

View file

@ -140,7 +140,7 @@ ChangePhoneBox::EnterPhone::EnterPhone(
QWidget*, QWidget*,
not_null<Main::Session*> session) not_null<Main::Session*> session)
: _session(session) : _session(session)
, _api(session->mtp()) { , _api(&session->mtp()) {
} }
void ChangePhoneBox::EnterPhone::prepare() { void ChangePhoneBox::EnterPhone::prepare() {
@ -257,7 +257,7 @@ ChangePhoneBox::EnterCode::EnterCode(
int codeLength, int codeLength,
int callTimeout) int callTimeout)
: _session(session) : _session(session)
, _api(session->mtp()) , _api(&session->mtp())
, _phone(phone) , _phone(phone)
, _hash(hash) , _hash(hash)
, _codeLength(codeLength) , _codeLength(codeLength)

View file

@ -36,7 +36,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_changes.h" #include "data/data_changes.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "facades.h" #include "mtproto/mtproto_config.h"
#include "facades.h" // Ui::showChatsList
#include "app.h" #include "app.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -351,7 +352,7 @@ MaxInviteBox::MaxInviteBox(QWidget*, not_null<ChannelData*> channel) : BoxConten
tr::lng_participant_invite_sorry( tr::lng_participant_invite_sorry(
tr::now, tr::now,
lt_count, lt_count,
Global::ChatSizeMax()), channel->session().serverConfig().chatSizeMax),
kInformBoxTextOptions, kInformBoxTextOptions,
(st::boxWidth (st::boxWidth
- st::boxPadding.left() - st::boxPadding.left()
@ -433,7 +434,7 @@ PinMessageBox::PinMessageBox(
not_null<PeerData*> peer, not_null<PeerData*> peer,
MsgId msgId) MsgId msgId)
: _peer(peer) : _peer(peer)
, _api(peer->session().mtp()) , _api(&peer->session().mtp())
, _msgId(msgId) , _msgId(msgId)
, _text(this, tr::lng_pinned_pin_sure(tr::now), st::boxLabel) { , _text(this, tr::lng_pinned_pin_sure(tr::now), st::boxLabel) {
} }

View file

@ -225,7 +225,7 @@ ConfirmPhoneBox::ConfirmPhoneBox(
const QString &phone, const QString &phone,
const QString &hash) const QString &hash)
: _session(session) : _session(session)
, _api(session->mtp()) , _api(&session->mtp())
, _phone(phone) , _phone(phone)
, _hash(hash) , _hash(hash)
, _call([this] { sendCall(); }, [this] { update(); }) { , _call([this] { sendCall(); }, [this] { update(); }) {

View file

@ -1059,9 +1059,7 @@ void ProxiesBoxController::refreshChecker(Item &item) {
const auto type = (item.data.type == Type::Http) const auto type = (item.data.type == Type::Http)
? Variants::Http ? Variants::Http
: Variants::Tcp; : Variants::Tcp;
const auto mtproto = _account->mtp(); const auto mtproto = &_account->mtp();
Assert(mtproto != nullptr);
const auto dcId = mtproto->mainDcId(); const auto dcId = mtproto->mainDcId();
item.state = ItemState::Checking; item.state = ItemState::Checking;
@ -1084,7 +1082,7 @@ void ProxiesBoxController::refreshChecker(Item &item) {
dcId); dcId);
item.checkerv6 = nullptr; item.checkerv6 = nullptr;
} else { } else {
const auto options = mtproto->dcOptions()->lookup( const auto options = mtproto->dcOptions().lookup(
dcId, dcId,
MTP::DcType::Regular, MTP::DcType::Regular,
true); true);
@ -1376,9 +1374,7 @@ void ProxiesBoxController::setTryIPv6(bool enabled) {
return; return;
} }
Global::SetTryIPv6(enabled); Global::SetTryIPv6(enabled);
if (const auto mtproto = _account->mtp()) { _account->mtp().restart();
mtproto->restart();
}
Global::RefConnectionTypeChanged().notify(); Global::RefConnectionTypeChanged().notify();
saveDelayed(); saveDelayed();
} }
@ -1410,8 +1406,7 @@ void ProxiesBoxController::updateView(const Item &item) {
if (!selected if (!selected
|| (Global::ProxySettings() != ProxyData::Settings::Enabled)) { || (Global::ProxySettings() != ProxyData::Settings::Enabled)) {
return item.state; return item.state;
} else if (_account->mtp() } else if (_account->mtp().dcstate() == MTP::ConnectedState) {
&& _account->mtp()->dcstate() == MTP::ConnectedState) {
return ItemState::Online; return ItemState::Online;
} }
return ItemState::Connecting; return ItemState::Connecting;

View file

@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/streaming/media_streaming_loader_local.h" #include "media/streaming/media_streaming_loader_local.h"
#include "storage/localimageloader.h" #include "storage/localimageloader.h"
#include "storage/storage_media_prepare.h" #include "storage/storage_media_prepare.h"
#include "mtproto/mtproto_config.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
@ -46,7 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "confirm_box.h" #include "confirm_box.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "facades.h" #include "facades.h" // App::LambdaDelayed.
#include "app.h" #include "app.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -67,7 +68,7 @@ EditCaptionBox::EditCaptionBox(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
not_null<HistoryItem*> item) not_null<HistoryItem*> item)
: _controller(controller) : _controller(controller)
, _api(controller->session().mtp()) , _api(&controller->session().mtp())
, _msgId(item->fullId()) { , _msgId(item->fullId()) {
Expects(item->media() != nullptr); Expects(item->media() != nullptr);
Expects(item->media()->allowsEditCaption()); Expects(item->media()->allowsEditCaption());
@ -304,8 +305,10 @@ EditCaptionBox::EditCaptionBox(
Ui::InputField::Mode::MultiLine, Ui::InputField::Mode::MultiLine,
tr::lng_photo_caption(), tr::lng_photo_caption(),
editData); editData);
_field->setMaxLength(Global::CaptionLengthMax()); _field->setMaxLength(
_field->setSubmitSettings(_controller->session().settings().sendSubmitWay()); _controller->session().serverConfig().captionLengthMax);
_field->setSubmitSettings(
_controller->session().settings().sendSubmitWay());
_field->setInstantReplaces(Ui::InstantReplaces::Default()); _field->setInstantReplaces(Ui::InstantReplaces::Default());
_field->setInstantReplacesEnabled( _field->setInstantReplacesEnabled(
_controller->session().settings().replaceEmojiValue()); _controller->session().settings().replaceEmojiValue());

View file

@ -50,7 +50,7 @@ PasscodeBox::PasscodeBox(
not_null<Main::Session*> session, not_null<Main::Session*> session,
bool turningOff) bool turningOff)
: _session(session) : _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _turningOff(turningOff) , _turningOff(turningOff)
, _about(st::boxWidth - st::boxPadding.left() * 1.5) , _about(st::boxWidth - st::boxPadding.left() * 1.5)
, _oldPasscode(this, st::defaultInputField, tr::lng_passcode_enter_old()) , _oldPasscode(this, st::defaultInputField, tr::lng_passcode_enter_old())
@ -66,7 +66,7 @@ PasscodeBox::PasscodeBox(
not_null<Main::Session*> session, not_null<Main::Session*> session,
const CloudFields &fields) const CloudFields &fields)
: _session(session) : _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _turningOff(fields.turningOff) , _turningOff(fields.turningOff)
, _cloudPwd(true) , _cloudPwd(true)
, _cloudFields(fields) , _cloudFields(fields)
@ -929,7 +929,7 @@ RecoverBox::RecoverBox(
not_null<Main::Session*> session, not_null<Main::Session*> session,
const QString &pattern, const QString &pattern,
bool notEmptyPassport) bool notEmptyPassport)
: _api(session->mtp()) : _api(&session->mtp())
, _pattern(st::normalFont->elided(tr::lng_signin_recover_hint(tr::now, lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5)) , _pattern(st::normalFont->elided(tr::lng_signin_recover_hint(tr::now, lt_recover_email, pattern), st::boxWidth - st::boxPadding.left() * 1.5))
, _notEmptyPassport(notEmptyPassport) , _notEmptyPassport(notEmptyPassport)
, _recoverCode(this, st::defaultInputField, tr::lng_signin_code()) { , _recoverCode(this, st::defaultInputField, tr::lng_signin_code()) {

View file

@ -146,7 +146,7 @@ void PeerListRowWithLink::paintAction(
PeerListGlobalSearchController::PeerListGlobalSearchController( PeerListGlobalSearchController::PeerListGlobalSearchController(
not_null<Window::SessionNavigation*> navigation) not_null<Window::SessionNavigation*> navigation)
: _navigation(navigation) : _navigation(navigation)
, _api(_navigation->session().mtp()) { , _api(&_navigation->session().mtp()) {
_timer.setCallback([this] { searchOnServer(); }); _timer.setCallback([this] { searchOnServer(); });
} }

View file

@ -20,11 +20,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "dialogs/dialogs_indexed_list.h" #include "dialogs/dialogs_indexed_list.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "facades.h" #include "facades.h" // Ui::showPeerHistory
#include "app.h" #include "app.h"
namespace { namespace {
@ -87,10 +88,11 @@ void AddParticipantsBoxController::subscribeToMigration() {
} }
void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) { void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
const auto &serverConfig = _peer->session().serverConfig();
auto count = fullCount(); auto count = fullCount();
auto limit = _peer && (_peer->isChat() || _peer->isMegagroup()) auto limit = _peer && (_peer->isChat() || _peer->isMegagroup())
? Global::MegagroupSizeMax() ? serverConfig.megagroupSizeMax
: Global::ChatSizeMax(); : serverConfig.chatSizeMax;
if (count < limit || row->checked()) { if (count < limit || row->checked()) {
delegate()->peerListSetRowChecked(row, !row->checked()); delegate()->peerListSetRowChecked(row, !row->checked());
updateTitle(); updateTitle();
@ -100,8 +102,8 @@ void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
Box<MaxInviteBox>(_peer->asChannel()), Box<MaxInviteBox>(_peer->asChannel()),
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
} }
} else if (count >= Global::ChatSizeMax() } else if (count >= serverConfig.chatSizeMax
&& count < Global::MegagroupSizeMax()) { && count < serverConfig.megagroupSizeMax) {
Ui::show( Ui::show(
Box<InformBox>(tr::lng_profile_add_more_after_create(tr::now)), Box<InformBox>(tr::lng_profile_add_more_after_create(tr::now)),
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
@ -166,7 +168,9 @@ void AddParticipantsBoxController::updateTitle() {
&& _peer->isChannel() && _peer->isChannel()
&& !_peer->isMegagroup()) && !_peer->isMegagroup())
? QString() ? QString()
: qsl("%1 / %2").arg(fullCount()).arg(Global::MegagroupSizeMax()); : qsl("%1 / %2"
).arg(fullCount()
).arg(session().serverConfig().megagroupSizeMax);
delegate()->peerListSetTitle(tr::lng_profile_add_participant()); delegate()->peerListSetTitle(tr::lng_profile_add_participant());
delegate()->peerListSetAdditionalTitle(rpl::single(additional)); delegate()->peerListSetAdditionalTitle(rpl::single(additional));
} }
@ -276,7 +280,7 @@ AddSpecialBoxController::AddSpecialBoxController(
peer, peer,
&_additional)) &_additional))
, _peer(peer) , _peer(peer)
, _api(_peer->session().mtp()) , _api(&_peer->session().mtp())
, _role(role) , _role(role)
, _additional(peer, Role::Members) , _additional(peer, Role::Members)
, _adminDoneCallback(std::move(adminDoneCallback)) , _adminDoneCallback(std::move(adminDoneCallback))
@ -829,7 +833,7 @@ AddSpecialBoxSearchController::AddSpecialBoxSearchController(
not_null<ParticipantsAdditionalData*> additional) not_null<ParticipantsAdditionalData*> additional)
: _peer(peer) : _peer(peer)
, _additional(additional) , _additional(additional)
, _api(_peer->session().mtp()) , _api(&_peer->session().mtp())
, _timer([=] { searchOnServer(); }) { , _timer([=] { searchOnServer(); }) {
subscribeToMigration(); subscribeToMigration();
} }

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "boxes/add_contact_box.h" #include "boxes/add_contact_box.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
@ -28,7 +29,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "history/history.h" #include "history/history.h"
#include "facades.h"
namespace { namespace {
@ -707,7 +707,8 @@ void ParticipantsOnlineSorter::sort() {
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
if (channel if (channel
&& (!channel->isMegagroup() && (!channel->isMegagroup()
|| channel->membersCount() > Global::ChatSizeMax())) { || (channel->membersCount()
> channel->session().serverConfig().chatSizeMax))) {
_onlineCount = 0; _onlineCount = 0;
return; return;
} }
@ -752,7 +753,7 @@ ParticipantsBoxController::ParticipantsBoxController(
: PeerListController(CreateSearchController(peer, role, &_additional)) : PeerListController(CreateSearchController(peer, role, &_additional))
, _navigation(navigation) , _navigation(navigation)
, _peer(peer) , _peer(peer)
, _api(_peer->session().mtp()) , _api(&_peer->session().mtp())
, _role(role) , _role(role)
, _additional(peer, _role) { , _additional(peer, _role) {
subscribeToMigration(); subscribeToMigration();
@ -844,8 +845,9 @@ void ParticipantsBoxController::Start(
return chat return chat
? chat->canAddMembers() ? chat->canAddMembers()
: (channel->canAddMembers() : (channel->canAddMembers()
&& (channel->membersCount() < Global::ChatSizeMax() && (channel->isMegagroup()
|| channel->isMegagroup())); || (channel->membersCount()
< channel->session().serverConfig().chatSizeMax)));
case Role::Admins: case Role::Admins:
return chat return chat
? chat->canAddAdmins() ? chat->canAddAdmins()
@ -924,7 +926,8 @@ void ParticipantsBoxController::addNewParticipants() {
if (chat) { if (chat) {
AddParticipantsBoxController::Start(_navigation, chat); AddParticipantsBoxController::Start(_navigation, chat);
} else if (channel->isMegagroup() } else if (channel->isMegagroup()
|| channel->membersCount() < Global::ChatSizeMax()) { || (channel->membersCount()
< channel->session().serverConfig().chatSizeMax)) {
const auto count = delegate()->peerListFullRowsCount(); const auto count = delegate()->peerListFullRowsCount();
auto already = std::vector<not_null<UserData*>>(); auto already = std::vector<not_null<UserData*>>();
already.reserve(count); already.reserve(count);
@ -1887,7 +1890,7 @@ void ParticipantsBoxController::subscribeToCreatorChange(
channel->inputChannel, channel->inputChannel,
MTP_channelParticipantsRecent(), MTP_channelParticipantsRecent(),
MTP_int(0), MTP_int(0),
MTP_int(Global::ChatSizeMax()), MTP_int(channel->session().serverConfig().chatSizeMax),
MTP_int(0) MTP_int(0)
)).done([=](const MTPchannels_ChannelParticipants &result) { )).done([=](const MTPchannels_ChannelParticipants &result) {
if (channel->amCreator()) { if (channel->amCreator()) {
@ -1922,7 +1925,7 @@ ParticipantsBoxSearchController::ParticipantsBoxSearchController(
: _channel(channel) : _channel(channel)
, _role(role) , _role(role)
, _additional(additional) , _additional(additional)
, _api(_channel->session().mtp()) { , _api(&_channel->session().mtp()) {
_timer.setCallback([=] { searchOnServer(); }); _timer.setCallback([=] { searchOnServer(); });
} }

View file

@ -355,7 +355,7 @@ Controller::Controller(
: _navigation(navigation) : _navigation(navigation)
, _box(box) , _box(box)
, _peer(peer) , _peer(peer)
, _api(_peer->session().mtp()) , _api(&_peer->session().mtp())
, _isGroup(_peer->isChat() || _peer->isMegagroup()) { , _isGroup(_peer->isChat() || _peer->isMegagroup()) {
_box->setTitle(_isGroup _box->setTitle(_isGroup
? tr::lng_edit_group() ? tr::lng_edit_group()

View file

@ -168,7 +168,7 @@ Controller::Controller(
std::optional<Privacy> privacySavedValue, std::optional<Privacy> privacySavedValue,
std::optional<QString> usernameSavedValue) std::optional<QString> usernameSavedValue)
: _peer(peer) : _peer(peer)
, _api(_peer->session().mtp()) , _api(&_peer->session().mtp())
, _privacySavedValue(privacySavedValue) , _privacySavedValue(privacySavedValue)
, _usernameSavedValue(usernameSavedValue) , _usernameSavedValue(usernameSavedValue)
, _useLocationPhrases(useLocationPhrases) , _useLocationPhrases(useLocationPhrases)
@ -335,7 +335,7 @@ object_ptr<Ui::RpWidget> Controller::createUsernameEdit() {
st::setupChannelLink, st::setupChannelLink,
nullptr, nullptr,
username, username,
true)); _peer->session().createInternalLink(QString())));
_controls.usernameInput->heightValue( _controls.usernameInput->heightValue(
) | rpl::start_with_next([placeholder](int height) { ) | rpl::start_with_next([placeholder](int height) {
placeholder->resize(placeholder->width(), height); placeholder->resize(placeholder->width(), height);

View file

@ -31,7 +31,7 @@ RateCallBox::RateCallBox(
uint64 callId, uint64 callId,
uint64 callAccessHash) uint64 callAccessHash)
: _session(session) : _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _callId(callId) , _callId(callId)
, _callAccessHash(callAccessHash) { , _callAccessHash(callAccessHash) {
} }

View file

@ -28,12 +28,12 @@ constexpr auto kReportReasonLengthMax = 200;
ReportBox::ReportBox(QWidget*, not_null<PeerData*> peer) ReportBox::ReportBox(QWidget*, not_null<PeerData*> peer)
: _peer(peer) : _peer(peer)
, _api(_peer->session().mtp()) { , _api(&_peer->session().mtp()) {
} }
ReportBox::ReportBox(QWidget*, not_null<PeerData*> peer, MessageIdsList ids) ReportBox::ReportBox(QWidget*, not_null<PeerData*> peer, MessageIdsList ids)
: _peer(peer) : _peer(peer)
, _api(_peer->session().mtp()) , _api(&_peer->session().mtp())
, _ids(std::move(ids)) { , _ids(std::move(ids)) {
} }

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "storage/storage_media_prepare.h" #include "storage/storage_media_prepare.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mtproto/mtproto_config.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_suggestions_widget.h"
#include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_panel.h"
@ -36,7 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_common.h" #include "api/api_common.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "layout.h" #include "layout.h"
#include "facades.h" #include "facades.h" // App::LambdaDelayed.
#include "app.h" #include "app.h"
#include "styles/style_history.h" #include "styles/style_history.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -2041,8 +2042,10 @@ void SendFilesBox::applyAlbumOrder() {
} }
void SendFilesBox::setupCaption() { void SendFilesBox::setupCaption() {
_caption->setMaxLength(Global::CaptionLengthMax()); _caption->setMaxLength(
_caption->setSubmitSettings(_controller->session().settings().sendSubmitWay()); _controller->session().serverConfig().captionLengthMax);
_caption->setSubmitSettings(
_controller->session().settings().sendSubmitWay());
connect(_caption, &Ui::InputField::resized, [=] { connect(_caption, &Ui::InputField::resized, [=] {
captionResized(); captionResized();
}); });

View file

@ -77,7 +77,7 @@ private:
SessionsBox::SessionsBox(QWidget*, not_null<Main::Session*> session) SessionsBox::SessionsBox(QWidget*, not_null<Main::Session*> session)
: _session(session) : _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _shortPollTimer([=] { shortPollSessions(); }) { , _shortPollTimer([=] { shortPollSessions(); }) {
} }

View file

@ -159,7 +159,7 @@ ShareBox::ShareBox(
SubmitCallback &&submitCallback, SubmitCallback &&submitCallback,
FilterCallback &&filterCallback) FilterCallback &&filterCallback)
: _navigation(navigation) : _navigation(navigation)
, _api(_navigation->session().mtp()) , _api(&_navigation->session().mtp())
, _copyCallback(std::move(copyCallback)) , _copyCallback(std::move(copyCallback))
, _submitCallback(std::move(submitCallback)) , _submitCallback(std::move(submitCallback))
, _filterCallback(std::move(filterCallback)) , _filterCallback(std::move(filterCallback))

View file

@ -190,7 +190,8 @@ void StickerSetBox::addStickers() {
} }
void StickerSetBox::shareStickers() { void StickerSetBox::shareStickers() {
auto url = Core::App().createInternalLinkFull(qsl("addstickers/") + _inner->shortName()); const auto url = _controller->session().createInternalLinkFull(
qsl("addstickers/") + _inner->shortName());
QGuiApplication::clipboard()->setText(url); QGuiApplication::clipboard()->setText(url);
Ui::show(Box<InformBox>(tr::lng_stickers_copied(tr::now))); Ui::show(Box<InformBox>(tr::lng_stickers_copied(tr::now)));
} }
@ -229,7 +230,7 @@ StickerSetBox::Inner::Inner(
const MTPInputStickerSet &set) const MTPInputStickerSet &set)
: RpWidget(parent) : RpWidget(parent)
, _controller(controller) , _controller(controller)
, _api(_controller->session().mtp()) , _api(&_controller->session().mtp())
, _input(set) , _input(set)
, _previewTimer([=] { showPreview(); }) { , _previewTimer([=] { showPreview(); }) {
set.match([&](const MTPDinputStickerSetID &data) { set.match([&](const MTPDinputStickerSetID &data) {

View file

@ -363,7 +363,7 @@ StickersBox::StickersBox(
not_null<Main::Session*> session, not_null<Main::Session*> session,
Section section) Section section)
: _session(session) : _session(session)
, _api(session->mtp()) , _api(&session->mtp())
, _tabs(this, st::stickersTabs) , _tabs(this, st::stickersTabs)
, _unreadBadge( , _unreadBadge(
this, this,
@ -377,7 +377,7 @@ StickersBox::StickersBox(
StickersBox::StickersBox(QWidget*, not_null<ChannelData*> megagroup) StickersBox::StickersBox(QWidget*, not_null<ChannelData*> megagroup)
: _session(&megagroup->session()) : _session(&megagroup->session())
, _api(_session->mtp()) , _api(&_session->mtp())
, _section(Section::Installed) , _section(Section::Installed)
, _installed(0, this, megagroup) , _installed(0, this, megagroup)
, _megagroupSet(megagroup) { , _megagroupSet(megagroup) {
@ -391,7 +391,7 @@ StickersBox::StickersBox(
not_null<Main::Session*> session, not_null<Main::Session*> session,
const MTPVector<MTPStickerSetCovered> &attachedSets) const MTPVector<MTPStickerSetCovered> &attachedSets)
: _session(session) : _session(session)
, _api(session->mtp()) , _api(&session->mtp())
, _section(Section::Attached) , _section(Section::Attached)
, _attached(0, this, session, Section::Attached) , _attached(0, this, session, Section::Attached)
, _attachedSets(attachedSets) { , _attachedSets(attachedSets) {
@ -928,7 +928,7 @@ StickersBox::Inner::Inner(
StickersBox::Section section) StickersBox::Section section)
: RpWidget(parent) : RpWidget(parent)
, _session(session) , _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _section(section) , _section(section)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _shiftingAnimation([=](crl::time now) { , _shiftingAnimation([=](crl::time now) {
@ -945,7 +945,7 @@ StickersBox::Inner::Inner(
StickersBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> megagroup) StickersBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> megagroup)
: RpWidget(parent) : RpWidget(parent)
, _session(&megagroup->session()) , _session(&megagroup->session())
, _api(_session->mtp()) , _api(&_session->mtp())
, _section(StickersBox::Section::Installed) , _section(StickersBox::Section::Installed)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _shiftingAnimation([=](crl::time now) { , _shiftingAnimation([=](crl::time now) {
@ -954,10 +954,16 @@ StickersBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> megagroup)
, _itemsTop(st::membersMarginTop) , _itemsTop(st::membersMarginTop)
, _megagroupSet(megagroup) , _megagroupSet(megagroup)
, _megagroupSetInput(_megagroupSet->mgInfo->stickerSet) , _megagroupSetInput(_megagroupSet->mgInfo->stickerSet)
, _megagroupSetField(this, st::groupStickersField, rpl::single(qsl("stickerset")), QString(), true) , _megagroupSetField(
this,
st::groupStickersField,
rpl::single(qsl("stickerset")),
QString(),
_session->createInternalLink(QString()))
, _megagroupDivider(this) , _megagroupDivider(this)
, _megagroupSubTitle(this, tr::lng_stickers_group_from_your(tr::now), st::boxTitle) { , _megagroupSubTitle(this, tr::lng_stickers_group_from_your(tr::now), st::boxTitle) {
_megagroupSetField->setLinkPlaceholder(Core::App().createInternalLink(qsl("addstickers/"))); _megagroupSetField->setLinkPlaceholder(
_session->createInternalLink(qsl("addstickers/")));
_megagroupSetField->setPlaceholderHidden(false); _megagroupSetField->setPlaceholderHidden(false);
_megagroupSetAddressChangedTimer.setCallback([this] { handleMegagroupSetAddressChange(); }); _megagroupSetAddressChangedTimer.setCallback([this] { handleMegagroupSetAddressChange(); });
connect( connect(

View file

@ -31,13 +31,13 @@ constexpr auto kMinUsernameLength = 5;
UsernameBox::UsernameBox(QWidget*, not_null<Main::Session*> session) UsernameBox::UsernameBox(QWidget*, not_null<Main::Session*> session)
: _session(session) : _session(session)
, _api(_session->mtp()) , _api(&_session->mtp())
, _username( , _username(
this, this,
st::defaultInputField, st::defaultInputField,
rpl::single(qsl("@username")), rpl::single(qsl("@username")),
session->user()->username, session->user()->username,
false) QString())
, _link(this, QString(), st::boxLinkButton) , _link(this, QString(), st::boxLinkButton)
, _about(st::boxWidth - st::usernamePadding.left()) , _about(st::boxWidth - st::usernamePadding.left())
, _checkTimer(this) { , _checkTimer(this) {
@ -94,7 +94,8 @@ void UsernameBox::paintEvent(QPaintEvent *e) {
if (_link->isHidden()) { if (_link->isHidden()) {
p.drawTextLeft(st::usernamePadding.left(), linky, width(), tr::lng_username_link_willbe(tr::now)); p.drawTextLeft(st::usernamePadding.left(), linky, width(), tr::lng_username_link_willbe(tr::now));
p.setPen(st::usernameDefaultFg); p.setPen(st::usernameDefaultFg);
p.drawTextLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2), width(), Core::App().createInternalLinkFull(qsl("username"))); const auto link = _session->createInternalLinkFull(qsl("username"));
p.drawTextLeft(st::usernamePadding.left(), linky + st::usernameTextStyle.lineHeight + ((st::usernameTextStyle.lineHeight - st::boxTextFont->height) / 2), width(), link);
} else { } else {
p.drawTextLeft(st::usernamePadding.left(), linky, width(), tr::lng_username_link(tr::now)); p.drawTextLeft(st::usernamePadding.left(), linky, width(), tr::lng_username_link(tr::now));
} }
@ -179,7 +180,8 @@ void UsernameBox::changed() {
} }
void UsernameBox::linkClick() { void UsernameBox::linkClick() {
QGuiApplication::clipboard()->setText(Core::App().createInternalLinkFull(getName())); QGuiApplication::clipboard()->setText(
_session->createInternalLinkFull(getName()));
Ui::Toast::Show(tr::lng_username_copied(tr::now)); Ui::Toast::Show(tr::lng_username_copied(tr::now));
} }
@ -251,7 +253,7 @@ QString UsernameBox::getName() const {
void UsernameBox::updateLinkText() { void UsernameBox::updateLinkText() {
QString uname = getName(); QString uname = getName();
_link->setText(st::boxTextFont->elided(Core::App().createInternalLinkFull(uname), st::boxWidth - st::usernamePadding.left() - st::usernamePadding.right())); _link->setText(st::boxTextFont->elided(_session->createInternalLinkFull(uname), st::boxWidth - st::usernamePadding.left() - st::usernamePadding.right()));
if (uname.isEmpty()) { if (uname.isEmpty()) {
if (!_link->isHidden()) { if (!_link->isHidden()) {
_link->hide(); _link->hide();

View file

@ -216,7 +216,7 @@ void BoxController::Row::stopLastActionRipple() {
BoxController::BoxController(not_null<Window::SessionController*> window) BoxController::BoxController(not_null<Window::SessionController*> window)
: _window(window) : _window(window)
, _api(_window->session().mtp()) { , _api(&_window->session().mtp()) {
} }
Main::Session &BoxController::session() const { Main::Session &BoxController::session() const {

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/calls_instance.h" #include "calls/calls_instance.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"
#include "mtproto/mtproto_dh_utils.h" #include "mtproto/mtproto_dh_utils.h"
#include "mtproto/mtproto_config.h"
#include "media/audio/media_audio_track.h" #include "media/audio/media_audio_track.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "calls/calls_panel.h" #include "calls/calls_panel.h"
@ -96,7 +97,7 @@ Call::Call(
Type type) Type type)
: _delegate(delegate) : _delegate(delegate)
, _user(user) , _user(user)
, _api(_user->session().mtp()) , _api(&_user->session().mtp())
, _type(type) { , _type(type) {
_discardByTimeoutTimer.setCallback([this] { hangup(); }); _discardByTimeoutTimer.setCallback([this] { hangup(); });
@ -193,7 +194,8 @@ void Call::startOutgoing() {
return; return;
} }
_discardByTimeoutTimer.callOnce(Global::CallReceiveTimeoutMs()); const auto &config = _user->session().serverConfig();
_discardByTimeoutTimer.callOnce(config.callReceiveTimeoutMs);
handleUpdate(phoneCall); handleUpdate(phoneCall);
}).fail([this](const RPCError &error) { }).fail([this](const RPCError &error) {
handleRequestError(error); handleRequestError(error);
@ -382,7 +384,8 @@ bool Call::handleUpdate(const MTPPhoneCall &call) {
if (_type == Type::Outgoing if (_type == Type::Outgoing
&& _state == State::Waiting && _state == State::Waiting
&& data.vreceive_date().value_or_empty() != 0) { && data.vreceive_date().value_or_empty() != 0) {
_discardByTimeoutTimer.callOnce(Global::CallRingTimeoutMs()); const auto &config = _user->session().serverConfig();
_discardByTimeoutTimer.callOnce(config.callRingTimeoutMs);
setState(State::Ringing); setState(State::Ringing);
startWaitingTrack(); startWaitingTrack();
} }
@ -534,6 +537,7 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
} }
const auto &protocol = call.vprotocol().c_phoneCallProtocol(); const auto &protocol = call.vprotocol().c_phoneCallProtocol();
const auto &serverConfig = _user->session().serverConfig();
TgVoipConfig config; TgVoipConfig config;
config.dataSaving = TgVoipDataSaving::Never; config.dataSaving = TgVoipDataSaving::Never;
@ -541,8 +545,8 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
config.enableNS = true; config.enableNS = true;
config.enableAGC = true; config.enableAGC = true;
config.enableVolumeControl = true; config.enableVolumeControl = true;
config.initializationTimeout = Global::CallConnectTimeoutMs() / 1000.; config.initializationTimeout = serverConfig.callConnectTimeoutMs / 1000.;
config.receiveTimeout = Global::CallPacketTimeoutMs() / 1000.; config.receiveTimeout = serverConfig.callPacketTimeoutMs / 1000.;
config.enableP2P = call.is_p2p_allowed(); config.enableP2P = call.is_p2p_allowed();
config.maxApiLayer = protocol.vmax_layer().v; config.maxApiLayer = protocol.vmax_layer().v;
if (Logs::DebugEnabled()) { if (Logs::DebugEnabled()) {

View file

@ -21,8 +21,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mtproto/mtproto_config.h"
#include "boxes/rate_call_box.h" #include "boxes/rate_call_box.h"
#include "facades.h"
#include "app.h" #include "app.h"
namespace Calls { namespace Calls {
@ -34,7 +34,7 @@ constexpr auto kServerConfigUpdateTimeoutMs = 24 * 3600 * crl::time(1000);
Instance::Instance(not_null<Main::Session*> session) Instance::Instance(not_null<Main::Session*> session)
: _session(session) : _session(session)
, _api(_session->mtp()) { , _api(&_session->mtp()) {
} }
void Instance::startOutgoingCall(not_null<UserData*> user) { void Instance::startOutgoingCall(not_null<UserData*> user) {
@ -248,6 +248,7 @@ void Instance::handleCallUpdate(const MTPPhoneCall &call) {
} else if (user->isSelf()) { } else if (user->isSelf()) {
LOG(("API Error: Self found in phoneCallRequested.")); LOG(("API Error: Self found in phoneCallRequested."));
} }
const auto &config = _session->serverConfig();
if (alreadyInCall() || !user || user->isSelf()) { if (alreadyInCall() || !user || user->isSelf()) {
_api.request(MTPphone_DiscardCall( _api.request(MTPphone_DiscardCall(
MTP_flags(0), MTP_flags(0),
@ -256,7 +257,7 @@ void Instance::handleCallUpdate(const MTPPhoneCall &call) {
MTP_phoneCallDiscardReasonBusy(), MTP_phoneCallDiscardReasonBusy(),
MTP_long(0) MTP_long(0)
)).send(); )).send();
} else if (phoneCall.vdate().v + (Global::CallRingTimeoutMs() / 1000) } else if (phoneCall.vdate().v + (config.callRingTimeoutMs / 1000)
< base::unixtime::now()) { < base::unixtime::now()) {
LOG(("Ignoring too old call.")); LOG(("Ignoring too old call."));
} else { } else {

View file

@ -134,7 +134,7 @@ GifsListWidget::GifsListWidget(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Inner(parent, controller) : Inner(parent, controller)
, _api(controller->session().mtp()) , _api(&controller->session().mtp())
, _section(Section::Gifs) , _section(Section::Gifs)
, _updateInlineItems([=] { updateInlineItems(); }) , _updateInlineItems([=] { updateInlineItems(); })
, _previewTimer([=] { showPreview(); }) { , _previewTimer([=] { showPreview(); }) {

View file

@ -873,7 +873,7 @@ StickersListWidget::StickersListWidget(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Inner(parent, controller) : Inner(parent, controller)
, _api(controller->session().mtp()) , _api(&controller->session().mtp())
, _section(Section::Stickers) , _section(Section::Stickers)
, _megagroupSetAbout(st::columnMinimalWidthThird - st::emojiScroll.width - st::emojiPanHeaderLeft) , _megagroupSetAbout(st::columnMinimalWidthThird - st::emojiScroll.width - st::emojiPanHeaderLeft)
, _addText(tr::lng_stickers_featured_add(tr::now).toUpper()) , _addText(tr::lng_stickers_featured_add(tr::now).toUpper())

View file

@ -39,7 +39,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_accounts.h" #include "main/main_accounts.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "media/view/media_view_overlay_widget.h" #include "media/view/media_view_overlay_widget.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/mtproto_config.h"
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
#include "media/audio/media_audio_track.h" #include "media/audio/media_audio_track.h"
@ -95,7 +96,8 @@ Application::Application(not_null<Launcher*> launcher)
, _private(std::make_unique<Private>()) , _private(std::make_unique<Private>())
, _databases(std::make_unique<Storage::Databases>()) , _databases(std::make_unique<Storage::Databases>())
, _animationsManager(std::make_unique<Ui::Animations::Manager>()) , _animationsManager(std::make_unique<Ui::Animations::Manager>())
, _dcOptions(std::make_unique<MTP::DcOptions>()) , _fallbackProductionConfig(
std::make_unique<MTP::Config>(MTP::Environment::Production))
, _accounts(std::make_unique<Main::Accounts>(cDataFile())) , _accounts(std::make_unique<Main::Accounts>(cDataFile()))
, _langpack(std::make_unique<Lang::Instance>()) , _langpack(std::make_unique<Lang::Instance>())
, _langCloudManager(std::make_unique<Lang::CloudManager>(langpack())) , _langCloudManager(std::make_unique<Lang::CloudManager>(langpack()))
@ -122,12 +124,8 @@ Application::Application(not_null<Launcher*> launcher)
}, _lifetime); }, _lifetime);
accounts().activeValue( accounts().activeValue(
) | rpl::map([=](Main::Account *account) { ) | rpl::filter(rpl::mappers::_1 != nullptr
return account ? account->mtpValue() : rpl::never<MTP::Instance*>(); ) | rpl::take(1) | rpl::start_with_next([=] {
}) | rpl::flatten_latest(
) | rpl::filter([=](MTP::Instance *instance) {
return instance != nullptr;
}) | rpl::start_with_next([=] {
if (_window) { if (_window) {
// Global::DesktopNotify is used in updateTrayMenu. // Global::DesktopNotify is used in updateTrayMenu.
// This should be called when user settings are read. // This should be called when user settings are read.
@ -149,14 +147,7 @@ Application::~Application() {
} }
unlockTerms(); unlockTerms();
for (const auto &[index, account] : accounts().list()) { accounts().finish();
if (account->sessionExists()) {
account->session().saveSettingsNowIfNeeded();
}
// Some MTP requests can be cancelled from data clearing.
account->destroySession();
account->clearMtp();
}
Local::finish(); Local::finish();
@ -269,7 +260,7 @@ void Application::run() {
_window->showSettings(); _window->showSettings();
} }
_window->updateIsActive(Global::OnlineFocusTimeout()); _window->updateIsActiveFocus();
for (const auto &error : Shortcuts::Errors()) { for (const auto &error : Shortcuts::Errors()) {
LOG(("Shortcuts Error: %1").arg(error)); LOG(("Shortcuts Error: %1").arg(error));
@ -399,6 +390,30 @@ void Application::saveSettingsDelayed(crl::time delay) {
_saveSettingsTimer.callOnce(delay); _saveSettingsTimer.callOnce(delay);
} }
MTP::Config &Application::fallbackProductionConfig() const {
if (!_fallbackProductionConfig) {
_fallbackProductionConfig = std::make_unique<MTP::Config>(
MTP::Environment::Production);
}
return *_fallbackProductionConfig;
}
void Application::refreshFallbackProductionConfig(
const MTP::Config &config) {
if (config.environment() == MTP::Environment::Production) {
_fallbackProductionConfig = std::make_unique<MTP::Config>(config);
}
}
void Application::constructFallbackProductionConfig(
const QByteArray &serialized) {
if (auto config = MTP::Config::FromSerialized(serialized)) {
if (config->environment() == MTP::Environment::Production) {
_fallbackProductionConfig = std::move(config);
}
}
}
void Application::setCurrentProxy( void Application::setCurrentProxy(
const MTP::ProxyData &proxy, const MTP::ProxyData &proxy,
MTP::ProxyData::Settings settings) { MTP::ProxyData::Settings settings) {
@ -436,18 +451,6 @@ void Application::badMtprotoConfigurationError() {
void Application::startLocalStorage() { void Application::startLocalStorage() {
Local::start(); Local::start();
const auto writing = _lifetime.make_state<bool>(false);
_dcOptions->changed(
) | rpl::filter([=] {
return !*writing;
}) | rpl::start_with_next([=] {
*writing = true;
Ui::PostponeCall(this, [=] {
Local::writeSettings();
});
}, _lifetime);
_saveSettingsTimer.setCallback([=] { Local::writeSettings(); }); _saveSettingsTimer.setCallback([=] { Local::writeSettings(); });
} }
@ -498,13 +501,13 @@ void Application::stateChanged(Qt::ApplicationState state) {
void Application::handleAppActivated() { void Application::handleAppActivated() {
checkLocalTime(); checkLocalTime();
if (_window) { if (_window) {
_window->updateIsActive(Global::OnlineFocusTimeout()); _window->updateIsActiveFocus();
} }
} }
void Application::handleAppDeactivated() { void Application::handleAppDeactivated() {
if (_window) { if (_window) {
_window->updateIsActive(Global::OfflineBlurTimeout()); _window->updateIsActiveBlur();
} }
Ui::Tooltip::Hide(); Ui::Tooltip::Hide();
} }
@ -530,21 +533,6 @@ void Application::switchDebugMode() {
} }
} }
void Application::switchTestMode() {
if (cTestMode()) {
QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove();
cSetTestMode(false);
} else {
QFile f(cWorkingDir() + qsl("tdata/withtestmode"));
if (f.open(QIODevice::WriteOnly)) {
f.write("1");
f.close();
}
cSetTestMode(true);
}
App::restart();
}
void Application::switchFreeType() { void Application::switchFreeType() {
if (cUseFreeType()) { if (cUseFreeType()) {
QFile(cWorkingDir() + qsl("tdata/withfreetype")).remove(); QFile(cWorkingDir() + qsl("tdata/withfreetype")).remove();
@ -613,45 +601,6 @@ bool Application::canApplyLangPackWithoutRestart() const {
return true; return true;
} }
void Application::setInternalLinkDomain(const QString &domain) const {
// This domain should start with 'http[s]://' and end with '/'.
// Like 'https://telegram.me/' or 'https://t.me/'.
auto validate = [](const auto &domain) {
const auto prefixes = {
qstr("https://"),
qstr("http://"),
};
for (const auto &prefix : prefixes) {
if (domain.startsWith(prefix, Qt::CaseInsensitive)) {
return domain.endsWith('/');
}
}
return false;
};
if (validate(domain) && domain != Global::InternalLinksDomain()) {
Global::SetInternalLinksDomain(domain);
}
}
QString Application::createInternalLink(const QString &query) const {
auto result = createInternalLinkFull(query);
auto prefixes = {
qstr("https://"),
qstr("http://"),
};
for (auto &prefix : prefixes) {
if (result.startsWith(prefix, Qt::CaseInsensitive)) {
return result.mid(prefix.size());
}
}
LOG(("Warning: bad internal url '%1'").arg(result));
return result;
}
QString Application::createInternalLinkFull(const QString &query) const {
return Global::InternalLinksDomain() + query;
}
void Application::checkStartUrl() { void Application::checkStartUrl() {
if (!cStartUrl().isEmpty() && !locked()) { if (!cStartUrl().isEmpty() && !locked()) {
const auto url = cStartUrl(); const auto url = cStartUrl();

View file

@ -49,7 +49,7 @@ class BoxContent;
} // namespace Ui } // namespace Ui
namespace MTP { namespace MTP {
class DcOptions; class Config;
class Instance; class Instance;
class AuthKey; class AuthKey;
using AuthKeyPtr = std::shared_ptr<AuthKey>; using AuthKeyPtr = std::shared_ptr<AuthKey>;
@ -82,6 +82,11 @@ struct LocalUrlHandler;
class Application final : public QObject, private base::Subscriber { class Application final : public QObject, private base::Subscriber {
public: public:
struct ProxyChange {
MTP::ProxyData was;
MTP::ProxyData now;
};
Application(not_null<Launcher*> launcher); Application(not_null<Launcher*> launcher);
Application(const Application &other) = delete; Application(const Application &other) = delete;
Application &operator=(const Application &other) = delete; Application &operator=(const Application &other) = delete;
@ -132,14 +137,10 @@ public:
} }
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay); void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
// Dc options and proxy. // Fallback config and proxy.
[[nodiscard]] not_null<MTP::DcOptions*> dcOptions() { [[nodiscard]] MTP::Config &fallbackProductionConfig() const;
return _dcOptions.get(); void refreshFallbackProductionConfig(const MTP::Config &config);
} void constructFallbackProductionConfig(const QByteArray &serialized);
struct ProxyChange {
MTP::ProxyData was;
MTP::ProxyData now;
};
void setCurrentProxy( void setCurrentProxy(
const MTP::ProxyData &proxy, const MTP::ProxyData &proxy,
MTP::ProxyData::Settings settings); MTP::ProxyData::Settings settings);
@ -183,9 +184,6 @@ public:
} }
// Internal links. // Internal links.
void setInternalLinkDomain(const QString &domain) const;
[[nodiscard]] QString createInternalLink(const QString &query) const;
[[nodiscard]] QString createInternalLinkFull(const QString &query) const;
void checkStartUrl(); void checkStartUrl();
bool openLocalUrl(const QString &url, QVariant context); bool openLocalUrl(const QString &url, QVariant context);
bool openInternalUrl(const QString &url, QVariant context); bool openInternalUrl(const QString &url, QVariant context);
@ -231,7 +229,6 @@ public:
void handleAppDeactivated(); void handleAppDeactivated();
void switchDebugMode(); void switchDebugMode();
void switchTestMode();
void switchFreeType(); void switchFreeType();
void writeInstallBetaVersionsSetting(); void writeInstallBetaVersionsSetting();
@ -284,7 +281,7 @@ private:
const std::unique_ptr<Storage::Databases> _databases; const std::unique_ptr<Storage::Databases> _databases;
const std::unique_ptr<Ui::Animations::Manager> _animationsManager; const std::unique_ptr<Ui::Animations::Manager> _animationsManager;
const std::unique_ptr<MTP::DcOptions> _dcOptions; mutable std::unique_ptr<MTP::Config> _fallbackProductionConfig;
const std::unique_ptr<Main::Accounts> _accounts; const std::unique_ptr<Main::Accounts> _accounts;
std::unique_ptr<Window::Controller> _window; std::unique_ptr<Window::Controller> _window;
std::unique_ptr<Media::View::OverlayWidget> _mediaView; std::unique_ptr<Media::View::OverlayWidget> _mediaView;

View file

@ -97,12 +97,6 @@ void ComputeDebugMode() {
} }
} }
void ComputeTestMode() {
if (QFile::exists(cWorkingDir() + qsl("tdata/withtestmode"))) {
cSetTestMode(true);
}
}
void ComputeExternalUpdater() { void ComputeExternalUpdater() {
QFile file(qsl("/etc/tdesktop/externalupdater")); QFile file(qsl("/etc/tdesktop/externalupdater"));
@ -350,7 +344,6 @@ int Launcher::exec() {
void Launcher::workingFolderReady() { void Launcher::workingFolderReady() {
srand((unsigned int)time(nullptr)); srand((unsigned int)time(nullptr));
ComputeTestMode();
ComputeDebugMode(); ComputeDebugMode();
ComputeExternalUpdater(); ComputeExternalUpdater();
ComputeFreeType(); ComputeFreeType();
@ -476,7 +469,6 @@ void Launcher::processArguments() {
if (parseResult.contains("-externalupdater")) { if (parseResult.contains("-externalupdater")) {
SetUpdaterDisabledAtStartup(); SetUpdaterDisabledAtStartup();
} }
gTestMode = parseResult.contains("-testmode");
gUseFreeType = parseResult.contains("-freetype"); gUseFreeType = parseResult.contains("-freetype");
Logs::SetDebugEnabled(parseResult.contains("-debug")); Logs::SetDebugEnabled(parseResult.contains("-debug"));
gManyInstance = parseResult.contains("-many"); gManyInstance = parseResult.contains("-many");

View file

@ -20,9 +20,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_account.h" #include "main/main_account.h"
//#include "storage/storage_feed_messages.h" // #feed //#include "storage/storage_feed_messages.h" // #feed
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "facades.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
namespace Data { namespace Data {
@ -31,17 +31,6 @@ namespace {
constexpr auto kLoadedChatsMinCount = 20; constexpr auto kLoadedChatsMinCount = 20;
constexpr auto kShowChatNamesCount = 8; constexpr auto kShowChatNamesCount = 8;
rpl::producer<int> PinnedDialogsInFolderMaxValue(
not_null<Main::Session*> session) {
return rpl::single(
rpl::empty_value()
) | rpl::then(
session->account().configUpdates()
) | rpl::map([=] {
return Global::PinnedDialogsInFolderMax();
});
}
} // namespace } // namespace
// #feed // #feed
@ -60,7 +49,7 @@ Folder::Folder(not_null<Data::Session*> owner, FolderId id)
, _chatsList( , _chatsList(
&owner->session(), &owner->session(),
FilterId(), FilterId(),
PinnedDialogsInFolderMaxValue(&owner->session())) owner->session().serverConfig().pinnedDialogsInFolderMax.value())
, _name(tr::lng_archived_name(tr::now)) { , _name(tr::lng_archived_name(tr::now)) {
indexNameParts(); indexNameParts();

View file

@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_app_config.h" #include "main/main_app_config.h"
#include "mtproto/mtproto_config.h"
#include "core/application.h" #include "core/application.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -34,7 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/history_view_element.h" #include "history/view/history_view_element.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "storage/file_download.h" #include "storage/file_download.h"
#include "facades.h" #include "facades.h" // Ui::showPeerProfile
#include "app.h" #include "app.h"
namespace { namespace {
@ -763,8 +764,8 @@ Data::RestrictionCheckResult PeerData::amRestricted(
bool PeerData::canRevokeFullHistory() const { bool PeerData::canRevokeFullHistory() const {
return isUser() return isUser()
&& !isSelf() && !isSelf()
&& Global::RevokePrivateInbox() && session().serverConfig().revokePrivateInbox
&& (Global::RevokePrivateTimeLimit() == 0x7FFFFFFF); && (session().serverConfig().revokePrivateTimeLimit == 0x7FFFFFFF);
} }
bool PeerData::slowmodeApplied() const { bool PeerData::slowmodeApplied() const {

View file

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image_location_factory.h" // Images::FromPhotoSize #include "ui/image/image_location_factory.h" // Images::FromPhotoSize
#include "export/export_controller.h" #include "export/export_controller.h"
#include "export/view/export_view_panel_controller.h" #include "export/view/export_view_panel_controller.h"
#include "mtproto/mtproto_config.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
@ -54,7 +55,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "facades.h" #include "facades.h" // Notify::switchInlineBotButtonReceived
#include "app.h" #include "app.h"
#include "styles/style_boxes.h" // st::backgroundSize #include "styles/style_boxes.h" // st::backgroundSize
@ -188,17 +189,6 @@ std::vector<UnavailableReason> ExtractUnavailableReasons(
return FindInlineThumbnail(data.vsizes().v); return FindInlineThumbnail(data.vsizes().v);
} }
[[nodiscard]] rpl::producer<int> PinnedDialogsCountMaxValue(
not_null<Main::Session*> session) {
return rpl::single(
rpl::empty_value()
) | rpl::then(
session->account().configUpdates()
) | rpl::map([=] {
return Global::PinnedDialogsCountMax();
});
}
} // namespace } // namespace
Session::Session(not_null<Main::Session*> session) Session::Session(not_null<Main::Session*> session)
@ -209,7 +199,10 @@ Session::Session(not_null<Main::Session*> session)
, _bigFileCache(Core::App().databases().get( , _bigFileCache(Core::App().databases().get(
_session->local().cacheBigFilePath(), _session->local().cacheBigFilePath(),
_session->local().cacheBigFileSettings())) _session->local().cacheBigFileSettings()))
, _chatsList(session, FilterId(), PinnedDialogsCountMaxValue(session)) , _chatsList(
session,
FilterId(),
session->serverConfig().pinnedDialogsCountMax.value())
, _contactsList(Dialogs::SortMode::Name) , _contactsList(Dialogs::SortMode::Name)
, _contactsNoChatsList(Dialogs::SortMode::Name) , _contactsNoChatsList(Dialogs::SortMode::Name)
, _selfDestructTimer([=] { checkSelfDestructItems(); }) , _selfDestructTimer([=] { checkSelfDestructItems(); })
@ -929,7 +922,7 @@ void Session::startExport(const MTPInputPeer &singlePeer) {
return; return;
} }
_export = std::make_unique<Export::Controller>( _export = std::make_unique<Export::Controller>(
session().mtp().get(), &session().mtp(),
singlePeer); singlePeer);
_exportPanel = std::make_unique<Export::View::PanelController>( _exportPanel = std::make_unique<Export::View::PanelController>(
&session(), &session(),
@ -1660,8 +1653,8 @@ int Session::pinnedChatsLimit(
FilterId filterId) const { FilterId filterId) const {
if (!filterId) { if (!filterId) {
return folder return folder
? Global::PinnedDialogsInFolderMax() ? session().serverConfig().pinnedDialogsInFolderMax.current()
: Global::PinnedDialogsCountMax(); : session().serverConfig().pinnedDialogsCountMax.current();
} }
const auto &list = chatsFilters().list(); const auto &list = chatsFilters().list();
const auto i = ranges::find(list, filterId, &Data::ChatFilter::id); const auto i = ranges::find(list, filterId, &Data::ChatFilter::id);

View file

@ -48,7 +48,7 @@ Storage::Cache::Key DocumentThumbCacheKey(int32 dcId, uint64 id) {
} }
Storage::Cache::Key WebDocumentCacheKey(const WebFileLocation &location) { Storage::Cache::Key WebDocumentCacheKey(const WebFileLocation &location) {
const auto CacheDcId = cTestMode() ? 2 : 4; const auto CacheDcId = 4; // The default production value. Doesn't matter.
const auto dcId = uint64(CacheDcId) & 0xFFULL; const auto dcId = uint64(CacheDcId) & 0xFFULL;
const auto &url = location.url(); const auto &url = location.url();
const auto hash = openssl::Sha256(bytes::make_span(url)); const auto hash = openssl::Sha256(bytes::make_span(url));

View file

@ -154,11 +154,11 @@ bool WallPaper::hasShareUrl() const {
return !_slug.isEmpty(); return !_slug.isEmpty();
} }
QString WallPaper::shareUrl() const { QString WallPaper::shareUrl(not_null<Main::Session*> session) const {
if (!hasShareUrl()) { if (!hasShareUrl()) {
return QString(); return QString();
} }
const auto base = Core::App().createInternalLinkFull("bg/" + _slug); const auto base = session->createInternalLinkFull("bg/" + _slug);
auto params = QStringList(); auto params = QStringList();
if (isPattern()) { if (isPattern()) {
if (_backgroundColor) { if (_backgroundColor) {

View file

@ -35,7 +35,7 @@ public:
[[nodiscard]] bool isBlurred() const; [[nodiscard]] bool isBlurred() const;
[[nodiscard]] int patternIntensity() const; [[nodiscard]] int patternIntensity() const;
[[nodiscard]] bool hasShareUrl() const; [[nodiscard]] bool hasShareUrl() const;
[[nodiscard]] QString shareUrl() const; [[nodiscard]] QString shareUrl(not_null<Main::Session*> session) const;
void loadDocument() const; void loadDocument() const;
void loadDocumentThumbnail() const; void loadDocumentThumbnail() const;

View file

@ -19,10 +19,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "storage/storage_account.h" #include "storage/storage_account.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/image/image_location_factory.h" #include "ui/image/image_location_factory.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "facades.h"
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
namespace Data { namespace Data {
@ -142,7 +142,9 @@ void Stickers::incrementSticker(not_null<DocumentData*> document) {
break; break;
} }
} }
while (!recent.isEmpty() && set->stickers.size() + recent.size() > Global::StickersRecentLimit()) { while (!recent.isEmpty()
&& (set->stickers.size() + recent.size()
> session().serverConfig().stickersRecentLimit)) {
writeOldRecent = true; writeOldRecent = true;
recent.pop_back(); recent.pop_back();
} }
@ -184,7 +186,7 @@ void Stickers::addSavedGif(not_null<DocumentData*> document) {
_savedGifs.remove(index); _savedGifs.remove(index);
} }
_savedGifs.push_front(document); _savedGifs.push_front(document);
if (_savedGifs.size() > Global::SavedGifsLimit()) { if (_savedGifs.size() > session().serverConfig().savedGifsLimit) {
_savedGifs.pop_back(); _savedGifs.pop_back();
} }
session().local().writeSavedGifs(); session().local().writeSavedGifs();
@ -387,7 +389,7 @@ bool Stickers::isFaved(not_null<const DocumentData*> document) {
} }
void Stickers::checkFavedLimit(StickersSet &set) { void Stickers::checkFavedLimit(StickersSet &set) {
if (set.stickers.size() <= Global::StickersFavedLimit()) { if (set.stickers.size() <= session().serverConfig().stickersFavedLimit) {
return; return;
} }
auto removing = set.stickers.back(); auto removing = set.stickers.back();

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/widgets/separate_panel.h" #include "ui/widgets/separate_panel.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "mtproto/mtproto_config.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "storage/storage_account.h" #include "storage/storage_account.h"
@ -20,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "facades.h"
#include "styles/style_export.h" #include "styles/style_export.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@ -77,9 +77,9 @@ void SuggestBox::prepare() {
} // namespace } // namespace
Environment PrepareEnvironment() { Environment PrepareEnvironment(not_null<Main::Session*> session) {
auto result = Environment(); auto result = Environment();
result.internalLinksDomain = Global::InternalLinksDomain(); result.internalLinksDomain = session->serverConfig().internalLinksDomain;
result.aboutTelegram = tr::lng_export_about_telegram(tr::now).toUtf8(); result.aboutTelegram = tr::lng_export_about_telegram(tr::now).toUtf8();
result.aboutContacts = tr::lng_export_about_contacts(tr::now).toUtf8(); result.aboutContacts = tr::lng_export_about_contacts(tr::now).toUtf8();
result.aboutFrequent = tr::lng_export_about_frequent(tr::now).toUtf8(); result.aboutFrequent = tr::lng_export_about_frequent(tr::now).toUtf8();
@ -188,7 +188,7 @@ void PanelController::showSettings() {
settings->startClicks( settings->startClicks(
) | rpl::start_with_next([=]() { ) | rpl::start_with_next([=]() {
showProgress(); showProgress();
_process->startExport(*_settings, PrepareEnvironment()); _process->startExport(*_settings, PrepareEnvironment(_session));
}, settings->lifetime()); }, settings->lifetime());
settings->cancelClicks( settings->cancelClicks(

View file

@ -22,12 +22,8 @@ class Session;
} // namespace Main } // namespace Main
namespace Export { namespace Export {
struct Environment;
namespace View { namespace View {
Environment PrepareEnvironment();
QPointer<Ui::BoxContent> SuggestStart(not_null<Main::Session*> session); QPointer<Ui::BoxContent> SuggestStart(not_null<Main::Session*> session);
void ClearSuggestStart(not_null<Main::Session*> session); void ClearSuggestStart(not_null<Main::Session*> session);
bool IsDefaultPath(not_null<Main::Session*> session, const QString &path); bool IsDefaultPath(not_null<Main::Session*> session, const QString &path);

View file

@ -356,43 +356,6 @@ struct Data {
float64 VideoVolume = kDefaultVolume; float64 VideoVolume = kDefaultVolume;
base::Observable<void> VideoVolumeChanged; base::Observable<void> VideoVolumeChanged;
// config
int32 ChatSizeMax = 200;
int32 MegagroupSizeMax = 10000;
int32 ForwardedCountMax = 100;
int32 OnlineUpdatePeriod = 120000;
int32 OfflineBlurTimeout = 5000;
int32 OfflineIdleTimeout = 30000;
int32 OnlineFocusTimeout = 1000;
int32 OnlineCloudTimeout = 300000;
int32 NotifyCloudDelay = 30000;
int32 NotifyDefaultDelay = 1500;
int32 PushChatPeriod = 60000;
int32 PushChatLimit = 2;
int32 SavedGifsLimit = 200;
int32 EditTimeLimit = 172800;
int32 RevokeTimeLimit = 172800;
int32 RevokePrivateTimeLimit = 172800;
bool RevokePrivateInbox = false;
int32 StickersRecentLimit = 30;
int32 StickersFavedLimit = 5;
int32 PinnedDialogsCountMax = 5;
int32 PinnedDialogsInFolderMax = 100;
QString InternalLinksDomain = qsl("https://t.me/");
int32 ChannelsReadMediaPeriod = 86400 * 7;
int32 CallReceiveTimeoutMs = 20000;
int32 CallRingTimeoutMs = 90000;
int32 CallConnectTimeoutMs = 30000;
int32 CallPacketTimeoutMs = 10000;
int32 WebFileDcId = cTestMode() ? 2 : 4;
QString TxtDomainString = cTestMode()
? qsl("tapv3.stel.com")
: qsl("apv3.stel.com");
bool PhoneCallsEnabled = true;
bool BlockedMode = false;
int32 CaptionLengthMax = 1024;
base::Observable<void> PhoneCallsEnabledChanged;
HiddenPinnedMessagesMap HiddenPinnedMessages; HiddenPinnedMessagesMap HiddenPinnedMessages;
bool AskDownloadPath = false; bool AskDownloadPath = false;
@ -475,41 +438,6 @@ DefineRefVar(Global, base::Observable<void>, SongVolumeChanged);
DefineVar(Global, float64, VideoVolume); DefineVar(Global, float64, VideoVolume);
DefineRefVar(Global, base::Observable<void>, VideoVolumeChanged); DefineRefVar(Global, base::Observable<void>, VideoVolumeChanged);
// config
DefineVar(Global, int32, ChatSizeMax);
DefineVar(Global, int32, MegagroupSizeMax);
DefineVar(Global, int32, ForwardedCountMax);
DefineVar(Global, int32, OnlineUpdatePeriod);
DefineVar(Global, int32, OfflineBlurTimeout);
DefineVar(Global, int32, OfflineIdleTimeout);
DefineVar(Global, int32, OnlineFocusTimeout);
DefineVar(Global, int32, OnlineCloudTimeout);
DefineVar(Global, int32, NotifyCloudDelay);
DefineVar(Global, int32, NotifyDefaultDelay);
DefineVar(Global, int32, PushChatPeriod);
DefineVar(Global, int32, PushChatLimit);
DefineVar(Global, int32, SavedGifsLimit);
DefineVar(Global, int32, EditTimeLimit);
DefineVar(Global, int32, RevokeTimeLimit);
DefineVar(Global, int32, RevokePrivateTimeLimit);
DefineVar(Global, bool, RevokePrivateInbox);
DefineVar(Global, int32, StickersRecentLimit);
DefineVar(Global, int32, StickersFavedLimit);
DefineVar(Global, int32, PinnedDialogsCountMax);
DefineVar(Global, int32, PinnedDialogsInFolderMax);
DefineVar(Global, QString, InternalLinksDomain);
DefineVar(Global, int32, ChannelsReadMediaPeriod);
DefineVar(Global, int32, CallReceiveTimeoutMs);
DefineVar(Global, int32, CallRingTimeoutMs);
DefineVar(Global, int32, CallConnectTimeoutMs);
DefineVar(Global, int32, CallPacketTimeoutMs);
DefineVar(Global, int32, WebFileDcId);
DefineVar(Global, QString, TxtDomainString);
DefineVar(Global, bool, PhoneCallsEnabled);
DefineVar(Global, bool, BlockedMode);
DefineVar(Global, int32, CaptionLengthMax);
DefineRefVar(Global, base::Observable<void>, PhoneCallsEnabledChanged);
DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages); DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages);
DefineVar(Global, bool, AskDownloadPath); DefineVar(Global, bool, AskDownloadPath);

View file

@ -166,41 +166,6 @@ DeclareRefVar(base::Observable<void>, SongVolumeChanged);
DeclareVar(float64, VideoVolume); DeclareVar(float64, VideoVolume);
DeclareRefVar(base::Observable<void>, VideoVolumeChanged); DeclareRefVar(base::Observable<void>, VideoVolumeChanged);
// config
DeclareVar(int32, ChatSizeMax);
DeclareVar(int32, MegagroupSizeMax);
DeclareVar(int32, ForwardedCountMax);
DeclareVar(int32, OnlineUpdatePeriod);
DeclareVar(int32, OfflineBlurTimeout);
DeclareVar(int32, OfflineIdleTimeout);
DeclareVar(int32, OnlineFocusTimeout); // not from config
DeclareVar(int32, OnlineCloudTimeout);
DeclareVar(int32, NotifyCloudDelay);
DeclareVar(int32, NotifyDefaultDelay);
DeclareVar(int32, PushChatPeriod);
DeclareVar(int32, PushChatLimit);
DeclareVar(int32, SavedGifsLimit);
DeclareVar(int32, EditTimeLimit);
DeclareVar(int32, RevokeTimeLimit);
DeclareVar(int32, RevokePrivateTimeLimit);
DeclareVar(bool, RevokePrivateInbox);
DeclareVar(int32, StickersRecentLimit);
DeclareVar(int32, StickersFavedLimit);
DeclareVar(int32, PinnedDialogsCountMax);
DeclareVar(int32, PinnedDialogsInFolderMax);
DeclareVar(QString, InternalLinksDomain);
DeclareVar(int32, ChannelsReadMediaPeriod);
DeclareVar(int32, CallReceiveTimeoutMs);
DeclareVar(int32, CallRingTimeoutMs);
DeclareVar(int32, CallConnectTimeoutMs);
DeclareVar(int32, CallPacketTimeoutMs);
DeclareVar(int32, WebFileDcId);
DeclareVar(QString, TxtDomainString);
DeclareVar(bool, PhoneCallsEnabled);
DeclareVar(bool, BlockedMode);
DeclareVar(int32, CaptionLengthMax);
DeclareRefVar(base::Observable<void>, PhoneCallsEnabledChanged);
typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap; typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages); DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);

View file

@ -229,7 +229,7 @@ InnerWidget::InnerWidget(
, _controller(controller) , _controller(controller)
, _channel(channel) , _channel(channel)
, _history(channel->owner().history(channel)) , _history(channel->owner().history(channel))
, _api(_channel->session().mtp()) , _api(&_channel->session().mtp())
, _scrollDateCheck([=] { scrollDateCheck(); }) , _scrollDateCheck([=] { scrollDateCheck(); })
, _emptyText( , _emptyText(
st::historyAdminLogEmptyWidth st::historyAdminLogEmptyWidth

View file

@ -472,7 +472,11 @@ void GenerateItems(
auto bodyClientFlags = MTPDmessage_ClientFlag::f_admin_log_entry; auto bodyClientFlags = MTPDmessage_ClientFlag::f_admin_log_entry;
auto bodyReplyTo = 0; auto bodyReplyTo = 0;
auto bodyViaBotId = 0; auto bodyViaBotId = 0;
auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Core::App().createInternalLinkFull(newValue), QString()); auto newLink = newValue.isEmpty()
? TextWithEntities()
: PrepareText(
history->session().createInternalLinkFull(newValue),
QString());
auto body = history->makeMessage( auto body = history->makeMessage(
history->nextNonHistoryEntryId(), history->nextNonHistoryEntryId(),
bodyFlags, bodyFlags,
@ -484,7 +488,9 @@ void GenerateItems(
QString(), QString(),
newLink); newLink);
if (!oldValue.isEmpty()) { if (!oldValue.isEmpty()) {
auto oldLink = PrepareText(Core::App().createInternalLinkFull(oldValue), QString()); auto oldLink = PrepareText(
history->session().createInternalLinkFull(oldValue),
QString());
body->addLogEntryOriginal(id, tr::lng_admin_log_previous_link(tr::now), oldLink); body->addLogEntryOriginal(id, tr::lng_admin_log_previous_link(tr::now), oldLink);
} }
addPart(body); addPart(body);

View file

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_service.h" #include "history/history_service.h"
#include "history/history_message.h" #include "history/history_message.h"
#include "history/history.h" #include "history/history.h"
#include "mtproto/mtproto_config.h"
#include "media/clip/media_clip_reader.h" #include "media/clip/media_clip_reader.h"
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "ui/text/text_isolated_emoji.h" #include "ui/text/text_isolated_emoji.h"
@ -42,7 +43,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "facades.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_history.h" #include "styles/style_history.h"
@ -289,7 +289,8 @@ void HistoryItem::finishEditionToEmpty() {
bool HistoryItem::hasUnreadMediaFlag() const { bool HistoryItem::hasUnreadMediaFlag() const {
if (_history->peer->isChannel()) { if (_history->peer->isChannel()) {
const auto passed = base::unixtime::now() - date(); const auto passed = base::unixtime::now() - date();
if (passed >= Global::ChannelsReadMediaPeriod()) { const auto &config = _history->session().serverConfig();
if (passed >= config.channelsReadMediaPeriod) {
return false; return false;
} }
} }
@ -566,12 +567,13 @@ bool HistoryItem::canDelete() const {
bool HistoryItem::canDeleteForEveryone(TimeId now) const { bool HistoryItem::canDeleteForEveryone(TimeId now) const {
const auto peer = history()->peer; const auto peer = history()->peer;
const auto &config = history()->session().serverConfig();
const auto messageToMyself = peer->isSelf(); const auto messageToMyself = peer->isSelf();
const auto messageTooOld = messageToMyself const auto messageTooOld = messageToMyself
? false ? false
: peer->isUser() : peer->isUser()
? (now - date() >= Global::RevokePrivateTimeLimit()) ? (now - date() >= config.revokePrivateTimeLimit)
: (now - date() >= Global::RevokeTimeLimit()); : (now - date() >= config.revokeTimeLimit);
if (id < 0 || messageToMyself || messageTooOld || isPost()) { if (id < 0 || messageToMyself || messageTooOld || isPost()) {
return false; return false;
} }
@ -599,7 +601,7 @@ bool HistoryItem::canDeleteForEveryone(TimeId now) const {
return false; return false;
} }
} else if (peer->isUser()) { } else if (peer->isUser()) {
return Global::RevokePrivateInbox(); return config.revokePrivateInbox;
} else { } else {
return false; return false;
} }

View file

@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "storage/storage_shared_media.h" #include "storage/storage_shared_media.h"
#include "mtproto/mtproto_config.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_game.h" #include "data/data_game.h"
@ -40,7 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "facades.h" #include "facades.h" // Notify::replyMarkupUpdated
#include "app.h" #include "app.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
@ -208,6 +209,7 @@ void FastShareMessage(not_null<HistoryItem*> item) {
}; };
const auto history = item->history(); const auto history = item->history();
const auto owner = &history->owner(); const auto owner = &history->owner();
const auto session = &history->session();
const auto data = std::make_shared<ShareData>( const auto data = std::make_shared<ShareData>(
history->peer, history->peer,
owner->itemOrItsGroup(item)); owner->itemOrItsGroup(item));
@ -220,13 +222,11 @@ void FastShareMessage(not_null<HistoryItem*> item) {
auto copyCallback = [=]() { auto copyCallback = [=]() {
if (const auto item = owner->message(data->msgIds[0])) { if (const auto item = owner->message(data->msgIds[0])) {
if (item->hasDirectLink()) { if (item->hasDirectLink()) {
HistoryView::CopyPostLink( HistoryView::CopyPostLink(session, item->fullId());
&item->history()->session(),
item->fullId());
} else if (const auto bot = item->getMessageBot()) { } else if (const auto bot = item->getMessageBot()) {
if (const auto media = item->media()) { if (const auto media = item->media()) {
if (const auto game = media->game()) { if (const auto game = media->game()) {
const auto link = Core::App().createInternalLinkFull( const auto link = session->createInternalLinkFull(
bot->username bot->username
+ qsl("?game=") + qsl("?game=")
+ game->shortName); + game->shortName);
@ -782,7 +782,7 @@ bool HistoryMessage::allowsSendNow() const {
bool HistoryMessage::isTooOldForEdit(TimeId now) const { bool HistoryMessage::isTooOldForEdit(TimeId now) const {
return !_history->peer->canEditMessagesIndefinitely() return !_history->peer->canEditMessagesIndefinitely()
&& (now - date() >= Global::EditTimeLimit()); && (now - date() >= _history->session().serverConfig().editTimeLimit);
} }
bool HistoryMessage::allowsEdit(TimeId now) const { bool HistoryMessage::allowsEdit(TimeId now) const {

View file

@ -65,6 +65,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/bot_keyboard.h" #include "chat_helpers/bot_keyboard.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "platform/platform_specific.h" #include "platform/platform_specific.h"
#include "mtproto/mtproto_config.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -6756,7 +6757,7 @@ void HistoryWidget::paintEditHeader(Painter &p, const QRect &rect, int left, int
QString editTimeLeftText; QString editTimeLeftText;
int updateIn = -1; int updateIn = -1;
auto timeSinceMessage = ItemDateTime(_replyEditMsg).msecsTo(QDateTime::currentDateTime()); auto timeSinceMessage = ItemDateTime(_replyEditMsg).msecsTo(QDateTime::currentDateTime());
auto editTimeLeft = (Global::EditTimeLimit() * 1000LL) - timeSinceMessage; auto editTimeLeft = (session().serverConfig().editTimeLimit * 1000LL) - timeSinceMessage;
if (editTimeLeft < 2) { if (editTimeLeft < 2) {
editTimeLeftText = qsl("0:00"); editTimeLeftText = qsl("0:00");
} else if (editTimeLeft > kDisplayEditTimeWarningMs) { } else if (editTimeLeft > kDisplayEditTimeWarningMs) {

View file

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "core/shortcuts.h" #include "core/shortcuts.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
@ -129,9 +130,10 @@ TopBarWidget::TopBarWidget(
} }
}, lifetime()); }, lifetime());
subscribe(Global::RefPhoneCallsEnabledChanged(), [this] { session().serverConfig().phoneCallsEnabled.changes(
) | rpl::start_with_next([=] {
updateControlsVisibility(); updateControlsVisibility();
}); }, lifetime());
rpl::combine( rpl::combine(
session().settings().thirdSectionInfoEnabledValue(), session().settings().thirdSectionInfoEnabledValue(),
@ -156,8 +158,8 @@ Main::Session &TopBarWidget::session() const {
} }
void TopBarWidget::updateConnectingState() { void TopBarWidget::updateConnectingState() {
const auto mtp = _controller->session().mtp()->dcstate(); const auto state = _controller->session().mtp().dcstate();
if (mtp == MTP::ConnectedState) { if (state == MTP::ConnectedState) {
if (_connecting) { if (_connecting) {
_connecting = nullptr; _connecting = nullptr;
update(); update();
@ -640,7 +642,8 @@ void TopBarWidget::updateControlsVisibility() {
const auto callsEnabled = [&] { const auto callsEnabled = [&] {
if (const auto peer = _activeChat.peer()) { if (const auto peer = _activeChat.peer()) {
if (const auto user = peer->asUser()) { if (const auto user = peer->asUser()) {
return Global::PhoneCallsEnabled() && user->hasCalls(); return session().serverConfig().phoneCallsEnabled.current()
&& user->hasCalls();
} }
} }
return false; return false;
@ -663,7 +666,9 @@ void TopBarWidget::updateMembersShowArea() {
return chat->amIn(); return chat->amIn();
} }
if (auto megagroup = peer->asMegagroup()) { if (auto megagroup = peer->asMegagroup()) {
return megagroup->canViewMembers() && (megagroup->membersCount() < Global::ChatSizeMax()); return megagroup->canViewMembers()
&& (megagroup->membersCount()
< megagroup->session().serverConfig().chatSizeMax);
} }
return false; return false;
}(); }();
@ -846,7 +851,10 @@ void TopBarWidget::updateOnlineDisplay() {
} }
} }
} else if (const auto channel = _activeChat.peer()->asChannel()) { } else if (const auto channel = _activeChat.peer()->asChannel()) {
if (channel->isMegagroup() && channel->membersCount() > 0 && channel->membersCount() <= Global::ChatSizeMax()) { if (channel->isMegagroup()
&& (channel->membersCount() > 0)
&& (channel->membersCount()
<= channel->session().serverConfig().chatSizeMax)) {
if (channel->lastParticipantsRequestNeeded()) { if (channel->lastParticipantsRequestNeeded()) {
session().api().requestLastParticipants(channel); session().api().requestLastParticipants(channel);
} }

View file

@ -68,7 +68,7 @@ ListController::ListController(
not_null<UserData*> user) not_null<UserData*> user)
: PeerListController() : PeerListController()
, _controller(controller) , _controller(controller)
, _api(_controller->session().mtp()) , _api(&_controller->session().mtp())
, _user(user) { , _user(user) {
_controller->setSearchEnabledByContent(false); _controller->setSearchEnabledByContent(false);
} }

View file

@ -28,12 +28,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "facades.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "styles/style_profile.h" #include "styles/style_profile.h"
@ -479,7 +479,9 @@ void WrapWidget::addProfileCallsButton() {
const auto peer = key().peer(); const auto peer = key().peer();
const auto user = peer ? peer->asUser() : nullptr; const auto user = peer ? peer->asUser() : nullptr;
if (!user || user->isSelf() || !Global::PhoneCallsEnabled()) { if (!user
|| user->isSelf()
|| !user->session().serverConfig().phoneCallsEnabled.current()) {
return; return;
} }

View file

@ -232,7 +232,7 @@ ListController::ListController(
, _poll(poll) , _poll(poll)
, _context(context) , _context(context)
, _option(option) , _option(option)
, _api(_session->mtp()) { , _api(&_session->mtp()) {
const auto i = ranges::find(poll->answers, option, &PollAnswer::option); const auto i = ranges::find(poll->answers, option, &PollAnswer::option);
Assert(i != poll->answers.end()); Assert(i != poll->answers.end());
_fullCount = i->votes; _fullCount = i->votes;

View file

@ -301,7 +301,7 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
std::move(linkText), std::move(linkText),
QString()); QString());
link->setClickHandlerFilter([peer = _peer](auto&&...) { link->setClickHandlerFilter([peer = _peer](auto&&...) {
const auto link = Core::App().createInternalLinkFull( const auto link = peer->session().createInternalLinkFull(
peer->userName()); peer->userName());
if (!link.isEmpty()) { if (!link.isEmpty()) {
QGuiApplication::clipboard()->setText(link); QGuiApplication::clipboard()->setText(link);

View file

@ -133,10 +133,10 @@ rpl::producer<TextWithEntities> AboutValue(not_null<PeerData*> peer) {
rpl::producer<QString> LinkValue(not_null<PeerData*> peer) { rpl::producer<QString> LinkValue(not_null<PeerData*> peer) {
return PlainUsernameValue( return PlainUsernameValue(
peer peer
) | rpl::map([](QString &&username) { ) | rpl::map([=](QString &&username) {
return username.isEmpty() return username.isEmpty()
? QString() ? QString()
: Core::App().createInternalLinkFull(username); : peer->session().createInternalLinkFull(username);
}); });
} }

View file

@ -746,7 +746,7 @@ Widget::Widget(
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: RpWidget(parent) : RpWidget(parent)
, _controller(controller) , _controller(controller)
, _api(_controller->session().mtp()) , _api(&_controller->session().mtp())
, _contentMaxHeight(st::emojiPanMaxHeight) , _contentMaxHeight(st::emojiPanMaxHeight)
, _contentHeight(_contentMaxHeight) , _contentHeight(_contentMaxHeight)
, _scroll(this, st::inlineBotsScroll) { , _scroll(this, st::inlineBotsScroll) {

View file

@ -211,9 +211,9 @@ void CodeWidget::finished() {
} }
void CodeWidget::cancelled() { void CodeWidget::cancelled() {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
api()->request(base::take(_callRequestId)).cancel(); api().request(base::take(_callRequestId)).cancel();
api()->request(MTPauth_CancelCode( api().request(MTPauth_CancelCode(
MTP_string(getData()->phone), MTP_string(getData()->phone),
MTP_bytes(getData()->phoneHash) MTP_bytes(getData()->phoneHash)
)).send(); )).send();
@ -224,12 +224,12 @@ void CodeWidget::stopCheck() {
} }
void CodeWidget::checkRequest() { void CodeWidget::checkRequest() {
auto status = api()->instance()->state(_sentRequest); auto status = api().instance().state(_sentRequest);
if (status < 0) { if (status < 0) {
auto leftms = -status; auto leftms = -status;
if (leftms >= 1000) { if (leftms >= 1000) {
if (_sentRequest) { if (_sentRequest) {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
_sentCode.clear(); _sentCode.clear();
} }
} }
@ -282,7 +282,7 @@ void CodeWidget::codeSubmitFail(const RPCError &error) {
showCodeError(tr::lng_bad_code()); showCodeError(tr::lng_bad_code());
} else if (err == qstr("SESSION_PASSWORD_NEEDED")) { } else if (err == qstr("SESSION_PASSWORD_NEEDED")) {
_checkRequestTimer.callEach(1000); _checkRequestTimer.callEach(1000);
_sentRequest = api()->request(MTPaccount_GetPassword( _sentRequest = api().request(MTPaccount_GetPassword(
)).done([=](const MTPaccount_Password &result) { )).done([=](const MTPaccount_Password &result) {
gotPassword(result); gotPassword(result);
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
@ -305,7 +305,7 @@ void CodeWidget::sendCall() {
if (--_callTimeout <= 0) { if (--_callTimeout <= 0) {
_callStatus = CallStatus::Calling; _callStatus = CallStatus::Calling;
_callTimer.cancel(); _callTimer.cancel();
_callRequestId = api()->request(MTPauth_ResendCode( _callRequestId = api().request(MTPauth_ResendCode(
MTP_string(getData()->phone), MTP_string(getData()->phone),
MTP_bytes(getData()->phoneHash) MTP_bytes(getData()->phoneHash)
)).done([=](const MTPauth_SentCode &result) { )).done([=](const MTPauth_SentCode &result) {
@ -383,7 +383,7 @@ void CodeWidget::submit() {
getData()->hasRecovery = false; getData()->hasRecovery = false;
getData()->pwdHint = QString(); getData()->pwdHint = QString();
getData()->pwdNotEmptyPassport = false; getData()->pwdNotEmptyPassport = false;
_sentRequest = api()->request(MTPauth_SignIn( _sentRequest = api().request(MTPauth_SignIn(
MTP_string(getData()->phone), MTP_string(getData()->phone),
MTP_bytes(getData()->phoneHash), MTP_bytes(getData()->phoneHash),
MTP_string(_sentCode) MTP_string(_sentCode)
@ -398,7 +398,7 @@ void CodeWidget::noTelegramCode() {
if (_noTelegramCodeRequestId) { if (_noTelegramCodeRequestId) {
return; return;
} }
_noTelegramCodeRequestId = api()->request(MTPauth_ResendCode( _noTelegramCodeRequestId = api().request(MTPauth_ResendCode(
MTP_string(getData()->phone), MTP_string(getData()->phone),
MTP_bytes(getData()->phoneHash) MTP_bytes(getData()->phoneHash)
)).done([=](const MTPauth_SentCode &result) { )).done([=](const MTPauth_SentCode &result) {

View file

@ -114,7 +114,7 @@ void PasswordCheckWidget::activate() {
} }
void PasswordCheckWidget::cancelled() { void PasswordCheckWidget::cancelled() {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
} }
void PasswordCheckWidget::pwdSubmitDone(bool recover, const MTPauth_Authorization &result) { void PasswordCheckWidget::pwdSubmitDone(bool recover, const MTPauth_Authorization &result) {
@ -181,8 +181,8 @@ void PasswordCheckWidget::checkPasswordHash() {
} }
void PasswordCheckWidget::requestPasswordData() { void PasswordCheckWidget::requestPasswordData() {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
_sentRequest = api()->request( _sentRequest = api().request(
MTPaccount_GetPassword() MTPaccount_GetPassword()
).done([=](const MTPaccount_Password &result) { ).done([=](const MTPaccount_Password &result) {
_sentRequest = 0; _sentRequest = 0;
@ -204,7 +204,7 @@ void PasswordCheckWidget::passwordChecked() {
return serverError(); return serverError();
} }
_request.id = 0; _request.id = 0;
_sentRequest = api()->request( _sentRequest = api().request(
MTPauth_CheckPassword(check.result) MTPauth_CheckPassword(check.result)
).done([=](const MTPauth_Authorization &result) { ).done([=](const MTPauth_Authorization &result) {
pwdSubmitDone(false, result); pwdSubmitDone(false, result);
@ -266,7 +266,7 @@ void PasswordCheckWidget::recoverStartFail(const RPCError &error) {
void PasswordCheckWidget::toRecover() { void PasswordCheckWidget::toRecover() {
if (_hasRecovery) { if (_hasRecovery) {
if (_sentRequest) { if (_sentRequest) {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
} }
hideError(); hideError();
_toRecover->hide(); _toRecover->hide();
@ -278,7 +278,7 @@ void PasswordCheckWidget::toRecover() {
_codeField->setFocus(); _codeField->setFocus();
updateDescriptionText(); updateDescriptionText();
if (_emailPattern.isEmpty()) { if (_emailPattern.isEmpty()) {
api()->request( api().request(
MTPauth_RequestPasswordRecovery() MTPauth_RequestPasswordRecovery()
).done([=](const MTPauth_PasswordRecovery &result) { ).done([=](const MTPauth_PasswordRecovery &result) {
recoverStarted(result); recoverStarted(result);
@ -301,7 +301,7 @@ void PasswordCheckWidget::toPassword() {
void PasswordCheckWidget::showReset() { void PasswordCheckWidget::showReset() {
if (_sentRequest) { if (_sentRequest) {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
} }
_toRecover->show(); _toRecover->show();
_toPassword->hide(); _toPassword->hide();
@ -334,7 +334,7 @@ void PasswordCheckWidget::submit() {
return; return;
} }
const auto send = crl::guard(this, [=] { const auto send = crl::guard(this, [=] {
_sentRequest = api()->request( _sentRequest = api().request(
MTPauth_RecoverPassword(MTP_string(code)) MTPauth_RecoverPassword(MTP_string(code))
).done([=](const MTPauth_Authorization &result) { ).done([=](const MTPauth_Authorization &result) {
pwdSubmitDone(true, result); pwdSubmitDone(true, result);

View file

@ -141,8 +141,8 @@ void PhoneWidget::submit() {
_checkRequestTimer.callEach(1000); _checkRequestTimer.callEach(1000);
_sentPhone = phone; _sentPhone = phone;
api()->instance()->setUserPhone(_sentPhone); api().instance().setUserPhone(_sentPhone);
_sentRequest = api()->request(MTPauth_SendCode( _sentRequest = api().request(MTPauth_SendCode(
MTP_string(_sentPhone), MTP_string(_sentPhone),
MTP_int(ApiId), MTP_int(ApiId),
MTP_string(ApiHash), MTP_string(ApiHash),
@ -159,11 +159,11 @@ void PhoneWidget::stopCheck() {
} }
void PhoneWidget::checkRequest() { void PhoneWidget::checkRequest() {
auto status = api()->instance()->state(_sentRequest); auto status = api().instance().state(_sentRequest);
if (status < 0) { if (status < 0) {
auto leftms = -status; auto leftms = -status;
if (leftms >= 1000) { if (leftms >= 1000) {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
} }
} }
if (!_sentRequest && status == MTP::RequestSent) { if (!_sentRequest && status == MTP::RequestSent) {
@ -246,7 +246,7 @@ void PhoneWidget::finished() {
} }
void PhoneWidget::cancelled() { void PhoneWidget::cancelled() {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
} }
} // namespace details } // namespace details

View file

@ -308,7 +308,7 @@ void QrWidget::refreshCode() {
if (_requestId) { if (_requestId) {
return; return;
} }
_requestId = api()->request(MTPauth_ExportLoginToken( _requestId = api().request(MTPauth_ExportLoginToken(
MTP_int(ApiId), MTP_int(ApiId),
MTP_string(ApiHash), MTP_string(ApiHash),
MTP_vector<MTPint>(0) MTP_vector<MTPint>(0)
@ -356,8 +356,8 @@ void QrWidget::showToken(const QByteArray &token) {
void QrWidget::importTo(MTP::DcId dcId, const QByteArray &token) { void QrWidget::importTo(MTP::DcId dcId, const QByteArray &token) {
Expects(_requestId != 0); Expects(_requestId != 0);
api()->instance()->setMainDcId(dcId); api().instance().setMainDcId(dcId);
_requestId = api()->request(MTPauth_ImportLoginToken( _requestId = api().request(MTPauth_ImportLoginToken(
MTP_bytes(token) MTP_bytes(token)
)).done([=](const MTPauth_LoginToken &result) { )).done([=](const MTPauth_LoginToken &result) {
handleTokenResult(result); handleTokenResult(result);
@ -382,7 +382,7 @@ void QrWidget::done(const MTPauth_Authorization &authorization) {
} }
void QrWidget::sendCheckPasswordRequest() { void QrWidget::sendCheckPasswordRequest() {
_requestId = api()->request(MTPaccount_GetPassword( _requestId = api().request(MTPaccount_GetPassword(
)).done([=](const MTPaccount_Password &result) { )).done([=](const MTPaccount_Password &result) {
result.match([&](const MTPDaccount_password &data) { result.match([&](const MTPDaccount_password &data) {
getData()->pwdRequest = Core::ParseCloudPasswordCheckRequest( getData()->pwdRequest = Core::ParseCloudPasswordCheckRequest(
@ -426,7 +426,7 @@ void QrWidget::finished() {
} }
void QrWidget::cancelled() { void QrWidget::cancelled() {
api()->request(base::take(_requestId)).cancel(); api().request(base::take(_requestId)).cancel();
} }
} // namespace details } // namespace details

View file

@ -101,7 +101,7 @@ void SignupWidget::activate() {
} }
void SignupWidget::cancelled() { void SignupWidget::cancelled() {
api()->request(base::take(_sentRequest)).cancel(); api().request(base::take(_sentRequest)).cancel();
} }
void SignupWidget::nameSubmitDone(const MTPauth_Authorization &result) { void SignupWidget::nameSubmitDone(const MTPauth_Authorization &result) {
@ -181,7 +181,7 @@ void SignupWidget::submit() {
_firstName = _first->getLastText().trimmed(); _firstName = _first->getLastText().trimmed();
_lastName = _last->getLastText().trimmed(); _lastName = _last->getLastText().trimmed();
_sentRequest = api()->request(MTPauth_SignUp( _sentRequest = api().request(MTPauth_SignUp(
MTP_string(getData()->phone), MTP_string(getData()->phone),
MTP_bytes(getData()->phoneHash), MTP_bytes(getData()->phoneHash),
MTP_string(_firstName), MTP_string(_firstName),

View file

@ -98,11 +98,11 @@ Step::Step(
Step::~Step() = default; Step::~Step() = default;
not_null<MTP::Sender*> Step::api() const { MTP::Sender &Step::api() const {
if (!_api) { if (!_api) {
_api.emplace(_account->mtp()); _api.emplace(&_account->mtp());
} }
return &*_api; return *_api;
} }
void Step::apiClear() { void Step::apiClear() {

View file

@ -45,7 +45,7 @@ public:
// It should not be called in StartWidget, in other steps it should be // It should not be called in StartWidget, in other steps it should be
// present and not changing. // present and not changing.
[[nodiscard]] not_null<MTP::Sender*> api() const; [[nodiscard]] MTP::Sender &api() const;
void apiClear(); void apiClear();
virtual void finishInit() { virtual void finishInit() {

View file

@ -24,7 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/fade_wrap.h" #include "ui/wrap/fade_wrap.h"
#include "core/update_checker.h" #include "core/update_checker.h"
#include "core/application.h" #include "core/application.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "window/window_slide_animation.h" #include "window/window_slide_animation.h"
#include "window/window_connecting_widget.h" #include "window/window_connecting_widget.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
@ -64,14 +64,11 @@ Widget::Widget(QWidget *parent, not_null<Main::Account*> account)
getData()->country = Platform::SystemCountry(); getData()->country = Platform::SystemCountry();
_account->mtpValue( _account->mtpValue(
) | rpl::start_with_next([=](MTP::Instance *instance) { ) | rpl::start_with_next([=](not_null<MTP::Instance*> instance) {
if (instance) { _api.emplace(instance);
_api.emplace(instance); createLanguageLink();
createLanguageLink();
} else {
_api.reset();
}
}, lifetime()); }, lifetime());
subscribe(Lang::CurrentCloudManager().firstLanguageSuggestion(), [=] { subscribe(Lang::CurrentCloudManager().firstLanguageSuggestion(), [=] {
createLanguageLink(); createLanguageLink();
}); });
@ -141,9 +138,9 @@ void Widget::handleUpdates(const MTPUpdates &updates) {
void Widget::handleUpdate(const MTPUpdate &update) { void Widget::handleUpdate(const MTPUpdate &update) {
update.match([&](const MTPDupdateDcOptions &data) { update.match([&](const MTPDupdateDcOptions &data) {
Core::App().dcOptions()->addFromList(data.vdc_options()); _account->mtp().dcOptions().addFromList(data.vdc_options());
}, [&](const MTPDupdateConfig &data) { }, [&](const MTPDupdateConfig &data) {
_account->mtp()->requestConfig(); _account->mtp().requestConfig();
}, [&](const MTPDupdateServiceNotification &data) { }, [&](const MTPDupdateServiceNotification &data) {
const auto text = TextWithEntities{ const auto text = TextWithEntities{
qs(data.vmessage()), qs(data.vmessage()),

View file

@ -160,15 +160,16 @@ CloudManager::CloudManager(Instance &langpack)
: _langpack(langpack) { : _langpack(langpack) {
Core::App().accounts().activeValue( Core::App().accounts().activeValue(
) | rpl::map([=](Main::Account *account) { ) | rpl::map([=](Main::Account *account) {
return account ? account->mtpValue() : rpl::never<MTP::Instance*>(); if (!account) {
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](MTP::Instance *instance) {
if (instance) {
_api.emplace(instance);
resendRequests();
} else {
_api.reset(); _api.reset();
} }
return account
? account->mtpValue()
: rpl::never<not_null<MTP::Instance*>>();
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](not_null<MTP::Instance*> instance) {
_api.emplace(instance);
resendRequests();
}, _lifetime); }, _lifetime);
} }
@ -604,7 +605,7 @@ void CloudManager::switchLangPackId(const Language &data) {
void CloudManager::changeIdAndReInitConnection(const Language &data) { void CloudManager::changeIdAndReInitConnection(const Language &data) {
_langpack.switchToId(data); _langpack.switchToId(data);
if (_api) { if (_api) {
const auto mtproto = _api->instance(); const auto mtproto = &_api->instance();
mtproto->reInitConnection(mtproto->mainDcId()); mtproto->reInitConnection(mtproto->mainDcId());
} }
} }

View file

@ -414,16 +414,11 @@ void start(not_null<Core::Launcher*> launcher) {
LogsData = nullptr; LogsData = nullptr;
} }
LOG(("Launched version: %1, " LOG(("Launched version: %1, install beta: %2, alpha: %3, debug mode: %4"
"install beta: %2, "
"alpha: %3, "
"debug mode: %4, "
"test dc: %5"
).arg(AppVersion ).arg(AppVersion
).arg(Logs::b(cInstallBetaVersion()) ).arg(Logs::b(cInstallBetaVersion())
).arg(cAlphaVersion() ).arg(cAlphaVersion()
).arg(Logs::b(DebugEnabled()) ).arg(Logs::b(DebugEnabled())));
).arg(Logs::b(cTestMode())));
LOG(("Executable dir: %1, name: %2").arg(cExeDir()).arg(cExeName())); LOG(("Executable dir: %1, name: %2").arg(cExeDir()).arg(cExeName()));
LOG(("Initial working dir: %1").arg(initialWorkingDir)); LOG(("Initial working dir: %1").arg(initialWorkingDir));
LOG(("Working dir: %1").arg(cWorkingDir())); LOG(("Working dir: %1").arg(cWorkingDir()));

View file

@ -13,12 +13,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/storage_account.h" #include "storage/storage_account.h"
#include "storage/storage_accounts.h" // Storage::StartResult. #include "storage/storage_accounts.h" // Storage::StartResult.
#include "storage/serialize_common.h" #include "storage/serialize_common.h"
#include "storage/serialize_peer.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
#include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h"
#include "mtproto/mtp_instance.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "api/api_updates.h" #include "api/api_updates.h"
@ -46,7 +50,14 @@ Account::Account(const QString &dataName, int index)
ComposeDataString(dataName, index))) { ComposeDataString(dataName, index))) {
} }
Account::~Account() = default; Account::~Account() {
if (sessionExists()) {
session().saveSettingsNowIfNeeded();
}
destroySession();
_mtpValue.reset(nullptr);
base::take(_mtp);
}
[[nodiscard]] Storage::StartResult Account::legacyStart( [[nodiscard]] Storage::StartResult Account::legacyStart(
const QByteArray &passcode) { const QByteArray &passcode) {
@ -54,22 +65,27 @@ Account::~Account() = default;
const auto result = _local->legacyStart(passcode); const auto result = _local->legacyStart(passcode);
if (result == Storage::StartResult::Success) { if (result == Storage::StartResult::Success) {
finishStarting(); finishStarting(nullptr);
} }
return result; return result;
} }
void Account::start(std::shared_ptr<MTP::AuthKey> localKey) { void Account::start(std::shared_ptr<MTP::AuthKey> localKey) {
_local->start(std::move(localKey)); finishStarting(_local->start(std::move(localKey)));
finishStarting();
} }
void Account::startAdded(std::shared_ptr<MTP::AuthKey> localKey) { void Account::startAdded(
std::shared_ptr<MTP::AuthKey> localKey,
std::unique_ptr<MTP::Config> config) {
_local->startAdded(std::move(localKey)); _local->startAdded(std::move(localKey));
finishStarting(); finishStarting(std::move(config));
} }
void Account::finishStarting() { void Account::finishStarting(std::unique_ptr<MTP::Config> config) {
startMtp(config
? std::move(config)
: std::make_unique<MTP::Config>(
Core::App().fallbackProductionConfig()));
_appConfig = std::make_unique<AppConfig>(this); _appConfig = std::make_unique<AppConfig>(this);
watchProxyChanges(); watchProxyChanges();
watchSessionChanges(); watchSessionChanges();
@ -195,12 +211,10 @@ rpl::producer<Session*> Account::sessionChanges() const {
return _sessionValue.changes(); return _sessionValue.changes();
} }
rpl::producer<MTP::Instance*> Account::mtpValue() const { rpl::producer<not_null<MTP::Instance*>> Account::mtpValue() const {
return _mtpValue.value(); return _mtpValue.value() | rpl::map([](MTP::Instance *instance) {
} return not_null{ instance };
});
rpl::producer<MTP::Instance*> Account::mtpChanges() const {
return _mtpValue.changes();
} }
rpl::producer<MTPUpdates> Account::mtpUpdates() const { rpl::producer<MTPUpdates> Account::mtpUpdates() const {
@ -214,14 +228,14 @@ rpl::producer<> Account::mtpNewSessionCreated() const {
void Account::setLegacyMtpMainDcId(MTP::DcId mainDcId) { void Account::setLegacyMtpMainDcId(MTP::DcId mainDcId) {
Expects(!_mtp); Expects(!_mtp);
_mtpConfig.mainDcId = mainDcId; _mtpFields.mainDcId = mainDcId;
} }
void Account::setLegacyMtpKey(std::shared_ptr<MTP::AuthKey> key) { void Account::setLegacyMtpKey(std::shared_ptr<MTP::AuthKey> key) {
Expects(!_mtp); Expects(!_mtp);
Expects(key != nullptr); Expects(key != nullptr);
_mtpConfig.keys.push_back(std::move(key)); _mtpFields.keys.push_back(std::move(key));
} }
QByteArray Account::serializeMtpAuthorization() const { QByteArray Account::serializeMtpAuthorization() const {
@ -270,9 +284,9 @@ QByteArray Account::serializeMtpAuthorization() const {
: MTP::AuthKeysList(); : MTP::AuthKeysList();
return serialize(_mtp->mainDcId(), keys, keysToDestroy); return serialize(_mtp->mainDcId(), keys, keysToDestroy);
} }
const auto &keys = _mtpConfig.keys; const auto &keys = _mtpFields.keys;
const auto &keysToDestroy = _mtpKeysToDestroy; const auto &keysToDestroy = _mtpKeysToDestroy;
return serialize(_mtpConfig.mainDcId, keys, keysToDestroy); return serialize(_mtpFields.mainDcId, keys, keysToDestroy);
} }
void Account::setSessionUserId(UserId userId) { void Account::setSessionUserId(UserId userId) {
@ -319,9 +333,9 @@ void Account::setMtpAuthorization(const QByteArray &serialized) {
} }
setSessionUserId(userId); setSessionUserId(userId);
_mtpConfig.mainDcId = mainDcId; _mtpFields.mainDcId = mainDcId;
const auto readKeys = [&stream](auto &keys) { const auto readKeys = [&](auto &keys) {
const auto count = Serialize::read<qint32>(stream); const auto count = Serialize::read<qint32>(stream);
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("MTP Error: " LOG(("MTP Error: "
@ -340,29 +354,53 @@ void Account::setMtpAuthorization(const QByteArray &serialized) {
keys.push_back(std::make_shared<MTP::AuthKey>(MTP::AuthKey::Type::ReadFromFile, dcId, keyData)); keys.push_back(std::make_shared<MTP::AuthKey>(MTP::AuthKey::Type::ReadFromFile, dcId, keyData));
} }
}; };
readKeys(_mtpConfig.keys); readKeys(_mtpFields.keys);
readKeys(_mtpKeysToDestroy); readKeys(_mtpKeysToDestroy);
LOG(("MTP Info: " LOG(("MTP Info: "
"read keys, current: %1, to destroy: %2" "read keys, current: %1, to destroy: %2"
).arg(_mtpConfig.keys.size() ).arg(_mtpFields.keys.size()
).arg(_mtpKeysToDestroy.size())); ).arg(_mtpKeysToDestroy.size()));
} }
void Account::startMtp() { void Account::startMtp(std::unique_ptr<MTP::Config> config) {
Expects(!_mtp); Expects(!_mtp);
auto config = base::take(_mtpConfig); auto fields = base::take(_mtpFields);
config.deviceModel = Core::App().launcher()->deviceModel(); fields.config = std::move(config);
config.systemVersion = Core::App().launcher()->systemVersion(); fields.deviceModel = Core::App().launcher()->deviceModel();
fields.systemVersion = Core::App().launcher()->systemVersion();
_mtp = std::make_unique<MTP::Instance>( _mtp = std::make_unique<MTP::Instance>(
Core::App().dcOptions(),
MTP::Instance::Mode::Normal, MTP::Instance::Mode::Normal,
std::move(config)); std::move(fields));
const auto writingKeys = _mtp->lifetime().make_state<bool>(false);
_mtp->writeKeysRequests( _mtp->writeKeysRequests(
) | rpl::start_with_next([=] { ) | rpl::filter([=] {
local().writeMtpData(); return !*writingKeys;
}) | rpl::start_with_next([=] {
*writingKeys = true;
Ui::PostponeCall(_mtp.get(), [=] {
local().writeMtpData();
*writingKeys = false;
});
}, _mtp->lifetime()); }, _mtp->lifetime());
_mtpConfig.mainDcId = _mtp->mainDcId();
const auto writingConfig = _lifetime.make_state<bool>(false);
rpl::merge(
_mtp->config().updates(),
_mtp->dcOptions().changed(
) | rpl::map([] { return rpl::empty_value(); })
) | rpl::filter([=] {
return !*writingConfig;
}) | rpl::start_with_next([=] {
*writingConfig = true;
Ui::PostponeCall(_mtp.get(), [=] {
local().writeMtpConfig();
*writingConfig = false;
});
}, _lifetime);
_mtpFields.mainDcId = _mtp->mainDcId();
_mtp->setUpdatesHandler(::rpcDone([=]( _mtp->setUpdatesHandler(::rpcDone([=](
const mtpPrime *from, const mtpPrime *from,
@ -466,6 +504,8 @@ void Account::loggedOut() {
} }
void Account::destroyMtpKeys(MTP::AuthKeysList &&keys) { void Account::destroyMtpKeys(MTP::AuthKeysList &&keys) {
Expects(_mtp != nullptr);
if (keys.empty()) { if (keys.empty()) {
return; return;
} }
@ -474,15 +514,16 @@ void Account::destroyMtpKeys(MTP::AuthKeysList &&keys) {
local().writeMtpData(); local().writeMtpData();
return; return;
} }
auto destroyConfig = MTP::Instance::Config(); auto destroyFields = MTP::Instance::Fields();
destroyConfig.mainDcId = MTP::Instance::Config::kNoneMainDc;
destroyConfig.keys = std::move(keys); destroyFields.mainDcId = MTP::Instance::Fields::kNoneMainDc;
destroyConfig.deviceModel = Core::App().launcher()->deviceModel(); destroyFields.config = std::make_unique<MTP::Config>(_mtp->config());
destroyConfig.systemVersion = Core::App().launcher()->systemVersion(); destroyFields.keys = std::move(keys);
destroyFields.deviceModel = Core::App().launcher()->deviceModel();
destroyFields.systemVersion = Core::App().launcher()->systemVersion();
_mtpForKeysDestroy = std::make_unique<MTP::Instance>( _mtpForKeysDestroy = std::make_unique<MTP::Instance>(
Core::App().dcOptions(),
MTP::Instance::Mode::KeysDestroyer, MTP::Instance::Mode::KeysDestroyer,
std::move(destroyConfig)); std::move(destroyFields));
_mtpForKeysDestroy->writeKeysRequests( _mtpForKeysDestroy->writeKeysRequests(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
local().writeMtpData(); local().writeMtpData();
@ -501,8 +542,8 @@ void Account::suggestMainDcId(MTP::DcId mainDcId) {
Expects(_mtp != nullptr); Expects(_mtp != nullptr);
_mtp->suggestMainDcId(mainDcId); _mtp->suggestMainDcId(mainDcId);
if (_mtpConfig.mainDcId != MTP::Instance::Config::kNotSetMainDc) { if (_mtpFields.mainDcId != MTP::Instance::Fields::kNotSetMainDc) {
_mtpConfig.mainDcId = mainDcId; _mtpFields.mainDcId = mainDcId;
} }
} }
@ -521,25 +562,15 @@ void Account::destroyStaleAuthorizationKeys() {
} }
} }
void Account::configUpdated() {
_configUpdates.fire({});
}
rpl::producer<> Account::configUpdates() const {
return _configUpdates.events();
}
void Account::resetAuthorizationKeys() { void Account::resetAuthorizationKeys() {
_mtpValue = nullptr; Expects(_mtp != nullptr);
_mtp = nullptr;
startMtp(); {
const auto old = base::take(_mtp);
auto config = std::make_unique<MTP::Config>(old->config());
startMtp(std::move(config));
}
local().writeMtpData(); local().writeMtpData();
} }
void Account::clearMtp() {
_mtpValue = nullptr;
_mtp = nullptr;
_mtpForKeysDestroy = nullptr;
}
} // namespace Main } // namespace Main

View file

@ -18,6 +18,7 @@ enum class StartResult : uchar;
namespace MTP { namespace MTP {
class AuthKey; class AuthKey;
class Config;
} // namespace MTP } // namespace MTP
namespace Main { namespace Main {
@ -37,7 +38,9 @@ public:
[[nodiscard]] Storage::StartResult legacyStart( [[nodiscard]] Storage::StartResult legacyStart(
const QByteArray &passcode); const QByteArray &passcode);
void start(std::shared_ptr<MTP::AuthKey> localKey); void start(std::shared_ptr<MTP::AuthKey> localKey);
void startAdded(std::shared_ptr<MTP::AuthKey> localKey); void startAdded(
std::shared_ptr<MTP::AuthKey> localKey,
std::unique_ptr<MTP::Config> config);
[[nodiscard]] UserId willHaveUserId() const; [[nodiscard]] UserId willHaveUserId() const;
void createSession(const MTPUser &user); void createSession(const MTPUser &user);
@ -67,11 +70,10 @@ public:
[[nodiscard]] rpl::producer<Session*> sessionValue() const; [[nodiscard]] rpl::producer<Session*> sessionValue() const;
[[nodiscard]] rpl::producer<Session*> sessionChanges() const; [[nodiscard]] rpl::producer<Session*> sessionChanges() const;
[[nodiscard]] MTP::Instance *mtp() const { [[nodiscard]] MTP::Instance &mtp() const {
return _mtp.get(); return *_mtp;
} }
[[nodiscard]] rpl::producer<MTP::Instance*> mtpValue() const; [[nodiscard]] rpl::producer<not_null<MTP::Instance*>> mtpValue() const;
[[nodiscard]] rpl::producer<MTP::Instance*> mtpChanges() const;
// Set from legacy storage. // Set from legacy storage.
void setLegacyMtpMainDcId(MTP::DcId mainDcId); void setLegacyMtpMainDcId(MTP::DcId mainDcId);
@ -89,24 +91,21 @@ public:
[[nodiscard]] QByteArray serializeMtpAuthorization() const; [[nodiscard]] QByteArray serializeMtpAuthorization() const;
void setMtpAuthorization(const QByteArray &serialized); void setMtpAuthorization(const QByteArray &serialized);
void startMtp();
void suggestMainDcId(MTP::DcId mainDcId); void suggestMainDcId(MTP::DcId mainDcId);
void destroyStaleAuthorizationKeys(); void destroyStaleAuthorizationKeys();
void configUpdated();
[[nodiscard]] rpl::producer<> configUpdates() const;
void clearMtp();
rpl::lifetime &lifetime() { [[nodiscard]] rpl::lifetime &lifetime() {
return _lifetime; return _lifetime;
} }
private: private:
void startMtp(std::unique_ptr<MTP::Config> config);
void createSession( void createSession(
const MTPUser &user, const MTPUser &user,
QByteArray serialized, QByteArray serialized,
int streamVersion, int streamVersion,
Settings &&settings); Settings &&settings);
void finishStarting(); void finishStarting(std::unique_ptr<MTP::Config> config);
void watchProxyChanges(); void watchProxyChanges();
void watchSessionChanges(); void watchSessionChanges();
bool checkForUpdates(const mtpPrime *from, const mtpPrime *end); bool checkForUpdates(const mtpPrime *from, const mtpPrime *end);
@ -124,7 +123,6 @@ private:
std::unique_ptr<MTP::Instance> _mtpForKeysDestroy; std::unique_ptr<MTP::Instance> _mtpForKeysDestroy;
rpl::event_stream<MTPUpdates> _mtpUpdates; rpl::event_stream<MTPUpdates> _mtpUpdates;
rpl::event_stream<> _mtpNewSessionCreated; rpl::event_stream<> _mtpNewSessionCreated;
rpl::event_stream<> _configUpdates;
std::unique_ptr<AppConfig> _appConfig; std::unique_ptr<AppConfig> _appConfig;
@ -135,7 +133,7 @@ private:
QByteArray _sessionUserSerialized; QByteArray _sessionUserSerialized;
int32 _sessionUserStreamVersion = 0; int32 _sessionUserStreamVersion = 0;
std::unique_ptr<Settings> _storedSettings; std::unique_ptr<Settings> _storedSettings;
MTP::Instance::Config _mtpConfig; MTP::Instance::Fields _mtpFields;
MTP::AuthKeysList _mtpKeysToDestroy; MTP::AuthKeysList _mtpKeysToDestroy;
bool _loggingOut = false; bool _loggingOut = false;

View file

@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/shortcuts.h" #include "core/shortcuts.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h"
#include "storage/storage_accounts.h" #include "storage/storage_accounts.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "facades.h" #include "facades.h"
@ -43,6 +45,12 @@ Storage::StartResult Accounts::start(const QByteArray &passcode) {
return result; return result;
} }
void Accounts::finish() {
_activeIndex = -1;
_active = nullptr;
base::take(_accounts);
}
void Accounts::accountAddedInStorage( void Accounts::accountAddedInStorage(
int index, int index,
std::unique_ptr<Account> account) { std::unique_ptr<Account> account) {
@ -115,7 +123,28 @@ rpl::producer<Session*> Accounts::activeSessionValue() const {
return rpl::single(current) | rpl::then(_activeSessions.events()); return rpl::single(current) | rpl::then(_activeSessions.events());
} }
int Accounts::add() { int Accounts::add(MTP::Environment environment) {
Expects(_active.current() != nullptr);
static const auto cloneConfig = [](const MTP::Config &config) {
return std::make_unique<MTP::Config>(config);
};
static const auto accountConfig = [](not_null<Account*> account) {
return cloneConfig(account->mtp().config());
};
auto config = [&] {
if (_active.current()->mtp().environment() == environment) {
return accountConfig(_active.current());
}
for (const auto &[index, account] : list()) {
if (account->mtp().environment() == environment) {
return accountConfig(account.get());
}
}
return (environment == MTP::Environment::Production)
? cloneConfig(Core::App().fallbackProductionConfig())
: std::make_unique<MTP::Config>(environment);
}();
auto index = 0; auto index = 0;
while (_accounts.contains(index)) { while (_accounts.contains(index)) {
++index; ++index;
@ -124,17 +153,16 @@ int Accounts::add() {
index, index,
std::make_unique<Account>(_dataName, index) std::make_unique<Account>(_dataName, index)
).first->second.get(); ).first->second.get();
_local->startAdded(account); _local->startAdded(account, std::move(config));
watchSession(account); watchSession(account);
return index; return index;
} }
void Accounts::watchSession(not_null<Account*> account) { void Accounts::watchSession(not_null<Account*> account) {
account->startMtp();
account->sessionChanges( account->sessionChanges(
) | rpl::filter([=](Session *session) { ) | rpl::filter([=](Session *session) {
return !session; // removeRedundantAccounts may remove passcode lock. return !session; // removeRedundantAccounts may remove passcode lock.
}) | rpl::start_with_next([=](Session *session) { }) | rpl::start_with_next([=] {
if (account == _active.current()) { if (account == _active.current()) {
activateAuthedAccount(); activateAuthedAccount();
} }
@ -183,6 +211,7 @@ void Accounts::removeRedundantAccounts() {
++i; ++i;
continue; continue;
} }
checkForLastProductionConfig(i->second.get());
i = _accounts.erase(i); i = _accounts.erase(i);
} }
@ -191,6 +220,21 @@ void Accounts::removeRedundantAccounts() {
} }
} }
void Accounts::checkForLastProductionConfig(
not_null<Main::Account*> account) {
const auto mtp = &account->mtp();
if (mtp->environment() != MTP::Environment::Production) {
return;
}
for (const auto &[index, other] : _accounts) {
if (other.get() != account
&& other->mtp().environment() == MTP::Environment::Production) {
return;
}
}
Core::App().refreshFallbackProductionConfig(mtp->config());
}
void Accounts::activate(int index) { void Accounts::activate(int index) {
Expects(_accounts.contains(index)); Expects(_accounts.contains(index));

View file

@ -12,6 +12,10 @@ class Accounts;
enum class StartResult : uchar; enum class StartResult : uchar;
} // namespace Storage } // namespace Storage
namespace MTP {
enum class Environment : uchar;
} // namespace MTP
namespace Main { namespace Main {
class Account; class Account;
@ -25,6 +29,7 @@ public:
[[nodiscard]] bool started() const; [[nodiscard]] bool started() const;
[[nodiscard]] Storage::StartResult start(const QByteArray &passcode); [[nodiscard]] Storage::StartResult start(const QByteArray &passcode);
void resetWithForgottenPasscode(); void resetWithForgottenPasscode();
void finish();
[[nodiscard]] Storage::Accounts &local() const { [[nodiscard]] Storage::Accounts &local() const {
return *_local; return *_local;
@ -42,7 +47,7 @@ public:
[[nodiscard]] rpl::producer<Session*> activeSessionValue() const; [[nodiscard]] rpl::producer<Session*> activeSessionValue() const;
[[nodiscard]] rpl::producer<Session*> activeSessionChanges() const; [[nodiscard]] rpl::producer<Session*> activeSessionChanges() const;
[[nodiscard]] int add(); [[nodiscard]] int add(MTP::Environment environment);
void activate(int index); void activate(int index);
// Interface for Storage::Accounts. // Interface for Storage::Accounts.
@ -55,6 +60,7 @@ private:
void removeRedundantAccounts(); void removeRedundantAccounts();
void watchSession(not_null<Account*> account); void watchSession(not_null<Account*> account);
void scheduleWriteAccounts(); void scheduleWriteAccounts();
void checkForLastProductionConfig(not_null<Main::Account*> account);
const QString _dataName; const QString _dataName;
const std::unique_ptr<Storage::Accounts> _local; const std::unique_ptr<Storage::Accounts> _local;

View file

@ -20,14 +20,9 @@ constexpr auto kRefreshTimeout = 3600 * crl::time(1000);
AppConfig::AppConfig(not_null<Account*> account) : _account(account) { AppConfig::AppConfig(not_null<Account*> account) : _account(account) {
account->mtpValue( account->mtpValue(
) | rpl::start_with_next([=](MTP::Instance *instance) { ) | rpl::start_with_next([=](not_null<MTP::Instance*> instance) {
if (instance) { _api.emplace(instance);
_api.emplace(instance); refresh();
refresh();
} else {
_api.reset();
_requestId = 0;
}
}, _lifetime); }, _lifetime);
} }

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "core/changelogs.h" #include "core/changelogs.h"
#include "main/main_account.h" #include "main/main_account.h"
#include "mtproto/mtproto_config.h"
#include "chat_helpers/stickers_emoji_pack.h" #include "chat_helpers/stickers_emoji_pack.h"
#include "chat_helpers/stickers_dice_pack.h" #include "chat_helpers/stickers_dice_pack.h"
#include "storage/file_download.h" #include "storage/file_download.h"
@ -40,6 +41,25 @@ namespace {
constexpr auto kLegacyCallsPeerToPeerNobody = 4; constexpr auto kLegacyCallsPeerToPeerNobody = 4;
[[nodiscard]] QString ValidatedInternalLinksDomain(
not_null<const Main::Session*> session) {
// This domain should start with 'http[s]://' and end with '/'.
// Like 'https://telegram.me/' or 'https://t.me/'.
const auto &domain = session->serverConfig().internalLinksDomain;
const auto prefixes = {
qstr("https://"),
qstr("http://"),
};
for (const auto &prefix : prefixes) {
if (domain.startsWith(prefix, Qt::CaseInsensitive)) {
return domain.endsWith('/')
? domain
: MTP::ConfigFields().internalLinksDomain;
}
}
return MTP::ConfigFields().internalLinksDomain;
}
} // namespace } // namespace
Session::Session( Session::Session(
@ -75,7 +95,7 @@ Session::Session(
_api->requestTermsUpdate(); _api->requestTermsUpdate();
_api->requestFullPeer(_user); _api->requestFullPeer(_user);
_api->instance()->setUserPhone(_user->phone()); _api->instance().setUserPhone(_user->phone());
crl::on_main(this, [=] { crl::on_main(this, [=] {
using Flag = Data::PeerUpdate::Flag; using Flag = Data::PeerUpdate::Flag;
@ -91,9 +111,9 @@ Session::Session(
if (update.flags & Flag::PhoneNumber) { if (update.flags & Flag::PhoneNumber) {
const auto phone = _user->phone(); const auto phone = _user->phone();
_api->instance()->setUserPhone(phone); _api->instance().setUserPhone(phone);
if (!phone.isEmpty()) { if (!phone.isEmpty()) {
_api->instance()->requestConfig(); _api->instance().requestConfig();
} }
} }
}, _lifetime); }, _lifetime);
@ -156,19 +176,42 @@ void Session::saveSettingsDelayed(crl::time delay) {
} }
MTP::DcId Session::mainDcId() const { MTP::DcId Session::mainDcId() const {
return _account->mtp()->mainDcId(); return _account->mtp().mainDcId();
} }
not_null<MTP::Instance*> Session::mtp() const { MTP::Instance &Session::mtp() const {
return _account->mtp(); return _account->mtp();
} }
const MTP::ConfigFields &Session::serverConfig() const {
return _account->mtp().configValues();
}
void Session::termsDeleteNow() { void Session::termsDeleteNow() {
api().request(MTPaccount_DeleteAccount( api().request(MTPaccount_DeleteAccount(
MTP_string("Decline ToS update") MTP_string("Decline ToS update")
)).send(); )).send();
} }
QString Session::createInternalLink(const QString &query) const {
auto result = createInternalLinkFull(query);
auto prefixes = {
qstr("https://"),
qstr("http://"),
};
for (auto &prefix : prefixes) {
if (result.startsWith(prefix, Qt::CaseInsensitive)) {
return result.mid(prefix.size());
}
}
LOG(("Warning: bad internal url '%1'").arg(result));
return result;
}
QString Session::createInternalLinkFull(const QString &query) const {
return ValidatedInternalLinksDomain(this) + query;
}
bool Session::supportMode() const { bool Session::supportMode() const {
return (_supportHelper != nullptr); return (_supportHelper != nullptr);
} }

View file

@ -21,6 +21,7 @@ class Updates;
namespace MTP { namespace MTP {
class Instance; class Instance;
struct ConfigFields;
} // namespace MTP } // namespace MTP
namespace Support { namespace Support {
@ -127,7 +128,8 @@ public:
// Shortcuts. // Shortcuts.
[[nodiscard]] base::Observable<void> &downloaderTaskFinished(); [[nodiscard]] base::Observable<void> &downloaderTaskFinished();
[[nodiscard]] MTP::DcId mainDcId() const; [[nodiscard]] MTP::DcId mainDcId() const;
[[nodiscard]] not_null<MTP::Instance*> mtp() const; [[nodiscard]] MTP::Instance &mtp() const;
[[nodiscard]] const MTP::ConfigFields &serverConfig() const;
[[nodiscard]] ApiWrap &api() { [[nodiscard]] ApiWrap &api() {
return *_api; return *_api;
} }
@ -138,6 +140,10 @@ public:
void termsDeleteNow(); void termsDeleteNow();
void setInternalLinkDomain(const QString &domain) const;
[[nodiscard]] QString createInternalLink(const QString &query) const;
[[nodiscard]] QString createInternalLinkFull(const QString &query) const;
[[nodiscard]] rpl::lifetime &lifetime() { [[nodiscard]] rpl::lifetime &lifetime() {
return _lifetime; return _lifetime;
} }

View file

@ -85,7 +85,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "window/window_history_hider.h" #include "window/window_history_hider.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "core/update_checker.h" #include "core/update_checker.h"
#include "core/shortcuts.h" #include "core/shortcuts.h"

View file

@ -516,7 +516,7 @@ bool MainWindow::doWeMarkAsRead() {
if (!_main || Ui::isLayerShown()) { if (!_main || Ui::isLayerShown()) {
return false; return false;
} }
updateIsActive(0); updateIsActive();
return isActive() && _main->doWeMarkAsRead(); return isActive() && _main->doWeMarkAsRead();
} }
@ -609,7 +609,7 @@ void MainWindow::updateTrayMenu(bool force) {
auto minimizeAction = actions.at(1); auto minimizeAction = actions.at(1);
minimizeAction->setEnabled(isVisible()); minimizeAction->setEnabled(isVisible());
} else { } else {
updateIsActive(0); updateIsActive();
auto active = Platform::IsWayland() ? isVisible() : isActive(); auto active = Platform::IsWayland() ? isVisible() : isActive();
auto toggleAction = actions.at(0); auto toggleAction = actions.at(0);
disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(minimizeToTray())); disconnect(toggleAction, SIGNAL(triggered(bool)), this, SLOT(minimizeToTray()));
@ -705,7 +705,7 @@ void MainWindow::activate() {
setVisible(true); setVisible(true);
psActivateProcess(); psActivateProcess();
activateWindow(); activateWindow();
updateIsActive(Global::OnlineFocusTimeout()); controller().updateIsActiveFocus();
if (wasHidden) { if (wasHidden) {
if (_main) { if (_main) {
_main->windowShown(); _main->windowShown();
@ -743,7 +743,7 @@ void MainWindow::showFromTray(QSystemTrayIcon::ActivationReason reason) {
void MainWindow::handleTrayIconActication( void MainWindow::handleTrayIconActication(
QSystemTrayIcon::ActivationReason reason) { QSystemTrayIcon::ActivationReason reason) {
updateIsActive(0); updateIsActive();
if (Platform::IsMac() && isActive()) { if (Platform::IsMac() && isActive()) {
if (trayIcon && !trayIcon->contextMenu()) { if (trayIcon && !trayIcon->contextMenu()) {
showFromTray(reason); showFromTray(reason);

View file

@ -27,7 +27,7 @@ LoaderMtproto::LoaderMtproto(
Data::FileOrigin origin) Data::FileOrigin origin)
: DownloadMtprotoTask(owner, location, origin) : DownloadMtprotoTask(owner, location, origin)
, _size(size) , _size(size)
, _api(api().instance()) { , _api(&api().instance()) {
} }
Storage::Cache::Key LoaderMtproto::baseCacheKey() const { Storage::Cache::Key LoaderMtproto::baseCacheKey() const {

View file

@ -2462,6 +2462,7 @@ void OverlayWidget::initThemePreview() {
return result; return result;
}(); }();
const auto weakSession = base::make_weak(&_document->session());
const auto path = _document->location().name(); const auto path = _document->location().name();
const auto id = _themePreviewId = rand_value<uint64>(); const auto id = _themePreviewId = rand_value<uint64>();
const auto weak = Ui::MakeWeak(this); const auto weak = Ui::MakeWeak(this);
@ -2473,7 +2474,8 @@ void OverlayWidget::initThemePreview() {
std::move(data), std::move(data),
Window::Theme::PreviewType::Extended); Window::Theme::PreviewType::Extended);
crl::on_main(weak, [=, result = std::move(preview)]() mutable { crl::on_main(weak, [=, result = std::move(preview)]() mutable {
if (id != _themePreviewId) { const auto session = weakSession.get();
if (id != _themePreviewId || !session) {
return; return;
} }
_themePreviewId = 0; _themePreviewId = 0;
@ -2509,7 +2511,7 @@ void OverlayWidget::initThemePreview() {
_themeShare->show(); _themeShare->show();
_themeShare->setClickedCallback([=] { _themeShare->setClickedCallback([=] {
QGuiApplication::clipboard()->setText( QGuiApplication::clipboard()->setText(
Core::App().createInternalLinkFull("addtheme/" + slug)); session->createInternalLinkFull("addtheme/" + slug));
Ui::Toast::Show( Ui::Toast::Show(
this, this,
tr::lng_background_link_copied(tr::now)); tr::lng_background_link_copied(tr::now));

View file

@ -9,7 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/special_config_request.h" #include "mtproto/special_config_request.h"
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/mtproto_config.h"
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
#include "facades.h" #include "facades.h"
@ -40,7 +41,7 @@ void ConfigLoader::load() {
sendRequest(_instance->mainDcId()); sendRequest(_instance->mainDcId());
_enumDCTimer.callOnce(kEnumerateDcTimeout); _enumDCTimer.callOnce(kEnumerateDcTimeout);
} else { } else {
auto ids = _instance->dcOptions()->configEnumDcIds(); auto ids = _instance->dcOptions().configEnumDcIds();
Assert(!ids.empty()); Assert(!ids.empty());
_enumCurrent = ids.front(); _enumCurrent = ids.front();
enumerate(); enumerate();
@ -87,7 +88,7 @@ void ConfigLoader::enumerate() {
if (!_enumCurrent) { if (!_enumCurrent) {
_enumCurrent = _instance->mainDcId(); _enumCurrent = _instance->mainDcId();
} }
auto ids = _instance->dcOptions()->configEnumDcIds(); auto ids = _instance->dcOptions().configEnumDcIds();
Assert(!ids.empty()); Assert(!ids.empty());
auto i = std::find(ids.cbegin(), ids.cend(), _enumCurrent); auto i = std::find(ids.cbegin(), ids.cend(), _enumCurrent);
@ -135,7 +136,7 @@ void ConfigLoader::createSpecialLoader() {
} else { } else {
addSpecialEndpoint(dcId, ip, port, secret); addSpecialEndpoint(dcId, ip, port, secret);
} }
}, _phone); }, _instance->configValues().txtDomainString, _phone);
} }
void ConfigLoader::addSpecialEndpoint( void ConfigLoader::addSpecialEndpoint(
@ -180,7 +181,7 @@ void ConfigLoader::sendSpecialRequest() {
using Flag = MTPDdcOption::Flag; using Flag = MTPDdcOption::Flag;
const auto flags = Flag::f_tcpo_only const auto flags = Flag::f_tcpo_only
| (endpoint->secret.empty() ? Flag(0) : Flag::f_secret); | (endpoint->secret.empty() ? Flag(0) : Flag::f_secret);
_instance->dcOptions()->constructAddOne( _instance->dcOptions().constructAddOne(
_specialEnumCurrent, _specialEnumCurrent,
flags, flags,
endpoint->ip, endpoint->ip,
@ -212,7 +213,7 @@ void ConfigLoader::specialConfigLoaded(const MTPConfig &result) {
// We use special config only for dc options. // We use special config only for dc options.
// For everything else we wait for normal config from main dc. // For everything else we wait for normal config from main dc.
_instance->dcOptions()->setFromList(data.vdc_options()); _instance->dcOptions().setFromList(data.vdc_options());
} }
} // namespace details } // namespace details

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/mtproto_proxy_data.h" #include "mtproto/mtproto_proxy_data.h"
#include "base/bytes.h" #include "base/bytes.h"

View file

@ -84,7 +84,7 @@ std::optional<DedicatedLoader::File> ParseFile(
WeakInstance::WeakInstance(base::weak_ptr<Main::Session> session) WeakInstance::WeakInstance(base::weak_ptr<Main::Session> session)
: _session(session) : _session(session)
, _instance(_session ? _session->account().mtp() : nullptr) { , _instance(_session ? &_session->account().mtp() : nullptr) {
if (!valid()) { if (!valid()) {
return; return;
} }

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "mtproto/mtproto_auth_key.h" #include "mtproto/mtproto_auth_key.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/mtp_instance.h" #include "mtproto/mtp_instance.h"
#include "mtproto/special_config_request.h" #include "mtproto/special_config_request.h"

View file

@ -294,7 +294,7 @@ void DomainResolver::performRequest(
request.setRawHeader("Host", host.toLatin1()); request.setRawHeader("Host", host.toLatin1());
} }
} break; } break;
default: Unexpected("Type in SpecialConfigRequest::performRequest."); default: Unexpected("Type in DomainResolver::performRequest.");
} }
request.setUrl(url); request.setUrl(url);
request.setRawHeader("User-Agent", DnsUserAgent()); request.setRawHeader("User-Agent", DnsUserAgent());

View file

@ -63,17 +63,17 @@ inline bool isCdnDc(MTPDdcOption::Flags flags) {
inline bool isTemporaryDcId(ShiftedDcId shiftedDcId) { inline bool isTemporaryDcId(ShiftedDcId shiftedDcId) {
auto dcId = BareDcId(shiftedDcId); auto dcId = BareDcId(shiftedDcId);
return (dcId >= Instance::Config::kTemporaryMainDc); return (dcId >= Instance::Fields::kTemporaryMainDc);
} }
inline DcId getRealIdFromTemporaryDcId(ShiftedDcId shiftedDcId) { inline DcId getRealIdFromTemporaryDcId(ShiftedDcId shiftedDcId) {
auto dcId = BareDcId(shiftedDcId); auto dcId = BareDcId(shiftedDcId);
return (dcId >= Instance::Config::kTemporaryMainDc) ? (dcId - Instance::Config::kTemporaryMainDc) : 0; return (dcId >= Instance::Fields::kTemporaryMainDc) ? (dcId - Instance::Fields::kTemporaryMainDc) : 0;
} }
inline DcId getTemporaryIdFromRealDcId(ShiftedDcId shiftedDcId) { inline DcId getTemporaryIdFromRealDcId(ShiftedDcId shiftedDcId) {
auto dcId = BareDcId(shiftedDcId); auto dcId = BareDcId(shiftedDcId);
return (dcId < Instance::Config::kTemporaryMainDc) ? (dcId + Instance::Config::kTemporaryMainDc) : 0; return (dcId < Instance::Fields::kTemporaryMainDc) ? (dcId + Instance::Fields::kTemporaryMainDc) : 0;
} }
namespace details { namespace details {

View file

@ -11,7 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/special_config_request.h" #include "mtproto/special_config_request.h"
#include "mtproto/session.h" #include "mtproto/session.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_config.h"
#include "mtproto/mtproto_dc_options.h"
#include "mtproto/config_loader.h" #include "mtproto/config_loader.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
@ -53,9 +54,18 @@ int GetNextRequestId() {
class Instance::Private : private Sender { class Instance::Private : private Sender {
public: public:
Private(not_null<Instance*> instance, not_null<DcOptions*> options, Instance::Mode mode); Private(
not_null<Instance*> instance,
Instance::Mode mode,
Fields &&fields);
void start(Config &&config); void start();
[[nodiscard]] Config &config() const;
[[nodiscard]] const ConfigFields &configValues() const;
[[nodiscard]] DcOptions &dcOptions() const;
[[nodiscard]] Environment environment() const;
[[nodiscard]] bool isTestMode() const;
void resolveProxyDomain(const QString &host); void resolveProxyDomain(const QString &host);
void setGoodProxyDomain(const QString &host, const QString &ip); void setGoodProxyDomain(const QString &host, const QString &ip);
@ -72,8 +82,6 @@ public:
void addKeysForDestroy(AuthKeysList &&keys); void addKeysForDestroy(AuthKeysList &&keys);
[[nodiscard]] rpl::producer<> allKeysDestroyed() const; [[nodiscard]] rpl::producer<> allKeysDestroyed() const;
[[nodiscard]] not_null<DcOptions*> dcOptions();
// Thread safe. // Thread safe.
[[nodiscard]] QString deviceModel() const; [[nodiscard]] QString deviceModel() const;
[[nodiscard]] QString systemVersion() const; [[nodiscard]] QString systemVersion() const;
@ -195,8 +203,8 @@ private:
void checkDelayedRequests(); void checkDelayedRequests();
const not_null<Instance*> _instance; const not_null<Instance*> _instance;
const not_null<DcOptions*> _dcOptions;
const Instance::Mode _mode = Instance::Mode::Normal; const Instance::Mode _mode = Instance::Mode::Normal;
const std::unique_ptr<Config> _config;
std::unique_ptr<QThread> _mainSessionThread; std::unique_ptr<QThread> _mainSessionThread;
std::unique_ptr<QThread> _otherSessionsThread; std::unique_ptr<QThread> _otherSessionsThread;
@ -205,7 +213,7 @@ private:
QString _deviceModel; QString _deviceModel;
QString _systemVersion; QString _systemVersion;
DcId _mainDcId = Config::kDefaultMainDc; DcId _mainDcId = Fields::kDefaultMainDc;
bool _mainDcIdForced = false; bool _mainDcIdForced = false;
base::flat_map<DcId, std::unique_ptr<Dcenter>> _dcenters; base::flat_map<DcId, std::unique_ptr<Dcenter>> _dcenters;
std::vector<std::unique_ptr<Dcenter>> _dcentersToDestroy; std::vector<std::unique_ptr<Dcenter>> _dcentersToDestroy;
@ -261,27 +269,36 @@ private:
}; };
Instance::Fields::Fields() = default;
Instance::Fields::Fields(Fields &&other) = default;
auto Instance::Fields::operator=(Fields &&other) -> Fields & = default;
Instance::Fields::~Fields() = default;
Instance::Private::Private( Instance::Private::Private(
not_null<Instance*> instance, not_null<Instance*> instance,
not_null<DcOptions*> options, Instance::Mode mode,
Instance::Mode mode) Fields &&fields)
: Sender(instance) : Sender(instance)
, _instance(instance) , _instance(instance)
, _dcOptions(options) , _mode(mode)
, _mode(mode) { , _config(std::move(fields.config)) {
Expects(_config != nullptr);
const auto idealThreadPoolSize = QThread::idealThreadCount(); const auto idealThreadPoolSize = QThread::idealThreadCount();
_fileSessionThreads.resize(2 * std::max(idealThreadPoolSize / 2, 1)); _fileSessionThreads.resize(2 * std::max(idealThreadPoolSize / 2, 1));
details::unpaused( details::unpaused(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
unpaused(); unpaused();
}, _lifetime); }, _lifetime);
}
void Instance::Private::start(Config &&config) { _deviceModel = std::move(fields.deviceModel);
_deviceModel = std::move(config.deviceModel); _systemVersion = std::move(fields.systemVersion);
_systemVersion = std::move(config.systemVersion);
for (auto &key : config.keys) { for (auto &key : fields.keys) {
auto dcId = key->dcId(); auto dcId = key->dcId();
auto shiftedDcId = dcId; auto shiftedDcId = dcId;
if (isKeysDestroyer()) { if (isKeysDestroyer()) {
@ -297,22 +314,24 @@ void Instance::Private::start(Config &&config) {
addDc(shiftedDcId, std::move(key)); addDc(shiftedDcId, std::move(key));
} }
if (config.mainDcId != Config::kNotSetMainDc) { if (fields.mainDcId != Fields::kNotSetMainDc) {
_mainDcId = config.mainDcId; _mainDcId = fields.mainDcId;
_mainDcIdForced = true; _mainDcIdForced = true;
} }
}
void Instance::Private::start() {
if (isKeysDestroyer()) { if (isKeysDestroyer()) {
for (const auto &[shiftedDcId, dc] : _dcenters) { for (const auto &[shiftedDcId, dc] : _dcenters) {
startSession(shiftedDcId); startSession(shiftedDcId);
} }
} else if (_mainDcId != Config::kNoneMainDc) { } else if (_mainDcId != Fields::kNoneMainDc) {
_mainSession = startSession(_mainDcId); _mainSession = startSession(_mainDcId);
} }
_checkDelayedTimer.setCallback([this] { checkDelayedRequests(); }); _checkDelayedTimer.setCallback([this] { checkDelayedRequests(); });
Assert((_mainDcId == Config::kNoneMainDc) == isKeysDestroyer()); Assert((_mainDcId == Fields::kNoneMainDc) == isKeysDestroyer());
requestConfig(); requestConfig();
} }
@ -418,7 +437,8 @@ void Instance::Private::setMainDcId(DcId mainDcId) {
} }
DcId Instance::Private::mainDcId() const { DcId Instance::Private::mainDcId() const {
Expects(_mainDcId != Config::kNoneMainDc); Expects(_mainDcId != Fields::kNoneMainDc);
return _mainDcId; return _mainDcId;
} }
@ -457,7 +477,7 @@ void Instance::Private::syncHttpUnixtime() {
InvokeQueued(_instance, [=] { InvokeQueued(_instance, [=] {
_httpUnixtimeLoader = nullptr; _httpUnixtimeLoader = nullptr;
}); });
}); }, configValues().txtDomainString);
} }
void Instance::Private::restartedByTimeout(ShiftedDcId shiftedDcId) { void Instance::Private::restartedByTimeout(ShiftedDcId shiftedDcId) {
@ -469,7 +489,7 @@ rpl::producer<ShiftedDcId> Instance::Private::restartsByTimeout() const {
} }
void Instance::Private::requestConfigIfOld() { void Instance::Private::requestConfigIfOld() {
const auto timeout = Global::BlockedMode() const auto timeout = _config->values().blockedMode
? kConfigBecomesOldForBlockedIn ? kConfigBecomesOldForBlockedIn
: kConfigBecomesOldIn; : kConfigBecomesOldIn;
if (crl::now() - _lastConfigLoadedTime >= timeout) { if (crl::now() - _lastConfigLoadedTime >= timeout) {
@ -490,7 +510,7 @@ void Instance::Private::requestConfigIfExpired() {
} }
void Instance::Private::requestCDNConfig() { void Instance::Private::requestCDNConfig() {
if (_cdnConfigLoadRequestId || _mainDcId == Config::kNoneMainDc) { if (_cdnConfigLoadRequestId || _mainDcId == Fields::kNoneMainDc) {
return; return;
} }
_cdnConfigLoadRequestId = request( _cdnConfigLoadRequestId = request(
@ -498,7 +518,7 @@ void Instance::Private::requestCDNConfig() {
).done([this](const MTPCdnConfig &result) { ).done([this](const MTPCdnConfig &result) {
_cdnConfigLoadRequestId = 0; _cdnConfigLoadRequestId = 0;
result.match([&](const MTPDcdnConfig &data) { result.match([&](const MTPDcdnConfig &data) {
dcOptions()->setCDNConfig(data); dcOptions().setCDNConfig(data);
}); });
Local::writeSettings(); Local::writeSettings();
}).send(); }).send();
@ -642,7 +662,7 @@ void Instance::Private::logoutGuestDcs() {
dcIds.push_back(key.first); dcIds.push_back(key.first);
} }
for (const auto dcId : dcIds) { for (const auto dcId : dcIds) {
if (dcId == mainDcId() || dcOptions()->dcType(dcId) == DcType::Cdn) { if (dcId == mainDcId() || dcOptions().dcType(dcId) == DcType::Cdn) {
continue; continue;
} }
const auto shiftedDcId = MTP::logoutDcId(dcId); const auto shiftedDcId = MTP::logoutDcId(dcId);
@ -784,8 +804,24 @@ rpl::producer<> Instance::Private::writeKeysRequests() const {
return _writeKeysRequests.events(); return _writeKeysRequests.events();
} }
not_null<DcOptions*> Instance::Private::dcOptions() { Config &Instance::Private::config() const {
return _dcOptions; return *_config;
}
const ConfigFields &Instance::Private::configValues() const {
return _config->values();
}
DcOptions &Instance::Private::dcOptions() const {
return _config->dcOptions();
}
Environment Instance::Private::environment() const {
return _config->environment();
}
bool Instance::Private::isTestMode() const {
return _config->isTestMode();
} }
QString Instance::Private::deviceModel() const { QString Instance::Private::deviceModel() const {
@ -809,58 +845,13 @@ void Instance::Private::configLoadDone(const MTPConfig &result) {
_lastConfigLoadedTime = crl::now(); _lastConfigLoadedTime = crl::now();
const auto &data = result.c_config(); const auto &data = result.c_config();
DEBUG_LOG(("MTP Info: got config, chat_size_max: %1, date: %2, test_mode: %3, this_dc: %4, dc_options.length: %5").arg(data.vchat_size_max().v).arg(data.vdate().v).arg(mtpIsTrue(data.vtest_mode())).arg(data.vthis_dc().v).arg(data.vdc_options().v.size())); _config->apply(data);
if (data.vdc_options().v.empty()) {
LOG(("MTP Error: config with empty dc_options received!"));
} else {
_dcOptions->setFromList(data.vdc_options());
}
Global::SetChatSizeMax(data.vchat_size_max().v);
Global::SetMegagroupSizeMax(data.vmegagroup_size_max().v);
Global::SetForwardedCountMax(data.vforwarded_count_max().v);
Global::SetOnlineUpdatePeriod(data.vonline_update_period_ms().v);
Global::SetOfflineBlurTimeout(data.voffline_blur_timeout_ms().v);
Global::SetOfflineIdleTimeout(data.voffline_idle_timeout_ms().v);
Global::SetOnlineCloudTimeout(data.vonline_cloud_timeout_ms().v);
Global::SetNotifyCloudDelay(data.vnotify_cloud_delay_ms().v);
Global::SetNotifyDefaultDelay(data.vnotify_default_delay_ms().v);
Global::SetPushChatPeriod(data.vpush_chat_period_ms().v);
Global::SetPushChatLimit(data.vpush_chat_limit().v);
Global::SetSavedGifsLimit(data.vsaved_gifs_limit().v);
Global::SetEditTimeLimit(data.vedit_time_limit().v);
Global::SetRevokeTimeLimit(data.vrevoke_time_limit().v);
Global::SetRevokePrivateTimeLimit(data.vrevoke_pm_time_limit().v);
Global::SetRevokePrivateInbox(data.is_revoke_pm_inbox());
Global::SetStickersRecentLimit(data.vstickers_recent_limit().v);
Global::SetStickersFavedLimit(data.vstickers_faved_limit().v);
Global::SetPinnedDialogsCountMax(
std::max(data.vpinned_dialogs_count_max().v, 1));
Global::SetPinnedDialogsInFolderMax(
std::max(data.vpinned_infolder_count_max().v, 1));
Core::App().setInternalLinkDomain(qs(data.vme_url_prefix()));
Global::SetChannelsReadMediaPeriod(data.vchannels_read_media_period().v);
Global::SetWebFileDcId(data.vwebfile_dc_id().v);
Global::SetTxtDomainString(qs(data.vdc_txt_domain_name()));
Global::SetCallReceiveTimeoutMs(data.vcall_receive_timeout_ms().v);
Global::SetCallRingTimeoutMs(data.vcall_ring_timeout_ms().v);
Global::SetCallConnectTimeoutMs(data.vcall_connect_timeout_ms().v);
Global::SetCallPacketTimeoutMs(data.vcall_packet_timeout_ms().v);
if (Global::PhoneCallsEnabled() != data.is_phonecalls_enabled()) {
Global::SetPhoneCallsEnabled(data.is_phonecalls_enabled());
Global::RefPhoneCallsEnabledChanged().notify();
}
Global::SetBlockedMode(data.is_blocked_mode());
Global::SetCaptionLengthMax(data.vcaption_length_max().v);
const auto lang = qs(data.vsuggested_lang_code().value_or_empty()); const auto lang = qs(data.vsuggested_lang_code().value_or_empty());
Lang::CurrentCloudManager().setSuggestedLanguage(lang); Lang::CurrentCloudManager().setSuggestedLanguage(lang);
Lang::CurrentCloudManager().setCurrentVersions( Lang::CurrentCloudManager().setCurrentVersions(
data.vlang_pack_version().value_or_empty(), data.vlang_pack_version().value_or_empty(),
data.vbase_lang_pack_version().value_or_empty()); data.vbase_lang_pack_version().value_or_empty());
Core::App().activeAccount().configUpdated(); // #TODO multi
if (const auto prefix = data.vautoupdate_url_prefix()) { if (const auto prefix = data.vautoupdate_url_prefix()) {
Local::writeAutoupdatePrefix(qs(*prefix)); Local::writeAutoupdatePrefix(qs(*prefix));
} }
@ -1520,7 +1511,7 @@ not_null<QThread*> Instance::Private::getThreadForDc(
void Instance::Private::scheduleKeyDestroy(ShiftedDcId shiftedDcId) { void Instance::Private::scheduleKeyDestroy(ShiftedDcId shiftedDcId) {
Expects(isKeysDestroyer()); Expects(isKeysDestroyer());
if (dcOptions()->dcType(shiftedDcId) == DcType::Cdn) { if (dcOptions().dcType(shiftedDcId) == DcType::Cdn) {
performKeyDestroy(shiftedDcId); performKeyDestroy(shiftedDcId);
} else { } else {
_instance->send(MTPauth_LogOut(), rpcDone([=](const MTPBool &) { _instance->send(MTPauth_LogOut(), rpcDone([=](const MTPBool &) {
@ -1643,10 +1634,10 @@ void Instance::Private::prepareToDestroy() {
} }
} }
Instance::Instance(not_null<DcOptions*> options, Mode mode, Config &&config) Instance::Instance(Mode mode, Fields &&fields)
: QObject() : QObject()
, _private(std::make_unique<Private>(this, options, mode)) { , _private(std::make_unique<Private>(this, mode, std::move(fields))) {
_private->start(std::move(config)); _private->start();
} }
void Instance::resolveProxyDomain(const QString &host) { void Instance::resolveProxyDomain(const QString &host) {
@ -1787,10 +1778,26 @@ void Instance::addKeysForDestroy(AuthKeysList &&keys) {
_private->addKeysForDestroy(std::move(keys)); _private->addKeysForDestroy(std::move(keys));
} }
not_null<DcOptions*> Instance::dcOptions() { Config &Instance::config() const {
return _private->config();
}
const ConfigFields &Instance::configValues() const {
return _private->configValues();
}
DcOptions &Instance::dcOptions() const {
return _private->dcOptions(); return _private->dcOptions();
} }
Environment Instance::environment() const {
return _private->environment();
}
bool Instance::isTestMode() const {
return _private->isTestMode();
}
QString Instance::deviceModel() const { QString Instance::deviceModel() const {
return _private->deviceModel(); return _private->deviceModel();
} }

View file

@ -21,20 +21,29 @@ class Session;
} // namespace details } // namespace details
class DcOptions; class DcOptions;
class Config;
struct ConfigFields;
class AuthKey; class AuthKey;
using AuthKeyPtr = std::shared_ptr<AuthKey>; using AuthKeyPtr = std::shared_ptr<AuthKey>;
using AuthKeysList = std::vector<AuthKeyPtr>; using AuthKeysList = std::vector<AuthKeyPtr>;
enum class Environment : uchar;
class Instance : public QObject { class Instance : public QObject {
Q_OBJECT Q_OBJECT
public: public:
struct Config { struct Fields {
Fields();
Fields(Fields &&other);
Fields &operator=(Fields &&other);
~Fields();
static constexpr auto kNoneMainDc = -1; static constexpr auto kNoneMainDc = -1;
static constexpr auto kNotSetMainDc = 0; static constexpr auto kNotSetMainDc = 0;
static constexpr auto kDefaultMainDc = 2; static constexpr auto kDefaultMainDc = 2;
static constexpr auto kTemporaryMainDc = 1000; static constexpr auto kTemporaryMainDc = 1000;
std::unique_ptr<Config> config;
DcId mainDcId = kNotSetMainDc; DcId mainDcId = kNotSetMainDc;
AuthKeysList keys; AuthKeysList keys;
QString deviceModel; QString deviceModel;
@ -46,7 +55,7 @@ public:
KeysDestroyer, KeysDestroyer,
}; };
Instance(not_null<DcOptions*> options, Mode mode, Config &&config); Instance(Mode mode, Fields &&fields);
Instance(const Instance &other) = delete; Instance(const Instance &other) = delete;
Instance &operator=(const Instance &other) = delete; Instance &operator=(const Instance &other) = delete;
~Instance(); ~Instance();
@ -64,6 +73,11 @@ public:
[[nodiscard]] rpl::producer<> allKeysDestroyed() const; [[nodiscard]] rpl::producer<> allKeysDestroyed() const;
// Thread-safe. // Thread-safe.
[[nodiscard]] Config &config() const;
[[nodiscard]] const ConfigFields &configValues() const;
[[nodiscard]] DcOptions &dcOptions() const;
[[nodiscard]] Environment environment() const;
[[nodiscard]] bool isTestMode() const;
[[nodiscard]] QString deviceModel() const; [[nodiscard]] QString deviceModel() const;
[[nodiscard]] QString systemVersion() const; [[nodiscard]] QString systemVersion() const;
@ -74,8 +88,6 @@ public:
[[nodiscard]] AuthKeysList getKeysForWrite() const; [[nodiscard]] AuthKeysList getKeysForWrite() const;
void addKeysForDestroy(AuthKeysList &&keys); void addKeysForDestroy(AuthKeysList &&keys);
[[nodiscard]] not_null<DcOptions*> dcOptions();
void restart(); void restart();
void restart(ShiftedDcId shiftedDcId); void restart(ShiftedDcId shiftedDcId);
int32 dcstate(ShiftedDcId shiftedDcId = 0); int32 dcstate(ShiftedDcId shiftedDcId = 0);

View file

@ -0,0 +1,259 @@
/*
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 "mtproto/mtproto_config.h"
#include "storage/serialize_common.h"
#include "mtproto/type_utils.h"
#include "logs.h"
namespace MTP {
namespace {
constexpr auto kVersion = 1;
}
Config::Config(Environment environment) : _dcOptions(environment) {
_fields.webFileDcId = _dcOptions.isTestMode() ? 2 : 4;
_fields.txtDomainString = _dcOptions.isTestMode()
? u"tapv3.stel.com"_q
: u"apv3.stel.com"_q;
}
Config::Config(const Config &other)
: _dcOptions(other.dcOptions())
, _fields(other._fields) {
}
QByteArray Config::serialize() const {
auto options = _dcOptions.serialize();
auto size = sizeof(qint32) * 2; // version + environment
size += Serialize::bytearraySize(options);
size += 28 * sizeof(qint32);
size += Serialize::stringSize(_fields.internalLinksDomain);
size += Serialize::stringSize(_fields.txtDomainString);
auto result = QByteArray();
result.reserve(size);
{
QDataStream stream(&result, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_1);
stream
<< qint32(kVersion)
<< qint32(_dcOptions.isTestMode()
? Environment::Test
: Environment::Production)
<< options
<< qint32(_fields.chatSizeMax)
<< qint32(_fields.megagroupSizeMax)
<< qint32(_fields.forwardedCountMax)
<< qint32(_fields.onlineUpdatePeriod)
<< qint32(_fields.offlineBlurTimeout)
<< qint32(_fields.offlineIdleTimeout)
<< qint32(_fields.onlineFocusTimeout)
<< qint32(_fields.onlineCloudTimeout)
<< qint32(_fields.notifyCloudDelay)
<< qint32(_fields.notifyDefaultDelay)
<< qint32(_fields.savedGifsLimit)
<< qint32(_fields.editTimeLimit)
<< qint32(_fields.revokeTimeLimit)
<< qint32(_fields.revokePrivateTimeLimit)
<< qint32(_fields.revokePrivateInbox ? 1 : 0)
<< qint32(_fields.stickersRecentLimit)
<< qint32(_fields.stickersFavedLimit)
<< qint32(_fields.pinnedDialogsCountMax.current())
<< qint32(_fields.pinnedDialogsInFolderMax.current())
<< _fields.internalLinksDomain
<< qint32(_fields.channelsReadMediaPeriod)
<< qint32(_fields.callReceiveTimeoutMs)
<< qint32(_fields.callRingTimeoutMs)
<< qint32(_fields.callConnectTimeoutMs)
<< qint32(_fields.callPacketTimeoutMs)
<< qint32(_fields.webFileDcId)
<< _fields.txtDomainString
<< qint32(_fields.phoneCallsEnabled.current() ? 1 : 0)
<< qint32(_fields.blockedMode ? 1 : 0)
<< qint32(_fields.captionLengthMax);
}
return result;
}
std::unique_ptr<Config> Config::FromSerialized(const QByteArray &serialized) {
auto result = std::unique_ptr<Config>();
auto raw = result.get();
QDataStream stream(serialized);
stream.setVersion(QDataStream::Qt_5_1);
auto version = qint32();
stream >> version;
if (version != kVersion) {
return result;
}
auto environment = qint32();
stream >> environment;
switch (environment) {
case qint32(Environment::Test):
result = std::make_unique<Config>(Environment::Test);
break;
case qint32(Environment::Production):
result = std::make_unique<Config>(Environment::Production);
break;
}
if (!(raw = result.get())) {
return result;
}
auto dcOptionsSerialized = QByteArray();
const auto read = [&](auto &field) {
using Type = std::decay_t<decltype(field)>();
if constexpr (std::is_same_v<Type, int>
|| std::is_same_v<Type, rpl::variable<int>>) {
auto value = qint32();
stream >> value;
field = value;
} else if constexpr (std::is_same_v<Type, bool>
|| std::is_same_v<Type, rpl::variable<bool>>) {
auto value = qint32();
stream >> value;
field = (value == 1);
} else if constexpr (std::is_same_v<Type, QByteArray>
|| std::is_same_v<Type, QString>) {
static_assert(false_(field), "Bad read() call.");
}
};
read(dcOptionsSerialized);
read(raw->_fields.chatSizeMax);
read(raw->_fields.megagroupSizeMax);
read(raw->_fields.forwardedCountMax);
read(raw->_fields.onlineUpdatePeriod);
read(raw->_fields.offlineBlurTimeout);
read(raw->_fields.offlineIdleTimeout);
read(raw->_fields.onlineFocusTimeout);
read(raw->_fields.onlineCloudTimeout);
read(raw->_fields.notifyCloudDelay);
read(raw->_fields.notifyDefaultDelay);
read(raw->_fields.savedGifsLimit);
read(raw->_fields.editTimeLimit);
read(raw->_fields.revokeTimeLimit);
read(raw->_fields.revokePrivateTimeLimit);
read(raw->_fields.revokePrivateInbox);
read(raw->_fields.stickersRecentLimit);
read(raw->_fields.stickersFavedLimit);
read(raw->_fields.pinnedDialogsCountMax);
read(raw->_fields.pinnedDialogsInFolderMax);
read(raw->_fields.internalLinksDomain);
read(raw->_fields.channelsReadMediaPeriod);
read(raw->_fields.callReceiveTimeoutMs);
read(raw->_fields.callRingTimeoutMs);
read(raw->_fields.callConnectTimeoutMs);
read(raw->_fields.callPacketTimeoutMs);
read(raw->_fields.webFileDcId);
read(raw->_fields.txtDomainString);
read(raw->_fields.phoneCallsEnabled);
read(raw->_fields.blockedMode);
read(raw->_fields.captionLengthMax);
if (stream.status() != QDataStream::Ok
|| !raw->_dcOptions.constructFromSerialized(dcOptionsSerialized)) {
return nullptr;
}
return result;
}
const ConfigFields &Config::values() const {
return _fields;
}
void Config::apply(const MTPDconfig &data) {
if (mtpIsTrue(data.vtest_mode()) != _dcOptions.isTestMode()) {
LOG(("MTP Error: config with wrong test mode field received!"));
return;
}
DEBUG_LOG(("MTP Info: got config, "
"chat_size_max: %1, "
"date: %2, "
"test_mode: %3, "
"this_dc: %4, "
"dc_options.length: %5"
).arg(data.vchat_size_max().v
).arg(data.vdate().v
).arg(mtpIsTrue(data.vtest_mode())
).arg(data.vthis_dc().v
).arg(data.vdc_options().v.size()));
_fields.chatSizeMax = data.vchat_size_max().v;
_fields.megagroupSizeMax = data.vmegagroup_size_max().v;
_fields.forwardedCountMax = data.vforwarded_count_max().v;
_fields.onlineUpdatePeriod = data.vonline_update_period_ms().v;
_fields.offlineBlurTimeout = data.voffline_blur_timeout_ms().v;
_fields.offlineIdleTimeout = data.voffline_idle_timeout_ms().v;
_fields.onlineCloudTimeout = data.vonline_cloud_timeout_ms().v;
_fields.notifyCloudDelay = data.vnotify_cloud_delay_ms().v;
_fields.notifyDefaultDelay = data.vnotify_default_delay_ms().v;
_fields.savedGifsLimit = data.vsaved_gifs_limit().v;
_fields.editTimeLimit = data.vedit_time_limit().v;
_fields.revokeTimeLimit = data.vrevoke_time_limit().v;
_fields.revokePrivateTimeLimit = data.vrevoke_pm_time_limit().v;
_fields.revokePrivateInbox = data.is_revoke_pm_inbox();
_fields.stickersRecentLimit = data.vstickers_recent_limit().v;
_fields.stickersFavedLimit = data.vstickers_faved_limit().v;
_fields.pinnedDialogsCountMax =
std::max(data.vpinned_dialogs_count_max().v, 1);
_fields.pinnedDialogsInFolderMax =
std::max(data.vpinned_infolder_count_max().v, 1);
_fields.internalLinksDomain = qs(data.vme_url_prefix());
_fields.channelsReadMediaPeriod = data.vchannels_read_media_period().v;
_fields.webFileDcId = data.vwebfile_dc_id().v;
_fields.callReceiveTimeoutMs = data.vcall_receive_timeout_ms().v;
_fields.callRingTimeoutMs = data.vcall_ring_timeout_ms().v;
_fields.callConnectTimeoutMs = data.vcall_connect_timeout_ms().v;
_fields.callPacketTimeoutMs = data.vcall_packet_timeout_ms().v;
_fields.phoneCallsEnabled = data.is_phonecalls_enabled();
_fields.blockedMode = data.is_blocked_mode();
_fields.captionLengthMax = data.vcaption_length_max().v;
if (data.vdc_options().v.empty()) {
LOG(("MTP Error: config with empty dc_options received!"));
} else {
dcOptions().setFromList(data.vdc_options());
}
_updates.fire({});
}
rpl::producer<> Config::updates() const {
return _updates.events();
}
void Config::setChatSizeMax(int value) {
_fields.chatSizeMax = value;
}
void Config::setSavedGifsLimit(int value) {
_fields.savedGifsLimit = value;
}
void Config::setStickersRecentLimit(int value) {
_fields.stickersRecentLimit = value;
}
void Config::setStickersFavedLimit(int value) {
_fields.stickersFavedLimit = value;
}
void Config::setMegagroupSizeMax(int value) {
_fields.megagroupSizeMax = value;
}
void Config::setTxtDomainString(const QString &value) {
_fields.txtDomainString = value;
}
} // namespace MTP

View file

@ -0,0 +1,93 @@
/*
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
*/
#pragma once
#include "mtproto/mtproto_dc_options.h"
namespace MTP {
struct ConfigFields {
int chatSizeMax = 200;
int megagroupSizeMax = 10000;
int forwardedCountMax = 100;
int onlineUpdatePeriod = 120000;
int offlineBlurTimeout = 5000;
int offlineIdleTimeout = 30000;
int onlineFocusTimeout = 1000; // Not from the server config.
int onlineCloudTimeout = 300000;
int notifyCloudDelay = 30000;
int notifyDefaultDelay = 1500;
int savedGifsLimit = 200;
int editTimeLimit = 172800;
int revokeTimeLimit = 172800;
int revokePrivateTimeLimit = 172800;
bool revokePrivateInbox = false;
int stickersRecentLimit = 30;
int stickersFavedLimit = 5;
rpl::variable<int> pinnedDialogsCountMax = 5;
rpl::variable<int> pinnedDialogsInFolderMax = 100;
QString internalLinksDomain = u"https://t.me/"_q;
int channelsReadMediaPeriod = 86400 * 7;
int callReceiveTimeoutMs = 20000;
int callRingTimeoutMs = 90000;
int callConnectTimeoutMs = 30000;
int callPacketTimeoutMs = 10000;
int webFileDcId = 4;
QString txtDomainString;
rpl::variable<bool> phoneCallsEnabled = true;
bool blockedMode = false;
int captionLengthMax = 1024;
};
class Config final {
struct PrivateTag {
};
public:
explicit Config(Environment environment);
Config(const Config &other);
[[nodiscard]] QByteArray serialize() const;
[[nodiscard]] static std::unique_ptr<Config> FromSerialized(
const QByteArray &serialized);
[[nodiscard]] DcOptions &dcOptions() {
return _dcOptions;
}
[[nodiscard]] const DcOptions &dcOptions() const {
return _dcOptions;
}
[[nodiscard]] MTP::Environment environment() const {
return _dcOptions.environment();
}
[[nodiscard]] bool isTestMode() const {
return _dcOptions.isTestMode();
}
void apply(const MTPDconfig &data);
[[nodiscard]] const ConfigFields &values() const;
[[nodiscard]] rpl::producer<> updates() const;
// Set from legacy local stored values.
void setChatSizeMax(int value);
void setSavedGifsLimit(int value);
void setStickersRecentLimit(int value);
void setStickersFavedLimit(int value);
void setMegagroupSizeMax(int value);
void setTxtDomainString(const QString &value);
private:
DcOptions _dcOptions;
ConfigFields _fields;
rpl::event_stream<> _updates;
};
} // namespace MTP

View file

@ -5,13 +5,16 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "mtproto/connection_tcp.h" #include "mtproto/connection_tcp.h"
#include "storage/serialize_common.h" #include "storage/serialize_common.h"
#include <QtCore/QFile>
#include <QtCore/QRegularExpression>
namespace MTP { namespace MTP {
namespace { namespace {
@ -136,10 +139,20 @@ private:
}; };
DcOptions::DcOptions() { DcOptions::DcOptions(Environment environment)
: _environment(environment) {
constructFromBuiltIn(); constructFromBuiltIn();
} }
DcOptions::DcOptions(const DcOptions &other)
: _environment(other._environment)
, _data(other._data)
, _cdnDcIds(other._cdnDcIds)
, _publicKeys(other._publicKeys)
, _cdnPublicKeys(other._cdnPublicKeys)
, _immutable(other._immutable) {
}
DcOptions::~DcOptions() = default; DcOptions::~DcOptions() = default;
bool DcOptions::ValidateSecret(bytes::const_span secret) { bool DcOptions::ValidateSecret(bytes::const_span secret) {
@ -163,13 +176,21 @@ void DcOptions::readBuiltInPublicKeys() {
} }
} }
Environment DcOptions::environment() const {
return _environment;
}
bool DcOptions::isTestMode() const {
return (_environment != Environment::Production);
}
void DcOptions::constructFromBuiltIn() { void DcOptions::constructFromBuiltIn() {
WriteLocker lock(this); WriteLocker lock(this);
_data.clear(); _data.clear();
readBuiltInPublicKeys(); readBuiltInPublicKeys();
const auto list = cTestMode() const auto list = isTestMode()
? gsl::make_span(kBuiltInDcsTest) ? gsl::make_span(kBuiltInDcsTest)
: gsl::make_span(kBuiltInDcs).subspan(0); : gsl::make_span(kBuiltInDcs).subspan(0);
for (const auto &entry : list) { for (const auto &entry : list) {
@ -181,7 +202,7 @@ void DcOptions::constructFromBuiltIn() {
).arg(entry.port)); ).arg(entry.port));
} }
const auto listv6 = cTestMode() const auto listv6 = isTestMode()
? gsl::make_span(kBuiltInDcsIPv6Test) ? gsl::make_span(kBuiltInDcsIPv6Test)
: gsl::make_span(kBuiltInDcsIPv6).subspan(0); : gsl::make_span(kBuiltInDcsIPv6).subspan(0);
for (const auto &entry : listv6) { for (const auto &entry : listv6) {
@ -204,7 +225,7 @@ void DcOptions::processFromList(
auto data = [&] { auto data = [&] {
if (overwrite) { if (overwrite) {
return std::map<DcId, std::vector<Endpoint>>(); return base::flat_map<DcId, std::vector<Endpoint>>();
} }
ReadLocker lock(this); ReadLocker lock(this);
return _data; return _data;
@ -313,7 +334,7 @@ bool DcOptions::applyOneGuarded(
} }
bool DcOptions::ApplyOneOption( bool DcOptions::ApplyOneOption(
std::map<DcId, std::vector<Endpoint>> &data, base::flat_map<DcId, std::vector<Endpoint>> &data,
DcId dcId, DcId dcId,
Flags flags, Flags flags,
const std::string &ip, const std::string &ip,
@ -336,8 +357,8 @@ bool DcOptions::ApplyOneOption(
} }
std::vector<DcId> DcOptions::CountOptionsDifference( std::vector<DcId> DcOptions::CountOptionsDifference(
const std::map<DcId, std::vector<Endpoint>> &a, const base::flat_map<DcId, std::vector<Endpoint>> &a,
const std::map<DcId, std::vector<Endpoint>> &b) { const base::flat_map<DcId, std::vector<Endpoint>> &b) {
auto result = std::vector<DcId>(); auto result = std::vector<DcId>();
const auto find = []( const auto find = [](
const std::vector<Endpoint> &where, const std::vector<Endpoint> &where,
@ -389,7 +410,7 @@ std::vector<DcId> DcOptions::CountOptionsDifference(
QByteArray DcOptions::serialize() const { QByteArray DcOptions::serialize() const {
if (_immutable) { if (_immutable) {
// Don't write the overriden options to our settings. // Don't write the overriden options to our settings.
return DcOptions().serialize(); return DcOptions(_environment).serialize();
} }
ReadLocker lock(this); ReadLocker lock(this);
@ -477,7 +498,7 @@ QByteArray DcOptions::serialize() const {
return result; return result;
} }
void DcOptions::constructFromSerialized(const QByteArray &serialized) { bool DcOptions::constructFromSerialized(const QByteArray &serialized) {
QDataStream stream(serialized); QDataStream stream(serialized);
stream.setVersion(QDataStream::Qt_5_1); stream.setVersion(QDataStream::Qt_5_1);
@ -493,7 +514,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
} }
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("MTP Error: Bad data for DcOptions::constructFromSerialized()")); LOG(("MTP Error: Bad data for DcOptions::constructFromSerialized()"));
return; return false;
} }
WriteLocker lock(this); WriteLocker lock(this);
@ -506,7 +527,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
constexpr auto kMaxIpSize = 45; constexpr auto kMaxIpSize = 45;
if (ipSize <= 0 || ipSize > kMaxIpSize) { if (ipSize <= 0 || ipSize > kMaxIpSize) {
LOG(("MTP Error: Bad data inside DcOptions::constructFromSerialized()")); LOG(("MTP Error: Bad data inside DcOptions::constructFromSerialized()"));
return; return false;
} }
auto ip = std::string(ipSize, ' '); auto ip = std::string(ipSize, ' ');
@ -519,7 +540,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
stream >> secretSize; stream >> secretSize;
if (secretSize < 0 || secretSize > kMaxSecretSize) { if (secretSize < 0 || secretSize > kMaxSecretSize) {
LOG(("MTP Error: Bad data inside DcOptions::constructFromSerialized()")); LOG(("MTP Error: Bad data inside DcOptions::constructFromSerialized()"));
return; return false;
} else if (secretSize > 0) { } else if (secretSize > 0) {
secret.resize(secretSize); secret.resize(secretSize);
stream.readRawData( stream.readRawData(
@ -530,7 +551,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("MTP Error: Bad data inside DcOptions::constructFromSerialized()")); LOG(("MTP Error: Bad data inside DcOptions::constructFromSerialized()"));
return; return false;
} }
applyOneGuarded( applyOneGuarded(
@ -547,7 +568,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
stream >> count; stream >> count;
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("MTP Error: Bad data for CDN config in DcOptions::constructFromSerialized()")); LOG(("MTP Error: Bad data for CDN config in DcOptions::constructFromSerialized()"));
return; return false;
} }
for (auto i = 0; i != count; ++i) { for (auto i = 0; i != count; ++i) {
@ -556,7 +577,7 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
stream >> dcId >> Serialize::bytes(n) >> Serialize::bytes(e); stream >> dcId >> Serialize::bytes(n) >> Serialize::bytes(e);
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
LOG(("MTP Error: Bad data for CDN config inside DcOptions::constructFromSerialized()")); LOG(("MTP Error: Bad data for CDN config inside DcOptions::constructFromSerialized()"));
return; return false;
} }
auto key = RSAPublicKey(n, e); auto key = RSAPublicKey(n, e);
@ -564,9 +585,11 @@ void DcOptions::constructFromSerialized(const QByteArray &serialized) {
_cdnPublicKeys[dcId].emplace(key.fingerprint(), std::move(key)); _cdnPublicKeys[dcId].emplace(key.fingerprint(), std::move(key));
} else { } else {
LOG(("MTP Error: Could not read valid CDN public key.")); LOG(("MTP Error: Could not read valid CDN public key."));
return false;
} }
} }
} }
return true;
} }
rpl::producer<DcId> DcOptions::changed() const { rpl::producer<DcId> DcOptions::changed() const {
@ -640,7 +663,8 @@ bool DcOptions::hasCDNKeysForDc(DcId dcId) const {
RSAPublicKey DcOptions::getDcRSAKey( RSAPublicKey DcOptions::getDcRSAKey(
DcId dcId, DcId dcId,
const QVector<MTPlong> &fingerprints) const { const QVector<MTPlong> &fingerprints) const {
const auto findKey = [&](const std::map<uint64, RSAPublicKey> &keys) { const auto findKey = [&](
const base::flat_map<uint64, RSAPublicKey> &keys) {
for (const auto &fingerprint : fingerprints) { for (const auto &fingerprint : fingerprints) {
const auto it = keys.find(static_cast<uint64>(fingerprint.v)); const auto it = keys.find(static_cast<uint64>(fingerprint.v));
if (it != keys.cend()) { if (it != keys.cend()) {

View file

@ -27,6 +27,12 @@ enum class DcType {
MediaCluster, MediaCluster,
Cdn, Cdn,
}; };
enum class Environment : uchar {
Production,
Test,
};
class DcOptions { class DcOptions {
public: public:
using Flag = MTPDdcOption::Flag; using Flag = MTPDdcOption::Flag;
@ -53,13 +59,17 @@ public:
}; };
DcOptions(); explicit DcOptions(Environment environment);
DcOptions(const DcOptions &other);
~DcOptions(); ~DcOptions();
[[nodiscard]] static bool ValidateSecret(bytes::const_span secret); [[nodiscard]] static bool ValidateSecret(bytes::const_span secret);
[[nodiscard]] Environment environment() const;
[[nodiscard]] bool isTestMode() const;
// construct methods don't notify "changed" subscribers. // construct methods don't notify "changed" subscribers.
void constructFromSerialized(const QByteArray &serialized); bool constructFromSerialized(const QByteArray &serialized);
void constructFromBuiltIn(); void constructFromBuiltIn();
void constructAddOne( void constructAddOne(
int id, int id,
@ -114,15 +124,15 @@ private:
int port, int port,
const bytes::vector &secret); const bytes::vector &secret);
static bool ApplyOneOption( static bool ApplyOneOption(
std::map<DcId, std::vector<Endpoint>> &data, base::flat_map<DcId, std::vector<Endpoint>> &data,
DcId dcId, DcId dcId,
Flags flags, Flags flags,
const std::string &ip, const std::string &ip,
int port, int port,
const bytes::vector &secret); const bytes::vector &secret);
static std::vector<DcId> CountOptionsDifference( static std::vector<DcId> CountOptionsDifference(
const std::map<DcId, std::vector<Endpoint>> &a, const base::flat_map<DcId, std::vector<Endpoint>> &a,
const std::map<DcId, std::vector<Endpoint>> &b); const base::flat_map<DcId, std::vector<Endpoint>> &b);
static void FilterIfHasWithFlag(Variants &variants, Flag flag); static void FilterIfHasWithFlag(Variants &variants, Flag flag);
[[nodiscard]] bool hasMediaOnlyOptionsFor(DcId dcId) const; [[nodiscard]] bool hasMediaOnlyOptionsFor(DcId dcId) const;
@ -138,10 +148,13 @@ private:
class ReadLocker; class ReadLocker;
friend class ReadLocker; friend class ReadLocker;
std::map<DcId, std::vector<Endpoint>> _data; const Environment _environment = Environment();
std::set<DcId> _cdnDcIds; base::flat_map<DcId, std::vector<Endpoint>> _data;
std::map<uint64, details::RSAPublicKey> _publicKeys; base::flat_set<DcId> _cdnDcIds;
std::map<DcId, std::map<uint64, details::RSAPublicKey>> _cdnPublicKeys; base::flat_map<uint64, details::RSAPublicKey> _publicKeys;
base::flat_map<
DcId,
base::flat_map<uint64, details::RSAPublicKey>> _cdnPublicKeys;
mutable QReadWriteLock _useThroughLockers; mutable QReadWriteLock _useThroughLockers;
rpl::event_stream<DcId> _changed; rpl::event_stream<DcId> _changed;

View file

@ -10,10 +10,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtNetwork/QNetworkProxy> #include <QtNetwork/QNetworkProxy>
#include <QtNetwork/QTcpSocket> #include <QtNetwork/QTcpSocket>
#include <range/v3/all.hpp>
#include <rpl/rpl.h> #include <rpl/rpl.h>
#include <crl/crl.h> #include <crl/crl.h>
#include "base/bytes.h" #include "base/bytes.h"
#include "base/flat_map.h"
#include "base/flat_set.h"
#include "logs.h" #include "logs.h"
#include "scheme.h" #include "scheme.h"

View file

@ -196,8 +196,8 @@ public:
: _instance(instance) { : _instance(instance) {
} }
[[nodiscard]] not_null<Instance*> instance() const { [[nodiscard]] Instance &instance() const {
return _instance; return *_instance;
} }
template <typename Request> template <typename Request>
@ -247,7 +247,7 @@ public:
} }
mtpRequestId send() { mtpRequestId send() {
const auto id = sender()->instance()->send( const auto id = sender()->_instance->send(
_request, _request,
takeOnDone(), takeOnDone(),
takeOnFail(), takeOnFail(),
@ -376,7 +376,7 @@ private:
}; };
template <typename Request> template <typename Request>
friend class SpecialRequestBuilder; friend class SpecificRequestBuilder;
friend class RequestBuilder; friend class RequestBuilder;
friend class RequestWrap; friend class RequestWrap;
friend class SentRequestWrap; friend class SentRequestWrap;

View file

@ -195,7 +195,7 @@ void Session::watchDcKeyChanges() {
} }
void Session::watchDcOptionsChanges() { void Session::watchDcOptionsChanges() {
_instance->dcOptions()->changed( _instance->dcOptions().changed(
) | rpl::filter([=](DcId dcId) { ) | rpl::filter([=](DcId dcId) {
return (BareDcId(_shiftedDcId) == dcId) && (_private != nullptr); return (BareDcId(_shiftedDcId) == dcId) && (_private != nullptr);
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
@ -204,8 +204,8 @@ void Session::watchDcOptionsChanges() {
}); });
}, _lifetime); }, _lifetime);
if (_instance->dcOptions()->dcType(_shiftedDcId) == DcType::Cdn) { if (_instance->dcOptions().dcType(_shiftedDcId) == DcType::Cdn) {
_instance->dcOptions()->cdnConfigChanged( _instance->dcOptions().cdnConfigChanged(
) | rpl::filter([=] { ) | rpl::filter([=] {
return (_private != nullptr); return (_private != nullptr);
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {

View file

@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/session.h" #include "mtproto/session.h"
#include "mtproto/mtproto_rpc_sender.h" #include "mtproto/mtproto_rpc_sender.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/connection_abstract.h" #include "mtproto/connection_abstract.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"
#include "base/qthelp_url.h" #include "base/qthelp_url.h"
@ -117,7 +117,7 @@ SessionPrivate::SessionPrivate(
: QObject(nullptr) : QObject(nullptr)
, _instance(instance) , _instance(instance)
, _shiftedDcId(shiftedDcId) , _shiftedDcId(shiftedDcId)
, _realDcType(_instance->dcOptions()->dcType(_shiftedDcId)) , _realDcType(_instance->dcOptions().dcType(_shiftedDcId))
, _currentDcType(_realDcType) , _currentDcType(_realDcType)
, _state(DisconnectedState) , _state(DisconnectedState)
, _retryTimer(thread, [=] { retryByTimer(); }) , _retryTimer(thread, [=] { retryByTimer(); })
@ -203,7 +203,7 @@ int16 SessionPrivate::getProtocolDcId() const {
const auto simpleDcId = isTemporaryDcId(dcId) const auto simpleDcId = isTemporaryDcId(dcId)
? getRealIdFromTemporaryDcId(dcId) ? getRealIdFromTemporaryDcId(dcId)
: dcId; : dcId;
const auto testedDcId = cTestMode() const auto testedDcId = _instance->isTestMode()
? (kTestModeDcIdShift + simpleDcId) ? (kTestModeDcIdShift + simpleDcId)
: simpleDcId; : simpleDcId;
return (_currentDcType == DcType::MediaCluster) return (_currentDcType == DcType::MediaCluster)
@ -374,7 +374,7 @@ uint32 SessionPrivate::nextRequestSeqNumber(bool needAck) {
} }
bool SessionPrivate::realDcTypeChanged() { bool SessionPrivate::realDcTypeChanged() {
const auto now = _instance->dcOptions()->dcType(_shiftedDcId); const auto now = _instance->dcOptions().dcType(_shiftedDcId);
if (_realDcType == now) { if (_realDcType == now) {
return false; return false;
} }
@ -936,7 +936,7 @@ void SessionPrivate::connectToServer(bool afterConfig) {
_currentDcType = tryAcquireKeyCreation(); _currentDcType = tryAcquireKeyCreation();
if (_currentDcType == DcType::Cdn && !_instance->isKeysDestroyer()) { if (_currentDcType == DcType::Cdn && !_instance->isKeysDestroyer()) {
if (!_instance->dcOptions()->hasCDNKeysForDc(bareDc)) { if (!_instance->dcOptions().hasCDNKeysForDc(bareDc)) {
requestCDNConfig(); requestCDNConfig();
return; return;
} }
@ -947,7 +947,7 @@ void SessionPrivate::connectToServer(bool afterConfig) {
} else { } else {
using Variants = DcOptions::Variants; using Variants = DcOptions::Variants;
const auto special = (_currentDcType == DcType::Temporary); const auto special = (_currentDcType == DcType::Temporary);
const auto variants = _instance->dcOptions()->lookup( const auto variants = _instance->dcOptions().lookup(
bareDc, bareDc,
_currentDcType, _currentDcType,
_options->proxy.type != ProxyData::Type::None); _options->proxy.type != ProxyData::Type::None);
@ -2366,7 +2366,7 @@ void SessionPrivate::applyAuthKey(AuthKeyPtr &&encryptionKey) {
BareDcId(_shiftedDcId), BareDcId(_shiftedDcId),
getProtocolDcId(), getProtocolDcId(),
_connection.get(), _connection.get(),
_instance->dcOptions()); &_instance->dcOptions());
} else { } else {
DEBUG_LOG(("AuthKey Info: No key in updateAuthKey(), " DEBUG_LOG(("AuthKey Info: No key in updateAuthKey(), "
"but someone is creating already, waiting.")); "but someone is creating already, waiting."));

View file

@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/details/mtproto_received_ids_manager.h" #include "mtproto/details/mtproto_received_ids_manager.h"
#include "mtproto/details/mtproto_serialized_request.h" #include "mtproto/details/mtproto_serialized_request.h"
#include "mtproto/mtproto_auth_key.h" #include "mtproto/mtproto_auth_key.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/connection_abstract.h" #include "mtproto/connection_abstract.h"
#include "mtproto/facade.h" #include "mtproto/facade.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"

View file

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/special_config_request.h" #include "mtproto/special_config_request.h"
#include "mtproto/details/mtproto_rsa_public_key.h" #include "mtproto/details/mtproto_rsa_public_key.h"
#include "mtproto/dc_options.h" #include "mtproto/mtproto_dc_options.h"
#include "mtproto/mtproto_auth_key.h" #include "mtproto/mtproto_auth_key.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "base/openssl_help.h" #include "base/openssl_help.h"
@ -189,9 +189,11 @@ SpecialConfigRequest::SpecialConfigRequest(
int port, int port,
bytes::const_span secret)> callback, bytes::const_span secret)> callback,
Fn<void()> timeDoneCallback, Fn<void()> timeDoneCallback,
const QString &domainString,
const QString &phone) const QString &phone)
: _callback(std::move(callback)) : _callback(std::move(callback))
, _timeDoneCallback(std::move(timeDoneCallback)) , _timeDoneCallback(std::move(timeDoneCallback))
, _domainString(domainString)
, _phone(phone) { , _phone(phone) {
Expects((_callback == nullptr) != (_timeDoneCallback == nullptr)); Expects((_callback == nullptr) != (_timeDoneCallback == nullptr));
@ -251,12 +253,19 @@ SpecialConfigRequest::SpecialConfigRequest(
const std::string &ip, const std::string &ip,
int port, int port,
bytes::const_span secret)> callback, bytes::const_span secret)> callback,
const QString &domainString,
const QString &phone) const QString &phone)
: SpecialConfigRequest(std::move(callback), nullptr, phone) { : SpecialConfigRequest(std::move(callback), nullptr, domainString, phone) {
} }
SpecialConfigRequest::SpecialConfigRequest(Fn<void()> timeDoneCallback) SpecialConfigRequest::SpecialConfigRequest(
: SpecialConfigRequest(nullptr, std::move(timeDoneCallback), QString()) { Fn<void()> timeDoneCallback,
const QString &domainString)
: SpecialConfigRequest(
nullptr,
std::move(timeDoneCallback),
domainString,
QString()) {
} }
void SpecialConfigRequest::sendNextRequest() { void SpecialConfigRequest::sendNextRequest() {
@ -283,7 +292,7 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) {
url.setHost(attempt.data); url.setHost(attempt.data);
url.setPath(qsl("/dns-query")); url.setPath(qsl("/dns-query"));
url.setQuery(qsl("name=%1&type=16&random_padding=%2" url.setQuery(qsl("name=%1&type=16&random_padding=%2"
).arg(Global::TxtDomainString() ).arg(_domainString
).arg(GenerateDnsRandomPadding())); ).arg(GenerateDnsRandomPadding()));
request.setRawHeader("accept", "application/dns-json"); request.setRawHeader("accept", "application/dns-json");
} break; } break;
@ -291,7 +300,7 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) {
url.setHost(attempt.data); url.setHost(attempt.data);
url.setPath(qsl("/resolve")); url.setPath(qsl("/resolve"));
url.setQuery(qsl("name=%1&type=ANY&random_padding=%2" url.setQuery(qsl("name=%1&type=ANY&random_padding=%2"
).arg(Global::TxtDomainString() ).arg(_domainString
).arg(GenerateDnsRandomPadding())); ).arg(GenerateDnsRandomPadding()));
if (!attempt.host.isEmpty()) { if (!attempt.host.isEmpty()) {
const auto host = attempt.host + ".google.com"; const auto host = attempt.host + ".google.com";

View file

@ -25,8 +25,11 @@ public:
const std::string &ip, const std::string &ip,
int port, int port,
bytes::const_span secret)> callback, bytes::const_span secret)> callback,
const QString &domainString,
const QString &phone); const QString &phone);
explicit SpecialConfigRequest(Fn<void()> timeDoneCallback); SpecialConfigRequest(
Fn<void()> timeDoneCallback,
const QString &domainString);
private: private:
enum class Type { enum class Type {
@ -49,6 +52,7 @@ private:
int port, int port,
bytes::const_span secret)> callback, bytes::const_span secret)> callback,
Fn<void()> timeDoneCallback, Fn<void()> timeDoneCallback,
const QString &domainString,
const QString &phone); const QString &phone);
void sendNextRequest(); void sendNextRequest();
@ -65,6 +69,7 @@ private:
int port, int port,
bytes::const_span secret)> _callback; bytes::const_span secret)> _callback;
Fn<void()> _timeDoneCallback; Fn<void()> _timeDoneCallback;
QString _domainString;
QString _phone; QString _phone;
MTPhelp_ConfigSimple _simpleConfig; MTPhelp_ConfigSimple _simpleConfig;

View file

@ -624,7 +624,7 @@ FormController::FormController(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
const FormRequest &request) const FormRequest &request)
: _controller(controller) : _controller(controller)
, _api(_controller->session().mtp()) , _api(&_controller->session().mtp())
, _request(PreprocessRequest(request)) , _request(PreprocessRequest(request))
, _shortPollTimer([=] { reloadPassword(); }) , _shortPollTimer([=] { reloadPassword(); })
, _view(std::make_unique<PanelController>(this)) { , _view(std::make_unique<PanelController>(this)) {

Some files were not shown because too many files have changed in this diff Show more