Fixed bookmarking with audio books.
This commit is contained in:
+97
-111
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user