import os import csv import time import sys import re import random from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.chrome.options import Options from dotenv import load_dotenv load_dotenv() USERNAME = os.getenv("TRAVIAN_USERNAME") PASSWORD = os.getenv("TRAVIAN_PASSWORD") SERVER = os.getenv("TRAVIAN_SERVER") if not USERNAME or not PASSWORD or not SERVER: print("Ошибка: Не удалось загрузить переменные окружения TRAVIAN_USERNAME, TRAVIAN_PASSWORD, TRAVIAN_SERVER") sys.exit(1) FARM_UNITS = { "leg": 10, "imp": 10, "horse_imp": 5 } UNIT_IDS = { "leg": "troop[t1]", "imp": "troop[t3]", "horse_imp": "troop[t5]" } def find_inactives(driver, coords): # 0 - x # 1 - y driver.get("https://www.gettertools.com/ts8.x1.europe.travian.com.6/42-Search-inactives") random_sleep() # Принять Cookies driver.find_elements(by=By.CSS_SELECTOR, value='button[name="cookieConsentAcceptAll"]')[0].click() random_sleep() driver.find_elements(by=By.CSS_SELECTOR, value='button[aria-label="Consent"]')[0].click() random_sleep() # Указать координаты деревни xyx = driver.find_element(By.CSS_SELECTOR, 'input[name="xyX"]') xyx.clear() xyx.send_keys(coords[0]) xyy = driver.find_element(By.CSS_SELECTOR, 'input[name="xyY"]') xyy.clear() xyy.send_keys(coords[1]) # Указать максимум деревень maxCities = driver.find_element(By.CSS_SELECTOR, 'input[name="maxSpielerCitys"]') maxCities.clear() maxCities.send_keys("1") # Начать поиск submit_button = driver.find_element(by=By.CSS_SELECTOR, value='button[class="stylebutton aicon load-feedback"]') submit_button.click() random_sleep() result = [] table = driver.find_element(By.CSS_SELECTOR, 'table[class="orangeTable dorf nowrap"]') rows = table.find_elements(By.TAG_NAME, "tr") for row in rows: if "it1" in row.get_attribute("class") or "it2" in row.get_attribute("class"): coords_text = row.find_element(By.TAG_NAME, "td").text.replace("\n", "").replace("( ", "").replace(" )", "") xx = coords_text.split("|")[0] yy = coords_text.split("|")[1] name = row.find_element(By.CSS_SELECTOR, 'td[class="rb"]').text ally = row.find_element(By.CSS_SELECTOR, 'td[class="tally"]').text pop = int(row.find_element(By.CSS_SELECTOR, 'td[class="tdews "]').text) result_item = (xx, yy, name, ally, pop) result.append(result_item) return result def login(driver): # Вызываем главную страницу сервера driver.get(SERVER) random_sleep() # Указываем логин и пароль в необходимых полях ввода driver.find_element(By.NAME, "name").send_keys(USERNAME) random_sleep() driver.find_element(By.NAME, "password").send_keys(PASSWORD) random_sleep() # Находим кнопку по тексту "Login" и нажимаем driver.find_elements(by=By.CSS_SELECTOR, value='button[type="submit"]')[0].click() random_sleep() def select_village(driver): villages = driver.find_element(By.CSS_SELECTOR, 'div[id="sidebarBoxVillageList"]') villages = villages.find_elements(By.CSS_SELECTOR, 'div[class="dropContainer"]') village_index = 1 villages_selectors = [] village_coords = [] for village in villages: villages_selectors.append(village) village_info = re.sub(r'[\u202A-\u202E\u200E\u200F]', '', village.text) village_name = village_info.split("\n")[0] coords = village_info.split("\n")[1] coords_cleaned = coords.replace("(", "").replace(")", "") xx = coords_cleaned.split("|")[0].replace("−", "-") yy = coords_cleaned.split("|")[1].replace("−", "-") print("(" + str(village_index) + ") " + village_name + " (" + xx + "|" + yy + ")") village_coords.append((xx, yy)) village_index = village_index + 1 selected = int(input("Выберите деревню для фарма ")) - 1 villages_selectors[selected].click() random_sleep() return village_coords[selected] def ask(question): resp = input(question + " ") if resp == "" or resp == "y": return True return False def send_raid(driver, info): # 0 - x # 1 - y # 2 - имя # 3 - альянс # 4 - население if info[3]: if not ask("Игрок в альянсе, продолжить?"): return if info[4] > 50: if not ask("Население больше 50, продолжить?"): return # Переход в пункт сбора driver.get(SERVER + "/build.php?tt=2&id=39") random_sleep() # Ввод координат driver.find_element(By.NAME, "x").send_keys(info[0]) driver.find_element(By.NAME, "y").send_keys(info[1]) # Выбор типа атаки (4 - набег) driver.find_element(By.CSS_SELECTOR, "input[value='4']").click() # Ввод войск success = False for unit, amount in FARM_UNITS.items(): input_name = UNIT_IDS[unit] unit_input = driver.find_element(By.NAME, input_name) available_elements = unit_input.find_element(By.XPATH, "..").find_elements(By.TAG_NAME, "a") if (len(available_elements) == 0): continue; available = available_elements[0].text # Удалить HTML сущности и превратить в число available = int(re.sub(r'[\u202A-\u202E\u200E\u200F]', '', available)) if available >= amount: unit_input.clear() unit_input.send_keys(str(amount)) success = True break else: continue if not success: print("Закончились юниты для фарма") sys.exit(1) # Отправить driver.find_elements(by=By.CSS_SELECTOR, value='button[type="submit"]')[0].click() random_sleep() # Подтверждение отправки confirm = driver.find_elements(by=By.CSS_SELECTOR, value='button[name="confirmSendTroops"]') if len(confirm) > 0: confirm[0].click() random_sleep() else: print("Ошибка отправки набега, деревня не существует?") def main(): options = Options() options.add_argument("--start-maximized") driver = webdriver.Chrome(options=options) try: login(driver) village = select_village(driver) targets = find_inactives(driver, village) for target in targets: print(f"Отправка рейда на ({target[0]}, {target[1]}), имя ({target[2]}), альянс ({target[3]}), население ({target[4]})") send_raid(driver, target) finally: driver.quit() def random_sleep(): value = random.randint(1, 3) time.sleep(value) if __name__ == "__main__": main()