Skip to content
Open
18 changes: 11 additions & 7 deletions admin_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,28 @@
from database import get_db_manager, User, RegisteredDomain, Order, WalletTransaction
from payment_service import get_payment_service
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from nomadly_clean.config import Config

logger = logging.getLogger(__name__)



class AdminPanel:
"""Administrative interface for bot management"""

def __init__(self):
self.db = get_db_manager()
self.payment_service = get_payment_service()

# Admin user IDs (telegram IDs of authorized admins)
self.admin_users = {
123456789, # Replace with actual admin telegram IDs
987654321, # Add more admin IDs as needed
}
self.admin_users = Config.load_admin_ids()

def is_admin(self, telegram_id: int) -> bool:
"""Check if user is authorized admin"""
return telegram_id in self.admin_users

# def refresh_admins_from_env(self):
# """Reload admin user IDs from environment or config"""
# self.admin_users = load_admin_ids()

async def show_admin_dashboard(self, query):
"""Show main admin dashboard"""
if not self.is_admin(query.from_user.id):
Expand Down Expand Up @@ -284,6 +285,9 @@ async def send_broadcast_message(self, query):
def get_system_statistics(self) -> Dict:
"""Get comprehensive system statistics"""
try:
# Make sure tables exist (safe to call repeatedly)
self.db.ensure_tables()

session = self.db.get_session()

# Count users
Expand All @@ -293,7 +297,7 @@ def get_system_statistics(self) -> Dict:
week_ago = datetime.now() - timedelta(days=7)
active_users_7d = (
session.query(User)
.filter(User.last_activity > week_ago)
.filter(User.updated_at > week_ago)
.count()
)

Expand Down
20 changes: 18 additions & 2 deletions nomadly_clean/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,33 @@
Centralizes environment variables and configuration settings
"""

import os
import os, re
from typing import List, Dict, Any
from dotenv import load_dotenv

# Load environment variables from .env file (override system environment)
load_dotenv(override=True)

import logging
logger = logging.getLogger(__name__)

class Config:
"""Centralized configuration for the bot"""

@staticmethod
def load_admin_ids(env_var: str = "ADMIN_IDS") -> set[int]:
raw = os.getenv(env_var, "")
ids: set[int] = set()
for piece in re.split(r"[,\s]+", raw.strip()):
if not piece:
continue
try:
ids.add(int(piece))
except ValueError:
logger.warning("Ignoring non-integer ADMIN_IDS entry: %r", piece)
if not ids:
logger.warning("ADMIN_IDS is empty; admin features will be locked down.")
return ids

# API Credentials
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
ADMIN_CHAT_ID = int(os.getenv("ADMIN_CHAT_ID", "0"))
Expand Down
41 changes: 41 additions & 0 deletions nomadly_clean/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,47 @@ def update_user_technical_email(self, telegram_id: int, email: str) -> bool:
finally:
session.close()

def get_all_user_ids(self) -> list[int]:
"""Return all telegram IDs for broadcast."""
self.ensure_tables()
s = self.get_session()
try:
rows = s.query(User.telegram_id).filter(User.telegram_id.isnot(None)).all()
ids = [uid for (uid,) in rows] # already Python ints from BIGINT
ids = [cid for cid in ids if cid > 0] # only user DMs, skip groups
# de-dup without losing order
seen = set()
uniq = []
for cid in ids:
if cid not in seen:
seen.add(cid)
uniq.append(cid)
logger.info("Broadcast targets from DB, %s users", len(uniq))
return uniq
finally:
s.close()


# def get_all_user_ids(self) -> list[int]:
# """Return all telegram IDs for broadcast (no chat_id column)."""
# self.ensure_tables()
# s = self.get_session()
# try:
# rows = s.query(User.telegram_id).filter(User.telegram_id.isnot(None)).all()
# ids = []
# for (uid,) in rows:
# try:
# ids.append(int(uid))
# except Exception:
# logger.warning(f"Skipping non-numeric telegram_id: {uid!r}")
# # de-dup in case the table ever gets odd data
# ids = list({i for i in ids if i > 0})
# logger.info(f"Broadcast targets from DB: {len(ids)} users")
# return ids
# finally:
# s.close()


def get_user_technical_email(self, telegram_id: int) -> Optional[str]:
"""Get user's stored technical email"""
session = self.get_session()
Expand Down
Loading