version 1.4.2: фикс кнопок бота и pip-таймауты
- bot.py: лимит 100 кнопок — имена пользователей вместо 2 кнопок на каждого, user_ меню - install-panel.sh: --retries 1, --timeout 5, timeout 30 на pip, зеркало aliyun - install-bot.sh: те же таймауты и зеркала - README: обновлён
This commit is contained in:
@@ -92,10 +92,8 @@ curl -Ls https://raw.githubusercontent.com/grendervilll/mitactl/main/bootstrap.s
|
|||||||
- [x] Защита сессий: динамический Secure cookie, in-memory rate limiter
|
- [x] Защита сессий: динамический Secure cookie, in-memory rate limiter
|
||||||
- [x] Bootstrap-установщик (одна команда)
|
- [x] Bootstrap-установщик (одна команда)
|
||||||
- [x] Мониторинг сервера: CPU, RAM, диск на дашборде (автообновление каждые 2 сек)
|
- [x] Мониторинг сервера: CPU, RAM, диск на дашборде (автообновление каждые 2 сек)
|
||||||
- [x] Telegram-бот: inline-кнопки, создание/удаление/WARP/дашборд, конфиг/Karing, fail2ban-безопасность
|
- [x] Telegram-бот: inline-кнопки, меню пользователя с конфигом/Karing, create/delete/WARP/дашборд/безопасность
|
||||||
- [x] Установка бота: веб-панель, CLI, полный установщик; автоопределение Telegram ID через API
|
- [x] Установка: веб-панель, CLI, полный установщик; авто-ID через API; venv + зеркала PyPI + fallback на apt
|
||||||
- [x] Бот в venv (обход externally-managed), авто-SSL, SSH-туннель, обновление из GitHub
|
|
||||||
- [x] Fallback-установка: зеркала PyPI + таймауты → apt при недоступности pip
|
|
||||||
|
|
||||||
### ⬜ Запланировано
|
### ⬜ Запланировано
|
||||||
|
|
||||||
|
|||||||
@@ -202,10 +202,18 @@ async def show_users(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
mon = f"{s.get('month_mb', 0):.1f} МБ" if s.get("month_mb") else "—"
|
mon = f"{s.get('month_mb', 0):.1f} МБ" if s.get("month_mb") else "—"
|
||||||
ename = escape_md(name)
|
ename = escape_md(name)
|
||||||
lines.append(f"{o} {ename} {w} день: {day} нед: {wk} мес: {mon}")
|
lines.append(f"{o} {ename} {w} день: {day} нед: {wk} мес: {mon}")
|
||||||
user_buttons.append([
|
# Каждый пользователь — одна кнопка, открывает меню с конфигом и Karing
|
||||||
InlineKeyboardButton(f"📋 {name}", callback_data=f"config_{name}"),
|
user_buttons.append([InlineKeyboardButton(
|
||||||
InlineKeyboardButton(f"📱 Karing", callback_data=f"karing_{name}"),
|
f"{'🟢 ' if s.get('online') else ''}{name}",
|
||||||
])
|
callback_data=f"user_{name}"
|
||||||
|
)])
|
||||||
|
|
||||||
|
user_buttons.extend([
|
||||||
|
[InlineKeyboardButton("➕ Создать", callback_data="create"),
|
||||||
|
InlineKeyboardButton("🗑 Удалить", callback_data="delete_menu")],
|
||||||
|
[InlineKeyboardButton("🔄 WARP", callback_data="warp_menu")],
|
||||||
|
[InlineKeyboardButton("« Назад", callback_data="main")],
|
||||||
|
])
|
||||||
|
|
||||||
user_buttons.extend([
|
user_buttons.extend([
|
||||||
[InlineKeyboardButton("➕ Создать", callback_data="create"),
|
[InlineKeyboardButton("➕ Создать", callback_data="create"),
|
||||||
@@ -413,6 +421,27 @@ def _build_client_config(name, password):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# ── config / Karing ──────────────────────────────────────────────────────────
|
# ── config / Karing ──────────────────────────────────────────────────────────
|
||||||
|
@admin_only
|
||||||
|
async def show_user_menu(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
query = update.callback_query
|
||||||
|
await query.answer()
|
||||||
|
name = query.data[len("user_"):]
|
||||||
|
cfg = load_mita_config()
|
||||||
|
user = next((u for u in cfg.get("users", []) if u["name"] == name), None)
|
||||||
|
if not user:
|
||||||
|
await query.answer("Пользователь не найден")
|
||||||
|
return
|
||||||
|
await query.edit_message_text(
|
||||||
|
f"👤 *{escape_md(name)}*",
|
||||||
|
reply_markup=InlineKeyboardMarkup([
|
||||||
|
[InlineKeyboardButton("📋 JSON-конфиг", callback_data=f"config_{name}"),
|
||||||
|
InlineKeyboardButton("📱 Karing", callback_data=f"karing_{name}")],
|
||||||
|
[InlineKeyboardButton("« К пользователям", callback_data="users")],
|
||||||
|
[InlineKeyboardButton("« На главную", callback_data="main")],
|
||||||
|
]),
|
||||||
|
parse_mode="MarkdownV2"
|
||||||
|
)
|
||||||
|
|
||||||
@admin_only
|
@admin_only
|
||||||
async def show_config(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
async def show_config(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
query = update.callback_query
|
query = update.callback_query
|
||||||
@@ -428,9 +457,9 @@ async def show_config(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
await query.edit_message_text(
|
await query.edit_message_text(
|
||||||
f"📋 Конфиг `{escape_md(name)}`:\n```json\n{data[:3500]}\n```",
|
f"📋 Конфиг `{escape_md(name)}`:\n```json\n{data[:3500]}\n```",
|
||||||
reply_markup=InlineKeyboardMarkup([
|
reply_markup=InlineKeyboardMarkup([
|
||||||
[InlineKeyboardButton("« К пользователям", callback_data="users")],
|
|
||||||
[InlineKeyboardButton("📱 Karing", callback_data=f"karing_{name}")],
|
[InlineKeyboardButton("📱 Karing", callback_data=f"karing_{name}")],
|
||||||
[InlineKeyboardButton("« На главную", callback_data="main")],
|
[InlineKeyboardButton("« К пользователю", callback_data=f"user_{name}")],
|
||||||
|
[InlineKeyboardButton("« К списку", callback_data="users")],
|
||||||
]),
|
]),
|
||||||
parse_mode="MarkdownV2"
|
parse_mode="MarkdownV2"
|
||||||
)
|
)
|
||||||
@@ -466,8 +495,8 @@ async def show_karing(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
text,
|
text,
|
||||||
reply_markup=InlineKeyboardMarkup([
|
reply_markup=InlineKeyboardMarkup([
|
||||||
[InlineKeyboardButton("📋 JSON-конфиг", callback_data=f"config_{name}")],
|
[InlineKeyboardButton("📋 JSON-конфиг", callback_data=f"config_{name}")],
|
||||||
[InlineKeyboardButton("« К пользователям", callback_data="users")],
|
[InlineKeyboardButton("« К пользователю", callback_data=f"user_{name}")],
|
||||||
[InlineKeyboardButton("« На главную", callback_data="main")],
|
[InlineKeyboardButton("« К списку", callback_data="users")],
|
||||||
]),
|
]),
|
||||||
parse_mode="MarkdownV2"
|
parse_mode="MarkdownV2"
|
||||||
)
|
)
|
||||||
@@ -690,6 +719,8 @@ async def router(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
return await warp_menu(update, context)
|
return await warp_menu(update, context)
|
||||||
elif data.startswith("warp_"):
|
elif data.startswith("warp_"):
|
||||||
return await toggle_warp(update, context)
|
return await toggle_warp(update, context)
|
||||||
|
elif data.startswith("user_"):
|
||||||
|
return await show_user_menu(update, context)
|
||||||
elif data == "security":
|
elif data == "security":
|
||||||
return await show_security(update, context)
|
return await show_security(update, context)
|
||||||
elif data.startswith("config_"):
|
elif data.startswith("config_"):
|
||||||
|
|||||||
+1
-1
@@ -75,7 +75,7 @@ fi
|
|||||||
|
|
||||||
info "Установка python-telegram-bot (может занять до минуты)..."
|
info "Установка python-telegram-bot (может занять до минуты)..."
|
||||||
_bot_pip() {
|
_bot_pip() {
|
||||||
timeout 120 "$BOT_VENV/bin/pip" install -q --disable-pip-version-check --timeout 15 "$@"
|
PIP_RETRIES=0 timeout 30 "$BOT_VENV/bin/pip" install -q --disable-pip-version-check --timeout 5 --retries 1 "$@"
|
||||||
}
|
}
|
||||||
bot_pip_ok=false
|
bot_pip_ok=false
|
||||||
for mirror in "https://pypi.org/simple/" "https://mirrors.aliyun.com/pypi/simple/"; do
|
for mirror in "https://pypi.org/simple/" "https://mirrors.aliyun.com/pypi/simple/"; do
|
||||||
|
|||||||
+2
-3
@@ -77,10 +77,9 @@ python3 -m venv "$PANEL_DIR/venv"
|
|||||||
info "Установка Flask и зависимостей (может занять до минуты)..."
|
info "Установка Flask и зависимостей (может занять до минуты)..."
|
||||||
|
|
||||||
_pip_install() {
|
_pip_install() {
|
||||||
# Принудительно IPv4 + таймаут 15 секунд на соединение
|
PIP_RETRIES=0 timeout 30 "$PANEL_DIR/venv/bin/pip" install \
|
||||||
timeout 120 "$PANEL_DIR/venv/bin/pip" install \
|
|
||||||
--no-input --quiet --disable-pip-version-check \
|
--no-input --quiet --disable-pip-version-check \
|
||||||
--timeout 15 \
|
--timeout 5 --retries 1 \
|
||||||
"$@"
|
"$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user