utils.py 4.1 KB

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