smart-bot-factory 0.3.6__py3-none-any.whl → 0.3.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of smart-bot-factory might be problematic. Click here for more details.
- smart_bot_factory/admin/__init__.py +7 -7
- smart_bot_factory/admin/admin_events.py +483 -383
- smart_bot_factory/admin/admin_logic.py +234 -158
- smart_bot_factory/admin/admin_manager.py +68 -53
- smart_bot_factory/admin/admin_tester.py +46 -40
- smart_bot_factory/admin/timeout_checker.py +201 -153
- smart_bot_factory/aiogram_calendar/__init__.py +11 -3
- smart_bot_factory/aiogram_calendar/common.py +12 -18
- smart_bot_factory/aiogram_calendar/dialog_calendar.py +126 -64
- smart_bot_factory/aiogram_calendar/schemas.py +49 -28
- smart_bot_factory/aiogram_calendar/simple_calendar.py +94 -50
- smart_bot_factory/analytics/analytics_manager.py +414 -392
- smart_bot_factory/cli.py +204 -148
- smart_bot_factory/config.py +123 -102
- smart_bot_factory/core/bot_utils.py +480 -324
- smart_bot_factory/core/conversation_manager.py +287 -200
- smart_bot_factory/core/decorators.py +1145 -739
- smart_bot_factory/core/message_sender.py +287 -266
- smart_bot_factory/core/router.py +170 -100
- smart_bot_factory/core/router_manager.py +121 -83
- smart_bot_factory/core/states.py +4 -3
- smart_bot_factory/creation/__init__.py +1 -1
- smart_bot_factory/creation/bot_builder.py +320 -242
- smart_bot_factory/creation/bot_testing.py +440 -365
- smart_bot_factory/dashboard/__init__.py +1 -3
- smart_bot_factory/event/__init__.py +2 -7
- smart_bot_factory/handlers/handlers.py +682 -466
- smart_bot_factory/integrations/openai_client.py +218 -168
- smart_bot_factory/integrations/supabase_client.py +928 -637
- smart_bot_factory/message/__init__.py +18 -22
- smart_bot_factory/router/__init__.py +2 -2
- smart_bot_factory/setup_checker.py +162 -126
- smart_bot_factory/supabase/__init__.py +1 -1
- smart_bot_factory/supabase/client.py +631 -515
- smart_bot_factory/utils/__init__.py +2 -3
- smart_bot_factory/utils/debug_routing.py +38 -27
- smart_bot_factory/utils/prompt_loader.py +153 -120
- smart_bot_factory/utils/user_prompt_loader.py +55 -56
- smart_bot_factory/utm_link_generator.py +123 -116
- {smart_bot_factory-0.3.6.dist-info → smart_bot_factory-0.3.8.dist-info}/METADATA +3 -1
- smart_bot_factory-0.3.8.dist-info/RECORD +59 -0
- smart_bot_factory-0.3.6.dist-info/RECORD +0 -59
- {smart_bot_factory-0.3.6.dist-info → smart_bot_factory-0.3.8.dist-info}/WHEEL +0 -0
- {smart_bot_factory-0.3.6.dist-info → smart_bot_factory-0.3.8.dist-info}/entry_points.txt +0 -0
- {smart_bot_factory-0.3.6.dist-info → smart_bot_factory-0.3.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
from .common import get_user_locale
|
|
2
|
-
from .simple_calendar import SimpleCalendar
|
|
3
2
|
from .dialog_calendar import DialogCalendar
|
|
4
|
-
from .schemas import
|
|
3
|
+
from .schemas import (CalendarLabels, DialogCalendarCallback,
|
|
4
|
+
SimpleCalendarCallback)
|
|
5
|
+
from .simple_calendar import SimpleCalendar
|
|
5
6
|
|
|
6
|
-
__all__ = [
|
|
7
|
+
__all__ = [
|
|
8
|
+
"SimpleCalendar",
|
|
9
|
+
"DialogCalendar",
|
|
10
|
+
"SimpleCalendarCallback",
|
|
11
|
+
"DialogCalendarCallback",
|
|
12
|
+
"CalendarLabels",
|
|
13
|
+
"get_user_locale",
|
|
14
|
+
]
|
|
@@ -1,41 +1,35 @@
|
|
|
1
1
|
import calendar
|
|
2
2
|
import locale
|
|
3
|
+
from datetime import datetime
|
|
3
4
|
|
|
4
5
|
from aiogram.types import User
|
|
5
|
-
from datetime import datetime
|
|
6
6
|
|
|
7
7
|
from .schemas import CalendarLabels
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
async def get_user_locale(from_user: User) -> str:
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
return locale.locale_alias[loc].split(".")[0]
|
|
11
|
+
"Always returns ru_RU locale for consistent Russian language support"
|
|
12
|
+
return "ru_RU"
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class GenericCalendar:
|
|
17
16
|
|
|
18
17
|
def __init__(
|
|
19
18
|
self,
|
|
20
|
-
locale: str = None,
|
|
19
|
+
locale: str = None, # оставляем для обратной совместимости
|
|
21
20
|
cancel_btn: str = None,
|
|
22
21
|
today_btn: str = None,
|
|
23
|
-
show_alerts: bool = False
|
|
22
|
+
show_alerts: bool = False,
|
|
24
23
|
) -> None:
|
|
25
|
-
"""
|
|
24
|
+
"""Initialize calendar with Russian language by default
|
|
26
25
|
|
|
27
26
|
Parameters:
|
|
28
|
-
locale (str):
|
|
27
|
+
locale (str): Ignored, always uses Russian
|
|
29
28
|
cancel_btn (str): label for button Cancel to cancel date input
|
|
30
29
|
today_btn (str): label for button Today to set calendar back to todays date
|
|
31
30
|
show_alerts (bool): defines how the date range error would shown (defaults to False)
|
|
32
31
|
"""
|
|
33
32
|
self._labels = CalendarLabels()
|
|
34
|
-
if locale:
|
|
35
|
-
# getting month names and days of week in specified locale
|
|
36
|
-
with calendar.different_locale(locale):
|
|
37
|
-
self._labels.days_of_week = list(calendar.day_abbr)
|
|
38
|
-
self._labels.months = calendar.month_abbr[1:]
|
|
39
33
|
|
|
40
34
|
if cancel_btn:
|
|
41
35
|
self._labels.cancel_caption = cancel_btn
|
|
@@ -56,15 +50,15 @@ class GenericCalendar:
|
|
|
56
50
|
date = datetime(int(data.year), int(data.month), int(data.day))
|
|
57
51
|
if self.min_date and self.min_date > date:
|
|
58
52
|
await query.answer(
|
|
59
|
-
f'
|
|
60
|
-
show_alert=self.show_alerts
|
|
53
|
+
f'Дата должна быть позже {self.min_date.strftime("%d/%m/%Y")}',
|
|
54
|
+
show_alert=self.show_alerts,
|
|
61
55
|
)
|
|
62
56
|
return False, None
|
|
63
57
|
elif self.max_date and self.max_date < date:
|
|
64
58
|
await query.answer(
|
|
65
|
-
f'
|
|
66
|
-
show_alert=self.show_alerts
|
|
59
|
+
f'Дата должна быть раньше {self.max_date.strftime("%d/%m/%Y")}',
|
|
60
|
+
show_alert=self.show_alerts,
|
|
67
61
|
)
|
|
68
62
|
return False, None
|
|
69
63
|
await query.message.delete_reply_markup() # removing inline keyboard
|
|
70
|
-
return True, date
|
|
64
|
+
return True, date
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import calendar
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
|
|
4
|
-
from aiogram.types import
|
|
5
|
-
|
|
4
|
+
from aiogram.types import (CallbackQuery, InlineKeyboardButton,
|
|
5
|
+
InlineKeyboardMarkup)
|
|
6
6
|
|
|
7
|
-
from .schemas import DialogCalendarCallback, DialogCalAct, highlight, superscript
|
|
8
7
|
from .common import GenericCalendar
|
|
8
|
+
from .schemas import (DialogCalAct, DialogCalendarCallback, highlight,
|
|
9
|
+
superscript)
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class DialogCalendar(GenericCalendar):
|
|
12
13
|
|
|
13
|
-
ignore_callback = DialogCalendarCallback(
|
|
14
|
+
ignore_callback = DialogCalendarCallback(
|
|
15
|
+
act=DialogCalAct.ignore
|
|
16
|
+
).pack() # placeholder for no answer buttons
|
|
14
17
|
|
|
15
18
|
async def _get_month_kb(self, year: int):
|
|
16
19
|
"""Creates an inline keyboard with months for specified year"""
|
|
@@ -25,14 +28,22 @@ class DialogCalendar(GenericCalendar):
|
|
|
25
28
|
years_row.append(
|
|
26
29
|
InlineKeyboardButton(
|
|
27
30
|
text=self._labels.cancel_caption,
|
|
28
|
-
callback_data=DialogCalendarCallback(
|
|
31
|
+
callback_data=DialogCalendarCallback(
|
|
32
|
+
act=DialogCalAct.cancel, year=year, month=1, day=1
|
|
33
|
+
).pack(),
|
|
29
34
|
)
|
|
30
35
|
)
|
|
31
|
-
years_row.append(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
years_row.append(
|
|
37
|
+
InlineKeyboardButton(
|
|
38
|
+
text=str(year) if year != today.year else highlight(year),
|
|
39
|
+
callback_data=DialogCalendarCallback(
|
|
40
|
+
act=DialogCalAct.start, year=year, month=-1, day=-1
|
|
41
|
+
).pack(),
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
years_row.append(
|
|
45
|
+
InlineKeyboardButton(text=" ", callback_data=self.ignore_callback)
|
|
46
|
+
)
|
|
36
47
|
kb.append(years_row)
|
|
37
48
|
# two rows with 6 months buttons
|
|
38
49
|
month6_row = []
|
|
@@ -44,21 +55,25 @@ class DialogCalendar(GenericCalendar):
|
|
|
44
55
|
return month_str
|
|
45
56
|
|
|
46
57
|
for month in range(1, 7):
|
|
47
|
-
month6_row.append(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
58
|
+
month6_row.append(
|
|
59
|
+
InlineKeyboardButton(
|
|
60
|
+
text=highlight_month(),
|
|
61
|
+
callback_data=DialogCalendarCallback(
|
|
62
|
+
act=DialogCalAct.set_m, year=year, month=month, day=-1
|
|
63
|
+
).pack(),
|
|
64
|
+
)
|
|
65
|
+
)
|
|
53
66
|
month12_row = []
|
|
54
67
|
|
|
55
68
|
for month in range(7, 13):
|
|
56
|
-
month12_row.append(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
69
|
+
month12_row.append(
|
|
70
|
+
InlineKeyboardButton(
|
|
71
|
+
text=highlight_month(),
|
|
72
|
+
callback_data=DialogCalendarCallback(
|
|
73
|
+
act=DialogCalAct.set_m, year=year, month=month, day=-1
|
|
74
|
+
).pack(),
|
|
75
|
+
)
|
|
76
|
+
)
|
|
62
77
|
|
|
63
78
|
kb.append(month6_row)
|
|
64
79
|
kb.append(month12_row)
|
|
@@ -101,23 +116,36 @@ class DialogCalendar(GenericCalendar):
|
|
|
101
116
|
nav_row.append(
|
|
102
117
|
InlineKeyboardButton(
|
|
103
118
|
text=self._labels.cancel_caption,
|
|
104
|
-
callback_data=DialogCalendarCallback(
|
|
119
|
+
callback_data=DialogCalendarCallback(
|
|
120
|
+
act=DialogCalAct.cancel, year=year, month=1, day=1
|
|
121
|
+
).pack(),
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
nav_row.append(
|
|
125
|
+
InlineKeyboardButton(
|
|
126
|
+
text=str(year) if year != now_year else highlight(year),
|
|
127
|
+
callback_data=DialogCalendarCallback(
|
|
128
|
+
act=DialogCalAct.start, year=year, month=-1, day=-1
|
|
129
|
+
).pack(),
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
nav_row.append(
|
|
133
|
+
InlineKeyboardButton(
|
|
134
|
+
text=highlight_month(),
|
|
135
|
+
callback_data=DialogCalendarCallback(
|
|
136
|
+
act=DialogCalAct.set_y, year=year, month=-1, day=-1
|
|
137
|
+
).pack(),
|
|
105
138
|
)
|
|
106
139
|
)
|
|
107
|
-
nav_row.append(InlineKeyboardButton(
|
|
108
|
-
text=str(year) if year != now_year else highlight(year),
|
|
109
|
-
callback_data=DialogCalendarCallback(act=DialogCalAct.start, year=year, month=-1, day=-1).pack()
|
|
110
|
-
))
|
|
111
|
-
nav_row.append(InlineKeyboardButton(
|
|
112
|
-
text=highlight_month(),
|
|
113
|
-
callback_data=DialogCalendarCallback(act=DialogCalAct.set_y, year=year, month=-1, day=-1).pack()
|
|
114
|
-
))
|
|
115
140
|
kb.append(nav_row)
|
|
116
141
|
|
|
117
142
|
week_days_labels_row = []
|
|
118
143
|
for weekday in self._labels.days_of_week:
|
|
119
|
-
week_days_labels_row.append(
|
|
120
|
-
|
|
144
|
+
week_days_labels_row.append(
|
|
145
|
+
InlineKeyboardButton(
|
|
146
|
+
text=highlight_weekday(), callback_data=self.ignore_callback
|
|
147
|
+
)
|
|
148
|
+
)
|
|
121
149
|
kb.append(week_days_labels_row)
|
|
122
150
|
|
|
123
151
|
month_calendar = calendar.monthcalendar(year, month)
|
|
@@ -126,19 +154,25 @@ class DialogCalendar(GenericCalendar):
|
|
|
126
154
|
days_row = []
|
|
127
155
|
for day in week:
|
|
128
156
|
if day == 0:
|
|
129
|
-
days_row.append(
|
|
157
|
+
days_row.append(
|
|
158
|
+
InlineKeyboardButton(
|
|
159
|
+
text=" ", callback_data=self.ignore_callback
|
|
160
|
+
)
|
|
161
|
+
)
|
|
130
162
|
continue
|
|
131
|
-
days_row.append(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
163
|
+
days_row.append(
|
|
164
|
+
InlineKeyboardButton(
|
|
165
|
+
text=highlight_day(),
|
|
166
|
+
callback_data=DialogCalendarCallback(
|
|
167
|
+
act=DialogCalAct.day, year=year, month=month, day=day
|
|
168
|
+
).pack(),
|
|
169
|
+
)
|
|
170
|
+
)
|
|
135
171
|
kb.append(days_row)
|
|
136
172
|
return InlineKeyboardMarkup(row_width=7, inline_keyboard=kb)
|
|
137
173
|
|
|
138
174
|
async def start_calendar(
|
|
139
|
-
self,
|
|
140
|
-
year: int = datetime.now().year,
|
|
141
|
-
month: int = None
|
|
175
|
+
self, year: int = datetime.now().year, month: int = None
|
|
142
176
|
) -> InlineKeyboardMarkup:
|
|
143
177
|
today = datetime.now()
|
|
144
178
|
now_year = today.year
|
|
@@ -150,48 +184,76 @@ class DialogCalendar(GenericCalendar):
|
|
|
150
184
|
# first row - years
|
|
151
185
|
years_row = []
|
|
152
186
|
for value in range(year - 2, year + 3):
|
|
153
|
-
years_row.append(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
187
|
+
years_row.append(
|
|
188
|
+
InlineKeyboardButton(
|
|
189
|
+
text=str(value) if value != now_year else highlight(value),
|
|
190
|
+
callback_data=DialogCalendarCallback(
|
|
191
|
+
act=DialogCalAct.set_y, year=value, month=-1, day=-1
|
|
192
|
+
).pack(),
|
|
193
|
+
)
|
|
194
|
+
)
|
|
157
195
|
kb.append(years_row)
|
|
158
196
|
# nav buttons
|
|
159
197
|
nav_row = []
|
|
160
|
-
nav_row.append(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
)
|
|
168
|
-
nav_row.append(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
198
|
+
nav_row.append(
|
|
199
|
+
InlineKeyboardButton(
|
|
200
|
+
text="<<",
|
|
201
|
+
callback_data=DialogCalendarCallback(
|
|
202
|
+
act=DialogCalAct.prev_y, year=year, month=-1, day=-1
|
|
203
|
+
).pack(),
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
nav_row.append(
|
|
207
|
+
InlineKeyboardButton(
|
|
208
|
+
text=self._labels.cancel_caption,
|
|
209
|
+
callback_data=DialogCalendarCallback(
|
|
210
|
+
act=DialogCalAct.cancel, year=year, month=1, day=1
|
|
211
|
+
).pack(),
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
nav_row.append(
|
|
215
|
+
InlineKeyboardButton(
|
|
216
|
+
text=">>",
|
|
217
|
+
callback_data=DialogCalendarCallback(
|
|
218
|
+
act=DialogCalAct.next_y, year=year, month=1, day=1
|
|
219
|
+
).pack(),
|
|
220
|
+
)
|
|
221
|
+
)
|
|
172
222
|
kb.append(nav_row)
|
|
173
223
|
return InlineKeyboardMarkup(row_width=5, inline_keyboard=kb)
|
|
174
224
|
|
|
175
|
-
async def process_selection(
|
|
225
|
+
async def process_selection(
|
|
226
|
+
self, query: CallbackQuery, data: DialogCalendarCallback
|
|
227
|
+
) -> tuple:
|
|
176
228
|
return_data = (False, None)
|
|
177
229
|
if data.act == DialogCalAct.ignore:
|
|
178
230
|
await query.answer(cache_time=60)
|
|
179
231
|
if data.act == DialogCalAct.set_y:
|
|
180
|
-
await query.message.edit_reply_markup(
|
|
232
|
+
await query.message.edit_reply_markup(
|
|
233
|
+
reply_markup=await self._get_month_kb(int(data.year))
|
|
234
|
+
)
|
|
181
235
|
if data.act == DialogCalAct.prev_y:
|
|
182
236
|
new_year = int(data.year) - 5
|
|
183
|
-
await query.message.edit_reply_markup(
|
|
237
|
+
await query.message.edit_reply_markup(
|
|
238
|
+
reply_markup=await self.start_calendar(year=new_year)
|
|
239
|
+
)
|
|
184
240
|
if data.act == DialogCalAct.next_y:
|
|
185
241
|
new_year = int(data.year) + 5
|
|
186
|
-
await query.message.edit_reply_markup(
|
|
242
|
+
await query.message.edit_reply_markup(
|
|
243
|
+
reply_markup=await self.start_calendar(year=new_year)
|
|
244
|
+
)
|
|
187
245
|
if data.act == DialogCalAct.start:
|
|
188
|
-
await query.message.edit_reply_markup(
|
|
246
|
+
await query.message.edit_reply_markup(
|
|
247
|
+
reply_markup=await self.start_calendar(int(data.year))
|
|
248
|
+
)
|
|
189
249
|
if data.act == DialogCalAct.set_m:
|
|
190
|
-
await query.message.edit_reply_markup(
|
|
250
|
+
await query.message.edit_reply_markup(
|
|
251
|
+
reply_markup=await self._get_days_kb(int(data.year), int(data.month))
|
|
252
|
+
)
|
|
191
253
|
if data.act == DialogCalAct.day:
|
|
192
254
|
|
|
193
255
|
return await self.process_day_select(data, query)
|
|
194
256
|
|
|
195
257
|
if data.act == DialogCalAct.cancel:
|
|
196
258
|
await query.message.delete_reply_markup()
|
|
197
|
-
return return_data
|
|
259
|
+
return return_data
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
1
|
from enum import Enum
|
|
3
|
-
|
|
4
|
-
from pydantic import BaseModel, conlist, Field
|
|
2
|
+
from typing import Optional
|
|
5
3
|
|
|
6
4
|
from aiogram.filters.callback_data import CallbackData
|
|
5
|
+
from pydantic import BaseModel, Field, conlist
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
class SimpleCalAct(str, Enum):
|
|
10
|
-
ignore =
|
|
11
|
-
prev_y =
|
|
12
|
-
next_y =
|
|
13
|
-
prev_m =
|
|
14
|
-
next_m =
|
|
15
|
-
cancel =
|
|
16
|
-
today =
|
|
17
|
-
day =
|
|
9
|
+
ignore = "IGNORE"
|
|
10
|
+
prev_y = "PREV-YEAR"
|
|
11
|
+
next_y = "NEXT-YEAR"
|
|
12
|
+
prev_m = "PREV-MONTH"
|
|
13
|
+
next_m = "NEXT-MONTH"
|
|
14
|
+
cancel = "CANCEL"
|
|
15
|
+
today = "TODAY"
|
|
16
|
+
day = "DAY"
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
class DialogCalAct(str, Enum):
|
|
21
|
-
ignore =
|
|
22
|
-
set_y =
|
|
23
|
-
set_m =
|
|
24
|
-
prev_y =
|
|
25
|
-
next_y =
|
|
26
|
-
cancel =
|
|
27
|
-
start =
|
|
28
|
-
day =
|
|
20
|
+
ignore = "IGNORE"
|
|
21
|
+
set_y = "SET-YEAR"
|
|
22
|
+
set_m = "SET-MONTH"
|
|
23
|
+
prev_y = "PREV-YEAR"
|
|
24
|
+
next_y = "NEXT-YEAR"
|
|
25
|
+
cancel = "CANCEL"
|
|
26
|
+
start = "START"
|
|
27
|
+
day = "SET-DAY"
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
class CalendarCallback(CallbackData, prefix="calendar"):
|
|
@@ -45,12 +44,34 @@ class DialogCalendarCallback(CalendarCallback, prefix="dialog_calendar"):
|
|
|
45
44
|
|
|
46
45
|
class CalendarLabels(BaseModel):
|
|
47
46
|
"Schema to pass labels for calendar. Can be used to put in different languages"
|
|
48
|
-
|
|
47
|
+
|
|
48
|
+
days_of_week: conlist(str, max_length=7, min_length=7) = [
|
|
49
|
+
"Пн",
|
|
50
|
+
"Вт",
|
|
51
|
+
"Ср",
|
|
52
|
+
"Чт",
|
|
53
|
+
"Пт",
|
|
54
|
+
"Сб",
|
|
55
|
+
"Вс",
|
|
56
|
+
]
|
|
49
57
|
months: conlist(str, max_length=12, min_length=12) = [
|
|
50
|
-
"
|
|
58
|
+
"Янв",
|
|
59
|
+
"Фев",
|
|
60
|
+
"Мар",
|
|
61
|
+
"Апр",
|
|
62
|
+
"Май",
|
|
63
|
+
"Июн",
|
|
64
|
+
"Июл",
|
|
65
|
+
"Авг",
|
|
66
|
+
"Сен",
|
|
67
|
+
"Окт",
|
|
68
|
+
"Ноя",
|
|
69
|
+
"Дек",
|
|
51
70
|
]
|
|
52
|
-
cancel_caption: str = Field(
|
|
53
|
-
|
|
71
|
+
cancel_caption: str = Field(
|
|
72
|
+
default="Отмена", description="Caprion for Cancel button"
|
|
73
|
+
)
|
|
74
|
+
today_caption: str = Field(default="Сегодня", description="Caprion for Today button")
|
|
54
75
|
|
|
55
76
|
|
|
56
77
|
HIGHLIGHT_FORMAT = "[{}]"
|
|
@@ -63,16 +84,16 @@ def highlight(text):
|
|
|
63
84
|
def superscript(text):
|
|
64
85
|
normal = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-=()"
|
|
65
86
|
super_s = "ᴬᴮᶜᴰᴱᶠᴳᴴᴵᴶᴷᴸᴹᴺᴼᴾQᴿˢᵀᵁⱽᵂˣʸᶻᵃᵇᶜᵈᵉᶠᵍʰᶦʲᵏˡᵐⁿᵒᵖ۹ʳˢᵗᵘᵛʷˣʸᶻ⁰¹²³⁴⁵⁶⁷⁸⁹⁺⁻⁼⁽⁾"
|
|
66
|
-
output =
|
|
87
|
+
output = ""
|
|
67
88
|
for i in text:
|
|
68
|
-
output +=
|
|
89
|
+
output += super_s[normal.index(i)] if i in normal else i
|
|
69
90
|
return output
|
|
70
91
|
|
|
71
92
|
|
|
72
93
|
def subscript(text):
|
|
73
94
|
normal = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-=()"
|
|
74
95
|
sub_s = "ₐ₈CDₑբGₕᵢⱼₖₗₘₙₒₚQᵣₛₜᵤᵥwₓᵧZₐ♭꜀ᑯₑբ₉ₕᵢⱼₖₗₘₙₒₚ૧ᵣₛₜᵤᵥwₓᵧ₂₀₁₂₃₄₅₆₇₈₉₊₋₌₍₎"
|
|
75
|
-
output =
|
|
96
|
+
output = ""
|
|
76
97
|
for i in text:
|
|
77
|
-
output +=
|
|
78
|
-
return output
|
|
98
|
+
output += sub_s[normal.index(i)] if i in normal else i
|
|
99
|
+
return output
|