Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified __pycache__/bot_handlers.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/code_processor.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/config.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/conversation_handlers.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/file_manager.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/github_menu_handler.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/integrations.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/main.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/search_engine.cpython-313.pyc
Binary file not shown.
Binary file modified __pycache__/utils.cpython-313.pyc
Binary file not shown.
10 changes: 10 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ class BotConfig:

# קידומת לשם נקודת שמירה ב-Git (ל-tags ולענפים בגיבוי)
GIT_CHECKPOINT_PREFIX: str = "checkpoint"

# Google Drive OAuth (Desktop App / Device Flow)
GOOGLE_CLIENT_ID: Optional[str] = None
GOOGLE_CLIENT_SECRET: Optional[str] = None
GOOGLE_OAUTH_SCOPES: str = "https://www.googleapis.com/auth/drive.file"
GOOGLE_TOKEN_REFRESH_MARGIN_SECS: int = 120

def __post_init__(self):
if self.SUPPORTED_LANGUAGES is None:
Expand Down Expand Up @@ -71,6 +77,10 @@ def load_config() -> BotConfig:
MAX_FILES_PER_USER=int(os.getenv('MAX_FILES_PER_USER', '1000')),
HIGHLIGHT_THEME=os.getenv('HIGHLIGHT_THEME', 'github-dark'),
GIT_CHECKPOINT_PREFIX=os.getenv('GIT_CHECKPOINT_PREFIX', 'checkpoint'),
GOOGLE_CLIENT_ID=os.getenv('GOOGLE_CLIENT_ID'),
GOOGLE_CLIENT_SECRET=os.getenv('GOOGLE_CLIENT_SECRET'),
GOOGLE_OAUTH_SCOPES=os.getenv('GOOGLE_OAUTH_SCOPES', 'https://www.googleapis.com/auth/drive.file'),
GOOGLE_TOKEN_REFRESH_MARGIN_SECS=int(os.getenv('GOOGLE_TOKEN_REFRESH_MARGIN_SECS', '120')),
MAINTENANCE_MODE=os.getenv('MAINTENANCE_MODE', 'false').lower() == 'true',
MAINTENANCE_MESSAGE=os.getenv('MAINTENANCE_MESSAGE', "🚀 אנחנו מעלים עדכון חדש!\nהבוט יחזור לפעול ממש בקרוב (1 - 3 דקות)"),
MAINTENANCE_AUTO_WARMUP_SECS=int(os.getenv('MAINTENANCE_AUTO_WARMUP_SECS', '180')),
Expand Down
2 changes: 1 addition & 1 deletion conversation_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def _format_bytes(num: int) -> str:
["🗜️ יצירת ZIP", "➕ הוסף קוד חדש"],
["📚 הצג את כל הקבצים שלי", "🔧 GitHub"],
["⚡ עיבוד Batch", "📥 ייבוא ZIP מריפו"],
["ℹ️ הסבר על הבוט"]
["☁️ Google Drive", "ℹ️ הסבר על הבוט"]
]

reporter = create_reporter(
Expand Down
16 changes: 16 additions & 0 deletions database/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,19 @@ def get_selected_repo(self, user_id: int) -> Optional[str]:
def save_user(self, user_id: int, username: str = None) -> bool:
return self._get_repo().save_user(user_id, username)

# Google Drive tokens & preferences
def save_drive_tokens(self, user_id: int, token_data: Dict[str, Any]) -> bool:
return self._get_repo().save_drive_tokens(user_id, token_data)

def get_drive_tokens(self, user_id: int) -> Optional[Dict[str, Any]]:
return self._get_repo().get_drive_tokens(user_id)

def delete_drive_tokens(self, user_id: int) -> bool:
return self._get_repo().delete_drive_tokens(user_id)

def save_drive_prefs(self, user_id: int, prefs: Dict[str, Any]) -> bool:
return self._get_repo().save_drive_prefs(user_id, prefs)

def get_drive_prefs(self, user_id: int) -> Optional[Dict[str, Any]]:
return self._get_repo().get_drive_prefs(user_id)

91 changes: 91 additions & 0 deletions database/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,97 @@ def save_user(self, user_id: int, username: str = None) -> bool:
logger.error(f"שגיאה בשמירת משתמש: {e}")
return False

# --- Google Drive tokens & preferences ---
def save_drive_tokens(self, user_id: int, token_data: Dict[str, Any]) -> bool:
try:
users_collection = self.manager.db.users
# Encrypt sensitive fields
from secret_manager import encrypt_secret
enc_access = encrypt_secret(token_data.get("access_token", "") or "")
enc_refresh = encrypt_secret(token_data.get("refresh_token", "") or "")
stored = {
"access_token": enc_access if enc_access else token_data.get("access_token"),
"refresh_token": enc_refresh if enc_refresh else token_data.get("refresh_token"),
"token_type": token_data.get("token_type"),
"expiry": token_data.get("expiry"),
"scope": token_data.get("scope"),
"expires_in": token_data.get("expires_in"),
"obtained_at": datetime.now(timezone.utc).isoformat(),
}
result = users_collection.update_one(
{"user_id": user_id},
{"$set": {"drive_tokens": stored, "updated_at": datetime.now(timezone.utc)}},
upsert=True,
)
return bool(result.acknowledged)
except Exception as e:
logger.error(f"Failed to save Drive tokens: {e}")
return False

def get_drive_tokens(self, user_id: int) -> Optional[Dict[str, Any]]:
try:
users_collection = self.manager.db.users
user = users_collection.find_one({"user_id": user_id})
if not user:
return None
data = user.get("drive_tokens")
if not data:
return None
# Decrypt
from secret_manager import decrypt_secret
acc = data.get("access_token")
ref = data.get("refresh_token")
acc_dec = decrypt_secret(acc) if acc else None
ref_dec = decrypt_secret(ref) if ref else None
out = dict(data)
if acc_dec:
out["access_token"] = acc_dec
if ref_dec:
out["refresh_token"] = ref_dec
return out
except Exception as e:
logger.error(f"Failed to get Drive tokens: {e}")
return None

def delete_drive_tokens(self, user_id: int) -> bool:
try:
users_collection = self.manager.db.users
res = users_collection.update_one(
{"user_id": user_id}, {"$unset": {"drive_tokens": ""}, "$set": {"updated_at": datetime.now(timezone.utc)}}
)
return bool(res.acknowledged)
except Exception as e:
logger.error(f"Failed to delete Drive tokens: {e}")
return False

def save_drive_prefs(self, user_id: int, prefs: Dict[str, Any]) -> bool:
try:
users_collection = self.manager.db.users
# merge with existing prefs
existing = users_collection.find_one({"user_id": user_id}) or {}
merged = dict(existing.get("drive_prefs") or {})
merged.update(prefs or {})
res = users_collection.update_one(
{"user_id": user_id},
{"$set": {"drive_prefs": merged, "updated_at": datetime.now(timezone.utc)}},
upsert=True,
)
return bool(res.acknowledged)
except Exception as e:
logger.error(f"Failed to save Drive prefs: {e}")
return False

def get_drive_prefs(self, user_id: int) -> Optional[Dict[str, Any]]:
try:
users_collection = self.manager.db.users
user = users_collection.find_one({"user_id": user_id})
if not user:
return None
return user.get("drive_prefs")
except Exception as e:
logger.error(f"Failed to get Drive prefs: {e}")
return None

# --- Backup ratings ---
def save_backup_rating(self, user_id: int, backup_id: str, rating: str) -> bool:
try:
Expand Down
Loading