migration between external squads/ make format
This commit is contained in:
@@ -105,8 +105,9 @@ async def handle_key_edit(
|
|||||||
is_configurable = False
|
is_configurable = False
|
||||||
if key_obj.tariff_id:
|
if key_obj.tariff_id:
|
||||||
result = await session.execute(
|
result = await session.execute(
|
||||||
select(Tariff.name, Tariff.subgroup_title, Tariff.device_limit, Tariff.traffic_limit, Tariff.configurable)
|
select(
|
||||||
.where(Tariff.id == key_obj.tariff_id)
|
Tariff.name, Tariff.subgroup_title, Tariff.device_limit, Tariff.traffic_limit, Tariff.configurable
|
||||||
|
).where(Tariff.id == key_obj.tariff_id)
|
||||||
)
|
)
|
||||||
row = result.first()
|
row = result.first()
|
||||||
if row:
|
if row:
|
||||||
@@ -122,13 +123,21 @@ async def handle_key_edit(
|
|||||||
sel_dev, cur_dev = key_obj.selected_device_limit, key_obj.current_device_limit
|
sel_dev, cur_dev = key_obj.selected_device_limit, key_obj.current_device_limit
|
||||||
if sel_dev is not None or cur_dev is not None:
|
if sel_dev is not None or cur_dev is not None:
|
||||||
base_dev = sel_dev if sel_dev is not None else (base_devices if base_devices is not None else cur_dev)
|
base_dev = sel_dev if sel_dev is not None else (base_devices if base_devices is not None else cur_dev)
|
||||||
extra = f" + {cur_dev - base_dev} (докуплено)" if (base_dev is not None and cur_dev is not None and cur_dev > base_dev) else ""
|
extra = (
|
||||||
|
f" + {cur_dev - base_dev} (докуплено)"
|
||||||
|
if (base_dev is not None and cur_dev is not None and cur_dev > base_dev)
|
||||||
|
else ""
|
||||||
|
)
|
||||||
devices_line = f"📱 <b>Устройства:</b> {base_dev}{extra}\n"
|
devices_line = f"📱 <b>Устройства:</b> {base_dev}{extra}\n"
|
||||||
|
|
||||||
sel_traf, cur_traf = key_obj.selected_traffic_limit, key_obj.current_traffic_limit
|
sel_traf, cur_traf = key_obj.selected_traffic_limit, key_obj.current_traffic_limit
|
||||||
if sel_traf is not None or cur_traf is not None:
|
if sel_traf is not None or cur_traf is not None:
|
||||||
base_traf = sel_traf if sel_traf is not None else (base_traffic if base_traffic is not None else cur_traf)
|
base_traf = sel_traf if sel_traf is not None else (base_traffic if base_traffic is not None else cur_traf)
|
||||||
extra = f" + {cur_traf - base_traf} ГБ (докуплено)" if (base_traf is not None and cur_traf is not None and cur_traf > base_traf) else ""
|
extra = (
|
||||||
|
f" + {cur_traf - base_traf} ГБ (докуплено)"
|
||||||
|
if (base_traf is not None and cur_traf is not None and cur_traf > base_traf)
|
||||||
|
else ""
|
||||||
|
)
|
||||||
traffic_line = f"📊 <b>Трафик:</b> {base_traf} ГБ{extra}\n"
|
traffic_line = f"📊 <b>Трафик:</b> {base_traf} ГБ{extra}\n"
|
||||||
|
|
||||||
text = (
|
text = (
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ from hooks.processors import (
|
|||||||
process_purchase_tariff_group_override,
|
process_purchase_tariff_group_override,
|
||||||
process_tariff_menu,
|
process_tariff_menu,
|
||||||
)
|
)
|
||||||
from .utils import add_tariff_button_generic
|
|
||||||
from logger import logger
|
from logger import logger
|
||||||
|
|
||||||
from .key_mode.key_cluster_mode import key_cluster_mode
|
from .key_mode.key_cluster_mode import key_cluster_mode
|
||||||
from .key_mode.key_country_mode import key_country_mode
|
from .key_mode.key_country_mode import key_country_mode
|
||||||
|
from .utils import add_tariff_button_generic
|
||||||
|
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
|
|||||||
@@ -95,9 +95,7 @@ async def key_country_mode(
|
|||||||
if state and plan:
|
if state and plan:
|
||||||
await state.update_data(tariff_id=plan)
|
await state.update_data(tariff_id=plan)
|
||||||
|
|
||||||
if state and any(
|
if state and any(value is not None for value in (selected_device_limit, selected_traffic_gb, selected_price_rub)):
|
||||||
value is not None for value in (selected_device_limit, selected_traffic_gb, selected_price_rub)
|
|
||||||
):
|
|
||||||
data = await state.get_data()
|
data = await state.get_data()
|
||||||
if selected_device_limit is not None:
|
if selected_device_limit is not None:
|
||||||
data["config_selected_device_limit"] = selected_device_limit
|
data["config_selected_device_limit"] = selected_device_limit
|
||||||
|
|||||||
@@ -53,9 +53,10 @@ from hooks.processors import (
|
|||||||
process_renewal_complete,
|
process_renewal_complete,
|
||||||
process_renewal_forbidden_groups,
|
process_renewal_forbidden_groups,
|
||||||
)
|
)
|
||||||
from .utils import add_tariff_button_generic
|
|
||||||
from logger import logger
|
from logger import logger
|
||||||
|
|
||||||
|
from .utils import add_tariff_button_generic
|
||||||
|
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
moscow_tz = pytz.timezone("Europe/Moscow")
|
moscow_tz = pytz.timezone("Europe/Moscow")
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ from database import (
|
|||||||
filter_cluster_by_subgroup,
|
filter_cluster_by_subgroup,
|
||||||
get_key_details,
|
get_key_details,
|
||||||
get_servers,
|
get_servers,
|
||||||
|
get_tariff_by_id,
|
||||||
resolve_device_limit_from_group,
|
resolve_device_limit_from_group,
|
||||||
update_key_expiry,
|
update_key_expiry,
|
||||||
update_key_link,
|
update_key_link,
|
||||||
get_tariff_by_id,
|
|
||||||
)
|
)
|
||||||
from hooks.processors import process_get_cryptolink_after_renewal
|
from hooks.processors import process_get_cryptolink_after_renewal
|
||||||
from logger import (
|
from logger import (
|
||||||
@@ -57,7 +57,6 @@ async def renew_on_remnawave(
|
|||||||
target_server_name: str | None = None,
|
target_server_name: str | None = None,
|
||||||
external_squad_uuid: str | None = None,
|
external_squad_uuid: str | None = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Продлевает подписку на Remnawave-узлах кластера."""
|
|
||||||
remnawave_nodes = [
|
remnawave_nodes = [
|
||||||
s for s in cluster if str(s.get("panel_type", "3x-ui")).lower() == "remnawave" and s.get("inbound_id")
|
s for s in cluster if str(s.get("panel_type", "3x-ui")).lower() == "remnawave" and s.get("inbound_id")
|
||||||
]
|
]
|
||||||
@@ -67,23 +66,24 @@ async def renew_on_remnawave(
|
|||||||
remnawave_nodes = [s for s in remnawave_nodes if s.get("server_name") == target_server_name] or remnawave_nodes[
|
remnawave_nodes = [s for s in remnawave_nodes if s.get("server_name") == target_server_name] or remnawave_nodes[
|
||||||
:1
|
:1
|
||||||
]
|
]
|
||||||
|
|
||||||
remna = RemnawaveAPI(remnawave_nodes[0]["api_url"])
|
remna = RemnawaveAPI(remnawave_nodes[0]["api_url"])
|
||||||
if not await remna.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD):
|
if not await remna.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD):
|
||||||
logger.error(f"{PANEL_REMNA} Не удалось войти в Remnawave API")
|
logger.error(f"{PANEL_REMNA} Не удалось войти в Remnawave API")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
expire_iso = datetime.utcfromtimestamp(new_expiry_time // 1000).isoformat() + "Z"
|
expire_iso = datetime.utcfromtimestamp(new_expiry_time // 1000).isoformat() + "Z"
|
||||||
traffic_limit_bytes = total_gb * 1024 * 1024 * 1024 if total_gb else 0
|
traffic_limit_bytes = total_gb * 1024 * 1024 * 1024 if total_gb else 0
|
||||||
active_inbounds = [s["inbound_id"] for s in remnawave_nodes]
|
active_inbounds = [s["inbound_id"] for s in remnawave_nodes]
|
||||||
|
|
||||||
update_kwargs = dict(
|
update_kwargs = {
|
||||||
uuid=client_id,
|
"uuid": client_id,
|
||||||
expire_at=expire_iso,
|
"expire_at": expire_iso,
|
||||||
active_user_inbounds=active_inbounds,
|
"active_user_inbounds": active_inbounds,
|
||||||
traffic_limit_bytes=traffic_limit_bytes,
|
"traffic_limit_bytes": traffic_limit_bytes,
|
||||||
hwid_device_limit=hwid_device_limit,
|
"hwid_device_limit": hwid_device_limit,
|
||||||
)
|
"external_squad_uuid": external_squad_uuid,
|
||||||
if external_squad_uuid:
|
}
|
||||||
update_kwargs["external_squad_uuid"] = external_squad_uuid
|
|
||||||
|
|
||||||
updated = await remna.update_user(**update_kwargs)
|
updated = await remna.update_user(**update_kwargs)
|
||||||
if updated:
|
if updated:
|
||||||
@@ -222,7 +222,11 @@ async def renew_key_in_cluster(
|
|||||||
if plan is not None:
|
if plan is not None:
|
||||||
tariff = await get_tariff_by_id(session, plan)
|
tariff = await get_tariff_by_id(session, plan)
|
||||||
if tariff:
|
if tariff:
|
||||||
external_squad_uuid = tariff.get("external_squad")
|
raw_external_squad = tariff.get("external_squad")
|
||||||
|
if raw_external_squad:
|
||||||
|
external_squad_uuid = raw_external_squad
|
||||||
|
else:
|
||||||
|
external_squad_uuid = ""
|
||||||
is_configurable = tariff.get("configurable", False)
|
is_configurable = tariff.get("configurable", False)
|
||||||
if not is_configurable:
|
if not is_configurable:
|
||||||
tariff_device_limit = tariff.get("device_limit")
|
tariff_device_limit = tariff.get("device_limit")
|
||||||
@@ -247,6 +251,7 @@ async def renew_key_in_cluster(
|
|||||||
reset_traffic=reset_traffic,
|
reset_traffic=reset_traffic,
|
||||||
old_subgroup=old_subgroup,
|
old_subgroup=old_subgroup,
|
||||||
target_subgroup=target_subgroup,
|
target_subgroup=target_subgroup,
|
||||||
|
external_squad_uuid=external_squad_uuid,
|
||||||
)
|
)
|
||||||
|
|
||||||
await update_key_expiry(session, new_client_id or client_id, new_expiry_time)
|
await update_key_expiry(session, new_client_id or client_id, new_expiry_time)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ async def ensure_on_remnawave(
|
|||||||
hwid_device_limit: int,
|
hwid_device_limit: int,
|
||||||
reset_traffic: bool,
|
reset_traffic: bool,
|
||||||
attempt_update_first: bool,
|
attempt_update_first: bool,
|
||||||
|
external_squad_uuid: str | None = None,
|
||||||
) -> tuple[str | None, str | None]:
|
) -> tuple[str | None, str | None]:
|
||||||
if not servers:
|
if not servers:
|
||||||
return None, None
|
return None, None
|
||||||
@@ -74,6 +75,7 @@ async def ensure_on_remnawave(
|
|||||||
active_user_inbounds=inbounds,
|
active_user_inbounds=inbounds,
|
||||||
traffic_limit_bytes=traffic_bytes,
|
traffic_limit_bytes=traffic_bytes,
|
||||||
hwid_device_limit=hwid_device_limit,
|
hwid_device_limit=hwid_device_limit,
|
||||||
|
external_squad_uuid=external_squad_uuid,
|
||||||
)
|
)
|
||||||
if not updated:
|
if not updated:
|
||||||
return None, None
|
return None, None
|
||||||
@@ -113,6 +115,8 @@ async def ensure_on_remnawave(
|
|||||||
if traffic_bytes > 0:
|
if traffic_bytes > 0:
|
||||||
payload["trafficLimitBytes"] = traffic_bytes
|
payload["trafficLimitBytes"] = traffic_bytes
|
||||||
payload["hwidDeviceLimit"] = hwid_device_limit
|
payload["hwidDeviceLimit"] = hwid_device_limit
|
||||||
|
if external_squad_uuid is not None:
|
||||||
|
payload["externalSquadUuid"] = external_squad_uuid or None
|
||||||
|
|
||||||
created = await api.create_user(payload)
|
created = await api.create_user(payload)
|
||||||
if not created:
|
if not created:
|
||||||
@@ -237,6 +241,7 @@ async def migrate_between_subgroups(
|
|||||||
reset_traffic: bool,
|
reset_traffic: bool,
|
||||||
old_subgroup: str,
|
old_subgroup: str,
|
||||||
target_subgroup: str,
|
target_subgroup: str,
|
||||||
|
external_squad_uuid: str | None = None,
|
||||||
) -> tuple[str, str | None]:
|
) -> tuple[str, str | None]:
|
||||||
target = await filter_cluster_by_subgroup(session, cluster_all, target_subgroup, cluster_id)
|
target = await filter_cluster_by_subgroup(session, cluster_all, target_subgroup, cluster_id)
|
||||||
xui_tgt, remna_tgt = split_by_panel(target)
|
xui_tgt, remna_tgt = split_by_panel(target)
|
||||||
@@ -293,6 +298,7 @@ async def migrate_between_subgroups(
|
|||||||
hwid_device_limit=hwid_device_limit,
|
hwid_device_limit=hwid_device_limit,
|
||||||
reset_traffic=reset_traffic,
|
reset_traffic=reset_traffic,
|
||||||
attempt_update_first=was_on_remna_before,
|
attempt_update_first=was_on_remna_before,
|
||||||
|
external_squad_uuid=external_squad_uuid,
|
||||||
)
|
)
|
||||||
if remna_old_non:
|
if remna_old_non:
|
||||||
await delete_on_remnawave(remna_old_non, client_id)
|
await delete_on_remnawave(remna_old_non, client_id)
|
||||||
@@ -315,6 +321,7 @@ async def migrate_between_subgroups(
|
|||||||
hwid_device_limit=hwid_device_limit,
|
hwid_device_limit=hwid_device_limit,
|
||||||
reset_traffic=reset_traffic,
|
reset_traffic=reset_traffic,
|
||||||
attempt_update_first=was_on_remna_before,
|
attempt_update_first=was_on_remna_before,
|
||||||
|
external_squad_uuid=external_squad_uuid,
|
||||||
)
|
)
|
||||||
|
|
||||||
if remna_old_non:
|
if remna_old_non:
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
DEFAULT_HOOK_TIMEOUT = 4.0
|
DEFAULT_HOOK_TIMEOUT = 4.0
|
||||||
|
|||||||
+5
-2
@@ -49,6 +49,7 @@ async def run_hooks(name: str, require_enabled: bool = True, **kwargs) -> list[A
|
|||||||
if require_enabled and owner:
|
if require_enabled and owner:
|
||||||
try:
|
try:
|
||||||
from utils.modules_manager import manager
|
from utils.modules_manager import manager
|
||||||
|
|
||||||
if not manager.is_enabled(owner):
|
if not manager.is_enabled(owner):
|
||||||
continue
|
continue
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -57,14 +58,16 @@ async def run_hooks(name: str, require_enabled: bool = True, **kwargs) -> list[A
|
|||||||
if inspect.iscoroutinefunction(func):
|
if inspect.iscoroutinefunction(func):
|
||||||
coro = func(**kwargs)
|
coro = func(**kwargs)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
async def _run_sync():
|
async def _run_sync():
|
||||||
return func(**kwargs)
|
return func(**kwargs)
|
||||||
|
|
||||||
coro = _run_sync()
|
coro = _run_sync()
|
||||||
|
|
||||||
result = await asyncio.wait_for(coro, timeout=DEFAULT_HOOK_TIMEOUT)
|
result = await asyncio.wait_for(coro, timeout=DEFAULT_HOOK_TIMEOUT)
|
||||||
if result:
|
if result:
|
||||||
results.append(result)
|
results.append(result)
|
||||||
except asyncio.TimeoutError:
|
except TimeoutError:
|
||||||
logger.error(
|
logger.error(
|
||||||
f"[HOOK:{name}] Таймаут в {getattr(func, '__name__', func)} при timeout={DEFAULT_HOOK_TIMEOUT}",
|
f"[HOOK:{name}] Таймаут в {getattr(func, '__name__', func)} при timeout={DEFAULT_HOOK_TIMEOUT}",
|
||||||
exc_info=True,
|
exc_info=True,
|
||||||
@@ -74,4 +77,4 @@ async def run_hooks(name: str, require_enabled: bool = True, **kwargs) -> list[A
|
|||||||
f"[HOOK:{name}] Ошибка в {getattr(func, '__name__', func)}: {e}",
|
f"[HOOK:{name}] Ошибка в {getattr(func, '__name__', func)}: {e}",
|
||||||
exc_info=True,
|
exc_info=True,
|
||||||
)
|
)
|
||||||
return results
|
return results
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user