1067 lines
46 KiB
Python
1067 lines
46 KiB
Python
# pylint: disable=fixme, line-too-long, missing-docstring, invalid-name
|
|
import datetime
|
|
import decimal
|
|
import hashlib
|
|
import random
|
|
import time
|
|
from collections import deque
|
|
from json import JSONDecodeError, loads, JSONEncoder
|
|
from typing import Any, Dict, List, Union
|
|
|
|
from requests import Response, Session
|
|
from slugify import slugify
|
|
|
|
from erepublik import utils
|
|
|
|
|
|
class ErepublikException(Exception):
|
|
def __init__(self, message):
|
|
super().__init__(message)
|
|
|
|
|
|
class ErepublikNetworkException(Exception):
|
|
def __init__(self, message, request):
|
|
super().__init__(message)
|
|
self.request = request
|
|
|
|
|
|
class MyCompanies:
|
|
work_units: int = 0
|
|
next_ot_time: datetime.datetime
|
|
holdings: Dict[int, Dict] = dict()
|
|
companies: Dict[int, Dict] = dict()
|
|
ff_lockdown: int = 0
|
|
|
|
def __init__(self):
|
|
self.next_ot_time = utils.now()
|
|
|
|
def prepare_holdings(self, holdings: dict):
|
|
"""
|
|
:param holdings: Parsed JSON to dict from en/economy/myCompanies
|
|
"""
|
|
self.holdings = {}
|
|
template = dict(id=0, num_factories=0, region_id=0, companies=[])
|
|
|
|
for holding_id, holding in holdings.items():
|
|
tmp: Dict[str, Union[List[Any], Any]] = {}
|
|
for key in template:
|
|
if key == 'companies':
|
|
tmp.update({key: []})
|
|
else:
|
|
tmp.update({key: holding[key]})
|
|
self.holdings.update({int(holding_id): tmp})
|
|
self.holdings.update({0: template}) # unassigned
|
|
|
|
def prepare_companies(self, companies: dict):
|
|
"""
|
|
:param companies: Parsed JSON to dict from en/economy/myCompanies
|
|
"""
|
|
self.companies = {}
|
|
template = dict(id=None, quality=0, is_raw=False, resource_bonus=0, effective_bonus=0, raw_usage=0,
|
|
production=0, base_production=0, wam_enabled=False, can_work_as_manager=False,
|
|
preset_own_work=0, already_worked=False, can_assign_employees=False, preset_works=0,
|
|
todays_works=0, holding_company_id=None, is_assigned_to_holding=False,
|
|
cannot_work_as_manager_reason=False)
|
|
|
|
for c_id, company in companies.items():
|
|
tmp = {}
|
|
for key in template.keys():
|
|
if key in ['id', 'holding_company_id']:
|
|
company[key] = int(company[key])
|
|
tmp.update({key: company[key]})
|
|
self.companies.update({int(c_id): tmp})
|
|
|
|
def update_holding_companies(self):
|
|
for company_id, company_data in self.companies.items():
|
|
if company_id not in self.holdings[company_data['holding_company_id']]['companies']:
|
|
self.holdings[company_data['holding_company_id']]['companies'].append(company_id)
|
|
else:
|
|
for holding_id in self.holdings:
|
|
self.holdings[holding_id]['companies'].sort()
|
|
|
|
def get_employable_factories(self) -> Dict[int, int]:
|
|
ret = {}
|
|
for company_id, company in self.companies.items():
|
|
if company.get('preset_works'):
|
|
preset_works: int = int(company.get('preset_works', 0))
|
|
ret.update({company_id: preset_works})
|
|
return ret
|
|
|
|
def get_total_wam_count(self) -> int:
|
|
ret = 0
|
|
for holding_id in self.holdings:
|
|
ret += self.get_holding_wam_count(holding_id)
|
|
return ret
|
|
|
|
def get_holding_wam_count(self, holding_id: int, raw_factory=None) -> int:
|
|
"""
|
|
Returns amount of wam enabled companies in the holding
|
|
:param holding_id: holding id
|
|
:param raw_factory: True - only raw, False - only factories, None - both
|
|
:return: int
|
|
"""
|
|
return len(self.get_holding_wam_companies(holding_id, raw_factory))
|
|
|
|
def get_holding_employee_count(self, holding_id):
|
|
employee_count = 0
|
|
if holding_id in self.holdings:
|
|
for company_id in self.holdings.get(holding_id, {}).get('companies', []):
|
|
employee_count += self.companies.get(company_id).get('preset_works', 0)
|
|
return employee_count
|
|
|
|
def get_holding_wam_companies(self, holding_id: int, raw_factory: bool = None) -> List[int]:
|
|
"""
|
|
Returns WAM enabled companies in the holding, True - only raw, False - only factories, None - both
|
|
:param holding_id: holding id
|
|
:param raw_factory: bool or None
|
|
:return: list
|
|
"""
|
|
raw = []
|
|
factory = []
|
|
if holding_id in self.holdings:
|
|
for company_id in self.holdings.get(holding_id, {}).get('companies', []):
|
|
company = self.companies.get(company_id, {})
|
|
wam_enabled = bool(company.get('wam_enabled', {}))
|
|
already_worked = not company.get('already_worked', {})
|
|
cannot_work_war = company.get("cannot_work_as_manager_reason", {}) == "war"
|
|
if wam_enabled and already_worked and not cannot_work_war:
|
|
if company.get('is_raw', False):
|
|
raw.append(company_id)
|
|
else:
|
|
factory.append(company_id)
|
|
if raw_factory is not None and not raw_factory:
|
|
return factory
|
|
elif raw_factory is not None and raw_factory:
|
|
return raw
|
|
elif raw_factory is None:
|
|
return raw + factory
|
|
else:
|
|
raise ErepublikException("raw_factory should be True/False/None")
|
|
|
|
def get_needed_inventory_usage(self, company_id: int = None, companies: list = None) -> float:
|
|
if not any([companies, company_id]):
|
|
return 0.
|
|
if company_id:
|
|
if company_id not in self.companies:
|
|
raise ErepublikException("Company ({}) not in all companies list".format(company_id))
|
|
company = self.companies[company_id]
|
|
if company.get("is_raw"):
|
|
return float(company["base_production"]) * company["effective_bonus"]
|
|
else:
|
|
products_made = company["base_production"] * company["effective_bonus"] / 100
|
|
# raw_used = products_made * company['upgrades'][str(company['quality'])]['raw_usage'] * 100
|
|
return float(products_made - company['raw_usage'])
|
|
if companies:
|
|
return float(sum([self.get_needed_inventory_usage(company_id=cid) for cid in companies]))
|
|
|
|
raise ErepublikException("Wrong function call")
|
|
|
|
|
|
class SlowRequests(Session):
|
|
last_time: datetime.datetime
|
|
timeout = datetime.timedelta(milliseconds=500)
|
|
uas = [
|
|
# Chrome
|
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
|
|
'Chrome/73.0.3683.103 Safari/537.36',
|
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
|
|
'Chrome/72.0.3626.13 Safari/537.36',
|
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
|
|
'Chrome/71.0.3578.98 Safari/537.36',
|
|
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
|
|
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.11 Safari/537.36',
|
|
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
|
|
# FireFox
|
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
|
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0',
|
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0',
|
|
'Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0',
|
|
'Mozilla/5.0 (X11; Linux x86_64; rv:65.0) Gecko/20100101 Firefox/65.0',
|
|
'Mozilla/5.0 (X11; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0',
|
|
]
|
|
debug = False
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.request_log_name = utils.get_file(utils.now().strftime("debug/requests_%Y-%m-%d.log"))
|
|
self.last_time = utils.now()
|
|
self.headers.update({
|
|
'User-Agent': random.choice(self.uas)
|
|
})
|
|
|
|
@property
|
|
def __dict__(self):
|
|
return dict(last_time=self.last_time, timeout=self.timeout, user_agent=self.headers['User-Agent'],
|
|
request_log_name=self.request_log_name)
|
|
|
|
def request(self, method, url, *args, **kwargs):
|
|
self._slow_down_requests()
|
|
self._log_request(url, method, **kwargs)
|
|
resp = super().request(method, url, *args, **kwargs)
|
|
self._log_response(url, resp)
|
|
return resp
|
|
|
|
def _slow_down_requests(self):
|
|
ltt = utils.good_timedelta(self.last_time, self.timeout)
|
|
if ltt > utils.now():
|
|
seconds = (ltt - utils.now()).total_seconds()
|
|
time.sleep(seconds if seconds > 0 else 0)
|
|
self.last_time = utils.now()
|
|
|
|
def _log_request(self, url, method, data=None, json=None, params=None, **kwargs):
|
|
if self.debug:
|
|
args = {}
|
|
args.update({'kwargs': kwargs})
|
|
if data:
|
|
args.update({"data": data})
|
|
|
|
if json:
|
|
args.update({"json": json})
|
|
|
|
if params:
|
|
args.update({"params": params})
|
|
|
|
body = "[{dt}]\tURL: '{url}'\tMETHOD: {met}\tARGS: {args}\n".format(dt=utils.now().strftime("%F %T"),
|
|
url=url, met=method, args=args)
|
|
|
|
with open(self.request_log_name, 'ab') as file:
|
|
file.write(body.encode("UTF-8"))
|
|
|
|
def _log_response(self, url, resp, redirect: bool = False):
|
|
from erepublik import Citizen
|
|
if self.debug:
|
|
if resp.history and not redirect:
|
|
for hist_resp in resp.history:
|
|
self._log_request(hist_resp.request.url, "REDIRECT")
|
|
self._log_response(hist_resp.request.url, hist_resp, redirect=True)
|
|
|
|
# TODO: Must thoroughly check response writing on windows systems
|
|
file_data = {
|
|
"path": 'debug/requests',
|
|
"time": self.last_time.strftime('%Y-%m-%d_%H-%M-%S'),
|
|
"name": slugify(url[len(Citizen.url):]),
|
|
"extra": "_REDIRECT" if redirect else ""
|
|
}
|
|
|
|
try:
|
|
loads(resp.text)
|
|
file_data.update({"ext": "json"})
|
|
except JSONDecodeError:
|
|
file_data.update({"ext": "html"})
|
|
|
|
filename = 'debug/requests/{time}_{name}{extra}.{ext}'.format(**file_data)
|
|
with open(utils.get_file(filename), 'wb') as f:
|
|
f.write(resp.text.encode('utf-8'))
|
|
|
|
|
|
class Config:
|
|
email = ""
|
|
password = ""
|
|
work = True
|
|
train = True
|
|
wam = False
|
|
auto_sell: List[str] = list()
|
|
auto_sell_all = False
|
|
employees = False
|
|
fight = False
|
|
air = False
|
|
ground = False
|
|
all_in = False
|
|
next_energy = False
|
|
boosters = False
|
|
travel_to_fight = False
|
|
always_travel = False
|
|
epic_hunt = False
|
|
epic_hunt_ebs = False
|
|
rw_def_side = False
|
|
interactive = True
|
|
continuous_fighting = False
|
|
auto_buy_raw = False
|
|
force_wam = False
|
|
sort_battles_time = True
|
|
force_travel = False
|
|
|
|
@property
|
|
def wt(self):
|
|
return self.work and self.train
|
|
|
|
def __dict__(self) -> Dict[str, Union[bool, str, List[str]]]:
|
|
return dict(
|
|
email=self.email,
|
|
password=self.password,
|
|
work=self.work,
|
|
train=self.train,
|
|
wam=self.wam,
|
|
auto_sell=self.auto_sell,
|
|
auto_sell_all=self.auto_sell_all,
|
|
employees=self.employees,
|
|
fight=self.fight,
|
|
air=self.air,
|
|
ground=self.ground,
|
|
all_in=self.all_in,
|
|
next_energy=self.next_energy,
|
|
boosters=self.boosters,
|
|
travel_to_fight=self.travel_to_fight,
|
|
epic_hunt=self.epic_hunt,
|
|
epic_hunt_ebs=self.epic_hunt_ebs,
|
|
rw_def_side=self.rw_def_side,
|
|
interactive=self.interactive,
|
|
continuous_fighting=self.continuous_fighting,
|
|
auto_buy_raw=self.auto_buy_raw,
|
|
force_wam=self.force_wam,
|
|
sort_battles_time=self.sort_battles_time,
|
|
force_travel=self.force_travel,
|
|
)
|
|
|
|
|
|
class Energy:
|
|
limit = 500 # energyToRecover
|
|
interval = 10 # energyPerInterval
|
|
recoverable = 0 # energyFromFoodRemaining
|
|
recovered = 0 # energy
|
|
_recovery_time = None
|
|
|
|
def __init__(self):
|
|
self._recovery_time = utils.now()
|
|
|
|
def __repr__(self):
|
|
return "{:4}/{:4} + {:4}, {:3}hp/6min".format(self.recovered, self.limit, self.recoverable, self.interval)
|
|
|
|
def set_reference_time(self, recovery_time: datetime.datetime):
|
|
self._recovery_time = recovery_time.replace(microsecond=0)
|
|
|
|
@property
|
|
def food_fights(self):
|
|
return (self.recoverable + self.recovered) // 10
|
|
|
|
@property
|
|
def reference_time(self):
|
|
if self.is_recovered_full or self._recovery_time < utils.now():
|
|
ret = utils.now()
|
|
else:
|
|
ret = self._recovery_time
|
|
return ret
|
|
|
|
@property
|
|
def is_recoverable_full(self):
|
|
return self.recoverable >= self.limit - self.interval
|
|
|
|
@property
|
|
def is_recovered_full(self):
|
|
return self.recovered >= self.limit - self.interval
|
|
|
|
@property
|
|
def is_energy_full(self):
|
|
return self.is_recoverable_full and self.is_recovered_full
|
|
|
|
@property
|
|
def available(self):
|
|
return self.recovered + self.recoverable
|
|
|
|
@property
|
|
def __dict__(self):
|
|
return dict(
|
|
limit=self.limit,
|
|
interval=self.interval,
|
|
recoverable=self.recoverable,
|
|
recovered=self.recovered,
|
|
reference_time=self.reference_time
|
|
)
|
|
|
|
|
|
class Details(object):
|
|
xp = 0
|
|
cc = 0
|
|
pp = 0
|
|
pin = None
|
|
gold = 0
|
|
next_pp: List[int] = []
|
|
citizen_id = 0
|
|
citizenship = 0
|
|
current_region = 0
|
|
current_country = 0
|
|
residence_region = 0
|
|
residence_country = 0
|
|
daily_task_done = False
|
|
daily_task_reward = False
|
|
mayhem_skills = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0, 14: 0, }
|
|
|
|
@property
|
|
def xp_till_level_up(self):
|
|
if self.xp >= 10000:
|
|
next_level_up = (1 + (self.xp // 5000)) * 5000
|
|
elif self.xp >= 7000:
|
|
next_level_up = 10000
|
|
elif self.xp >= 3000:
|
|
next_level_up = (1 + ((self.xp - 1000) // 2000)) * 2000 + 1000
|
|
elif self.xp >= 2000:
|
|
next_level_up = 3000
|
|
elif self.xp >= 450:
|
|
next_level_up = (1 + (self.xp // 500)) * 500
|
|
elif self.xp >= 370:
|
|
next_level_up = (1 + ((self.xp - 10) // 40)) * 40 + 10
|
|
elif self.xp >= 300:
|
|
next_level_up = (1 + ((self.xp - 20) // 35)) * 35 + 20
|
|
elif self.xp >= 150:
|
|
next_level_up = (1 + (self.xp // 30)) * 30
|
|
elif self.xp >= 50:
|
|
next_level_up = (1 + ((self.xp - 10) // 20)) * 20 + 10
|
|
elif self.xp >= 20:
|
|
next_level_up = (1 + ((self.xp - 5) // 15)) * 15 + 5
|
|
else:
|
|
next_level_up = (1 + (self.xp // 10)) * 10
|
|
return next_level_up - self.xp
|
|
|
|
|
|
class Politics:
|
|
is_party_member: bool = False
|
|
|
|
party_id: int = 0
|
|
party_slug: str = ""
|
|
is_party_president: bool = False
|
|
is_congressman: bool = False
|
|
is_country_president: bool = False
|
|
|
|
|
|
class House(object):
|
|
quality = None
|
|
unactivated_count = 0
|
|
active_untill = utils.good_timedelta(utils.now(), -datetime.timedelta(days=1))
|
|
|
|
def __init__(self, quality: int):
|
|
if 0 < quality < 6:
|
|
self.quality = quality
|
|
|
|
@property
|
|
def next_ot_point(self) -> datetime.datetime:
|
|
return self.active_untill
|
|
|
|
|
|
class CitizenAPI:
|
|
url = "https://www.erepublik.com/en"
|
|
_req = SlowRequests
|
|
|
|
def __init__(self):
|
|
self._req = SlowRequests()
|
|
|
|
def post(self, url: str, *args, **kwargs) -> Response:
|
|
return self._req.post(url, *args, **kwargs)
|
|
|
|
def get(self, url: str, **kwargs) -> Response:
|
|
return self._req.get(url, **kwargs)
|
|
|
|
def get_article_json(self, article_id: int) -> Response:
|
|
return self.get("{}/main/articleJson/{}".format(self.url, article_id))
|
|
|
|
def get_battlefield_choose_side(self, battle: int, side: int) -> Response:
|
|
return self.get("{}/military/battlefield-choose-side/{}/{}".format(self.url, battle, side))
|
|
|
|
def get_candidate_party(self, party_slug: str) -> Response:
|
|
return self.post("{}/candidate/{}".format(self.url, party_slug))
|
|
|
|
def get_citizen_hovercard(self, citizen: int) -> Response:
|
|
return self.get("{}/main/citizen-hovercard/{}".format(self.url, citizen))
|
|
|
|
def get_citizen_profile(self, player_id: int):
|
|
return self.get("{}/main/citizen-profile-json/{}".format(self.url, player_id))
|
|
|
|
def get_citizen_daily_assistant(self):
|
|
return self.get("{}/main/citizenDailyAssistant".format(self.url))
|
|
|
|
def get_city_data_residents(self, city: int, page: int = 1, params: Dict[str, Any] = {}):
|
|
return self.get("{}/main/city-data/{}/residents".format(self.url, city), params={"currentPage": page, **params})
|
|
|
|
def get_country_military(self, country: str) -> Response:
|
|
return self.get("{}/country/military/{}".format(self.url, country))
|
|
|
|
def get_economy_inventory_items(self) -> Response:
|
|
return self.get("{}/economy/inventory-items/".format(self.url))
|
|
|
|
def get_economy_job_market_json(self, country: int) -> Response:
|
|
return self.get("{}/economy/job-market-json/{}/1/desc".format(self.url, country))
|
|
|
|
def get_economy_my_companies(self) -> Response:
|
|
return self.get("{}/economy/myCompanies".format(self.url))
|
|
|
|
def get_economy_my_market_offers(self) -> Response:
|
|
return self.get("{}/economy/myMarketOffers".format(self.url))
|
|
|
|
def get_job_data(self) -> Response:
|
|
return self.get("{}/main/job-data".format(self.url))
|
|
|
|
def get_leaderboards_damage_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response:
|
|
data = (country, weeks, mu)
|
|
return self.get("{}/main/leaderboards-damage-aircraft-rankings/{}/{}/{}/0".format(self.url, *data))
|
|
|
|
def get_leaderboards_damage_rankings(self, country: int, weeks: int = 0, mu: int = 0, div: int = 0) -> Response:
|
|
data = (country, weeks, mu, div)
|
|
return self.get("{}/main/leaderboards-damage-rankings/{}/{}/{}/{}".format(self.url, *data))
|
|
|
|
def get_leaderboards_kills_aircraft_rankings(self, country: int, weeks: int = 0, mu: int = 0) -> Response:
|
|
data = (country, weeks, mu)
|
|
return self.get("{}/main/leaderboards-kills-aircraft-rankings/{}/{}/{}/0".format(self.url, *data))
|
|
|
|
def get_leaderboards_kills_rankings(self, country: int, weeks: int = 0, mu: int = 0, div: int = 0) -> Response:
|
|
data = (country, weeks, mu, div)
|
|
return self.get("{}/main/leaderboards-kills-rankings/{}/{}/{}/{}".format(self.url, *data))
|
|
|
|
def get_main(self):
|
|
return self.get(self.url)
|
|
|
|
def get_message_alerts(self, page: int = 1) -> Response:
|
|
return self.get_message_alerts(page)
|
|
|
|
def get_military_campaigns(self) -> Response:
|
|
return self.get("{}/military/campaigns-new/".format(self.url))
|
|
|
|
def get_military_unit_data(self, unit_id: int, page: int = 1) -> Response:
|
|
params = {"groupId": unit_id, "panel": "members", "currentPage": page}
|
|
return self.get("{}/military/military-unit-data/".format(self.url), params=params)
|
|
|
|
def get_money_donation_accept(self, token: str, donation_id: int) -> Response:
|
|
return self.get("{}/main/money-donation/accept/{}".format(self.url, donation_id), params={"_token": token})
|
|
|
|
def get_money_donation_reject(self, token: str, donation_id: int) -> Response:
|
|
return self.get("{}/main/money-donation/reject/{}".format(self.url, donation_id), params={"_token": token})
|
|
|
|
def get_party_members(self, party: int) -> Response:
|
|
return self.get("{}/main/party-members/{}".format(self.url, party))
|
|
|
|
def get_rankings_parties(self, country: int) -> Response:
|
|
return self.get("{}/main/rankings-parties/1/{}".format(self.url, country))
|
|
|
|
def get_training_grounds_json(self) -> Response:
|
|
return self.get("{}/main/training-grounds-json".format(self.url))
|
|
|
|
def get_weekly_challenge_data(self) -> Response:
|
|
return self.get("{}/main/weekly-challenge-data".format(self.url))
|
|
|
|
def post_activate_battle_effect(self, token: str, battle: int, kind: str, citizen_id: int) -> Response:
|
|
data = dict(battleId=battle, citizenId=citizen_id, type=kind, _token=token)
|
|
return self.post("{}/main/fight-activateBattleEffect".format(self.url), data=data)
|
|
|
|
def post_article_comments(self, token: str, article: int, page: int = 0) -> Response:
|
|
data = dict(_token=token, articleId=article, page=page)
|
|
if page:
|
|
data.update({'page': page})
|
|
return self.post("{}/main/articleComments".format(self.url), data=data)
|
|
|
|
def post_article_comments_create(self, token: str, message: str, article: int, parent: int = 0) -> Response:
|
|
data = dict(_token=token, message=message, articleId=article)
|
|
if parent:
|
|
data.update({"parentId": parent})
|
|
return self.post("{}/main/articleComments/create".format(self.url), data=data)
|
|
|
|
def post_battle_console(self, token: str, battle: int, zone: int, round_id: int, division: int, page: int,
|
|
damage: bool) -> Response:
|
|
data = dict(battleId=battle, zoneId=zone, action="battleStatistics", round=round_id, division=division,
|
|
leftPage=page, rightPage=page, _token=token)
|
|
if damage:
|
|
data.update({"type": "damage"})
|
|
else:
|
|
data.update({"type": "kills"})
|
|
|
|
return self.post("{}/military/battle-console".format(self.url), data=data)
|
|
|
|
def post_buy_gold_items(self, token: str, currency: str, item: str, amount: int) -> Response:
|
|
data = dict(itemId=item, currency=currency, amount=amount, _token=token)
|
|
return self.post("{}/main/buyGoldItems".format(self.url), data=data)
|
|
|
|
def post_candidate_for_congress(self, token: str, presentation: str = "") -> Response:
|
|
data = dict(_token=token, presentation=presentation)
|
|
return self.post("{}/candidate-for-congress".format(self.url), data=data)
|
|
|
|
def post_citizen_add_remove_friend(self, token: str, citizen: int, add: bool) -> Response:
|
|
data = dict(_token=token, citizenId=citizen, url="//www.erepublik.com/en/main/citizen-addRemoveFriend")
|
|
if add:
|
|
data.update({"action": "addFriend"})
|
|
else:
|
|
data.update({"action": "removeFriend"})
|
|
return self.post("{}/main/citizen-addRemoveFriend".format(self.url), data=data)
|
|
|
|
def post_collect_anniversary_reward(self, token: str) -> Response:
|
|
return self.post("{}/main/collect-anniversary-reward".format(self.url), data={"_token": token})
|
|
|
|
def post_country_donate(self, token: str, country: int, action: str, value: Union[int, float], quality: int = None):
|
|
json = dict(countryId=country, action=action, _token=token, value=value, quality=quality)
|
|
return self.post("{}/main/country-donate".format(self.url), data=json,
|
|
headers={"Referer": "{}/country/economy/Latvia".format(self.url)})
|
|
|
|
def post_daily_task_reward(self, token: str) -> Response:
|
|
return self.post("{}/main/daily-tasks-reward".format(self.url), data=dict(_token=token))
|
|
|
|
def post_delete_message(self, token: str, msg_id: list) -> Response:
|
|
data = {"_token": token, "delete_message[]": msg_id}
|
|
return self.post("{}/main/messages-delete".format(self.url), data)
|
|
|
|
def post_eat(self, token: str, color: str) -> Response:
|
|
data = dict(_token=token, buttonColor=color)
|
|
return self.post("{}/main/eat".format(self.url), params=data)
|
|
|
|
def post_economy_activate_house(self, token: str, quality: int) -> Response:
|
|
data = {"action": "activate", "quality": quality, "type": "house", "_token": token}
|
|
return self.post("{}/economy/activateHouse".format(self.url), data=data)
|
|
|
|
def post_economy_assign_to_holding(self, token: str, factory: int, holding: int) -> Response:
|
|
data = dict(_token=token, factoryId=factory, action="assign", holdingCompanyId=holding)
|
|
return self.post("{}/economy/assign-to-holding".format(self.url), data=data)
|
|
|
|
def post_economy_create_company(self, token: str, industry: int, building_type: int = 1) -> Response:
|
|
data = {"_token": token, "company[industry_id]": industry, "company[building_type]": building_type}
|
|
return self.post("{}/economy/create-company".format(self.url), data=data,
|
|
headers={"Referer": "{}/economy/create-company".format(self.url)})
|
|
|
|
def post_economy_donate_items_action(self, token: str, citizen: int, amount: int, industry: int,
|
|
quality: int) -> Response:
|
|
data = dict(citizen_id=citizen, amount=amount, industry_id=industry, quality=quality, _token=token)
|
|
return self.post("{}/economy/donate-items-action".format(self.url), data=data,
|
|
headers={"Referer": "{}/economy/donate-items/{}".format(self.url, citizen)})
|
|
|
|
def post_economy_donate_money_action(self, token: str, citizen: int, amount: float = 0.0,
|
|
currency: int = 62) -> Response:
|
|
data = dict(citizen_id=citizen, _token=token, currency_id=currency, amount=amount)
|
|
return self.post("{}/economy/donate-money-action".format(self.url), data=data,
|
|
headers={"Referer": "{}/economy/donate-money/{}".format(self.url, citizen)})
|
|
|
|
def post_economy_exchange_purchase(self, token: str, amount: float, currency: int, offer: int) -> Response:
|
|
data = dict(_token=token, amount=amount, currencyId=currency, offerId=offer)
|
|
return self.post("{}/economy/exchange/purchase/".format(self.url), data=data)
|
|
|
|
def post_economy_exchange_retrieve(self, token: str, personal: bool, page: int, currency: int) -> Response:
|
|
data = dict(_token=token, personalOffers=int(personal), page=page, currencyId=currency)
|
|
return self.post("{}/economy/exchange/retrieve/".format(self.url), data=data)
|
|
|
|
def post_economy_job_market_apply(self, token: str, citizen: int, salary: int) -> Response:
|
|
data = dict(_token=token, citizenId=citizen, salary=salary)
|
|
return self.post("{}/economy/job-market-apply".format(self.url), data=data)
|
|
|
|
def post_economy_marketplace(self, token: str, country: int, industry: int, quality: int,
|
|
order_asc: bool = True) -> Response:
|
|
data = dict(countryId=country, industryId=industry, quality=quality, ajaxMarket=1,
|
|
orderBy="price_asc" if order_asc else "price_desc", _token=token)
|
|
return self.post("{}/economy/marketplaceAjax".format(self.url), data=data)
|
|
|
|
def post_economy_marketplace_actions(self, token: str, amount: int, buy: bool = False, **kwargs) -> Response:
|
|
if buy:
|
|
data = dict(_token=token, offerId=kwargs['offer'], amount=amount, orderBy="price_asc", currentPage=1,
|
|
buyAction=1)
|
|
else:
|
|
data = dict(_token=token, countryId=kwargs["country"], price=kwargs["price"], industryId=kwargs["industry"],
|
|
quality=kwargs["quality"], amount=amount, sellAction='postOffer')
|
|
return self.post("{}/economy/marketplaceActions".format(self.url), data=data)
|
|
|
|
def post_economy_resign(self, token: str) -> Response:
|
|
return self.post("{}/economy/resign".format(self.url),
|
|
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
data={"_token": token, "action_type": "resign"})
|
|
|
|
def post_economy_sell_company(self, token: str, factory: int, pin: int = None, sell: bool = True) -> Response:
|
|
url = "{}/economy/sell-company/{}".format(self.url, factory)
|
|
data = dict(_token=token, pin="" if pin is None else pin)
|
|
if sell:
|
|
data.update({"sell": "sell"})
|
|
else:
|
|
data.update({"dissolve": factory})
|
|
return self.post(url, data=data, headers={"Referer": url})
|
|
|
|
def post_economy_train(self, token: str, tg_ids: List[int]) -> Response:
|
|
data: Dict[str, Union[int, str]] = {}
|
|
if not tg_ids:
|
|
return self.get_training_grounds_json()
|
|
else:
|
|
for idx, tg_id in enumerate(tg_ids):
|
|
data["grounds[%i][id]" % idx] = tg_id
|
|
data["grounds[%i][train]" % idx] = 1
|
|
if data:
|
|
data['_token'] = token
|
|
return self.post("{}/economy/train".format(self.url), data=data)
|
|
|
|
def post_economy_upgrade_company(self, token: str, factory: int, level: int, pin: str = None) -> Response:
|
|
data = dict(_token=token, type="upgrade", companyId=factory, level=level, pin="" if pin is None else pin)
|
|
return self.post("{}/economy/upgrade-company".format(self.url), data=data)
|
|
|
|
def post_economy_work(self, token: str, action_type: str, wam: List[int] = None, employ: Dict[int, int] = None):
|
|
"""
|
|
:return: requests.Response or None
|
|
"""
|
|
if employ is None:
|
|
employ = dict()
|
|
if wam is None:
|
|
wam = []
|
|
data: Dict[str, Union[int, str]] = dict(action_type=action_type, _token=token)
|
|
if action_type == "work":
|
|
return self.post("{}/economy/work".format(self.url), data=data)
|
|
elif action_type == "production":
|
|
max_idx = 0
|
|
for idx, company_id in enumerate(sorted(wam or [])):
|
|
data.update({
|
|
"companies[%i][id]" % idx: company_id,
|
|
"companies[%i][employee_works]" % idx: employ.pop(company_id, 0),
|
|
"companies[%i][own_work]" % idx: 1
|
|
})
|
|
max_idx = idx + 1
|
|
for idx, company_id in enumerate(sorted(employ or [])):
|
|
idx_ = idx + max_idx
|
|
data.update({
|
|
"companies[%i][id]" % idx_: company_id,
|
|
"companies[%i][employee_works]" % idx_: employ.pop(company_id),
|
|
"companies[%i][own_work]" % idx_: 0
|
|
})
|
|
return self.post("{}/economy/work".format(self.url), data=data)
|
|
else:
|
|
return
|
|
|
|
def post_economy_work_overtime(self, token: str) -> Response:
|
|
data = dict(action_type="workOvertime", _token=token)
|
|
return self.post("{}/economy/workOvertime".format(self.url), data=data)
|
|
|
|
def post_forgot_password(self, token: str, email: str) -> Response:
|
|
data = dict(_token=token, email=email, commit="Reset password")
|
|
return self.post("{}/forgot-password".format(self.url), data=data)
|
|
|
|
def post_fight_activate_booster(self, token: str, battle: int, quality: int, duration: int, kind: str) -> Response:
|
|
data = dict(type=kind, quality=quality, duration=duration, battleId=battle, _token=token)
|
|
return self.post("{}/military/fight-activateBooster".format(self.url), data=data)
|
|
|
|
def post_login(self, token: str, email: str, password: str) -> Response:
|
|
data = dict(csrf_token=token, citizen_email=email, citizen_password=password, remember='on')
|
|
return self.post("{}/login".format(self.url), data=data)
|
|
|
|
def post_messages_alert(self, token: str, notification_ids: list) -> Response:
|
|
data = {"_token": token, "delete_alerts[]": notification_ids, "deleteAllAlerts": "1", "delete": "Delete"}
|
|
return self.post("{}/main/messages-alerts/1".format(self.url), data=data)
|
|
|
|
def post_messages_compose(self, token: str, subject: str, body: str, citizens: List[int]) -> Response:
|
|
url_pk = 0 if len(citizens) > 1 else str(citizens[0])
|
|
data = dict(citizen_name=",".join([str(x) for x in citizens]),
|
|
citizen_subject=subject, _token=token, citizen_message=body)
|
|
return self.post("{}/main/messages-compose/{}}".format(self.url, url_pk), data=data)
|
|
|
|
def post_military_battle_console(self, token: str, battle_id: int, round_id: int, division: int) -> Response:
|
|
data = dict(battleId=battle_id, zoneId=round_id, action="battleStatistics", round=round_id, division=division,
|
|
type="damage", leftPage=1, rightPage=1, _token=token)
|
|
return self.post("{}/military/battle-console".format(self.url, battle_id), data=data)
|
|
|
|
def post_military_fight_air(self, token: str, battle_id: int, side_id: int) -> Response:
|
|
data = dict(sideId=side_id, battleId=battle_id, _token=token)
|
|
return self.post("{}/military/fight-shoooot/{}".format(self.url, battle_id), data=data)
|
|
|
|
def post_military_fight_ground(self, token: str, battle_id: int, side_id: int) -> Response:
|
|
data = dict(sideId=side_id, battleId=battle_id, _token=token)
|
|
return self.post("{}/military/fight-shooot/{}".format(self.url, battle_id), data=data)
|
|
|
|
def post_military_group_missions(self, token: str) -> Response:
|
|
data = dict(action="check", _token=token)
|
|
return self.post("{}/military/group-missions".format(self.url), data=data)
|
|
|
|
def post_travel(self, token: str, check: str, **kwargs) -> Response:
|
|
data = dict(_token=token, check=check, **kwargs)
|
|
return self.post("{}/main/travel".format(self.url), data=data)
|
|
|
|
def post_travel_data(self, token: str, **kwargs) -> Response:
|
|
return self.post("{}/main/travelData".format(self.url), data=dict(_token=token, **kwargs))
|
|
|
|
def post_wars_attack_region(self, token: str, war: int, region: int) -> Response:
|
|
data = dict(_token=token)
|
|
return self.post("{}/wars/attack-region/{}/{}".format(self.url, war, region), data=data)
|
|
|
|
def post_weekly_challenge_reward(self, token: str, reward_id: int) -> Response:
|
|
data = dict(_token=token, rewardId=reward_id)
|
|
return self.post("{}/main/weekly-challenge-collect-reward".format(self.url), data=data)
|
|
|
|
def post_write_article(self, token: str, title: str, content: str, location: int, kind: int) -> Response:
|
|
data = dict(_token=token, article_name=title, article_body=content, article_location=location,
|
|
article_category=kind)
|
|
return self.post("{}/main/write-article".format(self.url), data=data)
|
|
|
|
# Wall Posts
|
|
# ## Country
|
|
|
|
def post_country_comment_retrieve(self, token: str, post_id: int):
|
|
data = {"_token": token, "postId": post_id}
|
|
return self.post("{}/main/country-comment/retrieve/json".format(self.url), data=data)
|
|
|
|
def post_country_comment_create(self, token: str, post_id: int, comment_message: str):
|
|
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
|
|
return self.post("{}/main/country-comment/create/json".format(self.url), data=data)
|
|
|
|
def post_country_post_create(self, token: str, body: str, post_as: int):
|
|
data = {"_token": token, "post_message": body, "post_as": post_as}
|
|
return self.post("{}/main/country-post/create/json".format(self.url), data=data)
|
|
|
|
def post_country_post_retrieve(self, token: str):
|
|
data = {"_token": token, "page": 1, "switchedFrom": False}
|
|
return self.post("{}/main/country-post/retrieve/json".format(self.url), data=data)
|
|
|
|
# ## Military Unit
|
|
|
|
def post_military_unit_comment_retrieve(self, token: str, post_id: int):
|
|
data = {"_token": token, "postId": post_id}
|
|
return self.post("{}/main/military-unit-comment/retrieve/json".format(self.url), data=data)
|
|
|
|
def post_military_unit_comment_create(self, token: str, post_id: int, comment_message: str):
|
|
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
|
|
return self.post("{}/main/military-unit-comment/create/json".format(self.url), data=data)
|
|
|
|
def post_military_unit_post_create(self, token: str, body: str, post_as: int):
|
|
data = {"_token": token, "post_message": body, "post_as": post_as}
|
|
return self.post("{}/main/military-unit-post/create/json".format(self.url), data=data)
|
|
|
|
def post_military_unit_post_retrieve(self, token: str):
|
|
data = {"_token": token, "page": 1, "switchedFrom": False}
|
|
return self.post("{}/main/military-unit-post/retrieve/json".format(self.url), data=data)
|
|
|
|
# ## Party
|
|
|
|
def post_party_comment_retrieve(self, token: str, post_id: int):
|
|
data = {"_token": token, "postId": post_id}
|
|
return self.post("{}/main/party-comment/retrieve/json".format(self.url), data=data)
|
|
|
|
def post_party_comment_create(self, token: str, post_id: int, comment_message: str):
|
|
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
|
|
return self.post("{}/main/party-comment/create/json".format(self.url), data=data)
|
|
|
|
def post_party_post_create(self, token: str, body: str):
|
|
data = {"_token": token, "post_message": body}
|
|
return self.post("{}/main/party-post/create/json".format(self.url), data=data)
|
|
|
|
def post_party_post_retrieve(self, token: str):
|
|
data = {"_token": token, "page": 1, "switchedFrom": False}
|
|
return self.post("{}/main/party-post/retrieve/json".format(self.url), data=data)
|
|
|
|
# ## Friend's Wall
|
|
|
|
def post_wall_comment_retrieve(self, token: str, post_id: int):
|
|
data = {"_token": token, "postId": post_id}
|
|
return self.post("{}/main/wall-comment/retrieve/json".format(self.url), data=data)
|
|
|
|
def post_wall_comment_create(self, token: str, post_id: int, comment_message: str):
|
|
data = {"_token": token, "postId": post_id, 'comment_message': comment_message}
|
|
return self.post("{}/main/wall-comment/create/json".format(self.url), data=data)
|
|
|
|
def post_wall_post_create(self, token: str, body: str):
|
|
data = {"_token": token, "post_message": body}
|
|
return self.post("{}/main/wall-post/create/json".format(self.url), data=data)
|
|
|
|
def post_wall_post_retrieve(self, token: str):
|
|
data = {"_token": token, "page": 1, "switchedFrom": False}
|
|
return self.post("{}/main/wall-post/retrieve/json".format(self.url), data=data)
|
|
|
|
|
|
class Reporter:
|
|
__to_update: List[Dict[Any, Any]] = []
|
|
name: str = ""
|
|
email: str = ""
|
|
citizen_id: int = 0
|
|
key: str = ""
|
|
allowed: bool = False
|
|
|
|
def __init__(self):
|
|
self._req = Session()
|
|
self.url = "https://api.erep.lv"
|
|
self._req.headers.update({"user-agent": "Bot reporter v2"})
|
|
self.__registered: bool = False
|
|
|
|
@property
|
|
def __dict__(self):
|
|
return dict(allowed=self.allowed, __to_update=self.__to_update)
|
|
|
|
def do_init(self, name: str = "", email: str = "", citizen_id: int = 0):
|
|
self.name: str = name
|
|
self.email: str = email
|
|
self.citizen_id: int = citizen_id
|
|
self.key: str = ""
|
|
self.__update_key()
|
|
self.allowed = True
|
|
|
|
def __update_key(self):
|
|
self.key = hashlib.md5(bytes(f"{self.name}:{self.email}", encoding="UTF-8")).hexdigest()
|
|
self.allowed = True
|
|
self.register_account()
|
|
|
|
def __bot_update(self, data: dict) -> Response:
|
|
if self.__to_update:
|
|
for unreported_data in self.__to_update:
|
|
unreported_data.update(player_id=self.citizen_id, key=self.key)
|
|
self._req.post("{}/bot/update".format(self.url), json=unreported_data)
|
|
self.__to_update.clear()
|
|
r = self._req.post("{}/bot/update".format(self.url), json=data)
|
|
return r
|
|
|
|
def register_account(self):
|
|
if not self.__registered:
|
|
try:
|
|
r = self.__bot_update(dict(key=self.key, check=True, player_id=self.citizen_id))
|
|
if not r.json().get("status"):
|
|
self._req.post("{}/bot/register".format(self.url), json=dict(name=self.name, email=self.email,
|
|
player_id=self.citizen_id))
|
|
finally:
|
|
self.__registered = True
|
|
self.report_action("STARTED", value=utils.now().strftime("%F %T"))
|
|
|
|
def send_state_update(self, xp: int, cc: float, gold: float, inv_total: int, inv: int,
|
|
hp_limit: int, hp_interval: int, hp_available: int, food: int, pp: int):
|
|
|
|
data = dict(key=self.key, player_id=self.citizen_id, state=dict(
|
|
xp=xp, cc=cc, gold=gold, inv_total=inv_total, inv_free=inv_total - inv, inv=inv, food=food,
|
|
pp=pp, hp_limit=hp_limit, hp_interval=hp_interval, hp_available=hp_available,
|
|
))
|
|
|
|
if self.allowed:
|
|
self.__bot_update(data)
|
|
|
|
def report_action(self, action: str, json_val: Dict[Any, Any] = None, value: str = None):
|
|
if not self.key:
|
|
if not all([self.email, self.name, self.citizen_id]):
|
|
pass
|
|
json_data = {'player_id': self.citizen_id, 'key': self.key, 'log': dict(action=action)}
|
|
if json_val:
|
|
json_data['log'].update(dict(json=json_val))
|
|
if value:
|
|
json_data['log'].update(dict(value=value))
|
|
if self.allowed:
|
|
self.__bot_update(json_data)
|
|
else:
|
|
self.__to_update.append(json_data)
|
|
|
|
|
|
class MyJSONEncoder(JSONEncoder):
|
|
def default(self, o):
|
|
if isinstance(o, decimal.Decimal):
|
|
return float("{:.02f}".format(o))
|
|
elif isinstance(o, datetime.datetime):
|
|
return dict(__type__='datetime', year=o.year, month=o.month, day=o.day, hour=o.hour, minute=o.minute,
|
|
second=o.second, microsecond=o.microsecond)
|
|
elif isinstance(o, datetime.date):
|
|
return dict(__type__='date', year=o.year, month=o.month, day=o.day)
|
|
elif isinstance(o, datetime.timedelta):
|
|
return dict(__type__='timedelta', days=o.days, seconds=o.seconds,
|
|
microseconds=o.microseconds, total_seconds=o.total_seconds())
|
|
elif isinstance(o, Response):
|
|
return dict(_content=o._content.decode("UTF-8"), headers=o.headers.__dict__, url=o.url, text=o.text)
|
|
elif hasattr(o, '__dict__'):
|
|
return o.__dict__
|
|
elif isinstance(o, deque):
|
|
return list(o)
|
|
return super().default(o)
|
|
|
|
|
|
class BattleSide:
|
|
id: int
|
|
points: int
|
|
deployed: List[int] = list()
|
|
allies: List[int] = list()
|
|
|
|
def __init__(self, country_id: int, points: int, allies: List[int], deployed: List[int]):
|
|
self.id = country_id
|
|
self.points = points
|
|
self.allies = [int(ally) for ally in allies]
|
|
self.deployed = [int(ally) for ally in deployed]
|
|
|
|
|
|
class BattleDivision:
|
|
end: datetime.datetime
|
|
epic: bool
|
|
dom_pts: Dict[str, int] = dict()
|
|
wall: Dict[str, Union[int, float]] = dict()
|
|
|
|
@property
|
|
def div_end(self) -> bool:
|
|
return utils.now() >= self.end
|
|
|
|
def __init__(self, end: datetime.datetime, epic: bool, inv_pts: int, def_pts: int, wall_for: int, wall_dom: float):
|
|
self.end = end
|
|
self.epic = epic
|
|
self.dom_pts.update({"inv": inv_pts, "def": def_pts})
|
|
self.wall.update({"for": wall_for, "dom": wall_dom})
|
|
|
|
|
|
class Battle(object):
|
|
id: int = 0
|
|
war_id: int = 0
|
|
zone_id: int = 0
|
|
is_rw: bool = False
|
|
is_dict_lib: bool = False
|
|
start: datetime.datetime = None
|
|
invader: BattleSide = None
|
|
defender: BattleSide = None
|
|
div: Dict[int, BattleDivision] = dict()
|
|
|
|
@property
|
|
def is_air(self) -> bool:
|
|
return not bool(self.zone_id % 4)
|
|
|
|
def __init__(self, battle: dict):
|
|
self.id = int(battle.get('id', 0))
|
|
self.war_id = int(battle.get('war_id', 0))
|
|
self.zone_id = int(battle.get('zone_id', 0))
|
|
self.is_rw = bool(battle.get('is_rw'))
|
|
self.is_as = bool(battle.get('is_as'))
|
|
self.is_dict_lib = bool(battle.get('is_dict')) or bool(battle.get('is_lib'))
|
|
self.start = datetime.datetime.fromtimestamp(int(battle.get('start', 0)), tz=utils.erep_tz)
|
|
|
|
self.invader = BattleSide(battle.get('inv', {}).get('id'), battle.get('inv', {}).get('points'),
|
|
[row.get('id') for row in battle.get('inv', {}).get('ally_list')],
|
|
[row.get('id') for row in battle.get('inv', {}).get('ally_list') if row['deployed']])
|
|
|
|
self.defender = BattleSide(battle.get('def', {}).get('id'), battle.get('def', {}).get('points'),
|
|
[row.get('id') for row in battle.get('def', {}).get('ally_list')],
|
|
[row.get('id') for row in battle.get('def', {}).get('ally_list') if row['deployed']])
|
|
|
|
for div, data in battle.get('div', {}).items():
|
|
div = int(div)
|
|
if data.get('end'):
|
|
end = datetime.datetime.fromtimestamp(data.get('end'), tz=utils.erep_tz)
|
|
else:
|
|
end = datetime.datetime.max
|
|
|
|
battle_div = BattleDivision(
|
|
end=end, epic=data.get('epic_type') in [1, 5],
|
|
inv_pts=data.get('dom_pts').get("inv"), def_pts=data.get('dom_pts').get("def"),
|
|
wall_for=data.get('wall').get("for"), wall_dom=data.get('wall').get("dom")
|
|
)
|
|
|
|
self.div.update({div: battle_div})
|
|
|
|
def __repr__(self):
|
|
now = utils.now()
|
|
is_started = self.start < utils.now()
|
|
if is_started:
|
|
time_part = "{}".format(now - self.start)
|
|
else:
|
|
time_part = "- {}".format(self.start - now)
|
|
return "Battle {} | {:>21.21}:{:<21.21} | Round {:2} | Start {}".format(
|
|
self.id, utils.COUNTRIES[self.invader.id], utils.COUNTRIES[self.defender.id], self.zone_id, time_part
|
|
)
|
|
|
|
|
|
class EnergyToFight:
|
|
energy: int = 0
|
|
|
|
def __init__(self, energy: int = 0):
|
|
self.energy = energy
|
|
|
|
def __int__(self):
|
|
return self.energy
|
|
|
|
def __str__(self):
|
|
return str(self.energy)
|
|
|
|
def __repr__(self):
|
|
return str(self.energy)
|
|
|
|
@property
|
|
def i(self):
|
|
return self.__int__()
|
|
|
|
@property
|
|
def s(self):
|
|
return self.__str__()
|
|
|
|
def check(self, new_energy: int):
|
|
if not isinstance(new_energy, (tuple, int)):
|
|
return self.energy
|
|
if 0 < new_energy < self.energy:
|
|
self.energy = new_energy
|
|
return self.energy
|