import json import os import hashlib import requests from datetime import datetime # Конфигурация URL_PARSER_ROOT = "https://fazziclay.com/api/v1/vstu_schedule_parser_v2/parser.json" BASE_URL_FILES = "https://fazziclay.com/api/v1/vstu_schedule_parser_v2/parsed/" FILE_RESULT = "result.json" FILE_CACHE = "raw_cache.json" FILE_TO_AI = "to_ai.txt" FILE_FROM_AI = "from_ai.txt" def get_raw_hash(raw_list): normalized = "|".join(sorted([str(i).strip() for i in raw_list])) return hashlib.sha1(normalized.encode('utf-8')).hexdigest() def load_json(filename, default): if os.path.exists(filename): with open(filename, 'r', encoding='utf-8') as f: try: return json.load(f) except: return default return default def save_json(filename, data): with open(filename, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) def process_ai_input(cache): if not os.path.exists(FILE_FROM_AI): return cache with open(FILE_FROM_AI, 'r', encoding='utf-8') as f: content = f.read().strip() if not content: return cache try: new_data = json.loads(content) for r_hash, resolved_obj in new_data.items(): cache[r_hash] = resolved_obj print(f"[*] Добавлено {len(new_data)} записей из ИИ в кэш.") with open(FILE_FROM_AI, 'w', encoding='utf-8') as f: f.write("") except Exception as e: print(f"[!] Ошибка парсинга from_ai.txt: {e}") return cache def main(): print(f"--- Система Совместимости V1-V2 [{datetime.now().strftime('%H:%M:%S')}] ---") cache = load_json(FILE_CACHE, {}) cache = process_ai_input(cache) save_json(FILE_CACHE, cache) try: parser_data = requests.get(URL_PARSER_ROOT).json() except Exception as e: print(f"[!] Ошибка сети: {e}"); return final_groups = {} unknown_raws = {} for file_info in parser_data.get("all_files", []): file_url = f"{BASE_URL_FILES}{requests.utils.quote(file_info['json_represent'])}" print(f"[*] Рендеринг: {file_info['json_represent']}") try: faculty_data = requests.get(file_url).json() except: continue sheets = faculty_data.get("sheets", {}) for sheet_data in sheets.values(): groups = sheet_data.get("groups", {}) for group_id, group_data in groups.items(): # Инициализация группы в формате V1 if group_id not in final_groups: final_groups[group_data["name"]] = { "name": group_data["name"], "facultet": faculty_data['excel']['facultet'], "position": group_data.get("position"), "position_human": group_data.get("position_human"), "slots": {}, "data_source_hash": "TODO" } slots = group_data.get("slots", {}) for slot_key, pair_value in slots.items(): if not isinstance(pair_value, dict): continue if slot_key not in final_groups[group_data["name"]]["slots"]: final_groups[group_data["name"]]["slots"][slot_key] = {} for pair_key, pair_data in pair_value.items(): # Фильтр мета-ключей (пропускаем excel_range и т.д.) if not (isinstance(pair_key, str) and '-' in pair_key): continue # НОВЫЙ БЛОК: Обработка списка событий (если пара раздвоена) # Превращаем всё в список, даже если там один объект events = pair_data if isinstance(pair_data, list) else [pair_data] for i, event in enumerate(events): # Если событий больше одного, добавляем суффикс к ключу (напр. "5-6_1") current_pair_id = pair_key if i == 0 else f"{pair_key}_{i}" # Теперь event — это гарантированно словарь if not isinstance(event, dict): continue raw_list = event.get("raw", []) r_hash = get_raw_hash(raw_list) if r_hash in cache: res = cache[r_hash] # Парсим списки locs = [l.strip() for l in res.get("location", "").split(",")] if res.get("location") and res.get("location") != "Не указана" else [] leads = [l.strip() for l in res.get("teacher", "").split(",")] if res.get("teacher") and res.get("teacher") != "Не указан" else [] # Записываем в финальную структуру final_groups[group_data["name"]]["slots"][slot_key][current_pair_id] = { "discipline_name": res.get("subject", "Не указан"), "locations": locs, "leads": leads, "is_solid": event.get("is_solid", True), "is_flow": event.get("is_flow", False), "raw": raw_list, "weekday": event.get("weekday"), "weeknum": event.get("weeknum"), "excel_range": event.get("excel_range"), "excel_pos": event.get("excel_pos") } else: unknown_raws[r_hash] = raw_list # Управление to_ai.txt if unknown_raws: save_json(FILE_TO_AI, unknown_raws) print(f"[!] Найдено {len(unknown_raws)} новых записей. См. {FILE_TO_AI}") else: with open(FILE_TO_AI, 'w', encoding='utf-8') as f: f.write("") # Сохранение итогового результата output = { "actual_at": int(datetime.now().timestamp()), "groups": final_groups } save_json(FILE_RESULT, output) print(f"[*] Успешно: {FILE_RESULT} обновлен.") if __name__ == "__main__": main()