Compare commits
10 Commits
8cc68080e8
...
b0ea33cfff
Author | SHA1 | Date |
---|---|---|
Rhinemann | b0ea33cfff | |
dymik739 | e9bec0159f | |
dymik739 | 5dc78b8cb0 | |
dymik739 | 67b3c4278b | |
dymik739 | 0497cbf9b7 | |
dymik739 | 2b9ac41ced | |
dymik739 | fc450f633e | |
dymik739 | 1070362bc6 | |
dymik739 | d2915c10e2 | |
dymik739 | ebdae6256e |
|
@ -1,2 +1,3 @@
|
||||||
config/*
|
config/*
|
||||||
modules/irc-bridge/error.log
|
modules/irc-bridge/error.log
|
||||||
|
__pycache__/
|
||||||
|
|
45
main.py
45
main.py
|
@ -7,6 +7,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import importlib
|
import importlib
|
||||||
|
import traceback
|
||||||
|
|
||||||
# global variables
|
# global variables
|
||||||
STOP_REQUESTED = False
|
STOP_REQUESTED = False
|
||||||
|
@ -39,6 +40,7 @@ class ModuleV1:
|
||||||
# set environmental variables
|
# set environmental variables
|
||||||
def set_env(self):
|
def set_env(self):
|
||||||
self.RESPONSE = ""
|
self.RESPONSE = ""
|
||||||
|
self.FORMAT = ""
|
||||||
|
|
||||||
def set_predefine(self):
|
def set_predefine(self):
|
||||||
try:
|
try:
|
||||||
|
@ -54,10 +56,11 @@ class ModuleV1:
|
||||||
self.MESSAGE = msg
|
self.MESSAGE = msg
|
||||||
try:
|
try:
|
||||||
exec(self.code)
|
exec(self.code)
|
||||||
return self.RESPONSE
|
return self.RESPONSE, self.FORMAT
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] module v1: module \"{self.path}\" ({self.alias}) raised exception \"{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:
|
class ModuleV2:
|
||||||
|
@ -75,7 +78,8 @@ class ModuleV2:
|
||||||
return self.obj.process(msg, self.path)
|
return self.obj.process(msg, self.path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] module v2: module \"{self.path}\" ({self.alias}) raised exception \"{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
|
# module control unit
|
||||||
|
@ -94,7 +98,7 @@ class ModuleControlUnit:
|
||||||
print(f"[WARN] module_loader: no meta.json found in module folder \"{folder}\"")
|
print(f"[WARN] module_loader: no meta.json found in module folder \"{folder}\"")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
meta = json.loads( meta_raw )
|
meta = json.loads(meta_raw)
|
||||||
if "version" in meta:
|
if "version" in meta:
|
||||||
if meta["version"] == 1:
|
if meta["version"] == 1:
|
||||||
if "index_file" in meta:
|
if "index_file" in meta:
|
||||||
|
@ -102,8 +106,8 @@ class ModuleControlUnit:
|
||||||
else:
|
else:
|
||||||
index_file = "index.py"
|
index_file = "index.py"
|
||||||
|
|
||||||
code = readfile( "modules/{}/{}".format(folder, index_file) )
|
code = readfile("modules/{}/{}".format(folder, index_file))
|
||||||
if not code: # False both when readfile() returns False and when the code string is empty
|
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))
|
print("[WARN] reload_modules: module {} does not have any code, skipping...".format(folder))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -162,7 +166,7 @@ def queue_processor():
|
||||||
try:
|
try:
|
||||||
if len(message_queue) > 0:
|
if len(message_queue) > 0:
|
||||||
msg = 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
|
# check for control commands
|
||||||
if msg["chat"]["id"] == 575246355:
|
if msg["chat"]["id"] == 575246355:
|
||||||
|
@ -187,20 +191,23 @@ def queue_processor():
|
||||||
# modules are used in here
|
# modules are used in here
|
||||||
for mod in mcu.modules:
|
for mod in mcu.modules:
|
||||||
if mod.enabled:
|
if mod.enabled:
|
||||||
if mod.version == 1 or mod.version == 2:
|
if mod.version in [1, 2]:
|
||||||
response = mod.process(msg)
|
response, formatting = mod.process(msg)
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
# protecting output
|
if formatting == None:
|
||||||
symbols_to_escape = ['[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!']
|
updater.bot.send_message(chat_id=msg.chat.id, text=response,
|
||||||
for symbol in symbols_to_escape:
|
disable_web_page_preview=True)
|
||||||
response = response.replace(symbol, f"\\{symbol}")
|
print(f"Responded using module {mod.path} ({mod.alias}) with text: {response}")
|
||||||
|
break
|
||||||
|
|
||||||
updater.bot.send_message(chat_id=msg.chat.id, text=response,
|
elif formatting in ["Markdown", "MarkdownV2", "HTML"]:
|
||||||
disable_web_page_preview=True,
|
updater.bot.send_message(chat_id=msg.chat.id, text=response,
|
||||||
parse_mode="MarkdownV2")
|
disable_web_page_preview=True,
|
||||||
print(f"Responded using module {mod.path} ({mod.alias}) with text: {response}")
|
parse_mode=formatting)
|
||||||
break
|
print(
|
||||||
|
f"Responded using module {mod.path} ({mod.alias}) with text (using {formatting}): {response}")
|
||||||
|
break
|
||||||
|
|
||||||
del message_queue[0]
|
del message_queue[0]
|
||||||
|
|
||||||
|
@ -212,6 +219,7 @@ def queue_processor():
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] queue_processor: current message queue: {message_queue}")
|
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...")
|
print(f"[ERROR] queue_processor: error while processing message ({e}), trying to delete it...")
|
||||||
try:
|
try:
|
||||||
del message_queue[0]
|
del message_queue[0]
|
||||||
|
@ -240,7 +248,6 @@ mcu = ModuleControlUnit()
|
||||||
processor_thread = threading.Thread(target=queue_processor, args=[])
|
processor_thread = threading.Thread(target=queue_processor, args=[])
|
||||||
processor_thread.start()
|
processor_thread.start()
|
||||||
|
|
||||||
|
|
||||||
# connecting to Telegram servers and listening for messages
|
# connecting to Telegram servers and listening for messages
|
||||||
|
|
||||||
TOKEN = readfile("config/token")
|
TOKEN = readfile("config/token")
|
||||||
|
|
|
@ -6,6 +6,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import importlib
|
import importlib
|
||||||
|
import traceback
|
||||||
|
|
||||||
from telegram import Message, Chat
|
from telegram import Message, Chat
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ class ModuleV1:
|
||||||
# set environmental variables
|
# set environmental variables
|
||||||
def set_env(self):
|
def set_env(self):
|
||||||
self.RESPONSE = ""
|
self.RESPONSE = ""
|
||||||
|
self.FORMAT = ""
|
||||||
|
|
||||||
def set_predefine(self):
|
def set_predefine(self):
|
||||||
try:
|
try:
|
||||||
|
@ -55,10 +57,11 @@ class ModuleV1:
|
||||||
self.MESSAGE = msg
|
self.MESSAGE = msg
|
||||||
try:
|
try:
|
||||||
exec(self.code)
|
exec(self.code)
|
||||||
return self.RESPONSE
|
return self.RESPONSE, self.FORMAT
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] module v1: module \"{self.path}\" ({self.alias}) raised exception \"{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:
|
class ModuleV2:
|
||||||
|
@ -73,11 +76,11 @@ class ModuleV2:
|
||||||
# running the module
|
# running the module
|
||||||
def process(self, msg):
|
def process(self, msg):
|
||||||
try:
|
try:
|
||||||
responce = self.obj.process(msg, self.path)
|
return self.obj.process(msg, self.path)
|
||||||
return responce
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] module v2: module \"{self.path}\" ({self.alias}) raised exception \"{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
|
# module control unit
|
||||||
|
@ -188,11 +191,16 @@ def queue_processor():
|
||||||
# modules are used in here
|
# modules are used in here
|
||||||
for mod in mcu.modules:
|
for mod in mcu.modules:
|
||||||
if mod.enabled:
|
if mod.enabled:
|
||||||
if mod.version == 1 or mod.version == 2:
|
if mod.version in [1, 2]:
|
||||||
response = mod.process(msg)
|
response, formatting = mod.process(msg)
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
print(f"Responded using module {mod.path} ({mod.alias}) with text: {response}")
|
if formatting == None:
|
||||||
break
|
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]
|
del message_queue[0]
|
||||||
else:
|
else:
|
||||||
|
@ -203,6 +211,7 @@ def queue_processor():
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
print(f"[ERROR] queue_processor: current message queue: {message_queue}")
|
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...")
|
print("[ERROR] queue_processor: error while processing message, trying to delete it...")
|
||||||
try:
|
try:
|
||||||
del message_queue[0]
|
del message_queue[0]
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
]
|
|
@ -10,6 +10,7 @@ def readfile(filename):
|
||||||
# global constants
|
# global constants
|
||||||
# Accusative - znahidnyj
|
# Accusative - znahidnyj
|
||||||
WEEKDAYS_ACCUSATIVE = ["понеділок", "вівторок", "середу", "четвер", "п'ятницю", "суботу", "неділю"]
|
WEEKDAYS_ACCUSATIVE = ["понеділок", "вівторок", "середу", "четвер", "п'ятницю", "суботу", "неділю"]
|
||||||
|
|
||||||
# Genitive - rodovyj
|
# Genitive - rodovyj
|
||||||
WEEKDAYS_GENITIVE_NEXT = ["наступного понеділка", "наступного вівторка", "наступної середи", "наступного четверга",
|
WEEKDAYS_GENITIVE_NEXT = ["наступного понеділка", "наступного вівторка", "наступної середи", "наступного четверга",
|
||||||
"наступної п'ятниці", "наступної суботи", "наступної неділі"]
|
"наступної п'ятниці", "наступної суботи", "наступної неділі"]
|
||||||
|
@ -17,10 +18,38 @@ WEEKDAYS_GENITIVE_NEXT = ["наступного понеділка", "насту
|
||||||
WEEKDAYS_GENITIVE_THIS = ["цього понеділка", "цього вівторка", "цієї середи", "цього четверга", "цієї п'ятниці",
|
WEEKDAYS_GENITIVE_THIS = ["цього понеділка", "цього вівторка", "цієї середи", "цього четверга", "цієї п'ятниці",
|
||||||
"цієї суботи", "цієї неділі"]
|
"цієї суботи", "цієї неділі"]
|
||||||
|
|
||||||
|
lesson_types_to_strings = {
|
||||||
|
"lec": "лекція",
|
||||||
|
"prac": "практика",
|
||||||
|
"lab": "лабораторна"
|
||||||
|
}
|
||||||
|
|
||||||
# global variables
|
# global variables
|
||||||
module_path = ""
|
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,
|
def get_human_readable_date(start_datetime, end_datetime,
|
||||||
current_day, current_week):
|
current_day, current_week):
|
||||||
human_readable_date = ""
|
human_readable_date = ""
|
||||||
|
@ -43,25 +72,34 @@ def get_human_readable_date(start_datetime, end_datetime,
|
||||||
return human_readable_date
|
return human_readable_date
|
||||||
|
|
||||||
|
|
||||||
def generate_lesson_description(lesson, start_datetime, end_datetime, current_day, current_week, overrides={}):
|
def get_name_of_lesson_type(lesson_type):
|
||||||
output_settings = {"name": True, "date": True, "teacher": True, "link": True}
|
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)
|
output_settings.update(overrides)
|
||||||
|
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
if output_settings['name']:
|
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']:
|
if output_settings['date']:
|
||||||
human_readable_date = get_human_readable_date(start_datetime, end_datetime,
|
human_readable_date = get_human_readable_date(start_datetime, end_datetime,
|
||||||
current_day, current_week)
|
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']:
|
if output_settings['teacher']:
|
||||||
result += f"*Викладач*: {lesson['teacher']}\n"
|
result += f"<i>Викладач</i>: {escaped_string_html(lesson['teacher'])}\n"
|
||||||
|
|
||||||
if output_settings['link']:
|
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
|
return result
|
||||||
|
|
||||||
|
@ -76,8 +114,15 @@ def get_schedule_data_from(filename):
|
||||||
timestamp = day_number * 86400 + int(lesson_time.split(":")[0]) * 3600 \
|
timestamp = day_number * 86400 + int(lesson_time.split(":")[0]) * 3600 \
|
||||||
+ int(lesson_time.split(":")[1]) * 60
|
+ int(lesson_time.split(":")[1]) * 60
|
||||||
|
|
||||||
new_record = dict(raw_schedule[day_number][lesson_time])
|
new_record = raw_schedule[day_number][lesson_time]
|
||||||
new_record["source"] = filename.split(".json")[0]
|
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
|
baked_schedule[timestamp] = new_record
|
||||||
|
|
||||||
return baked_schedule
|
return baked_schedule
|
||||||
|
@ -105,14 +150,48 @@ def process_arguments(args, base_day):
|
||||||
return preferences, selected_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_record = schedule[lesson_time]
|
||||||
|
|
||||||
lesson_start_datetime = datetime.fromtimestamp(reference_time + lesson_time)
|
lesson_start_datetime = datetime.fromtimestamp(reference_time + lesson_time)
|
||||||
lesson_end_datetime = datetime.fromtimestamp(reference_time + lesson_time + 5400)
|
lesson_end_datetime = datetime.fromtimestamp(reference_time + lesson_time + 5400)
|
||||||
|
|
||||||
return generate_lesson_description(lesson_record, lesson_start_datetime, lesson_end_datetime, current_day,
|
if lesson_record.__class__ == dict:
|
||||||
current_week, overrides=overrides)
|
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):
|
def process(message, path):
|
||||||
|
@ -125,13 +204,13 @@ def process(message, path):
|
||||||
base_command = full_command[0].lower()
|
base_command = full_command[0].lower()
|
||||||
|
|
||||||
if base_command not in ["!пара", "!пари"]:
|
if base_command not in ["!пара", "!пари"]:
|
||||||
return ""
|
return None, None
|
||||||
|
|
||||||
global module_path
|
global module_path
|
||||||
module_path = path
|
module_path = path
|
||||||
|
|
||||||
schedule = get_schedule_data_from("schedule.json")
|
schedule = get_schedule_data_from("schedule-v2.json")
|
||||||
schedule.update(get_schedule_data_from("additions.json"))
|
schedule.update(get_schedule_data_from("additions-v2.json"))
|
||||||
|
|
||||||
current_time = datetime.now()
|
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"))
|
study_begin_ts = int(datetime(year=2023, month=9, day=4).strftime("%s"))
|
||||||
current_ts = int(datetime.now().strftime("%s"))
|
current_ts = int(datetime.now().strftime("%s"))
|
||||||
|
|
||||||
if -3600*4 < study_begin_ts - current_ts < 0:
|
if -3600 * 4 < study_begin_ts - current_ts < 0:
|
||||||
return "Навчання незабаром розпочнеться!"
|
return "Навчання незабаром розпочнеться!", None
|
||||||
elif 0 <= study_begin_ts - current_ts < 1209600:
|
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:
|
elif study_begin_ts - current_ts >= 1209600:
|
||||||
return "Ви маєте законне право відпочити, пари почнуться не скоро"
|
return "Ви маєте законне право відпочити, пари почнуться не скоро", None
|
||||||
|
|
||||||
upcoming_lessons = [timestamp for timestamp in schedule if timestamp > current_seconds - 5400]
|
upcoming_lessons = [timestamp for timestamp in schedule if timestamp > current_seconds - 5400]
|
||||||
|
|
||||||
|
@ -161,8 +240,8 @@ def process(message, path):
|
||||||
else:
|
else:
|
||||||
closest_lesson_time = min(schedule)
|
closest_lesson_time = min(schedule)
|
||||||
|
|
||||||
return "*Актуальна пара*: " + get_lesson_description(schedule, reference_time, closest_lesson_time, current_day,
|
return get_lesson_description(schedule, reference_time, closest_lesson_time, current_day,
|
||||||
current_week)
|
current_week, custom_name_prefix="<b>Актуальна пара</b>"), "HTML"
|
||||||
|
|
||||||
elif base_command == "!пари":
|
elif base_command == "!пари":
|
||||||
base_day = current_week * 7 + current_day
|
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_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,
|
lesson_descriptions_list = [get_lesson_description(schedule, reference_time, lesson_time, current_day,
|
||||||
current_day, current_week, overrides=preferences)
|
current_week, overrides=preferences,
|
||||||
|
custom_name_prefix="<b>Назва</b>", force_date_at_top=True)
|
||||||
for lesson_time in lesson_list]
|
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"
|
||||||
|
|
|
@ -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"}
|
"14:15": {"name": "Теорія електричних кіл та сигналів (лабораторна)", "teacher": "Лободзинський В. Ю. & Ілліна О. О.", "link": "https://meet.google.com/gwx-sshq-sqb"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "(посилання відсутнє!)"},
|
"8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-9ru-7vc"},
|
||||||
"10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "(посилання відсутнє!)"},
|
"10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-knq-z9h-pyl"},
|
||||||
"12:20": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"}
|
"12:20": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -36,8 +36,8 @@
|
||||||
"14:15": {"name": "Теорія ймовірності та математична статистика (практика)", "teacher": "Марковський Олександр Петрович", "link": "(посилання відсутнє!)"}
|
"14:15": {"name": "Теорія ймовірності та математична статистика (практика)", "teacher": "Марковський Олександр Петрович", "link": "(посилання відсутнє!)"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "(посилання відсутнє!)"},
|
"8:30": {"name": "Теорія ймовірності та математична статистика (лекція)", "teacher": "Марковський Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-9ru-7vc"},
|
||||||
"10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "(посилання відсутнє!)"},
|
"10:25": {"name": "Вступ до операційної системи Linux (лекція)", "teacher": "Роковий Олександр Петрович", "link": "https://bbb.comsys.kpi.ua/b/ole-knq-z9h-pyl"},
|
||||||
"12:20": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"},
|
"12:20": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"},
|
||||||
"14:15": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"}
|
"14:15": {"name": "Інженерія програмного забезпечення (лекція)", "teacher": "Васильєва Марія Давидівна", "link": "(посилання відсутнє!)"}
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,4 +13,6 @@ def get_num():
|
||||||
|
|
||||||
def process(message, path):
|
def process(message, path):
|
||||||
if message.text == "!v2-testing":
|
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 = self.MESSAGE['text'].split(" ", 2)
|
||||||
command_length = len(command)
|
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):
|
if (command[0] in self.aliases) and (1 <= command_length <= 3):
|
||||||
try:
|
try:
|
||||||
models = json.loads(readfile(self.path + "translate_models.json"))
|
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].capitalize(), i[1].capitalize())
|
||||||
decoded_text = decoded_text.replace(i[0].upper(), i[1].upper())
|
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:
|
except Exception as e:
|
||||||
print(f"[translit-decoder] Got exception: {e}")
|
print(f"[translit-decoder] Got exception: {e}")
|
||||||
|
|
Loading…
Reference in New Issue