הראה קוד מקור ל activity_reporter

"""
קובץ פשוט לדיווח פעילות - העתק את הקובץ הזה לכל בוט
"""
try:
    from pymongo import MongoClient  # type: ignore
    _HAS_PYMONGO = True
except Exception:
    MongoClient = None  # type: ignore
    _HAS_PYMONGO = False
from datetime import datetime, timezone
import atexit

# חיבור MongoDB גלובלי יחיד לכל האפליקציה
_client = None  # type: ignore
_owns_client = False  # האם המודול יצר את הלקוח בעצמו

[תיעוד] def get_mongo_client(mongodb_uri: str): """החזרת מופע MongoClient יחיד (singleton) לכל האפליקציה. בכל קריאה מחזיר את אותו אובייקט, ויוצר רק בפעם הראשונה. """ global _client if not _HAS_PYMONGO: raise RuntimeError("pymongo not available") if _client is None: # אם כבר קיים לקוח במסד הנתונים המרכזי – נמחזר אותו, כדי למנוע כפילויות try: from database import db as _db # import דינמי כדי להימנע מייבוא מעגלי בזמן טעינה existing = getattr(_db, "client", None) except Exception: existing = None if existing is not None: # שימוש בלקוח קיים של המערכת (לא אנחנו יוצרים/סוגרים) _client = existing globals()["_owns_client"] = False else: # יצירת לקוח משלנו עם timezone-aware _client = MongoClient(mongodb_uri, tz_aware=True, tzinfo=timezone.utc) globals()["_owns_client"] = True return _client
[תיעוד] def close_mongo_client() -> None: """סגירת החיבור הגלובלי בבטחה בזמן כיבוי השירות.""" global _client try: if _client is not None and globals().get("_owns_client", False): _client.close() finally: _client = None
# סגירה אוטומטית ביציאה מהתהליך atexit.register(close_mongo_client) try: from metrics import note_active_user # type: ignore except Exception: # pragma: no cover def note_active_user(user_id: int) -> None: # type: ignore return None
[תיעוד] class SimpleActivityReporter:
[תיעוד] def __init__(self, mongodb_uri, service_id, service_name=None): """ mongodb_uri: חיבור למונגו (אותו מהבוט המרכזי) service_id: מזהה השירות ב-Render service_name: שם הבוט (אופציונלי) """ try: if not _HAS_PYMONGO: raise RuntimeError("pymongo not available") # שימוש ב-singleton של MongoClient כדי למנוע חיבורים מרובים self.client = get_mongo_client(mongodb_uri) self.db = self.client["render_bot_monitor"] self.service_id = service_id self.service_name = service_name or service_id self.connected = True except Exception: self.connected = False # שקט בסביבת בדיקות/ללא pymongo pass
[תיעוד] def report_activity(self, user_id): """דיווח פעילות פשוט""" if not self.connected: try: # Even if DB is unavailable, update in-memory active users gauge if possible note_active_user(int(user_id)) except Exception: pass return try: now = datetime.now(timezone.utc) # עדכון אינטראקציית המשתמש self.db.user_interactions.update_one( {"service_id": self.service_id, "user_id": user_id}, { "$set": {"last_interaction": now}, "$inc": {"interaction_count": 1}, "$setOnInsert": {"created_at": now} }, upsert=True ) # עדכון פעילות השירות self.db.service_activity.update_one( {"_id": self.service_id}, { "$set": { "last_user_activity": now, "service_name": self.service_name, "updated_at": now }, "$setOnInsert": { "created_at": now, "status": "active", "total_users": 0, "suspend_count": 0 } }, upsert=True ) # Update active users gauge try: note_active_user(int(user_id)) except Exception: pass except Exception: # שקט - אל תיכשל את הבוט אם יש בעיה pass
# דוגמה לשימוש קל
[תיעוד] def create_reporter(mongodb_uri, service_id, service_name=None): """יצירת reporter פשוט""" return SimpleActivityReporter(mongodb_uri, service_id, service_name)