Fixed bookmarking with audio books.

This commit is contained in:
Storm Dragon
2025-10-16 16:30:58 -04:00
parent 542764be2a
commit 0bdc5bdf17
9 changed files with 648 additions and 178 deletions
+97 -111
View File
@@ -34,45 +34,44 @@ class BookmarkManager:
def _init_db(self):
"""Initialize database schema"""
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS bookmarks (
book_id TEXT PRIMARY KEY,
book_path TEXT NOT NULL,
book_title TEXT,
chapter_index INTEGER NOT NULL DEFAULT 0,
paragraph_index INTEGER NOT NULL DEFAULT 0,
sentence_index INTEGER NOT NULL DEFAULT 0,
last_accessed TEXT,
created_at TEXT
)
''')
cursor.execute('''
CREATE TABLE IF NOT EXISTS bookmarks (
book_id TEXT PRIMARY KEY,
book_path TEXT NOT NULL,
book_title TEXT,
chapter_index INTEGER NOT NULL DEFAULT 0,
paragraph_index INTEGER NOT NULL DEFAULT 0,
sentence_index INTEGER NOT NULL DEFAULT 0,
last_accessed TEXT,
created_at TEXT
)
''')
# Add audio_position column if it doesn't exist (migration for existing databases)
try:
cursor.execute('ALTER TABLE bookmarks ADD COLUMN audio_position REAL DEFAULT 0.0')
except sqlite3.OperationalError:
# Column already exists
pass
# Add audio_position column if it doesn't exist (migration for existing databases)
try:
cursor.execute('ALTER TABLE bookmarks ADD COLUMN audio_position REAL DEFAULT 0.0')
except sqlite3.OperationalError:
# Column already exists
pass
# Create named_bookmarks table for multiple bookmarks per book
cursor.execute('''
CREATE TABLE IF NOT EXISTS named_bookmarks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_id TEXT NOT NULL,
name TEXT NOT NULL,
chapter_index INTEGER NOT NULL DEFAULT 0,
paragraph_index INTEGER NOT NULL DEFAULT 0,
audio_position REAL DEFAULT 0.0,
created_at TEXT NOT NULL,
UNIQUE(book_id, name)
)
''')
# Create named_bookmarks table for multiple bookmarks per book
cursor.execute('''
CREATE TABLE IF NOT EXISTS named_bookmarks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
book_id TEXT NOT NULL,
name TEXT NOT NULL,
chapter_index INTEGER NOT NULL DEFAULT 0,
paragraph_index INTEGER NOT NULL DEFAULT 0,
audio_position REAL DEFAULT 0.0,
created_at TEXT NOT NULL,
UNIQUE(book_id, name)
)
''')
conn.commit()
conn.close()
conn.commit()
def _get_book_id(self, bookPath):
"""Generate unique book ID from file path"""
@@ -94,20 +93,19 @@ class BookmarkManager:
bookId = self._get_book_id(bookPath)
timestamp = datetime.now().isoformat()
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO bookmarks
(book_id, book_path, book_title, chapter_index, paragraph_index,
sentence_index, audio_position, last_accessed, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?,
COALESCE((SELECT created_at FROM bookmarks WHERE book_id = ?), ?))
''', (bookId, str(bookPath), bookTitle, chapterIndex, paragraphIndex,
sentenceIndex, audioPosition, timestamp, bookId, timestamp))
cursor.execute('''
INSERT OR REPLACE INTO bookmarks
(book_id, book_path, book_title, chapter_index, paragraph_index,
sentence_index, audio_position, last_accessed, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?,
COALESCE((SELECT created_at FROM bookmarks WHERE book_id = ?), ?))
''', (bookId, str(bookPath), bookTitle, chapterIndex, paragraphIndex,
sentenceIndex, audioPosition, timestamp, bookId, timestamp))
conn.commit()
conn.close()
conn.commit()
def get_bookmark(self, bookPath):
"""
@@ -121,18 +119,17 @@ class BookmarkManager:
"""
bookId = self._get_book_id(bookPath)
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('''
SELECT chapter_index, paragraph_index, sentence_index,
book_title, last_accessed, audio_position
FROM bookmarks
WHERE book_id = ?
''', (bookId,))
cursor.execute('''
SELECT chapter_index, paragraph_index, sentence_index,
book_title, last_accessed, audio_position
FROM bookmarks
WHERE book_id = ?
''', (bookId,))
row = cursor.fetchone()
conn.close()
row = cursor.fetchone()
if row:
return {
@@ -155,13 +152,10 @@ class BookmarkManager:
"""
bookId = self._get_book_id(bookPath)
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
cursor.execute('DELETE FROM bookmarks WHERE book_id = ?', (bookId,))
conn.commit()
conn.close()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('DELETE FROM bookmarks WHERE book_id = ?', (bookId,))
conn.commit()
def list_bookmarks(self):
"""
@@ -170,18 +164,17 @@ class BookmarkManager:
Returns:
List of dictionaries with bookmark data
"""
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('''
SELECT book_path, book_title, chapter_index, paragraph_index,
sentence_index, last_accessed
FROM bookmarks
ORDER BY last_accessed DESC
''')
cursor.execute('''
SELECT book_path, book_title, chapter_index, paragraph_index,
sentence_index, last_accessed
FROM bookmarks
ORDER BY last_accessed DESC
''')
rows = cursor.fetchall()
conn.close()
rows = cursor.fetchall()
bookmarks = []
for row in rows:
@@ -213,23 +206,21 @@ class BookmarkManager:
bookId = self._get_book_id(bookPath)
timestamp = datetime.now().isoformat()
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
try:
cursor.execute('''
INSERT INTO named_bookmarks
(book_id, name, chapter_index, paragraph_index, audio_position, created_at)
VALUES (?, ?, ?, ?, ?, ?)
''', (bookId, name, chapterIndex, paragraphIndex, audioPosition, timestamp))
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
conn.commit()
conn.close()
cursor.execute('''
INSERT INTO named_bookmarks
(book_id, name, chapter_index, paragraph_index, audio_position, created_at)
VALUES (?, ?, ?, ?, ?, ?)
''', (bookId, name, chapterIndex, paragraphIndex, audioPosition, timestamp))
conn.commit()
return True
except sqlite3.IntegrityError:
# Bookmark with this name already exists
conn.close()
return False
def get_named_bookmarks(self, bookPath):
@@ -244,18 +235,17 @@ class BookmarkManager:
"""
bookId = self._get_book_id(bookPath)
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('''
SELECT id, name, chapter_index, paragraph_index, audio_position, created_at
FROM named_bookmarks
WHERE book_id = ?
ORDER BY created_at DESC
''', (bookId,))
cursor.execute('''
SELECT id, name, chapter_index, paragraph_index, audio_position, created_at
FROM named_bookmarks
WHERE book_id = ?
ORDER BY created_at DESC
''', (bookId,))
rows = cursor.fetchall()
conn.close()
rows = cursor.fetchall()
bookmarks = []
for row in rows:
@@ -277,13 +267,10 @@ class BookmarkManager:
Args:
bookmarkId: Bookmark ID
"""
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
cursor.execute('DELETE FROM named_bookmarks WHERE id = ?', (bookmarkId,))
conn.commit()
conn.close()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('DELETE FROM named_bookmarks WHERE id = ?', (bookmarkId,))
conn.commit()
def get_named_bookmark_by_id(self, bookmarkId):
"""
@@ -295,17 +282,16 @@ class BookmarkManager:
Returns:
Bookmark dictionary or None if not found
"""
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
with sqlite3.connect(self.dbPath) as conn:
cursor = conn.cursor()
cursor.execute('''
SELECT name, chapter_index, paragraph_index, audio_position
FROM named_bookmarks
WHERE id = ?
''', (bookmarkId,))
cursor.execute('''
SELECT name, chapter_index, paragraph_index, audio_position
FROM named_bookmarks
WHERE id = ?
''', (bookmarkId,))
row = cursor.fetchone()
conn.close()
row = cursor.fetchone()
if row:
return {