Spaces:
Build error
Build error
| # modules/firebase_manager.py | |
| """ | |
| Firebase انٹیگریشن - ڈیٹا محفوظ کرنے کے لیے | |
| """ | |
| import os | |
| import logging | |
| from datetime import datetime | |
| from typing import Optional, Dict, List | |
| logger = logging.getLogger(__name__) | |
| # Firebase کو conditional import کریں | |
| try: | |
| import firebase_admin | |
| from firebase_admin import credentials, firestore | |
| FIREBASE_AVAILABLE = True | |
| except ImportError: | |
| FIREBASE_AVAILABLE = False | |
| logger.warning("Firebase not installed. Running without database.") | |
| class FirebaseManager: | |
| """Firebase Firestore کے ساتھ کام کرنے کے لیے""" | |
| _instance = None | |
| def __new__(cls): | |
| """Singleton pattern""" | |
| if cls._instance is None: | |
| cls._instance = super().__new__(cls) | |
| cls._instance._initialized = False | |
| return cls._instance | |
| def __init__(self): | |
| """Initialize Firebase""" | |
| if self._initialized: | |
| return | |
| self.enabled = False | |
| if not FIREBASE_AVAILABLE: | |
| logger.warning("Firebase SDK not available") | |
| self._initialized = True | |
| return | |
| try: | |
| # Hugging Face Spaces secrets سے credentials | |
| cred_dict = self._get_credentials_from_env() | |
| if cred_dict: | |
| cred = credentials.Certificate(cred_dict) | |
| if not firebase_admin._apps: | |
| firebase_admin.initialize_app(cred) | |
| self.db = firestore.client() | |
| self.enabled = True | |
| logger.info("Firebase initialized successfully") | |
| else: | |
| logger.warning("Firebase credentials not found in environment") | |
| except Exception as e: | |
| logger.error(f"Firebase initialization failed: {e}") | |
| self.enabled = False | |
| self._initialized = True | |
| def _get_credentials_from_env(self) -> Optional[Dict]: | |
| """Environment variables سے credentials بنائیں""" | |
| required_vars = [ | |
| 'FIREBASE_PROJECT_ID', | |
| 'FIREBASE_PRIVATE_KEY', | |
| 'FIREBASE_CLIENT_EMAIL' | |
| ] | |
| # چیک کریں کہ سب variables موجود ہیں | |
| if not all(os.getenv(var) for var in required_vars): | |
| return None | |
| # Private key کو ٹھیک کریں (\\n کو \n میں) | |
| private_key = os.getenv('FIREBASE_PRIVATE_KEY', '') | |
| private_key = private_key.replace('\\n', '\n') | |
| cred_dict = { | |
| "type": "service_account", | |
| "project_id": os.getenv('FIREBASE_PROJECT_ID'), | |
| "private_key_id": os.getenv('FIREBASE_PRIVATE_KEY_ID', ''), | |
| "private_key": private_key, | |
| "client_email": os.getenv('FIREBASE_CLIENT_EMAIL'), | |
| "client_id": os.getenv('FIREBASE_CLIENT_ID', ''), | |
| "auth_uri": "https://accounts.google.com/o/oauth2/auth", | |
| "token_uri": "https://oauth2.googleapis.com/token", | |
| "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | |
| "client_x509_cert_url": os.getenv('FIREBASE_CLIENT_CERT_URL', '') | |
| } | |
| return cred_dict | |
| def save_essay_result( | |
| self, | |
| user_id: str, | |
| essay_data: Dict, | |
| grading_result: Dict | |
| ) -> Optional[str]: | |
| """ | |
| مضمون کے نتائج محفوظ کریں | |
| Args: | |
| user_id: صارف کا ID | |
| essay_data: مضمون کی تفصیلات | |
| grading_result: جانچ کے نتائج | |
| Returns: | |
| Document ID یا None | |
| """ | |
| if not self.enabled: | |
| logger.debug("Firebase not enabled, skipping save") | |
| return None | |
| try: | |
| doc_ref = self.db.collection('essays').document() | |
| data = { | |
| 'user_id': user_id, | |
| 'student_name': essay_data.get('student_name', 'Unknown'), | |
| 'grade_level': essay_data.get('grade_level'), | |
| 'essay_type': essay_data.get('essay_type'), | |
| 'language': essay_data.get('language'), | |
| 'word_count': essay_data.get('word_count', 0), | |
| 'essay_text': essay_data.get('text', '')[:1000], | |
| 'grading': { | |
| 'total_score': grading_result['total_score'], | |
| 'scores': grading_result['scores'], | |
| 'grade': grading_result['grade'] | |
| }, | |
| 'created_at': firestore.SERVER_TIMESTAMP, | |
| 'month': datetime.now().strftime('%Y-%m') | |
| } | |
| doc_ref.set(data) | |
| logger.info(f"Essay saved to Firebase: {doc_ref.id}") | |
| return doc_ref.id | |
| except Exception as e: | |
| logger.error(f"Failed to save to Firebase: {e}") | |
| return None | |
| def get_user_essays( | |
| self, | |
| user_id: str, | |
| limit: int = 20 | |
| ) -> List[Dict]: | |
| """ | |
| صارف کے مضامین حاصل کریں | |
| Args: | |
| user_id: صارف کا ID | |
| limit: زیادہ سے زیادہ تعداد | |
| Returns: | |
| مضامین کی فہرست | |
| """ | |
| if not self.enabled: | |
| return [] | |
| try: | |
| query = self.db.collection('essays')\ | |
| .where('user_id', '==', user_id)\ | |
| .order_by('created_at', direction=firestore.Query.DESCENDING)\ | |
| .limit(limit) | |
| docs = query.stream() | |
| essays = [] | |
| for doc in docs: | |
| data = doc.to_dict() | |
| data['id'] = doc.id | |
| essays.append(data) | |
| logger.info(f"Retrieved {len(essays)} essays for user {user_id}") | |
| return essays | |
| except Exception as e: | |
| logger.error(f"Failed to get essays: {e}") | |
| return [] | |
| def check_monthly_limit( | |
| self, | |
| user_id: str, | |
| subscription: str = 'free' | |
| ) -> tuple: | |
| """ | |
| ماہانہ حد چیک کریں | |
| Args: | |
| user_id: صارف کا ID | |
| subscription: 'free', 'basic', یا 'premium' | |
| Returns: | |
| (حد میں ہے؟, استعمال شدہ, باقی) | |
| """ | |
| if not self.enabled: | |
| return (True, 0, 999) | |
| limits = { | |
| 'free': 20, | |
| 'basic': 100, | |
| 'premium': 999999 | |
| } | |
| max_essays = limits.get(subscription, 20) | |
| try: | |
| current_month = datetime.now().strftime('%Y-%m') | |
| query = self.db.collection('essays')\ | |
| .where('user_id', '==', user_id)\ | |
| .where('month', '==', current_month) | |
| count = len(list(query.stream())) | |
| remaining = max(0, max_essays - count) | |
| within_limit = remaining > 0 | |
| logger.info(f"User {user_id}: {count}/{max_essays} essays used") | |
| return (within_limit, count, remaining) | |
| except Exception as e: | |
| logger.error(f"Failed to check limit: {e}") | |
| return (True, 0, max_essays) |