actions.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. import re
  2. from random import uniform
  3. from asyncio import sleep
  4. from aiohttp import ClientSession
  5. from tortoise.contrib.postgres.functions import Random
  6. from telethon.utils import get_input_document
  7. from telethon.tl.functions.stickers import (
  8. CreateStickerSetRequest,
  9. AddStickerToSetRequest,
  10. )
  11. from telethon.tl.functions.messages import UploadMediaRequest
  12. from telethon.tl.types import (
  13. InputStickerSetID,
  14. InputStickerSetItem,
  15. InputMediaUploadedDocument,
  16. InputPeerSelf,
  17. )
  18. from tortoise.expressions import F
  19. from models import (
  20. Action,
  21. Gif,
  22. StickerPack,
  23. Admin,
  24. BirthDay,
  25. VPNServer,
  26. AllowedChat,
  27. MarkovChat,
  28. )
  29. from utils import is_valid_name, is_valid_ip, remove_ansi_escapes
  30. from config import config
  31. async def is_admin(bot, user):
  32. admin = await bot.get_entity(config.ADMIN)
  33. if user.id == admin.id:
  34. return True
  35. admin = await Admin.filter(user_id=user.id)
  36. if admin:
  37. return True
  38. return False
  39. async def add_admin(user):
  40. await Admin(user_id=user.id).save()
  41. async def delete_admin(user):
  42. admin = await Admin.filter(user_id=user.id).first()
  43. if not admin:
  44. raise IndexError
  45. await admin.delete()
  46. async def create_action(name, template, kind):
  47. if not is_valid_name(name):
  48. raise SyntaxError
  49. await Action(name=name, template=template, kind=kind).save()
  50. async def find_action(name):
  51. if not is_valid_name(name):
  52. raise SyntaxError
  53. return await Action.filter(name=name).first()
  54. async def delete_action(name):
  55. action = await find_action(name)
  56. if not action:
  57. raise NameError
  58. gifs = await action.gifs.all()
  59. for gif in gifs:
  60. await gif.delete()
  61. await action.delete()
  62. async def add_gif(action, file_id):
  63. await Gif(action=action, file_id=file_id).save()
  64. async def get_random_gif(action):
  65. return await action.gifs.all().annotate(order=Random()).order_by("order").first()
  66. async def create_new_pack(bot, sticker):
  67. last_pack = await StickerPack.all().order_by("-id").first()
  68. set_id = last_pack.id + 1 if last_pack else 1
  69. user = await bot.get_entity(config.USER)
  70. me = await bot.get_me()
  71. bot_username = me.username
  72. pack = await bot(
  73. CreateStickerSetRequest(
  74. user_id=user.id,
  75. title=f"Messages #{set_id}.",
  76. short_name=f"messages{set_id}_by_{bot_username}",
  77. stickers=[sticker],
  78. )
  79. )
  80. sid = pack.set.id
  81. hash = pack.set.access_hash
  82. await StickerPack(short_name=pack.set.short_name, sid=sid, hash=hash).save()
  83. return pack
  84. async def get_current_pack(bot):
  85. pack = await StickerPack.all().order_by("-id").first()
  86. if not pack or pack.stickers_count >= 119:
  87. return None
  88. return pack
  89. async def add_sticker(bot, file, emoji):
  90. file = await bot.upload_file(file)
  91. file = InputMediaUploadedDocument(file, "image/png", [])
  92. file = await bot(UploadMediaRequest(InputPeerSelf(), file))
  93. file = get_input_document(file)
  94. sticker = InputStickerSetItem(document=file, emoji=emoji)
  95. pack = await get_current_pack(bot)
  96. if not pack:
  97. pack = await create_new_pack(bot, sticker)
  98. else:
  99. await StickerPack.filter(id=pack.id).update(
  100. stickers_count=F("stickers_count") + 1
  101. )
  102. pack = await bot(
  103. AddStickerToSetRequest(
  104. stickerset=InputStickerSetID(id=pack.sid, access_hash=pack.hash),
  105. sticker=sticker,
  106. )
  107. )
  108. return get_input_document(pack.documents[-1])
  109. async def get_birthdays(peer_id):
  110. return await BirthDay.filter(peer_id=peer_id).all()
  111. async def add_or_update_birthday(peer_id, user, date):
  112. birthday = await BirthDay.filter(peer_id=peer_id, user_id=user.id).first()
  113. if birthday:
  114. await BirthDay.filter(id=birthday.id).update(date=date)
  115. return False
  116. await BirthDay(peer_id=peer_id, user_id=user.id, date=date).save()
  117. return True
  118. async def get_all_birthdays():
  119. return await BirthDay.all()
  120. async def add_server(name, ip):
  121. if not is_valid_ip(ip):
  122. raise ValueError
  123. await VPNServer(name=name, ip=ip).save()
  124. async def add_server(name, ip):
  125. if not is_valid_name(name):
  126. raise SyntaxError
  127. if not is_valid_ip(ip):
  128. raise ValueError
  129. await VPNServer(name=name, ip=ip).save()
  130. async def delete_server(name):
  131. if not is_valid_name(name):
  132. raise SyntaxError
  133. server = await VPNServer.filter(name=name).first()
  134. if not server:
  135. raise IndexError
  136. await server.delete()
  137. async def list_servers():
  138. servers = await VPNServer.all()
  139. if not servers:
  140. return "*пусто*"
  141. return ", ".join(map(lambda server: server.name, servers))
  142. async def get_server_ip(name):
  143. if not is_valid_name(name):
  144. raise SyntaxError
  145. server = await VPNServer.filter(name=name).first()
  146. if not server:
  147. raise IndexError
  148. return server.ip
  149. async def add_allowed(peer_id):
  150. await AllowedChat(peer_id=peer_id).save()
  151. async def delete_allowed(peer_id):
  152. chat = await AllowedChat.filter(peer_id=peer_id).first()
  153. if not chat:
  154. raise IndexError
  155. await chat.delete()
  156. async def is_allowed(peer_id):
  157. return await AllowedChat.filter(peer_id=peer_id).exists()
  158. async def is_markov_enabled(peer_id):
  159. return await MarkovChat.filter(peer_id=peer_id).exists()
  160. async def enable_markov(peer_id):
  161. await MarkovChat(peer_id=peer_id).save()
  162. async def set_markov_options(peer_id, **options):
  163. chat = await MarkovChat.filter(peer_id=peer_id).first()
  164. if not chat:
  165. raise IndexError
  166. await MarkovChat.filter(id=chat.id).update(**options)
  167. async def get_markov_option(peer_id, option):
  168. chat = await MarkovChat.filter(peer_id=peer_id).first()
  169. if not chat:
  170. raise IndexError
  171. return getattr(chat, option)
  172. async def disable_markov(peer_id):
  173. chat = await MarkovChat.filter(peer_id=peer_id).first()
  174. if not chat:
  175. raise IndexError
  176. await chat.delete()
  177. async def list_markov_chats():
  178. return await MarkovChat.all()
  179. async def markov_say(bot, peer_id, reply_to=None, init_state=None):
  180. if not bot.markov.is_ready:
  181. return
  182. text = bot.markov.generate(init_state)
  183. async with bot.action(peer_id, "typing"):
  184. amount = 0
  185. for _ in range(len(text)):
  186. amount += round(uniform(0.05, 0.2), 2)
  187. await sleep(min(amount, 8))
  188. await bot.send_message(peer_id, message=text, reply_to=reply_to)
  189. async def run(text):
  190. match = re.match(r"^(\w+)(?:\s|\n)((?:\n|.)*)$", text)
  191. if not match:
  192. return None, None, "Пожалуйста, не оставляйте ввод пустым!"
  193. language_name, text = match.groups()
  194. text = re.sub(r"^```\w+\n((?:\n|.)*)```$", r"\1", text)
  195. if text.startswith("```") and text.endswith("```"):
  196. text = text[3:-3]
  197. text = text.replace("\xa0", " ") # i hate telegram
  198. input_text = text
  199. async with ClientSession() as session:
  200. try:
  201. async with session.post(
  202. f"https://farlands.txlyre.website/run/{language_name}", data=text
  203. ) as resp:
  204. if resp.status in (404, 500):
  205. info = await resp.json()
  206. return (
  207. language_name,
  208. input_text,
  209. f"Произошла ошибка при попытке обращения к API… :(\nОтвет API: {info['detail']}",
  210. )
  211. elif resp.status != 200:
  212. return (
  213. language_name,
  214. input_text,
  215. "Сервер API временно недоступен. Пожалуйста, попробуйте ещё раз чуть позже.",
  216. )
  217. text = await resp.read()
  218. text = text.decode("UTF-8")[:4096]
  219. except Exception:
  220. return (
  221. language_name,
  222. input_text,
  223. "Произошла ошибка при попытке обращения к API… :(",
  224. )
  225. text = remove_ansi_escapes(text).strip()
  226. text = filter(
  227. lambda c: (c in " \t\n" or ord(c) >= 32) and ord(c) not in range(128, 159), text
  228. )
  229. text = "".join(text)
  230. text = text.replace("`", "")
  231. if not text:
  232. return language_name, input_text, "<пусто>"
  233. return language_name, input_text, f"```\n{text}```"