importer 3x-ui/CLI update/upload file/clearing logs
This commit is contained in:
@@ -75,7 +75,6 @@ async def edit_key_by_email(
|
||||
session: AsyncSession = Depends(get_session),
|
||||
admin: Admin = Depends(verify_admin_token),
|
||||
):
|
||||
logger.info(f"[API] edit_key_by_email called for email={email}, payload={key_update.dict(exclude_unset=False)}")
|
||||
|
||||
result = await session.execute(select(Key).where(Key.email == email))
|
||||
db_key = result.scalar_one_or_none()
|
||||
@@ -96,7 +95,6 @@ async def edit_key_by_email(
|
||||
|
||||
try:
|
||||
new_expiry_time = db_key.expiry_time
|
||||
logger.info(f"[API] renew_key_in_cluster new_expiry_time (ms) = {new_expiry_time}")
|
||||
await renew_key_in_cluster(
|
||||
cluster_id=db_key.server_id,
|
||||
email=db_key.email,
|
||||
@@ -123,7 +121,6 @@ async def create_key_api(
|
||||
session: AsyncSession = Depends(get_session),
|
||||
admin: Admin = Depends(verify_admin_token),
|
||||
):
|
||||
logger.info(f"[API] Запрос на создание ключа: {payload.dict()}")
|
||||
|
||||
try:
|
||||
await create_key_on_cluster(
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import os
|
||||
import subprocess
|
||||
import traceback
|
||||
import time
|
||||
from functools import lru_cache
|
||||
|
||||
from aiogram import Bot, Dispatcher
|
||||
from aiogram.client.default import DefaultBotProperties
|
||||
@@ -21,59 +23,61 @@ storage = MemoryStorage()
|
||||
dp = Dispatcher(bot=bot, storage=storage)
|
||||
|
||||
|
||||
def get_git_commit_number() -> str:
|
||||
_last_check_time = 0
|
||||
_last_git_info = ""
|
||||
|
||||
|
||||
def _get_git_commit_number_uncached() -> str:
|
||||
repo_url = "https://github.com/Vladless/Solo_bot"
|
||||
cwd = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
if not os.path.isdir(os.path.join(cwd, ".git")):
|
||||
cwd = "/root/Prod/Solo_bot"
|
||||
logger.info(f"[Git] .git не найден в текущем каталоге, используем {cwd}")
|
||||
|
||||
env = os.environ.copy()
|
||||
env["GIT_DIR"] = os.path.join(cwd, ".git")
|
||||
env["GIT_WORK_TREE"] = cwd
|
||||
|
||||
try:
|
||||
local_number = (
|
||||
subprocess.check_output(["git", "rev-list", "--count", "HEAD"], cwd=cwd, env=env).decode().strip()
|
||||
)
|
||||
|
||||
local_hash = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=cwd, env=env).decode().strip()
|
||||
|
||||
local_number = subprocess.check_output(
|
||||
["git", "rev-list", "--count", "HEAD"], cwd=cwd, env=env
|
||||
).decode().strip()
|
||||
local_hash = subprocess.check_output(
|
||||
["git", "rev-parse", "HEAD"], cwd=cwd, env=env
|
||||
).decode().strip()
|
||||
try:
|
||||
branch = (
|
||||
subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd, env=env).decode().strip()
|
||||
)
|
||||
|
||||
branch = subprocess.check_output(
|
||||
["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd, env=env
|
||||
).decode().strip()
|
||||
if branch == "HEAD":
|
||||
describe = (
|
||||
subprocess.check_output(
|
||||
["git", "describe", "--tags", "--exact-match"], cwd=cwd, env=env, stderr=subprocess.DEVNULL
|
||||
)
|
||||
.decode()
|
||||
.strip()
|
||||
)
|
||||
|
||||
if describe.startswith("v") or "release" in describe.lower():
|
||||
branch = "main"
|
||||
else:
|
||||
branch = "dev"
|
||||
describe = subprocess.check_output(
|
||||
["git", "describe", "--tags", "--exact-match"],
|
||||
cwd=cwd,
|
||||
env=env,
|
||||
stderr=subprocess.DEVNULL,
|
||||
).decode().strip()
|
||||
branch = "main" if describe.startswith("v") or "release" in describe.lower() else "dev"
|
||||
except Exception:
|
||||
branch = "dev"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[Git] Ошибка при получении локального коммита: {e}")
|
||||
return f"\n(Требуется обновление через CLI (команда <code>sudo solobot</code>): {e})"
|
||||
|
||||
try:
|
||||
subprocess.check_output(["git", "fetch", "origin"], cwd=cwd, env=env)
|
||||
remote_commit = subprocess.check_output(
|
||||
["git", "ls-remote", "origin", f"refs/heads/{branch}"], cwd=cwd, env=env
|
||||
).decode()
|
||||
remote_hash = remote_commit.split()[0]
|
||||
|
||||
remote_number = (
|
||||
subprocess.check_output(["git", "rev-list", "--count", remote_hash], cwd=cwd, env=env).decode().strip()
|
||||
)
|
||||
remote_number = subprocess.check_output(
|
||||
["git", "rev-list", "--count", remote_hash], cwd=cwd, env=env
|
||||
).decode().strip()
|
||||
|
||||
if local_hash == remote_hash:
|
||||
logger.info("[Git] Локальная версия актуальна")
|
||||
return "\n(Актуальная версия)"
|
||||
|
||||
return (
|
||||
@@ -81,12 +85,28 @@ def get_git_commit_number() -> str:
|
||||
f"#{local_number}</a> / actual commit "
|
||||
f'<a href="{repo_url}/commit/{remote_hash}">#{remote_number}</a>)'
|
||||
)
|
||||
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.error(f"[Git] Ошибка при получении удалённого коммита: {e}")
|
||||
return "\n(Требуется обновление через CLI, команда <code>sudo solobot</code>)"
|
||||
|
||||
|
||||
version = f"v4.4-preRelease{get_git_commit_number()}"
|
||||
@lru_cache(maxsize=1)
|
||||
def _cached_git_info() -> str:
|
||||
return _get_git_commit_number_uncached()
|
||||
|
||||
|
||||
def get_git_commit_number() -> str:
|
||||
global _last_check_time, _last_git_info
|
||||
now = time.time()
|
||||
if now - _last_check_time > 3600:
|
||||
_last_check_time = now
|
||||
_cached_git_info.cache_clear()
|
||||
_last_git_info = _cached_git_info()
|
||||
return _last_git_info
|
||||
|
||||
|
||||
def get_version() -> str:
|
||||
return f"v4.4-preRelease{get_git_commit_number()}"
|
||||
|
||||
|
||||
dp.message.filter(IsPrivateFilter())
|
||||
|
||||
+54
-38
@@ -2,6 +2,7 @@ import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
import requests
|
||||
|
||||
@@ -69,18 +70,51 @@ def backup_project():
|
||||
console.print(f"[green]✅ Бэкап сохранён в: {BACK_DIR}[/green]")
|
||||
|
||||
|
||||
def auto_update_cli():
|
||||
"""Обновляет CLI, если отличается от последней версии. Перезапускает при необходимости."""
|
||||
console.print("[yellow]🔄 Проверка обновлений CLI...[/yellow]")
|
||||
try:
|
||||
url = "https://raw.githubusercontent.com/Vladless/Solo_bot/dev/cli_launcher.py"
|
||||
response = requests.get(url, timeout=10)
|
||||
if response.status_code != 200:
|
||||
console.print("[red]⚠️ Не удалось получить обновление CLI[/red]")
|
||||
return
|
||||
|
||||
latest_text = response.text
|
||||
current_path = os.path.realpath(__file__)
|
||||
with open(current_path, encoding="utf-8") as f:
|
||||
current_text = f.read()
|
||||
|
||||
if current_text != latest_text:
|
||||
console.print("[green]🆕 Доступна новая версия CLI. Обновляю...[/green]")
|
||||
with open(current_path, "w", encoding="utf-8") as f:
|
||||
f.write(latest_text)
|
||||
os.chmod(current_path, 0o755)
|
||||
console.print("[green]✅ CLI обновлён. Перезапуск...[/green]")
|
||||
os.execv(sys.executable, [sys.executable, current_path])
|
||||
else:
|
||||
console.print("[green]✅ CLI уже актуален[/green]")
|
||||
except Exception as e:
|
||||
console.print(f"[red]❌ Ошибка при автообновлении CLI: {e}[/red]")
|
||||
|
||||
|
||||
def fix_permissions():
|
||||
"""Устанавливает корректные права на файлы проекта"""
|
||||
console.print("[yellow]🔧 Устанавливаю права на файлы...[/yellow]")
|
||||
try:
|
||||
user = os.getenv("SUDO_USER") or os.getenv("USER")
|
||||
if user:
|
||||
subprocess.run(["sudo", "chown", "-R", f"{user}:{user}", PROJECT_DIR], check=True)
|
||||
|
||||
if os.geteuid() != 0:
|
||||
console.print("[yellow]⚠️ Некоторые действия могут требовать прав администратора (sudo)[/yellow]")
|
||||
|
||||
try:
|
||||
stat_info = os.stat(PROJECT_DIR)
|
||||
uid = stat_info.st_uid
|
||||
user = subprocess.check_output(["id", "-nu", str(uid)], text=True).strip()
|
||||
|
||||
subprocess.run(["sudo", "chown", "-R", f"{user}:{user}", PROJECT_DIR], check=True)
|
||||
subprocess.run(["sudo", "chmod", "-R", "u=rwX,go=rX", PROJECT_DIR], check=True)
|
||||
|
||||
console.print("[green]✅ Права успешно установлены[/green]")
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"[green]✅ Права установлены для пользователя {user}[/green]")
|
||||
except Exception as e:
|
||||
console.print(f"[red]❌ Ошибка при установке прав: {e}[/red]")
|
||||
|
||||
|
||||
@@ -138,19 +172,26 @@ def install_git_if_needed():
|
||||
|
||||
def install_dependencies():
|
||||
console.print("[blue]🔧 Установка зависимостей...[/blue]")
|
||||
|
||||
python312_path = shutil.which("python3.12")
|
||||
if not python312_path:
|
||||
console.print("[red]❌ Не найден python3.12 в системе[/red]")
|
||||
console.print("[yellow]📦 Установите Python 3.12: sudo apt install python3.12 python3.12-venv[/yellow]")
|
||||
sys.exit(1)
|
||||
|
||||
with console.status("[bold green]Устанавливаются зависимости...[/bold green]"):
|
||||
try:
|
||||
if not os.path.exists("venv"):
|
||||
console.print("[yellow]⚠️ Виртуальное окружение не найдено. Создаю...[/yellow]")
|
||||
subprocess.run("python3 -m venv venv", shell=True, check=True)
|
||||
console.print("[yellow]⚠️ Виртуальное окружение не найдено. Создаю через python3.12...[/yellow]")
|
||||
subprocess.run(f"{python312_path} -m venv venv", shell=True, check=True)
|
||||
|
||||
subprocess.run(
|
||||
"bash -c 'source venv/bin/activate && pip install -r requirements.txt'",
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
except subprocess.CalledProcessError:
|
||||
console.print("[red]❌ Ошибка при установке зависимостей.[/red]")
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"[red]❌ Ошибка при установке зависимостей: {e}[/red]")
|
||||
|
||||
|
||||
def restart_service():
|
||||
@@ -189,7 +230,6 @@ def get_remote_version(branch="main"):
|
||||
|
||||
|
||||
def update_from_beta():
|
||||
update_cli_launcher()
|
||||
local_version = get_local_version()
|
||||
remote_version = get_remote_version(branch="dev")
|
||||
|
||||
@@ -246,7 +286,6 @@ def update_from_beta():
|
||||
|
||||
|
||||
def update_from_release():
|
||||
update_cli_launcher()
|
||||
if not Confirm.ask("[yellow]🔁 Подтвердите обновление Solobot до одного из последних релизов[/yellow]"):
|
||||
return
|
||||
|
||||
@@ -340,7 +379,7 @@ def show_update_menu():
|
||||
|
||||
|
||||
def show_menu():
|
||||
table = Table(title="Solobot CLI v0.2.0", title_style="bold magenta", header_style="bold blue")
|
||||
table = Table(title="Solobot CLI v0.2.7", title_style="bold magenta", header_style="bold blue")
|
||||
table.add_column("№", justify="center", style="cyan", no_wrap=True)
|
||||
table.add_column("Операция", style="white")
|
||||
table.add_row("1", "Запустить бота (systemd)")
|
||||
@@ -350,31 +389,13 @@ def show_menu():
|
||||
table.add_row("5", "Показать логи (80 строк)")
|
||||
table.add_row("6", "Показать статус")
|
||||
table.add_row("7", "Обновить Solobot")
|
||||
table.add_row("8", "Обновить CLI лаунчер")
|
||||
table.add_row("9", "Выход")
|
||||
table.add_row("8", "Выход")
|
||||
console.print(table)
|
||||
|
||||
|
||||
def update_cli_launcher():
|
||||
"""Обновляет CLI лаунчер с dev ветки"""
|
||||
console.print("[yellow]🔄 Обновление CLI лаунчера...[/yellow]")
|
||||
try:
|
||||
url = "https://raw.githubusercontent.com/Vladless/Solo_bot/dev/cli_launcher.py"
|
||||
response = requests.get(url, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
with open(os.path.join(PROJECT_DIR, "cli_launcher.py"), "w", encoding="utf-8") as f:
|
||||
f.write(response.text)
|
||||
console.print("[green]✅ CLI лаунчер успешно обновлён[/green]")
|
||||
os.chmod(os.path.join(PROJECT_DIR, "cli_launcher.py"), 0o755)
|
||||
else:
|
||||
console.print("[red]❌ Не удалось загрузить новый CLI[/red]")
|
||||
except Exception as e:
|
||||
console.print(f"[red]❌ Ошибка при обновлении CLI: {e}[/red]")
|
||||
|
||||
|
||||
def main():
|
||||
os.chdir(PROJECT_DIR)
|
||||
auto_update_cli()
|
||||
print_logo()
|
||||
try:
|
||||
while True:
|
||||
@@ -424,11 +445,6 @@ def main():
|
||||
elif choice == "7":
|
||||
show_update_menu()
|
||||
elif choice == "8":
|
||||
if Confirm.ask("[yellow]Обновить CLI лаунчер с dev ветки?[/yellow]"):
|
||||
update_cli_launcher()
|
||||
elif choice == "9":
|
||||
if Confirm.ask("[yellow]Хотите обновить CLI перед выходом?[/yellow]"):
|
||||
update_cli_launcher()
|
||||
console.print("[bold cyan]Выход из CLI. Удачного дня![/bold cyan]")
|
||||
break
|
||||
except KeyboardInterrupt:
|
||||
|
||||
+20
-11
@@ -8,6 +8,7 @@ from itertools import cycle
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from config import USE_COUNTRY_SELECTION
|
||||
|
||||
from database.models import Key, Server, User
|
||||
|
||||
@@ -16,15 +17,23 @@ async def import_keys_from_3xui_db(db_path: str, session: AsyncSession) -> tuple
|
||||
imported = 0
|
||||
skipped = 0
|
||||
|
||||
result = await session.execute(
|
||||
select(Server.cluster_name)
|
||||
.where(Server.enabled is True, Server.panel_type == "3x-ui", Server.cluster_name.isnot(None))
|
||||
.distinct()
|
||||
)
|
||||
clusters = [row[0] for row in result.fetchall()]
|
||||
if not clusters:
|
||||
raise RuntimeError("❌ Не найдено доступных кластеров для 3x-ui")
|
||||
cluster_cycle = cycle(clusters)
|
||||
if USE_COUNTRY_SELECTION:
|
||||
result = await session.execute(
|
||||
select(Server.name)
|
||||
.where(Server.enabled == True, Server.panel_type == "3x-ui")
|
||||
)
|
||||
else:
|
||||
result = await session.execute(
|
||||
select(Server.cluster_name)
|
||||
.where(Server.enabled == True, Server.panel_type == "3x-ui", Server.cluster_name.isnot(None))
|
||||
.distinct()
|
||||
)
|
||||
|
||||
server_ids = [row[0] for row in result.fetchall()]
|
||||
if not server_ids:
|
||||
raise RuntimeError("❌ Не найдено доступных серверов или кластеров для 3x-ui")
|
||||
|
||||
server_cycle = cycle(server_ids)
|
||||
|
||||
try:
|
||||
conn = sqlite3.connect(db_path)
|
||||
@@ -58,7 +67,7 @@ async def import_keys_from_3xui_db(db_path: str, session: AsyncSession) -> tuple
|
||||
email = c.get("email")
|
||||
expiry_time = int(c.get("expiryTime") or now_ts)
|
||||
created_at = now_ts
|
||||
server_id = next(cluster_cycle)
|
||||
server_id = next(server_cycle)
|
||||
|
||||
if not tg_id or not client_id:
|
||||
continue
|
||||
@@ -112,4 +121,4 @@ async def import_keys_from_3xui_db(db_path: str, session: AsyncSession) -> tuple
|
||||
continue
|
||||
|
||||
await session.commit()
|
||||
return imported, skipped
|
||||
return imported, skipped
|
||||
@@ -130,7 +130,6 @@ async def check_tariff_exists(session: AsyncSession, tariff_id: int):
|
||||
result = await session.execute(select(Tariff).where(Tariff.id == tariff_id, Tariff.is_active.is_(True)))
|
||||
tariff = result.scalar_one_or_none()
|
||||
if tariff:
|
||||
logger.info(f"[TARIFF] Тариф {tariff_id} найден в БД: {tariff.group_code}")
|
||||
return True
|
||||
logger.warning(f"[TARIFF] Тариф {tariff_id} не найден в БД")
|
||||
return False
|
||||
|
||||
@@ -28,13 +28,17 @@ def build_management_kb(admin_role: str) -> InlineKeyboardMarkup:
|
||||
callback_data=AdminPanelCallback(action="restart").pack(),
|
||||
)
|
||||
builder.button(
|
||||
text="🌐 Сменить домен",
|
||||
text="🌐 Сменить домен подписок",
|
||||
callback_data=AdminPanelCallback(action="change_domain").pack(),
|
||||
)
|
||||
builder.button(
|
||||
text="🔑 Восстановить пробники",
|
||||
callback_data=AdminPanelCallback(action="restore_trials").pack(),
|
||||
)
|
||||
builder.button(
|
||||
text="📤 Загрузить файл",
|
||||
callback_data=AdminPanelCallback(action="upload_file").pack(),
|
||||
)
|
||||
maintenance_text = "🛠️ Выключить тех. работы" if maintenance.maintenance_mode else "🛠️ Включить тех. работы"
|
||||
builder.button(
|
||||
text=maintenance_text,
|
||||
@@ -54,11 +58,11 @@ def build_database_kb() -> InlineKeyboardMarkup:
|
||||
callback_data=AdminPanelCallback(action="backups").pack(),
|
||||
)
|
||||
builder.button(
|
||||
text="♻️ Восстановить БД",
|
||||
text="♻️ Восстановить БД из бэкапа",
|
||||
callback_data=AdminPanelCallback(action="restore_db").pack(),
|
||||
)
|
||||
builder.button(
|
||||
text="📤 Получить данные БД",
|
||||
text="📤 Получить данные БД из панели",
|
||||
callback_data=AdminPanelCallback(action="export_db").pack(),
|
||||
)
|
||||
builder.row(build_admin_back_btn())
|
||||
|
||||
@@ -54,6 +54,10 @@ class Import3xuiStates(StatesGroup):
|
||||
waiting_for_file = State()
|
||||
|
||||
|
||||
class FileUploadState(StatesGroup):
|
||||
waiting_for_file = State()
|
||||
|
||||
|
||||
class DatabaseState(StatesGroup):
|
||||
waiting_for_backup_file = State()
|
||||
|
||||
@@ -92,7 +96,6 @@ async def request_new_domain(callback_query: CallbackQuery, state: FSMContext):
|
||||
async def process_new_domain(message: Message, state: FSMContext, session: AsyncSession):
|
||||
"""Обновляет домен в таблице keys."""
|
||||
new_domain = message.text.strip()
|
||||
logger.info(f"[DomainChange] Новый домен, введённый администратором: '{new_domain}'")
|
||||
|
||||
if not new_domain or " " in new_domain or not new_domain.replace(".", "").isalnum():
|
||||
logger.warning("[DomainChange] Некорректный домен")
|
||||
@@ -103,7 +106,6 @@ async def process_new_domain(message: Message, state: FSMContext, session: Async
|
||||
return
|
||||
|
||||
new_domain_url = f"https://{new_domain}"
|
||||
logger.info(f"[DomainChange] Новый домен с протоколом: '{new_domain_url}'")
|
||||
|
||||
try:
|
||||
stmt = (
|
||||
@@ -326,8 +328,6 @@ async def restore_database(message: Message, state: FSMContext, bot: Bot):
|
||||
if signature == b"PGDMP":
|
||||
is_custom_dump = True
|
||||
|
||||
logger.info(f"[Restore] Определён формат: {'custom' if is_custom_dump else 'plain'}")
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
"sudo",
|
||||
@@ -645,6 +645,46 @@ async def handle_resync_after_import(callback: CallbackQuery, session: AsyncSess
|
||||
|
||||
await callback.message.edit_text(
|
||||
f"🔁 Перевыпуск завершён:\n✅ Успешно: <b>{success}</b>\n❌ Ошибки: <b>{failed}</b>",
|
||||
parse_mode="HTML",
|
||||
reply_markup=build_back_to_db_menu(),
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(AdminPanelCallback.filter(F.action == "upload_file"))
|
||||
async def prompt_for_file_upload(callback: CallbackQuery, state: FSMContext):
|
||||
await callback.message.edit_text(
|
||||
"📤 <b>Загрузка файла</b>\n\n"
|
||||
"Вы можете заменить файл в корневой директории бота.\n\n"
|
||||
"📁 <b>Отправьте файл с таким же именем и расширением</b>, "
|
||||
"как у уже существующего файла. Он будет автоматически заменён.",
|
||||
reply_markup=build_admin_back_kb("management"),
|
||||
)
|
||||
await state.set_state(FileUploadState.waiting_for_file)
|
||||
|
||||
|
||||
|
||||
@router.message(FileUploadState.waiting_for_file, F.document)
|
||||
async def handle_admin_file_upload(message: Message, state: FSMContext):
|
||||
document = message.document
|
||||
file_name = document.file_name
|
||||
|
||||
if not file_name or "." not in file_name:
|
||||
await message.answer("❌ У файла должно быть имя с расширением.")
|
||||
return
|
||||
|
||||
dest_path = os.path.abspath(f"./{file_name}")
|
||||
|
||||
try:
|
||||
await message.bot.download(document, destination=dest_path)
|
||||
await message.answer(
|
||||
f"✅ Файл <code>{file_name}</code> успешно загружен и заменён.\n\n"
|
||||
"🔄 <b>Перезагрузите бота, чтобы изменения вступили в силу.</b>",
|
||||
reply_markup=build_admin_back_kb("management"),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"[Upload File] Ошибка при загрузке файла {file_name}: {e}")
|
||||
await message.answer(
|
||||
f"❌ Не удалось сохранить файл: {e}",
|
||||
reply_markup=build_admin_back_kb("management"),
|
||||
)
|
||||
await state.clear()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from aiogram.types import CallbackQuery, Message
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot import version
|
||||
from bot import get_version
|
||||
from database.models import Admin
|
||||
from filters.admin import IsAdminFilter
|
||||
from logger import logger
|
||||
@@ -19,7 +19,7 @@ router = Router()
|
||||
|
||||
@router.callback_query(AdminPanelCallback.filter(F.action == "admin"), IsAdminFilter())
|
||||
async def handle_admin_callback_query(callback_query: CallbackQuery, state: FSMContext, session: AsyncSession):
|
||||
text = f"🤖 Панель администратора\n\nВерсия бота:\n<blockquote>{version}</blockquote>"
|
||||
text = f"🤖 Панель администратора\n\nВерсия бота:\n<blockquote>{get_version()}</blockquote>"
|
||||
|
||||
await state.clear()
|
||||
|
||||
@@ -60,7 +60,7 @@ async def handle_admin_callback_query_simple(callback_query: CallbackQuery, stat
|
||||
|
||||
@router.message(Command("admin"), IsAdminFilter())
|
||||
async def handle_admin_message(message: Message, state: FSMContext, session: AsyncSession):
|
||||
text = f"🤖 Панель администратора\n\nВерсия бота:\n<blockquote>{version}</blockquote>"
|
||||
text = f"🤖 Панель администратора\n\nВерсия бота:\n<blockquote>{get_version()}</blockquote>"
|
||||
|
||||
await state.clear()
|
||||
|
||||
|
||||
@@ -98,7 +98,6 @@ async def process_callback_unfreeze_subscription_confirm(callback_query: Callbac
|
||||
|
||||
now_ms = int(time.time() * 1000)
|
||||
leftover = record["expiry_time"]
|
||||
logger.info(f"[Unfreeze Debug] expiry_time из БД: {leftover}")
|
||||
if leftover < 0:
|
||||
leftover = 0
|
||||
new_expiry_time = now_ms + leftover
|
||||
|
||||
@@ -70,7 +70,6 @@ async def process_callback_view_profile(
|
||||
username = "Пользователь"
|
||||
|
||||
image_path = os.path.join("img", "profile.jpg")
|
||||
logger.info(f"Переход в профиль. Используется изображение: {image_path}")
|
||||
|
||||
key_count = await get_key_count(session, chat_id)
|
||||
balance = await get_balance(session, chat_id) or 0
|
||||
|
||||
@@ -300,7 +300,6 @@ async def handle_utm_link(
|
||||
|
||||
async def show_start_menu(message: Message, admin: bool, session: AsyncSession):
|
||||
"""Функция для отображения стандартного меню через редактирование сообщения."""
|
||||
logger.info(f"Показываю главное меню для пользователя {message.chat.id}")
|
||||
|
||||
image_path = os.path.join("img", "pic.jpg")
|
||||
builder = InlineKeyboardBuilder()
|
||||
@@ -308,7 +307,6 @@ async def show_start_menu(message: Message, admin: bool, session: AsyncSession):
|
||||
trial_status = None
|
||||
if session is not None:
|
||||
trial_status = await get_trial(session, message.chat.id)
|
||||
logger.info(f"Trial status для {message.chat.id}: {trial_status}")
|
||||
else:
|
||||
logger.warning(f"Сессия базы данных отсутствует, пропускаем проверку триала для {message.chat.id}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user