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
+303
View File
@@ -0,0 +1,303 @@
"""
Менеджер задач по стримерам.
Простой список с возможностью изменять параметры на лету.
"""
import asyncio
from dataclasses import dataclass, field
from typing import Optional, List, Dict
from datetime import datetime
import random
import logging
logger = logging.getLogger(__name__)
@dataclass
class TaskParams:
"""Динамические параметры задачи."""
url: str = ""
task_type: str = "visit"
# Задержки
min_delay: int = 10
max_delay: int = 30
min_reading: int = 5
max_reading: int = 15
# Лимиты
max_visits: Optional[int] = None
current_visit: int = 0
# Twitch параметры
channel: str = ""
target_username: str = ""
visits_per_link: int = 5
monitor_minutes: int = 10
allowed_domains: Optional[List[str]] = None
# Состояние
paused: bool = False
skip_next: bool = False
force_delay: Optional[int] = None
force_reading: Optional[int] = None
# Статистика
started_at: Optional[datetime] = None
total_visits: int = 0
successful_visits: int = 0
links_found: int = 0
chat_id: Optional[int] = None
completed: bool = False # Задача завершена
stopped: bool = False # Задача остановлена пользователем
@property
def monitor_duration(self) -> int:
return self.monitor_minutes * 60
def update(self, **kwargs):
for key, value in kwargs.items():
if hasattr(self, key):
setattr(self, key, value)
def get_delay(self) -> int:
if self.skip_next:
self.skip_next = False
return 0
if self.force_delay:
delay = self.force_delay
self.force_delay = None
return delay
return random.randint(self.min_delay, self.max_delay)
def get_reading_time(self) -> int:
if self.force_reading:
reading = self.force_reading
self.force_reading = None
return reading
return random.randint(self.min_reading, self.max_reading)
def get_status_emoji(self) -> str:
if self.stopped:
return "🛑"
if self.completed:
return ""
if self.paused:
return "⏸️"
return "🔄"
def get_status_text(self) -> str:
if self.stopped:
return "🛑 Остановлена"
if self.completed:
return "✅ Завершена"
if self.paused:
return "⏸️ Пауза"
return "🔄 Активна"
def get_stats_text(self) -> str:
"""Текст статистики."""
if self.task_type == "twitch_irc":
status = self.get_status_text()
duration = ""
if self.started_at and (self.completed or self.stopped):
delta = datetime.now() - self.started_at
duration = f"├ ⏱️ Длилась: {delta.seconds // 60} мин\n"
# Домены
domains_text = ""
if self.allowed_domains:
domains_text = f"├ 🌐 Домены: {', '.join(self.allowed_domains)}\n"
else:
domains_text = "├ 🌐 Домены: все\n"
return (
f"📺 **{self.channel}**\n"
f"├ Статус: {status}\n"
f"├ 🔗 Ссылок найдено: {self.links_found}\n"
f"├ 📊 Всего визитов: {self.total_visits}\n"
f"├ ✅ Успешно: {self.successful_visits}\n"
f"├ ⏱️ Задержка: {self.min_delay}-{self.max_delay}с\n"
f"├ 📖 Чтение: {self.min_reading}-{self.max_reading}с\n"
f"├ 🔗 На ссылку: {self.visits_per_link} визитов\n"
f"├ ⏰ Мониторинг: {self.monitor_minutes} мин\n"
f"{domains_text}"
f"{duration}"
)
else:
return (
f"🌐 `{self.url[:50]}`\n"
f"├ Статус: {self.get_status_text()}\n"
f"├ 📊 Визитов: {self.total_visits}\n"
f"├ ✅ Успешно: {self.successful_visits}\n"
)
class TaskManager:
"""
Менеджер задач.
Хранит список стримеров и позволяет управлять каждым.
"""
def __init__(self):
self._tasks: Dict[str, TaskParams] = {} # task_id -> params
self._lock = asyncio.Lock()
async def add_task(self, task_id: str, params: TaskParams) -> None:
"""Добавляет задачу."""
async with self._lock:
self._tasks[task_id] = params
logger.info(f" Задача: {task_id[:12]} ({params.channel or params.url})")
async def remove_task(self, task_id: str) -> bool:
"""Удаляет задачу."""
async with self._lock:
if task_id in self._tasks:
del self._tasks[task_id]
logger.info(f" Задача удалена: {task_id[:12]}")
return True
return False
async def get_task(self, task_id: str) -> Optional[TaskParams]:
"""Получает задачу."""
async with self._lock:
return self._tasks.get(task_id)
async def update_task(self, task_id: str, **kwargs) -> bool:
"""Обновляет параметры задачи."""
params = await self.get_task(task_id)
if params:
params.update(**kwargs)
return True
return False
async def complete_task(self, task_id: str) -> bool:
"""Пометить задачу как завершенную."""
return await self.update_task(task_id, completed=True, paused=True)
async def stop_task(self, task_id: str) -> bool:
"""Пометить задачу как остановленную."""
return await self.update_task(task_id, stopped=True, paused=True)
async def get_active_tasks(self) -> Dict[str, TaskParams]:
"""Только активные задачи (не завершенные и не остановленные)."""
return {
tid: p for tid, p in self._tasks.items()
if not p.completed and not p.stopped
}
async def get_completed_tasks(self) -> Dict[str, TaskParams]:
"""Завершенные задачи (для просмотра статистики)."""
return {
tid: p for tid, p in self._tasks.items()
if p.completed or p.stopped
}
async def pause_task(self, task_id: str) -> bool:
"""Пауза задачи."""
return await self.update_task(task_id, paused=True)
async def resume_task(self, task_id: str) -> bool:
"""Снять с паузы."""
return await self.update_task(task_id, paused=False)
async def skip_next_task(self, task_id: str) -> bool:
"""Пропустить следующее действие."""
return await self.update_task(task_id, skip_next=True)
async def restart_task(self, task_id: str) -> bool:
"""Сбросить счетчики для перезапуска."""
return await self.update_task(
task_id,
current_visit=0,
total_visits=0,
successful_visits=0,
links_found=0
)
async def get_all_tasks(self) -> Dict[str, TaskParams]:
"""Все задачи."""
async with self._lock:
return dict(self._tasks)
async def get_tasks_by_type(self, task_type: str) -> Dict[str, TaskParams]:
"""Задачи по типу."""
return {
tid: p for tid, p in self._tasks.items()
if p.task_type == task_type
}
async def get_twitch_tasks(self) -> Dict[str, TaskParams]:
"""Только Twitch задачи."""
return await self.get_tasks_by_type("twitch_irc")
async def get_visit_tasks(self) -> Dict[str, TaskParams]:
"""Только задачи посещения."""
return await self.get_tasks_by_type("visit")
async def get_stats(self) -> dict:
"""Общая статистика."""
twitch_tasks = await self.get_twitch_tasks()
visit_tasks = await self.get_visit_tasks()
return {
"total": len(self._tasks),
"twitch": len(twitch_tasks),
"visit": len(visit_tasks),
"paused": sum(1 for p in self._tasks.values() if p.paused),
"active": sum(1 for p in self._tasks.values() if not p.paused),
}
def _get_task_info(self, task_id: str, params: TaskParams) -> str:
"""Информация о задаче для отображения."""
status = params.get_status_emoji()
if params.task_type == "twitch_irc":
return (
f"{status} 📺 **{params.channel}**\n"
f" `{task_id[:12]}...`\n"
f" 👤 @{params.target_username} | "
f"🔗{params.links_found} | "
f"📊{params.total_visits}\n"
)
else:
return (
f"{status} 🌐 `{params.url[:40]}`\n"
f" `{task_id[:12]}...`\n"
f" 📊{params.total_visits} визитов\n"
)
async def format_task_list(self, max_items: int = 15) -> str:
"""Форматирует список задач для сообщения."""
async with self._lock:
if not self._tasks:
return "📊 Нет активных задач"
# Сначала Twitch, потом визиты
twitch = await self.get_twitch_tasks()
visits = await self.get_visit_tasks()
async with self._lock:
total_tasks = len(self._tasks)
text = f"📊 **ЗАДАЧИ: {total_tasks}**\n\n"
if twitch:
text += "📺 **Twitch мониторинг:**\n"
for i, (task_id, params) in enumerate(list(twitch.items())[:5]):
text += self._get_task_info(task_id, params)
if len(twitch) > 5:
text += f" _...и еще {len(twitch) - 5}_\n"
text += "\n"
if visits:
text += "🌐 **Посещение страниц:**\n"
for i, (task_id, params) in enumerate(list(visits.items())[:5]):
text += self._get_task_info(task_id, params)
if len(visits) > 5:
text += f" _...и еще {len(visits) - 5}_\n"
return text