Initial commit.

This commit is contained in:
Storm Dragon
2025-10-04 02:55:01 -04:00
commit 1d19ed377c
16 changed files with 4401 additions and 0 deletions
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Bookmark Manager
Manages reading positions for books using SQLite for persistence.
Tracks chapter, paragraph, and sentence positions.
"""
import sqlite3
import hashlib
from pathlib import Path
from datetime import datetime
class BookmarkManager:
"""Manages bookmarks for books"""
def __init__(self, dbPath=None):
"""
Initialize bookmark manager
Args:
dbPath: Path to SQLite database (default: ~/.bookstorm/bookmarks.db)
"""
if dbPath is None:
homePath = Path.home()
bookstormDir = homePath / ".bookstorm"
bookstormDir.mkdir(exist_ok=True)
dbPath = bookstormDir / "bookmarks.db"
self.dbPath = dbPath
self._init_db()
def _init_db(self):
"""Initialize database schema"""
conn = sqlite3.connect(self.dbPath)
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
)
''')
conn.commit()
conn.close()
def _get_book_id(self, bookPath):
"""Generate unique book ID from file path"""
bookPath = str(Path(bookPath).resolve())
return hashlib.sha256(bookPath.encode()).hexdigest()[:16]
def save_bookmark(self, bookPath, bookTitle, chapterIndex, paragraphIndex, sentenceIndex=0):
"""
Save bookmark for a book
Args:
bookPath: Path to book file
bookTitle: Title of the book
chapterIndex: Current chapter index
paragraphIndex: Current paragraph index
sentenceIndex: Current sentence index (default: 0)
"""
bookId = self._get_book_id(bookPath)
timestamp = datetime.now().isoformat()
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO bookmarks
(book_id, book_path, book_title, chapter_index, paragraph_index,
sentence_index, last_accessed, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?,
COALESCE((SELECT created_at FROM bookmarks WHERE book_id = ?), ?))
''', (bookId, str(bookPath), bookTitle, chapterIndex, paragraphIndex,
sentenceIndex, timestamp, bookId, timestamp))
conn.commit()
conn.close()
def get_bookmark(self, bookPath):
"""
Get bookmark for a book
Args:
bookPath: Path to book file
Returns:
Dictionary with bookmark data or None if not found
"""
bookId = self._get_book_id(bookPath)
conn = sqlite3.connect(self.dbPath)
cursor = conn.cursor()
cursor.execute('''
SELECT chapter_index, paragraph_index, sentence_index,
book_title, last_accessed
FROM bookmarks
WHERE book_id = ?
''', (bookId,))
row = cursor.fetchone()
conn.close()
if row:
return {
'chapterIndex': row[0],
'paragraphIndex': row[1],
'sentenceIndex': row[2],
'bookTitle': row[3],
'lastAccessed': row[4]
}
return None
def delete_bookmark(self, bookPath):
"""
Delete bookmark for a book
Args:
bookPath: Path to book file
"""
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()
def list_bookmarks(self):
"""
List all bookmarks
Returns:
List of dictionaries with bookmark data
"""
conn = sqlite3.connect(self.dbPath)
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
''')
rows = cursor.fetchall()
conn.close()
bookmarks = []
for row in rows:
bookmarks.append({
'bookPath': row[0],
'bookTitle': row[1],
'chapterIndex': row[2],
'paragraphIndex': row[3],
'sentenceIndex': row[4],
'lastAccessed': row[5]
})
return bookmarks