rafael1994s commited on
Commit
f320da1
·
verified ·
1 Parent(s): 1691c2f

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +50 -12
main.py CHANGED
@@ -8,25 +8,63 @@ app = FastAPI()
8
 
9
  @app.post("/parse")
10
  async def parse_anki(file: UploadFile = File(...)):
11
- # 1. Сохраняем загруженный .apkg
12
- with open("deck.apkg", "wb") as buffer:
 
13
  shutil.copyfileobj(file.file, buffer)
14
 
15
- # 2. Распаковываем БД
16
  try:
17
- with zipfile.ZipFile("deck.apkg", 'r') as z:
18
- # Ищем файл коллекции (бывает .anki2 или .anki21)
19
- db_name = [f for f in z.namelist() if 'anki2' in f][0]
20
- z.extract(db_name, path="./")
 
21
 
22
- # 3. Читаем SQLite
 
 
 
23
  conn = sqlite3.connect(db_name)
 
 
24
  cursor = conn.cursor()
25
- cursor.execute("SELECT flds FROM notes")
26
- # Поля в Anki разделены символом \x1f
27
- notes = [row[0].split('\x1f') for row in cursor.fetchall()]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  conn.close()
29
 
30
- return {"success": True, "notes": notes}
 
 
 
 
 
 
 
 
 
 
 
31
  except Exception as e:
32
  return {"success": False, "error": str(e)}
 
8
 
9
  @app.post("/parse")
10
  async def parse_anki(file: UploadFile = File(...)):
11
+ temp_filename = "deck.apkg"
12
+
13
+ with open(temp_filename, "wb") as buffer:
14
  shutil.copyfileobj(file.file, buffer)
15
 
 
16
  try:
17
+ with zipfile.ZipFile(temp_filename, 'r') as z:
18
+ # Anki21 это более современный формат БД
19
+ db_files = [f for f in z.namelist() if 'anki2' in f]
20
+ if not db_files:
21
+ return {"success": False, "error": "No database found in apkg"}
22
 
23
+ # Берем последний (обычно collection.anki21)
24
+ db_name = sorted(db_files)[-1]
25
+ z.extract(db_name, path="./")
26
+
27
  conn = sqlite3.connect(db_name)
28
+ # Включаем Row factory, чтобы получать данные в виде словарей
29
+ conn.row_factory = sqlite3.Row
30
  cursor = conn.cursor()
31
+
32
+ # 1. Извлекаем карточки со всеми параметрами обучения
33
+ cursor.execute("""
34
+ SELECT
35
+ id, nid, did as deck_id, type, queue,
36
+ due, ivl as interval, factor as ease, reps, lapses
37
+ FROM cards
38
+ """)
39
+ cards = [dict(row) for row in cursor.fetchall()]
40
+
41
+ # 2. Извлекаем историю повторений (revlog)
42
+ cursor.execute("""
43
+ SELECT
44
+ id as time_ms, cid as card_id, ease,
45
+ ivl as interval, lastIvl as last_interval,
46
+ factor, time as duration_ms, type
47
+ FROM revlog
48
+ """)
49
+ revlog = [dict(row) for row in cursor.fetchall()]
50
+
51
+ # 3. Извлекаем заметки (текст), чтобы связать с картами через nid
52
+ cursor.execute("SELECT id, flds FROM notes")
53
+ notes = {row['id']: row['flds'].split('\x1f') for row in cursor.fetchall()}
54
+
55
  conn.close()
56
 
57
+ # Чистим за собой временные файлы
58
+ if os.path.exists(db_name):
59
+ os.remove(db_name)
60
+
61
+ return {
62
+ "success": True,
63
+ "cards_count": len(cards),
64
+ "cards": cards,
65
+ "revlog": revlog,
66
+ "notes": notes
67
+ }
68
+
69
  except Exception as e:
70
  return {"success": False, "error": str(e)}