diff --git a/.gitignore b/.gitignore
index e7d28ec..b250f05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
config/*
modules/irc-bridge/error.log
+__pycache__/
+modules/auto-schedule-pro-v2/preference-db
diff --git a/main.py b/main.py
index 382d0f8..cdbeb92 100644
--- a/main.py
+++ b/main.py
@@ -7,6 +7,7 @@ import sys
import os
import threading
import importlib
+import traceback
# global variables
STOP_REQUESTED = False
@@ -39,6 +40,7 @@ class ModuleV1:
# set environmental variables
def set_env(self):
self.RESPONSE = ""
+ self.FORMAT = ""
def set_predefine(self):
try:
@@ -54,10 +56,11 @@ class ModuleV1:
self.MESSAGE = msg
try:
exec(self.code)
- return self.RESPONSE
+ return self.RESPONSE, self.FORMAT
except Exception as e:
print(f"[ERROR] module v1: module \"{self.path}\" ({self.alias}) raised exception \"{e}\"")
- return ""
+ print(f"[ERROR] module v1: traceback:\ntraceback.format_exc()")
+ return "", None
class ModuleV2:
@@ -75,7 +78,8 @@ class ModuleV2:
return self.obj.process(msg, self.path)
except Exception as e:
print(f"[ERROR] module v2: module \"{self.path}\" ({self.alias}) raised exception \"{e}\"")
- return None
+ print(f"[ERROR] module v2: traceback:\ntraceback.format_exc()")
+ return None, None
# module control unit
@@ -187,21 +191,22 @@ def queue_processor():
# modules are used in here
for mod in mcu.modules:
if mod.enabled:
- if mod.version == 1 or mod.version == 2:
- response = mod.process(msg)
+ if mod.version in [1, 2]:
+ response, formatting = mod.process(msg)
if response:
- '''
- # protecting output
- symbols_to_escape = ['[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!']
- for symbol in symbols_to_escape:
- response = response.replace(symbol, f"\\{symbol}")
- '''
+ if formatting == None:
+ updater.bot.send_message(chat_id=msg.chat.id, text=response,
+ disable_web_page_preview=True)
+ print(f"Responded using module {mod.path} ({mod.alias}) with text: {response}")
+ break
- updater.bot.send_message(chat_id=msg.chat.id, text=response,
- disable_web_page_preview=True)
- print(f"Responded using module {mod.path} ({mod.alias}) with text: {response}")
- break
+ elif formatting in ["Markdown", "MarkdownV2", "HTML"]:
+ updater.bot.send_message(chat_id=msg.chat.id, text=response,
+ disable_web_page_preview=True,
+ parse_mode=formatting)
+ print(f"Responded using module {mod.path} ({mod.alias}) with text (using {formatting}): {response}")
+ break
del message_queue[0]
@@ -213,6 +218,7 @@ def queue_processor():
time.sleep(1)
except Exception as e:
print(f"[ERROR] queue_processor: current message queue: {message_queue}")
+ print(f"[ERROR] Traceback:\n{traceback.format_exc()}")
print(f"[ERROR] queue_processor: error while processing message ({e}), trying to delete it...")
try:
del message_queue[0]
diff --git a/module-testing.py b/module-testing.py
index 1db62da..820b976 100644
--- a/module-testing.py
+++ b/module-testing.py
@@ -6,6 +6,7 @@ import sys
import os
import threading
import importlib
+import traceback
from telegram import Message, Chat
@@ -40,6 +41,7 @@ class ModuleV1:
# set environmental variables
def set_env(self):
self.RESPONSE = ""
+ self.FORMAT = ""
def set_predefine(self):
try:
@@ -55,10 +57,11 @@ class ModuleV1:
self.MESSAGE = msg
try:
exec(self.code)
- return self.RESPONSE
+ return self.RESPONSE, self.FORMAT
except Exception as e:
print(f"[ERROR] module v1: module \"{self.path}\" ({self.alias}) raised exception \"{e}\"")
- return ""
+ print(f"[ERROR] module v1: traceback:\n{traceback.format_exc()}")
+ return "", None
class ModuleV2:
@@ -73,11 +76,11 @@ class ModuleV2:
# running the module
def process(self, msg):
try:
- responce = self.obj.process(msg, self.path)
- return responce
+ return self.obj.process(msg, self.path)
except Exception as e:
print(f"[ERROR] module v2: module \"{self.path}\" ({self.alias}) raised exception \"{e}\"")
- return None
+ print(f"[ERROR] module v2: traceback:\n{traceback.format_exc()}")
+ return None, None
# module control unit
@@ -188,11 +191,16 @@ def queue_processor():
# modules are used in here
for mod in mcu.modules:
if mod.enabled:
- if mod.version == 1 or mod.version == 2:
- response = mod.process(msg)
+ if mod.version in [1, 2]:
+ response, formatting = mod.process(msg)
+
if response:
- print(f"Responded using module {mod.path} ({mod.alias}) with text: {response}")
- break
+ if formatting == None:
+ print(f"Responded using module {mod.path} ({mod.alias}) with text: {response}")
+ break
+ elif formatting in ["Markdown", "MarkdownV2", "HTML"]:
+ print(f"Responded using module {mod.path} ({mod.alias}) with text (using {formatting}): {response}")
+ break
del message_queue[0]
else:
@@ -203,6 +211,7 @@ def queue_processor():
except Exception:
print(f"[ERROR] queue_processor: current message queue: {message_queue}")
+ print(f"[ERROR] Traceback:\n{traceback.format_exc()}")
print("[ERROR] queue_processor: error while processing message, trying to delete it...")
try:
del message_queue[0]
diff --git a/modules/auto-schedule-pro-v2/main.py b/modules/auto-schedule-pro-v2/main.py
index d2f1634..fa4e166 100644
--- a/modules/auto-schedule-pro-v2/main.py
+++ b/modules/auto-schedule-pro-v2/main.py
@@ -1,15 +1,19 @@
from datetime import datetime
import json
-
+import os
def readfile(filename):
with open(module_path + filename) as f:
return f.read()
+def writefile(filename, data):
+ with open(module_path + filename, 'w') as f:
+ f.write(data)
# global constants
# Accusative - znahidnyj
WEEKDAYS_ACCUSATIVE = ["понеділок", "вівторок", "середу", "четвер", "п'ятницю", "суботу", "неділю"]
+
# Genitive - rodovyj
WEEKDAYS_GENITIVE_NEXT = ["наступного понеділка", "наступного вівторка", "наступної середи", "наступного четверга",
"наступної п'ятниці", "наступної суботи", "наступної неділі"]
@@ -17,9 +21,119 @@ WEEKDAYS_GENITIVE_NEXT = ["наступного понеділка", "насту
WEEKDAYS_GENITIVE_THIS = ["цього понеділка", "цього вівторка", "цієї середи", "цього четверга", "цієї п'ятниці",
"цієї суботи", "цієї неділі"]
+lesson_types_to_strings = {
+ "lec": "лекція",
+ "prac": "практика",
+ "lab": "лабораторна"
+}
+
+
# global variables
module_path = ""
+def get_preference_by_id(user_id, name):
+ if not os.path.exists(module_path + f"preference-db/{user_id}.json"):
+ return None
+
+ raw_prefs = readfile(f"preference-db/{user_id}.json")
+ try:
+ preferences = json.loads(raw_prefs)
+ except Exception as e:
+ return None
+
+ if not name in preferences:
+ return None
+
+ return preferences[name]
+
+
+def get_all_preferences_by_id(user_id):
+ user_preferences = {
+ "output-style": "legacy-vibrant",
+ "output-style-lesson": "None",
+ "output-style-lookup": "None"
+ }
+
+ # label defaults as defaults and let custom settings override these labels
+ for i in user_preferences:
+ user_preferences[i] += " (default)"
+
+ for i in user_preferences:
+ override = get_preference_by_id(user_id, i)
+ if override != None:
+ user_preferences[i] = override
+
+ return user_preferences
+
+
+def set_preference_by_id(user_id, name, value):
+ if not os.path.exists(module_path + "preference-db/"):
+ os.mkdir(module_path + "preference-db/")
+
+ preferences = {}
+
+ if os.path.exists(module_path + f"preference-db/{user_id}.json"):
+ try:
+ raw_prefs = readfile(f"preference-db/{user_id}.json")
+ preferences = json.loads(raw_prefs)
+ except Exception as e:
+ preferences = {}
+ else:
+ preferences = {}
+
+ preferences[name] = value
+
+ final_data = json.dumps(preferences)
+ writefile(f"preference-db/{user_id}.json", final_data)
+
+
+def clear_preference_by_id(user_id, name):
+ if not os.path.exists(module_path + "preference-db/"):
+ os.mkdir(module_path + "preference-db/")
+
+ preferences = {}
+
+ if os.path.exists(module_path + f"preference-db/{user_id}.json"):
+ try:
+ raw_prefs = readfile(f"preference-db/{user_id}.json")
+ preferences = json.loads(raw_prefs)
+ except Exception as e:
+ preferences = {}
+ else:
+ preferences = {}
+
+ if name in preferences:
+ del preferences[name]
+
+ final_data = json.dumps(preferences)
+ writefile(f"preference-db/{user_id}.json", final_data)
+
+
+def load_template(template, part):
+ return readfile(f"templates/{template}/{part}.msg")
+
+
+def escaped_string_markdownV2(input_string):
+ result_string = input_string
+
+ symbols_to_escape = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!']
+
+ for symbol in symbols_to_escape:
+ result_string = result_string.replace(symbol, f"\\{symbol}")
+
+ return result_string
+
+
+def escaped_string_html(input_string):
+ result_string = input_string
+
+ symbols_to_escape = ['<', '>']
+
+ for symbol in symbols_to_escape:
+ result_string = result_string.replace(symbol, f"\\{symbol}")
+
+ return result_string
+
def get_human_readable_date(start_datetime, end_datetime,
current_day, current_week):
@@ -43,27 +157,69 @@ def get_human_readable_date(start_datetime, end_datetime,
return human_readable_date
-def generate_lesson_description(lesson, start_datetime, end_datetime, current_day, current_week, overrides={}):
- output_settings = {"name": True, "date": True, "teacher": True, "link": True}
- output_settings.update(overrides)
+def get_name_of_lesson_type(lesson_type):
+ if lesson_type in lesson_types_to_strings:
+ return lesson_types_to_strings[lesson_type]
- result = ""
- if output_settings['name']:
- result += f"{lesson['name']}\n"
+def generate_lesson_description(lesson, start_datetime, end_datetime, current_day, current_week, overrides={},
+ custom_name_prefix="Назва", template="legacy-vibrant", force_date_at_top=False):
+ # temporarily not supported
+ #output_settings = {"name": True, "date": True, "teacher": True, "link": True, "comment": True}
+ #output_settings.update(overrides)
- if output_settings['date']:
+ if lesson.__class__ == dict:
+ if force_date_at_top:
+ total_result = load_template(template, "date")
+ human_readable_date = get_human_readable_date(start_datetime, end_datetime,
+ current_day, current_week)
+ total_result = total_result.replace("%DATE%", human_readable_date)
+
+ total_result += load_template(template, "multiple")
+ for i in ['name', 'teacher', 'link']:
+ total_result = total_result.replace(f"%{i.upper()}%", lesson[i])
+
+ total_result = total_result.replace("%DATE%", human_readable_date)
+ total_result = total_result.replace("%TYPE%", get_name_of_lesson_type(lesson['type']))
+ total_result = total_result.replace("%NAME_PREFIX%", custom_name_prefix)
+
+ return total_result + "\n"
+
+ else:
+ active_template = load_template(template, "single")
+
+ for i in ['name', 'teacher', 'link']:
+ active_template = active_template.replace(f"%{i.upper()}%", lesson[i])
+
+
+ human_readable_date = get_human_readable_date(start_datetime, end_datetime,
+ current_day, current_week)
+
+ active_template = active_template.replace("%DATE%", human_readable_date)
+ active_template = active_template.replace("%TYPE%", get_name_of_lesson_type(lesson['type']))
+ active_template = active_template.replace("%NAME_PREFIX%", custom_name_prefix)
+
+ return active_template
+
+ elif lesson.__class__ == list:
+ total_result = load_template(template, "date")
human_readable_date = get_human_readable_date(start_datetime, end_datetime,
current_day, current_week)
- result += f"*Дата*: {human_readable_date}\n"
+ total_result = total_result.replace("%DATE%", human_readable_date)
- if output_settings['teacher']:
- result += f"*Викладач*: {lesson['teacher']}\n"
+ for l in lesson:
+ active_template = load_template(template, "multiple")
- if output_settings['link']:
- result += f"*Посилання*: {lesson['link']}"
+ for i in ['name', 'teacher', 'link']:
+ active_template = active_template.replace(f"%{i.upper()}%", l[i])
- return result
+ active_template = active_template.replace("%DATE%", human_readable_date)
+ active_template = active_template.replace("%TYPE%", get_name_of_lesson_type(l['type']))
+ active_template = active_template.replace("%NAME_PREFIX%", custom_name_prefix)
+
+ total_result += active_template + "\n"
+
+ return total_result
def get_schedule_data_from(filename):
@@ -76,8 +232,15 @@ def get_schedule_data_from(filename):
timestamp = day_number * 86400 + int(lesson_time.split(":")[0]) * 3600 \
+ int(lesson_time.split(":")[1]) * 60
- new_record = dict(raw_schedule[day_number][lesson_time])
- new_record["source"] = filename.split(".json")[0]
+ new_record = raw_schedule[day_number][lesson_time]
+ item_source = filename.split(".json")[0]
+
+ if new_record.__class__ == list:
+ for item in new_record:
+ item["source"] = item_source
+ else:
+ new_record["source"] = item_source
+
baked_schedule[timestamp] = new_record
return baked_schedule
@@ -105,14 +268,16 @@ def process_arguments(args, base_day):
return preferences, selected_day
-def get_lesson_description(schedule, reference_time, lesson_time, current_day, current_week, overrides={}):
+def get_lesson_description(schedule, reference_time, lesson_time, current_day, current_week, overrides={},
+ custom_name_prefix="Назва", template="legacy-vibrant", force_date_at_top=False):
lesson_record = schedule[lesson_time]
lesson_start_datetime = datetime.fromtimestamp(reference_time + lesson_time)
lesson_end_datetime = datetime.fromtimestamp(reference_time + lesson_time + 5400)
return generate_lesson_description(lesson_record, lesson_start_datetime, lesson_end_datetime, current_day,
- current_week, overrides=overrides)
+ current_week, overrides=overrides, custom_name_prefix=custom_name_prefix, template=template,
+ force_date_at_top=force_date_at_top)
def process(message, path):
@@ -124,14 +289,14 @@ def process(message, path):
# one printable symbol, so this is already protected
base_command = full_command[0].lower()
- if base_command not in ["!пара", "!пари"]:
- return ""
+ if base_command not in ["!пара", "!пари", "!schedule-ctl"]:
+ return None, None
global module_path
module_path = path
- schedule = get_schedule_data_from("schedule.json")
- schedule.update(get_schedule_data_from("additions.json"))
+ schedule = get_schedule_data_from("schedule-v2.json")
+ schedule.update(get_schedule_data_from("additions-v2.json"))
current_time = datetime.now()
@@ -144,16 +309,18 @@ def process(message, path):
reference_time = int(current_time.strftime("%s")) - current_seconds
if base_command == "!пара":
+ # easter egg
study_begin_ts = int(datetime(year=2023, month=9, day=4).strftime("%s"))
current_ts = int(datetime.now().strftime("%s"))
if -3600*4 < study_begin_ts - current_ts < 0:
- return "Навчання незабаром розпочнеться!"
+ return "Навчання от-от розпочнеться!", None
elif 0 <= study_begin_ts - current_ts < 1209600:
- return f"До навчання залишилося {study_begin_ts - current_ts} секунд..."
+ return f"До навчання залишилося {study_begin_ts - current_ts} секунд...", None
elif study_begin_ts - current_ts >= 1209600:
- return "Ви маєте законне право відпочити, пари почнуться не скоро"
-
+ return "Ви маєте законне право відпочити, пари почнуться не скоро", None
+
+ # actual lesson finding code
upcoming_lessons = [timestamp for timestamp in schedule if timestamp > current_seconds - 5400]
if len(upcoming_lessons) > 0:
@@ -161,8 +328,34 @@ def process(message, path):
else:
closest_lesson_time = min(schedule)
- return "*Актуальна пара*: " + get_lesson_description(schedule, reference_time, closest_lesson_time, current_day,
- current_week)
+ # shifting lesson pointer if requested to do so
+ if len(full_command) >= 2:
+ possible_times = list(schedule.keys())
+ current_pointer_position = possible_times.index(closest_lesson_time)
+ total_list_length = len(possible_times)
+
+ if len(full_command[1]) > 1 and full_command[1][1:].isdigit():
+ if full_command[1][0] == "+":
+ current_pointer_position = (current_pointer_position + int(full_command[1][1:])) % total_list_length
+ else:
+ current_pointer_position = (current_pointer_position - int(full_command[1][1:])) % total_list_length
+
+ closest_lesson_time = possible_times[current_pointer_position]
+
+ # getting corrent style
+ output_style_preference = "legacy-vibrant"
+
+ general_output_style_preference = get_preference_by_id(message.from_user.id, "output-style")
+ if general_output_style_preference != None:
+ output_style_preference = general_output_style_preference
+
+ specific_output_style_preference = get_preference_by_id(message.from_user.id, "output-style-lesson")
+ if specific_output_style_preference != None:
+ output_style_preference = specific_output_style_preference
+
+ # returning generated pair description
+ return get_lesson_description(schedule, reference_time, closest_lesson_time, current_day,
+ current_week, custom_name_prefix="Актуальна пара", template=output_style_preference), "HTML"
elif base_command == "!пари":
base_day = current_week * 7 + current_day
@@ -176,8 +369,52 @@ def process(message, path):
lesson_list = [i for i in schedule if selected_day * 86400 <= i < (selected_day + 1) * 86400]
- lesson_descriptions_list = ["*Назва*: " + get_lesson_description(schedule, reference_time, lesson_time,
- current_day, current_week, overrides=preferences)
+ output_style_preference = "legacy-vibrant"
+
+ general_output_style_preference = get_preference_by_id(message.from_user.id, "output-style")
+ if general_output_style_preference != None:
+ output_style_preference = general_output_style_preference
+
+ specific_output_style_preference = get_preference_by_id(message.from_user.id, "output-style-lookup")
+ if specific_output_style_preference != None:
+ output_style_preference = specific_output_style_preference
+
+ lesson_descriptions_list = [get_lesson_description(schedule, reference_time, lesson_time, current_day,
+ current_week, overrides=preferences, custom_name_prefix="Назва", template=output_style_preference, force_date_at_top=True)
for lesson_time in lesson_list]
- return f"__Пари у {WEEKDAYS_ACCUSATIVE[selected_day % 7]}__:\n" + "\n\n".join(lesson_descriptions_list)
+ return f"Пари у {WEEKDAYS_ACCUSATIVE[selected_day % 7]}:\n\n\n" + "\n".join(lesson_descriptions_list), "HTML"
+
+ elif base_command == "!schedule-ctl" and len(full_command) >= 2:
+ if full_command[1] == "list":
+ prefs = get_all_preferences_by_id(message.from_user.id)
+ return "Ваші персональні налаштування:\n" + '\n'.join([f"- {k} = {v}" for k, v in prefs.items()]), "HTML"
+
+ elif full_command[1] == "set" and len(full_command) == 4:
+ prefs = get_all_preferences_by_id(message.from_user.id)
+
+ if full_command[2] in prefs:
+ if full_command[2] in ["output-style", "output-style-lesson", "output-style-lookup"]:
+ if full_command[3] not in os.listdir(module_path + "templates/"):
+ return f"Стилю {full_command[3]} не існує; доступні варіанти: " \
+ + ', '.join(os.listdir(module_path + "templates/")), "HTML"
+
+ previous_value = prefs[full_command[2]]
+ prefs[full_command[2]] = full_command[3]
+
+ set_preference_by_id(message.from_user.id, full_command[2], full_command[3])
+
+ return f"Змінено значення {full_command[2]}: {previous_value} -> {full_command[3]}", "HTML"
+ else:
+ return f"Такого налаштування не існує; переглянути наявні налаштування можна за допомогою команди !schedule-ctl list", "HTML"
+
+ elif full_command[1] == "get" and len(full_command) == 3:
+ requested_preference = get_preference_by_id(message.from_user.id, full_command[2])
+ return f"Налаштування {full_command[2]} має значення {requested_preference}", "HTML"
+
+ elif full_command[1] == "clear" and len(full_command) == 3:
+ clear_preference_by_id(message.from_user.id, full_command[2])
+ return f"Очищено значення для налаштування {full_command[2]}, надалі для нього використовуватиметься стандартне значення", "HTML"
+
+ else:
+ return "Такої команди не існує (або був використаний помилковий синтаксис)", "HTML"
diff --git a/modules/auto-schedule-pro-v2/templates/legacy-vibrant/date.msg b/modules/auto-schedule-pro-v2/templates/legacy-vibrant/date.msg
new file mode 100644
index 0000000..5cdc8e1
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/legacy-vibrant/date.msg
@@ -0,0 +1 @@
+%DATE%:
diff --git a/modules/auto-schedule-pro-v2/templates/legacy-vibrant/multiple.msg b/modules/auto-schedule-pro-v2/templates/legacy-vibrant/multiple.msg
new file mode 100644
index 0000000..fd3369a
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/legacy-vibrant/multiple.msg
@@ -0,0 +1,3 @@
+%NAME_PREFIX%: %NAME% (%TYPE%)
+Викладач: %TEACHER%
+Посилання: %LINK%
diff --git a/modules/auto-schedule-pro-v2/templates/legacy-vibrant/single.msg b/modules/auto-schedule-pro-v2/templates/legacy-vibrant/single.msg
new file mode 100644
index 0000000..da66381
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/legacy-vibrant/single.msg
@@ -0,0 +1,4 @@
+%NAME_PREFIX%: %NAME% (%TYPE%)
+Дата: %DATE%
+Викладач: %TEACHER%
+Посилання: %LINK%
diff --git a/modules/auto-schedule-pro-v2/templates/legacy/date.msg b/modules/auto-schedule-pro-v2/templates/legacy/date.msg
new file mode 100644
index 0000000..dfd8af3
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/legacy/date.msg
@@ -0,0 +1 @@
+%DATE%:
diff --git a/modules/auto-schedule-pro-v2/templates/legacy/multiple.msg b/modules/auto-schedule-pro-v2/templates/legacy/multiple.msg
new file mode 100644
index 0000000..cfcdc79
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/legacy/multiple.msg
@@ -0,0 +1,3 @@
+%NAME_PREFIX%: %NAME% (%TYPE%)
+Викладач: %TEACHER%
+Посилання: %LINK%
diff --git a/modules/auto-schedule-pro-v2/templates/legacy/single.msg b/modules/auto-schedule-pro-v2/templates/legacy/single.msg
new file mode 100644
index 0000000..53f9f70
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/legacy/single.msg
@@ -0,0 +1,4 @@
+%NAME_PREFIX%: %NAME% (%TYPE%)
+Дата: %DATE%
+Викладач: %TEACHER%
+Посилання: %LINK%
diff --git a/modules/auto-schedule-pro-v2/templates/modern/date.msg b/modules/auto-schedule-pro-v2/templates/modern/date.msg
new file mode 100644
index 0000000..5cdc8e1
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/modern/date.msg
@@ -0,0 +1 @@
+%DATE%:
diff --git a/modules/auto-schedule-pro-v2/templates/modern/multiple.msg b/modules/auto-schedule-pro-v2/templates/modern/multiple.msg
new file mode 100644
index 0000000..7eb14cd
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/modern/multiple.msg
@@ -0,0 +1,3 @@
+%NAME% (%TYPE%)
+Викладач: %TEACHER%
+Посилання: %LINK%
diff --git a/modules/auto-schedule-pro-v2/templates/modern/single.msg b/modules/auto-schedule-pro-v2/templates/modern/single.msg
new file mode 100644
index 0000000..8b20b2f
--- /dev/null
+++ b/modules/auto-schedule-pro-v2/templates/modern/single.msg
@@ -0,0 +1,4 @@
+%NAME% (%TYPE%)
+Дата: %DATE%
+Викладач: %TEACHER%
+Посилання: %LINK%
diff --git a/modules/module-v2-example/index.py b/modules/module-v2-example/index.py
index c48f583..dee9fbb 100644
--- a/modules/module-v2-example/index.py
+++ b/modules/module-v2-example/index.py
@@ -13,4 +13,6 @@ def get_num():
def process(message, path):
if message.text == "!v2-testing":
- return f"Testing successful - call number {get_num()}"
+ return f"Testing successful - call number {get_num()}", None
+ else:
+ return None, None
diff --git a/modules/transliteration-decoder/index.py b/modules/transliteration-decoder/index.py
index dcbf772..9415be2 100644
--- a/modules/transliteration-decoder/index.py
+++ b/modules/transliteration-decoder/index.py
@@ -1,6 +1,14 @@
command = self.MESSAGE['text'].split(" ", 2)
command_length = len(command)
+def escaped_string(unescaped_string):
+ result_string = str(unescaped_string)
+
+ for i in ["/", "<", ">"]:
+ result_string = result_string.replace(i, f"\\{i}")
+
+ return result_string
+
if (command[0] in self.aliases) and (1 <= command_length <= 3):
try:
models = json.loads(readfile(self.path + "translate_models.json"))
@@ -25,7 +33,8 @@ if (command[0] in self.aliases) and (1 <= command_length <= 3):
decoded_text = decoded_text.replace(i[0].capitalize(), i[1].capitalize())
decoded_text = decoded_text.replace(i[0].upper(), i[1].upper())
- self.RESPONSE = f"__Результат__\n{decoded_text}"
+ self.RESPONSE = f"Результат\n{escaped_string(decoded_text)}"
+ self.FORMAT = "HTML"
except Exception as e:
print(f"[translit-decoder] Got exception: {e}")