mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-01-20 03:40:26 +00:00
Add English localization for admin support menus
This commit is contained in:
@@ -71,10 +71,10 @@ async def show_users_submenu(
|
||||
db: AsyncSession
|
||||
):
|
||||
texts = get_texts(db_user.language)
|
||||
|
||||
|
||||
await callback.message.edit_text(
|
||||
"👥 **Управление пользователями и подписками**\n\n"
|
||||
"Выберите нужный раздел:",
|
||||
texts.t("ADMIN_USERS_SUBMENU_TITLE", "👥 **Управление пользователями и подписками**\n\n") +
|
||||
texts.t("ADMIN_SUBMENU_SELECT_SECTION", "Выберите нужный раздел:"),
|
||||
reply_markup=get_admin_users_submenu_keyboard(db_user.language),
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
@@ -89,10 +89,10 @@ async def show_promo_submenu(
|
||||
db: AsyncSession
|
||||
):
|
||||
texts = get_texts(db_user.language)
|
||||
|
||||
|
||||
await callback.message.edit_text(
|
||||
"💰 **Промокоды и статистика**\n\n"
|
||||
"Выберите нужный раздел:",
|
||||
texts.t("ADMIN_PROMO_SUBMENU_TITLE", "💰 **Промокоды и статистика**\n\n") +
|
||||
texts.t("ADMIN_SUBMENU_SELECT_SECTION", "Выберите нужный раздел:"),
|
||||
reply_markup=get_admin_promo_submenu_keyboard(db_user.language),
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
@@ -107,10 +107,10 @@ async def show_communications_submenu(
|
||||
db: AsyncSession
|
||||
):
|
||||
texts = get_texts(db_user.language)
|
||||
|
||||
|
||||
await callback.message.edit_text(
|
||||
"📨 **Коммуникации**\n\n"
|
||||
"Управление рассылками и текстами интерфейса:",
|
||||
texts.t("ADMIN_COMMUNICATIONS_SUBMENU_TITLE", "📨 **Коммуникации**\n\n") +
|
||||
texts.t("ADMIN_COMMUNICATIONS_SUBMENU_DESCRIPTION", "Управление рассылками и текстами интерфейса:"),
|
||||
reply_markup=get_admin_communications_submenu_keyboard(db_user.language),
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
@@ -132,11 +132,15 @@ async def show_support_submenu(
|
||||
if is_moderator_only:
|
||||
# Rebuild keyboard to include only tickets and back to main menu
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="🎫 Тикеты поддержки", callback_data="admin_tickets")],
|
||||
[InlineKeyboardButton(text="⬅️ Назад", callback_data="back_to_menu")]
|
||||
[InlineKeyboardButton(text=texts.t("ADMIN_SUPPORT_TICKETS", "🎫 Тикеты поддержки"), callback_data="admin_tickets")],
|
||||
[InlineKeyboardButton(text=texts.BACK, callback_data="back_to_menu")]
|
||||
])
|
||||
await callback.message.edit_text(
|
||||
"🛟 **Поддержка**\n\n" + ("Доступ к тикетам." if is_moderator_only else "Управление тикетами и настройками поддержки:"),
|
||||
texts.t("ADMIN_SUPPORT_SUBMENU_TITLE", "🛟 **Поддержка**\n\n") + (
|
||||
texts.t("ADMIN_SUPPORT_SUBMENU_DESCRIPTION_MODERATOR", "Доступ к тикетам.")
|
||||
if is_moderator_only
|
||||
else texts.t("ADMIN_SUPPORT_SUBMENU_DESCRIPTION", "Управление тикетами и настройками поддержки:")
|
||||
),
|
||||
reply_markup=kb,
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
@@ -149,12 +153,14 @@ async def show_moderator_panel(
|
||||
db_user: User,
|
||||
db: AsyncSession
|
||||
):
|
||||
texts = get_texts(db_user.language)
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(text="🎫 Тикеты поддержки", callback_data="admin_tickets")],
|
||||
[InlineKeyboardButton(text="⬅️ В главное меню", callback_data="back_to_menu")]
|
||||
[InlineKeyboardButton(text=texts.t("ADMIN_SUPPORT_TICKETS", "🎫 Тикеты поддержки"), callback_data="admin_tickets")],
|
||||
[InlineKeyboardButton(text=texts.t("BACK_TO_MAIN_MENU_BUTTON", "⬅️ В главное меню"), callback_data="back_to_menu")]
|
||||
])
|
||||
await callback.message.edit_text(
|
||||
"🧑⚖️ <b>Модерация поддержки</b>\n\nДоступ к тикетам поддержки.",
|
||||
texts.t("ADMIN_SUPPORT_MODERATION_TITLE", "🧑⚖️ <b>Модерация поддержки</b>") + "\n\n" +
|
||||
texts.t("ADMIN_SUPPORT_MODERATION_DESCRIPTION", "Доступ к тикетам поддержки."),
|
||||
parse_mode="HTML",
|
||||
reply_markup=kb
|
||||
)
|
||||
@@ -168,6 +174,7 @@ async def show_support_audit(
|
||||
db_user: User,
|
||||
db: AsyncSession
|
||||
):
|
||||
texts = get_texts(db_user.language)
|
||||
# pagination
|
||||
page = 1
|
||||
if callback.data.startswith("admin_support_audit_page_"):
|
||||
@@ -185,18 +192,22 @@ async def show_support_audit(
|
||||
offset = (page - 1) * per_page
|
||||
logs = await TicketCRUD.list_support_audit(db, limit=per_page, offset=offset)
|
||||
|
||||
lines = ["🧾 <b>Аудит модераторов</b>", ""]
|
||||
lines = [texts.t("ADMIN_SUPPORT_AUDIT_TITLE", "🧾 <b>Аудит модераторов</b>"), ""]
|
||||
if not logs:
|
||||
lines.append("Пока пусто")
|
||||
lines.append(texts.t("ADMIN_SUPPORT_AUDIT_EMPTY", "Пока пусто"))
|
||||
else:
|
||||
for log in logs:
|
||||
role = "Модератор" if getattr(log, 'is_moderator', False) else "Админ"
|
||||
role = (
|
||||
texts.t("ADMIN_SUPPORT_AUDIT_ROLE_MODERATOR", "Модератор")
|
||||
if getattr(log, 'is_moderator', False)
|
||||
else texts.t("ADMIN_SUPPORT_AUDIT_ROLE_ADMIN", "Админ")
|
||||
)
|
||||
ts = log.created_at.strftime('%d.%m.%Y %H:%M') if getattr(log, 'created_at', None) else ''
|
||||
action_map = {
|
||||
'close_ticket': 'Закрытие тикета',
|
||||
'block_user_timed': 'Блокировка (время)',
|
||||
'block_user_perm': 'Блокировка (навсегда)',
|
||||
'unblock_user': 'Снятие блока',
|
||||
'close_ticket': texts.t("ADMIN_SUPPORT_AUDIT_ACTION_CLOSE_TICKET", "Закрытие тикета"),
|
||||
'block_user_timed': texts.t("ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_TIMED", "Блокировка (время)"),
|
||||
'block_user_perm': texts.t("ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_PERM", "Блокировка (навсегда)"),
|
||||
'unblock_user': texts.t("ADMIN_SUPPORT_AUDIT_ACTION_UNBLOCK", "Снятие блока"),
|
||||
}
|
||||
action_text = action_map.get(log.action, log.action)
|
||||
ticket_part = f" тикет #{log.ticket_id}" if log.ticket_id else ""
|
||||
@@ -218,7 +229,7 @@ async def show_support_audit(
|
||||
kb_rows = []
|
||||
if nav_row:
|
||||
kb_rows.append(nav_row)
|
||||
kb_rows.append([InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_submenu_support")])
|
||||
kb_rows.append([InlineKeyboardButton(text=texts.BACK, callback_data="admin_submenu_support")])
|
||||
kb = InlineKeyboardMarkup(inline_keyboard=kb_rows)
|
||||
|
||||
await callback.message.edit_text("\n".join(lines), parse_mode="HTML", reply_markup=kb)
|
||||
@@ -233,10 +244,10 @@ async def show_settings_submenu(
|
||||
db: AsyncSession
|
||||
):
|
||||
texts = get_texts(db_user.language)
|
||||
|
||||
|
||||
await callback.message.edit_text(
|
||||
"⚙️ **Настройки системы**\n\n"
|
||||
"Управление Remnawave, мониторингом и другими настройками:",
|
||||
texts.t("ADMIN_SETTINGS_SUBMENU_TITLE", "⚙️ **Настройки системы**\n\n") +
|
||||
texts.t("ADMIN_SETTINGS_SUBMENU_DESCRIPTION", "Управление Remnawave, мониторингом и другими настройками:"),
|
||||
reply_markup=get_admin_settings_submenu_keyboard(db_user.language),
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
@@ -251,10 +262,10 @@ async def show_system_submenu(
|
||||
db: AsyncSession
|
||||
):
|
||||
texts = get_texts(db_user.language)
|
||||
|
||||
|
||||
await callback.message.edit_text(
|
||||
"🛠️ **Системные функции**\n\n"
|
||||
"Отчеты, обновления, логи, резервные копии и системные операции:",
|
||||
texts.t("ADMIN_SYSTEM_SUBMENU_TITLE", "🛠️ **Системные функции**\n\n") +
|
||||
texts.t("ADMIN_SYSTEM_SUBMENU_DESCRIPTION", "Отчеты, обновления, логи, резервные копии и системные операции:"),
|
||||
reply_markup=get_admin_system_submenu_keyboard(db_user.language),
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
|
||||
@@ -29,33 +29,63 @@ def _get_support_settings_keyboard(language: str) -> types.InlineKeyboardMarkup:
|
||||
|
||||
rows: list[list[types.InlineKeyboardButton]] = []
|
||||
|
||||
status_enabled = texts.t("ADMIN_SUPPORT_SETTINGS_STATUS_ENABLED", "Включены")
|
||||
status_disabled = texts.t("ADMIN_SUPPORT_SETTINGS_STATUS_DISABLED", "Отключены")
|
||||
|
||||
def mode_button(label_key: str, default: str, active: bool) -> str:
|
||||
prefix = "🔘" if active else "⚪"
|
||||
return f"{prefix} {texts.t(label_key, default)}"
|
||||
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(
|
||||
text=("✅ Пункт 'Техподдержка' в меню" if menu_enabled else "🚫 Пункт 'Техподдержка' в меню"),
|
||||
text=(
|
||||
f"{'✅' if menu_enabled else '🚫'} "
|
||||
f"{texts.t('ADMIN_SUPPORT_SETTINGS_MENU_LABEL', 'Пункт «Техподдержка» в меню')}"
|
||||
),
|
||||
callback_data="admin_support_toggle_menu"
|
||||
)
|
||||
])
|
||||
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(text=("🔘 Тикеты" if mode == "tickets" else "⚪ Тикеты"), callback_data="admin_support_mode_tickets"),
|
||||
types.InlineKeyboardButton(text=("🔘 Контакт" if mode == "contact" else "⚪ Контакт"), callback_data="admin_support_mode_contact"),
|
||||
types.InlineKeyboardButton(text=("🔘 Оба" if mode == "both" else "⚪ Оба"), callback_data="admin_support_mode_both"),
|
||||
types.InlineKeyboardButton(
|
||||
text=mode_button("ADMIN_SUPPORT_SETTINGS_MODE_TICKETS", "Тикеты", mode == "tickets"),
|
||||
callback_data="admin_support_mode_tickets"
|
||||
),
|
||||
types.InlineKeyboardButton(
|
||||
text=mode_button("ADMIN_SUPPORT_SETTINGS_MODE_CONTACT", "Контакт", mode == "contact"),
|
||||
callback_data="admin_support_mode_contact"
|
||||
),
|
||||
types.InlineKeyboardButton(
|
||||
text=mode_button("ADMIN_SUPPORT_SETTINGS_MODE_BOTH", "Оба", mode == "both"),
|
||||
callback_data="admin_support_mode_both"
|
||||
),
|
||||
])
|
||||
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(text="📝 Изменить описание", callback_data="admin_support_edit_desc")
|
||||
types.InlineKeyboardButton(
|
||||
text=texts.t("ADMIN_SUPPORT_SETTINGS_EDIT_DESCRIPTION", "📝 Изменить описание"),
|
||||
callback_data="admin_support_edit_desc"
|
||||
)
|
||||
])
|
||||
|
||||
# Notifications block
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(
|
||||
text=("🔔 Админ-уведомления: Включены" if admin_notif else "🔕 Админ-уведомления: Отключены"),
|
||||
text=(
|
||||
f"{'🔔' if admin_notif else '🔕'} "
|
||||
f"{texts.t('ADMIN_SUPPORT_SETTINGS_ADMIN_NOTIFICATIONS', 'Админ-уведомления')}: "
|
||||
f"{status_enabled if admin_notif else status_disabled}"
|
||||
),
|
||||
callback_data="admin_support_toggle_admin_notifications"
|
||||
)
|
||||
])
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(
|
||||
text=("🔔 Пользовательские уведомления: Включены" if user_notif else "🔕 Пользовательские уведомления: Отключены"),
|
||||
text=(
|
||||
f"{'🔔' if user_notif else '🔕'} "
|
||||
f"{texts.t('ADMIN_SUPPORT_SETTINGS_USER_NOTIFICATIONS', 'Пользовательские уведомления')}: "
|
||||
f"{status_enabled if user_notif else status_disabled}"
|
||||
),
|
||||
callback_data="admin_support_toggle_user_notifications"
|
||||
)
|
||||
])
|
||||
@@ -63,13 +93,17 @@ def _get_support_settings_keyboard(language: str) -> types.InlineKeyboardMarkup:
|
||||
# SLA block
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(
|
||||
text=("⏰ SLA: Включено" if sla_enabled else "⏹️ SLA: Отключено"),
|
||||
text=(
|
||||
f"{'⏰' if sla_enabled else '⏹️'} "
|
||||
f"{texts.t('ADMIN_SUPPORT_SETTINGS_SLA_LABEL', 'SLA')}: "
|
||||
f"{status_enabled if sla_enabled else status_disabled}"
|
||||
),
|
||||
callback_data="admin_support_toggle_sla"
|
||||
)
|
||||
])
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(
|
||||
text=f"⏳ Время SLA: {sla_minutes} мин",
|
||||
text=texts.t("ADMIN_SUPPORT_SETTINGS_SLA_TIME", "⏳ Время SLA: {minutes} мин").format(minutes=sla_minutes),
|
||||
callback_data="admin_support_set_sla_minutes"
|
||||
)
|
||||
])
|
||||
@@ -79,15 +113,18 @@ def _get_support_settings_keyboard(language: str) -> types.InlineKeyboardMarkup:
|
||||
mod_count = len(moderators)
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(
|
||||
text=f"🧑⚖️ Модераторы: {mod_count}", callback_data="admin_support_list_moderators"
|
||||
text=texts.t("ADMIN_SUPPORT_SETTINGS_MODERATORS_COUNT", "🧑⚖️ Модераторы: {count}").format(count=mod_count),
|
||||
callback_data="admin_support_list_moderators"
|
||||
)
|
||||
])
|
||||
rows.append([
|
||||
types.InlineKeyboardButton(
|
||||
text="➕ Назначить модератора", callback_data="admin_support_add_moderator"
|
||||
text=texts.t("ADMIN_SUPPORT_SETTINGS_ADD_MODERATOR", "➕ Назначить модератора"),
|
||||
callback_data="admin_support_add_moderator"
|
||||
),
|
||||
types.InlineKeyboardButton(
|
||||
text="➖ Удалить модератора", callback_data="admin_support_remove_moderator"
|
||||
text=texts.t("ADMIN_SUPPORT_SETTINGS_REMOVE_MODERATOR", "➖ Удалить модератора"),
|
||||
callback_data="admin_support_remove_moderator"
|
||||
)
|
||||
])
|
||||
|
||||
@@ -108,8 +145,8 @@ async def show_support_settings(
|
||||
texts = get_texts(db_user.language)
|
||||
desc = SupportSettingsService.get_support_info_text(db_user.language)
|
||||
await callback.message.edit_text(
|
||||
"🛟 <b>Настройки поддержки</b>\n\n" +
|
||||
"Режим работы и видимость в меню. Ниже текущее описание меню поддержки:\n\n" +
|
||||
texts.t("ADMIN_SUPPORT_SETTINGS_TITLE", "🛟 <b>Настройки поддержки</b>") + "\n\n" +
|
||||
texts.t("ADMIN_SUPPORT_SETTINGS_DESCRIPTION", "Режим работы и видимость в меню. Ниже текущее описание меню поддержки:") + "\n\n" +
|
||||
desc,
|
||||
reply_markup=_get_support_settings_keyboard(db_user.language),
|
||||
parse_mode="HTML"
|
||||
@@ -161,11 +198,15 @@ class SupportAdvancedStates(StatesGroup):
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def start_set_sla_minutes(callback: types.CallbackQuery, db_user: User, db: AsyncSession, state: FSMContext):
|
||||
texts = get_texts(db_user.language)
|
||||
await callback.message.edit_text(
|
||||
"⏳ <b>Настройка SLA</b>\n\nВведите количество минут ожидания ответа (целое число > 0):",
|
||||
texts.t(
|
||||
"ADMIN_SUPPORT_SLA_SETUP_PROMPT",
|
||||
"⏳ <b>Настройка SLA</b>\n\nВведите количество минут ожидания ответа (целое число > 0):"
|
||||
),
|
||||
parse_mode="HTML",
|
||||
reply_markup=types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_support_settings")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.BACK, callback_data="admin_support_settings")]]
|
||||
)
|
||||
)
|
||||
await state.set_state(SupportAdvancedStates.waiting_for_sla_minutes)
|
||||
@@ -175,63 +216,53 @@ async def start_set_sla_minutes(callback: types.CallbackQuery, db_user: User, db
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def handle_sla_minutes(message: types.Message, db_user: User, db: AsyncSession, state: FSMContext):
|
||||
texts = get_texts(db_user.language)
|
||||
text = (message.text or "").strip()
|
||||
try:
|
||||
minutes = int(text)
|
||||
if minutes <= 0 or minutes > 1440:
|
||||
raise ValueError()
|
||||
except Exception:
|
||||
await message.answer("❌ Введите корректное число минут (1-1440)")
|
||||
await message.answer(texts.t("ADMIN_SUPPORT_SLA_INVALID", "❌ Введите корректное число минут (1-1440)"))
|
||||
return
|
||||
SupportSettingsService.set_sla_minutes(minutes)
|
||||
await state.clear()
|
||||
markup = types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="🗑 Удалить", callback_data="admin_support_delete_msg")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.t("DELETE_MESSAGE", "🗑 Удалить"), callback_data="admin_support_delete_msg")]]
|
||||
)
|
||||
await message.answer("✅ Значение SLA сохранено", reply_markup=markup)
|
||||
await message.answer(texts.t("ADMIN_SUPPORT_SLA_SAVED", "✅ Значение SLA сохранено"), reply_markup=markup)
|
||||
|
||||
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def start_add_moderator(callback: types.CallbackQuery, db_user: User, db: AsyncSession, state: FSMContext):
|
||||
texts = get_texts(db_user.language)
|
||||
await callback.message.edit_text(
|
||||
"🧑⚖️ <b>Назначение модератора</b>\n\nОтправьте Telegram ID пользователя (число)",
|
||||
texts.t(
|
||||
"ADMIN_SUPPORT_ASSIGN_MODERATOR_PROMPT",
|
||||
"🧑⚖️ <b>Назначение модератора</b>\n\nОтправьте Telegram ID пользователя (число)"
|
||||
),
|
||||
parse_mode="HTML",
|
||||
reply_markup=types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_support_settings")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.BACK, callback_data="admin_support_settings")]]
|
||||
)
|
||||
)
|
||||
await state.set_state(SupportAdvancedStates.waiting_for_moderator_id)
|
||||
await callback.answer()
|
||||
|
||||
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def handle_add_moderator(message: types.Message, db_user: User, db: AsyncSession, state: FSMContext):
|
||||
text = (message.text or "").strip()
|
||||
try:
|
||||
tid = int(text)
|
||||
except Exception:
|
||||
await message.answer("❌ Введите корректный Telegram ID (число)")
|
||||
return
|
||||
if SupportSettingsService.add_moderator(tid):
|
||||
markup = types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="🗑 Удалить", callback_data="admin_support_delete_msg")]]
|
||||
)
|
||||
await message.answer(f"✅ Пользователь {tid} назначен модератором", reply_markup=markup)
|
||||
else:
|
||||
await message.answer("❌ Не удалось сохранить")
|
||||
await state.clear()
|
||||
|
||||
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def start_remove_moderator(callback: types.CallbackQuery, db_user: User, db: AsyncSession, state: FSMContext):
|
||||
texts = get_texts(db_user.language)
|
||||
await callback.message.edit_text(
|
||||
"🧑⚖️ <b>Удаление модератора</b>\n\nОтправьте Telegram ID пользователя (число)",
|
||||
texts.t(
|
||||
"ADMIN_SUPPORT_REMOVE_MODERATOR_PROMPT",
|
||||
"🧑⚖️ <b>Удаление модератора</b>\n\nОтправьте Telegram ID пользователя (число)"
|
||||
),
|
||||
parse_mode="HTML",
|
||||
reply_markup=types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_support_settings")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.BACK, callback_data="admin_support_settings")]]
|
||||
)
|
||||
)
|
||||
await state.set_state(SupportAdvancedStates.waiting_for_moderator_id)
|
||||
@@ -243,24 +274,32 @@ async def start_remove_moderator(callback: types.CallbackQuery, db_user: User, d
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def handle_moderator_id(message: types.Message, db_user: User, db: AsyncSession, state: FSMContext):
|
||||
texts = get_texts(db_user.language)
|
||||
data = await state.get_data()
|
||||
action = data.get("action", "add")
|
||||
text = (message.text or "").strip()
|
||||
try:
|
||||
tid = int(text)
|
||||
except Exception:
|
||||
await message.answer("❌ Введите корректный Telegram ID (число)")
|
||||
await message.answer(texts.t("ADMIN_SUPPORT_INVALID_TELEGRAM_ID", "❌ Введите корректный Telegram ID (число)"))
|
||||
return
|
||||
ok = False
|
||||
if action == "remove_moderator":
|
||||
ok = SupportSettingsService.remove_moderator(tid)
|
||||
msg = "✅ Модератор удалён" if ok else "❌ Не удалось удалить"
|
||||
msg = (
|
||||
texts.t("ADMIN_SUPPORT_MODERATOR_REMOVED_SUCCESS", "✅ Модератор {tid} удалён").format(tid=tid)
|
||||
if ok
|
||||
else texts.t("ADMIN_SUPPORT_MODERATOR_REMOVED_FAIL", "❌ Не удалось удалить модератора")
|
||||
)
|
||||
else:
|
||||
ok = SupportSettingsService.add_moderator(tid)
|
||||
msg = "✅ Пользователь назначен модератором" if ok else "❌ Не удалось назначить"
|
||||
msg = (
|
||||
texts.t("ADMIN_SUPPORT_MODERATOR_ADDED_SUCCESS", "✅ Пользователь {tid} назначен модератором").format(tid=tid)
|
||||
if ok
|
||||
else texts.t("ADMIN_SUPPORT_MODERATOR_ADDED_FAIL", "❌ Не удалось назначить модератора")
|
||||
)
|
||||
await state.clear()
|
||||
markup = types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="🗑 Удалить", callback_data="admin_support_delete_msg")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.t("DELETE_MESSAGE", "🗑 Удалить"), callback_data="admin_support_delete_msg")]]
|
||||
)
|
||||
await message.answer(msg, reply_markup=markup)
|
||||
|
||||
@@ -268,13 +307,17 @@ async def handle_moderator_id(message: types.Message, db_user: User, db: AsyncSe
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def list_moderators(callback: types.CallbackQuery, db_user: User, db: AsyncSession):
|
||||
texts = get_texts(db_user.language)
|
||||
moderators = SupportSettingsService.get_moderators()
|
||||
if not moderators:
|
||||
await callback.answer("Список пуст", show_alert=True)
|
||||
await callback.answer(texts.t("ADMIN_SUPPORT_MODERATORS_EMPTY", "Список пуст"), show_alert=True)
|
||||
return
|
||||
text = "🧑⚖️ <b>Модераторы</b>\n\n" + "\n".join([f"• <code>{tid}</code>" for tid in moderators])
|
||||
text = (
|
||||
texts.t("ADMIN_SUPPORT_MODERATORS_TITLE", "🧑⚖️ <b>Модераторы</b>") +
|
||||
"\n\n" + "\n".join([f"• <code>{tid}</code>" for tid in moderators])
|
||||
)
|
||||
markup = types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="⬅️ Назад", callback_data="admin_support_settings")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.BACK, callback_data="admin_support_settings")]]
|
||||
)
|
||||
await callback.message.edit_text(text, parse_mode="HTML", reply_markup=markup)
|
||||
await callback.answer()
|
||||
@@ -311,7 +354,10 @@ async def start_edit_desc(callback: types.CallbackQuery, db_user: User, db: Asyn
|
||||
|
||||
kb_rows: list[list[types.InlineKeyboardButton]] = []
|
||||
kb_rows.append([
|
||||
types.InlineKeyboardButton(text="📨 Прислать текст", callback_data="admin_support_send_desc")
|
||||
types.InlineKeyboardButton(
|
||||
text=texts.t("ADMIN_SUPPORT_SEND_DESCRIPTION", "📨 Прислать текст"),
|
||||
callback_data="admin_support_send_desc"
|
||||
)
|
||||
])
|
||||
# Подготовим блок контакта (отдельным инлайном)
|
||||
from app.config import settings
|
||||
@@ -321,19 +367,19 @@ async def start_edit_desc(callback: types.CallbackQuery, db_user: User, db: Asyn
|
||||
])
|
||||
|
||||
text_parts = [
|
||||
"📝 <b>Редактирование описания поддержки</b>",
|
||||
texts.t("ADMIN_SUPPORT_EDIT_DESCRIPTION_TITLE", "📝 <b>Редактирование описания поддержки</b>"),
|
||||
"",
|
||||
"Текущее описание:",
|
||||
texts.t("ADMIN_SUPPORT_EDIT_DESCRIPTION_CURRENT", "Текущее описание:"),
|
||||
"",
|
||||
f"<code>{html.escape(current_desc_plain)}</code>",
|
||||
]
|
||||
if support_contact_display:
|
||||
text_parts += [
|
||||
"",
|
||||
"<b>Контакт для режима \u00abКонтакт\u00bb</b>",
|
||||
texts.t("ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_TITLE", "<b>Контакт для режима «Контакт»</b>"),
|
||||
f"<code>{html.escape(support_contact_display)}</code>",
|
||||
"",
|
||||
"Добавьте в описание при необходимости.",
|
||||
texts.t("ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_HINT", "Добавьте в описание при необходимости."),
|
||||
]
|
||||
await callback.message.edit_text(
|
||||
"\n".join(text_parts),
|
||||
@@ -347,24 +393,26 @@ async def start_edit_desc(callback: types.CallbackQuery, db_user: User, db: Asyn
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def handle_new_desc(message: types.Message, db_user: User, db: AsyncSession, state: FSMContext):
|
||||
texts = get_texts(db_user.language)
|
||||
new_text = message.html_text or message.text
|
||||
SupportSettingsService.set_support_info_text(db_user.language, new_text)
|
||||
await state.clear()
|
||||
markup = types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="🗑 Удалить", callback_data="admin_support_delete_msg")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.t("DELETE_MESSAGE", "🗑 Удалить"), callback_data="admin_support_delete_msg")]]
|
||||
)
|
||||
await message.answer("✅ Описание обновлено.", reply_markup=markup)
|
||||
await message.answer(texts.t("ADMIN_SUPPORT_DESCRIPTION_UPDATED", "✅ Описание обновлено."), reply_markup=markup)
|
||||
|
||||
|
||||
@admin_required
|
||||
@error_handler
|
||||
async def send_desc_copy(callback: types.CallbackQuery, db_user: User, db: AsyncSession):
|
||||
# send plain text for easy copying
|
||||
texts = get_texts(db_user.language)
|
||||
current_desc_html = SupportSettingsService.get_support_info_text(db_user.language)
|
||||
current_desc_plain = re.sub(r"<[^>]+>", "", current_desc_html)
|
||||
# attach delete button to the sent message
|
||||
markup = types.InlineKeyboardMarkup(
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text="🗑 Удалить", callback_data="admin_support_delete_msg")]]
|
||||
inline_keyboard=[[types.InlineKeyboardButton(text=texts.t("DELETE_MESSAGE", "🗑 Удалить"), callback_data="admin_support_delete_msg")]]
|
||||
)
|
||||
if len(current_desc_plain) <= 4000:
|
||||
await callback.message.answer(current_desc_plain, reply_markup=markup)
|
||||
@@ -376,7 +424,7 @@ async def send_desc_copy(callback: types.CallbackQuery, db_user: User, db: Async
|
||||
is_last = (chunk + 4000) >= len(current_desc_plain)
|
||||
await callback.message.answer(next_chunk, reply_markup=(markup if is_last else None))
|
||||
chunk += 4000
|
||||
await callback.answer("Текст отправлен ниже")
|
||||
await callback.answer(texts.t("ADMIN_SUPPORT_DESCRIPTION_SENT", "Текст отправлен ниже"))
|
||||
|
||||
|
||||
@error_handler
|
||||
@@ -386,15 +434,15 @@ async def delete_sent_message(callback: types.CallbackQuery, db_user: User, db:
|
||||
may_delete = (settings.is_admin(callback.from_user.id) or SupportSettingsService.is_moderator(callback.from_user.id))
|
||||
except Exception:
|
||||
may_delete = False
|
||||
texts = get_texts(db_user.language if db_user else 'ru')
|
||||
if not may_delete:
|
||||
texts = get_texts(db_user.language if db_user else 'ru')
|
||||
await callback.answer(texts.ACCESS_DENIED, show_alert=True)
|
||||
return
|
||||
try:
|
||||
await callback.message.delete()
|
||||
finally:
|
||||
with contextlib.suppress(Exception):
|
||||
await callback.answer("Сообщение удалено")
|
||||
await callback.answer(texts.t("ADMIN_SUPPORT_MESSAGE_DELETED", "Сообщение удалено"))
|
||||
|
||||
|
||||
def register_handlers(dp: Dispatcher):
|
||||
|
||||
@@ -564,5 +564,63 @@
|
||||
"USER_BLOCKED_FOREVER": "You are blocked from contacting support.",
|
||||
"USER_BLOCKED_UNTIL": "You are blocked until {time}",
|
||||
"VIEW_CLOSED_TICKETS": "🟢 Closed tickets",
|
||||
"VIEW_TICKET": "👁️ View ticket"
|
||||
"VIEW_TICKET": "👁️ View ticket",
|
||||
"ADMIN_USERS_SUBMENU_TITLE": "👥 **User and subscription management**\n\n",
|
||||
"ADMIN_PROMO_SUBMENU_TITLE": "💰 **Promo codes and statistics**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_TITLE": "📨 **Communications**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_DESCRIPTION": "Manage broadcasts and interface texts:",
|
||||
"ADMIN_SUBMENU_SELECT_SECTION": "Choose a section:",
|
||||
"ADMIN_SUPPORT_SUBMENU_TITLE": "🛟 **Support**\n\n",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION": "Manage tickets and support settings:",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION_MODERATOR": "Ticket access only.",
|
||||
"ADMIN_SUPPORT_MODERATION_TITLE": "🧑⚖️ <b>Support moderation</b>",
|
||||
"ADMIN_SUPPORT_MODERATION_DESCRIPTION": "Access to support tickets.",
|
||||
"ADMIN_SUPPORT_AUDIT_TITLE": "🧾 <b>Moderator audit</b>",
|
||||
"ADMIN_SUPPORT_AUDIT_EMPTY": "Nothing here yet",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_MODERATOR": "Moderator",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_ADMIN": "Admin",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_CLOSE_TICKET": "Ticket closed",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_TIMED": "Timed block",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_PERM": "Permanent block",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_UNBLOCK": "Unblock",
|
||||
"ADMIN_SETTINGS_SUBMENU_TITLE": "⚙️ **System settings**\n\n",
|
||||
"ADMIN_SETTINGS_SUBMENU_DESCRIPTION": "Manage Remnawave, monitoring and other settings:",
|
||||
"ADMIN_SYSTEM_SUBMENU_TITLE": "🛠️ **System tools**\n\n",
|
||||
"ADMIN_SYSTEM_SUBMENU_DESCRIPTION": "Reports, updates, logs, backups and system operations:",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_ENABLED": "Enabled",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_DISABLED": "Disabled",
|
||||
"ADMIN_SUPPORT_SETTINGS_MENU_LABEL": "\"Support\" menu item",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_TICKETS": "Tickets",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_CONTACT": "Contact",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_BOTH": "Both",
|
||||
"ADMIN_SUPPORT_SETTINGS_EDIT_DESCRIPTION": "📝 Edit description",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADMIN_NOTIFICATIONS": "Admin notifications",
|
||||
"ADMIN_SUPPORT_SETTINGS_USER_NOTIFICATIONS": "User notifications",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_LABEL": "SLA",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_TIME": "⏳ SLA time: {minutes} min",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODERATORS_COUNT": "🧑⚖️ Moderators: {count}",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADD_MODERATOR": "➕ Assign moderator",
|
||||
"ADMIN_SUPPORT_SETTINGS_REMOVE_MODERATOR": "➖ Remove moderator",
|
||||
"ADMIN_SUPPORT_SETTINGS_TITLE": "🛟 <b>Support settings</b>",
|
||||
"ADMIN_SUPPORT_SETTINGS_DESCRIPTION": "Working hours and menu visibility. Current support menu description:",
|
||||
"ADMIN_SUPPORT_SLA_SETUP_PROMPT": "⏳ <b>SLA configuration</b>\n\nEnter the response wait time in minutes (integer > 0):",
|
||||
"ADMIN_SUPPORT_SLA_INVALID": "❌ Enter a valid number of minutes (1-1440)",
|
||||
"ADMIN_SUPPORT_SLA_SAVED": "✅ SLA value saved",
|
||||
"ADMIN_SUPPORT_ASSIGN_MODERATOR_PROMPT": "🧑⚖️ <b>Assign moderator</b>\n\nSend the user's Telegram ID (number)",
|
||||
"ADMIN_SUPPORT_REMOVE_MODERATOR_PROMPT": "🧑⚖️ <b>Remove moderator</b>\n\nSend the user's Telegram ID (number)",
|
||||
"ADMIN_SUPPORT_INVALID_TELEGRAM_ID": "❌ Enter a valid Telegram ID (number)",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_SUCCESS": "✅ Moderator {tid} removed",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_FAIL": "❌ Failed to remove moderator",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_SUCCESS": "✅ User {tid} assigned as moderator",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_FAIL": "❌ Failed to assign moderator",
|
||||
"ADMIN_SUPPORT_MODERATORS_EMPTY": "List is empty",
|
||||
"ADMIN_SUPPORT_MODERATORS_TITLE": "🧑⚖️ <b>Moderators</b>",
|
||||
"ADMIN_SUPPORT_SEND_DESCRIPTION": "📨 Send description",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_TITLE": "📝 <b>Editing support description</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CURRENT": "Current description:",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_TITLE": "<b>Contact for \"Contact\" mode</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_HINT": "Add to the description if needed.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_UPDATED": "✅ Description updated.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_SENT": "Description sent below",
|
||||
"ADMIN_SUPPORT_MESSAGE_DELETED": "Message deleted"
|
||||
}
|
||||
|
||||
@@ -564,5 +564,63 @@
|
||||
"USER_BLOCKED_FOREVER": "Вы заблокированы для обращений в поддержку.",
|
||||
"USER_BLOCKED_UNTIL": "Вы заблокированы до {time}",
|
||||
"VIEW_CLOSED_TICKETS": "🟢 Закрытые тикеты",
|
||||
"VIEW_TICKET": "👁️ Посмотреть тикет"
|
||||
"VIEW_TICKET": "👁️ Посмотреть тикет",
|
||||
"ADMIN_USERS_SUBMENU_TITLE": "👥 **Управление пользователями и подписками**\n\n",
|
||||
"ADMIN_PROMO_SUBMENU_TITLE": "💰 **Промокоды и статистика**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_TITLE": "📨 **Коммуникации**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_DESCRIPTION": "Управление рассылками и текстами интерфейса:",
|
||||
"ADMIN_SUBMENU_SELECT_SECTION": "Выберите нужный раздел:",
|
||||
"ADMIN_SUPPORT_SUBMENU_TITLE": "🛟 **Поддержка**\n\n",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION": "Управление тикетами и настройками поддержки:",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION_MODERATOR": "Доступ к тикетам.",
|
||||
"ADMIN_SUPPORT_MODERATION_TITLE": "🧑⚖️ <b>Модерация поддержки</b>",
|
||||
"ADMIN_SUPPORT_MODERATION_DESCRIPTION": "Доступ к тикетам поддержки.",
|
||||
"ADMIN_SUPPORT_AUDIT_TITLE": "🧾 <b>Аудит модераторов</b>",
|
||||
"ADMIN_SUPPORT_AUDIT_EMPTY": "Пока пусто",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_MODERATOR": "Модератор",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_ADMIN": "Админ",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_CLOSE_TICKET": "Закрытие тикета",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_TIMED": "Блокировка (время)",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_PERM": "Блокировка (навсегда)",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_UNBLOCK": "Снятие блока",
|
||||
"ADMIN_SETTINGS_SUBMENU_TITLE": "⚙️ **Настройки системы**\n\n",
|
||||
"ADMIN_SETTINGS_SUBMENU_DESCRIPTION": "Управление Remnawave, мониторингом и другими настройками:",
|
||||
"ADMIN_SYSTEM_SUBMENU_TITLE": "🛠️ **Системные функции**\n\n",
|
||||
"ADMIN_SYSTEM_SUBMENU_DESCRIPTION": "Отчеты, обновления, логи, резервные копии и системные операции:",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_ENABLED": "Включены",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_DISABLED": "Отключены",
|
||||
"ADMIN_SUPPORT_SETTINGS_MENU_LABEL": "Пункт «Техподдержка» в меню",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_TICKETS": "Тикеты",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_CONTACT": "Контакт",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_BOTH": "Оба",
|
||||
"ADMIN_SUPPORT_SETTINGS_EDIT_DESCRIPTION": "📝 Изменить описание",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADMIN_NOTIFICATIONS": "Админ-уведомления",
|
||||
"ADMIN_SUPPORT_SETTINGS_USER_NOTIFICATIONS": "Пользовательские уведомления",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_LABEL": "SLA",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_TIME": "⏳ Время SLA: {minutes} мин",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODERATORS_COUNT": "🧑⚖️ Модераторы: {count}",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADD_MODERATOR": "➕ Назначить модератора",
|
||||
"ADMIN_SUPPORT_SETTINGS_REMOVE_MODERATOR": "➖ Удалить модератора",
|
||||
"ADMIN_SUPPORT_SETTINGS_TITLE": "🛟 <b>Настройки поддержки</b>",
|
||||
"ADMIN_SUPPORT_SETTINGS_DESCRIPTION": "Режим работы и видимость в меню. Ниже текущее описание меню поддержки:",
|
||||
"ADMIN_SUPPORT_SLA_SETUP_PROMPT": "⏳ <b>Настройка SLA</b>\n\nВведите количество минут ожидания ответа (целое число > 0):",
|
||||
"ADMIN_SUPPORT_SLA_INVALID": "❌ Введите корректное число минут (1-1440)",
|
||||
"ADMIN_SUPPORT_SLA_SAVED": "✅ Значение SLA сохранено",
|
||||
"ADMIN_SUPPORT_ASSIGN_MODERATOR_PROMPT": "🧑⚖️ <b>Назначение модератора</b>\n\nОтправьте Telegram ID пользователя (число)",
|
||||
"ADMIN_SUPPORT_REMOVE_MODERATOR_PROMPT": "🧑⚖️ <b>Удаление модератора</b>\n\nОтправьте Telegram ID пользователя (число)",
|
||||
"ADMIN_SUPPORT_INVALID_TELEGRAM_ID": "❌ Введите корректный Telegram ID (число)",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_SUCCESS": "✅ Модератор {tid} удалён",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_FAIL": "❌ Не удалось удалить модератора",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_SUCCESS": "✅ Пользователь {tid} назначен модератором",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_FAIL": "❌ Не удалось назначить модератора",
|
||||
"ADMIN_SUPPORT_MODERATORS_EMPTY": "Список пуст",
|
||||
"ADMIN_SUPPORT_MODERATORS_TITLE": "🧑⚖️ <b>Модераторы</b>",
|
||||
"ADMIN_SUPPORT_SEND_DESCRIPTION": "📨 Прислать текст",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_TITLE": "📝 <b>Редактирование описания поддержки</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CURRENT": "Текущее описание:",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_TITLE": "<b>Контакт для режима «Контакт»</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_HINT": "Добавьте в описание при необходимости.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_UPDATED": "✅ Описание обновлено.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_SENT": "Текст отправлен ниже",
|
||||
"ADMIN_SUPPORT_MESSAGE_DELETED": "Сообщение удалено"
|
||||
}
|
||||
|
||||
@@ -548,11 +548,69 @@
|
||||
"ADMIN_MAIN_MESSAGES": "📨 Messages",
|
||||
"ADMIN_MAIN_SETTINGS": "⚙️ Settings",
|
||||
"ADMIN_MAIN_SYSTEM": "🛠️ System",
|
||||
"ADMIN_USERS_SUBMENU_TITLE": "👥 **User and subscription management**\n\n",
|
||||
"ADMIN_PROMO_SUBMENU_TITLE": "💰 **Promo codes and statistics**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_TITLE": "📨 **Communications**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_DESCRIPTION": "Manage broadcasts and interface texts:",
|
||||
"ADMIN_SUBMENU_SELECT_SECTION": "Choose a section:",
|
||||
"ADMIN_COMMUNICATIONS_WELCOME_TEXT": "👋 Welcome message",
|
||||
"ADMIN_COMMUNICATIONS_MENU_MESSAGES": "📢 Menu messages",
|
||||
"ADMIN_SUPPORT_TICKETS": "🎫 Support tickets",
|
||||
"ADMIN_SUPPORT_AUDIT": "🧾 Moderator audit",
|
||||
"ADMIN_SUPPORT_SETTINGS": "🛟 Support settings",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_ENABLED": "Enabled",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_DISABLED": "Disabled",
|
||||
"ADMIN_SUPPORT_SETTINGS_MENU_LABEL": "\"Support\" menu item",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_TICKETS": "Tickets",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_CONTACT": "Contact",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_BOTH": "Both",
|
||||
"ADMIN_SUPPORT_SETTINGS_EDIT_DESCRIPTION": "📝 Edit description",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADMIN_NOTIFICATIONS": "Admin notifications",
|
||||
"ADMIN_SUPPORT_SETTINGS_USER_NOTIFICATIONS": "User notifications",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_LABEL": "SLA",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_TIME": "⏳ SLA time: {minutes} min",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODERATORS_COUNT": "🧑⚖️ Moderators: {count}",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADD_MODERATOR": "➕ Assign moderator",
|
||||
"ADMIN_SUPPORT_SETTINGS_REMOVE_MODERATOR": "➖ Remove moderator",
|
||||
"ADMIN_SUPPORT_SETTINGS_TITLE": "🛟 <b>Support settings</b>",
|
||||
"ADMIN_SUPPORT_SETTINGS_DESCRIPTION": "Working hours and menu visibility. Current support menu description:",
|
||||
"ADMIN_SUPPORT_SLA_SETUP_PROMPT": "⏳ <b>SLA configuration</b>\n\nEnter the response wait time in minutes (integer > 0):",
|
||||
"ADMIN_SUPPORT_SLA_INVALID": "❌ Enter a valid number of minutes (1-1440)",
|
||||
"ADMIN_SUPPORT_SLA_SAVED": "✅ SLA value saved",
|
||||
"ADMIN_SUPPORT_ASSIGN_MODERATOR_PROMPT": "🧑⚖️ <b>Assign moderator</b>\n\nSend the user's Telegram ID (number)",
|
||||
"ADMIN_SUPPORT_REMOVE_MODERATOR_PROMPT": "🧑⚖️ <b>Remove moderator</b>\n\nSend the user's Telegram ID (number)",
|
||||
"ADMIN_SUPPORT_INVALID_TELEGRAM_ID": "❌ Enter a valid Telegram ID (number)",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_SUCCESS": "✅ Moderator {tid} removed",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_FAIL": "❌ Failed to remove moderator",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_SUCCESS": "✅ User {tid} assigned as moderator",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_FAIL": "❌ Failed to assign moderator",
|
||||
"ADMIN_SUPPORT_MODERATORS_EMPTY": "List is empty",
|
||||
"ADMIN_SUPPORT_MODERATORS_TITLE": "🧑⚖️ <b>Moderators</b>",
|
||||
"ADMIN_SUPPORT_SEND_DESCRIPTION": "📨 Send description",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_TITLE": "📝 <b>Editing support description</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CURRENT": "Current description:",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_TITLE": "<b>Contact for \"Contact\" mode</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_HINT": "Add to the description if needed.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_UPDATED": "✅ Description updated.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_SENT": "Description sent below",
|
||||
"ADMIN_SUPPORT_MESSAGE_DELETED": "Message deleted",
|
||||
"ADMIN_SUPPORT_SUBMENU_TITLE": "🛟 **Support**\n\n",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION": "Manage tickets and support settings:",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION_MODERATOR": "Ticket access only.",
|
||||
"ADMIN_SUPPORT_MODERATION_TITLE": "🧑⚖️ <b>Support moderation</b>",
|
||||
"ADMIN_SUPPORT_MODERATION_DESCRIPTION": "Access to support tickets.",
|
||||
"ADMIN_SUPPORT_AUDIT_TITLE": "🧾 <b>Moderator audit</b>",
|
||||
"ADMIN_SUPPORT_AUDIT_EMPTY": "Nothing here yet",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_MODERATOR": "Moderator",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_ADMIN": "Admin",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_CLOSE_TICKET": "Ticket closed",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_TIMED": "Timed block",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_PERM": "Permanent block",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_UNBLOCK": "Unblock",
|
||||
"ADMIN_SETTINGS_SUBMENU_TITLE": "⚙️ **System settings**\n\n",
|
||||
"ADMIN_SETTINGS_SUBMENU_DESCRIPTION": "Manage Remnawave, monitoring and other settings:",
|
||||
"ADMIN_SYSTEM_SUBMENU_TITLE": "🛠️ **System tools**\n\n",
|
||||
"ADMIN_SYSTEM_SUBMENU_DESCRIPTION": "Reports, updates, logs, backups and system operations:",
|
||||
"ADMIN_SETTINGS_BOT_CONFIG": "🧩 Bot configuration",
|
||||
"ADMIN_SETTINGS_MAINTENANCE": "🔧 Maintenance",
|
||||
"ADMIN_SYSTEM_UPDATES": "📄 Updates",
|
||||
|
||||
@@ -548,11 +548,69 @@
|
||||
"ADMIN_MAIN_MESSAGES": "📨 Сообщения",
|
||||
"ADMIN_MAIN_SETTINGS": "⚙️ Настройки",
|
||||
"ADMIN_MAIN_SYSTEM": "🛠️ Система",
|
||||
"ADMIN_USERS_SUBMENU_TITLE": "👥 **Управление пользователями и подписками**\n\n",
|
||||
"ADMIN_PROMO_SUBMENU_TITLE": "💰 **Промокоды и статистика**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_TITLE": "📨 **Коммуникации**\n\n",
|
||||
"ADMIN_COMMUNICATIONS_SUBMENU_DESCRIPTION": "Управление рассылками и текстами интерфейса:",
|
||||
"ADMIN_SUBMENU_SELECT_SECTION": "Выберите нужный раздел:",
|
||||
"ADMIN_COMMUNICATIONS_WELCOME_TEXT": "👋 Приветственный текст",
|
||||
"ADMIN_COMMUNICATIONS_MENU_MESSAGES": "📢 Сообщения в меню",
|
||||
"ADMIN_SUPPORT_TICKETS": "🎫 Тикеты поддержки",
|
||||
"ADMIN_SUPPORT_AUDIT": "🧾 Аудит модераторов",
|
||||
"ADMIN_SUPPORT_SETTINGS": "🛟 Настройки поддержки",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_ENABLED": "Включены",
|
||||
"ADMIN_SUPPORT_SETTINGS_STATUS_DISABLED": "Отключены",
|
||||
"ADMIN_SUPPORT_SETTINGS_MENU_LABEL": "Пункт «Техподдержка» в меню",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_TICKETS": "Тикеты",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_CONTACT": "Контакт",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODE_BOTH": "Оба",
|
||||
"ADMIN_SUPPORT_SETTINGS_EDIT_DESCRIPTION": "📝 Изменить описание",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADMIN_NOTIFICATIONS": "Админ-уведомления",
|
||||
"ADMIN_SUPPORT_SETTINGS_USER_NOTIFICATIONS": "Пользовательские уведомления",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_LABEL": "SLA",
|
||||
"ADMIN_SUPPORT_SETTINGS_SLA_TIME": "⏳ Время SLA: {minutes} мин",
|
||||
"ADMIN_SUPPORT_SETTINGS_MODERATORS_COUNT": "🧑⚖️ Модераторы: {count}",
|
||||
"ADMIN_SUPPORT_SETTINGS_ADD_MODERATOR": "➕ Назначить модератора",
|
||||
"ADMIN_SUPPORT_SETTINGS_REMOVE_MODERATOR": "➖ Удалить модератора",
|
||||
"ADMIN_SUPPORT_SETTINGS_TITLE": "🛟 <b>Настройки поддержки</b>",
|
||||
"ADMIN_SUPPORT_SETTINGS_DESCRIPTION": "Режим работы и видимость в меню. Ниже текущее описание меню поддержки:",
|
||||
"ADMIN_SUPPORT_SLA_SETUP_PROMPT": "⏳ <b>Настройка SLA</b>\n\nВведите количество минут ожидания ответа (целое число > 0):",
|
||||
"ADMIN_SUPPORT_SLA_INVALID": "❌ Введите корректное число минут (1-1440)",
|
||||
"ADMIN_SUPPORT_SLA_SAVED": "✅ Значение SLA сохранено",
|
||||
"ADMIN_SUPPORT_ASSIGN_MODERATOR_PROMPT": "🧑⚖️ <b>Назначение модератора</b>\n\nОтправьте Telegram ID пользователя (число)",
|
||||
"ADMIN_SUPPORT_REMOVE_MODERATOR_PROMPT": "🧑⚖️ <b>Удаление модератора</b>\n\nОтправьте Telegram ID пользователя (число)",
|
||||
"ADMIN_SUPPORT_INVALID_TELEGRAM_ID": "❌ Введите корректный Telegram ID (число)",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_SUCCESS": "✅ Модератор {tid} удалён",
|
||||
"ADMIN_SUPPORT_MODERATOR_REMOVED_FAIL": "❌ Не удалось удалить модератора",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_SUCCESS": "✅ Пользователь {tid} назначен модератором",
|
||||
"ADMIN_SUPPORT_MODERATOR_ADDED_FAIL": "❌ Не удалось назначить модератора",
|
||||
"ADMIN_SUPPORT_MODERATORS_EMPTY": "Список пуст",
|
||||
"ADMIN_SUPPORT_MODERATORS_TITLE": "🧑⚖️ <b>Модераторы</b>",
|
||||
"ADMIN_SUPPORT_SEND_DESCRIPTION": "📨 Прислать текст",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_TITLE": "📝 <b>Редактирование описания поддержки</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CURRENT": "Текущее описание:",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_TITLE": "<b>Контакт для режима «Контакт»</b>",
|
||||
"ADMIN_SUPPORT_EDIT_DESCRIPTION_CONTACT_HINT": "Добавьте в описание при необходимости.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_UPDATED": "✅ Описание обновлено.",
|
||||
"ADMIN_SUPPORT_DESCRIPTION_SENT": "Текст отправлен ниже",
|
||||
"ADMIN_SUPPORT_MESSAGE_DELETED": "Сообщение удалено",
|
||||
"ADMIN_SUPPORT_SUBMENU_TITLE": "🛟 **Поддержка**\n\n",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION": "Управление тикетами и настройками поддержки:",
|
||||
"ADMIN_SUPPORT_SUBMENU_DESCRIPTION_MODERATOR": "Доступ к тикетам.",
|
||||
"ADMIN_SUPPORT_MODERATION_TITLE": "🧑⚖️ <b>Модерация поддержки</b>",
|
||||
"ADMIN_SUPPORT_MODERATION_DESCRIPTION": "Доступ к тикетам поддержки.",
|
||||
"ADMIN_SUPPORT_AUDIT_TITLE": "🧾 <b>Аудит модераторов</b>",
|
||||
"ADMIN_SUPPORT_AUDIT_EMPTY": "Пока пусто",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_MODERATOR": "Модератор",
|
||||
"ADMIN_SUPPORT_AUDIT_ROLE_ADMIN": "Админ",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_CLOSE_TICKET": "Закрытие тикета",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_TIMED": "Блокировка (время)",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_BLOCK_PERM": "Блокировка (навсегда)",
|
||||
"ADMIN_SUPPORT_AUDIT_ACTION_UNBLOCK": "Снятие блока",
|
||||
"ADMIN_SETTINGS_SUBMENU_TITLE": "⚙️ **Настройки системы**\n\n",
|
||||
"ADMIN_SETTINGS_SUBMENU_DESCRIPTION": "Управление Remnawave, мониторингом и другими настройками:",
|
||||
"ADMIN_SYSTEM_SUBMENU_TITLE": "🛠️ **Системные функции**\n\n",
|
||||
"ADMIN_SYSTEM_SUBMENU_DESCRIPTION": "Отчеты, обновления, логи, резервные копии и системные операции:",
|
||||
"ADMIN_SETTINGS_BOT_CONFIG": "🧩 Конфигурация бота",
|
||||
"ADMIN_SETTINGS_MAINTENANCE": "🔧 Техработы",
|
||||
"ADMIN_SYSTEM_UPDATES": "📄 Обновления",
|
||||
|
||||
Reference in New Issue
Block a user