import requests from typing import Dict, Any from .db import get_draw, upsert_draw, upsert_many_draws, get_latest_draw, count_draws def _normalize_item(item: dict) -> dict: # smok95 all.json / latest.json 구조 # - draw_no: int # - numbers: [n1..n6] # - bonus_no: int # - date: "YYYY-MM-DD ..." numbers = item["numbers"] return { "drw_no": int(item["draw_no"]), "drw_date": (item.get("date") or "")[:10], "n1": int(numbers[0]), "n2": int(numbers[1]), "n3": int(numbers[2]), "n4": int(numbers[3]), "n5": int(numbers[4]), "n6": int(numbers[5]), "bonus": int(item["bonus_no"]), } def sync_all_from_json(all_url: str) -> Dict[str, Any]: r = requests.get(all_url, timeout=60) r.raise_for_status() data = r.json() # list[dict] # 정규화 rows = [_normalize_item(item) for item in data] # Bulk Insert (성능 향상) upsert_many_draws(rows) return {"mode": "all_json", "url": all_url, "total": len(rows)} def sync_latest(latest_url: str) -> Dict[str, Any]: r = requests.get(latest_url, timeout=30) r.raise_for_status() item = r.json() row = _normalize_item(item) before = get_draw(row["drw_no"]) upsert_draw(row) return {"mode": "latest_json", "url": latest_url, "was_new": (before is None), "drawNo": row["drw_no"]} def sync_ensure_all(latest_url: str, all_url: str) -> Dict[str, Any]: """ 1회부터 최신 회차까지 빠짐없이 있는지 확인하고, 없으면 전체 동기화 수행. 반환값: {"synced": bool, "reason": str, ...} """ # 1. 원격 최신 회차 확인 try: r = requests.get(latest_url, timeout=10) r.raise_for_status() remote_item = r.json() remote_no = int(remote_item["draw_no"]) except Exception as e: # 외부 통신 실패 시, 그냥 로컬 데이터로 진행하도록 에러 억제 (혹은 에러 발생) # 여기서는 통계 기능 작동이 우선이므로 로그만 남기고 pass하고 싶지만, # 확실한 동기화를 위해 에러를 던지거나 False 리턴 return {"synced": False, "error": str(e)} # 2. 로컬 상태 확인 local_latest_row = get_latest_draw() local_no = local_latest_row["drw_no"] if local_latest_row else 0 local_cnt = count_draws() # 3. 동기화 필요 여부 판단 # - 전체 개수가 최신 회차 번호보다 적으면 중간에 빈 것 (1회부터 시작한다고 가정) # - 혹은 DB 최신 번호가 원격보다 낮으면 업데이트 필요 need_sync = (local_no < remote_no) or (local_cnt < local_no) if not need_sync: return {"synced": True, "updated": False, "local_no": local_no} # 4. 전체 동기화 실행 # (단순 latest sync로는 중간 구멍을 못 채우므로, 구멍이 있거나 차이가 크면 all_sync 수행) # 만약 차이가 1회차 뿐이고 구멍이 없다면 sync_latest만 해도 되지만, # 로직 단순화를 위해 missing 감지 시 그냥 all_sync (Bulk Insert라 빠름) res = sync_all_from_json(all_url) return {"synced": True, "updated": True, "detail": res}