openkriemy.py 6.8 KB

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