hikka_security.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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. # scope: inline
  9. import logging
  10. from typing import List, Union
  11. from telethon.tl.types import Message, PeerUser, User
  12. from telethon.utils import get_display_name
  13. from .. import loader, security, utils, main
  14. from ..inline.types import InlineCall
  15. from ..security import (
  16. DEFAULT_PERMISSIONS,
  17. EVERYONE,
  18. GROUP_ADMIN,
  19. GROUP_ADMIN_ADD_ADMINS,
  20. GROUP_ADMIN_BAN_USERS,
  21. GROUP_ADMIN_CHANGE_INFO,
  22. GROUP_ADMIN_DELETE_MESSAGES,
  23. GROUP_ADMIN_INVITE_USERS,
  24. GROUP_ADMIN_PIN_MESSAGES,
  25. GROUP_MEMBER,
  26. GROUP_OWNER,
  27. PM,
  28. SUDO,
  29. SUPPORT,
  30. )
  31. logger = logging.getLogger(__name__)
  32. @loader.tds
  33. class HikkaSecurityMod(loader.Module):
  34. """Control security settings"""
  35. strings = {
  36. "name": "HikkaSecurity",
  37. "no_command": "🚫 <b>Command </b><code>{}</code><b> not found!</b>",
  38. "permissions": (
  39. "🔐 <b>Here you can configure permissions for </b><code>{}{}</code>"
  40. ),
  41. "close_menu": "🙈 Close this menu",
  42. "global": (
  43. "🔐 <b>Here you can configure global bounding mask. If the permission is"
  44. " excluded here, it is excluded everywhere!</b>"
  45. ),
  46. "owner": "<emoji document_id='5386399931378440814'>😎</emoji> Owner",
  47. "sudo": "🤵 Sudo",
  48. "support": "<emoji document_id='5415729507128580146'>🤓</emoji> Support",
  49. "group_owner": "🧛‍♂️ Group owner",
  50. "group_admin_add_admins": "🧑‍⚖️ Admin (add members)",
  51. "group_admin_change_info": "🧑‍⚖️ Admin (change info)",
  52. "group_admin_ban_users": "🧑‍⚖️ Admin (ban)",
  53. "group_admin_delete_messages": "🧑‍⚖️ Admin (delete msgs)",
  54. "group_admin_pin_messages": "🧑‍⚖️ Admin (pin)",
  55. "group_admin_invite_users": "🧑‍⚖️ Admin (invite)",
  56. "group_admin": "🧑‍⚖️ Admin (any)",
  57. "group_member": "👥 In group",
  58. "pm": "🤙 In PM",
  59. "everyone": "🌍 Everyone (Inline)",
  60. "owner_list": (
  61. "<emoji document_id='5386399931378440814'>😎</emoji> <b>Users in group"
  62. " </b><code>owner</code><b>:</b>\n\n{}"
  63. ),
  64. "sudo_list": (
  65. "<emoji document_id='5418133868475587618'>🧐</emoji> <b>Users in group"
  66. " </b><code>sudo</code><b>:</b>\n\n{}"
  67. ),
  68. "support_list": (
  69. "<emoji document_id='5415729507128580146'>🤓</emoji> <b>Users in group"
  70. " </b><code>support</code><b>:</b>\n\n{}"
  71. ),
  72. "no_owner": (
  73. "<emoji document_id='5386399931378440814'>😎</emoji> <b>There is no users in"
  74. " group </b><code>owner</code>"
  75. ),
  76. "no_sudo": (
  77. "<emoji document_id='5418133868475587618'>🧐</emoji> <b>There is no users in"
  78. " group </b><code>sudo</code>"
  79. ),
  80. "no_support": (
  81. "<emoji document_id='5415729507128580146'>🤓</emoji> <b>There is no users in"
  82. " group </b><code>support</code>"
  83. ),
  84. "owner_added": (
  85. '<emoji document_id="5386399931378440814">😎</emoji> <b><a'
  86. ' href="tg://user?id={}">{}</a> added to group </b><code>owner</code>'
  87. ),
  88. "sudo_added": (
  89. '<emoji document_id="5418133868475587618">🧐</emoji> <b><a'
  90. ' href="tg://user?id={}">{}</a> added to group </b><code>sudo</code>'
  91. ),
  92. "support_added": (
  93. '<emoji document_id="5415729507128580146">🤓</emoji> <b><a'
  94. ' href="tg://user?id={}">{}</a> added to group </b><code>support</code>'
  95. ),
  96. "owner_removed": (
  97. '<emoji document_id="5386399931378440814">😎</emoji> <b><a'
  98. ' href="tg://user?id={}">{}</a> removed from group </b><code>owner</code>'
  99. ),
  100. "sudo_removed": (
  101. '<emoji document_id="5418133868475587618">🧐</emoji> <b><a'
  102. ' href="tg://user?id={}">{}</a> removed from group </b><code>sudo</code>'
  103. ),
  104. "support_removed": (
  105. '<emoji document_id="5415729507128580146">🤓</emoji> <b><a'
  106. ' href="tg://user?id={}">{}</a> removed from group </b><code>support</code>'
  107. ),
  108. "no_user": (
  109. "<emoji document_id='5415905755406539934'>🚫</emoji> <b>Specify user to"
  110. " permit</b>"
  111. ),
  112. "not_a_user": (
  113. "<emoji document_id='5415905755406539934'>🚫</emoji> <b>Specified entity is"
  114. " not a user</b>"
  115. ),
  116. "li": '⦿ <b><a href="tg://user?id={}">{}</a></b>',
  117. "warning": (
  118. "⚠️ <b>Please, confirm, that you want to add <a"
  119. ' href="tg://user?id={}">{}</a> to group </b><code>{}</code><b>!\nThis'
  120. " action may reveal personal info and grant full or partial access to"
  121. " userbot to this user</b>"
  122. ),
  123. "cancel": "🚫 Cancel",
  124. "confirm": "👑 Confirm",
  125. "enable_nonick_btn": "🔰 Enable",
  126. "self": (
  127. "<emoji document_id='5415905755406539934'>🚫</emoji> <b>You can't"
  128. " promote/demote yourself!</b>"
  129. ),
  130. "suggest_nonick": "🔰 <i>Do you want to enable NoNick for this user?</i>",
  131. "user_nn": '🔰 <b>NoNick for <a href="tg://user?id={}">{}</a> enabled</b>',
  132. }
  133. strings_ru = {
  134. "no_command": (
  135. "<emoji document_id='5415905755406539934'>🚫</emoji> <b>Команда"
  136. " </b><code>{}</code><b> не найдена!</b>"
  137. ),
  138. "permissions": (
  139. "🔐 <b>Здесь можно настроить разрешения для команды </b><code>{}{}</code>"
  140. ),
  141. "close_menu": "🙈 Закрыть это меню",
  142. "global": (
  143. "🔐 <b>Здесь можно настроить глобальную исключающую маску. Если тумблер"
  144. " выключен здесь, он выключен для всех команд</b>"
  145. ),
  146. "owner": "<emoji document_id='5386399931378440814'>😎</emoji> Владелец",
  147. "sudo": "🤵 Sudo",
  148. "support": "<emoji document_id='5415729507128580146'>🤓</emoji> Помощник",
  149. "group_owner": "🧛‍♂️ Влад. группы",
  150. "group_admin_add_admins": "🧑‍⚖️ Админ (добавлять участников)",
  151. "group_admin_change_info": "🧑‍⚖️ Админ (изменять инфо)",
  152. "group_admin_ban_users": "🧑‍⚖️ Админ (банить)",
  153. "group_admin_delete_messages": "🧑‍⚖️ Админ (удалять сообщения)",
  154. "group_admin_pin_messages": "🧑‍⚖️ Админ (закреплять)",
  155. "group_admin_invite_users": "🧑‍⚖️ Админ (приглашать)",
  156. "group_admin": "🧑‍⚖️ Админ (любой)",
  157. "group_member": "👥 В группе",
  158. "pm": "🤙 В лс",
  159. "owner_list": (
  160. "<emoji document_id='5386399931378440814'>😎</emoji> <b>Пользователи группы"
  161. " </b><code>owner</code><b>:</b>\n\n{}"
  162. ),
  163. "sudo_list": (
  164. "<emoji document_id='5418133868475587618'>🧐</emoji> <b>Пользователи группы"
  165. " </b><code>sudo</code><b>:</b>\n\n{}"
  166. ),
  167. "support_list": (
  168. "<emoji document_id='5415729507128580146'>🤓</emoji> <b>Пользователи группы"
  169. " </b><code>support</code><b>:</b>\n\n{}"
  170. ),
  171. "no_owner": (
  172. "<emoji document_id='5386399931378440814'>😎</emoji> <b>Нет пользователей в"
  173. " группе </b><code>owner</code>"
  174. ),
  175. "no_sudo": (
  176. "<emoji document_id='5418133868475587618'>🧐</emoji> <b>Нет пользователей в"
  177. " группе </b><code>sudo</code>"
  178. ),
  179. "no_support": (
  180. "<emoji document_id='5415729507128580146'>🤓</emoji> <b>Нет пользователей в"
  181. " группе </b><code>support</code>"
  182. ),
  183. "no_user": (
  184. "<emoji document_id='5415905755406539934'>🚫</emoji> <b>Укажи, кому выдавать"
  185. " права</b>"
  186. ),
  187. "not_a_user": (
  188. "<emoji document_id='5415905755406539934'>🚫</emoji> <b>Указанная цель - не"
  189. " пользователь</b>"
  190. ),
  191. "cancel": "🚫 Отмена",
  192. "confirm": "👑 Подтвердить",
  193. "self": (
  194. "<emoji document_id='5415905755406539934'>🚫</emoji> <b>Нельзя управлять"
  195. " своими правами!</b>"
  196. ),
  197. "warning": (
  198. '⚠️ <b>Ты действительно хочешь добавить <a href="tg://user?id={}">{}</a> в'
  199. " группу </b><code>{}</code><b>!\nЭто действие может передать частичный или"
  200. " полный доступ к юзерботу этому пользователю!</b>"
  201. ),
  202. "suggest_nonick": (
  203. "🔰 <i>Хочешь ли ты включить NoNick для этого пользователя?</i>"
  204. ),
  205. "user_nn": '🔰 <b>NoNick для <a href="tg://user?id={}">{}</a> включен</b>',
  206. "enable_nonick_btn": "🔰 Включить",
  207. "owner_added": (
  208. '<emoji document_id="5386399931378440814">😎</emoji> <b><a'
  209. ' href="tg://user?id={}">{}</a> добавлен в группу </b><code>owner</code>'
  210. ),
  211. "sudo_added": (
  212. '<emoji document_id="5418133868475587618">🧐</emoji> <b><a'
  213. ' href="tg://user?id={}">{}</a> добавлен в группу </b><code>sudo</code>'
  214. ),
  215. "support_added": (
  216. '<emoji document_id="5415729507128580146">🤓</emoji> <b><a'
  217. ' href="tg://user?id={}">{}</a> добавлен в группу </b><code>support</code>'
  218. ),
  219. "owner_removed": (
  220. '<emoji document_id="5386399931378440814">😎</emoji> <b><a'
  221. ' href="tg://user?id={}">{}</a> удален из группы </b><code>owner</code>'
  222. ),
  223. "sudo_removed": (
  224. '<emoji document_id="5418133868475587618">🧐</emoji> <b><a'
  225. ' href="tg://user?id={}">{}</a> удален из группы </b><code>sudo</code>'
  226. ),
  227. "support_removed": (
  228. '<emoji document_id="5415729507128580146">🤓</emoji> <b><a'
  229. ' href="tg://user?id={}">{}</a> удален из группы </b><code>support</code>'
  230. ),
  231. "_cls_doc": "Управление настройками безопасности",
  232. }
  233. async def inline__switch_perm(
  234. self,
  235. call: InlineCall,
  236. command: str,
  237. group: str,
  238. level: bool,
  239. is_inline: bool,
  240. ):
  241. cmd = (
  242. self.allmodules.inline_handlers[command]
  243. if is_inline
  244. else self.allmodules.commands[command]
  245. )
  246. mask = self._db.get(security.__name__, "masks", {}).get(
  247. f"{cmd.__module__}.{cmd.__name__}",
  248. getattr(cmd, "security", security.DEFAULT_PERMISSIONS),
  249. )
  250. bit = security.BITMAP[group.upper()]
  251. if level:
  252. mask |= bit
  253. else:
  254. mask &= ~bit
  255. masks = self._db.get(security.__name__, "masks", {})
  256. masks[f"{cmd.__module__}.{cmd.__name__}"] = mask
  257. self._db.set(security.__name__, "masks", masks)
  258. if (
  259. not self._db.get(security.__name__, "bounding_mask", DEFAULT_PERMISSIONS)
  260. & bit
  261. and level
  262. ):
  263. await call.answer(
  264. "Security value set but not applied. Consider enabling this value in"
  265. f" .{'inlinesec' if is_inline else 'security'}",
  266. show_alert=True,
  267. )
  268. else:
  269. await call.answer("Security value set!")
  270. await call.edit(
  271. self.strings("permissions").format(
  272. f"@{self.inline.bot_username} " if is_inline else self.get_prefix(),
  273. command,
  274. ),
  275. reply_markup=self._build_markup(cmd, is_inline),
  276. )
  277. async def inline__switch_perm_bm(
  278. self,
  279. call: InlineCall,
  280. group: str,
  281. level: bool,
  282. is_inline: bool,
  283. ):
  284. mask = self._db.get(security.__name__, "bounding_mask", DEFAULT_PERMISSIONS)
  285. bit = security.BITMAP[group.upper()]
  286. if level:
  287. mask |= bit
  288. else:
  289. mask &= ~bit
  290. self._db.set(security.__name__, "bounding_mask", mask)
  291. await call.answer("Bounding mask value set!")
  292. await call.edit(
  293. self.strings("global"),
  294. reply_markup=self._build_markup_global(is_inline),
  295. )
  296. def _build_markup(
  297. self,
  298. command: callable,
  299. is_inline: bool = False,
  300. ) -> List[List[dict]]:
  301. perms = self._get_current_perms(command, is_inline)
  302. return (
  303. utils.chunks(
  304. [
  305. {
  306. "text": f"{'✅' if level else '🚫'} {self.strings[group]}",
  307. "callback": self.inline__switch_perm,
  308. "args": (
  309. command.__name__.rsplit("_inline_handler", maxsplit=1)[0],
  310. group,
  311. not level,
  312. is_inline,
  313. ),
  314. }
  315. for group, level in perms.items()
  316. ],
  317. 2,
  318. )
  319. + [[{"text": self.strings("close_menu"), "action": "close"}]]
  320. if is_inline
  321. else utils.chunks(
  322. [
  323. {
  324. "text": f"{'✅' if level else '🚫'} {self.strings[group]}",
  325. "callback": self.inline__switch_perm,
  326. "args": (
  327. command.__name__.rsplit("cmd", maxsplit=1)[0],
  328. group,
  329. not level,
  330. is_inline,
  331. ),
  332. }
  333. for group, level in perms.items()
  334. ],
  335. 2,
  336. )
  337. + [
  338. [
  339. {
  340. "text": self.strings("close_menu"),
  341. "action": "close",
  342. }
  343. ]
  344. ]
  345. )
  346. def _build_markup_global(self, is_inline: bool = False) -> List[List[dict]]:
  347. perms = self._get_current_bm(is_inline)
  348. return utils.chunks(
  349. [
  350. {
  351. "text": f"{'✅' if level else '🚫'} {self.strings[group]}",
  352. "callback": self.inline__switch_perm_bm,
  353. "args": (group, not level, is_inline),
  354. }
  355. for group, level in perms.items()
  356. ],
  357. 2,
  358. ) + [[{"text": self.strings("close_menu"), "action": "close"}]]
  359. def _get_current_bm(self, is_inline: bool = False) -> dict:
  360. return self._perms_map(
  361. self._db.get(security.__name__, "bounding_mask", DEFAULT_PERMISSIONS),
  362. is_inline,
  363. )
  364. @staticmethod
  365. def _perms_map(perms: int, is_inline: bool) -> dict:
  366. return (
  367. {
  368. "sudo": bool(perms & SUDO),
  369. "support": bool(perms & SUPPORT),
  370. "everyone": bool(perms & EVERYONE),
  371. }
  372. if is_inline
  373. else {
  374. "sudo": bool(perms & SUDO),
  375. "support": bool(perms & SUPPORT),
  376. "group_owner": bool(perms & GROUP_OWNER),
  377. "group_admin_add_admins": bool(perms & GROUP_ADMIN_ADD_ADMINS),
  378. "group_admin_change_info": bool(perms & GROUP_ADMIN_CHANGE_INFO),
  379. "group_admin_ban_users": bool(perms & GROUP_ADMIN_BAN_USERS),
  380. "group_admin_delete_messages": bool(
  381. perms & GROUP_ADMIN_DELETE_MESSAGES
  382. ),
  383. "group_admin_pin_messages": bool(perms & GROUP_ADMIN_PIN_MESSAGES),
  384. "group_admin_invite_users": bool(perms & GROUP_ADMIN_INVITE_USERS),
  385. "group_admin": bool(perms & GROUP_ADMIN),
  386. "group_member": bool(perms & GROUP_MEMBER),
  387. "pm": bool(perms & PM),
  388. "everyone": bool(perms & EVERYONE),
  389. }
  390. )
  391. def _get_current_perms(
  392. self,
  393. command: callable,
  394. is_inline: bool = False,
  395. ) -> dict:
  396. config = self._db.get(security.__name__, "masks", {}).get(
  397. f"{command.__module__}.{command.__name__}",
  398. getattr(command, "security", self._client.dispatcher.security._default),
  399. )
  400. return self._perms_map(config, is_inline)
  401. @loader.owner
  402. @loader.command(ru_doc="[команда] - Настроить разрешения для команды")
  403. async def security(self, message: Message):
  404. """[command] - Configure command's security settings"""
  405. args = utils.get_args_raw(message).lower().strip()
  406. if args and args not in self.allmodules.commands:
  407. await utils.answer(message, self.strings("no_command").format(args))
  408. return
  409. if not args:
  410. await self.inline.form(
  411. self.strings("global"),
  412. reply_markup=self._build_markup_global(),
  413. message=message,
  414. ttl=5 * 60,
  415. )
  416. return
  417. cmd = self.allmodules.commands[args]
  418. await self.inline.form(
  419. self.strings("permissions").format(self.get_prefix(), args),
  420. reply_markup=self._build_markup(cmd),
  421. message=message,
  422. ttl=5 * 60,
  423. )
  424. @loader.owner
  425. @loader.command(ru_doc="[команда] - Настроить разрешения для инлайн команды")
  426. async def inlinesec(self, message: Message):
  427. """[command] - Configure inline command's security settings"""
  428. args = utils.get_args_raw(message).lower().strip()
  429. if not args:
  430. await self.inline.form(
  431. self.strings("global"),
  432. reply_markup=self._build_markup_global(True),
  433. message=message,
  434. ttl=5 * 60,
  435. )
  436. return
  437. if args not in self.allmodules.inline_handlers:
  438. await utils.answer(message, self.strings("no_command").format(args))
  439. return
  440. i_handler = self.allmodules.inline_handlers[args]
  441. await self.inline.form(
  442. self.strings("permissions").format(f"@{self.inline.bot_username} ", args),
  443. reply_markup=self._build_markup(i_handler, True),
  444. message=message,
  445. ttl=5 * 60,
  446. )
  447. async def _resolve_user(self, message: Message):
  448. reply = await message.get_reply_message()
  449. args = utils.get_args_raw(message)
  450. if not args and not reply:
  451. await utils.answer(message, self.strings("no_user"))
  452. return
  453. user = None
  454. if args:
  455. try:
  456. if str(args).isdigit():
  457. args = int(args)
  458. user = await self._client.get_entity(args)
  459. except Exception:
  460. pass
  461. if user is None:
  462. user = await self._client.get_entity(reply.sender_id)
  463. if not isinstance(user, (User, PeerUser)):
  464. await utils.answer(message, self.strings("not_a_user"))
  465. return
  466. if user.id == self.tg_id:
  467. await utils.answer(message, self.strings("self"))
  468. return
  469. return user
  470. async def _add_to_group(
  471. self,
  472. message: Union[Message, InlineCall], # noqa: F821
  473. group: str,
  474. confirmed: bool = False,
  475. user: int = None,
  476. ):
  477. if user is None:
  478. user = await self._resolve_user(message)
  479. if not user:
  480. return
  481. if isinstance(user, int):
  482. user = await self._client.get_entity(user)
  483. if not confirmed:
  484. await self.inline.form(
  485. self.strings("warning").format(
  486. user.id,
  487. utils.escape_html(get_display_name(user)),
  488. group,
  489. ),
  490. message=message,
  491. ttl=10 * 60,
  492. reply_markup=[
  493. {
  494. "text": self.strings("cancel"),
  495. "action": "close",
  496. },
  497. {
  498. "text": self.strings("confirm"),
  499. "callback": self._add_to_group,
  500. "args": (group, True, user.id),
  501. },
  502. ],
  503. )
  504. return
  505. self._db.set(
  506. security.__name__,
  507. group,
  508. list(set(self._db.get(security.__name__, group, []) + [user.id])),
  509. )
  510. m = (
  511. self.strings(f"{group}_added").format(
  512. user.id,
  513. utils.escape_html(get_display_name(user)),
  514. )
  515. + "\n\n"
  516. + self.strings("suggest_nonick")
  517. )
  518. await utils.answer(message, m)
  519. await message.edit(
  520. m,
  521. reply_markup=[
  522. {
  523. "text": self.strings("cancel"),
  524. "action": "close",
  525. },
  526. {
  527. "text": self.strings("enable_nonick_btn"),
  528. "callback": self._enable_nonick,
  529. "args": (user,),
  530. },
  531. ],
  532. )
  533. async def _enable_nonick(self, call: InlineCall, user: User):
  534. self._db.set(
  535. main.__name__,
  536. "nonickusers",
  537. list(set(self._db.get(main.__name__, "nonickusers", []) + [user.id])),
  538. )
  539. await call.edit(
  540. self.strings("user_nn").format(
  541. user.id,
  542. utils.escape_html(get_display_name(user)),
  543. )
  544. )
  545. await call.unload()
  546. async def _remove_from_group(self, message: Message, group: str):
  547. user = await self._resolve_user(message)
  548. if not user:
  549. return
  550. self._db.set(
  551. security.__name__,
  552. group,
  553. list(set(self._db.get(security.__name__, group, [])) - {user.id}),
  554. )
  555. m = self.strings(f"{group}_removed").format(
  556. user.id,
  557. utils.escape_html(get_display_name(user)),
  558. )
  559. await utils.answer(message, m)
  560. async def _list_group(self, message: Message, group: str):
  561. _resolved_users = []
  562. for user in self._db.get(security.__name__, group, []) + (
  563. [self.tg_id] if group == "owner" else []
  564. ):
  565. try:
  566. _resolved_users += [await self._client.get_entity(user)]
  567. except Exception:
  568. pass
  569. if _resolved_users:
  570. await utils.answer(
  571. message,
  572. self.strings(f"{group}_list").format(
  573. "\n".join(
  574. [
  575. self.strings("li").format(
  576. i.id, utils.escape_html(get_display_name(i))
  577. )
  578. for i in _resolved_users
  579. ]
  580. )
  581. ),
  582. )
  583. else:
  584. await utils.answer(message, self.strings(f"no_{group}"))
  585. @loader.command(ru_doc="<пользователь> - Добавить пользователя в группу `sudo`")
  586. async def sudoadd(self, message: Message):
  587. """<user> - Add user to `sudo`"""
  588. await self._add_to_group(message, "sudo")
  589. @loader.command(ru_doc="<пользователь> - Добавить пользователя в группу `owner`")
  590. async def owneradd(self, message: Message):
  591. """<user> - Add user to `owner`"""
  592. await self._add_to_group(message, "owner")
  593. @loader.command(ru_doc="<пользователь> - Добавить пользователя в группу `support`")
  594. async def supportadd(self, message: Message):
  595. """<user> - Add user to `support`"""
  596. await self._add_to_group(message, "support")
  597. @loader.command(ru_doc="<пользователь> - Удалить пользователя из группы `sudo`")
  598. async def sudorm(self, message: Message):
  599. """<user> - Remove user from `sudo`"""
  600. await self._remove_from_group(message, "sudo")
  601. @loader.command(ru_doc="<пользователь> - Удалить пользователя из группы `owner`")
  602. async def ownerrm(self, message: Message):
  603. """<user> - Remove user from `owner`"""
  604. await self._remove_from_group(message, "owner")
  605. @loader.command(ru_doc="<пользователь> - Удалить пользователя из группы `support`")
  606. async def supportrm(self, message: Message):
  607. """<user> - Remove user from `support`"""
  608. await self._remove_from_group(message, "support")
  609. @loader.command(ru_doc="Показать список пользователей в группе `sudo`")
  610. async def sudolist(self, message: Message):
  611. """List users in `sudo`"""
  612. await self._list_group(message, "sudo")
  613. @loader.command(ru_doc="Показать список пользователей в группе `owner`")
  614. async def ownerlist(self, message: Message):
  615. """List users in `owner`"""
  616. await self._list_group(message, "owner")
  617. @loader.command(ru_doc="Показать список пользователей в группе `support`")
  618. async def supportlist(self, message: Message):
  619. """List users in `support`"""
  620. await self._list_group(message, "support")