fix view
This commit is contained in:
+84
-26
@@ -436,13 +436,12 @@ class BotInterface:
|
||||
"delay": (
|
||||
"⏱️ *Пауза между переходами*\n"
|
||||
"Сколько секунд ждать перед следующим кликом.\n"
|
||||
"Диапазон `30-60` — каждый раз рандом от 30 до 60.\n"
|
||||
"Одно число `45` — всегда фиксированно."
|
||||
"Диапазон `30-60` — каждый раз рандом от 30 до 60."
|
||||
),
|
||||
"reading": (
|
||||
"📖 *Время на странице*\n"
|
||||
"Сколько секунд браузер будет листать страницу (имитация чтения).\n"
|
||||
"Диапазон `45-90` или фиксированно `60`."
|
||||
"Диапазон `45-90`."
|
||||
),
|
||||
"perlink": (
|
||||
"🔗 *Резервное кол-во кликов*\n"
|
||||
@@ -454,8 +453,7 @@ class BotInterface:
|
||||
"📊 *CTR — процент от зрителей*\n"
|
||||
"Формула: клики = зрители × CTR%.\n"
|
||||
"Например: 120 зрителей × 1% = 1 клик.\n"
|
||||
"Диапазон `0.8-1` — случайно в этом диапазоне.\n"
|
||||
"Одно число `1` — фиксированно."
|
||||
"Диапазон `0.8-1` — случайно в этом диапазоне."
|
||||
),
|
||||
"minutes": (
|
||||
"⏰ *Длительность мониторинга*\n"
|
||||
@@ -817,7 +815,7 @@ class BotInterface:
|
||||
f"🔢 *Кликов в одном цикле*\n"
|
||||
f"Сколько кликов подряд делать перед паузой.\n"
|
||||
f"Текущее: {cur}\n"
|
||||
f"Диапазон `2-5` или фиксированно `3`."
|
||||
f"Диапазон `2-5`."
|
||||
)
|
||||
_d_mn = params.min_delay // 60
|
||||
_d_mx = params.max_delay // 60
|
||||
@@ -826,7 +824,7 @@ class BotInterface:
|
||||
f"⏱️ *Пауза между циклами*\n"
|
||||
f"Сколько минут ждать после каждого цикла кликов.\n"
|
||||
f"Текущая: {_d_cur} мин\n"
|
||||
f"Диапазон `2-5` или фиксированно `3`."
|
||||
f"Диапазон `2-5`."
|
||||
)
|
||||
else:
|
||||
perlink_label = (
|
||||
@@ -840,7 +838,7 @@ class BotInterface:
|
||||
f"⏱️ *Пауза между переходами*\n"
|
||||
f"Сколько секунд ждать перед следующим кликом.\n"
|
||||
f"Текущая: {params.min_delay}–{params.max_delay} сек\n"
|
||||
f"Диапазон `30-60` или фиксированно `45`."
|
||||
f"Диапазон `30-60`."
|
||||
)
|
||||
prompts = {
|
||||
"delay": delay_label,
|
||||
@@ -848,13 +846,13 @@ class BotInterface:
|
||||
f"📖 *Время на странице*\n"
|
||||
f"Сколько секунд браузер листает страницу (имитация чтения).\n"
|
||||
f"Текущее: {params.min_reading}–{params.max_reading} сек\n"
|
||||
f"Диапазон `45-90` или фиксированно `60`."
|
||||
f"Диапазон `45-90`."
|
||||
),
|
||||
"percent": (
|
||||
f"👥 *Кликов = % от зрителей*\n"
|
||||
f"Количество кликов рассчитывается как % от числа зрителей стрима.\n"
|
||||
f"Текущий: {params.visits_percent}%\n"
|
||||
f"`0` — отключить, использовать фиксированное кол-во.\n"
|
||||
f"`0` — отключить.\n"
|
||||
f"Пример: `5` = 5 кликов на 100 зрителей."
|
||||
),
|
||||
"perlink": perlink_label,
|
||||
@@ -862,13 +860,13 @@ class BotInterface:
|
||||
f"⏳ *Задержка между кликами в цикле*\n"
|
||||
f"Сколько секунд ждать между каждым кликом внутри одного цикла.\n"
|
||||
f"Текущая: {params.min_click_delay}–{params.max_click_delay} сек\n"
|
||||
f"Диапазон `5-15` или фиксированно `10`."
|
||||
f"Диапазон `5-15`."
|
||||
),
|
||||
"ctr": (
|
||||
f"📊 *CTR — процент от зрителей*\n"
|
||||
f"Формула: клики = зрители × CTR%.\n"
|
||||
f"Текущий: {params.min_ctr}%–{params.max_ctr}%\n"
|
||||
f"Диапазон `0.8-1` или фиксированно `1`."
|
||||
f"Диапазон `0.8-1`."
|
||||
),
|
||||
}
|
||||
prompt = prompts.get(param, f"Введите значение для {param}:")
|
||||
@@ -1089,6 +1087,59 @@ class BotInterface:
|
||||
await callback.answer("🗑️ Задача удалена")
|
||||
await interface._show_user_tasks(callback.message, uid, edit=True)
|
||||
|
||||
@dp.callback_query(F.data.startswith("urestart_"))
|
||||
async def cb_user_restart_task(callback: CallbackQuery):
|
||||
tid = callback.data.replace("urestart_", "", 1)
|
||||
params, uid = await _get_user_task(callback, tid)
|
||||
if not params:
|
||||
return
|
||||
|
||||
balance = await interface.balance_storage.get_balance(uid)
|
||||
if balance <= 0:
|
||||
await callback.answer("❌ Недостаточно переходов", show_alert=True)
|
||||
return
|
||||
|
||||
# Сбрасываем статистику и статус
|
||||
await interface.task_manager.update_task(
|
||||
tid,
|
||||
completed=False,
|
||||
stopped=False,
|
||||
paused=False,
|
||||
successful_visits=0,
|
||||
total_visits=0,
|
||||
)
|
||||
|
||||
if params.task_type == "user_visit":
|
||||
await interface.background_tasks.cancel_task(tid)
|
||||
success = await interface.background_tasks.start_task(
|
||||
task_id=tid,
|
||||
coro=interface._run_url_visits(tid, params, callback.message.bot),
|
||||
task_type="user_visit",
|
||||
metadata={"type": "user_visit", "url": params.url, "chat_id": params.chat_id},
|
||||
)
|
||||
else:
|
||||
from types import SimpleNamespace
|
||||
msg_mock = SimpleNamespace(
|
||||
chat=SimpleNamespace(id=params.chat_id),
|
||||
bot=callback.message.bot,
|
||||
)
|
||||
await interface.background_tasks.cancel_task(tid)
|
||||
success = await interface.background_tasks.start_task(
|
||||
task_id=tid,
|
||||
coro=interface._run_twitch(tid, params, msg_mock),
|
||||
task_type="twitch_irc",
|
||||
metadata={"type": "twitch_irc", "channel": params.channel, "chat_id": params.chat_id},
|
||||
)
|
||||
|
||||
if success:
|
||||
if interface.storage:
|
||||
await interface.storage.save_task(tid, params)
|
||||
await callback.answer("🔄 Задача перезапущена")
|
||||
else:
|
||||
await callback.answer("❌ Ошибка перезапуска", show_alert=True)
|
||||
|
||||
await interface._show_user_tasks(callback.message, uid, edit=True)
|
||||
|
||||
@dp.callback_query(F.data.startswith("upause_"))
|
||||
async def cb_user_pause_task(callback: CallbackQuery):
|
||||
tid = callback.data.replace("upause_", "", 1)
|
||||
@@ -2022,12 +2073,22 @@ class BotInterface:
|
||||
def is_active():
|
||||
return not params.paused and not params.stopped and not params.stream_offline
|
||||
|
||||
async def on_drain_fail():
|
||||
await self.task_manager.pause_task(task_id)
|
||||
await send_message_safe(
|
||||
message.bot, params.chat_id,
|
||||
f"⚠️ IRC #{params.channel}: ошибка соединения (3 попытки) — задача поставлена на паузу"
|
||||
)
|
||||
|
||||
logger.info(f"🚀 IRC monitor: {params.channel}")
|
||||
|
||||
watcher = asyncio.create_task(self._stream_watcher(task_id, params, message))
|
||||
|
||||
try:
|
||||
await irc.listen_for_messages(on_url, params.monitor_duration, params.allowed_domains, is_active=is_active)
|
||||
await irc.listen_for_messages(
|
||||
on_url, params.monitor_duration, params.allowed_domains,
|
||||
is_active=is_active, on_drain_fail=on_drain_fail
|
||||
)
|
||||
if params.monitor_minutes > 0:
|
||||
await self.task_manager.complete_task(task_id)
|
||||
except asyncio.CancelledError:
|
||||
@@ -2044,7 +2105,6 @@ class BotInterface:
|
||||
|
||||
async def _run_url_visits(self, task_id: str, params: TaskParams, bot):
|
||||
"""Посещает URL циклами: sleep(межцикловая) → N кликов(+sleep между ними) → повтор."""
|
||||
total_done = 0
|
||||
max_v = params.max_visits or 1
|
||||
|
||||
async def _sleep_interruptible(seconds: int):
|
||||
@@ -2056,7 +2116,7 @@ class BotInterface:
|
||||
await asyncio.sleep(1)
|
||||
|
||||
try:
|
||||
while total_done < max_v and not params.stopped:
|
||||
while params.successful_visits < max_v and not params.stopped:
|
||||
# --- пауза перед циклом ---
|
||||
await _sleep_interruptible(params.get_delay())
|
||||
if params.stopped:
|
||||
@@ -2067,7 +2127,7 @@ class BotInterface:
|
||||
|
||||
# --- цикл кликов ---
|
||||
for click_num in range(series_size):
|
||||
if params.stopped or total_done >= max_v:
|
||||
if params.stopped or params.successful_visits >= max_v:
|
||||
break
|
||||
|
||||
while params.paused and not params.stopped:
|
||||
@@ -2085,7 +2145,6 @@ class BotInterface:
|
||||
try:
|
||||
result = await self.browser_service.visit_page(params.url, reading)
|
||||
params.total_visits += 1
|
||||
total_done += 1
|
||||
if result.success:
|
||||
params.successful_visits += 1
|
||||
await self.balance_storage.deduct(params.user_id, 1)
|
||||
@@ -2093,10 +2152,10 @@ class BotInterface:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"URL visit error: {e}")
|
||||
total_done += 1
|
||||
params.total_visits += 1
|
||||
|
||||
# задержка между кликами внутри цикла (кроме последнего)
|
||||
if click_num < series_size - 1 and not params.stopped and total_done < max_v:
|
||||
if click_num < series_size - 1 and not params.stopped and params.successful_visits < max_v:
|
||||
await _sleep_interruptible(params.get_click_delay())
|
||||
|
||||
await self.task_manager.complete_task(task_id)
|
||||
@@ -2290,10 +2349,11 @@ class BotInterface:
|
||||
InlineKeyboardButton(text="🗑️", callback_data=f"ustop_{tid}"),
|
||||
)
|
||||
else:
|
||||
builder.row(InlineKeyboardButton(
|
||||
text=f"🗑️ {label} (завершена)",
|
||||
callback_data=f"ustop_{tid}"
|
||||
))
|
||||
builder.row(
|
||||
InlineKeyboardButton(text=label, callback_data=f"utask_{tid}"),
|
||||
InlineKeyboardButton(text="🔄", callback_data=f"urestart_{tid}"),
|
||||
InlineKeyboardButton(text="🗑️", callback_data=f"ustop_{tid}"),
|
||||
)
|
||||
builder.row(InlineKeyboardButton(text="📝 Новая задача", callback_data="new_task"))
|
||||
builder.row(InlineKeyboardButton(text="🔙 Мои задачи", callback_data="my_tasks"))
|
||||
|
||||
@@ -2417,8 +2477,7 @@ class BotInterface:
|
||||
f"✅ Переходов: {count}\n\n"
|
||||
"Шаг 3/4 — сколько кликов в одном цикле?\n\n"
|
||||
"Бот делает N кликов подряд, затем ждёт паузу и начинает следующий цикл.\n\n"
|
||||
"Диапазон `2-5` — каждый цикл будет случайной длины от 2 до 5.\n"
|
||||
"Одно число `3` — всегда ровно 3 клика.",
|
||||
"Диапазон `2-5` — каждый цикл будет случайной длины от 2 до 5.",
|
||||
reply_markup=builder.as_markup()
|
||||
)
|
||||
self._menu_msg[user_id] = sent.message_id
|
||||
@@ -2444,7 +2503,6 @@ class BotInterface:
|
||||
sent = await message.answer(
|
||||
f"✅ Цикл: {series_label} кликов\n\n"
|
||||
"Шаг 4/4 — таймаут между циклами (в минутах)\n\n"
|
||||
"`3` — ровно 3 минуты.\n"
|
||||
"`2-5` — случайно от 2 до 5 минут.",
|
||||
reply_markup=builder.as_markup()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user