mtproto_config.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "mtproto/mtproto_config.h"
  8. #include "storage/serialize_common.h"
  9. #include "mtproto/type_utils.h"
  10. #include "logs.h"
  11. namespace MTP {
  12. namespace {
  13. constexpr auto kVersion = 1;
  14. [[nodiscard]] QString ConfigDefaultReactionEmoji() {
  15. static const auto result = QString::fromUtf8("\xf0\x9f\x91\x8d");
  16. return result;
  17. }
  18. } // namespace
  19. ConfigFields::ConfigFields(Environment environment)
  20. : webFileDcId(environment == Environment::Test ? 2 : 4)
  21. , txtDomainString(environment == Environment::Test
  22. ? u"tapv3.stel.com"_q
  23. : u"apv3.stel.com"_q)
  24. , reactionDefaultEmoji(ConfigDefaultReactionEmoji())
  25. , gifSearchUsername(environment == Environment::Test
  26. ? u"izgifbot"_q
  27. : u"gif"_q)
  28. , venueSearchUsername(environment == Environment::Test
  29. ? u"foursquarebot"_q
  30. : u"foursquare"_q) {
  31. }
  32. Config::Config(Environment environment)
  33. : _dcOptions(environment)
  34. , _fields(environment) {
  35. }
  36. Config::Config(const Config &other)
  37. : _dcOptions(other.dcOptions())
  38. , _fields(other._fields) {
  39. }
  40. QByteArray Config::serialize() const {
  41. auto options = _dcOptions.serialize();
  42. auto size = sizeof(qint32) * 2 // version + environment
  43. + Serialize::bytearraySize(options)
  44. + 19 * sizeof(qint32)
  45. + Serialize::stringSize(_fields.internalLinksDomain)
  46. + 6 * sizeof(qint32)
  47. + Serialize::stringSize(_fields.txtDomainString)
  48. + 3 * sizeof(qint32)
  49. + Serialize::stringSize(_fields.reactionDefaultEmoji)
  50. + sizeof(quint64)
  51. + sizeof(qint32)
  52. + Serialize::stringSize(_fields.gifSearchUsername)
  53. + Serialize::stringSize(_fields.venueSearchUsername);
  54. auto result = QByteArray();
  55. result.reserve(size);
  56. {
  57. QDataStream stream(&result, QIODevice::WriteOnly);
  58. stream.setVersion(QDataStream::Qt_5_1);
  59. stream
  60. << qint32(kVersion)
  61. << qint32(_dcOptions.isTestMode()
  62. ? Environment::Test
  63. : Environment::Production)
  64. << options
  65. << qint32(_fields.chatSizeMax)
  66. << qint32(_fields.megagroupSizeMax)
  67. << qint32(_fields.forwardedCountMax)
  68. << qint32(_fields.onlineUpdatePeriod)
  69. << qint32(_fields.offlineBlurTimeout)
  70. << qint32(_fields.offlineIdleTimeout)
  71. << qint32(_fields.onlineFocusTimeout)
  72. << qint32(_fields.onlineCloudTimeout)
  73. << qint32(_fields.notifyCloudDelay)
  74. << qint32(_fields.notifyDefaultDelay)
  75. << qint32(0) // legacy savedGifsLimit
  76. << qint32(_fields.editTimeLimit)
  77. << qint32(_fields.revokeTimeLimit)
  78. << qint32(_fields.revokePrivateTimeLimit)
  79. << qint32(_fields.revokePrivateInbox ? 1 : 0)
  80. << qint32(_fields.stickersRecentLimit)
  81. << qint32(0) // legacy stickersFavedLimit
  82. << qint32(0) // legacy pinnedDialogsCountMax
  83. << qint32(0) // legacy pinnedDialogsInFolderMax
  84. << _fields.internalLinksDomain
  85. << qint32(_fields.channelsReadMediaPeriod)
  86. << qint32(_fields.callReceiveTimeoutMs)
  87. << qint32(_fields.callRingTimeoutMs)
  88. << qint32(_fields.callConnectTimeoutMs)
  89. << qint32(_fields.callPacketTimeoutMs)
  90. << qint32(_fields.webFileDcId)
  91. << _fields.txtDomainString
  92. << qint32(1) // legacy phoneCallsEnabled
  93. << qint32(_fields.blockedMode ? 1 : 0)
  94. << qint32(_fields.captionLengthMax)
  95. << _fields.reactionDefaultEmoji
  96. << quint64(_fields.reactionDefaultCustom)
  97. << qint32(_fields.ratingDecay)
  98. << _fields.gifSearchUsername
  99. << _fields.venueSearchUsername;
  100. }
  101. return result;
  102. }
  103. std::unique_ptr<Config> Config::FromSerialized(const QByteArray &serialized) {
  104. auto result = std::unique_ptr<Config>();
  105. auto raw = result.get();
  106. QDataStream stream(serialized);
  107. stream.setVersion(QDataStream::Qt_5_1);
  108. auto version = qint32();
  109. stream >> version;
  110. if (version != kVersion) {
  111. return result;
  112. }
  113. auto environment = qint32();
  114. stream >> environment;
  115. switch (environment) {
  116. case qint32(Environment::Test):
  117. result = std::make_unique<Config>(Environment::Test);
  118. break;
  119. case qint32(Environment::Production):
  120. result = std::make_unique<Config>(Environment::Production);
  121. break;
  122. }
  123. if (!(raw = result.get())) {
  124. return result;
  125. }
  126. auto dcOptionsSerialized = QByteArray();
  127. auto legacySavedGifsLimit = int();
  128. auto legacyStickersFavedLimit = int();
  129. auto legacyPinnedDialogsCountMax = 0;
  130. auto legacyPinnedDialogsInFolderMax = 0;
  131. auto legacyPhoneCallsEnabled = rpl::variable<bool>();
  132. const auto read = [&](auto &field) {
  133. using Type = std::remove_reference_t<decltype(field)>;
  134. if constexpr (std::is_same_v<Type, int>
  135. || std::is_same_v<Type, rpl::variable<int>>) {
  136. auto value = qint32();
  137. stream >> value;
  138. field = value;
  139. } else if constexpr (std::is_same_v<Type, uint64>) {
  140. auto value = quint64();
  141. stream >> value;
  142. field = value;
  143. } else if constexpr (std::is_same_v<Type, bool>
  144. || std::is_same_v<Type, rpl::variable<bool>>) {
  145. auto value = qint32();
  146. stream >> value;
  147. field = (value == 1);
  148. } else if constexpr (std::is_same_v<Type, QByteArray>
  149. || std::is_same_v<Type, QString>) {
  150. stream >> field;
  151. } else {
  152. static_assert(false_(field), "Bad read() call.");
  153. }
  154. };
  155. read(dcOptionsSerialized);
  156. read(raw->_fields.chatSizeMax);
  157. read(raw->_fields.megagroupSizeMax);
  158. read(raw->_fields.forwardedCountMax);
  159. read(raw->_fields.onlineUpdatePeriod);
  160. read(raw->_fields.offlineBlurTimeout);
  161. read(raw->_fields.offlineIdleTimeout);
  162. read(raw->_fields.onlineFocusTimeout);
  163. read(raw->_fields.onlineCloudTimeout);
  164. read(raw->_fields.notifyCloudDelay);
  165. read(raw->_fields.notifyDefaultDelay);
  166. read(legacySavedGifsLimit);
  167. read(raw->_fields.editTimeLimit);
  168. read(raw->_fields.revokeTimeLimit);
  169. read(raw->_fields.revokePrivateTimeLimit);
  170. read(raw->_fields.revokePrivateInbox);
  171. read(raw->_fields.stickersRecentLimit);
  172. read(legacyStickersFavedLimit);
  173. read(legacyPinnedDialogsCountMax);
  174. read(legacyPinnedDialogsInFolderMax);
  175. read(raw->_fields.internalLinksDomain);
  176. read(raw->_fields.channelsReadMediaPeriod);
  177. read(raw->_fields.callReceiveTimeoutMs);
  178. read(raw->_fields.callRingTimeoutMs);
  179. read(raw->_fields.callConnectTimeoutMs);
  180. read(raw->_fields.callPacketTimeoutMs);
  181. read(raw->_fields.webFileDcId);
  182. read(raw->_fields.txtDomainString);
  183. read(legacyPhoneCallsEnabled);
  184. read(raw->_fields.blockedMode);
  185. read(raw->_fields.captionLengthMax);
  186. if (!stream.atEnd()) {
  187. read(raw->_fields.reactionDefaultEmoji);
  188. read(raw->_fields.reactionDefaultCustom);
  189. }
  190. if (!stream.atEnd()) {
  191. read(raw->_fields.ratingDecay);
  192. }
  193. if (!stream.atEnd()) {
  194. read(raw->_fields.gifSearchUsername);
  195. read(raw->_fields.venueSearchUsername);
  196. }
  197. if (stream.status() != QDataStream::Ok
  198. || !raw->_dcOptions.constructFromSerialized(dcOptionsSerialized)) {
  199. return nullptr;
  200. }
  201. return result;
  202. }
  203. const ConfigFields &Config::values() const {
  204. return _fields;
  205. }
  206. void Config::apply(const MTPDconfig &data) {
  207. if (mtpIsTrue(data.vtest_mode()) != _dcOptions.isTestMode()) {
  208. LOG(("MTP Error: config with wrong test mode field received!"));
  209. return;
  210. }
  211. DEBUG_LOG(("MTP Info: got config, "
  212. "chat_size_max: %1, "
  213. "date: %2, "
  214. "test_mode: %3, "
  215. "this_dc: %4, "
  216. "dc_options.length: %5"
  217. ).arg(data.vchat_size_max().v
  218. ).arg(data.vdate().v
  219. ).arg(mtpIsTrue(data.vtest_mode())
  220. ).arg(data.vthis_dc().v
  221. ).arg(data.vdc_options().v.size()));
  222. _fields.chatSizeMax = data.vchat_size_max().v;
  223. _fields.megagroupSizeMax = data.vmegagroup_size_max().v;
  224. _fields.forwardedCountMax = data.vforwarded_count_max().v;
  225. _fields.onlineUpdatePeriod = data.vonline_update_period_ms().v;
  226. _fields.offlineBlurTimeout = data.voffline_blur_timeout_ms().v;
  227. _fields.offlineIdleTimeout = data.voffline_idle_timeout_ms().v;
  228. _fields.onlineCloudTimeout = data.vonline_cloud_timeout_ms().v;
  229. _fields.notifyCloudDelay = data.vnotify_cloud_delay_ms().v;
  230. _fields.notifyDefaultDelay = data.vnotify_default_delay_ms().v;
  231. _fields.editTimeLimit = data.vedit_time_limit().v;
  232. _fields.revokeTimeLimit = data.vrevoke_time_limit().v;
  233. _fields.revokePrivateTimeLimit = data.vrevoke_pm_time_limit().v;
  234. _fields.revokePrivateInbox = data.is_revoke_pm_inbox();
  235. _fields.stickersRecentLimit = data.vstickers_recent_limit().v;
  236. _fields.internalLinksDomain = qs(data.vme_url_prefix());
  237. _fields.channelsReadMediaPeriod = data.vchannels_read_media_period().v;
  238. _fields.webFileDcId = data.vwebfile_dc_id().v;
  239. _fields.callReceiveTimeoutMs = data.vcall_receive_timeout_ms().v;
  240. _fields.callRingTimeoutMs = data.vcall_ring_timeout_ms().v;
  241. _fields.callConnectTimeoutMs = data.vcall_connect_timeout_ms().v;
  242. _fields.callPacketTimeoutMs = data.vcall_packet_timeout_ms().v;
  243. _fields.blockedMode = data.is_blocked_mode();
  244. _fields.captionLengthMax = data.vcaption_length_max().v;
  245. _fields.reactionDefaultEmoji = ConfigDefaultReactionEmoji();
  246. _fields.reactionDefaultCustom = 0;
  247. if (const auto reaction = data.vreactions_default()) {
  248. reaction->match([&](const MTPDreactionEmpty &) {
  249. }, [&](const MTPDreactionEmoji &data) {
  250. _fields.reactionDefaultEmoji = qs(data.vemoticon());
  251. }, [&](const MTPDreactionCustomEmoji &data) {
  252. _fields.reactionDefaultCustom = data.vdocument_id().v;
  253. }, [&](const MTPDreactionPaid &data) {
  254. _fields.reactionDefaultEmoji = QString(QChar('*'));
  255. });
  256. }
  257. _fields.autologinToken = qs(data.vautologin_token().value_or_empty());
  258. _fields.ratingDecay = data.vrating_e_decay().v;
  259. if (_fields.ratingDecay <= 0) {
  260. _fields.ratingDecay = ConfigFields(
  261. _dcOptions.environment()
  262. ).ratingDecay;
  263. }
  264. _fields.gifSearchUsername = qs(data.vgif_search_username().value_or_empty());
  265. _fields.venueSearchUsername = qs(data.vvenue_search_username().value_or_empty());
  266. if (data.vdc_options().v.empty()) {
  267. LOG(("MTP Error: config with empty dc_options received!"));
  268. } else {
  269. dcOptions().setFromList(data.vdc_options());
  270. }
  271. _updates.fire({});
  272. }
  273. rpl::producer<> Config::updates() const {
  274. return _updates.events();
  275. }
  276. void Config::setChatSizeMax(int value) {
  277. _fields.chatSizeMax = value;
  278. }
  279. void Config::setStickersRecentLimit(int value) {
  280. _fields.stickersRecentLimit = value;
  281. }
  282. void Config::setMegagroupSizeMax(int value) {
  283. _fields.megagroupSizeMax = value;
  284. }
  285. void Config::setTxtDomainString(const QString &value) {
  286. _fields.txtDomainString = value;
  287. }
  288. } // namespace MTP