import asyncio
import json
import math
import random
import re
import ctypes
from playwright.async_api import async_playwright
# --- Ẩn cửa sổ CMD ---
def hide_console():
try:
hwnd = ctypes.windll.kernel32.GetConsoleWindow()
if hwnd:
ctypes.windll.user32.ShowWindow(hwnd, 0)
except Exception:
pass
hide_console()
# ================== CẤU HÌNH ==================
USERNAME = "hoangchan2"
PASSWORD = "abc13579"
LOGIN_URL = "https://1900.fun/login.php"
THAM_HIEM_URL = "https://1900.fun/city/thamhiem/"
# Thời gian nghỉ giữa các vòng = 1 phút
INTERVAL_SECONDS = 1 * 60
# ==============================================
def clean_and_parse_json(raw_text: str) -> dict:
try:
match = re.search(r"\{.*\}", raw_text, re.DOTALL)
if match:
return json.loads(match.group(0))
return {"success": False, "error": f"Không tìm thấy JSON: {raw_text[:150]}"}
except Exception as e:
return {"success": False, "error": f"Lỗi parse JSON: {e}"}
async def fetch_ajax(page, body: str) -> dict:
raw = await page.evaluate(
f"""async () => {{
try {{
const res = await fetch('ajax_dungeon.php', {{
method: 'POST',
headers: {{ 'Content-Type': 'application/x-www-form-urlencoded' }},
body: '{body}'
}});
return await res.text();
}} catch (e) {{
return e.toString();
}}
}}"""
)
return clean_and_parse_json(raw)
async def run_boss_bot() -> str:
"""
Chạy 1 vòng thám hiểm.
Trả về: "win_cycle" | "lose" | "error"
"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
)
page = await context.new_page()
try:
# 1. Đăng nhập
print(f"[*] Đăng nhập: {USERNAME}")
await page.goto(LOGIN_URL, wait_until="domcontentloaded")
await page.fill("input[name='username']", USERNAME)
await page.fill("input[name='password']", PASSWORD)
async with page.expect_navigation(wait_until="domcontentloaded"):
await page.click("button[type='submit']")
await page.wait_for_timeout(1200)
# 2. Vào trang Thám hiểm
print("[*] Vào trang Thám hiểm...")
await page.goto(THAM_HIEM_URL, wait_until="domcontentloaded")
await page.wait_for_timeout(1500)
# 3. Lấy dữ liệu cửa ải hiện tại
init_data = await fetch_ajax(page, "action=get_current_floor")
if not init_data.get("success"):
err = init_data.get("error", "Không xác định")
print(f"[!] Lỗi khởi tạo: {err}")
if "reset" in str(err).lower() or "chờ" in str(err).lower() or "đợi" in str(err).lower():
return "lose"
return "error"
current_floor = init_data.get("floor", 1)
monster = init_data.get("monster", {})
monster_hp = monster.get("hp", 0)
monster_strength = monster.get("strength", 0)
monster_name = monster.get("name", "Boss")
player_hp = init_data.get("player_hp", 0)
player_strength = init_data.get("player_strength", 0)
# 4. Vòng lặp leo ải
while True:
print(f"\n========== [ CỬA ẢI {current_floor} ] ==========")
print(f"👤 Bạn | HP: {player_hp:,} | SM: {player_strength}")
print(f"👾 {monster_name} | HP: {monster_hp:,} | SM: {monster_strength}")
curr_p_hp = player_hp
curr_m_hp = monster_hp
is_my_turn = True
while curr_p_hp > 0 and curr_m_hp > 0:
if is_my_turn:
dmg = max(5, math.floor(random.random() * player_strength) + 8)
curr_m_hp = max(0, curr_m_hp - dmg)
is_my_turn = False
else:
dmg = max(5, math.floor(random.random() * monster_strength) + 8)
curr_p_hp = max(0, curr_p_hp - dmg)
is_my_turn = True
is_win = curr_m_hp <= 0
print(f"[⚔️] Kết quả: {'CHIẾN THẮNG' if is_win else 'THẤT BẠI'}")
result = "win" if is_win else "lose"
battle_res = await fetch_ajax(
page,
f"action=end_battle&result={result}&floor={current_floor}"
)
if not battle_res.get("success"):
print(f"[!] Server từ chối: {battle_res.get('error')}")
return "error"
print(f" └─ {battle_res.get('message', 'OK')}")
if battle_res.get("drop_item"):
item = battle_res["drop_item"]
print(f" └─ 🎁 {item.get('name')} (+{item.get('enhance_level', 0)})")
if battle_res.get("new_xu"):
print(f" └─ 🪙 Xu mới: {battle_res['new_xu']:,}")
if not is_win:
print("\n[⛔] Thua → về cửa ải 1.")
return "lose"
await asyncio.sleep(random.uniform(1.2, 2.0))
next_data = await fetch_ajax(page, "action=get_current_floor")
if not next_data.get("success"):
print("[!] Không lấy được cửa ải tiếp theo.")
return "error"
current_floor = next_data.get("floor", current_floor + 1)
monster = next_data.get("monster", {})
monster_hp = monster.get("hp", 0)
monster_strength = monster.get("strength", 0)
monster_name = monster.get("name", "Boss")
player_hp = next_data.get("player_hp", player_hp)
player_strength = next_data.get("player_strength", player_strength)
except Exception as e:
print(f"[!] Lỗi: {e}")
return "error"
finally:
await browser.close()
return "win_cycle"
async def main():
cycle = 1
while True:
print("\n" + "=" * 60)
print(f" BẮT ĐẦU VÒNG LẶP THỨ {cycle}")
print("=" * 60)
try:
result = await run_boss_bot()
except Exception as e:
print(f"[!] Lỗi ngoài: {e}")
result = "error"
if result == "lose":
print(f"\n[⏳] Thua / đang cooldown. Nghỉ 1 phút rồi thử lại...")
elif result == "error":
print(f"\n[⏳] Có lỗi. Nghỉ 1 phút rồi thử lại...")
else:
print(f"\n[⏳] Hoàn thành vòng. Nghỉ 1 phút rồi chạy tiếp...")
await asyncio.sleep(INTERVAL_SECONDS)
cycle += 1
if __name__ == "__main__":
asyncio.run(main())