GrepolisBot

Automates farm collection, culture events, and attack dodging in Grepolis

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         GrepolisBot
// @namespace    http://tampermonkey.net/
// @version      2.0.0
// @description  Automates farm collection, culture events, and attack dodging in Grepolis
// @author       ničite4000l
// @homepageURL  https://github.com/NaKamize/GrepolisBot
// @match        *://*.grepolis.com/*
// @grant        none
// ==/UserScript==
"use strict";(()=>{var f=class{constructor(t,e){this.mainDiv=t,this.autoFarm=e,this.isRunning=!1}createHeading(){let t=document.createElement("h3");return t.textContent="Farm Manager",t.className="gb-section-title",t.style.color="#74ff97",t}createDropDown(){let t=document.createElement("select");t.setAttribute("name","farm-drop-down"),t.className="gb-select";let e=["00:05:00","00:10:00","00:20:00","00:40:00","01:30:00","03:00:00","04:00:00","08:00:00"];for(let i=0;i<e.length;i++){let n=document.createElement("option");n.text=e[i],t.appendChild(n)}return t}createButton(){let t=document.createElement("button");return t.textContent="Start",t.className="gb-btn",t.addEventListener("click",async()=>{let i=document.querySelector("select[name='farm-drop-down']").value;if(!this.isRunning){this.isRunning=!0,t.textContent="Stop";try{await this.autoFarm.start(i)}catch(n){console.error("Failed to start AutoFarm:",n),this.autoFarm.stop()}this.isRunning=!1,t.textContent="Start";return}this.autoFarm.stop(),this.isRunning=!1,t.textContent="Start"}),t}createAutoFarmDiv(){let t=document.createElement("div");return t.className="auto-farm gb-row",t}createFarmUI(){let t=document.createElement("section");t.className="gb-section";let e=this.createHeading(),i=document.createElement("div");i.className="gb-title-row";let n=document.createElement("span");n.className="gb-info-badge",n.textContent="i";let a=document.createElement("span");a.className="gb-tooltip",a.textContent="Vyber interval vo formate HH:MM:SS. Po kazdom kole sa prida nahodny delay 5-30 sekund.",n.appendChild(a),i.appendChild(e),i.appendChild(n);let o=document.createElement("p");o.className="gb-label",o.textContent="Interval farmenia (HH:MM:SS)";let s=this.createDropDown(),r=this.createButton(),l=this.createAutoFarmDiv();l.appendChild(s),l.appendChild(r),t.appendChild(i),t.appendChild(o),t.appendChild(l),this.mainDiv.appendChild(t)}};var y=class{constructor(t,e){this.mainDiv=t,this.autoCulture=e,this.isRunning=!1}createHeading(){let t=document.createElement("h3");return t.textContent="Culture Planner",t.className="gb-section-title",t.style.color="#ffd77d",t}createDropDown(t,e){let i=document.createElement("select");i.setAttribute("name",e),i.className="gb-select";for(let n=0;n<t.length;n++){let a=document.createElement("option");a.text=t[n],i.appendChild(a)}return i}createMinutesInput(){let t=document.createElement("input");return t.type="number",t.min="1",t.step="1",t.value="60",t.placeholder="Interval (minutes)",t.setAttribute("name","culture-interval-minutes"),t.className="gb-input",t}createButton(){let t=document.createElement("button");return t.textContent="Start",t.className="gb-btn",t.addEventListener("click",async()=>{let e=document.querySelector("input[name='culture-interval-minutes']"),i=document.querySelector("select[name='option-drop-down']"),n=e.value,a=i.value;if(!this.isRunning){this.isRunning=!0,t.textContent="Stop";try{await this.autoCulture.start(a,n)}catch(o){console.error("Failed to start AutoCulture:",o),this.autoCulture.stop()}this.isRunning=!1,t.textContent="Start";return}this.autoCulture.stop(),this.isRunning=!1,t.textContent="Start"}),t}createAutoCultureDiv(t){let e=document.createElement("div");return e.className=t+" gb-row",e}createCultureUI(){let t=document.createElement("section");t.className="gb-section";let e=["Mestský festival","Olympijské hry","Víťazná procesia","Divadelné hry"],i=this.createHeading(),n=document.createElement("div");n.className="gb-title-row";let a=document.createElement("span");a.className="gb-info-badge",a.textContent="i";let o=document.createElement("span");o.className="gb-tooltip",o.textContent="Zadaj interval v minutach. Kultura sa po spusteni opakuje kazdych X minut + nahodny delay 60-90 sekund.",a.appendChild(o),n.appendChild(i),n.appendChild(a);let s=document.createElement("p");s.className="gb-label",s.textContent="Typ oslavy";let r=document.createElement("p");r.className="gb-label",r.textContent="Interval opakovania (minuty)";let l=this.createDropDown(e,"option-drop-down"),u=this.createMinutesInput();u.placeholder="Napr. 60 min";let g=this.createButton(),v=this.createAutoCultureDiv("auto-culture-options"),d=this.createAutoCultureDiv("auto-culture-timer");v.appendChild(l),d.appendChild(u),d.appendChild(g),t.appendChild(n),t.appendChild(s),t.appendChild(v),t.appendChild(r),t.appendChild(d),this.mainDiv.appendChild(t)}};var x=class{constructor(t,e){this.mainDiv=t,this.readOnlyInput=null,this.mappingsList=null,this.attackDodger=e,this.isRunning=!1}createHeading(){let t=document.createElement("h3");return t.textContent="AttackDodger",t.className="gb-section-title",t.style.color="#ff8f80",t}createStart(t){let e=document.createElement("button");return e.textContent=t,e.className="gb-btn",e.addEventListener("click",()=>{if(!this.isRunning){this.attackDodger.run(),this.isRunning=!0,e.textContent="Stop";return}this.attackDodger.stop(),this.isRunning=!1,e.textContent="Start"}),e}createSubmit(t){let e=document.createElement("button");return e.textContent=t,e.className="gb-btn gb-muted",e.addEventListener("click",()=>{let i=document.querySelector("#ui_box > div.town_name_area > div.town_groups_dropdown.btn_toggle_town_groups_menu > div.caption.js-viewport > div");if(!i)return;let n=document.getElementById("playerNameInput"),a=document.getElementById("townNameInput");if(!n||!a)return;let o=n.value,s=a.value;console.log(i.textContent+" is doding to"),console.log("Player Name:",o),console.log("Town Name:",s);let r={pname:o,tname:s};console.log(r);let l=JSON.stringify(r);localStorage.setItem(i.textContent,l),this.refreshDodgeInfo(),this.refreshMappingsList()}),e}createAutoDodgeeDiv(t){let e=document.createElement("div");return e.className=t,e}isJsonString(t){try{return JSON.parse(t),!0}catch(e){return!1}}refreshDodgeInfo(){if(!this.readOnlyInput)return;let t=document.querySelector("#ui_box > div.town_name_area > div.town_groups_dropdown.btn_toggle_town_groups_menu > div.caption.js-viewport > div");if(!t){this.readOnlyInput.value="";return}let e=localStorage.getItem(t.textContent);if(e===null||!this.isJsonString(e)){this.readOnlyInput.value="";return}let i=JSON.parse(e);this.readOnlyInput.value=i.tname+" : "+i.pname}getAllMappings(){let t=[];for(let e=0;e<localStorage.length;e++){let i=localStorage.key(e),n=localStorage.getItem(i);if(!n||!this.isJsonString(n))continue;let a=JSON.parse(n);!a||!a.tname||!a.pname||t.push({fromTown:i,toTown:a.tname,playerName:a.pname})}return t.sort((e,i)=>e.fromTown.localeCompare(i.fromTown)),t}refreshMappingsList(){if(!this.mappingsList)return;this.mappingsList.innerHTML="";let t=this.getAllMappings();if(t.length===0){let e=document.createElement("li");e.className="gb-mapping-item",e.textContent="No dodge routes saved yet.",this.mappingsList.appendChild(e);return}for(let e of t){let i=document.createElement("li");i.className="gb-mapping-item",i.textContent=e.fromTown+" -> "+e.toTown+" ("+e.playerName+")",this.mappingsList.appendChild(i)}}createDodgeUI(){let t=document.createElement("section");t.className="gb-section";let e=this.createHeading(),i=document.createElement("div");i.className="gb-title-row";let n=document.createElement("span");n.className="gb-info-badge",n.textContent="i";let a=document.createElement("span");a.className="gb-tooltip",a.textContent="Nastav cielovu trasu pre aktualne mesto. Ulozene trasy uvidis nizsie v zozname.",n.appendChild(a),i.appendChild(e),i.appendChild(n);let o=this.createStart("Start"),s=this.createSubmit("Submit"),r=document.createElement("input"),l=document.createElement("input");this.readOnlyInput=document.createElement("input"),r.type="text",l.type="text",r.className="gb-input",l.className="gb-input",this.readOnlyInput.type="text",this.readOnlyInput.readOnly=!0,this.readOnlyInput.className="gb-input gb-muted",this.refreshDodgeInfo(),this.mappingsList=document.createElement("ul"),this.mappingsList.className="gb-mapping-list";let u=document.createElement("h4");u.className="gb-section-title",u.style.marginTop="10px",u.style.fontSize="12px",u.style.color="#b8d7ff",u.textContent="Saved Dodge Routes";let g=document.createElement("p");g.className="gb-label",g.textContent="Hrac (kam sa bude uhybat)";let v=document.createElement("p");v.className="gb-label",v.textContent="Mesto ciela (nazov mesta)";let d=document.querySelector("#ui_box > div.town_name_area > div.btn_next_town.button_arrow.right"),b=document.querySelector("#ui_box > div.town_name_area > div.btn_prev_town.button_arrow.left");d&&d.addEventListener("click",()=>{this.refreshDodgeInfo(),this.refreshMappingsList()}),b&&b.addEventListener("click",()=>{this.refreshDodgeInfo(),this.refreshMappingsList()}),r.placeholder="Enter Player Name",l.placeholder="Enter Town Name",this.readOnlyInput.placeholder="Not set",r.setAttribute("id","playerNameInput"),l.setAttribute("id","townNameInput");let h=document.createElement("div");h.className="gb-row-full";let w=document.createElement("div");w.className="gb-row",w.appendChild(s),w.appendChild(o),h.appendChild(g),h.appendChild(r),h.appendChild(v),h.appendChild(l),h.appendChild(this.readOnlyInput),t.appendChild(i),t.appendChild(h),t.appendChild(w),t.appendChild(u),t.appendChild(this.mappingsList),this.mainDiv.appendChild(t),this.refreshDodgeInfo(),this.refreshMappingsList()}};var _=class{constructor(t,e){this.mainDiv=t,this.autoSilverVault=e,this.isRunning=!1}createHeading(){let t=document.createElement("h3");return t.textContent="Silver Vault",t.className="gb-section-title",t.style.color="#9fd5ff",t}createInput(t,e,i){let n=document.createElement("input");return n.type="number",n.min="0",n.step="1",n.className="gb-input",n.setAttribute("name",t),n.placeholder=e,n.value=i,n}createButton(){let t=document.createElement("button");return t.textContent="Start",t.className="gb-btn",t.addEventListener("click",async()=>{let e=document.querySelector("input[name='silver-vault-keep']"),i=document.querySelector("input[name='silver-vault-store']"),n=document.querySelector("input[name='silver-vault-interval']");if(!this.isRunning){this.isRunning=!0,t.textContent="Stop";try{await this.autoSilverVault.start({keepAmount:e.value,storeAmount:i.value,intervalMinutes:n.value})}catch(a){console.error("Failed to start Silver Vault automation:",a),this.autoSilverVault.stop()}this.isRunning=!1,t.textContent="Start";return}this.autoSilverVault.stop(),this.isRunning=!1,t.textContent="Start"}),t}createSilverVaultUI(){let t=document.createElement("section");t.className="gb-section";let e=this.createHeading(),i=document.createElement("div");i.className="gb-title-row";let n=document.createElement("span");n.className="gb-info-badge",n.textContent="i";let a=document.createElement("span");a.className="gb-tooltip",a.textContent="Zadaj hodnoty v striebre. Cyklus bezi podla intervalu v minutach + nahodny delay 30-300 sekund.",n.appendChild(a),i.appendChild(e),i.appendChild(n);let o=document.createElement("p");o.className="gb-label",o.textContent="Ponechat v meste (striebra)";let s=this.createInput("silver-vault-keep","Napr. 15000 striebra","15000"),r=document.createElement("p");r.className="gb-label",r.textContent="Ulozit do jaskyne (striebra)";let l=this.createInput("silver-vault-store","Napr. 5000 striebra","5000"),u=document.createElement("p");u.className="gb-label",u.textContent="Interval opakovania (minuty)";let g=this.createInput("silver-vault-interval","Napr. 30 min","30");g.min="1";let v=this.createButton(),d=document.createElement("div");d.className="gb-row-full",d.appendChild(o),d.appendChild(s),d.appendChild(r),d.appendChild(l),d.appendChild(u),d.appendChild(g);let b=document.createElement("div");b.className="gb-row";let h=document.createElement("div");b.appendChild(h),b.appendChild(v),t.appendChild(i),t.appendChild(d),t.appendChild(b),this.mainDiv.appendChild(t)}};var m=class{timeout(t){return new Promise(e=>setTimeout(e,t))}generateDelay(){return Math.floor(Math.random()*2310+1e3)}convertToSeconds(t){let[e,i,n]=t.split(":");return parseInt(e)*3600+parseInt(i)*60+parseInt(n)}waitForElementToAppear(t,e,i=100,n=10){return new Promise(a=>{let o=0,s=setInterval(()=>{o++;let r=document.querySelector(t);(r||o>=n)&&(clearInterval(s),r?(e&&e(r),a(r)):(console.warn(`Element not found: ${t}`),a(null)))},i)})}async clickWhenAvailable(t,e=100,i=20){let n=await this.waitForElementToAppear(t,null,e,i);return n?(n.click(),!0):!1}async waitFor(t,e){let i=Date.now()+t;for(;Date.now()<i;){if(typeof e=="function"&&!e())return;let n=i-Date.now();await this.timeout(Math.min(1e3,Math.max(n,0)))}}};var c={dialogs:{closeAllWindows:"#ui_box > div.btn_close_all_windows > div.middle > div > div.box-middle > div"},farm:{overviewLink:"#overviews_link_hover_menu > div.box.middle.left > div > div > ul > li.subsection.captain.enabled > ul > li.farm_town_overview > a",selectAll:"#fto_town_wrapper > div > div.game_header.bold > span.checkbox_wrapper > a",claimButton:"#fto_claim_button > div.caption.js-caption",confirmButton:".window_content.js-window-content > div > div.buttons > div.btn_confirm.button_new > div.caption.js-caption"},culture:{overviewLink:"#overviews_link_hover_menu > div.box.middle.left > div > div > ul > li.subsection.curator.enabled > ul > li.culture_overview > a",startAllButton:"#start_all_celebrations",celebrationSelect:"#place_celebration_select"},silverVault:{overviewLink:"#overviews_link_hover_menu > div.box.middle.left > div > div > ul > li.subsection.curator.enabled > ul > li.hides_overview > a",keepInput:"#hides_overview_all_towns_iron_keep > div.body > input[type=text]",storeInput:"#hides_overview_all_towns_iron_store > div.body > input[type=text]",confirmButton:"#store_iron_in_all_towns",closeAllWindows:"#ui_box > div.btn_close_all_windows > div.middle > div > div.box-middle > div"}};var E=class{constructor(){this.utils=new m,this.running=!1,this.seconds=0}async selectVillages(){let t=document.querySelector(c.farm.overviewLink);if(!t)throw new Error("Unable to open farm town overview.");function e(i){let n=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0});i.dispatchEvent(n)}e(t),await this.utils.timeout(200+this.utils.generateDelay())}async selectAll(){this.utils.waitForElementToAppear(c.farm.selectAll,t=>{t.click()}),await this.utils.timeout(947+this.utils.generateDelay())}async checkTime(t){t===300||t===1200||t===5400||t===14400?this.utils.waitForElementToAppear("#time_options_wrapper > div.time_options_default > div.fto_time_checkbox.fto_"+t+"> a",e=>{e.click()}):this.utils.waitForElementToAppear("#time_options_wrapper > div.time_options_loyalty > div.fto_time_checkbox.fto_"+t+" > a",e=>{e.click()}),await this.utils.timeout(1550+this.utils.generateDelay())}async collect(){this.utils.waitForElementToAppear(c.farm.claimButton,t=>{t.click()}),await this.utils.timeout(1480+this.utils.generateDelay())}async confirm(){this.utils.waitForElementToAppear(c.farm.confirmButton,t=>{t.click()}),await this.utils.timeout(888+this.utils.generateDelay())}async close(){this.utils.waitForElementToAppear(c.dialogs.closeAllWindows,t=>{t.click()}),await this.utils.timeout(105+this.utils.generateDelay())}async repeatFarm(){console.log("Starting AutoFarm cycle..."),await this.selectVillages(),await this.selectAll(),await this.checkTime(this.seconds),await this.collect(),await this.confirm(),await this.close(),console.log("Collecting is finished")}async start(t){if(this.running){console.warn("AutoFarm is already running.");return}let e=this.utils.convertToSeconds(t);if(!e||e<1)throw new Error("Invalid farming interval.");for(this.seconds=e,this.running=!0;this.running;){try{await this.repeatFarm()}catch(n){console.error("AutoFarm cycle failed:",n)}let i=this.seconds*1e3+Math.floor(Math.random()*5e4+25e3);console.log(`Next farm run in ${Math.round(i/1e3)} seconds`),await this.utils.waitFor(i,()=>this.running),this.running&&console.log("AutoFarm wait finished, starting next cycle.")}}stop(){this.running=!1}};var C=class{constructor(){this.utils=new m,this.running=!1,this.intervalMinutes=0}randomBetween(t,e){return Math.floor(Math.random()*(e-t+1)+t)}async selectOverview(){this.utils.waitForElementToAppear(c.culture.overviewLink,t=>{t.click()}),await this.utils.timeout(658+this.utils.generateDelay())}async confirm(){this.utils.waitForElementToAppear(c.culture.startAllButton,t=>{t.click()}),await this.utils.timeout(1001+this.utils.generateDelay())}async close(){this.utils.waitForElementToAppear(c.dialogs.closeAllWindows,t=>{t.click()}),await this.utils.timeout(588+this.utils.generateDelay())}async selectOption(t){let e=1;switch(t){case"Mestský festival":e=1;break;case"Olympijské hry":e=2;break;case"Víťazná procesia":e=3;break;case"Divadelné hry":e=4;break}this.utils.waitForElementToAppear(c.culture.celebrationSelect,i=>{i.click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#place_celebration_select_list > div > div:nth-child("+e+")",i=>{i.click()}),await this.utils.timeout(1488+this.utils.generateDelay())}async repeatCulture(t){await this.selectOverview(),await this.selectOption(t),await this.confirm(),await this.close(),console.log("Culture celebration started.")}async start(t,e){if(this.running){console.warn("AutoCulture is already running.");return}let i=Number.parseInt(e,10);if(!Number.isFinite(i)||i<1)throw new Error("Invalid culture interval in minutes.");for(this.intervalMinutes=i,this.running=!0;this.running;){try{await this.repeatCulture(t)}catch(s){console.error("AutoCulture cycle failed:",s)}let n=this.intervalMinutes*60*1e3,a=this.randomBetween(60,90),o=n+a*1e3;console.log(`Next culture run in ${Math.round(o/1e3)} seconds (${a}s extra)`),await this.utils.waitFor(o,()=>this.running)}}stop(){this.running=!1}};var k=class{constructor(){this.utils=new m,this.attackCount=0,this.running=!1,this.mutationObserver=null,this.pendingDodges=[]}async getListOfAttacks(){this.utils.waitForElementToAppear("#toolbar_activity_commands",t=>{t.click()}),await this.utils.timeout(3877+this.utils.generateDelay()),await this.getIncomingAttacks()}async parseTimeAndTown(t){let e=t.children[1].children[3].innerHTML;console.log(e);let i=t.children[7].innerHTML;console.log(i);let[n,a,o]=i.split(":").map(Number),s=n*3600+a*60+o;console.log(s);let r=Math.max(s*1e3-4e4,0),l=setTimeout(async()=>{this.running&&await this.makeDodge(e)},r);this.pendingDodges.push(l)}async villagerDef(){this.utils.waitForElementToAppear("#ui_box > div.topleft_navigation_area > div.bull_eye_buttons > div.rb_map > div.option.city_overview.circle_button.js-option",t=>{t.click()}),await this.utils.timeout(300+this.utils.generateDelay()),this.utils.waitForElementToAppear("#building_main_area_farm",t=>{t.click()}),await this.utils.timeout(300+this.utils.generateDelay()),this.utils.waitForElementToAppear("#request_militia_button > span.left > span > span",t=>{t.click()}),await this.utils.timeout(300+this.utils.generateDelay()),this.utils.waitForElementToAppear("div > div.window_content.js-window-content > div > div.buttons > div.btn_confirm.button_new",t=>{t.click()})}async sendAllUnits(){this.utils.waitForElementToAppear("div > form > div.town_units_wrapper > div > div.unit_wrapper > div.naval_units.clearfix > div",()=>{let t=document.querySelectorAll("div > form > div.town_units_wrapper > div > div.unit_wrapper > div.naval_units.clearfix > div");for(let e of t)e.childNodes[1].click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("div > form > div.button_wrapper > a > span.left > span > span",t=>{t.click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("div > form > div.town_units_wrapper > div > div.unit_wrapper > div.ground_units.clearfix > div",()=>{let t=document.querySelectorAll("div > form > div.town_units_wrapper > div > div.unit_wrapper > div.ground_units.clearfix > div");for(let e of t)e.childNodes[1].click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("div > form > div.button_wrapper > a > span.left > span > span",t=>{t.click()}),await this.utils.timeout(1e4+this.utils.generateDelay())}async closeAll(){await this.utils.clickWhenAvailable(c.dialogs.closeAllWindows,100,20),await this.utils.timeout(200+this.utils.generateDelay())}simulateHover(t){let e=new MouseEvent("mouseover",{bubbles:!0,cancelable:!0,view:window});t.dispatchEvent(e)}async cancelSendingUnits(){console.log("canceling");let t=document.querySelector("#ui_box > div.tb_activities.toolbar_activities > div.middle > div:nth-child(5) > div.activity.commands > div.hover_state");this.simulateHover(t);let e=document.querySelectorAll("div > div.button_new.square.remove.js-delete.cancelable");for(let i of e)i.click();await this.utils.timeout(888+this.utils.generateDelay())}async makeDodge(t){console.log("Hello i was called after 10 seconds");let e=localStorage.getItem(t);if(!e){console.warn(`No dodge target configured for town: ${t}`);return}let i=JSON.parse(e);await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#ui_box > div.town_name_area > div.town_groups_dropdown.btn_toggle_town_groups_menu > div.caption.js-viewport",a=>{a.click()}),await this.utils.timeout(1488+this.utils.generateDelay());let n=(a,o)=>{let s=document.querySelectorAll(o);for(let r of s)if(r.innerText===a)return r;return null};await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#town_groups_list > div.content.js-dropdown-item-list.town_groups_list > div.town_group.town_group_-1.selected > div.group_towns.ui-droppable > div > span",()=>{let a=n(t,"#town_groups_list > div.content.js-dropdown-item-list.town_groups_list > div.town_group.town_group_-1.selected > div.group_towns.ui-droppable > div > span");console.log(a),a.click()}),await this.villagerDef(),await this.utils.timeout(200+this.utils.generateDelay()),this.utils.waitForElementToAppear("#ui_box > div.nui_main_menu > div.middle > div.content > ul > li.ranking.main_menu_item",a=>{a.click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#player_name",a=>{console.log(i),a.value=i.pname}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#ranking_search > a.button > span.left > span > span",a=>{a.click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#ranking_inner > tr.game_table_even.bottom > td.r_name > a",a=>{a.click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#player_towns > div > ul > li > a",()=>{let a=document.querySelectorAll("#player_towns > div > ul > li > a");console.log(a);for(let o of a)console.log(o.innerText),o.innerText===i.tname&&o.click()}),await this.utils.timeout(1488+this.utils.generateDelay()),this.utils.waitForElementToAppear("#support",a=>{a.click()}),await this.utils.timeout(1488+this.utils.generateDelay()),await this.sendAllUnits(),await this.cancelSendingUnits(),await this.closeAll()}filterAttacks(t){let e=t.documentElement;for(let i=0;i<e.children.length;i++){let n=e.children[i];if(n.tagName==="BODY")for(let a=0;a<n.children.length;a++){let o=n.children[a],s=o.attributes[2].value;(s==="attack_land"||s==="attack_sea")&&(console.log(o),console.log(o.children[0].children[1].children[2].attributes[0].value),o.children[0].children[1].children[2].attributes[0].value==="overview_outgoing icon"&&this.parseTimeAndTown(o.children[0]))}}}async getIncomingAttacks(){this.utils.waitForElementToAppear("#command_overview",r=>{r.click()});let t=document.querySelector("#command_overview");console.log(t.innerHTML);let e=new DOMParser().parseFromString(t.innerHTML,"text/html");console.log(e),this.filterAttacks(e);let i=new Date,n=i.getDay(),a=i.getHours(),o=i.getMinutes(),s=i.getSeconds();console.log(n+":"+a+":"+o+":"+s)}run(){if(this.running){console.warn("AttackDodger is already running.");return}this.running=!0;let t=document.querySelector("#ui_box > div.tb_activities.toolbar_activities > div.middle > div:nth-child(1) > div.activity.attack_indicator > div.hover_state > div > div");if(!t){console.warn("Attack indicator not found."),this.running=!1;return}t.innerText!==""&&(this.attackCount=parseInt(t.innerText),console.log("Attack count: "+this.attackCount)),this.mutationObserver=new MutationObserver(i=>{this.running&&setTimeout(()=>{!this.running||i.length<3||!i[2].addedNodes[1]||i[2].type==="childList"&&(parseInt(i[2].addedNodes[1].childNodes[1].firstElementChild.innerText)>this.attackCount?(this.attackCount++,console.log("Attack detected"),this.getListOfAttacks()):parseInt(i[2].addedNodes[1].childNodes[1].firstElementChild.innerText)<this.attackCount?(this.attackCount--,console.log("Attack canceled")):(this.attackCount=0,console.log("No Attacks")))},5e3)});let e=document.querySelector("#ui_box > div.tb_activities.toolbar_activities > div.middle > div:nth-child(1) > div.activity.attack_indicator");if(!e){console.warn("Activity container not found."),this.running=!1;return}this.mutationObserver.observe(e,{childList:!0,subtree:!0,attributes:!0})}stop(){this.running=!1,this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null);for(let t of this.pendingDodges)clearTimeout(t);this.pendingDodges=[]}};var D=class{constructor(){this.utils=new m,this.running=!1,this.keepAmount=0,this.storeAmount=0,this.intervalMinutes=0}randomBetween(t,e){return Math.floor(Math.random()*(e-t+1)+t)}async applyHumanDelay(){await this.utils.timeout(350+this.utils.generateDelay())}async openOverview(){let t=await this.utils.waitForElementToAppear(c.silverVault.overviewLink,null,100,20);if(!t)throw new Error("Unable to open silver vault overview.");t.click(),await this.applyHumanDelay()}setInputValue(t,e){t.focus(),t.value=String(e),t.dispatchEvent(new Event("input",{bubbles:!0})),t.dispatchEvent(new Event("change",{bubbles:!0})),t.blur()}async setKeepAmount(){let t=await this.utils.waitForElementToAppear(c.silverVault.keepInput,null,100,30);if(!t)throw new Error("Keep amount input not found.");this.setInputValue(t,this.keepAmount),await this.applyHumanDelay()}async setStoreAmount(){let t=await this.utils.waitForElementToAppear(c.silverVault.storeInput,null,100,30);if(!t)throw new Error("Store amount input not found.");this.setInputValue(t,this.storeAmount),await this.applyHumanDelay()}async confirmStore(){if(!await this.utils.clickWhenAvailable(c.silverVault.confirmButton,100,20))throw new Error("Silver vault confirm button not found.");await this.applyHumanDelay()}async closeAllWindows(){await this.utils.clickWhenAvailable(c.dialogs.closeAllWindows,100,20),await this.applyHumanDelay()}async runOnce(){await this.openOverview(),await this.setKeepAmount(),await this.setStoreAmount(),await this.confirmStore(),await this.closeAllWindows()}async start({keepAmount:t,storeAmount:e,intervalMinutes:i}){if(this.running){console.warn("AutoSilverVault is already running.");return}let n=Number.parseInt(t,10),a=Number.parseInt(e,10),o=Number.parseInt(i,10);if(!Number.isFinite(n)||n<0)throw new Error("Invalid keep amount.");if(!Number.isFinite(a)||a<0)throw new Error("Invalid store amount.");if(!Number.isFinite(o)||o<1)throw new Error("Invalid interval in minutes.");for(this.keepAmount=n,this.storeAmount=a,this.intervalMinutes=o,this.running=!0;this.running;){try{await this.runOnce()}catch(u){console.error("AutoSilverVault cycle failed:",u)}let s=this.intervalMinutes*60*1e3,r=this.randomBetween(30,300),l=s+r*1e3;console.log(`Next silver vault run in ${Math.round(l/1e3)} seconds (${r}s extra)`),await this.utils.waitFor(l,()=>this.running)}}stop(){this.running=!1}};var A=class{constructor(){if(this.panel=document.getElementsByClassName("ui_construction_queue instant_buy")[0],!this.panel||!this.panel.parentNode)throw new Error("Unable to mount GrepolisBot UI panel.");this.autoFarm=new E,this.autoCulture=new C,this.attackDodger=new k,this.autoSilverVault=new D,this.injectStyles(),this.createMainDiv(),this.addDragFunctionality(),this.createAutoFarmUI()}injectStyles(){if(document.getElementById("grepolisbot-theme"))return;let t=document.createElement("style");t.id="grepolisbot-theme",t.textContent=`
      [name="bot-main-div"] {
        position: absolute;
        left: 12px;
        top: 12px;
        width: 340px;
        max-height: 78vh;
        overflow-y: auto;
        z-index: 1000;
        border-radius: 16px;
        border: 1px solid rgba(255, 255, 255, 0.22);
        background:
          radial-gradient(circle at 0% 0%, rgba(244, 170, 78, 0.22), transparent 45%),
          radial-gradient(circle at 100% 0%, rgba(41, 93, 151, 0.22), transparent 48%),
          linear-gradient(160deg, rgba(15, 25, 44, 0.9), rgba(10, 14, 27, 0.92));
        box-shadow: 0 16px 45px rgba(6, 10, 22, 0.55);
        backdrop-filter: blur(7px);
        box-sizing: border-box;
        padding: 12px;
        font-family: "Trebuchet MS", "Segoe UI", sans-serif;
        color: #eef3ff;
      }

      .gb-drag-handle {
        cursor: move;
        user-select: none;
        border-radius: 12px;
        border: 1px solid rgba(243, 194, 94, 0.45);
        background: linear-gradient(120deg, rgba(216, 137, 58, 0.3), rgba(53, 104, 163, 0.26));
        padding: 9px 12px;
        margin-bottom: 12px;
        text-transform: uppercase;
        letter-spacing: 0.08em;
        font-size: 12px;
        font-weight: 700;
      }

      .gb-easter-egg {
        display: none;
        margin: -6px 0 10px;
        font-size: 11px;
        color: #ffe9b8;
        text-align: right;
      }

      .gb-easter-egg.visible {
        display: block;
      }

      .gb-tabs {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
        margin-bottom: 10px;
      }

      .gb-tab {
        border: 1px solid rgba(255, 255, 255, 0.25);
        border-radius: 10px;
        background: rgba(10, 23, 45, 0.55);
        color: #eaf0ff;
        padding: 7px 10px;
        font-weight: 700;
        font-size: 12px;
        cursor: pointer;
      }

      .gb-tab.active {
        border-color: rgba(243, 194, 94, 0.55);
        background: linear-gradient(150deg, rgba(244, 160, 61, 0.35), rgba(204, 111, 42, 0.3));
        color: #fff6e8;
      }

      .gb-page {
        display: block;
      }

      .gb-page.hidden {
        display: none;
      }

      .gb-section {
        border: 1px solid rgba(255, 255, 255, 0.14);
        background: linear-gradient(150deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03));
        border-radius: 12px;
        padding: 10px;
        margin-bottom: 10px;
      }

      .gb-section-title {
        font-size: 14px;
        margin: 0 0 8px;
        letter-spacing: 0.03em;
      }

      .gb-title-row {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
      }

      .gb-info-badge {
        position: relative;
        width: 18px;
        height: 18px;
        border-radius: 50%;
        border: 1px solid rgba(255, 255, 255, 0.35);
        background: rgba(11, 26, 50, 0.78);
        color: #d8e8ff;
        font-size: 11px;
        font-weight: 700;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        cursor: help;
      }

      .gb-tooltip {
        position: absolute;
        right: 0;
        top: 24px;
        width: 220px;
        padding: 8px;
        border-radius: 8px;
        background: rgba(5, 12, 24, 0.95);
        border: 1px solid rgba(255, 255, 255, 0.18);
        color: #d9e7ff;
        font-size: 11px;
        line-height: 1.35;
        opacity: 0;
        visibility: hidden;
        transform: translateY(-4px);
        transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s ease;
        z-index: 2000;
      }

      .gb-info-badge:hover .gb-tooltip {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
      }

      .gb-hint {
        margin: 0 0 8px;
        font-size: 11px;
        line-height: 1.35;
        color: #c4d8ff;
      }

      .gb-label {
        margin: 2px 0 4px;
        font-size: 11px;
        color: #e0ecff;
        letter-spacing: 0.02em;
      }

      .gb-row {
        display: grid;
        grid-template-columns: 1fr auto;
        gap: 8px;
        margin-bottom: 8px;
      }

      .gb-row-full {
        display: grid;
        gap: 8px;
      }

      .gb-select,
      .gb-input {
        border: 1px solid rgba(224, 234, 255, 0.35);
        border-radius: 8px;
        background: rgba(3, 13, 31, 0.56);
        color: #eff4ff;
        padding: 7px 9px;
        font-size: 13px;
      }

      .gb-input::placeholder {
        color: rgba(220, 230, 255, 0.55);
      }

      .gb-btn {
        border: 1px solid rgba(255, 224, 158, 0.45);
        border-radius: 8px;
        background: linear-gradient(150deg, #f4a03d, #cc6f2a);
        color: #11203b;
        font-weight: 700;
        padding: 7px 11px;
        min-width: 74px;
        cursor: pointer;
      }

      .gb-btn:hover {
        filter: brightness(1.05);
      }

      .gb-muted {
        border: 1px solid rgba(168, 203, 255, 0.28);
        background: rgba(6, 18, 38, 0.5);
        color: #d3e0fc;
      }

      .gb-mapping-list {
        list-style: none;
        margin: 8px 0 0;
        padding: 0;
        border-top: 1px solid rgba(255, 255, 255, 0.14);
      }

      .gb-mapping-item {
        font-size: 12px;
        color: #dbe7ff;
        padding: 7px 2px;
        border-bottom: 1px dashed rgba(255, 255, 255, 0.12);
      }
    `,document.head.appendChild(t)}createMainDiv(){this.mainDiv=document.createElement("div"),this.mainDiv.setAttribute("name","bot-main-div"),this.dragHandle=document.createElement("div"),this.dragHandle.className="gb-drag-handle",this.dragHandle.textContent="GrepolisBot Control Deck",this.mainDiv.appendChild(this.dragHandle),this.easterEgg=document.createElement("div"),this.easterEgg.className="gb-easter-egg",this.easterEgg.textContent="Forged by ničite4000l | GitHub: NaKamize",this.mainDiv.appendChild(this.easterEgg),this.dragHandle.addEventListener("dblclick",()=>{this.easterEgg.classList.toggle("visible")}),this.tabBar=document.createElement("div"),this.tabBar.className="gb-tabs",this.automationTab=document.createElement("button"),this.automationTab.className="gb-tab active",this.automationTab.textContent="Automation",this.dodgeTab=document.createElement("button"),this.dodgeTab.className="gb-tab",this.dodgeTab.textContent="Dodge",this.tabBar.appendChild(this.automationTab),this.tabBar.appendChild(this.dodgeTab),this.mainDiv.appendChild(this.tabBar),this.automationPage=document.createElement("div"),this.automationPage.className="gb-page",this.dodgePage=document.createElement("div"),this.dodgePage.className="gb-page hidden",this.mainDiv.appendChild(this.automationPage),this.mainDiv.appendChild(this.dodgePage),this.panel.parentNode.insertBefore(this.mainDiv,this.panel),this.wireTabs()}wireTabs(){this.automationTab.addEventListener("click",()=>{this.automationTab.classList.add("active"),this.dodgeTab.classList.remove("active"),this.automationPage.classList.remove("hidden"),this.dodgePage.classList.add("hidden")}),this.dodgeTab.addEventListener("click",()=>{this.dodgeTab.classList.add("active"),this.automationTab.classList.remove("active"),this.dodgePage.classList.remove("hidden"),this.automationPage.classList.add("hidden")})}addDragFunctionality(){let t=!1,e=0,i=0,n=s=>{t=!0,e=s.clientX-this.mainDiv.offsetLeft,i=s.clientY-this.mainDiv.offsetTop},a=()=>{t=!1},o=s=>{t&&(this.mainDiv.style.left=s.clientX-e+"px",this.mainDiv.style.top=s.clientY-i+"px")};this.dragHandle.addEventListener("mousedown",n),document.addEventListener("mouseup",a),document.addEventListener("mousemove",o)}createAutoFarmUI(){new f(this.automationPage,this.autoFarm).createFarmUI(),new y(this.automationPage,this.autoCulture).createCultureUI(),new _(this.automationPage,this.autoSilverVault).createSilverVaultUI(),new x(this.dodgePage,this.attackDodger).createDodgeUI()}};(function(){window.addEventListener("load",function(){setTimeout(function(){try{new A}catch(p){console.error("GrepolisBot failed to initialize:",p)}},2e3)})})();})();