from fastapi import FastAPI, UploadFile, File import zipfile import sqlite3 import os import shutil app = FastAPI() @app.post("/parse") async def parse_anki(file: UploadFile = File(...)): temp_filename = "deck.apkg" with open(temp_filename, "wb") as buffer: shutil.copyfileobj(file.file, buffer) try: with zipfile.ZipFile(temp_filename, 'r') as z: # Anki21 — это более современный формат БД db_files = [f for f in z.namelist() if 'anki2' in f] if not db_files: return {"success": False, "error": "No database found in apkg"} # Берем последний (обычно collection.anki21) db_name = sorted(db_files)[-1] z.extract(db_name, path="./") conn = sqlite3.connect(db_name) # Включаем Row factory, чтобы получать данные в виде словарей conn.row_factory = sqlite3.Row cursor = conn.cursor() # 1. Извлекаем карточки со всеми параметрами обучения cursor.execute(""" SELECT id, nid, did as deck_id, type, queue, due, ivl as interval, factor as ease, reps, lapses FROM cards """) cards = [dict(row) for row in cursor.fetchall()] # 2. Извлекаем историю повторений (revlog) cursor.execute(""" SELECT id as time_ms, cid as card_id, ease, ivl as interval, lastIvl as last_interval, factor, time as duration_ms, type FROM revlog """) revlog = [dict(row) for row in cursor.fetchall()] # 3. Извлекаем заметки (текст), чтобы связать с картами через nid cursor.execute("SELECT id, flds FROM notes") notes = {row['id']: row['flds'].split('\x1f') for row in cursor.fetchall()} conn.close() # Чистим за собой временные файлы if os.path.exists(db_name): os.remove(db_name) return { "success": True, "cards_count": len(cards), "cards": cards, "revlog": revlog, "notes": notes } except Exception as e: return {"success": False, "error": str(e)}