login_simulate.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # mautrix-instagram - A Matrix-Instagram puppeting bridge.
  2. # Copyright (C) 2020 Tulir Asokan
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU Affero General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU Affero General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Affero General Public License
  15. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. from typing import List, Awaitable, Any
  17. import random
  18. from ..types import LoginResponse
  19. from .account import AccountAPI
  20. from .login import LoginAPI
  21. from .qe import QeSyncAPI
  22. from .zr import ZRTokenAPI
  23. from .attribution import LogAttributionAPI
  24. from .launcher import LauncherSyncAPI
  25. class LoginSimulateAPI(AccountAPI, LogAttributionAPI, QeSyncAPI, ZRTokenAPI, LoginAPI,
  26. LauncherSyncAPI):
  27. @property
  28. def _pre_login_flow_requests(self) -> List[Awaitable[Any]]:
  29. return [
  30. self.read_msisdn_header(),
  31. self.msisdn_header_bootstrap("ig_select_app"),
  32. self.zr_token_result(),
  33. self.contact_point_prefill("prefill"),
  34. self.launcher_pre_login_sync(),
  35. self.qe_sync_login_experiments(),
  36. self.log_attribution(),
  37. self.get_prefill_candidates(),
  38. ]
  39. @property
  40. def _post_login_flow_requests(self) -> List[Awaitable[Any]]:
  41. return [
  42. self.zr_token_result(),
  43. self.launcher_post_login_sync(),
  44. self.qe_sync_experiments(),
  45. self.log_attribution(),
  46. self.log_resurrect_attribution(),
  47. self._facebook_ota(),
  48. ]
  49. async def simulate_pre_login_flow(self) -> None:
  50. items = self._pre_login_flow_requests
  51. random.shuffle(items)
  52. for item in items:
  53. await item
  54. async def simulate_post_login_flow(self) -> None:
  55. items = self._post_login_flow_requests
  56. random.shuffle(items)
  57. for item in items:
  58. await item
  59. async def _facebook_ota(self):
  60. url = (self.url / "api/v1/facebook_ota/").with_query({
  61. "fields": self.state.application.FACEBOOK_OTA_FIELDS,
  62. "custom_user_id": self.state.cookies.user_id,
  63. "signed_body": "SIGNATURE.",
  64. "version_code": self.state.application.APP_VERSION_CODE,
  65. "version_name": self.state.application.APP_VERSION,
  66. "custom_app_id": self.state.application.FACEBOOK_ORCA_APPLICATION_ID,
  67. "custom_device_id": self.state.device.uuid,
  68. })
  69. resp = await self.http.get(url)
  70. return await self.handle_response(resp)
  71. async def upgrade_login(self) -> LoginResponse:
  72. user_id = self.state.cookies.user_id
  73. resp = await self.logout(one_tap_app_login=True)
  74. return await self.one_tap_app_login(user_id, resp.login_nonce)