forked from dymik739/modular-bot-framework-for-telegram
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			8cc68080e8
			...
			b0ea33cfff
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b0ea33cfff | |||
| e9bec0159f | |||
| 5dc78b8cb0 | |||
| 67b3c4278b | |||
| 0497cbf9b7 | |||
| 2b9ac41ced | |||
| fc450f633e | |||
| 1070362bc6 | |||
| d2915c10e2 | |||
| ebdae6256e | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,2 +1,3 @@ | ||||
| config/* | ||||
| modules/irc-bridge/error.log | ||||
| __pycache__/ | ||||
|  | ||||
							
								
								
									
										45
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								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 | ||||
| @ -94,7 +98,7 @@ class ModuleControlUnit: | ||||
|                     print(f"[WARN] module_loader: no meta.json found in module folder \"{folder}\"") | ||||
|                     continue | ||||
| 
 | ||||
|                 meta = json.loads( meta_raw ) | ||||
|                 meta = json.loads(meta_raw) | ||||
|                 if "version" in meta: | ||||
|                     if meta["version"] == 1: | ||||
|                         if "index_file" in meta: | ||||
| @ -102,8 +106,8 @@ class ModuleControlUnit: | ||||
|                         else: | ||||
|                             index_file = "index.py" | ||||
| 
 | ||||
|                         code = readfile( "modules/{}/{}".format(folder, index_file) ) | ||||
|                         if not code: # False both when readfile() returns False and when the code string is empty | ||||
|                         code = readfile("modules/{}/{}".format(folder, index_file)) | ||||
|                         if not code:  # False both when readfile() returns False and when the code string is empty | ||||
|                             print("[WARN] reload_modules: module {} does not have any code, skipping...".format(folder)) | ||||
|                             continue | ||||
| 
 | ||||
| @ -162,7 +166,7 @@ def queue_processor(): | ||||
|         try: | ||||
|             if len(message_queue) > 0: | ||||
|                 msg = message_queue[0] | ||||
|                 print("[DEBUG] queue_processor: {}".format(msg)) # debug | ||||
|                 print("[DEBUG] queue_processor: {}".format(msg))  # debug | ||||
| 
 | ||||
|                 # check for control commands | ||||
|                 if msg["chat"]["id"] == 575246355: | ||||
| @ -187,20 +191,23 @@ 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, | ||||
|                                                          parse_mode="MarkdownV2") | ||||
|                                 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] | ||||
| 
 | ||||
| @ -212,6 +219,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] | ||||
| @ -240,7 +248,6 @@ mcu = ModuleControlUnit() | ||||
| processor_thread = threading.Thread(target=queue_processor, args=[]) | ||||
| processor_thread.start() | ||||
| 
 | ||||
| 
 | ||||
| # connecting to Telegram servers and listening for messages | ||||
| 
 | ||||
| TOKEN = readfile("config/token") | ||||
|  | ||||
| @ -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:\ntraceback.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] | ||||
|  | ||||
							
								
								
									
										26
									
								
								modules/auto-schedule-pro-v2/additions-v2.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								modules/auto-schedule-pro-v2/additions-v2.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| [ | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     {}, | ||||
|     {}, | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     { | ||||
|     }, | ||||
|     {}, | ||||
|     {} | ||||
| ] | ||||
| @ -10,6 +10,7 @@ def readfile(filename): | ||||
| # global constants | ||||
| # Accusative - znahidnyj | ||||
| WEEKDAYS_ACCUSATIVE = ["понеділок", "вівторок", "середу", "четвер", "п'ятницю", "суботу", "неділю"] | ||||
| 
 | ||||
| # Genitive - rodovyj | ||||
| WEEKDAYS_GENITIVE_NEXT = ["наступного понеділка", "наступного вівторка", "наступної середи", "наступного четверга", | ||||
|                           "наступної п'ятниці", "наступної суботи", "наступної неділі"] | ||||
| @ -17,10 +18,38 @@ WEEKDAYS_GENITIVE_NEXT = ["наступного понеділка", "насту | ||||
| WEEKDAYS_GENITIVE_THIS = ["цього понеділка", "цього вівторка", "цієї середи", "цього четверга", "цієї п'ятниці", | ||||
|                           "цієї суботи", "цієї неділі"] | ||||
| 
 | ||||
| lesson_types_to_strings = { | ||||
|     "lec": "лекція", | ||||
|     "prac": "практика", | ||||
|     "lab": "лабораторна" | ||||
| } | ||||
| 
 | ||||
| # global variables | ||||
| module_path = "" | ||||
| 
 | ||||
| 
 | ||||
| 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): | ||||
|     human_readable_date = "" | ||||
| @ -43,25 +72,34 @@ 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} | ||||
| def get_name_of_lesson_type(lesson_type): | ||||
|     if lesson_type in lesson_types_to_strings: | ||||
|         return lesson_types_to_strings[lesson_type] | ||||
| 
 | ||||
| 
 | ||||
| def generate_lesson_description(lesson, start_datetime, end_datetime, current_day, current_week, overrides={}, | ||||
|                                 custom_name_prefix="<b>Назва</b>"): | ||||
|     output_settings = {"name": True, "date": True, "teacher": True, "link": True, "comment": True} | ||||
|     output_settings.update(overrides) | ||||
| 
 | ||||
|     result = "" | ||||
| 
 | ||||
|     if output_settings['name']: | ||||
|         result += f"{lesson['name']}\n" | ||||
|         result += f"<b>{escaped_string_html(lesson['name'])}<b> ({escaped_string_html(get_name_of_lesson_type(lesson['type']))})\n" | ||||
| 
 | ||||
|     if output_settings['date']: | ||||
|         human_readable_date = get_human_readable_date(start_datetime, end_datetime, | ||||
|                                                       current_day, current_week) | ||||
|         result += f"*Дата*: {human_readable_date}\n" | ||||
|         result += f"<i>Дата</ii>: {escaped_string_html(human_readable_date)}\n" | ||||
| 
 | ||||
|     if output_settings['teacher']: | ||||
|         result += f"*Викладач*: {lesson['teacher']}\n" | ||||
|         result += f"<i>Викладач</i>: {escaped_string_html(lesson['teacher'])}\n" | ||||
| 
 | ||||
|     if output_settings['link']: | ||||
|         result += f"*Посилання*: {lesson['link']}" | ||||
|         result += f"<i>Посилання</i>: {escaped_string_html(lesson['link'])}\n" | ||||
| 
 | ||||
|     if output_settings['comment'] and 'comment' in lesson: | ||||
|         result += f"<i>Примітка</i>: {escaped_string_html(lesson['comment'])}\n" | ||||
| 
 | ||||
|     return result | ||||
| 
 | ||||
| @ -76,8 +114,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 +150,48 @@ 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="<b>Назва</b>", 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) | ||||
|     if lesson_record.__class__ == dict: | ||||
|         if force_date_at_top: | ||||
|             user_defined_overrides = dict(overrides) | ||||
|             internal_overrides = dict(overrides) | ||||
|             internal_overrides['date'] = False | ||||
| 
 | ||||
|             description = generate_lesson_description(lesson_record, lesson_start_datetime, lesson_end_datetime, | ||||
|                                                       current_day, | ||||
|                                                       current_week, overrides=internal_overrides) | ||||
| 
 | ||||
|             if 'date' in user_defined_overrides and not user_defined_overrides['date']: | ||||
|                 return description | ||||
|             else: | ||||
|                 human_readable_date = get_human_readable_date(lesson_start_datetime, lesson_end_datetime, | ||||
|                                                               current_day, current_week) | ||||
|                 return f"<b><u>{human_readable_date.capitalize()}</u></b>:\n" + description | ||||
|         else: | ||||
|             return generate_lesson_description(lesson_record, lesson_start_datetime, lesson_end_datetime, current_day, | ||||
|                                                current_week, overrides=overrides) | ||||
| 
 | ||||
|     elif lesson_record.__class__ == list: | ||||
|         user_defined_overrides = dict(overrides) | ||||
|         internal_overrides = dict(overrides) | ||||
|         internal_overrides['date'] = False | ||||
| 
 | ||||
|         descriptions = [generate_lesson_description(i, lesson_start_datetime, lesson_end_datetime, current_day, | ||||
|                                                     current_week, overrides=internal_overrides, | ||||
|                                                     custom_name_prefix=custom_name_prefix) for i in lesson_record] | ||||
| 
 | ||||
|         if 'date' in user_defined_overrides and not user_defined_overrides['date']: | ||||
|             return "\n".join(descriptions) | ||||
|         else: | ||||
|             human_readable_date = get_human_readable_date(lesson_start_datetime, lesson_end_datetime, | ||||
|                                                           current_day, current_week) | ||||
|             return f"<b><u>{human_readable_date.capitalize()}</u></b>:\n" + "\n".join(descriptions) | ||||
| 
 | ||||
| 
 | ||||
| def process(message, path): | ||||
| @ -125,13 +204,13 @@ def process(message, path): | ||||
|     base_command = full_command[0].lower() | ||||
| 
 | ||||
|     if base_command not in ["!пара", "!пари"]: | ||||
|         return "" | ||||
|         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() | ||||
| 
 | ||||
| @ -147,12 +226,12 @@ def process(message, path): | ||||
|         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 "Навчання незабаром розпочнеться!" | ||||
|         if -3600 * 4 < study_begin_ts - current_ts < 0: | ||||
|             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 | ||||
| 
 | ||||
|         upcoming_lessons = [timestamp for timestamp in schedule if timestamp > current_seconds - 5400] | ||||
| 
 | ||||
| @ -161,8 +240,8 @@ def process(message, path): | ||||
|         else: | ||||
|             closest_lesson_time = min(schedule) | ||||
| 
 | ||||
|         return "*Актуальна пара*: " + get_lesson_description(schedule, reference_time, closest_lesson_time, current_day, | ||||
|                                                            current_week) | ||||
|         return get_lesson_description(schedule, reference_time, closest_lesson_time, current_day, | ||||
|                                       current_week, custom_name_prefix="<b>Актуальна пара</b>"), "HTML" | ||||
| 
 | ||||
|     elif base_command == "!пари": | ||||
|         base_day = current_week * 7 + current_day | ||||
| @ -176,8 +255,10 @@ 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) | ||||
|         lesson_descriptions_list = [get_lesson_description(schedule, reference_time, lesson_time, current_day, | ||||
|                                                            current_week, overrides=preferences, | ||||
|                                                            custom_name_prefix="<b>Назва</b>", 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"<b><u>Пари у {WEEKDAYS_ACCUSATIVE[selected_day % 7]}</u></b>:\n\n\n" + "\n\n".join( | ||||
|             lesson_descriptions_list), "HTML" | ||||
|  | ||||
							
								
								
									
										286
									
								
								modules/auto-schedule-pro-v2/schedule-v2.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								modules/auto-schedule-pro-v2/schedule-v2.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,286 @@ | ||||
| [ | ||||
|     { | ||||
|         "8:30": { | ||||
|             "name": "Політична наука: конфліктологічний підхід", | ||||
|             "teacher": "Багінський Андрій Владиславович", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": true | ||||
|         }, | ||||
| 
 | ||||
|         "10:25": [ | ||||
|             { | ||||
|                 "name": "Захист персональних даних: стандарти ЄС та Ради Європи", | ||||
|                 "teacher": "Дубняк М. В.", | ||||
|                 "link": "https://us04web.zoom.us/j/7423381732?pwd=c1pJclU2ZDRUWDgyUE10dmhJUDhiZz09", | ||||
|                 "type": "lec", | ||||
|                 "selectable": true | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Психологія", | ||||
|                 "teacher": "Волянюк Н. Ю.", | ||||
|                 "link": "https://us04web.zoom.us/j/6762396563?pwd=L1EvTmpFZHBSdkRHUjZyRG95SFl4QT0", | ||||
|                 "type": "lec", | ||||
|                 "selectable": true | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Психологія конфлікту", | ||||
|                 "teacher": "Москаленко О. В.", | ||||
|                 "link": "https://zoom.us/j/5175581158?pwd=UlhFY3lBOUUrNG9pclRVNndTNTZzQT09", | ||||
|                 "type": "prac", | ||||
|                 "selectable": true | ||||
|             } | ||||
|         ], | ||||
| 
 | ||||
|         "14:15": { | ||||
|             "name": "Основи електронного урядування", | ||||
|             "teacher": "Чукут Світлана Анатоліївна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": true | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "12:20": { | ||||
|             "name": "Інженерія програмного забезпечення", | ||||
|             "teacher": "Васильєва Марія Давидівна", | ||||
|             "link": "https://zoom.us/wc/88696149166/join?from=join&_x_zm_rtaid=qhdJKhYLQNakh-zwxMG4lg.1693903841334.ad606145c892a54a4b450526e2394cbe&_x_zm_rhtaid=531", | ||||
|             "type": "lab", | ||||
|             "selectable": false, | ||||
|             "notice": "Код: 4VHkdw" | ||||
|         }, | ||||
| 
 | ||||
|         "14:15": { | ||||
|             "name": "Теорія електричних кіл та сигналів", | ||||
|             "teacher": "Лободзинський В. Ю. & Ілліна О. О.", | ||||
|             "link": "https://meet.google.com/gwx-sshq-sqb", | ||||
|             "type": "lab", | ||||
|             "selectable": false | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "8:30": { | ||||
|             "name": "Теорія ймовірності та математична статистика", | ||||
|             "teacher": "Марковський Олександр Петрович", | ||||
|             "link": "https://bbb.comsys.kpi.ua/b/ole-9ru-7vc", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
| 
 | ||||
|         "10:25": { | ||||
|             "name": "Вступ до операційної системи Linux", | ||||
|             "teacher": "Роковий Олександр Петрович", | ||||
|             "link": "https://bbb.comsys.kpi.ua/b/ole-knq-z9h-pyl", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "12:20": { | ||||
|             "name": "Інженерія програмного забезпечення", | ||||
|             "teacher": "Васильєва Марія Давидівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "10:25": { | ||||
|             "name": "Вища математика. Частина 3. Ряди. Теорія функцій комплексної змінної. Операційне числення", | ||||
|             "teacher": "Стаматієва Вікторія В'ячеславівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "prac", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "12:20": { | ||||
|             "name": "Практичний курс іноземної мови. Частина 2", | ||||
|             "teacher": "Шевченко Ольга Миколаївна", | ||||
|             "link": "(старе посилання!) https://meet.google.com/bwg-pdnr-evh", | ||||
|             "type": "prac", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "14:15": { | ||||
|             "name": "Соціальна психологія", | ||||
|             "teacher": "Блохіна Ірина Олександрівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "prac", | ||||
|             "selectable": true | ||||
|         }, | ||||
|         "16:10": { | ||||
|             "name": "Основи електронного урядування", | ||||
|             "teacher": "Чукут Світлана Анатоліївна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "prac", | ||||
|             "selectable": true | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "8:30": { | ||||
|             "name": "Вступ до філософії", | ||||
|             "teacher": "Руденко Тамара Петрівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "10:25": { | ||||
|             "name": "Теорія електричних кіл та сигналів", | ||||
|             "teacher": "Лободзинський Вадим Юрійович", | ||||
|             "link": "https://meet.google.com/gwx-sshq-sqb", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "12:20": { | ||||
|             "name": "Вища математика. Частина 3. Ряди. Теорія функцій комплексної змінної. Операційне числення", | ||||
|             "teacher": "Овчар Раїса Федорівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         } | ||||
|     }, | ||||
|     {}, | ||||
|     {}, | ||||
|     { | ||||
|         "10:25": [ | ||||
|             { | ||||
|                 "name": "Психологія", | ||||
|                 "teacher": "Сербова О. В.", | ||||
|                 "link": "https://us04web.zoom.us/j/6762396563?pwd=L1EvTmpFZHBSdkRHUjZyRG95SFl4QT09", | ||||
|                 "type": "prac", | ||||
|                 "selectable": true | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Психологія конфлікту", | ||||
|                 "teacher": "Кононець М. О.", | ||||
|                 "link": "https://zoom.us/j/5175581158?pwd=UlhFY3lBOUUrNG9pclRVNndTNTZzQT09", | ||||
|                 "type": "lec", | ||||
|                 "selectable": true | ||||
|             } | ||||
|         ], | ||||
| 
 | ||||
|         "12:20": [ | ||||
|             { | ||||
|                 "name": "Політична наука: конфліктологічний підхід", | ||||
|                 "teacher": "Северинчик О. П.", | ||||
|                 "link": "https://zoom.us/j/5175581158?pwd=UlhFY3lBOUUrNG9pclRVNndTNTZzQT09", | ||||
|                 "type": "prac", | ||||
|                 "selectable": true | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Захист персональних даних: стандарти ЄС та Ради Європи", | ||||
|                 "teacher": "Самчинська О. А.", | ||||
|                 "link": "(посилання відсутнє!)", | ||||
|                 "type": "prac", | ||||
|                 "selectable": true  | ||||
|             } | ||||
|         ], | ||||
| 
 | ||||
|         "14:15": { | ||||
|             "name": "Розумні міста", | ||||
|             "teacher": "Чукут Світлана Анатоліївна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": true  | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "10:25": { | ||||
|             "name": "Вступ до філософії", | ||||
|             "teacher": "Руденко Тамара Петрівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "prac", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "14:15": { | ||||
|             "name": "Теорія ймовірності та математична статистика", | ||||
|             "teacher": "Марковський Олександр Петрович", | ||||
|             "link": "https://bbb.comsys.kpi.ua/b/ole-9ru-7vc", | ||||
|             "type": "prac", | ||||
|             "selectable": false | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "8:30": { | ||||
|             "name": "Теорія ймовірності та математична статистика", | ||||
|             "teacher": "Марковський Олександр Петрович", | ||||
|             "link": "https://bbb.comsys.kpi.ua/b/ole-9ru-7vc", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "10:25": { | ||||
|             "name": "Вступ до операційної системи Linux", | ||||
|             "teacher": "Роковий Олександр Петрович", | ||||
|             "link": "https://bbb.comsys.kpi.ua/b/ole-knq-z9h-pyl", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "12:20": { | ||||
|             "name": "Інженерія програмного забезпечення", | ||||
|             "teacher": "Васильєва Марія Давидівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "14:15": { | ||||
|             "name": "Інженерія програмного забезпечення", | ||||
|             "teacher": "Васильєва Марія Давидівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         } | ||||
|     }, | ||||
|     { | ||||
|         "8:30": { | ||||
|             "name": "Вступ до операційної системи Linux", | ||||
|             "teacher": "Алєнін Олег Ігорович", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lab", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "10:25": { | ||||
|             "name": "Вища математика. Частина 3. Ряди. Теорія функцій комплексної змінної. Операційне числення", | ||||
|             "teacher": "Стаматієва Вікторія В'ячеславівна", | ||||
|             "link": "(старе посилання!) https://us04web.zoom.us/j/2313886209?pwd=dnZHanV3cU9LUXJBVWYyYVArUFg5dz09", | ||||
|             "type": "prac", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "12:20": { | ||||
|             "name": "Практичний курс іноземної мови. Частина 2", | ||||
|             "teacher": "Шевченко Ольга Миколаївна", | ||||
|             "link": "(старе посилання!) https://meet.google.com/bwg-pdnr-evh", | ||||
|             "type": "prac", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "14:15": [ | ||||
|             { | ||||
|                 "name": "Соціальна психологія", | ||||
|                 "teacher": "Винославська О. В.", | ||||
|                 "link": "(посилання відсутнє!)", | ||||
|                 "type": "lec", | ||||
|                 "selectable": true | ||||
|             }, | ||||
|             { | ||||
|                 "name": "Розумні міста", | ||||
|                 "teacher": "Чукут С. А.", | ||||
|                 "link": "(посилання відсутні!)", | ||||
|                 "type": "prac", | ||||
|                 "selectable": true | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     { | ||||
|         "10:25": { | ||||
|             "name": "Теорія електричних кіл та сигналів", | ||||
|             "teacher": "Лободзинський Вадим Юрійович", | ||||
|             "link": "https://meet.google.com/gwx-sshq-sqb", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         }, | ||||
|         "12:20": { | ||||
|             "name": "Вища математика. Частина 3. Ряди. Теорія функцій комплексної змінної. Операційне числення", | ||||
|             "teacher": "Овчар Раїса Федорівна", | ||||
|             "link": "(посилання відсутнє!)", | ||||
|             "type": "lec", | ||||
|             "selectable": false | ||||
|         } | ||||
|     }, | ||||
|     {}, | ||||
|     {} | ||||
| ] | ||||
| @ -9,8 +9,8 @@ | ||||
|         "14:15": {"name": "Теорія електричних кіл та сигналів (лабораторна)", "teacher": "Лободзинський В. Ю. & Ілліна О. О.", "link": "https://meet.google.com/gwx-sshq-sqb"} | ||||
|     }, | ||||
|     { | ||||
|         "8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "(посилання відсутнє!)"}, | ||||
|         "10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "(посилання відсутнє!)"}, | ||||
|         "8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-9ru-7vc"}, | ||||
|         "10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-knq-z9h-pyl"}, | ||||
|         "12:20": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"} | ||||
|     }, | ||||
|     { | ||||
| @ -36,8 +36,8 @@ | ||||
|         "14:15": {"name": "Теорія ймовірності та математична статистика (практика)", "teacher": "Марковський Олександр Петрович", "link": "(посилання відсутнє!)"} | ||||
|     }, | ||||
|     { | ||||
|         "8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "(посилання відсутнє!)"}, | ||||
|         "10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "(посилання відсутнє!)"}, | ||||
|         "8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-9ru-7vc"}, | ||||
|         "10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-knq-z9h-pyl"}, | ||||
|         "12:20": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"}, | ||||
|         "14:15": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"} | ||||
|     }, | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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"<b><u>Результат</u></b>\n{escaped_string(decoded_text)}" | ||||
|             self.FORMAT = "HTML" | ||||
| 
 | ||||
|     except Exception as e: | ||||
|         print(f"[translit-decoder] Got exception: {e}") | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user