diff --git a/README.md b/README.md index 0c7d80f..b02def5 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ - [x] Автоматическая отправка героя в приключение - [x] Автоматическое переключение ресурсов героя - [x] Сканирование собственных деревень для отображения ресурсов и информации в одном месте +- [x] Автоматический запуск празднований - [ ] Автоматическая отправка набегов на учетные записи или автоматическая отправка волн атак - [ ] Автоматический скан карты - [ ] Автоматическая отправка ресурсов на другие учетные записи - [ ] Автоматическое размещение ставок на аукционе -- [ ] Автоматический запуск празднований - [ ] Сканирование статистики других игроков ## To do diff --git a/src/Action/CelebrationAction.ts b/src/Action/CelebrationAction.ts new file mode 100644 index 0000000..b6030ac --- /dev/null +++ b/src/Action/CelebrationAction.ts @@ -0,0 +1,21 @@ +import { ActionController, registerAction } from './ActionController'; +import { GrabError, TryLaterError } from '../Errors'; +import { aroundMinutes } from '../utils'; +import { Args } from '../Queue/Args'; +import { Task } from '../Queue/TaskProvider'; +import { clickCelebrationButton } from '../Page/BuildingPage/GuildHallPage'; + +@registerAction +export class CelebrationAction extends ActionController { + async run(args: Args, task: Task): Promise { + try { + this.ensureSameVillage(args, task); + clickCelebrationButton(); + } catch (e) { + if (e instanceof GrabError) { + throw new TryLaterError(aroundMinutes(60), e.message); + } + throw e; + } + } +} diff --git a/src/Core/Buildings.ts b/src/Core/Buildings.ts index c905696..888e7cd 100644 --- a/src/Core/Buildings.ts +++ b/src/Core/Buildings.ts @@ -5,4 +5,5 @@ export const COLLECTION_POINT_ID = 16; export const MARKET_ID = 17; export const QUARTERS_ID = 19; export const HORSE_STABLE_ID = 20; +export const GUILD_HALL_ID = 24; export const EMBASSY_ID = 25; diff --git a/src/Page/BuildingPage/GuildHallPage.ts b/src/Page/BuildingPage/GuildHallPage.ts new file mode 100644 index 0000000..a644cea --- /dev/null +++ b/src/Page/BuildingPage/GuildHallPage.ts @@ -0,0 +1,49 @@ +import { elClassId, getNumber, uniqId } from '../../utils'; +import { Resources } from '../../Core/Resources'; +import { grabResourcesFromList } from './BuildingPage'; +import { GrabError } from '../../Errors'; + +interface CelebrationClickHandler { + (resources: Resources, id: number): void; +} + +export function createCelebrationButtons(onClickHandler: CelebrationClickHandler) { + const $els = jQuery('.build_details.researches .research'); + if ($els.length === 0) { + throw new GrabError('No celebration research blocks'); + } + $els.each((idx, el) => createCelebrationButton(jQuery(el), idx, onClickHandler)); +} + +export function clickCelebrationButton() { + const $els = jQuery('.build_details.researches .research'); + if ($els.length === 0) { + throw new GrabError('No celebration research blocks'); + } + const $first = jQuery($els.get(0)); + const $btn = $first.find('.cta').find('button.green'); + if ($btn.length !== 1) { + throw new GrabError('No celebration buttons'); + } + $btn.trigger('click'); +} + +function createCelebrationButton($blockEl: JQuery, idx: number, onClickHandler: CelebrationClickHandler) { + const resources = grabResources($blockEl); + + const id = uniqId(); + + $blockEl.find('.information').append(`
+ Праздновать +
`); + + jQuery(`#${id}`).on('click', evt => { + evt.preventDefault(); + onClickHandler(resources, idx); + }); +} + +function grabResources($blockEl: JQuery) { + const $resEls = $blockEl.find('.resourceWrapper .resource'); + return grabResourcesFromList($resEls); +} diff --git a/src/Page/BuildingPageController.ts b/src/Page/BuildingPageController.ts index 3b29e48..6ac7a7f 100644 --- a/src/Page/BuildingPageController.ts +++ b/src/Page/BuildingPageController.ts @@ -10,11 +10,13 @@ import { Resources } from '../Core/Resources'; import { Coordinates } from '../Core/Village'; import { SendResourcesTask } from '../Task/SendResourcesTask'; import { EMBASSY_ID, HORSE_STABLE_ID, QUARTERS_ID } from '../Core/Buildings'; -import { BuildingPageAttributes, isForgePage, isMarketSendResourcesPage } from './PageDetectors'; +import { BuildingPageAttributes, isForgePage, isGuildHallPage, isMarketSendResourcesPage } from './PageDetectors'; import { createTrainTroopButtons } from './BuildingPage/TrooperPage'; import { createSendResourcesButton } from './BuildingPage/MarketPage'; import { createResearchButtons } from './BuildingPage/ForgePage'; import { ForgeImprovementTask } from '../Task/ForgeImprovementTask'; +import { createCelebrationButtons } from './BuildingPage/GuildHallPage'; +import { CelebrationTask } from '../Task/CelebrationTask'; export class BuildingPageController { private scheduler: Scheduler; @@ -56,6 +58,10 @@ export class BuildingPageController { if (isForgePage()) { createResearchButtons((res, unitId) => this.onResearch(res, unitId)); } + + if (isGuildHallPage()) { + createCelebrationButtons((res, idx) => this.onCelebration(res, idx)); + } } private onScheduleBuildBuilding(buildTypeId: number, resources: Resources) { @@ -115,4 +121,15 @@ export class BuildingPageController { }); notify(`Researching ${unitId} scheduled`); } + + private onCelebration(resources: Resources, idx: number) { + const villageId = grabActiveVillageId(); + this.scheduler.scheduleTask(CelebrationTask.name, { + villageId, + buildTypeId: this.attributes.buildTypeId, + buildId: this.attributes.buildId, + resources, + }); + notify(`Celebration scheduled`); + } } diff --git a/src/Page/PageDetectors.ts b/src/Page/PageDetectors.ts index ff1b73b..c5558cb 100644 --- a/src/Page/PageDetectors.ts +++ b/src/Page/PageDetectors.ts @@ -1,5 +1,5 @@ import { elClassId, getNumber, parseLocation } from '../utils'; -import { FORGE_ID, MARKET_ID } from '../Core/Buildings'; +import { FORGE_ID, GUILD_HALL_ID, MARKET_ID } from '../Core/Buildings'; export interface BuildingPageAttributes { buildTypeId: number; @@ -51,3 +51,11 @@ export function isForgePage(): boolean { const { buildTypeId } = getBuildingPageAttributes(); return buildTypeId === FORGE_ID; } + +export function isGuildHallPage(): boolean { + if (!isBuildingPage()) { + return false; + } + const { buildTypeId } = getBuildingPageAttributes(); + return buildTypeId === GUILD_HALL_ID; +} diff --git a/src/Scheduler.ts b/src/Scheduler.ts index 8a638c5..63ee375 100644 --- a/src/Scheduler.ts +++ b/src/Scheduler.ts @@ -14,6 +14,7 @@ import { SendResourcesTask } from './Task/SendResourcesTask'; import { Args } from './Queue/Args'; import { ImmutableTaskList, Task, TaskId } from './Queue/TaskProvider'; import { ForgeImprovementTask } from './Task/ForgeImprovementTask'; +import { CelebrationTask } from './Task/CelebrationTask'; export enum ContractType { UpgradeBuilding, @@ -208,12 +209,21 @@ function isBuildingTask(taskName: string) { return taskName === BuildBuildingTask.name || taskName === UpgradeBuildingTask.name; } +function isCelebrationTask(taskName: string) { + return taskName === CelebrationTask.name; +} + /** * List on non intersected task type predicates. * * Placed in order of execution priority. Order is important! */ -const TASK_TYPE_PREDICATES: Array = [isTrainTroopTask, isForgeImprovementTask, isBuildingTask]; +const TASK_TYPE_PREDICATES: Array = [ + isTrainTroopTask, + isForgeImprovementTask, + isBuildingTask, + isCelebrationTask, +]; function sameVillage(villageId: number | undefined, args: Args) { return villageId !== undefined && args.villageId === villageId; diff --git a/src/Task/CelebrationTask.ts b/src/Task/CelebrationTask.ts new file mode 100644 index 0000000..915d31e --- /dev/null +++ b/src/Task/CelebrationTask.ts @@ -0,0 +1,20 @@ +import { TaskController, registerTask, ActionDefinition } from './TaskController'; +import { GoToPageAction } from '../Action/GoToPageAction'; +import { Task } from '../Queue/TaskProvider'; +import { path } from '../Helpers/Path'; +import { CelebrationAction } from '../Action/CelebrationAction'; + +@registerTask +export class CelebrationTask extends TaskController { + defineActions(task: Task): Array { + const args = task.args; + + const pathArgs = { + newdid: args.villageId, + gid: args.buildTypeId || undefined, + id: args.buildId || undefined, + }; + + return [[GoToPageAction.name, { ...args, path: path('/build.php', pathArgs) }], [CelebrationAction.name]]; + } +}