fix admin crypto links / fix sender button formatting
This commit is contained in:
@@ -314,11 +314,6 @@ async def handle_sync_server(
|
||||
sub = await remna.get_subscription_by_username(key["email"])
|
||||
if sub:
|
||||
new_remnawave_link = sub.get("subscriptionUrl")
|
||||
if HAPP_CRYPTOLINK:
|
||||
happ = sub.get("happ") or {}
|
||||
new_remnawave_link = (
|
||||
happ.get("cryptoLink") or happ.get("link") or new_remnawave_link
|
||||
)
|
||||
|
||||
if new_remnawave_link:
|
||||
server_result = await session.execute(
|
||||
@@ -336,7 +331,7 @@ async def handle_sync_server(
|
||||
email=key["email"],
|
||||
client_id=key["client_id"],
|
||||
tg_id=key["tg_id"],
|
||||
remna_link_override=new_remnawave_link,
|
||||
remna_link_override=None,
|
||||
plan=key["tariff_id"],
|
||||
)
|
||||
|
||||
@@ -544,11 +539,6 @@ async def handle_sync_cluster(
|
||||
sub = await remna.get_subscription_by_username(key["email"])
|
||||
if sub:
|
||||
new_remnawave_link = sub.get("subscriptionUrl")
|
||||
if HAPP_CRYPTOLINK:
|
||||
happ = sub.get("happ") or {}
|
||||
new_remnawave_link = (
|
||||
happ.get("cryptoLink") or happ.get("link") or new_remnawave_link
|
||||
)
|
||||
|
||||
if new_remnawave_link:
|
||||
servers = await get_servers(session)
|
||||
@@ -561,7 +551,7 @@ async def handle_sync_cluster(
|
||||
email=key["email"],
|
||||
client_id=key["client_id"],
|
||||
tg_id=key["tg_id"],
|
||||
remna_link_override=new_remnawave_link,
|
||||
remna_link_override=None,
|
||||
plan=key["tariff_id"],
|
||||
)
|
||||
|
||||
|
||||
@@ -170,13 +170,24 @@ async def get_recipients(session: AsyncSession, send_to: str, cluster_name: str
|
||||
return tg_ids, len(tg_ids)
|
||||
|
||||
|
||||
def strip_html_tags(text: str) -> str:
|
||||
text = re.sub(r'<tg-emoji emoji-id="[^"]*">([^<]*)</tg-emoji>', r"\1", text)
|
||||
text = re.sub(r'<[^>]+>', '', text)
|
||||
text = text.replace('<', '<').replace('>', '>').replace('&', '&')
|
||||
return text.strip()
|
||||
|
||||
|
||||
def parse_message_buttons(text: str) -> tuple[str, InlineKeyboardMarkup | None]:
|
||||
if "BUTTONS:" not in text:
|
||||
buttons_match = re.search(r'(<[^>]+>)?\s*BUTTONS\s*:\s*(</[^>]+>)?', text, re.IGNORECASE)
|
||||
if not buttons_match:
|
||||
return text, None
|
||||
|
||||
parts = text.split("BUTTONS:", 1)
|
||||
clean_text = parts[0].strip()
|
||||
buttons_text = parts[1].strip()
|
||||
clean_text = text[:buttons_match.start()].strip()
|
||||
|
||||
buttons_section = text[buttons_match.start():].strip()
|
||||
buttons_text = strip_html_tags(buttons_section)
|
||||
|
||||
buttons_text = re.sub(r'^.*?BUTTONS\s*:\s*', '', buttons_text, flags=re.IGNORECASE).strip()
|
||||
|
||||
if not buttons_text:
|
||||
return clean_text, None
|
||||
@@ -186,9 +197,7 @@ def parse_message_buttons(text: str) -> tuple[str, InlineKeyboardMarkup | None]:
|
||||
|
||||
for line in button_lines:
|
||||
try:
|
||||
cleaned_line = re.sub(r'<tg-emoji emoji-id="[^"]*">([^<]*)</tg-emoji>', r"\1", line)
|
||||
|
||||
button_data = json.loads(cleaned_line)
|
||||
button_data = json.loads(line)
|
||||
|
||||
if not isinstance(button_data, dict) or "text" not in button_data:
|
||||
logger.warning(f"Неверный формат кнопки: {line}")
|
||||
@@ -307,6 +316,21 @@ async def handle_message_input(message: Message, state: FSMContext, session: Asy
|
||||
cluster_name = data.get("cluster_name")
|
||||
_, user_count = await get_recipients(session, send_to, cluster_name)
|
||||
|
||||
if keyboard:
|
||||
try:
|
||||
keyboard_dict = keyboard.model_dump()
|
||||
InlineKeyboardMarkup.model_validate(keyboard_dict)
|
||||
except Exception as e:
|
||||
await message.answer(
|
||||
f"❌ <b>Ошибка в клавиатуре!</b>\n\n"
|
||||
f"Не удалось сохранить клавиатуру из указанных кнопок.\n"
|
||||
f"Ошибка: {str(e)}\n\n"
|
||||
f"Пожалуйста, проверьте формат кнопок и попробуйте снова.",
|
||||
reply_markup=build_admin_back_kb("sender"),
|
||||
)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
await state.update_data(text=clean_text, photo=photo, keyboard=keyboard.model_dump() if keyboard else None)
|
||||
await state.set_state(AdminSender.preview)
|
||||
|
||||
@@ -343,9 +367,33 @@ async def handle_send_confirm(callback_query: CallbackQuery, state: FSMContext,
|
||||
keyboard = InlineKeyboardMarkup.model_validate(keyboard_data)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка восстановления клавиатуры: {e}")
|
||||
await callback_query.message.edit_text(
|
||||
f"❌ <b>Ошибка восстановления клавиатуры!</b>\n\n"
|
||||
f"Не удалось восстановить клавиатуру из сохраненных данных.\n"
|
||||
f"Ошибка: {str(e)}\n\n"
|
||||
f"Пожалуйста, создайте рассылку заново.",
|
||||
reply_markup=build_admin_back_kb("sender"),
|
||||
)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
tg_ids, total_users = await get_recipients(session, send_to, cluster_name)
|
||||
|
||||
if keyboard:
|
||||
try:
|
||||
keyboard.model_dump()
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка валидации клавиатуры перед рассылкой: {e}")
|
||||
await callback_query.message.edit_text(
|
||||
f"❌ <b>Ошибка валидации клавиатуры!</b>\n\n"
|
||||
f"Клавиатура не прошла финальную проверку перед рассылкой.\n"
|
||||
f"Ошибка: {str(e)}\n\n"
|
||||
f"Пожалуйста, создайте рассылку заново.",
|
||||
reply_markup=build_admin_back_kb("sender"),
|
||||
)
|
||||
await state.clear()
|
||||
return
|
||||
|
||||
await callback_query.message.edit_text(f"📤 <b>Рассылка начата!</b>\n👥 Количество получателей: {total_users}")
|
||||
|
||||
messages = []
|
||||
|
||||
@@ -486,11 +486,7 @@ async def finalize_key_creation(
|
||||
)
|
||||
|
||||
if not remnawave_link:
|
||||
if bool(MODES_CONFIG.get("HAPP_CRYPTOLINK_ENABLED", HAPP_CRYPTOLINK)):
|
||||
happ = sub.get("happ") or {}
|
||||
remnawave_link = happ.get("cryptoLink") or happ.get("link")
|
||||
if not remnawave_link:
|
||||
remnawave_link = sub.get("subscriptionUrl")
|
||||
remnawave_link = sub.get("subscriptionUrl")
|
||||
|
||||
if old_key_name:
|
||||
await session.execute(
|
||||
|
||||
@@ -172,6 +172,9 @@ async def make_aggregated_link(
|
||||
):
|
||||
logger.info("[agg_link] choose override Remnawave (non-vless)")
|
||||
return remna_link_override
|
||||
if sub_url and sub_url.startswith("happ://"):
|
||||
logger.info("[agg_link] choose Remnawave cryptoLink (non-vless)")
|
||||
return sub_url
|
||||
kd = await get_key_details(session, email)
|
||||
stored = kd.get("remnawave_link") if kd else None
|
||||
if stored:
|
||||
|
||||
@@ -115,6 +115,7 @@ async def create_key_on_cluster(
|
||||
remnawave_created = False
|
||||
remnawave_key = None
|
||||
remnawave_client_id = None
|
||||
remnawave_link_value = None
|
||||
|
||||
if remnawave_servers:
|
||||
remna = RemnawaveAPI(remnawave_servers[0]["api_url"])
|
||||
@@ -146,38 +147,15 @@ async def create_key_on_cluster(
|
||||
if result:
|
||||
remnawave_created = True
|
||||
remnawave_client_id = result.get("uuid")
|
||||
link_vless = None
|
||||
remnawave_link_value = result.get("subscriptionUrl")
|
||||
|
||||
remnawave_key = None
|
||||
if need_vless_key:
|
||||
try:
|
||||
link_vless = await get_vless_link_for_remnawave_by_username(remna, email, email)
|
||||
remnawave_key = await get_vless_link_for_remnawave_by_username(remna, email, email)
|
||||
except Exception as e:
|
||||
logger.error(f"{PANEL_REMNA} Ошибка сборки VLESS: {e}")
|
||||
|
||||
base_use_crypto_link = bool(
|
||||
MODES_CONFIG.get("HAPP_CRYPTOLINK_ENABLED", HAPP_CRYPTOLINK)
|
||||
)
|
||||
use_crypto_link = base_use_crypto_link
|
||||
try:
|
||||
hook_results = await run_hooks(
|
||||
"happ_cryptolink_override",
|
||||
cluster_id=cluster_id,
|
||||
plan=plan,
|
||||
session=session,
|
||||
email=email,
|
||||
tg_id=tg_id,
|
||||
happ_cryptolink=base_use_crypto_link,
|
||||
)
|
||||
if hook_results:
|
||||
for hook_result in hook_results:
|
||||
if hook_result is True or hook_result is False:
|
||||
use_crypto_link = hook_result
|
||||
break
|
||||
except Exception as e:
|
||||
logger.warning(f"[HAPP_CRYPTOLINK_OVERRIDE] Ошибка при применении хуков: {e}")
|
||||
|
||||
remnawave_key = link_vless or (
|
||||
result["happ"]["cryptoLink"] if use_crypto_link else result.get("subscriptionUrl")
|
||||
)
|
||||
|
||||
logger.info(f"{PANEL_REMNA} Пользователь создан: {result}")
|
||||
else:
|
||||
logger.warning(f"{PANEL_REMNA} Нет inbound_id у серверов")
|
||||
@@ -246,7 +224,7 @@ async def create_key_on_cluster(
|
||||
expiry_time=expiry_timestamp,
|
||||
key=public_link,
|
||||
server_id=server_id_to_store,
|
||||
remnawave_link=remnawave_key,
|
||||
remnawave_link=remnawave_link_value if remnawave_created else None,
|
||||
tariff_id=plan,
|
||||
)
|
||||
await session.execute(update(User).where(User.tg_id == tg_id, User.trial.in_([0, -1])).values(trial=1))
|
||||
|
||||
@@ -287,6 +287,24 @@ async def renew_key_in_cluster(
|
||||
await update_key_expiry(session, client_id, new_expiry_time)
|
||||
for prefix in ["key_24h", "key_10h", "key_expired", "renew"]:
|
||||
await delete_notification(session, tg_id, f"{email}_{prefix}")
|
||||
|
||||
try:
|
||||
key_link = await make_aggregated_link(
|
||||
session=session,
|
||||
cluster_all=cluster_scope,
|
||||
cluster_id=cluster_id,
|
||||
email=email,
|
||||
client_id=client_id,
|
||||
tg_id=tg_id,
|
||||
subgroup_code=target_subgroup,
|
||||
remna_link_override=None,
|
||||
plan=plan,
|
||||
)
|
||||
if key_link:
|
||||
await update_key_link(session, email, key_link)
|
||||
except Exception as le:
|
||||
logger.warning(f"[Link] ошибка генерации/сохранения после продления: {le}")
|
||||
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -6,7 +6,7 @@ from sqlalchemy import delete, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from config import PUBLIC_LINK, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD, SUPERNODE
|
||||
from database import filter_cluster_by_subgroup, get_servers, store_key
|
||||
from database import filter_cluster_by_subgroup, get_servers, get_tariff_by_id, store_key
|
||||
from database.models import Key, Tariff
|
||||
from handlers.utils import get_least_loaded_cluster
|
||||
from logger import (
|
||||
@@ -62,6 +62,7 @@ async def update_key_on_cluster(
|
||||
|
||||
remnawave_client_id = None
|
||||
remnawave_key = None
|
||||
remnawave_link_value = None
|
||||
|
||||
if remnawave_servers:
|
||||
inbound_ids = [s["inbound_id"] for s in remnawave_servers if s.get("inbound_id")]
|
||||
@@ -104,7 +105,9 @@ async def update_key_on_cluster(
|
||||
result = await remna.create_user(user_data)
|
||||
if result:
|
||||
remnawave_client_id = result.get("uuid")
|
||||
remnawave_key = result.get("subscriptionUrl")
|
||||
remnawave_link_value = result.get("subscriptionUrl")
|
||||
remnawave_key = None
|
||||
|
||||
logger.info(f"{PANEL_REMNA} Клиент заново создан, uuid={remnawave_client_id}")
|
||||
else:
|
||||
logger.error(f"{PANEL_REMNA} Ошибка создания клиента")
|
||||
@@ -162,7 +165,7 @@ async def update_key_on_cluster(
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
logger.info(f"[Update] Ключ {remnawave_client_id} обновлён на серверах подгруппы в {cluster_id}")
|
||||
return remnawave_client_id, remnawave_key
|
||||
return remnawave_client_id, remnawave_link_value
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[Update Error] Ошибка при обновлении ключа {client_id} на {cluster_id}: {e}")
|
||||
@@ -246,7 +249,7 @@ async def update_subscription(
|
||||
traffic_limit = int(tariff.traffic_limit) if tariff.traffic_limit is not None else None
|
||||
device_limit = int(tariff.device_limit) if tariff.device_limit is not None else 0
|
||||
|
||||
new_client_id, remnawave_key = await update_key_on_cluster(
|
||||
new_client_id, remnawave_link_value = await update_key_on_cluster(
|
||||
tg_id=tg_id,
|
||||
client_id=client_id,
|
||||
email=email,
|
||||
@@ -267,7 +270,7 @@ async def update_subscription(
|
||||
client_id=new_client_id,
|
||||
tg_id=tg_id,
|
||||
subgroup_code=subgroup_code,
|
||||
remna_link_override=remnawave_key,
|
||||
remna_link_override=None,
|
||||
plan=tariff_id,
|
||||
)
|
||||
|
||||
@@ -280,7 +283,7 @@ async def update_subscription(
|
||||
email=email,
|
||||
expiry_time=expiry_time,
|
||||
key=final_key_link,
|
||||
remnawave_link=remnawave_key,
|
||||
remnawave_link=remnawave_link_value or remnawave_link,
|
||||
server_id=new_cluster_id,
|
||||
tariff_id=tariff_id,
|
||||
alias=alias,
|
||||
|
||||
Reference in New Issue
Block a user