summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitrii Morozov <snoopdesigns@gmail.com>2025-06-01 22:04:06 +0200
committerDmitrii Morozov <snoopdesigns@gmail.com>2025-06-01 22:04:06 +0200
commit15e171ee3cf667439b8703a70436a3db3f592aba (patch)
tree0d6a5bb091e407064f8357911ac8f7ec58339bbe
Initial
-rw-r--r--.gitignore2
-rwxr-xr-xcrop-finder.py64
-rw-r--r--farmer.py209
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()