diff options
author | Dmitrii Morozov <snoopdesigns@gmail.com> | 2025-06-01 22:04:06 +0200 |
---|---|---|
committer | Dmitrii Morozov <snoopdesigns@gmail.com> | 2025-06-01 22:04:06 +0200 |
commit | 15e171ee3cf667439b8703a70436a3db3f592aba (patch) | |
tree | 0d6a5bb091e407064f8357911ac8f7ec58339bbe |
Initial
-rw-r--r-- | .gitignore | 2 | ||||
-rwxr-xr-x | crop-finder.py | 64 | ||||
-rw-r--r-- | farmer.py | 209 |
3 files changed, 275 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d38d3d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +chrome-*
\ No newline at end of file diff --git a/crop-finder.py b/crop-finder.py new file mode 100755 index 0000000..7704a88 --- /dev/null +++ b/crop-finder.py @@ -0,0 +1,64 @@ +import csv +import time +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys + +from dotenv import load_dotenv + +load_dotenv() + +USERNAME = os.getenv("TRAVIAN_USERNAME") +PASSWORD = os.getenv("TRAVIAN_PASSWORD") +SERVER_URL = os.getenv("TRAVIAN_SERVER") + +if not USERNAME or not PASSWORD or not SERVER: + print("Ошибка: Не удалось загрузить переменные окружения TRAVIAN_USERNAME, TRAVIAN_PASSWORD, TRAVIAN_SERVER") + sys.exit(1) + +CENTER_X = -125 +CENTER_Y = -18 +RADIUS = 20 + +# === НАЧАЛО === +driver = webdriver.Chrome() +driver.get(f"{SERVER_URL}/login.php") + +# Логин +driver.find_element(By.NAME, "name").send_keys(USERNAME) +driver.find_element(By.NAME, "password").send_keys(PASSWORD) +time.sleep(1) +# Находим кнопку по тексту "Login" и нажимаем +buttons = driver.find_elements(by=By.CSS_SELECTOR, value='button[type="submit"]') +buttons[0].click() +time.sleep(5) + +def in_radius(x1, y1, x2, y2, r): + return ((x1 - x2)**2 + (y1 - y2)**2)**0.5 <= r + +tiles = [] + +# Проходим по диапазону клеток +for dx in range(CENTER_X - RADIUS, CENTER_X + RADIUS + 1): + for dy in range(CENTER_Y - RADIUS, CENTER_Y + RADIUS + 1): + if not in_radius(CENTER_X, CENTER_Y, dx, dy, RADIUS): + continue + + driver.get(f"{SERVER_URL}/karte.php?x={dx}&y={dy}") + + try: + title = driver.find_element(by=By.CLASS_NAME, value="titleInHeader").text + if "Покинутая долина" in title: + info = driver.find_element(By.ID, "distribution") + trs = info.find_elements(by=By.TAG_NAME, value="tr") + for tr in trs: + desc = tr.find_element(by=By.CLASS_NAME, value="desc").text + val = tr.find_element(by=By.CLASS_NAME, value="val").text + if desc == "Ферм" and (int(val) == 9 or int(val) == 15): + print(f"{dx} {dy}, {desc} {val}") + except: + continue + + time.sleep(0.5) + +driver.quit() diff --git a/farmer.py b/farmer.py new file mode 100644 index 0000000..0b70376 --- /dev/null +++ b/farmer.py @@ -0,0 +1,209 @@ +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": 5, + "imp": 5, + "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() |