165 lines
5.6 KiB
Python
Executable File
165 lines
5.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
scripts/import_user_edits.py
|
|
|
|
Imports custom edits made on a mobile device (exported from Oracle 999 app)
|
|
into the desktop repository:
|
|
- Updates the respective dossiers in oracle_enricher/out/dossiers/
|
|
- Updates oracle_enricher/out/oracle_kb.json
|
|
- Automatically regenerates assets/data/oracle_kb.json via sync_kb_asset.py
|
|
- Preserves git traceability with timestamps and user_edited flags
|
|
|
|
Usage:
|
|
# From a file:
|
|
python3 scripts/import_user_edits.py edits.json
|
|
|
|
# Interactive paste:
|
|
python3 scripts/import_user_edits.py
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
from datetime import datetime, timezone
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
ENRICHER = ROOT / 'oracle_enricher'
|
|
DOSSIERS_DIR = ENRICHER / 'out' / 'dossiers'
|
|
KB_FILE = ENRICHER / 'out' / 'oracle_kb.json'
|
|
SYNC_SCRIPT = ROOT / 'scripts' / 'sync_kb_asset.py'
|
|
|
|
def load_input_json():
|
|
if len(sys.argv) > 1 and sys.argv[1] not in ('-', '--stdin'):
|
|
p = Path(sys.argv[1])
|
|
if not p.exists():
|
|
print(f"Error: File not found: {p}")
|
|
sys.exit(1)
|
|
return json.loads(p.read_text(encoding='utf-8'))
|
|
|
|
if not sys.stdin.isatty():
|
|
return json.loads(sys.stdin.read())
|
|
|
|
print("=== Импорт пользовательских правок из Оракула 999 ===")
|
|
print("Вставьте JSON с телефона (скопированный через кнопку 'Скопировать JSON правок')")
|
|
print("После вставки введите строку с 'EOF' или нажмите Ctrl+D:")
|
|
lines = []
|
|
try:
|
|
while True:
|
|
line = input()
|
|
if line.strip() == 'EOF':
|
|
break
|
|
lines.append(line)
|
|
except EOFError:
|
|
pass
|
|
|
|
raw = '\n'.join(lines).strip()
|
|
if not raw:
|
|
print("Отмена: входные данные пусты.")
|
|
sys.exit(0)
|
|
return json.loads(raw)
|
|
|
|
def main():
|
|
data = load_input_json()
|
|
if not isinstance(data, dict):
|
|
print("Ошибка: ожидался словарь вида { 'слово': { ... } }")
|
|
sys.exit(1)
|
|
|
|
print(f"Найдено правок для импорта: {len(data)} слов")
|
|
|
|
# Index existing dossiers
|
|
word_to_dossier = {}
|
|
if DOSSIERS_DIR.exists():
|
|
for p in DOSSIERS_DIR.glob('*.json'):
|
|
try:
|
|
d = json.loads(p.read_text(encoding='utf-8'))
|
|
w = d.get('word')
|
|
if w:
|
|
word_to_dossier[w.lower().strip()] = p
|
|
except Exception:
|
|
pass
|
|
|
|
kb = json.loads(KB_FILE.read_text(encoding='utf-8')) if KB_FILE.exists() else {}
|
|
|
|
now_iso = datetime.now(timezone.utc).isoformat()
|
|
updated_words = []
|
|
|
|
for raw_word, edits in data.items():
|
|
w = raw_word.lower().strip()
|
|
if not isinstance(edits, dict):
|
|
continue
|
|
|
|
core = edits.get('core', '').strip()
|
|
oracle = edits.get('oracle', '').strip()
|
|
shadow = edits.get('shadow', '').strip()
|
|
asks = edits.get('asks', '').strip()
|
|
step = edits.get('step', '').strip()
|
|
|
|
# 1. Update dossier if exists
|
|
p = word_to_dossier.get(w)
|
|
if p and p.exists():
|
|
try:
|
|
dossier = json.loads(p.read_text(encoding='utf-8'))
|
|
except Exception:
|
|
dossier = {'word': w}
|
|
else:
|
|
p = DOSSIERS_DIR / f"{w}.json"
|
|
dossier = {'word': w}
|
|
|
|
if 'canon' not in dossier or not isinstance(dossier['canon'], dict):
|
|
dossier['canon'] = {'word': w}
|
|
|
|
canon = dossier['canon']
|
|
if core:
|
|
canon['core'] = core
|
|
if oracle:
|
|
canon['oracle'] = oracle
|
|
if shadow:
|
|
canon['shadow'] = shadow
|
|
if asks:
|
|
canon['asks'] = asks
|
|
if step:
|
|
canon['step'] = step
|
|
|
|
canon['user_edited'] = True
|
|
canon['via'] = 'user_edit'
|
|
canon['updated_at'] = edits.get('updatedAt') or now_iso
|
|
|
|
p.parent.mkdir(parents=True, exist_ok=True)
|
|
p.write_text(json.dumps(dossier, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
|
|
# 2. Update oracle_kb.json
|
|
if w not in kb or not isinstance(kb[w], dict):
|
|
kb[w] = canon
|
|
else:
|
|
kb[w].update({
|
|
'core': canon.get('core', ''),
|
|
'oracle': canon.get('oracle', ''),
|
|
'shadow': canon.get('shadow', ''),
|
|
'asks': canon.get('asks', ''),
|
|
'step': canon.get('step', ''),
|
|
'user_edited': True,
|
|
'via': 'user_edit',
|
|
'updated_at': canon.get('updated_at'),
|
|
})
|
|
|
|
updated_words.append(w)
|
|
|
|
KB_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
KB_FILE.write_text(json.dumps(kb, ensure_ascii=False, indent=2), encoding='utf-8')
|
|
|
|
print(f"Обновлено досье и KB для {len(updated_words)} слов: {', '.join(updated_words[:10])}{'...' if len(updated_words) > 10 else ''}")
|
|
|
|
# 3. Synchronize assets/data/oracle_kb.json
|
|
print("Синхронизация assets/data/oracle_kb.json...")
|
|
subprocess.run([sys.executable, str(SYNC_SCRIPT)], check=True)
|
|
|
|
print("\n✅ УСПЕШНО! Все правки зафиксированы в кодовой базе.")
|
|
print("Теперь они станут частью базового канона во всех будущих релизах приложения.")
|
|
print("Чтобы закоммитить в git:")
|
|
print(" git add oracle_enricher/ assets/data/oracle_kb.json")
|
|
print(" git commit -m 'feat: import user canon edits from mobile app'")
|
|
|
|
if __name__ == '__main__':
|
|
main()
|