הראה קוד מקור ל database.bookmark

"""
Bookmark Model for file line bookmarks
"""
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Optional, Dict, Any
from bson import ObjectId


[תיעוד] @dataclass class FileBookmark: """מודל סימנייה לשורה בקובץ קוד""" # Required fields user_id: int # Telegram user ID file_id: str # MongoDB ObjectId של הקובץ file_name: str # שם הקובץ לחיפוש מהיר file_path: str # נתיב הקובץ המלא line_number: int # מספר השורה (1-based). במקרה של עוגן (Markdown/HTML) יכול להיות 0 # Content preview line_text_preview: str = "" # 100 התווים הראשונים של השורה code_context: str = "" # 3 שורות לפני ואחרי (אופציונלי) # User content note: str = "" # הערת המשתמש (עד 500 תווים) color: str = "yellow" # צבע הסימנייה (yellow/red/green/blue) # Anchor-based bookmarks (Markdown/HTML) anchor_id: str = "" # מזהה עוגן ייחודי בתוך המסמך (id של כותרת למשל) anchor_text: str = "" # טקסט תיאורי לעוגן (למשל כותרת) anchor_type: str = "" # סוג העוגן: 'md_heading'/'html_id' וכד'. ריק כשמבוסס שורה # Sync metadata file_hash: str = "" # SHA256 של הקובץ בזמן היצירה valid: bool = True # האם הסימנייה עדיין תקפה sync_status: str = "synced" # synced/moved/modified/deleted sync_confidence: float = 1.0 # רמת הביטחון בסנכרון (0-1) # Timestamps created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc)) updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc)) last_accessed: Optional[datetime] = None # MongoDB ID _id: Optional[ObjectId] = None
[תיעוד] def to_dict(self) -> Dict[str, Any]: """המרה ל-dictionary לשמירה ב-MongoDB""" data = { "user_id": self.user_id, "file_id": self.file_id, "file_name": self.file_name, "file_path": self.file_path, "line_number": self.line_number, "line_text_preview": self.line_text_preview[:100], # הגבלה ל-100 תווים "code_context": self.code_context[:500], # הגבלה ל-500 תווים "note": self.note[:500], # הגבלה ל-500 תווים "color": self.color, "file_hash": self.file_hash, "valid": self.valid, "sync_status": self.sync_status, "sync_confidence": self.sync_confidence, "created_at": self.created_at, "updated_at": self.updated_at, "last_accessed": self.last_accessed } # הוסף שדות עוגן רק כאשר קיים anchor_id ממשי (לא ריק) if isinstance(self.anchor_id, str) and (self.anchor_id or "").strip(): data["anchor_id"] = self.anchor_id if self.anchor_text: data["anchor_text"] = self.anchor_text if self.anchor_type: data["anchor_type"] = self.anchor_type if self._id: data["_id"] = self._id return data
[תיעוד] @classmethod def from_dict(cls, data: Dict[str, Any]) -> "FileBookmark": """יצירה מ-dictionary שהגיע מ-MongoDB""" def _required(key: str) -> Any: if key not in data or data[key] is None: raise ValueError(f"Missing required field: {key}") return data[key] # שדות חובה עם המרות בסיסיות user_id = _required("user_id") file_id = _required("file_id") try: line_number_val = _required("line_number") line_number = int(line_number_val) except Exception: raise ValueError("Invalid line_number: must be an integer") bookmark = cls( user_id=user_id, file_id=file_id, file_name=data.get("file_name", ""), file_path=data.get("file_path", ""), line_number=line_number, line_text_preview=data.get("line_text_preview", ""), code_context=data.get("code_context", ""), note=data.get("note", ""), color=data.get("color", "yellow"), anchor_id=data.get("anchor_id", ""), anchor_text=data.get("anchor_text", ""), anchor_type=data.get("anchor_type", ""), file_hash=data.get("file_hash", ""), valid=data.get("valid", True), sync_status=data.get("sync_status", "synced"), sync_confidence=data.get("sync_confidence", 1.0), created_at=data.get("created_at", datetime.now(timezone.utc)), updated_at=data.get("updated_at", datetime.now(timezone.utc)), last_accessed=data.get("last_accessed") ) if "_id" in data: bookmark._id = data["_id"] return bookmark
def __str__(self) -> str: return f"Bookmark({self.file_name}:{self.line_number})" def __repr__(self) -> str: return (f"FileBookmark(user={self.user_id}, file={self.file_name}, " f"line={self.line_number}, note='{self.note[:20]}...')")
# Constants for validation MAX_BOOKMARKS_PER_FILE = 50 MAX_BOOKMARKS_PER_USER = 500 MAX_NOTE_LENGTH = 500 MAX_CONTEXT_LENGTH = 500 VALID_COLORS = ["yellow", "red", "green", "blue", "purple", "orange", "pink"]