ruff format/ minor fixes and improvements
This commit is contained in:
Binary file not shown.
Binary file not shown.
+9
-23
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import delete, exists, or_, select, update, func
|
||||
from sqlalchemy import delete, exists, func, or_, select, update
|
||||
from sqlalchemy.dialects.postgresql import insert
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -11,12 +11,12 @@ from database.models import (
|
||||
CouponUsage,
|
||||
Gift,
|
||||
GiftUsage,
|
||||
Key,
|
||||
Notification,
|
||||
Payment,
|
||||
Referral,
|
||||
TemporaryData,
|
||||
User,
|
||||
Key,
|
||||
)
|
||||
from logger import logger
|
||||
|
||||
@@ -81,17 +81,13 @@ async def check_user_exists(session: AsyncSession, tg_id: int) -> bool:
|
||||
|
||||
|
||||
async def get_balance(session: AsyncSession, tg_id: int) -> float:
|
||||
result = await session.execute(
|
||||
select(func.coalesce(User.balance, 0.0)).where(User.tg_id == tg_id)
|
||||
)
|
||||
result = await session.execute(select(func.coalesce(User.balance, 0.0)).where(User.tg_id == tg_id))
|
||||
return round(float(result.scalar_one()), 1)
|
||||
|
||||
|
||||
async def set_user_balance(session: AsyncSession, tg_id: int, balance: float) -> None:
|
||||
try:
|
||||
await session.execute(
|
||||
update(User).where(User.tg_id == tg_id).values(balance=balance)
|
||||
)
|
||||
await session.execute(update(User).where(User.tg_id == tg_id).values(balance=balance))
|
||||
await session.commit()
|
||||
except SQLAlchemyError as e:
|
||||
logger.error(f"Ошибка при установке баланса для пользователя {tg_id}: {e}")
|
||||
@@ -100,9 +96,7 @@ async def set_user_balance(session: AsyncSession, tg_id: int, balance: float) ->
|
||||
|
||||
async def update_trial(session: AsyncSession, tg_id: int, status: int):
|
||||
try:
|
||||
await session.execute(
|
||||
update(User).where(User.tg_id == tg_id).values(trial=status)
|
||||
)
|
||||
await session.execute(update(User).where(User.tg_id == tg_id).values(trial=status))
|
||||
await session.commit()
|
||||
logger.info(f"[DB] Триал статус обновлён для пользователя {tg_id}: {status}")
|
||||
except SQLAlchemyError as e:
|
||||
@@ -111,9 +105,7 @@ async def update_trial(session: AsyncSession, tg_id: int, status: int):
|
||||
|
||||
|
||||
async def get_trial(session: AsyncSession, tg_id: int) -> int:
|
||||
result = await session.execute(
|
||||
select(func.coalesce(User.trial, 0)).where(User.tg_id == tg_id)
|
||||
)
|
||||
result = await session.execute(select(func.coalesce(User.trial, 0)).where(User.tg_id == tg_id))
|
||||
return int(result.scalar_one())
|
||||
|
||||
|
||||
@@ -189,19 +181,13 @@ async def delete_user_data(session: AsyncSession, tg_id: int):
|
||||
try:
|
||||
await session.execute(delete(Notification).where(Notification.tg_id == tg_id))
|
||||
await session.execute(
|
||||
delete(GiftUsage).where(
|
||||
GiftUsage.gift_id.in_(select(Gift.gift_id).where(Gift.sender_tg_id == tg_id))
|
||||
)
|
||||
delete(GiftUsage).where(GiftUsage.gift_id.in_(select(Gift.gift_id).where(Gift.sender_tg_id == tg_id)))
|
||||
)
|
||||
await session.execute(delete(Gift).where(Gift.sender_tg_id == tg_id))
|
||||
await session.execute(
|
||||
update(Gift).where(Gift.recipient_tg_id == tg_id).values(recipient_tg_id=None)
|
||||
)
|
||||
await session.execute(update(Gift).where(Gift.recipient_tg_id == tg_id).values(recipient_tg_id=None))
|
||||
await session.execute(delete(Payment).where(Payment.tg_id == tg_id))
|
||||
await session.execute(
|
||||
delete(Referral).where(
|
||||
or_(Referral.referrer_tg_id == tg_id, Referral.referred_tg_id == tg_id)
|
||||
)
|
||||
delete(Referral).where(or_(Referral.referrer_tg_id == tg_id, Referral.referred_tg_id == tg_id))
|
||||
)
|
||||
await session.execute(delete(CouponUsage).where(CouponUsage.user_id == tg_id))
|
||||
await delete_key(session, tg_id)
|
||||
|
||||
@@ -537,7 +537,7 @@ async def handle_sync_server(
|
||||
expire_iso = (
|
||||
datetime.utcfromtimestamp(key["expiry_time"] / 1000).replace(tzinfo=timezone.utc).isoformat()
|
||||
)
|
||||
|
||||
|
||||
remna = RemnawaveAPI(key["api_url"])
|
||||
if not await remna.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD):
|
||||
logger.error(f"Не удалось авторизоваться в Remnawave для сервера {server_name}")
|
||||
@@ -561,7 +561,7 @@ async def handle_sync_server(
|
||||
traffic_limit_bytes=traffic_limit_bytes,
|
||||
hwid_device_limit=hwid_limit,
|
||||
)
|
||||
|
||||
|
||||
if not success:
|
||||
logger.warning("[Sync] ошибка обновления, пробуем пересоздать")
|
||||
|
||||
@@ -673,7 +673,9 @@ async def handle_sync_cluster(
|
||||
|
||||
filtered_servers = cluster_servers
|
||||
if subgroup_title:
|
||||
filtered_servers = [s for s in cluster_servers if subgroup_title in s.get("tariff_subgroups", [])]
|
||||
filtered_servers = [
|
||||
s for s in cluster_servers if subgroup_title in s.get("tariff_subgroups", [])
|
||||
]
|
||||
if not filtered_servers:
|
||||
logger.warning(
|
||||
f"[Sync] В кластере {cluster_name} не найдено серверов для подгруппы '{subgroup_title}'. Использую весь кластер."
|
||||
|
||||
@@ -23,7 +23,9 @@ async def build_panel_kb(admin_role: str) -> InlineKeyboardMarkup:
|
||||
builder = InlineKeyboardBuilder()
|
||||
|
||||
builder.row(
|
||||
InlineKeyboardButton(text="👤 Поиск пользователя", callback_data=AdminPanelCallback(action="search_user").pack()),
|
||||
InlineKeyboardButton(
|
||||
text="👤 Поиск пользователя", callback_data=AdminPanelCallback(action="search_user").pack()
|
||||
),
|
||||
InlineKeyboardButton(text="🔑 Поиск подписок", callback_data=AdminPanelCallback(action="search_key").pack()),
|
||||
)
|
||||
|
||||
|
||||
@@ -137,14 +137,14 @@ async def process_callback_delete_server(
|
||||
builder = InlineKeyboardBuilder()
|
||||
for s_name, key_count in all_servers:
|
||||
callback_data = f"transfer_to_server|{s_name}|{server_name}"
|
||||
if len(callback_data.encode('utf-8')) > 64:
|
||||
if len(callback_data.encode("utf-8")) > 64:
|
||||
await callback_query.message.edit_text(
|
||||
text=f"❌ Ошибка: название сервера '{s_name}' слишком длинное.\n\n"
|
||||
f"Пожалуйста, переименуйте сервер в более короткое название и попробуйте снова.",
|
||||
f"Пожалуйста, переименуйте сервер в более короткое название и попробуйте снова.",
|
||||
reply_markup=build_admin_back_kb("clusters"),
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=f"{s_name} ({key_count})",
|
||||
@@ -199,14 +199,14 @@ async def process_callback_delete_server(
|
||||
builder = InlineKeyboardBuilder()
|
||||
for cl_name, key_count in all_clusters:
|
||||
callback_data = f"transfer_to_cluster|{cl_name}|{cluster_name}|{server_name}"
|
||||
if len(callback_data.encode('utf-8')) > 64:
|
||||
if len(callback_data.encode("utf-8")) > 64:
|
||||
await callback_query.message.edit_text(
|
||||
text=f"❌ Ошибка: название сервера '{server_name}' или кластера '{cl_name}' слишком длинное.\n\n"
|
||||
f"Пожалуйста, переименуйте сервер в более короткое название и попробуйте снова.",
|
||||
f"Пожалуйста, переименуйте сервер в более короткое название и попробуйте снова.",
|
||||
reply_markup=build_admin_back_kb("clusters"),
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=f"{cl_name} ({key_count})",
|
||||
@@ -448,7 +448,7 @@ async def apply_field_edit(message: types.Message, state: FSMContext, session: A
|
||||
reply_markup=build_admin_back_kb("clusters"),
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
success = await update_server_name_with_keys(session, server_name, value)
|
||||
if success:
|
||||
server_name = value
|
||||
|
||||
@@ -1226,7 +1226,9 @@ async def change_expiry_time(expiry_time: int, email: str, session: AsyncSession
|
||||
key_subgroup = None
|
||||
if tariff_id:
|
||||
result = await session.execute(
|
||||
select(Tariff.traffic_limit, Tariff.device_limit, Tariff.subgroup_title).where(Tariff.id == tariff_id, Tariff.is_active.is_(True))
|
||||
select(Tariff.traffic_limit, Tariff.device_limit, Tariff.subgroup_title).where(
|
||||
Tariff.id == tariff_id, Tariff.is_active.is_(True)
|
||||
)
|
||||
)
|
||||
tariff = result.first()
|
||||
if tariff:
|
||||
@@ -1234,7 +1236,6 @@ async def change_expiry_time(expiry_time: int, email: str, session: AsyncSession
|
||||
device_limit = int(tariff[1]) if tariff[1] is not None else 0
|
||||
key_subgroup = tariff[2]
|
||||
|
||||
|
||||
servers = await get_servers(session=session)
|
||||
|
||||
if server_id in servers:
|
||||
|
||||
+1
-1
@@ -227,7 +227,7 @@ async def handle_key_extension(
|
||||
|
||||
key_subgroup = None
|
||||
if tariff:
|
||||
key_subgroup = tariff.get('subgroup_title')
|
||||
key_subgroup = tariff.get("subgroup_title")
|
||||
|
||||
await renew_key_in_cluster(
|
||||
cluster_id=key.server_id,
|
||||
|
||||
@@ -38,7 +38,17 @@ from database import (
|
||||
update_trial,
|
||||
)
|
||||
from database.models import Key, Server, Tariff
|
||||
from handlers.buttons import BACK, CONNECT_DEVICE, CONNECT_PHONE, MAIN_MENU, MY_SUB, PC_BUTTON, SUPPORT, TV_BUTTON, ROUTER_BUTTON
|
||||
from handlers.buttons import (
|
||||
BACK,
|
||||
CONNECT_DEVICE,
|
||||
CONNECT_PHONE,
|
||||
MAIN_MENU,
|
||||
MY_SUB,
|
||||
PC_BUTTON,
|
||||
ROUTER_BUTTON,
|
||||
SUPPORT,
|
||||
TV_BUTTON,
|
||||
)
|
||||
from handlers.keys.operations import create_client_on_server
|
||||
from handlers.keys.operations.aggregated_links import make_aggregated_link
|
||||
from handlers.texts import SELECT_COUNTRY_MSG, key_message_success
|
||||
@@ -509,14 +519,16 @@ async def finalize_key_creation(
|
||||
)
|
||||
|
||||
subgroup_code = tariff.subgroup_title if tariff and tariff.subgroup_title else None
|
||||
cluster_all = [{
|
||||
"server_name": server_info.server_name,
|
||||
"api_url": server_info.api_url,
|
||||
"panel_type": server_info.panel_type,
|
||||
"inbound_id": getattr(server_info, "inbound_id", None),
|
||||
"enabled": True,
|
||||
"max_keys": getattr(server_info, "max_keys", None),
|
||||
}]
|
||||
cluster_all = [
|
||||
{
|
||||
"server_name": server_info.server_name,
|
||||
"api_url": server_info.api_url,
|
||||
"panel_type": server_info.panel_type,
|
||||
"inbound_id": getattr(server_info, "inbound_id", None),
|
||||
"enabled": True,
|
||||
"max_keys": getattr(server_info, "max_keys", None),
|
||||
}
|
||||
]
|
||||
|
||||
link_to_show = await make_aggregated_link(
|
||||
session=session,
|
||||
@@ -575,7 +587,11 @@ async def finalize_key_creation(
|
||||
is_full_remnawave = await is_full_remnawave_cluster(cluster_name, session)
|
||||
is_vless = bool(public_link and public_link.lower().startswith("vless://")) or bool(need_vless_key)
|
||||
final_link = public_link or remnawave_link
|
||||
webapp_url = final_link if isinstance(final_link, str) and final_link.strip().lower().startswith(("http://", "https://")) else None
|
||||
webapp_url = (
|
||||
final_link
|
||||
if isinstance(final_link, str) and final_link.strip().lower().startswith(("http://", "https://"))
|
||||
else None
|
||||
)
|
||||
|
||||
if panel_type == "remnawave" or is_full_remnawave:
|
||||
if is_vless:
|
||||
|
||||
@@ -77,16 +77,13 @@ async def process_callback_renew_key(callback_query: CallbackQuery, state: FSMCo
|
||||
|
||||
try:
|
||||
hook_commands = await run_hooks(
|
||||
"process_callback_renew_key",
|
||||
callback_query=callback_query,
|
||||
state=state,
|
||||
session=session
|
||||
"process_callback_renew_key", callback_query=callback_query, state=state, session=session
|
||||
)
|
||||
if hook_commands:
|
||||
kb = insert_hook_buttons(kb, hook_commands)
|
||||
except Exception as e:
|
||||
logger.warning(f"[RENEW] Ошибка при применении хуков: {e}")
|
||||
|
||||
|
||||
await edit_or_send_message(
|
||||
target_message=callback_query.message,
|
||||
text=f"Продление доступно с {dt_msk}",
|
||||
|
||||
@@ -134,7 +134,7 @@ async def build_keys_response(records, session):
|
||||
formatted_date_full = "без срока действия"
|
||||
|
||||
is_vless = False
|
||||
if hasattr(record, 'tariff_id') and record.tariff_id:
|
||||
if hasattr(record, "tariff_id") and record.tariff_id:
|
||||
try:
|
||||
tariff = await get_tariff_by_id(session, record.tariff_id)
|
||||
if tariff and tariff.get("vless"):
|
||||
@@ -143,7 +143,7 @@ async def build_keys_response(records, session):
|
||||
pass
|
||||
|
||||
icon = "📶" if is_vless else "🔑"
|
||||
|
||||
|
||||
key_button = InlineKeyboardButton(text=f"{icon} {key_display}", callback_data=f"view_key|{email}")
|
||||
rename_button = InlineKeyboardButton(text=ALIAS, callback_data=f"rename_key|{client_id}")
|
||||
builder.row(key_button, rename_button)
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import asyncio
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from sqlalchemy import delete, select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from config import PUBLIC_LINK, REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD, SUPERNODE
|
||||
from database import get_servers, store_key, filter_cluster_by_subgroup
|
||||
from database import filter_cluster_by_subgroup, get_servers, store_key
|
||||
from database.models import Key, Tariff
|
||||
from handlers.utils import get_least_loaded_cluster
|
||||
from logger import CLOGGER as logger, PANEL_REMNA, PANEL_XUI
|
||||
from logger import (
|
||||
CLOGGER as logger,
|
||||
PANEL_REMNA,
|
||||
PANEL_XUI,
|
||||
)
|
||||
from panels._3xui import ClientConfig, add_client, get_xui_instance
|
||||
from panels.remnawave import RemnawaveAPI
|
||||
|
||||
from .deletion import delete_key_from_cluster
|
||||
from .aggregated_links import make_aggregated_link
|
||||
from .deletion import delete_key_from_cluster
|
||||
|
||||
|
||||
async def update_key_on_cluster(
|
||||
@@ -229,7 +234,9 @@ async def update_subscription(
|
||||
if subgroup_code:
|
||||
prefiltered = await filter_cluster_by_subgroup(session, cluster_servers, subgroup_code, new_cluster_id)
|
||||
if not prefiltered:
|
||||
logger.warning(f"[Update] Пересоздание пропущено: нет серверов под подгруппу {subgroup_code} в {new_cluster_id}.")
|
||||
logger.warning(
|
||||
f"[Update] Пересоздание пропущено: нет серверов под подгруппу {subgroup_code} в {new_cluster_id}."
|
||||
)
|
||||
return
|
||||
cluster_servers = prefiltered
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ def prepare_headers(
|
||||
"announce": "base64:" + base64.b64encode(announce_str.encode("utf-8")).decode("utf-8"),
|
||||
"profile-web-page-url": f"https://t.me/{USERNAME_BOT}",
|
||||
"subscription-userinfo": subscription_userinfo,
|
||||
#"routing": "happ://routing/onadd/...",
|
||||
# "routing": "happ://routing/onadd/...",
|
||||
}
|
||||
elif "Hiddify" in user_agent:
|
||||
parts = subscription_info.split(" - ")[0].split(": ")
|
||||
|
||||
@@ -536,7 +536,7 @@ async def process_auto_renew_or_notify(
|
||||
keyboard = build_notification_kb(email)
|
||||
|
||||
await add_notification(conn, tg_id, notification_id)
|
||||
text_to_send = message_text if 'message_text' in locals() else standard_caption
|
||||
text_to_send = message_text if "message_text" in locals() else standard_caption
|
||||
await send_notification(bot, tg_id, standard_photo, text_to_send, keyboard)
|
||||
return
|
||||
|
||||
@@ -566,7 +566,7 @@ async def process_auto_renew_or_notify(
|
||||
f"Продление подписки {email} на {duration_days} дней для пользователя {tg_id}. Баланс: {balance}, списываем: {renewal_cost}"
|
||||
)
|
||||
|
||||
key_subgroup = selected_tariff.get('subgroup_title')
|
||||
key_subgroup = selected_tariff.get("subgroup_title")
|
||||
|
||||
await renew_key_in_cluster(
|
||||
cluster_id=server_id,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+7
-3
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
|
||||
from typing import Any
|
||||
|
||||
from aiogram import F, Router
|
||||
@@ -6,6 +7,7 @@ from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, InlineKeyboardButton, Message
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from bot import bot
|
||||
@@ -25,6 +27,7 @@ from database import (
|
||||
get_user_snapshot,
|
||||
upsert_source_if_empty,
|
||||
)
|
||||
from database.models import TrackingSource
|
||||
from handlers.buttons import (
|
||||
ABOUT_VPN,
|
||||
BACK,
|
||||
@@ -55,8 +58,7 @@ from logger import logger
|
||||
from .admin.panel.keyboard import AdminPanelCallback
|
||||
from .refferal import handle_referral_link
|
||||
from .utils import edit_or_send_message, extract_user_data
|
||||
from sqlalchemy import select
|
||||
from database.models import TrackingSource
|
||||
|
||||
|
||||
router = Router()
|
||||
processing_gifts = set()
|
||||
@@ -235,7 +237,9 @@ async def show_start_menu(
|
||||
key_cnt = key_count or 0
|
||||
|
||||
show_trial = (trial_status in (-1, 0)) and (not TRIAL_TIME_DISABLE) and (key_cnt == 0)
|
||||
show_profile = (key_cnt > 0) or (((not SHOW_START_MENU_ONCE) or (trial_status not in (-1, 0)) or TRIAL_TIME_DISABLE) and (not show_trial))
|
||||
show_profile = (key_cnt > 0) or (
|
||||
((not SHOW_START_MENU_ONCE) or (trial_status not in (-1, 0)) or TRIAL_TIME_DISABLE) and (not show_trial)
|
||||
)
|
||||
|
||||
if show_trial:
|
||||
kb.row(InlineKeyboardButton(text=TRIAL_SUB, callback_data="create_key"))
|
||||
|
||||
+92
-49
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import html
|
||||
import os
|
||||
import re
|
||||
@@ -5,8 +6,6 @@ import secrets
|
||||
import string
|
||||
|
||||
from collections import OrderedDict
|
||||
import asyncio
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import aiofiles
|
||||
@@ -14,9 +13,9 @@ import aiofiles
|
||||
from aiogram.types import (
|
||||
BufferedInputFile,
|
||||
InlineKeyboardMarkup,
|
||||
InputMediaAnimation,
|
||||
InputMediaPhoto,
|
||||
InputMediaVideo,
|
||||
InputMediaAnimation,
|
||||
Message,
|
||||
)
|
||||
from sqlalchemy import func, select
|
||||
@@ -201,20 +200,20 @@ def format_hours(hours: int) -> str:
|
||||
|
||||
def get_media_type(media_path: str) -> str:
|
||||
if not media_path:
|
||||
return 'photo'
|
||||
|
||||
return "photo"
|
||||
|
||||
ext = os.path.splitext(media_path.lower())[1]
|
||||
|
||||
if ext in ['.jpg', '.jpeg', '.png', '.webp']:
|
||||
return 'photo'
|
||||
if ext in [".jpg", ".jpeg", ".png", ".webp"]:
|
||||
return "photo"
|
||||
|
||||
if ext in ['.mp4', '.mov', '.avi']:
|
||||
return 'video'
|
||||
if ext in [".mp4", ".mov", ".avi"]:
|
||||
return "video"
|
||||
|
||||
if ext == '.gif':
|
||||
return 'animation'
|
||||
|
||||
return 'photo'
|
||||
if ext == ".gif":
|
||||
return "animation"
|
||||
|
||||
return "photo"
|
||||
|
||||
|
||||
async def edit_or_send_message(
|
||||
@@ -227,8 +226,10 @@ async def edit_or_send_message(
|
||||
disable_cache: bool = False,
|
||||
):
|
||||
if not hasattr(edit_or_send_message, "cache"):
|
||||
from collections import OrderedDict
|
||||
import asyncio
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
edit_or_send_message.cache = OrderedDict()
|
||||
edit_or_send_message.lock = asyncio.Lock()
|
||||
edit_or_send_message.max = 256
|
||||
@@ -236,49 +237,70 @@ async def edit_or_send_message(
|
||||
def find_media_file(original_path: str) -> str | None:
|
||||
if not original_path:
|
||||
return None
|
||||
|
||||
|
||||
if os.path.isfile(original_path):
|
||||
return original_path
|
||||
|
||||
base_name = os.path.splitext(original_path)[0]
|
||||
supported_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.mp4', '.mov', '.avi']
|
||||
|
||||
supported_extensions = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".mp4", ".mov", ".avi"]
|
||||
|
||||
for ext in supported_extensions:
|
||||
fallback_path = base_name + ext
|
||||
if os.path.isfile(fallback_path):
|
||||
return fallback_path
|
||||
|
||||
|
||||
return None
|
||||
|
||||
if media_path:
|
||||
actual_media_path = find_media_file(media_path)
|
||||
if actual_media_path:
|
||||
media_type = get_media_type(actual_media_path)
|
||||
|
||||
|
||||
cached_id = None
|
||||
if not disable_cache:
|
||||
async with edit_or_send_message.lock:
|
||||
cached_id = edit_or_send_message.cache.get(actual_media_path)
|
||||
if cached_id:
|
||||
edit_or_send_message.cache.move_to_end(actual_media_path)
|
||||
|
||||
|
||||
if cached_id:
|
||||
try:
|
||||
if media_type == 'photo':
|
||||
await target_message.edit_media(InputMediaPhoto(media=cached_id, caption=text), reply_markup=reply_markup)
|
||||
elif media_type == 'video':
|
||||
await target_message.edit_media(InputMediaVideo(media=cached_id, caption=text), reply_markup=reply_markup)
|
||||
elif media_type == 'animation':
|
||||
await target_message.edit_media(InputMediaAnimation(media=cached_id, caption=text), reply_markup=reply_markup)
|
||||
if media_type == "photo":
|
||||
await target_message.edit_media(
|
||||
InputMediaPhoto(media=cached_id, caption=text), reply_markup=reply_markup
|
||||
)
|
||||
elif media_type == "video":
|
||||
await target_message.edit_media(
|
||||
InputMediaVideo(media=cached_id, caption=text), reply_markup=reply_markup
|
||||
)
|
||||
elif media_type == "animation":
|
||||
await target_message.edit_media(
|
||||
InputMediaAnimation(media=cached_id, caption=text), reply_markup=reply_markup
|
||||
)
|
||||
return
|
||||
except Exception:
|
||||
try:
|
||||
if media_type == 'photo':
|
||||
await target_message.answer_photo(photo=cached_id, caption=text, reply_markup=reply_markup, disable_web_page_preview=disable_web_page_preview)
|
||||
elif media_type == 'video':
|
||||
await target_message.answer_video(video=cached_id, caption=text, reply_markup=reply_markup, disable_web_page_preview=disable_web_page_preview)
|
||||
elif media_type == 'animation':
|
||||
await target_message.answer_animation(animation=cached_id, caption=text, reply_markup=reply_markup, disable_web_page_preview=disable_web_page_preview)
|
||||
if media_type == "photo":
|
||||
await target_message.answer_photo(
|
||||
photo=cached_id,
|
||||
caption=text,
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
)
|
||||
elif media_type == "video":
|
||||
await target_message.answer_video(
|
||||
video=cached_id,
|
||||
caption=text,
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
)
|
||||
elif media_type == "animation":
|
||||
await target_message.answer_animation(
|
||||
animation=cached_id,
|
||||
caption=text,
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
)
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
@@ -286,30 +308,51 @@ async def edit_or_send_message(
|
||||
async with aiofiles.open(actual_media_path, "rb") as f:
|
||||
data = await f.read()
|
||||
upload = BufferedInputFile(data, filename=os.path.basename(actual_media_path))
|
||||
|
||||
|
||||
try:
|
||||
if media_type == 'photo':
|
||||
msg = await target_message.edit_media(InputMediaPhoto(media=upload, caption=text), reply_markup=reply_markup)
|
||||
elif media_type == 'video':
|
||||
msg = await target_message.edit_media(InputMediaVideo(media=upload, caption=text), reply_markup=reply_markup)
|
||||
elif media_type == 'animation':
|
||||
msg = await target_message.edit_media(InputMediaAnimation(media=upload, caption=text), reply_markup=reply_markup)
|
||||
if media_type == "photo":
|
||||
msg = await target_message.edit_media(
|
||||
InputMediaPhoto(media=upload, caption=text), reply_markup=reply_markup
|
||||
)
|
||||
elif media_type == "video":
|
||||
msg = await target_message.edit_media(
|
||||
InputMediaVideo(media=upload, caption=text), reply_markup=reply_markup
|
||||
)
|
||||
elif media_type == "animation":
|
||||
msg = await target_message.edit_media(
|
||||
InputMediaAnimation(media=upload, caption=text), reply_markup=reply_markup
|
||||
)
|
||||
except Exception:
|
||||
if media_type == 'photo':
|
||||
msg = await target_message.answer_photo(photo=upload, caption=text, reply_markup=reply_markup, disable_web_page_preview=disable_web_page_preview)
|
||||
elif media_type == 'video':
|
||||
msg = await target_message.answer_video(video=upload, caption=text, reply_markup=reply_markup, disable_web_page_preview=disable_web_page_preview)
|
||||
elif media_type == 'animation':
|
||||
msg = await target_message.answer_animation(animation=upload, caption=text, reply_markup=reply_markup, disable_web_page_preview=disable_web_page_preview)
|
||||
if media_type == "photo":
|
||||
msg = await target_message.answer_photo(
|
||||
photo=upload,
|
||||
caption=text,
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
)
|
||||
elif media_type == "video":
|
||||
msg = await target_message.answer_video(
|
||||
video=upload,
|
||||
caption=text,
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
)
|
||||
elif media_type == "animation":
|
||||
msg = await target_message.answer_animation(
|
||||
animation=upload,
|
||||
caption=text,
|
||||
reply_markup=reply_markup,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
)
|
||||
|
||||
file_id = None
|
||||
if hasattr(msg, 'photo') and msg.photo:
|
||||
if hasattr(msg, "photo") and msg.photo:
|
||||
file_id = msg.photo[-1].file_id
|
||||
elif hasattr(msg, 'video') and msg.video:
|
||||
elif hasattr(msg, "video") and msg.video:
|
||||
file_id = msg.video.file_id
|
||||
elif hasattr(msg, 'animation') and msg.animation:
|
||||
elif hasattr(msg, "animation") and msg.animation:
|
||||
file_id = msg.animation.file_id
|
||||
|
||||
|
||||
if file_id and not disable_cache:
|
||||
async with edit_or_send_message.lock:
|
||||
if actual_media_path not in edit_or_send_message.cache:
|
||||
|
||||
@@ -3,17 +3,16 @@ from collections.abc import Iterable
|
||||
from aiogram import Dispatcher
|
||||
from aiogram.dispatcher.middlewares.base import BaseMiddleware
|
||||
|
||||
from config import DISABLE_DIRECT_START, CHANNEL_REQUIRED
|
||||
|
||||
from config import CHANNEL_REQUIRED, DISABLE_DIRECT_START
|
||||
from middlewares.ban_checker import BanCheckerMiddleware
|
||||
from middlewares.subscription import SubscriptionMiddleware
|
||||
|
||||
from .probe import StreamProbeMiddleware, MiddlewareProbe, TailHandlerProbe
|
||||
from .admin import AdminMiddleware
|
||||
from .answer import CallbackAnswerMiddleware
|
||||
from .direct_start_blocker import DirectStartBlockerMiddleware
|
||||
from .loggings import LoggingMiddleware
|
||||
from .maintenance import MaintenanceModeMiddleware
|
||||
from .probe import MiddlewareProbe, StreamProbeMiddleware, TailHandlerProbe
|
||||
from .session import SessionMiddleware
|
||||
from .throttling import ThrottlingMiddleware
|
||||
from .user import UserMiddleware
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import time
|
||||
|
||||
from aiogram.dispatcher.middlewares.base import BaseMiddleware
|
||||
|
||||
from logger import logger
|
||||
|
||||
|
||||
class StreamProbeMiddleware(BaseMiddleware):
|
||||
def __init__(self, name: str = "global"):
|
||||
def __init__(self, name: str = "global") -> None:
|
||||
self.name = name
|
||||
|
||||
async def __call__(self, handler, event, data):
|
||||
@@ -21,7 +23,7 @@ class StreamProbeMiddleware(BaseMiddleware):
|
||||
|
||||
|
||||
class MiddlewareProbe(BaseMiddleware):
|
||||
def __init__(self, inner: BaseMiddleware, name: str):
|
||||
def __init__(self, inner: BaseMiddleware, name: str) -> None:
|
||||
self.inner = inner
|
||||
self.name = name
|
||||
|
||||
@@ -29,7 +31,7 @@ class MiddlewareProbe(BaseMiddleware):
|
||||
now = time.perf_counter()
|
||||
t0 = data.setdefault("_mw_t0", now)
|
||||
prev = data.setdefault("_mw_prev", now)
|
||||
logger.info(f"[mw:{self.name}] +{(now - prev)*1000:.2f} ms total {(now - t0)*1000:.2f} ms")
|
||||
logger.info(f"[mw:{self.name}] +{(now - prev) * 1000:.2f} ms total {(now - t0) * 1000:.2f} ms")
|
||||
|
||||
downstream_ms = 0.0
|
||||
|
||||
@@ -54,14 +56,14 @@ class MiddlewareProbe(BaseMiddleware):
|
||||
|
||||
|
||||
class TailHandlerProbe(BaseMiddleware):
|
||||
def __init__(self, name: str = "handler"):
|
||||
def __init__(self, name: str = "handler") -> None:
|
||||
self.name = name
|
||||
|
||||
async def __call__(self, handler, event, data):
|
||||
now = time.perf_counter()
|
||||
t0 = data.setdefault("_mw_t0", now)
|
||||
prev = data.setdefault("_mw_prev", now)
|
||||
logger.info(f"[mw:{self.name}:enter] +{(now - prev)*1000:.2f} ms total {(now - t0)*1000:.2f} ms")
|
||||
logger.info(f"[mw:{self.name}:enter] +{(now - prev) * 1000:.2f} ms total {(now - t0) * 1000:.2f} ms")
|
||||
start = time.perf_counter()
|
||||
try:
|
||||
return await handler(event, data)
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
from aiohttp.web_urldispatcher import UrlDispatcher
|
||||
|
||||
from utils.modules_loader import load_module_webhooks
|
||||
|
||||
from handlers.payments.heleket.webhook import heleket_webhook
|
||||
from handlers.payments.kassai.webhook import kassai_webhook
|
||||
from utils.modules_loader import load_module_webhooks
|
||||
|
||||
from .wata_payment import wata_payment_webhook
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user