openkriemy.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import re
  2. from random import random, randint
  3. from asyncio import sleep
  4. from datetime import datetime, timedelta, date, time
  5. from telethon import TelegramClient
  6. from telethon.events import NewMessage, InlineQuery
  7. from telethon.utils import resolve_bot_file_id, get_peer_id
  8. from tortoise.exceptions import ConfigurationError
  9. from actions import get_all_birthdays
  10. from utils import parse_command, get_link_to_user, calculate_age, Kind
  11. from config import config
  12. from db import init_db
  13. from actions import (
  14. find_action,
  15. get_random_gif,
  16. is_admin,
  17. is_allowed,
  18. is_markov_enabled,
  19. get_markov_option,
  20. list_markov_chats,
  21. markov_say,
  22. run,
  23. )
  24. from commands import COMMANDS, CHESS_COMMANDS, CHESS_ALIASES
  25. from markov import Markov
  26. from chess0 import ChessManager
  27. bot = TelegramClient("openkriemy", config.API_ID, config.API_HASH).start(
  28. bot_token=config.API_TOKEN
  29. )
  30. markov = Markov()
  31. if config.CHESS_UCI_ENGINE:
  32. chess = ChessManager(config.CHESS_UCI_ENGINE)
  33. else:
  34. chess = None
  35. # Wait isn't that illegal??
  36. bot.markov = markov
  37. bot.chess = chess
  38. @bot.on(InlineQuery)
  39. async def on_inline_query(event):
  40. text = event.text.strip()
  41. if not text:
  42. return
  43. lang, input_text, result = await run(text)
  44. if not lang:
  45. await event.answer(
  46. [
  47. event.builder.article(result, text=result),
  48. ]
  49. )
  50. return
  51. await event.answer(
  52. [
  53. event.builder.article(
  54. "Результат.",
  55. text=f"Язык: {lang}\nКод:```\n{input_text.replace('`', '')}```Результат: {result}",
  56. ),
  57. ]
  58. )
  59. @bot.on(NewMessage)
  60. async def on_message(event):
  61. peer_id = get_peer_id(event.peer_id)
  62. text = event.text
  63. try:
  64. command = parse_command(text)
  65. except ValueError:
  66. if chess and (event.sender.id in chess.sessions or str(peer_id) in chess.sessions):
  67. reply = await event.get_reply_message()
  68. if reply and get_peer_id(reply.from_id) == await bot.get_peer_id("me") and reply.media:
  69. text = text.strip()
  70. cmd = text.lower().split(" ")[0]
  71. if cmd not in CHESS_COMMANDS and cmd not in CHESS_ALIASES:
  72. text = f"/chess m {text}"
  73. else:
  74. text = f"/chess {text}"
  75. await COMMANDS["chess"].handler(bot, event, parse_command(text))
  76. return
  77. if await is_markov_enabled(peer_id):
  78. markov.extend_corpus(text)
  79. for word in config.MARKOV_TRIGGER_WORDS:
  80. if word.lower() in text.lower() and random() > 0.5:
  81. await markov_say(bot, peer_id, reply_to=event)
  82. return
  83. reply_prob = await get_markov_option(peer_id, "opt_reply_prob")
  84. reply = await event.get_reply_message()
  85. if (
  86. reply
  87. and get_peer_id(reply.from_id) == await bot.get_peer_id("me")
  88. and random() > 0.5
  89. ) or random() > reply_prob:
  90. await markov_say(bot, peer_id, reply_to=event)
  91. return
  92. handler = COMMANDS.get(command.name, None)
  93. if handler and handler.is_public:
  94. await handler.handler(bot, event, command)
  95. return
  96. action = None
  97. try:
  98. action = await find_action(command.name)
  99. except (SyntaxError, ConfigurationError):
  100. pass
  101. if not await is_allowed(peer_id):
  102. if not action and (not handler or not handler.is_restricted):
  103. return
  104. if handler:
  105. if handler.is_restricted and not await is_admin(bot, event.sender):
  106. await event.reply("К сожалению, данная команда Вам недоступна.")
  107. else:
  108. await handler.handler(bot, event, command)
  109. return
  110. if not action:
  111. return
  112. reply_to = None
  113. target = None
  114. if action.kind != Kind.NO_TARGET:
  115. target = await event.get_reply_message()
  116. if not target:
  117. try:
  118. target = await bot.get_entity(command.args[0])
  119. except (ValueError, IndexError):
  120. if action.kind != Kind.NO_TARGET_MAYBE:
  121. await event.reply("Это действие нужно применить на кого-то!")
  122. return
  123. else:
  124. reply_to = target
  125. target = target.sender
  126. if target is None:
  127. target = await bot.get_entity(event.peer_id.channel_id)
  128. if action.kind == Kind.CANNOT_APPLY_TO_SELF and target.id == event.sender.id:
  129. await event.reply("Данное действие нельзя применять к самому себе...")
  130. return
  131. try:
  132. await event.delete()
  133. except Exception:
  134. pass
  135. if event.sender is None:
  136. initiator = await bot.get_entity(event.peer_id.channel_id)
  137. initiator = initiator.title
  138. else:
  139. initiator = get_link_to_user(event.sender)
  140. text = action.template.format(
  141. **{"initiator": initiator, "target": get_link_to_user(target) if target else ""}
  142. )
  143. gif = await get_random_gif(action)
  144. if gif:
  145. gif = resolve_bot_file_id(gif.file_id)
  146. await bot.send_message(event.peer_id, message=text, file=gif, reply_to=reply_to)
  147. async def notify_birthdays():
  148. birthdays = await get_all_birthdays()
  149. for birthday in birthdays:
  150. age = calculate_age(birthday.date)
  151. if age.days_until < 1:
  152. try:
  153. try:
  154. entity = await bot.get_entity(birthday.user_id)
  155. except ValueError:
  156. await bot.get_participants(birthday.peer_id)
  157. entity = await bot.get_entity(birthday.user_id)
  158. await bot.send_message(
  159. birthday.peer_id,
  160. f"{get_link_to_user(entity)}, поздравляю с днём рождения!!~~",
  161. )
  162. except Exception:
  163. pass
  164. async def notify_birthdays_loop():
  165. interval = datetime.combine(date.today(), time(hour=0, minute=0))
  166. while True:
  167. await sleep(((interval - datetime.now()) % timedelta(days=1)).total_seconds())
  168. await notify_birthdays()
  169. async def markov_say_loop():
  170. while True:
  171. await sleep(randint(30, 60 * 5))
  172. for chat in await list_markov_chats():
  173. if random() > chat.opt_message_prob:
  174. await markov_say(bot, chat.peer_id)
  175. async def chess_cleanup():
  176. while True:
  177. await sleep(60 * 60)
  178. await chess.cleanup()
  179. with bot:
  180. bot.loop.run_until_complete(init_db())
  181. bot.loop.create_task(notify_birthdays_loop())
  182. bot.loop.create_task(markov_say_loop())
  183. if chess:
  184. bot.loop.create_task(chess_cleanup())
  185. bot.start()
  186. bot.run_until_disconnected()