init auth and main function

This commit is contained in:
Yuriy Yuriev
2026-05-14 16:15:58 +07:00
commit 27c53e897e
47 changed files with 5750 additions and 0 deletions
View File
+45
View File
@@ -0,0 +1,45 @@
"""Utility helper functions."""
from typing import Tuple
from config.settings import settings
def parse_range(value: str, default_min: int = 5) -> tuple:
"""Парсит строку диапазона 'мин-макс' или одиночное число."""
# Очищаем от кавычек и пробелов
value = str(value).replace("'", "").replace('"', "").replace("`", "").strip()
if '-' in value:
parts = value.split('-')
if len(parts) != 2:
raise ValueError(f"Неверный формат: {value}. Пример: 10-30")
try:
min_val = int(parts[0].strip())
max_val = int(parts[1].strip())
except ValueError:
raise ValueError(f"Не числа: {value}. Пример: 10-30")
if min_val < default_min:
raise ValueError(f"Минимум: {default_min}")
if min_val >= max_val:
raise ValueError("Мин должно быть меньше макс")
return min_val, max_val
else:
try:
val = int(value)
except ValueError:
raise ValueError(f"Не число: {value}")
if val < default_min:
raise ValueError(f"Минимум: {default_min}")
return val, val
def format_range(min_val: int, max_val: int) -> str:
"""Format range for display."""
return f"{min_val}-{max_val}" if min_val != max_val else str(min_val)
def extract_domain(url: str) -> str:
"""Extract domain from URL."""
return url.replace("https://", "").replace("http://", "").split("/")[0]
+83
View File
@@ -0,0 +1,83 @@
"""Telegram message utilities."""
import logging
import os
from typing import Optional
from aiogram import Bot
from aiogram.types import FSInputFile
logger = logging.getLogger(__name__)
async def send_message_safe(
bot: Optional[Bot],
chat_id: Optional[int],
text: str,
**kwargs
) -> None:
"""
Safely send message to Telegram.
Args:
bot: Bot instance
chat_id: Target chat ID
text: Message text
**kwargs: Additional arguments for send_message
"""
if not bot or not chat_id:
return
try:
await bot.send_message(chat_id=chat_id, text=text, **kwargs)
except Exception as e:
logger.error(f"Failed to send message: {e}")
async def send_visit_result(
bot: Optional[Bot],
chat_id: int,
visit_num: int,
result: dict,
delay: int,
reading: int,
successful: int,
failed: int
) -> None:
"""
Send visit result with optional screenshot.
Args:
bot: Bot instance
chat_id: Target chat ID
visit_num: Visit number
result: Visit result dictionary
delay: Next visit delay
reading: Reading time
successful: Count of successful visits
failed: Count of failed visits
"""
if not bot:
return
try:
text = (
f"{'' if result['success'] else ''} **Посещение {visit_num}**\n"
f"🌐 `{result.get('final_url', 'N/A')[:60]}`\n"
f"📖 Чтение: {reading}с | След. через: {delay}с\n"
f"📊 Успешно: {successful} | Ошибок: {failed}"
)
screenshot_path = result.get('screenshot_path')
if screenshot_path and os.path.exists(screenshot_path):
photo = FSInputFile(screenshot_path)
await bot.send_photo(chat_id=chat_id, photo=photo, caption=text)
else:
await bot.send_message(chat_id=chat_id, text=text)
except Exception as e:
logger.error(f"Failed to send visit result: {e}")
try:
await bot.send_message(chat_id=chat_id, text=text)
except Exception as e2:
logger.warning(f"Fallback send failed: {e2}")