feat: Add admin management system with super admin controls
Some checks failed
continuous-integration/drone/pr Build is failing
Some checks failed
continuous-integration/drone/pr Build is failing
- Implemented two-level admin hierarchy (super admin from .env and assigned admins) - Only super admins (from ADMIN_IDS in .env) can manage admin assignments - Added admin management menu to settings (visible only for super admins) - Admins can add/remove other admins through the bot interface - Protected super admins from deletion - Added CLI tool for admin management (scripts/manage_admins.py) - Added database check script (scripts/check_db.py) - Added deployment scripts for server setup - Added comprehensive documentation on admin management system - Added backup and server deployment guides
This commit is contained in:
102
scripts/backup_db.sh
Normal file
102
scripts/backup_db.sh
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
# Скрипт резервного копирования БД PostgreSQL
|
||||
# Использование: ./backup_db.sh
|
||||
# Для автоматизации добавьте в crontab: 0 3 * * * /path/to/backup_db.sh
|
||||
|
||||
set -e
|
||||
|
||||
# Переменные
|
||||
BACKUP_DIR="${HOME}/new_lottery_bot/backups"
|
||||
DB_NAME="${DATABASE_DEFAULT:-lottery_bot}"
|
||||
DB_USER="${DATABASE_USER:-trevor}"
|
||||
DB_HOST="${DATABASE_HOST:-localhost}"
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
BACKUP_FILE="${BACKUP_DIR}/lottery_bot_${TIMESTAMP}.sql.gz"
|
||||
KEEP_DAYS=7 # Хранить резервные копии 7 дней
|
||||
|
||||
# Цвета
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
echo "🔄 Резервное копирование БД PostgreSQL"
|
||||
echo "========================================"
|
||||
|
||||
# Создание директории для резервных копий
|
||||
if [ ! -d "$BACKUP_DIR" ]; then
|
||||
log_info "Создание директории для резервных копий..."
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
fi
|
||||
|
||||
# Получение размера БД перед резервной копией
|
||||
DB_SIZE=$(psql -h "$DB_HOST" -U "$DB_USER" -t -c "
|
||||
SELECT pg_size_pretty(pg_database.datsize)
|
||||
FROM pg_database
|
||||
WHERE datname = '$DB_NAME';
|
||||
")
|
||||
|
||||
log_info "База данных: $DB_NAME"
|
||||
log_info "Размер БД: $DB_SIZE"
|
||||
log_info "Файл резервной копии: $BACKUP_FILE"
|
||||
|
||||
# Создание резервной копии
|
||||
echo ""
|
||||
echo "⏳ Выполнение резервной копии..."
|
||||
|
||||
if pg_dump -h "$DB_HOST" -U "$DB_USER" "$DB_NAME" | gzip > "$BACKUP_FILE" 2>/dev/null; then
|
||||
BACKUP_SIZE=$(ls -lh "$BACKUP_FILE" | awk '{print $5}')
|
||||
log_info "Резервная копия создана успешно"
|
||||
log_info "Размер файла: $BACKUP_SIZE"
|
||||
else
|
||||
log_error "Ошибка при создании резервной копии"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Удаление старых резервных копий
|
||||
echo ""
|
||||
echo "🧹 Удаление старых резервных копий..."
|
||||
find "$BACKUP_DIR" -name "lottery_bot_*.sql.gz" -mtime +$KEEP_DAYS -exec rm -f {} \;
|
||||
log_info "Очистка завершена (хранятся копии за последние $KEEP_DAYS дней)"
|
||||
|
||||
# Статистика
|
||||
echo ""
|
||||
echo "📊 Статистика резервных копий:"
|
||||
TOTAL_SIZE=$(du -sh "$BACKUP_DIR" | awk '{print $1}')
|
||||
COUNT=$(ls -1 "$BACKUP_DIR"/lottery_bot_*.sql.gz 2>/dev/null | wc -l)
|
||||
log_info "Всего резервных копий: $COUNT"
|
||||
log_info "Общий размер: $TOTAL_SIZE"
|
||||
|
||||
# Информация о последних копиях
|
||||
echo ""
|
||||
echo "📋 Последние 5 резервных копий:"
|
||||
ls -1t "$BACKUP_DIR"/lottery_bot_*.sql.gz 2>/dev/null | head -5 | while read file; do
|
||||
size=$(ls -lh "$file" | awk '{print $5}')
|
||||
name=$(basename "$file")
|
||||
echo " • $name ($size)"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
log_info "Резервная копия завершена!"
|
||||
|
||||
# Дополнительная информация
|
||||
echo ""
|
||||
echo "💡 Советы:"
|
||||
echo " • Важные копии загружайте на облако"
|
||||
echo " • Тестируйте восстановление из копий"
|
||||
echo " • Добавьте в crontab для автоматизации:"
|
||||
echo " 0 3 * * * $PWD/scripts/backup_db.sh"
|
||||
echo ""
|
||||
134
scripts/check_db.py
Normal file
134
scripts/check_db.py
Normal file
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Скрипт для проверки и инициализации БД перед запуском бота
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Добавляем путь к проекту
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from src.core.database import engine, async_session_maker, Base
|
||||
from src.core.models import User, Lottery, Participation, Winner, Account
|
||||
from sqlalchemy import text, inspect, select
|
||||
import logging
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def check_db_connection():
|
||||
"""Проверка подключения к БД"""
|
||||
logger.info("🔍 Проверка подключения к БД...")
|
||||
try:
|
||||
async with async_session_maker() as session:
|
||||
result = await session.execute(text("SELECT 1"))
|
||||
logger.info("✅ Подключение к БД успешно")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Ошибка подключения к БД: {e}")
|
||||
return False
|
||||
|
||||
|
||||
async def check_tables():
|
||||
"""Проверка наличия таблиц"""
|
||||
logger.info("📊 Проверка таблиц БД...")
|
||||
|
||||
async with engine.begin() as conn:
|
||||
inspector = inspect(conn)
|
||||
tables = inspector.get_table_names()
|
||||
|
||||
required_tables = ['users', 'lotteries', 'participations', 'winners', 'accounts']
|
||||
|
||||
missing_tables = [t for t in required_tables if t not in tables]
|
||||
|
||||
if missing_tables:
|
||||
logger.warning(f"⚠️ Отсутствуют таблицы: {', '.join(missing_tables)}")
|
||||
return False, missing_tables
|
||||
else:
|
||||
logger.info(f"✅ Все необходимые таблицы найдены: {', '.join(required_tables)}")
|
||||
return True, []
|
||||
|
||||
|
||||
async def create_tables():
|
||||
"""Создание таблиц БД"""
|
||||
logger.info("📝 Создание таблиц БД...")
|
||||
try:
|
||||
async with engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
logger.info("✅ Таблицы созданы успешно")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Ошибка при создании таблиц: {e}")
|
||||
return False
|
||||
|
||||
|
||||
async def check_data():
|
||||
"""Проверка наличия данных"""
|
||||
logger.info("📈 Проверка данных в БД...")
|
||||
|
||||
async with async_session_maker() as session:
|
||||
users_count = await session.execute(select(User))
|
||||
users_count = len(users_count.scalars().all())
|
||||
|
||||
lotteries_count = await session.execute(select(Lottery))
|
||||
lotteries_count = len(lotteries_count.scalars().all())
|
||||
|
||||
logger.info(f"👥 Пользователей: {users_count}")
|
||||
logger.info(f"🎲 Розыгрышей: {lotteries_count}")
|
||||
|
||||
return {
|
||||
'users': users_count,
|
||||
'lotteries': lotteries_count
|
||||
}
|
||||
|
||||
|
||||
async def main():
|
||||
"""Главная функция"""
|
||||
logger.info("=" * 60)
|
||||
logger.info("🔧 Проверка и инициализация БД")
|
||||
logger.info("=" * 60)
|
||||
|
||||
# Шаг 1: Проверка подключения
|
||||
if not await check_db_connection():
|
||||
logger.error("❌ Не удалось подключиться к БД. Проверьте переменную DATABASE_URL")
|
||||
return False
|
||||
|
||||
# Шаг 2: Проверка таблиц
|
||||
tables_exist, missing_tables = await check_tables()
|
||||
|
||||
if not tables_exist:
|
||||
logger.info("🔄 Создание отсутствующих таблиц...")
|
||||
if not await create_tables():
|
||||
logger.error("❌ Не удалось создать таблицы")
|
||||
return False
|
||||
logger.info("✅ Таблицы созданы")
|
||||
|
||||
# Шаг 3: Проверка данных
|
||||
data = await check_data()
|
||||
|
||||
# Итоговая информация
|
||||
logger.info("")
|
||||
logger.info("=" * 60)
|
||||
logger.info("✅ БД готова к работе!")
|
||||
logger.info("=" * 60)
|
||||
logger.info("")
|
||||
logger.info("📋 Информация о БД:")
|
||||
logger.info(f" 👥 Пользователей: {data['users']}")
|
||||
logger.info(f" 🎲 Розыгрышей: {data['lotteries']}")
|
||||
logger.info("")
|
||||
logger.info("🚀 Вы можете запустить бота командой:")
|
||||
logger.info(" python3 main.py")
|
||||
logger.info("")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = asyncio.run(main())
|
||||
sys.exit(0 if success else 1)
|
||||
53
scripts/deploy_and_run.sh
Normal file
53
scripts/deploy_and_run.sh
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
# Быстрый запуск: deploy_and_run.sh
|
||||
# Выполняет развертывание и запуск бота одной командой
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Lottery Bot - Быстрое развертывание и запуск"
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
|
||||
# Проверка .env
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "❌ Файл .env не найден!"
|
||||
echo ""
|
||||
echo "Создайте .env файл с содержимым:"
|
||||
echo "────────────────────────────────────────────"
|
||||
cat << 'EOF'
|
||||
BOT_TOKEN=your_bot_token
|
||||
DATABASE_URL=postgresql://trevor:password@localhost:5432/lottery_bot
|
||||
ADMIN_IDS=123456789
|
||||
LOG_LEVEL=INFO
|
||||
EOF
|
||||
echo "────────────────────────────────────────────"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Файл .env найден"
|
||||
|
||||
# Создание виртуального окружения
|
||||
if [ ! -d "venv" ]; then
|
||||
echo "📦 Создание виртуального окружения..."
|
||||
python3 -m venv venv
|
||||
fi
|
||||
|
||||
# Активация
|
||||
source venv/bin/activate
|
||||
|
||||
# Установка dependencies
|
||||
echo "📚 Установка dependencies..."
|
||||
pip3 install -q --upgrade pip
|
||||
pip3 install -q -r requirements.txt
|
||||
|
||||
# Проверка БД
|
||||
echo "🗄️ Проверка и инициализация БД..."
|
||||
python3 scripts/check_db.py
|
||||
|
||||
# Запуск бота
|
||||
echo ""
|
||||
echo "🤖 Запуск бота..."
|
||||
echo "=================================================="
|
||||
echo ""
|
||||
python3 main.py
|
||||
172
scripts/deploy_server.sh
Normal file
172
scripts/deploy_server.sh
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/bin/bash
|
||||
# Скрипт развертывания lottery_bot на сервере
|
||||
# Использование: ./deploy_server.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔧 ============================================"
|
||||
echo "🔧 Развертывание Lottery Bot на сервер"
|
||||
echo "🔧 ============================================"
|
||||
echo ""
|
||||
|
||||
# Цвета для вывода
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Функция для вывода сообщений
|
||||
log_info() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# Проверка переменных окружения
|
||||
if [ -z "$DATABASE_URL" ]; then
|
||||
log_error "DATABASE_URL не установлен в .env"
|
||||
echo "Пример: export DATABASE_URL='postgresql://user:password@host:5432/lottery_bot'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$BOT_TOKEN" ]; then
|
||||
log_error "BOT_TOKEN не установлен в .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_info "Переменные окружения проверены"
|
||||
|
||||
# 1. Проверка зависимостей
|
||||
echo ""
|
||||
echo "📦 Проверка зависимостей..."
|
||||
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
log_error "Python 3 не установлен"
|
||||
exit 1
|
||||
fi
|
||||
log_info "Python 3 найден: $(python3 --version)"
|
||||
|
||||
if ! command -v pip3 &> /dev/null; then
|
||||
log_error "pip3 не установлен"
|
||||
exit 1
|
||||
fi
|
||||
log_info "pip3 установлен"
|
||||
|
||||
# 2. Создание виртуального окружения
|
||||
echo ""
|
||||
echo "🐍 Подготовка виртуального окружения..."
|
||||
|
||||
if [ ! -d "venv" ]; then
|
||||
log_info "Создание виртуального окружения..."
|
||||
python3 -m venv venv
|
||||
else
|
||||
log_warn "Виртуальное окружение уже существует"
|
||||
fi
|
||||
|
||||
# Активируем виртуальное окружение
|
||||
source venv/bin/activate
|
||||
log_info "Виртуальное окружение активировано"
|
||||
|
||||
# 3. Установка зависимостей
|
||||
echo ""
|
||||
echo "📚 Установка зависимостей из requirements.txt..."
|
||||
|
||||
if [ -f "requirements.txt" ]; then
|
||||
pip3 install --upgrade pip setuptools wheel -q
|
||||
pip3 install -r requirements.txt -q
|
||||
log_info "Зависимости установлены"
|
||||
else
|
||||
log_error "requirements.txt не найден"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 4. Проверка подключения к БД
|
||||
echo ""
|
||||
echo "🗄️ Проверка подключения к базе данных..."
|
||||
|
||||
python3 << 'EOF'
|
||||
import asyncio
|
||||
from src.core.database import async_session_maker
|
||||
from sqlalchemy import text
|
||||
|
||||
async def test_db():
|
||||
try:
|
||||
async with async_session_maker() as session:
|
||||
result = await session.execute(text("SELECT 1"))
|
||||
print("✅ Подключение к БД успешно")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка подключения: {e}")
|
||||
return False
|
||||
|
||||
if not asyncio.run(test_db()):
|
||||
exit(1)
|
||||
EOF
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
log_error "Не удалось подключиться к базе данных"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 5. Запуск миграций
|
||||
echo ""
|
||||
echo "📝 Запуск миграций базы данных..."
|
||||
|
||||
if command -v alembic &> /dev/null; then
|
||||
log_info "Alembic найден, запуск миграций..."
|
||||
alembic upgrade head
|
||||
log_info "Миграции завершены"
|
||||
else
|
||||
log_warn "Alembic не найден, пропуск миграций Alembic"
|
||||
|
||||
# Используем встроенный скрипт инициализации
|
||||
if [ -f "scripts/db_setup.py" ]; then
|
||||
log_info "Использование скрипта инициализации БД..."
|
||||
python3 scripts/db_setup.py
|
||||
log_info "БД инициализирована"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 6. Проверка конфигурации
|
||||
echo ""
|
||||
echo "⚙️ Проверка конфигурации..."
|
||||
|
||||
python3 << 'EOF'
|
||||
from src.core.config import BOT_TOKEN, DATABASE_URL, ADMIN_IDS
|
||||
|
||||
print(f"✅ BOT_TOKEN загружен")
|
||||
print(f"✅ DATABASE_URL: {DATABASE_URL[:50]}...")
|
||||
print(f"✅ ADMIN_IDS: {ADMIN_IDS if ADMIN_IDS else 'Не установлены'}")
|
||||
EOF
|
||||
|
||||
log_info "Конфигурация проверена"
|
||||
|
||||
# 7. Информация о запуске
|
||||
echo ""
|
||||
echo "🚀 ============================================"
|
||||
echo "🚀 Приложение готово к запуску"
|
||||
echo "🚀 ============================================"
|
||||
echo ""
|
||||
echo "📋 Команды для запуска:"
|
||||
echo ""
|
||||
echo "Режим разработки:"
|
||||
echo " python3 main.py"
|
||||
echo ""
|
||||
echo "Производство (с systemd):"
|
||||
echo " sudo systemctl start lottery-bot"
|
||||
echo " sudo systemctl enable lottery-bot"
|
||||
echo ""
|
||||
echo "Docker:"
|
||||
echo " docker-compose up -d"
|
||||
echo ""
|
||||
echo "⚙️ Переменные окружения:"
|
||||
echo " DATABASE_URL: $(echo $DATABASE_URL | cut -c1-50)..."
|
||||
echo " BOT_TOKEN: $(echo $BOT_TOKEN | cut -c1-20)...${BOT_TOKEN: -5}"
|
||||
echo ""
|
||||
log_info "Развертывание завершено!"
|
||||
158
scripts/manage_admins.py
Normal file
158
scripts/manage_admins.py
Normal file
@@ -0,0 +1,158 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Скрипт для управления администраторами через CLI
|
||||
Используется для быстрого доступа к функциям управления админами
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Добавляем путь к проекту
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
from src.core.database import async_session_maker
|
||||
from src.core.services import UserService
|
||||
from src.core.config import ADMIN_IDS
|
||||
|
||||
|
||||
async def list_admins():
|
||||
"""Показать список всех администраторов"""
|
||||
async with async_session_maker() as session:
|
||||
from sqlalchemy import select
|
||||
from src.core.models import User
|
||||
|
||||
# Получаем всех администраторов из БД
|
||||
result = await session.execute(
|
||||
select(User).where(User.is_admin == True).order_by(User.created_at.desc())
|
||||
)
|
||||
db_admins = result.scalars().all()
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("👑 СПИСОК АДМИНИСТРАТОРОВ")
|
||||
print("="*60)
|
||||
|
||||
print("\n🔴 Главные администраторы (.env):")
|
||||
if ADMIN_IDS:
|
||||
for admin_id in ADMIN_IDS:
|
||||
print(f" • ID: {admin_id}")
|
||||
else:
|
||||
print(" Нет главных администраторов")
|
||||
|
||||
print("\n🟠 Назначенные администраторы:")
|
||||
if db_admins:
|
||||
for admin in db_admins:
|
||||
name = admin.first_name or admin.username or f"@ID_{admin.telegram_id}"
|
||||
print(f" • {name} (Telegram ID: {admin.telegram_id})")
|
||||
else:
|
||||
print(" Нет назначенных администраторов")
|
||||
|
||||
print("\n" + "="*60 + "\n")
|
||||
|
||||
|
||||
async def add_admin(telegram_id: int):
|
||||
"""Добавить администратора"""
|
||||
async with async_session_maker() as session:
|
||||
# Проверяем, существует ли пользователь
|
||||
user = await UserService.get_user_by_telegram_id(session, telegram_id)
|
||||
|
||||
if not user:
|
||||
print(f"❌ Пользователь с ID {telegram_id} не найден")
|
||||
return
|
||||
|
||||
if telegram_id in ADMIN_IDS:
|
||||
print(f"❌ ID {telegram_id} - это главный администратор (.env)")
|
||||
return
|
||||
|
||||
if user.is_admin:
|
||||
print(f"❌ Пользователь {user.first_name or user.username} уже администратор")
|
||||
return
|
||||
|
||||
# Назначаем админа
|
||||
success = await UserService.set_admin(session, telegram_id, is_admin=True)
|
||||
|
||||
if success:
|
||||
name = user.first_name or user.username or f"@ID_{telegram_id}"
|
||||
print(f"✅ {name} назначен администратором")
|
||||
else:
|
||||
print(f"❌ Ошибка при назначении администратора")
|
||||
|
||||
|
||||
async def remove_admin(telegram_id: int):
|
||||
"""Удалить администратора"""
|
||||
async with async_session_maker() as session:
|
||||
if telegram_id in ADMIN_IDS:
|
||||
print(f"❌ Нельзя удалить главного администратора (.env)")
|
||||
print(f" Для изменения отредактируйте .env")
|
||||
return
|
||||
|
||||
# Проверяем, существует ли пользователь
|
||||
user = await UserService.get_user_by_telegram_id(session, telegram_id)
|
||||
|
||||
if not user:
|
||||
print(f"❌ Пользователь с ID {telegram_id} не найден")
|
||||
return
|
||||
|
||||
if not user.is_admin:
|
||||
print(f"❌ Пользователь {user.first_name or user.username} не является администратором")
|
||||
return
|
||||
|
||||
# Удаляем админа
|
||||
success = await UserService.set_admin(session, telegram_id, is_admin=False)
|
||||
|
||||
if success:
|
||||
name = user.first_name or user.username or f"@ID_{telegram_id}"
|
||||
print(f"✅ Права администратора удалены у {name}")
|
||||
else:
|
||||
print(f"❌ Ошибка при удалении прав администратора")
|
||||
|
||||
|
||||
async def main():
|
||||
"""Главная функция"""
|
||||
if len(sys.argv) < 2:
|
||||
print("""
|
||||
Использование: python scripts/manage_admins.py <команда> [аргументы]
|
||||
|
||||
Команды:
|
||||
list - Показать список всех администраторов
|
||||
add <id> - Добавить администратора (по Telegram ID)
|
||||
remove <id> - Удалить администратора (по Telegram ID)
|
||||
|
||||
Примеры:
|
||||
python scripts/manage_admins.py list
|
||||
python scripts/manage_admins.py add 123456789
|
||||
python scripts/manage_admins.py remove 123456789
|
||||
""")
|
||||
return
|
||||
|
||||
command = sys.argv[1].lower()
|
||||
|
||||
if command == "list":
|
||||
await list_admins()
|
||||
|
||||
elif command == "add":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ Требуется указать Telegram ID")
|
||||
return
|
||||
try:
|
||||
telegram_id = int(sys.argv[2])
|
||||
await add_admin(telegram_id)
|
||||
except ValueError:
|
||||
print("❌ Telegram ID должен быть числом")
|
||||
|
||||
elif command == "remove":
|
||||
if len(sys.argv) < 3:
|
||||
print("❌ Требуется указать Telegram ID")
|
||||
return
|
||||
try:
|
||||
telegram_id = int(sys.argv[2])
|
||||
await remove_admin(telegram_id)
|
||||
except ValueError:
|
||||
print("❌ Telegram ID должен быть числом")
|
||||
|
||||
else:
|
||||
print(f"❌ Неизвестная команда: {command}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user