import asyncio
import ctypes
import os
import time
from playwright.async_api import async_playwright
# --- 1. Ẩn cửa sổ CMD ngay khi khởi động ---
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 CÀI ĐẶT
# -------------------------------------------------------------
TOTAL_CAGES = 3
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ACCOUNTS_FILE = os.path.join(BASE_DIR, "accounts.txt")
INTERVAL_HOURLY = 1 * 60 * 60 # Chu kỳ 1 giờ (Nông trại, Hồ cá)
INTERVAL_12HOURS = 12 * 60 * 60 # Chu kỳ 12 giờ (Điểm danh, Vật nuôi)
HEADLESS = True # Chạy ẩn trình duyệt
# -------------------------------------------------------------
def load_accounts(file_path):
accounts = []
if not os.path.exists(file_path):
print(f"[-] File {file_path} không tồn tại!")
return accounts
with open(file_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if "|" in line and not line.startswith("#"):
user, pwd = line.split("|", 1)
accounts.append((user.strip(), pwd.strip()))
return accounts
async def safe_goto(page, url, retries=3):
"""Hàm truy cập URL an toàn với cơ chế thử lại khi gặp lỗi mạng."""
for attempt in range(1, retries + 1):
try:
await page.goto(url, wait_until="domcontentloaded", timeout=60000)
return True
except Exception as e:
print(f" [!] Lỗi tải trang ({attempt}/{retries}): {e}")
if attempt < retries:
await asyncio.sleep(2)
else:
raise e
async def process_account(browser, username, password, should_run_12h_task):
"""Xử lý toàn bộ công việc cho một tài khoản."""
print("\n==========================================")
print(f"[*] Đang xử lý tài khoản: {username}")
context = await browser.new_context()
page = await context.new_page()
# Tự động bấm "OK" cho các hộp thoại xác nhận
page.on("dialog", lambda dialog: dialog.accept())
page.set_default_timeout(60000)
page.set_default_navigation_timeout(60000)
try:
# 1. ĐĂNG NHẬP
print("[1] Mở trang đăng nhập...")
await safe_goto(page, "https://1900.fun/login.php")
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(1500)
# =========================================================
# NHÓM TÁC VỤ 12 GIỜ (ĐIỂM DANH & VẬT NUÔI)
# =========================================================
if should_run_12h_task:
print("\n--- [ TÁC VỤ 12 GIỜ: ĐIỂM DANH & CHUỒNG VẬT NUÔI ] ---")
# 2. ĐIỂM DANH
print("[2] Kiểm tra điểm danh hàng ngày...")
await safe_goto(page, "https://1900.fun/profile.php")
await page.wait_for_timeout(1000)
checkin_button = page.locator("button[name='checkin']")
if await checkin_button.count() > 0:
is_disabled = await checkin_button.is_disabled()
if not is_disabled:
print(" -> Chưa điểm danh → Tiến hành điểm danh...")
await checkin_button.click()
await page.wait_for_timeout(1500)
print(" -> Điểm danh thành công!")
else:
print(" -> Đã điểm danh rồi → Bỏ qua")
else:
print(" -> Không tìm thấy nút điểm danh")
# 3. BÁN TẤT CẢ VẬT NUÔI HIỆN CÓ
print("[3] BÁN VẬT NUÔI: Đang thực hiện bán cho từng chuồng...")
for cage_idx in range(TOTAL_CAGES):
await safe_goto(page, "https://1900.fun/nongtrai/vatnuoi.php")
await page.wait_for_timeout(1000)
sell_btn = page.locator(f"a[href='?harvest={cage_idx}']")
if await sell_btn.count() > 0:
async with page.expect_navigation(
wait_until="domcontentloaded"
):
await sell_btn.click()
print(
f" -> Đã bán thành công vật nuôi ở Chuồng {cage_idx + 1}"
)
await page.wait_for_timeout(1500)
else:
print(
f" -> Chuồng {cage_idx + 1} không có vật nuôi để bán hoặc đã trống."
)
# 4. CHỌN VẬT NUÔI CẤP CAO NHẤT
print("[4] Tính toán chọn vật nuôi tối ưu theo Cấp độ & Số xu...")
await safe_goto(page, "https://1900.fun/nongtrai/vatnuoi.php")
await page.wait_for_timeout(1000)
animal_data = await page.evaluate("""() => {
return {
animals: typeof animals !== 'undefined' ? animals : [],
userLevel: typeof userLevel !== 'undefined' ? userLevel : 1,
userMoney: typeof userMoney !== 'undefined' ? userMoney : 0
};
}""")
animals = animal_data.get("animals", [])
user_level = animal_data.get("userLevel", 1)
user_money = animal_data.get("userMoney", 0)
print(
f" -> Cấp trại: {user_level} | Số xu hiện có: {user_money:,} xu"
)
affordable_animals = [
a
for a in animals
if user_level >= a.get("level_required", 1)
and user_money >= a.get("price", 0)
]
if not affordable_animals:
print(
" -> [!] Không đủ tiền hoặc cấp độ không đủ để mua vật nuôi!"
)
selected_animal_id = None
else:
best_animal = max(
affordable_animals,
key=lambda x: (
x.get("level_required", 1),
x.get("price", 0),
),
)
selected_animal_id = str(best_animal.get("id"))
print(
f" -> [Chốt] Mua loại cao nhất: {best_animal.get('name')} (ID: {selected_animal_id})"
)
# 5. MUA VẬT NUÔI CHO TỪNG CHUỒNG
if selected_animal_id:
print("[5] MUA VẬT NUÔI: Tiến hành thả nuôi...")
for cage_idx in range(TOTAL_CAGES):
await safe_goto(
page, "https://1900.fun/nongtrai/vatnuoi.php"
)
await page.wait_for_timeout(1000)
if await page.locator("#buyForm").count() > 0:
await page.evaluate(f"""() => {{
document.getElementById('buyCageIndex').value = '{cage_idx}';
document.getElementById('buyAnimalId').value = '{selected_animal_id}';
}}""")
async with page.expect_navigation(
wait_until="domcontentloaded"
):
await page.eval_on_selector(
"#buyForm", "form => form.submit()"
)
print(
f" -> Đã mua thành công cho Chuồng {cage_idx + 1}"
)
await page.wait_for_timeout(1500)
# =========================================================
# NHÓM TÁC VỤ 1 GIỜ (VƯỜN CÂY & HỒ CÁ)
# =========================================================
print("\n--- [ TÁC VỤ HÀNG GIỜ: VƯỜN CÂY & HỒ CÁ ] ---")
# 6. THU HOẠCH VƯỜN
print("[6] Thu hoạch nông trại...")
await safe_goto(
page, "https://1900.fun/nongtrai/index.php?harvest_all=1"
)
await page.wait_for_timeout(2000)
# 7. CHỌN CÂY VÀ GIEO HẠT
print("[7] Kiểm tra cấp độ nông trại và chọn cây trồng phù hợp...")
await safe_goto(page, "https://1900.fun/nongtrai/index.php")
best_crop = await page.evaluate("""() => {
if (typeof cropsData !== 'undefined' && typeof userLevel !== 'undefined') {
const availableCrops = cropsData.filter(c => c.level_required <= userLevel);
if (availableCrops.length > 0) {
availableCrops.sort((a, b) => b.level_required - a.level_required);
return availableCrops[0];
}
}
return null;
}""")
if best_crop and await page.locator("#quickPlantForm").count() > 0:
crop_id = str(best_crop["id"])
crop_name = best_crop["name"]
req_lvl = best_crop["level_required"]
print(
f" -> Cây phù hợp nhất: {crop_name} (ID: {crop_id} - Yêu cầu Cấp {req_lvl})"
)
print(f" -> Tiến hành gieo hạt nhanh {crop_name}...")
await page.evaluate(
f"document.getElementById('quickCropId').value = '{crop_id}';"
)
async with page.expect_navigation(wait_until="domcontentloaded"):
await page.eval_on_selector(
"#quickPlantForm", "form => form.submit()"
)
await page.wait_for_timeout(2000)
else:
print(" -> Không tìm thấy thông tin cây trồng phù hợp.")
# 8. BÁN CÁ
print("[8] Bán tất cả cá...")
await safe_goto(
page, "https://1900.fun/nongtrai/hoca.php?sell_all_fish=1"
)
await page.wait_for_timeout(2000)
# 9. CHỌN VÀ MUA CÁ MỚI
print("[9] Kiểm tra cấp độ và mua loại cá phù hợp nhất...")
await safe_goto(page, "https://1900.fun/nongtrai/hoca.php")
fish_info = await page.evaluate("""() => {
const el = document.querySelector('.pond-level-box span:last-child');
if (el) {
const match = el.innerText.match(/(\\d+)\\/(\\d+)/);
if (match) {
return { current: parseInt(match[1]), max: parseInt(match[2]) };
}
}
return { current: 0, max: 2 };
}""")
needed_fish = fish_info["max"] - fish_info["current"]
if needed_fish > 0:
best_fish = await page.evaluate("""() => {
if (typeof fishList !== 'undefined' && typeof userLevel !== 'undefined' && typeof userMoney !== 'undefined') {
const available = fishList.filter(f => f.level_required <= userLevel && f.price <= userMoney);
if (available.length > 0) {
available.sort((a, b) => b.level_required - a.level_required);
return available[0];
}
}
return null;
}""")
if best_fish:
fish_id = str(best_fish["id"])
fish_name = best_fish.get("name", "Cá")
print(
f" -> Hồ hiện tại: {fish_info['current']}/{fish_info['max']}. Mua cá: {fish_name} (ID: {fish_id})"
)
for i in range(needed_fish):
print(
f" -> Đang mua con thứ {i + 1}/{needed_fish}..."
)
await page.evaluate(f"""() => {{
document.getElementById('buyFishType').value = '{fish_id}';
}}""")
async with page.expect_navigation(
wait_until="domcontentloaded"
):
await page.eval_on_selector(
"#buyForm", "form => form.submit()"
)
await page.wait_for_timeout(1500)
else:
print(
" -> Không tìm thấy loại cá phù hợp hoặc không đủ Xu."
)
else:
print(
f" -> Hồ đã đầy ({fish_info['current']}/{fish_info['max']} con)."
)
# 10. ĐĂNG XUẤT
print("\n[10] Đăng xuất...")
await safe_goto(page, "https://1900.fun/logout.php")
await page.wait_for_timeout(1500)
print(f"[+] Hoàn tất cho: {username}")
except Exception as e:
print(f"[-] Có lỗi xảy ra đối với {username}: {e}")
finally:
await context.close()
await asyncio.sleep(2)
async def run_automation(should_run_12h_task):
accounts = load_accounts(ACCOUNTS_FILE)
if not accounts:
print("[-] Danh sách tài khoản trống!")
return
async with async_playwright() as p:
browser = await p.chromium.launch(headless=HEADLESS)
for username, password in accounts:
await process_account(browser, username, password, should_run_12h_task)
await browser.close()
if __name__ == "__main__":
last_12h_run_time = 0
while True:
try:
current_time = time.time()
# Kiểm tra xem đã đủ 12 giờ kể từ lần chạy tác vụ 12h trước đó chưa
should_run_12h_task = (
current_time - last_12h_run_time
) >= INTERVAL_12HOURS
print(
"\n==================== [ BẮT ĐẦU VÒNG LẶP NÔNG TRẠI TỔNG HỢP ] ===================="
)
if should_run_12h_task:
print("[*] Chế độ: Chạy ĐẦY ĐỦ (Cả tác vụ 12h và 1h)")
else:
print("[*] Chế độ: Chạy NHANH (Chỉ tác vụ Hàng giờ)")
asyncio.run(run_automation(should_run_12h_task))
if should_run_12h_task:
last_12h_run_time = current_time
except Exception as err:
print(f"[!] Gặp lỗi ngoài dự kiến: {err}")
print(
f"\n[⏳] Đã hoàn thành vòng lặp. Chờ 1 giờ ({INTERVAL_HOURLY}s) để chạy tiếp..."
)
time.sleep(INTERVAL_HOURLY)