query_gallery.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. # █ █ ▀ █▄▀ ▄▀█ █▀█ ▀
  2. # █▀█ █ █ █ █▀█ █▀▄ █
  3. # © Copyright 2022
  4. # https://t.me/hikariatama
  5. #
  6. # 🔒 Licensed under the GNU AGPLv3
  7. # 🌐 https://www.gnu.org/licenses/agpl-3.0.html
  8. import asyncio
  9. import logging
  10. import time
  11. import typing
  12. from aiogram.types import InlineQuery, InlineQueryResultArticle, InputTextMessageContent
  13. from .. import utils
  14. from .types import InlineUnit
  15. logger = logging.getLogger(__name__)
  16. class QueryGallery(InlineUnit):
  17. async def query_gallery(
  18. self,
  19. query: InlineQuery,
  20. items: typing.List[typing.Dict[str, typing.Any]],
  21. *,
  22. force_me: bool = False,
  23. disable_security: bool = False,
  24. always_allow: typing.Optional[typing.List[int]] = None,
  25. ) -> bool:
  26. """
  27. Answer inline query with a bunch of inline galleries
  28. :param query: `InlineQuery` which should be answered with inline gallery
  29. :param items: Array of dicts with inline results.
  30. Each dict *must* has a:
  31. - `title` - The title of the result
  32. - `description` - Short description of the result
  33. - `next_handler` - Inline gallery handler. Callback or awaitable
  34. Each dict *can* has a:
  35. - `caption` - Caption of photo. Defaults to `""`
  36. - `force_me` - Whether the button must be accessed only by owner. Defaults to `False`
  37. - `disable_security` - Whether to disable the security checks at all. Defaults to `False`
  38. :param force_me: Either this gallery buttons must be pressed only by owner scope or no
  39. :param always_allow: Users, that are allowed to press buttons in addition to previous rules
  40. :param disable_security: By default, Hikka will try to check security of gallery
  41. If you want to disable all security checks on this gallery in particular, pass `disable_security=True`
  42. :return: Status of answer
  43. """
  44. if not isinstance(force_me, bool):
  45. logger.error(
  46. "Invalid type for `force_me`. Expected `bool`, got %s",
  47. type(force_me),
  48. )
  49. return False
  50. if not isinstance(disable_security, bool):
  51. logger.error(
  52. "Invalid type for `disable_security`. Expected `bool`, got %s",
  53. type(disable_security),
  54. )
  55. return False
  56. if always_allow and not isinstance(always_allow, list):
  57. logger.error(
  58. "Invalid type for `always_allow`. Expected `list`, got %s",
  59. type(always_allow),
  60. )
  61. return False
  62. if not always_allow:
  63. always_allow = []
  64. if (
  65. not isinstance(items, list)
  66. or not all(isinstance(i, dict) for i in items)
  67. or not all(
  68. "title" in i
  69. and "description" in i
  70. and "next_handler" in i
  71. and (
  72. callable(i["next_handler"])
  73. or asyncio.iscoroutinefunction(i)
  74. or isinstance(i, list)
  75. )
  76. and isinstance(i["title"], str)
  77. and isinstance(i["description"], str)
  78. for i in items
  79. )
  80. ):
  81. logger.error("Invalid `items` specified in query gallery")
  82. return False
  83. result = []
  84. for i in items:
  85. if "thumb_handler" not in i:
  86. photo_url = await self._call_photo(i["next_handler"])
  87. if not photo_url:
  88. return False
  89. if isinstance(photo_url, list):
  90. photo_url = photo_url[0]
  91. if not isinstance(photo_url, str):
  92. logger.error(
  93. "Invalid result from `next_handler`. Expected `str`, got %s",
  94. type(photo_url),
  95. )
  96. continue
  97. else:
  98. photo_url = await self._call_photo(i["thumb_handler"])
  99. if not photo_url:
  100. return False
  101. if isinstance(photo_url, list):
  102. photo_url = photo_url[0]
  103. if not isinstance(photo_url, str):
  104. logger.error(
  105. "Invalid result from `thumb_handler`. Expected `str`, got %s",
  106. type(photo_url),
  107. )
  108. continue
  109. id_ = utils.rand(16)
  110. self._custom_map[id_] = {
  111. "handler": i["next_handler"],
  112. "ttl": round(time.time()) + 120,
  113. **({"always_allow": always_allow} if always_allow else {}),
  114. **({"force_me": force_me} if force_me else {}),
  115. **({"disable_security": disable_security} if disable_security else {}),
  116. **({"caption": i["caption"]} if "caption" in i else {}),
  117. }
  118. result += [
  119. InlineQueryResultArticle(
  120. id=utils.rand(20),
  121. title=i["title"],
  122. description=i["description"],
  123. input_message_content=InputTextMessageContent(
  124. f"🌘 <b>Opening gallery...</b>\n<i>#id: {id_}</i>",
  125. "HTML",
  126. disable_web_page_preview=True,
  127. ),
  128. thumb_url=photo_url,
  129. thumb_width=128,
  130. thumb_height=128,
  131. )
  132. ]
  133. await query.answer(result, cache_time=0)
  134. return True