112 lines
4.0 KiB
Python
112 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import sqlite3
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
|
|
class HeavenRepositoryMixin:
|
|
@staticmethod
|
|
def _heaven_reading_dict(row: sqlite3.Row | None) -> dict[str, Any] | None:
|
|
if not row:
|
|
return None
|
|
return {
|
|
"id": int(row["id"]),
|
|
"mode": str(row["mode"]),
|
|
"context_date": str(row["context_date"]),
|
|
"subject": str(row["subject"]),
|
|
"subject_detail": str(row["subject_detail"]),
|
|
"answer": str(row["answer"]),
|
|
"created_at": str(row["created_at"]),
|
|
}
|
|
|
|
def save_heaven_reading(
|
|
self,
|
|
user_id: int,
|
|
mode: str,
|
|
context_date: str,
|
|
subject: str,
|
|
subject_detail: str,
|
|
answer: str,
|
|
context_snapshot: dict[str, Any],
|
|
dedupe_key: str,
|
|
) -> dict[str, Any]:
|
|
now = datetime.now().astimezone().isoformat(timespec="seconds")
|
|
snapshot_json = json.dumps(
|
|
context_snapshot, ensure_ascii=False, separators=(",", ":")
|
|
)
|
|
with self.connect() as connection:
|
|
connection.execute(
|
|
"""
|
|
INSERT INTO heaven_readings
|
|
(user_id, mode, context_date, subject, subject_detail, answer,
|
|
context_snapshot, dedupe_key, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(user_id, dedupe_key) DO NOTHING
|
|
""",
|
|
(
|
|
int(user_id), mode, context_date, subject, subject_detail,
|
|
answer, snapshot_json, dedupe_key, now,
|
|
),
|
|
)
|
|
row = connection.execute(
|
|
"""
|
|
SELECT id, mode, context_date, subject, subject_detail, answer, created_at
|
|
FROM heaven_readings WHERE user_id = ? AND dedupe_key = ?
|
|
""",
|
|
(int(user_id), dedupe_key),
|
|
).fetchone()
|
|
connection.execute(
|
|
"""
|
|
DELETE FROM heaven_readings
|
|
WHERE user_id = ? AND mode = ? AND id NOT IN (
|
|
SELECT id FROM heaven_readings
|
|
WHERE user_id = ? AND mode = ? ORDER BY id DESC LIMIT 100
|
|
)
|
|
""",
|
|
(int(user_id), mode, int(user_id), mode),
|
|
)
|
|
result = self._heaven_reading_dict(row)
|
|
if not result:
|
|
raise ValueError("解读记录保存失败。")
|
|
return result
|
|
|
|
def list_heaven_readings(
|
|
self,
|
|
user_id: int,
|
|
mode: str,
|
|
context_date: str = "",
|
|
limit: int = 100,
|
|
) -> list[dict[str, Any]]:
|
|
clauses = ["user_id = ?", "mode = ?"]
|
|
parameters: list[Any] = [int(user_id), mode]
|
|
if context_date:
|
|
clauses.append("context_date = ?")
|
|
parameters.append(context_date)
|
|
parameters.append(max(1, min(100, int(limit))))
|
|
with self.connect() as connection:
|
|
rows = connection.execute(
|
|
f"""
|
|
SELECT id, mode, context_date, subject, subject_detail, answer, created_at
|
|
FROM heaven_readings WHERE {' AND '.join(clauses)}
|
|
ORDER BY context_date DESC, id DESC LIMIT ?
|
|
""",
|
|
parameters,
|
|
).fetchall()
|
|
return [self._heaven_reading_dict(row) for row in rows if row]
|
|
|
|
def latest_heaven_reading(
|
|
self, user_id: int, mode: str, context_date: str = ""
|
|
) -> dict[str, Any] | None:
|
|
items = self.list_heaven_readings(user_id, mode, context_date, 1)
|
|
return items[0] if items else None
|
|
|
|
def delete_heaven_reading(self, user_id: int, reading_id: int) -> bool:
|
|
with self.connect() as connection:
|
|
cursor = connection.execute(
|
|
"DELETE FROM heaven_readings WHERE id = ? AND user_id = ?",
|
|
(int(reading_id), int(user_id)),
|
|
)
|
|
return cursor.rowcount > 0
|