chgksuite 0.26.0b8__py3-none-any.whl → 0.26.0b10__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.
- chgksuite/cli.py +72 -31
- chgksuite/composer/pptx.py +2 -4
- chgksuite/composer/telegram.py +68 -46
- chgksuite/parser.py +33 -6
- chgksuite/resources/regexes_ru.json +1 -1
- chgksuite/version.py +1 -1
- {chgksuite-0.26.0b8.dist-info → chgksuite-0.26.0b10.dist-info}/METADATA +1 -1
- {chgksuite-0.26.0b8.dist-info → chgksuite-0.26.0b10.dist-info}/RECORD +12 -12
- {chgksuite-0.26.0b8.dist-info → chgksuite-0.26.0b10.dist-info}/WHEEL +1 -1
- {chgksuite-0.26.0b8.dist-info → chgksuite-0.26.0b10.dist-info}/entry_points.txt +0 -0
- {chgksuite-0.26.0b8.dist-info → chgksuite-0.26.0b10.dist-info}/licenses/LICENSE +0 -0
- {chgksuite-0.26.0b8.dist-info → chgksuite-0.26.0b10.dist-info}/top_level.txt +0 -0
chgksuite/cli.py
CHANGED
|
@@ -72,37 +72,6 @@ class ArgparseBuilder:
|
|
|
72
72
|
advanced=True,
|
|
73
73
|
argtype="filename",
|
|
74
74
|
)
|
|
75
|
-
self.add_argument(
|
|
76
|
-
parser,
|
|
77
|
-
"--add_ts",
|
|
78
|
-
"-ts",
|
|
79
|
-
choices=["on", "off"],
|
|
80
|
-
default=default_overrides.get("add_ts") or "off",
|
|
81
|
-
help="append timestamp to filenames",
|
|
82
|
-
caption="Добавить временную отметку в имя файла",
|
|
83
|
-
advanced=True,
|
|
84
|
-
argtype="radiobutton",
|
|
85
|
-
)
|
|
86
|
-
self.add_argument(
|
|
87
|
-
parser,
|
|
88
|
-
"--replace_no_break_spaces",
|
|
89
|
-
choices=["on", "off"],
|
|
90
|
-
default=default_overrides.get("replace_no_break_spaces") or "on",
|
|
91
|
-
help="add non-breaking spaces where applicable",
|
|
92
|
-
caption="Добавить неразрывные пробелы",
|
|
93
|
-
advanced=True,
|
|
94
|
-
argtype="radiobutton",
|
|
95
|
-
)
|
|
96
|
-
self.add_argument(
|
|
97
|
-
parser,
|
|
98
|
-
"--replace_no_break_hyphens",
|
|
99
|
-
choices=["on", "off"],
|
|
100
|
-
default=default_overrides.get("replace_no_break_hyphens") or "on",
|
|
101
|
-
help="add non-breaking hyphens where applicable",
|
|
102
|
-
caption="Добавить неразрывные дефисы",
|
|
103
|
-
advanced=True,
|
|
104
|
-
argtype="radiobutton",
|
|
105
|
-
)
|
|
106
75
|
self.add_argument(
|
|
107
76
|
parser,
|
|
108
77
|
"-v",
|
|
@@ -298,6 +267,47 @@ class ArgparseBuilder:
|
|
|
298
267
|
caption="Обработка строчек, состоящих из одного числа",
|
|
299
268
|
argtype="radiobutton",
|
|
300
269
|
)
|
|
270
|
+
self.add_argument(
|
|
271
|
+
cmdparse,
|
|
272
|
+
"--tour_numbers_as_words",
|
|
273
|
+
choices=["on", "off"],
|
|
274
|
+
default=default_overrides.get("tour_numbers_as_words") or "off",
|
|
275
|
+
help="force tour numbers as words",
|
|
276
|
+
caption="Номера туров словами",
|
|
277
|
+
advanced=True,
|
|
278
|
+
argtype="radiobutton",
|
|
279
|
+
)
|
|
280
|
+
self.add_argument(
|
|
281
|
+
cmdparse,
|
|
282
|
+
"--add_ts",
|
|
283
|
+
"-ts",
|
|
284
|
+
choices=["on", "off"],
|
|
285
|
+
default=default_overrides.get("add_ts") or "off",
|
|
286
|
+
help="append timestamp to filenames",
|
|
287
|
+
caption="Добавить временную отметку в имя файла",
|
|
288
|
+
advanced=True,
|
|
289
|
+
argtype="radiobutton",
|
|
290
|
+
)
|
|
291
|
+
self.add_argument(
|
|
292
|
+
cmdparse,
|
|
293
|
+
"--replace_no_break_spaces",
|
|
294
|
+
choices=["on", "off"],
|
|
295
|
+
default=default_overrides.get("replace_no_break_spaces") or "on",
|
|
296
|
+
help="add non-breaking spaces where applicable",
|
|
297
|
+
caption="Добавить неразрывные пробелы",
|
|
298
|
+
advanced=True,
|
|
299
|
+
argtype="radiobutton",
|
|
300
|
+
)
|
|
301
|
+
self.add_argument(
|
|
302
|
+
cmdparse,
|
|
303
|
+
"--replace_no_break_hyphens",
|
|
304
|
+
choices=["on", "off"],
|
|
305
|
+
default=default_overrides.get("replace_no_break_hyphens") or "on",
|
|
306
|
+
help="add non-breaking hyphens where applicable",
|
|
307
|
+
caption="Добавить неразрывные дефисы",
|
|
308
|
+
advanced=True,
|
|
309
|
+
argtype="radiobutton",
|
|
310
|
+
)
|
|
301
311
|
|
|
302
312
|
cmdcompose = subparsers.add_parser("compose")
|
|
303
313
|
self.add_argument(
|
|
@@ -334,6 +344,37 @@ class ArgparseBuilder:
|
|
|
334
344
|
caption="Client ID для API Imgur",
|
|
335
345
|
advanced=True,
|
|
336
346
|
)
|
|
347
|
+
self.add_argument(
|
|
348
|
+
cmdcompose,
|
|
349
|
+
"--add_ts",
|
|
350
|
+
"-ts",
|
|
351
|
+
choices=["on", "off"],
|
|
352
|
+
default=default_overrides.get("add_ts") or "off",
|
|
353
|
+
help="append timestamp to filenames",
|
|
354
|
+
caption="Добавить временную отметку в имя файла",
|
|
355
|
+
advanced=True,
|
|
356
|
+
argtype="radiobutton",
|
|
357
|
+
)
|
|
358
|
+
self.add_argument(
|
|
359
|
+
cmdcompose,
|
|
360
|
+
"--replace_no_break_spaces",
|
|
361
|
+
choices=["on", "off"],
|
|
362
|
+
default=default_overrides.get("replace_no_break_spaces") or "on",
|
|
363
|
+
help="add non-breaking spaces where applicable",
|
|
364
|
+
caption="Добавить неразрывные пробелы",
|
|
365
|
+
advanced=True,
|
|
366
|
+
argtype="radiobutton",
|
|
367
|
+
)
|
|
368
|
+
self.add_argument(
|
|
369
|
+
cmdcompose,
|
|
370
|
+
"--replace_no_break_hyphens",
|
|
371
|
+
choices=["on", "off"],
|
|
372
|
+
default=default_overrides.get("replace_no_break_hyphens") or "on",
|
|
373
|
+
help="add non-breaking hyphens where applicable",
|
|
374
|
+
caption="Добавить неразрывные дефисы",
|
|
375
|
+
advanced=True,
|
|
376
|
+
argtype="radiobutton",
|
|
377
|
+
)
|
|
337
378
|
cmdcompose_filetype = cmdcompose.add_subparsers(dest="filetype")
|
|
338
379
|
cmdcompose_docx = cmdcompose_filetype.add_parser("docx")
|
|
339
380
|
self.add_argument(
|
chgksuite/composer/pptx.py
CHANGED
|
@@ -182,9 +182,8 @@ class PptxExporter(BaseExporter):
|
|
|
182
182
|
r = self.add_run(
|
|
183
183
|
p,
|
|
184
184
|
self._replace_no_break(
|
|
185
|
-
("\n" if add_line_break else "")
|
|
185
|
+
("\n\n" if add_line_break else "")
|
|
186
186
|
+ self.pptx_process_text(editor[0][1])
|
|
187
|
-
+ "\n"
|
|
188
187
|
),
|
|
189
188
|
)
|
|
190
189
|
add_line_break = True
|
|
@@ -193,9 +192,8 @@ class PptxExporter(BaseExporter):
|
|
|
193
192
|
r = self.add_run(
|
|
194
193
|
p,
|
|
195
194
|
self._replace_no_break(
|
|
196
|
-
("\n" if add_line_break else "")
|
|
195
|
+
("\n\n" if add_line_break else "")
|
|
197
196
|
+ self.pptx_process_text(element[1])
|
|
198
|
-
+ "\n"
|
|
199
197
|
),
|
|
200
198
|
)
|
|
201
199
|
add_line_break = True
|
chgksuite/composer/telegram.py
CHANGED
|
@@ -16,6 +16,11 @@ from chgksuite.composer.composer_common import BaseExporter, parseimg
|
|
|
16
16
|
from chgksuite.composer.telegram_bot import run_bot_in_thread
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def get_text(msg_data):
|
|
20
|
+
if "message" in msg_data and "text" in msg_data["message"]:
|
|
21
|
+
return msg_data["message"]["text"]
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
class TelegramExporter(BaseExporter):
|
|
20
25
|
def __init__(self, *args, **kwargs):
|
|
21
26
|
super().__init__(*args, **kwargs)
|
|
@@ -37,6 +42,7 @@ class TelegramExporter(BaseExporter):
|
|
|
37
42
|
self.channel_id = None # Target channel ID
|
|
38
43
|
self.chat_id = None # Discussion group ID linked to the channel
|
|
39
44
|
self.auth_uuid = uuid.uuid4().hex[:8]
|
|
45
|
+
self.chat_auth_uuid = uuid.uuid4().hex[:8]
|
|
40
46
|
self.init_telegram()
|
|
41
47
|
|
|
42
48
|
def check_connectivity(self):
|
|
@@ -119,6 +125,9 @@ class TelegramExporter(BaseExporter):
|
|
|
119
125
|
|
|
120
126
|
if result:
|
|
121
127
|
msg_data = json.loads(result["raw_data"])
|
|
128
|
+
if msg_data["message"]["chat"]["type"] != "private":
|
|
129
|
+
print("You should post to the PRIVATE chat, not to the channel/group")
|
|
130
|
+
continue
|
|
122
131
|
self.control_chat_id = msg_data["message"]["chat"]["id"]
|
|
123
132
|
self.send_api_request(
|
|
124
133
|
"sendMessage",
|
|
@@ -860,6 +869,7 @@ class TelegramExporter(BaseExporter):
|
|
|
860
869
|
raise Exception("Failed to get channel ID from forwarded message")
|
|
861
870
|
else:
|
|
862
871
|
raise Exception("Channel ID is undefined")
|
|
872
|
+
|
|
863
873
|
# Handle chat resolution
|
|
864
874
|
if isinstance(chat_result, int):
|
|
865
875
|
chat_id = chat_result
|
|
@@ -868,9 +878,10 @@ class TelegramExporter(BaseExporter):
|
|
|
868
878
|
if not chat_id:
|
|
869
879
|
print("\n" + "=" * 50)
|
|
870
880
|
print(
|
|
871
|
-
"Please
|
|
881
|
+
f"Please write a message in the discussion group with text: {self.chat_auth_uuid}"
|
|
872
882
|
)
|
|
873
883
|
print("This will allow me to extract the group ID automatically.")
|
|
884
|
+
print("The bot MUST be added do the group and made admin, else it won't work!")
|
|
874
885
|
print("=" * 50 + "\n")
|
|
875
886
|
|
|
876
887
|
# Wait for a forwarded message with chat information
|
|
@@ -883,8 +894,7 @@ class TelegramExporter(BaseExporter):
|
|
|
883
894
|
while chat_id == channel_id:
|
|
884
895
|
error_msg = (
|
|
885
896
|
"Chat ID and channel ID are the same. The problem may be that "
|
|
886
|
-
"you
|
|
887
|
-
"from the channel by Telegram. Please forward a message that was sent directly in the discussion group."
|
|
897
|
+
"you posted a message in the channel, not in the discussion group."
|
|
888
898
|
)
|
|
889
899
|
self.logger.error(error_msg)
|
|
890
900
|
chat_id = self.wait_for_forwarded_message(
|
|
@@ -903,7 +913,10 @@ class TelegramExporter(BaseExporter):
|
|
|
903
913
|
raise Exception("Chat ID is undefined")
|
|
904
914
|
|
|
905
915
|
self.channel_id = f"-100{channel_id}"
|
|
906
|
-
|
|
916
|
+
if not str(chat_id).startswith("-100"):
|
|
917
|
+
self.chat_id = f"-100{chat_id}"
|
|
918
|
+
else:
|
|
919
|
+
self.chat_id = chat_id
|
|
907
920
|
|
|
908
921
|
self.logger.info(
|
|
909
922
|
f"Using channel ID {self.channel_id} and discussion group ID {self.chat_id}"
|
|
@@ -1087,7 +1100,10 @@ class TelegramExporter(BaseExporter):
|
|
|
1087
1100
|
failure_message = "❌ Failed to extract channel ID."
|
|
1088
1101
|
else:
|
|
1089
1102
|
entity_name = "discussion group"
|
|
1090
|
-
instruction_message =
|
|
1103
|
+
instruction_message = (
|
|
1104
|
+
f"🔄 Please post to the discussion group a message with text: {self.chat_auth_uuid}\n\n"
|
|
1105
|
+
"⚠️ IMPORTANT: Bot should be added to the discussion group and have ADMIN rights!"
|
|
1106
|
+
)
|
|
1091
1107
|
success_message = "✅ Successfully extracted discussion group ID: {}"
|
|
1092
1108
|
failure_message = "❌ Failed to extract discussion group ID."
|
|
1093
1109
|
|
|
@@ -1104,6 +1120,7 @@ class TelegramExporter(BaseExporter):
|
|
|
1104
1120
|
resolved = False
|
|
1105
1121
|
retry_count = 0
|
|
1106
1122
|
max_retries = 30 # 5 minutes (10 seconds per retry)
|
|
1123
|
+
extracted_id = None
|
|
1107
1124
|
|
|
1108
1125
|
# Extract channel ID for comparison if we're looking for a discussion group
|
|
1109
1126
|
channel_numeric_id = None
|
|
@@ -1132,58 +1149,63 @@ class TelegramExporter(BaseExporter):
|
|
|
1132
1149
|
messages = cursor.fetchall()
|
|
1133
1150
|
|
|
1134
1151
|
for row in messages:
|
|
1152
|
+
if self.args.debug:
|
|
1153
|
+
self.logger.info(row["raw_data"])
|
|
1135
1154
|
if self.created_at and row["created_at"] < self.created_at:
|
|
1136
1155
|
break
|
|
1137
1156
|
msg_data = json.loads(row["raw_data"])
|
|
1138
|
-
if
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
# Remove -100 prefix if present
|
|
1146
|
-
if str(chat_id).startswith("-100"):
|
|
1147
|
-
extracted_id = int(str(chat_id)[4:])
|
|
1148
|
-
else:
|
|
1149
|
-
extracted_id = chat_id
|
|
1150
|
-
|
|
1151
|
-
# If we're looking for a discussion group, verify it's not the same as the channel ID
|
|
1152
|
-
if entity_type == "chat" and channel_numeric_id:
|
|
1153
|
-
if extracted_id == channel_numeric_id:
|
|
1154
|
-
self.logger.warning(
|
|
1155
|
-
"User forwarded a message from the channel, not the discussion group"
|
|
1156
|
-
)
|
|
1157
|
-
self.send_api_request(
|
|
1158
|
-
"sendMessage",
|
|
1159
|
-
{
|
|
1160
|
-
"chat_id": self.control_chat_id,
|
|
1161
|
-
"text": "⚠️ You forwarded a message from the channel, not from the discussion group.\n\nPlease forward a message that was originally sent IN the discussion group, not an automatic repost from the channel.",
|
|
1162
|
-
},
|
|
1163
|
-
)
|
|
1164
|
-
# Skip this message and continue waiting
|
|
1165
|
-
continue
|
|
1166
|
-
|
|
1167
|
-
# For channels, check the type; for chats, accept any type except "channel" if check_type is False
|
|
1168
|
-
if (check_type and forward_info.get("type") == "channel") or (
|
|
1169
|
-
not check_type
|
|
1170
|
-
):
|
|
1171
|
-
resolved = True
|
|
1172
|
-
self.created_at = row["created_at"]
|
|
1173
|
-
self.logger.info(
|
|
1174
|
-
f"Extracted {entity_name} ID: {extracted_id} from forwarded message"
|
|
1157
|
+
if entity_type == "chat":
|
|
1158
|
+
if get_text(msg_data) != self.chat_auth_uuid:
|
|
1159
|
+
continue
|
|
1160
|
+
extracted_id = msg_data["message"]["chat"]["id"]
|
|
1161
|
+
if extracted_id == channel_numeric_id or extracted_id == self.control_chat_id:
|
|
1162
|
+
self.logger.warning(
|
|
1163
|
+
"User posted a message in the channel, not the discussion group"
|
|
1175
1164
|
)
|
|
1176
|
-
|
|
1177
|
-
# Send confirmation message
|
|
1178
1165
|
self.send_api_request(
|
|
1179
1166
|
"sendMessage",
|
|
1180
1167
|
{
|
|
1181
1168
|
"chat_id": self.control_chat_id,
|
|
1182
|
-
"text":
|
|
1169
|
+
"text": (
|
|
1170
|
+
"⚠️ You posted a message in the channel, not in the discussion group."
|
|
1171
|
+
)
|
|
1183
1172
|
},
|
|
1184
1173
|
)
|
|
1174
|
+
# Skip this message and continue waiting
|
|
1175
|
+
continue
|
|
1176
|
+
elif entity_type == "channel":
|
|
1177
|
+
if msg_data["message"]["chat"]["id"] != self.control_chat_id:
|
|
1178
|
+
continue
|
|
1179
|
+
if "message" in msg_data and "forward_from_chat" in msg_data["message"]:
|
|
1180
|
+
forward_info = msg_data["message"]["forward_from_chat"]
|
|
1181
|
+
|
|
1182
|
+
# Extract chat ID from the message
|
|
1183
|
+
chat_id = forward_info.get("id")
|
|
1184
|
+
# Remove -100 prefix if present
|
|
1185
|
+
if str(chat_id).startswith("-100"):
|
|
1186
|
+
extracted_id = int(str(chat_id)[4:])
|
|
1187
|
+
else:
|
|
1188
|
+
extracted_id = chat_id
|
|
1189
|
+
# For channels, check the type; for chats, accept any type except "channel" if check_type is False
|
|
1190
|
+
if extracted_id and ((check_type and forward_info.get("type") == "channel") or (
|
|
1191
|
+
not check_type
|
|
1192
|
+
)):
|
|
1193
|
+
resolved = True
|
|
1194
|
+
self.created_at = row["created_at"]
|
|
1195
|
+
self.logger.info(
|
|
1196
|
+
f"Extracted {entity_name} ID: {extracted_id} from forwarded message"
|
|
1197
|
+
)
|
|
1198
|
+
|
|
1199
|
+
# Send confirmation message
|
|
1200
|
+
self.send_api_request(
|
|
1201
|
+
"sendMessage",
|
|
1202
|
+
{
|
|
1203
|
+
"chat_id": self.control_chat_id,
|
|
1204
|
+
"text": success_message.format(extracted_id),
|
|
1205
|
+
},
|
|
1206
|
+
)
|
|
1185
1207
|
|
|
1186
|
-
|
|
1208
|
+
return extracted_id
|
|
1187
1209
|
|
|
1188
1210
|
retry_count += 1
|
|
1189
1211
|
|
chgksuite/parser.py
CHANGED
|
@@ -91,6 +91,19 @@ class ChgkParser:
|
|
|
91
91
|
BADNEXTFIELDS = set(["question", "answer"])
|
|
92
92
|
RE_NUM = re.compile("^([0-9]+)\\.?$")
|
|
93
93
|
RE_NUM_START = re.compile("^([0-9]+)\\.")
|
|
94
|
+
ZERO_PREFIXES = ("Нулевой вопрос", "Разминочный вопрос")
|
|
95
|
+
TOUR_NUMBERS_AS_WORDS = (
|
|
96
|
+
"Первый",
|
|
97
|
+
"Второй",
|
|
98
|
+
"Третий",
|
|
99
|
+
"Четвертый",
|
|
100
|
+
"Пятый",
|
|
101
|
+
"Шестой",
|
|
102
|
+
"Седьмой",
|
|
103
|
+
"Восьмой",
|
|
104
|
+
"Девятый",
|
|
105
|
+
"Десятый",
|
|
106
|
+
)
|
|
94
107
|
|
|
95
108
|
def __init__(self, defaultauthor=None, args=None, logger=None):
|
|
96
109
|
self.defaultauthor = defaultauthor
|
|
@@ -200,7 +213,7 @@ class ChgkParser:
|
|
|
200
213
|
@classmethod
|
|
201
214
|
def _replace(cls, obj, val, new_val):
|
|
202
215
|
if isinstance(obj, str):
|
|
203
|
-
return obj.replace(val, new_val)
|
|
216
|
+
return obj.replace(val, new_val).strip()
|
|
204
217
|
elif isinstance(obj, list):
|
|
205
218
|
for i, el in enumerate(obj):
|
|
206
219
|
obj[i] = cls._replace(el, val, new_val)
|
|
@@ -214,6 +227,11 @@ class ChgkParser:
|
|
|
214
227
|
for el in val:
|
|
215
228
|
self._get_strings(el, list_)
|
|
216
229
|
|
|
230
|
+
def _get_strings_joined(self, val):
|
|
231
|
+
strings = []
|
|
232
|
+
self._get_strings(val, strings)
|
|
233
|
+
return "\n".join(strings)
|
|
234
|
+
|
|
217
235
|
def _try_extract_field(self, question, k):
|
|
218
236
|
regex = self.regexes[k]
|
|
219
237
|
keys = sorted(question.keys())
|
|
@@ -255,14 +273,18 @@ class ChgkParser:
|
|
|
255
273
|
and not question["number"].strip()
|
|
256
274
|
):
|
|
257
275
|
question.pop("number")
|
|
276
|
+
question_str = self._get_strings_joined(question["question"])
|
|
277
|
+
for prefix in self.ZERO_PREFIXES:
|
|
278
|
+
if question_str.startswith(prefix):
|
|
279
|
+
question["question"] = self._replace(question["question"], prefix, "")
|
|
280
|
+
question["number"] = 0
|
|
281
|
+
question_str = self._get_strings_joined(question["question"])
|
|
258
282
|
for k in ("zachet", "nezachet", "source", "comment", "author"):
|
|
259
283
|
if k not in question:
|
|
260
284
|
self._try_extract_field(question, k)
|
|
261
|
-
|
|
262
|
-
self._get_strings(question["question"], strings)
|
|
263
|
-
strings = "\n".join(strings)
|
|
285
|
+
question_str = self._get_strings_joined(question["question"])
|
|
264
286
|
handout = self.labels["question_labels"]["handout"]
|
|
265
|
-
srch = re.search(f"{handout}:([ \n]+)\\[",
|
|
287
|
+
srch = re.search(f"{handout}:([ \n]+)\\[", question_str, flags=re.DOTALL)
|
|
266
288
|
if srch:
|
|
267
289
|
question["question"] = self._replace(
|
|
268
290
|
question["question"],
|
|
@@ -608,7 +630,8 @@ class ChgkParser:
|
|
|
608
630
|
|
|
609
631
|
for element in self.structure:
|
|
610
632
|
if (
|
|
611
|
-
element[0]
|
|
633
|
+
element[0]
|
|
634
|
+
in set(["number", "tour", "tourrev", "question", "meta", "editor"])
|
|
612
635
|
and "question" in current_question
|
|
613
636
|
):
|
|
614
637
|
if self.defaultauthor and "author" not in current_question:
|
|
@@ -682,9 +705,13 @@ class ChgkParser:
|
|
|
682
705
|
except ValueError:
|
|
683
706
|
pass
|
|
684
707
|
|
|
708
|
+
tour_cnt = 0
|
|
685
709
|
for i, element in enumerate(final_structure):
|
|
686
710
|
if element[0] == "Question":
|
|
687
711
|
self.postprocess_question(element[1])
|
|
712
|
+
elif element[0] == "tour" and self.args.tour_numbers_as_words == "on":
|
|
713
|
+
element[1] = f"{self.TOUR_NUMBERS_AS_WORDS[tour_cnt]} тур"
|
|
714
|
+
tour_cnt += 1
|
|
688
715
|
|
|
689
716
|
if debug:
|
|
690
717
|
with codecs.open("debug_final.json", "w", "utf8") as f:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"tour": "^(#\\s+)?Т[Уу][Рр]\\s?№?\\s?([0-9IVXLCDM]*)([\\.:])?$",
|
|
3
|
-
"tourrev": "^([0-9IVXLCDM]
|
|
3
|
+
"tourrev": "^([0-9IVXLCDM]+|[Пп][Ее][Рр][Вв][Ыы][Йй]|[Вв][Тт][Оо][Рр][Оо][Йй]|[Тт][Рр][Ее][Тт][Ии][Йй]|[Чч][Ее][Тт][Вв][Ее][Рр][Тт][Ыы][Йй]|[Пп][Яя][Тт][Ыы][Йй]|[Шш][Ее][Сс][Тт][Оо][Йй]|[Сс][Ее][Дд][Ьь][Мм][Оо][Йй]|[Вв][Оо][Сс][Ьь][Мм][Оо][Йй]|[Дд][Ее][Вв][Яя][Тт][Ыы][Йй]|[Дд][Ее][Сс][Яя][Тт][Ыы][Йй])\\s[Тт][Уу][Рр]([\\.:])?$",
|
|
4
4
|
"question": "В[Оо][Пп][Рр][Оо][Сс]\\s?[№N]?([0-9\\s]*)\\s?([\\.:]|\n|\r\n|$)",
|
|
5
5
|
"handout": "^Р[Аа][Зз][Дд][Аа][Тт][Оо][Чч][Нн][Ыы][Йй]\\s+[Мм][Аа][Тт][Ее][Рр][Ии][Аа][Лл][\\.:]",
|
|
6
6
|
"answer": "О[Тт][Вв][Ее][Тт][Ыы]?\\s?[№N]?([0-9]+)?\\s?[\\.:]",
|
chgksuite/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.26.
|
|
1
|
+
__version__ = "0.26.0b10"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
chgksuite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
chgksuite/__main__.py,sha256=0-_jfloveTW3SZYW5XEagbyaHKGCiDhGNgcLxsT_dMs,140
|
|
3
|
-
chgksuite/cli.py,sha256=
|
|
3
|
+
chgksuite/cli.py,sha256=6mmd_TcGaBykW9tye9km6hp6STNF0LZzlleDRfOh4-o,40276
|
|
4
4
|
chgksuite/common.py,sha256=VkOhoBA_P3qY5VgtvfrBjOsm5uVNL2s2Th2AhGB2pg8,11207
|
|
5
|
-
chgksuite/parser.py,sha256=
|
|
5
|
+
chgksuite/parser.py,sha256=CXx7p-MZ75BpmgtaO53sq3U9OVR6wAeo0_GntI8pK5M,38360
|
|
6
6
|
chgksuite/parser_db.py,sha256=W1--OcDnx18mehH1T2ISHu3Saeq-9mqHo-xJopNySXI,11135
|
|
7
7
|
chgksuite/trello.py,sha256=BG1Qb_W7Uu4o3Mfc_tK71ElU8ysdSplGlj_sAKfvUn4,14730
|
|
8
8
|
chgksuite/typotools.py,sha256=Jdk65Wn_bXqpQtOT7PkBZyD2ZG1MBeeZFPMzcHEPkf4,12771
|
|
9
|
-
chgksuite/version.py,sha256=
|
|
9
|
+
chgksuite/version.py,sha256=a3axD55VIZso4_2Zx6fsyG63nRbiCKIcpl2QMABpnnQ,26
|
|
10
10
|
chgksuite/vulture_whitelist.py,sha256=P__p_X0zt10ivddIf81uyxsobV14vFg8uS2lt4foYpc,3582
|
|
11
11
|
chgksuite/composer/__init__.py,sha256=MAOVZIYXmZmD6nNQSo9DueV6b5RgxF7_HGeLvsAhMJs,6490
|
|
12
12
|
chgksuite/composer/chgksuite_parser.py,sha256=MFcLUWbccMqo3OYEuaAIA0loEvWM_PNS9vR7c1z_c60,8843
|
|
@@ -16,10 +16,10 @@ chgksuite/composer/docx.py,sha256=5MASXACM-ztWrr3VdO8HZ-W-hWWQ5TY1jXMsCQIufGc,18
|
|
|
16
16
|
chgksuite/composer/latex.py,sha256=WtLdUICxeX4_5vHEJRF0YhFLpTsOUwBkQFunQS488FA,9248
|
|
17
17
|
chgksuite/composer/lj.py,sha256=nty3Zs3N1H0gNK378U04aAHo71_5cABhCM1Mm9jiUEA,15213
|
|
18
18
|
chgksuite/composer/openquiz.py,sha256=4adZewvRXpZhKrh9H4epKoMMDhmki9US55-Q0LcpZW0,7019
|
|
19
|
-
chgksuite/composer/pptx.py,sha256
|
|
19
|
+
chgksuite/composer/pptx.py,sha256=KszvRAbSbKmbPS257YcYhE6wB1gSf7gIXRH8VwiSqyg,23775
|
|
20
20
|
chgksuite/composer/reddit.py,sha256=-Eg4CqMHhyGGfCteVwdQdtE1pfUXQ42XcP5OYUrBXmo,3878
|
|
21
21
|
chgksuite/composer/stats.py,sha256=GbraSrjaZ8Mc2URs5aGAsI4ekboAKzlJJOqsbe96ELA,3995
|
|
22
|
-
chgksuite/composer/telegram.py,sha256=
|
|
22
|
+
chgksuite/composer/telegram.py,sha256=ZiCBFXxKJJ5vD5ttkfvmURd4Q9Gif6eT8R93nz-LAq0,47146
|
|
23
23
|
chgksuite/composer/telegram_bot.py,sha256=xT5D39m4zGmIbHV_ZfyQ9Rc8PAmG2V5FGUeDKpkgyTw,3767
|
|
24
24
|
chgksuite/composer/telegram_parser.py,sha256=50WqOuvzzdMJJm5wsSLS49oURAQRYToPnbPJjQbMYC4,8096
|
|
25
25
|
chgksuite/handouter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -44,16 +44,16 @@ chgksuite/resources/pptx_config.toml,sha256=pbdQpZTBZajfXxf9Ej6jFQv8luA9_h2Lsihx
|
|
|
44
44
|
chgksuite/resources/regexes_by.json,sha256=43K_jjNocNrx75OcSlVxg2zHNJKoHwzceFbtfZgM0Vo,1296
|
|
45
45
|
chgksuite/resources/regexes_en.json,sha256=v1RPW8Oj0UiS_86ieYjpFOGm3qN5-OlM-qgAqa6oCy4,1003
|
|
46
46
|
chgksuite/resources/regexes_kz_cyr.json,sha256=QW6MxkPjSRNU-KPAAqh4jwFZ--ckJo9EOn_p30gihiQ,1679
|
|
47
|
-
chgksuite/resources/regexes_ru.json,sha256=
|
|
47
|
+
chgksuite/resources/regexes_ru.json,sha256=Oxp2Y74YdJcwgL1Dr9ZBYTvaxlzoCO7E_CpNy0NDm1A,2058
|
|
48
48
|
chgksuite/resources/regexes_sr.json,sha256=SiDDtxWND41XOBvHM4MgSXcogh7bRTqsY3JbJPT2wF4,925
|
|
49
49
|
chgksuite/resources/regexes_ua.json,sha256=IXtJtoUY15OoBu5Y5yW6adhJUhsDRkwfxWsPYIrbgPA,1330
|
|
50
50
|
chgksuite/resources/regexes_uz_cyr.json,sha256=mIvWjyZZXQ3lr_ntuC7-ybknnYJxSSQEKxqnGluTvow,1106
|
|
51
51
|
chgksuite/resources/template.docx,sha256=Do29TAsg3YbH0rRSaXhVzKEoh4pwXkklW_idWA34HVE,11189
|
|
52
52
|
chgksuite/resources/template.pptx,sha256=hEFWqE-yYpwZ8ejrMCJIPEyoMT3eDqaqtiEeQ7I4fyk,29777
|
|
53
53
|
chgksuite/resources/trello.json,sha256=M5Q9JR-AAJF1u16YtNAxDX-7c7VoVTXuq4POTqYvq8o,555
|
|
54
|
-
chgksuite-0.26.
|
|
55
|
-
chgksuite-0.26.
|
|
56
|
-
chgksuite-0.26.
|
|
57
|
-
chgksuite-0.26.
|
|
58
|
-
chgksuite-0.26.
|
|
59
|
-
chgksuite-0.26.
|
|
54
|
+
chgksuite-0.26.0b10.dist-info/licenses/LICENSE,sha256=_a1yfntuPmctLsuiE_08xMSORuCfGS8X5hQph2U_PUw,1081
|
|
55
|
+
chgksuite-0.26.0b10.dist-info/METADATA,sha256=3Dle9cm_nzKRc5ZwetXoqa390v1emHoV1cBoF1m3Rk4,1342
|
|
56
|
+
chgksuite-0.26.0b10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
chgksuite-0.26.0b10.dist-info/entry_points.txt,sha256=lqjX6ULQZGDt0rgouTXBuwEPiwKkDQkSiNsT877A_Jg,54
|
|
58
|
+
chgksuite-0.26.0b10.dist-info/top_level.txt,sha256=cSWiRBOGZW9nIO6Rv1IrEfwPgV2ZWs87QV9wPXeBGqM,10
|
|
59
|
+
chgksuite-0.26.0b10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|