import json
import os
from datetime import datetime, timedelta, timezone
from collections import defaultdict
import logging
def _get_files_facade_or_none():
try:
from src.infrastructure.composition import get_files_facade # type: ignore
return get_files_facade()
except Exception:
return None
def _get_users_collection():
facade = _get_files_facade_or_none()
if facade is None:
return None
try:
mongo_db = facade.get_mongo_db()
except Exception:
return None
if mongo_db is None:
return None
coll = getattr(mongo_db, "users", None)
if coll is not None:
return coll
try:
return mongo_db["users"] # type: ignore[index]
except Exception:
return None
logger = logging.getLogger(__name__)
[תיעוד]
class UserStats:
[תיעוד]
def __init__(self):
# כבר לא צריך קובץ זמני - נשתמש ב-MongoDB
pass
[תיעוד]
def log_user(self, user_id, username=None, weight: int = 1):
"""רישום משתמש ב-MongoDB עם משקל לדגימה (weight)."""
try:
# שמור או עדכן משתמש ב-MongoDB
facade = _get_files_facade_or_none()
if facade is None:
return
facade.save_user(user_id, username)
# עדכן את הזמן האחרון שהמשתמש היה פעיל
users_collection = _get_users_collection()
if users_collection is None:
return
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
# עדכון המשתמש עם פעילות אחרונה
users_collection.update_one(
{"user_id": user_id},
{
"$set": {
"last_seen": today,
"username": username if username else f"User_{user_id}",
"updated_at": datetime.now(timezone.utc)
},
"$inc": {
"total_actions": max(1, int(weight or 1))
},
"$addToSet": {
"usage_days": today
},
"$setOnInsert": {
"first_seen": today,
"created_at": datetime.now(timezone.utc)
}
},
upsert=True
)
except Exception as e:
logger.error(f"Error logging user: {e}")
[תיעוד]
def get_weekly_stats(self):
"""סטטיסטיקת שבוע אחרון מ-MongoDB"""
try:
users_collection = _get_users_collection()
if users_collection is None:
return []
week_ago = datetime.now(timezone.utc) - timedelta(days=7)
# השוואת ימים תתבצע לפי אובייקטי date כדי להימנע מהשוואת naive מול aware
week_ago_date = week_ago.date()
# מצא משתמשים פעילים בשבוע האחרון
active_users = []
# שאילתה למשתמשים שהיו פעילים בשבוע האחרון
users = users_collection.find({
"updated_at": {"$gte": week_ago}
})
for user in users:
# חשב כמה ימים המשתמש היה פעיל
usage_days = user.get("usage_days", [])
# הפוך מחרוזות תאריך (YYYY-MM-DD) ל-date והשווה ל-week_ago_date
recent_days = [
day for day in usage_days
if datetime.strptime(day, "%Y-%m-%d").date() >= week_ago_date
]
if recent_days:
active_users.append({
"username": user.get("username", f"User_{user['user_id']}"),
"days": len(recent_days),
"total_actions": user.get("total_actions", 0)
})
return sorted(active_users, key=lambda x: (x["days"], x["total_actions"]), reverse=True)
except Exception as e:
logger.error(f"Error getting weekly stats: {e}")
return []
[תיעוד]
def get_all_time_stats(self):
"""סטטיסטיקות כלליות מ-MongoDB"""
try:
users_collection = _get_users_collection()
if users_collection is None:
return {
"total_users": 0,
"active_today": 0,
"active_week": 0
}
# סה"כ משתמשים
total_users = users_collection.count_documents({})
# פעילים היום
today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
active_today = users_collection.count_documents({"last_seen": today})
# פעילים השבוע
week_ago = datetime.now(timezone.utc) - timedelta(days=7)
active_week = users_collection.count_documents({
"updated_at": {"$gte": week_ago}
})
return {
"total_users": total_users,
"active_today": active_today,
"active_week": active_week
}
except Exception as e:
logger.error(f"Error getting all time stats: {e}")
return {
"total_users": 0,
"active_today": 0,
"active_week": 0
}
# יצירת אובייקט סטטיסטיקות גלובלי
user_stats = UserStats()