response.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 Optional, get_type_hints
  17. from aiohttp import ClientResponse
  18. from mautrix.types import JSON, Serializable
  19. from ..types import (
  20. ChallengeResponse,
  21. CheckpointResponse,
  22. ConsentRequiredResponse,
  23. LoginErrorResponse,
  24. LoginRequiredResponse,
  25. SpamResponse,
  26. )
  27. from .base import IGError
  28. class IGChallengeWrongCodeError(IGError):
  29. pass
  30. class IGUnknownError(IGError):
  31. response: ClientResponse
  32. def __init__(self, response: ClientResponse) -> None:
  33. super().__init__(
  34. f"Request {response.request_info.method} {response.request_info.url.path} failed: "
  35. f"HTTP {response.status} with non-JSON body"
  36. )
  37. self.response = response
  38. class IGResponseError(IGError):
  39. response: ClientResponse
  40. def __init__(self, response: ClientResponse, json: JSON) -> None:
  41. prefix = f"Request {response.request_info.method} {response.request_info.url.path} failed"
  42. message = f"HTTP {response.status}"
  43. self.response = response
  44. if "message" in json:
  45. message = json["message"]
  46. if "error_type" in json:
  47. error_type = json["error_type"]
  48. message = f"{error_type}: {message}"
  49. type_hint = get_type_hints(type(self)).get("body", JSON)
  50. if type_hint is not JSON and issubclass(type_hint, Serializable):
  51. self.body = type_hint.deserialize(json)
  52. else:
  53. self.body = json
  54. super().__init__(f"{prefix}: {self._message_override or message}")
  55. @property
  56. def _message_override(self) -> Optional[str]:
  57. return None
  58. class IGActionSpamError(IGResponseError):
  59. body: SpamResponse
  60. @property
  61. def _message(self) -> str:
  62. return f"HTTP {self.body.message}"
  63. class IGNotFoundError(IGResponseError):
  64. pass
  65. class IGRateLimitError(IGResponseError):
  66. pass
  67. class IGCheckpointError(IGResponseError):
  68. body: CheckpointResponse
  69. class IGChallengeError(IGResponseError):
  70. body: ChallengeResponse
  71. @property
  72. def url(self) -> str:
  73. return self.body.challenge.api_path
  74. class IGConsentRequiredError(IGResponseError):
  75. body: ConsentRequiredResponse
  76. class IGNotLoggedInError(IGResponseError):
  77. body: LoginRequiredResponse
  78. @property
  79. def proper_message(self) -> str:
  80. return (
  81. f"{self.body.error_title or self.body.message} "
  82. f"(reason code: {self.body.logout_reason})"
  83. )
  84. class IGUserHasLoggedOutError(IGNotLoggedInError):
  85. pass
  86. class IGLoginRequiredError(IGNotLoggedInError):
  87. pass
  88. class IGPrivateUserError(IGResponseError):
  89. pass
  90. class IGSentryBlockError(IGResponseError):
  91. pass
  92. class IGInactiveUserError(IGResponseError):
  93. pass
  94. class IGLoginError(IGResponseError):
  95. body: LoginErrorResponse
  96. class IGLoginTwoFactorRequiredError(IGLoginError):
  97. pass
  98. class IGLoginBadPasswordError(IGLoginError):
  99. pass
  100. class IGLoginUnusablePasswordError(IGLoginError):
  101. pass
  102. class IGLoginInvalidUserError(IGLoginError):
  103. pass
  104. class IGLoginInvalidCredentialsError(IGLoginError):
  105. pass
  106. class IGBad2FACodeError(IGResponseError):
  107. pass
  108. class IG2FACodeExpiredError(IGResponseError):
  109. pass
  110. class IGFBNoContactPointFoundError(IGLoginError):
  111. pass
  112. class IGFBEmailTaken(IGLoginError):
  113. pass
  114. class IGFBSSODisabled(IGLoginError):
  115. pass