openkriemy.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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
  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:
  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().lower()
  70. if re.match(r"^[a-h][1-8][a-h][1-8]$", text):
  71. text = f"/chess m {text}"
  72. else:
  73. text = f"/chess {text}"
  74. await COMMANDS["chess"].handler(bot, event, parse_command(text))
  75. return
  76. if await is_markov_enabled(peer_id):
  77. markov.extend_corpus(text)
  78. for word in config.MARKOV_TRIGGER_WORDS:
  79. if word.lower() in text.lower() and random() > 0.5:
  80. await markov_say(bot, peer_id, reply_to=event)
  81. return
  82. reply_prob = await get_markov_option(peer_id, "opt_reply_prob")
  83. reply = await event.get_reply_message()
  84. if (
  85. reply
  86. and get_peer_id(reply.from_id) == await bot.get_peer_id("me")
  87. and random() > 0.5
  88. ) or random() > reply_prob:
  89. await markov_say(bot, peer_id, reply_to=event)
  90. return
  91. handler = COMMANDS.get(command.name, None)
  92. if handler and handler.is_public:
  93. await handler.handler(bot, event, command)
  94. return
  95. action = None
  96. try:
  97. action = await find_action(command.name)
  98. except (SyntaxError, ConfigurationError):
  99. pass
  100. if not await is_allowed(peer_id):
  101. if not action and (not handler or not handler.is_restricted):
  102. return
  103. if handler:
  104. if handler.is_restricted and not await is_admin(bot, event.sender):
  105. await event.reply("К сожалению, данная команда Вам недоступна.")
  106. else:
  107. await handler.handler(bot, event, command)
  108. return
  109. if not action:
  110. return
  111. reply_to = None
  112. target = None
  113. if action.kind != Kind.NO_TARGET:
  114. target = await event.get_reply_message()
  115. if not target:
  116. try:
  117. target = await bot.get_entity(command.args[0])
  118. except (ValueError, IndexError):
  119. if action.kind != Kind.NO_TARGET_MAYBE:
  120. await event.reply("Это действие нужно применить на кого-то!")
  121. return
  122. else:
  123. reply_to = target
  124. target = target.sender
  125. if target is None:
  126. target = await bot.get_entity(event.peer_id.channel_id)
  127. if action.kind == Kind.CANNOT_APPLY_TO_SELF and target.id == event.sender.id:
  128. await event.reply("Данное действие нельзя применять к самому себе...")
  129. return
  130. try:
  131. await event.delete()
  132. except Exception:
  133. pass
  134. if event.sender is None:
  135. initiator = await bot.get_entity(event.peer_id.channel_id)
  136. initiator = initiator.title
  137. else:
  138. initiator = get_link_to_user(event.sender)
  139. text = action.template.format(
  140. **{"initiator": initiator, "target": get_link_to_user(target) if target else ""}
  141. )
  142. gif = await get_random_gif(action)
  143. if gif:
  144. gif = resolve_bot_file_id(gif.file_id)
  145. await bot.send_message(event.peer_id, message=text, file=gif, reply_to=reply_to)
  146. async def notify_birthdays():
  147. birthdays = await get_all_birthdays()
  148. for birthday in birthdays:
  149. age = calculate_age(birthday.date)
  150. if age.days_until < 1:
  151. try:
  152. try:
  153. entity = await bot.get_entity(birthday.user_id)
  154. except ValueError:
  155. await bot.get_participants(birthday.peer_id)
  156. entity = await bot.get_entity(birthday.user_id)
  157. await bot.send_message(
  158. birthday.peer_id,
  159. f"{get_link_to_user(entity)}, поздравляю с днём рождения!!~~",
  160. )
  161. except Exception:
  162. pass
  163. async def notify_birthdays_loop():
  164. interval = datetime.combine(date.today(), time(hour=0, minute=0))
  165. while True:
  166. await sleep(((interval - datetime.now()) % timedelta(days=1)).total_seconds())
  167. await notify_birthdays()
  168. async def markov_say_loop():
  169. while True:
  170. await sleep(randint(30, 60 * 5))
  171. for chat in await list_markov_chats():
  172. if random() > chat.opt_message_prob:
  173. await markov_say(bot, chat.peer_id)
  174. async def chess_cleanup():
  175. while True:
  176. await sleep(60 * 60)
  177. await chess.cleanup()
  178. with bot:
  179. bot.loop.run_until_complete(init_db())
  180. bot.loop.create_task(notify_birthdays_loop())
  181. bot.loop.create_task(markov_say_loop())
  182. if chess:
  183. bot.loop.create_task(chess_cleanup())
  184. bot.start()
  185. bot.run_until_disconnected()