You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmftools/bookscraper/db/state_sql.py

166 lines
4.2 KiB

# ============================================================
# File: db/state_sql.py
# Purpose:
# Low-level SQLite snapshot layer for BookScraper metadata.
# Used ONLY through db.repository façade.
# ============================================================
import sqlite3
import os
from logbus.publisher import log
DB_PATH = os.getenv("BOOKSCRAPER_DB", "/app/db/books.db")
# ------------------------------------------------------------
# INTERNAL HELPERS
# ------------------------------------------------------------
def _connect():
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
return conn
# ------------------------------------------------------------
# FETCH
# ------------------------------------------------------------
def sql_fetch_book(book_id):
conn = _connect()
cur = conn.cursor()
cur.execute("SELECT * FROM books WHERE book_id = ?", (book_id,))
row = cur.fetchone()
conn.close()
return dict(row) if row else None
def sql_fetch_all_books():
conn = _connect()
cur = conn.cursor()
cur.execute("SELECT * FROM books ORDER BY rowid DESC")
rows = cur.fetchall()
conn.close()
return [dict(r) for r in rows]
# ------------------------------------------------------------
# REGISTER / UPDATE
# ------------------------------------------------------------
def sql_register_book(book_id, fields: dict):
conn = _connect()
cur = conn.cursor()
cols = ", ".join(["book_id"] + list(fields.keys()))
placeholders = ", ".join(["?"] * (1 + len(fields)))
values = [book_id] + list(fields.values())
cur.execute(
f"INSERT OR REPLACE INTO books ({cols}) VALUES ({placeholders})", values
)
conn.commit()
conn.close()
def sql_update_book(book_id, fields: dict):
if not fields:
return
conn = _connect()
cur = conn.cursor()
set_clause = ", ".join([f"{k} = ?" for k in fields])
params = list(fields.values()) + [book_id]
cur.execute(f"UPDATE books SET {set_clause} WHERE book_id = ?", params)
conn.commit()
conn.close()
# ------------------------------------------------------------
# STATUS
# ------------------------------------------------------------
def sql_set_status(book_id, status: str):
conn = _connect()
cur = conn.cursor()
cur.execute("UPDATE books SET status = ? WHERE book_id = ?", (status, book_id))
conn.commit()
conn.close()
# ------------------------------------------------------------
# CHAPTER TOTAL (snapshot)
# ------------------------------------------------------------
def sql_set_chapters_total(book_id, total: int):
conn = _connect()
cur = conn.cursor()
cur.execute(
"UPDATE books SET chapters_total = ? WHERE book_id = ?", (total, book_id)
)
conn.commit()
conn.close()
# ------------------------------------------------------------
# COUNTERS (SNAPSHOT-ONLY)
# ------------------------------------------------------------
def sql_inc_downloaded(book_id, amount=1):
conn = _connect()
cur = conn.cursor()
cur.execute(
"""
UPDATE books
SET downloaded = COALESCE(downloaded,0) + ?
WHERE book_id = ?
""",
(amount, book_id),
)
conn.commit()
conn.close()
def sql_inc_parsed(book_id, amount=1):
conn = _connect()
cur = conn.cursor()
cur.execute(
"""
UPDATE books
SET parsed = COALESCE(parsed,0) + ?
WHERE book_id = ?
""",
(amount, book_id),
)
conn.commit()
conn.close()
def sql_inc_audio_done(book_id, amount=1):
log(f"[DB-SQL] Incrementing audio done for {book_id} by {amount}")
conn = _connect()
cur = conn.cursor()
cur.execute(
"""
UPDATE books
SET audio_done = COALESCE(audio_done,0) + ?
WHERE book_id = ?
""",
(amount, book_id),
)
conn.commit()
conn.close()
def sql_inc_audio_skipped(book_id, amount=1):
log(f"[DB-SQL] Incrementing audio skipped for {book_id} by {amount}")
conn = _connect()
cur = conn.cursor()
cur.execute(
"""
UPDATE books
SET audio_skipped = COALESCE(audio_skipped,0) + ?
WHERE book_id = ?
""",
(amount, book_id),
)
conn.commit()
conn.close()