diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e7d28ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +config/* +modules/irc-bridge/error.log diff --git a/main.py b/main.py index ba07c41..f6bac81 100644 --- a/main.py +++ b/main.py @@ -180,11 +180,13 @@ def queue_processor(): if mod.version == 1: responce = mod.process(msg) if len(responce) > 0: - updater.bot.send_message(chat_id = msg.chat.id, text = responce) + updater.bot.send_message(chat_id = msg.chat.id, text = responce, disable_web_page_preview = True) print("Responded using module {} ({}) with text: {}".format(mod.path, mod.alias, responce)) break del message_queue[0] + + time.sleep(0.1) else: if STOP_REQUESTED: break diff --git a/modules/auto-schedule-pro/additions.json b/modules/auto-schedule-pro/additions.json new file mode 100644 index 0000000..e71bbb4 --- /dev/null +++ b/modules/auto-schedule-pro/additions.json @@ -0,0 +1,27 @@ +[ + { + "12:20": {"name": "Культура мовлення та ділове мовлення", "teacher": "Кушлаба М. П.", "link": "https://bbb.comsys.kpi.ua/b/myk-0iw-red-p01"} + }, + { + }, + { + }, + { + }, + { + }, + {}, + {}, + { + }, + { + }, + { + }, + { + }, + { + }, + {}, + {} +] diff --git a/modules/auto-schedule-pro/index.py b/modules/auto-schedule-pro/index.py new file mode 100644 index 0000000..5950cce --- /dev/null +++ b/modules/auto-schedule-pro/index.py @@ -0,0 +1,234 @@ +## env approximation ## +''' +import datetime, json, time + +class Self: + def __init__(self): + self.path = "" + self.WEEKDAY_NAMES_ROD = ["понеділка", "вівторка", "середи", "четверга", "п'ятниці", "суботи", "неділі"] + self.WEEKDAY_NAMES_ROD_WITH_NEXT = ["наступного понеділка", "наступного вівторка", "наступної середи", "наступного четверга", "наступної п'ятниці", "наступної суботи", "наступної неділі"] + self.WEEKDAY_NAMES_ROD_WITH_THIS = ["цього понеділка", "цього вівторка", "цієї середи", "цього четверга", "цієї п'ятниці", "цієї суботи", "цієї неділі"] + + +def readfile(path): + return open(path).read() + +self = Self() +''' + + +## code ## +if self.MESSAGE["text"].lower() == "!пара": + current_time = datetime.datetime.now() + + current_week = current_time.isocalendar()[1] % 2 + current_day = current_time.weekday() + current_seconds = current_week*604800 + current_day*86400 + current_time.hour*3600 + current_time.minute*60 + current_time.second + reference_time = int(current_time.strftime("%s")) - current_seconds + + # baking defined schedule + raw_schedule = json.loads( readfile(self.path + "schedule.json") ) + schedule = {} + for day in range(len(raw_schedule)): + for i in raw_schedule[day]: + ts = day*86400 + int(i.split(":")[0])*3600 + int(i.split(":")[1])*60 + new_item = dict(raw_schedule[day][i]) + new_item["source"] = "schedule" + schedule[ts] = new_item + + # baking additions (extra pairs) + raw_additions = json.loads( readfile(self.path + "additions.json") ) + additions = {} + for day in range(len(raw_additions)): + for i in raw_additions[day]: + ts = day*86400 + int(i.split(":")[0])*3600 + int(i.split(":")[1])*60 + new_item = dict(raw_additions[day][i]) + new_item["source"] = "additions" + schedule[ts] = new_item + + full_schedule = dict(list(schedule.items()) + list(additions.items())) + + print("test1") + print(f"Full schedule printout: {full_schedule}") + print(f"Current delta_time: {current_seconds}") + p = None + next_pair_time = None + + key_list = list(full_schedule.keys()) + key_list.sort() + for i in key_list: + if i > current_seconds - 5400: + p = full_schedule[i] + next_pair_time = i + break + + print("test2") + if next_pair_time == None: + if len(full_schedule.keys()) > 0: + print("test3.1") + actual_pair_ts = reference_time + min(full_schedule.keys()) + dt_pair = datetime.datetime.fromtimestamp(actual_pair_ts) + dt_pair_finish = datetime.datetime.fromtimestamp(actual_pair_ts + 5400) + p = full_schedule[min(full_schedule.keys())] + print("test3.1.1") + + print("{} == 6 && {} == 1, {}".format(current_day, dt_pair.strftime('%u'), str( ((current_day + 2) == int(dt_pair.strftime("%u"))) or ((str(current_day) == "6") and (dt_pair.strftime("%u") == "1")) ))) + + human_readable_date = "" + if ((current_day + 2) == int(dt_pair.strftime("%u"))) or ((str(current_day) == "6") and (dt_pair.strftime("%u") == "1")): + human_readable_date += "завтра " + elif current_week != int(dt_pair.strftime("%W")) % 2: + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_NEXT[int(dt_pair.strftime("%u")) - 1]) + elif current_day != (int(dt_pair.strftime("%u")) - 1): + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_THIS[int(dt_pair.strftime("%u")) - 1]) + else: + human_readable_date += "сьогодні " + + print("test3.1.2") + + human_readable_date += "з " + + print("test3.1.3") + human_readable_date += dt_pair.strftime("%H:%M") + print("test3.1.4") + + human_readable_date += " до " + human_readable_date += dt_pair_finish.strftime("%H:%M") + + self.RESPONCE = "Актуальна пара: {}\nДата: {}\nВикладач: {}\nПосилання на пару: {}".format(p['name'], human_readable_date, p['teacher'], p['link']) + print("test3.1.5") + else: + self.RESPONCE = "Пар немає взагалі. Ми вільні!" + + else: + print("test3.2") + actual_pair_ts = reference_time + next_pair_time + dt_pair = datetime.datetime.fromtimestamp(actual_pair_ts) + dt_pair_finish = datetime.datetime.fromtimestamp(actual_pair_ts + 5400) + + human_readable_date = "" + if ((current_day + 2) == int(dt_pair.strftime("%u"))) or ((str(current_day) == "6") and (dt_pair.strftime("%u") == "1")): + human_readable_date += "завтра " + elif current_week != int(dt_pair.strftime("%W")) % 2: + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_NEXT[int(dt_pair.strftime("%u")) - 1]) + elif current_day != (int(dt_pair.strftime("%u")) - 1): + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_THIS[int(dt_pair.strftime("%u")) - 1]) + else: + human_readable_date += "сьогодні " + + human_readable_date += "з " + human_readable_date += dt_pair.strftime("%H:%M") + + human_readable_date += " до " + human_readable_date += dt_pair_finish.strftime("%H:%M") + + self.RESPONCE = "Актуальна пара: {}\nДата: {}\nВикладач: {}\nПосилання на пару: {}".format(p['name'], human_readable_date, p['teacher'], p['link']) + +if self.MESSAGE["text"].lower().split()[0] == "!пари": + command = self.MESSAGE["text"].lower().split() + + current_time = datetime.datetime.now() + + current_week = current_time.isocalendar()[1] % 2 + current_day = current_time.weekday() + current_seconds = current_week*604800 + current_day*86400 + current_time.hour*3600 + current_time.minute*60 + current_time.second + reference_time = int(current_time.strftime("%s")) - current_seconds + + # baking defined schedule + raw_schedule = json.loads( readfile(self.path + "schedule.json") ) + schedule = {} + for day in range(len(raw_schedule)): + for i in raw_schedule[day]: + ts = day*86400 + int(i.split(":")[0])*3600 + int(i.split(":")[1])*60 + new_item = dict(raw_schedule[day][i]) + new_item["source"] = "schedule" + schedule[ts] = new_item + + # baking additions (extra pairs) + raw_additions = json.loads( readfile(self.path + "additions.json") ) + additions = {} + for day in range(len(raw_additions)): + for i in raw_additions[day]: + ts = day*86400 + int(i.split(":")[0])*3600 + int(i.split(":")[1])*60 + new_item = dict(raw_additions[day][i]) + new_item["source"] = "additions" + schedule[ts] = new_item + + full_schedule = dict(list(schedule.items()) + list(additions.items())) + + preferences = {"name": True, "date": True, "teacher": True, "link": True} + selected_day = current_week*7 + current_day + + if len(command) >= 2 and len(command[1]) > 0: + if command[1][0] == "+": + try: + selected_day += int(command[1][1:]) + except Exception as e: + print(f"[auto-schedule-pro:error] Got exception '{e}' while parsing {command[1]}") + elif command[1][0] == "-": + try: + selected_day -= int(command[1][1:]) + except Exception as e: + print(f"[auto-schedule-pro:error] Got exception '{e}' while parsing {command[1]}") + else: + try: + selected_day = int(command[1]) + except Exception as e: + print(f"[auto-schedule-pro:error] Got exception '{e}' while parsing {command[1]}") + + # keeping day in bounds + while selected_day > 13: + selected_day -= 14 + while selected_day < 0: + selected_day += 14 + + if len(command) > 2: + for i in command[2:]: + if len(i) >= 2: + if i[1:] in preferences: + if i[0] == "+": + preferences[i[1:]] = True + elif i[0] == "-": + preferences[i[1:]] = False + + found_pairs = {} + for i in full_schedule: + if selected_day*86400 <= i < (selected_day+1)*86400: + found_pairs[i] = dict(full_schedule[i]) + + result_text = f"Пари у {self.WEEKDAY_NAMES_ZNAH[selected_day%7]}:\n\n" + for i in found_pairs: + actual_pair_ts = reference_time + i + dt_pair = datetime.datetime.fromtimestamp(actual_pair_ts) + dt_pair_finish = datetime.datetime.fromtimestamp(actual_pair_ts + 5400) + p = found_pairs[i] + + human_readable_date = "" + if ((current_day + 2) == int(dt_pair.strftime("%u"))) or ((str(current_day) == "6") and (dt_pair.strftime("%u") == "1")): + human_readable_date += "завтра " + elif current_week != int(dt_pair.strftime("%W")) % 2: + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_NEXT[int(dt_pair.strftime("%u")) - 1]) + elif current_day != (int(dt_pair.strftime("%u")) - 1): + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_THIS[int(dt_pair.strftime("%u")) - 1]) + else: + human_readable_date += "сьогодні " + + human_readable_date += "з " + human_readable_date += dt_pair.strftime("%H:%M") + + human_readable_date += " до " + human_readable_date += dt_pair_finish.strftime("%H:%M") + + + if preferences['name']: + result_text += f"Назва: {p['name']}\n" + if preferences['date']: + result_text += f"Дата: {human_readable_date}\n" + if preferences['teacher']: + result_text += f"Викладач: {p['teacher']}\n" + if preferences['link']: + result_text += f"Посилання на пару: {p['link']}\n" + + result_text += "\n" + + self.RESPONCE = result_text diff --git a/modules/auto-schedule-pro/meta.json b/modules/auto-schedule-pro/meta.json new file mode 100644 index 0000000..732f1ea --- /dev/null +++ b/modules/auto-schedule-pro/meta.json @@ -0,0 +1,7 @@ +{ + "start_on_boot": true, + "alias": "auto-schedule-pro", + "version": 1, + "index_file": "index.py", + "predefine": "predefine.py" +} diff --git a/modules/auto-schedule-pro/predefine.py b/modules/auto-schedule-pro/predefine.py new file mode 100644 index 0000000..6092c07 --- /dev/null +++ b/modules/auto-schedule-pro/predefine.py @@ -0,0 +1,4 @@ +self.WEEKDAY_NAMES_ZNAH = ["понедулок", "вівторок", "середу", "четвер", "п'ятницю", "суботу", "неділю"] +self.WEEKDAY_NAMES_ROD_WITH_NEXT = ["наступного понеділка", "наступного вівторка", "наступної середи", "наступного четверга", "наступної п'ятниці", "наступної суботи", "наступної неділі"] +self.WEEKDAY_NAMES_ROD_WITH_THIS = ["цього понеділка", "цього вівторка", "цієї середи", "цього четверга", "цієї п'ятниці", "цієї суботи", "цієї неділі"] +self.current_seconds = 0 diff --git a/modules/auto-schedule-pro/schedule.json b/modules/auto-schedule-pro/schedule.json new file mode 100644 index 0000000..e7bb0cc --- /dev/null +++ b/modules/auto-schedule-pro/schedule.json @@ -0,0 +1,53 @@ +[ + { + "8:30": {"name": "Дискретна математика", "teacher": "Новотарський М. А.", "link": "https://us02web.zoom.us/j/87578307057?pwd=UGwyVGlwc3M4Q0Q0Q0NLWUt6bmVpUT09"}, + "10:25": {"name": "Комп'ютерна логіка", "teacher": "Жабін В. І.", "link": "https://bbb.comsys.kpi.ua/b/val-2vb-o7w-y5y АБО https://bbb.ugrid.org/b/val-osi-lup-ou8"}, + "12:20": {"name": "Культура мовлення та ділове мовлення", "teacher": "Онуфрієнко О. П.", "link": "В житті не буває нічого вічного. Життя мінливе, як і посилання на кожну нову пару. Щасти вам його віднайти!"} + }, + { + "12:20": {"name": "Практичний курс іноземної мови. Частина 1", "teacher": "Шевченко О. М.", "link": "https://meet.google.com/bwg-pdnr-evh"}, + "14:15": {"name": "Фізика", "teacher": "Федотов В. В. & Іванова І. М.", "link": "В житті не буває нічого вічного. Життя мінливе, як і посилання на кожну нову пару. Щасти вам його віднайти!"} + }, + { + "8:30": {"name": "Програмування. Частина 2. Об'єктно-орієнтоване програмування", "teacher": "Алещенко О. В.", "link": "https://us02web.zoom.us/j/2711546637?pwd=Ry82RHp3SjV6WTZRMXl6WUNod25hUT09"}, + "10:25": {"name": "Вища математика", "teacher": "Ординська З. П.", "link": "https://us04web.zoom.us/j/2684350438?pwd=kiOi3BrgbJHeYvkrx7qaSxa08J8m8O.1"} + }, + { + "10:25": {"name": "Вища математика", "teacher": "Ординська З. П.", "link": "https://us04web.zoom.us/j/2684350438?pwd=kiOi3BrgbJHeYvkrx7qaSxa08J8m8O.1"}, + "12:20": {"name": "Фізика", "teacher": "Русаков В. Ф.", "link": "В житті не буває нічого вічного. Життя мінливе, як і посилання на кожну нову пару. Щасти вам його віднайти!", "container_id": "1"}, + "14:15": {"name": "Програмування. Частина 2. Об'єктно-орієнтоване програмування", "teacher": "Алещенко О. В.", "link": "https://us02web.zoom.us/j/2711546637?pwd=Ry82RHp3SjV6WTZRMXl6WUNod25hUT09"} + }, + { + "10:25": {"name": "Фізика", "teacher": "Русаков В. Ф.", "link": "В житті не буває нічого вічного. Життя мінливе, як і посилання на кожну нову пару. Щасти вам його віднайти!", "container_id": "1"}, + "12:20": {"name": "Дискретна математика", "teacher": "Пономаренко А. М.", "link": "https://us05web.zoom.us/j/7089075754?pwd=TWRlZmxyVlFiTWU1UGlVVU1XcFE0Zz09"}, + "14:15": {"name": "Основи здорового способу життя", "teacher": "Соболенко А. І.", "link": "https://zoom.us/j/2035574145?pwd=bk1wTVhGbjJsQTR4WmVQMlROWFBCZz09"} + }, + {}, + {}, + { + "8:30": {"name": "Дискретна математика", "teacher": "Новотарський М. А.", "link": "https://us02web.zoom.us/j/87578307057?pwd=UGwyVGlwc3M4Q0Q0Q0NLWUt6bmVpUT09"}, + "10:25": {"name": "Комп'ютерна логіка", "teacher": "Жабін В. І.", "link": "https://bbb.comsys.kpi.ua/b/val-2vb-o7w-y5y АБО https://bbb.ugrid.org/b/val-osi-lup-ou8"}, + "12:20": {"name": "Вища математика", "teacher": "Ординська З. П.", "link": "https://us04web.zoom.us/j/2684350438?pwd=kiOi3BrgbJHeYvkrx7qaSxa08J8m8O.1"} + }, + { + "8:30": {"name": "Комп'ютерна логіка", "teacher": "Верба О. А.", "link": "https://us04web.zoom.us/j/7382214783?pwd=RnZ3SWgwK1JoVkZtNndnKzdPZjFGdz09"}, + "10:25": {"name": "Вища математика", "teacher": "Ординська З. П.", "link": "https://us04web.zoom.us/j/2684350438?pwd=kiOi3BrgbJHeYvkrx7qaSxa08J8m8O.1"}, + "12:20": {"name": "Практичний курс іноземної мови. Частина 1", "teacher": "Шевченко О. М.", "link": "https://meet.google.com/bwg-pdnr-evh"}, + "14:15": {"name": "Фізика", "teacher": "Федотов В. В. & Іванова І. М.", "link": "В житті не буває нічого вічного. Життя мінливе, як і посилання на кожну нову пару. Щасти вам його віднайти!"} + }, + { + "10:25": {"name": "Вища математика", "teacher": "Ординська З. П.", "link": "https://us04web.zoom.us/j/2684350438?pwd=kiOi3BrgbJHeYvkrx7qaSxa08J8m8O.1"} + }, + { + "10:25": {"name": "Вища математика", "teacher": "Ординська З. П.", "link": "https://us04web.zoom.us/j/2684350438?pwd=kiOi3BrgbJHeYvkrx7qaSxa08J8m8O.1"}, + "12:20": {"name": "Фізика", "teacher": "Русаков В. Ф.", "link": "В житті не буває нічого вічного. Життя мінливе, як і посилання на кожну нову пару. Щасти вам його віднайти!", "container_id": "1"}, + "14:15": {"name": "Програмування. Частина 2. Об'єктно-орієнтоване програмування", "teacher": "Алещенко О. В.", "link": "https://us02web.zoom.us/j/2711546637?pwd=Ry82RHp3SjV6WTZRMXl6WUNod25hUT09"} + }, + { + "10:25": {"name": "Фізика", "teacher": "Русаков В. Ф.", "link": "В житті не буває нічого вічного. Життя мінливе, як і посилання на кожну нову пару. Щасти вам його віднайти!", "container_id": "1"}, + "12:20": {"name": "Культура мовлення та ділове мовлення", "teacher": "Кушлаба М. П.", "link": "https://bbb.comsys.kpi.ua/b/myk-0iw-red-p01"}, + "14:15": {"name": "Основи здорового способу життя", "teacher": "Соболенко А. І.", "link": "https://zoom.us/j/2035574145?pwd=bk1wTVhGbjJsQTR4WmVQMlROWFBCZz09"} + }, + {}, + {} +] diff --git a/modules/auto-schedule-pro/www/index.py b/modules/auto-schedule-pro/www/index.py new file mode 100644 index 0000000..af0a50c --- /dev/null +++ b/modules/auto-schedule-pro/www/index.py @@ -0,0 +1,165 @@ +import datetime +import json +import os + +current_time = datetime.datetime.now() + +current_week = current_time.isocalendar()[1] % 2 +current_day = current_time.weekday() +current_seconds = current_week*604800 + current_day*86400 + current_time.hour*3600 + current_time.minute*60 + current_time.second +reference_time = int(current_time.strftime("%s")) - current_seconds + +# baking defined schedule +raw_schedule = json.loads( open("../schedule.json").read() ) +schedule = {} +for day in range(len(raw_schedule)): + for i in raw_schedule[day]: + ts = day*86400 + int(i.split(":")[0])*3600 + int(i.split(":")[1])*60 + new_item = dict(raw_schedule[day][i]) + new_item["source"] = "schedule" + schedule[ts] = new_item + +# baking additions (extra pairs) +raw_additions = json.loads( open("../additions.json").read() ) +additions = {} +for day in range(len(raw_additions)): + for i in raw_additions[day]: + ts = day*86400 + int(i.split(":")[0])*3600 + int(i.split(":")[1])*60 + new_item = dict(raw_additions[day][i]) + new_item["source"] = "additions" + schedule[ts] = new_item + +full_schedule = dict(list(schedule.items()) + list(additions.items())) + +#print("test1") +#print(f"Full schedule #printout: {full_schedule}") +#print(f"Current delta_time: {current_seconds}") +p = None +next_pair_time = None + +key_list = list(full_schedule.keys()) +key_list.sort() +for i in key_list: + if i > current_seconds - 5400: + p = full_schedule[i] + next_pair_time = i + break + +#print("test2") +if next_pair_time == None: + if len(full_schedule.keys()) > 0: + #print("test3.1") + + #actual_pair_ts = reference_time + min(full_schedule.keys()) + #dt_pair = datetime.datetime.fromtimestamp(actual_pair_ts) + #dt_pair_finish = datetime.datetime.fromtimestamp(actual_pair_ts + 5400) + p = full_schedule[min(full_schedule.keys())] + #print("test3.1.1") + + #print("{} == 6 && {} == 1, {}".format(current_day, dt_pair.strftime('%u'), str( ((current_day + 2) == int(dt_pair.strftime("%u"))) or ((str(current_day) == "6") and (dt_pair.strftime("%u") == "1")) ))) + ''' + human_readable_date = "" + if ((current_day + 2) == int(dt_pair.strftime("%u"))) or ((str(current_day) == "6") and (dt_pair.strftime("%u") == "1")): + human_readable_date += "завтра " + elif current_week != int(dt_pair.strftime("%W")) % 2: + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_NEXT[int(dt_pair.strftime("%u")) - 1]) + elif current_day != (int(dt_pair.strftime("%u")) - 1): + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_THIS[int(dt_pair.strftime("%u")) - 1]) + else: + human_readable_date += "сьогодні " + + #print("test3.1.2") + + human_readable_date += "з " + + #print("test3.1.3") + human_readable_date += dt_pair.strftime("%H:%M") + #print("test3.1.4") + + human_readable_date += " до " + human_readable_date += dt_pair_finish.strftime("%H:%M") + ''' + + #self.RESPONCE = "Актуальна пара: {}\nДата: {}\nВикладач: {}\nПосилання на пару: {}".format(p['name'], human_readable_date, p['teacher'], p['link']) + #print("test3.1.5") + if 'container_id' in p: + try: + cont = json.decode(open(f"../containers/{p['container_id']}", 'r').read()) + if (time.time() - cont['update_ts']) > 43200: + if ("QUERY_STRING" in os.environ) and ("force" in os.environ['QUERY_STRING'].lower()): + print(f"Location: {cont['link']}\n\n", end = '') + else: + import random + new_seed = os.environ['REMOTE_ADDR'] + datetime.datetime.now().replace(minute = 0, second = 0).strftime("%s") + random.seed(new_seed) + surprise_pool = ["Йой!", "От халепа!", "Ой лишенько!"] + print(f"Content-Type: text/html; charset=UTF-8\n\n
Посилання на пару {p['name']}, яке зберігається у сховищі, було отримане більш ніж 12 годин тому (рівно {time.time() - cont['update_ts']} секунд тому), тому, скоріш за все, не є дійсним.
На жаль, нового посилання ще не надходило, тому Ви можете або чекати на нього і оновлювати цю сторінку (перенаправлення станеться, щойно з'явиться нове посилання), або перейти вручну за старим посиланням (не рекомендується):
{cont['link']}PS: щоб обійти цю сторінку та завжди автоматично переходити за будь-яким наявним посиланням, можна додати у рядок URL в кінці напис: ?force
") + else: + print(f"Location: {cont['link']}\n\n", end = '') + + except Exception as e: + import random + new_seed = os.environ['REMOTE_ADDR'] + datetime.datetime.now().replace(minute = 0, second = 0).strftime("%s") + random.seed(new_seed) + surprise_pool = ["Йой!", "От халепа!", "Ой лишенько!"] + print(f"Content-Type: text/html; charset=UTF-8\n\nПід час спроби отримання посилання на пару {p['name']} сталася непередбачена помилка. Ви можете оновлювати сторінку, поки проблема не зникне (перенаправлення відбудеться, щойно все запрацює), або пошукати посилання де-інде.
Вибачте за тимчасові незручності(
") + + else: + print(f"Location: {p['link'].split()[0]}\n\n", end = '') + + else: + #self.RESPONCE = "Пар немає взагалі. Ми вільні!" + pass + +else: + #print("test3.2") + ''' + actual_pair_ts = reference_time + next_pair_time + dt_pair = datetime.datetime.fromtimestamp(actual_pair_ts) + dt_pair_finish = datetime.datetime.fromtimestamp(actual_pair_ts + 5400) + + human_readable_date = "" + if ((current_day + 2) == int(dt_pair.strftime("%u"))) or ((str(current_day) == "6") and (dt_pair.strftime("%u") == "1")): + human_readable_date += "завтра " + elif current_week != int(dt_pair.strftime("%W")) % 2: + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_NEXT[int(dt_pair.strftime("%u")) - 1]) + elif current_day != (int(dt_pair.strftime("%u")) - 1): + human_readable_date += "{} ".format(self.WEEKDAY_NAMES_ROD_WITH_THIS[int(dt_pair.strftime("%u")) - 1]) + else: + human_readable_date += "сьогодні " + + human_readable_date += "з " + human_readable_date += dt_pair.strftime("%H:%M") + + human_readable_date += " до " + human_readable_date += dt_pair_finish.strftime("%H:%M") + ''' + + #self.RESPONCE = "Актуальна пара: {}\nДата: {}\nВикладач: {}\nПосилання на пару: {}".format(p['name'], human_readable_date, p['teacher'], p['link']) + + if 'container_id' in p: + try: + cont = json.decode(open(f"../containers/{p['container_id']}", 'r').read()) + if (time.time() - cont['update_ts']) > 43200: + if ("QUERY_STRING" in os.environ) and ("force" in os.environ['QUERY_STRING'].lower()): + print(f"Location: {cont['link']}\n\n", end = '') + else: + import random + new_seed = os.environ['REMOTE_ADDR'] + datetime.datetime.now().replace(minute = 0, second = 0).strftime("%s") + random.seed(new_seed) + surprise_pool = ["Йой!", "От халепа!", "Ой лишенько!"] + print(f"Content-Type: text/html; charset=UTF-8\n\nПосилання на пару {p['name']}, яке зберігається у сховищі, було отримане більш ніж 12 годин тому (рівно {time.time() - cont['update_ts']} секунд тому), тому, скоріш за все, не є дійсним.
На жаль, нового посилання ще не надходило, тому Ви можете або чекати на нього і оновлювати цю сторінку (перенаправлення станеться, щойно з'явиться нове посилання), або перейти вручну за старим посиланням (не рекомендується):
{cont['link']}PS: щоб обійти цю сторінку та завжди автоматично переходити за будь-яким наявним посиланням, можна додати у рядок URL в кінці напис: ?force
") + else: + print(f"Location: {cont['link']}\n\n", end = '') + + except Exception as e: + import random + new_seed = os.environ['REMOTE_ADDR'] + datetime.datetime.now().replace(minute = 0, second = 0).strftime("%s") + random.seed(new_seed) + surprise_pool = ["Йой!", "От халепа!", "Ой лишенько!"] + print(f"Content-Type: text/html; charset=UTF-8\n\nПід час спроби отримання посилання на пару {p['name']} сталася непередбачена помилка. Ви можете оновлювати сторінку, поки проблема не зникне (перенаправлення відбудеться, щойно все запрацює), або пошукати посилання де-інде.
Вибачте за тимчасові незручності(
") + + else: + print(f"Location: {p['link'].split()[0]}\n\n", end = '') + + #print(f"Location: {p['link'].split()[0]}\n\n") diff --git a/modules/auto-schedule/index.py b/modules/auto-schedule/index.py index 677f98a..ebb1e6c 100644 --- a/modules/auto-schedule/index.py +++ b/modules/auto-schedule/index.py @@ -1,4 +1,4 @@ -if self.MESSAGE["text"].lower() == "!пара": +if self.MESSAGE["text"].lower() == "!пара-old": try: schedule = json.loads( readfile(self.path + "schedule.json") ) @@ -42,4 +42,4 @@ if self.MESSAGE["text"].lower() == "!пара": self.RESPONCE = "Сьогодні більше немає пар" except Exception as e: - print("[WARN] module: auto-schedule: failed to process schedule.json ({e})") + print(f"[WARN] module: auto-schedule: failed to process schedule.json ({e})") diff --git a/modules/auto-schedule/schedule.json b/modules/auto-schedule/schedule.json index 7f97be7..dd4b943 100644 --- a/modules/auto-schedule/schedule.json +++ b/modules/auto-schedule/schedule.json @@ -46,7 +46,7 @@ "lector": "Новотарський М. А." }, "3": { - "link": "https://bbb.comsys.kpi.ua/b/val-zdp-vw0-dbr", + "link": "https://bbb.ugrid.org/b/val-zdp-vw0-dbr", "subject": "Комп'ютерна логіка", "lector": "Жабін В. І." } @@ -122,7 +122,7 @@ "lector": "Новотарський М. А." }, "3": { - "link": "https://bbb.comsys.kpi.ua/b/val-zdp-vw0-dbr", + "link": "https://bbb.ugrid.org/b/val-zdp-vw0-dbr", "subject": "Комп'ютерна логіка", "lector": "Жабін В. І." } diff --git a/modules/irc-bridge/bot.py b/modules/irc-bridge/bot.py new file mode 100644 index 0000000..93392c8 --- /dev/null +++ b/modules/irc-bridge/bot.py @@ -0,0 +1,122 @@ +import time +import socket +import threading + +login_lines_raw = [ + "NICK bridge", + "USER bridge bridge * !", + "JOIN #io23-bridge" +] + +login_lines = map( lambda x: (x + "\n").encode("utf-8"), login_lines_raw ) + +recv_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +send_buffer = [] +reconnecting = False + +LINE_END = "\r\n".encode("utf-8") + +recv_s.bind( ("127.0.0.1", 5001) ) + +def reconnect(): + global s, reconnecting + reconnecting = True + while True: + try: + s.close() + except: + pass + + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect( ("10.1.1.1", 6667) ) + + for i in login_lines: + s.send(i) + time.sleep(0.5) + + reconnecting = False + break + except Exception as e: + print(f"[reconnect:main] ERROR: got exception {e}") + t = time.time() + open("error.log", "a", encoding = "utf-8").write(f"[{t}] recv_thread:main ERROR: got exception {e}\n") + + time.sleep(2) + +def recv_thread(): + global s, send_buffer, reconnecting + databuffer = bytes() + while True: + try: + new_data = s.recv(1024) + print(f"[DEBUG] new_data: {new_data}") + if len(new_data) == 0: + if not reconnecting: + reconnect() # bin the old socket and get a new one instead + continue + + databuffer += new_data + + if LINE_END in databuffer: + commands = map( lambda x: x.decode("UTF-8"), databuffer.split(LINE_END)[:-1]) + + for command in commands: + if len(command) > 0: + if command.split(" ")[0] == "PING": + print("[DEBUG] recv_thread:command:ping: Responding with {}".format(command.split(" ")[1]).encode("UTF-8")) + send_buffer.append(("PONG {}\n".format( command.split(" ")[1]).encode("UTF-8") )) + else: + pass + + databuffer = databuffer.split(LINE_END)[-1] + except Exception as e: + print(f"[recv_thread:main] ERROR: got exception {e}") + t = time.time() + open("error.log", "a", encoding = "utf-8").write(f"[{t}] recv_thread:main ERROR: got exception {e}\n") + try: + if not reconnecting: + reconnect() + except Exception as e: + print(f"[recv_thread:except:reconnect] ERROR: got exception {e}") + t = time.time() + open("error.log", "a", encoding = "utf-8").write(f"[{t}] recv_thread:except:reconnect ERROR: got exception {e}\n") + +def send_thread(): + global s, send_buffer, reconnecting + while True: + if len(send_buffer) > 0: + try: + print(f"[DEBUG] send_thread: sending {send_buffer[0]}") + s.send(send_buffer[0]) + del send_buffer[0] + except Exception as e: + print(f"[send_thread:main] ERROR: got exception {e}") + t = time.time() + open("error.log", "a", encoding = "utf-8").write(f"[{t}] send_thread:main ERROR: got exception {e}\n") + + if not reconnecting: + reconnect() + + time.sleep(0.2) + else: + time.sleep(3) + +def msg_thread(): + global recv_s, send_buffer + while True: + d = recv_s.recvfrom(16384) + print(f"[DEBUG] msg_thread:d: {d}") + send_buffer.append(d[0]) + +st = threading.Thread(target = send_thread, args = []) +rt = threading.Thread(target = recv_thread, args = []) +mt = threading.Thread(target = msg_thread, args = []) + +reconnect() + +st.start() +rt.start() +mt.start() diff --git a/modules/irc-bridge/index.py b/modules/irc-bridge/index.py new file mode 100644 index 0000000..e27e77f --- /dev/null +++ b/modules/irc-bridge/index.py @@ -0,0 +1,10 @@ +if self.MESSAGE["chat"]["id"] == -1001570221452: + l = min( len(self.MESSAGE["text"]), 300 ) + new_msg = "{} {}: {}".format(self.MESSAGE.from_user.first_name,\ + self.MESSAGE.from_user.last_name,\ + self.MESSAGE.text.replace("\n", " | ")[:l]) + + import socket + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.sendto(f"PRIVMSG #io23-bridge :{new_msg}\n".encode("utf-8"), ("127.0.0.1", 5001)) + del s diff --git a/modules/irc-bridge/meta.json b/modules/irc-bridge/meta.json new file mode 100644 index 0000000..0309cdc --- /dev/null +++ b/modules/irc-bridge/meta.json @@ -0,0 +1,7 @@ +{ + "start_on_boot": true, + "alias": "irc-bridge", + "version": 1, + "index_file": "index.py", + "predefine": "predefine.py" +} diff --git a/modules/irc-bridge/predefine.py b/modules/irc-bridge/predefine.py new file mode 100644 index 0000000..7d007f2 --- /dev/null +++ b/modules/irc-bridge/predefine.py @@ -0,0 +1,5 @@ +import socket + +SEND_ADDR = ( "127.0.0.1", 5001 ) + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) diff --git a/modules/transliteration-decoder/index.py b/modules/transliteration-decoder/index.py new file mode 100644 index 0000000..cd955c1 --- /dev/null +++ b/modules/transliteration-decoder/index.py @@ -0,0 +1,22 @@ +if self.MESSAGE['text'].split()[0] == "!decode" and (2 <= len(self.MESSAGE['text'].split(" ", 2)) <= 3): + try: + models = json.loads(readfile(self.path + "translate_models.json")) + chosen_model = self.MESSAGE['text'].split(" ", 2)[1] + + if len(self.MESSAGE['text'].split(" ", 2)) == 3: + t = self.MESSAGE['text'].split(" ", 2)[2] + elif len(self.MESSAGE['text'].split(" ", 2)) == 2: + t = self.MESSAGE['reply_to_message']['text'] + + translated_t = t + if chosen_model not in models: + self.RESPONCE = f"Такого варіанту транслітерації не існує. Доступні варіанти: {', '.join(list(models.keys()))}" + else: + for i in models[chosen_model]: + translated_t = translated_t.replace(i[0], i[1]) + translated_t = translated_t.replace(i[0].capitalize(), i[1].capitalize()) + translated_t = translated_t.replace(i[0].upper(), i[1].upper()) + + self.RESPONCE = f"Результат: {translated_t}" + except Exception as e: + print(f"[translit-decoder] Got exception: {e}") diff --git a/modules/transliteration-decoder/meta.json b/modules/transliteration-decoder/meta.json new file mode 100644 index 0000000..4bcbdeb --- /dev/null +++ b/modules/transliteration-decoder/meta.json @@ -0,0 +1,6 @@ +{ + "version": 1, + "index_file": "index.py", + "start_on_boot": true, + "alias": "translit-decoder" +} diff --git a/modules/transliteration-decoder/translate_models.json b/modules/transliteration-decoder/translate_models.json new file mode 100644 index 0000000..bb2ca30 --- /dev/null +++ b/modules/transliteration-decoder/translate_models.json @@ -0,0 +1,35 @@ +{ + "cz-ua": [ + ["šč", "щ"], + ["ja", "я"], + ["ju", "ю"], + ["ji", "ї"], + ["je", "є"], + ["f", "ф"], + ["b", "б"], + ["ž", "ж"], + ["q", "к"], + ["š", "ш"], + ["n", "н"], + ["p", "п"], + ["r", "р"], + ["s", "с"], + ["t", "т"], + ["h", "х"], + ["č", "ч"], + ["'", "ь"], + ["y", "и"], + ["z", "з"], + ["l", "л"], + ["k", "к"], + ["d", "д"], + ["u", "у"], + ["m", "м"], + ["v", "в"], + ["j", "й"], + ["s", "с"], + ["a", "а"], + ["i", "і"], + ["g", "г"] + ] +}