CLI 0.1.8/update tariff menu

This commit is contained in:
Vladless
2025-05-28 20:48:11 +03:00
parent 8e88316efd
commit 30bb953dcd
2 changed files with 59 additions and 62 deletions
+23 -25
View File
@@ -96,17 +96,17 @@ def install_rsync_if_needed():
os.system("sudo apt update && sudo apt install -y rsync")
def clean_project_dir_safe(update_buttons=False):
def clean_project_dir_safe(update_buttons=False, update_img=False):
console.print("[yellow]🧹 Очистка проекта перед обновлением...[/yellow]")
preserved_paths = {
os.path.join(PROJECT_DIR, "config.py"),
os.path.join(PROJECT_DIR, "handlers", "buttons.py"),
os.path.join(PROJECT_DIR, "handlers", "texts.py"),
os.path.join(PROJECT_DIR, "img"),
}
if not update_buttons:
preserved_paths.add(os.path.join(PROJECT_DIR, "handlers", "buttons.py"))
if not update_img:
preserved_paths.add(os.path.join(PROJECT_DIR, "img"))
for root, dirs, files in os.walk(PROJECT_DIR, topdown=False):
for file in files:
@@ -124,6 +124,8 @@ def clean_project_dir_safe(update_buttons=False):
dir_path = os.path.join(root, dir)
if os.path.abspath(dir_path) == os.path.join(PROJECT_DIR, "handlers"):
continue
if not update_img and os.path.abspath(dir_path) == os.path.join(PROJECT_DIR, "img"):
continue
try:
os.rmdir(dir_path)
except Exception:
@@ -207,18 +209,15 @@ def update_from_beta():
else:
console.print("[red]⚠️ Не удалось определить версии.[/red]")
if not Confirm.ask(
"[yellow]🔁 Подтвердите обновление Solobot с ветки DEV[/yellow]"
):
if not Confirm.ask("[yellow]🔁 Подтвердите обновление Solobot с ветки DEV[/yellow]"):
return
console.print("[red]⚠️ ВНИМАНИЕ! Папка бота будет перезаписана![/red]")
if not Confirm.ask("[red]❓ Продолжить обновление?[/red]"):
return
update_buttons = Confirm.ask(
"[yellow]🔄 Обновлять файл buttons.py?[/yellow]", default=False
)
update_buttons = Confirm.ask("[yellow]🔄 Обновлять файл buttons.py?[/yellow]", default=False)
update_img = Confirm.ask("[yellow]🖼 Обновлять папку img?[/yellow]", default=False)
backup_project()
install_git_if_needed()
@@ -232,11 +231,13 @@ def update_from_beta():
return
subprocess.run(["sudo", "rm", "-rf", os.path.join(PROJECT_DIR, "venv")])
clean_project_dir_safe(update_buttons=update_buttons)
clean_project_dir_safe(update_buttons=update_buttons, update_img=update_img)
exclude_options = "--exclude=img"
exclude_options = ""
if not update_img:
exclude_options += "--exclude=img "
if not update_buttons:
exclude_options += " --exclude=handlers/buttons.py"
exclude_options += "--exclude=handlers/buttons.py "
subprocess.run(f"rsync -a {exclude_options} {TEMP_DIR}/ {PROJECT_DIR}/", shell=True)
subprocess.run(["rm", "-rf", TEMP_DIR])
@@ -259,9 +260,8 @@ def update_from_release():
if not Confirm.ask("[red]❓ Вы точно хотите продолжить?[/red]"):
return
update_buttons = Confirm.ask(
"[yellow]🔄 Обновлять файл buttons.py?[/yellow]", default=False
)
update_buttons = Confirm.ask("[yellow]🔄 Обновлять файл buttons.py?[/yellow]", default=False)
update_img = Confirm.ask("[yellow]🖼 Обновлять папку img?[/yellow]", default=False)
backup_project()
install_git_if_needed()
@@ -292,9 +292,7 @@ def update_from_release():
):
return
console.print(
f"[cyan]📥 Клонируем релиз {tag_name} во временную папку...[/cyan]"
)
console.print(f"[cyan]📥 Клонируем релиз {tag_name} во временную папку...[/cyan]")
subprocess.run(["rm", "-rf", TEMP_DIR])
subprocess.run(
f"git clone --depth 1 --branch {tag_name} {GITHUB_REPO} {TEMP_DIR}",
@@ -304,15 +302,15 @@ def update_from_release():
console.print("[red]⚠️ Начинается перезапись файлов бота![/red]")
subprocess.run(["sudo", "rm", "-rf", os.path.join(PROJECT_DIR, "venv")])
clean_project_dir_safe(update_buttons=update_buttons)
clean_project_dir_safe(update_buttons=update_buttons, update_img=update_img)
exclude_options = "--exclude=img"
exclude_options = ""
if not update_img:
exclude_options += "--exclude=img "
if not update_buttons:
exclude_options += " --exclude=handlers/buttons.py"
exclude_options += "--exclude=handlers/buttons.py "
subprocess.run(
f"rsync -a {exclude_options} {TEMP_DIR}/ {PROJECT_DIR}/", shell=True
)
subprocess.run(f"rsync -a {exclude_options} {TEMP_DIR}/ {PROJECT_DIR}/", shell=True)
subprocess.run(["rm", "-rf", TEMP_DIR])
fix_permissions()
@@ -350,7 +348,7 @@ def show_update_menu():
def show_menu():
table = Table(
title="Solobot CLI v0.1.7", title_style="bold magenta", header_style="bold blue"
title="Solobot CLI v0.1.8", title_style="bold magenta", header_style="bold blue"
)
table.add_column("", justify="center", style="cyan", no_wrap=True)
table.add_column("Операция", style="white")
+36 -37
View File
@@ -314,26 +314,8 @@ async def view_tariff(
await callback.message.edit_text("❌ Тариф не найден.")
return
traffic_text = (
f"{tariff.traffic_limit} ГБ" if tariff.traffic_limit else "Безлимит"
)
device_text = (
f"{tariff.device_limit}" if tariff.device_limit is not None else "Безлимит"
)
text = (
f"<b>📄 Тариф: {tariff.name}</b>\n\n"
f"📁 Группа: <code>{tariff.group_code}</code>\n"
f"📅 Длительность: <b>{tariff.duration_days} дней</b>\n"
f"💰 Стоимость: <b>{tariff.price_rub}₽</b>\n"
f"📦 Трафик: <b>{traffic_text}</b>\n"
f"📱 Устройств: <b>{device_text}</b>\n"
f"{'✅ Активен' if tariff.is_active else '⛔ Отключен'}"
)
await callback.message.edit_text(
text, reply_markup=build_single_tariff_kb(tariff_id)
)
text, markup = render_tariff_card(tariff)
await callback.message.edit_text(text=text, reply_markup=markup)
@router.callback_query(
@@ -452,9 +434,7 @@ async def apply_edit(message: Message, state: FSMContext, session: AsyncSession)
num = int(value)
if num < 0:
raise ValueError
if field == "traffic_limit":
value = num if num > 0 else None
elif field == "device_limit":
if field in ["traffic_limit", "device_limit"]:
value = num if num > 0 else None
else:
value = num
@@ -467,29 +447,27 @@ async def apply_edit(message: Message, state: FSMContext, session: AsyncSession)
await session.commit()
await state.clear()
await message.answer("✅ Тариф успешно обновлён.")
text, markup = render_tariff_card(tariff)
await message.answer(text=text, reply_markup=markup)
@router.callback_query(F.data.startswith("toggle_active|"), IsAdminFilter())
async def toggle_tariff_status(callback: CallbackQuery, session):
async def toggle_tariff_status(callback: CallbackQuery, session: AsyncSession):
tariff_id = int(callback.data.split("|")[1])
row = await session.fetchrow(
"SELECT is_active FROM tariffs WHERE id = $1", tariff_id
)
if not row:
result = await session.execute(select(Tariff).where(Tariff.id == tariff_id))
tariff = result.scalar_one_or_none()
if not tariff:
await callback.message.edit_text("❌ Тариф не найден.")
return
new_status = not row["is_active"]
await session.execute(
"UPDATE tariffs SET is_active = $1, updated_at = NOW() WHERE id = $2",
new_status,
tariff_id,
)
tariff.is_active = not tariff.is_active
await session.commit()
status_text = "✅ Тариф активирован." if new_status else "⛔ Тариф отключён."
await callback.message.edit_text(status_text)
text, markup = render_tariff_card(tariff)
await callback.message.edit_text(text=text, reply_markup=markup)
@router.callback_query(
@@ -505,3 +483,24 @@ async def start_tariff_creation_existing_group(
f"📦 Добавление нового тарифа в группу <code>{group_code}</code>\n\n📝 Введите <b>название тарифа</b>:",
reply_markup=build_cancel_kb(),
)
def render_tariff_card(tariff: Tariff) -> tuple[str, InlineKeyboardMarkup]:
traffic_text = (
f"{tariff.traffic_limit} ГБ" if tariff.traffic_limit else "Безлимит"
)
device_text = (
f"{tariff.device_limit}" if tariff.device_limit is not None else "Безлимит"
)
text = (
f"<b>📄 Тариф: {tariff.name}</b>\n\n"
f"📁 Группа: <code>{tariff.group_code}</code>\n"
f"📅 Длительность: <b>{tariff.duration_days} дней</b>\n"
f"💰 Стоимость: <b>{tariff.price_rub}₽</b>\n"
f"📦 Трафик: <b>{traffic_text}</b>\n"
f"📱 Устройств: <b>{device_text}</b>\n"
f"{'✅ Активен' if tariff.is_active else '⛔ Отключен'}"
)
return text, build_single_tariff_kb(tariff.id)