utils.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. from uuid import uuid4
  2. from enum import IntEnum
  3. from datetime import datetime
  4. from collections import namedtuple
  5. from telethon.utils import get_display_name
  6. from telethon.tl.types import MessageEntityBold, MessageEntityItalic, MessageEntityStrike, MessageEntityCode
  7. Command = namedtuple(
  8. 'Command',
  9. 'name argc args args_string'
  10. )
  11. Age = namedtuple(
  12. 'Age',
  13. 'days_until age age_now date_string'
  14. )
  15. class Kind(IntEnum):
  16. CANNOT_APPLY_TO_SELF = 0
  17. CAN_APPLY_TO_SELF = 1
  18. NO_TARGET = 2
  19. class WordKind(IntEnum):
  20. FIRST = 0 # «год» / «день».
  21. SECOND = 1 # «лет» / «дней».
  22. THIRD = 2 # «года» / «дня».
  23. WORDS_TABLE = {
  24. 'год': ('год', 'лет', 'года'),
  25. 'день': ('день', 'дней', 'дня')
  26. }
  27. def parse_command(text):
  28. text = text.strip()
  29. if not text.startswith('/'):
  30. raise ValueError
  31. text = text.split(' ')
  32. if len(text) < 1:
  33. raise ValueError
  34. command = text[0][1:].lower()
  35. if '@' in command:
  36. command = command.split('@')
  37. command = command[0]
  38. args = text[1:]
  39. argc = len(args)
  40. args_string = ' '.join(args)
  41. return Command(
  42. name=command,
  43. argc=argc,
  44. args=args,
  45. args_string=args_string
  46. )
  47. def get_user_name(user):
  48. full_name = get_display_name(user)
  49. if not full_name:
  50. full_name = user.username
  51. if not full_name:
  52. full_name = '?'
  53. return full_name
  54. def get_link_to_user(user):
  55. full_name = get_user_name(user)
  56. if user.username:
  57. return f'[{full_name}](@{user.username})'
  58. return f'[{full_name}](tg://user?id={user.id})'
  59. def is_valid_name(name):
  60. return name.isidentifier()
  61. def make_temporary_filename(ext):
  62. uid = uuid4().hex
  63. return f'tmp_{uid}.{ext}'
  64. def parse_kind(kind):
  65. kind = int(kind)
  66. if kind < 0 or kind > 2:
  67. raise ValueError
  68. return kind
  69. # Bruh?
  70. def get_word_kind(number):
  71. if number == 0 or 5 <= number <= 20:
  72. return WordKind.SECOND
  73. last_digit = number % 10
  74. if last_digit == 0:
  75. return WordKind.SECOND
  76. if last_digit == 1:
  77. return WordKind.FIRST
  78. if 5 <= last_digit <= 9:
  79. return WordKind.SECOND
  80. return WordKind.THIRD
  81. def get_word_for(word, number):
  82. return f'{number} {WORDS_TABLE[word][get_word_kind(number)]}'
  83. def calculate_age(date):
  84. now = datetime.now().date()
  85. birthday_date = date.replace(year=now.year)
  86. if now > birthday_date:
  87. birthday_date = date.replace(year=now.year + 1)
  88. delta = birthday_date - now
  89. age = (birthday_date - date).days // 365
  90. age_now = age - 1
  91. return Age(
  92. days_until=delta.days,
  93. age=age,
  94. age_now=age_now,
  95. date_string=date.strftime('%d.%m.%Y')
  96. )
  97. DELIMITERS = {
  98. MessageEntityBold: '**',
  99. MessageEntityItalic: '__',
  100. MessageEntityStrike: '~~',
  101. MessageEntityCode: '`',
  102. }
  103. class LookupTable:
  104. def __init__(self):
  105. self._start = {}
  106. self._end = {}
  107. def insert(self, entity):
  108. delimiter = DELIMITERS.get(type(entity))
  109. if not delimiter:
  110. return
  111. start = entity.offset
  112. end = entity.offset + entity.length
  113. if start in self._start:
  114. self._start[start].append(delimiter)
  115. else:
  116. self._start[start] = [delimiter]
  117. if end in self._end:
  118. self._end[end].insert(0, delimiter)
  119. else:
  120. self._end[end] = [delimiter]
  121. def _lookup(self, position):
  122. if position in self._start:
  123. return ''.join(self._start[position])
  124. elif position in self._end:
  125. return ''.join(self._end[position])
  126. def process(self, text):
  127. text = list(text) + ['']
  128. result = ''
  129. for position, character in zip(range(len(text)), text):
  130. delimiter = self._lookup(position)
  131. if delimiter:
  132. result += delimiter
  133. result += character
  134. return result
  135. def unparse(text, entities):
  136. table = LookupTable()
  137. for entity in entities:
  138. table.insert(entity)
  139. return table.process(text)