"""数据库连接与初始化(建表、文章旧库迁移、提示词种子)。""" from __future__ import annotations import sqlite3 from typing import TYPE_CHECKING from content_manager.config import get_db_path from content_manager.db.schema import ( ARTICLES_TABLE_SQL, IMAGES_TABLE_SQL, PROMPT_TEMPLATE_USAGE_TABLE_SQL, PROMPT_TEMPLATES_TABLE_SQL, VIDEOS_TABLE_SQL, ) from content_manager.util.timeutil import now_unix, parse_ts_to_unix if TYPE_CHECKING: pass def get_conn() -> sqlite3.Connection: return sqlite3.connect(get_db_path()) def _is_legacy_articles_table(cur: sqlite3.Cursor) -> bool: cur.execute("PRAGMA table_info(articles)") rows = cur.fetchall() if not rows: return False for _cid, name, ctype, _nn, _d, _pk in rows: if name == "id" and ctype and ctype.upper() == "INTEGER": return False cur.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name='articles'") row = cur.fetchone() if row and row[0] and "TEXT" in row[0] and "id" in row[0]: return True return False def _migrate_legacy_articles(conn: sqlite3.Connection) -> None: cur = conn.cursor() cur.executescript( """ CREATE TABLE _articles_migrated ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, body TEXT NOT NULL, content_html TEXT, status TEXT NOT NULL DEFAULT 'draft', source TEXT NOT NULL DEFAULT 'manual', account_id TEXT, error_msg TEXT, llm_target TEXT, extra_json TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL ); """ ) cur.execute( "SELECT id, title, content, content_html, status, account_id, error_msg, created_at, updated_at FROM articles" ) ts = now_unix() for row in cur.fetchall(): _oid, title, content, content_html, status, account_id, error_msg, cat, uat = row body = content or "" ch = content_html if content_html else None cts = parse_ts_to_unix(cat) or ts uts = parse_ts_to_unix(uat) or ts cur.execute( """ INSERT INTO _articles_migrated ( title, body, content_html, status, source, account_id, error_msg, created_at, updated_at ) VALUES (?, ?, ?, ?, 'import', ?, ?, ?, ?) """, ( title or "", body, ch, (status or "draft"), account_id, error_msg, cts, uts, ), ) cur.execute("DROP TABLE articles") cur.execute("ALTER TABLE _articles_migrated RENAME TO articles") conn.commit() def init_db() -> None: conn = get_conn() try: cur = conn.cursor() cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='articles'") if cur.fetchone(): if _is_legacy_articles_table(cur): _migrate_legacy_articles(conn) else: cur.executescript(ARTICLES_TABLE_SQL) cur.executescript(IMAGES_TABLE_SQL) cur.executescript(VIDEOS_TABLE_SQL) cur.executescript(PROMPT_TEMPLATES_TABLE_SQL) cur.executescript(PROMPT_TEMPLATE_USAGE_TABLE_SQL) from content_manager.db.prompts_repository import seed_prompt_templates_if_empty seed_prompt_templates_if_empty(conn.cursor()) conn.commit() finally: conn.close()