api_confirm_phone.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 "api/api_confirm_phone.h"
  8. #include "apiwrap.h"
  9. #include "lang/lang_keys.h"
  10. #include "main/main_account.h"
  11. #include "main/main_session.h"
  12. #include "ui/boxes/confirm_box.h"
  13. #include "ui/boxes/confirm_phone_box.h"
  14. #include "ui/text/format_values.h" // Ui::FormatPhone
  15. #include "window/window_session_controller.h"
  16. namespace Api {
  17. ConfirmPhone::ConfirmPhone(not_null<ApiWrap*> api)
  18. : _api(&api->instance()) {
  19. }
  20. void ConfirmPhone::resolve(
  21. not_null<Window::SessionController*> controller,
  22. const QString &phone,
  23. const QString &hash) {
  24. if (_sendRequestId) {
  25. return;
  26. }
  27. _sendRequestId = _api.request(MTPaccount_SendConfirmPhoneCode(
  28. MTP_string(hash),
  29. MTP_codeSettings(
  30. MTP_flags(0),
  31. MTPVector<MTPbytes>(),
  32. MTPstring(),
  33. MTPBool())
  34. )).done([=](const MTPauth_SentCode &result) {
  35. _sendRequestId = 0;
  36. result.match([&](const MTPDauth_sentCode &data) {
  37. const auto bad = [](const char *type) {
  38. LOG(("API Error: Should not be '%1'.").arg(type));
  39. return 0;
  40. };
  41. const auto sentCodeLength = data.vtype().match([&](
  42. const MTPDauth_sentCodeTypeApp &data) {
  43. LOG(("Error: should not be in-app code!"));
  44. return 0;
  45. }, [&](const MTPDauth_sentCodeTypeSms &data) {
  46. return data.vlength().v;
  47. }, [&](const MTPDauth_sentCodeTypeFragmentSms &data) {
  48. return data.vlength().v;
  49. }, [&](const MTPDauth_sentCodeTypeCall &data) {
  50. return data.vlength().v;
  51. }, [&](const MTPDauth_sentCodeTypeFlashCall &) {
  52. return bad("FlashCall");
  53. }, [&](const MTPDauth_sentCodeTypeMissedCall &) {
  54. return bad("MissedCall");
  55. }, [&](const MTPDauth_sentCodeTypeFirebaseSms &) {
  56. return bad("FirebaseSms");
  57. }, [&](const MTPDauth_sentCodeTypeEmailCode &) {
  58. return bad("EmailCode");
  59. }, [&](const MTPDauth_sentCodeTypeSmsWord &) {
  60. return bad("SmsWord");
  61. }, [&](const MTPDauth_sentCodeTypeSmsPhrase &) {
  62. return bad("SmsPhrase");
  63. }, [&](const MTPDauth_sentCodeTypeSetUpEmailRequired &) {
  64. return bad("SetUpEmailRequired");
  65. });
  66. const auto fragmentUrl = data.vtype().match([](
  67. const MTPDauth_sentCodeTypeFragmentSms &data) {
  68. return qs(data.vurl());
  69. }, [](const auto &) { return QString(); });
  70. const auto phoneHash = qs(data.vphone_code_hash());
  71. const auto timeout = [&]() -> std::optional<int> {
  72. if (const auto nextType = data.vnext_type()) {
  73. if (nextType->type() == mtpc_auth_codeTypeCall) {
  74. return data.vtimeout().value_or(60);
  75. }
  76. }
  77. return std::nullopt;
  78. }();
  79. auto box = Box<Ui::ConfirmPhoneBox>(
  80. phone,
  81. sentCodeLength,
  82. fragmentUrl,
  83. timeout);
  84. const auto boxWeak = Ui::MakeWeak(box.data());
  85. using LoginCode = rpl::event_stream<QString>;
  86. const auto codeHandles = box->lifetime().make_state<LoginCode>();
  87. controller->session().account().setHandleLoginCode([=](
  88. const QString &code) {
  89. codeHandles->fire_copy(code);
  90. });
  91. box->resendRequests(
  92. ) | rpl::start_with_next([=] {
  93. _api.request(MTPauth_ResendCode(
  94. MTP_flags(0),
  95. MTP_string(phone),
  96. MTP_string(phoneHash),
  97. MTPstring() // reason
  98. )).done([=] {
  99. if (boxWeak) {
  100. boxWeak->callDone();
  101. }
  102. }).send();
  103. }, box->lifetime());
  104. rpl::merge(
  105. codeHandles->events(),
  106. box->checkRequests()
  107. ) | rpl::start_with_next([=](const QString &code) {
  108. if (_checkRequestId) {
  109. return;
  110. }
  111. _checkRequestId = _api.request(MTPaccount_ConfirmPhone(
  112. MTP_string(phoneHash),
  113. MTP_string(code)
  114. )).done([=] {
  115. _checkRequestId = 0;
  116. controller->show(
  117. Ui::MakeInformBox(
  118. tr::lng_confirm_phone_success(
  119. tr::now,
  120. lt_phone,
  121. Ui::FormatPhone(phone))),
  122. Ui::LayerOption::CloseOther);
  123. }).fail([=](const MTP::Error &error) {
  124. _checkRequestId = 0;
  125. if (!boxWeak) {
  126. return;
  127. }
  128. const auto errorText = MTP::IsFloodError(error)
  129. ? tr::lng_flood_error(tr::now)
  130. : (error.type() == (u"PHONE_CODE_EMPTY"_q)
  131. || error.type() == (u"PHONE_CODE_INVALID"_q))
  132. ? tr::lng_bad_code(tr::now)
  133. : Lang::Hard::ServerError();
  134. boxWeak->showServerError(errorText);
  135. }).handleFloodErrors().send();
  136. }, box->lifetime());
  137. box->boxClosing(
  138. ) | rpl::start_with_next([=] {
  139. controller->session().account().setHandleLoginCode(nullptr);
  140. }, box->lifetime());
  141. controller->show(std::move(box), Ui::LayerOption::CloseOther);
  142. }, [](const MTPDauth_sentCodeSuccess &) {
  143. LOG(("API Error: Unexpected auth.sentCodeSuccess "
  144. "(Api::ConfirmPhone)."));
  145. });
  146. }).fail([=](const MTP::Error &error) {
  147. _sendRequestId = 0;
  148. _checkRequestId = 0;
  149. const auto errorText = MTP::IsFloodError(error)
  150. ? tr::lng_flood_error(tr::now)
  151. : (error.code() == 400)
  152. ? tr::lng_confirm_phone_link_invalid(tr::now)
  153. : Lang::Hard::ServerError();
  154. controller->show(
  155. Ui::MakeInformBox(errorText),
  156. Ui::LayerOption::CloseOther);
  157. }).handleFloodErrors().send();
  158. }
  159. } // namespace Api