/* 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 "main/main_app_config.h" #include "apiwrap.h" #include "base/call_delayed.h" #include "main/main_account.h" #include "ui/chat/chat_style.h" namespace Main { namespace { constexpr auto kRefreshTimeout = 3600 * crl::time(1000); } // namespace AppConfig::AppConfig(not_null account) : _account(account) { account->sessionChanges( ) | rpl::filter([=](Session *session) { return (session != nullptr); }) | rpl::start_with_next([=] { refresh(); }, _lifetime); } AppConfig::~AppConfig() = default; void AppConfig::start() { _account->mtpMainSessionValue( ) | rpl::start_with_next([=](not_null instance) { _api.emplace(instance); refresh(); }, _lifetime); } void AppConfig::refresh() { if (_requestId || !_api) { return; } _requestId = _api->request(MTPhelp_GetAppConfig( MTP_int(_hash) )).done([=](const MTPhelp_AppConfig &result) { _requestId = 0; refreshDelayed(); result.match([&](const MTPDhelp_appConfig &data) { _hash = data.vhash().v; const auto &config = data.vconfig(); if (config.type() != mtpc_jsonObject) { LOG(("API Error: Unexpected config type.")); return; } _data.clear(); for (const auto &element : config.c_jsonObject().vvalue().v) { element.match([&](const MTPDjsonObjectValue &data) { _data.emplace_or_assign(qs(data.vkey()), data.vvalue()); }); } DEBUG_LOG(("getAppConfig result handled.")); _refreshed.fire({}); }, [](const MTPDhelp_appConfigNotModified &) {}); }).fail([=] { _requestId = 0; refreshDelayed(); }).send(); } void AppConfig::refreshDelayed() { base::call_delayed(kRefreshTimeout, _account, [=] { refresh(); }); } rpl::producer<> AppConfig::refreshed() const { return _refreshed.events(); } rpl::producer<> AppConfig::value() const { return _refreshed.events_starting_with({}); } template auto AppConfig::getValue(const QString &key, Extractor &&extractor) const { const auto i = _data.find(key); return extractor((i != end(_data)) ? i->second : MTPJSONValue(MTP_jsonNull())); } bool AppConfig::getBool(const QString &key, bool fallback) const { return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonBool &data) { return mtpIsTrue(data.vvalue()); }, [&](const auto &data) { return fallback; }); }); } double AppConfig::getDouble(const QString &key, double fallback) const { return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonNumber &data) { return data.vvalue().v; }, [&](const auto &data) { return fallback; }); }); } QString AppConfig::getString( const QString &key, const QString &fallback) const { return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonString &data) { return qs(data.vvalue()); }, [&](const auto &data) { return fallback; }); }); } std::vector AppConfig::getStringArray( const QString &key, std::vector &&fallback) const { return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonArray &data) { auto result = std::vector(); result.reserve(data.vvalue().v.size()); for (const auto &entry : data.vvalue().v) { if (entry.type() != mtpc_jsonString) { return std::move(fallback); } result.push_back(qs(entry.c_jsonString().vvalue())); } return result; }, [&](const auto &data) { return std::move(fallback); }); }); } std::vector> AppConfig::getStringMapArray( const QString &key, std::vector> &&fallback) const { return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonArray &data) { auto result = std::vector>(); result.reserve(data.vvalue().v.size()); for (const auto &entry : data.vvalue().v) { if (entry.type() != mtpc_jsonObject) { return std::move(fallback); } auto element = std::map(); for (const auto &field : entry.c_jsonObject().vvalue().v) { const auto &data = field.c_jsonObjectValue(); if (data.vvalue().type() != mtpc_jsonString) { return std::move(fallback); } element.emplace( qs(data.vkey()), qs(data.vvalue().c_jsonString().vvalue())); } result.push_back(std::move(element)); } return result; }, [&](const auto &data) { return std::move(fallback); }); }); } std::vector AppConfig::getIntArray( const QString &key, std::vector &&fallback) const { return getValue(key, [&](const MTPJSONValue &value) { return value.match([&](const MTPDjsonArray &data) { auto result = std::vector(); result.reserve(data.vvalue().v.size()); for (const auto &entry : data.vvalue().v) { if (entry.type() != mtpc_jsonNumber) { return std::move(fallback); } result.push_back( int(base::SafeRound(entry.c_jsonNumber().vvalue().v))); } return result; }, [&](const auto &data) { return std::move(fallback); }); }); } bool AppConfig::suggestionCurrent(const QString &key) const { return !_dismissedSuggestions.contains(key) && ranges::contains( get>( u"pending_suggestions"_q, std::vector()), key); } rpl::producer<> AppConfig::suggestionRequested(const QString &key) const { return value( ) | rpl::filter([=] { return suggestionCurrent(key); }); } void AppConfig::dismissSuggestion(const QString &key) { Expects(_api.has_value()); if (!_dismissedSuggestions.emplace(key).second) { return; } _api->request(MTPhelp_DismissSuggestion( MTP_inputPeerEmpty(), MTP_string(key) )).send(); } bool AppConfig::newRequirePremiumFree() const { return get( u"new_noncontact_peers_require_premium_without_ownpremium"_q, false); } } // namespace Main