token_obtainment.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. # ©️ Dan Gazizullin, 2021-2023
  2. # This file is a part of Hikka Userbot
  3. # 🌐 https://github.com/hikariatama/Hikka
  4. # You can redistribute it and/or modify it under the terms of the GNU AGPLv3
  5. # 🔑 https://www.gnu.org/licenses/agpl-3.0.html
  6. import asyncio
  7. import logging
  8. import re
  9. from hikkatl.errors.rpcerrorlist import YouBlockedUserError
  10. from hikkatl.tl.functions.contacts import UnblockRequest
  11. from .. import utils
  12. from .._internal import fw_protect
  13. from .types import InlineUnit
  14. logger = logging.getLogger(__name__)
  15. class TokenObtainment(InlineUnit):
  16. async def _create_bot(self):
  17. logger.info("User doesn't have bot, attempting creating new one")
  18. async with self._client.conversation("@BotFather", exclusive=False) as conv:
  19. await fw_protect()
  20. m = await conv.send_message("/newbot")
  21. r = await conv.get_response()
  22. logger.debug(">> %s", m.raw_text)
  23. logger.debug("<< %s", r.raw_text)
  24. if "20" in r.raw_text:
  25. return False
  26. await fw_protect()
  27. await m.delete()
  28. await r.delete()
  29. if self._db.get("hikka.inline", "custom_bot", False):
  30. username = self._db.get("hikka.inline", "custom_bot").strip("@")
  31. username = f"@{username}"
  32. try:
  33. await self._client.get_entity(username)
  34. except ValueError:
  35. pass
  36. else:
  37. uid = utils.rand(6)
  38. username = f"@hikka_{uid}_bot"
  39. else:
  40. uid = utils.rand(6)
  41. username = f"@hikka_{uid}_bot"
  42. for msg in [
  43. f"🌘 Hikka Userbot of {self._name}"[:64],
  44. username,
  45. "/setuserpic",
  46. username,
  47. ]:
  48. await fw_protect()
  49. m = await conv.send_message(msg)
  50. r = await conv.get_response()
  51. logger.debug(">> %s", m.raw_text)
  52. logger.debug("<< %s", r.raw_text)
  53. await fw_protect()
  54. await m.delete()
  55. await r.delete()
  56. try:
  57. await fw_protect()
  58. from .. import main
  59. m = await conv.send_file(main.BASE_PATH / "assets" / "bot_pfp.png")
  60. r = await conv.get_response()
  61. logger.debug(">> <Photo>")
  62. logger.debug("<< %s", r.raw_text)
  63. except Exception:
  64. await fw_protect()
  65. m = await conv.send_message("/cancel")
  66. r = await conv.get_response()
  67. logger.debug(">> %s", m.raw_text)
  68. logger.debug("<< %s", r.raw_text)
  69. await fw_protect()
  70. await m.delete()
  71. await r.delete()
  72. return await self._assert_token(False)
  73. async def _assert_token(
  74. self,
  75. create_new_if_needed: bool = True,
  76. revoke_token: bool = False,
  77. ) -> bool:
  78. if self._token:
  79. return True
  80. logger.info("Bot token not found in db, attempting search in BotFather")
  81. if not self._db.get(__name__, "no_mute", False):
  82. await utils.dnd(
  83. self._client,
  84. await self._client.get_entity("@BotFather"),
  85. True,
  86. )
  87. self._db.set(__name__, "no_mute", True)
  88. async with self._client.conversation("@BotFather", exclusive=False) as conv:
  89. try:
  90. await fw_protect()
  91. m = await conv.send_message("/token")
  92. except YouBlockedUserError:
  93. await self._client(UnblockRequest(id="@BotFather"))
  94. await fw_protect()
  95. m = await conv.send_message("/token")
  96. r = await conv.get_response()
  97. logger.debug(">> %s", m.raw_text)
  98. logger.debug("<< %s", r.raw_text)
  99. await fw_protect()
  100. await m.delete()
  101. await r.delete()
  102. if not hasattr(r, "reply_markup") or not hasattr(r.reply_markup, "rows"):
  103. await conv.cancel_all()
  104. return await self._create_bot() if create_new_if_needed else False
  105. for row in r.reply_markup.rows:
  106. for button in row.buttons:
  107. if self._db.get(
  108. "hikka.inline", "custom_bot", False
  109. ) and self._db.get(
  110. "hikka.inline", "custom_bot", False
  111. ) != button.text.strip(
  112. "@"
  113. ):
  114. continue
  115. if not self._db.get(
  116. "hikka.inline",
  117. "custom_bot",
  118. False,
  119. ) and not re.search(r"@hikka_[0-9a-zA-Z]{6}_bot", button.text):
  120. continue
  121. await fw_protect()
  122. m = await conv.send_message(button.text)
  123. r = await conv.get_response()
  124. logger.debug(">> %s", m.raw_text)
  125. logger.debug("<< %s", r.raw_text)
  126. if revoke_token:
  127. await fw_protect()
  128. await m.delete()
  129. await r.delete()
  130. await fw_protect()
  131. m = await conv.send_message("/revoke")
  132. r = await conv.get_response()
  133. logger.debug(">> %s", m.raw_text)
  134. logger.debug("<< %s", r.raw_text)
  135. await fw_protect()
  136. await m.delete()
  137. await r.delete()
  138. await fw_protect()
  139. m = await conv.send_message(button.text)
  140. r = await conv.get_response()
  141. logger.debug(">> %s", m.raw_text)
  142. logger.debug("<< %s", r.raw_text)
  143. token = r.raw_text.splitlines()[1]
  144. self._db.set("hikka.inline", "bot_token", token)
  145. self._token = token
  146. await fw_protect()
  147. await m.delete()
  148. await r.delete()
  149. for msg in [
  150. "/setinline",
  151. button.text,
  152. "user@hikka:~$",
  153. "/setinlinefeedback",
  154. button.text,
  155. "Enabled",
  156. "/setuserpic",
  157. button.text,
  158. ]:
  159. await fw_protect()
  160. m = await conv.send_message(msg)
  161. r = await conv.get_response()
  162. logger.debug(">> %s", m.raw_text)
  163. logger.debug("<< %s", r.raw_text)
  164. await fw_protect()
  165. await m.delete()
  166. await r.delete()
  167. try:
  168. await fw_protect()
  169. from .. import main
  170. m = await conv.send_file(
  171. main.BASE_PATH / "assets" / "bot_pfp.png"
  172. )
  173. r = await conv.get_response()
  174. logger.debug(">> <Photo>")
  175. logger.debug("<< %s", r.raw_text)
  176. except Exception:
  177. await fw_protect()
  178. m = await conv.send_message("/cancel")
  179. r = await conv.get_response()
  180. logger.debug(">> %s", m.raw_text)
  181. logger.debug("<< %s", r.raw_text)
  182. await fw_protect()
  183. await m.delete()
  184. await r.delete()
  185. return True
  186. return await self._create_bot() if create_new_if_needed else False
  187. async def _reassert_token(self):
  188. is_token_asserted = await self._assert_token(revoke_token=True)
  189. if not is_token_asserted:
  190. self.init_complete = False
  191. else:
  192. await self.register_manager(ignore_token_checks=True)
  193. async def _dp_revoke_token(self, already_initialised: bool = True):
  194. if already_initialised:
  195. await self._stop()
  196. logger.error("Got polling conflict. Attempting token revocation...")
  197. self._db.set("hikka.inline", "bot_token", None)
  198. self._token = None
  199. if already_initialised:
  200. asyncio.ensure_future(self._reassert_token())
  201. else:
  202. return await self._reassert_token()