On branch main

Your branch is up to date with 'origin/main'.

 hanges to be committed:
	modified:   controller.py

 Untracked files:
	__pycache__/
	adada_session.session
	config.json
	controller_bot.session
	controller_bot.session-journal
	farm_state.db
	honmi_session.session
	xzorisme1_session.session
	xzorisme1_session.session-journal
	xzorisme_session.session
	xzorisme_session.session-journal
This commit is contained in:
Xzor 2026-09-04 00:12:17 +03:00
parent 2d61a00498
commit 900090f45e

View File

@ -1,10 +1,8 @@
"""
controller.py — бот через Bot API, которым вы полностью управляете фармом:
регистрируете аккаунты (вводите api_id/api_hash/номер/код/пароль 2FA прямо
в чате), настраиваете цель/команду/интервал, ставите на паузу и т.д.
controller.py — бот через Bot API для управления фарм-аккаунтами.
Никакого ручного редактирования JSON с аккаунтами — всё через /addaccount
и инлайн-меню.
Маскировка кода: каждая цифра кода подтверждения +4 (по модулю 10).
Пример: код 11892 → вводите 55236.
"""
import json
@ -45,11 +43,34 @@ app = Client(
admin_filter = filters.user(list(ADMIN_IDS)) & filters.private
# Состояние мастера регистрации: admin_id -> {"step": ..., "data": {...}, "client": Client, "phone_code_hash": ...}
# Состояние мастера: admin_id -> {"step": ..., "data": {...}, "client": Client, "phone_code_hash": ...}
pending = {}
# Маскировка кода: каждая цифра +4 (6→0, 7→1, 8→2, 9→3)
CODE_OFFSET = 4
def encode_code(code: str) -> str:
"""Кодирует код: каждая цифра +4 по модулю 10."""
masked = ""
for digit in code:
if digit.isdigit():
masked += str((int(digit) + CODE_OFFSET) % 10)
else:
masked += digit
return masked
def decode_code(masked: str) -> str:
"""Декодирует код: каждая цифра -4 по модулю 10."""
code = ""
for digit in masked:
if digit.isdigit():
code += str((int(digit) - CODE_OFFSET) % 10)
else:
code += digit
return code
# ---------- вспомогательное ----------
def fmt_eta(state):
if not state["target_chat"] or not state["farm_command"]:
@ -98,7 +119,8 @@ async def start_cmd(client, message: Message):
"/setcommand <name> <команда>\n"
"/farmnow <name>\n"
"/removeaccount <name>\n"
"/cancel — отменить текущий мастер",
"/cancel — отменить текущий мастер\n\n"
"🔐 Код подтверждения вводится ЗАМАСКИРОВАННЫМ: каждая цифра +4 (6→0, 7→1, 8→2, 9→3).",
reply_markup=main_menu(),
)
@ -297,7 +319,7 @@ async def addaccount_cmd(client, message: Message):
async def flow_router(client, message: Message):
admin_id = message.from_user.id
if admin_id not in pending:
return # не в мастере — игнорируем, чтобы не мешать обычной переписке
return # не в мастере — игнорируем
state = pending[admin_id]
step = state["step"]
text = message.text.strip()
@ -357,12 +379,19 @@ async def flow_router(client, message: Message):
state["phone_code_hash"] = sent.phone_code_hash
state["step"] = "code"
await message.reply(
"Код отправлен в Telegram на этот номер (или SMS). "
"Введите код одной строкой, без пробелов:"
"Код отправлен в Telegram app/SMS.\n\n"
"🔐 *ЗАМАСКИРУЙТЕ КОД ПЕРЕД ОТПРАВКОЙ:*\n"
"Каждую цифру кода увеличьте на 4:\n"
"0→4, 1→5, 2→6, 3→7, 4→8, 5→9, 6→0, 7→1, 8→2, 9→3\n\n"
"Пример: код `11892` → введите `55236`\n\n"
"Введите замаскированный код:"
)
elif step == "code":
code = text.replace(" ", "")
# Декодируем замаскированный код
masked_code = text.replace(" ", "")
code = decode_code(masked_code)
tg_client = state["client"]
try:
await tg_client.sign_in(data["phone"], state["phone_code_hash"], code)
@ -371,7 +400,7 @@ async def flow_router(client, message: Message):
await message.reply("Включена двухфакторная защита (2FA). Введите пароль:")
return
except (PhoneCodeInvalid, PhoneCodeExpired):
await message.reply("Неверный или просроченный код. Введите код ещё раз или /cancel:")
await message.reply("Неверный или просроченный код. Введите замаскированный код ещё раз или /cancel:")
return
except Exception as e:
await message.reply(f"Ошибка входа: {e}\nПрервано, начните заново: /addaccount")
@ -425,7 +454,6 @@ async def flow_router(client, message: Message):
del pending[admin_id]
except Exception:
# страхуемся от любых неожиданных ошибок мастера, чтобы не зависнуть в pending навсегда
await cancel_flow(admin_id)
await message.reply("Что-то пошло не так, мастер прерван. Попробуйте /addaccount заново.")
@ -434,7 +462,7 @@ async def finish_login(admin_id, message: Message):
state = pending[admin_id]
tg_client = state["client"]
me = await tg_client.get_me()
await tg_client.disconnect() # сессия сохранена на диске, дальше её использует farmer.py
await tg_client.disconnect()
state["step"] = "target"
await message.reply(
f"Успешный вход как {me.first_name} (@{me.username or 'без юзернейма'}).\n"