Queer European MD passionate about IT

helper.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. """Make a self-consistent bot help section."""
  2. # Third party modules
  3. from davtelepot.utilities import (
  4. get_cleaned_text, make_inline_keyboard,
  5. make_lines_of_buttons, make_button
  6. )
  7. # Project modules
  8. from .messages import default_help_messages
  9. def get_commands_description(bot, update, user_record):
  10. """Get a string description of `bot` commands.
  11. Show only commands available for `update` sender.
  12. """
  13. user_role = bot.Role.get_user_role(
  14. user_record=user_record
  15. )
  16. commands = {}
  17. for command, details in bot.commands.items():
  18. if 'description' not in details or not details['description']:
  19. continue
  20. if 'authorization_level' not in details:
  21. continue
  22. command_role = bot.Role.get_role_by_name(details['authorization_level'])
  23. if command_role.code < user_role.code:
  24. continue
  25. if command_role.code not in commands:
  26. commands[command_role.code] = []
  27. commands[command_role.code].append(
  28. "/{command}{authorization_level}: {description}".format(
  29. command=command,
  30. authorization_level=(
  31. f" <i>[{command_role.plural}]</i>"
  32. if command_role.code != bot.Role.default_role_code
  33. else ""
  34. ),
  35. description=bot.get_message(
  36. 'commands', command, 'description',
  37. user_record=user_record, update=update,
  38. default_message=(
  39. details['description']
  40. if type(details['description']) is str
  41. else ''
  42. )
  43. )
  44. )
  45. )
  46. return "\n".join(
  47. [
  48. command
  49. for role, commands in sorted(
  50. commands.items(),
  51. key=(lambda x: -x[0])
  52. )
  53. for command in sorted(
  54. commands
  55. )
  56. ]
  57. )
  58. # [
  59. # "/{command}{authorization_level}: {description}".format(
  60. # command=command,
  61. # authorization_level=(
  62. # ""
  63. # if 1
  64. # else ""
  65. # ),
  66. # description=bot.get_message(
  67. # 'commands', command, 'description',
  68. # user_record=user_record, update=update,
  69. # default_message=(
  70. # details['description']
  71. # if type(details['description']) is str
  72. # else ''
  73. # )
  74. # )
  75. # )
  76. # if 'description' in details and details['description']
  77. # and user_role.code <= bot.Role.get_user_role(
  78. # user_role_id=details['authorization_level']
  79. # ).code
  80. # ]
  81. # )
  82. def _make_button(text=None, callback_data='',
  83. prefix='help:///', delimiter='|', data=None):
  84. return make_button(text=text, callback_data=callback_data,
  85. prefix=prefix, delimiter=delimiter, data=data)
  86. def get_back_to_help_menu_keyboard(bot, update, user_record):
  87. """Return a keyboard to let user come back to help menu."""
  88. return make_inline_keyboard(
  89. [
  90. _make_button(
  91. text=bot.get_message(
  92. 'help', 'help_command', 'back_to_help_menu',
  93. update=update, user_record=user_record
  94. ),
  95. data=['menu']
  96. )
  97. ],
  98. 1
  99. )
  100. def get_help_buttons(bot, update, user_record):
  101. """Get `bot` help menu inline keyboard.
  102. Show only buttons available for `update` sender.
  103. """
  104. user_role = bot.Role.get_user_role(
  105. user_record=user_record
  106. )
  107. buttons_list = [
  108. _make_button(
  109. text=bot.get_message(
  110. 'help_sections', section['name'], 'label',
  111. update=update, user_record=user_record,
  112. ),
  113. data=['section', name]
  114. )
  115. for name, section in bot.messages['help_sections'].items()
  116. if 'authorization_level' in section
  117. and user_role.code <= bot.Role.get_user_role(
  118. user_role_id=section['authorization_level']
  119. ).code
  120. ]
  121. return dict(
  122. inline_keyboard=(
  123. make_lines_of_buttons(buttons_list, 3)
  124. + make_lines_of_buttons(
  125. [
  126. _make_button(
  127. text=bot.get_message(
  128. 'help', 'commands_button_label',
  129. update=update, user_record=user_record,
  130. ),
  131. data=['commands']
  132. )
  133. ],
  134. 1
  135. )
  136. )
  137. )
  138. async def _help_command(bot, update, user_record):
  139. if not bot.authorization_function(update=update,
  140. authorization_level='everybody'):
  141. return bot.get_message(
  142. 'help', 'help_command', 'access_denied_message',
  143. update=update, user_record=user_record
  144. )
  145. reply_markup = get_help_buttons(bot, update, user_record)
  146. return dict(
  147. text=bot.get_message(
  148. 'help', 'help_command', 'text',
  149. update=update, user_record=user_record,
  150. bot=bot
  151. ),
  152. parse_mode='HTML',
  153. reply_markup=reply_markup,
  154. disable_web_page_preview=True
  155. )
  156. async def _help_button(bot, update, user_record, data):
  157. result, text, reply_markup = '', '', None
  158. if data[0] == 'commands':
  159. text = bot.get_message(
  160. 'help', 'help_command', 'header',
  161. update=update, user_record=user_record,
  162. bot=bot,
  163. commands=get_commands_description(bot, update, user_record)
  164. )
  165. reply_markup = get_back_to_help_menu_keyboard(
  166. bot=bot, update=update, user_record=user_record
  167. )
  168. elif data[0] == 'menu':
  169. text = bot.get_message(
  170. 'help', 'help_command', 'text',
  171. update=update, user_record=user_record,
  172. bot=bot
  173. )
  174. reply_markup = get_help_buttons(bot, update, user_record)
  175. elif (
  176. data[0] == 'section'
  177. and len(data) > 1
  178. and data[1] in bot.messages['help_sections']
  179. ):
  180. section = bot.messages['help_sections'][data[1]]
  181. if bot.authorization_function(
  182. update=update,
  183. authorization_level=section['authorization_level']
  184. ):
  185. text = (
  186. "<b>{label}</b>\n\n"
  187. "{description}"
  188. ).format(
  189. label=bot.get_message(
  190. 'help_sections', section['name'], 'label',
  191. update=update, user_record=user_record,
  192. ),
  193. description=bot.get_message(
  194. 'help_sections', section['name'], 'description',
  195. update=update, user_record=user_record,
  196. bot=bot
  197. ),
  198. )
  199. else:
  200. text = bot.authorization_denied_message
  201. reply_markup = get_back_to_help_menu_keyboard(
  202. bot=bot, update=update, user_record=user_record
  203. )
  204. if text or reply_markup:
  205. return dict(
  206. text=result,
  207. edit=dict(
  208. text=text,
  209. parse_mode='HTML',
  210. reply_markup=reply_markup,
  211. disable_web_page_preview=True
  212. )
  213. )
  214. return result
  215. async def _start_command(bot, update, user_record):
  216. text = get_cleaned_text(update=update, bot=bot, replace=['start'])
  217. if not text:
  218. return await _help_command(bot, update, user_record)
  219. update['text'] = text
  220. await bot.text_message_handler(
  221. update=update,
  222. user_record=None
  223. )
  224. return
  225. def init(telegram_bot, help_messages=None):
  226. """Assign parsers, commands, buttons and queries to given `bot`."""
  227. if help_messages is None:
  228. help_messages = default_help_messages
  229. telegram_bot.messages['help'] = help_messages
  230. @telegram_bot.command("/start", authorization_level='everybody')
  231. async def start_command(bot, update, user_record):
  232. return await _start_command(bot, update, user_record)
  233. @telegram_bot.command(command='/help', aliases=['00help'],
  234. reply_keyboard_button=help_messages['help_command'][
  235. 'reply_keyboard_button'],
  236. show_in_keyboard=True,
  237. description=help_messages['help_command']['description'],
  238. authorization_level='everybody')
  239. async def help_command(bot, update, user_record):
  240. return await _help_command(bot, update, user_record)
  241. @telegram_bot.button(prefix='help:///', separator='|',
  242. authorization_level='everybody')
  243. async def help_button(bot, update, user_record, data):
  244. return await _help_button(bot, update, user_record, data)