Greasy Fork is available in English.
Automates farm collection, culture events, and attack dodging in Grepolis
// ==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)})})();})();