settings.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  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 os
  9. import telethon
  10. from telethon.tl.types import Message
  11. from telethon.extensions.html import CUSTOM_EMOJIS
  12. from .. import loader, main, translations, utils, version
  13. from ..inline.types import InlineCall
  14. @loader.tds
  15. class CoreMod(loader.Module):
  16. """Control core userbot settings"""
  17. strings = {
  18. "name": "Settings",
  19. "too_many_args": (
  20. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Too many args</b>"
  21. ),
  22. "blacklisted": (
  23. '<emoji document_id="5368324170671202286">👍</emoji> <b>Chat {} blacklisted'
  24. " from userbot</b>"
  25. ),
  26. "unblacklisted": (
  27. '<emoji document_id="5368324170671202286">👍</emoji> <b>Chat {}'
  28. " unblacklisted from userbot</b>"
  29. ),
  30. "user_blacklisted": (
  31. '<emoji document_id="5368324170671202286">👍</emoji> <b>User {} blacklisted'
  32. " from userbot</b>"
  33. ),
  34. "user_unblacklisted": (
  35. '<emoji document_id="5368324170671202286">👍</emoji> <b>User {}'
  36. " unblacklisted from userbot</b>"
  37. ),
  38. "what_prefix": "❓ <b>What should the prefix be set to?</b>",
  39. "prefix_incorrect": (
  40. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Prefix must be one"
  41. " symbol in length</b>"
  42. ),
  43. "prefix_set": (
  44. '<emoji document_id="5368324170671202286">👍</emoji> <b>Command prefix'
  45. " updated. Type</b> <code>{newprefix}setprefix {oldprefix}</code> <b>to"
  46. " change it back</b>"
  47. ),
  48. "alias_created": (
  49. '<emoji document_id="5368324170671202286">👍</emoji> <b>Alias created.'
  50. " Access it with</b> <code>{}</code>"
  51. ),
  52. "aliases": "<b>🔗 Aliases:</b>\n",
  53. "no_command": (
  54. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Command</b>"
  55. " <code>{}</code> <b>does not exist</b>"
  56. ),
  57. "alias_args": (
  58. "<emoji document_id=5436162517686557387>🚫</emoji> <b>You must provide a"
  59. " command and the alias for it</b>"
  60. ),
  61. "delalias_args": (
  62. "<emoji document_id=5436162517686557387>🚫</emoji> <b>You must provide the"
  63. " alias name</b>"
  64. ),
  65. "alias_removed": (
  66. '<emoji document_id="5368324170671202286">👍</emoji> <b>Alias</b>'
  67. " <code>{}</code> <b>removed</b>."
  68. ),
  69. "no_alias": (
  70. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Alias</b>"
  71. " <code>{}</code> <b>does not exist</b>"
  72. ),
  73. "db_cleared": (
  74. '<emoji document_id="5368324170671202286">👍</emoji><b> Database cleared</b>'
  75. ),
  76. "hikka": (
  77. "{}\n\n<emoji document_id=5406931726184225260>🧐</emoji> <b>Version:"
  78. " {}.{}.{}</b>\n<emoji document_id=6318902906900711458>🧱</emoji> <b>Build:"
  79. " </b><i>{}</i>\n\n<emoji document_id=5233346091725888979>⚙️</emoji>"
  80. " <b>Hikka-TL: </b><i>{}</i>\n\n<emoji"
  81. " document_id=5454182070156794055>⌨️</emoji> <b>Developer:"
  82. " t.me/hikariatama</b>"
  83. ),
  84. "check_url": (
  85. "<emoji document_id=5436162517686557387>🚫</emoji> <b>You need to specify"
  86. " valid url containing a langpack</b>"
  87. ),
  88. "lang_saved": "{} <b>Language saved!</b>",
  89. "pack_saved": (
  90. '<emoji document_id="5368324170671202286">👍</emoji> <b>Translate pack'
  91. " saved!</b>"
  92. ),
  93. "incorrect_language": (
  94. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Incorrect language"
  95. " specified</b>"
  96. ),
  97. "lang_removed": (
  98. '<emoji document_id="5368324170671202286">👍</emoji> <b>Translations reset'
  99. " to default ones</b>"
  100. ),
  101. "check_pack": (
  102. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Invalid pack format"
  103. " in url</b>"
  104. ),
  105. "confirm_cleardb": "⚠️ <b>Are you sure, that you want to clear database?</b>",
  106. "cleardb_confirm": "🗑 Clear database",
  107. "cancel": "🚫 Cancel",
  108. "who_to_blacklist": (
  109. "<emoji document_id=5384612769716774600>❓</emoji> <b>Who to blacklist?</b>"
  110. ),
  111. "who_to_unblacklist": (
  112. "<emoji document_id=5384612769716774600>❓</emoji> <b>Who to"
  113. " unblacklist?</b>"
  114. ),
  115. "unstable": (
  116. "\n\n<emoji document_id=5467370583282950466>🙈</emoji> <b>You are using an"
  117. " unstable branch </b><code>{}</code><b>!</b>"
  118. ),
  119. }
  120. strings_ru = {
  121. "too_many_args": (
  122. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Слишком много"
  123. " аргументов</b>"
  124. ),
  125. "blacklisted": (
  126. '<emoji document_id="5368324170671202286">👍</emoji> <b>Чат {} добавлен в'
  127. " черный список юзербота</b>"
  128. ),
  129. "unblacklisted": (
  130. '<emoji document_id="5368324170671202286">👍</emoji> <b>Чат {} удален из'
  131. " черного списка юзербота</b>"
  132. ),
  133. "user_blacklisted": (
  134. '<emoji document_id="5368324170671202286">👍</emoji> <b>Пользователь {}'
  135. " добавлен в черный список юзербота</b>"
  136. ),
  137. "user_unblacklisted": (
  138. '<emoji document_id="5368324170671202286">👍</emoji> <b>Пользователь {}'
  139. " удален из черного списка юзербота</b>"
  140. ),
  141. "what_prefix": "❓ <b>А какой префикс ставить то?</b>",
  142. "prefix_incorrect": (
  143. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Префикс должен"
  144. " состоять только из одного символа</b>"
  145. ),
  146. "prefix_set": (
  147. '<emoji document_id="5368324170671202286">👍</emoji> <b>Префикс обновлен.'
  148. " Чтобы вернуть его, используй</b> <code>{newprefix}setprefix"
  149. " {oldprefix}</code>"
  150. ),
  151. "alias_created": (
  152. '<emoji document_id="5368324170671202286">👍</emoji> <b>Алиас создан.'
  153. " Используй его через</b> <code>{}</code>"
  154. ),
  155. "aliases": "<b>🔗 Алиасы:</b>\n",
  156. "no_command": (
  157. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Команда</b>"
  158. " <code>{}</code> <b>не существует</b>"
  159. ),
  160. "alias_args": (
  161. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Требуется ввести"
  162. " команду и алиас для нее</b>"
  163. ),
  164. "delalias_args": (
  165. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Требуется имя"
  166. " алиаса</b>"
  167. ),
  168. "alias_removed": (
  169. '<emoji document_id="5368324170671202286">👍</emoji> <b>Алиас</b>'
  170. " <code>{}</code> <b>удален</b>."
  171. ),
  172. "no_alias": (
  173. "<emoji document_id=5436162517686557387>🚫</emoji><b> Алиас</b>"
  174. " <code>{}</code> <b>не существует</b>"
  175. ),
  176. "db_cleared": (
  177. '<emoji document_id="5368324170671202286">👍</emoji><b> База очищена</b>'
  178. ),
  179. "hikka": (
  180. "{}\n\n<emoji document_id=5406931726184225260>🧐</emoji> <b>Версия:"
  181. " {}.{}.{}</b>\n<emoji document_id=6318902906900711458>🧱</emoji> <b>Сборка:"
  182. " </b><i>{}</i>\n\n<emoji document_id=5233346091725888979>⚙️</emoji>"
  183. " <b>Hikka-TL: </b><i>{}</i>\n\n<emoji"
  184. " document_id=5454182070156794055>⌨️</emoji> <b>Developer:"
  185. " t.me/hikariatama</b>"
  186. ),
  187. "check_url": (
  188. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Укажи правильную"
  189. " ссылку, ведущую на пак с переводом</b>"
  190. ),
  191. "lang_saved": "{} <b>Язык сохранен!</b>",
  192. "pack_saved": (
  193. '<emoji document_id="5368324170671202286">👍</emoji> <b>Пак перевода'
  194. " сохранен!</b>"
  195. ),
  196. "incorrect_language": (
  197. "<emoji document_id=5436162517686557387>🚫</emoji> <b>Указан неверный"
  198. " язык</b>"
  199. ),
  200. "lang_removed": (
  201. '<emoji document_id="5368324170671202286">👍</emoji> <b>Переводы'
  202. " сброшены</b>"
  203. ),
  204. "check_pack": (
  205. "<emoji document_id=5436162517686557387>🚫</emoji> <b>По ссылке находится"
  206. " неправильный пак</b>"
  207. ),
  208. "_cls_doc": "Управление базовыми настройками юзербота",
  209. "confirm_cleardb": "⚠️ <b>Вы уверены, что хотите сбросить базу данных?</b>",
  210. "cleardb_confirm": "🗑 Очистить базу",
  211. "cancel": "🚫 Отмена",
  212. "who_to_blacklist": (
  213. "<emoji document_id=5384612769716774600>❓</emoji> <b>Кого заблокировать"
  214. " то?</b>"
  215. ),
  216. "who_to_unblacklist": (
  217. "<emoji document_id=5384612769716774600>❓</emoji> <b>Кого разблокировать"
  218. " то?</b>"
  219. ),
  220. "unstable": (
  221. "\n\n<emoji document_id=5467370583282950466>🙈</emoji> <b>Ты используешь"
  222. " нестабильную ветку </b><code>{}</code><b>!</b>"
  223. ),
  224. }
  225. async def blacklistcommon(self, message: Message):
  226. args = utils.get_args(message)
  227. if len(args) > 2:
  228. await utils.answer(message, self.strings("too_many_args"))
  229. return
  230. chatid = None
  231. module = None
  232. if args:
  233. try:
  234. chatid = int(args[0])
  235. except ValueError:
  236. module = args[0]
  237. if len(args) == 2:
  238. module = args[1]
  239. if chatid is None:
  240. chatid = utils.get_chat_id(message)
  241. module = self.allmodules.get_classname(module)
  242. return f"{str(chatid)}.{module}" if module else chatid
  243. @loader.command(ru_doc="Показать версию Hikka")
  244. async def hikkacmd(self, message: Message):
  245. """Get Hikka version"""
  246. await utils.answer(
  247. message,
  248. self.strings("hikka").format(
  249. (
  250. utils.get_platform_emoji()
  251. + (
  252. "<emoji document_id=5192756799647785066>✌️</emoji><emoji"
  253. " document_id=5193117564015747203>✌️</emoji><emoji"
  254. " document_id=5195050806105087456>✌️</emoji><emoji"
  255. " document_id=5195457642587233944>✌️</emoji>"
  256. if "LAVHOST" in os.environ
  257. else ""
  258. )
  259. )
  260. if self._client.hikka_me.premium and CUSTOM_EMOJIS
  261. else "🌘 <b>Hikka userbot</b>",
  262. *version.__version__,
  263. utils.get_commit_url(),
  264. f"{telethon.__version__} #{telethon.tl.alltlobjects.LAYER}",
  265. )
  266. + (
  267. ""
  268. if version.branch == "master"
  269. else self.strings("unstable").format(version.branch)
  270. ),
  271. )
  272. @loader.command(ru_doc="[чат] [модуль] - Отключить бота где-либо")
  273. async def blacklist(self, message: Message):
  274. """[chat_id] [module] - Blacklist the bot from operating somewhere"""
  275. chatid = await self.blacklistcommon(message)
  276. self._db.set(
  277. main.__name__,
  278. "blacklist_chats",
  279. self._db.get(main.__name__, "blacklist_chats", []) + [chatid],
  280. )
  281. await utils.answer(message, self.strings("blacklisted").format(chatid))
  282. @loader.command(ru_doc="[чат] - Включить бота где-либо")
  283. async def unblacklist(self, message: Message):
  284. """<chat_id> - Unblacklist the bot from operating somewhere"""
  285. chatid = await self.blacklistcommon(message)
  286. self._db.set(
  287. main.__name__,
  288. "blacklist_chats",
  289. list(set(self._db.get(main.__name__, "blacklist_chats", [])) - {chatid}),
  290. )
  291. await utils.answer(message, self.strings("unblacklisted").format(chatid))
  292. async def getuser(self, message: Message):
  293. try:
  294. return int(utils.get_args(message)[0])
  295. except (ValueError, IndexError):
  296. reply = await message.get_reply_message()
  297. if reply:
  298. return reply.sender_id
  299. return message.to_id.user_id if message.is_private else False
  300. @loader.command(ru_doc="[пользователь] - Запретить пользователю выполнять команды")
  301. async def blacklistuser(self, message: Message):
  302. """[user_id] - Prevent this user from running any commands"""
  303. user = await self.getuser(message)
  304. if not user:
  305. await utils.answer(message, self.strings("who_to_blacklist"))
  306. return
  307. self._db.set(
  308. main.__name__,
  309. "blacklist_users",
  310. self._db.get(main.__name__, "blacklist_users", []) + [user],
  311. )
  312. await utils.answer(message, self.strings("user_blacklisted").format(user))
  313. @loader.command(ru_doc="[пользователь] - Разрешить пользователю выполнять команды")
  314. async def unblacklistuser(self, message: Message):
  315. """[user_id] - Allow this user to run permitted commands"""
  316. user = await self.getuser(message)
  317. if not user:
  318. await utils.answer(message, self.strings("who_to_unblacklist"))
  319. return
  320. self._db.set(
  321. main.__name__,
  322. "blacklist_users",
  323. list(set(self._db.get(main.__name__, "blacklist_users", [])) - {user}),
  324. )
  325. await utils.answer(
  326. message,
  327. self.strings("user_unblacklisted").format(user),
  328. )
  329. @loader.owner
  330. @loader.command(ru_doc="<префикс> - Установить префикс команд")
  331. async def setprefix(self, message: Message):
  332. """<prefix> - Sets command prefix"""
  333. args = utils.get_args_raw(message)
  334. if not args:
  335. await utils.answer(message, self.strings("what_prefix"))
  336. return
  337. if len(args) != 1:
  338. await utils.answer(message, self.strings("prefix_incorrect"))
  339. return
  340. oldprefix = self.get_prefix()
  341. self._db.set(main.__name__, "command_prefix", args)
  342. await utils.answer(
  343. message,
  344. self.strings("prefix_set").format(
  345. newprefix=utils.escape_html(args[0]),
  346. oldprefix=utils.escape_html(oldprefix),
  347. ),
  348. )
  349. @loader.owner
  350. @loader.command(ru_doc="Показать список алиасов")
  351. async def aliases(self, message: Message):
  352. """Print all your aliases"""
  353. aliases = self.allmodules.aliases
  354. string = self.strings("aliases")
  355. string += "\n".join(
  356. [f"▫️ <code>{i}</code> &lt;- {y}" for i, y in aliases.items()]
  357. )
  358. await utils.answer(message, string)
  359. @loader.owner
  360. @loader.command(ru_doc="Установить алиас для команды")
  361. async def addalias(self, message: Message):
  362. """Set an alias for a command"""
  363. args = utils.get_args(message)
  364. if len(args) != 2:
  365. await utils.answer(message, self.strings("alias_args"))
  366. return
  367. alias, cmd = args
  368. if self.allmodules.add_alias(alias, cmd):
  369. self.set(
  370. "aliases",
  371. {
  372. **self.get("aliases", {}),
  373. alias: cmd,
  374. },
  375. )
  376. await utils.answer(
  377. message,
  378. self.strings("alias_created").format(utils.escape_html(alias)),
  379. )
  380. else:
  381. await utils.answer(
  382. message,
  383. self.strings("no_command").format(utils.escape_html(cmd)),
  384. )
  385. @loader.owner
  386. @loader.command(ru_doc="Удалить алиас для команды")
  387. async def delalias(self, message: Message):
  388. """Remove an alias for a command"""
  389. args = utils.get_args(message)
  390. if len(args) != 1:
  391. await utils.answer(message, self.strings("delalias_args"))
  392. return
  393. alias = args[0]
  394. removed = self.allmodules.remove_alias(alias)
  395. if not removed:
  396. await utils.answer(
  397. message,
  398. self.strings("no_alias").format(utils.escape_html(alias)),
  399. )
  400. return
  401. current = self.get("aliases", {})
  402. del current[alias]
  403. self.set("aliases", current)
  404. await utils.answer(
  405. message,
  406. self.strings("alias_removed").format(utils.escape_html(alias)),
  407. )
  408. @loader.command(ru_doc="[ссылка на пак] - Изменить внешний пак перевода")
  409. async def dllangpackcmd(self, message: Message):
  410. """[link to a langpack | empty to remove] - Change Hikka translate pack (external)
  411. """
  412. args = utils.get_args_raw(message)
  413. if not args:
  414. self._db.set(translations.__name__, "pack", False)
  415. await self.translator.init()
  416. await utils.answer(message, self.strings("lang_removed"))
  417. return
  418. if not utils.check_url(args):
  419. await utils.answer(message, self.strings("check_url"))
  420. return
  421. self._db.set(translations.__name__, "pack", args)
  422. success = await self.translator.init()
  423. await utils.answer(
  424. message, self.strings("pack_saved" if success else "check_pack")
  425. )
  426. @loader.command(ru_doc="[языки] - Изменить стандартный язык")
  427. async def setlang(self, message: Message):
  428. """[languages in the order of priority] - Change default language"""
  429. args = utils.get_args_raw(message)
  430. if not args or any(len(i) != 2 for i in args.split(" ")):
  431. await utils.answer(message, self.strings("incorrect_language"))
  432. return
  433. self._db.set(translations.__name__, "lang", args.lower())
  434. await self.translator.init()
  435. await utils.answer(
  436. message,
  437. self.strings("lang_saved").format(
  438. "".join(
  439. [
  440. utils.get_lang_flag(
  441. lang.lower() if lang.lower() != "en" else "gb"
  442. )
  443. for lang in args.lower().split(" ")
  444. ]
  445. )
  446. ),
  447. )
  448. @loader.owner
  449. @loader.command(ru_doc="Очистить базу данных")
  450. async def cleardb(self, message: Message):
  451. """Clear the entire database, effectively performing a factory reset"""
  452. await self.inline.form(
  453. self.strings("confirm_cleardb"),
  454. message,
  455. reply_markup=[
  456. {
  457. "text": self.strings("cleardb_confirm"),
  458. "callback": self._inline__cleardb,
  459. },
  460. {
  461. "text": self.strings("cancel"),
  462. "action": "close",
  463. },
  464. ],
  465. )
  466. async def _inline__cleardb(self, call: InlineCall):
  467. self._db.clear()
  468. self._db.save()
  469. await utils.answer(call, self.strings("db_cleared"))