Audiobookshelf support mostly working.

This commit is contained in:
Storm Dragon
2025-10-05 20:19:16 -04:00
parent 1d19ed377c
commit 4387a5cb56
14 changed files with 3979 additions and 67 deletions
+151 -6
View File
@@ -50,6 +50,27 @@ class BookmarkManager:
)
''')
# 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)
)
''')
conn.commit()
conn.close()
@@ -58,7 +79,7 @@ class BookmarkManager:
bookPath = str(Path(bookPath).resolve())
return hashlib.sha256(bookPath.encode()).hexdigest()[:16]
def save_bookmark(self, bookPath, bookTitle, chapterIndex, paragraphIndex, sentenceIndex=0):
def save_bookmark(self, bookPath, bookTitle, chapterIndex, paragraphIndex, sentenceIndex=0, audioPosition=0.0):
"""
Save bookmark for a book
@@ -68,6 +89,7 @@ class BookmarkManager:
chapterIndex: Current chapter index
paragraphIndex: Current paragraph index
sentenceIndex: Current sentence index (default: 0)
audioPosition: Audio playback position in seconds (default: 0.0)
"""
bookId = self._get_book_id(bookPath)
timestamp = datetime.now().isoformat()
@@ -78,11 +100,11 @@ class BookmarkManager:
cursor.execute('''
INSERT OR REPLACE INTO bookmarks
(book_id, book_path, book_title, chapter_index, paragraph_index,
sentence_index, last_accessed, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?,
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, timestamp, bookId, timestamp))
sentenceIndex, audioPosition, timestamp, bookId, timestamp))
conn.commit()
conn.close()
@@ -104,7 +126,7 @@ class BookmarkManager:
cursor.execute('''
SELECT chapter_index, paragraph_index, sentence_index,
book_title, last_accessed
book_title, last_accessed, audio_position
FROM bookmarks
WHERE book_id = ?
''', (bookId,))
@@ -118,7 +140,8 @@ class BookmarkManager:
'paragraphIndex': row[1],
'sentenceIndex': row[2],
'bookTitle': row[3],
'lastAccessed': row[4]
'lastAccessed': row[4],
'audioPosition': row[5] if row[5] is not None else 0.0
}
return None
@@ -172,3 +195,125 @@ class BookmarkManager:
})
return bookmarks
def create_named_bookmark(self, bookPath, name, chapterIndex, paragraphIndex, audioPosition=0.0):
"""
Create a named bookmark for a book
Args:
bookPath: Path to book file
name: Bookmark name
chapterIndex: Chapter index
paragraphIndex: Paragraph index
audioPosition: Audio position in seconds (default: 0.0)
Returns:
True if created successfully, False if name already exists
"""
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))
conn.commit()
conn.close()
return True
except sqlite3.IntegrityError:
# Bookmark with this name already exists
conn.close()
return False
def get_named_bookmarks(self, bookPath):
"""
Get all named bookmarks for a book
Args:
bookPath: Path to book file
Returns:
List of named bookmark dictionaries
"""
bookId = self._get_book_id(bookPath)
conn = sqlite3.connect(self.dbPath)
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,))
rows = cursor.fetchall()
conn.close()
bookmarks = []
for row in rows:
bookmarks.append({
'id': row[0],
'name': row[1],
'chapterIndex': row[2],
'paragraphIndex': row[3],
'audioPosition': row[4],
'createdAt': row[5]
})
return bookmarks
def delete_named_bookmark(self, bookmarkId):
"""
Delete a named bookmark by ID
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()
def get_named_bookmark_by_id(self, bookmarkId):
"""
Get a named bookmark by ID
Args:
bookmarkId: Bookmark ID
Returns:
Bookmark dictionary or None if not found
"""
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
cursor.execute('''
SELECT name, chapter_index, paragraph_index, audio_position
FROM named_bookmarks
WHERE id = ?
''', (bookmarkId,))
row = cursor.fetchone()
conn.close()
if row:
return {
'name': row[0],
'chapterIndex': row[1],
'paragraphIndex': row[2],
'audioPosition': row[3]
}
return None