Ruff format/ Cleanup

This commit is contained in:
Vladless
2026-04-14 07:19:14 +00:00
parent 0e8b0d04f0
commit 39dd2432cc
224 changed files with 1583 additions and 1182 deletions
+6 -6
View File
@@ -16,20 +16,20 @@ from config import (
BACKUP_CAPTION,
BACKUP_CHANNEL_ID,
BACKUP_CHANNEL_THREAD_ID,
BACKUP_CREATE_ARCHIVE,
BACKUP_INCLUDE_CONFIG,
BACKUP_INCLUDE_DB,
BACKUP_INCLUDE_IMG,
BACKUP_INCLUDE_TEXTS,
BACKUP_OTHER_BOT_TOKEN,
BACKUP_SEND_MODE,
BACK_DIR,
DB_NAME,
DB_PASSWORD,
DB_USER,
PG_IN_DOCKER,
PG_HOST,
PG_IN_DOCKER,
PG_PORT,
BACKUP_CREATE_ARCHIVE,
BACKUP_INCLUDE_DB,
BACKUP_INCLUDE_CONFIG,
BACKUP_INCLUDE_TEXTS,
BACKUP_INCLUDE_IMG,
)
from logger import logger
+3 -1
View File
@@ -1,8 +1,10 @@
from __future__ import annotations
import aiogram.types
from pydantic import ConfigDict
_UniqueGiftColors = getattr(aiogram.types, "UniqueGiftColors", None)
if _UniqueGiftColors is not None:
_cfg = getattr(_UniqueGiftColors, "model_config", None)
@@ -24,7 +26,7 @@ def apply_button_icons_patch(config: dict[str, dict[str, str]] | None = None) ->
_button_icon_config.update(config)
class _PatchedInlineKeyboardButton(_OriginalInlineKeyboardButton):
def __init__(self, **kwargs: object):
def __init__(self, **kwargs: object) -> None:
key = kwargs.get("callback_data") or kwargs.get("url")
if key is not None and isinstance(key, str):
config = _button_icon_config.get(key)
+1 -1
View File
@@ -8,8 +8,8 @@ from sqlalchemy import exists, func, join, not_, select
from sqlalchemy.ext.asyncio import AsyncSession
from core.constants import PAYMENT_SYSTEMS_EXCLUDED
from database.models import Key, Payment, Referral, Tariff, User
from database.access.resolution import resolve_user_optional
from database.models import Key, Payment, Referral, Tariff, User
async def export_users_csv(session: AsyncSession) -> BufferedInputFile:
+3
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import re
from typing import Any
from aiogram import Bot
@@ -9,6 +10,7 @@ from aiogram.types import MessageEntity
from logger import logger
_PLACEHOLDER_CACHE: dict[str, str] = {}
_BOT: Bot | None = None
@@ -274,6 +276,7 @@ def patch_bot_methods() -> bool:
global _BOT
try:
from aiogram.types import Message
from bot import bot
_BOT = bot
+145 -48
View File
@@ -1,53 +1,149 @@
from logger import logger
_BUILTIN_DOMAINS: set[str] = {
"mailinator.com", "guerrillamail.com", "guerrillamail.de", "guerrillamail.net",
"guerrillamail.org", "guerrillamailblock.com", "grr.la", "sharklasers.com",
"guerrillamail.info", "tempmail.com", "temp-mail.org", "temp-mail.io",
"throwaway.email", "fakeinbox.com", "tempail.com", "tempr.email",
"dispostable.com", "yopmail.com", "yopmail.fr", "yopmail.net",
"cool.fr.nf", "jetable.fr.nf", "nospam.ze.tc", "nomail.xl.cx",
"mega.zik.dj", "speed.1s.fr", "courriel.fr.nf", "moncourrier.fr.nf",
"monemail.fr.nf", "monmail.fr.nf", "hide.biz.st", "mytrashmail.com",
"mailnesia.com", "maildrop.cc", "discard.email", "discardmail.com",
"discardmail.de", "trashmail.com", "trashmail.me", "trashmail.net",
"trashmail.org", "trashmail.at", "trashmail.io", "trashmail.ws",
"trash-mail.com", "trash-mail.at", "trashemail.de",
"mailcatch.com", "mailscrap.com", "mailforspam.com",
"spamgourmet.com", "spamgourmet.net", "spamgourmet.org",
"mailexpire.com", "tempinbox.com", "tempomail.fr",
"10minutemail.com", "10minutemail.co.za", "10minutemail.net",
"minutemail.io", "emailondeck.com", "getnada.com",
"mohmal.com", "burnermail.io", "inboxbear.com",
"mailsac.com", "harakirimail.com", "33mail.com",
"maildax.com", "crazymailing.com", "mailtemp.info",
"emkei.cz", "example.com", "test.com", "mailinator.net",
"binkmail.com", "bobmail.info", "chammy.info",
"devnullmail.com", "letthemeatspam.com", "mailnull.com",
"nomail.pw", "nowmymail.com", "rmqkr.net",
"sharklasers.com", "spamfree24.org", "spamhereplease.com",
"tempmailaddress.com", "wegwerfmail.de", "wegwerfmail.net",
"wh4f.org", "mailzilla.com", "anonbox.net",
"bspamfree.org", "kurzepost.de", "objectmail.com",
"proxymail.eu", "rcpt.at", "reallymymail.com",
"recode.me", "regbypass.com", "s0ny.net",
"safetymail.info", "safetypost.de", "shieldedmail.com",
"sogetthis.com", "soodonims.com", "spambox.us",
"spamcero.com", "spamday.com", "spamex.com",
"spamfighter.cf", "spamfighter.ga", "spamfighter.gq",
"spamfighter.ml", "spamfighter.tk",
"spamhole.com", "spaml.com", "spaml.de",
"uggsrock.com", "uroid.com", "veryreallymymail.com",
"viditag.com", "vomoto.com", "vpn.st",
"vsimcard.com", "vubby.com", "vztc.com",
"wasteland.rfc822.org", "webemail.me",
"zetmail.com", "zippymail.info",
"mailnator.com", "mailtothis.com",
"mx0.wwwnew.eu", "mypartyclip.de",
"myzx.com", "nb.gy", "nobulk.com",
"noclickemail.com", "nogmailspam.info",
"nomail.xl.cx", "nomorespamemails.com",
"nospam.ze.tc", "nothingtoseehere.ca",
"mailinator.com",
"guerrillamail.com",
"guerrillamail.de",
"guerrillamail.net",
"guerrillamail.org",
"guerrillamailblock.com",
"grr.la",
"sharklasers.com",
"guerrillamail.info",
"tempmail.com",
"temp-mail.org",
"temp-mail.io",
"throwaway.email",
"fakeinbox.com",
"tempail.com",
"tempr.email",
"dispostable.com",
"yopmail.com",
"yopmail.fr",
"yopmail.net",
"cool.fr.nf",
"jetable.fr.nf",
"nospam.ze.tc",
"nomail.xl.cx",
"mega.zik.dj",
"speed.1s.fr",
"courriel.fr.nf",
"moncourrier.fr.nf",
"monemail.fr.nf",
"monmail.fr.nf",
"hide.biz.st",
"mytrashmail.com",
"mailnesia.com",
"maildrop.cc",
"discard.email",
"discardmail.com",
"discardmail.de",
"trashmail.com",
"trashmail.me",
"trashmail.net",
"trashmail.org",
"trashmail.at",
"trashmail.io",
"trashmail.ws",
"trash-mail.com",
"trash-mail.at",
"trashemail.de",
"mailcatch.com",
"mailscrap.com",
"mailforspam.com",
"spamgourmet.com",
"spamgourmet.net",
"spamgourmet.org",
"mailexpire.com",
"tempinbox.com",
"tempomail.fr",
"10minutemail.com",
"10minutemail.co.za",
"10minutemail.net",
"minutemail.io",
"emailondeck.com",
"getnada.com",
"mohmal.com",
"burnermail.io",
"inboxbear.com",
"mailsac.com",
"harakirimail.com",
"33mail.com",
"maildax.com",
"crazymailing.com",
"mailtemp.info",
"emkei.cz",
"example.com",
"test.com",
"mailinator.net",
"binkmail.com",
"bobmail.info",
"chammy.info",
"devnullmail.com",
"letthemeatspam.com",
"mailnull.com",
"nomail.pw",
"nowmymail.com",
"rmqkr.net",
"spamfree24.org",
"spamhereplease.com",
"tempmailaddress.com",
"wegwerfmail.de",
"wegwerfmail.net",
"wh4f.org",
"mailzilla.com",
"anonbox.net",
"bspamfree.org",
"kurzepost.de",
"objectmail.com",
"proxymail.eu",
"rcpt.at",
"reallymymail.com",
"recode.me",
"regbypass.com",
"s0ny.net",
"safetymail.info",
"safetypost.de",
"shieldedmail.com",
"sogetthis.com",
"soodonims.com",
"spambox.us",
"spamcero.com",
"spamday.com",
"spamex.com",
"spamfighter.cf",
"spamfighter.ga",
"spamfighter.gq",
"spamfighter.ml",
"spamfighter.tk",
"spamhole.com",
"spaml.com",
"spaml.de",
"uggsrock.com",
"uroid.com",
"veryreallymymail.com",
"viditag.com",
"vomoto.com",
"vpn.st",
"vsimcard.com",
"vubby.com",
"vztc.com",
"wasteland.rfc822.org",
"webemail.me",
"zetmail.com",
"zippymail.info",
"mailnator.com",
"mailtothis.com",
"mx0.wwwnew.eu",
"mypartyclip.de",
"myzx.com",
"nb.gy",
"nobulk.com",
"noclickemail.com",
"nogmailspam.info",
"nomorespamemails.com",
"nothingtoseehere.ca",
}
_loaded_extra = False
@@ -61,7 +157,8 @@ def _load_extra() -> None:
_loaded_extra = True
try:
from config import DISPOSABLE_EMAIL_BLOCKLIST_EXTRA
if isinstance(DISPOSABLE_EMAIL_BLOCKLIST_EXTRA, (list, set, tuple)):
if isinstance(DISPOSABLE_EMAIL_BLOCKLIST_EXTRA, list | set | tuple):
_extra_domains = {d.strip().lower() for d in DISPOSABLE_EMAIL_BLOCKLIST_EXTRA if isinstance(d, str)}
if _extra_domains:
logger.info("[DisposableEmail] загружено {} дополнительных доменов", len(_extra_domains))
+5 -3
View File
@@ -8,8 +8,10 @@ from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError, Teleg
from aiogram.filters import ExceptionTypeFilter
from aiogram.types import BufferedInputFile, ErrorEvent
from aiogram.utils.markdown import hbold
from sqlalchemy.exc import InterfaceError as SQLAlchemyInterfaceError
from sqlalchemy.exc import OperationalError as SQLAlchemyOperationalError
from sqlalchemy.exc import (
InterfaceError as SQLAlchemyInterfaceError,
OperationalError as SQLAlchemyOperationalError,
)
from config import ADMIN_ID
from database import async_session_maker
@@ -104,7 +106,7 @@ def setup_error_handlers(dp: Dispatcher) -> None:
if isinstance(
event.exception,
(SQLAlchemyInterfaceError, SQLAlchemyOperationalError),
SQLAlchemyInterfaceError | SQLAlchemyOperationalError,
):
chat_id = None
if event.update.message:
+4 -4
View File
@@ -22,7 +22,7 @@ def encode_referral_code(user_id: int) -> str:
raw = int(user_id).to_bytes(8, byteorder="big", signed=False)
secret = _secret_bytes()
mask = hmac.new(secret, b"ref-mask-v1", hashlib.sha256).digest()[:8]
obfuscated = bytes(a ^ b for a, b in zip(raw, mask))
obfuscated = bytes(a ^ b for a, b in zip(raw, mask, strict=False))
signature = hmac.new(secret, b"ref-sign-v1:" + obfuscated, hashlib.sha256).digest()[:6]
payload = base64.urlsafe_b64encode(obfuscated + signature).decode("ascii").rstrip("=")
return f"r1_{payload}"
@@ -34,7 +34,7 @@ def encode_partner_code(user_id: int) -> str:
raw = int(user_id).to_bytes(8, byteorder="big", signed=False)
secret = _secret_bytes()
mask = hmac.new(secret, b"partner-mask-v1", hashlib.sha256).digest()[:8]
obfuscated = bytes(a ^ b for a, b in zip(raw, mask))
obfuscated = bytes(a ^ b for a, b in zip(raw, mask, strict=False))
signature = hmac.new(secret, b"partner-sign-v1:" + obfuscated, hashlib.sha256).digest()[:6]
payload = base64.urlsafe_b64encode(obfuscated + signature).decode("ascii").rstrip("=")
return f"p1_{payload}"
@@ -58,7 +58,7 @@ def decode_referral_code(value: str | None) -> int | None:
if not hmac.compare_digest(signature, expected):
return None
mask = hmac.new(secret, b"ref-mask-v1", hashlib.sha256).digest()[:8]
raw = bytes(a ^ b for a, b in zip(obfuscated, mask))
raw = bytes(a ^ b for a, b in zip(obfuscated, mask, strict=False))
parsed = int.from_bytes(raw, byteorder="big", signed=False)
return parsed if parsed > 0 else None
if token.startswith("p1_"):
@@ -88,7 +88,7 @@ def decode_partner_code(value: str | None) -> int | None:
if not hmac.compare_digest(signature, expected):
return None
mask = hmac.new(secret, b"partner-mask-v1", hashlib.sha256).digest()[:8]
raw = bytes(a ^ b for a, b in zip(obfuscated, mask))
raw = bytes(a ^ b for a, b in zip(obfuscated, mask, strict=False))
parsed = int.from_bytes(raw, byteorder="big", signed=False)
return parsed if parsed > 0 else None
if token.startswith("r1_"):
+1
View File
@@ -47,6 +47,7 @@ def verify_webapp_init_data(
https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app
"""
import json
from urllib.parse import parse_qs
if not init_data or not bot_token:
+1
View File
@@ -3,6 +3,7 @@ import httpx
from config import TURNSTILE_SECRET_KEY
from logger import logger
_VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
+1
View File
@@ -11,6 +11,7 @@ from core.redis_cache import (
redis_connection_ok,
)
_RESEND_COOLDOWN_SEC = 60.0
_IP_WINDOW_SEC = 3600.0
_IP_MAX_SENDS = 40